@agentunion/fastaun-browser 0.5.3 → 0.5.6

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 (151) hide show
  1. package/CHANGELOG.md +130 -56
  2. package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/216/245/345/205/245/344/270/216/346/274/224/347/244/272/346/214/207/345/215/227.md +290 -0
  3. package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/346/236/266/346/236/204/344/270/216/350/257/246/347/273/206/345/256/236/347/216/260/350/256/241/345/210/222-codex.md +994 -0
  4. package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/350/277/220/347/273/264/344/270/216/345/217/221/345/270/203/346/214/207/345/215/227.md +144 -0
  5. package/_packed_docs/CHANGELOG.md +130 -56
  6. package/_packed_docs/INDEX.md +127 -69
  7. package/_packed_docs/KITE_DOCS_GUIDE.md +63 -29
  8. package/_packed_docs/audit/AUN/346/234/215/345/212/241Go/345/214/226/351/207/215/346/236/204/347/262/276/347/273/206/345/214/226/346/272/220/347/240/201/345/256/241/346/237/245-20260718.md +366 -0
  9. package/_packed_docs/aun/345/205/254/347/275/221/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +227 -0
  10. package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1004 -0
  11. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +999 -0
  12. package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +6 -4
  13. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -20
  14. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +219 -247
  15. package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +14 -14
  16. package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +3 -3
  17. package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +165 -421
  18. package/_packed_docs/protocol/README.md +1 -0
  19. package/_packed_docs/protocol/aun-docs-guide.md +7 -4
  20. package/_packed_docs/protocol/index.md +25 -19
  21. package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +62 -17
  22. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +22 -0
  23. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +67 -78
  24. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -2
  25. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +87 -41
  26. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +18 -5
  27. package/_packed_docs/sdk/09-group-rpc-manual.md +307 -267
  28. package/_packed_docs/sdk/09-message-rpc-manual.md +142 -103
  29. package/_packed_docs/sdk/09-payload-reference.md +1 -1
  30. package/_packed_docs/sdk/09-stream-rpc-manual.md +8 -8
  31. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +26 -17
  32. package/_packed_docs/sdk/INDEX.md +42 -34
  33. package/_packed_docs/sdk/README.md +7 -6
  34. package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/344/273/243/347/240/201/345/256/241/346/237/245/351/227/256/351/242/230/346/270/205/345/215/225.md +229 -0
  35. package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/346/224/271/351/200/240/346/226/271/346/241/210.md +750 -0
  36. package/dist/agent-md.d.ts +4 -5
  37. package/dist/agent-md.d.ts.map +1 -1
  38. package/dist/agent-md.js +66 -43
  39. package/dist/agent-md.js.map +1 -1
  40. package/dist/aid-store.d.ts +2 -6
  41. package/dist/aid-store.d.ts.map +1 -1
  42. package/dist/aid-store.js +20 -14
  43. package/dist/aid-store.js.map +1 -1
  44. package/dist/auth.d.ts.map +1 -1
  45. package/dist/auth.js +30 -11
  46. package/dist/auth.js.map +1 -1
  47. package/dist/bundle.js +3399 -1069
  48. package/dist/client/delivery.d.ts +75 -8
  49. package/dist/client/delivery.d.ts.map +1 -1
  50. package/dist/client/delivery.js +1419 -245
  51. package/dist/client/delivery.js.map +1 -1
  52. package/dist/client/group-state.d.ts.map +1 -1
  53. package/dist/client/group-state.js +27 -24
  54. package/dist/client/group-state.js.map +1 -1
  55. package/dist/client/lifecycle.d.ts.map +1 -1
  56. package/dist/client/lifecycle.js +48 -4
  57. package/dist/client/lifecycle.js.map +1 -1
  58. package/dist/client/mention-mode.d.ts +7 -0
  59. package/dist/client/mention-mode.d.ts.map +1 -0
  60. package/dist/client/mention-mode.js +184 -0
  61. package/dist/client/mention-mode.js.map +1 -0
  62. package/dist/client/peers.d.ts +1 -1
  63. package/dist/client/peers.d.ts.map +1 -1
  64. package/dist/client/peers.js +26 -3
  65. package/dist/client/peers.js.map +1 -1
  66. package/dist/client/rpc-pipeline.d.ts +22 -1
  67. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  68. package/dist/client/rpc-pipeline.js +309 -74
  69. package/dist/client/rpc-pipeline.js.map +1 -1
  70. package/dist/client/v2-e2ee.d.ts +25 -2
  71. package/dist/client/v2-e2ee.d.ts.map +1 -1
  72. package/dist/client/v2-e2ee.js +606 -97
  73. package/dist/client/v2-e2ee.js.map +1 -1
  74. package/dist/client.d.ts +24 -5
  75. package/dist/client.d.ts.map +1 -1
  76. package/dist/client.js +404 -215
  77. package/dist/client.js.map +1 -1
  78. package/dist/errors.d.ts.map +1 -1
  79. package/dist/errors.js +4 -1
  80. package/dist/errors.js.map +1 -1
  81. package/dist/facades.d.ts +6 -0
  82. package/dist/facades.d.ts.map +1 -1
  83. package/dist/facades.js +199 -104
  84. package/dist/facades.js.map +1 -1
  85. package/dist/group-index.d.ts +6 -1
  86. package/dist/group-index.d.ts.map +1 -1
  87. package/dist/group-index.js +44 -25
  88. package/dist/group-index.js.map +1 -1
  89. package/dist/index.d.ts +1 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +1 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/keystore/index.d.ts +10 -5
  94. package/dist/keystore/index.d.ts.map +1 -1
  95. package/dist/keystore/indexeddb-identity-store.d.ts +0 -12
  96. package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
  97. package/dist/keystore/indexeddb-identity-store.js +0 -60
  98. package/dist/keystore/indexeddb-identity-store.js.map +1 -1
  99. package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
  100. package/dist/keystore/indexeddb-shared.js +9 -5
  101. package/dist/keystore/indexeddb-shared.js.map +1 -1
  102. package/dist/keystore/indexeddb-token-store.d.ts +3 -1
  103. package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
  104. package/dist/keystore/indexeddb-token-store.js +47 -2
  105. package/dist/keystore/indexeddb-token-store.js.map +1 -1
  106. package/dist/register-flow.d.ts.map +1 -1
  107. package/dist/register-flow.js +28 -3
  108. package/dist/register-flow.js.map +1 -1
  109. package/dist/seq-tracker.d.ts +28 -8
  110. package/dist/seq-tracker.d.ts.map +1 -1
  111. package/dist/seq-tracker.js +218 -61
  112. package/dist/seq-tracker.js.map +1 -1
  113. package/dist/storage/vfs.d.ts +1 -0
  114. package/dist/storage/vfs.d.ts.map +1 -1
  115. package/dist/storage/vfs.js +26 -2
  116. package/dist/storage/vfs.js.map +1 -1
  117. package/dist/tools/cross-sdk-agent.js +376 -10
  118. package/dist/tools/cross-sdk-agent.js.map +1 -1
  119. package/dist/transport.d.ts +12 -0
  120. package/dist/transport.d.ts.map +1 -1
  121. package/dist/transport.js +218 -101
  122. package/dist/transport.js.map +1 -1
  123. package/dist/v2/session/session.d.ts.map +1 -1
  124. package/dist/v2/session/session.js +3 -4
  125. package/dist/v2/session/session.js.map +1 -1
  126. package/dist/v2/state/commitment.d.ts.map +1 -1
  127. package/dist/v2/state/commitment.js +1 -2
  128. package/dist/v2/state/commitment.js.map +1 -1
  129. package/dist/version.d.ts +1 -1
  130. package/dist/version.js +1 -1
  131. package/package.json +6 -5
  132. package/dist/group-resources.d.ts +0 -98
  133. package/dist/group-resources.d.ts.map +0 -1
  134. package/dist/group-resources.js +0 -635
  135. package/dist/group-resources.js.map +0 -1
  136. package/dist/keystore/indexeddb.d.ts +0 -179
  137. package/dist/keystore/indexeddb.d.ts.map +0 -1
  138. package/dist/keystore/indexeddb.js +0 -2031
  139. package/dist/keystore/indexeddb.js.map +0 -1
  140. package/dist/namespaces/auth.d.ts +0 -98
  141. package/dist/namespaces/auth.d.ts.map +0 -1
  142. package/dist/namespaces/auth.js +0 -992
  143. package/dist/namespaces/auth.js.map +0 -1
  144. package/dist/namespaces/custody.d.ts +0 -51
  145. package/dist/namespaces/custody.d.ts.map +0 -1
  146. package/dist/namespaces/custody.js +0 -302
  147. package/dist/namespaces/custody.js.map +0 -1
  148. package/dist/namespaces/meta.d.ts +0 -109
  149. package/dist/namespaces/meta.d.ts.map +0 -1
  150. package/dist/namespaces/meta.js +0 -549
  151. package/dist/namespaces/meta.js.map +0 -1
