@agentunion/fastaun 0.5.15 → 0.5.17

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 (48) hide show
  1. package/CHANGELOG.md +311 -271
  2. package/_packed_docs/CHANGELOG.md +311 -271
  3. package/_packed_docs/INDEX.md +8 -2
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +2 -0
  5. package/_packed_docs/agent.md/SCHEMA.md +7 -0
  6. 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 +1178 -1178
  7. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1213 -1213
  8. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -43
  9. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +80 -17
  10. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +27 -6
  11. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +7 -4
  12. package/_packed_docs/sdk/09-group-rpc-manual.md +167 -35
  13. package/_packed_docs/sdk/09-message-rpc-manual.md +72 -42
  14. package/_packed_docs/sdk/09-storage-rpc-manual.md +23 -14
  15. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +16 -12
  16. package/_packed_docs/sdk/INDEX.md +12 -12
  17. package/dist/agent-md-schema.js +6 -0
  18. package/dist/agent-md-schema.js.map +1 -1
  19. package/dist/agent-md.d.ts +3 -0
  20. package/dist/agent-md.js +9 -1
  21. package/dist/agent-md.js.map +1 -1
  22. package/dist/client/delivery.d.ts +17 -0
  23. package/dist/client/delivery.js +140 -12
  24. package/dist/client/delivery.js.map +1 -1
  25. package/dist/client/group-state.d.ts +4 -0
  26. package/dist/client/group-state.js +63 -0
  27. package/dist/client/group-state.js.map +1 -1
  28. package/dist/client/rpc-pipeline.js +22 -5
  29. package/dist/client/rpc-pipeline.js.map +1 -1
  30. package/dist/client/v2-e2ee.d.ts +10 -1
  31. package/dist/client/v2-e2ee.js +187 -36
  32. package/dist/client/v2-e2ee.js.map +1 -1
  33. package/dist/client.js +56 -13
  34. package/dist/client.js.map +1 -1
  35. package/dist/facades.d.ts +5 -0
  36. package/dist/facades.js +5 -0
  37. package/dist/facades.js.map +1 -1
  38. package/dist/group-fs.js +7 -5
  39. package/dist/group-fs.js.map +1 -1
  40. package/dist/storage/vfs.d.ts +1 -0
  41. package/dist/storage/vfs.js +61 -6
  42. package/dist/storage/vfs.js.map +1 -1
  43. package/dist/tools/cross-sdk-agent.js +31 -1
  44. package/dist/tools/cross-sdk-agent.js.map +1 -1
  45. package/dist/types.d.ts +16 -1
  46. package/dist/version.d.ts +1 -1
  47. package/dist/version.js +1 -1
  48. package/package.json +8 -8
@@ -261,11 +261,12 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
261
261
  | `queue` | 单实例实时消费 | 内存环形缓冲 | 有限时间窗口(默认 5 分钟)+ 有限条数(默认 200 条/AID) | Worker/执行器消费、同一发送者尽量命中同一实例 |
262
262
  | `fanout` | 广播到在线实例 | 数据库 + 文件存储 | TTL 过期前持久保存(默认 24 小时) | 离线送达、历史查询、多实例同步接收 |
263
263
 
264
- **序列号机制**:
265
-
266
- - 每条消息(无论临时或持久化)在收件人维度分配一个递增 `seq`
267
- - 客户端通过 `after_seq` 游标增量拉取,支持多设备各自维护进度
268
- - `message.pull` 合并返回临时消息和持久化消息,按 `seq` 排序
264
+ **序列号机制**:
265
+
266
+ - `ttl <= 0` 的现有消息在收件人维度分配递增 `seq`
267
+ - `ttl > 0` 的 volatile 消息不分配持久 `seq`,使用独立 opaque `volatile_cursor`
268
+ - 客户端通过 `after_seq` 游标增量拉取,支持多设备各自维护进度
269
+ - `message.pull` 分别读取持久流与 volatile 流,并按服务端创建时间稳定合并
269
270
 
270
271
  #### `message.send`
271
272
 
@@ -277,9 +278,11 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
277
278
  "jsonrpc": "2.0",
278
279
  "id": 10,
279
280
  "method": "message.send",
280
- "params": {
281
- "to": "bob.aid.pub",
282
- "payload": {"type": "text", "text": "你好"}
281
+ "params": {
282
+ "to": "bob.aid.pub",
283
+ "device_id": "bob-phone",
284
+ "ttl": 300,
285
+ "payload": {"type": "text", "text": "你好"}
283
286
  }
284
287
  }
