@agentunion/fastaun 0.5.33 → 0.5.34

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/README.md +28 -26
  3. package/_packed_docs/CHANGELOG.md +30 -2
  4. package/_packed_docs/INDEX.md +17 -3
  5. package/_packed_docs/KITE_DOCS_GUIDE.md +10 -4
  6. package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +58 -8
  7. package/_packed_docs/sdk/0.5.33-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +464 -316
  8. package/_packed_docs/sdk/0.5.33-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +499 -304
  9. package/_packed_docs/sdk/0.5.34-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +133 -0
  10. package/_packed_docs/sdk/0.5.34-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +107 -0
  11. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +16 -13
  12. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +13 -1
  13. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +17 -7
  14. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +55 -14
  15. package/_packed_docs/sdk/09-collab-rpc-manual.md +48 -30
  16. package/_packed_docs/sdk/09-custody-api-manual.md +3 -3
  17. package/_packed_docs/sdk/09-group-rpc-manual.md +53 -6
  18. package/_packed_docs/sdk/09-message-rpc-manual.md +22 -0
  19. package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -1
  20. package/_packed_docs/sdk/09-payload-reference.md +9 -8
  21. package/_packed_docs/sdk/09-proxy-rpc-manual.md +20 -14
  22. package/_packed_docs/sdk/09-storage-rpc-manual.md +1698 -1659
  23. package/_packed_docs/sdk/09-stream-rpc-manual.md +33 -20
  24. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +11 -9
  25. package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +53 -28
  26. package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/274/200/345/217/221/347/247/273/346/244/215/346/214/207/345/215/227.md +62 -28
  27. package/_packed_docs/sdk/INDEX.md +21 -9
  28. package/_packed_docs/sdk/README.md +11 -6
  29. package/dist/auth.js +8 -2
  30. package/dist/auth.js.map +1 -1
  31. package/dist/client/control-messages.js +2 -2
  32. package/dist/client/control-messages.js.map +1 -1
  33. package/dist/client/delivery.d.ts +5 -0
  34. package/dist/client/delivery.js +146 -32
  35. package/dist/client/delivery.js.map +1 -1
  36. package/dist/client/lifecycle.js +3 -0
  37. package/dist/client/lifecycle.js.map +1 -1
  38. package/dist/client/rpc-budget.d.ts +21 -0
  39. package/dist/client/rpc-budget.js +82 -0
  40. package/dist/client/rpc-budget.js.map +1 -0
  41. package/dist/client/rpc-pipeline.d.ts +3 -0
  42. package/dist/client/rpc-pipeline.js +166 -60
  43. package/dist/client/rpc-pipeline.js.map +1 -1
  44. package/dist/client/sync-channels.d.ts +89 -0
  45. package/dist/client/sync-channels.js +489 -0
  46. package/dist/client/sync-channels.js.map +1 -0
  47. package/dist/client/v2-e2ee.d.ts +4 -1
  48. package/dist/client/v2-e2ee.js +401 -298
  49. package/dist/client/v2-e2ee.js.map +1 -1
  50. package/dist/client.d.ts +2 -0
  51. package/dist/client.js +63 -1
  52. package/dist/client.js.map +1 -1
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.js.map +1 -1
  55. package/dist/pubsub/binding.js +14 -1
  56. package/dist/pubsub/binding.js.map +1 -1
  57. package/dist/pubsub/channel.d.ts +4 -0
  58. package/dist/pubsub/channel.js +26 -0
  59. package/dist/pubsub/channel.js.map +1 -1
  60. package/dist/pubsub/client.d.ts +9 -0
  61. package/dist/pubsub/client.js +154 -31
  62. package/dist/pubsub/client.js.map +1 -1
  63. package/dist/pubsub/credentials.d.ts +3 -0
  64. package/dist/pubsub/credentials.js +57 -20
  65. package/dist/pubsub/credentials.js.map +1 -1
  66. package/dist/pubsub/index.d.ts +3 -0
  67. package/dist/pubsub/index.js +69 -53
  68. package/dist/pubsub/index.js.map +1 -1
  69. package/dist/pubsub/service.d.ts +3 -0
  70. package/dist/pubsub/service.js +167 -12
  71. package/dist/pubsub/service.js.map +1 -1
  72. package/dist/pubsub/types.d.ts +2 -0
  73. package/dist/storage/lowlevel.d.ts +3 -1
  74. package/dist/storage/lowlevel.js +13 -0
  75. package/dist/storage/lowlevel.js.map +1 -1
  76. package/dist/storage/types.d.ts +10 -0
  77. package/dist/storage/types.js.map +1 -1
  78. package/dist/storage/vfs.d.ts +3 -1
  79. package/dist/storage/vfs.js +2 -2
  80. package/dist/storage/vfs.js.map +1 -1
  81. package/dist/tools/cross-sdk-agent.d.ts +55 -5
  82. package/dist/tools/cross-sdk-agent.js +88 -21
  83. package/dist/tools/cross-sdk-agent.js.map +1 -1
  84. package/dist/transport.d.ts +12 -0
  85. package/dist/transport.js +91 -6
  86. package/dist/transport.js.map +1 -1
  87. package/dist/version.d.ts +1 -1
  88. package/dist/version.js +1 -1
  89. package/package.json +1 -1
@@ -6,7 +6,15 @@
6
6
  >
7
7
  > **授权 = 协作根写 ACL**:谁能 `commit` = 谁对 `collab_root` 有写权限。普通 AID storage 可继续用 `storage.set_acl/remove_acl` 管理写授权;群 `memberdata` 协作根必须用 `collab.set_acl/remove_acl` 按 `collab_root` 授权,SDK/CLI 不得拼接真实 `group_data` 路径。
8
8
  >
9
- > SDK 侧通过 `client.collab` 访问(`CollabClient`),每个命令 1:1 映射一条 `collab.*` RPC。
9
+ > Python / TypeScript / Browser SDK 通过 `client.collab` 访问(`CollabClient`);Go 使用 `client.Collab()`,标签入口为 `.Tag()`。每个命令映射一条 `collab.*` RPC。
10
+
11
+ ## SDK 返回差异
12
+
13
+ 下文定义服务端原始 RPC 字段。Python / TypeScript / Browser 保留原始结果;Go 0.5.34 的类型化返回尚有以下差异,需要完整字段时使用原始 `client.Call()`:
14
+
15
+ - GC 不保留 `reachable` / `freed_bytes`;Reflog 不保留 `seq` / `metadata`,且其 `RequesterAID` / `CreatedAt` 不能接收当前 `requester` / `timestamp` 字段。
16
+ - Tag Create 不保留 `bump` / `changed`;Revert 不保留 `no_change`;Tag Restore 不保留 `partial`,`new_snapshot_version: null` 解析为空字符串。
17
+ - Tag Diff 的 `added` / `removed` 实际为文档名字符串数组,Go 类型仍按对象数组解析,非空时会返回解码错误;Tag Rm 的 `removed: true` 转为整数 `1`,且不保留 `version`。
10
18
 