@@ -217,8 +217,8 @@ retry_backoff / reconnecting / connection_failed / closed
217
217
  Python:
218
218
 
219
219
  ```python
220
- auth = await client.authenticate()
221
- await client.connect({"slot_id": "main", "auto_reconnect": True})
220
+ auth = await client.authenticate()
221
+ await client.connect({"auto_reconnect": True})
222
222
  await client.disconnect()
223
223
  await client.close()
224
224
  ```
@@ -329,17 +329,22 @@ headers = client.get_protected_headers()
329
329
  | Collab | `client.collab` | `client.collab` | `client.Collab()` | 版本化文档、标签、`gc` / `reflog` / `revert` |
330
330
  | Group FS | `client.group.fs` | `client.group.fs` | `client.Group().FS()` | POSIX 风格群文件系统;`ls/find/stat/lstat/mkdir/rm/cp/mv/df/mount/umount`,以及 `set_acl/remove_acl/get_acl/list_acl` 角色 ACL 门面,上传下载数据面由 SDK 编排 |
331
331
 
332
- 群文件系统路径统一使用 `group_aid:/...`,成员数据区使用 `group_aid:/memberdata/{member_ref}/...`。SDK 不拼接真实 storage 路径,`memberdata` 到成员 `group_data/{group_aid}` 的映射只在服务端完成。群自有区写入允许当前 `group_aid` 证书签名、默认 `role:owner`、以及 owner 通过 `group.fs.set_acl` 显式授权后的 `role:admin`;撤销使用 `group.fs.remove_acl`,查询使用 `group.fs.get_acl/list_acl`,这些角色 ACL 操作都要求当前 group owner 调用且对外权限位显示为 `rwx`。JS 浏览器版上传中 `string` 默认表示文本内容,Node 本地路径需显式 `sourceType: "path"`、`localPath: true` 或 `local:` 前缀;Python/TS/Go 默认把 `string` 当本地路径。
332
+ 群文件系统路径统一使用 `group_aid:/...`,成员数据区使用 `group_aid:/memberdata/{member_ref}/...`。SDK 不拼接真实 storage 路径,`memberdata` 到成员 `group_data/{group_aid}` 的映射只在服务端完成。群自有区写入允许当前 `group_aid` 证书签名;成员角色中 `owner/admin` 默认可写群自有区,`member` 默认不可写。`owner/admin` 可通过 `group.fs.set_acl` 对特定业务目录授予 `role:member` `rw` 权限,用于后续群协作场景;`rw` 只允许创建/写入,不授予删除、移动、重命名权限。`rwd` 是 storage 内部权限位,SDK/RPC 对外按 POSIX 视图显示为 `rwx`,不给删除/移动/重命名权限时只使用 `rw`。`.group/` 是系统控制目录,默认给 `owner/admin` 写权限,用于群公告、群规则、入群要求附件,不能向 `role:member` 授权。老群如果缺少 `.group/` 默认 ACL,group 服务会在该群首次被 RPC 访问时 best-effort 触发 namespace/ACL lazy repair;ACL 同步全部成功后才记录本进程已检查,失败会在后续访问继续重试。JS 浏览器版上传中 `string` 默认表示文本内容,Node 本地路径需显式 `sourceType: "path"`、`localPath: true` 或 `local:` 前缀;Python/TS/Go 默认把 `string` 当本地路径。
333
333
 