285
288
  ```
@@ -288,8 +291,11 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
288
291
 
289
292
  | 参数 | 必需 | 说明 |
290
293
  |------|:----:|------|
291
- | `to` | ✅ | 接收者 AID |
292
- | `payload` | | 消息载荷,对协议层透明,由应用层定义 |
294
+ | `to` | ✅ | 接收者 AID |
295
+ | `device_id` | | 目标接收设备;指定后只投递该设备,不会降级为 AID 全设备投递 |
296
+ | `to_device_id` | ❌ | `device_id` 的兼容别名 |
297
+ | `ttl` | ❌ | 秒;缺省或 `<=0` 持久化,正数钳制到 1–3600 秒并进入 volatile 内存通道 |
298
+ | `payload` | ✅ | 消息载荷,对协议层透明,由应用层定义 |
293
299
  | `type` | ❌ | 信封/封装类型,普通业务消息无需填写;SDK 加密发送时自动使用 `e2ee.encrypted` |
294
300
  | `encrypted` | ❌ | E2EE 标记(默认 `false`) |
295
301
  | `message_id` | ❌ | 幂等键(客户端提供或服务端生成 UUID) |
@@ -307,8 +313,10 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
307
313
  "status": "sent",
308
314
  "delivery_mode": "queue"
309
315
  }
310
- }
311
- ```
316
+ }
317
+ ```
318
+
319
+ 正 TTL 消息不写数据库或 WAL、不分配持久 `seq`,响应包含 `storage="volatile"`、`volatile_cursor`(多设备时可含 `volatile_cursors`)、`created_at`、`expires_at` 和 `status="accepted"`。`delivery_mode` 继续控制在线投递方式,不改变 TTL 存储语义。跨域只传递剩余 TTL,目标域不得重新应用 1 秒下限。
312
320
 
313
321
  ##### Payload 参考约定
314
322
 
@@ -360,7 +368,7 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
360
368
 
361
369
  #### `message.pull`
362
370
 
363
- 按游标拉取新消息。合并返回临时消息和持久化消息,按 `seq` 排序。
371
+ 按两个独立游标拉取持久消息和 volatile 消息。volatile 消息不进入持久 `seq` 空间。
364
372
 
365
373
  **请求**:
366
374
  ```json
@@ -368,11 +376,11 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
368
376
  "jsonrpc": "2.0",
369
377
  "id": 11,
370
378
  "method": "message.pull",
371
- "params": {
372
- "after_seq": 0,
379
+ "params": {
380
+ "after_seq": 0,
381
+ "after_volatile_cursor": "v1:i1:7:20",
373
382
  "limit": 50,
374
- "device_id": "device-001",
375
- "slot_id": "slot-a"
383
+ "device_id": "device-001"
376
384
  }
377
385
  }
378
386
  ```
@@ -381,10 +389,10 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
381
389
 
382
390
  | 参数 | 必需 | 说明 |
383
391
  |------|:----:|------|
384
- | `after_seq` | ❌ | 起始序列号(默认 0),返回 `seq > after_seq` 的消息 |
392
+ | `after_seq` | ❌ | 起始序列号(默认 0),返回 `seq > after_seq` 的消息 |
393
+ | `after_volatile_cursor` | ❌ | opaque volatile 游标;四个 SDK 自动维护,应用通常无需传入 |
385
394
  | `limit` | ❌ | 单次返回上限(默认 50,最大 50) |
386
395
  | `device_id` | ❌ | 多实例消费上下文中的设备标识;缺省时使用连接认证上下文 |
387
- | `slot_id` | ❌ | 同一设备下的消费槽位;空字符串表示设备单实例模式 |
388
396
  | `window_mode` | ❌ | 可选 Pull 模式;`tail` 表示读取以安全 Head 结尾的最新一页 |
389
397
 
390
398
  **响应**:
@@ -416,13 +424,17 @@ proxy-server 处理 `https://proxy.{issuer}/{user_name}/{svc_name}/...` 或等
416
424
  |------|------|------|
417
425
  | `messages` | array | 消息列表(临时 + 持久化合并,按 `seq` 排序) |
418
426
  | `count` | integer | 本次返回的消息条数 |