11
19
  ## 方法索引
12
20
 
@@ -74,11 +82,11 @@
74
82
 
75
83
  ### 乐观锁(commit)
76
84
 
77
- 1. `put_object`(写新版本文件,永不失败,数据先存下)。
85
+ 1. `put_object` 写入候选版本文件;上传失败直接返回错误。
78
86
  2. 同一事务:`atomic_repoint(<doc>@current, new_target, expected_version=onto)` + 台账追加。
79
- 3. CAS 成功 → version+1;CAS 失败 → 整事务回滚,返回 `{ok:false, current_version, hint}`。
87
+ 3. CAS 成功 → version+1;CAS 失败 → 返回 JSON-RPC `-32009`,`error.data` 包含 `current_version`、`current_target`、`hint`,并清理候选文件。
80
88
 
81
- `onto` 来源:`collab.show` 响应的 `version` 字段;merge 后用 commit 失败响应的 `current_version`。
89
+ `onto` 来源:`collab.show` 响应的 `version` 字段;冲突时由 SDK 的 `CollabConflictError` 取得当前版本,合并后再提交。失败请求不保证保留候选正文,调用方应保留自己的草稿。
82
90
 
83
91
  ### 数据不变量
84
92
 
@@ -126,7 +134,7 @@ docs = await client.collab.ls_files("alice.aid.pub:/projects/myapp")
126
134
  |------|------|------|------|
127
135
  | `collab_root` | string | 是 | 协作根 `<aid>:<path>` |
128
136
  | `doc` | string | 是 | 文档名 |
129
- | `source` | string | 是 | 初始内容:本地文件路径或 `<aid>:<path>` |
137
+ | `source` | string | 是 | Base64 编码的正文或可读的 `<aid>:<path>`;SDK 不读取本地文件路径 |
130
138
 
131
139
  ### 响应
132
140
 
@@ -153,11 +161,11 @@ docs = await client.collab.ls_files("alice.aid.pub:/projects/myapp")
153
161
 
154
162
  | 字段 | 类型 | 说明 |
155
163
  |------|------|------|
156
- | `content` | string | base64 编码的当前内容 |
164
+ | `content` | string | base64 编码的所读版本内容 |
157
165
  | `version` | integer | 当前或指定版本号(**commit 的 onto 来源**) |
158
- | `author` | string | 当前版本作者 AID |
159
- | `anchor` | string | 台账锚点(读取历史版本时返回) |
160
- | `current_target` | string | 当前版本文件绝对路径(读取当前版本时返回) |
166
+ | `author` | string | 所读版本作者 AID |
167
+ | `anchor` | string | 台账锚点,当前和历史版本均返回 |
168
+ | `current_target` | string | 所读版本文件绝对路径,当前和历史版本均返回 |
161
169
 
162
170
  ---
163
171
 
@@ -171,8 +179,9 @@ docs = await client.collab.ls_files("alice.aid.pub:/projects/myapp")
171
179
  |------|------|------|------|
172
180
  | `collab_root` | string | 是 | 协作根 `<aid>:<path>` |
173
181
  | `doc` | string | 是 | 文档名 |
174
- | `source` | string | 是 | 新内容:本地路径或 `<aid>:<path>` |
182
+ | `source` | string | 是 | Base64 编码的新正文或可读的 `<aid>:<path>`;不是本地文件路径 |
175
183
  | `onto` | integer | 是 | 基线版本号(来自 `collab.show` 的 `version`) |
184
+ | `message` | string | 否 | 台账说明,默认空字符串 |
176
185
 
177
186
  ### 响应
178
187
 
@@ -184,23 +193,27 @@ docs = await client.collab.ls_files("alice.aid.pub:/projects/myapp")
184
193
  | `version` | integer | 新版本号(onto+1) |
185
194
  | `current_target` | string | 新版本文件绝对路径 |
186
195
 
187
- **撞版本失败**(数据已安全保存,需 merge 后重提):
196
+ **撞版本失败**:JSON-RPC `-32009` 的 `error.data` 字段如下;四个 SDK 映射为 `CollabConflictError`,不是成功响应中的 `ok:false`。
188
197
 
189
198
  | 字段 | 类型 | 说明 |
190
199
  |------|------|------|
191
- | `ok` | boolean | `false` |
192
200
  | `current_version` | integer | 当前权威版本号(**merge 后 commit 用此作新 onto**) |
193
201
  | `current_target` | string | 当前权威版本文件绝对路径 |
194
- | `hint` | string | 后端格式化好的下一步命令行字符串 |
202
+ | `hint` | string | 合并并重新提交的提示语,不是可执行命令 |
195
203
 
196
204
  ### 示例
197
205
 
198
206
  ```python
207
+ from aun_core.collab.errors import CollabConflictError
208
+ import base64
209
+ source = base64.b64encode(draft_bytes).decode()
199
210
  cur = await client.collab.show(root, "design.md")
200
- res = await client.collab.commit(root, "design.md", "./design.md", cur["version"])
201
- if not res["ok"]:
202
- await client.collab.merge(root, "design.md", "./design.md", cur["version"])
203
- res = await client.collab.commit(root, "design.md", "./design.md", res["current_version"])
211
+ try:
212
+ res = await client.collab.commit(root, "design.md", source, cur["version"])
213
+ except CollabConflictError as conflict:
214
+ merged = await client.collab.merge(root, "design.md", source, cur["version"])
215
+ if not merged["conflicts"]:
216
+ res = await client.collab.commit(root, "design.md", merged["content"], conflict.current_version)
204
217
  ```
205
218
 
206
219
  ---
@@ -215,7 +228,7 @@ if not res["ok"]:
215
228
  |------|------|------|------|
216
229
  | `collab_root` | string | 是 | 协作根 `<aid>:<path>` |
217
230
  | `doc` | string | 是 | 文档名 |
218
- | `source` | string | 是 | 本地草稿内容(ours):本地路径或 `<aid>:<path>` |
231
+ | `source` | string | 是 | 草稿内容(ours):Base64 正文或可读的 `<aid>:<path>` |
219
232
  | `onto` | integer | 是 | 共同祖先版本号 |
220
233
 
221
234
  ### 响应
@@ -225,7 +238,7 @@ if not res["ok"]:
225
238
  | `content` | string | base64 编码的合并结果 |
226
239
  | `conflicts` | boolean | 是否含冲突标记(`<<<<<<<` / `=======` / `>>>>>>>`) |
227
240
 
228
- `conflicts=true` 时需人工编辑消解冲突后再 commit。
241
+ merge 只计算并返回正文,不修改草稿或当前版本。`conflicts=true` 时需编辑消解冲突;提交时将合并正文编码后传给 `commit`。
229
242
 
