@agentunion/fastaun 0.5.31 → 0.5.33
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 +69 -1
- package/_packed_docs/CHANGELOG.md +69 -1
- package/_packed_docs/sdk/0.5.32-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +350 -0
- package/_packed_docs/sdk/0.5.32-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +319 -0
- package/_packed_docs/sdk/0.5.33-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +316 -0
- package/_packed_docs/sdk/0.5.33-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +304 -0
- package/_packed_docs/sdk/09-storage-rpc-manual.md +33 -16
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +12 -5
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +459 -0
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/274/200/345/217/221/347/247/273/346/244/215/346/214/207/345/215/227.md +554 -0
- package/_packed_docs/sdk/INDEX.md +27 -5
- package/_packed_docs/sdk//345/255/220AID/344/277/256/346/224/271agent.md/351/200/232/347/237/245Owner/345/234/272/346/231/257/346/214/207/345/215/227.md +234 -0
- package/dist/agent-md.d.ts +2 -1
- package/dist/agent-md.js +17 -0
- package/dist/agent-md.js.map +1 -1
- package/dist/client/control-messages.d.ts +22 -6
- package/dist/client/control-messages.js +210 -148
- package/dist/client/control-messages.js.map +1 -1
- package/dist/client/delivery.d.ts +3 -0
- package/dist/client/delivery.js +67 -3
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts +3 -0
- package/dist/client/group-state.js +48 -14
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/lifecycle.js +3 -2
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +9 -3
- package/dist/client/rpc-pipeline.js +80 -27
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +13 -1
- package/dist/client/v2-e2ee.js +32 -19
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +13 -5
- package/dist/client.js +121 -37
- package/dist/client.js.map +1 -1
- package/dist/group-fs.js +1 -1
- package/dist/group-fs.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ownership-workflow.d.ts +23 -3
- package/dist/ownership-workflow.js +39 -16
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/pubsub/binding.d.ts +54 -0
- package/dist/pubsub/binding.js +343 -0
- package/dist/pubsub/binding.js.map +1 -0
- package/dist/pubsub/channel.d.ts +45 -0
- package/dist/pubsub/channel.js +137 -0
- package/dist/pubsub/channel.js.map +1 -0
- package/dist/pubsub/client.d.ts +93 -0
- package/dist/pubsub/client.js +318 -0
- package/dist/pubsub/client.js.map +1 -0
- package/dist/pubsub/credentials.d.ts +51 -0
- package/dist/pubsub/credentials.js +360 -0
- package/dist/pubsub/credentials.js.map +1 -0
- package/dist/pubsub/errors.d.ts +5 -0
- package/dist/pubsub/errors.js +6 -0
- package/dist/pubsub/errors.js.map +1 -0
- package/dist/pubsub/index.d.ts +48 -0
- package/dist/pubsub/index.js +152 -0
- package/dist/pubsub/index.js.map +1 -0
- package/dist/pubsub/scheduler.d.ts +58 -0
- package/dist/pubsub/scheduler.js +249 -0
- package/dist/pubsub/scheduler.js.map +1 -0
- package/dist/pubsub/service.d.ts +100 -0
- package/dist/pubsub/service.js +650 -0
- package/dist/pubsub/service.js.map +1 -0
- package/dist/pubsub/types.d.ts +119 -0
- package/dist/pubsub/types.js +2 -0
- package/dist/pubsub/types.js.map +1 -0
- package/dist/storage/lowlevel.d.ts +4 -2
- package/dist/storage/lowlevel.js +46 -7
- package/dist/storage/lowlevel.js.map +1 -1
- package/dist/storage/read-cache.d.ts +7 -3
- package/dist/storage/read-cache.js +149 -18
- package/dist/storage/read-cache.js.map +1 -1
- package/dist/storage/vfs.d.ts +5 -2
- package/dist/storage/vfs.js +13 -3
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +8 -2
- package/dist/tools/cross-sdk-agent.js +81 -16
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/tools/pubsub-actor.d.ts +27 -0
- package/dist/tools/pubsub-actor.js +260 -0
- package/dist/tools/pubsub-actor.js.map +1 -0
- package/dist/transport.d.ts +25 -1
- package/dist/transport.js +175 -10
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# AUN SDK 0.5.32 开发与移植指南
|
|
2
|
+
|
|
3
|
+
面向四端 SDK 维护者和新语言移植者,说明相对已发布 0.5.31 的实现顺序、关键约束和验收方法。目标 0.5.32 尚未发布,本文按 2026-11-05 工作区整理;应用接线见 [0.5.32 应用集成指南](0.5.32-SDK应用集成指南.md)。
|
|
4
|
+
|
|
5
|
+
## 1. 本版范围与实现分层
|
|
6
|
+
|
|
7
|
+
源码对照提交为 `2df732673`。已核验 0.5.31 Python 发布包的 135 个源文件与其一致,TS/JS 各 11 个关键编译文件与其转译结果一致;Go 使用该仓库参考点,本轮未取得可核验的 0.5.31 远端 tag。详细增量与发布证据见 [parity 0.5.32](../../python/CHANGES_FOR_PARITY.md#v0532)。
|
|
8
|
+
|
|
9
|
+
本版新增 EventService,调整分类消息恢复、RPC 后台隔离及 VFS Cache;群/组织通用共识、`message_classes_v2`、无 `scan_proof` ACK 和严格 CAS 已由 0.5.31 提供。
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
%%{init: {"theme":"base","flowchart":{"curve":"linear","nodeSpacing":26,"rankSpacing":34}}}%%
|
|
13
|
+
flowchart TB
|
|
14
|
+
subgraph SDK["各 Agent 进程内的 SDK"]
|
|
15
|
+
direction TB
|
|
16
|
+
F["AUNClient 门面<br/>EventService · VFS / Storage"]:::entry
|
|
17
|
+
subgraph EVENT["事件逻辑"]
|
|
18
|
+
direction LR
|
|
19
|
+
P["Pub<br/>目录缓存 · 有界发布队列"]:::role
|
|
20
|
+
B["Bus<br/>授权 · 设备订阅 · 公平 fanout"]:::bus
|
|
21
|
+
S["Sub<br/>接收校验 · 应用交付"]:::role
|
|
22
|
+
end
|
|
23
|
+
V["VFS Cache<br/>资源索引 · 正文校验 · 写版本"]:::cache
|
|
24
|
+
T["公共传输层<br/>分类 Pull · RPC 预算 · deadline · E2EE"]:::entry
|
|
25
|
+
F --> P & B & S & V
|
|
26
|
+
P & B & S & V --> T
|
|
27
|
+
end
|
|
28
|
+
G["Gateway<br/>认证连接 · 可信 AID / device / slot · 转发"]:::infra
|
|
29
|
+
M["Message<br/>Bus 单实例租约 · 设备定向 TTL 收件箱"]:::infra
|
|
30
|
+
C["Credential<br/>登记 · 状态证明 · 撤销"]:::infra
|
|
31
|
+
R["Storage / Group<br/>对象 · 权威版本 · CAS"]:::infra
|
|
32
|
+
T --> G
|
|
33
|
+
G --> M & C & R
|
|
34
|
+
classDef entry fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
|
|
35
|
+
classDef role fill:#f0fdf4,stroke:#16a34a,color:#14532d
|
|
36
|
+
classDef bus fill:#ede9fe,stroke:#7c3aed,color:#4c1d95
|
|
37
|
+
classDef cache fill:#fff7ed,stroke:#ea580c,color:#7c2d12
|
|
38
|
+
classDef infra fill:#f8fafc,stroke:#64748b,color:#0f172a
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
图中 Pub、Bus、Sub 通常属于不同 AID。每个 Client 按 `bus_aid` 保存绑定,同一 Bus 仅绑定一种角色;`close` 后角色约束保留,不同 Bus 可担任不同角色。Message 只维护唯一承接设备与通用定向收件箱;事件目录、权限、订阅表和分发算法都在 Bus SDK。
|
|
42
|
+
|
|
43
|
+
| 实现层 | Python | TS/JS | Go |
|
|
44
|
+
| --- | --- | --- | --- |
|
|
45
|
+
| 公共门面 | `client.EventService` | `client.EventService` | `client.EventService()` |
|
|
46
|
+
| 生命周期 | `start/drain/close/update_config` | `start/drain/close/updateConfig` | `Start/Drain/Close/UpdateConfig` |
|
|
47
|
+
| 授权与目录 | `authorize/renew/catalog` | 同名 | `Authorize/Renew/Catalog` |
|
|
48
|
+
| 发布结果 | `publish/wait_published/on_publish` | `publish/waitPublished/onPublish` | `Publish/WaitPublished/OnPublish` |
|
|
49
|
+
| 订阅与应用交付 | `subscribe/unsubscribe/on_event/next_event` | `subscribe/unsubscribe/onEvent/nextEvent` | `Subscribe/Unsubscribe/OnEvent/NextEvent` |
|
|
50
|
+
| 本地 Bus 管理 | `issue_grant/revoke_grant/stats` | `issueGrant/revokeGrant/stats` | `IssueGrant/RevokeGrant/Stats` |
|
|
51
|
+
|
|
52
|
+
以下伪代码描述 SDK 内部顺序,公开方法使用上表名称。完整事件字段与错误码见 [事件服务开发移植指南](AUN事件发布订阅开发移植指南.md)。
|
|
53
|
+
|
|
54
|
+
## 2. Bus:先注册承接设备,再开放接收
|
|
55
|
+
|
|
56
|
+
`start` 要求 `bus_aid` 等于自身 AID;Pub/Sub 由 `authorize` 初始化。Bus 启动默认凭证适配器、核心和 Binding,注册成功后才接管消息。服务端从认证连接取得设备身份,不能信任请求正文自报的设备。
|
|
57
|
+
|
|
58
|
+
```mermaid
|
|
59
|
+
sequenceDiagram
|
|
60
|
+
autonumber
|
|
61
|
+
participant H as Bus 宿主应用
|
|
62
|
+
participant B as Bus SDK
|
|
63
|
+
participant G as Gateway
|
|
64
|
+
participant M as Message
|
|
65
|
+
H->>B: EventService.start(bus_aid, options)
|
|
66
|
+
B->>B: 载入配置和默认凭证材料,生成 registration_id
|
|
67
|
+
B->>G: message.evtsvc.register
|
|
68
|
+
G->>M: 可信 AID / device / slot + registration_id
|
|
69
|
+
alt 已有其它承接实例
|
|
70
|
+
M-->>B: DEVICE_CONFLICT,经 Gateway 返回
|
|
71
|
+
B-->>H: 启动失败
|
|
72
|
+
else 注册成功
|
|
73
|
+
M-->>B: ttl_seconds=100,renew_after_seconds=30
|
|
74
|
+
B->>B: 保存保守期限,启动接收与调度
|
|
75
|
+
B-->>H: 启动成功
|
|
76
|
+
loop 实例有效期间,每 30 秒
|
|
77
|
+
B->>G: message.evtsvc.renew
|
|
78
|
+
G->>M: 当前 registration_id
|
|
79
|
+
M-->>B: 新期限,经 Gateway 返回
|
|
80
|
+
end
|
|
81
|
+
H->>B: close(bus_aid)
|
|
82
|
+
B->>B: 停接收、取消在途任务、清理队列
|
|
83
|
+
B->>G: message.evtsvc.unregister
|
|
84
|
+
G->>M: 注销当前承接实例
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
代次 = 当前生命周期代次
|
|
90
|
+
请求起点 = 单调时钟()
|
|
91
|
+
租约 = register(当前注册令牌)
|
|
92
|
+
确认回复属于当前令牌和代次
|
|
93
|
+
截止 = 请求起点 + 租约.ttl_seconds
|
|
94
|
+
仅在单调时钟() < 截止时接管和发送
|
|
95
|
+
失租时关闭接收、worker 与 fanout
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
期限从请求发出前起算,不能从慢回复到达后再加 100 秒。续期超时不越过已有截止;失租后显式重启使用新注册令牌,旧回复、队列和任务不得进入新代次。`drain` 等待已有工作,应用应先停止产生新事件,再排空并关闭。
|
|
99
|
+
|
|
100
|
+
| 状态 | 默认保存位置 | 恢复要求 |
|
|
101
|
+
| --- | --- | --- |
|
|
102
|
+
| 默认凭证签发/登记/撤销材料和结果 | Python/Go/Node TS:自身 `{aun_path}/AIDs/{self-aid}/aun.db`,键 `pubsub_credentials_v1`;浏览器 JS:IndexedDB `aun-keystore/metadata`,同键并按 AID 隔离 | 恢复原操作,不重复签发;显式存储优先 |
|
|
103
|
+
| Bus 配置与服务状态 | Python `state_path`、Go `StatePath`;TS/JS `state.load/save` | 应用显式配置,区别于默认凭证入库 |
|
|
104
|
+
| 运行时租约、订阅关系、队列与事件正文 | 有界内存 | 重新鉴权与恢复订阅意图,不作为重启消息账本 |
|
|
105
|
+
|
|
106
|
+
凭证适配器可独立覆盖:TS/JS 使用 `credentialOptions.state.load/save`,Python/Go 显式状态路径优先。关闭时要完成本代在途持久化,不能让旧任务写入新身份的状态。
|
|
107
|
+
|
|
108
|
+
## 3. Pub/Sub:完整鉴权后一次提交目录和租约
|
|
109
|
+
|
|
110
|
+
白名单依据可信 AID 判断;事件名或 AID 的 `*` 表示不限制,仅建议用于受控本机多 Agent。凭证由 Bus AID 签发、Bus SDK 完整验证;Credential 服务登记并提供签名状态证明和撤销。应用审批后调用本地 Bus 的签发方法;签发、撤销和统计不经 Pub/Sub 通道开放,也不设置 manager。
|
|
111
|
+
|
|
112
|
+
```mermaid
|
|
113
|
+
sequenceDiagram
|
|
114
|
+
autonumber
|
|
115
|
+
participant A as Bus 宿主应用
|
|
116
|
+
participant B as Bus SDK
|
|
117
|
+
participant C as Credential,经 Gateway
|
|
118
|
+
participant P as Pub 或 Sub SDK
|
|
119
|
+
participant N as Gateway / Message
|
|
120
|
+
opt 应用批准凭证授权
|
|
121
|
+
A->>B: 本地 issue_grant / issueGrant
|
|
122
|
+
B->>B: Bus AID 私钥签发
|
|
123
|
+
B->>C: 登记凭证,保存原操作材料
|
|
124
|
+
C-->>B: 登记证据
|
|
125
|
+
B-->>A: grant 与登记结果
|
|
126
|
+
A->>P: 通过应用渠道提供 grant
|
|
127
|
+
end
|
|
128
|
+
P->>N: authorize,scope 与授权材料
|
|
129
|
+
N->>B: SDK 消息,携可信发送设备
|
|
130
|
+
B->>B: 白名单检查,或完整凭证验证
|
|
131
|
+
opt 凭证模式需要状态证明
|
|
132
|
+
B->>C: 获取并校验绑定本次请求的状态证明
|
|
133
|
+
C-->>B: 状态及有效期
|
|
134
|
+
end
|
|
135
|
+
B-->>P: 经 Gateway / Message 返回租约与目录首页
|
|
136
|
+
loop 首页带 next_page_token
|
|
137
|
+
P->>N: catalog,当前租约与续页 token
|
|
138
|
+
N->>B: 请求授权范围内的下一页
|
|
139
|
+
B-->>P: 经 Gateway / Message 返回目录页
|
|
140
|
+
end
|
|
141
|
+
P->>P: 全部续页成功且代次有效,提交授权、租约并更新目录缓存
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
候选 = 请求 authorize
|
|
146
|
+
暂存目录 = 校验(候选.catalog)
|
|
147
|
+
当仍有续页 token:校验并暂存 catalog 下一页
|
|
148
|
+
确认当前生命周期代次仍有效
|
|
149
|
+
全部成功:提交候选授权、租约并合并目录缓存
|
|
150
|
+
任一步失败:保留原来的本地授权状态
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`authorize` 返回值保留首页,取得的目录合并到 SDK 缓存。内嵌目录最多 2 KiB UTF-8 JSON;包含封装的单次回复最多 64 KiB。首页放不下一条时允许空首页与 offset=0 续页;Bus 校验 token 绑定的身份、租约、scope、revision 和期限,客户端检查响应关联、代次及续页进展。分页默认 50、最大 200,目录变化后重新取首页。
|
|
154
|
+
|
|
155
|
+
Pub/Sub 默认每 1 小时续期,租约 200 分钟,绑定 AID/device/slot。凭证到期会缩短租约;状态证明过期需复核,不能据本地长租约继续使用已撤销授权。续租不能扩权,缩权、撤销、设备切换及迟到校验结果都要核对当前代次。
|
|
156
|
+
|
|
157
|
+
## 4. 消息与调度:有界接管,再公平分发
|
|
158
|
+
|
|
159
|
+
| 线上层级 | 移植约定 |
|
|
160
|
+
| --- | --- |
|
|
161
|
+
| Pub → Bus、Bus → Sub、业务回复 | E2EE P2P `message.send`,正整数 TTL,volatile |
|
|
162
|
+
| SDK 消费标记 | `message_class=sdk_control`,受保护 `sdk_control_protocol=aun.pubsub`、`sdk_control_version=1` |
|
|
163
|
+
| 消息正文 | 外层 `payload.type=e2ee.p2p_encrypted`;解密后 `type=app.pubsub.v1`,事件 `op=event`,`data` 为 JSON 对象 |
|
|
164
|
+
| 发往 Bus | 受保护 `service_target=event_service`,由 Message 路由到有效承接实例 |
|
|
165
|
+
| 回复/事件定向 | 受保护 `target_device_id/target_slot_id`;授权关联可信发送设备,不从正文取得权限 |
|
|
166
|
+
| 关联与幂等 | 回复核对 Bus、op、request_id、event_id;物理投递 ID 区分目标设备/slot;Bus 按发布者 AID+event_id 保留摘要并检查冲突 |
|
|
167
|
+
|
|
168
|
+
```mermaid
|
|
169
|
+
sequenceDiagram
|
|
170
|
+
autonumber
|
|
171
|
+
participant A as 发布应用
|
|
172
|
+
participant P as Pub SDK
|
|
173
|
+
participant N as Gateway / Message
|
|
174
|
+
participant B as Bus SDK
|
|
175
|
+
participant W as 按订阅 AID 调度
|
|
176
|
+
participant S as Sub SDK / 应用
|
|
177
|
+
A->>P: publish(bus_aid, event_name, JSON 对象)
|
|
178
|
+
P->>P: 校验目录、TTL,进入有界发布队列
|
|
179
|
+
P-->>A: event_id
|
|
180
|
+
P->>N: event 类别,按剩余 TTL 发送 sdk_control
|
|
181
|
+
N-->>P: AUN 接受发送
|
|
182
|
+
N->>B: Push 或分类 Pull
|
|
183
|
+
alt 接管与 fanout 衔接容量已满
|
|
184
|
+
B-->>N: 保留待拉取页,不提交接管 ACK
|
|
185
|
+
Note over N,B: 容量释放后唤醒对应 Pull
|
|
186
|
+
else 接管成功
|
|
187
|
+
B->>B: 授权、内容及幂等检查,固定订阅快照
|
|
188
|
+
opt reply_mode=accepted
|
|
189
|
+
B->>N: 定向 publish.result
|
|
190
|
+
N-->>P: Bus 已受理
|
|
191
|
+
end
|
|
192
|
+
B->>W: 批次投递,按 AID 公平轮转
|
|
193
|
+
alt 全局目标容量已满
|
|
194
|
+
W-->>B: 等待容量,向上游背压
|
|
195
|
+
else 单个 AID 额度已满
|
|
196
|
+
W-->>B: 跳过该目标,计 skipped_overloaded
|
|
197
|
+
else 目标可发送
|
|
198
|
+
W->>N: 向订阅设备定向发送,保留原截止
|
|
199
|
+
N->>S: Sub 校验、去重、有界接收
|
|
200
|
+
S->>S: on_event / onEvent 或 next_event / NextEvent
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
P-->>A: wait_published / 对应语言结果接口
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`none` 的后台完成表示 AUN 接受发送;`accepted` 表示 Bus 已受理。两者都不等待订阅应用 ACK。Bus 受理去重记录只留摘要及结果;队列为当前分发保留正文,过期即失效,不承诺离线补发或跨重启 exactly-once。
|
|
207
|
+
|
|
208
|
+
| 预算 | 默认值与边界 |
|
|
209
|
+
| --- | --- |
|
|
210
|
+
| Pub 发布/Sub 接收 | 各 256 条/1 MiB;单个事件封装 64 KiB;Pub 默认 4 个 worker |
|
|
211
|
+
| Pull 接管到 fanout | 合计最多 64 条;未接管不提交 ACK、去重或越过游标 |
|
|
212
|
+
| Bus 正文 | 入站、受理、目标队列、在途与凭证复核保留材料合计硬封 64 MiB,区别于进程 RSS |
|
|
213
|
+
| 目标队列 | 合计 4096 条/8 MiB;每 AID 512 条/2 MiB;全局满等待,单 AID 满跳过 |
|
|
214
|
+
| 公平调度 | 每订阅 AID 一个逻辑 worker;同 AID 多设备共享份额,按 AID/工作量 DRR 调度 |
|
|
215
|
+
| RPC | total=16、background=8;其中 event=4、pull=4;普通 RPC 使用总池 |
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
事件入队立即返回 event_id;后台 worker 执行发送
|
|
219
|
+
派生的凭证、密钥和加密准备 RPC 继承 event 类别与 deadline
|
|
220
|
+
前台等待或写缓冲达到 64 KiB:暂停新事件发送
|
|
221
|
+
发送前核对身份、代次、期限,重算 TTL 和签名
|
|
222
|
+
剩余不足 1 秒:结束发送,不能将 TTL 变成 0
|
|
223
|
+
按订阅 AID 串行发送,各 AID 共享最多 4 个发送名额
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
同一加密消息流的发布和续租在 Pull 前无法区分;SDK 可让普通 RPC、同页及完整 Push 管理消息继续,但同流后续管理消息仍可能受满载背压。当前不增加服务端事件用途注册表。
|
|
227
|
+
|
|
228
|
+
## 5. 恢复、限流与任务生命周期
|
|
229
|
+
|
|
230
|
+
| 路径 | 0.5.32 实现要求 |
|
|
231
|
+
| --- | --- |
|
|
232
|
+
| 分类消息恢复 | `control/sdk_control` 接入已有后台 Pull 调度,重连恢复已保存流与 pending ACK,随后由 Push 驱动;替换独立控制扫描 worker |
|
|
233
|
+
| 应用处理器 | 普通/control 消费等待对应处理器注册;内部 sdk_control 由 SDK 消费,注册处理器后唤醒原待处理流 |
|
|
234
|
+
| 群目录 | `group.list_my` 每页 200,按身份、device、slot、连接代次合并完整分页;自动确认提案复用目录,检查游标前进 |
|
|
235
|
+
| 限流等待 | 识别 `-32429/-32029/429/4290`,后台派发、必要回源与 token 刷新等待至少 60 秒或服务端更长提示;不自动重试全部业务失败 |
|
|
236
|
+
| Python 状态 I/O | 串行异步读写,保存成功后确认消息,关闭时排空实际在途 I/O,避免阻塞事件循环 |
|
|
237
|
+
| Python 加解密 | event/normal 独立线程池,各 4 线程、64 个等待项;取消后实际计算结束才归还名额 |
|
|
238
|
+
| Python 应用队列 | 连续最多 4 个 control 后给普通应用事件处理机会 |
|
|
239
|
+
| TS/JS 连接 | Gateway 发现结果绑定当前连接尝试,旧任务不能覆盖新候选 |
|
|
240
|
+
|
|
241
|
+
实例续租与 Pub/Sub 授权续租各自随有效实例运行;没有独立的周期 peers/群全量扫描。期限等待、重试和队列唤醒复用现有生命周期,关闭、身份切换与重连后都核对代次。移植时保留这些行为边界,线程 API 或协程数量可按语言选择。
|
|
242
|
+
|
|
243
|
+
## 6. VFS Cache:精确失效与在途读取隔离
|
|
244
|
+
|
|
245
|
+
本版调整现有缓存,保留有效的无关资源。资源标记包括 space、owner、bucket、路径;对象、子树和目录列表分别匹配。移动/rename 同时失效两端,复制失效目标,ACL 变更失效相关范围;内存与持久缓存索引使用相同规则。缺资源标记的旧持久记录在相关写入时保守失效。
|
|
246
|
+
|
|
247
|
+
```mermaid
|
|
248
|
+
sequenceDiagram
|
|
249
|
+
autonumber
|
|
250
|
+
participant R as 读取调用
|
|
251
|
+
participant V as VFS / 读缓存
|
|
252
|
+
participant W as 写入调用
|
|
253
|
+
participant S as Storage,经 Gateway
|
|
254
|
+
R->>V: 读取资源 A,缓存未命中
|
|
255
|
+
V->>S: 发起 A 的读取,保存资源标记和有效标志
|
|
256
|
+
W->>V: 修改资源 A
|
|
257
|
+
V->>V: 标记 A 的旧在途读取不可回填
|
|
258
|
+
V->>S: 带 expected_version 提交写入
|
|
259
|
+
S-->>V: 写入成功
|
|
260
|
+
V->>V: 失效 A 及受影响列表的内存、持久索引
|
|
261
|
+
V-->>W: 返回写入结果
|
|
262
|
+
S-->>V: 原读取返回旧版本
|
|
263
|
+
V-->>R: 原调用可收到自身读取结果
|
|
264
|
+
Note over V: 旧结果不回填缓存,也不供后续读取复用
|
|
265
|
+
R->>V: 再读 A
|
|
266
|
+
V->>S: 重新读取;无关资源 B 的缓存保留
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
写前:推导资源范围,标记匹配的在途读取失效
|
|
271
|
+
写成功:删除匹配的内存条目和持久索引
|
|
272
|
+
读完成:仅当前身份、代次、资源仍有效且无同范围写时回填
|
|
273
|
+
原调用结果:可返回给原调用方,不把旧结果提供给后续调用
|
|
274
|
+
删除或 rename 成功:清除对应路径及受影响子树的写版本
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
正文按摘要存放的文件可留待正常回收;索引失效不表示立即删除全部正文文件。rename 清理源/目标的旧写版本,删除后重建不沿用已删除对象的版本;冲突和摘要失败也只失效相关资源。
|
|
278
|
+
|
|
279
|
+
| 读取条件 | 当前行为 |
|
|
280
|
+
| --- | --- |
|
|
281
|
+
| 普通读取,缓存仍有效 | 复用对应正文或元数据,满足原有校验规则 |
|
|
282
|
+
| 限流等待期,缓存仍有效 | 在允许的读取路径复用,可能覆盖 `no_cache/noCache`、`consistency=authoritative`;兼容已验证正文的不同读取形式 |
|
|
283
|
+
| 限流等待期,缓存未命中 | 先等待,再回源;新 TTL 从实际开始回源时起算 |
|
|
284
|
+
| 强制刷新遇限流错误 | 保留原有效缓存,向当前调用方保留限流错误 |
|
|
285
|
+
| 显式签名、Range 或强校验路径 | 继续遵守各自限制,不能统一改为缓存读取 |
|
|
286
|
+
|
|
287
|
+
Storage 写入仍提交 `expected_version` 供服务端 CAS。Go/TS/JS 补齐 Python 原有例外:显式版本下,权限不足或已核验挂载无法权威预读时可交服务端检查;未提供版本仍需取得权威版本。`force` 不绕过 CAS。
|
|
288
|
+
|
|
289
|
+
## 7. 四端落点与独有变化
|
|
290
|
+
|
|
291
|
+
| 模块 | Python | TypeScript/JavaScript | Go |
|
|
292
|
+
| --- | --- | --- | --- |
|
|
293
|
+
| EventService | [pubsub](../../python/src/aun_core/pubsub/__init__.py):门面、Binding、client、service、credentials、scheduler | [TS](../../ts/src/pubsub/index.ts)/[JS](../../js/src/pubsub/index.ts):同层级模块,另有 channel | [pubsub_service.go](../../go/pubsub_service.go)、[Binding](../../go/pubsub_binding.go)、[接收](../../go/pubsub_control_receive.go) |
|
|
294
|
+
| 消息恢复 | [delivery](../../python/src/aun_core/_client/delivery.py)、[control](../../python/src/aun_core/_client/control_messages.py) | [TS delivery](../../ts/src/client/delivery.ts)/[JS delivery](../../js/src/client/delivery.ts) 与 control-messages | [delivery](../../go/client_delivery.go)、[control](../../go/control_messages.go) |
|
|
295
|
+
| 预算与期限 | [transport](../../python/src/aun_core/transport.py)、[crypto_executor](../../python/src/aun_core/_client/crypto_executor.py) | [TS transport](../../ts/src/transport.ts)/[JS transport](../../js/src/transport.ts) 与 rpc-pipeline | [transport](../../go/transport.go)、[RPC 管线](../../go/client_rpc_pipeline.go) |
|
|
296
|
+
| VFS Cache | [cache](../../python/src/aun_core/storage/cache.py)、[VFS](../../python/src/aun_core/storage/vfs.py) | [TS cache](../../ts/src/storage/read-cache.ts)/[JS cache](../../js/src/storage/read-cache.ts)、各自 VFS/GroupFS | [cache](../../go/storage_read_cache.go)、[持久索引](../../go/storage_read_cache_disk.go)、[VFS](../../go/storage_vfs.go) |
|
|
297
|
+
|
|
298
|
+
- 四端本地 Ownership 绑定/转移的 subaid 扩为非空且非 `human/group/org` 类型,支持 service 等;owner/新 owner 仍限 human/agent,保留身份、私钥、已验证名片和共识检查。
|
|
299
|
+
- Python 语义凭证恢复撤销状态时保留已有 `event_seq` 并核对原件摘要,缺序号的旧记录按 0 比较;见 [semantic_facades](../../python/src/aun_core/semantic_facades.py)。
|
|
300
|
+
- Browser JS 恢复 agent.md 的 `refresh_pending` 与待交付事件,验签/共识/ETag 暂未就绪保留刷新意图,同目标串行;见 [agent-md-control](../../js/src/agent-md-control.ts)。Go 加密 Push 补充兼容 `envelope` 字段。
|
|
301
|
+
|
|
302
|
+
独有修复按其语言验证,不把 Python 线程池或 JS 通知恢复写成所有语言相同的内部机制。
|
|
303
|
+
|
|
304
|
+
## 8. 验收场景与已有证据
|
|
305
|
+
|
|
306
|
+
| 必须核对的场景 | 验收结果要求 | 现有回归入口 |
|
|
307
|
+
| --- | --- | --- |
|
|
308
|
+
| 单实例及设备定向 | 第二实例冲突;失租不再承接;回复只给发布设备,事件只给订阅设备 | [Python Binding](../../python/tests/unit/test_pubsub_binding.py)、[Go Binding](../../go/pubsub_binding_test.go) |
|
|
309
|
+
| 双授权与目录续页 | 两种模式均成功;多页目录全部通过才更新缓存;分页失败保留原状态 | [Python 凭证](../../python/tests/unit/test_pubsub_credentials.py)、[TS client](../../ts/tests/unit/pubsub-client.test.ts)、[JS client](../../js/tests/unit/pubsub-client.test.ts) |
|
|
310
|
+
| 异步发布与背压 | 立即返回 ID;none/accepted 完成点正确;满 64 条后保留待处理页 | [容量](../../python/tests/unit/test_pubsub_capacity_contracts.py)、[Pull gate](../../python/tests/unit/test_pubsub_pull_gate.py) |
|
|
311
|
+
| 公平性与 RPC | 慢 AID 不拖住其它 AID;后台不占满前台额度;截止不因重试延长 | [调度](../../python/tests/unit/test_pubsub_sustained_fairness.py)、[Go 预算](../../go/pubsub_rpc_budget_test.go)、[期限](../../python/tests/unit/test_pubsub_deadline.py) |
|
|
312
|
+
| 默认凭证恢复 | 真正关闭重开 SQLite/IndexedDB 后原操作可恢复,AID 隔离,显式存储优先 | 上述凭证测试及 [Go 凭证](../../go/pubsub_credentials_test.go) |
|
|
313
|
+
| VFS Cache | 无关缓存保留;旧在途不回填;重启后失效正确;删除/rename 不留旧写版本 | [Python cache](../../python/tests/unit/test_storage_read_cache.py)、[TS cache](../../ts/tests/unit/storage-read-cache.test.ts)、[JS VFS](../../js/tests/unit/storage-vfs-read-cache.test.ts)、[Go cache](../../go/storage_read_cache_boundary_test.go) |
|
|
314
|
+
| 限流缓存与 TTL | 有效缓存按当前规则复用,未命中等待,等待结束才计算回源 TTL | 上述 cache 测试及 [跨 SDK cache](../../python/tests/unit/test_cross_sdk_cache_control.py) |
|
|
315
|
+
| 生命周期与语言独有修复 | 关闭排空状态 I/O;旧连接不覆盖新连接;独有凭证/通知兼容有回归 | [状态 I/O](../../python/tests/unit/test_pubsub_control_state_io.py)、[TS 连接](../../ts/tests/unit/transport-connect-race.test.ts)、[Python 语义凭证](../../python/tests/unit/test_semantic_facades.py) |
|
|
316
|
+
|
|
317
|
+
已有 Ubuntu Docker EventService 矩阵完成 **128/128**:4 种 Bus × 2 种授权 × 4 种 Pub × 4 种 Sub,每种 Bus 32 项;256 份获准目录由 `authorize` 自动取得。见 [最终汇总](../../tests/cross-sdk/artifacts/pubsub-4sdk-20261105/remove-manager-acceptance/final-acceptance-summary.json)与[实施计划 §9.9](../../../docs/AUN文档/AUN事件订阅发布TDD实施计划.md#99-凭证默认存储授权目录与移除管理身份)。
|
|
318
|
+
|
|
319
|
+
这些记录不等同于本版所有改动的完整验收:JS 矩阵使用 Node+fake-indexeddb,真实浏览器、macOS、真实双域设备、实填 64 MiB/RSS 压力不在其中;全部 Storage/Ownership/限流改动需按相应回归入口分别核实。本轮仅整理文档,未重跑 SDK 测试或发布产物。
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# AUN SDK 0.5.33 应用集成指南
|
|
2
|
+
|
|
3
|
+
面向应用开发者,说明从仓库 0.5.32 基线升级到当前目标 0.5.33 的接入变化。本文对照 `072b7c69f` 与截至 2026-11-07 的未提交源码;0.5.33 为未发布目标,安装产物和配套服务部署需分别核对。四端实现差异见 [parity 0.5.33](../../python/CHANGES_FOR_PARITY.md#v0533),内部流程见[开发与移植指南](0.5.33-SDK开发与移植指南.md)。
|
|
4
|
+
|
|
5
|
+
## 1. 本版变化与整体架构
|
|
6
|
+
|
|
7
|
+
| 本版变化 | 应用如何使用 |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| 应用控制消息兼容 | 保留原 `control` 调用,SDK 按协商结果选择分类或普通投递;明文仍可发送 |
|
|
10
|
+
| Ownership 批量申请/审批 | 同批申请传同一 UUIDv4,Owner 归组展示后一次提交操作 ID 列表 |
|
|
11
|
+
| agent.md 与共识本地优先 | 保留本地身份仓库;新 Client 和连接成功不再触发无条件首查 |
|
|
12
|
+
| Storage 多 AID ACL | VFS/LowLevel 直接传列表,单个 AID 的旧参数继续可用 |
|
|
13
|
+
| Python 专项 | 拥塞等待采用新策略,容量压测使用新增 `bench run/report` |
|
|
14
|
+
|
|
15
|
+
EventService、设备租约、有界 fanout 和原有 VFS Cache 已由 0.5.32 提供,接入方法继续参考[上一版应用指南](0.5.32-SDK应用集成指南.md)。
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
%%{init: {"theme":"base","themeVariables":{"fontFamily":"Microsoft YaHei, sans-serif","fontSize":"14px"},"flowchart":{"curve":"linear","nodeSpacing":24,"rankSpacing":32}}}%%
|
|
19
|
+
flowchart TB
|
|
20
|
+
subgraph APP["各 AID 的应用进程"]
|
|
21
|
+
direction LR
|
|
22
|
+
U["Owner 应用<br/>批次展示与审批"]:::app
|
|
23
|
+
A["Agent 应用<br/>绑定 / 消息 / 文件"]:::app
|
|
24
|
+
end
|
|
25
|
+
subgraph SDK["每个 AID 各自持有 SDK"]
|
|
26
|
+
F["AUNClient 门面"]:::entry
|
|
27
|
+
O["Ownership<br/>批次 / agent.md / 本地共识"]:::owner
|
|
28
|
+
R["消息发送与接收<br/>分类协商 / E2EE / 应用回调"]:::entry
|
|
29
|
+
V["Storage VFS<br/>多 AID ACL / 读缓存"]:::storage
|
|
30
|
+
E["EventService · 继承 0.5.32<br/>Pub / Bus / Sub"]:::event
|
|
31
|
+
F --> O & R & V & E
|
|
32
|
+
end
|
|
33
|
+
G["Gateway<br/>认证会话 / 可信发送者 / RPC 转发"]:::gateway
|
|
34
|
+
subgraph SERVICES["AUN 服务"]
|
|
35
|
+
direction LR
|
|
36
|
+
M["Message / Group<br/>P2P / 群消息 / TTL 投递"]:::infra
|
|
37
|
+
N["Name Service<br/>归属关系 / 权威名片状态"]:::infra
|
|
38
|
+
S["Storage<br/>对象 / ACL / 条件写入"]:::infra
|
|
39
|
+
C["Credential<br/>事件授权凭证登记 / 状态证明"]:::infra
|
|
40
|
+
end
|
|
41
|
+
U & A --> F
|
|
42
|
+
O & R & V & E --> G
|
|
43
|
+
G --> M & N & S & C
|
|
44
|
+
classDef app fill:#eff6ff,stroke:#93c5fd,color:#1e3a8a,rx:10,ry:10
|
|
45
|
+
classDef entry fill:#f0f9ff,stroke:#7dd3fc,color:#0c4a6e,rx:10,ry:10
|
|
46
|
+
classDef owner fill:#eef2ff,stroke:#a5b4fc,color:#312e81,rx:10,ry:10
|
|
47
|
+
classDef storage fill:#fff7ed,stroke:#fdba74,color:#9a3412,rx:10,ry:10
|
|
48
|
+
classDef event fill:#f0fdf4,stroke:#86efac,color:#166534,rx:10,ry:10
|
|
49
|
+
classDef gateway fill:#f5f3ff,stroke:#a78bfa,color:#4c1d95,rx:10,ry:10
|
|
50
|
+
classDef infra fill:#f8fafc,stroke:#cbd5e1,color:#334155,rx:10,ry:10
|
|
51
|
+
style APP fill:#ffffff,stroke:#e2e8f0
|
|
52
|
+
style SDK fill:#ffffff,stroke:#e2e8f0
|
|
53
|
+
style SERVICES fill:#f8fafc,stroke:#e2e8f0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
图中合并表示相同的 SDK 能力;每个 AID 的身份、连接和缓存分别保存。批次归组和审批界面由应用完成,归属共识仍由原有 Ownership 流程确认。EventService 的目录、订阅表和分发仍在 Bus SDK,Message 只负责承接实例租约及通用消息投递。
|
|
57
|
+
|
|
58
|
+
## 2. 示例前提与四端入口
|
|
59
|
+
|
|
60
|
+
以下 TypeScript 片段使用应用已加载身份且连接就绪的 Client,加载与连接沿用[快速开始](01-快速开始.md)。Owner 与新 Owner 为 human/agent 身份,两个 Agent 已符合 Ownership 适用条件。
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import type { AUNClient } from '@agentunion/fastaun';
|
|
64
|
+
declare const ownerClient: AUNClient;
|
|
65
|
+
declare const nextOwnerClient: AUNClient;
|
|
66
|
+
declare const firstAgent: AUNClient;
|
|
67
|
+
declare const secondAgent: AUNClient;
|
|
68
|
+
const ownerAid = String(ownerClient.aid);
|
|
69
|
+
const nextOwnerAid = String(nextOwnerClient.aid);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
片段分别运行在相应身份的应用中;跨进程通过 SDK 收到的事件或应用界面传递选择结果。
|
|
73
|
+
|
|
74
|
+
| 用途 | Python | TypeScript/Browser JS | Go |
|
|
75
|
+
| --- | --- | --- | --- |
|
|
76
|
+
| 申请绑定 | `bind_owner_aid(..., batch_id=...)` | `bindOwneraid(..., { batchId })` | `BindOwneraid(..., OwnershipRequestOptions{BatchID: ...})` |
|
|
77
|
+
| Owner 发起绑定 | `bind_sub_aid` | `bindSubaid` | `BindSubaid` |
|
|
78
|
+
| 转移 | `transfer_sub_aid` | `transferSubaid` | `TransferSubaid` |
|
|
79
|
+
| 批量同意/拒绝 | `accept_ownership_requests/reject_ownership_requests` | `acceptOwnershipRequests/rejectOwnershipRequests` | `AcceptOwnershipRequests/RejectOwnershipRequests` |
|
|
80
|
+
| ACL 列表 | `grantee_aids` | `granteeAids` | `GranteeAIDs` |
|
|
81
|
+
| 共识查询 | `check_ownership_consensus(..., force=True)` | `checkOwnershipConsensus(aid, true)` | `CheckOwnershipConsensusWithOptions(..., OwnershipConsensusOptions{Force: true})` |
|
|
82
|
+
|
|
83
|
+
Go 网络及等待方法还需传入 `context`。原有单次 Ownership 调用和 ACL 单 AID 参数保留。
|
|
84
|
+
|
|
85
|
+
## 3. 应用控制消息:保留调用,按能力投递
|
|
86
|
+
|
|
87
|
+
### 3.1 明文或加密的页面响应
|
|
88
|
+
|
|
89
|
+
发送应用控制消息时继续声明 `message_class: 'control'`,由 SDK 处理协商和加密位置。例如向 Owner 发送一条有期限的明文页面响应:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
await firstAgent.call('message.send', {
|
|
93
|
+
to: ownerAid, message_class: 'control', encrypt: false, ttl: 60,
|
|
94
|
+
payload: { type: 'menu.response', request_id: 'request-1', data: { ready: true } },
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
需要加密时改为 `encrypt: true`。群应用控制使用既有 `group.send` 入口,并按群能力协商;应用无需自己移动保护头或构造 E2EE 信封。
|
|
99
|
+
|
|
100
|
+
```mermaid
|
|
101
|
+
sequenceDiagram
|
|
102
|
+
autonumber
|
|
103
|
+
participant A as 发送应用
|
|
104
|
+
participant S as 发送 SDK
|
|
105
|
+
participant G as Gateway
|
|
106
|
+
participant M as Message / Group
|
|
107
|
+
participant R as 接收 SDK
|
|
108
|
+
participant U as 接收应用
|
|
109
|
+
A->>S: send(control, encrypt, ttl)
|
|
110
|
+
alt 已协商应用控制类别
|
|
111
|
+
S->>G: 保留类别;按 encrypt 选择明文或 E2EE
|
|
112
|
+
else 未协商应用控制类别
|
|
113
|
+
S->>S: 构造请求时去掉外层及可改写保护头的类别
|
|
114
|
+
S->>G: 普通消息投递,保留正文、TTL 和设备目标
|
|
115
|
+
end
|
|
116
|
+
G->>M: 可信发送者身份与请求
|
|
117
|
+
M->>R: 在线 Push 或后续 Pull
|
|
118
|
+
R->>U: 通过原有消息事件交付
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
接收应用继续注册 `message.received`、`group.message_created` 等已有事件;按业务 `payload.type` 识别页面响应。降级后不依赖 `message_class` 仍为 `control` 来识别业务。
|
|
122
|
+
|
|
123
|
+
### 3.2 SDK 控制消息由 SDK 管理
|
|
124
|
+
|
|
125
|
+
| 消息 | 分类/协议能力已协商 | 未协商 |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| 普通 P2P/群消息 | 普通投递 | 普通投递;普通群 TTL 不再被分类门禁阻断 |
|
|
128
|
+
| 明文/加密的应用 `control` | 保留控制类别 | 构造请求时降级为普通投递 |
|
|
129
|
+
| P2P 加密 `sdk_control` | SDK 校验并消费 | 外层路由降级,E2EE 保护头保留 SDK 类别及协议,仍由 SDK 消费 |
|
|
130
|
+
| 明文 `sdk_control`、群 `sdk_control` | 拒绝 | 拒绝 |
|
|
131
|
+
|
|
132
|
+
应用通过 `EventService`、Ownership 等门面调用 SDK 功能。SDK 控制消息不会因为普通通道投递就交给应用消息处理器。已签名的信封保持受保护内容,由配套服务完成通道路由;部署升级时应同时核对 Gateway、Message 和 Group 的兼容逻辑。
|
|
133
|
+
|
|
134
|
+
## 4. Ownership:一批申请,一次选择审批
|
|
135
|
+
|
|
136
|
+
### 4.1 Owner 先接收并按批次展示
|
|
137
|
+
|
|
138
|
+
注册处理器后,SDK 交付的 `ownership.request` 已经过原请求校验。以下集合是应用的待审批列表;没有批次的旧请求以自身操作 ID 单独展示。
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
type RequestItem = { batch_id?: string; operation_id: string; sub_aid: string };
|
|
142
|
+
const requests = new Map<string, RequestItem[]>();
|
|
143
|
+
ownerClient.on('ownership.request', (payload) => {
|
|
144
|
+
const item = payload as RequestItem;
|
|
145
|
+
const key = item.batch_id ?? item.operation_id;
|
|
146
|
+
requests.set(key, [...(requests.get(key) ?? []), item]);
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
同一操作可能再次通知,应用列表可按 `operation_id` 合并展示。SDK 的审批接口也会对提交列表去重。
|
|
151
|
+
|
|
152
|
+
### 4.2 多个 Agent 向同一 Owner 申请绑定
|
|
153
|
+
|
|
154
|
+
由发起这批操作的应用生成一个 UUIDv4,并传给每个 Agent。实际使用可由同一进程里的多个 Client,也可由应用将批次号传到各进程。
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const batchId = crypto.randomUUID();
|
|
158
|
+
const firstBinding = await firstAgent.bindOwneraid(ownerAid, { batchId });
|
|
159
|
+
const secondBinding = await secondAgent.bindOwneraid(ownerAid, { batchId });
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Owner 收到并展示两项请求后,用户点一次同意,将选中请求的操作 ID 提交给批量接口:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const selectedIds: string[] = [];
|
|
166
|
+
for (const item of requests.get(batchId) ?? []) selectedIds.push(item.operation_id);
|
|
167
|
+
const approval = await ownerClient.acceptOwnershipRequests(selectedIds);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
拒绝时调用 `ownerClient.rejectOwnershipRequests(selectedIds, '本批不予绑定')`。`batchId` 只用于申请及展示归组,审批使用已收到的 `operation_id`,不会按一个批次号自动批准后来加入的请求。
|
|
171
|
+
|
|
172
|
+
```mermaid
|
|
173
|
+
sequenceDiagram
|
|
174
|
+
autonumber
|
|
175
|
+
participant A as Agent A
|
|
176
|
+
participant B as Agent B
|
|
177
|
+
participant M as AUN 消息投递
|
|
178
|
+
participant O as Owner SDK
|
|
179
|
+
participant U as Owner 审批界面
|
|
180
|
+
participant N as 原有文件与归属服务
|
|
181
|
+
A->>M: bind.request(operation A, batch X)
|
|
182
|
+
B->>M: bind.request(operation B, batch X)
|
|
183
|
+
M->>O: 认证原请求,保留各自上下文
|
|
184
|
+
O->>U: ownership.request,按 batch X 展示
|
|
185
|
+
U->>O: 一次同意 [operation A, operation B]
|
|
186
|
+
loop 对列表中每个独立操作
|
|
187
|
+
O->>N: 强制核对当前关系并执行单项绑定
|
|
188
|
+
N-->>O: 当前项结果
|
|
189
|
+
O->>M: 单项回复/后续通知
|
|
190
|
+
end
|
|
191
|
+
O-->>U: total / succeeded / failed / results
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
批量结果保留每项的 `result` 或 `error`。`succeeded` 表示该次审批调用未落入失败分类,结果仍可能为 `pending`;应用应查看每项状态,通过后续 `ownership.completed` 或共识查询确认归属完成。单项失败不回滚其它项。
|
|
195
|
+
|
|
196
|
+
### 4.3 批量转移给新 Owner
|
|
197
|
+
|
|
198
|
+
当前 Owner 使用新的批次号发起转移,审批发生在新 Owner:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
const transferBatchId = crypto.randomUUID();
|
|
202
|
+
const firstTransfer = await ownerClient.transferSubaid(String(firstAgent.aid), nextOwnerAid, { batchId: transferBatchId });
|
|
203
|
+
const secondTransfer = await ownerClient.transferSubaid(String(secondAgent.aid), nextOwnerAid, { batchId: transferBatchId });
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
新 Owner 按 §4.1 注册自己的请求处理器;用户确认后提交已收到的转移操作列表:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
declare const selectedTransferIds: string[];
|
|
210
|
+
const transferApproval = await nextOwnerClient.acceptOwnershipRequests(selectedTransferIds);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
SDK 逐项保留原发送者、目标 Owner、关系版本和批次上下文;同一操作换批次或换内容会触发冲突。批量执行期间切换身份也不会继续用新身份批准旧请求。
|
|
214
|
+
|
|
215
|
+
## 5. 新 Client 与重连:本地名片和共识优先
|
|
216
|
+
|
|
217
|
+
应用保留原身份仓库及本地 `agent.md`,按原流程加载身份、连接即可。SDK 不再因“这个 Client 还没有查过”而强制访问服务器,群/组织首次访问同样复用有效本地状态。
|
|
218
|
+
|
|
219
|
+
```mermaid
|
|
220
|
+
flowchart LR
|
|
221
|
+
Q["连接后 / 首次查询"] --> L["读取本地 agent.md 与共识快照"]
|
|
222
|
+
L --> C{"本地记录仍一致?"}
|
|
223
|
+
C -->|"ETag / 摘要 / 关系声明一致"| H["复用本地名片及已达共识结果"]
|
|
224
|
+
C -->|"缺失 / 未共识 / 内容或 ETag 变化"| R["查询远端并更新观察"]
|
|
225
|
+
F["管理流程或 force=true"] --> R
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
本地有正文不等于已经达成归属共识;SDK 还核对已保存快照、锁状态、ETag、正文摘要、Owner 和关系版本。绑定、审批、转移、释放等管理流程继续强制核对当前状态。
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
const localFirst = await firstAgent.checkOwnershipConsensus();
|
|
232
|
+
const current = await firstAgent.checkOwnershipConsensus(undefined, true);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
普通展示使用默认查询;应用确需当前远端事实时显式强刷。Ownership 状态变化后 SDK 清除相关快照,本轮没有新增周期共识查询任务。
|
|
236
|
+
|
|
237
|
+
## 6. Storage:一次授予或撤销多个 AID
|
|
238
|
+
|
|
239
|
+
以下文件已存在且属于 `ownerClient`;传入列表即可从 VFS 贯通到 LowLevel 和 RPC。数组也可以只有一个 AID。
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
await ownerClient.storage.setAcl('/reports/result.json', {
|
|
243
|
+
granteeAids: [String(firstAgent.aid), String(secondAgent.aid)],
|
|
244
|
+
perms: 'r', maxUses: 10,
|
|
245
|
+
});
|
|
246
|
+
await ownerClient.storage.removeAcl('/reports/result.json', {
|
|
247
|
+
granteeAids: [String(firstAgent.aid), String(secondAgent.aid)],
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`maxUses: 10` 表示每个被授权 AID 各有自己的使用次数;权限、过期时间等设置应用到每项。配套 Storage 服务归一化并去重 AID,SDK 请求使用 `grantee_aids`。
|
|
252
|
+
|
|
253
|
+
原调用保持可用:
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
await ownerClient.storage.setAcl('/reports/result.json', {
|
|
257
|
+
granteeAid: String(firstAgent.aid), perms: 'r',
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
```mermaid
|
|
262
|
+
sequenceDiagram
|
|
263
|
+
autonumber
|
|
264
|
+
participant A as 应用
|
|
265
|
+
participant V as VFS / LowLevel
|
|
266
|
+
participant C as SDK 读缓存
|
|
267
|
+
participant S as Storage 服务
|
|
268
|
+
A->>V: setAcl 或 removeAcl,多 AID
|
|
269
|
+
V->>S: storage.set_acl / remove_acl,grantee_aids
|
|
270
|
+
S->>S: 逐项授予或撤销
|
|
271
|
+
S-->>V: 成功结果或中途错误
|
|
272
|
+
V->>C: 两种结果都失效相关路径缓存
|
|
273
|
+
V-->>A: 返回结果或保留原始错误
|
|
274
|
+
A->>V: 按需重新查询 ACL
|
|
275
|
+
V->>S: 回源确认当前实际权限
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
批量请求发生中途错误时,可能已有部分 AID 更新成功。应用保留错误并重新查询当前 ACL,再决定如何处理剩余项;SDK 会清理相关路径缓存,保留无关路径缓存。接口字段及精简后的对象/下载票据/共享链接返回值见 [Storage RPC 手册](09-storage-rpc-manual.md)。
|
|
279
|
+
|
|
280
|
+
## 7. Python 独有变化
|
|
281
|
+
|
|
282
|
+
### 7.1 限流与拥塞等待
|
|
283
|
+
|
|
284
|
+
| 响应条件 | Python 等待策略 |
|
|
285
|
+
| --- | --- |
|
|
286
|
+
| 有效正数 `retry_after_seconds/retry_after_ms` | 按服务端提示等待,取适用的较长值 |
|
|
287
|
+
| 无有效提示,`-32029/-32429` 且错误文本表明队列/背压/容量拥塞 | 默认 1 秒 |
|
|
288
|
+
| 其它可识别限流 | 默认 60 秒 |
|
|
289
|
+
|
|
290
|
+
这项调整仅为本轮 Python 变更,TS/JS/Go 没有同等退避修改;应用写请求不会因此自动重试。应用仍需根据单次请求结果决定后续操作。
|
|
291
|
+
|
|
292
|
+
### 7.2 容量压测 CLI
|
|
293
|
+
|
|
294
|
+
新增 `aun bench run` 和 `aun bench report`,支持 16 种场景、套件选择、多进程、多身份通道、预算和断点续跑。将 `<issuer>` 替换为目标域,先查看计划,再启动选定场景:
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
aun bench run "<issuer>" --suite messaging --dry-run
|
|
298
|
+
aun bench run "<issuer>" --case p2p-plain --budget 10 --run-id sdk033
|
|
299
|
+
aun bench run "<issuer>" --case p2p-plain --budget 10 --run-id sdk033 --resume
|
|
300
|
+
aun bench report ".aun-bench/<issuer>/runs/sdk033"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
报告提供 JSON/HTML,区分延迟达标容量、稳态吞吐、边界区间和发压端瓶颈。`pubsub` 场景包含发压端的 Bus SDK;未验证的结果或发压端瓶颈不能当作已确认的纯服务端容量。
|
|
304
|
+
|
|
305
|
+
## 8. 升级与验收
|
|
306
|
+
|
|
307
|
+
| 检查项 | 验收行为 |
|
|
308
|
+
| --- | --- |
|
|
309
|
+
| 四 SDK 产物 | 核对目标版本 0.5.33;Browser JS 与 Node TS 使用各自包 |
|
|
310
|
+
| 消息兼容 | 已协商/未协商的明文和加密应用控制可投递;普通消息继续工作;SDK 控制由 SDK 消费 |
|
|
311
|
+
| 批次审批 | 同批多个 Agent 可一次选择;逐项显示结果,失败项可单独处理;最终归属以完成事件/共识为准 |
|
|
312
|
+
| 本地优先 | 保存的有效共识可跨 Client/重连复用;无共识或记录变化会查询远端;管理调用强刷 |
|
|
313
|
+
| 批量 ACL | 列表及旧单项调用都可用;计数按 AID 独立;部分失败后可读到实际权限 |
|
|
314
|
+
| 配套服务 | Gateway/Message/Group 支持兼容路由;Storage 支持批量 ACL;原 EventService 服务依赖继续保留 |
|
|
315
|
+
|
|
316
|
+
已有版本升级验证包括四端版本一致性、TS 加密回环 17 项、JS 加密回环 13 项、Go E2EE 包及对应类型/vet 检查。控制消息 runner 的 96 格脚本已纳入工作区,但本轮没有取得其完整通过产物;它只关闭发送端能力,不能代表接收端缺少能力的全部组合。详细覆盖与前序定向回归记录见 [parity 验证边界](../../python/CHANGES_FOR_PARITY.md#v0533)。本文整理不代替全量或跨 SDK E2E 验收。
|