419
- | `latest_seq` | integer | 本次返回的最大 `seq` |
427
+ | `latest_seq` | integer | 本次返回的最大 `seq` |
428
+ | `latest_volatile_cursor` | string\|null | 本页最后一个 volatile 游标;不改变 `latest_seq` |
429
+ | `volatile_has_more` | boolean | 是否仍有未返回的 volatile 消息;SDK 在 volatile 游标前进时据此继续分页 |
430
+ | `volatile_earliest_cursor` | string\|null | 当前 boot epoch 内仍可读取的最早 volatile 游标 |
431
+ | `volatile_dropped_count` | integer | 当前 boot epoch 内因过期或容量淘汰而不可读的累计数 |
420
432
  | `ephemeral_earliest_available_seq` | integer\|null | 当前临时缓冲中最早可用的 `seq`,`null` 表示无临时消息 |
421
433
  | `ephemeral_dropped_count` | integer | 因缓冲淘汰而丢弃的临时消息计数 |
422
434
 
423
435
  > 客户端可通过 `ephemeral_earliest_available_seq` 判断是否有临时消息丢失:若 `after_seq < ephemeral_earliest_available_seq`,说明存在已被淘汰的消息。
424
436
 
425
- **说明**:不修改消息状态,多设备安全(各 `(aid, device_id, slot_id)` 维护各自的 `after_seq`),同一 `after_seq` 多次调用返回相同结果(幂等)。显式传入的 `device_id` / `slot_id` 若与连接认证上下文不一致,服务端 **MUST** 拒绝请求。
437
+ **说明**:持久游标与 volatile 游标独立推进。SDK 只把含正 `seq` 的消息送入持久 tracker;volatile push/pull 按发送方和 `message_id` 去重,交付成功后自动 ACK。SDK 在传输层注入内部 slot,应用不得传入或读取,任何消息、响应和事件都不得包含该字段。epoch 不匹配时 SDK 清空 volatile 游标并重试一次。`message.history` 不返回 volatile 消息。
426
438
 
427
439
  **Tail 模式**:`window_mode="tail"` 时,服务端固定安全 `head_seq`,返回跨度不超过 `limit` 的最新 seq band,并额外返回:
428
440
 
@@ -463,18 +475,18 @@ History 不触发实时消息事件。客户端解密 History 结果时不得修
463
475
 
464
476
  #### `message.ack`
465
477
 
466
- 确认已收到消息,推进服务端 ack 游标。
478
+ 确认已收到消息。持久 ACK 与 volatile ACK 可以单独提交,也可以在同一请求中提交。
467
479
 
468
480
  **请求**:
469
481
  ```json
470
482
  {
471
483
  "jsonrpc": "2.0",
472
484
  "id": 12,
473
- "method": "message.ack",
474
- "params": {
475
- "seq": 43,
476
- "device_id": "device-001",
477
- "slot_id": "slot-a"
485
+ "method": "message.ack",
486
+ "params": {
487
+ "seq": 43,
488
+ "volatile_cursors": ["v1:i1:7:21"],
489
+ "device_id": "device-001"
478
490
  }
479
491
  }
480
492
  ```
@@ -483,9 +495,11 @@ History 不触发实时消息事件。客户端解密 History 结果时不得修
483
495
 
484
496
  | 参数 | 必需 | 说明 |
485
497
  |------|:----:|------|
486
- | `seq` | | 确认到的序列号(含),表示该 seq 及之前的所有消息已收到 |
487
- | `device_id` | ❌ | 多实例消费上下文中的设备标识;缺省时使用连接认证上下文 |
488
- | `slot_id` | ❌ | 同一设备下的消费槽位;空字符串表示设备单实例模式 |
498
+ | `seq` | | 确认到的持久序列号(含);未提交 volatile ACK 时必填 |
499
+ | `volatile_cursor` | ❌ | 单个 volatile 游标的兼容形式 |
500
+ | `volatile_cursors` | ❌ | 要确认的 volatile 游标数组 |
501
+ | `volatile_ids` | ❌ | 要按 `message_id` 确认的 volatile 消息数组 |
502
+ | `device_id` | ❌ | 多实例消费上下文中的设备标识;缺省时使用连接认证上下文 |
489
503
 
490
504
  **响应**:
491
505
  ```json
@@ -496,7 +510,7 @@ History 不触发实时消息事件。客户端解密 History 结果时不得修
496
510
  }
497
511
  ```
498
512
 