230
243
  ---
231
244
 
@@ -256,8 +269,8 @@ if not res["ok"]:
256
269
  |------|------|------|------|
257
270
  | `collab_root` | string | 是 | 协作根 `<aid>:<path>` |
258
271
  | `doc` | string | 是 | 文档名 |
259
- | `from` | integer | 是 | 起始版本号(SDK 形参 `v_from`) |
260
- | `to` | integer | 是 | 目标版本号(SDK 形参 `v_to`) |
272
+ | `from` | integer | 是 | 起始版本号;Python 形参 `v_from`,TS/Browser/Go 为 `fromVersion` |
273
+ | `to` | integer | 是 | 目标版本号;Python 形参 `v_to`,TS/Browser/Go 为 `toVersion` |
261
274
 
262
275
  ### 响应
263
276
 
@@ -342,7 +355,7 @@ if not res["ok"]:
342
355
 
343
356
  ### 响应
344
357
 
345
- 返回日志数组,每项包含 `seq`、`action`、`requester`、`doc`、`version`、`onto`、`target`、`status`、`error_code`、`error_msg`、`metadata`、`timestamp` 等字段。
358
+ 返回日志数组,每项包含 `seq`、`action`、`requester`、`doc`、`version`、`base_version`、`target`、`status`、`error_code`、`error_msg`、`metadata`、`timestamp` 等字段。
346
359
 
347
360
  ---
348
361
 
@@ -441,13 +454,13 @@ if not res["ok"]:
441
454
 
442
455
  ### 响应
443
456
 
444
- 返回新增/删除/版本变化的文档清单。
457
+ 返回 `added`、`removed`、`changed` 三个文档名字符串数组。
445
458
 
446
459
  ---
447
460
 
448
461
  ## collab.tag.restore
449
462
 
450
- 回滚到某标签。**forward-only**:不回退 version 计数器,而是对每个文档以标签中的旧内容写一个新版本(vN+1),最后以回滚后状态自动创建新标签。
463
+ 回滚到某标签。**forward-only**:不回退 version 计数器,而是对每个文档以标签中的旧内容写一个新版本(vN+1),完成后尝试创建新标签;部分失败或无变化时不保证产生新标签。
451
464
 
452
465
  ### 参数
453
466
 
@@ -462,14 +475,16 @@ if not res["ok"]:
462
475
  | 字段 | 类型 | 说明 |
463
476
  |------|------|------|
464
477
  | `restored_from` | string | 回滚来源标签版本 |
465
- | `new_snapshot_version` | string | 回滚后自动创建的新标签版本(历史字段名保留为 `new_snapshot_version`) |
478
+ | `new_snapshot_version` | string / null | 回滚后创建的新标签版本;部分失败或无变化时可为 `null`,历史字段名保留 |
466
479
  | `warnings` | array | 回滚过程中的告警(如某文档被他人并发提交而跳过) |
480
+ | `restored_docs` | array | 已恢复的文档 |
481
+ | `partial` | boolean | 可选;部分失败时为 `true`,RPC 本身仍可成功返回 |
467
482
 
468
483
  ---
469
484
 
470
485
  ## collab.tag.rm
471
486
 
472
- 删除单个标签。
487
+ 删除单个标签;当前活动标签不能删除。
473
488
 
474
489
  ### 参数
475
490
 
@@ -482,7 +497,8 @@ if not res["ok"]:
482
497
 
483
498
  | 字段 | 类型 | 说明 |
484
499
  |------|------|------|
485
- | `ok` | boolean | `true` |
500
+ | `removed` | boolean | 是否删除 |
501
+ | `version` | string | 标签版本 |
486
502
 
487
503
  ---
488
504
 
@@ -537,7 +553,7 @@ if not res["ok"]:
537
553
 
538
554
  | 字段 | 类型 | 说明 |
539
555
  |------|------|------|
540
- | `ok` | boolean | `true` |
556
+ | `removed` | integer | 删除的注册表条目数 |
541
557
 
542
558
  ---
543
559
 
@@ -577,5 +593,7 @@ if not res["ok"]:
577
593
  | -32002 | 服务暂不可用(数据库未连接) |
578
594
  | -32004 | 权限拒绝(requester 对 collab_root 无写权限) |
579
595
  | -32008 | 协作文档 / 版本 / 标签不存在 |
580
- | -32009 | 版本冲突(commit 撞版本,见 `ok:false` 响应;tag create 时标签头已移动) |
581
- | -32000 | 通用错误(参数校验失败、源内容读取失败、无变更可打标签等) |
596
+ | -32009 | 版本冲突;commit 的 `error.data` 包含当前版本与合并提示,tag create 时也可能表示标签头已移动 |
597
+ | -32010 | 无变化可创建标签 |
598
+ | -32602 | 参数校验失败 |
599
+ | -32000 | 其它服务错误,如源内容读取失败 |
@@ -20,7 +20,7 @@ SDK 使用约束:
20
20
 
21
21
  - `custody_url` 不作为 `AUNClient` 构造配置参数传入。
22
22
  - Python SDK 不在 `AUNClient` 上挂载 custody namespace;需要时使用独立 custody 辅助客户端或直接按本手册 HTTP API 调用。
23
- - TS / JS / Go 仍保留历史 custody namespace 兼容层;新代码应避免把 custody 当作 AUNClient 核心会话能力。
23
+ - 各 SDK 均不把 custody 作为 AUNClient 核心会话能力;如需调用,请使用独立 custody 辅助客户端(若 SDK 提供)或直接按本手册 HTTP API 调用。
24
24
  - 可通过 `https://{aid}/.well-known/aun-custody` 自动发现官方托管服务地址,并缓存发现结果。
25
25
 
26
26
  ## 手机号验证码备份/恢复时序
@@ -96,8 +96,8 @@ SDK 方法:
96
96
  | 语言 | 发起复制 | 上传复制材料 | 领取复制材料 |
97
97
  |------|----------|--------------|--------------|
98
98
  | Python | 独立 custody 辅助客户端或 HTTP API | 独立 custody 辅助客户端或 HTTP API | 独立 custody 辅助客户端或 HTTP API |
99
- | JS/TS | 历史 custody namespace 兼容层或 HTTP API | 历史 custody namespace 兼容层或 HTTP API | 历史 custody namespace 兼容层或 HTTP API |
100
- | Go | 历史 custody namespace 兼容层或 HTTP API | 历史 custody namespace 兼容层或 HTTP API | 历史 custody namespace 兼容层或 HTTP API |
99
+ | JS/TS | 独立 custody 辅助客户端(若 SDK 提供)或 HTTP API | 独立 custody 辅助客户端(若 SDK 提供)或 HTTP API | 独立 custody 辅助客户端(若 SDK 提供)或 HTTP API |
100
+ | Go | 独立 custody 辅助客户端(若 SDK 提供)或 HTTP API | 独立 custody 辅助客户端(若 SDK 提供)或 HTTP API | 独立 custody 辅助客户端(若 SDK 提供)或 HTTP API |
101
101
 
