@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
@@ -58,7 +58,7 @@
58
58
 
59
59
  | 方法 | 说明 |
60
60
  |------|------|
61
- | [group.set_settings](#groupset_settings) | 统一设置群参数,含 `dispatch_mode` |
61
+ | [group.set_settings](#groupset_settings) | 统一设置群参数,含 `mention_mode` |
62
62
  | [group.get_settings](#groupget_settings) | 统一读取群参数 |
63
63
 
64
64
  ### 消息
@@ -70,6 +70,7 @@
70
70
  | [group.thought.put](#groupthoughtput) | 写入某个群上下文的思考内容 |
71
71
  | [group.thought.get](#groupthoughtget) | 获取某个群上下文的思考内容 |
72
72
  | [group.pull](#grouppull) | 增量拉取消息 |
73
+ | [group.history](#grouphistory) | 向前只读翻页群消息 |
73
74
  | [group.pull_events](#grouppull_events) | 增量拉取事件 |
74
75
  | [group.ack](#groupack) | 确认已读(旧接口,等同 ack_messages) |
75
76
  | [group.ack_messages](#groupack_messages) | 确认消息游标 |
@@ -100,10 +101,10 @@
100
101
 
101
102
  | 方法 | 说明 |
102
103
  |------|------|
103
- | [group.set_settings](#groupset_settings) | 统一设置群参数(含公告、规则、入群要求、dispatch_mode 等) |
104
+ | [group.set_settings](#groupset_settings) | 统一设置群参数(含公告、规则、入群要求、mention_mode 等) |
104
105
  | [group.get_settings](#groupget_settings) | 统一读取群参数 |
105
106
 
106
- **便利方法**:SDK 提供向后兼容的便利方法(`getAnnouncement`/`updateAnnouncement`/`getRules`/`updateRules`/`getJoinRequirements`/`updateJoinRequirements`)。读取方法优先返回 SDK 本地缓存,本地没有对应值时才调用 `get_settings` 初始化;即使观察到远端 etag 不一致也不会自动 pull 远端。indexed 写入方法内部调用 `updateGroupIndex` 生成签名 `group.index` 并通过 `set_settings` CAS 提交。
107
+ **便利方法**:SDK 提供向后兼容的便利方法(`getAnnouncement`/`updateAnnouncement`/`getRules`/`updateRules`/`getJoinRequirements`/`updateJoinRequirements`),并提供通用文档型方法(`getSettingWithIndex`/`updateSettingWithIndex`,Python 为 `get_setting_with_index`/`update_setting_with_index`,Go 为 `GetSettingWithIndex`/`UpdateSettingWithIndex`)。读取方法优先返回 SDK 本地缓存,本地没有对应值时才调用 `get_settings` 初始化;即使观察到远端 etag 不一致也不会自动 pull 远端。indexed 写入方法内部调用 `updateGroupIndex` 生成签名 `group.index` 并通过 `set_settings` CAS 提交。
107
108
 
108
109
  ### 群文件系统
109
110
 
@@ -137,17 +138,17 @@
137
138
 
138
139
  ---
139
140
 
140
- ## Group AID / Group ID 兼容规范
141
-
142
- 目标态群组主标识是 `group_aid`,canonical 形式为 `{base}.{issuer-domain}`,例如 `10042.agentid.pub`、`team01.agentid.pub`、`g-abc123.agentid.pub`。新建群以 `group_aid` 为准;新群的兼容 `group_id` 列值也使用同一个 `group_aid` 字符串。历史 `group_id` 字段名和 RPC 参数名继续保留,但语义上只是兼容字段。
143
-
144
- SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_aid` / `groupAid` 统一规范化为 `group_aid`。裸客户端也应使用同一 `group_aid` 生成签名材料和 E2EE AAD,避免同一群的历史别名产生不同材料。服务端响应可能同时返回 `group_id` 和 `group_aid`;新代码应优先读取 `group_aid`,仅兼容旧版本或历史数据时回退读取 `group_id`。
145
-
146
- 兼容输入包括目标态 `{base}.{issuer-domain}`、本域简写 `{base}` / `g-{slug}`,以及旧格式 `group.{issuer-domain}/{base}`、`{base}@issuer-domain`、`g-{slug}@issuer-domain`、`g-{slug}.{issuer-domain}`。带域的旧输入会转换为 `{base}.{issuer-domain}`;本域简写会在服务端或 SDK 有本域 issuer 配置时补成本域 `group_aid`。`base` 支持 5 位及以上小写字母或数字,或 4 到 64 位 `[a-z0-9_-]` 风格名称;旧 `g-` 前缀形式继续兼容,`g-` 后为 4 到 32 位小写字母或数字。命名群使用 `group_name` 作为 base,规则见 `group.create` 参数说明。
147
-
148
- `group.create` 的新建语义以 `group_aid` 为准:命名群由 `group_name + issuer` 生成 `group_aid`,自动群由服务端群号生成 `{number}.{issuer}`。`group_id` 参数只作为旧客户端兼容别名;传入时不能是纯数字(纯数字群号保留给服务端自动分配),且规范化后的 `group_aid` 未被占用。如果已被占用或与历史别名碰撞会返回错误。
149
-
150
- 在 `https://group.issuer-domain/...` 这类群链接中,path 使用单段 `group_aid`,例如 `https://group.agentid.pub/10042.agentid.pub/invite/ic-xxx`、`https://group.agentid.pub/g-abc123.agentid.pub/invite/ic-xxx`。历史 base 简写链接可继续由服务端兼容解析。
141
+ ## Group AID / Group ID 兼容规范
142
+
143
+ 目标态群组主标识是 `group_aid`,canonical 形式为 `{base}.{issuer-domain}`,例如 `10042.agentid.pub`、`team01.agentid.pub`、`g-abc123.agentid.pub`。新建群以 `group_aid` 为准;新群的兼容 `group_id` 列值也使用同一个 `group_aid` 字符串。历史 `group_id` 字段名和 RPC 参数名继续保留,但语义上只是兼容字段。
144
+
145
+ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_aid` / `groupAid` 统一规范化为 `group_aid`。裸客户端也应使用同一 `group_aid` 生成签名材料和 E2EE AAD,避免同一群的历史别名产生不同材料。服务端响应可能同时返回 `group_id` 和 `group_aid`;新代码应优先读取 `group_aid`,仅兼容旧版本或历史数据时回退读取 `group_id`。
146
+
147
+ 兼容输入包括目标态 `{base}.{issuer-domain}`、本域简写 `{base}` / `g-{slug}`,以及旧格式 `group.{issuer-domain}/{base}`、`{base}@issuer-domain`、`g-{slug}@issuer-domain`、`g-{slug}.{issuer-domain}`。带域的旧输入会转换为 `{base}.{issuer-domain}`;本域简写会在服务端或 SDK 有本域 issuer 配置时补成本域 `group_aid`。`base` 支持 5 位及以上小写字母或数字,或 4 到 64 位 `[a-z0-9_-]` 风格名称;旧 `g-` 前缀形式继续兼容,`g-` 后为 4 到 32 位小写字母或数字。命名群使用 `group_name` 作为 base,规则见 `group.create` 参数说明。
148
+
149
+ `group.create` 的新建语义以 `group_aid` 为准:命名群由 `group_name + issuer` 生成 `group_aid`,自动群由服务端群号生成 `{number}.{issuer}`。`group_id` 参数只作为旧客户端兼容别名;传入时不能是纯数字(纯数字群号保留给服务端自动分配),且规范化后的 `group_aid` 未被占用。如果已被占用或与历史别名碰撞会返回错误。
150
+
151
+ 在 `https://group.issuer-domain/...` 这类群链接中,path 使用单段 `group_aid`,例如 `https://group.agentid.pub/10042.agentid.pub/invite/ic-xxx`、`https://group.agentid.pub/g-abc123.agentid.pub/invite/ic-xxx`。历史 base 简写链接可继续由服务端兼容解析。
151
152
 
152
153
  ---
153
154
 
@@ -155,16 +156,16 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
155
156
 
156
157
  ### group.create
157
158
 
158
- 创建群组。调用者自动成为 owner。支持创建命名群(传入 `group_name` + `public_key`)。新建群主标识以 `group_aid` 为准;`group_id` 仅作为兼容字段保留。
159
+ 创建群组。调用者自动成为 owner。支持创建命名群(传入 `group_name` + `public_key`)。新建群主标识以 `group_aid` 为准;`group_id` 仅作为兼容字段保留。
159
160
 
160
161
  **参数**:
161
162
 
162
163
  | 参数 | 类型 | 必填 | 说明 |
163
164
  |------|------|------|------|
164
165
  | `name` | string | 是 | 群组显示名称 |
165
- | `group_aid` | string | 否 | 目标态群 AID;新代码优先使用。传入时会规范化为 `{base}.{issuer-domain}`,不能是纯数字 |
166
- | `group_id` | string | 否 | 兼容旧客户端的别名;值语义同 `group_aid`,不再推荐新代码使用 |
167
- | `group_name` | string | 否 | 命名群标识,4-64 字符,`[a-z0-9_-]+`,不以 `guest`/`g-` 开头。与 `public_key` 同时提供时创建命名群,并生成 `{group_name}.{issuer-domain}` |
166
+ | `group_aid` | string | 否 | 目标态群 AID;新代码优先使用。传入时会规范化为 `{base}.{issuer-domain}`,不能是纯数字 |
167
+ | `group_id` | string | 否 | 兼容旧客户端的别名;值语义同 `group_aid`,不再推荐新代码使用 |
168
+ | `group_name` | string | 否 | 命名群标识,4-64 字符,`[a-z0-9_-]+`,不以 `guest`/`g-` 开头。与 `public_key` 同时提供时创建命名群,并生成 `{group_name}.{issuer-domain}` |
168
169
  | `public_key` | string | 否 | 命名群公钥(base64 编码),与 `group_name` 同时提供 |
169
170
  | `curve` | string | 否 | 密钥曲线,默认 `"P-256"` |
170
171
  | `visibility` | string | 否 | `"public"` / `"private"`,默认由配置决定 |
@@ -181,8 +182,8 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
181
182
  ```json
182
183
  {
183
184
  "group": {
184
- "group_id": "my-team.agentid.pub",
185
- "group_aid": "my-team.agentid.pub",
185
+ "group_id": "my-team.agentid.pub",
186
+ "group_aid": "my-team.agentid.pub",
186
187
  "name": "测试群",
187
188
  "owner_aid": "alice.agentid.pub",
188
189
  "creator_aid": "alice.agentid.pub",
@@ -193,9 +194,9 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
193
194
  "member_count": 1,
194
195
  "message_seq": 0,
195
196
  "event_seq": 0,
196
- "group_url": "https://group.agentid.pub/my-team.agentid.pub",
197
- "created_at": 1234567890000,
198
- "updated_at": 1234567890000
197
+ "group_url": "https://group.agentid.pub/my-team.agentid.pub",
198
+ "created_at": 1234567890000,
199
+ "updated_at": 1234567890000
199
200
  },
200
201
  "aid_cert": {
201
202
  "cert": "-----BEGIN CERTIFICATE-----...",
@@ -207,9 +208,9 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
207
208
  }
208
209
  ```
209
210
 
210
- > `aid_cert` 仅在命名群创建时返回。`group_aid` 是新代码应使用的主标识;`group_id` 为兼容字段,新群通常与 `group_aid` 相同,历史群可能保留旧存储值。
211
-
212
- **标识格式**:目标态为 `{base}.{issuer-domain}`。旧格式 `group.{issuer-domain}/{base}`、`{base}@{issuer-domain}` 会在 API 边界转换为目标态 `group_aid`。
211
+ > `aid_cert` 仅在命名群创建时返回。`group_aid` 是新代码应使用的主标识;`group_id` 为兼容字段,新群通常与 `group_aid` 相同,历史群可能保留旧存储值。
212
+
213
+ **标识格式**:目标态为 `{base}.{issuer-domain}`。旧格式 `group.{issuer-domain}/{base}`、`{base}@{issuer-domain}` 会在 API 边界转换为目标态 `group_aid`。
213
214
 
214
215
  ### group.bind_aid
215
216
 
@@ -219,7 +220,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
219
220
 
220
221
  | 参数 | 类型 | 必填 | 说明 |
221
222
  |------|------|------|------|
222
- | `group_id` | string | 是 | 群组标识;兼容参数名,值使用目标态 `group_aid` |
223
+ | `group_id` | string | 是 | 群组标识;兼容参数名,值使用目标态 `group_aid` |
223
224
  | `group_name` | string | 是 | 命名群标识,4-64 字符,`[a-z0-9_-]+` |
224
225
  | `public_key` | string | 是 | 群公钥(base64 编码) |
225
226
  | `curve` | string | 否 | 密钥曲线,默认 `"P-256"` |
@@ -241,7 +242,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
241
242
 
242
243
  | 参数 | 类型 | 必填 | 说明 |
243
244
  |------|------|------|------|
244
- | `group_id` | string | 是 | 群组标识;兼容参数名,值使用目标态 `group_aid` |
245
+ | `group_id` | string | 是 | 群组标识;兼容参数名,值使用目标态 `group_aid` |
245
246
  | `required` | string[] | 否 | 受限字段声明:`member`、`state`、`e2ee`、`avatar` |
246
247
 
247
248
  **默认响应**:
@@ -256,7 +257,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
256
257
  "status": "active",
257
258
  "description": "技术讨论群",
258
259
  "member_count": 42,
259
- "created_at": 1234567890000
260
+ "created_at": 1234567890000
260
261
  }
261
262
  ```
262
263
 
@@ -272,7 +273,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
272
273
 
273
274
  | 参数 | 类型 | 必填 | 说明 |
274
275
  |------|------|------|------|
275
- | `group_id` | string | 是 | 群组标识;兼容参数名,值使用目标态 `group_aid` |
276
+ | `group_id` | string | 是 | 群组标识;兼容参数名,值使用目标态 `group_aid` |
276
277
  | `name` | string | 否 | 新名称 |
277
278
  | `visibility` | string | 否 | 新可见性 |
278
279
  | `description` | string | 否 | 新描述 |
@@ -301,7 +302,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
301
302
  "name": "项目讨论",
302
303
  "visibility": "private",
303
304
  "member_count": 5,
304
- "updated_at": 1234567890000,
305
+ "updated_at": 1234567890000,
305
306
  "role": "owner"
306
307
  }
307
308
  ],
@@ -343,7 +344,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
343
344
 
344
345
  暂停群组。暂停期间不能发送消息。需要 **admin 及以上**权限。
345
346
 
346
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
347
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
347
348
 
348
349
  **响应**:
349
350
 
@@ -360,7 +361,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
360
361
 
361
362
  恢复暂停的群组。需要 **admin 及以上**权限。
362
363
 
363
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
364
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
364
365
 
365
366
  **响应**:
366
367
 
@@ -377,7 +378,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
377
378
 
378
379
  永久解散群组。不可恢复。需要 **owner** 权限。
379
380
 
380
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
381
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
381
382
 
382
383
  **响应**:
383
384
 
@@ -401,7 +402,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
401
402
 
402
403
  | 参数 | 类型 | 必填 | 说明 |
403
404
  |------|------|------|------|
404
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
405
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
405
406
  | `aid` | string | 是 | 要添加的 AID |
406
407
  | `role` | string | 否 | `"admin"` / `"member"`,默认 `"member"` |
407
408
  | `member_type` | string | 否 | `"human"` / `"ai"`,默认 `"human"` |
@@ -415,7 +416,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
415
416
  "aid": "bob.agentid.pub",
416
417
  "role": "member",
417
418
  "member_type": "human",
418
- "joined_at": 1234567890000
419
+ "joined_at": 1234567890000
419
420
  }
420
421
  }
421
422
  ```
@@ -428,7 +429,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
428
429
 
429
430
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
430
431
  |------|------|------|--------|------|
431
- | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
432
+ | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
432
433
  | `page` | integer | 否 | 1 | 页码 |
433
434
  | `size` | integer | 否 | 50 | 每页条数(最大 200) |
434
435
  | `role` | string | 否 | — | 按角色过滤(owner/admin/member) |
@@ -444,9 +445,9 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
444
445
  "aid": "alice.agentid.pub",
445
446
  "role": "owner",
446
447
  "member_type": "human",
447
- "joined_at": 1234567890000,
448
+ "joined_at": 1234567890000,
448
449
  "last_ack_seq": 100,
449
- "last_pull_at": 1234567890000
450
+ "last_pull_at": 1234567890000
450
451
  }
451
452
  ],
452
453
  "total": 1,
@@ -464,7 +465,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
464
465
 
465
466
  | 参数 | 类型 | 必填 | 说明 |
466
467
  |------|------|------|------|
467
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
468
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
468
469
  | `aid` | string | 是 | 要踢出的 AID |
469
470
 
470
471
  **响应**:
@@ -480,7 +481,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
480
481
 
481
482
  主动退出群组。owner 不能直接退群,需先转让群主。
482
483
 
483
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
484
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
484
485
 
485
486
  **响应**:
486
487
 
@@ -493,13 +494,13 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
493
494
 
494
495
  ### group.set_role
495
496
 
496
- 设置成员角色。需要 **owner** 权限。不能改变 owner 角色。该 RPC 只改变 membership 中的角色事实,不授予或撤销群自有区写 ACL;`role:admin` 是否可写群自有区由 `group.fs.set_acl` / `group.fs.remove_acl` 显式控制。
497
+ 设置成员角色。`owner` 可将普通成员设为 `admin`,也可将 `admin` 设回 `member`;`admin` 不能修改其它成员角色,只能将自己的角色降为 `member`。不能通过 `group.set_role` 改变 `owner` 角色;群主只在建群或 `group.transfer_owner` 中变更。该 RPC 改变 membership 中的角色事实;`owner/admin` 默认拥有群自有区写权限,`member` 默认没有写权限。成员级群协作目录应通过 `group.fs.set_acl` 显式授予 `role:member` 的 `rw` 权限。
497
498
 
498
499
  **参数**:
499
500
 
500
501
  | 参数 | 类型 | 必填 | 说明 |
501
502
  |------|------|------|------|
502
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
503
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
503
504
  | `aid` | string | 是 | 目标 AID |
504
505
  | `role` | string | 是 | `"admin"` / `"member"` |
505
506
 
@@ -513,7 +514,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
513
514
  "aid": "bob.agentid.pub",
514
515
  "role": "admin",
515
516
  "member_type": "human",
516
- "joined_at": 1234567890000,
517
+ "joined_at": 1234567890000,
517
518
  "last_ack_seq": 0,
518
519
  "last_pull_at": 0
519
520
  },
@@ -532,7 +533,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
532
533
 
533
534
  | 参数 | 类型 | 必填 | 说明 |
534
535
  |------|------|------|------|
535
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
536
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
536
537
  | `new_owner` | string | 是 | 新群主 AID(也接受 `aid`) |
537
538
 
538
539
  **响应**:
@@ -558,7 +559,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
558
559
 
559
560
  | 参数 | 类型 | 必填 | 说明 |
560
561
  |------|------|------|------|
561
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
562
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
562
563
  | `public_key` | string | 是 | 公钥 DER base64(SPKI 格式) |
563
564
  | `curve` | string | 否 | 曲线名称(默认 P-256) |
564
565
 
@@ -567,7 +568,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
567
568
  ```json
568
569
  {
569
570
  "group": {
570
- "group_id": "my-team.agentid.pub",
571
+ "group_id": "my-team.agentid.pub",
571
572
  "group_aid": "my-team.agentid.pub",
572
573
  ...
573
574
  },
@@ -602,7 +603,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
602
603
 
603
604
  | 参数 | 类型 | 必填 | 说明 |
604
605
  |------|------|------|------|
605
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
606
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
606
607
  | `group_aid` | string | 否 | 群身份 AID(可选,服务端可推导) |
607
608
  | `old_public_key` | string | 是 | 旧公钥 DER base64 |
608
609
  | `new_public_key` | string | 是 | 新公钥 DER base64 |
@@ -632,7 +633,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
632
633
  ```json
633
634
  {
634
635
  "group": {
635
- "group_id": "my-team.agentid.pub",
636
+ "group_id": "my-team.agentid.pub",
636
637
  "group_aid": "my-team.agentid.pub",
637
638
  ...
638
639
  },
@@ -660,7 +661,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
660
661
 
661
662
  | 参数 | 类型 | 必填 | 说明 |
662
663
  |------|------|------|------|
663
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
664
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
664
665
  | `subject` | string | 是 | 要封禁的 AID(也接受 `aid`) |
665
666
  | `reason` | string | 否 | 封禁原因 |
666
667
  | `expires_at` | integer | 否 | 过期时间戳(0 = 永久) |
@@ -677,7 +678,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
677
678
  "banned_by": "alice.agentid.pub",
678
679
  "reason": "垃圾消息",
679
680
  "expires_at": 0,
680
- "created_at": 1234567890000
681
+ "created_at": 1234567890000
681
682
  }
682
683
  }
683
684
  ```
@@ -686,7 +687,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
686
687
 
687
688
  解除封禁。需要 **admin 及以上**权限。
688
689
 
689
- **参数**:`group_id`(string,兼容字段,值使用目标态 `group_aid`),`subject` 或 `aid` (string)
690
+ **参数**:`group_id`(string,兼容字段,值使用目标态 `group_aid`),`subject` 或 `aid` (string)
690
691
 
691
692
  **响应**:
692
693
 
@@ -702,7 +703,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
702
703
 
703
704
  获取封禁列表。需要 **admin 及以上**权限。
704
705
 
705
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
706
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
706
707
 
707
708
  **响应**:
708
709
 
@@ -716,7 +717,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
716
717
  "banned_by": "alice.agentid.pub",
717
718
  "reason": "垃圾消息",
718
719
  "expires_at": 0,
719
- "created_at": 1234567890000
720
+ "created_at": 1234567890000
720
721
  }
721
722
  ],
722
723
  "total": 1,
@@ -737,7 +738,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
737
738
 
738
739
  | 参数 | 类型 | 必填 | 说明 |
739
740
  |------|------|------|------|
740
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
741
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
741
742
  | `message` | string | 否 | 申请留言 |
742
743
  | `answer` | string | 否 | 入群问题的答案 |
743
744
 
@@ -773,8 +774,8 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
773
774
  "message": "请加我",
774
775
  "answer": "...",
775
776
  "status": "pending",
776
- "created_at": 1234567890000,
777
- "updated_at": 1234567890000,
777
+ "created_at": 1234567890000,
778
+ "updated_at": 1234567890000,
778
779
  "expires_at": 1234654290,
779
780
  "reviewed_by": null,
780
781
  "rejection_reason": null
@@ -790,7 +791,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
790
791
 
791
792
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
792
793
  |------|------|------|--------|------|
793
- | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
794
+ | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
794
795
  | `status` | string | 否 | `"pending"` | `"pending"` / `"approved"` / `"rejected"` |
795
796
  | `page` | integer | 否 | 1 | 页码 |
796
797
  | `size` | integer | 否 | — | 每页数量 |
@@ -806,8 +807,8 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
806
807
  "aid": "carol.agentid.pub",
807
808
  "message": "请加我",
808
809
  "status": "pending",
809
- "created_at": 1234567890000,
810
- "updated_at": 1234567890000
810
+ "created_at": 1234567890000,
811
+ "updated_at": 1234567890000
811
812
  }
812
813
  ],
813
814
  "total": 1,
@@ -824,7 +825,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
824
825
 
825
826
  | 参数 | 类型 | 必填 | 说明 |
826
827
  |------|------|------|------|
827
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
828
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
828
829
  | `aid` | string | 是 | 申请人 AID |
829
830
  | `approve` | boolean | 否 | 批准或拒绝,默认 `true` |
830
831
  | `reason` | string | 否 | 拒绝原因 |
@@ -862,7 +863,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
862
863
 
863
864
  | 参数 | 类型 | 必填 | 说明 |
864
865
  |------|------|------|------|
865
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
866
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
866
867
  | `requests` | array | 是 | 审批列表 |
867
868
 
868
869
  `requests` 数组每项:
@@ -894,7 +895,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
894
895
 
895
896
  | 参数 | 类型 | 必填 | 说明 |
896
897
  |------|------|------|------|
897
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
898
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
898
899
  | `code` | string | 否 | 自定义邀请码(不提供则自动生成) |
899
900
  | `max_uses` | integer | 否 | 最大使用次数,默认 1,必须 > 0 |
900
901
  | `expires_in_seconds` | integer | 否 | 有效期(秒),默认由 invite_code_ttl_days 配置(7 天) |
@@ -912,7 +913,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
912
913
  "max_uses": 10,
913
914
  "used_count": 0,
914
915
  "status": "active",
915
- "created_at": 1234567890000
916
+ "created_at": 1234567890000
916
917
  }
917
918
  }
918
919
  ```
@@ -937,13 +938,13 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
937
938
 
938
939
  列出群组的邀请码。需要 admin 权限。
939
940
 
940
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
941
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
941
942
 
942
943
  ### group.revoke_invite_code
943
944
 
944
945
  撤销邀请码。需要 admin 权限。
945
946
 
946
- **参数**:`group_id`(string,兼容字段,值使用目标态 `group_aid`),`code` (string)
947
+ **参数**:`group_id`(string,兼容字段,值使用目标态 `group_aid`),`code` (string)
947
948
 
948
949
  ---
949
950
 
@@ -951,23 +952,28 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
951
952
 
952
953
  ### group.set_settings
953
954
 
954
- 统一写入群参数。需要 admin 及以上权限。`dispatch_mode` 是群消息的应用层分发模式标签,会随 `group.send` 生成的消息持久化,并由 SDK 在解密后注入到消息顶层和 `payload.dispatch_mode`。
955
-
956
- `group.index` 是保留设置 key,用于保存 owner/admin SDK 生成并签名的群索引。更新 indexed settings 时必须同包提交新的签名 `group.index`,并通过 `expected_index_etag` 做 CAS。
955
+ 统一写入群参数。需要 admin 及以上权限。`mention_mode` 是群消息的应用层提及过滤模式标签,会随 `group.send` 生成的消息持久化,并由 SDK 在解密后注入到消息顶层和对象 `payload.mention_mode`。
957
956
 
958
- `dispatch_mode` 不是 `group.send` 的单次入参;要修改后续消息的模式,请通过 `group.set_settings` 更新群设置。
957
+ `group.index` 是保留设置 key,用于保存 owner/admin SDK 生成并签名的群索引。更新 indexed settings 时必须同包提交新的签名 `group.index`,并通过 `expected_index_etag` 做 CAS。
958
+
959
+ `mention_mode` 不是 `group.send` 的单次入参;要修改后续消息的模式,请通过 `group.set_settings` 更新群设置。
959
960
 
960
961
  **参数**:
961
962
 
962
963
  | 参数 | 类型 | 必填 | 说明 |
963
964
  |------|------|------|------|
964
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
965
- | `settings` | object | 是 | 要写入的设置键值 |
966
- | `expected_index_etag` | string | 写 `group.index` 时必填 | CAS 期望旧 etag;空字符串表示只允许创建首个 `group.index` |
967
- | `settings["dispatch_mode"]` | string | 否 | `"broadcast"` / `"mention"`,默认 `"broadcast"` |
968
- | `settings["rules.content"]` | string | 否 | 群规则正文 |
969
- | `settings["announcement.content"]` | string | 否 | 群公告正文 |
970
- | `settings["group.index"]` | object | 更新 indexed settings 时必填 | 签名 group index,当前结构至少包含 `body` |
965
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
966
+ | `settings` | object | 是 | 要写入的设置键值 |
967
+ | `expected_index_etag` | string | 写 `group.index` 时必填 | CAS 期望旧 etag;空字符串表示只允许创建首个 `group.index` |
968
+ | `settings["mention_mode"]` | string | 否 | `"disabled"` / `"mention-only"`,默认 `"disabled"`;服务端兼容旧名和值 |
969
+ | `settings["rules.content"]` | string | 否 | 群规则正文 |
970
+ | `settings["rules.attachments"]` | array | 否 | 群规则附件稳定引用 |
971
+ | `settings["announcement.content"]` | string | | 群公告正文 |
972
+ | `settings["announcement.attachments"]` | array | 否 | 群公告附件稳定引用 |
973
+ | `settings["join.attachments"]` | array | 否 | 入群要求附件稳定引用 |
974
+ | `settings["{keyName}.content"]` | string | 否 | 通用文档型 indexed setting 正文;`keyName` 需满足受控命名规则 |
975
+ | `settings["{keyName}.attachments"]` | array | 否 | 通用文档型 indexed setting 附件稳定引用 |
976
+ | `settings["group.index"]` | object | 更新 indexed settings 时必填 | 签名 group index,当前结构至少包含 `body` |
971
977
 
972
978
  **预定义群级参数**:
973
979
 
@@ -983,116 +989,120 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
983
989
  | `join.mode` | string | 按 `visibility` 推导:`public -> open`,`private -> approval` | 入群模式:`"open"` / `"approval"` / `"invite_only"` / `"closed"` |
984
990
  | `join.question` | string | `""` | 入群问题 |
985
991
  | `join.auto_approve_patterns` | array | `[]` | 自动批准 AID 匹配规则 |
986
- | `join.max_pending` | integer | `100` | 最大待审批入群申请数 |
987
- | `dispatch_mode` | string | `"broadcast"` | 群消息分发标签:`"broadcast"` / `"mention"`;未显式设置时 `get_settings` 仍返回默认值 |
988
- | `group.index` | object | | 保留 key;签名 JSONL 群索引,由 SDK 生成,服务端只校验、CAS 保存和返回 |
989
-
990
- **indexed settings**:
991
-
992
- | key | 说明 |
993
- |-----|------|
994
- | `rules.content` / `rules.attachments` | 群规则正文与附件稳定引用 |
995
- | `announcement.content` / `announcement.attachments` | 群公告正文与附件稳定引用 |
996
- | `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` | 入群要求配置 |
997
-
998
- 写入规则:
999
-
1000
- - 只更新非 indexed settings 时,继续直接调用 `set_settings`,不需要 `group.index`。
1001
- - 更新任意 indexed setting 时,必须在同一次 `settings` 中携带签名 `group.index`。
1002
- - 写入 `group.index` 时必须传 `expected_index_etag`。
1003
- - 服务端在同一事务内比较当前 `group.index` etag、写 indexed settings、写 `group.index`。
1004
- - CAS 失败时错误消息包含 `group.index etag conflict`;SDK `updateGroupIndex` 会重新读取当前 index、重建签名并按 `max_attempts` 重试。
1005
-
1006
- ```python
1007
- await client.call("group.set_settings", {
992
+ | `join.max_pending` | integer | `100` | 最大待审批入群申请数 |
993
+ | `join.attachments` | array | `[]` | 入群材料附件稳定引用 |
994
+ | `mention_mode` | string | `"disabled"` | 群消息提及过滤标签:`"disabled"` / `"mention-only"`;未显式设置时 `get_settings` 仍返回默认值 |
995
+ | `group.index` | object | — | 保留 key;签名 JSONL 群索引,由 SDK 生成,服务端只校验、CAS 保存和返回 |
996
+
997
+ **indexed settings**:
998
+
999
+ | key | 说明 |
1000
+ |-----|------|
1001
+ | `rules.content` / `rules.attachments` | 群规则正文与附件稳定引用 |
1002
+ | `announcement.content` / `announcement.attachments` | 群公告正文与附件稳定引用 |
1003
+ | `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments` | 入群要求配置与附件稳定引用 |
1004
+ | `{keyName}.content` / `{keyName}.attachments` | 通用文档型设置正文与附件稳定引用 |
1005
+
1006
+ 写入规则:
1007
+
1008
+ - 只更新非 indexed settings 时,继续直接调用 `set_settings`,不需要 `group.index`。
1009
+ - 更新任意 indexed setting 时,必须在同一次 `settings` 中携带签名 `group.index`。
1010
+ - 服务端只接受受控动态文档 key:`{keyName}.content` / `{keyName}.attachments`,其中 `keyName` 匹配 `^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀。调用方不能用该机制写任意 settings key。
1011
+ - 写入 `group.index` 时必须传 `expected_index_etag`。
1012
+ - 服务端在同一事务内比较当前 `group.index` etag、写 indexed settings、写 `group.index`。
1013
+ - CAS 失败时错误消息包含 `group.index etag conflict`;SDK 的 `updateGroupIndex` 会重新读取当前 index、重建签名并按 `max_attempts` 重试。
1014
+ - `rules.attachments`、`announcement.attachments`、`join.attachments` 和 `{keyName}.attachments` 只保存附件引用;附件实体应先写入群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。群自有区默认允许 `owner/admin` 写入,`member` 默认不可写;`.group/` 是系统控制目录,不允许授予 `role:member` 写权限。
1015
+
1016
+ ```python
1017
+ await client.call("group.set_settings", {
1008
1018
  "group_id": "g-abc123.agentid.pub",
1009
- "settings": {"dispatch_mode": "mention"},
1019
+ "settings": {"mention_mode": "mention-only"},
1010
1020
  })
1011
1021
  ```
1012
1022
 
1013
1023
  **响应**:
1014
1024
 
1015
1025
  ```json
1016
- {
1017
- "group_id": "g-abc123.agentid.pub",
1018
- "group_aid": "g-abc123.agentid.pub",
1019
- "updated_keys": ["dispatch_mode"]
1020
- }
1021
- ```
1022
-
1023
- 写入 `group.index` 成功时,响应顶层会强制携带 `_meta.group_indexes`:
1024
-
1025
- ```json
1026
- {
1027
- "group_id": "g-abc123.agentid.pub",
1028
- "group_aid": "g-abc123.agentid.pub",
1029
- "updated_keys": ["announcement.content", "group.index"],
1030
- "_meta": {
1031
- "group_indexes": {
1032
- "g-abc123.agentid.pub": {
1033
- "etag": "\"sha256:...\"",
1034
- "last_modified": 1780000000000,
1035
- "schema": "aun.group.index.v1"
1036
- }
1037
- }
1038
- }
1039
- }
1040
- ```
1041
-
1042
- `group.index` 的正文格式:
1043
-
1044
- ```jsonl
1045
- {"type":"index_meta","group_aid":"g-abc123.agentid.pub","etag":"\"sha256:...\"","last_modified":1780000000000,"schema":"aun.group.index.v1","body_hash":"sha256:...","signed_by":"alice.agentid.pub","sig_alg":"ECDSA-P256-SHA256","signature":"base64..."}
1046
- {"key":"announcement.content","source":"db","etag":"\"sha256:...\"","last_modified":1780000000000}
1047
- ```
1048
-
1049
- `etag` 和 `body_hash` 都由 index 条目的 canonical JSONL bytes 计算。`signature` 覆盖去掉 `signature` 字段后的 `index_meta` 和正文条目,`signed_by` 必须等于本次 RPC actor AID。服务端不会根据 DB 状态生成 `group.index`。
1050
-
1051
- ### group.get_settings
1052
-
1053
- 统一读取群参数。成员可读;不传 `keys` 时返回核心群资料和 settings 表中的全部设置。未显式设置 `dispatch_mode` 时,服务端仍返回默认值 `"broadcast"`。读取 `keys=["group.index"]` 可从服务端摘取当前签名 `group.index`。
1026
+ {
1027
+ "group_id": "g-abc123.agentid.pub",
1028
+ "group_aid": "g-abc123.agentid.pub",
1029
+ "updated_keys": ["mention_mode"]
1030
+ }
1031
+ ```
1032
+
1033
+ 写入 `group.index` 成功时,响应顶层会强制携带 `_meta.group_indexes`:
1034
+
1035
+ ```json
1036
+ {
1037
+ "group_id": "g-abc123.agentid.pub",
1038
+ "group_aid": "g-abc123.agentid.pub",
1039
+ "updated_keys": ["announcement.content", "group.index"],
1040
+ "_meta": {
1041
+ "group_indexes": {
1042
+ "g-abc123.agentid.pub": {
1043
+ "etag": "\"sha256:...\"",
1044
+ "last_modified": 1780000000000,
1045
+ "schema": "aun.group.index.v1"
1046
+ }
1047
+ }
1048
+ }
1049
+ }
1050
+ ```
1051
+
1052
+ `group.index` 的正文格式:
1053
+
1054
+ ```jsonl
1055
+ {"type":"index_meta","group_aid":"g-abc123.agentid.pub","etag":"\"sha256:...\"","last_modified":1780000000000,"schema":"aun.group.index.v1","body_hash":"sha256:...","signed_by":"alice.agentid.pub","sig_alg":"ECDSA-P256-SHA256","signature":"base64..."}
1056
+ {"key":"announcement.content","source":"db","etag":"\"sha256:...\"","last_modified":1780000000000}
1057
+ ```
1058
+
1059
+ `etag` 和 `body_hash` 都由 index 条目的 canonical JSONL bytes 计算。`signature` 覆盖去掉 `signature` 字段后的 `index_meta` 和正文条目,`signed_by` 必须等于本次 RPC actor AID。服务端不会根据 DB 状态生成 `group.index`。
1060
+
1061
+ ### group.get_settings
1062
+
1063
+ 统一读取群参数。成员可读;不传 `keys` 时返回核心群资料和 settings 表中的全部设置。未显式设置 `mention_mode` 时,服务端仍返回默认值 `"disabled"`。读取 `keys=["group.index"]` 可从服务端摘取当前签名 `group.index`。
1054
1064
 
1055
1065
  **参数**:
1056
1066
 
1057
1067
  | 参数 | 类型 | 必填 | 说明 |
1058
1068
  |------|------|------|------|
1059
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1060
- | `keys` | array | 否 | 只读取指定 key,如 `["dispatch_mode", "rules.content"]`;读取 `["group.index"]` 时强制返回 `_meta.group_indexes` |
1069
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1070
+ | `keys` | array | 否 | 只读取指定 key,如 `["mention_mode", "rules.content"]`;读取 `["group.index"]` 时强制返回 `_meta.group_indexes` |
1061
1071
 
1062
1072
  **响应**:
1063
1073
 
1064
1074
  ```json
1065
- {
1066
- "group_id": "g-abc123.agentid.pub",
1067
- "group_aid": "g-abc123.agentid.pub",
1068
- "settings": [
1069
- {"key": "dispatch_mode", "value": "broadcast", "updated_at": 1234567890000}
1070
- ]
1071
- }
1072
- ```
1073
-
1074
- 如果服务端已保存 `group.index`,普通 settings 读取可能在顶层返回 `_meta.group_indexes`。该 meta 受服务端注入频率控制;显式读取 `group.index` 时会强制返回:
1075
-
1076
- ```json
1077
- {
1078
- "group_id": "g-abc123.agentid.pub",
1079
- "group_aid": "g-abc123.agentid.pub",
1080
- "settings": [
1081
- {"key": "group.index", "value": {"body": "..."}, "updated_by": "alice.agentid.pub", "updated_at": 1780000000000}
1082
- ],
1083
- "_meta": {
1084
- "group_indexes": {
1085
- "g-abc123.agentid.pub": {
1086
- "etag": "\"sha256:...\"",
1087
- "last_modified": 1780000000000,
1088
- "schema": "aun.group.index.v1"
1089
- }
1090
- }
1091
- }
1092
- }
1093
- ```
1094
-
1095
- SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本地 index 或业务缓存。etag 不一致只表示本地与观察到的远端版本不同,方向由应用层决定:`checkGroupIndex` 用于检查是否不同步,`getGroupIndex` 用于显式 pull 远端 manifest 并同步本地缓存,`updateGroupIndex` 用于显式 CAS push 本地 indexed settings。
1075
+ {
1076
+ "group_id": "g-abc123.agentid.pub",
1077
+ "group_aid": "g-abc123.agentid.pub",
1078
+ "settings": [
1079
+ {"key": "mention_mode", "value": "disabled", "updated_at": 1234567890000}
1080
+ ]
1081
+ }
1082
+ ```
1083
+
1084
+ 如果服务端已保存 `group.index`,普通 settings 读取可能在顶层返回 `_meta.group_indexes`。该 meta 受服务端注入频率控制;显式读取 `group.index` 时会强制返回:
1085
+
1086
+ ```json
1087
+ {
1088
+ "group_id": "g-abc123.agentid.pub",
1089
+ "group_aid": "g-abc123.agentid.pub",
1090
+ "settings": [
1091
+ {"key": "group.index", "value": {"body": "..."}, "updated_by": "alice.agentid.pub", "updated_at": 1780000000000}
1092
+ ],
1093
+ "_meta": {
1094
+ "group_indexes": {
1095
+ "g-abc123.agentid.pub": {
1096
+ "etag": "\"sha256:...\"",
1097
+ "last_modified": 1780000000000,
1098
+ "schema": "aun.group.index.v1"
1099
+ }
1100
+ }
1101
+ }
1102
+ }
1103
+ ```
1104
+
1105
+ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本地 index 或业务缓存。etag 不一致只表示本地与观察到的远端版本不同,方向由应用层决定:`checkGroupIndex` 用于检查是否不同步,`getGroupIndex` 用于显式 pull 远端 manifest 并同步本地缓存,`updateGroupIndex` 用于显式 CAS push 本地 indexed settings。
1096
1106
 
1097
1107
  ## 消息
1098
1108
 
@@ -1100,13 +1110,13 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
1100
1110
 
1101
1111
  发送群消息。需要 member 权限。
1102
1112
 
1103
- 群消息的持久化 `dispatch_mode` 来自群设置,取值为 `"broadcast"` / `"mention"`;服务端会写入消息对象并在 pull / push 中返回。运行时是否广播全员或分发给值班 Agent,由响应中的 `dispatch` / `message_dispatch` 描述。
1113
+ 群消息的持久化 `mention_mode` 来自群设置,取值为 `"disabled"` / `"mention-only"`;服务端会写入消息对象并在 pull / push 中返回。运行时是否广播全员或分发给值班 Agent,由响应中的 `dispatch` / `message_dispatch` 描述。V2 加密消息把快照放在既有 `envelope_json` 元数据中,不改变 `per_device` 投递列。
1104
1114
 
1105
1115
  **参数**:
1106
1116
 
1107
1117
  | 参数 | 类型 | 必填 | 说明 |
1108
1118
  |------|------|------|------|
1109
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1119
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1110
1120
  | `payload` | object | 否 | 消息内容 |
1111
1121
  | `type` | string | 否 | 信封/封装类型,普通业务消息无需填写;SDK 加密群消息时自动使用 `e2ee.group_encrypted` |
1112
1122
  | `attachments` | array | 否 | 兼容旧接口的顶层附件元数据;推荐把业务附件放入 `payload.attachments` |
@@ -1114,7 +1124,7 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
1114
1124
 
1115
1125
  ### Payload 参考约定
1116
1126
 
1117
- `group.send.params.payload` 的统一业务负载格式见 [09-payload-reference](09-payload-reference.md)。完整群消息请求仍在 `payload` 同级传入 `group_id`(兼容参数名,值使用目标态 `group_aid`);业务类型放在 `payload.type`,不要与 `group.send.params.type` 信封/封装类型混用。
1127
+ `group.send.params.payload` 的统一业务负载格式见 [09-payload-reference](09-payload-reference.md)。完整群消息请求仍在 `payload` 同级传入 `group_id`(兼容参数名,值使用目标态 `group_aid`);业务类型放在 `payload.type`,不要与 `group.send.params.type` 信封/封装类型混用。
1118
1128
 
1119
1129
  `protected_headers` 只在 SDK 加密路径生效;裸 RPC 发送明文或已加密信封时,调用方需自行遵守 [05-E2EE加密通信](05-E2EE加密通信.md#protectedheaders-与可验证上下文) 的格式和校验规则。
1120
1130
 
@@ -1129,52 +1139,52 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
1129
1139
  "message_id": "uuid",
1130
1140
  "sender_aid": "alice.agentid.pub",
1131
1141
  "message_type": "e2ee.group_encrypted",
1132
- "dispatch_mode": "broadcast",
1142
+ "mention_mode": "disabled",
1133
1143
  "payload": {"type": "e2ee.group_encrypted", "...": "..."},
1134
1144
  "attachments": [],
1135
1145
  "created_at": 1234567890000
1136
1146
  },
1137
1147
  "event": { ... },
1138
- "dispatch_mode": "broadcast",
1139
- "dispatch": {"mode": "broadcast", "reason": "duty_disabled"},
1140
- "message_dispatch": { ... },
1141
- "envelope": {
1142
- "from": "alice.agentid.pub",
1143
- "group_id": "g-abc123.agentid.pub",
1144
- "type": "text",
1145
- "timestamp": 1234567890000,
1146
- "encrypted": true,
1147
- "payload_type": "text"
1148
- },
1149
- "payload": {"type": "text", "text": "Hello"}
1150
- }
1151
- ```
1148
+ "mention_mode": "disabled",
1149
+ "dispatch": {"mode": "broadcast", "reason": "duty_disabled"},
1150
+ "message_dispatch": { ... },
1151
+ "envelope": {
1152
+ "from": "alice.agentid.pub",
1153
+ "group_id": "g-abc123.agentid.pub",
1154
+ "type": "text",
1155
+ "timestamp": 1234567890000,
1156
+ "encrypted": true,
1157
+ "payload_type": "text"
1158
+ },
1159
+ "payload": {"type": "text", "text": "Hello"}
1160
+ }
1161
+ ```
1152
1162
 
1153
1163
  | 字段 | 类型 | 说明 |
1154
1164
  |------|------|------|
1155
- | `group_id` | string | 兼容字段,值语义为目标态 `group_aid` |
1165
+ | `group_id` | string | 兼容字段,值语义为目标态 `group_aid` |
1156
1166
  | `message` | object | 消息对象(含 seq、message_id、sender_aid 等) |
1157
1167
  | `event` | object | 关联的群事件对象 |
1158
- | `dispatch_mode` | string | 群消息持久化分发模式标签:`"broadcast"` / `"mention"`;SDK 解密后也会注入到 `payload.dispatch_mode` |
1159
- | `dispatch` | object | 分发策略:`mode` 为 `"broadcast"`(广播全员)或 `"duty"`(值班分发);`reason` 说明原因(如 `"duty_disabled"` / `"active_duty"` / `"no_duty_candidate"` 等) |
1160
- | `duty_state` | object | 可选,值班模式下的当前状态 |
1161
- | `message_dispatch` | object | 运行时分发结果;常见 `status` 包括 `"broadcast"`、`"sent"`、`"queued_batch"`、`"debounced"`、`"skipped"`、`"failed"` |
1162
- | `envelope` | object | SDK 回填的发送结果信封,包含发送方、群标识、业务类型、时间戳、加密标志、protected headers 等可转发元数据 |
1163
- | `payload` | object | SDK 回填的应用层业务 payload;裸 RPC 或内部 `_skip_send_result_envelope` 路径可能没有该字段 |
1168
+ | `mention_mode` | string | 群消息提及过滤模式标签:`"disabled"` / `"mention-only"`;SDK 解密后也会注入到对象 `payload.mention_mode` |
1169
+ | `dispatch` | object | 分发策略:`mode` 为 `"broadcast"`(广播全员)或 `"duty"`(值班分发);`reason` 说明原因(如 `"duty_disabled"` / `"active_duty"` / `"no_duty_candidate"` 等) |
1170
+ | `duty_state` | object | 可选,值班模式下的当前状态 |
1171
+ | `message_dispatch` | object | 运行时分发结果;常见 `status` 包括 `"broadcast"`、`"sent"`、`"queued_batch"`、`"debounced"`、`"skipped"`、`"failed"` |
1172
+ | `envelope` | object | SDK 回填的发送结果信封,包含发送方、群标识、业务类型、时间戳、加密标志、protected headers 等可转发元数据 |
1173
+ | `payload` | object | SDK 回填的应用层业务 payload;裸 RPC 或内部 `_skip_send_result_envelope` 路径可能没有该字段 |
1164
1174
 
1165
1175
  ### group.thought.put
1166
1176
 
1167
1177
  写入某个发送者针对一个群上下文的思考内容。该内容不是普通群消息:服务端不分配消息 `seq`,不广播,不进入 `group.pull`,不需要 ack,也不持久化;只在内存中保留当前 head。
1168
1178
 
1169
- SDK 调用时必须走群组 E2EE。应用层传入明文 `payload`,SDK 会加密成 V2 `e2ee.group_encrypted` 信封、补齐 `thought_id` / `timestamp`,并附加 `client_signature`。裸 WebSocket 客户端若绕过 SDK,至少必须自行完成 V2 envelope、`sender_signature`、AAD 和 state commitment 生成;`client_signature` 按 Gateway 连接级身份语义携带。
1179
+ SDK 调用时必须走群组 E2EE。应用层传入明文 `payload`,SDK 会加密成 V2 `e2ee.group_encrypted` 信封、补齐 `thought_id` / `timestamp`,并附加 `client_signature`。裸 WebSocket 客户端若绕过 SDK,至少必须自行完成 V2 envelope、`sender_signature`、AAD 和 state commitment 生成;`client_signature` 按 Gateway 连接级身份语义携带。
1170
1180
 
1171
- 存储键为规范化后的 `group_aid + sender_aid + context.type + context.id`。RPC 字段名仍为 `group_id` 以兼容旧客户端,但服务端会先规范化为目标态群标识;`sender_aid` 由服务端认证态派生,不能由客户端指定;`context` 是 thought head 的唯一 selector,推荐使用 `{"type": "run", "id": "run-xxx"}`。同一 `(group_aid, sender_aid)` 保留最近 N 个 context 对应的 head,N 由群服务配置 `max_thought_heads_per_sender` 控制,当前默认值为 100;同一个 head 下可追加多条 thought item。
1181
+ 存储键为规范化后的 `group_aid + sender_aid + context.type + context.id`。RPC 字段名仍为 `group_id` 以兼容旧客户端,但服务端会先规范化为目标态群标识;`sender_aid` 由服务端认证态派生,不能由客户端指定;`context` 是 thought head 的唯一 selector,推荐使用 `{"type": "run", "id": "run-xxx"}`。同一 `(group_aid, sender_aid)` 保留最近 N 个 context 对应的 head,N 由群服务配置 `max_thought_heads_per_sender` 控制,当前默认值为 100;同一个 head 下可追加多条 thought item。
1172
1182
 
1173
1183
  **参数**:
1174
1184
 
1175
1185
  | 参数 | 类型 | 必填 | 说明 |
1176
1186
  |------|------|------|------|
1177
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1187
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1178
1188
  | `context.type` | string | 是 | 思考的上下文类型,推荐 `run` |
1179
1189
  | `context.id` | string | 是 | 思考的上下文 ID,如 `run_id` |
1180
1190
  | `payload` | object | 是 | SDK 加密前的思考内容;推荐格式见 [09-payload-reference](09-payload-reference.md#thought思考内容) |
@@ -1202,7 +1212,7 @@ await client.call("group.thought.put", {
1202
1212
  "thought_id": "gt-...",
1203
1213
  "type": "e2ee.group_encrypted",
1204
1214
  "encrypted": true,
1205
- "payload": {"type": "e2ee.group_encrypted", "version": "v2", "...": "..."},
1215
+ "payload": {"type": "e2ee.group_encrypted", "version": "v2", "...": "..."},
1206
1216
  "client_signature": { "...": "..." }
1207
1217
  }
1208
1218
  ```
@@ -1228,7 +1238,7 @@ await client.call("group.thought.put", {
1228
1238
 
1229
1239
  | 参数 | 类型 | 必填 | 说明 |
1230
1240
  |------|------|------|------|
1231
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1241
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1232
1242
  | `sender_aid` | string | 是 | thought 作者 AID |
1233
1243
  | `context.type` | string | 是 | 思考的上下文类型,推荐 `run` |
1234
1244
  | `context.id` | string | 是 | 思考的上下文 ID,如 `run_id` |
@@ -1277,9 +1287,9 @@ result = await client.call("group.thought.get", {
1277
1287
 
1278
1288
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
1279
1289
  |------|------|------|--------|------|
1280
- | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1290
+ | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1281
1291
  | `after_message_seq` | integer | 否 | 0 | 从该消息 seq 之后拉取 |
1282
- | `limit` | integer | 否 | 50 | 最大条数(最大 50;`pull_max_limit` 配置只能进一步收紧) |
1292
+ | `limit` | integer | 否 | 50 | 最大条数(最大 50;`pull_max_limit` 配置只能进一步收紧) |
1283
1293
  | `device_id` | string | 否 | — | 设备 ID(多设备模式) |
1284
1294
 
1285
1295
  **响应**:
@@ -1290,13 +1300,35 @@ result = await client.call("group.thought.get", {
1290
1300
  "messages": [ ... ],
1291
1301
  "latest_message_seq": 42,
1292
1302
  "has_more": false,
1293
- "limit": 50
1303
+ "limit": 50,
1304
+ "retention_floor_message_seq": 20,
1305
+ "earliest_available_message_seq": 31
1294
1306
  }
1295
1307
  ```
1296
1308
 
1297
1309
  多设备模式时额外返回 `cursor` 对象(含 `current_seq`、`join_seq`、`latest_seq`、`unread_count`)。
1298
1310
 
1299
- 返回的每条群消息包含 `dispatch_mode`。Python / Go / TS / JS SDK 在解密后会保留顶层 `dispatch_mode`,并把同一值注入到 `payload.dispatch_mode`,方便应用层按 `"broadcast"` / `"mention"` UI 或通知策略。
1311
+ `group.pull` 是公开的 Forward Pull。实时 A/T/H 最新页同步由 SDK 内部自动完成,不提供需要应用传入的模式参数。普通 Forward 中,`retention_floor_message_seq` 只表示已提交物理 GC;`earliest_available_message_seq-1` 表示服务端综合 retention、入群点和 epoch 后的当前成员可见性排他下界。SDK 以 `max(retention_floor_message_seq, cursor.join_seq, earliest_available_message_seq-1)` 推进 A;History 不修改 A/T/H。
1312
+
1313
+ Forward 原始页校验通过后按页内最大 seq 推进 A,单条解密失败通过 `group.message_undecryptable` 报告而不阻塞水位。Piggy ACK 保留:有待提交 ACK 时,非满页会继续拉一页并携带 ACK,空页后停止。
1314
+
1315
+ 解密当前群消息时若缺少 sender IK,SDK 先执行同发送端 single-flight 的有界同步 bootstrap,最多等待 3 秒;P2P bootstrap 未命中时可继续读取 Group bootstrap。成功后立即重试当前消息,失败或超时才 pending,且不阻塞实时扫描水位。
1316
+
1317
+ SDK 只保证单个实时拉取响应页内按 seq 升序、同 seq 最多发布一次。A/T/H 是扫描水位,不记录应用是否已经收到回调;跨 Push、SDK 自动最新页同步和 Forward 页允许重复和乱序。全局去重与排序由应用业务仓库负责,不是 SDK 交付契约;应用必须在群 namespace 内按 `message_id` 幂等并按 `seq` 排序。SDK 进程内折叠仅作 best-effort 优化。History 只返回结果,不参与实时发布。
1318
+
1319
+ 返回的每条群消息包含 `mention_mode`。Python / Go / TS / JS SDK 在解密后会保留顶层 `mention_mode`,并把同一值注入到对象 `payload.mention_mode`,方便应用层按 `"disabled"` / `"mention-only"` 做 UI 或通知策略。
1320
+
1321
+ ### group.history
1322
+
1323
+ 只读向前翻页群消息。Group Event 不进入此接口,也不受消息 A/T/H 影响。
1324
+
1325
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
1326
+ |------|------|------|--------|------|
1327
+ | `group_id` | string | 是 | — | 群组标识 |
1328
+ | `before_seq` | integer | 是 | — | 排他上界,只返回 `seq < before_seq` 的消息 |
1329
+ | `limit` | integer | 否 | 50 | 单页上限,最大 50 |
1330
+
1331
+ 响应包含 `messages`、`window_start_seq`、`next_before_seq`、`has_older`、`retention_floor_seq` 和 `earliest_available_seq`。页内按 seq 升序;解密失败项以结构化错误返回。下一页必须直接复用 `next_before_seq`,不得根据首条消息自行加减。History 不推进消息/事件 ACK,不修改实时 A/T/H,也不触发 `group.message_created`。
1300
1332
 
1301
1333
  ### group.ack
1302
1334
 
@@ -1306,7 +1338,7 @@ result = await client.call("group.thought.get", {
1306
1338
 
1307
1339
  | 参数 | 类型 | 必填 | 说明 |
1308
1340
  |------|------|------|------|
1309
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1341
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1310
1342
  | `device_id` | string | 是 | 设备 ID |
1311
1343
  | `msg_seq` | integer | 是 | 确认到的消息序号 |
1312
1344
 
@@ -1331,7 +1363,7 @@ result = await client.call("group.thought.get", {
1331
1363
 
1332
1364
  | 参数 | 类型 | 必填 | 说明 |
1333
1365
  |------|------|------|------|
1334
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1366
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1335
1367
  | `message_ids` | string[] | 是 | 待撤回消息 ID 列表,最多 100 个(`recall_max_batch`)|
1336
1368
  | `reason` | string | 否 | 可选撤回理由,建议短文本(最长 255 字符)|
1337
1369
 
@@ -1386,8 +1418,9 @@ result = await client.call("group.thought.get", {
1386
1418
 
1387
1419
  权限与签名约束:
1388
1420
 
1389
- - 群自有区是除 `memberdata` 等系统保留路径外的整个 `group_aid` namespace。`group_aid` 当前证书签名可写;`role:owner` 默认可写;`role:admin` 需要 owner 通过 `group.fs.set_acl` 显式授权后才可写。
1390
- - `group.fs.set_acl` / `group.fs.remove_acl` / `group.fs.get_acl` / `group.fs.list_acl` 只能由当前 group owner 调用,且当前只允许管理或查询 `grantee_aid="role:admin"` 的群自有区角色 ACL;成员升降级、退群、踢出不会联动授权或撤销。
1421
+ - 群自有区是除 `memberdata` 等系统保留路径外的整个 `group_aid` namespace。`group_aid` 当前证书签名可写;成员角色中 `owner/admin` 默认可写,`member` 默认不可写。`group_aid:/.group/` 是系统控制目录,用于群公告、群规则、入群要求附件,默认允许 `owner/admin` 写入。
1422
+ - 老群如果缺少 `.group/` 默认 ACL,group 服务会在该群首次被 RPC 访问时 best-effort 触发 namespace/ACL lazy repair;只有本次 baseline ACL 全部同步成功才记录本进程已检查,失败会在后续访问继续重试。
1423
+ - `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。
1391
1424
  - `memberdata/{member_ref}` 写入默认只允许该成员本人;SDK 只传 group path,不拼接真实 storage 路径。
1392
1425
  - 上传控制面会透传 `parents` 到 storage:默认 `parents=true` 时可递归创建父目录,显式 `parents=false` 时父目录必须已存在。
1393
1426
  - JavaScript 浏览器版 `cp(string, group)` 默认把 string 当文本内容上传;Node 本地路径需显式传 `sourceType: "path"`、`localPath: true` 或使用 `local:` 前缀。Python、TypeScript 和 Go 默认把 string 当本地路径。
@@ -1418,21 +1451,21 @@ result = await client.call("group.thought.get", {
1418
1451
 
1419
1452
  ### group.fs.set_acl
1420
1453
 
1421
- 授予群自有区角色 ACL。需要当前 group owner 身份签名调用;底层由 group 服务以内部门面写入 `storage.set_acl`。
1454
+ 授予群自有区角色 ACL。需要当前 group `owner/admin` 身份调用;底层由 group 服务以内部门面写入 `storage.set_acl`。
1422
1455
 
1423
- 参数:`path` 必填,指向群自有区路径;`grantee_aid` 只能为 `role:admin`;`perms` 默认 `rwx`,必须包含写权限。`path` 可传 `group_aid:/archive` 等 group path。服务端写入 storage 内部权限位时会把 POSIX 删除位 `x` 映射为内部 `d`,对外响应仍显示 `rwx`。
1456
+ 参数:`path` 必填,指向群自有区路径;`grantee_aid` 可为 `role:admin` 或 `role:member`。`role:admin` 默认 `rwx`;`role:member` 只能为 `rw`,且只能授到具体业务目录,不能授到根目录或 `.group/`。`path` 可传 `group_aid:/archive` 等 group path。服务端写入 storage 内部权限位时会把 POSIX 删除位 `x` 映射为内部 `d`,对外响应仍显示 `rwx`;不授删除、移动、重命名权限时使用 `rw`。
1424
1457
 
1425
1458
  ### group.fs.remove_acl
1426
1459
 
1427
- 撤销群自有区角色 ACL。需要当前 group owner 身份签名调用;底层由 group 服务以内部门面写入 `storage.remove_acl`。
1460
+ 撤销群自有区角色 ACL。需要当前 group `owner/admin` 身份调用;底层由 group 服务以内部门面写入 `storage.remove_acl`。
1428
1461
 
1429
- 参数:`path` 必填,指向群自有区路径;`grantee_aid` 只能为 `role:admin`。撤销后,当前 admin 角色成员不再因该路径的 `role:admin` ACL 获得写权限。
1462
+ 参数:`path` 必填,指向群自有区路径;`grantee_aid` 可为 `role:admin` `role:member`。撤销 `role:member` 后,member 不再因该目录 ACL 获得创建/写入权限。
1430
1463
 
1431
1464
  ### group.fs.get_acl
1432
1465
 
1433
- 查询群自有区角色 ACL。需要当前 group owner 身份签名调用;普通 admin/member 不能查询。参数:`path` 必填,指向群自有区路径;可传裸路径 + `group_id`,也可传完整 `group_aid:/...`。
1466
+ 查询群自有区角色 ACL。需要当前 group `owner/admin` 身份调用;普通 member 不能查询。参数:`path` 必填,指向群自有区路径;可传裸路径 + `group_id`,也可传完整 `group_aid:/...`。
1434
1467
 
1435
- 响应包含 `group_id`、`group_aid`、`path`、`area`、`storage` 和 `acls`。`acls[].perms` 使用 POSIX 视图,删除权限显示为 `x`,因此 owner 授权 `role:admin:rwx` 后查询也返回 `rwx`。
1468
+ 响应包含 `group_id`、`group_aid`、`path`、`area`、`storage` 和 `acls`。`acls[].perms` 使用 POSIX 视图,删除权限显示为 `x`,因此授权 `role:admin:rwx` 后查询也返回 `rwx`;`role:member` 只应返回 `rw`。
1436
1469
 
1437
1470
  ### group.fs.list_acl
1438
1471
 
@@ -1480,7 +1513,7 @@ result = await client.call("group.thought.get", {
1480
1513
 
1481
1514
  获取当前在线成员列表。
1482
1515
 
1483
- **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
1516
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
1484
1517
 
1485
1518
  **响应**:
1486
1519
 
@@ -1495,10 +1528,10 @@ result = await client.call("group.thought.get", {
1495
1528
  {
1496
1529
  "aid": "alice.agentid.pub",
1497
1530
  "role": "owner",
1498
- "joined_at": 1234567890000,
1531
+ "joined_at": 1234567890000,
1499
1532
  "online": true,
1500
1533
  "session_id": "sess_123",
1501
- "last_active_at": 1234567890000,
1534
+ "last_active_at": 1234567890000,
1502
1535
  "expire_at": 1234571490
1503
1536
  }
1504
1537
  ]
@@ -1513,18 +1546,18 @@ result = await client.call("group.thought.get", {
1513
1546
 
1514
1547
  ### group.pull_events
1515
1548
 
1516
- 增量拉取群事件,支持多设备独立游标。
1549
+ 增量拉取群事件,支持多设备独立游标。SDK 将其作为后台 Pull 放入独立的 Group Event Gate;该 Gate 内单飞、同请求 key 折叠、不同 key FIFO,排队超过 3 秒时旁路执行。它不与 Group Message Gate 共用,也不修改消息 A/T/H。
1517
1550
 
1518
1551
  **参数**:
1519
1552
 
1520
1553
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
1521
1554
  |------|------|------|--------|------|
1522
- | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1555
+ | `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1523
1556
  | `device_id` | string | 否 | — | 设备 ID,多设备模式必填 |
1524
1557
  | `device_name` | string | 否 | — | 设备名称(首次注册时使用) |
1525
1558
  | `device_type` | string | 否 | — | 设备类型 |
1526
1559
  | `after_event_seq` | integer | 否 | 游标位置 | 从该事件 seq 之后拉取;多设备模式下默认使用设备游标 |
1527
- | `limit` | integer | 否 | 50 | 最大条数(最大 50;`pull_max_limit` 配置只能进一步收紧) |
1560
+ | `limit` | integer | 否 | 50 | 最大条数(最大 50;`pull_max_limit` 配置只能进一步收紧) |
1528
1561
 
1529
1562
  **响应**:
1530
1563
 
@@ -1534,17 +1567,20 @@ result = await client.call("group.thought.get", {
1534
1567
  "events": [ ... ],
1535
1568
  "latest_event_seq": 100,
1536
1569
  "has_more": false,
1537
- "limit": 50,
1570
+ "limit": 50,
1571
+ "retention_floor_event_seq": 20,
1572
+ "earliest_available_event_seq": 31,
1538
1573
  "cursor": {
1539
- "current_seq": 50,
1540
- "join_seq": 0,
1574
+ "current_seq": 25,
1575
+ "join_seq": 30,
1541
1576
  "latest_seq": 100,
1542
- "unread_count": 50
1577
+ "retention_floor_seq": 20,
1578
+ "unread_count": 70
1543
1579
  }
1544
1580
  }
1545
1581
  ```
1546
1582
 
1547
- > `cursor` 仅多设备模式(提供 `device_id`)时返回。响应大小受 `pull_max_response_bytes` 配置限制。包含 E2EE epoch 范围检查,不返回成员加入前的加密事件。
1583
+ > `retention_floor_event_seq` 只表示已提交物理 GC;`earliest_available_event_seq-1` 是综合 retention、入群点和 epoch 后的当前成员可见性排他下界。SDK 以 `max(retention_floor_event_seq, cursor.current_seq, cursor.join_seq, earliest_available_event_seq-1)` 恢复或推进 Group Event A,ACK 仍只能提交已持久化 A。`cursor` 仅多设备模式(提供 `device_id`)时返回。响应大小受 `pull_max_response_bytes` 配置限制。
1548
1584
 
1549
1585
  ### group.ack_messages
1550
1586
 
@@ -1554,7 +1590,7 @@ result = await client.call("group.thought.get", {
1554
1590
 
1555
1591
  | 参数 | 类型 | 必填 | 说明 |
1556
1592
  |------|------|------|------|
1557
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1593
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1558
1594
  | `device_id` | string | 是 | 设备 ID |
1559
1595
  | `msg_seq` | integer | 是 | 确认到的消息序号 |
1560
1596
 
@@ -1570,7 +1606,7 @@ result = await client.call("group.thought.get", {
1570
1606
 
1571
1607
  | 参数 | 类型 | 必填 | 说明 |
1572
1608
  |------|------|------|------|
1573
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1609
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
1574
1610
  | `device_id` | string | 是 | 设备 ID |
1575
1611
  | `event_seq` | integer | 是 | 确认到的事件序号 |
1576
1612
 
@@ -1580,7 +1616,7 @@ result = await client.call("group.thought.get", {
1580
1616
 
1581
1617
  列出当前用户在指定群组的所有设备及游标状态。
1582
1618
 
1583
- **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1619
+ **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1584
1620
 
1585
1621
  **响应**:
1586
1622
 
@@ -1603,7 +1639,7 @@ result = await client.call("group.thought.get", {
1603
1639
 
1604
1640
  注销设备游标(清理不再使用的设备记录)。
1605
1641
 
1606
- **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`),`device_id` (必填)
1642
+ **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`),`device_id` (必填)
1607
1643
 
1608
1644
  **响应**:`{ "success": true }`
1609
1645
 
@@ -1615,7 +1651,7 @@ result = await client.call("group.thought.get", {
1615
1651
 
1616
1652
  获取管理员列表(owner + admin 角色)。
1617
1653
 
1618
- **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1654
+ **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1619
1655
 
1620
1656
  **响应**:
1621
1657
 
@@ -1626,7 +1662,7 @@ result = await client.call("group.thought.get", {
1626
1662
  "aid": "alice.agentid.pub",
1627
1663
  "role": "owner",
1628
1664
  "member_type": "human",
1629
- "joined_at": 1234567890000
1665
+ "joined_at": 1234567890000
1630
1666
  }
1631
1667
  ]
1632
1668
  }
@@ -1636,7 +1672,7 @@ result = await client.call("group.thought.get", {
1636
1672
 
1637
1673
  获取群主 AID。
1638
1674
 
1639
- **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1675
+ **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1640
1676
 
1641
1677
  **响应**:`{ "group_id": "g-abc123.agentid.pub", "owner_aid": "alice.agentid.pub" }`
1642
1678
 
@@ -1644,7 +1680,7 @@ result = await client.call("group.thought.get", {
1644
1680
 
1645
1681
  获取群组综合统计摘要。
1646
1682
 
1647
- **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1683
+ **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1648
1684
 
1649
1685
  **响应**:
1650
1686
 
@@ -1663,8 +1699,8 @@ result = await client.call("group.thought.get", {
1663
1699
  "message_seq": 1000,
1664
1700
  "event_seq": 2000,
1665
1701
  "e2ee_epoch": 3,
1666
- "created_at": 1234567890000,
1667
- "updated_at": 1234567890000
1702
+ "created_at": 1234567890000,
1703
+ "updated_at": 1234567890000
1668
1704
  }
1669
1705
  ```
1670
1706
 
@@ -1673,7 +1709,7 @@ result = await client.call("group.thought.get", {
1673
1709
 
1674
1710
  刷新成员类型分类统计。
1675
1711
 
1676
- **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1712
+ **参数**:`group_id`(必填;兼容字段,值使用目标态 `group_aid`)
1677
1713
 
1678
1714
  **响应**:
1679
1715
 
@@ -1729,14 +1765,14 @@ result = await client.call("group.thought.get", {
1729
1765
  }
1730
1766
  ```
1731
1767
 
1732
- SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x 当前仍保留顶层 `module_id` / `action` / `group_id` / `event_seq` 等兼容别名;新代码应优先通过 `ev["envelope"]["action"]` 等路径访问。
1768
+ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x 当前仍保留顶层 `module_id` / `action` / `group_id` / `event_seq` 等兼容别名;新代码应优先通过 `ev["envelope"]["action"]` 等路径访问。
1733
1769
 
1734
1770
  | 字段 | 类型 | 说明 |
1735
1771
  |------|------|------|
1736
1772
  | `envelope` | object | 群事件信封,包含 `module_id`、`action`、`group_id`、`event_seq`、`event_type`、`actor_aid`、`created_at`、`device_id`、`slot_id` 等存在的字段 |
1737
1773
  | `module_id` | string | 固定 `"group"` |
1738
1774
  | `action` | string | 变更类型(见下表) |
1739
- | `group_id` | string | 兼容字段,值语义为目标态 `group_aid` |
1775
+ | `group_id` | string | 兼容字段,值语义为目标态 `group_aid` |
1740
1776
  | `event_seq` | integer | 可选,服务端分配的单调递增序号,用于 SDK 内部保序去重 |
1741
1777
  | `path` | string | 可选,Group FS 相关 action 的节点路径 |
1742
1778
 
@@ -1774,9 +1810,9 @@ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x
1774
1810
  | `invite_code_revoked` | 邀请码撤销 |
1775
1811
  | `member_banned` | 成员封禁 |
1776
1812
  | `member_unbanned` | 成员解封 |
1777
- | `suspended` | 群组暂停 |
1778
- | `resumed` | 群组恢复 |
1779
- | `dissolved` | 群组解散 |
1813
+ | `suspended` | 群组暂停 |
1814
+ | `resumed` | 群组恢复 |
1815
+ | `dissolved` | 群组解散 |
1780
1816
 
1781
1817
  **订阅**:
1782
1818
 
@@ -1786,9 +1822,13 @@ client.on("group.changed", lambda ev: print(ev["action"]))
1786
1822
 
1787
1823
  ### event/group.message_created
1788
1824
 
1789
- 群消息创建时推送给所有在线成员。支持两种模式:
1825
+ 群消息创建时推送给所有在线成员。
1826
+
1827
+ **实时推送优化**(0.5.6+):当客户端在 `auth.connect` 时声明 `inline_realtime_payload_v1: true` 能力后,Gateway 会优先推送带完整 `payload` 的消息模式。SDK 自动声明此能力,应用层无需关注。
1790
1828
 
1791
- **消息推送模式**(带 `payload`):
1829
+ 支持两种模式:
1830
+
1831
+ **模式 1:消息推送模式**(带 `payload`):
1792
1832
 
1793
1833
  ```json
1794
1834
  {
@@ -1798,27 +1838,27 @@ client.on("group.changed", lambda ev: print(ev["action"]))
1798
1838
  "message_id": "uuid",
1799
1839
  "sender_aid": "alice.agentid.pub",
1800
1840
  "type": "e2ee.group_encrypted",
1801
- "dispatch_mode": "broadcast",
1841
+ "mention_mode": "disabled",
1802
1842
  "payload": { "type": "e2ee.group_encrypted", "..." : "..." },
1803
- "dispatch": {"mode": "broadcast", "reason": "duty_disabled"},
1804
- "kind": "group.broadcast",
1805
- "member_aids": ["bob.agentid.pub"],
1806
- "proximity": {
1807
- "same_device": false,
1808
- "same_egress_ip": true,
1809
- "same_network": true,
1810
- "basis": "egress_ip",
1811
- "asserted_by": "gateway"
1812
- },
1813
- "same_device": false,
1814
- "same_egress_ip": true,
1815
- "same_network": true
1816
- }
1817
- ```
1843
+ "dispatch": {"mode": "broadcast", "reason": "duty_disabled"},
1844
+ "kind": "group.broadcast",
1845
+ "member_aids": ["bob.agentid.pub"],
1846
+ "proximity": {
1847
+ "same_device": false,
1848
+ "same_egress_ip": true,
1849
+ "same_network": true,
1850
+ "basis": "egress_ip",
1851
+ "asserted_by": "gateway"
1852
+ },
1853
+ "same_device": false,
1854
+ "same_egress_ip": true,
1855
+ "same_network": true
1856
+ }
1857
+ ```
1818
1858
 
1819
1859
  SDK 收到后自动解密 `payload`,解密后的明文消息直接交付用户回调。
1820
1860
 
1821
- **通知模式**(不带 `payload`):
1861
+ **模式 2:通知模式**(不带 `payload`,回退场景):
1822
1862
 
1823
1863
  ```json
1824
1864
  {
@@ -1828,12 +1868,12 @@ SDK 收到后自动解密 `payload`,解密后的明文消息直接交付用户
1828
1868
  "message_id": "uuid",
1829
1869
  "sender_aid": "alice.agentid.pub",
1830
1870
  "type": "e2ee.group_encrypted",
1831
- "dispatch_mode": "broadcast",
1871
+ "mention_mode": "disabled",
1832
1872
  "dispatch": {"mode": "broadcast", "reason": "duty_disabled"}
1833
1873
  }
1834
1874
  ```
1835
1875
 
1836
- SDK 收到后自动调用 `group.pull` 拉取最新消息并逐条解密后交付用户回调。
1876
+ SDK 收到新 Head 后自动同步最新消息页并逐条解密;若 A 与 T 之间仍有未扫描区间,再执行一页后台 Forward。应用无需为此调用 `group.pull`。
1837
1877
 
1838
1878
  **SDK 应用层回调形态**:
1839
1879
 
@@ -1850,12 +1890,12 @@ SDK 收到后自动调用 `group.pull` 拉取最新消息并逐条解密后交
1850
1890
  "message_id": "uuid",
1851
1891
  "sender_aid": "alice.agentid.pub",
1852
1892
  "message_type": "group.message",
1853
- "dispatch_mode": "broadcast",
1893
+ "mention_mode": "disabled",
1854
1894
  "payload": {"type": "text", "text": "Hello"}
1855
1895
  }
1856
1896
  ```
1857
1897
 
1858
- SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信封字段统一放在 `envelope`。`envelope` 只保留可转发的归一化元数据,`from` 由 `sender_aid` 归一化而来,`timestamp` 由 `created_at` / `t_server` 归一化而来。0.5.x 当前仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` / `dispatch_mode` 等兼容别名;新代码应优先通过 `msg["envelope"]["from"]`、`msg["envelope"]["timestamp"]` 等路径访问。Gateway 可能附加 `proximity` 及 `same_device` / `same_egress_ip` / `same_network`,表示由 Gateway 基于连接上下文判断的近端关系提示,不参与 E2EE AAD 或业务鉴权。
1898
+ SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信封字段统一放在 `envelope`。`envelope` 只保留可转发的归一化元数据,`from` 由 `sender_aid` 归一化而来,`timestamp` 由 `created_at` / `t_server` 归一化而来。当前仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` / `mention_mode` 等字段;新代码应优先通过 `msg["envelope"]["from"]`、`msg["envelope"]["timestamp"]` 等路径访问。Gateway 可能附加 `proximity` 及 `same_device` / `same_egress_ip` / `same_network`,表示由 Gateway 基于连接上下文判断的近端关系提示,不参与 E2EE AAD 或业务鉴权。
1859
1899
 
1860
1900
  ### event/group.message_recalled
1861
1901
 
@@ -1887,13 +1927,13 @@ SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;群消息信
1887
1927
  }
1888
1928
  ```
1889
1929
 
1890
- SDK 交付给应用层的撤回事件同样带 `envelope`。`envelope` 表示当前交付的撤回 tombstone / 通知自身信封,不是被撤回原消息的信封;业务侧被撤回的原消息列表继续使用 `message_ids` / `target_message_seqs`。`message_id` / `seq` 继续只保留在顶层兼容字段中,不进入 `envelope`。0.5.x 当前仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` 等兼容别名;新代码应优先读取 `envelope`、`message_ids` 和 `target_message_seqs`。
1930
+ SDK 交付给应用层的撤回事件同样带 `envelope`。`envelope` 表示当前交付的撤回 tombstone / 通知自身信封,不是被撤回原消息的信封;业务侧被撤回的原消息列表继续使用 `message_ids` / `target_message_seqs`。`message_id` / `seq` 继续只保留在顶层兼容字段中,不进入 `envelope`。0.5.x 当前仍保留顶层 `group_id` / `seq` / `message_id` / `sender_aid` 等兼容别名;新代码应优先读取 `envelope`、`message_ids` 和 `target_message_seqs`。
1891
1931
 
1892
1932
  | 字段 | 类型 | 说明 |
1893
1933
  |------|------|------|
1894
1934
  | `envelope` | object | 撤回 tombstone / 通知自身信封,包含 `group_id`、`from`、`type`、`kind`、`timestamp`、`encrypted`、`context`、`protected_headers` 等存在的字段 |
1895
1935
  | `module_id` | string | 固定 `"group"` |
1896
- | `group_id` | string | 兼容字段,值语义为目标态 `group_aid` |
1936
+ | `group_id` | string | 兼容字段,值语义为目标态 `group_aid` |
1897
1937
  | `seq` | integer | 当前交付的撤回 tombstone / 通知 seq;在线 push 为 notice_seq,原 seq 占位 tombstone 为原消息 seq |
1898
1938
  | `message_id` | string | 当前交付的撤回 tombstone / 通知自己的 message_id |
1899
1939
  | `tombstone_message_id` | string | 兼容别名,等同于撤回 tombstone / 通知自身的 `message_id` |