499
- **说明**:`ack_seq` 仅增不减。现代连接按 `(aid, device_id, slot_id)` 维护 ack 游标;未携带 `device_id` legacy 连接继续走 per-AID 兼容路径。显式传入的 `device_id` / `slot_id` 若与连接认证上下文不一致,服务端 **MUST** 拒绝请求。
513
+ **说明**:`ack_seq` 仅增不减;volatile 结果通过 `volatile_ack` 返回 `accepted`、`expired` 等幂等计数。服务端内部按消费 slot 隔离 lease,但 slot 不属于对外协议对象。
500
514
 
501
515
  #### `message.recall`
502
516
 
@@ -589,8 +603,9 @@ History 不触发实时消息事件。客户端解密 History 结果时不得修
589
603
  {
590
604
  "jsonrpc": "2.0",
591
605
  "method": "event/message.received",
592
- "params": {
593
- "from": "bob.aid.pub",
606
+ "params": {
607
+ "from": "bob.aid.pub",
608
+ "sender_device_id": "bob-phone",
594
609
  "to": "alice.aid.pub",
595
610
  "message_id": "550e8400-...",
596
611
  "seq": 42,
@@ -599,8 +614,10 @@ History 不触发实时消息事件。客户端解密 History 结果时不得修
599
614
  "delivery_mode": "queue",
600
615
  "encrypted": false
601
616
  }
602
- }
603
- ```
617
+ }
618
+ ```
619
+
620
+ volatile 事件包含 `storage="volatile"`、`volatile_cursor`、`created_at`、`expires_at`,不含持久 `seq` 或内部 slot。`sender_device_id` 始终表示发送方设备,可用于下一次定向发送。
604
621
 
605
622
  #### `event/message.ack`
606
623
 
@@ -611,19 +628,17 @@ History 不触发实时消息事件。客户端解密 History 结果时不得修
611
628
  "jsonrpc": "2.0",
612
629
  "method": "event/message.ack",
613
630
  "params": {
614
- "to": "bob.aid.pub",
615
- "device_id": "device-001",
616
- "slot_id": "slot-a",
617
- "ack_seq": 43,
631
+ "to": "bob.aid.pub",
632
+ "device_id": "device-001",
633
+ "ack_seq": 43,
618
634
  "timestamp": 1709712003
619
635
  }
620
636
  }
