@agentunion/fastaun 0.5.20 → 0.5.22
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 +104 -0
- package/_packed_docs/CHANGELOG.md +104 -0
- package/_packed_docs/INDEX.md +59 -34
- package/_packed_docs/KITE_DOCS_GUIDE.md +59 -52
- package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/344/270/216/346/215/242owner/347/274/226/346/216/222/346/226/271/346/241/210.md +530 -0
- package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/345/256/214/346/225/264/350/256/276/350/256/241/344/270/216/345/256/236/346/226/275/350/256/241/345/210/222.md +685 -0
- package/_packed_docs/agent.md/working/agent.md-schema/344/270/216/347/255/276/345/217/221/351/252/214/347/255/276/346/265/201/347/250/213/346/276/204/346/270/205.md +349 -0
- package/_packed_docs/agent.md/working//346/234/254/345/234/260Docker/346/265/213/350/257/225Bug/346/270/205/345/215/225.md +40 -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 +307 -67
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +41 -15
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1433 -1392
- package/_packed_docs/protocol/08-AUN-E2EE.md +17 -12
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +30 -8
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +2 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +33 -22
- package/_packed_docs/sdk/0.5.21-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +368 -0
- package/_packed_docs/sdk/0.5.21-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +350 -0
- package/_packed_docs/sdk/0.5.22-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +212 -0
- package/_packed_docs/sdk/0.5.22-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +199 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +5 -1
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +64 -64
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +4 -1
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +42 -39
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +163 -14
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +48 -47
- package/_packed_docs/sdk/09-group-rpc-manual.md +15 -2
- package/_packed_docs/sdk/09-message-rpc-manual.md +250 -160
- package/_packed_docs/sdk/09-storage-rpc-manual.md +64 -7
- package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +73 -0
- package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +90 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +33 -25
- package/_packed_docs/sdk/INDEX.md +67 -33
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +74 -57
- 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 +312 -300
- 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 +322 -382
- 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 -708
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +28 -20
- 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 +190 -97
- 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 +158 -127
- package/dist/agent-md-schema.js +6 -4
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +22 -2
- package/dist/agent-md.js +92 -68
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +13 -0
- package/dist/aid-store.js +50 -15
- package/dist/aid-store.js.map +1 -1
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +22 -2
- package/dist/auth.js.map +1 -1
- package/dist/cert-utils.d.ts +1 -0
- package/dist/cert-utils.js +13 -0
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +87 -1
- package/dist/client/delivery.js +1387 -139
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.js +3 -0
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +4 -1
- package/dist/client/rpc-pipeline.js +149 -37
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +12 -2
- package/dist/client/v2-e2ee.js +831 -304
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +26 -2
- package/dist/client.js +412 -68
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/events.d.ts +18 -1
- package/dist/events.js +148 -9
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts +43 -1
- package/dist/facades.js +363 -7
- package/dist/facades.js.map +1 -1
- package/dist/group-fs.d.ts +1 -0
- package/dist/group-fs.js +37 -19
- package/dist/group-fs.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/aid-db.d.ts +6 -1
- package/dist/keystore/aid-db.js +184 -42
- package/dist/keystore/aid-db.js.map +1 -1
- package/dist/keystore/index.d.ts +14 -0
- package/dist/keystore/local-token-store.d.ts +9 -1
- package/dist/keystore/local-token-store.js +79 -14
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +46 -0
- package/dist/org-protocol.js +802 -12
- package/dist/org-protocol.js.map +1 -1
- package/dist/ownership-v21.d.ts +36 -5
- package/dist/ownership-v21.js +168 -52
- package/dist/ownership-v21.js.map +1 -1
- package/dist/ownership-workflow.d.ts +24 -2
- package/dist/ownership-workflow.js +682 -41
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/secret-store/file-store.js +84 -0
- package/dist/secret-store/file-store.js.map +1 -1
- package/dist/seq-tracker.d.ts +1 -0
- package/dist/seq-tracker.js +2 -2
- package/dist/seq-tracker.js.map +1 -1
- package/dist/storage/lowlevel.d.ts +6 -0
- package/dist/storage/lowlevel.js +24 -7
- package/dist/storage/lowlevel.js.map +1 -1
- package/dist/storage/read-cache.d.ts +70 -0
- package/dist/storage/read-cache.js +625 -0
- package/dist/storage/read-cache.js.map +1 -0
- package/dist/storage/vfs.d.ts +2 -0
- package/dist/storage/vfs.js +50 -15
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +86 -3
- package/dist/tools/cross-sdk-agent.js +758 -46
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +3 -0
- package/dist/transport.js +104 -46
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/v2/e2ee/encrypt-group.js +1 -0
- package/dist/v2/e2ee/encrypt-group.js.map +1 -1
- package/dist/v2/e2ee/encrypt-p2p.js +1 -0
- package/dist/v2/e2ee/encrypt-p2p.js.map +1 -1
- package/dist/v2/e2ee/types.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -67,7 +67,7 @@ store := aun.NewAIDStore(aunPath, encryptionSeed, aun.AIDStoreOptions{
|
|
|
67
67
|
| `register(aid)` | `register(aid)` | `Register(ctx, aid[, opts])` | 注册并落盘证书和私钥;Go 两参数旧调用仍可用,显式选项使用 `AIDStoreRegisterOptions` |
|
|
68
68
|
| `list()` | `list()` | `List()` | 列出本地 AID |
|
|
69
69
|
| `exists(aid)` | `exists(aid)` | `Exists(ctx, aid)` | 远端存在性检查 |
|
|
70
|
-
| `resolve(aid, opts=None)` | `resolve(aid, opts?)` | `Resolve(ctx, aid, opts...)` |
|
|
70
|
+
| `resolve(aid, opts=None)` | `resolve(aid, opts?)` | `Resolve(ctx, aid, opts...)` | 解析身份及名片,返回结构化 `agent_md.frontmatter`;可按需复用 ownership 共识校验并缓存 owner.md,完整输入输出见下节 |
|
|
71
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 |
|
|
72
72
|
| `download_agent_md(aid, timeout_s=None)` | `downloadAgentMd(aid, timeoutMs=30000)` | `DownloadAgentMD(ctx, aid)` | 下载 agent.md,返回 `DownloadAgentMdResult` / `AgentMDInfo` |
|
|
73
73
|
| `check_agent_md(aid, ttl_days=1)` | `checkAgentMd(aid, ttlDays=1)` | `CheckAgentMD(ctx, aid, maxUnsyncedDays...)` | 通过 HEAD 和本地记录检查一致性 |
|
|
@@ -83,6 +83,125 @@ Python、TS/Node 与 Go 的 `AIDStore` 本地方法返回 Result 包装;浏览
|
|
|
83
83
|
|
|
84
84
|
自有私钥身份的 `resolve` 默认优先返回本地草稿/缓存,标记 `verification.status=unverified`、`source.agent_md_fetched=false`;草稿的 `in_sync=false`。需要读取远端内容时,显式下载或强制刷新,本地草稿仍保留;刷新选项分别为 Python `force_refresh`、TS/JS `forceRefresh`、Go `ForceRefresh`。失败稿由应用显式重试上传,重连不自动重传。
|
|
85
85
|
|
|
86
|
+
### resolve 输入与输出
|
|
87
|
+
|
|
88
|
+
沿用 `AIDStore.resolve`,不增加独立的 frontmatter 查询方法。`agent_md.content` 保留完整原文,`agent_md.frontmatter` 提供同一名片的 YAML 元数据;普通调用不额外查询 ownership。
|
|
89
|
+
|
|
90
|
+
| SDK | 签名 |
|
|
91
|
+
|-----|------|
|
|
92
|
+
| Python | `await store.resolve(aid: str, opts: dict \| None = None) -> Result[ResolveResult]` |
|
|
93
|
+
| TypeScript / JavaScript | `await store.resolve(aid: string, opts?: ResolveOpts): Promise<Result<ResolveResult>>` |
|
|
94
|
+
| Go | `store.Resolve(ctx context.Context, aid string, opts ...AIDStoreResolveOptions) Result[AIDStoreResolveResult]` |
|
|
95
|
+
|
|
96
|
+
#### 输入与 opts
|
|
97
|
+
|
|
98
|
+
`aid` 为目标 AID 字符串,如 `alice.agentid.pub`。`opts` 全部可选;Go 不传 options 时使用零值选项。
|
|
99
|
+
|
|
100
|
+
| TS/JS | Python | Go | 类型、默认值与行为 |
|
|
101
|
+
|-------|--------|----|--------------------|
|
|
102
|
+
| `forceRefresh` | `force_refresh` | `ForceRefresh` | bool,默认 false;绕过本地身份/名片优先路径并刷新证书和远端名片;启用 ownership 时也绕过共识缓存 |
|
|
103
|
+
| `skipAgentMd` | `skip_agent_md` | `SkipAgentMD` | bool,默认 false;省略输出的 `agent_md`。与 ownership 同用时,共识校验仍可在内部读取当前 agent.md |
|
|
104
|
+
| `timeout` | `timeout` | `Timeout` | TS/JS 为毫秒数,名片下载默认 10000 ms;Python 为毫秒数,未传时名片下载默认 30 s;Go 为 `time.Duration`,默认 10 s,约束整个 Resolve context |
|
|
105
|
+
| `ownership` | `ownership` | `Ownership` | 默认不传;传入已有 `AUNClient` 或实现共识查询接口的对象,调用 `checkOwnershipConsensus(aid)` / `check_ownership_consensus(aid)` / `CheckOwnershipConsensus(ctx, aid)`;不接受布尔开关 |
|
|
106
|
+
| `ownershipTtlMs` | `ownership_ttl_ms` | `OwnershipTTL` | TS/JS/Python 为毫秒数,默认 60000;Go 为 `*time.Duration`,nil 表示一分钟,指向 0 表示不复用缓存;各端的 0 均表示每次查询 |
|
|
107
|
+
|
|
108
|
+
Python 兼容 `forceRefresh`、`skipAgentMd`、`timeoutMs`、`ownershipTtlMs` 别名。TS/JS/Python 的 timeout 沿用名片下载的超时范围,共识请求沿用所传 client 的配置;Go 将 Resolve context 传给共识入口。`ownership` 使用现有身份和连接,不在 resolve 中新建 client。
|
|
109
|
+
|
|
110
|
+
#### 成功输出
|
|
111
|
+
|
|
112
|
+
返回既有 Result 包装:Python/TS/JS 读取 `ok/data/error`,Go 读取 `Ok/Data/Error`。
|
|
113
|
+
|
|
114
|
+
| Python / TS / JS 的 `data` 字段 | Go 字段 | 类型与含义 |
|
|
115
|
+
|-------------------------------|---------|------------|
|
|
116
|
+
| `aid` | `AID` | 目标 `AID` 对象,含既有证书与身份能力;不是 AID 字符串 |
|
|
117
|
+
| `agent_md` | `AgentMD` | `DownloadAgentMdResult` / `AgentMDInfo`,含原文、frontmatter、验签与缓存信息;skip 时省略,Go 为 nil |
|
|
118
|
+
| `ownership` | `Ownership` | 共识结果加 `checked_at/cached`;未传 ownership 时省略,Go 为 nil |
|
|
119
|
+
| `source.cert_from_cache` | `Source.CertFromCache` | bool,身份材料是否由本地加载 |
|
|
120
|
+
| `source.agent_md_fetched` | `Source.AgentMDFetched` | bool,是否执行名片下载;包含使用本地内容完成的 HTTP 304;本地草稿/缓存和 skip 路径为 false |
|
|
121
|
+
|
|
122
|
+
身份解析、证书或名片下载失败沿用原有外层 `ok=false` 和错误码。身份及名片已成功时,额外的 ownership 查询失败写入 `ownership.status=unavailable`,外层仍成功,不回退为过期的成功关系。
|
|
123
|
+
|
|
124
|
+
#### frontmatter 结构与公开字段
|
|
125
|
+
|
|
126
|
+
公开原文 frontmatter 中的全部字段,包括扩展字段;不把字段统一转换成字符串、不扁平化嵌套结构。对象、数组、字符串、数字、布尔值及 null 保留各语言 YAML 解析后的类型。TS/JS 为公开的 `AgentMdFrontmatter` 接口,扩展值类型为 `unknown`;Python 为 `AgentMdFrontmatter = dict[str, Any]`;Go 为 `AgentMDFrontmatter map[string]any`,通过 `AgentMD.Frontmatter` 访问。
|
|
127
|
+
|
|
128
|
+
| 字段 | 类型 | 当前 Schema 含义 |
|
|
129
|
+
|------|------|-----------------|
|
|
130
|
+
| `aid` | string | 名片所属主体的 AID |
|
|
131
|
+
| `name` | string | 显示名 |
|
|
132
|
+
| `type` | string | 开放字符串;常见 human、agent、service、device、group、org、host |
|
|
133
|
+
| `version` | string | 名片 Schema 版本,SemVer,如 `1.0.0` |
|
|
134
|
+
| `exttype` | string | 主体扩展类型 |
|
|
135
|
+
| `description` | string | 简介,不超过 100 个 Unicode 字符 |
|
|
136
|
+
| `avatar` | string | 头像地址,不超过 256 个 Unicode 字符 |
|
|
137
|
+
| `tags` | string[] | 标签 |
|
|
138
|
+
| `owner` | string | 名片声明的 owner;普通主体需结合 2.1 共识状态判断;Group/Org 属于专属生命周期 |
|
|
139
|
+
| `ownership` | object | 普通主体的声明容器,当前核心字段为 `statement` |
|
|
140
|
+
| `entity_cert_fingerprint` | string | Group/Org 实体证书的 `sha256:<hex>` 指纹 |
|
|
141
|
+
| 其它键 | 任意解析值 | 如 visibility、skills 或应用自定义字段,存在时原样返回 |
|
|
142
|
+
|
|
143
|
+
当前发布 Schema 要求 `aid/name/type/version`;读取接口兼容历史名片,因此类型声明中的标准字段可缺省,不补默认值,裸 Markdown 正文返回 `{}`。`ownership.statement` 保留六字段:`version=2`(整数)、`declaration_id`(小写 UUIDv4)、`owner_aid`、`sub_aid`、`relation_version`(正整数)和 `declared_at`(Unix 秒)。普通主体的 owner 与 statement 同时存在或同时缺省;human 禁止通用 ownership,Group/Org 不使用此声明容器。
|
|
144
|
+
|
|
145
|
+
字段定义与签名规则以 [当前协议 §1.3、§2](../protocol/Ownership协议定义2.1.md) 为准;[agent.md/SCHEMA.md](../agent.md/SCHEMA.md) 是 legacy Ownership 2.0。`frontmatter.owner` 和已有 `agent_md.verification.ownership_status` 都不替代下面的 2.1 共识结果。
|
|
146
|
+
|
|
147
|
+
#### ownership 输出
|
|
148
|
+
|
|
149
|
+
查询复用现有双文件共识校验:读取当前 NS agent.md 与 owner Storage 的 `default/sub_aids/{aid}/owner.md`,沿用声明、签名、证书、前后新鲜读取及 30 秒窗口检查。
|
|
150
|
+
|
|
151
|
+
| 字段 | 类型 | 含义 |
|
|
152
|
+
|------|------|------|
|
|
153
|
+
| `status` | string | 下表七种共识状态之一 |
|
|
154
|
+
| `sub_aid` | string | 被查询的目标 AID |
|
|
155
|
+
| `owner_aid` | string \| null | 仅 consensus 返回当前有效 owner,其余状态为 null |
|
|
156
|
+
| `relation_version` | integer \| null | 本次观察的关系代际;尚未取得材料时 TS/JS/Go 为 0,Python 可为 null |
|
|
157
|
+
| `lock` | string \| null | 本次 NS 的 locked/unlocked;尚未取得材料时 TS/JS/Go 为 unlocked,Python 可为 null |
|
|
158
|
+
| `agent_md_etag` | string \| null | 本次共识所读 agent.md 的 ETag |
|
|
159
|
+
| `agent_md_sha256` | string \| null | 本次共识所读完整 agent.md 的 SHA-256 十六进制摘要 |
|
|
160
|
+
| `owner_md_sha256` | string \| null | owner.md 完整原文摘要;缺失时 TS/JS/Go 为空串,Python 可为 null |
|
|
161
|
+
| `ns_protocol` | string,可选 | 既有共识入口提供时保留的 NS 协议标记 |
|
|
162
|
+
| `owner_md` | object,可选 | 实际读取到的 owner 文件快照,结构见下表;未进入 owner 读取阶段时省略 |
|
|
163
|
+
| `code/reason/retryable` | string/string/bool,可选 | 沿用共识入口的错误说明及可重试性,如 unsupported_protocol;不根据缺省值推断成功 |
|
|
164
|
+
| `checked_at` | integer | 本次共识查询完成时间,Unix 毫秒;缓存命中时保留原值 |
|
|
165
|
+
| `cached` | bool | 是否复用了本地共识快照 |
|
|
166
|
+
|
|
167
|
+
| status | 含义 |
|
|
168
|
+
|--------|------|
|
|
169
|
+
| `consensus` | 双方当前文件匹配且通过校验,关系成立 |
|
|
170
|
+
| `released` | 当前材料确认关系已释放 |
|
|
171
|
+
| `unbound` | 当前没有成立的绑定 |
|
|
172
|
+
| `single_sided` | 只有一方声明或待确认材料,关系尚未成立 |
|
|
173
|
+
| `invalid` | 声明、签名或身份绑定等材料无效 |
|
|
174
|
+
| `unavailable` | 网络、证书、服务能力、权威性或读取一致性不足,当前无法确认 |
|
|
175
|
+
| `not_applicable` | Group/Org 等使用专属生命周期,不适用通用共识 |
|
|
176
|
+
|
|
177
|
+
`owner_md` 包含 `owner_aid: string`、`bucket: "default"`、`path: "sub_aids/{aid}/owner.md"`、`exists: bool`、`content: string`(完整原文,含签名)、`sha256: string`、`observed_at: integer`(Storage 观察时间,Unix 秒)。确认不存在时 exists=false、content/sha256 为空串;存在快照不表示整体共识成功,须检查 status。
|
|
178
|
+
|
|
179
|
+
#### 缓存与刷新
|
|
180
|
+
|
|
181
|
+
共识快照连同 owner.md 原文保存在该 AID 的 `agentmd.json.ownership_snapshot`;浏览器使用 IndexedDB 等价记录,沿用现有存储不可用时的内存回退。该记录不进入名片 frontmatter 或上传内容。
|
|
182
|
+
|
|
183
|
+
仅在目标匹配、时间未倒退且仍在 TTL 内、上次状态不是 unavailable,并且本次返回的 agent.md 原文摘要与快照一致时复用;skip 路径没有名片内容可比时按目标和 TTL 判断。forceRefresh 绕过缓存,TTL=0 每次重新查询;返回对象与缓存隔离,修改返回值不污染后续结果。
|
|
184
|
+
|
|
185
|
+
自有身份可返回本地草稿,同时 ownership 检查当前远端原件;两者以 `agent_md_sha256` 区分,不能把草稿中的 owner 当成已成立关系。缓存结果供读取和展示;绑定、释放、转移及其它依赖 owner 的授权操作继续执行原有的新鲜共识校验。
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const result = await store.resolve('alice.agentid.pub', { ownership: client });
|
|
189
|
+
if (result.ok) console.log(result.data.agent_md?.frontmatter, result.data.ownership?.status);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
result = await store.resolve("alice.agentid.pub", {"ownership": client})
|
|
194
|
+
if result.ok:
|
|
195
|
+
print(result.data["agent_md"]["frontmatter"], result.data["ownership"]["status"])
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```go
|
|
199
|
+
result := store.Resolve(ctx, "alice.agentid.pub", aun.AIDStoreResolveOptions{Ownership: client})
|
|
200
|
+
if result.Ok && result.Data.AgentMD != nil {
|
|
201
|
+
fmt.Println(result.Data.AgentMD.Frontmatter, result.Data.Ownership.Status)
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
86
205
|
### 通用 sign / verify
|
|
87
206
|
|
|
88
207
|
`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。
|
|
@@ -107,14 +226,18 @@ Python、TS/Node 与 Go 的 `AIDStore` 本地方法返回 Result 包装;浏览
|
|
|
107
226
|
|------|------|------|
|
|
108
227
|
| `aid` | str | AID 字符串 |
|
|
109
228
|
| `content` | str | agent.md 原始内容 |
|
|
110
|
-
| `
|
|
229
|
+
| `frontmatter` | object | 原文 YAML 元数据,字段和类型见 [resolve 规格](#resolve-输入与输出);Go 为 `Frontmatter` |
|
|
230
|
+
| `verification` | `{status, reason?, ownership_status?}` | 名片读取的签名状态,如 verified、unsigned;本地草稿为 unverified,验签失败沿用外层错误;ownership_status 保留既有语义 |
|
|
111
231
|
| `signature` | dict | 低层签名解析和验签结果 |
|
|
112
232
|
| `cert_pem` | str | 签名所用证书 PEM |
|
|
113
233
|
| `etag` | str | HTTP ETag |
|
|
114
234
|
| `last_modified` | str | HTTP Last-Modified |
|
|
115
|
-
| `status` | int | HTTP
|
|
235
|
+
| `status` | int | Python/TS/JS 下载的 HTTP 状态码,缓存内容完成读取时可为 304;Go 的 AgentMDInfo 不提供该字段 |
|
|
116
236
|
| `in_sync` | bool\|null | 目标是当前 AID 时表示本地内容 ETag 是否等于远端 ETag;对端 AID 通常为 null |
|
|
117
|
-
| `saved_to` | str | SDK 管理的本地 agent.md 位置或浏览器 logical key |
|
|
237
|
+
| `saved_to` | str\|null | SDK 管理的本地 agent.md 位置或浏览器 logical key |
|
|
238
|
+
| `save_error` | str\|null | 既有本地保存错误信息,无错误时为空;Go 空值可省略 |
|
|
239
|
+
|
|
240
|
+
resolve 的本地草稿/缓存路径不执行远程下载,其辅助字段沿用各端现状:TS 的 status 为 200、浏览器为 0,Python 可省略 status/signature/saved_to;验签信息不代表本轮重新验签。HTTP 200 与 304 路径均根据实际返回的 content 提供 frontmatter。
|
|
118
241
|
|
|
119
242
|
### CheckAgentMdResult
|
|
120
243
|
|
|
@@ -265,6 +388,8 @@ result = await client.call("message.send", {
|
|
|
265
388
|
|
|
266
389
|
`ttl` 单位为秒:缺省或 `<=0` 保持持久化;正数钳制到 1–3600 秒,只存于消息服务内存且不分配持久 `seq`。四个 SDK 自动维护 volatile 游标、去重及 ACK;返回和事件中的 `storage`、`volatile_cursor`、`created_at`、`expires_at` 可用于识别此类消息。
|
|
267
390
|
|
|
391
|
+
`message.send` / `group.send` 的可选 `need_render` 默认为 `true`;SDK 将它放入外层信封,历史缺字段或 NULL 也按 `true`。它用于展示和待同步数量统计,不改变拉取顺序,不进入 E2EE AAD、protected headers、消息保护签名或元数据 HMAC;RPC `client_signature` 仍按原业务参数规则覆盖该字段。
|
|
392
|
+
|
|
268
393
|
常用 meta RPC 直接透传:
|
|
269
394
|
|
|
270
395
|
```python
|
|
@@ -350,11 +475,13 @@ headers = client.get_protected_headers()
|
|
|
350
475
|
|
|
351
476
|
| 领域 | 当前入口 | 详细指南 |
|
|
352
477
|
|------|----------|----------|
|
|
353
|
-
| Ownership 2.1 |
|
|
478
|
+
| Ownership 2.1 | 七个关系业务Facade:`bindOwneraid`、`bindSubaid`、`releaseSubaid`、`transferSubaid`、`acceptOwnershipRequest`、`rejectOwnershipRequest`、`checkOwnershipConsensus`;无参数任务管理Facade `resetOwnershipTask()`(Python `reset_ownership_task()`、Go `ResetOwnershipTask(ctx)`),批量清理当前AID发起的未完成任务,返回`{reset_operation_ids:[],skipped_operation_ids:[]}`(其余为TS/JS命名) | [应用集成](Ownership2.1-SDK应用集成指南.md#4-七个-facade-的参数角色与结果)、[开发与移植](Ownership2.1-SDK开发与移植指南.md) |
|
|
354
479
|
| Credential/Org | Python/TS/JS:`client.credential`、`client.org`;Go:`client.Credential()`、`client.Org()`;包含本地协议助手和业务 facade,服务端可用方法以 RPC 手册为准 | [应用集成](凭证与组织服务SDK应用集成指南.md)、[开发与移植](凭证与组织服务SDK开发与移植指南.md) |
|
|
355
480
|
|
|
356
481
|
Ownership 2.1 关系须检查当前双文件共识;Group/Org 使用专属生命周期,通用关系操作返回 `not_applicable`。Credential/Org 的本地验签不代替当前状态和请求授权检查。
|
|
357
482
|
|
|
483
|
+
sub-first 绑定在 sub 同意后 Stage 暂存 `agent.md`;NS 的 `pending/unlocked` 对公共共识映射为 `single_sided`,不授予 owner 权限,Storage 名片副本待 fresh 验收清除 pending 后同步。owner-first 绑定先 fresh 确认无锁并条件发布 `owner.md`,sub fresh 验证后同意并直接条件提交 `agent.md`,不走 Stage 或 bind.accept/owner.ready 往返。已有 owner 锁时只能由当前 owner 发起解绑或转移;拒绝清理与 reset 的原件/CAS 边界见 [应用指南 §6.1](Ownership2.1-SDK应用集成指南.md#61-绑定按发起方分流)。普通消息建议连接前订阅,READY 后补订阅也会触发任务恢复。
|
|
484
|
+
|
|
358
485
|
### 文件与存储门面
|
|
359
486
|
|
|
360
487
|
| 能力 | Python | TS/JS | Go | 说明 |
|
|
@@ -367,11 +494,25 @@ Ownership 2.1 关系须检查当前双文件共识;Group/Org 使用专属生
|
|
|
367
494
|
|
|
368
495
|
群文件系统路径统一使用 `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` 当本地路径。
|
|
369
496
|
|
|
497
|
+
#### 默认读缓存与单次刷新
|
|
498
|
+
|
|
499
|
+
四个 SDK 的 Storage / Group FS 读取默认由客户端决定缓存:响应未提供 `read_cache` 或值为 `null` 时,元数据默认缓存 60 秒;完整正文仅在实际大小不超过 65,536 字节且 SHA-256 校验通过时进入默认 inline 缓存。显式策略须 `reusable: true`,正文还须 `inline: true`;省略 `max_age_ms` 时默认 60 秒,有限正数最多使用 60 秒。显式禁止、null/非正数/非法 TTL 不复用。限次授权的 inline 读取仅返回正文时计次;inline 和大对象无正文 `not_modified` 均不计次,额度耗尽后仍允许匹配 SHA 的条件验证。SDK 本地缓存命中与 HEAD 等纯元数据查询不计次;撤销、过期、身份及权限检查保持。大对象按 URL 签发/授权 302 的下载授权计次,同 URL 有效期内复用属于同次授权,不统计外部 OSS 实际 GET 次数。
|
|
500
|
+
|
|
501
|
+
| 调用方 | 单次读取选项 | 语义 |
|
|
502
|
+
|--------|--------------|------|
|
|
503
|
+
| TypeScript / JavaScript | `noCache: true` | 跳过有效缓存命中,向远端重新校验 |
|
|
504
|
+
| Python | `no_cache=True` | 同上 |
|
|
505
|
+
| Go | 对应 VFS Options 的 `NoCache: true` | 同上 |
|
|
506
|
+
|
|
507
|
+
TS/JS 的底层 RPC 和 Group FS 也兼容 `no_cache: true`;TypeScript Storage VFS 的类型化选项使用 `noCache`。这些选项由 SDK 消费,不作为服务端业务参数发送。强制刷新可携带已有 `if_sha256`,远端确认未变化时继续使用已校验正文;新结果仍可写入缓存,不能把 `noCache` 当作 no-store。需要完整权威读取时,在支持该参数的底层 RPC 上使用 `consistency: "authoritative"`;该路径绕过 SDK 读缓存,也绕过服务端正负缓存。
|
|
508
|
+
|
|
509
|
+
普通文件 API 读取 `owner.md` 同样遵循默认缓存规则。Ownership 管理维护及新鲜共识检查继续使用权威读取;`resolve` 的 ownership 快照是单独的展示缓存,其 `forceRefresh` / `ownershipTtlMs` 规则不变。完整的 `read_cache`、条件读取及范围见 [Storage RPC 手册](09-storage-rpc-manual.md#sdk-默认读缓存);Group FS 适用同一策略。
|
|
510
|
+
|
|
370
511
|
### 消息与群组门面
|
|
371
512
|
|
|
372
513
|
| 能力 | Python | TS/JS | Go | 说明 |
|
|
373
514
|
|------|--------|-------|----|------|
|
|
374
|
-
| Message | `client.message` | `client.message` | `client.Message()` | 消息便利方法:`send()`、`pull()`、`history()`、`ack()`、`read()`、`read_state/readState/ReadState`、`recall()`、`queryOnline()` |
|
|
515
|
+
| Message | `client.message` | `client.message` | `client.Message()` | 消息便利方法:`send()`、`peers()`、`pull()`、`history()`、`ack()`、`read()`、`read_state/readState/ReadState`、`recall()`、`queryOnline()` |
|
|
375
516
|
| Message Thought | `client.message.thought` | `client.message.thought` | `client.Message().Thought()` | P2P 思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
|
|
376
517
|
| Group | `client.group` | `client.group` | `client.Group()` | 群组便利方法:`create()`、`send()`、`pull()`、`history()`、`ack()`、`read()`、`read_state/readState/ReadState`、群管理方法、群查询方法、群设置便利方法 |
|
|
377
518
|
| Group Thought | `client.group.thought` | `client.group.thought` | `client.Group().Thought()` | 群思考内容:`put()`、`get()`(不持久化、不分配 seq、强制 E2EE) |
|
|
@@ -380,9 +521,11 @@ Ownership 2.1 关系须检查当前双文件共识;Group/Org 使用专属生
|
|
|
380
521
|
|
|
381
522
|
业务已读与投递 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
523
|
|
|
383
|
-
`message.
|
|
524
|
+
新 SDK 声明严格布尔能力 `p2p_peer_pull_v1: true`,保留设备原共享 seq,按完整 `sender_aid` 隔离 P2P 游标。`message.pull` 指定 sender 时读取该对端;省略时先查询完整 pending `message.peers`,再通过共享 N=4 Gate 并发读取全部待同步对端。显式游标(包括 `after_seq=0`)、force 或 Tail 必须指定 sender。pending 列表不分页、不截断到 200,peer 单页 Pull/History 默认及最大 200 条。目录 `next_pending_seq` 直接使用 peer 服务端 A 作近似;调度优先采用有效非负整数提示的原值(含 0),缺失或非法才回退到 `max(已确认覆盖水位,本地A)`,不取 `max(A,hint)`,不改变应用列表顺序。
|
|
384
525
|
|
|
385
|
-
|
|
526
|
+
`message.history` 必须指定 `sender_aid`,与 `group.history` 一样使用 `before_seq` 排他上界向左翻页,下一页复用 `next_before_seq`。History 不推进实时 A/T/H、不 ACK、不触发实时消息事件。P2P 仅在已验证自身 `agent.md.type=human` 时自动优先 Tail→Forward,其余类型直接 Forward;指定 sender 后也可显式传 `window_mode="tail"`。Group 保持原实时窗口模型。
|
|
527
|
+
|
|
528
|
+
SDK 保留运行期内存去重:发布序号窗口按 namespace 保留最高 50,000 个 seq;P2P 成功交付绑定最多 50,000 条,按接收 AID、设备、slot、事件类别及原正 delivery seq 识别,另校验 sender/message_id,不因 namespace 或 Push/Pull 来源改变该 P2P 身份。消息热路径不逐条读写耐久 receipt,自定义 store 不要求提供 receipt 能力。所选应用 handler 全部成功后才完成内存标记;持久消息 Forward 页依据有效 proof 提交页 A/T/H 后,再发送本页新增累计 seq ACK,实际耐久性取决于 store 的持久化能力。volatile 与群事件 ACK 沿用各自原路径,失败不提前确认。淘汰、重建 client、进程崩溃或新旧 SDK 切换后允许重放,应用须将消息幂等与业务副作用放在同一持久事务中;持久 P2P 使用 message_id 唯一键,volatile 保留原 sender+message_id 隔离;多个 client/进程没有跨实例原子 claim。跨 peer 不保证全局回调顺序,显式 History/force/Tail 返回列表不因内存去重删行。
|
|
386
529
|
|
|
387
530
|
**群成员管理与状态方法**:
|
|
388
531
|
|
|
@@ -781,11 +924,15 @@ sub.unsubscribe()
|
|
|
781
924
|
| `token.refreshed` | token 刷新完成 |
|
|
782
925
|
| `token.refresh_exhausted` | refresh_token 缺失、过期或刷新链耗尽,SDK 已清理本地 token 并等待重新登录 |
|
|
783
926
|
| `message.received` | 收到 P2P 消息 |
|
|
927
|
+
| `message.batch` | P2P 消息/撤回批次,items 保留原 `message.received` / `message.recalled` |
|
|
928
|
+
| `message.peers_snapshot` | SDK 本地待拉对端、水位、可选 next_pending_seq 与整体积压估计;列表保持响应原顺序,应用查询成功时空/非空均发布,后台仅发布非空列表 |
|
|
784
929
|
| `message.read_changed` / `group.read_changed` | 同一 AID 共享已读位置提交并前进;owner 必须为当前身份、scope 匹配原事件 |
|
|
785
930
|
| `read_state_sync` | SDK 本地已读补偿完成,含本轮 `owner_aid`、去重 `states` 和逐项 `errors`;连接返回不表示补偿完成 |
|
|
786
931
|
| `message.undecryptable` | P2P E2EE 解密失败 |
|
|
787
932
|
| `group.message_created` | 收到群消息 |
|
|
933
|
+
| `group.message_batch` | 群消息/撤回批次,items 保留原 `group.message_created` / `group.message_recalled` |
|
|
788
934
|
| `group.changed` | 群组事件 |
|
|
935
|
+
| `group.event_batch` | 群事件批次,items 保留原 `group.changed` |
|
|
789
936
|
| `group.message_recalled` | 群消息撤回 |
|
|
790
937
|
| `group.message_undecryptable` | 群 E2EE 解密失败 |
|
|
791
938
|
| `sync.started` / `sync.progress` / `sync.stopped` | Pull 同步生命周期 |
|
|
@@ -793,13 +940,15 @@ sub.unsubscribe()
|
|
|
793
940
|
| `push.offline_message` | Push Server 收到离线唤醒批次;普通终端无需订阅 |
|
|
794
941
|
| `storage.object_changed` | Storage 对象变更事件透传 |
|
|
795
942
|
|
|
796
|
-
|
|
943
|
+
`message.ack` 通知与应用业务已读独立。peer ACK 通知携带 `cursor_scope="peer"`、`sender_aid`、`peer_ack_seq`,不能代替本地交付证明或推进旧 global 游标。`message.peers_snapshot` 包含待拉对端、水位、可选 `next_pending_seq` 与整体 `pending_count_estimate`,列表保持响应原顺序,调度只重排内部副本;next_pending_seq只作尽力调度提示,不推进游标或证明完成;取消每 peer/整体三项精确数量;估计仅透传、不求和/缺省填 0,排除 volatile,不用于同步完成或调度;Pull 最终返回页保留含本页 volatile 的三项页内计数;它通过应用事件队列发布,不等待 handler 才继续 Pull,完整字段见 [Message RPC](09-message-rpc-manual.md#messagepeers_snapshot)。已读事件只向 owner AID 分发且不进入 Pull 队列;重连查询补偿不受消息 `background_sync=false` 影响。身份切换按代际隔离旧缓存与补偿完成事件;已排队的 raw/public `read_changed` 与 `read_state_sync` 在出队和每个处理器执行前重新核对身份代际,处理器等待期间切换身份也会停止后续交付,A→B→A 同样隔离;原在途 RPC 仍可返回。详见 [跨设备已读未读 SDK 集成指南](../跨设备已读未读SDK集成指南.md)。
|
|
797
944
|
|
|
798
945
|
`message.received` 的应用层消息保留 `sender_device_id`,表示发送方设备;需要只回复原设备时,将该值作为下一次 `message.send.device_id`。volatile 消息还保留 `storage="volatile"`、`volatile_cursor`、`created_at`、`expires_at`,不含持久 `seq`;内部 slot 不会暴露给应用。
|
|
799
946
|
|
|
947
|
+
三类批量事件统一为 `{namespace,items:[{event,payload}],source}`。每个实际页固定 batch 模式与 batch handlers:订阅该类 batch 时只发 batch,否则完整沿用原逐条发布路径;single listeners 仍动态查找,没有 single 订阅也不跳过原处理链,不双发。批次不跨页或 namespace,空 items 不发布,Push/inline 单条使用单元素批次;保留原 event/payload、页内顺序和 need_render=false。全部所需 handler 成功后才进入各类型原页提交/ACK 路径,失败保留重试责任;Go 可用 `OnBatch(event, func(any) error)`,返回 error 阻止成功确认,原 `On` 保持兼容。详见 [SDK 批量消息事件](09-message-rpc-manual.md#sdk-批量消息事件)。
|
|
948
|
+
|
|
800
949
|
### delivery.changed
|
|
801
950
|
|
|
802
|
-
`delivery.changed` 是 Python、Go、JavaScript 和 TypeScript SDK 统一提供的本地事件,用于通知应用层一批消息已经完成交付,可以从业务仓库刷新相关会话 UI
|
|
951
|
+
`delivery.changed` 是 Python、Go、JavaScript 和 TypeScript SDK 统一提供的本地事件,用于通知应用层一批消息已经完成交付,可以从业务仓库刷新相关会话 UI。它不替代消息明细交付:应用通过已订阅的批量事件或原逐条事件完成业务幂等与持久化,再把 `delivery.changed` 作为批量刷新信号。
|
|
803
952
|
|
|
804
953
|
该事件由 SDK 本地 dispatcher 发布,不是 Gateway 推送事件,不属于 JSON-RPC `event/...` 协议;裸 WebSocket 客户端不会收到它。
|
|
805
954
|
|
|
@@ -819,7 +968,7 @@ sub.unsubscribe()
|
|
|
819
968
|
|------|------|------|
|
|
820
969
|
| `trigger` | string | `pull_drained`、`push` 或 `inline_push` |
|
|
821
970
|
| `changes` | array | 本次刷新涉及的 namespace,按 `namespace` 稳定排序且不重复 |
|
|
822
|
-
| `changes[].namespace` | string | P2P
|
|
971
|
+
| `changes[].namespace` | string | P2P 仍聚合为逻辑名称 `p2p`,不是内部 peer Pull namespace;群消息为 `group:<canonical-group-aid>` |
|
|
823
972
|
| `changes[].delivered_count` | integer | 本次合并窗口内已发布到应用层的原消息事件数;不是未读数、服务端页大小或最大 seq |
|
|
824
973
|
|
|
825
974
|
触发与折叠规则:
|
|
@@ -829,7 +978,7 @@ sub.unsubscribe()
|
|
|
829
978
|
- 有效的 `push` / `inline_push` 可以原子吸收尚未通知的 Pull 变更;这些变更不会在后续 `pull_drained` 中再次通知。
|
|
830
979
|
- 空 Pull、重复或过滤消息、非法 payload、解密失败,以及未带来有效消息交付的 Head 通知,不发布 `delivery.changed`。
|
|
831
980
|
|
|
832
|
-
`delivery.changed` 只表示 UI
|
|
981
|
+
`delivery.changed` 只表示 UI 刷新时机,不是消息明细或持久化账本。应用仓库仍应按照原消息业务身份幂等,并在对应会话内按 `seq` 排序。
|
|
833
982
|
|
|
834
983
|
### 消息来源 `source`
|
|
835
984
|
|
|
@@ -856,7 +1005,7 @@ sub.unsubscribe()
|
|
|
856
1005
|
"source": "pull",
|
|
857
1006
|
"syncing": true,
|
|
858
1007
|
"namespaces_pending": 1,
|
|
859
|
-
"namespace": "p2p",
|
|
1008
|
+
"namespace": "p2p.peer.v1/YWxpY2UuYWdlbnRpZC5wdWI",
|
|
860
1009
|
"received_total": 0,
|
|
861
1010
|
"started_at": 1730000000000
|
|
862
1011
|
}
|
|
@@ -868,7 +1017,7 @@ sub.unsubscribe()
|
|
|
868
1017
|
{
|
|
869
1018
|
"run_id": 7,
|
|
870
1019
|
"source": "pull",
|
|
871
|
-
"namespace": "p2p",
|
|
1020
|
+
"namespace": "p2p.peer.v1/YWxpY2UuYWdlbnRpZC5wdWI",
|
|
872
1021
|
"page": 2,
|
|
873
1022
|
"page_raw_count": 50,
|
|
874
1023
|
"page_pulled_count": 48,
|
|
@@ -16,7 +16,7 @@ async def ensure_ready(aid: str) -> AUNClient:
|
|
|
16
16
|
loaded = store.load(aid)
|
|
17
17
|
|
|
18
18
|
me = loaded["data"]["aid"]
|
|
19
|
-
client = AUNClient(me)
|
|
19
|
+
client = AUNClient(me)
|
|
20
20
|
await client.connect({"slot_id": "main", "auto_reconnect": True})
|
|
21
21
|
return client
|
|
22
22
|
```
|
|
@@ -65,7 +65,7 @@ async def close_all(*clients: AUNClient):
|
|
|
65
65
|
sender.e2ee.invalidate_prekey_cache(peer_aid=receiver_aid)
|
|
66
66
|
receiver.e2ee.invalidate_prekey_cache(peer_aid=sender_aid)
|
|
67
67
|
|
|
68
|
-
cursor = await receiver.call("message.pull", {"after_seq": 0, "limit": 1})
|
|
68
|
+
cursor = await receiver.call("message.pull", {"sender_aid": sender_aid, "after_seq": 0, "limit": 1})
|
|
69
69
|
recv_cursor = cursor.get("latest_seq", 0)
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -78,62 +78,63 @@ recv_cursor = cursor.get("latest_seq", 0)
|
|
|
78
78
|
实例级 `protected_headers` 适合放 SDK 版本、运行环境、调用方链路标识等需要签名保护的元数据:
|
|
79
79
|
|
|
80
80
|
```python
|
|
81
|
-
client = AUNClient(me)
|
|
82
|
-
client.set_protected_headers({"sdk": "python", "trace": "abc"})
|
|
81
|
+
client = AUNClient(me)
|
|
82
|
+
client.set_protected_headers({"sdk": "python", "trace": "abc"})
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
只对 `message.send`、`group.send`、`message.thought.put`、`group.thought.put` 生效。
|
|
86
86
|
|
|
87
87
|
---
|
|
88
88
|
|
|
89
|
-
## 6. Flow Control
|
|
90
|
-
|
|
91
|
-
SDK 内部自动管理 RPC 并发,应用层无需配置:
|
|
89
|
+
## 6. Flow Control
|
|
90
|
+
|
|
91
|
+
SDK 内部自动管理 RPC 并发,应用层无需配置:
|
|
92
92
|
|
|
93
93
|
| 机制 | 说明 |
|
|
94
94
|
|------|------|
|
|
95
|
-
| RPC 并发上限 | 全局最多 16 个并发 RPC 请求 |
|
|
96
|
-
| 后台 RPC 限制 | 后台任务额外限制为 8 个 |
|
|
95
|
+
| RPC 并发上限 | 全局最多 16 个并发 RPC 请求 |
|
|
96
|
+
| 后台 RPC 限制 | 后台任务额外限制为 8 个 |
|
|
97
97
|
| Pull Gate | 四端均为每个 `AUNClient` 一个客户端级 Gate;P2P Message、Group Message、Group Event Pull 共享,同 namespace 单飞,不同 namespace 最多 4 个并行 |
|
|
98
|
-
| 队列优先级 | Tail/History 前台 FIFO 优先于 Forward/Gap Fill 后台 FIFO;Group Event Pull 为后台;同 key 自动折叠 |
|
|
99
|
-
|
|
98
|
+
| 队列优先级 | Tail/History 前台 FIFO 优先于 Forward/Gap Fill 后台 FIFO;Group Event Pull 为后台;同 key 自动折叠 |
|
|
99
|
+
|
|
100
100
|
同一 namespace 的 Tail、History、Forward 保持单飞;相同 key 的调用共享同一结果,其余可运行请求按前台优先、队列顺序调度。namespace 划分见 [核心概念](03-核心概念.md#消息实时窗口与历史拉取)。应用层保持普通 `await client.call(...)` 即可,不应自行实现重复并发控制。
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## 7. 消息同步与历史读取
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
- 冷启动缺 sender IK 时允许 SDK 最多同步等待 3 秒 bootstrap;同发送端并发请求自动合并。成功后当前消息立即重试解密,失败或超时才 pending,不要在应用层并发重复拉取 IK。
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
- 用 `message.history(before_seq=..., limit=...)` 或 `group.history(group_id=..., before_seq=..., limit=...)`
|
|
112
|
-
- Forward
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 7. 消息同步与历史读取
|
|
105
|
+
|
|
106
|
+
- P2P 上线/Push 提示由 SDK 查询完整 pending peers 并按 peer 同步;已验证自身 type=human 才自动优先 Tail→Forward,其余直接 Forward。不要用对端 type 决定接收策略,Group 保持原行为。
|
|
107
|
+
- peer A/ACK 只越过已解密并成功交付的消息,覆盖证明不能跳过失败回调;运行中的 server ACK 不替代本地交付。Group 保持原终态规则。
|
|
108
|
+
- 冷启动缺 sender IK 时允许 SDK 最多同步等待 3 秒 bootstrap;同发送端并发请求自动合并。成功后当前消息立即重试解密,失败或超时才 pending,不要在应用层并发重复拉取 IK。
|
|
109
|
+
- 单个 Tail/Forward 响应页内按 seq 升序处理;A/T/H 描述可靠同步进度,SDK 用 50,000 条运行期内存成功记录协调重复交付,不逐条读写持久 receipt。
|
|
110
|
+
- 订阅批量事件时只走 batch,否则完整沿用原单条发布链;全部所需 handler 成功→内存成功标记→可靠页 A/T/H→ACK。内存淘汰、重建 client、崩溃及版本切换后允许重放,应用将消息业务身份去重与副作用放在同一持久事务中。跨 peer 不保证全局回调顺序,volatile 和 Group 维持原去重边界。
|
|
111
|
+
- 用 `message.history(sender_aid=..., before_seq=..., limit=...)` 或 `group.history(group_id=..., before_seq=..., limit=...)` 向左翻页;下一页复用 `next_before_seq`。History 不影响实时游标和 ACK,History/force 返回列表不因内存去重删行。
|
|
112
|
+
- peer Forward 仅按验证通过的覆盖证明及严格 `has_more` 续拉;Group 保持原续页规则。volatile 消息按独立游标及 `volatile_has_more` 续页。正常后页携带已提交水位的 Piggy ACK,末页以独立 ACK 收尾,不会只为 ACK 额外拉取空页。ACK 失败保留待确认水位,供后续 Pull 重试。
|
|
113
|
+
- peer Forward 使用稀疏覆盖证明及严格的持久/volatile `has_more`,不由恰好满页推断;后台 `max_pages` 是工作片预算,达到 100 页后仍有积压会自主续调度。公开无 sender 的 Pull 是全部 pending peer 的聚合,显式游标/force/Tail 必须指定 sender。
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 8. Group Index 更新流程
|
|
118
|
+
|
|
119
|
+
公告、规则、入群要求属于 indexed settings。owner/admin 修改这些内容时,不要直接裸调 `group.set_settings` 写单个 key,应使用 SDK facade 的 `updateGroupIndex` 语义。
|
|
120
|
+
|
|
121
|
+
推荐流程:
|
|
122
|
+
|
|
123
|
+
1. 调用 `checkGroupIndex` 判断本地已处理 etag 与观察到的远端 etag 是否不同步。
|
|
124
|
+
2. 如果不同步,由应用层决定以本地还是远端为准:选择远端时调用 `getGroupIndex` 显式 pull,选择本地时继续保留本地缓存并准备 push。
|
|
125
|
+
3. 在选定基线上合并本地要修改的 settings 和附件稳定引用。
|
|
126
|
+
4. 调用 `updateGroupIndex`。SDK 会读取当前服务端 index、生成新签名 index,并带 `expected_index_etag` 调用 `group.set_settings`。
|
|
127
|
+
5. 如果服务端返回 `group.index etag conflict`,说明提交基线已变化;应用层需要重新决定 pull、merge 或保留本地修改后再提交。
|
|
128
|
+
|
|
129
|
+
`getAnnouncement`、`getRules`、`getJoinRequirements` 只读 SDK 本地缓存;本地没有对应值时才读取相应 settings 初始化缓存,不会因为 etag 不一致自动 pull 远端。`updateAnnouncement`、`updateRules`、`updateJoinRequirements` 已内置 indexed 写入路径。普通不进入 index 的设置,例如 `mention_mode`,仍可直接使用 `setSettings` / `set_settings` / `SetSettings`。
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 9. 测试数据保护
|
|
134
|
+
|
|
135
|
+
- 不要删除 `AIDs/` 下的私钥、证书、seed、数据库或 token 文件。
|
|
136
|
+
- 不要并行跑共享同一身份材料的集成 / E2E / 跨域测试。
|
|
137
|
+
- 需要换身份时使用新的 AID 名称,避免制造不可恢复的 key mismatch。
|
|
137
138
|
|
|
138
139
|
---
|
|
139
140
|
|
|
@@ -1269,6 +1269,7 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
|
|
|
1269
1269
|
| `payload` | object | 否 | 消息内容 |
|
|
1270
1270
|
| `type` | string | 否 | 信封/封装类型,普通业务消息无需填写;SDK 加密群消息时自动使用 `e2ee.group_encrypted` |
|
|
1271
1271
|
| `attachments` | array | 否 | 兼容旧接口的顶层附件元数据;推荐把业务附件放入 `payload.attachments` |
|
|
1272
|
+
| `need_render` | boolean | 否 | 默认 `true`,表示消息是否需要应用渲染;不改变群 seq/Pull/ACK 模型 |
|
|
1272
1273
|
| `protected_headers` / `headers` | object | 否 | SDK 加密前读取的 E2EE 信封元数据,类似 HTTP headers;推荐使用 `protected_headers`,`headers` 仅作为兼容别名;服务端不解释,接收端验 `_auth` 后在 `e2ee.protected_headers` 暴露 |
|
|
1273
1274
|
|
|
1274
1275
|
### Payload 参考约定
|
|
@@ -1277,6 +1278,8 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
|
|
|
1277
1278
|
|
|
1278
1279
|
`protected_headers` 只在 SDK 加密路径生效;裸 RPC 发送明文或已加密信封时,调用方需自行遵守 [05-E2EE加密通信](05-E2EE加密通信.md#protectedheaders-与可验证上下文) 的格式和校验规则。
|
|
1279
1280
|
|
|
1281
|
+
`need_render` 与 P2P 一致,由 SDK 提取到外层信封,接收消息保留该标记;历史缺字段或 NULL 按 `true`。该字段不参与 E2EE AAD、`protected_headers`、消息保护签名或元数据 HMAC,RPC `client_signature` 仍按既有完整业务参数规则覆盖它。服务端不按此标记拆流或优先拉取。
|
|
1282
|
+
|
|
1280
1283
|
**响应**:
|
|
1281
1284
|
|
|
1282
1285
|
```json
|
|
@@ -1438,7 +1441,7 @@ result = await client.call("group.thought.get", {
|
|
|
1438
1441
|
|------|------|------|--------|------|
|
|
1439
1442
|
| `group_id` | string | 是 | — | 群组标识;兼容字段,值语义为目标态 `group_aid` |
|
|
1440
1443
|
| `after_message_seq` | integer | 否 | 0 | 从该消息 seq 之后拉取 |
|
|
1441
|
-
| `limit` | integer | 否 | 50 |
|
|
1444
|
+
| `limit` | integer | 否 | 50 | Python V2 Forward 最大 200;其余模式保留原限制,`pull_max_limit` 配置可进一步收紧 |
|
|
1442
1445
|
| `device_id` | string | 否 | — | 设备 ID(多设备模式) |
|
|
1443
1446
|
|
|
1444
1447
|
**响应**:
|
|
@@ -1459,7 +1462,7 @@ result = await client.call("group.thought.get", {
|
|
|
1459
1462
|
|
|
1460
1463
|
旧 `group.pull` 的服务端 `has_more` 通过 `limit + 1` 可见消息探测及响应截页确定,表示仍有当前成员可见的消息未返回,不由 `unread_count` 或恰好满页推断。底层 `group.v2.pull` 的 Forward 响应可不含该字段,SDK 仍结合 head 与游标判断是否续页。
|
|
1461
1464
|
|
|
1462
|
-
|
|
1465
|
+
Group V2 拉取默认每页 50;Python SDK 的 Forward 上限已为 200。直接调用底层 `group.v2.pull` 时,服务端默认 50、最大 200,受 `pull_max_limit` 配置进一步限制;旧 `group.pull`、`group.history` 与 `group.pull_events` 仍为最大 50。
|
|
1463
1466
|
|
|
1464
1467
|
`group.pull` 是公开的 Forward Pull。实时 A/T/H 最新页同步由 SDK 内部自动完成,不提供需要应用传入的模式参数。普通 Forward 中,`retention_floor_message_seq` 只表示已提交物理 GC;`earliest_available_message_seq-1` 表示服务端综合 retention、入群点和 epoch 后的当前成员可见性排他下界。SDK 以 `max(retention_floor_message_seq, cursor.join_seq, earliest_available_message_seq-1)` 推进 A;History 不修改 A/T/H。
|
|
1465
1468
|
|
|
@@ -1580,6 +1583,12 @@ SDK 只保证单个实时拉取响应页内按 seq 升序、同 seq 最多发布
|
|
|
1580
1583
|
- 上传控制面会透传 `parents` 到 storage:默认 `parents=true` 时可递归创建父目录,显式 `parents=false` 时父目录必须已存在。
|
|
1581
1584
|
- JavaScript 浏览器版 `cp(string, group)` 默认把 string 当文本内容上传;Node 本地路径需显式传 `sourceType: "path"`、`localPath: true` 或使用 `local:` 前缀。Python、TypeScript 和 Go 默认把 string 当本地路径。
|
|
1582
1585
|
|
|
1586
|
+
### SDK 默认读缓存
|
|
1587
|
+
|
|
1588
|
+
四个 SDK 的 Group FS 元数据查询与符合条件的完整下载正文复用 Storage 读缓存规则:服务端缺少或返回 `null` 的 `read_cache` 时默认缓存,元数据 TTL 为 60 秒,默认正文上限为 65,536 字节并校验 SHA-256。显式允许策略须 `reusable: true`,正文还须 `inline: true`;省略 `max_age_ms` 时默认 60 秒,有限正数最多使用 60 秒。显式禁止、null/非正数/非法 TTL 不复用。大正文不进入缺省 inline 缓存,Group 服务仍仅返回票据,由 SDK 完成 HTTP 下载。
|
|
1589
|
+
|
|
1590
|
+
单次调用可用 TS/JS `noCache: true`(兼容 `no_cache`)、Python `no_cache=True` 或 Go 对应 Group FS Options 的 `NoCache: true` 强制远端校验。该选项由 SDK 消费,既有 SHA-256 仍可用于条件读取,新结果仍可缓存;它不等于 no-store。缓存按调用身份及群路径/参数隔离,群文件写入和 ACL 等相关变更继续触发失效。完整策略和条件读取说明见 [Storage RPC 手册](09-storage-rpc-manual.md#sdk-默认读缓存)。
|
|
1591
|
+
|
|
1583
1592
|
### group.fs.ls
|
|
1584
1593
|
|
|
1585
1594
|
列出目录。参数:`path` 必填;可选 `page`、`size`、`marker`、`long`、`recursive`。响应返回 group view `items`,节点 `path` 仍为 group path。
|
|
@@ -1604,8 +1613,12 @@ SDK 只保证单个实时拉取响应页内按 seq 升序、同 seq 最多发布
|
|
|
1604
1613
|
|
|
1605
1614
|
创建下载票据。参数:`path` 必填。响应包含 `url` / `download_url`、`expire_at`,以及可选的 `token`、`sha256`、`content_type`、`file_name`。私有文件和跨 issuer 文件由资源所在域签发短 TTL 的 `?t=` 能力凭据;Group 只返回票据,不代理文件字节。
|
|
1606
1615
|
|
|
1616
|
+
还支持 `if_sha256`(string,64 位十六进制完整正文摘要)和 `consistency`;服务端向 Storage 传递这两个条件,响应可包含 `read_cache`(object)及 `not_modified`(boolean)。当前访问校验通过且摘要匹配时可只返回对象元数据,不签发新 URL/token;SDK 必须已有摘要匹配且验证通过的正文才能复用,否则重新申请完整票据。范围读取不复用普通完整正文缓存,`noCache`/`no_cache` 由 SDK 消费,不是本 RPC 的业务参数。字段类型及策略见 [Storage 条件读取](09-storage-rpc-manual.md#策略字段与条件读取)。
|
|
1617
|
+
|
|
1607
1618
|
SDK Group FS 门面使用票据执行 HTTP GET 并校验 sha256。应用自行下载时遵守与 `storage.create_download_ticket` 相同的数据面规则:完整保留 URL 中的 `?t=`;只有端点明确要求 AID Bearer 时,才在每次请求前调用 Python `get_access_token()`、TypeScript / JavaScript `getAccessToken()` 或 Go `GetAccessToken()`;不得长期复用 `authenticate()` 首次返回的 token,也不得把当前域的 AID JWT 发送给另一 issuer 的 storage。401/403 仅在重新读取到不同 token 时重试一次;票据过期应重新申请。完整流程见 [Storage RPC 手册](09-storage-rpc-manual.md#数据面-http-下载流程)。
|
|
1608
1619
|
|
|
1620
|
+
Group FS 的读缓存保存符合策略的已验证正文,不把下载票据及其 token/URL 长期保存复用;热命中不联网,远端修改或撤权可能到刷新/TTL 到期才被观察,默认最多 60 秒。身份/网关隔离、写入及权限变更失效、持久后端、已对齐分支和验证边界见 [0.5.22 移植指南](0.5.22-SDK开发与移植指南.md#61-storage--group-fs-默认读缓存)。
|
|
1621
|
+
|
|
1609
1622
|
### group.fs.set_acl
|
|
1610
1623
|
|
|
1611
1624
|
授予群自有区角色 ACL。需要当前 group `owner/admin` 身份调用;底层由 group 服务以内部门面写入 `storage.set_acl`。
|