@agentunion/fastaun 0.5.25 → 0.5.27
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 +41 -0
- package/_packed_docs/CHANGELOG.md +41 -0
- package/_packed_docs/INDEX.md +22 -14
- package/_packed_docs/KITE_DOCS_GUIDE.md +11 -6
- package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +16 -1
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +37 -9
- package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +20 -9
- package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +57 -12
- package/_packed_docs/cli//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241CLI/345/274/200/345/217/221/344/270/216/344/275/277/347/224/250/346/214/207/345/215/227.md +869 -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 +2 -2
- package/_packed_docs/sdk/0.5.27-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +408 -0
- package/_packed_docs/sdk/0.5.27-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +410 -0
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +2 -2
- package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +187 -73
- package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +1 -1
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +13 -9
- package/_packed_docs/sdk/INDEX.md +21 -13
- package/_packed_docs/sdk/agent.md/344/270/216group.index/347/232/204ETag/350/247/202/345/257/237/344/270/216/345/220/214/346/255/245/346/234/272/345/210/266.md +240 -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 +973 -266
- 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 +950 -242
- package/dist/agent-md-schema.js +1 -1
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.js +5 -0
- package/dist/agent-md.js.map +1 -1
- package/dist/aid.js +3 -3
- package/dist/aid.js.map +1 -1
- package/dist/auth.js +21 -19
- package/dist/auth.js.map +1 -1
- package/dist/cert-utils.d.ts +1 -1
- package/dist/cert-utils.js +4 -4
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/lifecycle.d.ts +1 -1
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-pipeline.js +8 -1
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.js +7 -0
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +12 -0
- package/dist/client.js +305 -29
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +38 -0
- package/dist/facades.js +49 -5
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/keystore/local-identity-store.js +16 -1
- package/dist/keystore/local-identity-store.js.map +1 -1
- package/dist/keystore/local-token-store.js +16 -1
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +1 -0
- package/dist/org-protocol.js +39 -36
- package/dist/org-protocol.js.map +1 -1
- package/dist/ownership-v21.js +7 -7
- package/dist/ownership-v21.js.map +1 -1
- package/dist/register-flow.js +2 -2
- package/dist/register-flow.js.map +1 -1
- package/dist/semantic-facade.d.ts +176 -0
- package/dist/semantic-facade.js +611 -0
- package/dist/semantic-facade.js.map +1 -0
- package/dist/semantic-protocol.d.ts +810 -0
- package/dist/semantic-protocol.js +894 -0
- package/dist/semantic-protocol.js.map +1 -0
- package/dist/tools/cross-sdk-agent.d.ts +11 -1
- package/dist/tools/cross-sdk-agent.js +388 -7
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +1 -0
- package/dist/transport.js +28 -2
- package/dist/transport.js.map +1 -1
- package/dist/v2/e2ee/decrypt.d.ts +5 -0
- package/dist/v2/e2ee/decrypt.js +22 -2
- 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 +2 -1
- package/src/certs/root.crt +13 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# agent.md 与 group.index 的 ETag 观察与同步机制
|
|
2
|
+
|
|
3
|
+
## 1. 先看结论
|
|
4
|
+
|
|
5
|
+
| 对象 | ETag 权威来源 | 观察入口 | 正文/设置何时更新 |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| `agent.md` | Nameservice 对当前 HTTP 表示的完整响应正文计算 SHA-256,返回带引号的十六进制 ETag | Gateway RPC `_meta`、消息信封 `agent_md` | 观察只更新 `remote_etag`;显式下载或“本地无正文”的自动补拉完成验签后才更新正文 |
|
|
8
|
+
| `group.index` | Group 服务对签名 JSONL entries 的 canonical bytes 计算 `"sha256:<hex>"` | RPC 响应 `_meta.group_indexes` | 观察只标记 stale;`getGroupIndex` 显式拉取并验签,`updateGroupIndex` 以 ETag CAS 提交 |
|
|
9
|
+
|
|
10
|
+
`remote_etag` 是远端版本提示,`local_etag` 是当前本地已验证正文/索引的版本。两者不能混用。观察到新 ETag 不等于已经下载了新正文,也不等于应自动覆盖应用缓存。
|
|
11
|
+
|
|
12
|
+
## 2. 总体流程
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
flowchart LR
|
|
16
|
+
W[写入 agent.md / group.index] --> A[服务端生成权威 ETag]
|
|
17
|
+
A --> P[Gateway RPC _meta / 消息信封携带版本提示]
|
|
18
|
+
P --> O[SDK observer 保存 remote_etag 或 remote_meta]
|
|
19
|
+
O --> C{本地版本相同?}
|
|
20
|
+
C -->|是| K[保持正文/设置缓存]
|
|
21
|
+
C -->|否| D{资源类型与本地状态}
|
|
22
|
+
D -->|agent.md 无正文| G[自动 GET + 验签]
|
|
23
|
+
D -->|agent.md 已有正文| H[仅标记待更新,由应用显式 download/check]
|
|
24
|
+
D -->|group.index| I[仅标记 stale]
|
|
25
|
+
G --> U[写入 content/local_etag]
|
|
26
|
+
I --> J[getGroupIndex 显式拉取、验签、hydrate]
|
|
27
|
+
J --> U2[写入 settings/local_etag]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 3. agent.md
|
|
31
|
+
|
|
32
|
+
### 3.1 服务端写入和版本发布
|
|
33
|
+
|
|
34
|
+
```mermaid
|
|
35
|
+
sequenceDiagram
|
|
36
|
+
participant SDK as SDK
|
|
37
|
+
participant NS as Nameservice
|
|
38
|
+
participant GW as Gateway
|
|
39
|
+
participant MSG as Message Service
|
|
40
|
+
|
|
41
|
+
SDK->>NS: PUT /agent.md
|
|
42
|
+
NS->>NS: 保存权威正文并计算 HTTP ETag
|
|
43
|
+
NS-->>SDK: 200 + ETag + Last-Modified
|
|
44
|
+
NS-->>GW: nameservice.agent_md_updated(aid)
|
|
45
|
+
GW->>GW: 清除该 AID 的 agent.md 元数据缓存和发送节流
|
|
46
|
+
GW-->>SDK: 后续 RPC response 的 _meta.agent_md_etags
|
|
47
|
+
MSG-->>SDK: message envelope.agent_md.sender/group
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Nameservice 的 `GET`/`HEAD` 对相同请求头返回同一表示的 ETag;`HEAD` 不返回正文,并支持 `If-None-Match`/`If-Modified-Since`。成功写入会发 `nameservice.agent_md_updated`,Gateway 用它清理自己的 ETag 元数据缓存;该通知不是 SDK 的版本事件。当前已确认的 Gateway 下发入口是后续 RPC response 的 `_meta`;消息信封也会携带发送者观察值。SDK 能解析事件 `_meta`,但当前服务端链路未确认普通事件推送会注入 agent.md ETag。四个 SDK 的下载 GET 不主动发送条件头;对代理返回的 304 仅做兼容处理。
|
|
51
|
+
|
|
52
|
+
事件 payload 中的 ETag 针对 Nameservice 保存的完整记录;HTTP ETag 针对本次请求的响应表示,签名格式投影可能使两者不同。事件的可靠用途是让 Gateway 失效并重新读取元数据,SDK 不应把它当作已下载正文。
|
|
53
|
+
|
|
54
|
+
Gateway 元数据示例:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"_meta": {
|
|
59
|
+
"agent_md_etag": "\"<sha256-hex>\"",
|
|
60
|
+
"agent_md_etags": {
|
|
61
|
+
"requester": {"aid": "alice.agentid.pub", "etag": "\"<sha256-hex>\""},
|
|
62
|
+
"peer": {"aid": "bob.agentid.pub", "etag": "\"<sha256-hex>\"", "last_modified": "..."},
|
|
63
|
+
"group": {"aid": "team.agentid.pub", "etag": "\"<sha256-hex>\""}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
消息信封只承载观察值,不承载正文:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{"agent_md":{"sender":{"aid":"bob.agentid.pub","etag":"\"<sha256-hex>\""}}}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3.2 SDK 观察和下载判定
|
|
76
|
+
|
|
77
|
+
四个 SDK 都在传输层注册 observer,读取 `_meta.agent_md_etag`、`_meta.agent_md_etags`,并读取信封的 `agent_md.sender`/`group`。记录至少区分:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
remote_etag 观察到的服务端版本
|
|
81
|
+
local_etag 本地已验证 content 的版本
|
|
82
|
+
observed_at 最近观察时间
|
|
83
|
+
observation_version 观察代次
|
|
84
|
+
fetched_at 正文最近成功下载时间
|
|
85
|
+
verify_status 最近一次验签结果
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
观察流程:
|
|
89
|
+
|
|
90
|
+
```mermaid
|
|
91
|
+
flowchart TD
|
|
92
|
+
E[收到 RPC _meta 或 message envelope 的 ETag] --> S[保存 remote_etag/observed_at]
|
|
93
|
+
S --> Q{本地是否已有已验证正文?}
|
|
94
|
+
Q -->|否| F[单飞 GET /agent.md]
|
|
95
|
+
Q -->|是| N[不 HEAD、不自动 GET;触发 changed/待更新标记]
|
|
96
|
+
F --> V[校验 AID、Schema、签名]
|
|
97
|
+
V -->|成功| L[保存正文、local_etag、fetched_at]
|
|
98
|
+
V -->|失败| R[记录错误并退避;等待新观察或显式重试]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
SDK 也能解析带 `_meta` 的事件,但当前服务端实现中已确认的 agent.md ETag 下发路径是 Gateway RPC 响应;普通事件推送不作为同步保证。`check_agent_md`/`checkAgentMd`/`CheckAgentMD` 是检查入口:本地 ETag 与观察值一致且检查 TTL 未过时可直接返回缓存;否则发一次 `HEAD`,只报告 `needs_update`,不会自动跟随 GET。Python、TS、JS 管理器可按 TTL 短路;Go 管理器的 `Check` 支持 TTL,但公开 `AIDStore.CheckAgentMD` 直接发 HEAD。`download_agent_md`/`downloadAgentMd`/`DownloadAgentMD` 才是正文下载入口。
|
|
102
|
+
|
|
103
|
+
四端当前实现位置:
|
|
104
|
+
|
|
105
|
+
- Python:`python/src/aun_core/agent_md.py` 的 `observe_meta`、`observe_rpc_meta`、`check`、`download`。
|
|
106
|
+
- Go:`go/agent_md_manager.go` 的观察、`Check`、下载;公开 `AIDStore.CheckAgentMD` 是直接 HEAD 的低层入口。
|
|
107
|
+
- TypeScript:`ts/src/agent-md.ts` 的 `observeMeta`、`observeRpcMeta`、`check`、`download`。
|
|
108
|
+
- JavaScript:`js/src/agent-md.ts` 的同名逻辑;浏览器记录存 IndexedDB,缺少持久层时退化为内存。
|
|
109
|
+
|
|
110
|
+
应用层按需同步示例(`AIDStore`):
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const state = await store.checkAgentMd(peerAid, 1);
|
|
114
|
+
if (state.ok && state.data.needs_update) {
|
|
115
|
+
await store.downloadAgentMd(peerAid);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
checked = await store.check_agent_md(peer_aid, ttl_days=1)
|
|
121
|
+
if checked.ok and checked.data["needs_update"]:
|
|
122
|
+
await store.download_agent_md(peer_aid)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```go
|
|
126
|
+
checked := store.CheckAgentMD(ctx, peerAid)
|
|
127
|
+
if checked.Ok && checked.Data.NeedsUpdate {
|
|
128
|
+
downloaded := store.DownloadAgentMD(ctx, peerAid)
|
|
129
|
+
if !downloaded.Ok { /* handle downloaded.Error */ }
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Go 的公开 `AIDStore.CheckAgentMD` 每次都执行 HEAD;`maxUnsyncedDays` 不会让该入口跳过 HEAD。
|
|
134
|
+
|
|
135
|
+
不要把 `remote_etag` 放进 `If-None-Match`,也不要因为每次 RPC 都收到相同 ETag 就重复下载。SDK 已按 AID、身份存储范围和观察代次做单飞/退避。
|
|
136
|
+
|
|
137
|
+
## 4. group.index
|
|
138
|
+
|
|
139
|
+
### 4.1 服务端协议
|
|
140
|
+
|
|
141
|
+
`group.index` 是 owner/admin SDK 生成并签名的 canonical JSONL。服务端不根据数据库重建正文,只做签名、Schema、`body_hash`、ETag、权限和 CAS 校验。
|
|
142
|
+
|
|
143
|
+
```mermaid
|
|
144
|
+
sequenceDiagram
|
|
145
|
+
participant SDK as Owner/Admin SDK
|
|
146
|
+
participant G as Group Service
|
|
147
|
+
participant DB as Group DB
|
|
148
|
+
|
|
149
|
+
SDK->>G: group.set_settings(indexed settings + signed group.index + expected_index_etag)
|
|
150
|
+
G->>DB: 事务内锁定 group.index
|
|
151
|
+
G->>DB: 比较当前 etag
|
|
152
|
+
alt ETag 匹配
|
|
153
|
+
G->>DB: 写 indexed settings 和 group.index
|
|
154
|
+
G-->>SDK: 成功 + _meta.group_indexes
|
|
155
|
+
else 冲突
|
|
156
|
+
G-->>SDK: group.index etag conflict
|
|
157
|
+
end
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
索引元数据示例:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"type": "index_meta",
|
|
165
|
+
"group_aid": "team.agentid.pub",
|
|
166
|
+
"etag": "\"sha256:...\"",
|
|
167
|
+
"last_modified": 1780000000000,
|
|
168
|
+
"body_hash": "sha256:...",
|
|
169
|
+
"schema": "aun.group.index.v1",
|
|
170
|
+
"signed_by": "alice.agentid.pub",
|
|
171
|
+
"sig_alg": "ECDSA-P256-SHA256",
|
|
172
|
+
"signature": "base64..."
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
响应版本提示:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{"_meta":{"group_indexes":{"team.agentid.pub":{
|
|
180
|
+
"etag":"\"sha256:...\"",
|
|
181
|
+
"last_modified":1780000000000,
|
|
182
|
+
"schema":"aun.group.index.v1"
|
|
183
|
+
}}}}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 4.2 SDK 观察、读取和写入
|
|
187
|
+
|
|
188
|
+
```mermaid
|
|
189
|
+
flowchart TD
|
|
190
|
+
M[收到 _meta.group_indexes] --> R[保存 remote_meta]
|
|
191
|
+
R --> E{remote etag == local_etag?}
|
|
192
|
+
E -->|是| F[本地快照 fresh]
|
|
193
|
+
E -->|否| T[标记 stale]
|
|
194
|
+
T --> A{应用需要最新设置?}
|
|
195
|
+
A -->|否| W[继续使用已验证本地快照,并暴露 stale]
|
|
196
|
+
A -->|是| P[getGroupIndex: group.get_settings(group.index)]
|
|
197
|
+
P --> V[验签、校验 entry etag、校验 signer 权限]
|
|
198
|
+
V --> U[保存 settings、entry_etags、index.jsonl、local_etag]
|
|
199
|
+
U --> F[结束:本地快照 fresh]
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
四端共同规则:
|
|
203
|
+
|
|
204
|
+
TypeScript/JavaScript 按需读取:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
const state = await client.group.checkGroupIndex({ group_id: groupAid });
|
|
208
|
+
if (state.needs_update) {
|
|
209
|
+
await client.group.getGroupIndex({ group_id: groupAid });
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Python 与 Go 分别调用 `client.group.check_group_index(...)` / `client.Group().CheckGroupIndex(...)`,需同步时调用对应的 `get_group_index` / `GetGroupIndex`。`updateGroupIndex` / `update_group_index` / `UpdateGroupIndex` 才执行签名写入和 `expected_index_etag` CAS。
|
|
214
|
+
|
|
215
|
+
- `checkGroupIndex` 只比较本地 `local_etag` 与已观察的 `remote_meta.etag`,不发 RPC;尚未观察到远端 meta 时,不能据此确认远端最新版本。
|
|
216
|
+
- `getGroupIndex` 才拉正文;成功验签后才把 `local_etag` 标为 fresh。
|
|
217
|
+
- `updateGroupIndex` 先读取最新索引、合并设置、重新签名,再提交 CAS;遇到 `group.index etag conflict` 重新读取并重试。
|
|
218
|
+
- indexed settings 的便捷读取可能使用已验证本地缓存;收到新远端 ETag 不会自动 pull 覆盖缓存,应用需显式调用 `getGroupIndex` 获取最新快照。
|
|
219
|
+
- 本地缓存按 `local_aid + group_aid` 隔离。Python/Go/TS 使用文件缓存;JS 使用 IndexedDB。
|
|
220
|
+
- `_meta.group_indexes` 不是索引正文;Gateway/Message 只透传或合并 meta,不生成索引。
|
|
221
|
+
|
|
222
|
+
Go/Python/TS/JS 的门面名称分别为 `check_group_index`/`CheckGroupIndex`/`checkGroupIndex`、`get_group_index`/`GetGroupIndex`/`getGroupIndex`、`update_group_index`/`UpdateGroupIndex`/`updateGroupIndex`。
|
|
223
|
+
|
|
224
|
+
## 5. 规范与实现边界
|
|
225
|
+
|
|
226
|
+
- `agent.md` 格式和发现规则见 [06-服务协议](../../../docs/aun文档/aun协议/06-服务协议.md#641-agentmd-规范);显式 `/agent.md` 访问见 [附录 K](../../../docs/aun文档/aun协议/附录K-Agent_Web发现协议.md#1342-显式访问-agentmd)。
|
|
227
|
+
- `group.index`、`expected_index_etag`、`_meta.group_indexes` 和冲突处理见 [Group 子协议 §10.13](../../../docs/aun文档/aun协议/10-Group-子协议.md#1013-群设置与-groupindex)。
|
|
228
|
+
- SDK agent.md 上传/下载/检查及被动观察见 [API 手册](06-API手册.md#agentmd)。
|
|
229
|
+
- Storage 的 `if_sha256` 是另一套 RPC 条件读取语义,不等于 agent.md 的 HTTP ETag,也不等于 group.index 的 CAS ETag。
|
|
230
|
+
|
|
231
|
+
源码索引:
|
|
232
|
+
|
|
233
|
+
| 链路 | 主要实现 |
|
|
234
|
+
|---|---|
|
|
235
|
+
| agent.md 服务端写入/HTTP ETag | `extensions/services/nameservice/go/internal/httpserver/agentmd.go` |
|
|
236
|
+
| Gateway agent.md meta | `extensions/services/gateway/go/internal/httpserver/server.go` |
|
|
237
|
+
| group.index ETag/签验 | `extensions/services/group/go/internal/groupindex/index.go` |
|
|
238
|
+
| group.index CAS | `extensions/services/group/go/internal/store/group_index_cas.go` |
|
|
239
|
+
| Group meta 注入 | `extensions/services/group/go/internal/settings/get_settings.go` |
|
|
240
|
+
|