@agentunion/fastaun-browser 0.5.18 → 0.5.20
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 +172 -79
- package/_packed_docs/CHANGELOG.md +172 -79
- package/_packed_docs/INDEX.md +244 -116
- package/_packed_docs/KITE_DOCS_GUIDE.md +98 -69
- package/_packed_docs/agent.md/SCHEMA.md +245 -205
- package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +11 -11
- 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 +42 -15
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +4 -4
- package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +45 -134
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1072 -1072
- package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +5 -20
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +687 -668
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +19 -28
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +443 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.0.md +161 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +658 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2113.0.md +233 -0
- package/_packed_docs/protocol/agent.md/SCHEMA.md +4 -0
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +1 -1
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +68 -61
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +279 -285
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +3 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +271 -235
- package/_packed_docs/sdk/09-message-rpc-manual.md +47 -6
- package/_packed_docs/sdk/09-storage-rpc-manual.md +70 -68
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +63 -34
- package/_packed_docs/sdk/INDEX.md +105 -34
- package/_packed_docs/sdk/Ownership-SDK/345/256/236/347/216/260/346/214/207/345/215/227.md +169 -0
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/227.md +349 -0
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +922 -0
- package/_packed_docs/sdk/Ownership-SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +270 -0
- package/_packed_docs/sdk/Ownership2.1-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +300 -0
- package/_packed_docs/sdk/Ownership2.1-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +382 -0
- package/_packed_docs/sdk/Ownership2.1-TDD/345/210/206/351/230/266/346/256/265/345/256/236/346/226/275/350/256/241/345/210/222.md +708 -0
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +476 -0
- package/_packed_docs/sdk/Ownership/347/256/241/347/220/206/344/270/223/351/242/230.md +559 -0
- package/_packed_docs/sdk/ProtectedHeaders/347/224/250/346/263/225/344/270/223/351/242/230.md +299 -0
- package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +173 -0
- package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +211 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/345/256/236/347/216/260/347/247/273/346/244/215/346/214/207/345/215/227.md +331 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +207 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/344/273/243/347/240/201/345/256/241/346/237/245/346/212/245/345/221/212.md +252 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/345/256/236/346/226/275/350/256/241/345/210/222.md +156 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/346/226/271/346/241/210.md +273 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/350/257/246/347/273/206/350/256/276/350/256/241.md +211 -0
- package/dist/agent-md-schema.d.ts +17 -3
- package/dist/agent-md-schema.d.ts.map +1 -1
- package/dist/agent-md-schema.js +94 -26
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +54 -3
- package/dist/agent-md.d.ts.map +1 -1
- package/dist/agent-md.js +711 -65
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +58 -46
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +254 -248
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.d.ts +4 -1
- package/dist/aid.d.ts.map +1 -1
- package/dist/aid.js +27 -33
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts +4 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +426 -39
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +38179 -32054
- package/dist/cert-utils.d.ts +50 -2
- package/dist/cert-utils.d.ts.map +1 -1
- package/dist/cert-utils.js +105 -47
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +22 -1
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +389 -78
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +103 -77
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +1 -0
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +182 -89
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +100 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1220 -25
- package/dist/client.js.map +1 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +8 -6
- package/dist/crypto.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -2
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +9 -2
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +72 -13
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts +82 -2
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +100 -6
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +17 -0
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.d.ts +10 -1
- package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.js +111 -0
- package/dist/keystore/indexeddb-shared.js.map +1 -1
- package/dist/keystore/indexeddb-token-store.d.ts +7 -1
- package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-token-store.js +30 -1
- package/dist/keystore/indexeddb-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +98 -0
- package/dist/org-protocol.d.ts.map +1 -0
- package/dist/org-protocol.js +1802 -0
- package/dist/org-protocol.js.map +1 -0
- package/dist/ownership-proof.d.ts +93 -5
- package/dist/ownership-proof.d.ts.map +1 -1
- package/dist/ownership-proof.js +239 -53
- package/dist/ownership-proof.js.map +1 -1
- package/dist/ownership-v21.d.ts +194 -0
- package/dist/ownership-v21.d.ts.map +1 -0
- package/dist/ownership-v21.js +678 -0
- package/dist/ownership-v21.js.map +1 -0
- package/dist/ownership-workflow.d.ts +151 -0
- package/dist/ownership-workflow.d.ts.map +1 -0
- package/dist/ownership-workflow.js +1229 -0
- package/dist/ownership-workflow.js.map +1 -0
- package/dist/seq-tracker.d.ts +1 -0
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +10 -2
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +83 -0
- package/dist/tools/cross-sdk-agent.d.ts.map +1 -1
- package/dist/tools/cross-sdk-agent.js +415 -7
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +7 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +90 -2
- package/dist/transport.js.map +1 -1
- package/dist/v2/e2ee/decrypt.d.ts +1 -0
- package/dist/v2/e2ee/decrypt.d.ts.map +1 -1
- package/dist/v2/e2ee/decrypt.js +9 -1
- package/dist/v2/e2ee/decrypt.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- [AIDStore](#aidstore)
|
|
8
8
|
- [AID](#aid)
|
|
9
9
|
- [AUNClient](#aunclient)
|
|
10
|
+
- [业务门面](#业务门面)
|
|
10
11
|
- [事件](#事件)
|
|
11
12
|
- [ServiceProxyClient](#serviceproxyclient)
|
|
12
13
|
- [E2EE 高级 API](#e2ee-高级-api)
|
|
@@ -62,57 +63,33 @@ store := aun.NewAIDStore(aunPath, encryptionSeed, aun.AIDStoreOptions{
|
|
|
62
63
|
|
|
63
64
|
| Python | TS/JS | Go | 说明 |
|
|
64
65
|
|--------|-------|----|------|
|
|
65
|
-
| `load(aid)` | `load(aid)` | `Load(aid)` | 从本地加载 AID |
|
|
66
|
-
| `register(aid)` | `register(aid)` | `Register(ctx, aid)` |
|
|
67
|
-
| `
|
|
68
|
-
| `bind_aid(params)` | `bindAid(params)` | `BindAID(ctx, params)` | 已有证书的 legacy/unbound 关系绑定 |
|
|
69
|
-
| `get_aid_binding_status(aid)` | `getAidBindingStatus(aid)` | `GetAIDBindingStatus(ctx, aid)` | 查询绑定状态 |
|
|
70
|
-
| `resume_aid_binding(operation_id)` | `resumeAidBinding(operation_id)` | `ResumeAIDBinding(ctx, operationID, aid...)` | 查询 operation 并恢复激活 |
|
|
71
|
-
| `change_owner(params)` | `changeOwner(params)` | `ChangeOwner(ctx, params)` | 三方换 owner 编排 |
|
|
72
|
-
| `list()` | `list()` | `List()` | 列出本地 AID |
|
|
66
|
+
| `load(aid)` | `load(aid)` | `Load(aid)` | 从本地加载 AID |
|
|
67
|
+
| `register(aid)` | `register(aid)` | `Register(ctx, aid[, opts])` | 注册并落盘证书和私钥;Go 两参数旧调用仍可用,显式选项使用 `AIDStoreRegisterOptions` |
|
|
68
|
+
| `list()` | `list()` | `List()` | 列出本地 AID |
|
|
73
69
|
| `exists(aid)` | `exists(aid)` | `Exists(ctx, aid)` | 远端存在性检查 |
|
|
74
|
-
| `resolve(aid, opts=None)` | `resolve(aid, opts?)` | `Resolve(ctx, aid, opts...)` |
|
|
75
|
-
| `upload_agent_md(aid, content=None)` | `uploadAgentMd(aid, content?)` | `UploadAgentMD(ctx, aid, content...)` |
|
|
70
|
+
| `resolve(aid, opts=None)` | `resolve(aid, opts?)` | `Resolve(ctx, aid, opts...)` | 拉证书并缓存;自有私钥身份优先本地名片草稿/缓存,可用 `skip_agent_md` / `skipAgentMd` / `SkipAgentMD` 跳过名片 |
|
|
71
|
+
| `upload_agent_md(aid, content=None, *, uploader_aid=None, co_signer_aid=None)` | `uploadAgentMd(aid, content?, options?)` | `UploadAgentMD(ctx, aid, content...)` / `UploadAgentMDWithOptions(ctx, aid, opts, content...)` | 普通主体自签自传;Group/Org 实体主签、owner token 上传及可选 owner 附签,见协议 §2.5 |
|
|
76
72
|
| `download_agent_md(aid, timeout_s=None)` | `downloadAgentMd(aid, timeoutMs=30000)` | `DownloadAgentMD(ctx, aid)` | 下载 agent.md,返回 `DownloadAgentMdResult` / `AgentMDInfo` |
|
|
77
73
|
| `check_agent_md(aid, ttl_days=1)` | `checkAgentMd(aid, ttlDays=1)` | `CheckAgentMD(ctx, aid, maxUnsyncedDays...)` | 通过 HEAD 和本地记录检查一致性 |
|
|
74
|
+
| `sign(aid, input, *, input_type="text", format="raw", tag="", append=False, in_place=False, ...)` | `sign(aid, input, {inputType, format, tag, append, inPlace, ...})` | `Sign(ctx, aid, input, opts)` | 通用裸签或文档多签 |
|
|
75
|
+
| `verify(aid, input, signature=None, *, input_type="text", format="raw", ...)` | `verify(aid, input, signature?, {inputType, format, ...})` | `Verify(ctx, aid, input, opts)` | 裸签或逐块文档验签;Go detached 签名传 opts.Signature |
|
|
78
76
|
| `diagnose(aid)` | `diagnose(aid)` | `Diagnose(ctx, aid)` | 本地 + 远端诊断 |
|
|
79
77
|
| `renew_cert(aid)` / `rekey(aid)` | `renewCert(aid)` / `rekey(aid)` | `RenewCert(ctx, aid)` / `Rekey(ctx, aid)` | 证书运维 |
|
|
80
78
|
| `change_seed(old, new)` | `changeSeed(old, new)` | `ChangeSeed(old, new)` | 本地密钥保护种子迁移 |
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
`register(aid)` / `Register(ctx, aid)` 保持兼容语义:只创建或恢复证书并上传普通 `agent.md`,不会创建 owner 关系。新建非 `human` AID 必须在新注册入口提供 owner;`human` 不得提供 owner;只有 `agent` 可以使用 self-owner(`owner == aid`)。外部 owner 需要 subject 和 owner 两份签名,self-owner 只需要 subject 签名。
|
|
96
|
-
|
|
97
|
-
Auth 关系类型可接受 `org`,但当前 CA/Name Service 只实现 `signing` 与 `group_identity` 证书用途;`org_identity` 尚未实现,SDK 不应把组织身份证书映射或组织专用 agent.md 签名描述为可用能力。
|
|
98
|
-
|
|
99
|
-
新注册和绑定完成 `prepare` 后,SDK 将服务端返回的 `proof_id`、`fact_hash`、`statement_hash` 及签名封套写入 `ownership_proof`,并用 `owner_operation_id` 上传 `agent.md`;普通 `uploadAgentMd` 不能改变已激活关系。operation 有效期为 7 天,证书在 pending/失败/过期期间仍可登录和通信。
|
|
100
|
-
|
|
101
|
-
状态可通过 `get_aid_binding_status` / `auth.aid_register_status` / `auth.owner_relation_status` 查询,通过 `resume_aid_binding` 或 `aid_operation_get` 在进程重启后恢复。常见状态为 `legacy_unbound`、`pending`、`proof_pending`、`agent_md_pending`、`active`、`not_applicable`、`unbound`、`unusable`、`expired`。
|
|
102
|
-
|
|
103
|
-
### Ownership proof 约定
|
|
104
|
-
|
|
105
|
-
四端 SDK 使用同一组 UTF-8 canonical bytes(对象键按字典序、无空格):
|
|
106
|
-
|
|
107
|
-
```text
|
|
108
|
-
fact = canonical_json({"subject_aid": subject, "owner_aid": owner})
|
|
109
|
-
statement = canonical_json({"proof_id": proof_id, "subject_aid": subject, "owner_aid": owner})
|
|
110
|
-
signing_bytes = UTF-8("AUN-AID-OWNER-RELATION-V1;") || statement
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
AID 先规范化为 ASCII 小写;`proof_id` 必须是 UUID v4;`fact_hash` 是 `SHA-256(fact)`,`statement_hash` 是 `SHA-256(signing_bytes)`,均为小写十六进制。签名封套只有 `cert_fingerprint`(`sha256:<64 hex>`)和严格 Base64 的 `signature`。`owner_signature` 对外部 owner 必需,对 self-owner 必须省略。
|
|
114
|
-
|
|
115
|
-
`change_owner` 由当前 owner 发起,`expected_relation_version` 用于 CAS;提交 `old_owner_signature`、subject signature 和 new owner signature 后,subject 发布新 proof 并激活。成功后 `relation_version` 递增,旧 owner 的 Storage ACL 撤销但数据保留,新 owner 的 ACL 重新创建。
|
|
80
|
+
Go 的 `Register(ctx, aid)` 保留原有简单身份注册行为;`Register(ctx, aid, AIDStoreRegisterOptions{...})` 是显式类型/owner 登记入口。历史 owner-aware `RegisterWithOptions(ctx, AIDRegisterParams{...})` 单独保留旧注册编排,不等同于 Ownership 2.1 的双文件关系确认。
|
|
81
|
+
|
|
82
|
+
Python、TS/Node 与 Go 的 `AIDStore` 本地方法返回 Result 包装;浏览器 JS 因 IndexedDB / WebCrypto 约束返回 `Promise<Result>`。TS/Node 的 Store.sign/verify 也是异步 `Promise<Result>`,属于上述本地方法的例外;联网方法在 TS/JS 中均返回 `Promise<Result>`;Go 形态为 `Result[T]`,字段为 `Ok` / `Data` / `Error`。
|
|
83
|
+
|
|
84
|
+
自有私钥身份的 `resolve` 默认优先返回本地草稿/缓存,标记 `verification.status=unverified`、`source.agent_md_fetched=false`;草稿的 `in_sync=false`。需要读取远端内容时,显式下载或强制刷新,本地草稿仍保留;刷新选项分别为 Python `force_refresh`、TS/JS `forceRefresh`、Go `ForceRefresh`。失败稿由应用显式重试上传,重连不自动重传。
|
|
85
|
+
|
|
86
|
+
### 通用 sign / verify
|
|
87
|
+
|
|
88
|
+
`format="raw"` 为默认,保留 detached Base64 签名/验签;`format="document"` 处理任意 UTF-8 文本文档的连续尾签,不要求 YAML 或 agent.md 业务字段。sign 返回 `signed` 全文、本次 `signature` 和实际 `signatures` 列表;verify 返回 `valid`、`status`、首块前 `payload` 及逐块 `signatures`。普通 agent.md 与 owner.md 主签不输出且业务不接受 signer_aid;实体主块显式 signer_aid=target,主签身份、Schema、资源及授权由调用者另验,SDK 文件流程和服务端均复用各自唯一同构签验 core。
|
|
89
|
+
|
|
90
|
+
`input_type="text"` 默认把输入视作内容;显式 `input_type="file"` 才读取文件;raw 按原始字节处理,包括非 UTF-8 文件,document 必须严格 UTF-8,raw/document 字符串均严格校验 Unicode 并编码为 UTF-8,无效 Unicode 拒绝。不识别 `file://` 或自动猜路径,缺失文件报错。`in_place=True` 仅适用于 file + document,签名成功后才写回;TS/JS 使用 `inputType/inPlace`,Go 使用 `InputType/Format/Tag/Append/InPlace`。浏览器 File/Blob 只读,FileSystemFileHandle 可原地写,不接受裸本地路径。
|
|
91
|
+
|
|
92
|
+
`append=True` 仅在已有签名链末尾追加时,末字节非 LF/CR 才补 LF,其余字节不变;无旧块时仍按首签要求正文以 CR/LF 结束,否则拒绝;新块签完整 prefix,含该分隔及所有前序完整块。主块保持旧正文裸签;附签必填 signer_aid。tag 是 `[A-Z0-9-]+` 字面后缀:空串无 TAG,`AGENTMD-V2` 生成 `AUN-SIGNATURE-AGENTMD-V2`,`AUN-SIGNATURE` 不作特殊选项;内部 wrapper 传短 tag,标签不授予角色。verify 必须全块验签并报告实际顺序,不能保证检测末端删签;签名区总计仍限 2048 字节,不加证书链字段,证书沿用可信指纹 resolver。verify 默认离线 load 本地公钥/证书,不要求私钥;历史/远端材料由业务显式注入可信 certificateResolver,并沿用既有证书链及生命周期检查,既有 agent.md 远程下载流程不变。数学验签失败仍返回全部逐签 records;resolver 操作异常保留外层 error,不能误标坏签名。精确字节及主签规则见 [协议 §2.4](../protocol/Ownership协议定义2.1.md#24-文件签名)。
|
|
116
93
|
|
|
117
94
|
### Result 类型
|
|
118
95
|
|
|
@@ -190,8 +167,8 @@ AID 由 `AIDStore.load()` 返回,应用层不直接构造。
|
|
|
190
167
|
| `is_private_key_valid()` | `isPrivateKeyValid()` | `IsPrivateKeyValid()` | 私钥是否可用 |
|
|
191
168
|
| `sign(data)` | `sign(data)` | `Sign(data)` | 签名 bytes |
|
|
192
169
|
| `verify(data, signature)` | `verify(data, signature)` | `Verify(data, signature)` | 验签 |
|
|
193
|
-
| `sign_agent_md(content)` | `signAgentMd(content)` | `SignAgentMd(content)` | agent.md 签名 |
|
|
194
|
-
| `verify_agent_md(content)` | `verifyAgentMd(content)` | `VerifyAgentMd(content)` | agent.md 验签 |
|
|
170
|
+
| `sign_agent_md(content)` | `signAgentMd(content)` | `SignAgentMd(content)` | agent.md 签名 |
|
|
171
|
+
| `verify_agent_md(content)` | `verifyAgentMd(content)` | `VerifyAgentMd(content)` | agent.md 验签 |
|
|
195
172
|
|
|
196
173
|
---
|
|
197
174
|
|
|
@@ -231,20 +208,20 @@ client := aun.NewAUNClient(aid)
|
|
|
231
208
|
|
|
232
209
|
| Python | TS/JS | Go | 说明 |
|
|
233
210
|
|--------|-------|----|------|
|
|
234
|
-
| `load_identity(aid)` | `loadIdentity(aid)` | `LoadIdentity(aid)` | 在 `no_identity` / `closed` 状态加载身份 |
|
|
235
|
-
| `state` | `state` | `ConnectionState()` | 九态公开状态 |
|
|
236
|
-
| `gateway_url` | `gatewayUrl` | `GetGatewayURL()` | 当前连接的 Gateway URL(只读,自动发现,连接前为空) |
|
|
237
|
-
| `get_access_token()` | `getAccessToken()` | `GetAccessToken()` | 同步读取后台刷新任务维护的当前 access token;不发起认证、刷新或网络请求;无 token 时分别返回 `None` / `null` / 空字符串 |
|
|
238
|
-
| `current_aid` | `currentAid` | `CurrentAID()` | 当前 AID 对象 |
|
|
211
|
+
| `load_identity(aid)` | `loadIdentity(aid)` | `LoadIdentity(aid)` | 在 `no_identity` / `closed` 状态加载身份 |
|
|
212
|
+
| `state` | `state` | `ConnectionState()` | 九态公开状态 |
|
|
213
|
+
| `gateway_url` | `gatewayUrl` | `GetGatewayURL()` | 当前连接的 Gateway URL(只读,自动发现,连接前为空) |
|
|
214
|
+
| `get_access_token()` | `getAccessToken()` | `GetAccessToken()` | 同步读取后台刷新任务维护的当前 access token;不发起认证、刷新或网络请求;无 token 时分别返回 `None` / `null` / 空字符串 |
|
|
215
|
+
| `current_aid` | `currentAid` | `CurrentAID()` | 当前 AID 对象 |
|
|
239
216
|
| `aid` | `aid` | `AID()` | 当前 AID 字符串 |
|
|
240
217
|
| `has_identity` | `hasIdentity` | `HasIdentity()` | 是否已加载身份 |
|
|
241
218
|
| `can_sign` | `canSign` | `CanSign()` | 是否可签名 |
|
|
242
219
|
| `can_connect` | `canConnect` | `CanConnect()` | 是否可连接 |
|
|
243
220
|
| `can_send` / `is_ready` | `canSend` / `isReady` | `CanSend()` / `IsReady()` | 是否可发送 |
|
|
244
|
-
| `is_online` | `isOnline` | `IsOnline()` | 是否处于在线或重连相关状态 |
|
|
245
|
-
| `is_closed` | `isClosed` | `IsClosed()` | 是否已关闭 |
|
|
246
|
-
|
|
247
|
-
`get_access_token()` / `getAccessToken()` / `GetAccessToken()` 面向需要自行发起 HTTP 数据面请求的应用。返回值是调用时刻的缓存快照,不是可长期持有的凭据:应在每次需要 AID Bearer 的请求前重新读取,不能持续复用 `authenticate()` 首次返回的字符串。getter 本身不会主动刷新,也不独立检查 token 是否临近过期;其有效性依赖客户端后台刷新任务正常运行。返回空值时应先完成身份加载和认证/连接,且不得发送空的 `Authorization` 头。Storage VFS 和 Group FS 等 SDK 门面会自行编排其数据面请求,普通应用优先使用门面。Bearer、资源域 ticket、跨 issuer 下载和 401/403 重试边界见 [Storage RPC 手册:数据面 HTTP 下载流程](09-storage-rpc-manual.md#数据面-http-下载流程)。
|
|
221
|
+
| `is_online` | `isOnline` | `IsOnline()` | 是否处于在线或重连相关状态 |
|
|
222
|
+
| `is_closed` | `isClosed` | `IsClosed()` | 是否已关闭 |
|
|
223
|
+
|
|
224
|
+
`get_access_token()` / `getAccessToken()` / `GetAccessToken()` 面向需要自行发起 HTTP 数据面请求的应用。返回值是调用时刻的缓存快照,不是可长期持有的凭据:应在每次需要 AID Bearer 的请求前重新读取,不能持续复用 `authenticate()` 首次返回的字符串。getter 本身不会主动刷新,也不独立检查 token 是否临近过期;其有效性依赖客户端后台刷新任务正常运行。返回空值时应先完成身份加载和认证/连接,且不得发送空的 `Authorization` 头。Storage VFS 和 Group FS 等 SDK 门面会自行编排其数据面请求,普通应用优先使用门面。Bearer、资源域 ticket、跨 issuer 下载和 401/403 重试边界见 [Storage RPC 手册:数据面 HTTP 下载流程](09-storage-rpc-manual.md#数据面-http-下载流程)。
|
|
248
225
|
|
|
249
226
|
状态值:
|
|
250
227
|
|
|
@@ -258,35 +235,35 @@ retry_backoff / reconnecting / connection_failed / closed
|
|
|
258
235
|
Python:
|
|
259
236
|
|
|
260
237
|
```python
|
|
261
|
-
auth = await client.authenticate()
|
|
262
|
-
await client.connect({"auto_reconnect": True})
|
|
238
|
+
auth = await client.authenticate()
|
|
239
|
+
await client.connect({"auto_reconnect": True})
|
|
263
240
|
await client.disconnect()
|
|
264
241
|
await client.close()
|
|
265
242
|
```
|
|
266
243
|
|
|
267
244
|
说明:
|
|
268
245
|
|
|
269
|
-
- `authenticate()` 只取 token,不建立业务会话。
|
|
270
|
-
- `connect()` 可从 `standby` 自动认证并进入 `ready`。
|
|
271
|
-
- `disconnect()` 断开当前传输连接,对象仍可重新连接。
|
|
272
|
-
- `close()` 关闭连接和后台任务;之后只能重新加载身份再复用。
|
|
246
|
+
- `authenticate()` 只取 token,不建立业务会话。
|
|
247
|
+
- `connect()` 可从 `standby` 自动认证并进入 `ready`。
|
|
248
|
+
- `disconnect()` 断开当前传输连接,对象仍可重新连接。
|
|
249
|
+
- `close()` 关闭连接和后台任务;之后只能重新加载身份再复用。
|
|
273
250
|
|
|
274
251
|
四个 SDK 的公开构造入口均已对齐为“无参或 AID 对象”。调试、TLS、根证书、device_id、slot_id 等配置由 `AIDStore` 传递到 AID,再由 `AUNClient` 继承;连接级选项只传给 `connect()`。
|
|
275
252
|
|
|
276
253
|
### RPC
|
|
277
254
|
|
|
278
255
|
```python
|
|
279
|
-
result = await client.call("message.send", {
|
|
280
|
-
"to": "bob.agentid.pub",
|
|
281
|
-
"device_id": "bob-phone",
|
|
282
|
-
"ttl": 300,
|
|
283
|
-
"payload": {"type": "text", "text": "hello"},
|
|
284
|
-
})
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
`message.send` 可选传入目标 `device_id`,非空时只投递该设备;`to_device_id` 仅为兼容别名,规范字段优先。目标无效时发送失败且不会退化为全设备投递。这里的 `device_id` 是接收目标,`message.pull` / `message.ack` 的同名字段则表示当前消费设备。
|
|
288
|
-
|
|
289
|
-
`ttl` 单位为秒:缺省或 `<=0` 保持持久化;正数钳制到 1–3600 秒,只存于消息服务内存且不分配持久 `seq`。四个 SDK 自动维护 volatile 游标、去重及 ACK;返回和事件中的 `storage`、`volatile_cursor`、`created_at`、`expires_at` 可用于识别此类消息。
|
|
256
|
+
result = await client.call("message.send", {
|
|
257
|
+
"to": "bob.agentid.pub",
|
|
258
|
+
"device_id": "bob-phone",
|
|
259
|
+
"ttl": 300,
|
|
260
|
+
"payload": {"type": "text", "text": "hello"},
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`message.send` 可选传入目标 `device_id`,非空时只投递该设备;`to_device_id` 仅为兼容别名,规范字段优先。目标无效时发送失败且不会退化为全设备投递。这里的 `device_id` 是接收目标,`message.pull` / `message.ack` 的同名字段则表示当前消费设备。
|
|
265
|
+
|
|
266
|
+
`ttl` 单位为秒:缺省或 `<=0` 保持持久化;正数钳制到 1–3600 秒,只存于消息服务内存且不分配持久 `seq`。四个 SDK 自动维护 volatile 游标、去重及 ACK;返回和事件中的 `storage`、`volatile_cursor`、`created_at`、`expires_at` 可用于识别此类消息。
|
|
290
267
|
|
|
291
268
|
常用 meta RPC 直接透传:
|
|
292
269
|
|
|
@@ -350,15 +327,16 @@ headers = client.get_protected_headers()
|
|
|
350
327
|
|
|
351
328
|
| Python | TS/JS | Go | 说明 |
|
|
352
329
|
|--------|-------|----|------|
|
|
353
|
-
| `AIDStore.upload_agent_md(aid, content=None)` | `store.uploadAgentMd(aid, content?)` | `store.UploadAgentMD(ctx, aid, content...)` | 发布指定本地 AID 的 agent.md |
|
|
354
|
-
| `AIDStore.download_agent_md(aid)` | `store.downloadAgentMd(aid)` | `store.DownloadAgentMD(ctx, aid)` | 下载并验签 |
|
|
355
|
-
| `AIDStore.check_agent_md(aid)` | `store.checkAgentMd(aid)` | `store.CheckAgentMD(ctx, aid, maxUnsyncedDays...)` | 检查一致性 |
|
|
356
|
-
|
|
357
|
-
说明:
|
|
358
|
-
|
|
359
|
-
- agent.md 上传、下载和检查入口都在 `AIDStore`;`AUNClient` 不再暴露上传入口。
|
|
360
|
-
-
|
|
361
|
-
-
|
|
330
|
+
| `AIDStore.upload_agent_md(aid, content=None, *, uploader_aid=None, co_signer_aid=None)` | `store.uploadAgentMd(aid, content?, options?)` | `store.UploadAgentMD(ctx, aid, content...)` / `store.UploadAgentMDWithOptions(ctx, aid, opts, content...)` | 发布指定本地 AID 的 agent.md |
|
|
331
|
+
| `AIDStore.download_agent_md(aid)` | `store.downloadAgentMd(aid)` | `store.DownloadAgentMD(ctx, aid)` | 下载并验签 |
|
|
332
|
+
| `AIDStore.check_agent_md(aid)` | `store.checkAgentMd(aid)` | `store.CheckAgentMD(ctx, aid, maxUnsyncedDays...)` | 检查一致性 |
|
|
333
|
+
|
|
334
|
+
说明:
|
|
335
|
+
|
|
336
|
+
- agent.md 上传、下载和检查入口都在 `AIDStore`;`AUNClient` 不再暴露上传入口。
|
|
337
|
+
- 普通主体目标 AID 须有本地签名材料并使用自身 token;Group/Org 用实体主签、当前 owner token 上传,可选 owner 附签,不能以附签替换资源授权。agent.md 与 owner.md 统一调用 Store document 签验 core,再验证业务 Schema。
|
|
338
|
+
- 实体上传默认使用名片当前 owner;显式指定上传者分别使用 Python `uploader_aid`、TS/JS `options.uploaderAid`、Go `AIDStoreUploadAgentMDOptions.UploaderAID`。追加 owner 附签分别使用 `co_signer_aid`、`options.coSignerAid`、`AIDStoreUploadAgentMDOptions.CoSignerAID`,值必须为当前 owner;Go 通过 `UploadAgentMDWithOptions` 传入选项。
|
|
339
|
+
- SDK 全部 NS GET/HEAD/PUT 携带 `X-AUN-Signature-Format: multi-v1`;GET 同时发送 `Accept: text/markdown`;实体 fresh GET 另带 `X-AUN-Ownership-Check: 1` 与 `Cache-Control: no-cache` 以绕 LRU 全块验证,仍为 not_applicable、不进入通用账本;不主动发送 `If-None-Match` / `If-Modified-Since`。如果服务端异常返回 304,本地有内容则复用;无内容时再发一次无条件 GET。
|
|
362
340
|
- SDK 会自动从 Gateway `_meta.agent_md_etags` 和信封 `agent_md` 观察远端版本;`requester`、`peer`、`group` 是标准角色键,`receiver`、`target`、`to`、`sender`、`from` 是兼容别名。
|
|
363
341
|
- `Accept: text/markdown` 与 agent.md 的 YAML frontmatter + Markdown 格式兼容;agent.md 仍是 Markdown 媒体类型上的结构化约定。
|
|
364
342
|
|
|
@@ -368,43 +346,54 @@ headers = client.get_protected_headers()
|
|
|
368
346
|
|
|
369
347
|
除 `client.call(method, params)` 外,四语言 SDK 提供高层门面(Facade),封装常用操作并简化参数。普通应用优先用门面,只有需要精确控制底层参数时再直调 RPC。
|
|
370
348
|
|
|
349
|
+
### Ownership、凭证与组织专题
|
|
350
|
+
|
|
351
|
+
| 领域 | 当前入口 | 详细指南 |
|
|
352
|
+
|------|----------|----------|
|
|
353
|
+
| Ownership 2.1 | 七个 Facade:`bindOwneraid`、`bindSubaid`、`releaseSubaid`、`transferSubaid`、`acceptOwnershipRequest`、`rejectOwnershipRequest`、`checkOwnershipConsensus`(TS/JS 命名) | [应用集成](Ownership2.1-SDK应用集成指南.md#4-七个-facade-的参数角色与结果)、[开发与移植](Ownership2.1-SDK开发与移植指南.md) |
|
|
354
|
+
| Credential/Org | Python/TS/JS:`client.credential`、`client.org`;Go:`client.Credential()`、`client.Org()`;包含本地协议助手和业务 facade,服务端可用方法以 RPC 手册为准 | [应用集成](凭证与组织服务SDK应用集成指南.md)、[开发与移植](凭证与组织服务SDK开发与移植指南.md) |
|
|
355
|
+
|
|
356
|
+
Ownership 2.1 关系须检查当前双文件共识;Group/Org 使用专属生命周期,通用关系操作返回 `not_applicable`。Credential/Org 的本地验签不代替当前状态和请求授权检查。
|
|
357
|
+
|
|
371
358
|
### 文件与存储门面
|
|
372
359
|
|
|
373
360
|
| 能力 | Python | TS/JS | Go | 说明 |
|
|
374
361
|
|------|--------|-------|----|------|
|
|
375
|
-
| Storage VFS | `client.storage` | `client.storage` | `client.Storage()` | 类 POSIX 文件操作;上传自动选择 inline / session / 秒传并统一 Content-Type,下载自动选择 inline / ticket;支持 `touch`、`find`、`du`、`df`、ACL/token/软链/挂载门面 |
|
|
362
|
+
| Storage VFS | `client.storage` | `client.storage` | `client.Storage()` | 类 POSIX 文件操作;上传自动选择 inline / session / 秒传并统一 Content-Type,下载自动选择 inline / ticket;支持 `touch`、`find`、`du`、`df`、ACL/token/软链/挂载门面 |
|
|
376
363
|
| Collab | `client.collab` | `client.collab` | `client.Collab()` | 版本化文档、标签、`gc` / `reflog` / `revert` |
|
|
377
364
|
| 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 编排 |
|
|
378
365
|
|
|
379
|
-
四个 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。
|
|
380
|
-
|
|
381
|
-
群文件系统路径统一使用 `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` 当本地路径。
|
|
366
|
+
四个 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。
|
|
367
|
+
|
|
368
|
+
群文件系统路径统一使用 `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` 当本地路径。
|
|
382
369
|
|
|
383
370
|
### 消息与群组门面
|
|
384
371
|
|
|
385
372
|
| 能力 | Python | TS/JS | Go | 说明 |
|
|
386
373
|
|------|--------|-------|----|------|
|
|
387
|
-
| Message | `client.message` | `client.message` | `client.Message()` | 消息便利方法:`send()`、`pull()`、`history()`、`ack()`、`recall()`、`queryOnline()` |
|
|
374
|
+
| Message | `client.message` | `client.message` | `client.Message()` | 消息便利方法:`send()`、`pull()`、`history()`、`ack()`、`read()`、`read_state/readState/ReadState`、`recall()`、`queryOnline()` |
|
|
388
375
|
| Message Thought | `client.message.thought` | `client.message.thought` | `client.Message().Thought()` | P2P 思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
|
|
389
|
-
| Group | `client.group` | `client.group` | `client.Group()` | 群组便利方法:`create()`、`send()`、`pull()`、`history()`、`ack()`、群管理方法、群查询方法、群设置便利方法 |
|
|
390
|
-
| Group Thought | `client.group.thought` | `client.group.thought` | `client.Group().Thought()` | 群思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
|
|
391
|
-
| Offline Push | `client.push` | — | — | Python SDK:登记/注销当前安装的 `push_notify_aid`,Push Server 处理批次后 ACK |
|
|
392
|
-
| Stream | `client.stream` | `client.stream` | — | 流式数据:`createStream()`、`sendChunk()`、`endStream()`、`subscribeStream()` |
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
|
403
|
-
|
|
404
|
-
|
|
|
405
|
-
|
|
|
406
|
-
|
|
407
|
-
|
|
376
|
+
| Group | `client.group` | `client.group` | `client.Group()` | 群组便利方法:`create()`、`send()`、`pull()`、`history()`、`ack()`、`read()`、`read_state/readState/ReadState`、群管理方法、群查询方法、群设置便利方法 |
|
|
377
|
+
| Group Thought | `client.group.thought` | `client.group.thought` | `client.Group().Thought()` | 群思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
|
|
378
|
+
| Offline Push | `client.push` | — | — | Python SDK:登记/注销当前安装的 `push_notify_aid`,Push Server 处理批次后 ACK |
|
|
379
|
+
| Stream | `client.stream` | `client.stream` | — | 流式数据:`createStream()`、`sendChunk()`、`endStream()`、`subscribeStream()` |
|
|
380
|
+
|
|
381
|
+
业务已读与投递 ACK 独立。Python 使用 `read/read_state`,TS/JS 使用 `read/readState`,Go 使用 `Read/ReadState`;四个已读门面保留显式 `None/null/nil` 字段交服务端校验。只有省略 `states` 时兼容顶层单条,显式空/null 批次拒绝;写入回执不是共享汇总。完整字段与事件契约见 [Message RPC](09-message-rpc-manual.md#messageread) 和 [Group RPC](09-group-rpc-manual.md#groupread)。
|
|
382
|
+
|
|
383
|
+
`message.history` 和 `group.history` 使用 `before_seq` 排他上界向左翻页,下一页直接使用响应的 `next_before_seq`。History 只读,不推进实时 A/T/H、不 ACK、不触发实时消息事件。实时 Push 的最新页同步完全由 SDK 内部自动执行,再按 A/T/H 决定是否补一页 Forward;没有需要应用调用的 Tail 方法或参数。
|
|
384
|
+
|
|
385
|
+
消息回调只提供页级语义:单个 Tail/Forward 响应页内按 seq 升序、同 seq 最多一次;跨 Push/Tail/Forward 页可能重复或乱序。A/T/H 不能用于判断某条消息是否已经回调。全局去重与排序不是 SDK 业务逻辑保证;应用仓库应以 `(namespace, message_id)` 做唯一键,并按 `seq` 排序。SDK 的进程内折叠仅是 best-effort 优化。
|
|
386
|
+
|
|
387
|
+
**群成员管理与状态方法**:
|
|
388
|
+
|
|
389
|
+
| 语义 | Python | TS/JS | Go |
|
|
390
|
+
|------|--------|-------|----|
|
|
391
|
+
| 屏蔽/取消屏蔽 | `block()` / `unblock()` | `block()` / `unblock()` | `Block()` / `Unblock()` |
|
|
392
|
+
| 获取屏蔽列表 | `get_blocklist()` | `getBlocklist()` | `GetBlocklist()` |
|
|
393
|
+
| 上报自己的群内状态 | `report_status()` | `reportStatus()` | `ReportStatus()` |
|
|
394
|
+
| 获取所有成员状态 | `get_member_statuses()` | `getMemberStatuses()` | `GetMemberStatuses()` |
|
|
395
|
+
|
|
396
|
+
屏蔽与禁言相互独立且可以同时设置。屏蔽成员仍可向群发送消息,但不接收群消息;禁言成员不能向群发送消息,但仍可接收。群主转让是两阶段流程:旧群主先生成授权并调用 `group.transfer_owner`,新群主 SDK 收到 `owner_transfer_rekey_pending` 后生成新群密钥并调用 `group.complete_transfer`。四个 SDK 会在新群主在线或重连恢复时自动尝试第二阶段,也保留 `completeTransfer`(Python 为 `complete_transfer`,Go 为 `CompleteTransfer`)供显式恢复;发起调用返回 `pending_rekey`,不表示转让已经完成。
|
|
408
397
|
|
|
409
398
|
**群查询方法**:`GroupFacade` 提供三个查询方法,适用不同场景:
|
|
410
399
|
|
|
@@ -412,20 +401,20 @@ headers = client.get_protected_headers()
|
|
|
412
401
|
- `getInfo()` — 查询群组信息(扁平化格式,提升常用字段到顶层),**推荐外部使用**
|
|
413
402
|
- `info()` — 查询群组详细信息(带权限控制,非成员只能看公开群,成员能看 seq/epoch 等运行时状态)
|
|
414
403
|
|
|
415
|
-
**群设置便利方法**:`GroupFacade` 提供向后兼容的便利方法:
|
|
416
|
-
|
|
417
|
-
- `getAnnouncement()` / `updateAnnouncement()` — 群公告
|
|
418
|
-
- `getRules()` / `updateRules()` — 群规则
|
|
419
|
-
- `getJoinRequirements()` / `updateJoinRequirements()` — 入群要求
|
|
420
|
-
- `getSettingWithIndex()` / `updateSettingWithIndex()` — 通用文档型 indexed setting(Python 为 `get_setting_with_index()` / `update_setting_with_index()`,Go 为 `GetSettingWithIndex()` / `UpdateSettingWithIndex()`)
|
|
421
|
-
|
|
422
|
-
读取方法优先返回 SDK 本地缓存;本地没有对应值时才读取相应 settings 做初始化。便利读取从服务端拿到 canonical `group_aid` 后,会同时以 canonical `group_aid` 和本次入参 `group_id` 写入 settings cache,避免 legacy/base `group_id` 下一次读取直接 cache miss。即使 `checkGroupIndex` 观察到远端 etag 与本地 etag 不一致,`getAnnouncement()` / `getRules()` / `getJoinRequirements()` / `getSettingWithIndex()` 也不会自动拉取远端版本覆盖本地缓存。`updateAnnouncement()` / `updateRules()` / `updateJoinRequirements()` / `updateSettingWithIndex()` 属于 indexed 写入,内部会调用 `updateGroupIndex` 生成签名 `group.index` 并带 `expected_index_etag` CAS 提交。
|
|
423
|
-
|
|
424
|
-
`getSettingWithIndex()` / `updateSettingWithIndex()` 比三对预定义方法多一个 `keyName`(Python 可传 `key_name`,Go 同时接受 `keyName` / `key_name`)。SDK 会生成 `{keyName}.content` 和 `{keyName}.attachments` 两个 settings key;`keyName` 只能是受控文档名(`^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀)。`getRules()` / `updateRules()` 与 `getAnnouncement()` / `updateAnnouncement()` 是该通用方法在 `rules`、`announcement` 上的薄封装;`getJoinRequirements()` / `updateJoinRequirements()` 保持结构化 schema,不改成 `join.content`。
|
|
425
|
-
|
|
426
|
-
这些 `update*` 便利方法只更新群设置元数据:`updateRules()` / `updateAnnouncement()` / `updateSettingWithIndex()` 写入 `*.content` 与 `*.attachments`,`updateJoinRequirements()` 写入 `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments`。`attachments` 只保存稳定引用,附件实体应先上传到 group.fs 群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。
|
|
427
|
-
|
|
428
|
-
**Group Index 高级同步方法**:`group.index` 是 SDK 内部签名 manifest,用于记录群公告、群规则、入群要求及附件稳定引用的版本。SDK 观察 `_meta.group_indexes` 后只记录远端 etag;etag 不一致只表示本地与观察到的远端版本不同,可能是远端更新,也可能是本地有未提交修改。应用层需要显式选择 pull 远端或 push 本地。
|
|
404
|
+
**群设置便利方法**:`GroupFacade` 提供向后兼容的便利方法:
|
|
405
|
+
|
|
406
|
+
- `getAnnouncement()` / `updateAnnouncement()` — 群公告
|
|
407
|
+
- `getRules()` / `updateRules()` — 群规则
|
|
408
|
+
- `getJoinRequirements()` / `updateJoinRequirements()` — 入群要求
|
|
409
|
+
- `getSettingWithIndex()` / `updateSettingWithIndex()` — 通用文档型 indexed setting(Python 为 `get_setting_with_index()` / `update_setting_with_index()`,Go 为 `GetSettingWithIndex()` / `UpdateSettingWithIndex()`)
|
|
410
|
+
|
|
411
|
+
读取方法优先返回 SDK 本地缓存;本地没有对应值时才读取相应 settings 做初始化。便利读取从服务端拿到 canonical `group_aid` 后,会同时以 canonical `group_aid` 和本次入参 `group_id` 写入 settings cache,避免 legacy/base `group_id` 下一次读取直接 cache miss。即使 `checkGroupIndex` 观察到远端 etag 与本地 etag 不一致,`getAnnouncement()` / `getRules()` / `getJoinRequirements()` / `getSettingWithIndex()` 也不会自动拉取远端版本覆盖本地缓存。`updateAnnouncement()` / `updateRules()` / `updateJoinRequirements()` / `updateSettingWithIndex()` 属于 indexed 写入,内部会调用 `updateGroupIndex` 生成签名 `group.index` 并带 `expected_index_etag` CAS 提交。
|
|
412
|
+
|
|
413
|
+
`getSettingWithIndex()` / `updateSettingWithIndex()` 比三对预定义方法多一个 `keyName`(Python 可传 `key_name`,Go 同时接受 `keyName` / `key_name`)。SDK 会生成 `{keyName}.content` 和 `{keyName}.attachments` 两个 settings key;`keyName` 只能是受控文档名(`^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀)。`getRules()` / `updateRules()` 与 `getAnnouncement()` / `updateAnnouncement()` 是该通用方法在 `rules`、`announcement` 上的薄封装;`getJoinRequirements()` / `updateJoinRequirements()` 保持结构化 schema,不改成 `join.content`。
|
|
414
|
+
|
|
415
|
+
这些 `update*` 便利方法只更新群设置元数据:`updateRules()` / `updateAnnouncement()` / `updateSettingWithIndex()` 写入 `*.content` 与 `*.attachments`,`updateJoinRequirements()` 写入 `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments`。`attachments` 只保存稳定引用,附件实体应先上传到 group.fs 群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。
|
|
416
|
+
|
|
417
|
+
**Group Index 高级同步方法**:`group.index` 是 SDK 内部签名 manifest,用于记录群公告、群规则、入群要求及附件稳定引用的版本。SDK 观察 `_meta.group_indexes` 后只记录远端 etag;etag 不一致只表示本地与观察到的远端版本不同,可能是远端更新,也可能是本地有未提交修改。应用层需要显式选择 pull 远端或 push 本地。
|
|
429
418
|
|
|
430
419
|
| 语义 | Python | TS/JS | Go | 说明 |
|
|
431
420
|
|------|--------|-------|----|------|
|
|
@@ -433,7 +422,7 @@ headers = client.get_protected_headers()
|
|
|
433
422
|
| 显式 pull 远端 index | `client.group.get_group_index({...})` | `client.group.getGroupIndex({...})` | `client.Group().GetGroupIndex(ctx, params)` | 调用 `group.get_settings(keys=["group.index"])` 摘取 manifest,并按 entry etag 只拉取变化的 db settings 写入本地缓存 |
|
|
434
423
|
| 显式 push 本地 indexed settings + index | `client.group.update_group_index({...})` | `client.group.updateGroupIndex({...})` | `client.Group().UpdateGroupIndex(ctx, params)` | 先读取当前 index 得到 `expected_index_etag`,在远端基线上合并本地变更,生成签名 `group.index` 后 CAS push |
|
|
435
424
|
|
|
436
|
-
`getGroupIndex` pull 验签成功后会持久化本地视图。Python / TypeScript(Node) / Go 使用 `{aun_path}/AIDs/{local_aid}/groups/{group_aid}/index.jsonl` 保存签名 `group.index.body` 原文,并用同目录 `group-index-cache.json` 保存 `local_etag`、`remote_meta`、`settings`、`entry_etags` 等 cache envelope。浏览器 JavaScript 使用 IndexedDB `group_index_cache` store 的等价记录,按 `local_aid + group_aid` 隔离。普通便利读取可额外写入本次请求 `group_id` 的 settings cache alias;签名正文和 `getGroupIndex` 视图仍以 canonical `group_aid` 为准。不要使用 `{aun_path}/AIDs/{group_aid}/`,也不要使用旧单文件 `group-index.json`。
|
|
425
|
+
`getGroupIndex` pull 验签成功后会持久化本地视图。Python / TypeScript(Node) / Go 使用 `{aun_path}/AIDs/{local_aid}/groups/{group_aid}/index.jsonl` 保存签名 `group.index.body` 原文,并用同目录 `group-index-cache.json` 保存 `local_etag`、`remote_meta`、`settings`、`entry_etags` 等 cache envelope。浏览器 JavaScript 使用 IndexedDB `group_index_cache` store 的等价记录,按 `local_aid + group_aid` 隔离。普通便利读取可额外写入本次请求 `group_id` 的 settings cache alias;签名正文和 `getGroupIndex` 视图仍以 canonical `group_aid` 为准。不要使用 `{aun_path}/AIDs/{group_aid}/`,也不要使用旧单文件 `group-index.json`。
|
|
437
426
|
|
|
438
427
|
#### checkGroupIndex — 检查 index 同步状态
|
|
439
428
|
|
|
@@ -595,14 +584,14 @@ fmt.Printf("拉取成功,etag: %s\n", result["meta"].(map[string]any)["etag"])
|
|
|
595
584
|
| `last_modified` | int | ❌ | 时间戳毫秒(默认 `Date.now()` / `time.time()*1000`) |
|
|
596
585
|
| `max_attempts` | int | ❌ | CAS 冲突最大重试次数(默认 2) |
|
|
597
586
|
|
|
598
|
-
**支持的 indexed settings keys**:
|
|
599
|
-
|
|
600
|
-
- `rules.content` / `rules.attachments` — 群规则及附件
|
|
601
|
-
- `announcement.content` / `announcement.attachments` — 群公告及附件
|
|
602
|
-
- `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments` — 入群要求及附件
|
|
603
|
-
- `{keyName}.content` / `{keyName}.attachments` — 通用文档型 indexed setting;`keyName` 需满足 `^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀
|
|
604
|
-
|
|
605
|
-
**返回值**:
|
|
587
|
+
**支持的 indexed settings keys**:
|
|
588
|
+
|
|
589
|
+
- `rules.content` / `rules.attachments` — 群规则及附件
|
|
590
|
+
- `announcement.content` / `announcement.attachments` — 群公告及附件
|
|
591
|
+
- `join.mode` / `join.question` / `join.auto_approve_patterns` / `join.max_pending` / `join.attachments` — 入群要求及附件
|
|
592
|
+
- `{keyName}.content` / `{keyName}.attachments` — 通用文档型 indexed setting;`keyName` 需满足 `^[A-Za-z][A-Za-z0-9_-]{0,63}$`,且不能使用 `join` 等保留前缀
|
|
593
|
+
|
|
594
|
+
**返回值**:
|
|
606
595
|
|
|
607
596
|
```python
|
|
608
597
|
{
|
|
@@ -671,16 +660,16 @@ console.log(`推送成功,新 etag: ${result._meta.group_indexes['g-team.agent
|
|
|
671
660
|
|
|
672
661
|
```go
|
|
673
662
|
// Go - 更新入群要求
|
|
674
|
-
result, err := client.Group().UpdateGroupIndex(ctx, map[string]any{
|
|
675
|
-
"group_id": "g-team.agentid.pub",
|
|
676
|
-
"settings": map[string]any{
|
|
677
|
-
"join.mode": "approval",
|
|
678
|
-
"join.question": "你是如何知道本群的?",
|
|
679
|
-
"join.attachments": []any{
|
|
680
|
-
map[string]any{"type": "group.fs", "path": "/.group/attachments/join/guide.pdf"},
|
|
681
|
-
},
|
|
682
|
-
},
|
|
683
|
-
})
|
|
663
|
+
result, err := client.Group().UpdateGroupIndex(ctx, map[string]any{
|
|
664
|
+
"group_id": "g-team.agentid.pub",
|
|
665
|
+
"settings": map[string]any{
|
|
666
|
+
"join.mode": "approval",
|
|
667
|
+
"join.question": "你是如何知道本群的?",
|
|
668
|
+
"join.attachments": []any{
|
|
669
|
+
map[string]any{"type": "group.fs", "path": "/.group/attachments/join/guide.pdf"},
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
})
|
|
684
673
|
if err != nil {
|
|
685
674
|
log.Fatal(err)
|
|
686
675
|
}
|
|
@@ -692,41 +681,41 @@ fmt.Printf("推送成功\n")
|
|
|
692
681
|
1. **权限要求**:写入 indexed settings 需要 admin 及以上权限
|
|
693
682
|
2. **签名算法限制**:当前版本仅支持 ECDSA-P256-SHA256,使用其他算法的 AID 无法签名
|
|
694
683
|
3. **CAS 冲突策略**:默认重试 2 次,高并发场景建议增加 `max_attempts`
|
|
695
|
-
4. **`signer` 必须是当前连接身份**:服务端强制校验 `signed_by == actor_aid`,传入其他 AID 会被拒绝
|
|
696
|
-
5. **附件字段只存引用**:`updateRules` / `updateAnnouncement` / `updateSettingWithIndex` 传入 `content` 和 `attachments` 元数据引用;`updateJoinRequirements` 传入结构化入群字段和 `attachments` 元数据引用。附件实体先上传到群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。群自有区默认允许 `owner/admin` 写入,`member` 默认不可写;`.group/` 不允许授予 `role:member` 写权限。
|
|
697
|
-
|
|
698
|
-
---
|
|
699
|
-
|
|
700
|
-
### 离线推送门面(Python)
|
|
701
|
-
|
|
702
|
-
应用启动时推荐把推送代理和 opaque token 交给 `connect()`:
|
|
703
|
-
|
|
704
|
-
```python
|
|
705
|
-
await client.connect({
|
|
706
|
-
"push_notify_aid": "push.example.com",
|
|
707
|
-
"push_token": token,
|
|
708
|
-
})
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
SDK 先建立 AUN 会话,再调用 `push.register` 登记当前安装。`push_notify_aid` 是 SDK 公共名称,线上 RPC 字段仍是冻结契约中的 `push_server_aid`;它不会被透传给 `auth.connect`。
|
|
712
|
-
|
|
713
|
-
运行期间更换 token 或停止推送时使用 facade:
|
|
714
|
-
|
|
715
|
-
```python
|
|
716
|
-
await client.push.register(push_notify_aid="push.example.com", push_token=new_token)
|
|
717
|
-
await client.push.unregister()
|
|
718
|
-
```
|
|
719
|
-
|
|
720
|
-
- `register()` 可附带 `provider`、`app_id`;身份范围始终由 Gateway 注入的当前 `aid/device_id/slot_id` 决定,调用方不能伪造。
|
|
721
|
-
- `unregister()` 幂等禁用当前安装,不删除历史 delivery。
|
|
722
|
-
- `ack(batch_id, status)` 只供 Push Server 实现使用;V1 status 仅允许 `accepted`、`retryable_failure`、`permanent_failure`。
|
|
723
|
-
- 本轮只修改 Python SDK;Go、TypeScript、JavaScript 尚无专用 Push facade。
|
|
724
|
-
|
|
725
|
-
协议与可靠性边界见 `docs/protocol/15-离线推送通知协议.md`。
|
|
726
|
-
|
|
727
|
-
---
|
|
728
|
-
|
|
729
|
-
## ServiceProxyClient
|
|
684
|
+
4. **`signer` 必须是当前连接身份**:服务端强制校验 `signed_by == actor_aid`,传入其他 AID 会被拒绝
|
|
685
|
+
5. **附件字段只存引用**:`updateRules` / `updateAnnouncement` / `updateSettingWithIndex` 传入 `content` 和 `attachments` 元数据引用;`updateJoinRequirements` 传入结构化入群字段和 `attachments` 元数据引用。附件实体先上传到群自有区,推荐路径为 `group_aid:/.group/attachments/{rules|announcement|join|<keyName>}/...`。群自有区默认允许 `owner/admin` 写入,`member` 默认不可写;`.group/` 不允许授予 `role:member` 写权限。
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
### 离线推送门面(Python)
|
|
690
|
+
|
|
691
|
+
应用启动时推荐把推送代理和 opaque token 交给 `connect()`:
|
|
692
|
+
|
|
693
|
+
```python
|
|
694
|
+
await client.connect({
|
|
695
|
+
"push_notify_aid": "push.example.com",
|
|
696
|
+
"push_token": token,
|
|
697
|
+
})
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
SDK 先建立 AUN 会话,再调用 `push.register` 登记当前安装。`push_notify_aid` 是 SDK 公共名称,线上 RPC 字段仍是冻结契约中的 `push_server_aid`;它不会被透传给 `auth.connect`。
|
|
701
|
+
|
|
702
|
+
运行期间更换 token 或停止推送时使用 facade:
|
|
703
|
+
|
|
704
|
+
```python
|
|
705
|
+
await client.push.register(push_notify_aid="push.example.com", push_token=new_token)
|
|
706
|
+
await client.push.unregister()
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
- `register()` 可附带 `provider`、`app_id`;身份范围始终由 Gateway 注入的当前 `aid/device_id/slot_id` 决定,调用方不能伪造。
|
|
710
|
+
- `unregister()` 幂等禁用当前安装,不删除历史 delivery。
|
|
711
|
+
- `ack(batch_id, status)` 只供 Push Server 实现使用;V1 status 仅允许 `accepted`、`retryable_failure`、`permanent_failure`。
|
|
712
|
+
- 本轮只修改 Python SDK;Go、TypeScript、JavaScript 尚无专用 Push facade。
|
|
713
|
+
|
|
714
|
+
协议与可靠性边界见 `docs/protocol/15-离线推送通知协议.md`。
|
|
715
|
+
|
|
716
|
+
---
|
|
717
|
+
|
|
718
|
+
## ServiceProxyClient
|
|
730
719
|
|
|
731
720
|
Service Proxy 用于 provider 通过 AUN 身份暴露本地 HTTP / WebSocket 服务。当前公开封装在 Python SDK 的 `ServiceProxyClient` 中;其它语言可以按 [09-proxy-rpc-manual.md](09-proxy-rpc-manual.md) 直接实现同等控制面和隧道消息。
|
|
732
721
|
|
|
@@ -791,113 +780,116 @@ sub.unsubscribe()
|
|
|
791
780
|
| `connection.error` | 连接或重连错误 |
|
|
792
781
|
| `token.refreshed` | token 刷新完成 |
|
|
793
782
|
| `token.refresh_exhausted` | refresh_token 缺失、过期或刷新链耗尽,SDK 已清理本地 token 并等待重新登录 |
|
|
794
|
-
| `message.received` | 收到 P2P 消息 |
|
|
795
|
-
| `message.
|
|
796
|
-
| `
|
|
797
|
-
| `
|
|
798
|
-
| `group.
|
|
799
|
-
| `group.
|
|
800
|
-
| `group.
|
|
801
|
-
| `
|
|
802
|
-
| `
|
|
803
|
-
| `
|
|
804
|
-
| `
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
|
830
|
-
|
|
831
|
-
| `
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
-
|
|
839
|
-
|
|
840
|
-
`
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
| `
|
|
850
|
-
|
|
851
|
-
| `
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
"
|
|
867
|
-
"
|
|
868
|
-
"
|
|
869
|
-
"
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
"
|
|
881
|
-
"
|
|
882
|
-
"
|
|
883
|
-
"
|
|
884
|
-
"
|
|
885
|
-
"
|
|
886
|
-
"
|
|
887
|
-
"
|
|
888
|
-
"
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
783
|
+
| `message.received` | 收到 P2P 消息 |
|
|
784
|
+
| `message.read_changed` / `group.read_changed` | 同一 AID 共享已读位置提交并前进;owner 必须为当前身份、scope 匹配原事件 |
|
|
785
|
+
| `read_state_sync` | SDK 本地已读补偿完成,含本轮 `owner_aid`、去重 `states` 和逐项 `errors`;连接返回不表示补偿完成 |
|
|
786
|
+
| `message.undecryptable` | P2P E2EE 解密失败 |
|
|
787
|
+
| `group.message_created` | 收到群消息 |
|
|
788
|
+
| `group.changed` | 群组事件 |
|
|
789
|
+
| `group.message_recalled` | 群消息撤回 |
|
|
790
|
+
| `group.message_undecryptable` | 群 E2EE 解密失败 |
|
|
791
|
+
| `sync.started` / `sync.progress` / `sync.stopped` | Pull 同步生命周期 |
|
|
792
|
+
| `delivery.changed` | SDK 本地批量交付完成通知,用于合并应用层 UI 刷新 |
|
|
793
|
+
| `push.offline_message` | Push Server 收到离线唤醒批次;普通终端无需订阅 |
|
|
794
|
+
| `storage.object_changed` | Storage 对象变更事件透传 |
|
|
795
|
+
|
|
796
|
+
服务端不产生 `message.ack` 通知;SDK 保留的透传订阅不能作为可依赖的 ACK 或对端已读事件。已读事件只向 owner AID 分发且不进入 Pull 队列;重连查询补偿不受消息 `background_sync=false` 影响。身份切换按代际隔离旧缓存与补偿完成事件;已排队的 raw/public `read_changed` 与 `read_state_sync` 在出队和每个处理器执行前重新核对身份代际,处理器等待期间切换身份也会停止后续交付,A→B→A 同样隔离;原在途 RPC 仍可返回。详见 [跨设备已读未读 SDK 集成指南](../跨设备已读未读SDK集成指南.md)。
|
|
797
|
+
|
|
798
|
+
`message.received` 的应用层消息保留 `sender_device_id`,表示发送方设备;需要只回复原设备时,将该值作为下一次 `message.send.device_id`。volatile 消息还保留 `storage="volatile"`、`volatile_cursor`、`created_at`、`expires_at`,不含持久 `seq`;内部 slot 不会暴露给应用。
|
|
799
|
+
|
|
800
|
+
### delivery.changed
|
|
801
|
+
|
|
802
|
+
`delivery.changed` 是 Python、Go、JavaScript 和 TypeScript SDK 统一提供的本地事件,用于通知应用层一批消息已经完成交付,可以从业务仓库刷新相关会话 UI。它不替代 `message.received` / `group.message_created`:应用仍应逐条处理和持久化原消息事件,再把 `delivery.changed` 作为批量刷新信号。
|
|
803
|
+
|
|
804
|
+
该事件由 SDK 本地 dispatcher 发布,不是 Gateway 推送事件,不属于 JSON-RPC `event/...` 协议;裸 WebSocket 客户端不会收到它。
|
|
805
|
+
|
|
806
|
+
**Payload**:
|
|
807
|
+
|
|
808
|
+
```json
|
|
809
|
+
{
|
|
810
|
+
"trigger": "pull_drained",
|
|
811
|
+
"changes": [
|
|
812
|
+
{"namespace": "group:team.agentid.pub", "delivered_count": 50},
|
|
813
|
+
{"namespace": "p2p", "delivered_count": 3}
|
|
814
|
+
]
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
| 字段 | 类型 | 说明 |
|
|
819
|
+
|------|------|------|
|
|
820
|
+
| `trigger` | string | `pull_drained`、`push` 或 `inline_push` |
|
|
821
|
+
| `changes` | array | 本次刷新涉及的 namespace,按 `namespace` 稳定排序且不重复 |
|
|
822
|
+
| `changes[].namespace` | string | P2P 固定为 `p2p`;群消息为 `group:<canonical-group-aid>` |
|
|
823
|
+
| `changes[].delivered_count` | integer | 本次合并窗口内已发布到应用层的原消息事件数;不是未读数、服务端页大小或最大 seq |
|
|
824
|
+
|
|
825
|
+
触发与折叠规则:
|
|
826
|
+
|
|
827
|
+
- `pull_drained`:当前 `AUNClient` 上所有已排队或正在执行的 Pull 工作,包括后续分页、continuation、gap fill 和缺失 Sender IK 的延迟补齐,全部排空后最多发布一次。一次通知可以同时包含 P2P 和多个群 namespace,不会按 Pull 页或单个 namespace 分别通知。
|
|
828
|
+
- `push` / `inline_push`:有效实时消息在对应的 `message.received` / `group.message_created` 事件处理完成后通知;同一次有序队列 drain 放行的同类实时消息折叠为一次通知。
|
|
829
|
+
- 有效的 `push` / `inline_push` 可以原子吸收尚未通知的 Pull 变更;这些变更不会在后续 `pull_drained` 中再次通知。
|
|
830
|
+
- 空 Pull、重复或过滤消息、非法 payload、解密失败,以及未带来有效消息交付的 Head 通知,不发布 `delivery.changed`。
|
|
831
|
+
|
|
832
|
+
`delivery.changed` 只表示 UI 刷新时机,不是消息明细或持久化账本。应用仓库仍应按照原消息事件的 `(namespace, message_id)` 做幂等,并按 `seq` 排序。
|
|
833
|
+
|
|
834
|
+
### 消息来源 `source`
|
|
835
|
+
|
|
836
|
+
消息、群消息、群事件、撤回和不可解密事件的 payload 可能带有顶层 `source`,用于区分 SDK 的投递来源:
|
|
837
|
+
|
|
838
|
+
| `source` | 含义 |
|
|
839
|
+
|----------|------|
|
|
840
|
+
| `push` | 普通实时推送 |
|
|
841
|
+
| `pull` | Pull、Tail、Forward 或群事件补洞 |
|
|
842
|
+
| `inline_push` | 已在连续窗口内直接消费的实时载荷 |
|
|
843
|
+
| `pending_retry` | 缺失 Sender IK 后延迟恢复的消息 |
|
|
844
|
+
|
|
845
|
+
直接由应用或无来源内部调用产生的事件不强行添加 `source`。`source` 位于应用事件 payload 顶层,不改变业务 `payload` 内的数据结构;应用应将其视为保留字段。
|
|
846
|
+
|
|
847
|
+
### Pull 同步生命周期
|
|
848
|
+
|
|
849
|
+
四个 SDK 均通过本地 dispatcher 发布以下异步生命周期事件;它们不是 Gateway 的 `event/...` 消息,应用 handler 不会阻塞网络 reader。
|
|
850
|
+
|
|
851
|
+
`sync.started` 在本次 Pull 的第一个 namespace 开始时发布一次:
|
|
852
|
+
|
|
853
|
+
```json
|
|
854
|
+
{
|
|
855
|
+
"run_id": 7,
|
|
856
|
+
"source": "pull",
|
|
857
|
+
"syncing": true,
|
|
858
|
+
"namespaces_pending": 1,
|
|
859
|
+
"namespace": "p2p",
|
|
860
|
+
"received_total": 0,
|
|
861
|
+
"started_at": 1730000000000
|
|
862
|
+
}
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
每完成一页消息或群事件的处理、提交和有序投递,发布一次 `sync.progress`。`page_raw_count` 是本页有效原始条数,`page_pulled_count` 是本页实际投递条数;`pulled_count` / `received_total` 是本次 namespace 的累计投递数。服务端返回合法非负整数时透传 `remaining`,并同步设置 `estimated_remaining`;否则仅在协议可推导时提供估算值。
|
|
866
|
+
|
|
867
|
+
```json
|
|
868
|
+
{
|
|
869
|
+
"run_id": 7,
|
|
870
|
+
"source": "pull",
|
|
871
|
+
"namespace": "p2p",
|
|
872
|
+
"page": 2,
|
|
873
|
+
"page_raw_count": 50,
|
|
874
|
+
"page_pulled_count": 48,
|
|
875
|
+
"pulled_count": 98,
|
|
876
|
+
"received_total": 98,
|
|
877
|
+
"batch_size": 48,
|
|
878
|
+
"has_more": true,
|
|
879
|
+
"remaining": 102,
|
|
880
|
+
"estimated_remaining": 102
|
|
881
|
+
}
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
当所有 namespace、续页、gap fill、ordered drain 和延迟 Sender IK 任务均排空时发布一次 `sync.stopped`。正常终态使用 `reason: "pull_drained"`;异常、取消、断线或连接/身份代次失效使用 `reason: "aborted"`。`sync.stopped` 描述同步生命周期终点,`delivery.changed(trigger="pull_drained")` 只汇总实际投递变化;空 Pull 可以有前者而没有后者。
|
|
885
|
+
|
|
886
|
+
### JS/TS Worker 降级
|
|
887
|
+
|
|
888
|
+
JavaScript 浏览器 SDK 的 Worker 是网络隔离增强:`new Worker()` 同步失败、CSP `worker-src` 阻止、Worker 启动后未及时 `open` 或异步崩溃时,SDK 会销毁 Worker 并回退原生 WebSocket。TypeScript Node.js SDK 在 `worker_threads` 不可用、启动超时或 Network Actor 崩溃时回退本地 transport。两种降级均保留异步 dispatcher 和 Pull 生命周期语义,不要求应用改变消息处理代码。
|
|
889
|
+
|
|
890
|
+
---
|
|
891
|
+
|
|
892
|
+
## E2EE 高级 API
|
|
901
893
|
|
|
902
894
|
普通业务无需直接操作 E2EE manager;`message.send` / `group.send` 默认加密并自动解密收到的消息。
|
|
903
895
|
|
|
@@ -919,14 +911,16 @@ JavaScript 浏览器 SDK 的 Worker 是网络隔离增强:`new Worker()` 同
|
|
|
919
911
|
|
|
920
912
|
| 领域 | 手册 | 关键方法 |
|
|
921
913
|
|------|------|----------|
|
|
922
|
-
| 消息 | [09-message-rpc-manual.md](09-message-rpc-manual.md) | `message.send` / `message.pull` / `message.history` / `message.ack` / `message.thought.*` |
|
|
923
|
-
| 群组 | [09-group-rpc-manual.md](09-group-rpc-manual.md) | `group.create` / `group.send` / `group.pull` / `group.history` / `group.v2.*` / `group.fs.*` |
|
|
914
|
+
| 消息 | [09-message-rpc-manual.md](09-message-rpc-manual.md) | `message.send` / `message.pull` / `message.history` / `message.ack` / `message.read` / `message.read_state` / `message.thought.*` |
|
|
915
|
+
| 群组 | [09-group-rpc-manual.md](09-group-rpc-manual.md) | `group.create` / `group.send` / `group.pull` / `group.history` / `group.read` / `group.read_state` / `group.v2.*` / `group.fs.*` |
|
|
916
|
+
| 凭证 | [凭证服务 RPC 手册](09-凭证服务RPC手册.md) | `credential.register` / `credential.revoke` / `credential.status` / `credential.revocationList` |
|
|
917
|
+
| 组织 | [组织服务 RPC 手册](09-组织服务RPC手册.md) | `org.lifecycle.*` / `org.member.*` / `org.credential.*` / `org.audit.query` / `org.authz.check`;内部及未实现方法见手册 |
|
|
924
918
|
| 存储 | [09-storage-rpc-manual.md](09-storage-rpc-manual.md) | `storage.put_object` / `storage.fs.*` / `storage.volume.*` / ACL / token / share link |
|
|
925
919
|
| 协作 | [09-collab-rpc-manual.md](09-collab-rpc-manual.md) | `collab.ls-files` / `collab.show` / `collab.commit` / `collab.merge` / `collab.log` / `collab.diff` / `collab.clone` / `collab.prune` / `collab.gc` / `collab.reflog` / `collab.revert` / `collab.tag.*` / `collab.ls-remote` / `collab.unregister` |
|
|
926
920
|
| 元信息 | [09-meta-rpc-manual.md](09-meta-rpc-manual.md) | `meta.ping` / `meta.status` / `meta.trust_roots` |
|
|
927
|
-
| Stream | [09-stream-rpc-manual.md](09-stream-rpc-manual.md) | `stream.create` / `stream.close` / `stream.list_active` |
|
|
928
|
-
| Offline Push | `docs/protocol/15-离线推送通知协议.md` | `push.register` / `push.unregister` / `push.ack` / `push.offline_message` |
|
|
929
|
-
| Service Proxy | [09-proxy-rpc-manual.md](09-proxy-rpc-manual.md) | `proxy.register_services` / `proxy.unregister_services` / `proxy.list_services` |
|
|
921
|
+
| Stream | [09-stream-rpc-manual.md](09-stream-rpc-manual.md) | `stream.create` / `stream.close` / `stream.list_active` |
|
|
922
|
+
| Offline Push | `docs/protocol/15-离线推送通知协议.md` | `push.register` / `push.unregister` / `push.ack` / `push.offline_message` |
|
|
923
|
+
| Service Proxy | [09-proxy-rpc-manual.md](09-proxy-rpc-manual.md) | `proxy.register_services` / `proxy.unregister_services` / `proxy.list_services` |
|
|
930
924
|
|
|
931
925
|
---
|
|
932
926
|
|