621
637
  ```
622
638
 
623
- - `to`:确认方 AID
624
- - `device_id`:触发 ack 的设备标识;legacy 客户端为空字符串
625
- - `slot_id`:触发 ack 的消费槽位;空字符串表示设备单实例或 legacy 路径
626
- - `ack_seq`:确认到的序列号(含该 seq 及之前的所有消息)
639
+ - `to`:确认方 AID
640
+ - `device_id`:触发 ack 的设备标识;legacy 客户端为空字符串
641
+ - `ack_seq`:确认到的序列号(含该 seq 及之前的所有消息)
627
642
 
628
643
  #### `event/message.recalled`
629
644
 
@@ -83,7 +83,7 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
83
83
 
84
84
  `mention-only` 必须基于结构化的 `payload.mentions` 判断,不得仅扫描文本中的 `@xxx`;`{ "scope": "all" }` 视为命中所有成员。该设置仅适用于群组,群 owner/admin 可写,普通成员只读。
85
85
 
86
- ### Member 对象
86
+ ### Member 对象
87
87
 
88
88
  | 字段 | 类型 | 说明 |
89
89
  |------|------|------|
@@ -91,7 +91,19 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
91
91
  | `group_id` | string | 群组 ID |
92
92
  | `role` | string | `"owner"` / `"admin"` / `"member"` |
93
93
  | `joined_at` | integer | 加入时间(Unix 秒) |
94
- | `last_ack_seq` | integer | 最后已读消息序号 |
94
+ | `last_ack_seq` | integer | 最后已读消息序号 |
95
+
96
+ ### Member Status 对象
97
+
98
+ | 字段 | 类型 | 说明 |
99
+ |------|------|------|
100
+ | `group_id` | string | 群组 ID |
101
+ | `aid` | string | 成员 AID |
102
+ | `online_status` | string | 成员上报的在线状态;未上报时为空字符串 |
103
+ | `work_status` | string | 成员上报的工作状态;未上报时为空字符串 |
104
+ | `updated_at` | integer | 最近一次状态上报时间(Unix 毫秒) |
105
+ | `last_message_at` | integer | 该成员在此群最后一条成功发送消息的时间(Unix 毫秒) |
106
+ | `last_payload_type` | string | 最后一条成功发送消息的 `payload.type` |
95
107
 
96
108
  ### Message 对象
97
109
 
@@ -119,8 +131,12 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
119
131
  | 设置角色 | ✅ | ❌ | ❌ |
120
132
  | 更新群信息 | ✅ | ✅ | ❌ |
121
133
  | 更新公告 | ✅ | ✅ | ❌ |
122
- | 审批申请 | ✅ | ✅ | ❌ |
123
- | 暂停/关闭群 | ✅ | | ❌ |
134
+ | 审批申请 | ✅ | ✅ | ❌ |
135
+ | 禁言/取消禁言 | ✅ | ✅(受角色层级限制) | ❌ |
136
+ | 屏蔽/取消屏蔽其他成员 | ✅ | ✅(受角色层级限制) | ❌ |
137
+ | 屏蔽/取消屏蔽自己 | ✅ | ✅ | ✅ |
138
+ | 上报自己状态/查询成员状态 | ✅ | ✅ | ✅ |
139
+ | 暂停/关闭群 | ✅ | ✅ | ❌ |
124
140
  | 转让群主 | ✅ | ❌ | ❌ |
125
141
  | Group FS 写入 | ✅ | 配置决定 | ❌ |
126
142
 
@@ -130,7 +146,9 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
130
146
 
131
147
  ### `group.create`
132
148
 
133
- 创建群组。
149
+ 创建群组。
150
+
151
+ SDK 高层建群流程必须支持崩溃恢复:命名群复用已持久化密钥并重放相同 `group_name + public_key` 的已提交结果;匿名群复用已持久化的创建上下文,使响应丢失后的重试返回同一数字群,再继续群身份绑定和 `agent.md` 上传。服务端必须原子提交群记录、群主成员、成员索引、入群设置、首个 `group.changed` 事件及匿名创建映射。直接调用 RPC 且没有 SDK 恢复上下文时,每次调用仍表示一次新的自动群创建。
134
152
 
135
153
  **参数**:
136
154
 
@@ -210,7 +228,7 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
210
228
 
211
229
  ### `group.suspend`
212
230
 
213
- 暂停群组,暂停期间不能发送消息。需要 admin 及以上权限。
231
+ 暂停群组。暂停期间 owner/admin 可以继续通过 `group.send`、`group.v2.send` 和 `group.thought.put` 发言;member 禁止发言,入群、邀请、申请审批等准入操作继续拒绝。需要 admin 及以上权限。
214
232
 
215
233
  **参数**:`group_id` (string, 必填)
216
234
 
@@ -293,9 +311,9 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
293
311
 
294
312
  **响应**:`{ "group": { ... }, "member": { ... } }`
295
313
 
296
- ### `group.transfer_owner`
297
-
298
- 转让群主身份。需要 **owner** 权限。
314
+ ### `group.transfer_owner`
315
+
316
+ 转让群主身份。需要 **owner** 权限。受让方无需手动确认,SDK 自动完成确认和转让收尾。
299
317
 
300
318
  **参数**:`group_id` (必填), `new_owner` (必填,新群主 AID;别名 `aid` 向后兼容)
301
319
 
@@ -332,13 +350,55 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
332
350
 
333
351
  **响应**:`{ "group_id": "g-abc123.agentid.pub", "unbanned_aid": "bob.agentid.pub" }`
334
352
 
335
- ### `group.get_banlist`
353
+ ### `group.get_banlist`
336
354
 
337
355
  获取封禁列表。需要 admin 及以上权限。
338
356
 
339
357
  **参数**:`group_id` (必填)
340
358
 
341
- **响应**:`{ "group_id": "g-abc123.agentid.pub", "items": [ ... ] }`
359
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "items": [ ... ] }`
360
+
361
+ 禁言和屏蔽是独立状态,可以同时设置。禁言禁止发送但不影响接收;屏蔽停止接收但不影响发送。
362
+
363
+ ### `group.block`
364
+
365
+ 屏蔽成员接收群消息。owner/admin 可以屏蔽其权限范围内的成员;成员可以屏蔽自己。屏蔽后,该成员不再收到实时消息 Push、离线消息 Push、Pull 或 E2EE wrap,但仍可向群内发送消息。
366
+
367
+ **参数**:`group_id`(必填)、`subject` 或 `aid`(必填;传入调用者自己的 AID 即可屏蔽自己)、`reason`(可选)。
368
+
369
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "block": { "group_id": "g-abc123.agentid.pub", "subject": "bob.agentid.pub", "blocked_by": "alice.agentid.pub", "reason": "", "created_at": 1234567890000 } }`
370
+
371
+ ### `group.unblock`
372
+
373
+ 取消屏蔽。owner/admin 可以取消其权限范围内成员的屏蔽;成员可以取消自己的屏蔽。
374
+
375
+ **参数**:`group_id`(必填)、`subject` 或 `aid`(必填;传入调用者自己的 AID 即可取消自己的屏蔽)。
376
+
377
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "subject": "bob.agentid.pub", "status": "removed" }`
378
+
379
+ ### `group.get_blocklist`
380
+
381
+ 获取群屏蔽列表。需要 admin 及以上权限。
382
+
383
+ **参数**:`group_id`(必填)
384
+
385
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "items": [ ... ], "total": 1, "page": 1, "size": 1 }`
386
+
387
+ ### `group.report_status`
388
+
389
+ 上报调用者在指定群内的 `online_status` 和 `work_status`。调用者只能更新自己的状态,`updated_at` 由服务端记录;`last_message_at` 和 `last_payload_type` 由服务端在消息发送成功后维护。
390
+
391
+ **参数**:`group_id`(必填)、`online_status`(必填)、`work_status`(必填)。
392
+
393
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "status": { ... } }`
394
+
395
+ ### `group.get_member_statuses`
396
+
397
+ 查询群内所有成员状态。调用者必须是群成员;响应包含未上报状态的成员。
398
+
399
+ **参数**:`group_id`(必填)
400
+
401
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "items": [ { "group_id": "g-abc123.agentid.pub", "aid": "alice.agentid.pub", "online_status": "online", "work_status": "busy", "updated_at": 1234567890000, "last_message_at": 1234567890123, "last_payload_type": "text" } ] }`
342
402
 
343
403
  ---
344
404
 
@@ -389,7 +449,7 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
389
449
  ```
