@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.
- package/CHANGELOG.md +311 -271
- package/_packed_docs/CHANGELOG.md +311 -271
- package/_packed_docs/INDEX.md +8 -2
- package/_packed_docs/KITE_DOCS_GUIDE.md +2 -0
- package/_packed_docs/agent.md/SCHEMA.md +7 -0
- 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
- 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
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -43
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +80 -17
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +27 -6
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +7 -4
- package/_packed_docs/sdk/09-group-rpc-manual.md +167 -35
- package/_packed_docs/sdk/09-message-rpc-manual.md +72 -42
- package/_packed_docs/sdk/09-storage-rpc-manual.md +23 -14
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +16 -12
- package/_packed_docs/sdk/INDEX.md +12 -12
- package/dist/agent-md-schema.js +6 -0
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +3 -0
- package/dist/agent-md.js +9 -1
- package/dist/agent-md.js.map +1 -1
- package/dist/client/delivery.d.ts +17 -0
- package/dist/client/delivery.js +140 -12
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts +4 -0
- package/dist/client/group-state.js +63 -0
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.js +22 -5
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +10 -1
- package/dist/client/v2-e2ee.js +187 -36
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.js +56 -13
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +5 -0
- package/dist/facades.js +5 -0
- package/dist/facades.js.map +1 -1
- package/dist/group-fs.js +7 -5
- package/dist/group-fs.js.map +1 -1
- package/dist/storage/vfs.d.ts +1 -0
- package/dist/storage/vfs.js +61 -6
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +31 -1
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/types.d.ts +16 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -8
|
@@ -38,13 +38,19 @@
|
|
|
38
38
|
| [group.get_members](#groupget_members) | 获取成员列表 |
|
|
39
39
|
| [group.kick](#groupkick) | 踢出成员 |
|
|
40
40
|
| [group.leave](#groupleave) | 主动退群 |
|
|
41
|
-
| [group.set_role](#groupset_role) | 设置角色 |
|
|
42
|
-
| [group.transfer_owner](#grouptransfer_owner) | 转让群主 |
|
|
43
|
-
| [group.
|
|
41
|
+
| [group.set_role](#groupset_role) | 设置角色 |
|
|
42
|
+
| [group.transfer_owner](#grouptransfer_owner) | 转让群主 |
|
|
43
|
+
| [group.complete_transfer](#groupcomplete_transfer) | 完成群主转让与群身份换钥 |
|
|
44
|
+
| [group.bind_group_aid](#groupbind_group_aid) | 为匿名群绑定群身份 |
|
|
44
45
|
| [group.renew_group_aid](#grouprenew_group_aid) | 轮换群身份密钥 |
|
|
45
|
-
| [group.ban](#groupban) | 封禁成员 |
|
|
46
|
-
| [group.unban](#groupunban) | 解封成员 |
|
|
47
|
-
| [group.get_banlist](#groupget_banlist) | 获取封禁列表 |
|
|
46
|
+
| [group.ban](#groupban) | 封禁成员 |
|
|
47
|
+
| [group.unban](#groupunban) | 解封成员 |
|
|
48
|
+
| [group.get_banlist](#groupget_banlist) | 获取封禁列表 |
|
|
49
|
+
| [group.block](#groupblock) | 屏蔽成员接收群消息 |
|
|
50
|
+
| [group.unblock](#groupunblock) | 取消屏蔽 |
|
|
51
|
+
| [group.get_blocklist](#groupget_blocklist) | 获取屏蔽列表 |
|
|
52
|
+
| [group.report_status](#groupreport_status) | 上报自己的群内状态 |
|
|
53
|
+
| [group.get_member_statuses](#groupget_member_statuses) | 获取群成员状态列表 |
|
|
48
54
|
|
|
49
55
|
### 入群流程
|
|
50
56
|
|
|
@@ -161,7 +167,9 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
|
|
|
161
167
|
|
|
162
168
|
### group.create
|
|
163
169
|
|
|
164
|
-
创建群组。调用者自动成为 owner。支持创建命名群(传入 `group_name` + `public_key`)。新建群主标识以 `group_aid` 为准;`group_id` 仅作为兼容字段保留。
|
|
170
|
+
创建群组。调用者自动成为 owner。支持创建命名群(传入 `group_name` + `public_key`)。新建群主标识以 `group_aid` 为准;`group_id` 仅作为兼容字段保留。
|
|
171
|
+
|
|
172
|
+
四种 SDK 的高层建群接口均支持崩溃恢复。命名群在 RPC 前持久化群密钥,并按 `group_name + public_key` 重放已提交结果;匿名群在 RPC 前持久化群密钥和创建上下文,重试会取回同一数字群并继续 `group_aid` 证书绑定与 `agent.md` 上传。群记录、群主成员、成员索引、入群设置、首个 `group.changed` 事件及匿名创建映射由服务端在同一数据库事务提交;证书服务和存储服务不参与该数据库事务,由 SDK pending 状态和服务端幂等重放恢复。
|
|
165
173
|
|
|
166
174
|
**参数**:
|
|
167
175
|
|
|
@@ -347,7 +355,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
|
|
|
347
355
|
|
|
348
356
|
### group.suspend
|
|
349
357
|
|
|
350
|
-
|
|
358
|
+
暂停群组。暂停期间 owner/admin 可以继续通过 `group.send`、`group.v2.send` 和 `group.thought.put` 发言;member 禁止发言,入群、邀请、申请审批等准入操作继续拒绝。需要 **admin 及以上**权限。
|
|
351
359
|
|
|
352
360
|
**参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
|
|
353
361
|
|
|
@@ -530,26 +538,72 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
|
|
|
530
538
|
}
|
|
531
539
|
```
|
|
532
540
|
|
|
533
|
-
### group.transfer_owner
|
|
534
|
-
|
|
535
|
-
|
|
541
|
+
### group.transfer_owner
|
|
542
|
+
|
|
543
|
+
发起两阶段群主转让。需要 owner 权限;该调用只记录待换钥状态,不会立即变更群主。新群主完成 `group.complete_transfer` 后,原 owner 才转为 admin。
|
|
536
544
|
|
|
537
545
|
**参数**:
|
|
538
546
|
|
|
539
547
|
| 参数 | 类型 | 必填 | 说明 |
|
|
540
|
-
|------|------|------|------|
|
|
541
|
-
| `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
|
|
542
|
-
| `
|
|
548
|
+
|------|------|------|------|
|
|
549
|
+
| `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
|
|
550
|
+
| `group_aid` | string | 否 | 群身份;高层 SDK 会查询并补齐 |
|
|
551
|
+
| `new_owner` | string | 是 | 新群主 AID(也接受 `aid`) |
|
|
552
|
+
| `transfer_auth` | object | 是 | 旧群主使用当前 group_aid 私钥签名的授权,包含 `nonce`、`issued_ms`、`signature` |
|
|
543
553
|
|
|
544
554
|
**响应**:
|
|
545
555
|
|
|
546
556
|
```json
|
|
547
|
-
{
|
|
548
|
-
"
|
|
549
|
-
"
|
|
550
|
-
"
|
|
551
|
-
}
|
|
552
|
-
|
|
557
|
+
{
|
|
558
|
+
"status": "pending_rekey",
|
|
559
|
+
"requires_ca_rekey": true,
|
|
560
|
+
"complete_rpc": "group.complete_transfer",
|
|
561
|
+
"group": { ... },
|
|
562
|
+
"group_id": "team.agentid.pub",
|
|
563
|
+
"group_aid": "team.agentid.pub",
|
|
564
|
+
"old_owner": "alice.agentid.pub",
|
|
565
|
+
"new_owner": "bob.agentid.pub",
|
|
566
|
+
"pending_owner_transfer": {
|
|
567
|
+
"status": "pending_rekey",
|
|
568
|
+
"old_owner": "alice.agentid.pub",
|
|
569
|
+
"new_owner": "bob.agentid.pub",
|
|
570
|
+
"group_aid": "team.agentid.pub",
|
|
571
|
+
"transfer_auth": { ... }
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
四语言 SDK 会在新群主在线收到 `owner_transfer_rekey_pending` 事件,或重连发现本地 pending 状态时自动尝试完成转让。发起方的高层转让方法返回上述 `pending_rekey`,不会等待新群主完成。Python / TypeScript / JavaScript 门面需要传入 `aid_store` / `aidStore` 才执行签名编排;Go 的高层发起入口为 `AUNClient.StartGroupTransfer`,`GroupFacade.TransferOwner` 当前是原始 RPC 门面。
|
|
577
|
+
|
|
578
|
+
### group.complete_transfer
|
|
579
|
+
|
|
580
|
+
由 pending 中的新群主完成群身份换钥和所有权切换。成功后响应状态为 `transferred`,新群主成为 owner,原群主转为 admin。
|
|
581
|
+
|
|
582
|
+
**参数**:
|
|
583
|
+
|
|
584
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
585
|
+
|------|------|------|------|
|
|
586
|
+
| `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
|
|
587
|
+
| `group_aid` | string | 否 | 群身份;高层 SDK 会查询并补齐 |
|
|
588
|
+
| `public_key` | string | 是 | 新 group_aid 公钥 DER base64(SPKI 格式) |
|
|
589
|
+
| `curve` | string | 否 | 曲线名称,默认 `P-256` |
|
|
590
|
+
| `transfer_accept` | object | 是 | 新群主使用自身 AID 私钥签名的接受证明,包含 `nonce`、`issued_ms`、`signature` |
|
|
591
|
+
|
|
592
|
+
**响应**:
|
|
593
|
+
|
|
594
|
+
```json
|
|
595
|
+
{
|
|
596
|
+
"status": "transferred",
|
|
597
|
+
"group": { ... },
|
|
598
|
+
"group_id": "team.agentid.pub",
|
|
599
|
+
"group_aid": "team.agentid.pub",
|
|
600
|
+
"old_owner": "alice.agentid.pub",
|
|
601
|
+
"new_owner": "bob.agentid.pub",
|
|
602
|
+
"aid_cert": { "cert": "-----BEGIN CERTIFICATE-----..." }
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
高层 SDK 会生成并暂存新群身份密钥,签名 `transfer_accept`,成功后导入新的 group_aid 身份;重复提交同一已完成转让时,服务端可幂等返回已完成结果。
|
|
553
607
|
|
|
554
608
|
### group.bind_group_aid
|
|
555
609
|
|
|
@@ -704,7 +758,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
|
|
|
704
758
|
}
|
|
705
759
|
```
|
|
706
760
|
|
|
707
|
-
### group.get_banlist
|
|
761
|
+
### group.get_banlist
|
|
708
762
|
|
|
709
763
|
获取封禁列表。需要 **admin 及以上**权限。
|
|
710
764
|
|
|
@@ -728,10 +782,88 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
|
|
|
728
782
|
"total": 1,
|
|
729
783
|
"page": 1,
|
|
730
784
|
"size": 200
|
|
731
|
-
}
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
|
|
785
|
+
}
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
禁言与屏蔽是两个独立状态,可以同时设置。禁言成员仍能接收群消息,但不能发送;屏蔽成员仍能发送群消息,但不再收到该群的实时消息 Push、离线消息 Push、Pull 或 E2EE wrap。
|
|
789
|
+
|
|
790
|
+
### group.block
|
|
791
|
+
|
|
792
|
+
屏蔽成员接收群消息。owner/admin 可以屏蔽其权限范围内的成员;所有成员都可以屏蔽自己。屏蔽只影响接收,不影响该成员向群内发送消息,也不改变已有禁言状态。
|
|
793
|
+
|
|
794
|
+
**参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`),`subject` 或 `aid`(string,必填;传入自己的 AID 即可屏蔽自己),`reason`(string,可选)。
|
|
795
|
+
|
|
796
|
+
**响应**:
|
|
797
|
+
|
|
798
|
+
```json
|
|
799
|
+
{
|
|
800
|
+
"group_id": "g-abc123.agentid.pub",
|
|
801
|
+
"group_aid": "g-abc123.agentid.pub",
|
|
802
|
+
"block": {
|
|
803
|
+
"group_id": "g-abc123.agentid.pub",
|
|
804
|
+
"subject": "bob.agentid.pub",
|
|
805
|
+
"blocked_by": "alice.agentid.pub",
|
|
806
|
+
"reason": "暂不接收群消息",
|
|
807
|
+
"created_at": 1234567890000
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
### group.unblock
|
|
813
|
+
|
|
814
|
+
取消屏蔽。owner/admin 可以取消其权限范围内成员的屏蔽;所有成员都可以取消自己的屏蔽。取消屏蔽不改变禁言状态。
|
|
815
|
+
|
|
816
|
+
**参数**:`group_id`(string,必填),`subject` 或 `aid`(string,必填;传入自己的 AID 即可取消自己的屏蔽)。
|
|
817
|
+
|
|
818
|
+
**响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "subject": "bob.agentid.pub", "status": "removed" }`
|
|
819
|
+
|
|
820
|
+
### group.get_blocklist
|
|
821
|
+
|
|
822
|
+
获取群屏蔽列表。需要 **admin 及以上**权限。
|
|
823
|
+
|
|
824
|
+
**参数**:`group_id`(string,必填)
|
|
825
|
+
|
|
826
|
+
**响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "items": [ ... ], "total": 1, "page": 1, "size": 1 }`
|
|
827
|
+
|
|
828
|
+
每个条目包含 `group_id`、`subject`、`blocked_by`、`reason` 和 `created_at`。
|
|
829
|
+
|
|
830
|
+
### group.report_status
|
|
831
|
+
|
|
832
|
+
上报当前成员在指定群内的在线状态和工作状态。调用者只能上报自己的状态;`updated_at` 由服务端记录。消息发送成功后,服务端独立维护该成员的 `last_message_at` 和 `last_payload_type`。
|
|
833
|
+
|
|
834
|
+
**参数**:`group_id`(string,必填),`online_status`(string,必填),`work_status`(string,必填)。
|
|
835
|
+
|
|
836
|
+
**响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "status": { ... } }`
|
|
837
|
+
|
|
838
|
+
### group.get_member_statuses
|
|
839
|
+
|
|
840
|
+
查询群内所有成员状态。调用者必须是群成员。响应始终以数组返回,并包含尚未上报状态的成员。
|
|
841
|
+
|
|
842
|
+
**参数**:`group_id`(string,必填)
|
|
843
|
+
|
|
844
|
+
**响应**:
|
|
845
|
+
|
|
846
|
+
```json
|
|
847
|
+
{
|
|
848
|
+
"group_id": "g-abc123.agentid.pub",
|
|
849
|
+
"group_aid": "g-abc123.agentid.pub",
|
|
850
|
+
"items": [
|
|
851
|
+
{
|
|
852
|
+
"group_id": "g-abc123.agentid.pub",
|
|
853
|
+
"aid": "alice.agentid.pub",
|
|
854
|
+
"online_status": "online",
|
|
855
|
+
"work_status": "busy",
|
|
856
|
+
"updated_at": 1234567890000,
|
|
857
|
+
"last_message_at": 1234567890123,
|
|
858
|
+
"last_payload_type": "text"
|
|
859
|
+
}
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
`online_status` 和 `work_status` 是成员上报值;未上报时为空字符串。`last_message_at` 为该成员在此群最后一条成功发送消息的时间,`last_payload_type` 为该消息的 `payload.type`;没有历史消息时分别为 `0` 和空字符串。
|
|
865
|
+
|
|
866
|
+
---
|
|
735
867
|
|
|
736
868
|
## 入群流程
|
|
737
869
|
|
|
@@ -1113,7 +1245,7 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
|
|
|
1113
1245
|
|
|
1114
1246
|
### group.send
|
|
1115
1247
|
|
|
1116
|
-
发送群消息。需要 member
|
|
1248
|
+
发送群消息。需要 member 权限。群为 `suspended` 时仅 owner/admin 可以发送,member 会被拒绝。
|
|
1117
1249
|
|
|
1118
1250
|
群消息的持久化 `mention_mode` 来自群设置,取值为 `"disabled"` / `"mention-only"`;服务端会写入消息对象并在 pull / push 中返回。运行时是否广播全员或分发给值班 Agent,由响应中的 `dispatch` / `message_dispatch` 描述。V2 加密消息把快照放在既有 `envelope_json` 元数据中,不改变 `per_device` 投递列。
|
|
1119
1251
|
|
|
@@ -1179,7 +1311,7 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
|
|
|
1179
1311
|
|
|
1180
1312
|
### group.thought.put
|
|
1181
1313
|
|
|
1182
|
-
写入某个发送者针对一个群上下文的思考内容。该内容不是普通群消息:服务端不分配消息 `seq`,不广播,不进入 `group.pull`,不需要 ack,也不持久化;只在内存中保留当前 head
|
|
1314
|
+
写入某个发送者针对一个群上下文的思考内容。该内容不是普通群消息:服务端不分配消息 `seq`,不广播,不进入 `group.pull`,不需要 ack,也不持久化;只在内存中保留当前 head。群为 `suspended` 时仅 owner/admin 可以写入,member 会被拒绝。
|
|
1183
1315
|
|
|
1184
1316
|
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 连接级身份语义携带。
|
|
1185
1317
|
|
|
@@ -1502,7 +1634,7 @@ SDK Group FS 门面使用票据执行 HTTP GET 并校验 sha256。应用自行
|
|
|
1502
1634
|
|
|
1503
1635
|
### group.fs.create_upload_session
|
|
1504
1636
|
|
|
1505
|
-
创建上传会话。参数同 `check_upload
|
|
1637
|
+
创建上传会话。参数同 `check_upload`。响应透传 Storage session 字段并增加 Group FS 路径视图,包含 `upload_url`、`content_type`、`size_bytes` 等;当前 Storage 服务不返回 `session_id` 或 `headers`。四个 SDK 的 Group FS 门面会按实际字节识别 MIME,并在 session、HTTP PUT 与 complete 中保持 `Content-Type` 一致;若 session 返回 headers,SDK 保留其它 header 并替换其中的 Content-Type,避免 OSS 签名不一致导致 403。
|
|
1506
1638
|
|
|
1507
1639
|
### group.fs.complete_upload
|
|
1508
1640
|
|
|
@@ -1805,8 +1937,9 @@ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x
|
|
|
1805
1937
|
| `member_added` | 成员加入 |
|
|
1806
1938
|
| `member_left` | 成员退出 |
|
|
1807
1939
|
| `member_removed` | 成员被踢出 |
|
|
1808
|
-
| `role_changed` | 角色变更 |
|
|
1809
|
-
| `
|
|
1940
|
+
| `role_changed` | 角色变更 |
|
|
1941
|
+
| `owner_transfer_rekey_pending` | 群主转让已发起,等待新群主完成群身份换钥 |
|
|
1942
|
+
| `owner_transferred` | 群主转让 |
|
|
1810
1943
|
| `rules_updated` | 规则更新 |
|
|
1811
1944
|
| `announcement_updated` | 公告更新 |
|
|
1812
1945
|
| `join_requested` | 收到入群申请 |
|
|
@@ -1817,8 +1950,10 @@ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x
|
|
|
1817
1950
|
| `invite_code_created` | 邀请码创建 |
|
|
1818
1951
|
| `invite_code_used` | 邀请码使用 |
|
|
1819
1952
|
| `invite_code_revoked` | 邀请码撤销 |
|
|
1820
|
-
| `member_banned` | 成员封禁 |
|
|
1821
|
-
| `member_unbanned` | 成员解封 |
|
|
1953
|
+
| `member_banned` | 成员封禁 |
|
|
1954
|
+
| `member_unbanned` | 成员解封 |
|
|
1955
|
+
| `member_blocked` | 成员被屏蔽 |
|
|
1956
|
+
| `member_unblocked` | 成员取消屏蔽 |
|
|
1822
1957
|
| `suspended` | 群组暂停 |
|
|
1823
1958
|
| `resumed` | 群组恢复 |
|
|
1824
1959
|
| `dissolved` | 群组解散 |
|
|
@@ -2017,6 +2152,3 @@ Group 服务定义了以下专用错误码(-33xxx 段):
|
|
|
2017
2152
|
| -33009 | Resource request not found | 检查 request_id |
|
|
2018
2153
|
|
|
2019
2154
|
> SDK 客户端将 -33001 映射为 `GroupNotFoundError`,-33002~-33003 映射为 `GroupStateError`,其余映射为 `GroupError`。未识别的错误码 fallback 到 `AUNError`。
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
@@ -61,8 +61,10 @@ P2P `message.*` 的最终投递语义由连接阶段声明的 `delivery_mode`
|
|
|
61
61
|
"jsonrpc": "2.0",
|
|
62
62
|
"method": "message.send",
|
|
63
63
|
"params": {
|
|
64
|
-
"to": "bob.agentid.pub",
|
|
65
|
-
"
|
|
64
|
+
"to": "bob.agentid.pub",
|
|
65
|
+
"device_id": "bob-phone",
|
|
66
|
+
"ttl": 300,
|
|
67
|
+
"payload": {"type": "text", "text": "Hello!"},
|
|
66
68
|
"encrypted": false,
|
|
67
69
|
"message_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
68
70
|
"timestamp": 1234567890000
|
|
@@ -75,16 +77,23 @@ P2P `message.*` 的最终投递语义由连接阶段声明的 `delivery_mode`
|
|
|
75
77
|
|
|
76
78
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
77
79
|
|------|------|------|--------|------|
|
|
78
|
-
| `to` | string | 是 | — | 接收方 AID |
|
|
79
|
-
| `
|
|
80
|
+
| `to` | string | 是 | — | 接收方 AID |
|
|
81
|
+
| `device_id` | string | 否 | — | 目标接收设备。非空时仅投递该设备;未指定时按接收方 AID 投递全部设备 |
|
|
82
|
+
| `to_device_id` | string | 否 | — | `device_id` 的兼容别名;两者均非空时以 `device_id` 为准 |
|
|
83
|
+
| `ttl` | integer | 否 | `0` | 秒。`ttl <= 0` 持久化;`ttl > 0` 钳制到 1–3600 秒并只保存在消息服务内存中 |
|
|
84
|
+
| `payload` | object | 是 | — | 消息内容(任意 JSON 对象) |
|
|
80
85
|
| `type` | string | 否 | — | 信封/封装类型,普通业务消息无需填写;SDK V2 加密发送时自动使用 `e2ee.p2p_encrypted` |
|
|
81
86
|
| `encrypted` | boolean | 否 | `false` | 底层 RPC 的 E2EE 标记。Python SDK 便捷层通常使用 `encrypt` 入参并由 SDK 自动填充此字段 |
|
|
82
87
|
| `message_id` | string | 否 | — | 幂等键(客户端提供或服务端生成 UUID) |
|
|
83
88
|
| `timestamp` | integer | 否 | — | 客户端时间戳(毫秒)。**服务端忽略此字段,始终使用服务端时间** |
|
|
84
89
|
| `protected_headers` / `headers` | object | 否 | — | SDK 加密前读取的 E2EE 信封元数据,类似 HTTP headers;推荐使用 `protected_headers`,`headers` 仅作为兼容别名;服务端不解释,接收端验 `_auth` 后在 `e2ee.protected_headers` 暴露 |
|
|
85
90
|
|
|
86
|
-
> 连接级 `delivery_mode` 在 `auth.connect` 阶段声明,结构见 `02-WebSocket协议.md`。Python SDK 的 P2P 消息发送会沿用当前连接的 `delivery_mode`,应用层发送时无需重复指定。
|
|
87
|
-
> `protected_headers` 只在 SDK 加密路径生效;裸 RPC 发送明文或已加密信封时,调用方需自行遵守 [05-E2EE加密通信](05-E2EE加密通信.md#protectedheaders-与可验证上下文) 的格式和校验规则。
|
|
91
|
+
> 连接级 `delivery_mode` 在 `auth.connect` 阶段声明,结构见 `02-WebSocket协议.md`。Python SDK 的 P2P 消息发送会沿用当前连接的 `delivery_mode`,应用层发送时无需重复指定。
|
|
92
|
+
> `protected_headers` 只在 SDK 加密路径生效;裸 RPC 发送明文或已加密信封时,调用方需自行遵守 [05-E2EE加密通信](05-E2EE加密通信.md#protectedheaders-与可验证上下文) 的格式和校验规则。
|
|
93
|
+
|
|
94
|
+
`message.send.device_id` 表示接收目标,不是发送方设备,也不同于 `message.pull` / `message.ack` 中表示当前消费实例的 `device_id`。指定目标设备时,SDK 的 V2 加密信封只选择该设备对应的 peer wrap(AID scope 使用对应 AID wrap),同时保留发送方 self-sync 和监管 audit wrap。目标设备不存在或不可用时发送失败,不会降级为 AID 全设备广播。
|
|
95
|
+
|
|
96
|
+
`ttl` 与连接级 `delivery_mode` 相互独立。正 TTL 消息不写数据库或 WAL、不分配持久 `seq`;跨域只转发剩余 TTL,目标域不会重新执行 1 秒下限钳制。
|
|
88
97
|
|
|
89
98
|
### Payload 参考约定
|
|
90
99
|
|
|
@@ -117,17 +126,24 @@ P2P `message.*` 的最终投递语义由连接阶段声明的 `delivery_mode`
|
|
|
117
126
|
|
|
118
127
|
| 字段 | 类型 | 说明 |
|
|
119
128
|
|------|------|------|
|
|
120
|
-
| `message_id` | string | 消息 ID |
|
|
121
|
-
| `
|
|
129
|
+
| `message_id` | string | 消息 ID |
|
|
130
|
+
| `storage` | string | `persistent` 或 `volatile`;旧服务端未返回时按 `persistent` 处理 |
|
|
131
|
+
| `seq` | integer | 持久消息的接收方收件箱序号;volatile 消息不返回 |
|
|
132
|
+
| `volatile_cursor` | string | volatile 消息的 opaque 游标;不得解析 |
|
|
133
|
+
| `volatile_cursors` | string[] | 未指定目标设备且投递多个设备时的 volatile 游标列表 |
|
|
134
|
+
| `created_at` | integer | volatile 消息的服务端创建时间(毫秒) |
|
|
135
|
+
| `expires_at` | integer | volatile 消息的服务端过期时间(毫秒) |
|
|
122
136
|
| `timestamp` | integer | 服务端时间戳(毫秒) |
|
|
123
|
-
| `status` | string | `"sent"` / `"delivered"` / `"duplicate"` |
|
|
137
|
+
| `status` | string | `"sent"` / `"delivered"` / `"accepted"` / `"duplicate"` |
|
|
124
138
|
| `delivery_mode` | string | 最终生效的连接级投递语义:`fanout` 或 `queue` |
|
|
125
139
|
| `envelope` | object | SDK 回填的发送结果信封,包含发送方、接收方、业务类型、时间戳、加密标志、protected headers 等可转发元数据 |
|
|
126
140
|
| `payload` | object | SDK 回填的应用层业务 payload;裸 RPC 或内部 `_skip_send_result_envelope` 路径可能没有该字段 |
|
|
127
141
|
| `cross_domain` | boolean | 仅跨域投递时出现,当前值为 `true` |
|
|
128
142
|
| `target_issuer` | string | 仅跨域投递时出现,表示目标 issuer |
|
|
129
143
|
|
|
130
|
-
> **duplicate 响应**:当 `message_id` 重复时,若服务端仍缓存首次结果,返回完整首次响应并附加 `"status": "duplicate"`;若缓存已过期,仅返回 `message_id`、`timestamp`、`status`,**不含** `seq` 和 `delivery_mode`。客户端收到 `"duplicate"` 状态时应视为幂等成功,无需重试。
|
|
144
|
+
> **duplicate 响应**:当 `message_id` 重复时,若服务端仍缓存首次结果,返回完整首次响应并附加 `"status": "duplicate"`;若缓存已过期,仅返回 `message_id`、`timestamp`、`status`,**不含** `seq` 和 `delivery_mode`。客户端收到 `"duplicate"` 状态时应视为幂等成功,无需重试。
|
|
145
|
+
|
|
146
|
+
volatile 成功响应以 `storage="volatile"`、`volatile_cursor`(多设备时还可含 `volatile_cursors`)、`created_at`、`expires_at` 和 `status="accepted"` 表示,不含 `seq`。到期或服务重启后消息允许丢失。
|
|
131
147
|
|
|
132
148
|
### 错误
|
|
133
149
|
|
|
@@ -136,16 +152,18 @@ P2P `message.*` 的最终投递语义由连接阶段声明的 `delivery_mode`
|
|
|
136
152
|
| -32002 | 服务暂不可用(如数据库未连接、服务证书未加载) |
|
|
137
153
|
| -32603 | 参数缺失(to 或 payload) |
|
|
138
154
|
| -32603 | payload 超过大小限制(默认 1 MB) |
|
|
139
|
-
| -32603 | 目标 AID 不存在 |
|
|
140
|
-
| -32603 |
|
|
155
|
+
| -32603 | 目标 AID 不存在 |
|
|
156
|
+
| -32603 | 指定的目标设备不存在、未注册或 V2 bootstrap 中不可用 |
|
|
157
|
+
| -32603 | 频率限制超限 |
|
|
141
158
|
|
|
142
159
|
### 示例
|
|
143
160
|
|
|
144
161
|
```python
|
|
145
|
-
result = await client.call("message.send", {
|
|
146
|
-
"to": "bob.agentid.pub",
|
|
147
|
-
"
|
|
148
|
-
}
|
|
162
|
+
result = await client.call("message.send", {
|
|
163
|
+
"to": "bob.agentid.pub",
|
|
164
|
+
"device_id": "bob-phone",
|
|
165
|
+
"payload": {"type": "text", "text": "Hello!"},
|
|
166
|
+
})
|
|
149
167
|
# result: {"message_id": "...", "seq": 42, "status": "delivered", ...}
|
|
150
168
|
```
|
|
151
169
|
|
|
@@ -278,7 +296,7 @@ result = await client.call("message.thought.get", {
|
|
|
278
296
|
|
|
279
297
|
## message.pull
|
|
280
298
|
|
|
281
|
-
|
|
299
|
+
按两个独立游标增量拉取持久消息和 volatile 消息。volatile 消息不进入持久 `seq` 空间。
|
|
282
300
|
|
|
283
301
|
### 请求
|
|
284
302
|
|
|
@@ -287,10 +305,10 @@ result = await client.call("message.thought.get", {
|
|
|
287
305
|
"jsonrpc": "2.0",
|
|
288
306
|
"method": "message.pull",
|
|
289
307
|
"params": {
|
|
290
|
-
"after_seq": 100,
|
|
291
|
-
"
|
|
292
|
-
"
|
|
293
|
-
"
|
|
308
|
+
"after_seq": 100,
|
|
309
|
+
"after_volatile_cursor": "v1:i1:7:20",
|
|
310
|
+
"limit": 50,
|
|
311
|
+
"device_id": "device-001"
|
|
294
312
|
},
|
|
295
313
|
"id": 2
|
|
296
314
|
}
|
|
@@ -300,12 +318,12 @@ result = await client.call("message.thought.get", {
|
|
|
300
318
|
|
|
301
319
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
302
320
|
|------|------|------|--------|------|
|
|
303
|
-
| `after_seq` | integer | 否 | 0 | 拉取 seq > after_seq 的消息 |
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
|
|
308
|
-
> 四个 SDK
|
|
321
|
+
| `after_seq` | integer | 否 | 0 | 拉取 seq > after_seq 的消息 |
|
|
322
|
+
| `after_volatile_cursor` | string | 否 | SDK 当前游标 | 拉取该 opaque volatile 游标之后的消息;应用通常无需传入 |
|
|
323
|
+
| `limit` | integer | 否 | 50 | 单次返回上限(最大 50;`pull_max_limit` 配置只能在 1-50 内进一步收紧) |
|
|
324
|
+
| `device_id` | string | 否 | 当前连接实例 | 多实例消费上下文中的设备标识 |
|
|
325
|
+
|
|
326
|
+
> 四个 SDK 自动管理 `after_volatile_cursor`,并在传输层注入当前消费实例的内部 slot。slot 不属于应用参数,也不会出现在消息、响应或事件中。
|
|
309
327
|
|
|
310
328
|
### 响应
|
|
311
329
|
|
|
@@ -336,9 +354,13 @@ result = await client.call("message.thought.get", {
|
|
|
336
354
|
|
|
337
355
|
| 字段 | 类型 | 说明 |
|
|
338
356
|
|------|------|------|
|
|
339
|
-
| `messages` | array |
|
|
357
|
+
| `messages` | array | 持久与 volatile 消息按服务端时间合并;持久消息子序列仍按 `seq` 升序。消息对象含 `encrypted` 字段(仅 `encrypted=true` 时出现) |
|
|
340
358
|
| `count` | integer | 本次返回的消息数 |
|
|
341
|
-
| `latest_seq` | integer | 返回的最大 seq |
|
|
359
|
+
| `latest_seq` | integer | 返回的最大 seq |
|
|
360
|
+
| `latest_volatile_cursor` | string\|null | 本页最后一个 volatile 游标;不影响 `latest_seq` |
|
|
361
|
+
| `volatile_has_more` | boolean | 是否仍有未返回的 volatile 消息;SDK 在 volatile cursor 前进时据此继续分页 |
|
|
362
|
+
| `volatile_earliest_cursor` | string\|null | 当前 boot epoch 内仍可读取的最早 volatile 游标 |
|
|
363
|
+
| `volatile_dropped_count` | integer | 当前 boot epoch 内因过期或容量淘汰而不可读的累计数 |
|
|
342
364
|
| `server_ack_seq` | integer | 服务端已确认的 ack_seq(仅设备视图路径返回)。客户端用此值跳过 retention window 之外的空洞 |
|
|
343
365
|
| `retention_floor_seq` | integer | 持久化保留窗口的下界 seq;seq 小于等于此值的消息已过期不可再拉取 |
|
|
344
366
|
| `earliest_available_seq` | integer\|null | 当前可拉取的最小 seq(`retention_floor_seq + 1`);`retention_floor_seq=0` 时为 `null` |
|
|
@@ -347,6 +369,8 @@ result = await client.call("message.thought.get", {
|
|
|
347
369
|
|
|
348
370
|
`message.pull` 是公开的 Forward Pull。实时 A/T/H 最新页同步由 SDK 内部自动完成,不提供需要应用传入的模式参数。Forward 页通过结构校验后,本地 A 按原始页最大 seq 推进。页内缺号视为服务端永久空号;单条解密失败通过 `message.undecryptable` 报告,不阻塞后续水位。Forward 仍支持 Piggy ACK:存在待提交 ACK 时,即使当前页非满页也会再拉一页并携带 ACK,空页后停止。
|
|
349
371
|
|
|
372
|
+
四个 SDK 只让含正 `seq` 的持久消息进入 seq tracker。volatile push 与 pull 在进程内按发送方和 `message_id` 去重,成功交付后自动 ACK;epoch 不匹配时清空本地 volatile 游标并重试一次。`message.history` 永远不返回 volatile 消息。
|
|
373
|
+
|
|
350
374
|
`message.pull` 与 `message.history` 进入当前 `AUNClient` 的客户端级 Pull Gate。该 Gate 与 Group Message、Group Event Pull 共享,始终 single-inflight;相同请求 key 折叠并共享结果,不同 key 按前台 FIFO(Tail/History)优先于后台 FIFO(Forward/Gap Fill/Group Event)排队。不同 `AUNClient` 实例之间不共享 Gate,应用层无需自行实现并发控制。
|
|
351
375
|
|
|
352
376
|
解密当前消息时若缺少 sender IK,SDK 会把同发送端请求 single-flight 合并,最多同步等待 3 秒执行 bootstrap;获取成功立即重试当前消息,失败或超时才进入 pending。该补救不改变 Forward 按原始页推进 A 的规则。
|
|
@@ -395,7 +419,7 @@ while page.get("has_older"):
|
|
|
395
419
|
|
|
396
420
|
## message.ack
|
|
397
421
|
|
|
398
|
-
|
|
422
|
+
确认已收到消息。持久 ACK 与 volatile ACK 可以单独提交,也可以在同一请求中提交。
|
|
399
423
|
|
|
400
424
|
### 请求
|
|
401
425
|
|
|
@@ -404,9 +428,9 @@ while page.get("has_older"):
|
|
|
404
428
|
"jsonrpc": "2.0",
|
|
405
429
|
"method": "message.ack",
|
|
406
430
|
"params": {
|
|
407
|
-
"seq": 150,
|
|
408
|
-
"
|
|
409
|
-
"
|
|
431
|
+
"seq": 150,
|
|
432
|
+
"volatile_cursors": ["v1:i1:7:21"],
|
|
433
|
+
"device_id": "device-001"
|
|
410
434
|
},
|
|
411
435
|
"id": 3
|
|
412
436
|
}
|
|
@@ -416,11 +440,13 @@ while page.get("has_older"):
|
|
|
416
440
|
|
|
417
441
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
418
442
|
|------|------|------|--------|------|
|
|
419
|
-
| `seq` | integer |
|
|
420
|
-
| `
|
|
421
|
-
| `
|
|
422
|
-
|
|
423
|
-
|
|
443
|
+
| `seq` | integer | 否 | — | 确认 seq ≤ 此值的所有持久消息;未提交 volatile ACK 时必填 |
|
|
444
|
+
| `volatile_cursor` | string | 否 | — | 单个 volatile 游标的兼容形式 |
|
|
445
|
+
| `volatile_cursors` | string[] | 否 | — | 确认指定 volatile 游标;可独立于 `seq` 使用 |
|
|
446
|
+
| `volatile_ids` | string[] | 否 | — | 按 `message_id` 确认 volatile 消息 |
|
|
447
|
+
| `device_id` | string | 否 | 当前连接实例 | 多实例消费上下文中的设备标识 |
|
|
448
|
+
|
|
449
|
+
> 四个 SDK 在传输层注入当前消费实例的内部 slot;应用不传入或读取 slot。
|
|
424
450
|
|
|
425
451
|
### 响应
|
|
426
452
|
|
|
@@ -437,8 +463,9 @@ while page.get("has_older"):
|
|
|
437
463
|
|
|
438
464
|
| 字段 | 类型 | 说明 |
|
|
439
465
|
|------|------|------|
|
|
440
|
-
| `success` | boolean | 操作是否成功 |
|
|
441
|
-
| `ack_seq` | integer | 本次推进到的 ack_seq |
|
|
466
|
+
| `success` | boolean | 操作是否成功 |
|
|
467
|
+
| `ack_seq` | integer | 本次推进到的 ack_seq |
|
|
468
|
+
| `volatile_ack` | object | volatile ACK 的 `accepted`、`expired` 等幂等结果;只提交持久 ACK 时可省略 |
|
|
442
469
|
|
|
443
470
|
### 副作用
|
|
444
471
|
|
|
@@ -574,7 +601,8 @@ result = await client.call("message.ack", {"seq": 150})
|
|
|
574
601
|
"encrypted": false
|
|
575
602
|
},
|
|
576
603
|
"message_id": "uuid-1",
|
|
577
|
-
"from": "alice.agentid.pub",
|
|
604
|
+
"from": "alice.agentid.pub",
|
|
605
|
+
"sender_device_id": "alice-phone",
|
|
578
606
|
"to": "bob.agentid.pub",
|
|
579
607
|
"seq": 42,
|
|
580
608
|
"timestamp": 1234567890000,
|
|
@@ -594,7 +622,9 @@ result = await client.call("message.ack", {"seq": 150})
|
|
|
594
622
|
}
|
|
595
623
|
```
|
|
596
624
|
|
|
597
|
-
SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;信封字段统一放在 `envelope`。`envelope` 只保留可转发的归一化元数据,`from` 由 `from_aid` / `sender_aid` 归一化而来,`timestamp` 由 `created_at` / `t_server` 归一化而来。0.5.x 当前仍保留顶层 `message_id` / `from` / `to` / `seq` / `timestamp` 等兼容别名;新代码应优先通过 `msg["envelope"]["from"]`、`msg["envelope"]["timestamp"]` 等路径访问。`envelope.agent_md.sender` / `envelope.agent_md.group` 是 agent.md 云端版本提示,SDK 会自动观察并写入本地 `remote_etag`。Gateway 可能附加 `proximity` 及 `same_device` / `same_egress_ip` / `same_network`,表示由 Gateway 基于连接上下文判断的近端关系提示,不参与 E2EE AAD 或业务鉴权。
|
|
625
|
+
SDK 交付给应用层的 `payload` 是明文业务 JSON 对象;信封字段统一放在 `envelope`。`sender_device_id` 是发送方设备标识,四个 SDK 均会保留给应用层,可用于把回复定向到原发送设备。`envelope` 只保留可转发的归一化元数据,`from` 由 `from_aid` / `sender_aid` 归一化而来,`timestamp` 由 `created_at` / `t_server` 归一化而来。0.5.x 当前仍保留顶层 `message_id` / `from` / `to` / `seq` / `timestamp` 等兼容别名;新代码应优先通过 `msg["envelope"]["from"]`、`msg["envelope"]["timestamp"]` 等路径访问。`envelope.agent_md.sender` / `envelope.agent_md.group` 是 agent.md 云端版本提示,SDK 会自动观察并写入本地 `remote_etag`。Gateway 可能附加 `proximity` 及 `same_device` / `same_egress_ip` / `same_network`,表示由 Gateway 基于连接上下文判断的近端关系提示,不参与 E2EE AAD 或业务鉴权。
|
|
626
|
+
|
|
627
|
+
volatile 事件额外包含 `storage="volatile"`、`volatile_cursor`、`created_at` 和 `expires_at`,不含持久 `seq`。四个 SDK 保留这些字段、自动去重和 ACK,并确保应用可见对象不含内部 slot。
|
|
598
628
|
|
|
599
629
|
### 订阅
|
|
600
630
|
|
|
@@ -120,7 +120,11 @@
|
|
|
120
120
|
|
|
121
121
|
## SDK 封装状态
|
|
122
122
|
|
|
123
|
-
Python / Go / TypeScript / JavaScript SDK 均提供 storage low-level 与 VFS 门面。普通应用优先使用 SDK VFS:`write_bytes` / `upload_file` 会先 `check_upload`,小对象走 `put_object`,大对象走 `create_upload_session` → HTTP PUT → `complete_upload`,秒传路径用 `complete_upload(skip_blob=true)`;`read_bytes` / `download_file` 优先尝试 inline `get_object`,超限时回退 `create_download_ticket`;`touch` 直接封装 `storage.fs.touch`。需要精确控制 ACL、token、软链、卷、批量操作或 URL 字段时,再直接调用本手册中的 `storage.*` RPC。
|
|
123
|
+
Python / Go / TypeScript / JavaScript SDK 均提供 storage low-level 与 VFS 门面。普通应用优先使用 SDK VFS:`write_bytes` / `upload_file` 会先 `check_upload`,小对象走 `put_object`,大对象走 `create_upload_session` → HTTP PUT → `complete_upload`,秒传路径用 `complete_upload(skip_blob=true)`;`read_bytes` / `download_file` 优先尝试 inline `get_object`,超限时回退 `create_download_ticket`;`touch` 直接封装 `storage.fs.touch`。需要精确控制 ACL、token、软链、卷、批量操作或 URL 字段时,再直接调用本手册中的 `storage.*` RPC。
|
|
124
|
+
|
|
125
|
+
四个 SDK 的 VFS 会优先按实际字节识别 PNG、JPEG、GIF、BMP、WebP、PDF、gzip、ZIP、MP4、JSON、HTML 和 UTF-8 文本,再回退文件扩展名及 `application/octet-stream`。大文件上传时,`create_upload_session`、HTTP PUT 和 `complete_upload` 使用同一个 `Content-Type`;如果 session 响应额外提供 `headers`,SDK 会保留其它 header 并以实际识别结果替换其中的 Content-Type。OSS 预签名 PUT 会把 Content-Type 纳入签名校验,缺失或不一致时可直接返回 403。
|
|
126
|
+
|
|
127
|
+
直接调用底层 RPC 的高级客户端必须自行完成相同编排:先确定内容类型,再把同一个值传给 session 和 complete,并在 PUT 请求中发送一致的 `Content-Type`。绕过 VFS 后未遵守该约束属于调用方式错误。
|
|
124
128
|
|
|
125
129
|
## storage.put_object
|
|
126
130
|
|
|
@@ -561,22 +565,27 @@ for obj in result["items"]:
|
|
|
561
565
|
|
|
562
566
|
### 响应
|
|
563
567
|
|
|
564
|
-
| 字段 | 类型 | 说明 |
|
|
565
|
-
|------|------|------|
|
|
566
|
-
| `upload_url` | string | 上传用 presigned URL |
|
|
567
|
-
| `
|
|
568
|
-
| `
|
|
569
|
-
| `
|
|
570
|
-
| `
|
|
571
|
-
| `
|
|
572
|
-
| `
|
|
573
|
-
| `
|
|
574
|
-
|
|
575
|
-
|
|
568
|
+
| 字段 | 类型 | 说明 |
|
|
569
|
+
|------|------|------|
|
|
570
|
+
| `upload_url` | string | 上传用 presigned URL |
|
|
571
|
+
| `expire_at` | integer | URL 过期时间戳 |
|
|
572
|
+
| `owner_aid` | string | 所有者 AID |
|
|
573
|
+
| `bucket` | string | 存储桶 |
|
|
574
|
+
| `object_key` | string | 对象路径 |
|
|
575
|
+
| `name` | string | 对象名称 |
|
|
576
|
+
| `path` | string | 对象路径 |
|
|
577
|
+
| `path_url` | string | Storage path URL |
|
|
578
|
+
| `url` / `download_url` | string | AID 风格对象 URL |
|
|
579
|
+
| `logical_url` | string | Storage 直链 URL |
|
|
580
|
+
| `content_type` | string | MIME 类型 |
|
|
581
|
+
| `size_bytes` | integer | 声明的文件大小 |
|
|
582
|
+
| `overwrite` | boolean | 是否覆盖已有对象 |
|
|
583
|
+
|
|
584
|
+
客户端获得 `upload_url` 后,通过 HTTP PUT 上传文件数据。当前服务响应不包含 `blob_key`、`session_id` 或 `headers`;调用方不得依赖这些字段。
|
|
576
585
|
|
|
577
586
|
> 当前实现会对 BlobStore 返回的 loopback URL 做对外地址规范化:优先使用 `KITE_STORAGE_EXTERNAL_URL`,否则按 `storage.{issuer}` 形式改写。对外地址不可使用 `127.0.0.1` 或 `localhost`。
|
|
578
587
|
|
|
579
|
-
>
|
|
588
|
+
> 当前实现会在 `create_upload_session` 阶段按声明的 `size_bytes` 校验最大文件限制;实际 blob 大小、SHA-256 和配额在 `storage.complete_upload` 阶段校验。
|
|
580
589
|
|
|
581
590
|
---
|
|
582
591
|
|