334
334
  ### 消息与群组门面
335
335
 
336
336
  | 能力 | Python | TS/JS | Go | 说明 |
337
337
  |------|--------|-------|----|------|
338
- | Message | `client.message` | `client.message` | `client.Message()` | 消息便利方法:`send()`、`pull()`、`ack()`、`recall()`、`queryOnline()` |
338
+ | Message | `client.message` | `client.message` | `client.Message()` | 消息便利方法:`send()`、`pull()`、`history()`、`ack()`、`recall()`、`queryOnline()` |
339
339
  | Message Thought | `client.message.thought` | `client.message.thought` | `client.Message().Thought()` | P2P 思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
340
- | Group | `client.group` | `client.group` | `client.Group()` | 群组便利方法:`create()`、`send()`、`pull()`、`ack()`、群管理方法、群查询方法、群设置便利方法 |
341
- | Group Thought | `client.group.thought` | `client.group.thought` | `client.Group().Thought()` | 群思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
342
- | Stream | `client.stream` | `client.stream` | — | 流式数据:`createStream()`、`sendChunk()`、`endStream()`、`subscribeStream()` |
340
+ | Group | `client.group` | `client.group` | `client.Group()` | 群组便利方法:`create()`、`send()`、`pull()`、`history()`、`ack()`、群管理方法、群查询方法、群设置便利方法 |
341
+ | Group Thought | `client.group.thought` | `client.group.thought` | `client.Group().Thought()` | 群思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
342
+ | Offline Push | `client.push` | | — | Python SDK:登记/注销当前安装的 `push_notify_aid`,Push Server 处理批次后 ACK |
343
+ | Stream | `client.stream` | `client.stream` | — | 流式数据:`createStream()`、`sendChunk()`、`endStream()`、`subscribeStream()` |
344
+
345
+ `message.history` 和 `group.history` 使用 `before_seq` 排他上界向左翻页,下一页直接使用响应的 `next_before_seq`。History 只读,不推进实时 A/T/H、不 ACK、不触发实时消息事件。实时 Push 的最新页同步完全由 SDK 内部自动执行,再按 A/T/H 决定是否补一页 Forward;没有需要应用调用的 Tail 方法或参数。
346
+
347
+ 消息回调只提供页级语义:单个 Tail/Forward 响应页内按 seq 升序、同 seq 最多一次;跨 Push/Tail/Forward 页可能重复或乱序。A/T/H 不能用于判断某条消息是否已经回调。全局去重与排序不是 SDK 业务逻辑保证;应用仓库应以 `(namespace, message_id)` 做唯一键,并按 `seq` 排序。SDK 的进程内折叠仅是 best-effort 优化。
343
348
 