390
450
 
391
451
  **设计约束**:
392
- - 群 `status=suspended` 时拒绝发送
452
+ - 群 `status=suspended` 时仅 owner/admin 可以发送,member 发送会被拒绝
393
453
  - 消息 ID 自动生成(格式:`gm-{uuid}`),客户端无需提供
394
454
 
395
455
  ### `group.pull`
@@ -631,7 +691,7 @@ Group FS 是群文件系统的唯一对外模型,所有群文件浏览、创
631
691
 
632
692
  ---
633
693
 
634
- ## 10.12 在线状态
694
+ ## 10.12 在线状态与群内成员状态
635
695
 
636
696
  群组在线状态是 per-AID 的全局状态(非 per-group)。在线索引由 Gateway 的 `client.online` / `client.offline` 事件驱动,Group 服务消费这些事件维护在线状态;客户端不需要也不能调用单独的上线、下线或心跳 RPC。
637
697
 
@@ -643,7 +703,9 @@ Group FS 是群文件系统的唯一对外模型,所有群文件浏览、创
643
703
 
644
704
  **响应**:`{ "group_id": "g-abc123.agentid.pub", "members": [ ... ], "items": [ ... ], "online_members": [ ... ], "online_count": 2, "total": 10, "page": 1, "size": 10 }`
645
705
 
646
- 字段约定:`members` 是主字段;`items` 和 `online_members` 是兼容别名,内容与 `members` 完全相同。
706
+ 字段约定:`members` 是主字段;`items` 和 `online_members` 是兼容别名,内容与 `members` 完全相同。
707
+
708
+ `group.get_online_members` 返回 Gateway 在线索引中的全局连接状态。`group.report_status` / `group.get_member_statuses` 管理成员在单个群内主动上报的在线/工作状态及最后发言摘要,两套状态来源相互独立。
647
709
 
648
710
  ---
649
711
 
@@ -725,8 +787,10 @@ Group 服务通过 `event/group.*` 事件推送变更通知给相关 AID。
725
787
  | `invite_code_created` | 邀请码创建 |
726
788
  | `invite_code_used` | 邀请码使用 |
727
789
  | `invite_code_revoked` | 邀请码撤销 |