102
102
  复制请求:
103
103
 
@@ -129,6 +129,8 @@
129
129
  | [group.fs.lstat](#groupfslstat) | 查看链接本身 |
130
130
  | [group.fs.df](#groupfsdf) | 查看用量 |
131
131
  | [group.fs.create_download_ticket](#groupfscreate_download_ticket) | 创建下载票据 |
132
+ | [group.fs.set_visibility](#groupfsset_visibility) | 设置节点可见性 |
133
+ | [group.fs.namespace_ready](#groupfsnamespace_ready) | 初始化群文件命名空间 |
132
134
  | [group.fs.set_acl](#groupfsset_acl) | 授予群自有区角色写 ACL |
133
135
  | [group.fs.remove_acl](#groupfsremove_acl) | 撤销群自有区角色写 ACL |
134
136
  | [group.fs.get_acl](#groupfsget_acl) | 查询群自有区角色 ACL |
@@ -1444,6 +1446,27 @@ result = await client.call("group.thought.get", {
1444
1446
  | `limit` | integer | 否 | 50 | Python V2 Forward 最大 200;其余模式保留原限制,`pull_max_limit` 配置可进一步收紧 |
1445
1447
  | `device_id` | string | 否 | — | 设备 ID(多设备模式) |
1446
1448
 
1449
+ #### 存储范围与字节分页
1450
+
1451
+ 群消息 Pull(含底层 `group.v2.pull`)、`group.history` 及 `group.pull_events` 支持可选字节上限;Forward Pull 通过存储范围选择持久或临时数据:
1452
+
1453
+ | 参数 | 类型 | 默认值 | 说明 |
1454
+ | --- | --- | --- | --- |
1455
+ | `storage_scope` | string | `all` | `all` 保持既有来源;`persistent` 只读取持久消息/事件;`volatile` 返回临时来源专用页 |
1456
+ | `max_page_bytes` | integer | 原服务配置 | 显式范围 `1024..786432`,按单次 RPC `result` 的 JSON 编码字节截页,与条数上限同时执行 |
1457
+
1458
+ `persistent` 不读取 volatile mailbox;`volatile` 沿用原消息类别、设备、slot 与 TTL 过滤,没有临时数据时返回空页。临时页不返回持久消息/事件 coverage、head 或 server ACK,也不接受 `ack_up_to_seq`、`before_seq` 或 `window_mode`。群消息与群事件仍使用独立游标,History 保持只读。
1459
+
1460
+ 首条记录超过预算时,`error.data.code="OVERSIZED_MESSAGE"`,并附带 `required_page_bytes`、`max_page_bytes` 及可用的记录标识;该失败页不推进游标或 ACK。后台 SDK 通过 `sync.error` 报告并停止该流自动续页,其它流继续;显式前台调用返回原错误。
1461
+
1462
+ 弹性历史请求使用 `persistent`,主辅合计初始编码预留 1 MiB,本地按页上限的 8 倍预留至消费结束、初始总额 8 MiB;实时临时页独立走主连接。群成员可见性、入群下界及 ACK 提交规则沿用原契约。
1463
+
1464
+ SDK 遵从 `max_aux_channels` 支持 0..N 条辅助连接(当前协议测试到 2);本轮 Gateway 对同一 AID+设备跨 slot 最多授权 1 条,开关关闭或压力回收时为 0。连接数量不是 Pull 总并发上限:同 namespace 串行,不同 namespace 可在策略和预算允许时并行。
1465
+
1466
+ 普通持久 Forward 带 `max_page_bytes` 时,`group.pull`、`group.v2.pull`、`group.pull_events` 可返回 `pending_count_lower_bound`(0—100);Group 当前 `all` 也只含持久来源。它只取本次既有读取、可见且去重候选中最终未返回的数量,包含字节截页移出的行,不新增查询、COUNT、扫描或读取 limit。缺省或 0 都不证明追平;续页、游标与 ACK 继续遵守原分页契约。force、Tail、History、control、sdk_control、volatile 不返回此提示。`limit+1` 通常只能证明还有 1 条,V2 原读取可能只能证明 0,不能保证识别所有单流大积压。
1467
+
1468
+ 普通短连接和 `history_sync` 补拉辅助连接均不触发或接收群 unread hint;群提示由主长连接接收。短连接显式调用 Pull 不受影响。
1469
+
1447
1470
  **响应**:
1448
1471
 
1449
1472
  ```json
@@ -1581,7 +1604,7 @@ SDK 只保证单个实时拉取响应页内按 seq 升序、同 seq 最多发布
1581
1604
  - `group.fs.set_acl` / `group.fs.remove_acl` / `group.fs.get_acl` / `group.fs.list_acl` 只能由当前 group `owner/admin` 调用。当前支持 `grantee_aid="role:admin"` 与 `grantee_aid="role:member"`;`role:member` 只能授予具体业务目录的 `rw` 权限,不能授予根目录或 `.group/`,也不能获得删除、移动、重命名权限。成员升降级、退群、踢出不会联动授权或撤销目录 ACL。
1582
1605
  - `memberdata/{member_ref}` 写入默认只允许该成员本人;SDK 只传 group path,不拼接真实 storage 路径。
1583
1606
  - 上传控制面会透传 `parents` 到 storage:默认 `parents=true` 时可递归创建父目录,显式 `parents=false` 时父目录必须已存在。
1584
- - JavaScript 浏览器版 `cp(string, group)` 默认把 string 当文本内容上传;Node 本地路径需显式传 `sourceType: "path"`、`localPath: true` 或使用 `local:` 前缀。Python、TypeScript 和 Go 默认把 string 当本地路径。
1607
+ - JavaScript SDK 的 `cp(string, group)` 默认把 string 当 UTF-8 文本内容上传;本地路径需显式传 `sourceType: "path"`、`localPath: true` 或使用 `local:` 前缀。Python、TypeScript 和 Go 默认把 string 当本地路径。
1585
1608
 
1586
1609
  ### SDK 默认读缓存
1587
1610
 
@@ -1591,7 +1614,7 @@ SDK 只保证单个实时拉取响应页内按 seq 升序、同 seq 最多发布
1591
1614
 
1592
1615
  ### group.fs.ls
1593
1616
 
1594
- 列出目录。参数:`path` 必填;可选 `page`、`size`、`marker`、`long`、`recursive`。响应返回 group view `items`,节点 `path` 仍为 group path。
1617
+ 列出目录。参数:`path` 必填;可选 `page`、`size`(也接受 `limit` 作为 `size` 别名)。当前 Group 服务将 `page` 规范化为至少 1、`size` 限制在 1..1000,并向 Storage 传递这两个分页参数;`marker`、`long`、`recursive` 不属于当前 RPC 的生效参数。响应返回 group view `items`,节点 `path` 仍为 group path。
1595
1618
 
1596
1619
  ### group.fs.find
1597
1620
 
@@ -1663,19 +1686,27 @@ Group FS 的读缓存保存符合策略的已验证正文,不把下载票据
1663
1686
 
1664
1687
  ### group.fs.create_upload_session
1665
1688
 
1666
- 创建上传会话。参数同 `check_upload`。响应透传 Storage session 字段并增加 Group FS 路径视图,包含 `upload_url`、`content_type`、`size_bytes` 等;当前 Storage 服务不返回 `session_id` 或 `headers`。四个 SDK 的 Group FS 门面会按实际字节识别 MIME,并在 session、HTTP PUT 与 complete 中保持 `Content-Type` 一致;若 session 返回 headers,SDK 保留其它 header 并替换其中的 Content-Type,避免 OSS 签名不一致导致 403。
1689
+ 创建上传会话。参数同 `check_upload`。响应透传 Storage session 字段并增加 Group FS 路径视图,通常包含 `upload_url`、可选 `session_id`、可选 `headers`、`content_type`、`size_bytes` 等。四个 SDK 的 Group FS 门面会按实际字节识别 MIME,并在 session、HTTP PUT 与 complete 中保持 `Content-Type` 一致;若 session 返回 headers,SDK 保留其它 header 并替换其中的 Content-Type,避免 OSS 签名不一致导致 403。
1667
1690
 
1668
1691
  ### group.fs.complete_upload
1669
1692
 
1670
1693
  完成上传。参数包含 `path`、`sha256`、`size_bytes`、可选 `session_id`、`skip_blob`、`metadata`、`expected_version`。响应为 group view NodeView。
1671
1694
 
1695
+ ### group.fs.set_visibility
1696
+
1697
+ 设置群自有区节点可见性。参数:`path` 必填;`visibility` 必填,为 `public` 或 `private`(也可用兼容布尔参数 `is_public`);可选 `expected_version`。`memberdata` 及其子路径的可见性由成员自挂载流程管理,不能通过此 RPC 修改。成功响应为 NodeView,并包含最终 `visibility`。
1698
+
1699
+ ### group.fs.namespace_ready
1700
+
1701
+ 初始化或检查群文件命名空间。参数:`group_id` 必填;可选 `folder_ids` 对已有 Storage 文件夹 ID 做绑定。调用者须为群身份、owner 或 admin。成功响应包含 `namespace_ready=true`、`baseline_paths`、`items`、`baseline_role_acls_synced`、`own_area_ready` 和 `memberdata_ready`;命名群的基线目录为 `.group`、`announce`、`public`、`archive`、`memberdata`,普通群至少返回 `memberdata`。该调用会触发缺失基线目录/ACL 的 best-effort 初始化。
1702
+
1672
1703
  ### group.fs.mount
1673
1704
 
1674
- 挂载成员数据区。参数:`path` 必填;可选 `readonly`、`require_approval`、`source_bucket`、`expires_at`、`volume_id`。
1705
+ 挂载成员数据区。`path` 必须是 `/memberdata/{member_ref}`(可使用带 group AID 的 group path);可选 `readonly`(默认 `true`)、`require_approval`(默认 `false`)、`source_bucket`、`expires_at`、`volume_id`。未提供 `volume_id` 时从成员 AID 和其群数据根目录挂载;提供 `volume_id` 时挂载指定 volume。
1675
1706
 
1676
1707
  ### group.fs.umount
1677
1708
 
1678
- 卸载成员数据区。参数:`path` 必填。对成员数据区卸载不删除成员源数据。
1709
+ 卸载成员数据区。`path` 必须是 `/memberdata/{member_ref}`(可使用带 group AID 的 group path);对成员数据区卸载不删除成员源数据。
1679
1710
 
1680
1711
  ## 在线状态
1681
1712
 
@@ -1716,7 +1747,9 @@ Group FS 的读缓存保存符合策略的已验证正文,不把下载票据
1716
1747
 
1717
1748
  ### group.pull_events
1718
1749
 
1719
- 增量拉取群事件,支持多设备独立游标。SDK 将其作为后台 Pull 放入当前 `AUNClient` 的客户端级 Pull Gate;该 Gate 与 P2P Message、Group Message Pull 共享,同一 namespace 单飞,客户端最多 4 个不同 namespace 并行。Group Event 使用 `group_event:{群标识}`,与同群消息 namespace 独立;相同完整请求 key 折叠并共享结果,可运行的不同 key 按后台 FIFO 调度并让前台请求优先。Group Event 使用独立的 Forward Cursor,不修改消息 A/T/H;不同 `AUNClient` 实例之间不共享 Gate。应用层无需自行实现并发控制。
1750
+ `storage_scope`、`max_page_bytes` 及超页错误沿用[群 Pull 的存储与字节分页规则](#存储范围与字节分页)。
1751
+
1752
+ 增量拉取群事件,支持多设备独立游标;`pending_count_lower_bound` 沿用上述普通持久字节限页规则。SDK 将其作为后台 Pull 放入当前 `AUNClient` 的客户端级 Pull Gate;该 Gate 与 P2P Message、Group Message Pull 共享,同一 namespace 单飞,客户端最多 4 个不同 namespace 并行。Group Event 使用 `group_event:{群标识}`,与同群消息 namespace 独立;相同完整请求 key 折叠并共享结果,可运行的不同 key 按后台 FIFO 调度并让前台请求优先。Group Event 使用独立的 Forward Cursor,不修改消息 A/T/H;不同 `AUNClient` 实例之间不共享 Gate。应用层无需自行实现并发控制。
1720
1753
 
1721
1754
  **参数**:
1722
1755
 
@@ -2006,6 +2039,20 @@ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x
2006
2039
  | `suspended` | 群组暂停 |
2007
2040
  | `resumed` | 群组恢复 |
2008
2041
  | `dissolved` | 群组解散 |
2042
+ | `fs_set_visibility` | 文件节点可见性变更 |
2043
+ | `fs_set_acl` | 文件节点 ACL 授予 |
2044
+ | `fs_remove_acl` | 文件节点 ACL 撤销 |
2045
+ | `fs_mkdir` | 创建目录 |
2046
+ | `fs_rm` | 删除节点 |
2047
+ | `fs_cp` | 远程复制节点 |
2048
+ | `fs_mv` | 远程移动节点 |
2049
+ | `fs_upload_completed` | 上传完成 |
2050
+ | `fs_mount` | 挂载成员数据区 |
2051
+ | `fs_umount` | 卸载成员数据区 |
2052
+ | `fs_namespace_ready` | 文件命名空间初始化完成 |
2053
+ | `fs_confirmed` | 文件 ACL 操作确认 |
2054
+ | `fs_mount_confirmed` | 挂载操作确认 |
2055
+ | `fs_mount_unavailable` | 挂载 volume 不可用 |
2009
2056
 
2010
2057
  **订阅**:
2011
2058
 
@@ -406,6 +406,25 @@ result = await client.call("message.thought.get", {
406
406
 
407
407
  新 SDK 的 peer Pull/Tail/History 单页默认及最大 200;旧 SDK 的 global 请求保留原默认值和限制。连接上线提示及重连恢复触发 pending 目录查询。后台同步的 `max_pages` 是工作片预算,达到 100 页仍有剩余时必须继续编排,不能将其当作同步终点。
408
408
 
409
+ ### 存储范围与字节分页
410
+
411
+ `message.pull`/底层 `message.v2.pull` 增加两个可选参数;旧请求不传时保留原行为:
412
+
413
+ | 参数 | 类型 | 默认值 | 说明 |
414
+ | --- | --- | --- | --- |
415
+ | `storage_scope` | string | `all` | `all` 合并原有来源;`persistent` 只读持久消息;`volatile` 只读当前设备/slot 的内存收件箱 |
416
+ | `max_page_bytes` | integer | 原服务配置 | 显式范围 `1024..786432`,按单次 RPC `result` 的 JSON 编码字节截页;可比 `limit` 更早结束 |
417
+
418
+ `persistent` 不读取 volatile mailbox。`volatile` 返回 `storage_scope`、`messages`、volatile cursor 与 `volatile_has_more` 等临时页信息,不返回持久 coverage/head/server ACK,不接受 `ack_up_to_seq`、Tail 或 History 条件;SDK 仅交付临时消息并更新独立 volatile cursor。`message.history` 保持只读持久消息,可使用相同字节上限。
419
+
420
+ 首条单消息仍超过预算时返回结构化错误,`error.data.code="OVERSIZED_MESSAGE"`,附带 `required_page_bytes`、`max_page_bytes` 及可用的消息标识。该页不成功,也不越过未返回消息推进游标。后台 SDK 发布 `sync.error`(`namespace`、`method`、`code`、`error`)并停止该流自动续页,其它流继续;显式前台调用返回原 RPC 错误。
421
+
422
+ 弹性历史补拉的初始页上限为 256 KiB,主辅共享编码预留 1 MiB、本地放大预留 8 MiB;历史 `persistent` 请求遵守 Gateway 策略,实时 `volatile` Pull 独立走主连接。设备、slot、TTL 和分类路由继续使用原有规则。
423
+
424
+ SDK 遵从 `max_aux_channels` 支持 0..N 条辅助连接(当前协议测试到 2);本轮 Gateway 对同一 AID+设备跨 slot 最多授权 1 条,开关关闭或压力回收时为 0。连接数量不是 Pull 总并发上限:同 namespace 串行,不同 namespace 可在策略和预算允许时并行。
425
+
426
+ 带 `max_page_bytes` 的普通 `persistent` Forward 响应可含 `pending_count_lower_bound`(1—100):只用本次既有读取、去重及可见性过滤后最终未返回的候选数,字节截页移出的行计入下界,不增加查询或读取 limit。未能证明正下界时省略;缺省不表示追平。该字段仅供 SDK 判断明显积压,续页/完成仍遵守原分页证明;force、Tail、History、control、sdk_control、volatile 和混合来源不返回。`limit+1` 常只能证明还有 1 条,不能据此声称所有单流大积压均能识别。
427
+
409
428
  ### 响应
410
429
 
411
430
  以下基础消息字段沿用原格式;下表扫描证明与页内计数描述服务端单次 RPC 的原始页。SDK 自动续页后可能合并 `messages`,即使保留某一页的 proof/count,也只能解释该原始页,不能用于验证或计数整个合并列表。多 peer 聚合外层返回 `peers` / `messages` / `partial`,保留逐 peer 进度,不提供全体 peer 共用的 proof、可提交游标或精确总计数。
@@ -441,6 +460,7 @@ result = await client.call("message.thought.get", {
441
460
  | `count` | integer | 本次返回的消息数 |
442
461
  | `latest_seq` | integer | 返回的最大 seq |
443
462
  | `has_more` | boolean | 服务端 Forward 响应中仍有可见持久消息未返回;通过 `limit + 1` 探测及响应截页确定,不由 `unread_count` 或恰好满页推断 |
463
+ | `pending_count_lower_bound` | integer | 可选,普通持久字节限页 Forward 的剩余候选数下界,上限 100;用于辅助连接门槛,不参与游标、ACK 或完成判断 |
444
464
  | `latest_volatile_cursor` | string\|null | 本页最后一个 volatile 游标;不影响 `latest_seq` |
445
465
  | `volatile_has_more` | boolean | 是否仍有未返回的 volatile 消息;SDK 在 volatile cursor 前进时据此继续分页 |
446
466
  | `volatile_earliest_cursor` | string\|null | 当前 boot epoch 内仍可读取的最早 volatile 游标 |
@@ -689,6 +709,8 @@ result = await client.call("message.ack", {"sender_aid": "alice.agentid.pub", "s
689
709
 
690
710
  收到新消息时推送。
691
711
 
712
+ 普通短连接和 `history_sync` 补拉辅助连接均不触发或接收 unread hint;消息提示由主长连接接收。短连接显式调用 Pull 不受影响。
713
+
692
714
  **实时推送优化**(0.5.6+):当客户端在 `auth.connect` 时声明 `inline_realtime_payload_v1: true` 能力后,Gateway 会在事件中直接内联完整的消息载荷(`payload`、`envelope` 等),无需额外调用 `message.pull`。SDK 自动声明此能力,应用层无需关注。对于离线消息和历史消息,仍需通过 `message.pull` 拉取。
693
715
 
694
716
  ### Payload
@@ -12,7 +12,7 @@
12
12
 
13
13
  ## meta.ping
14
14
 
15
- 心跳检测。SDK Core 自动调用以保持连接活性,也可手动调用验证连接是否正常。
15
+ 诊断连接并校验服务端时间。RPC `meta.ping` 不再承担 WebSocket 连接保活;连接保活由 WebSocket 控制帧完成,也可手动调用本方法验证连接是否正常。
16
16
 
17
17
  ### 参数
18
18
 
@@ -26,6 +26,7 @@
26
26
  |------|------|------|
27
27
  | `pong` | boolean | 固定为 `true` |
28
28
  | `timestamp` | integer | 服务端当前 Unix 时间戳(秒) |
29
+ | `heartbeat_interval` | integer | 兼容字段,当前为 `0`;不表示 RPC 保活间隔 |
29
30
 
30
31
  ### 示例
31
32
 
@@ -44,6 +44,7 @@
44
44
  | `from` / `sender_aid` | 服务端生成的消息信封 | 发送方身份 |
45
45
  | `message_id` / `seq` / `timestamp` / `created_at` | 服务端生成或发送参数 | 当前消息 ID、序号和服务端时间 |
46
46
  | `encrypted` / `delivery_mode` | 发送参数或连接上下文 | 加密和 P2P 投递语义 |
47
+ | `need_render` | 消息信封 | 是否需要在接收端展示;默认 `true`,不属于 `payload`,不进入 E2EE AAD 或保护头 |
47
48
  | `mention_mode` | 群消息信封和 SDK 注入的群消息 payload | 群消息应用层提及过滤模式标签:`disabled` / `mention-only`;由群设置决定,不作为 `group.send` 单次入参。SDK 从服务端消息元数据复制到对象 payload |
48
49
  | `type` / `message_type` | 发送参数或消息信封 | 信封/封装类型,如 `e2ee.p2p_encrypted` / `e2ee.group_encrypted` |
49
50
  | `dispatch` / `duty_state` / `message_dispatch` | `group.send` 响应和群消息事件 | 群消息运行时分发状态和值班分发结果 |
@@ -163,7 +164,7 @@
163
164
  "duration_ms": 8200,
164
165
  "transcript": "我稍后处理这个问题",
165
166
  "attachments": [{
166
- "url": "aun://storage/default/voice/msg-1.opus",
167
+ "url": "https://alice.agentid.pub/voice/msg-1.opus",
167
168
  "filename": "msg-1.opus",
168
169
  "content_type": "audio/ogg"
169
170
  }]
@@ -188,7 +189,7 @@
188
189
  "width": 1280,
189
190
  "height": 720,
190
191
  "attachments": [{
191
- "url": "aun://storage/default/images/flow.png",
192
+ "url": "https://alice.agentid.pub/images/flow.png",
192
193
  "filename": "flow.png",
193
194
  "content_type": "image/png"
194
195
  }]
@@ -211,11 +212,11 @@
211
212
  "text": "演示录屏",
212
213
  "duration_ms": 30500,
213
214
  "thumbnail": {
214
- "url": "aun://storage/default/videos/demo-cover.jpg",
215
+ "url": "https://alice.agentid.pub/videos/demo-cover.jpg",
215
216
  "content_type": "image/jpeg"
216
217
  },
217
218
  "attachments": [{
218
- "url": "aun://storage/default/videos/demo.mp4",
219
+ "url": "https://alice.agentid.pub/videos/demo.mp4",
219
220
  "filename": "demo.mp4",
220
221
  "content_type": "video/mp4"
221
222
  }]
@@ -235,7 +236,7 @@
235
236
  "type": "file",
236
237
  "text": "请查收附件",
237
238
  "attachments": [{
238
- "url": "aun://storage/default/docs/report.pdf",
239
+ "url": "https://alice.agentid.pub/docs/report.pdf",
239
240
  "filename": "report.pdf",
240
241
  "content_type": "application/pdf",
241
242
  "size_bytes": 245678,
@@ -283,7 +284,7 @@
283
284
  "title": "AUN 设计说明",
284
285
  "description": "消息、群组和 E2EE 的设计摘要",
285
286
  "thumbnail": {
286
- "url": "aun://storage/default/previews/aun-design.png",
287
+ "url": "https://alice.agentid.pub/previews/aun-design.png",
287
288
  "content_type": "image/png"
288
289
  }
289
290
  }
@@ -682,7 +683,7 @@ Agent 场景中,长时间运行的任务(代码生成、文件处理、多
682
683
  | `sha256` | string | 否 | 内容哈希,用于完整性校验 |
683
684
  | `thumbnail` | object | 否 | 缩略图引用,结构同附件引用 |
684
685
 
685
- AUN Storage 的 `url` 是长期对象引用,不是最终文件下载地址。接收端下载时先使用该 `url` 向 Storage 获取 `download_ticket`,再使用 ticket 中的短期 `download_url` 下载文件。`owner_aid`、`bucket`、`object_key` 可作为可选对象标识补充,便于没有 `url` 解析能力的客户端或服务端工具定位对象。
686
+ AUN Storage 的 `url` 是长期对象引用,不是最终文件下载地址。接收端使用 `owner_aid`、`bucket`、`object_key`(或从 AID 风格的 `url` 解析这些字段)调用 `storage.create_download_ticket`,再使用票据返回的短期 `url` / `download_url` 下载文件。`logical_url` 仅用于服务端返回的直达对象引用;票据、短期 URL 和授权 token 不应长期写入消息正文或附件索引。
686
687
 
687
688
  ```json
688
689
  {
@@ -692,7 +693,7 @@ AUN Storage 的 `url` 是长期对象引用,不是最终文件下载地址。
692
693
  "owner_aid": "alice.agentid.pub",
693
694
  "bucket": "default",
694
695
  "object_key": "docs/report.pdf",
695
- "url": "https://storage.agentid.pub/objects/default/docs/report.pdf",
696
+ "url": "https://alice.agentid.pub/docs/report.pdf",
696
697
  "filename": "report.pdf",
697
698
  "content_type": "application/pdf",
698
699
  "size_bytes": 245678,
@@ -38,12 +38,12 @@ Service Proxy 有两层注册,二者都必须存在:
38
38
 
39
39
  | 字段 | 类型 | 必填 | 说明 |
40
40
  |------|------|------|------|
41
- | `service_name` | string | 是 | 服务名,建议使用 `[a-z0-9_-]+` |
41
+ | `service_name` | string | 是 | 服务名,必须匹配 `[a-z0-9_-]+`,且不能使用 `api`、`health`、`metrics`、`status`、`proxy`、`admin`、`ws`、`wss`、`static` 等保留名 |
42
42
  | `service_type` | string | 否 | 服务类型,默认 `http`;常见值为 `http` / `websocket` / `sse` / `mcp` |
43
43
  | `visibility` | string | 否 | 可见性,默认 `private` |
44
44
  | `metadata` | object | 否 | 非敏感描述信息。服务端会移除 token、secret、endpoint、url、cookie、key、cert 等敏感字段 |
45
45
 
46
- Python `ServiceProxyClient.register_service()` 会保存本地 endpoint,但 `list_service_summaries()`、Gateway 注册和 proxy-server 注册只发送摘要。
46
+ 四端 `ServiceProxyClient` 会保存本地 endpoint,但服务摘要、Gateway 注册和 proxy-server 注册只发送摘要。
47
47
 
48
48
  ---
49
49
 
@@ -111,7 +111,7 @@ result = await client.call("proxy.register_services", {
111
111
  | `provider_aid` | string | 认证后的 provider AID |
112
112
  | `connection_id` | string | Gateway 连接 ID |
113
113
  | `removed` | array | 实际移除的服务名 |
114
- | `count` | integer | 剩余服务数量;全部注销时可省略 |
114
+ | `count` | integer | 剩余服务数量;全部注销时为 `0` |
115
115
 
116
116
  ### 示例
117
117
 
@@ -182,32 +182,36 @@ proxy-client 连接 proxy-server `/ws/client` 并收到 `service_proxy_auth_resp
182
182
  "request_id": "register-services",
183
183
  "error": {
184
184
  "code": "proxy_services_inconsistent",
185
- "message": "provider service list is inconsistent with existing connections"
185
+ "message": "provider connections must register identical services"
186
186
  }
187
187
  }
188
188
  ```
189
189
 
190
190
  ---
191
191
 
192
- ## Python ServiceProxyClient
192
+ ## 四端 ServiceProxyClient
193
193
 
194
- Python SDK 的 `ServiceProxyClient` 已封装双注册流程:
194
+ Python、Go、Node.js TypeScript 和 Browser SDK 均公开 `ServiceProxyClient`,封装服务注册、发现、双注册及 persistent / on-demand 重连流程。Python 使用 `aun_core.service_proxy.ServiceProxyClient`,TS/Browser 从 SDK 包入口导入,Go 使用 `NewServiceProxyClient()`。入口及选项见 [SDK API 手册](06-API手册.md)。
195
+
196
+ Browser 原生 WebSocket 不能设置隧道认证所需的 `Authorization` header;在 Browser SDK 中运行 provider 隧道时,需要注入支持该 header 的 `webSocketFactory`,仅提供原生 WebSocket 不足以建立隧道。
197
+
198
+ 流程如下(方法名以 Python 为例):
195
199
 
196
200
  1. `connect_once()` / `serve_once()` / `serve_forever()` 建立 proxy-server 隧道前,会在存在 `aun_client.call()` 时自动调用 `proxy.register_services`。
197
- 2. proxy-server 连接地址必须通过 `/.well-known/aun-proxy` 发现:先读 provider AID SQLite metadata 中 1 小时 TTL 的 `service_proxy_discovery` 缓存;缓存缺失或过期时查询 `https://{provider_aid}/.well-known/aun-proxy`,失败后回退 `https://proxy.{issuer}/.well-known/aun-proxy`。应用不得传入、配置或硬拼 proxy-server URL。
201
+ 2. proxy-server 连接地址通过 `/.well-known/aun-proxy` 发现:先读 provider AID metadata 中 1 小时 TTL 的 `service_proxy_discovery` 缓存(Python / Go / Node TS 使用 SQLite,Browser 使用 IndexedDB);缓存缺失或过期时查询 `https://{provider_aid}/.well-known/aun-proxy`,失败后回退 `https://proxy.{issuer}/.well-known/aun-proxy`。应用不得硬拼 proxy-server URL。
198
202
  3. proxy-server 隧道使用 AUN auth token 鉴权:优先复用 cached access token;缓存缺失或过期时,必须通过 `aun_client.authenticate()` 经 Gateway 两步登录刷新 token。
199
203
  4. proxy-server 隧道认证成功后,会自动发送 `register_services` 隧道消息。
200
204
  5. persistent 和 on-demand 重连时,每条新连接都会重新执行以上流程。
201
205
 
202
- 常用入口:
206
+ 常用入口(Python;TS/Browser 使用对应 camelCase,Go 使用 PascalCase 并传 `context.Context`):
203
207
 
204
208
  | 方法 | 说明 |
205
209
  |------|------|
206
- | `register_service(name, endpoint, service_type="http", visibility="private", metadata=None)` | 注册本地 embedded endpoint |
207
- | `unregister_service(name)` | 移除本地 endpoint |
210
+ | `register_service(service_name, endpoint, *, service_type="http", visibility="private", metadata=None)` | 注册本地 embedded endpoint |
211
+ | `unregister_service(service_name)` | 移除本地 endpoint |
208
212
  | `list_service_summaries()` | 返回可上报的服务摘要 |
209
213
  | `register_services_with_gateway()` | 显式向 Gateway 注册控制面服务列表 |
210
- | `unregister_services_from_gateway(names=None)` | 显式从 Gateway 注销控制面服务 |
214
+ | `unregister_services_from_gateway(service_names=None)` | 显式从 Gateway 注销控制面服务 |
211
215
  | `list_gateway_services()` | 查询 Gateway 当前连接服务列表 |
212
216
  | `register_services_with_proxy_server(ws)` | 通过已认证 proxy-server 隧道注册数据面服务列表 |
213
217
  | `discover_proxy_server(force_refresh=False)` | 通过缓存 / well-known 发现 proxy-server |
@@ -222,12 +226,14 @@ proxy-server 收到 `https://proxy.{issuer}/{user_name}/{svc_name}` 或对应 We
222
226
  1. 本 proxy-server 已有 `(provider_aid, service_name)` 数据面连接:直接转发,并按 visitor/provider/service 维持稳定粘性。
223
227
  2. provider 已连接本 proxy-server 且已注册服务列表,但没有目标服务:返回 `service_not_registered`,不 wakeup。
224
228
  3. provider 未连接本 proxy-server:查询 Gateway 控制面。
225
- 4. Gateway 检查 provider AID 证书不存在:返回 `provider_aid_not_found`;证书查询失败:返回 `provider_aid_check_failed`。
226
- 5. Gateway 显示 provider 没有在线长连接:返回 `provider_offline`。
227
- 6. Gateway 显示 provider 在线但未声明目标服务:返回 `service_not_registered`,不 wakeup。
229
+ 4. Gateway 检查 provider AID 证书不存在:内部拒绝原因是 `provider_aid_not_found`;证书查询失败为 `provider_aid_check_failed`。
230
+ 5. Gateway 显示 provider 没有在线长连接:内部拒绝原因为 `provider_offline`。
231
+ 6. Gateway 显示 provider 在线但未声明目标服务:内部拒绝原因为 `service_not_registered`,不 wakeup。
228
232
  7. Gateway 显示 provider 在线且声明目标服务:仅向注册了该服务的 provider 连接发送 wakeup。
229
233
  8. wakeup 已投递但本 proxy-server 等不到目标数据面隧道注册时,返回 `provider_wakeup_timeout`。
230
234
 
235
+ 上述 Gateway 内部拒绝原因不会逐项原样返回给 visitor:当前 proxy-server 将控制面查询/wakeup 失败统一为 `provider_wakeup_failed`,HTTP / WebSocket 入口返回 503;本地已有 provider 数据面连接但缺少目标服务时,直接返回 404 `service_not_registered`。
236
+
231
237
  因此,只向 Gateway 注册不足以承载请求;只有 proxy-server 数据面也注册了目标服务,访问才会真正转发。
232
238
 
233
239