344
349
  **群查询方法**:`GroupFacade` 提供三个查询方法,适用不同场景:
345
350
 
@@ -347,15 +352,20 @@ headers = client.get_protected_headers()
347
352
  - `getInfo()` — 查询群组信息(扁平化格式,提升常用字段到顶层),**推荐外部使用**
348
353
  - `info()` — 查询群组详细信息(带权限控制,非成员只能看公开群,成员能看 seq/epoch 等运行时状态)
349
354
 
350
- **群设置便利方法**:`GroupFacade` 提供向后兼容的便利方法:
351
-
352
- - `getAnnouncement()` / `updateAnnouncement()` — 群公告
353
- - `getRules()` / `updateRules()` — 群规则
354
- - `getJoinRequirements()` / `updateJoinRequirements()` — 入群要求
355
-
356
- 读取方法优先返回 SDK 本地缓存;本地没有对应值时才读取相应 settings 做初始化。便利读取从服务端拿到 canonical `group_aid` 后,会同时以 canonical `group_aid` 和本次入参 `group_id` 写入 settings cache,避免 legacy/base `group_id` 下一次读取直接 cache miss。即使 `checkGroupIndex` 观察到远端 etag 与本地 etag 不一致,`getAnnouncement()` / `getRules()` / `getJoinRequirements()` 也不会自动拉取远端版本覆盖本地缓存。`updateAnnouncement()` / `updateRules()` / `updateJoinRequirements()` 属于 indexed 写入,内部会调用 `updateGroupIndex` 生成签名 `group.index` 并带 `expected_index_etag` CAS 提交。
357
-
358
- **Group Index 高级同步方法**:`group.index` 是 SDK 内部签名 manifest,用于记录群公告、群规则、入群要求及附件稳定引用的版本。SDK 观察 `_meta.group_indexes` 后只记录远端 etag;etag 不一致只表示本地与观察到的远端版本不同,可能是远端更新,也可能是本地有未提交修改。应用层需要显式选择 pull 远端或 push 本地。
355
+ **群设置便利方法**:`GroupFacade` 提供向后兼容的便利方法:
356
+
357
+ - `getAnnouncement()` / `updateAnnouncement()` — 群公告
358
+ - `getRules()` / `updateRules()` — 群规则
359
+ - `getJoinRequirements()` / `updateJoinRequirements()` — 入群要求
360
+ - `getSettingWithIndex()` / `updateSettingWithIndex()` — 通用文档型 indexed setting(Python 为 `get_setting_with_index()` / `update_setting_with_index()`,Go 为 `GetSettingWithIndex()` / `UpdateSettingWithIndex()`)
361
+
362
+ 读取方法优先返回 SDK 本地缓存;本地没有对应值时才读取相应 settings 做初始化。便利读取从服务端拿到 canonical `group_aid` 后,会同时以 canonical `group_aid` 和本次入参 `group_id` 写入 settings cache,避免 legacy/base `group_id` 下一次读取直接 cache miss。即使 `checkGroupIndex` 观察到远端 etag 与本地 etag 不一致,`getAnnouncement()` / `getRules()` / `getJoinRequirements()` / `getSettingWithIndex()` 也不会自动拉取远端版本覆盖本地缓存。`updateAnnouncement()` / `updateRules()` / `updateJoinRequirements()` / `updateSettingWithIndex()` 属于 indexed 写入,内部会调用 `updateGroupIndex` 生成签名 `group.index` 并带 `expected_index_etag` CAS 提交。
363
+
364
+ `getSettingWithIndex()` / `updateSettingWithIndex()` 比三对预定义方法多一个 `keyName`(Python 可传 `key_name`,Go 同时接受 `keyName` / `key_name`)。SDK 会生成 `{keyName}.content` 和 `{keyName}.attachments` 两个 settings key;`keyName` 只能是受控文档名(`^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀)。`getRules()` / `updateRules()` 与 `getAnnouncement()` / `updateAnnouncement()` 是该通用方法在 `rules`、`announcement` 上的薄封装;`getJoinRequirements()` / `updateJoinRequirements()` 保持结构化 schema,不改成 `join.content`。
365
+
366
+ 这些 `update*` 便利方法只更新群设置元数据:`updateRules()` / `updateAnnouncement()` / `updateSettingWithIndex()` 写入 `*.content` 与 `*.attachments`,`updateJoinRequirements()` 写入 `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments`。`attachments` 只保存稳定引用,附件实体应先上传到 group.fs 群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。
367
+
368
+ **Group Index 高级同步方法**:`group.index` 是 SDK 内部签名 manifest,用于记录群公告、群规则、入群要求及附件稳定引用的版本。SDK 观察 `_meta.group_indexes` 后只记录远端 etag;etag 不一致只表示本地与观察到的远端版本不同,可能是远端更新,也可能是本地有未提交修改。应用层需要显式选择 pull 远端或 push 本地。
359
369
 
360
370
  | 语义 | Python | TS/JS | Go | 说明 |
361
371
  |------|--------|-------|----|------|
@@ -525,13 +535,14 @@ fmt.Printf("拉取成功,etag: %s\n", result["meta"].(map[string]any)["etag"])
525
535
  | `last_modified` | int | ❌ | 时间戳毫秒(默认 `Date.now()` / `time.time()*1000`) |
526
536
  | `max_attempts` | int | ❌ | CAS 冲突最大重试次数(默认 2) |
527
537
 
528
- **支持的 indexed settings keys**:
529
-
530
- - `rules.content` / `rules.attachments` — 群规则及附件
531
- - `announcement.content` / `announcement.attachments` — 群公告及附件
532
- - `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` — 入群要求
533
-
534
- **返回值**:
538
+ **支持的 indexed settings keys**:
539
+
540
+ - `rules.content` / `rules.attachments` — 群规则及附件
541
+ - `announcement.content` / `announcement.attachments` — 群公告及附件
542
+ - `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments` 入群要求及附件
543
+ - `{keyName}.content` / `{keyName}.attachments` — 通用文档型 indexed setting;`keyName` 需满足 `^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀
544
+
545
+ **返回值**:
535
546
 
536
547
  ```python
537
548
  {
@@ -600,13 +611,16 @@ console.log(`推送成功,新 etag: ${result._meta.group_indexes['g-team.agent
600
611
 
601
612
  ```go
602
613
  // Go - 更新入群要求
603
- result, err := client.Group().UpdateGroupIndex(ctx, map[string]any{
604
- "group_id": "g-team.agentid.pub",
605
- "settings": map[string]any{
606
- "join.mode": "approval",
607
- "join.question": "你是如何知道本群的?",
608
- },
609
- })
614
+ result, err := client.Group().UpdateGroupIndex(ctx, map[string]any{
615
+ "group_id": "g-team.agentid.pub",
616
+ "settings": map[string]any{
617
+ "join.mode": "approval",
618
+ "join.question": "你是如何知道本群的?",
619
+ "join.attachments": []any{
620
+ map[string]any{"type": "group.fs", "path": "/.group/attachments/join/guide.pdf"},
621
+ },
622
+ },
623
+ })
610
624
  if err != nil {
611
625
  log.Fatal(err)
612
626
  }
@@ -618,11 +632,41 @@ fmt.Printf("推送成功\n")
618
632
  1. **权限要求**:写入 indexed settings 需要 admin 及以上权限
619
633
  2. **签名算法限制**:当前版本仅支持 ECDSA-P256-SHA256,使用其他算法的 AID 无法签名
620
634
  3. **CAS 冲突策略**:默认重试 2 次,高并发场景建议增加 `max_attempts`
621
- 4. **`signer` 必须是当前连接身份**:服务端强制校验 `signed_by == actor_aid`,传入其他 AID 会被拒绝
622
-
623
- ---
624
-
625
- ## ServiceProxyClient
635
+ 4. **`signer` 必须是当前连接身份**:服务端强制校验 `signed_by == actor_aid`,传入其他 AID 会被拒绝
636
+ 5. **附件字段只存引用**:`updateRules` / `updateAnnouncement` / `updateSettingWithIndex` 传入 `content` 和 `attachments` 元数据引用;`updateJoinRequirements` 传入结构化入群字段和 `attachments` 元数据引用。附件实体先上传到群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。群自有区默认允许 `owner/admin` 写入,`member` 默认不可写;`.group/` 不允许授予 `role:member` 写权限。
637
+
638
+ ---
639
+
640
+ ### 离线推送门面(Python)
641
+
642
+ 应用启动时推荐把推送代理和 opaque token 交给 `connect()`:
643
+
644
+ ```python
645
+ await client.connect({
646
+ "push_notify_aid": "push.example.com",
647
+ "push_token": token,
648
+ })
649
+ ```
650
+
651
+ SDK 先建立 AUN 会话,再调用 `push.register` 登记当前安装。`push_notify_aid` 是 SDK 公共名称,线上 RPC 字段仍是冻结契约中的 `push_server_aid`;它不会被透传给 `auth.connect`。
652
+
653
+ 运行期间更换 token 或停止推送时使用 facade:
654
+
655
+ ```python
656
+ await client.push.register(push_notify_aid="push.example.com", push_token=new_token)
657
+ await client.push.unregister()
658
+ ```
659
+
660
+ - `register()` 可附带 `provider`、`app_id`;身份范围始终由 Gateway 注入的当前 `aid/device_id/slot_id` 决定,调用方不能伪造。
661
+ - `unregister()` 幂等禁用当前安装,不删除历史 delivery。
662
+ - `ack(batch_id, status)` 只供 Push Server 实现使用;V1 status 仅允许 `accepted`、`retryable_failure`、`permanent_failure`。
663
+ - 本轮只修改 Python SDK;Go、TypeScript、JavaScript 尚无专用 Push facade。
664
+
665
+ 协议与可靠性边界见 `docs/protocol/15-离线推送通知协议.md`。
666
+
667
+ ---
668
+
669
+ ## ServiceProxyClient
626
670
 
627
671
  Service Proxy 用于 provider 通过 AUN 身份暴露本地 HTTP / WebSocket 服务。当前公开封装在 Python SDK 的 `ServiceProxyClient` 中;其它语言可以按 [09-proxy-rpc-manual.md](09-proxy-rpc-manual.md) 直接实现同等控制面和隧道消息。
628
672
 
@@ -691,8 +735,9 @@ sub.unsubscribe()
691
735
  | `message.ack` | 消息 ack |
692
736
  | `message.undecryptable` | P2P E2EE 解密失败 |
693
737
  | `group.changed` | 群组事件 |
694
- | `group.message_undecryptable` | 群 E2EE 解密失败 |
695
- | `storage.object_changed` | Storage 对象变更事件透传 |
738
+ | `group.message_undecryptable` | 群 E2EE 解密失败 |
739
+ | `push.offline_message` | Push Server 收到离线唤醒批次;普通终端无需订阅 |
740
+ | `storage.object_changed` | Storage 对象变更事件透传 |
696
741
 
697
742
  ---
698
743
 
@@ -718,13 +763,14 @@ sub.unsubscribe()
718
763
 
719
764
  | 领域 | 手册 | 关键方法 |
720
765
  |------|------|----------|
721
- | 消息 | [09-message-rpc-manual.md](09-message-rpc-manual.md) | `message.send` / `message.pull` / `message.ack` / `message.thought.*` |
722
- | 群组 | [09-group-rpc-manual.md](09-group-rpc-manual.md) | `group.create` / `group.send` / `group.v2.*` / `group.fs.*` |
766
+ | 消息 | [09-message-rpc-manual.md](09-message-rpc-manual.md) | `message.send` / `message.pull` / `message.history` / `message.ack` / `message.thought.*` |
767
+ | 群组 | [09-group-rpc-manual.md](09-group-rpc-manual.md) | `group.create` / `group.send` / `group.pull` / `group.history` / `group.v2.*` / `group.fs.*` |
723
768
  | 存储 | [09-storage-rpc-manual.md](09-storage-rpc-manual.md) | `storage.put_object` / `storage.fs.*` / `storage.volume.*` / ACL / token / share link |
724
769
  | 协作 | [09-collab-rpc-manual.md](09-collab-rpc-manual.md) | `collab.ls-files` / `collab.show` / `collab.commit` / `collab.merge` / `collab.log` / `collab.diff` / `collab.clone` / `collab.prune` / `collab.gc` / `collab.reflog` / `collab.revert` / `collab.tag.*` / `collab.ls-remote` / `collab.unregister` |
725
770
  | 元信息 | [09-meta-rpc-manual.md](09-meta-rpc-manual.md) | `meta.ping` / `meta.status` / `meta.trust_roots` |
726
- | Stream | [09-stream-rpc-manual.md](09-stream-rpc-manual.md) | `stream.create` / `stream.close` / `stream.list_active` |
727
- | Service Proxy | [09-proxy-rpc-manual.md](09-proxy-rpc-manual.md) | `proxy.register_services` / `proxy.unregister_services` / `proxy.list_services` |
771
+ | Stream | [09-stream-rpc-manual.md](09-stream-rpc-manual.md) | `stream.create` / `stream.close` / `stream.list_active` |
772
+ | Offline Push | `docs/protocol/15-离线推送通知协议.md` | `push.register` / `push.unregister` / `push.ack` / `push.offline_message` |
773
+ | Service Proxy | [09-proxy-rpc-manual.md](09-proxy-rpc-manual.md) | `proxy.register_services` / `proxy.unregister_services` / `proxy.list_services` |
728
774
 
729
775
  ---
730
776
 
@@ -94,14 +94,27 @@ SDK 内部自动管理 RPC 并发,应用层无需配置:
94
94
  |------|------|
95
95
  | RPC 并发上限 | 全局最多 16 个并发 RPC 请求 |
96
96
  | 后台 RPC 限制 | 后台任务额外限制为 8 个 |
97
- | Pull Gate | 同一 namespace/group pull 操作自动序列化 |
98
- | 队列超时 | 排队超过 timeout `TimeoutError` |
97
+ | Pull Gate | P2P Message、Group Message、Group Event 各一个 Gate;每个 Gate single-inflight |
98
+ | 队列优先级 | Tail/History 前台 FIFO 优先于 Forward/Gap Fill 后台 FIFO;Group Event Pull 为后台;同 key 自动折叠 |
99
+ | 队列超时 | 排队或等待折叠结果超过 3 秒时旁路 Gate 执行,不取消原请求 |
99
100
 
100
101
  应用层保持普通 `await client.call(...)` 即可。
101
102
 
102
103
  ---
103
104
 
104
- ## 7. Group Index 更新流程
105
+ ## 7. 消息同步与历史读取
106
+
107
+ - V2 Push 只作为服务端 Head 通知。只要本地 H 落后,就先 Tail;Tail 后仍有未扫描 Gap 才执行一页后台 Forward。
108
+ - 不要把回调成功当作 ACK 条件。SDK 按服务端原始页最大 seq 推进 Forward 水位;坏密文通过 `message.undecryptable` / `group.message_undecryptable` 单独处理。
109
+ - 冷启动缺 sender IK 时允许 SDK 最多同步等待 3 秒 bootstrap;同发送端并发请求自动合并。成功后当前消息立即重试解密,失败或超时才 pending,不要在应用层并发重复拉取 IK。
110
+ - SDK 只保证单个 Tail/Forward 响应页内按 seq 升序、同 seq 最多发布一次;A/T/H 只是扫描水位,不是发布账本。
111
+ - 实时消息可能从 Push、Tail、Forward 重复到达,跨页、跨通道都不保证全局回调顺序。全局去重与排序由应用业务仓库负责,不属于 SDK 业务逻辑保证;业务仓库必须按 `(namespace, message_id)` 幂等,并按 seq 排序展示。SDK 进程内折叠只能作为 best-effort 优化。
112
+ - 用 `message.history(before_seq=..., limit=...)` 或 `group.history(group_id=..., before_seq=..., limit=...)` 向左翻页;下一页直接复用响应的 `next_before_seq`。History 不影响实时游标和 ACK。
113
+ - Forward Piggy ACK 保留:有待提交 ACK 时,非满页仍会再拉一页并携带 ACK,拉到空页后停止。
114
+
115
+ ---
116
+
117
+ ## 8. Group Index 更新流程
105
118
 
106
119
  公告、规则、入群要求属于 indexed settings。owner/admin 修改这些内容时,不要直接裸调 `group.set_settings` 写单个 key,应使用 SDK facade 的 `updateGroupIndex` 语义。
107
120
 
@@ -113,11 +126,11 @@ SDK 内部自动管理 RPC 并发,应用层无需配置:
113
126
  4. 调用 `updateGroupIndex`。SDK 会读取当前服务端 index、生成新签名 index,并带 `expected_index_etag` 调用 `group.set_settings`。
114
127
  5. 如果服务端返回 `group.index etag conflict`,说明提交基线已变化;应用层需要重新决定 pull、merge 或保留本地修改后再提交。
115
128
 
116
- `getAnnouncement`、`getRules`、`getJoinRequirements` 只读 SDK 本地缓存;本地没有对应值时才读取相应 settings 初始化缓存,不会因为 etag 不一致自动 pull 远端。`updateAnnouncement`、`updateRules`、`updateJoinRequirements` 已内置 indexed 写入路径。普通不进入 index 的设置,例如 `dispatch_mode`,仍可直接使用 `setSettings` / `set_settings` / `SetSettings`。
129
+ `getAnnouncement`、`getRules`、`getJoinRequirements` 只读 SDK 本地缓存;本地没有对应值时才读取相应 settings 初始化缓存,不会因为 etag 不一致自动 pull 远端。`updateAnnouncement`、`updateRules`、`updateJoinRequirements` 已内置 indexed 写入路径。普通不进入 index 的设置,例如 `mention_mode`,仍可直接使用 `setSettings` / `set_settings` / `SetSettings`。
117
130
 
118
131
  ---
119
132
 
120
- ## 8. 测试数据保护
133
+ ## 9. 测试数据保护
121
134
 
122
135
  - 不要删除 `AIDs/` 下的私钥、证书、seed、数据库或 token 文件。
123
136
  - 不要并行跑共享同一身份材料的集成 / E2E / 跨域测试。