728
- | `member_banned` | 成员被封禁 |
729
- | `member_unbanned` | 成员解除封禁 |
790
+ | `member_banned` | 成员被封禁 |
791
+ | `member_unbanned` | 成员解除封禁 |
792
+ | `member_blocked` | 成员被屏蔽 |
793
+ | `member_unblocked` | 成员取消屏蔽 |
730
794
  | `suspended` | 群组暂停 |
731
795
  | `resumed` | 群组恢复 |
732
796
  | `dissolved` | 群组解散 |
@@ -807,4 +871,3 @@ Group 服务通过 `event/group.*` 事件推送变更通知给相关 AID。
807
871
  - **Group FS**:群文件能力统一由 `group.fs.*` 提供;不再提供独立资源审批 RPC。
808
872
  - **在线状态**:通过 `group.get_online_members` 查询当前在线成员列表。
809
873
  - **Group FS 系统目录保护**:`memberdata` 是 Group FS 视图层的虚拟系统目录;根节点和成员槽位根不得被普通文件操作删除、覆盖或重命名。成员槽位子路径映射到成员个人 Storage 的 `group_data/{group_aid}`,只能通过 `group.fs.*` 间接访问。完整保护规则见 [16-系统目录保护方案.md](16-系统目录保护方案.md)。
810
-
@@ -238,11 +238,17 @@ await client.close()
238
238
  ### RPC
239
239
 
