@agentunion/fastaun-browser 0.5.20 → 0.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/_packed_docs/CHANGELOG.md +47 -0
- package/_packed_docs/INDEX.md +453 -440
- package/_packed_docs/KITE_DOCS_GUIDE.md +164 -161
- package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/344/270/216/346/215/242owner/347/274/226/346/216/222/346/226/271/346/241/210.md +530 -0
- package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/345/256/214/346/225/264/350/256/276/350/256/241/344/270/216/345/256/236/346/226/275/350/256/241/345/210/222.md +685 -0
- package/_packed_docs/agent.md/working/agent.md-schema/344/270/216/347/255/276/345/217/221/351/252/214/347/255/276/346/265/201/347/250/213/346/276/204/346/270/205.md +349 -0
- package/_packed_docs/agent.md/working//346/234/254/345/234/260Docker/346/265/213/350/257/225Bug/346/270/205/345/215/225.md +40 -0
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1433 -1392
- package/_packed_docs/protocol/08-AUN-E2EE.md +17 -12
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +2 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +666 -658
- package/_packed_docs/sdk/0.5.21-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +368 -0
- package/_packed_docs/sdk/0.5.21-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +350 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +5 -1
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +64 -64
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +4 -1
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +42 -39
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +147 -14
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +48 -47
- package/_packed_docs/sdk/09-group-rpc-manual.md +5 -2
- package/_packed_docs/sdk/09-message-rpc-manual.md +250 -160
- package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +71 -0
- package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +88 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +134 -130
- package/_packed_docs/sdk/INDEX.md +239 -221
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +930 -922
- package/_packed_docs/sdk/Ownership2.1-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +106 -43
- package/_packed_docs/sdk/Ownership2.1-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +180 -9
- package/_packed_docs/sdk/Ownership2.1-TDD/345/210/206/351/230/266/346/256/265/345/256/236/346/226/275/350/256/241/345/210/222.md +708 -708
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +480 -476
- package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +1 -1
- package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +2 -2
- package/dist/agent-md-schema.d.ts +1 -0
- package/dist/agent-md-schema.d.ts.map +1 -1
- package/dist/agent-md-schema.js +5 -4
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +25 -1
- package/dist/agent-md.d.ts.map +1 -1
- package/dist/agent-md.js +148 -71
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +13 -0
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +55 -8
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.d.ts.map +1 -1
- package/dist/aid.js +2 -1
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +4 -0
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +4981 -1219
- package/dist/cert-utils.d.ts +1 -0
- package/dist/cert-utils.d.ts.map +1 -1
- package/dist/cert-utils.js +21 -0
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +101 -16
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +1172 -160
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +4 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +122 -48
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +22 -3
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +1258 -649
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +23 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +391 -87
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/events.d.ts +19 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +146 -23
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts +42 -1
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +363 -7
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +14 -1
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.d.ts +4 -0
- package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.js +30 -13
- package/dist/keystore/indexeddb-identity-store.js.map +1 -1
- package/dist/keystore/indexeddb-shared.d.ts +19 -2
- package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.js +193 -6
- package/dist/keystore/indexeddb-shared.js.map +1 -1
- package/dist/keystore/indexeddb-token-store.d.ts +15 -2
- package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-token-store.js +308 -27
- package/dist/keystore/indexeddb-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +45 -0
- package/dist/org-protocol.d.ts.map +1 -1
- package/dist/org-protocol.js +757 -11
- package/dist/org-protocol.js.map +1 -1
- package/dist/ownership-v21.d.ts +21 -4
- package/dist/ownership-v21.d.ts.map +1 -1
- package/dist/ownership-v21.js +49 -16
- package/dist/ownership-v21.js.map +1 -1
- package/dist/ownership-workflow.d.ts +30 -0
- package/dist/ownership-workflow.d.ts.map +1 -1
- package/dist/ownership-workflow.js +412 -54
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/seq-tracker.d.ts +2 -0
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +3 -2
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +60 -3
- package/dist/tools/cross-sdk-agent.d.ts.map +1 -1
- package/dist/tools/cross-sdk-agent.js +433 -37
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +3 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +62 -30
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,1392 +1,1433 @@
|
|
|
1
|
-
## 6. 服务协议(业务层)
|
|
2
|
-
|
|
3
|
-
> 本文描述认证完成后的业务层方法。连接与身份认证见对应子协议文档:
|
|
4
|
-
> - 身份与凭证:[01-身份与凭证协议-auth.md](01-身份与凭证协议-auth.md)
|
|
5
|
-
> - Gateway 连接:[03-Gateway-连接模式.md](03-Gateway-连接模式.md)
|
|
6
|
-
> - Peer 对等认证:[04-Peer-子协议.md](04-Peer-子协议.md)
|
|
7
|
-
> - Relay 中继:[05-Relay-子协议.md](05-Relay-子协议.md)
|
|
8
|
-
>
|
|
9
|
-
> 业务层方法与连接拓扑无关。无论使用 gateway、peer 或 relay 模式,认证完成后都可调用以下方法。
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### 6.1 命名空间概览
|
|
14
|
-
|
|
15
|
-
| 命名空间 | 分类 | 功能 | 对应服务 | 传输方式 |
|
|
16
|
-
|---------|------|------|---------|---------|
|
|
17
|
-
| `auth.*` | 核心 | AID 注册、认证、令牌管理 | auth 服务 | WebSocket |
|
|
18
|
-
| `ca.*` | 核心 | 证书签发、续期、吊销 | ca 服务 | WebSocket / HTTP |
|
|
19
|
-
| `message.*` | 核心 | 点对点消息路由、E2EE prekey 管理 | message 服务 | WebSocket |
|
|
20
|
-
| `meta.*` | 核心 | 健康检查、状态查询、受信根证书 | meta 服务 | WebSocket |
|
|
21
|
-
| `storage.*` | 扩展 | 对象存储、大文件上传下载(详见 [11-Storage-子协议.md](11-Storage-子协议.md)) | storage 服务 | WebSocket + HTTP |
|
|
22
|
-
| `group.*` | 扩展 | 群组管理、群消息、资源共享(详见 [10-Group-子协议.md](10-Group-子协议.md)) | group 服务 | WebSocket |
|
|
23
|
-
| `mail.*` | 扩展 | 邮件服务 | mail 服务 | WebSocket |
|
|
24
|
-
| `stream.*` | 扩展 | 实时流式传输(详见 [12-Stream-子协议.md](12-Stream-子协议.md)) | stream 服务 | WebSocket + HTTP SSE |
|
|
25
|
-
| `proxy.*` | 扩展 | Service Proxy 服务列表控制面 | Gateway 本地处理 / service_proxy 查询 | WebSocket |
|
|
26
|
-
| `search.*` | 扩展 | Agent 搜索与发现 | search 服务 | WebSocket |
|
|
27
|
-
| `relay.*` | 扩展 | NAT 穿透中继(详见 [05-Relay-子协议.md](05-Relay-子协议.md)) | relay 服务 | WebSocket |
|
|
28
|
-
| `peer.*` | 协议定义 | 点对点直连(详见 [04-Peer-子协议.md](04-Peer-子协议.md)) | 无对应服务 | WebSocket |
|
|
29
|
-
| `task.*` | 协议定义 | Agent 协作与任务执行 | 无对应服务 | WebSocket |
|
|
30
|
-
|
|
31
|
-
**控制面与数据面分离**:
|
|
32
|
-
|
|
33
|
-
- `message.*` 用于传递消息语义、小型结构化负载和控制信息,不承担大对象传输职责
|
|
34
|
-
- `storage.*` 用于承载大文件、大对象及附件内容的上传、下载与持久保存
|
|
35
|
-
- `stream.*` 用于实时流式传输(LLM 输出、数据推送等),控制面通过 RPC 管理流生命周期,数据面通过独立端口的 WebSocket(推流)和 HTTP SSE(拉流)传输
|
|
36
|
-
- 大文件、二进制附件、长时流式内容不应直接嵌入 `message.*` 的 `payload`,应先经 `storage.*` 存储,再由 `message.*` 传递对象引用
|
|
37
|
-
- 实现应分别对 `message.*` 的消息体大小和 `storage.*` 的对象大小进行独立限制
|
|
38
|
-
|
|
39
|
-
**应用层扩展服务**本身也是 AID 持有者,通过核心协议(`message.*`)与客户端通信。客户端可以选择使用或不使用这些扩展服务。
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
### 6.2 Service Proxy 服务列表控制面 `proxy.*`
|
|
44
|
-
|
|
45
|
-
`proxy.*` 是 AUN Service Proxy 的控制面命名空间,用于 provider 通过 Gateway 长连接声明自己能够通过 Service Proxy 暴露哪些服务。它不承载 HTTP/WS 数据面流量;真实访问数据面由 `service_proxy` 模块的独立 proxy-server 隧道处理。
|
|
46
|
-
|
|
47
|
-
#### 控制面与数据面
|
|
48
|
-
|
|
49
|
-
- **Gateway 控制面**:provider 的 AUN 长连接调用 `proxy.register_services` / `proxy.unregister_services` / `proxy.list_services`。Gateway 记录每个 provider 长连接声明的服务摘要,供 `service_proxy` 模块判断 provider 是否在线、是否声明目标服务。
|
|
50
|
-
- **proxy-server 数据面**:service-proxy-client 连接 `service_proxy` 模块的 `/ws/client` 后,认证成功后必须再次发送隧道消息 `register_services`。proxy-server 只向已在本地数据面连接并注册目标服务的 provider 隧道转发请求。
|
|
51
|
-
- **服务列表生命周期**:Gateway 控制面服务列表绑定 Gateway 长连接;proxy-server 数据面服务列表绑定 proxy-server 隧道连接。连接断开后对应服务列表必须清理。
|
|
52
|
-
- **一致性要求**:同一 provider AID 的多个实例可以同时在线,但它们注册的服务列表必须一致。这里的一致性以清洗后的服务摘要为准,包括 `service_name`、`service_type`、`visibility` 和非敏感 `metadata`。
|
|
53
|
-
- **粘性路由**:同一 provider AID 的多个实例若提供相同服务,proxy-server 必须对同一访问亲和键保持稳定路由;亲和键可由 requester AID、客户端 IP、provider AID 和服务名组合得到。
|
|
54
|
-
|
|
55
|
-
#### 服务摘要
|
|
56
|
-
|
|
57
|
-
服务摘要不得包含内网 endpoint、token、cookie、私钥、证书等敏感字段。实现必须在 Gateway 控制面和 proxy-server 数据面分别清洗摘要,不能依赖共享代码。
|
|
58
|
-
|
|
59
|
-
```json
|
|
60
|
-
{
|
|
61
|
-
"service_name": "fileshare",
|
|
62
|
-
"service_type": "http",
|
|
63
|
-
"visibility": "public",
|
|
64
|
-
"metadata": {"label": "Files"}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
| 字段 | 必需 | 说明 |
|
|
69
|
-
|------|:----:|------|
|
|
70
|
-
| `service_name` | ✅ | 服务名,只允许小写字母、数字、`_`、`-`;不得使用 `api`、`health`、`proxy`、`ws` 等保留名 |
|
|
71
|
-
| `service_type` | ❌ | 服务类型,默认 `http`;可用于提示 `http` / `sse` / `websocket` / `mcp` / `file` 等 |
|
|
72
|
-
| `visibility` | ❌ | 访问策略,默认 `private`;当前实现支持 `public`、`private`、`aun-auth` |
|
|
73
|
-
| `metadata` | ❌ | 非敏感元数据;实现必须过滤 endpoint、url、token、authorization、cookie、secret、private_key、cert 等敏感键 |
|
|
74
|
-
|
|
75
|
-
#### `proxy.register_services`
|
|
76
|
-
|
|
77
|
-
注册当前 Gateway 长连接提供的 Service Proxy 服务列表。服务端必须以连接认证得到的 AID 作为 provider AID;客户端传入的 `provider_aid` 只能作为兼容字段或诊断字段,不能覆盖认证身份。
|
|
78
|
-
|
|
79
|
-
**请求**:
|
|
80
|
-
```json
|
|
81
|
-
{
|
|
82
|
-
"jsonrpc": "2.0",
|
|
83
|
-
"id": "reg-1",
|
|
84
|
-
"method": "proxy.register_services",
|
|
85
|
-
"params": {
|
|
86
|
-
"provider_aid": "alice.agentid.pub",
|
|
87
|
-
"services": [{
|
|
88
|
-
"service_name": "fileshare",
|
|
89
|
-
"service_type": "http",
|
|
90
|
-
"visibility": "public",
|
|
91
|
-
"metadata": {"label": "Files"}
|
|
92
|
-
}]
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**响应**:
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"jsonrpc": "2.0",
|
|
101
|
-
"id": "reg-1",
|
|
102
|
-
"result": {
|
|
103
|
-
"ok": true,
|
|
104
|
-
"provider_aid": "alice.agentid.pub",
|
|
105
|
-
"connection_id": "conn-1",
|
|
106
|
-
"count": 1,
|
|
107
|
-
"services": [{
|
|
108
|
-
"service_name": "fileshare",
|
|
109
|
-
"service_type": "http",
|
|
110
|
-
"visibility": "public",
|
|
111
|
-
"metadata": {"label": "Files"}
|
|
112
|
-
}]
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
#### `proxy.unregister_services`
|
|
118
|
-
|
|
119
|
-
注销当前 Gateway 长连接上的部分或全部 Service Proxy 服务。省略 `service_names` 时注销该连接全部服务。
|
|
120
|
-
|
|
121
|
-
```json
|
|
122
|
-
{
|
|
123
|
-
"jsonrpc": "2.0",
|
|
124
|
-
"id": "unreg-1",
|
|
125
|
-
"method": "proxy.unregister_services",
|
|
126
|
-
"params": {"service_names": ["fileshare"]}
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
响应包含 `removed` 和剩余 `count`。如果同一 provider AID 还有其他连接,部分注销导致服务列表不一致时,服务端应拒绝该操作。
|
|
131
|
-
|
|
132
|
-
#### `proxy.list_services`
|
|
133
|
-
|
|
134
|
-
列出当前 Gateway 长连接已注册的服务摘要。
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
{
|
|
138
|
-
"jsonrpc": "2.0",
|
|
139
|
-
"id": "list-1",
|
|
140
|
-
"method": "proxy.list_services",
|
|
141
|
-
"params": {}
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
#### 内部查询 `gateway.query_proxy_services`
|
|
146
|
-
|
|
147
|
-
`gateway.query_proxy_services` 是 service_proxy 模块调用 Gateway 的内部模块 RPC,不是普通客户端公开方法。调用方必须是 `service_proxy` 模块。
|
|
148
|
-
|
|
149
|
-
请求参数:
|
|
150
|
-
|
|
151
|
-
| 参数 | 必需 | 说明 |
|
|
152
|
-
|------|:----:|------|
|
|
153
|
-
| `provider_aid` | ✅ | 被访问 provider AID |
|
|
154
|
-
| `service_name` | ❌ | 目标服务名;为空时只查询 provider 在线和服务列表概览 |
|
|
155
|
-
|
|
156
|
-
响应字段:
|
|
157
|
-
|
|
158
|
-
| 字段 | 说明 |
|
|
159
|
-
|------|------|
|
|
160
|
-
| `provider_aid_exists` | Gateway 通过 CA 证书查询确认 provider AID 是否存在;查询失败时为 `null` |
|
|
161
|
-
| `provider_online` | provider 是否存在 Gateway 长连接 |
|
|
162
|
-
| `has_registered_services` | 在线连接中是否已有 proxy 服务列表注册 |
|
|
163
|
-
| `service_registered` | 指定 `service_name` 是否已由在线 provider 注册 |
|
|
164
|
-
| `service_names` | 当前 provider 声明的服务名集合 |
|
|
165
|
-
| `connections` | 已注册服务列表的 Gateway 长连接摘要 |
|
|
166
|
-
| `matched_connections` | 注册了指定服务的 Gateway 长连接摘要 |
|
|
167
|
-
|
|
168
|
-
#### proxy-server well-known 发现
|
|
169
|
-
|
|
170
|
-
proxy-client 不得由应用外部传入、配置或硬拼 proxy-server 地址。连接 proxy-server 前必须先执行发现:
|
|
171
|
-
|
|
172
|
-
1. 优先请求 `https://{provider_aid}/.well-known/aun-proxy`。
|
|
173
|
-
2. 请求失败时回退 `https://proxy.{issuer}/.well-known/aun-proxy`。
|
|
174
|
-
3. 发现结果可缓存到 provider AID 本地 SQLite metadata,缓存 TTL 为 1 小时。
|
|
175
|
-
|
|
176
|
-
响应示例:
|
|
177
|
-
|
|
178
|
-
```json
|
|
179
|
-
{
|
|
180
|
-
"issuer": "agentid.pub",
|
|
181
|
-
"provider_aid": "alice.agentid.pub",
|
|
182
|
-
"proxy_host": "proxy.agentid.pub",
|
|
183
|
-
"https_url": "https://proxy.agentid.pub:19890",
|
|
184
|
-
"ws_url": "wss://proxy.agentid.pub:19890/ws/client",
|
|
185
|
-
"proxy_servers": [{
|
|
186
|
-
"https_url": "https://proxy.agentid.pub:19890",
|
|
187
|
-
"ws_url": "wss://proxy.agentid.pub:19890/ws/client",
|
|
188
|
-
"priority": 1
|
|
189
|
-
}]
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
proxy-client 连接 `ws_url` 时必须带 `Authorization: Bearer <access_token>`。`access_token` 优先复用本地 cached token;缓存缺失或过期时,必须通过 AUNClient 向 Gateway 完成两步登录取得新 token。
|
|
194
|
-
|
|
195
|
-
#### proxy-server 隧道注册
|
|
196
|
-
|
|
197
|
-
service-proxy-client 连接 `service_proxy` 模块的 `/ws/client` 后,认证成功后必须发送:
|
|
198
|
-
|
|
199
|
-
```json
|
|
200
|
-
{
|
|
201
|
-
"type": "register_services",
|
|
202
|
-
"request_id": "reg-1",
|
|
203
|
-
"services": [{
|
|
204
|
-
"service_name": "fileshare",
|
|
205
|
-
"service_type": "http",
|
|
206
|
-
"visibility": "public",
|
|
207
|
-
"metadata": {"label": "Files"}
|
|
208
|
-
}]
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
成功响应:
|
|
213
|
-
|
|
214
|
-
```json
|
|
215
|
-
{"type": "register_services_ack", "request_id": "reg-1", "ok": true, "count": 1}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
若同一 provider AID 的另一条 proxy-server 隧道已注册不同服务列表,proxy-server 必须返回:
|
|
219
|
-
|
|
220
|
-
```json
|
|
221
|
-
{
|
|
222
|
-
"type": "service_proxy_error",
|
|
223
|
-
"request_id": "reg-1",
|
|
224
|
-
"error": {
|
|
225
|
-
"code": "proxy_services_inconsistent",
|
|
226
|
-
"message": "provider service list is inconsistent with existing connections"
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
#### 路由与 wakeup 策略
|
|
232
|
-
|
|
233
|
-
proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等价路由时,必须按以下顺序决策:
|
|
234
|
-
|
|
235
|
-
1. 本地 proxy-server 连接索引中存在 `(provider_aid, service_name)`:直接选择对应数据面连接;多连接时按亲和键稳定选择。
|
|
236
|
-
2. provider 已连接本 proxy-server 且已注册服务列表,但没有目标服务:返回 `service_not_registered`,不得 wakeup。
|
|
237
|
-
3. provider 未连接本 proxy-server 时,查询 Gateway 控制面:
|
|
238
|
-
- `provider_aid_exists=false`:返回 `provider_aid_not_found`。
|
|
239
|
-
- `provider_aid_exists=null`:返回 `provider_aid_check_failed`。
|
|
240
|
-
- `provider_online=false`:返回 `provider_offline`。
|
|
241
|
-
- `provider_online=true` 且 `service_registered=false`:返回 `service_not_registered`,不得 wakeup。
|
|
242
|
-
- `provider_online=true` 且 `service_registered=true`:通过 Gateway 向注册了目标服务的 provider 长连接发送 `app.service_proxy.wakeup`。
|
|
243
|
-
4. wakeup 已投递但本 proxy-server 仍未等到目标服务注册时,返回 `provider_wakeup_timeout`。
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
### 6.3 点对点消息 `message.*`
|
|
248
|
-
|
|
249
|
-
**设计原则**:
|
|
250
|
-
|
|
251
|
-
- **无会话生命周期**:不需要 create/invite/join/close 流程,直接发送即可
|
|
252
|
-
- **投递语义由 `delivery_mode` 决定**:`fanout` 会进入离线历史并广播到同一 AID 的在线实例;`queue` 只做实时单实例投递,不进入历史存储
|
|
253
|
-
- **控制面与数据面分离**:`message.*` 承载消息语义和小型结构化数据;附件、大对象应通过 `storage.*` 传输,消息中只保留引用
|
|
254
|
-
|
|
255
|
-
> 本节仅适用于 P2P `message.*`。`group.send` 不支持 `queue`,群消息始终是 fanout 语义。
|
|
256
|
-
|
|
257
|
-
**消息存储模型**:
|
|
258
|
-
|
|
259
|
-
| `delivery_mode.mode` | 投递方式 | 存储位置 | 生命周期 | 适用场景 |
|
|
260
|
-
|----------------------|----------|---------|---------|---------|
|
|
261
|
-
| `queue` | 单实例实时消费 | 内存环形缓冲 | 有限时间窗口(默认 5 分钟)+ 有限条数(默认 200 条/AID) | Worker/执行器消费、同一发送者尽量命中同一实例 |
|
|
262
|
-
| `fanout` | 广播到在线实例 | 数据库 + 文件存储 | TTL 过期前持久保存(默认 24 小时) | 离线送达、历史查询、多实例同步接收 |
|
|
263
|
-
|
|
264
|
-
**序列号机制**:
|
|
265
|
-
|
|
266
|
-
- `ttl <= 0` 的现有消息在收件人维度分配递增 `seq`
|
|
267
|
-
- `ttl > 0` 的 volatile 消息不分配持久 `seq`,使用独立 opaque `volatile_cursor`
|
|
268
|
-
- 客户端通过 `after_seq` 游标增量拉取,支持多设备各自维护进度
|
|
269
|
-
- `message.pull` 分别读取持久流与 volatile 流,并按服务端创建时间稳定合并
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
|
297
|
-
|
|
298
|
-
| `
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
302
|
-
| `
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
```json
|
|
400
|
-
{
|
|
401
|
-
"jsonrpc": "2.0",
|
|
402
|
-
"id": 11,
|
|
403
|
-
"
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
|
457
|
-
|
|
458
|
-
| `
|
|
459
|
-
| `
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
|
464
|
-
|
|
465
|
-
| `
|
|
466
|
-
| `
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
| `
|
|
500
|
-
| `
|
|
501
|
-
| `
|
|
502
|
-
| `
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
| `
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
"
|
|
605
|
-
"
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
"
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
- `
|
|
731
|
-
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
"
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
"
|
|
751
|
-
"
|
|
752
|
-
"
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
`
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
|
818
|
-
|
|
819
|
-
| `
|
|
820
|
-
| `
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
```
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
```
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
"
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
```
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
```
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
"
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
"
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
"
|
|
1004
|
-
"
|
|
1005
|
-
"
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
```
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
```json
|
|
1174
|
-
{"jsonrpc": "2.0", "id":
|
|
1175
|
-
```
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
```
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
```
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
```
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
```
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
```
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
```
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
| 错误码 | 名称 | 说明 |
|
|
1367
|
-
|-------:|------|------|
|
|
1368
|
-
| `-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
-
|
|
1391
|
-
-
|
|
1392
|
-
-
|
|
1
|
+
## 6. 服务协议(业务层)
|
|
2
|
+
|
|
3
|
+
> 本文描述认证完成后的业务层方法。连接与身份认证见对应子协议文档:
|
|
4
|
+
> - 身份与凭证:[01-身份与凭证协议-auth.md](01-身份与凭证协议-auth.md)
|
|
5
|
+
> - Gateway 连接:[03-Gateway-连接模式.md](03-Gateway-连接模式.md)
|
|
6
|
+
> - Peer 对等认证:[04-Peer-子协议.md](04-Peer-子协议.md)
|
|
7
|
+
> - Relay 中继:[05-Relay-子协议.md](05-Relay-子协议.md)
|
|
8
|
+
>
|
|
9
|
+
> 业务层方法与连接拓扑无关。无论使用 gateway、peer 或 relay 模式,认证完成后都可调用以下方法。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### 6.1 命名空间概览
|
|
14
|
+
|
|
15
|
+
| 命名空间 | 分类 | 功能 | 对应服务 | 传输方式 |
|
|
16
|
+
|---------|------|------|---------|---------|
|
|
17
|
+
| `auth.*` | 核心 | AID 注册、认证、令牌管理 | auth 服务 | WebSocket |
|
|
18
|
+
| `ca.*` | 核心 | 证书签发、续期、吊销 | ca 服务 | WebSocket / HTTP |
|
|
19
|
+
| `message.*` | 核心 | 点对点消息路由、E2EE prekey 管理 | message 服务 | WebSocket |
|
|
20
|
+
| `meta.*` | 核心 | 健康检查、状态查询、受信根证书 | meta 服务 | WebSocket |
|
|
21
|
+
| `storage.*` | 扩展 | 对象存储、大文件上传下载(详见 [11-Storage-子协议.md](11-Storage-子协议.md)) | storage 服务 | WebSocket + HTTP |
|
|
22
|
+
| `group.*` | 扩展 | 群组管理、群消息、资源共享(详见 [10-Group-子协议.md](10-Group-子协议.md)) | group 服务 | WebSocket |
|
|
23
|
+
| `mail.*` | 扩展 | 邮件服务 | mail 服务 | WebSocket |
|
|
24
|
+
| `stream.*` | 扩展 | 实时流式传输(详见 [12-Stream-子协议.md](12-Stream-子协议.md)) | stream 服务 | WebSocket + HTTP SSE |
|
|
25
|
+
| `proxy.*` | 扩展 | Service Proxy 服务列表控制面 | Gateway 本地处理 / service_proxy 查询 | WebSocket |
|
|
26
|
+
| `search.*` | 扩展 | Agent 搜索与发现 | search 服务 | WebSocket |
|
|
27
|
+
| `relay.*` | 扩展 | NAT 穿透中继(详见 [05-Relay-子协议.md](05-Relay-子协议.md)) | relay 服务 | WebSocket |
|
|
28
|
+
| `peer.*` | 协议定义 | 点对点直连(详见 [04-Peer-子协议.md](04-Peer-子协议.md)) | 无对应服务 | WebSocket |
|
|
29
|
+
| `task.*` | 协议定义 | Agent 协作与任务执行 | 无对应服务 | WebSocket |
|
|
30
|
+
|
|
31
|
+
**控制面与数据面分离**:
|
|
32
|
+
|
|
33
|
+
- `message.*` 用于传递消息语义、小型结构化负载和控制信息,不承担大对象传输职责
|
|
34
|
+
- `storage.*` 用于承载大文件、大对象及附件内容的上传、下载与持久保存
|
|
35
|
+
- `stream.*` 用于实时流式传输(LLM 输出、数据推送等),控制面通过 RPC 管理流生命周期,数据面通过独立端口的 WebSocket(推流)和 HTTP SSE(拉流)传输
|
|
36
|
+
- 大文件、二进制附件、长时流式内容不应直接嵌入 `message.*` 的 `payload`,应先经 `storage.*` 存储,再由 `message.*` 传递对象引用
|
|
37
|
+
- 实现应分别对 `message.*` 的消息体大小和 `storage.*` 的对象大小进行独立限制
|
|
38
|
+
|
|
39
|
+
**应用层扩展服务**本身也是 AID 持有者,通过核心协议(`message.*`)与客户端通信。客户端可以选择使用或不使用这些扩展服务。
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### 6.2 Service Proxy 服务列表控制面 `proxy.*`
|
|
44
|
+
|
|
45
|
+
`proxy.*` 是 AUN Service Proxy 的控制面命名空间,用于 provider 通过 Gateway 长连接声明自己能够通过 Service Proxy 暴露哪些服务。它不承载 HTTP/WS 数据面流量;真实访问数据面由 `service_proxy` 模块的独立 proxy-server 隧道处理。
|
|
46
|
+
|
|
47
|
+
#### 控制面与数据面
|
|
48
|
+
|
|
49
|
+
- **Gateway 控制面**:provider 的 AUN 长连接调用 `proxy.register_services` / `proxy.unregister_services` / `proxy.list_services`。Gateway 记录每个 provider 长连接声明的服务摘要,供 `service_proxy` 模块判断 provider 是否在线、是否声明目标服务。
|
|
50
|
+
- **proxy-server 数据面**:service-proxy-client 连接 `service_proxy` 模块的 `/ws/client` 后,认证成功后必须再次发送隧道消息 `register_services`。proxy-server 只向已在本地数据面连接并注册目标服务的 provider 隧道转发请求。
|
|
51
|
+
- **服务列表生命周期**:Gateway 控制面服务列表绑定 Gateway 长连接;proxy-server 数据面服务列表绑定 proxy-server 隧道连接。连接断开后对应服务列表必须清理。
|
|
52
|
+
- **一致性要求**:同一 provider AID 的多个实例可以同时在线,但它们注册的服务列表必须一致。这里的一致性以清洗后的服务摘要为准,包括 `service_name`、`service_type`、`visibility` 和非敏感 `metadata`。
|
|
53
|
+
- **粘性路由**:同一 provider AID 的多个实例若提供相同服务,proxy-server 必须对同一访问亲和键保持稳定路由;亲和键可由 requester AID、客户端 IP、provider AID 和服务名组合得到。
|
|
54
|
+
|
|
55
|
+
#### 服务摘要
|
|
56
|
+
|
|
57
|
+
服务摘要不得包含内网 endpoint、token、cookie、私钥、证书等敏感字段。实现必须在 Gateway 控制面和 proxy-server 数据面分别清洗摘要,不能依赖共享代码。
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"service_name": "fileshare",
|
|
62
|
+
"service_type": "http",
|
|
63
|
+
"visibility": "public",
|
|
64
|
+
"metadata": {"label": "Files"}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| 字段 | 必需 | 说明 |
|
|
69
|
+
|------|:----:|------|
|
|
70
|
+
| `service_name` | ✅ | 服务名,只允许小写字母、数字、`_`、`-`;不得使用 `api`、`health`、`proxy`、`ws` 等保留名 |
|
|
71
|
+
| `service_type` | ❌ | 服务类型,默认 `http`;可用于提示 `http` / `sse` / `websocket` / `mcp` / `file` 等 |
|
|
72
|
+
| `visibility` | ❌ | 访问策略,默认 `private`;当前实现支持 `public`、`private`、`aun-auth` |
|
|
73
|
+
| `metadata` | ❌ | 非敏感元数据;实现必须过滤 endpoint、url、token、authorization、cookie、secret、private_key、cert 等敏感键 |
|
|
74
|
+
|
|
75
|
+
#### `proxy.register_services`
|
|
76
|
+
|
|
77
|
+
注册当前 Gateway 长连接提供的 Service Proxy 服务列表。服务端必须以连接认证得到的 AID 作为 provider AID;客户端传入的 `provider_aid` 只能作为兼容字段或诊断字段,不能覆盖认证身份。
|
|
78
|
+
|
|
79
|
+
**请求**:
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"jsonrpc": "2.0",
|
|
83
|
+
"id": "reg-1",
|
|
84
|
+
"method": "proxy.register_services",
|
|
85
|
+
"params": {
|
|
86
|
+
"provider_aid": "alice.agentid.pub",
|
|
87
|
+
"services": [{
|
|
88
|
+
"service_name": "fileshare",
|
|
89
|
+
"service_type": "http",
|
|
90
|
+
"visibility": "public",
|
|
91
|
+
"metadata": {"label": "Files"}
|
|
92
|
+
}]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**响应**:
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"jsonrpc": "2.0",
|
|
101
|
+
"id": "reg-1",
|
|
102
|
+
"result": {
|
|
103
|
+
"ok": true,
|
|
104
|
+
"provider_aid": "alice.agentid.pub",
|
|
105
|
+
"connection_id": "conn-1",
|
|
106
|
+
"count": 1,
|
|
107
|
+
"services": [{
|
|
108
|
+
"service_name": "fileshare",
|
|
109
|
+
"service_type": "http",
|
|
110
|
+
"visibility": "public",
|
|
111
|
+
"metadata": {"label": "Files"}
|
|
112
|
+
}]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### `proxy.unregister_services`
|
|
118
|
+
|
|
119
|
+
注销当前 Gateway 长连接上的部分或全部 Service Proxy 服务。省略 `service_names` 时注销该连接全部服务。
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"jsonrpc": "2.0",
|
|
124
|
+
"id": "unreg-1",
|
|
125
|
+
"method": "proxy.unregister_services",
|
|
126
|
+
"params": {"service_names": ["fileshare"]}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
响应包含 `removed` 和剩余 `count`。如果同一 provider AID 还有其他连接,部分注销导致服务列表不一致时,服务端应拒绝该操作。
|
|
131
|
+
|
|
132
|
+
#### `proxy.list_services`
|
|
133
|
+
|
|
134
|
+
列出当前 Gateway 长连接已注册的服务摘要。
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"jsonrpc": "2.0",
|
|
139
|
+
"id": "list-1",
|
|
140
|
+
"method": "proxy.list_services",
|
|
141
|
+
"params": {}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### 内部查询 `gateway.query_proxy_services`
|
|
146
|
+
|
|
147
|
+
`gateway.query_proxy_services` 是 service_proxy 模块调用 Gateway 的内部模块 RPC,不是普通客户端公开方法。调用方必须是 `service_proxy` 模块。
|
|
148
|
+
|
|
149
|
+
请求参数:
|
|
150
|
+
|
|
151
|
+
| 参数 | 必需 | 说明 |
|
|
152
|
+
|------|:----:|------|
|
|
153
|
+
| `provider_aid` | ✅ | 被访问 provider AID |
|
|
154
|
+
| `service_name` | ❌ | 目标服务名;为空时只查询 provider 在线和服务列表概览 |
|
|
155
|
+
|
|
156
|
+
响应字段:
|
|
157
|
+
|
|
158
|
+
| 字段 | 说明 |
|
|
159
|
+
|------|------|
|
|
160
|
+
| `provider_aid_exists` | Gateway 通过 CA 证书查询确认 provider AID 是否存在;查询失败时为 `null` |
|
|
161
|
+
| `provider_online` | provider 是否存在 Gateway 长连接 |
|
|
162
|
+
| `has_registered_services` | 在线连接中是否已有 proxy 服务列表注册 |
|
|
163
|
+
| `service_registered` | 指定 `service_name` 是否已由在线 provider 注册 |
|
|
164
|
+
| `service_names` | 当前 provider 声明的服务名集合 |
|
|
165
|
+
| `connections` | 已注册服务列表的 Gateway 长连接摘要 |
|
|
166
|
+
| `matched_connections` | 注册了指定服务的 Gateway 长连接摘要 |
|
|
167
|
+
|
|
168
|
+
#### proxy-server well-known 发现
|
|
169
|
+
|
|
170
|
+
proxy-client 不得由应用外部传入、配置或硬拼 proxy-server 地址。连接 proxy-server 前必须先执行发现:
|
|
171
|
+
|
|
172
|
+
1. 优先请求 `https://{provider_aid}/.well-known/aun-proxy`。
|
|
173
|
+
2. 请求失败时回退 `https://proxy.{issuer}/.well-known/aun-proxy`。
|
|
174
|
+
3. 发现结果可缓存到 provider AID 本地 SQLite metadata,缓存 TTL 为 1 小时。
|
|
175
|
+
|
|
176
|
+
响应示例:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"issuer": "agentid.pub",
|
|
181
|
+
"provider_aid": "alice.agentid.pub",
|
|
182
|
+
"proxy_host": "proxy.agentid.pub",
|
|
183
|
+
"https_url": "https://proxy.agentid.pub:19890",
|
|
184
|
+
"ws_url": "wss://proxy.agentid.pub:19890/ws/client",
|
|
185
|
+
"proxy_servers": [{
|
|
186
|
+
"https_url": "https://proxy.agentid.pub:19890",
|
|
187
|
+
"ws_url": "wss://proxy.agentid.pub:19890/ws/client",
|
|
188
|
+
"priority": 1
|
|
189
|
+
}]
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
proxy-client 连接 `ws_url` 时必须带 `Authorization: Bearer <access_token>`。`access_token` 优先复用本地 cached token;缓存缺失或过期时,必须通过 AUNClient 向 Gateway 完成两步登录取得新 token。
|
|
194
|
+
|
|
195
|
+
#### proxy-server 隧道注册
|
|
196
|
+
|
|
197
|
+
service-proxy-client 连接 `service_proxy` 模块的 `/ws/client` 后,认证成功后必须发送:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"type": "register_services",
|
|
202
|
+
"request_id": "reg-1",
|
|
203
|
+
"services": [{
|
|
204
|
+
"service_name": "fileshare",
|
|
205
|
+
"service_type": "http",
|
|
206
|
+
"visibility": "public",
|
|
207
|
+
"metadata": {"label": "Files"}
|
|
208
|
+
}]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
成功响应:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{"type": "register_services_ack", "request_id": "reg-1", "ok": true, "count": 1}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
若同一 provider AID 的另一条 proxy-server 隧道已注册不同服务列表,proxy-server 必须返回:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"type": "service_proxy_error",
|
|
223
|
+
"request_id": "reg-1",
|
|
224
|
+
"error": {
|
|
225
|
+
"code": "proxy_services_inconsistent",
|
|
226
|
+
"message": "provider service list is inconsistent with existing connections"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### 路由与 wakeup 策略
|
|
232
|
+
|
|
233
|
+
proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等价路由时,必须按以下顺序决策:
|
|
234
|
+
|
|
235
|
+
1. 本地 proxy-server 连接索引中存在 `(provider_aid, service_name)`:直接选择对应数据面连接;多连接时按亲和键稳定选择。
|
|
236
|
+
2. provider 已连接本 proxy-server 且已注册服务列表,但没有目标服务:返回 `service_not_registered`,不得 wakeup。
|
|
237
|
+
3. provider 未连接本 proxy-server 时,查询 Gateway 控制面:
|
|
238
|
+
- `provider_aid_exists=false`:返回 `provider_aid_not_found`。
|
|
239
|
+
- `provider_aid_exists=null`:返回 `provider_aid_check_failed`。
|
|
240
|
+
- `provider_online=false`:返回 `provider_offline`。
|
|
241
|
+
- `provider_online=true` 且 `service_registered=false`:返回 `service_not_registered`,不得 wakeup。
|
|
242
|
+
- `provider_online=true` 且 `service_registered=true`:通过 Gateway 向注册了目标服务的 provider 长连接发送 `app.service_proxy.wakeup`。
|
|
243
|
+
4. wakeup 已投递但本 proxy-server 仍未等到目标服务注册时,返回 `provider_wakeup_timeout`。
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### 6.3 点对点消息 `message.*`
|
|
248
|
+
|
|
249
|
+
**设计原则**:
|
|
250
|
+
|
|
251
|
+
- **无会话生命周期**:不需要 create/invite/join/close 流程,直接发送即可
|
|
252
|
+
- **投递语义由 `delivery_mode` 决定**:`fanout` 会进入离线历史并广播到同一 AID 的在线实例;`queue` 只做实时单实例投递,不进入历史存储
|
|
253
|
+
- **控制面与数据面分离**:`message.*` 承载消息语义和小型结构化数据;附件、大对象应通过 `storage.*` 传输,消息中只保留引用
|
|
254
|
+
|
|
255
|
+
> 本节仅适用于 P2P `message.*`。`group.send` 不支持 `queue`,群消息始终是 fanout 语义。
|
|
256
|
+
|
|
257
|
+
**消息存储模型**:
|
|
258
|
+
|
|
259
|
+
| `delivery_mode.mode` | 投递方式 | 存储位置 | 生命周期 | 适用场景 |
|
|
260
|
+
|----------------------|----------|---------|---------|---------|
|
|
261
|
+
| `queue` | 单实例实时消费 | 内存环形缓冲 | 有限时间窗口(默认 5 分钟)+ 有限条数(默认 200 条/AID) | Worker/执行器消费、同一发送者尽量命中同一实例 |
|
|
262
|
+
| `fanout` | 广播到在线实例 | 数据库 + 文件存储 | TTL 过期前持久保存(默认 24 小时) | 离线送达、历史查询、多实例同步接收 |
|
|
263
|
+
|
|
264
|
+
**序列号机制**:
|
|
265
|
+
|
|
266
|
+
- `ttl <= 0` 的现有消息在收件人维度分配递增 `seq`
|
|
267
|
+
- `ttl > 0` 的 volatile 消息不分配持久 `seq`,使用独立 opaque `volatile_cursor`
|
|
268
|
+
- 客户端通过 `after_seq` 游标增量拉取,支持多设备各自维护进度
|
|
269
|
+
- `message.pull` 分别读取持久流与 volatile 流,并按服务端创建时间稳定合并
|
|
270
|
+
|
|
271
|
+
**按对端隔离消费(`p2p_peer_pull_v1`)**:新 SDK 在 `auth.connect.capabilities` 中声明严格布尔值 `p2p_peer_pull_v1: true`。Gateway 将连接能力作为可信认证上下文传给 Message 服务,并在上线、重连后发送待同步提示;能力不由发送消息时的在线状态决定。旧 SDK 继续使用 global Pull/ACK。新 SDK 使用 `cursor_scope="peer"` 与完整 `sender_aid`,按接收方 AID、认证设备、内部消费 slot 和发送方隔离游标;原设备共享 `seq`、消息密文及群组 Pull/ACK 模型保持不变,不分配 `peer_seq`,不逐条回填历史。
|
|
272
|
+
|
|
273
|
+
首次进入 peer 模式时,服务端原子冻结同设备、同 slot 的旧 `server_acked_seq` 为 `bootstrap_floor_seq`;无旧记录为 0,已有 peer ACK 优先。每个新 peer 从该固定基线初始化,不能用后来变化的旧 global ACK 跳过历史。peer ACK 不推进旧 global ACK;同一设备降级到旧 SDK 可能重拉,应用必须幂等。当前 peer 模式只支持单 Message 服务实例,单实例内可有多个 writer shard;多实例支持留待 AUN 分布式 2.0。
|
|
274
|
+
|
|
275
|
+
#### `message.send`
|
|
276
|
+
|
|
277
|
+
发送 P2P 消息。
|
|
278
|
+
|
|
279
|
+
**请求**:
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"jsonrpc": "2.0",
|
|
283
|
+
"id": 10,
|
|
284
|
+
"method": "message.send",
|
|
285
|
+
"params": {
|
|
286
|
+
"to": "bob.aid.pub",
|
|
287
|
+
"device_id": "bob-phone",
|
|
288
|
+
"ttl": 300,
|
|
289
|
+
"payload": {"type": "text", "text": "你好"}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**参数**:
|
|
295
|
+
|
|
296
|
+
| 参数 | 必需 | 说明 |
|
|
297
|
+
|------|:----:|------|
|
|
298
|
+
| `to` | ✅ | 接收者 AID |
|
|
299
|
+
| `device_id` | ❌ | 目标接收设备;指定后只投递该设备,不会降级为 AID 全设备投递 |
|
|
300
|
+
| `to_device_id` | ❌ | `device_id` 的兼容别名 |
|
|
301
|
+
| `ttl` | ❌ | 秒;缺省或 `<=0` 持久化,正数钳制到 1–3600 秒并进入 volatile 内存通道 |
|
|
302
|
+
| `payload` | ✅ | 消息载荷,对协议层透明,由应用层定义 |
|
|
303
|
+
| `type` | ❌ | 信封/封装类型,普通业务消息无需填写;SDK 加密发送时自动使用 `e2ee.encrypted` |
|
|
304
|
+
| `encrypted` | ❌ | E2EE 标记(默认 `false`) |
|
|
305
|
+
| `message_id` | ❌ | 持久 P2P 的逻辑消息幂等键;新消息使用新的唯一 ID,重试复用原 ID,sender 隔离不扩大复用范围;客户端提供或服务端生成 UUID。volatile 保留原 sender+ID 隔离 |
|
|
306
|
+
| `need_render` | ❌ | 布尔值,默认 `true`;表示消息是否需要应用渲染,不改变拉取顺序或 ACK 规则 |
|
|
307
|
+
| `timestamp` | ❌ | 客户端时间戳(毫秒),服务端忽略此字段,始终使用服务端时间 |
|
|
308
|
+
|
|
309
|
+
**响应**:
|
|
310
|
+
```json
|
|
311
|
+
{
|
|
312
|
+
"jsonrpc": "2.0",
|
|
313
|
+
"id": 10,
|
|
314
|
+
"result": {
|
|
315
|
+
"message_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
316
|
+
"seq": 42,
|
|
317
|
+
"timestamp": 1709712000,
|
|
318
|
+
"status": "sent",
|
|
319
|
+
"delivery_mode": "queue"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
正 TTL 消息不写数据库或 WAL、不分配持久 `seq`,响应包含 `storage="volatile"`、`volatile_cursor`(多设备时可含 `volatile_cursors`)、`created_at`、`expires_at` 和 `status="accepted"`。`delivery_mode` 继续控制在线投递方式,不改变 TTL 存储语义。跨域只传递剩余 TTL,目标域不得重新应用 1 秒下限。
|
|
325
|
+
|
|
326
|
+
`need_render` 同样适用于 `group.send`。SDK 提取后放入明文信封,接收端同时可读取消息顶层该字段;历史缺字段或数据库 NULL 按 `true`。它不进入 E2EE AAD、`protected_headers`、消息保护签名或元数据 HMAC;RPC `client_signature` 仍按既有业务参数签名规则覆盖该参数,不新增 canonical 排除项。
|
|
327
|
+
|
|
328
|
+
##### Payload 参考约定
|
|
329
|
+
|
|
330
|
+
`message.send.params.payload` 的统一业务负载格式见 [消息Payload参考约定](../sdk/消息Payload参考约定.md)。完整 P2P 请求仍在 `payload` 同级传入 `to`;业务类型放在 `payload.type`,不要与 `message.send.params.type` 信封/封装类型混用。
|
|
331
|
+
|
|
332
|
+
协议层只要求 `payload` 是 JSON 对象,并按服务端配置做大小限制;字段语义由应用层约定,接收端应对未知 `payload.type`、未知 `kind` 和缺失展示字段做降级处理。
|
|
333
|
+
|
|
334
|
+
#### 连接升级控制消息
|
|
335
|
+
|
|
336
|
+
`peer.offer` / `peer.accept` / `peer.reject` / `peer.switch` 不是独立 JSON-RPC 方法,而是通过普通 `message.send` 发送的**协议控制负载**。三种连接模式在业务层复用统一的 `message.*`。
|
|
337
|
+
|
|
338
|
+
**用途**:
|
|
339
|
+
|
|
340
|
+
- `gateway → peer`:通过 Gateway 交换直连地址,尝试升级到 Peer
|
|
341
|
+
- `relay → peer`:已通过 Relay 联通的双方尝试升级到直连
|
|
342
|
+
- 失败时可回退到原有通道,不影响业务层 API
|
|
343
|
+
|
|
344
|
+
**`peer.offer` 示例**:
|
|
345
|
+
```json
|
|
346
|
+
{
|
|
347
|
+
"method": "message.send",
|
|
348
|
+
"params": {
|
|
349
|
+
"to": "bob.company.com",
|
|
350
|
+
"payload": {
|
|
351
|
+
"type": "peer.offer",
|
|
352
|
+
"session_id": "upgrade-550e8400",
|
|
353
|
+
"from_mode": "gateway",
|
|
354
|
+
"preferred_mode": "peer",
|
|
355
|
+
"endpoints": [{"url": "wss://alice.company.com:9900/acp", "priority": 1}],
|
|
356
|
+
"expires_in": 30
|
|
357
|
+
},
|
|
358
|
+
"delivery_mode": {"mode": "queue"}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**`peer.accept` 负载**:`{ "type": "peer.accept", "session_id": "...", "selected_endpoint": "wss://..." }`
|
|
364
|
+
|
|
365
|
+
**`peer.reject` 负载**:`{ "type": "peer.reject", "session_id": "...", "reason": "policy_denied" }`
|
|
366
|
+
|
|
367
|
+
**`peer.switch` 负载**:`{ "type": "peer.switch", "session_id": "...", "new_mode": "peer", "keep_fallback": true }`
|
|
368
|
+
|
|
369
|
+
**规范要求**:
|
|
370
|
+
|
|
371
|
+
- 接收方 **MAY** 接受或拒绝 `peer.offer`
|
|
372
|
+
- 接受后,双方 **MUST** 在新通道上重新执行完整 `initialize(mode=peer)` 与 `peer.*` 认证流程
|
|
373
|
+
- 旧通道在 `peer.switch` 完成前 **MUST** 保持可用
|
|
374
|
+
- 升级失败或超时时双方 **MUST** 回退到原通道
|
|
375
|
+
|
|
376
|
+
#### `message.peers`
|
|
377
|
+
|
|
378
|
+
返回当前认证设备、消费 slot 的消息对端目录,不是联系人服务。要求连接已声明 `p2p_peer_pull_v1: true`。
|
|
379
|
+
|
|
380
|
+
| 参数 | 必需 | 说明 |
|
|
381
|
+
|------|:----:|------|
|
|
382
|
+
| `filter` | ❌ | 默认 `pending`;只返回有持久待拉取消息或可用 volatile 消息的对端。`all` 返回仍有消息状态的全部对端 |
|
|
383
|
+
| `limit` | ❌ | 仅 `all` 可用,默认 100,范围 1–200 |
|
|
384
|
+
| `page_token` | ❌ | 仅 `all` 可用,复用响应的 `next_page_token` |
|
|
385
|
+
|
|
386
|
+
`pending` 一次完整返回,不分页、不截断到 200 个 peer,传入分页参数会拒绝。响应包含 `cursor_scope="peer"`、`receiver_aid`、`device_id`、固定的 `bootstrap_floor_seq`、`catalog_ready`、`catalog_revision` 和 `peers`;`all` 另含 `has_more`、`next_page_token`。`catalog_ready=false` 表示目录尚未覆盖可靠读取边界,不能把其空列表当作已同步完成,SDK 保留后台重试。
|
|
387
|
+
|
|
388
|
+
每个 peer 包含 `sender_aid`、`head_seq`、`server_ack_seq`、`initial_after_seq`、`initialization_source`、`retention_floor_seq`、`earliest_available_seq` 和 `volatile_has_more`。正常 `pending` 直接从同一游标表的 peer A/H 筛选持久候选:内部 `peer_H>A` 且 `peer_H>R`,再合并可用 volatile sender;不扫描消息积压、不逐 peer seek,也不执行 COUNT/SUM。候选可以保守偏大,完成仍由 Forward 覆盖证明及 ACK 确认;不返回每 peer 或整体的 `pending_count`、`need_render_pending_count`、`non_render_pending_count` 三项精确计数。
|
|
389
|
+
|
|
390
|
+
`peers[].next_pending_seq` 是可选排序近似;正常 `pending` 的持久候选直接返回该 peer 的 `server_ack_seq`(A),包含 0,`all` 或 volatile-only 允许省略。它不是首条未确认投递的真实 seq,无需额外查询或 SQL 往返;仅用于 SDK 调度,不是覆盖证明、可提交游标或完成依据,不能由它推进 A/H,也不能用 `covered_through_seq+1` 推导下一提示。公共 S 不用于抬高某个 peer 的 Forward 扫描起点,仍按该 peer ACK 与永久保留边界校验。
|
|
391
|
+
|
|
392
|
+
响应顶层可选 `pending_count_estimate=max(0,H-max(R,S_used))`:H 是当前设备已知可靠 Head,R 是已证明永久不可取得的前缀,S_used 是当前消费 slot 的有效公共安全前缀;S 缺失或 S>H 时按 0 使用,H 未知时省略字段。它是整体持久 seq 跨度上界,可含空号及 S 后已 ACK 的消息,不含 volatile,不是精确条数、未读数或 all 单页数量。SDK 仅透传给应用,不能缺省填 0、对 peer 求和或据此调度/推进游标/判断同步完成。volatile-only peer 在估计为 0 或缺省时仍须返回与同步。
|
|
393
|
+
|
|
394
|
+
#### `message.pull`
|
|
395
|
+
|
|
396
|
+
按持久和 volatile 两个独立游标拉取消息。以下请求/响应示例表示旧 global 路径;peer 路径增加 `cursor_scope="peer"`、`sender_aid`,持久页默认及最大 200 条,volatile 游标同样按 peer 隔离。
|
|
397
|
+
|
|
398
|
+
**请求**:
|
|
399
|
+
```json
|
|
400
|
+
{
|
|
401
|
+
"jsonrpc": "2.0",
|
|
402
|
+
"id": 11,
|
|
403
|
+
"method": "message.pull",
|
|
404
|
+
"params": {
|
|
405
|
+
"after_seq": 0,
|
|
406
|
+
"after_volatile_cursor": "v1:i1:7:20",
|
|
407
|
+
"limit": 50,
|
|
408
|
+
"device_id": "device-001"
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**参数**:
|
|
414
|
+
|
|
415
|
+
| 参数 | 必需 | 说明 |
|
|
416
|
+
|------|:----:|------|
|
|
417
|
+
| `after_seq` | ❌ | 起始序列号(默认 0),返回 `seq > after_seq` 的消息 |
|
|
418
|
+
| `after_volatile_cursor` | ❌ | opaque volatile 游标;四个 SDK 自动维护,应用通常无需传入 |
|
|
419
|
+
| `limit` | ❌ | 单次返回上限(默认 50,最大 50) |
|
|
420
|
+
| `device_id` | ❌ | 多实例消费上下文中的设备标识;缺省时使用连接认证上下文 |
|
|
421
|
+
| `window_mode` | ❌ | 可选 Pull 模式;`tail` 表示读取以安全 Head 结尾的最新一页 |
|
|
422
|
+
| `cursor_scope` | ❌ | 旧请求缺省 `global`;新 SDK 使用 `peer`,须有连接能力声明 |
|
|
423
|
+
| `sender_aid` | peer 必需 | 完整发送方 AID,只返回该对端消息;global 请求不得携带此字段 |
|
|
424
|
+
|
|
425
|
+
peer Forward 响应另含 `cursor_scope`、`sender_aid`、`scan_after_seq`、`covered_through_seq`、`next_after_seq`、`head_seq`、`server_ack_seq`、`persistent_has_more`、`volatile_has_more`、`has_more`、可选 `next_pending_seq`、`page_need_render_count` 和 `page_non_render_count`。固定可靠 Head 后,扫描 `(scan_after_seq, covered_through_seq]`,下一页使用 `next_after_seq=covered_through_seq`;原 seq 在不同 sender 之间共享,peer 页可稀疏,不能由相邻数字或返回条数推断缺消息。三个 `has_more` 必须为布尔值,且 `has_more = persistent_has_more OR volatile_has_more`。`count` 与两类页内数量按最终返回消息在内存计算,包含本页 volatile,不扫描全部积压;计数不改变扫描范围,不优先过滤可渲染消息。
|
|
426
|
+
|
|
427
|
+
`next_pending_seq` 是 peer Forward(含 force)的可选调度提示:`persistent_has_more=true` 时,返回本页最终边界之后首条未返回持久投递的原 seq,满足 `covered_through_seq < seq <= head_seq`;无持久更多时省略,only-volatile 仍按 `volatile_has_more` 继续。它直接复用原 `limit+1` 查询和去重合并结果:200 条页取第 201 条,字节截断取第一条未返回持久消息,volatile 混排挤掉持久消息时修正为最终第一条未返回持久 seq,不新增 SQL。Tail/History/旧 global 不增加此字段。正常 Forward 在消息页可靠 commit 后即可将页提示用于排序,不等待 ACK;仅收到响应或 commit 失败不能采用,ACK 未完成或失败保留独立确认责任,拒绝旧/迟到页回退;Tail/force/History 不更新正常调度。非法或缺失的可选提示不使合法消息页失败,不能用 `covered_through_seq+1` 推导,也不参与覆盖、ACK 或完成判断。
|
|
428
|
+
|
|
429
|
+
`server_ack_seq` 只可用于首次 peer 初始化,运行中的 SDK 不得据此跳过本地未交付区间;合法 `retention_floor_seq` 才能解释已经永久不可取得的前缀。peer 内解密或应用交付未完成时,不得仅凭扫描覆盖证明推进 A/ACK。
|
|
430
|
+
|
|
431
|
+
**响应**:
|
|
432
|
+
```json
|
|
433
|
+
{
|
|
434
|
+
"jsonrpc": "2.0",
|
|
435
|
+
"id": 11,
|
|
436
|
+
"result": {
|
|
437
|
+
"messages": [{
|
|
438
|
+
"message_id": "550e8400-...",
|
|
439
|
+
"seq": 43,
|
|
440
|
+
"from": "alice.aid.pub",
|
|
441
|
+
"to": "bob.aid.pub",
|
|
442
|
+
"timestamp": 1709712000,
|
|
443
|
+
"payload": {"type": "text", "text": "你好"},
|
|
444
|
+
"delivery_mode": "fanout"
|
|
445
|
+
}],
|
|
446
|
+
"count": 1,
|
|
447
|
+
"latest_seq": 43,
|
|
448
|
+
"ephemeral_earliest_available_seq": 38,
|
|
449
|
+
"ephemeral_dropped_count": 5
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**响应字段**:
|
|
455
|
+
|
|
456
|
+
| 字段 | 类型 | 说明 |
|
|
457
|
+
|------|------|------|
|
|
458
|
+
| `messages` | array | 消息列表(临时 + 持久化合并,按 `seq` 排序) |
|
|
459
|
+
| `count` | integer | 本次返回的消息条数 |
|
|
460
|
+
| `latest_seq` | integer | 本次返回的最大 `seq` |
|
|
461
|
+
| `latest_volatile_cursor` | string\|null | 本页最后一个 volatile 游标;不改变 `latest_seq` |
|
|
462
|
+
| `volatile_has_more` | boolean | 是否仍有未返回的 volatile 消息;SDK 在 volatile 游标前进时据此继续分页 |
|
|
463
|
+
| `volatile_earliest_cursor` | string\|null | 当前 boot epoch 内仍可读取的最早 volatile 游标 |
|
|
464
|
+
| `volatile_dropped_count` | integer | 当前 boot epoch 内因过期或容量淘汰而不可读的累计数 |
|
|
465
|
+
| `ephemeral_earliest_available_seq` | integer\|null | 当前临时缓冲中最早可用的 `seq`,`null` 表示无临时消息 |
|
|
466
|
+
| `ephemeral_dropped_count` | integer | 因缓冲淘汰而丢弃的临时消息计数 |
|
|
467
|
+
|
|
468
|
+
> 客户端可通过 `ephemeral_earliest_available_seq` 判断是否有临时消息丢失:若 `after_seq < ephemeral_earliest_available_seq`,说明存在已被淘汰的消息。
|
|
469
|
+
|
|
470
|
+
**说明**:持久游标与 volatile 游标独立推进。SDK 只把含正 `seq` 的消息送入持久 tracker;volatile push/pull 按发送方和 `message_id` 去重,交付成功后自动 ACK。SDK 在传输层注入内部 slot,应用不得传入或读取,任何消息、响应和事件都不得包含该字段。epoch 不匹配时 SDK 清空 volatile 游标并重试一次。`message.history` 不返回 volatile 消息。
|
|
471
|
+
|
|
472
|
+
**Tail 模式**:`window_mode="tail"` 时,服务端固定安全 `head_seq`;global 返回跨度不超过 `limit` 的最新 seq band,peer 按该 sender 最新消息条数取页,seq 跨度可大于 `limit`。额外返回:
|
|
473
|
+
|
|
474
|
+
| 字段 | 说明 |
|
|
475
|
+
|------|------|
|
|
476
|
+
| `window_mode` | 固定为 `tail` |
|
|
477
|
+
| `window_start_seq` | 已扫描窗口的包含式左边界 |
|
|
478
|
+
| `head_seq` | 本次请求固定的安全 Head |
|
|
479
|
+
| `covered_through_seq` | 覆盖终点,正常等于 `head_seq` |
|
|
480
|
+
|
|
481
|
+
Tail 不推进 ACK、retention/visibility floor、Pull activity 或 catch-up 状态,不接受 `ack_up_to_seq` 或 `force=true`。Tail 使用窗口证明,不要求 Forward 的三个 `has_more` 字段。global seq band 内未返回的序号视为服务端永久空号;peer 仅按服务端覆盖证明合并窗口,不能套用 dense seq 校验。新 SDK 仅在已验证自身 `agent.md.type=human` 时自动优先 Tail 再 Forward;其他或未知类型直接 Forward。无 `window_mode` 的旧 global 请求保持原副作用语义。
|
|
482
|
+
|
|
483
|
+
#### `message.history`
|
|
484
|
+
|
|
485
|
+
按 `before_seq` 排他上界向前只读翻页,不修改 ACK、cursor、floor 或 Pull activity。
|
|
486
|
+
|
|
487
|
+
**参数**:
|
|
488
|
+
|
|
489
|
+
| 参数 | 必需 | 说明 |
|
|
490
|
+
|------|:----:|------|
|
|
491
|
+
| `before_seq` | ✅ | 正整数排他上界,只返回 `seq < before_seq` 的消息 |
|
|
492
|
+
| `limit` | ❌ | 单页上限(默认 50,最大 50) |
|
|
493
|
+
| `cursor_scope` / `sender_aid` | peer 必需 | 与 Pull 相同;peer 页默认及最大 200 条,隔离读取该 sender 历史 |
|
|
494
|
+
|
|
495
|
+
**响应字段**:
|
|
496
|
+
|
|
497
|
+
| 字段 | 说明 |
|
|
498
|
+
|------|------|
|
|
499
|
+
| `messages` | 页内按 seq 升序 |
|
|
500
|
+
| `window_start_seq` | 本页最小边界;空页为 `null` |
|
|
501
|
+
| `next_before_seq` | 下一页直接使用的排他上界;无更早消息为 `null` |
|
|
502
|
+
| `has_older` | 是否仍有更早的可见消息 |
|
|
503
|
+
| `retention_floor_seq` | 已实际删除、不可恢复的 seq 下界 |
|
|
504
|
+
| `earliest_available_seq` | 当前最早可拉取边界 |
|
|
505
|
+
|
|
506
|
+
History 不触发实时消息事件。客户端解密 History 结果时不得修改实时 A/T/H 或发送 ACK。
|
|
507
|
+
|
|
508
|
+
**客户端发布语义**:peer 页内按 seq 升序处理;SDK 在当前运行实例内协调并发交付,并以最多 50,000 条的内存成功绑定去重,按接收 AID、设备、消费 slot、事件类别和原正 delivery seq 识别投递,校验 sender 与 `message_id`,不因 namespace 或 Push/Pull/Tail 来源另造身份。消息热路径不逐条读写耐久 receipt,自定义 store 不要求提供 receipt 能力。应用 handler 成功后才完成内存标记,peer 持久消息 Forward 页依据有效 proof 提交页 A/T/H 后发送本页新增累计 ACK;使用持久化 store 时保存页状态。内存淘汰、重建 client、崩溃或版本切换后允许重放,应用须在业务事务中按消息身份持久幂等;多个 client/进程不提供跨实例首次回调原子 claim。跨 peer 不承诺全局回调顺序,显式 History/force/Tail 列表不因内存去重删行;History 不进入实时发布流。
|
|
509
|
+
|
|
510
|
+
#### `message.ack`
|
|
511
|
+
|
|
512
|
+
确认已收到消息。持久 ACK 与 volatile ACK 可以单独提交,也可以在同一请求中提交。
|
|
513
|
+
|
|
514
|
+
**请求**:
|
|
515
|
+
```json
|
|
516
|
+
{
|
|
517
|
+
"jsonrpc": "2.0",
|
|
518
|
+
"id": 12,
|
|
519
|
+
"method": "message.ack",
|
|
520
|
+
"params": {
|
|
521
|
+
"seq": 43,
|
|
522
|
+
"volatile_cursors": ["v1:i1:7:21"],
|
|
523
|
+
"device_id": "device-001"
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
**参数**:
|
|
529
|
+
|
|
530
|
+
| 参数 | 必需 | 说明 |
|
|
531
|
+
|------|:----:|------|
|
|
532
|
+
| `seq` | ❌ | 确认到的持久序列号(含);未提交 volatile ACK 时必填 |
|
|
533
|
+
| `volatile_cursor` | ❌ | 单个 volatile 游标的兼容形式 |
|
|
534
|
+
| `volatile_cursors` | ❌ | 要确认的 volatile 游标数组 |
|
|
535
|
+
| `volatile_ids` | ❌ | 要按 `message_id` 确认的 volatile 消息数组 |
|
|
536
|
+
| `device_id` | ❌ | 多实例消费上下文中的设备标识;缺省时使用连接认证上下文 |
|
|
537
|
+
| `cursor_scope` / `sender_aid` | peer 必需 | 按 peer 确认;持久水位使用 `up_to_seq`,兼容 `seq` / `ack_seq` |
|
|
538
|
+
|
|
539
|
+
**响应**:
|
|
540
|
+
```json
|
|
541
|
+
{
|
|
542
|
+
"jsonrpc": "2.0",
|
|
543
|
+
"id": 12,
|
|
544
|
+
"result": {"success": true, "ack_seq": 43}
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**说明**:`ack_seq` 仅增不减;volatile 结果通过 `volatile_ack` 返回 `accepted`、`expired` 等幂等计数。服务端内部按消费 slot 隔离 lease,但 slot 不属于对外协议对象。
|
|
549
|
+
|
|
550
|
+
peer 响应以 `peer_ack_seq` / `effective_ack_seq` 表示该 sender 的确认水位,不能把 `ack_seq` 当作 peer ACK。可选 `legacy_safe_ack_seq` 与 `previous_legacy_safe_ack_seq` 表示当前消费 slot 的公共安全前缀 S 及原值,不写回旧 global ACK。服务端在同一 `message_peer_slot_cursor` 表以真实 sender 行保存 peer ACK Ap、内部 `sender_aid='*'` 行保存同 owner/device/slot 的 S,与 ACK 同 RR 事务原子持久,单调且不得超过可靠 H;`*` 不对外接受或枚举。bootstrap G 独立冻结,不用 S 替代;来源或潜在 legacy 低位迁入不明时不提高 S。本期不新增设备级聚合游标行;缺完整持久设备 slot 名册时 `device_safe_ack_seq` 可省略,SDK 不得由单 peer 或单 slot 的水位推断设备全部旧密钥可销毁。
|
|
551
|
+
|
|
552
|
+
#### `message.recall`
|
|
553
|
+
|
|
554
|
+
撤回消息。仅发送方可撤回,受时间窗口限制(默认 2 分钟)。
|
|
555
|
+
|
|
556
|
+
**请求**:
|
|
557
|
+
```json
|
|
558
|
+
{
|
|
559
|
+
"jsonrpc": "2.0",
|
|
560
|
+
"id": 13,
|
|
561
|
+
"method": "message.recall",
|
|
562
|
+
"params": {"message_ids": ["uuid-1", "uuid-2"]}
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**参数**:
|
|
567
|
+
|
|
568
|
+
| 参数 | 必需 | 说明 |
|
|
569
|
+
|------|:----:|------|
|
|
570
|
+
| `message_ids` | ✅ | 要撤回的消息 ID 列表(最多 100 个) |
|
|
571
|
+
|
|
572
|
+
**响应**:
|
|
573
|
+
```json
|
|
574
|
+
{
|
|
575
|
+
"jsonrpc": "2.0",
|
|
576
|
+
"id": 13,
|
|
577
|
+
"result": {
|
|
578
|
+
"success": true,
|
|
579
|
+
"accepted": 2,
|
|
580
|
+
"recalled": 1,
|
|
581
|
+
"errors": [{"message_id": "uuid-2", "error": "expired"}]
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
| 字段 | 类型 | 说明 |
|
|
587
|
+
|------|------|------|
|
|
588
|
+
| `success` | boolean | 操作是否执行 |
|
|
589
|
+
| `accepted` | integer | 接收的 message_id 数 |
|
|
590
|
+
| `recalled` | integer | 实际撤回数 |
|
|
591
|
+
| `errors` | array\|null | 失败项,错误码:`not_found` / `not_sender` / `already_recalled` / `expired` |
|
|
592
|
+
|
|
593
|
+
**说明**:撤回成功后向接收方推送 `event/message.recalled` 事件。仅 `delivery_mode.mode = "fanout"` 的消息支持撤回;`queue` 消息不进入历史,无法可靠追溯。
|
|
594
|
+
|
|
595
|
+
#### `message.query_online`
|
|
596
|
+
|
|
597
|
+
批量查询 AID 在线状态。
|
|
598
|
+
|
|
599
|
+
**请求**:
|
|
600
|
+
```json
|
|
601
|
+
{
|
|
602
|
+
"jsonrpc": "2.0",
|
|
603
|
+
"id": 14,
|
|
604
|
+
"method": "message.query_online",
|
|
605
|
+
"params": {"aids": ["alice.aid.pub", "bob.example.com"]}
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**参数**:
|
|
610
|
+
|
|
611
|
+
| 参数 | 必需 | 说明 |
|
|
612
|
+
|------|:----:|------|
|
|
613
|
+
| `aids` | ✅ | 要查询的 AID 列表(最多 100 个) |
|
|
614
|
+
|
|
615
|
+
**响应**:
|
|
616
|
+
```json
|
|
617
|
+
{
|
|
618
|
+
"jsonrpc": "2.0",
|
|
619
|
+
"id": 14,
|
|
620
|
+
"result": {
|
|
621
|
+
"online": {
|
|
622
|
+
"alice.aid.pub": true,
|
|
623
|
+
"bob.example.com": false
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**当前实现说明**:
|
|
630
|
+
|
|
631
|
+
- 本域 AID 直接由 message 服务本地在线跟踪器返回
|
|
632
|
+
- 外域 AID 通过 `gateway.forward_federation` 转发到目标域查询
|
|
633
|
+
- 当前实现中,若某个外域查询失败,该域内 AID 会回落为 `false`
|
|
634
|
+
|
|
635
|
+
#### `event/message.received`
|
|
636
|
+
|
|
637
|
+
收到 P2P 消息事件。
|
|
638
|
+
|
|
639
|
+
```json
|
|
640
|
+
{
|
|
641
|
+
"jsonrpc": "2.0",
|
|
642
|
+
"method": "event/message.received",
|
|
643
|
+
"params": {
|
|
644
|
+
"from": "bob.aid.pub",
|
|
645
|
+
"sender_device_id": "bob-phone",
|
|
646
|
+
"to": "alice.aid.pub",
|
|
647
|
+
"message_id": "550e8400-...",
|
|
648
|
+
"seq": 42,
|
|
649
|
+
"payload": {"type": "text", "text": "你好"},
|
|
650
|
+
"timestamp": 1709712005,
|
|
651
|
+
"delivery_mode": "queue",
|
|
652
|
+
"encrypted": false
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
volatile 事件包含 `storage="volatile"`、`volatile_cursor`、`created_at`、`expires_at`,不含持久 `seq` 或内部 slot。`sender_device_id` 始终表示发送方设备,可用于下一次定向发送。
|
|
658
|
+
|
|
659
|
+
peer 连接按接收 AID、设备及 sender 折叠待拉取通知;上线恢复可以只发 `cursor_scope="peer"` 的同步提示,由 SDK 调用完整 pending `message.peers` 后并行拉取,不能把提示的 0 seq 当作消息水位。可信消息元数据可携带 `prev_peer_seq`,表示同接收设备、同 sender 的前一条原 seq;未知时省略,只有可证明为首条才返回 0。若本地 A=103 收到 seq=105,前驱为103时可确认相接,前驱大于103则需要补拉;缺前驱时保守交由 peer Forward 覆盖证明判断,不能仅由105−103认定 Gap。
|
|
660
|
+
|
|
661
|
+
#### `event/message.ack`
|
|
662
|
+
|
|
663
|
+
消息确认事件(通知发送方消息已被接收方确认)。
|
|
664
|
+
|
|
665
|
+
```json
|
|
666
|
+
{
|
|
667
|
+
"jsonrpc": "2.0",
|
|
668
|
+
"method": "event/message.ack",
|
|
669
|
+
"params": {
|
|
670
|
+
"to": "bob.aid.pub",
|
|
671
|
+
"device_id": "device-001",
|
|
672
|
+
"ack_seq": 43,
|
|
673
|
+
"timestamp": 1709712003
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
- `to`:确认方 AID
|
|
679
|
+
- `device_id`:触发 ack 的设备标识;legacy 客户端为空字符串
|
|
680
|
+
- `ack_seq`:确认到的序列号(含该 seq 及之前的所有消息)
|
|
681
|
+
|
|
682
|
+
peer 能力连接收到的 peer ACK 通知使用 `cursor_scope="peer"`、`sender_aid` 和 `peer_ack_seq`,不得用它推进旧 global 游标或其他 peer。旧 ACK 通知不能替代新 SDK 的本地交付证明;投递 ACK 不表示应用业务已读。
|
|
683
|
+
|
|
684
|
+
#### `event/message.recalled`
|
|
685
|
+
|
|
686
|
+
消息被撤回事件(通知接收方消息已被发送方撤回)。
|
|
687
|
+
|
|
688
|
+
```json
|
|
689
|
+
{
|
|
690
|
+
"jsonrpc": "2.0",
|
|
691
|
+
"method": "event/message.recalled",
|
|
692
|
+
"params": {
|
|
693
|
+
"from": "alice.aid.pub",
|
|
694
|
+
"to": "bob.aid.pub",
|
|
695
|
+
"message_ids": ["uuid-1"],
|
|
696
|
+
"timestamp": 1709712000
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
- `from`:发送方(撤回者)AID
|
|
702
|
+
- `to`:接收方 AID
|
|
703
|
+
- `message_ids`:被撤回的消息 ID 列表
|
|
704
|
+
- `timestamp`:服务端时间戳(毫秒)
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
### 6.4 元协议 `meta.*`
|
|
709
|
+
|
|
710
|
+
#### `meta.ping`
|
|
711
|
+
|
|
712
|
+
健康检查。
|
|
713
|
+
|
|
714
|
+
**请求**:
|
|
715
|
+
```json
|
|
716
|
+
{"jsonrpc": "2.0", "id": 30, "method": "meta.ping"}
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
**响应**:
|
|
720
|
+
```json
|
|
721
|
+
{"jsonrpc": "2.0", "id": 30, "result": {"pong": true, "timestamp": 1709712000}}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
#### `meta.status`
|
|
725
|
+
|
|
726
|
+
查询当前连接状态。
|
|
727
|
+
|
|
728
|
+
**当前实现事实**:
|
|
729
|
+
|
|
730
|
+
- `meta.status` 由 Gateway 本地处理,不转发到独立 `meta` 服务
|
|
731
|
+
- 当前 Gateway 返回的是简化状态对象,不是完整的 peer / relay 拓扑诊断结构
|
|
732
|
+
- Python SDK 当前也只实现 Gateway 拓扑;`peer` 和 `relay` 拓扑在 Python SDK 中尚未实现
|
|
733
|
+
|
|
734
|
+
**当前返回字段**:
|
|
735
|
+
|
|
736
|
+
| 字段 | 说明 |
|
|
737
|
+
|------|------|
|
|
738
|
+
| `mode` | 当前连接模式。现实现固定为 `gateway` |
|
|
739
|
+
| `aid` | 当前会话 AID |
|
|
740
|
+
| `role` | 当前会话角色 |
|
|
741
|
+
| `connected_at` | 会话建立时间戳(毫秒) |
|
|
742
|
+
| `protocol_version` | 协议版本,当前为 `1.0` |
|
|
743
|
+
|
|
744
|
+
**当前实现示例**:
|
|
745
|
+
```json
|
|
746
|
+
{
|
|
747
|
+
"jsonrpc": "2.0",
|
|
748
|
+
"id": 31,
|
|
749
|
+
"result": {
|
|
750
|
+
"mode": "gateway",
|
|
751
|
+
"aid": "alice.aid.pub",
|
|
752
|
+
"role": "user",
|
|
753
|
+
"connected_at": 1709712000000,
|
|
754
|
+
"protocol_version": "1.0"
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
**协议演进约束**:
|
|
760
|
+
|
|
761
|
+
- 客户端 **MUST** 容忍未知字段,以便未来扩展更完整的连接诊断结构
|
|
762
|
+
- 文档中关于 peer / relay 诊断字段的 richer 结构,目前应视为未来扩展方向,而非当前稳定返回契约
|
|
763
|
+
|
|
764
|
+
#### `meta.trust_roots`
|
|
765
|
+
|
|
766
|
+
查询当前 AUN 受信根证书列表。Gateway 内部转发给 CA 模块处理。
|
|
767
|
+
|
|
768
|
+
该 RPC 适合已连接客户端查询服务端缓存列表。首次信任根更新应优先使用公开 HTTP 端点:
|
|
769
|
+
|
|
770
|
+
- `GET https://trust.aun.network/.well-known/aun/trust-roots.json`
|
|
771
|
+
- `GET https://pki.{issuer}/trust-root.json`
|
|
772
|
+
- `GET https://gateway.{issuer}/pki/trust-roots.json`
|
|
773
|
+
|
|
774
|
+
Issuer PKI 泛域名服务还必须提供 `GET https://pki.{issuer}/root.crt`,用于下载该 issuer 证书链锚定的 Root CA PEM。客户端导入前必须验证受信根列表的 `authority_signature`,并确认 `root.crt` 的 SHA-256 指纹存在于已验签列表中。
|
|
775
|
+
|
|
776
|
+
**请求**:
|
|
777
|
+
```json
|
|
778
|
+
{"jsonrpc": "2.0", "id": 32, "method": "meta.trust_roots"}
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
**参数**:无。
|
|
782
|
+
|
|
783
|
+
**响应**:
|
|
784
|
+
```json
|
|
785
|
+
{
|
|
786
|
+
"jsonrpc": "2.0",
|
|
787
|
+
"id": 32,
|
|
788
|
+
"result": {
|
|
789
|
+
"version": 2,
|
|
790
|
+
"issued_at": "2026-03-15T10:00:00Z",
|
|
791
|
+
"next_update": "2026-03-16T10:00:00Z",
|
|
792
|
+
"authority_signature": "MEUCIQDx...",
|
|
793
|
+
"root_cas": [
|
|
794
|
+
{
|
|
795
|
+
"id": "root-ca-001",
|
|
796
|
+
"name": "AUN Root CA A",
|
|
797
|
+
"organization": "Organization A",
|
|
798
|
+
"certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
|
|
799
|
+
"fingerprint_sha256": "a1b2c3d4...",
|
|
800
|
+
"status": "active",
|
|
801
|
+
"crl_url": "http://crl.rootca-a.example/root.crl",
|
|
802
|
+
"ocsp_url": "http://ocsp.rootca-a.example"
|
|
803
|
+
}
|
|
804
|
+
]
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
**响应字段**:
|
|
810
|
+
|
|
811
|
+
| 字段 | 类型 | 说明 |
|
|
812
|
+
|------|------|------|
|
|
813
|
+
| `version` | integer | 受信根列表版本,单调递增 |
|
|
814
|
+
| `issued_at` | string | 列表签发时间 |
|
|
815
|
+
| `next_update` | string | 建议下次更新时间 |
|
|
816
|
+
| `authority_signature` | string | 管理局对规范化列表内容的签名 |
|
|
817
|
+
| `root_cas` | array | Root CA 列表 |
|
|
818
|
+
| `root_cas[].certificate` | string | PEM 格式 Root CA 证书 |
|
|
819
|
+
| `root_cas[].fingerprint_sha256` | string | Root CA 证书 DER SHA-256 指纹 |
|
|
820
|
+
| `root_cas[].status` | string | `active` / `retired` / `revoked` 等状态 |
|
|
821
|
+
|
|
822
|
+
> **兼容说明**:早期服务可能仍返回 `roots/count` 简化结构。客户端可以查询该结构,但默认不得将未签名列表导入本地信任根。客户端仍应容忍未知字段。
|
|
823
|
+
|
|
824
|
+
#### CT 公开 HTTP 端点
|
|
825
|
+
|
|
826
|
+
Issuer 必须通过 `https://ct.{issuer}` 提供证书透明日志(CT)的公开只读查询入口。该入口不属于 SDK RPC 命名空间,不通过 `AUNClient` 暴露专用方法;审计方和客户端可直接使用 HTTP 查询。
|
|
827
|
+
|
|
828
|
+
`ct.{issuer}` 是稳定的公开访问面,CA 服务本身不得直接暴露公网 HTTP 端点。服务端对外只能暴露公开只读查询路径,CT 写入接口不得通过 `ct.{issuer}` 暴露。
|
|
829
|
+
|
|
830
|
+
规范端点:
|
|
831
|
+
|
|
832
|
+
| 方法 | URL | 说明 |
|
|
833
|
+
|------|-----|------|
|
|
834
|
+
| GET | `https://ct.{issuer}/sth` | 获取最新签名树头(STH) |
|
|
835
|
+
| GET | `https://ct.{issuer}/entries?start=0&limit=100` | 分页查询公开 CT 条目 |
|
|
836
|
+
| GET | `https://ct.{issuer}/entries/{log_id}` | 按日志 ID 查询单条公开 CT 条目 |
|
|
837
|
+
| GET | `https://ct.{issuer}/certs/{serial}` | 按证书序列号查询对应 CT 条目 |
|
|
838
|
+
| GET | `https://ct.{issuer}/proof/{tree_size}/{log_id}` | 获取指定树大小下的 Merkle inclusion proof |
|
|
839
|
+
|
|
840
|
+
完整日志范围、字段定义、SCT/STH 格式和 Issuer CA 写入要求见 [附录D D.8](附录D-Root_CA_治理机制.md) 与 [附录F](附录F-Issuer_CA_申请流程.md)。
|
|
841
|
+
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
### 6.5 搜索与发现 `search.*`
|
|
845
|
+
|
|
846
|
+
`search.*` 定义 AUN 中 Agent 的公开发现机制,围绕 `agent.md` 工作:
|
|
847
|
+
|
|
848
|
+
- `agent.md` 是 Agent 的标准公开描述文档,对标 A2A 的 Agent Card
|
|
849
|
+
- AP 内部通过 `search.*` 为本 AP 托管或索引的公开 `agent.md` 提供检索服务
|
|
850
|
+
- 整个 AUN 网络可通过公开 AP 之间的同步,聚合形成跨 AP、跨 Issuer 的全网 Agent 搜索与发现能力
|
|
851
|
+
|
|
852
|
+
#### 6.4.1 `agent.md` 规范
|
|
853
|
+
|
|
854
|
+
`agent.md` **MUST** 采用 `YAML frontmatter + Markdown 正文` 结构。
|
|
855
|
+
|
|
856
|
+
**必填字段**:
|
|
857
|
+
|
|
858
|
+
| 字段 | 说明 |
|
|
859
|
+
|------|------|
|
|
860
|
+
| `aid` | Agent 的唯一身份标识,必须为合法 AID |
|
|
861
|
+
| `name` | Agent 显示名称 |
|
|
862
|
+
| `type` | Agent 类型,如 `human`、`assistant`、`avatar`、`codeagent` |
|
|
863
|
+
| `version` | 该公开描述文档自身的版本号 |
|
|
864
|
+
| `description` | 一句话简介 |
|
|
865
|
+
|
|
866
|
+
**可选字段**:`tags`、`visibility`(`public`/`unlisted`/`private`)、`updated_at`、`skills`、`input_modes`、`output_modes`、`service_endpoints`、`provider`、`contact`、`license`、`signature`
|
|
867
|
+
|
|
868
|
+
**最小格式示例**:
|
|
869
|
+
|
|
870
|
+
```markdown
|
|
871
|
+
---
|
|
872
|
+
aid: "agent-name.aid.pub"
|
|
873
|
+
name: "Agent Name"
|
|
874
|
+
type: "assistant"
|
|
875
|
+
version: "1.0.0"
|
|
876
|
+
description: "一句话描述"
|
|
877
|
+
visibility: "public"
|
|
878
|
+
tags:
|
|
879
|
+
- tag1
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
# Markdown 正文
|
|
883
|
+
详细说明、Skills、使用示���等...
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
- `visibility=private` 的记录 **MUST NOT** 进入公开索引
|
|
887
|
+
- `agent.md` **MUST NOT** 包含私钥或敏感凭据
|
|
888
|
+
|
|
889
|
+
#### 6.4.2 发现模型
|
|
890
|
+
|
|
891
|
+
**AP 内发现**:
|
|
892
|
+
|
|
893
|
+
- AP **MUST** 能索引其服务范围内公开可见的 `agent.md`
|
|
894
|
+
- `search.query`、`search.get_agent`、`search.suggest` 返回的是该 AP 当前索引视图
|
|
895
|
+
|
|
896
|
+
**全网发现**:
|
|
897
|
+
|
|
898
|
+
- 公开 AP **SHOULD** 从其他公开 AP 同步公开的 `agent.md`
|
|
899
|
+
- 同步模型推荐"增量追加日志 + 周期性快照"
|
|
900
|
+
- 客户端 **MUST** 把搜索结果视为"最终一致",而不是强事务视图
|
|
901
|
+
|
|
902
|
+
#### `search.ap_info`
|
|
903
|
+
|
|
904
|
+
查询公开 AP 的同步能力与当前索引状态。
|
|
905
|
+
|
|
906
|
+
**请求**:
|
|
907
|
+
```json
|
|
908
|
+
{"jsonrpc": "2.0", "id": 40, "method": "search.ap_info"}
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
**响应**:
|
|
912
|
+
```json
|
|
913
|
+
{
|
|
914
|
+
"jsonrpc": "2.0",
|
|
915
|
+
"id": 40,
|
|
916
|
+
"result": {
|
|
917
|
+
"ap_id": "search.aid.pub",
|
|
918
|
+
"public": true,
|
|
919
|
+
"capabilities": {"query": true, "suggest": true, "snapshot": true, "changes": true},
|
|
920
|
+
"current_snapshot_version": "2026-03-21T00:00:00Z",
|
|
921
|
+
"change_cursor_head": "chg_00000991",
|
|
922
|
+
"updated_at": "2026-03-21T08:00:00Z"
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
#### `search.snapshot`
|
|
928
|
+
|
|
929
|
+
获取公开 AP 的全量快照,用于冷启动或游标失效后重建。
|
|
930
|
+
|
|
931
|
+
**请求**:
|
|
932
|
+
```json
|
|
933
|
+
{
|
|
934
|
+
"jsonrpc": "2.0",
|
|
935
|
+
"id": 41,
|
|
936
|
+
"method": "search.snapshot",
|
|
937
|
+
"params": {"version": "2026-03-21T00:00:00Z", "cursor": null, "limit": 500}
|
|
938
|
+
}
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
**响应**:
|
|
942
|
+
```json
|
|
943
|
+
{
|
|
944
|
+
"jsonrpc": "2.0",
|
|
945
|
+
"id": 41,
|
|
946
|
+
"result": {
|
|
947
|
+
"snapshot_version": "2026-03-21T00:00:00Z",
|
|
948
|
+
"items": [{
|
|
949
|
+
"aid": "reviewer.aid.pub",
|
|
950
|
+
"agent_md_url": "https://reviewer.aid.pub/agent.md",
|
|
951
|
+
"agent_md_sha256": "6f4c...9a",
|
|
952
|
+
"source_ap": "search.aid.pub",
|
|
953
|
+
"updated_at": "2026-03-20T12:00:00Z"
|
|
954
|
+
}],
|
|
955
|
+
"next_cursor": "snap_0002",
|
|
956
|
+
"has_more": true
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
#### `search.changes`
|
|
962
|
+
|
|
963
|
+
获取某个游标之后的增量变更,用于持续同步。
|
|
964
|
+
|
|
965
|
+
**请求**:
|
|
966
|
+
```json
|
|
967
|
+
{
|
|
968
|
+
"jsonrpc": "2.0",
|
|
969
|
+
"id": 42,
|
|
970
|
+
"method": "search.changes",
|
|
971
|
+
"params": {"cursor": "chg_00000920", "limit": 200}
|
|
972
|
+
}
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
**响应**:
|
|
976
|
+
```json
|
|
977
|
+
{
|
|
978
|
+
"jsonrpc": "2.0",
|
|
979
|
+
"id": 42,
|
|
980
|
+
"result": {
|
|
981
|
+
"from_cursor": "chg_00000920",
|
|
982
|
+
"next_cursor": "chg_00000991",
|
|
983
|
+
"changes": [
|
|
984
|
+
{"sequence": 921, "op": "upsert", "aid": "reviewer.aid.pub", "updated_at": "2026-03-21T07:55:00Z"},
|
|
985
|
+
{"sequence": 922, "op": "delete", "aid": "oldbot.aid.pub", "updated_at": "2026-03-21T07:56:00Z"}
|
|
986
|
+
],
|
|
987
|
+
"has_more": false
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
- `op` 至少支持 `upsert` 与 `delete`
|
|
993
|
+
- 若游标已过期,服务端 **SHOULD** 返回错误,要求下游重新拉取 `search.snapshot`
|
|
994
|
+
|
|
995
|
+
#### `search.query`
|
|
996
|
+
|
|
997
|
+
搜索公开 Agent。
|
|
998
|
+
|
|
999
|
+
**请求**:
|
|
1000
|
+
```json
|
|
1001
|
+
{
|
|
1002
|
+
"jsonrpc": "2.0",
|
|
1003
|
+
"id": 43,
|
|
1004
|
+
"method": "search.query",
|
|
1005
|
+
"params": {"q": "code review assistant", "tags": ["coding"], "limit": 10}
|
|
1006
|
+
}
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
**响应**:
|
|
1010
|
+
```json
|
|
1011
|
+
{
|
|
1012
|
+
"jsonrpc": "2.0",
|
|
1013
|
+
"id": 43,
|
|
1014
|
+
"result": {
|
|
1015
|
+
"items": [{
|
|
1016
|
+
"aid": "reviewer.aid.pub",
|
|
1017
|
+
"name": "Reviewer",
|
|
1018
|
+
"description": "面向工程团队的代码审查 Agent",
|
|
1019
|
+
"tags": ["coding", "review"],
|
|
1020
|
+
"agent_md_url": "https://reviewer.aid.pub/agent.md"
|
|
1021
|
+
}],
|
|
1022
|
+
"next_cursor": "cur_abc123"
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
#### `search.get_agent`
|
|
1028
|
+
|
|
1029
|
+
获取单个 Agent 的公开描述。
|
|
1030
|
+
|
|
1031
|
+
**请求**:
|
|
1032
|
+
```json
|
|
1033
|
+
{
|
|
1034
|
+
"jsonrpc": "2.0",
|
|
1035
|
+
"id": 44,
|
|
1036
|
+
"method": "search.get_agent",
|
|
1037
|
+
"params": {"aid": "reviewer.aid.pub"}
|
|
1038
|
+
}
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
**响应**:
|
|
1042
|
+
```json
|
|
1043
|
+
{
|
|
1044
|
+
"jsonrpc": "2.0",
|
|
1045
|
+
"id": 44,
|
|
1046
|
+
"result": {
|
|
1047
|
+
"aid": "reviewer.aid.pub",
|
|
1048
|
+
"agent_md": "---\naid: \"reviewer.aid.pub\"\nname: \"Reviewer\"\n...\n---\n# Reviewer\n",
|
|
1049
|
+
"content_type": "text/markdown",
|
|
1050
|
+
"agent_md_url": "https://reviewer.aid.pub/agent.md",
|
|
1051
|
+
"updated_at": "2026-03-20T12:00:00Z"
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
#### `search.suggest`
|
|
1057
|
+
|
|
1058
|
+
返回搜索建议、热门标签或前缀匹配结果。
|
|
1059
|
+
|
|
1060
|
+
**请求**:
|
|
1061
|
+
```json
|
|
1062
|
+
{"jsonrpc": "2.0", "id": 45, "method": "search.suggest", "params": {"prefix": "code"}}
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
**响应**:
|
|
1066
|
+
```json
|
|
1067
|
+
{
|
|
1068
|
+
"jsonrpc": "2.0",
|
|
1069
|
+
"id": 45,
|
|
1070
|
+
"result": {
|
|
1071
|
+
"suggestions": [
|
|
1072
|
+
{"type": "query", "value": "code review"},
|
|
1073
|
+
{"type": "tag", "value": "coding"},
|
|
1074
|
+
{"type": "aid", "value": "reviewer.aid.pub"}
|
|
1075
|
+
]
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
#### 错误码
|
|
1081
|
+
|
|
1082
|
+
| 错误码 | 名称 | 说明 |
|
|
1083
|
+
|-------:|------|------|
|
|
1084
|
+
| `-32160` | Search unavailable | 当前 AP 未启用搜索服务 |
|
|
1085
|
+
| `-32161` | Agent not found | 指定 AID 的公开 `agent.md` 不存在 |
|
|
1086
|
+
| `-32162` | Invalid search query | 查询参数非法 |
|
|
1087
|
+
| `-32163` | Snapshot stale | 当前结果基于过期快照 |
|
|
1088
|
+
| `-32164` | Change cursor expired | 增量游标已超出保留窗口 |
|
|
1089
|
+
|
|
1090
|
+
---
|
|
1091
|
+
|
|
1092
|
+
### 6.6 Agent 协作与任务 `task.*`
|
|
1093
|
+
|
|
1094
|
+
`task.*` 用于表达 Agent 之间的长生命周期协作任务,参考 A2A 的 task 机制,对齐 AUN 特点:
|
|
1095
|
+
|
|
1096
|
+
- 任务对象通过 `task.*` 暴露统一的状态、输入、产物和事件
|
|
1097
|
+
- 大对象、附件 **SHOULD** 通过 `storage.*` 承载,`task.*` 仅传递元数据与引用
|
|
1098
|
+
|
|
1099
|
+
**任务对象核心字段**:
|
|
1100
|
+
|
|
1101
|
+
| 字段 | 说明 |
|
|
1102
|
+
|------|------|
|
|
1103
|
+
| `task_id` | 任务唯一标识 |
|
|
1104
|
+
| `status` | 任务状态 |
|
|
1105
|
+
| `owner` | 发起方 AID |
|
|
1106
|
+
| `assignee` | 执行方 AID |
|
|
1107
|
+
| `participants` | 参与方列表 |
|
|
1108
|
+
| `visibility` | 任务可见性(`private`/`shared`/`public`) |
|
|
1109
|
+
| `parent_task_id` | 父任务标识(如有) |
|
|
1110
|
+
| `input` | 初始输入 |
|
|
1111
|
+
| `artifacts` | 任务产物 |
|
|
1112
|
+
| `messages` | 上下文消息 |
|
|
1113
|
+
|
|
1114
|
+
**状态机**:
|
|
1115
|
+
|
|
1116
|
+
| 状态 | 说明 |
|
|
1117
|
+
|------|------|
|
|
1118
|
+
| `submitted` | 已创建,等待接收方受理 |
|
|
1119
|
+
| `rejected` | 接收方明确拒绝受理(终态) |
|
|
1120
|
+
| `working` | 正在执行 |
|
|
1121
|
+
| `input_required` | 需要发起方补充信息 |
|
|
1122
|
+
| `completed` | 正常完成(终态) |
|
|
1123
|
+
| `failed` | 执行失败(终态) |
|
|
1124
|
+
| `canceled` | 被取消(终态) |
|
|
1125
|
+
|
|
1126
|
+
终态任务 **MAY** 允许读取历史,但 **MUST NOT** 再接受新的执行输入。
|
|
1127
|
+
|
|
1128
|
+
#### `task.create`
|
|
1129
|
+
|
|
1130
|
+
**请求**:
|
|
1131
|
+
```json
|
|
1132
|
+
{
|
|
1133
|
+
"jsonrpc": "2.0",
|
|
1134
|
+
"id": 50,
|
|
1135
|
+
"method": "task.create",
|
|
1136
|
+
"params": {
|
|
1137
|
+
"to": "reviewer.aid.pub",
|
|
1138
|
+
"input": {"type": "text", "content": "请审查这个 PR 的风险点"},
|
|
1139
|
+
"visibility": "private"
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
```
|
|
1143
|
+
|
|
1144
|
+
**响应**:
|
|
1145
|
+
```json
|
|
1146
|
+
{
|
|
1147
|
+
"jsonrpc": "2.0",
|
|
1148
|
+
"id": 50,
|
|
1149
|
+
"result": {
|
|
1150
|
+
"task_id": "task_01HV7J6N8F",
|
|
1151
|
+
"status": "submitted",
|
|
1152
|
+
"owner": "alice.aid.pub",
|
|
1153
|
+
"assignee": "reviewer.aid.pub",
|
|
1154
|
+
"created_at": "2026-03-21T13:00:00Z"
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
#### `task.get`
|
|
1160
|
+
|
|
1161
|
+
**请求**:
|
|
1162
|
+
```json
|
|
1163
|
+
{"jsonrpc": "2.0", "id": 51, "method": "task.get", "params": {"task_id": "task_01HV7J6N8F"}}
|
|
1164
|
+
```
|
|
1165
|
+
|
|
1166
|
+
**响应**:返回完整任务对象(含 `status`、`participants`、`children`、`messages`、`artifacts` 等)。
|
|
1167
|
+
|
|
1168
|
+
#### `task.accept`
|
|
1169
|
+
|
|
1170
|
+
接收方显式受理任务,把 `submitted` 推进到 `working`。
|
|
1171
|
+
|
|
1172
|
+
**请求**:
|
|
1173
|
+
```json
|
|
1174
|
+
{"jsonrpc": "2.0", "id": 52, "method": "task.accept", "params": {"task_id": "task_01HV7J6N8F"}}
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
**响应**:
|
|
1178
|
+
```json
|
|
1179
|
+
{"jsonrpc": "2.0", "id": 52, "result": {"task_id": "task_01HV7J6N8F", "status": "working"}}
|
|
1180
|
+
```
|
|
1181
|
+
|
|
1182
|
+
#### `task.reject`
|
|
1183
|
+
|
|
1184
|
+
接收方显式拒绝受理任务。
|
|
1185
|
+
|
|
1186
|
+
**请求**:
|
|
1187
|
+
```json
|
|
1188
|
+
{"jsonrpc": "2.0", "id": 53, "method": "task.reject", "params": {"task_id": "task_01HV7J6N8F", "reason": "unsupported_scope"}}
|
|
1189
|
+
```
|
|
1190
|
+
|
|
1191
|
+
**响应**:
|
|
1192
|
+
```json
|
|
1193
|
+
{"jsonrpc": "2.0", "id": 53, "result": {"task_id": "task_01HV7J6N8F", "status": "rejected"}}
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
#### `task.send_input`
|
|
1197
|
+
|
|
1198
|
+
向任务追加新的输入,用于继续协作或响应 `input_required`。
|
|
1199
|
+
|
|
1200
|
+
**请求**:
|
|
1201
|
+
```json
|
|
1202
|
+
{
|
|
1203
|
+
"jsonrpc": "2.0",
|
|
1204
|
+
"id": 54,
|
|
1205
|
+
"method": "task.send_input",
|
|
1206
|
+
"params": {
|
|
1207
|
+
"task_id": "task_01HV7J6N8F",
|
|
1208
|
+
"input": {"type": "text", "content": "补充说明:重点检查数据库迁移部分"}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
**响应**:
|
|
1214
|
+
```json
|
|
1215
|
+
{"jsonrpc": "2.0", "id": 54, "result": {"task_id": "task_01HV7J6N8F", "status": "working"}}
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
#### `task.delegate`
|
|
1219
|
+
|
|
1220
|
+
把当前任务的一个子问题委派给另一个 Agent,创建子任务。
|
|
1221
|
+
|
|
1222
|
+
**请求**:
|
|
1223
|
+
```json
|
|
1224
|
+
{
|
|
1225
|
+
"jsonrpc": "2.0",
|
|
1226
|
+
"id": 55,
|
|
1227
|
+
"method": "task.delegate",
|
|
1228
|
+
"params": {
|
|
1229
|
+
"task_id": "task_01HV7J6N8F",
|
|
1230
|
+
"to": "db-reviewer.aid.pub",
|
|
1231
|
+
"input": {"type": "text", "content": "请专门检查数据库迁移风险"}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
**响应**:
|
|
1237
|
+
```json
|
|
1238
|
+
{
|
|
1239
|
+
"jsonrpc": "2.0",
|
|
1240
|
+
"id": 55,
|
|
1241
|
+
"result": {
|
|
1242
|
+
"task_id": "task_child_01",
|
|
1243
|
+
"parent_task_id": "task_01HV7J6N8F",
|
|
1244
|
+
"status": "submitted",
|
|
1245
|
+
"assignee": "db-reviewer.aid.pub"
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
- 服务端 **SHOULD** 限制递归委派深度和扇出数量,避免任务风暴
|
|
1251
|
+
|
|
1252
|
+
#### `task.complete`
|
|
1253
|
+
|
|
1254
|
+
将任务标记为完成,附带最终产物。
|
|
1255
|
+
|
|
1256
|
+
**请求**:
|
|
1257
|
+
```json
|
|
1258
|
+
{
|
|
1259
|
+
"jsonrpc": "2.0",
|
|
1260
|
+
"id": 56,
|
|
1261
|
+
"method": "task.complete",
|
|
1262
|
+
"params": {
|
|
1263
|
+
"task_id": "task_01HV7J6N8F",
|
|
1264
|
+
"artifacts": [{
|
|
1265
|
+
"id": "artifact-1",
|
|
1266
|
+
"type": "text",
|
|
1267
|
+
"name": "summary",
|
|
1268
|
+
"mime_type": "text/markdown",
|
|
1269
|
+
"content": "数据库迁移存在锁表风险"
|
|
1270
|
+
}]
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
#### `task.fail`
|
|
1276
|
+
|
|
1277
|
+
将任务标记为失败。
|
|
1278
|
+
|
|
1279
|
+
**请求**:
|
|
1280
|
+
```json
|
|
1281
|
+
{"jsonrpc": "2.0", "id": 57, "method": "task.fail", "params": {"task_id": "task_01HV7J6N8F", "reason": "missing_required_context"}}
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
#### `task.cancel`
|
|
1285
|
+
|
|
1286
|
+
取消未完成任务。
|
|
1287
|
+
|
|
1288
|
+
**请求**:
|
|
1289
|
+
```json
|
|
1290
|
+
{"jsonrpc": "2.0", "id": 58, "method": "task.cancel", "params": {"task_id": "task_01HV7J6N8F", "reason": "user_abort"}}
|
|
1291
|
+
```
|
|
1292
|
+
|
|
1293
|
+
**响应**:
|
|
1294
|
+
```json
|
|
1295
|
+
{"jsonrpc": "2.0", "id": 58, "result": {"task_id": "task_01HV7J6N8F", "status": "canceled"}}
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
#### `task.children`
|
|
1299
|
+
|
|
1300
|
+
列出指定任务的子任务摘要。
|
|
1301
|
+
|
|
1302
|
+
**请求**:
|
|
1303
|
+
```json
|
|
1304
|
+
{"jsonrpc": "2.0", "id": 59, "method": "task.children", "params": {"task_id": "task_01HV7J6N8F"}}
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
#### `task.list`
|
|
1308
|
+
|
|
1309
|
+
分页列出任务。
|
|
1310
|
+
|
|
1311
|
+
**请求**:
|
|
1312
|
+
```json
|
|
1313
|
+
{"jsonrpc": "2.0", "id": 60, "method": "task.list", "params": {"status": "working", "limit": 20, "cursor": null}}
|
|
1314
|
+
```
|
|
1315
|
+
|
|
1316
|
+
- 返回结果 **MUST** 受调用方身份约束,**MUST NOT** 泄露无权访问的任务
|
|
1317
|
+
|
|
1318
|
+
#### `task.subscribe`
|
|
1319
|
+
|
|
1320
|
+
订阅任务后续事件。
|
|
1321
|
+
|
|
1322
|
+
**请求**:
|
|
1323
|
+
```json
|
|
1324
|
+
{
|
|
1325
|
+
"jsonrpc": "2.0",
|
|
1326
|
+
"id": 61,
|
|
1327
|
+
"method": "task.subscribe",
|
|
1328
|
+
"params": {"task_ids": ["task_01HV7J6N8F"], "events": ["updated", "completed", "artifact"]}
|
|
1329
|
+
}
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
**响应**:
|
|
1333
|
+
```json
|
|
1334
|
+
{"jsonrpc": "2.0", "id": 61, "result": {"subscribed": ["task_01HV7J6N8F"]}}
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
- 服务端 **MUST NOT** 为无访问权限的任务建立订阅
|
|
1338
|
+
- 服务端 **MAY** 在连接断开后丢失订阅状态,客户端应负责重订阅
|
|
1339
|
+
|
|
1340
|
+
#### 任务事件
|
|
1341
|
+
|
|
1342
|
+
```text
|
|
1343
|
+
event/task.updated # 任务状态更新
|
|
1344
|
+
event/task.completed # 任务完成
|
|
1345
|
+
event/task.failed # 任务失败
|
|
1346
|
+
event/task.artifact # 任务产物可用
|
|
1347
|
+
event/task.delegated # 已创建子任务
|
|
1348
|
+
```
|
|
1349
|
+
|
|
1350
|
+
**`event/task.updated` 示例**:
|
|
1351
|
+
```json
|
|
1352
|
+
{
|
|
1353
|
+
"jsonrpc": "2.0",
|
|
1354
|
+
"method": "event/task.updated",
|
|
1355
|
+
"params": {
|
|
1356
|
+
"task_id": "task_01HV7J6N8F",
|
|
1357
|
+
"status": "input_required",
|
|
1358
|
+
"updated_at": "2026-03-21T13:01:00Z",
|
|
1359
|
+
"message": {"type": "text", "content": "请提供 PR 链接"}
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
```
|
|
1363
|
+
|
|
1364
|
+
#### 错误码
|
|
1365
|
+
|
|
1366
|
+
| 错误码 | 名称 | 说明 |
|
|
1367
|
+
|-------:|------|------|
|
|
1368
|
+
| `-32170` | Task not found | 指定任务不存在 |
|
|
1369
|
+
| `-32171` | Task state invalid | 当前状态不允许该操作 |
|
|
1370
|
+
| `-32172` | Task input required | 需要补充输入 |
|
|
1371
|
+
| `-32173` | Task canceled | 任务已取消 |
|
|
1372
|
+
| `-32174` | Task output too large | 输出过大,应改用 `storage.*` 引用 |
|
|
1373
|
+
| `-32175` | Task access denied | 无权访问该任务 |
|
|
1374
|
+
| `-32176` | Task already accepted | 不能重复 accept |
|
|
1375
|
+
| `-32177` | Task rejected | 任务已被拒绝 |
|
|
1376
|
+
| `-32178` | Task delegation denied | 无权创建子任务 |
|
|
1377
|
+
| `-32179` | Task child limit exceeded | 子任务数量或深度超限 |
|
|
1378
|
+
| `-32185` | Task completion blocked | 存在未完成的必需子任务 |
|
|
1379
|
+
| `-32186` | Task failure recorded | 任务已进入失败终态 |
|
|
1380
|
+
|
|
1381
|
+
---
|
|
1382
|
+
|
|
1383
|
+
### 6.7 端到端加密(E2EE)摘要
|
|
1384
|
+
|
|
1385
|
+
> 当前 V2 主路径见 [E2EE V2 消息通信时序图](../sdk/E2EE_V2消息通信时序图.md);群组规范见 [08-AUN-E2EE-Group](08-AUN-E2EE-Group.md)。[08-AUN-E2EE](08-AUN-E2EE.md) 仅说明 Legacy 信封。
|
|
1386
|
+
|
|
1387
|
+
**核心原则**:
|
|
1388
|
+
|
|
1389
|
+
- E2EE 加解密**完全由客户端实现**,无需在线协商
|
|
1390
|
+
- 服务端只做消息中转和 prekey 存储,对加密内容完全透明
|
|
1391
|
+
- 当前 P2P 使用 `message.send` 承载 `e2ee.p2p_encrypted` 信封,群组使用 `group.v2.send` 承载 `e2ee.group_encrypted` 信封
|
|
1392
|
+
- 当前默认每消息独立密钥,按设备使用 `3DH` / `1DH` wrap;`prekey_ecdh_v2` / `long_term_key` 仅用于 Legacy 兼容
|
|
1393
|
+
|
|
1394
|
+
**服务端兼容性要求**:
|
|
1395
|
+
|
|
1396
|
+
- 接受并转发当前 V2 加密信封及 Legacy `encrypted: true` 消息
|
|
1397
|
+
- 在离线队列和历史消息中存储密文 payload
|
|
1398
|
+
- 不对密文 payload 施加额外的语义解析要求
|
|
1399
|
+
- 当前 P2P 设备 SPK 使用 `message.v2.put_peer_pk` / `message.v2.bootstrap`;`message.e2ee.put_prekey` / `message.e2ee.get_prekey` 仅为 Legacy 兼容
|
|
1400
|
+
|
|
1401
|
+
**互操作要求**:
|
|
1402
|
+
|
|
1403
|
+
跨语言、跨平台 SDK 必须按当前 V2 路径保持算法、信封、AAD 与 recipient proof 一致;旧格式才适用 [Legacy E2EE 规范](08-AUN-E2EE.md),不得用旧信封替代默认 V2 发送格式。
|
|
1404
|
+
|
|
1405
|
+
**错误码**:
|
|
1406
|
+
|
|
1407
|
+
| 错误码 | 名称 | 说明 |
|
|
1408
|
+
|-------:|------|------|
|
|
1409
|
+
| `-32604` | E2EE capability required | 客户端不支持群组 E2EE(无法加入群组) |
|
|
1410
|
+
|
|
1411
|
+
---
|
|
1412
|
+
|
|
1413
|
+
### 6.8 跨域消息路由
|
|
1414
|
+
|
|
1415
|
+
**当前实现事实**:
|
|
1416
|
+
|
|
1417
|
+
- 跨域消息路由已落地在 Gateway federation 通道上
|
|
1418
|
+
- 本域服务通过 `gateway.forward_federation` / `gateway.forward_federation_batch` 发起跨域 RPC 中继
|
|
1419
|
+
- Gateway federation client 当前通过 `https://{issuer}/.well-known/aun-gateway` 发现远端 Gateway 地址
|
|
1420
|
+
- 远端 Gateway 通过 `federation.hello` 完成双向认证后,接收 `federation.relay` / `federation.relay_batch`
|
|
1421
|
+
- `message.send`、`message.query_online`、`storage.*`、`group.*` 等服务当前都已复用该通道进行跨域转发
|
|
1422
|
+
|
|
1423
|
+
**当前约束**:
|
|
1424
|
+
|
|
1425
|
+
- 这是一条 Gateway 级 federation 中继通道,不是独立的 `message.*` 子协议扩展
|
|
1426
|
+
- 跨域转发的具体可用 namespace 受 Gateway 白名单控制
|
|
1427
|
+
- 服务端会向被中继的 RPC 注入 `_federation` 上下文,并校验调用方 AID 的 issuer 与来源 issuer 一致
|
|
1428
|
+
|
|
1429
|
+
**错误语义**:
|
|
1430
|
+
|
|
1431
|
+
- `gateway.forward_federation` 当前在连接失败时返回 `-32010`
|
|
1432
|
+
- 超时时返回 `-32011`
|
|
1433
|
+
- 运行时拒绝或协议错误返回 `-32012`
|