aude-wire(7)
NAME
aude-wire — aude
的远程控制协议
DESCRIPTION
sdk/conformance/ 定义该协议。
TRANSPORT
链路是到机器监听器的
WebSocket,方式为:到 127.0.0.1 的
TCP、到隧道名称 443
端口的 TLS,或
~/.aude/rc/listener.socket。
‘Origin’
标头得到
403。每条二进制消息都是一条最多
65535 字节的 Noise
消息。握手
‘Noise_XX_25519_ChaChaPoly_SHA256’
有 ‘aude-wire’
序言和空载荷。客户端期望拨号所用的指纹,在
listener.socket
上则期望机器的指纹。
指纹是标准形式的 X25519 公钥的 SHA-256,截断为 28 个 base32 字符。
FRAMING
帧是一行中的一个严格 UTF-8 JSON 对象:
- ‘
type’ - ‘
id’ - 小写的 UUID v4 或提交项的
ID,由 1 到 64 个
‘
[A-Za-z0-9-]’ 字符组成 - ‘
timestamp’ - 发送方的 RFC 3339
时间,形如
‘
2026-01-01T12:00:00.000Z’ - ‘
reply_to’ - 在应答中,为所应答帧的
‘
id’ - ‘
body’ - 该类型的字段(如果有)
有多个种类的对象只有一个字段,该字段以种类命名。保留未知的种类或词。忽略未知的字段或类型。
HANDSHAKE
链路的第一帧是
‘hello’
帧。它的字段为链路命名:
- ‘
machine’ - 每个会话:
‘
name’ 字段和可选的配对码 ‘code’ - ‘
session’ - 一个会话:
‘
name’、‘session’ ID,以及带有客户端最后一个 ‘sequence’ 或 0 的 ‘since’ - ‘
host’ - aude 自用,用于宿主:
‘
session’ 字段,以及 ‘replaces’ 字段中它所替换的 ID - ‘
home’ - aude 自用,为空,用于
aude pair、revoke和tunnel
‘welcome’
帧以相同的字段应答:
- ‘
machine’ - ‘
backlog_count’ 字段,即随后的 ‘machine’ 帧的数量 - ‘
session’ - ‘
record’ 字段,即最后一个条目处的记录, ‘backlog_count’ 字段,即随后发送的 ‘since’ 之后的实录 ‘entry’ 帧的数量,以及客户端提交项所带的 ‘origin’ - ‘
host’、‘home’ - 监听器的
‘
aude_version’
‘origin’ 含有
‘connection’ ID 和
‘name’ 名称。
FRAMES
| 类型 | 发送方 | 内容 |
| hello | 打开方 | 见 HANDSHAKE |
| welcome | 监听器 | 见 HANDSHAKE |
| entry | 监听器 | 一个条目,见 ENTRIES |
| presence | 监听器 | ‘attached’ 或
‘detached’
字段,其值为一个
‘origin’ |
| machine | 监听器 | ‘record’
字段,即新出现或已改变的记录,或
‘removed’
字段,即一个 ID |
| submission | 客户端、监听器 | ‘text’
字段,即一个轮次的文本行,可选的
‘budget’
字段(以秒为单位),以及发给宿主时的
‘origin’ |
| interrupt | 客户端、监听器 | 无,发给宿主时为
‘origin’ |
| request | 客户端 | 见 REQUESTS |
| response | 监听器、宿主 | 见 REQUESTS |
| head | 宿主 | 无,在日志增长之后 |
| ping, pong | 双方 | 无,但 ‘pong’
有 ‘reply_to’ |
| failure | 监听器 | 见 PROTOCOL FAILURES |
ENTRIES
条目有
‘sequence’、‘timestamp’
和 ‘kind’
字段。实录条目就是
aude(1) 的 JSON
条目。其他每个种类都把它的字段放在它的名称之下:
- ‘
settings’ - ‘
conversation’、‘model’、‘alias’、‘effort’、‘agent’、‘context_tokens’、‘branch’ 和 ‘choices’ - ‘
status’ - 宿主的
‘
queue’、‘last’ 和 ‘phase’ 字段,后者为 ‘starting’、‘held’、‘idle’、‘exiting’ 或 ‘busy’ 之一,而 ‘busy’ 带有 ‘submissions’ 和 ‘deadline’ - ‘
gate’ - 见 GATE
- ‘
settled’ - ‘
submission’、‘origin’ 和 ‘fate’ 字段,后者为 ‘answered’、‘dropped’ 或 ‘ran’ - ‘
ended’ - ‘
stopped’、‘refused’、‘instructions_file’、‘died’ 或 ‘unknown_model’ - ‘
began’ - 宿主的
‘
identity’、‘lifetime’ 和 ‘subagent’ - ‘
merged’ - 无
记录的
‘work.state’
说明的是工作。每个
‘settings’ 或
‘status’
条目都替换上一个。只有
‘settled’ 条目的
‘origin’
所属的客户端会显示它。
‘ended’ 是
‘session’
链路的最后一帧。
GATE
‘gate’
不含任何凭据。它有
‘harness’ 和
‘finding’
字段,后者为
‘ok’、‘not_logged_in’、‘other_provider’、‘timed_out’、‘not_found’、‘silent’、‘unreadable’、‘spawn’
或 ‘unreported’
之一。 ‘silent’
带有
‘exit’,‘spawn’
带有
‘detail’。
REQUESTS
| 请求 | 链路 | 内容 |
| start | machine | ‘name’、‘harness’、‘text’、‘budget’、‘working_directory’
和 ‘prerequisites’
字段,以及可选的
‘model’、‘effort’
和 ‘agent’ |
| remove | machine | 一个会话 ID |
| pair | home | 无 |
| revoke | home | ‘device’
字段,其值为一个指纹,或者
‘all’ |
| tunnel | home | 可选的 ‘tunnel’
字段,其值为
aude-tunnel(7)
中的一个词 |
‘response’
帧应答其
‘reply_to’
所指的帧,内容为下列之一:
- ‘
taken’ - ‘
started’、‘continued’ - 记录
- ‘
window’ - ‘
expires’ 和 ‘url’ 字段,后者有 ‘endpoint’ 和 ‘code’ - ‘
paired’ - ‘
name’ 和 ‘fingerprint’ - ‘
reach’ - 用于 ‘
tunnel’ 请求 - ‘
refused’、‘failed’ - wire.schema.json 中的一种情形
‘pair’
请求先得到
‘window’
响应,然后得到
‘paired’
响应,或者得到
‘refused’ 或
‘failed’
响应。每个提交项和中断都得到
‘taken’、‘refused’
或 ‘failed’
响应。
PROTOCOL FAILURES
‘failure’ 帧有
‘code’、‘detail’
和 ‘is_fatal’
字段。致命的失败会关闭链路。
| 代码 | 致命 | 条件 |
| bad_json | 否 | 错误的行、重复的字段、未知的类型或请求、不属于该链路的帧、第二个
‘hello’
帧,或错误的 ID |
| line_too_long | 是 | 超过 8 MiB 的行 |
| unauthorised | 是 | 被拒绝或被撤销的设备、未知的链路,或没有
‘hello’ 帧 |
| busy | 是 | 会话的第二个宿主 |
| not_found | 是 | 机器未持有的会话 |
| internal | 是 | 无法写入 peers.json,或它已改变 |
| retired | 是 | 已退役的名称 |
ADMISSION
收到 ‘hello’
帧时,监听器使用第一条匹配的规则:
- 在 listener.socket 上,它只接受机器的密钥。
- 在端口上,它拒绝机器的密钥。
- 对于指纹在
peers.json
中的密钥,它只在
‘
machine’ 或 ‘session’ 链路上接受。 - 其他密钥在
‘
machine’ 链路上带有打开的配对窗口的配对码时,它配对并接受该密钥。 - 对于错误或过期的配对码,它以
‘
pairing code rejected’ 拒绝。 - 它拒绝没有配对码的密钥。
拒绝是致命的
‘unauthorised’
失败。它的
‘detail’
是规则给出的值,或者是
‘this machine does not list this
device’ 这一值。
LIMITS
‘hello’
帧必须在 30 秒和 16 KiB
之内到达。没有
‘hello’
帧的端口链路超过 8
条时,最早的一条会关闭。静默
15 秒的链路会收到
‘ping’ 帧,30
秒内没有收到
‘pong’
帧时,链路会关闭。名称会被清理,并截断为
48 个标量值。
wire.schema.json
给出每个文本和数组的最大长度。队列中已有
8
个提交项时,新的提交项会得到带有
‘queue_full’ 的
‘dropped’
结果。积压内容按链路读取的速度发送。
EXAMPLES
第一个
‘hello’ 帧:
{"body":{"machine":{"code":"<code>","name":"my phone"}},
"id":"<uuid>","timestamp":"<time>","type":"hello"}
一个
‘submission’ 帧及其
‘entry’ 帧:
{"body":{"budget":300,"text":"hi"},"id":"<id>","timestamp":"<time>",
"type":"submission"}
{"body":{"kind":"user","origin":{"connection":"<id>","name":"my phone"},
"sequence":7,"text":"hi","timestamp":"<time>"},"id":"<uuid>",
"timestamp":"<time>","type":"entry"}