240
240
  ```python
241
- result = await client.call("message.send", {
242
- "to": "bob.agentid.pub",
243
- "payload": {"type": "text", "text": "hello"},
244
- })
245
- ```
241
+ result = await client.call("message.send", {
242
+ "to": "bob.agentid.pub",
243
+ "device_id": "bob-phone",
244
+ "ttl": 300,
245
+ "payload": {"type": "text", "text": "hello"},
246
+ })
247
+ ```
248
+
249
+ `message.send` 可选传入目标 `device_id`,非空时只投递该设备;`to_device_id` 仅为兼容别名,规范字段优先。目标无效时发送失败且不会退化为全设备投递。这里的 `device_id` 是接收目标,`message.pull` / `message.ack` 的同名字段则表示当前消费设备。
250
+
251
+ `ttl` 单位为秒:缺省或 `<=0` 保持持久化;正数钳制到 1–3600 秒,只存于消息服务内存且不分配持久 `seq`。四个 SDK 自动维护 volatile 游标、去重及 ACK;返回和事件中的 `storage`、`volatile_cursor`、`created_at`、`expires_at` 可用于识别此类消息。
246
252
 
247
253
  常用 meta RPC 直接透传:
248
254
 
@@ -328,10 +334,12 @@ headers = client.get_protected_headers()
328
334
 
329
335
  | 能力 | Python | TS/JS | Go | 说明 |
330
336
  |------|--------|-------|----|------|
331
- | Storage VFS | `client.storage` | `client.storage` | `client.Storage()` | 类 POSIX 文件操作;上传自动选择 inline / session / 秒传,下载自动选择 inline / ticket;支持 `touch`、`find`、`du`、`df`、ACL/token/软链/挂载门面 |
337
+ | Storage VFS | `client.storage` | `client.storage` | `client.Storage()` | 类 POSIX 文件操作;上传自动选择 inline / session / 秒传并统一 Content-Type,下载自动选择 inline / ticket;支持 `touch`、`find`、`du`、`df`、ACL/token/软链/挂载门面 |
332
338
  | Collab | `client.collab` | `client.collab` | `client.Collab()` | 版本化文档、标签、`gc` / `reflog` / `revert` |
333
339
  | 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 编排 |
334
340
 
341
+ 四个 SDK 的 Storage VFS 与 Group FS 上传门面在未显式指定 `content_type` / `contentType` 时,先按实际字节识别 PNG、JPEG、GIF、BMP、WebP、PDF、gzip、ZIP、MP4、JSON、HTML 和 UTF-8 文本,再回退文件扩展名及 `application/octet-stream`。session 上传会把同一 MIME 值用于 create session、HTTP PUT 的 `Content-Type` 和 complete;session 响应中的其它 header 会保留,Content-Type 会替换为该 MIME。OSS 预签名 URL 会校验签名头,应用绕过 VFS 时缺少或改写该请求头可能直接收到 OSS 403。
342
+
335
343
  群文件系统路径统一使用 `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` 当本地路径。
336
344
 
337
345
  ### 消息与群组门面
@@ -348,6 +356,17 @@ headers = client.get_protected_headers()
348
356
  `message.history` 和 `group.history` 使用 `before_seq` 排他上界向左翻页,下一页直接使用响应的 `next_before_seq`。History 只读,不推进实时 A/T/H、不 ACK、不触发实时消息事件。实时 Push 的最新页同步完全由 SDK 内部自动执行,再按 A/T/H 决定是否补一页 Forward;没有需要应用调用的 Tail 方法或参数。
349
357
 
350
358
  消息回调只提供页级语义:单个 Tail/Forward 响应页内按 seq 升序、同 seq 最多一次;跨 Push/Tail/Forward 页可能重复或乱序。A/T/H 不能用于判断某条消息是否已经回调。全局去重与排序不是 SDK 业务逻辑保证;应用仓库应以 `(namespace, message_id)` 做唯一键,并按 `seq` 排序。SDK 的进程内折叠仅是 best-effort 优化。
359
+
360
+ **群成员管理与状态方法**:
361
+
362
+ | 语义 | Python | TS/JS | Go |
363
+ |------|--------|-------|----|
364
+ | 屏蔽/取消屏蔽 | `block()` / `unblock()` | `block()` / `unblock()` | `Block()` / `Unblock()` |
365
+ | 获取屏蔽列表 | `get_blocklist()` | `getBlocklist()` | `GetBlocklist()` |
366
+ | 上报自己的群内状态 | `report_status()` | `reportStatus()` | `ReportStatus()` |
367
+ | 获取所有成员状态 | `get_member_statuses()` | `getMemberStatuses()` | `GetMemberStatuses()` |
368
+
369
+ 屏蔽与禁言相互独立且可以同时设置。屏蔽成员仍可向群发送消息,但不接收群消息;禁言成员不能向群发送消息,但仍可接收。群主转让是两阶段流程:旧群主先生成授权并调用 `group.transfer_owner`,新群主 SDK 收到 `owner_transfer_rekey_pending` 后生成新群密钥并调用 `group.complete_transfer`。四个 SDK 会在新群主在线或重连恢复时自动尝试第二阶段,也保留 `completeTransfer`(Python 为 `complete_transfer`,Go 为 `CompleteTransfer`)供显式恢复;发起调用返回 `pending_rekey`,不表示转让已经完成。
351
370
 
352
371
  **群查询方法**:`GroupFacade` 提供三个查询方法,适用不同场景:
353
372
 
@@ -746,6 +765,8 @@ sub.unsubscribe()
746
765
  | `push.offline_message` | Push Server 收到离线唤醒批次;普通终端无需订阅 |
747
766
  | `storage.object_changed` | Storage 对象变更事件透传 |
748
767
 
768
+ `message.received` 的应用层消息保留 `sender_device_id`,表示发送方设备;需要只回复原设备时,将该值作为下一次 `message.send.device_id`。volatile 消息还保留 `storage="volatile"`、`volatile_cursor`、`created_at`、`expires_at`,不含持久 `seq`;内部 slot 不会暴露给应用。
769
+
749
770
  ### delivery.changed
750
771
 
751
772
  `delivery.changed` 是 Python、Go、JavaScript 和 TypeScript SDK 统一提供的本地事件,用于通知应用层一批消息已经完成交付,可以从业务仓库刷新相关会话 UI。它不替代 `message.received` / `group.message_created`:应用仍应逐条处理和持久化原消息事件,再把 `delivery.changed` 作为批量刷新信号。
@@ -29,10 +29,13 @@ AUNError
29
29
  Result 格式:
30
30
 
31
31
  ```python
32
- loaded = store.load("alice.agentid.pub")
33
- if not loaded["ok"]:
34
- print(loaded["error"]["code"], loaded["error"]["message"])
35
- ```
32
+ loaded = store.load("alice.agentid.pub")
33
+ if not loaded["ok"]:
34
+ print(loaded["error"]["code"], loaded["error"]["message"])
35
+ print(loaded.error.cause)
36
+ ```
37
+
38
+ Python `ErrorInfo.cause` 保存 SDK 捕获到的本地原始异常,供诊断或异常类型判断使用。它不会进入 `ErrorInfo.to_dict()` / `Result.to_dict()`,因此不能通过 `loaded["error"]["cause"]` 读取,也不会进入序列化结果。
36
39
 
37
40
  异常属性:
38
41