@agentunion/fastaun 0.5.34 → 0.5.36
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 +56 -1
- package/_packed_docs/CHANGELOG.md +56 -1
- package/_packed_docs/INDEX.md +18 -11
- package/_packed_docs/KITE_DOCS_GUIDE.md +9 -9
- package/_packed_docs/agent.md/SCHEMA.md +1 -1
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +2 -2
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +17 -17
- package/_packed_docs/protocol/echo-probe-gateway.md +99 -0
- package/_packed_docs/protocol/echo-probe-sdk.md +91 -0
- package/_packed_docs/sdk/0.5.35-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +189 -0
- package/_packed_docs/sdk/0.5.35-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +204 -0
- package/_packed_docs/sdk/0.5.36-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +130 -0
- package/_packed_docs/sdk/0.5.36-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +176 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +2 -2
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +32 -6
- package/_packed_docs/sdk/09-group-rpc-manual.md +7 -7
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +13 -13
- 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 +73 -3
- 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 +50 -8
- package/_packed_docs/sdk/INDEX.md +23 -18
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +1 -1
- 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 +5 -5
- 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 +5 -5
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +9 -9
- package/_packed_docs//346/266/210/346/201/257/345/274/271/346/200/247/350/241/245/346/213/211/351/200/232/351/201/223/345/256/236/346/226/275/350/256/241/345/210/222.md +400 -0
- package/_packed_docs//346/266/210/346/201/257/345/274/271/346/200/247/350/241/245/346/213/211/351/200/232/351/201/223/346/226/271/346/241/210.md +485 -0
- package/dist/agent-md.d.ts +2 -1
- package/dist/agent-md.js +33 -6
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.js +5 -1
- package/dist/aid-store.js.map +1 -1
- package/dist/auth.js +36 -45
- package/dist/auth.js.map +1 -1
- package/dist/client/delivery.d.ts +8 -1
- package/dist/client/delivery.js +203 -50
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/lifecycle.js +10 -1
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +4 -0
- package/dist/client/rpc-pipeline.js +93 -10
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/sync-channels.d.ts +2 -1
- package/dist/client/sync-channels.js +33 -14
- package/dist/client/sync-channels.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +1 -0
- package/dist/client/v2-e2ee.js +24 -6
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +15 -0
- package/dist/client.js +329 -56
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +1 -0
- package/dist/events.js +5 -0
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mail-client.d.ts +101 -0
- package/dist/mail-client.js +369 -0
- package/dist/mail-client.js.map +1 -0
- package/dist/ownership-v21.d.ts +2 -1
- package/dist/ownership-v21.js +19 -9
- package/dist/ownership-v21.js.map +1 -1
- package/dist/pubsub/binding.js +9 -2
- package/dist/pubsub/binding.js.map +1 -1
- package/dist/pubsub/channel.d.ts +11 -3
- package/dist/pubsub/channel.js +91 -10
- package/dist/pubsub/channel.js.map +1 -1
- package/dist/pubsub/client.d.ts +8 -2
- package/dist/pubsub/client.js +62 -21
- package/dist/pubsub/client.js.map +1 -1
- package/dist/pubsub/index.d.ts +2 -2
- package/dist/pubsub/index.js +1 -1
- package/dist/pubsub/index.js.map +1 -1
- package/dist/pubsub/service.d.ts +6 -0
- package/dist/pubsub/service.js +101 -10
- package/dist/pubsub/service.js.map +1 -1
- package/dist/pubsub/types.d.ts +11 -1
- package/dist/tools/cross-sdk-agent.d.ts +1 -1
- package/dist/transport.d.ts +4 -0
- package/dist/transport.js +39 -2
- package/dist/transport.js.map +1 -1
- package/dist/udp-standby.d.ts +88 -0
- package/dist/udp-standby.js +483 -0
- package/dist/udp-standby.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
- package/scripts/patch-imapflow-external.mjs +69 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# echo 探针协议 — Gateway / Message / Group 实现规范
|
|
2
|
+
|
|
3
|
+
**状态**:v3.2,单 hop 全程递减规范
|
|
4
|
+
**日期**:2026-11-11
|
|
5
|
+
**适用**:本项目 AUN Gateway、Message、Group
|
|
6
|
+
**配套文档**:[`echo-probe-sdk.md`](./echo-probe-sdk.md)
|
|
7
|
+
|
|
8
|
+
## 1. 节点职责
|
|
9
|
+
|
|
10
|
+
| 节点 | 实际处理边界 |
|
|
11
|
+
|---|---|
|
|
12
|
+
| `AUN-Gateway.route` | 客户端、服务间或联邦 RPC 入站路由 |
|
|
13
|
+
| `AUN-Gateway.push` | 向客户端投递 message/group 事件 |
|
|
14
|
+
| `AUN-Message.relay` | 单聊 Message 转发 |
|
|
15
|
+
| `AUN-Group.relay` | 群聊 Group 转发 |
|
|
16
|
+
|
|
17
|
+
去程、回程使用相同节点名,由 dir 区分。每次实际经过都附行,包括后续 Gateway、同域多实例、跨域和相同名称的节点;不固定假设探针必定经过多少行或必定走满链路。
|
|
18
|
+
|
|
19
|
+
## 2. 识别与正文
|
|
20
|
+
|
|
21
|
+
只检查第一行,移除该行前导空白,再按最长前缀、大小写不敏感判断。
|
|
22
|
+
|
|
23
|
+
| 前缀 | 后继边界 | 处理 |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `echo.ecdiag` | 空白或行尾 | 与 echo 相同,网络节点允许附行 |
|
|
26
|
+
| `echo.ask` | 空白或行尾 | 与 echo 相同 |
|
|
27
|
+
| `echo` | 空白、`[` 或行尾 | 计数、附行、必要时提前回送 |
|
|
28
|
+
|
|
29
|
+
` echo hop=5`、`ECHO`、`echo[tag]` 均命中;`hello echo`、`echoes`、`echo.path` 不命中。不按正文或首行长度决定是否命中。
|
|
30
|
+
|
|
31
|
+
命中后仅移除第一行前导空白,保留原 echo 的其余首行内容、参数、正文及历史 trace。新增信息从第二行开始,以换行追加,不能覆盖或重排原文。
|
|
32
|
+
|
|
33
|
+
## 3. Payload 与唯一跳数
|
|
34
|
+
|
|
35
|
+
明文 payload 使用 `type=text`、`text`、`hop`,另以 `dir=fwd|ret` 标记方向。**跳数字段只有 hop**,删除旧诊断字段 max_hop/rhop,不再使用或生成。
|
|
36
|
+
|
|
37
|
+
有效 payload.hop 优先于首行 `hop=N`,两者都没有时默认 **100**。服务与四 SDK 统一使用 JSON 安全整数范围 `[-9007199254740991, 9007199254740991]`,首行允许 `+` / `-` 符号;布尔值、字符串型 payload.hop 和非整数无效,按首行参数或默认值处理。整数超出范围或递减结果超出范围时必须明确报错,不能回退 100。首次发起用非负预算,负数表示已经提前返程,不得重置或归零。历史 trace 不作为控制字段的权威来源。普通消息不自动注入诊断字段。
|
|
38
|
+
|
|
39
|
+
hop 为负数时必须按返程处理,即使旧 dir 仍为 fwd;其余情况优先读取有效 payload.dir,缺少有效方向时兼容正文独立行 `[AUN-Echo.return]`。非负 hop 的显式 dir=fwd 优先于旧标记。方向不能仅由正文最后一行推断。
|
|
40
|
+
|
|
41
|
+
### 3.1 去程
|
|
42
|
+
|
|
43
|
+
每个实际节点读取 hop,先执行 `hop = max(hop - 1, 0)`,再用结果附 dir=fwd 行并传递该值。
|
|
44
|
+
|
|
45
|
+
**减到 0 必须停止前送并立即提前返程**。收到 hop=0 也立即返程,不减到负数。Gateway、Message、Group 都必须生成完整回包,不能只停止、丢弃或以超时作为预期结果。
|
|
46
|
+
|
|
47
|
+
### 3.2 回程
|
|
48
|
+
|
|
49
|
+
反射节点把 dir 改为 ret,继续把 hop 减 1,写自己的回程行,沿原路返回。去程到 0 提前返程时,反射节点写 -1,上游依次写 -2、-3。正常业务终点尚未耗尽时可用 dir=ret 进入回程,后续每个实际回程节点同样先减 1 再写行。
|
|
50
|
+
|
|
51
|
+
例如初始 hop=3:SDK 去程 2 → Gateway 1 → Message 0;Message 回程 -1 → Gateway -2 → SDK -3,交付应用。
|
|
52
|
+
|
|
53
|
+
回程不再受去程预算阻断,不因 hop 为 0 或负数丢弃,不重新反射;正常回程跨过 0 时也继续递减。一个实际处理边界只计一次;终点有去程、回程两行,普通消息构造、持久化或复制事件不是额外网络节点。
|
|
54
|
+
|
|
55
|
+
## 4. 完整提前回送
|
|
56
|
+
|
|
57
|
+
沿原同步 RPC 调用链返回 `status=echo_return`,保留完整 payload、message_id 及适用的 from/to/group_id。上游不得把结果降为投递数、空成功结果或仅保留状态码。
|
|
58
|
+
|
|
59
|
+
Gateway 入站、push、后续 session-owner Gateway、联邦转发、Message、Group 均须传回下游获得的完整响应,并各自附本节点回程行。
|
|
60
|
+
|
|
61
|
+
Message 和 Group 都有同步回包通道;到限必须回送,不能要求发起者等待超时。同步 echo 诊断路径不强制落库,也不进入业务消息去重;重试相同 message_id 仍按实际经过附行、保留完整 echo_return。普通消息存储和去重策略不受影响。
|
|
62
|
+
|
|
63
|
+
需要取得回程结果的 echo 路径不得放入丢弃结果的异步队列。保留实际群成员路由,每个已执行分支保留完整 trace;回送定向原发起者、保留 group_id,不把诊断响应广播给全群。现有单 RPC 返回已获得的诊断结果,不自动聚合所有群成员。接收 SDK 发起的定向回送是新的异步请求,不保证同一物理 Gateway。
|
|
64
|
+
|
|
65
|
+
收件人待机且仅能唤醒时,Gateway 应在本跳完整提前回送并记录原因,不能只返回 woken。离线、零投递、写入失败、owner 不可用等无法继续的情况,必须完整提前回送或通过现有 RPC 错误如实报告,不能返回 sent。message_id 应在提前返回前补齐,适用 group_id 在本域、联邦和回包中均须保留。
|
|
66
|
+
|
|
67
|
+
SDK 本地早停和服务端回包均必须进入应用接收事件,具体见配套 SDK 文档。
|
|
68
|
+
|
|
69
|
+
## 5. 明文约束
|
|
70
|
+
|
|
71
|
+
不支持加密 echo,由 SDK 在加密前识别并强制明文。服务端仅处理可见的明文 echo。
|
|
72
|
+
|
|
73
|
+
收到 encrypted/encrypt 标记、e2ee.* payload 或密文数据时,按普通消息原样处理,不追加 trace、不改密文、不尝试解密寻找前缀。这不构成加密 echo 的支持或验收。
|
|
74
|
+
|
|
75
|
+
## 6. 每跳 Trace 与耗时
|
|
76
|
+
|
|
77
|
+
`HH:MM:SS.mmm [node] dir=fwd|ret hop=N enc=0 ver=VERSION epoch=MS tz=±HH:MM [duration_ms=N] <节点字段>`
|
|
78
|
+
|
|
79
|
+
每行包含墙钟前缀、节点、dir、hop、enc、ver、epoch、tz,毫秒之后紧跟空格。ver 取服务编译版本,取不到为 unknown。route 保留 from/to/conn_uptime,push 保留 to,Message/Group 保留 from/to 及适用群标识。
|
|
80
|
+
|
|
81
|
+
每条回程行包含自身真实 duration_ms。同步获得 echo_return 时,用本地单调时钟测请求入口至形成回程结果,包含等待下游;新的定向返程请求没有原去程上下文,测本节点本次请求入口到向下一节点交接正文的处理时间。不得固定填 0 或用跨机器 epoch 差值代替。
|
|
82
|
+
|
|
83
|
+
不去重:同名节点、同方向或重复实际处理也必须附行。不设 echo 专用长度限制,不截断、不添加 `[TRUNCATED]`。通用传输层限制导致的失败必须如实返回,不得静默丢失 trace。
|
|
84
|
+
|
|
85
|
+
## 7. 实现入口
|
|
86
|
+
|
|
87
|
+
| 服务 | 现有入口 |
|
|
88
|
+
|---|---|
|
|
89
|
+
| Gateway | `extensions/services/gateway/go/internal/httpserver/server.go` 的 route、push、dispatch、后续 Gateway 与联邦路径 |
|
|
90
|
+
| Message | `extensions/services/message/go/internal/legacy/service.go`、`cmd/message-go/main.go` 的本域与联邦同步转发 |
|
|
91
|
+
| Group | `extensions/services/group/go/internal/service/send_message.go`、`relay_event.go` 及 rpc/cmd 的本域与联邦路径 |
|
|
92
|
+
|
|
93
|
+
保持模块独立实现,不引入跨模块共享代码。路由元数据 `_route`、RPC 级 `_trace` 与 echo 正文诊断分开。
|
|
94
|
+
|
|
95
|
+
## 8. 验收
|
|
96
|
+
|
|
97
|
+
更新已有测试,覆盖默认 hop=100、payload 优先首行参数、每个节点去程减 1、到 0 停止前送并完整回送、反射及上游每条回程继续减 1、负 hop 自动识别为返程、仅 hop 一个跳数字段、三前缀、前导空白移除、首行与其余正文保留、长正文和重复节点继续附行、普通密文不变、真实回程耗时、单聊/群聊/跨域/多 Gateway 的完整回包不被异步路径或投递统计吞掉。
|
|
98
|
+
|
|
99
|
+
不启动 Kite 或部署环境作为本机单元测试的一部分。外部 App、Rust SDK、EvolCore 的完整链路验收另行开展。
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# echo 探针协议 — SDK 实现规范
|
|
2
|
+
|
|
3
|
+
**状态**:v3.2,单 hop 全程递减规范
|
|
4
|
+
**日期**:2026-11-11
|
|
5
|
+
**适用**:本项目 fastaun SDK(Python / Go / TS / JS)
|
|
6
|
+
**配套文档**:[`echo-probe-gateway.md`](./echo-probe-gateway.md)
|
|
7
|
+
|
|
8
|
+
## 1. 范围与节点
|
|
9
|
+
|
|
10
|
+
SDK 负责 `AUN-SDK.send`、`AUN-SDK.receive`。外部 Rust SDK 可采用 `AUN-RustSDK.send/receive`;其位置为 `D:/modelunion/acp-app`,与 App、EvolCore 一样不在本次代码修改范围内。
|
|
11
|
+
|
|
12
|
+
SDK、Gateway、Message、Group 每次实际处理 echo 都记录自己的节点。同名节点再次经过仍附行,不能按节点名或方向去重。业务内部阶段不额外消耗网络跳数。
|
|
13
|
+
|
|
14
|
+
## 2. 前缀与正文
|
|
15
|
+
|
|
16
|
+
只检查第一行,先移除该行前导空白,再按最长前缀、大小写不敏感识别。
|
|
17
|
+
|
|
18
|
+
| 前缀 | 后继边界 | SDK 行为 |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `echo.ecdiag` | 空白或行尾 | 明文、计数、附行;允许网络节点记录 |
|
|
21
|
+
| `echo.ask` | 空白或行尾 | 与 echo 相同,业务端决定是否经过 agent |
|
|
22
|
+
| `echo` | 空白、`[` 或行尾 | 明文、计数、附行 |
|
|
23
|
+
|
|
24
|
+
` echo hop=5`、`ECHO`、`echo[tag]` 均命中;`hello echo`、`echoes`、`echo.path` 不命中。正文和首行长度不参与识别。
|
|
25
|
+
|
|
26
|
+
命中后只移除原始第一行的前导空白,保留其余首行内容、参数、正文和历史 trace 的顺序。所有新增 trace 从第二行开始,以换行追加。普通消息不因本规范改变正文。
|
|
27
|
+
|
|
28
|
+
不做 trace 去重,不设 echo 专用字数或字节限制,不截断、不添加 `[TRUNCATED]`。通用传输大小限制仍由原传输层处理,失败必须如实报告,不能静默丢掉正文或 trace。
|
|
29
|
+
|
|
30
|
+
## 3. Payload 与方向
|
|
31
|
+
|
|
32
|
+
| 字段 | 约定 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `type` | 固定 `text` |
|
|
35
|
+
| `text` | 第一行为原 echo,按第 2 节移除前导空白 |
|
|
36
|
+
| `hop` | 唯一跳数字段;去程、回程均递减,负数表示提前返程 |
|
|
37
|
+
| `dir` | 方向标记 `fwd` / `ret`,不是第二个跳数;缺省 fwd |
|
|
38
|
+
|
|
39
|
+
删除旧诊断字段 `max_hop`、`rhop`,不再生成或使用。普通消息不自动携带 echo 的诊断字段。
|
|
40
|
+
|
|
41
|
+
有效 `payload.hop` 优先于首行 `hop=N`;两者都没有时默认 **100**。四 SDK 和服务统一使用 JSON 安全整数范围 `[-9007199254740991, 9007199254740991]`,首行允许 `+` / `-` 符号;布尔值、字符串型 payload.hop 和非整数无效,按首行参数或默认值处理。整数超出范围或递减结果超出范围时必须明确报错,不能回退 100。首次发起用非负预算,负数表示已经提前返程,不能重置或归零。正文历史 trace 不作为控制字段的权威来源。
|
|
42
|
+
|
|
43
|
+
hop 为负数时必须按返程处理,即使旧方向字段仍为 fwd;其余情况优先读取有效 `payload.dir`,没有有效方向时兼容正文独立行 `[AUN-Echo.return]`。非负 hop 的显式 `dir=fwd` 优先于旧标记。不能只检查正文最后一行决定方向。
|
|
44
|
+
|
|
45
|
+
## 4. 去程与回程
|
|
46
|
+
|
|
47
|
+
每次去程处理:读取 hop,计算 `hop = max(hop - 1, 0)`,用所得值写 `dir=fwd` trace 并传递同一值。**减到 0 就必须停止前送,立即提前返程**;收到 hop=0 也立即返程,不减为负数。
|
|
48
|
+
|
|
49
|
+
反射节点将 `dir` 改为 `ret`,继续把 hop 减 1,追加自己的回程行,然后返回完整正文。因此到 0 提前返程时,反射节点写 -1,上游依次写 -2、-3。正常业务终点尚未耗尽时可用 dir=ret 进入回程,每个回程节点同样先减 1 再附行。
|
|
50
|
+
|
|
51
|
+
示例:初始 hop=3,SDK 去程写 2,Gateway 写 1,Message 写 0;Message 停止前送,回程写 -1,Gateway 写 -2,SDK 写 -3,最终交付应用。
|
|
52
|
+
|
|
53
|
+
回程不再按去程预算停止,不因 hop=0 或负数丢弃结果,也不重新反射;已经在正常回程时跨过 0 仍继续递减。每个实际处理边界只执行一次计数;终点分别记录去程、回程。接收 SDK 自动回送时,不得因调用内部发送入口而重复记录同一个接收节点。
|
|
54
|
+
|
|
55
|
+
## 5. 明文约束
|
|
56
|
+
|
|
57
|
+
不支持加密 echo。SDK 必须在加密路由之前识别三种前缀,强制 `encrypt=false`,发送明文 `payload.type=text`,trace 固定 `enc=0`。
|
|
58
|
+
|
|
59
|
+
收到仍为密文的消息时按普通消息处理,不解开密文寻找 echo,不修改密文。不能把仅端节点有行的加密消息当作本协议的成功验收。
|
|
60
|
+
|
|
61
|
+
## 6. 提前回送与应用交付
|
|
62
|
+
|
|
63
|
+
SDK 本地去程减到 0 时不发网络请求,直接生成 `status=echo_return` 响应,包含完整 payload、message_id 和适用的 from/to/group_id,并追加本地回程行。
|
|
64
|
+
|
|
65
|
+
SDK 收到服务端 `echo_return` 时,先追加 `AUN-SDK.receive` 回程行,再通过现有 `message.received` 或 `group.message_created` 应用入口交付。本地提前返回同样使用 receive 回程行;不能只把回包作为 send 状态返回。
|
|
66
|
+
|
|
67
|
+
接收 SDK 去程到 0 时停止交给业务端处理,自动明文回送原发送者。群聊回送定向原发送者,保留 group_id 诊断上下文,不再次广播全群。该定向发送是新的异步请求,不能据此宣称返回经过原同步调用栈或同一物理 Gateway。
|
|
68
|
+
|
|
69
|
+
沿现有同步 RPC 原调用链返回时,完整响应不得被投递统计、空成功结果、业务去重或异步队列覆盖。投递不可继续时应完整提前回送或如实报错,不能把零投递、仅唤醒或写入失败报告为 sent。普通消息的持久化与投递策略保持原有约定。
|
|
70
|
+
|
|
71
|
+
## 7. Trace 与处理耗时
|
|
72
|
+
|
|
73
|
+
`HH:MM:SS.mmm [node] dir=fwd|ret hop=N enc=0 ver=VERSION epoch=MS tz=±HH:MM [duration_ms=N] <节点字段>`
|
|
74
|
+
|
|
75
|
+
每行必须包含墙钟前缀、节点名、dir、hop、enc、ver、epoch、tz;毫秒墙钟之后紧跟空格。ver 取包版本,无法取得时为 unknown。SDK 自定义字段保留 aid、conn_uptime。
|
|
76
|
+
|
|
77
|
+
每条回程行必须包含本节点真实 `duration_ms`。同步获得 echo_return 时,用本地单调时钟测量从该请求入口到形成回程结果的时间,包含等待下游;新的定向返程请求没有原去程上下文,测从本节点本次请求或接收入口到向下一节点交接正文的处理时间。不得固定填 0,也不得用跨机器 epoch 相减代替。
|
|
78
|
+
|
|
79
|
+
仅追加实际发生的节点记录,不删除历史行。RPC 级 `_trace`、`setTraceMode` 与正文探针相互独立。
|
|
80
|
+
|
|
81
|
+
## 8. 实现入口与验收
|
|
82
|
+
|
|
83
|
+
| SDK | 现有入口 |
|
|
84
|
+
|---|---|
|
|
85
|
+
| Python | `src/aun_core/client.py`、`_client/rpc_pipeline.py`、`_client/delivery.py` |
|
|
86
|
+
| Go | `client.go`、`client_rpc_pipeline.go`、`client_delivery.go` |
|
|
87
|
+
| TS / JS | `src/client.ts`、`src/client/rpc-pipeline.ts`、`src/client/delivery.ts` |
|
|
88
|
+
|
|
89
|
+
更新已有测试,覆盖三前缀、前导空白移除、首行与其余正文保留、长正文、同名节点重复附行、默认 hop=100、首行 hop 参数与 payload 优先级、仅一个跳数字段、去程递减到 0、回程继续递减及负 hop 识别、强制明文、真实耗时、本地无网络提前回送、服务回包进入应用事件、单聊与群定向回送。
|
|
90
|
+
|
|
91
|
+
外部 App、Rust SDK、EvolCore 未升级时不得宣称外部完整链路验收通过。
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# 0.5.35 SDK 应用集成指南
|
|
2
|
+
|
|
3
|
+
本文面向从已发布 **0.5.34** 升级到 **0.5.35** 的应用,依据截至 2026-11-12 的工作区源码整理。0.5.35 为目标版本,本文不代表安装包已发布或部署验收已完成。
|
|
4
|
+
|
|
5
|
+
首次接入先读 [快速开始](01-快速开始.md)、[连接与认证](04-连接与认证.md)和 [API 手册](06-API手册.md)。本版实现契约见 [开发与移植指南](0.5.35-SDK开发与移植指南.md),源码差异和比较基线见 [parity 0.5.35](../../python/CHANGES_FOR_PARITY.md#v0535)。0.5.34 的多角色、持久目录、durable outbox、Storage/Group FS/Service Proxy 接入见 [历史应用指南](0.5.34-SDK应用集成指南.md)。
|
|
6
|
+
|
|
7
|
+
## 1. 升级范围与支持边界
|
|
8
|
+
|
|
9
|
+
| 能力 | Python | Node TypeScript | Browser JavaScript | Go |
|
|
10
|
+
| --- | --- | --- | --- | --- |
|
|
11
|
+
| EventService 通配订阅、发布者过滤、同 Client 本地收发 | 支持 | 支持 | 支持 | 支持 |
|
|
12
|
+
| 后台累计 ACK、同步恢复调整、Echo v3.2 | 支持 | 支持 | 支持 | 支持 |
|
|
13
|
+
| 原生 UDP 待机 | 支持 | 支持 | 无原生实现 | 支持 |
|
|
14
|
+
| 独立 SMTP/IMAP MailClient | 支持 | 支持 | 无原生实现 | 支持 |
|
|
15
|
+
| 本版语言专属变化 | Windows 路径、上传清理、闭环压测 CLI | 邮件信封与 ImapFlow 适配 | 浏览器交付与测试版本对齐 | 只读凭据身份、DNS 回退、SQLite 初始化 |
|
|
16
|
+
|
|
17
|
+
本次发布按**配套服务单实例部署**支持。Redis 缓存的存在不代表同一服务已支持多副本共享状态;本版不据此扩大部署范围。独立 Mail 尚未完成整体端到端验收,核心 IM 接入不要求启用 Mail。
|
|
18
|
+
|
|
19
|
+
四 SDK 的代码、项目配置和相关测试版本已统一为 `0.5.35`。应用需核对实际安装产物的版本,并使用支持对应能力的配套服务;客户端升级不会自动启用 Gateway 的 UDP 待机或部署独立 Mail。
|
|
20
|
+
|
|
21
|
+
## 2. EventService:通配订阅和发布者过滤
|
|
22
|
+
|
|
23
|
+
### 2.1 先授权具体事件,再按模式订阅
|
|
24
|
+
|
|
25
|
+
`subscribe`/`unsubscribe` 新增点分层通配:`task.*` 可匹配 `task.completed`,不能匹配 `task.worker.completed`。层内可使用 `*`,不支持 `**`、空层或正则表达式。
|
|
26
|
+
|
|
27
|
+
授权申请、grant scope 和发布仍使用完整事件名。订阅模式只在**当前 Bus 目录与当前设备有效租约的授权交集**内展开,返回实际订阅的具体事件。目录后来新增事件时,应在取得相应授权后重新订阅;旧通配订阅不会自动扩展。
|
|
28
|
+
|
|
29
|
+
没有目录命中返回 `UNKNOWN_EVENT`;有目录命中但无可用授权返回 `FORBIDDEN`。取消订阅按当前已订阅集合展开模式。
|
|
30
|
+
|
|
31
|
+
### 2.2 按可信发布者信息筛选
|
|
32
|
+
|
|
33
|
+
| 过滤含义 | Python/线上字段 | TS/JS 选项 | Go 选项 |
|
|
34
|
+
| --- | --- | --- | --- |
|
|
35
|
+
| 发布者 AID | `publisher_aids` | `publisherAids` | `PublisherAIDs` |
|
|
36
|
+
| 名片主体类型 | `publisher_types` | `publisherTypes` | `PublisherTypes` |
|
|
37
|
+
| 名片扩展类型 | `publisher_exttypes` | `publisherExttypes` | `PublisherExtTypes` |
|
|
38
|
+
|
|
39
|
+
同一字段内多个模式为 OR,不同字段之间为 AND;模式沿用上述分层 `*` 规则。省略字段表示该维度不限,显式空数组无效。每个字段允许 1–64 项,每个模式的 UTF-8 长度最多 256 字节。
|
|
40
|
+
|
|
41
|
+
以下示例假定应用已启动 EventService、取得 Sub 授权,且当前目录包含允许订阅的 `task` 事件:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
await client.EventService.subscribe(busAid, ['task.*'], {
|
|
45
|
+
publisherTypes: ['worker-*'],
|
|
46
|
+
publisherExttypes: ['task.executor'],
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
AID 来自认证发送者,`type`/`exttype` 来自验签通过的发布者 `agent.md`,不能通过事件正文自报身份。名片暂时无法读取或验证时,要求类型的订阅不会匹配;不设类型条件或仅按 AID 过滤的订阅不受该名片读取失败影响。
|
|
51
|
+
|
|
52
|
+
### 2.3 修改、恢复与同进程投递
|
|
53
|
+
|
|
54
|
+
再次订阅同一具体事件会**替换该事件的过滤条件**;省略过滤字段会恢复为不限。希望保留过滤时,更新订阅应再次传入完整条件。
|
|
55
|
+
|
|
56
|
+
SDK 持久化具体事件及其过滤条件,重新授权后逐事件恢复。Python/Node/Go 使用 SQLite,Browser 使用 IndexedDB;状态按身份、Bus、设备与 slot 隔离。修改条件或取消订阅后,排队和回调开始前会复核订阅代次,已经执行的业务操作仍由应用负责。
|
|
57
|
+
|
|
58
|
+
同一个 Client 内,Bus 为本端 AID、device/slot 匹配的 Bus/Pub/Sub 可以直接在进程内投递。跨 Client、设备或 slot 仍走网络。本地路径继续执行角色授权、租约、TTL、去重和容量检查;容量满时等待容量或期限到达,不提供无限队列。
|
|
59
|
+
|
|
60
|
+
完整角色配置、凭证和事件生命周期见 [事件应用集成专题](AUN事件发布订阅应用集成指南.md)。
|
|
61
|
+
|
|
62
|
+
## 3. 消息 ACK、同步与连接恢复
|
|
63
|
+
|
|
64
|
+
后台 Pull 在本地提交消息后调度累计 ACK,同一 namespace 的更高水位会合并,失败后重试。前台 Pull 继续等待 ACK。ACK 表示协议消费进度,不是应用的业务处理完成证明;业务入库、幂等和完成回执仍按应用自己的契约处理。
|
|
65
|
+
|
|
66
|
+
关闭 Client 仅有限等待后台 ACK,不保证关闭前全部确认已抵达服务端。重连后的重复交付应继续使用现有消息标识去重,不能因后台 ACK 改为异步就删除应用幂等逻辑。
|
|
67
|
+
|
|
68
|
+
| 变化 | 升级时的应用影响 |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| 自动连接后恢复随机延后 30–60 秒 | 包含补拉及组织身份/待上传名片恢复;不要将认证成功等同于历史已补齐 |
|
|
71
|
+
| 关闭后台同步时不调度上述自动恢复 | 显式 Pull 和消息通知触发仍使用各自入口 |
|
|
72
|
+
| 移除 `history_bytes_per_second` 主动节流 | 不再依赖该项限制历史吞吐;并发、页字节上限、在途内存预留和背压仍有效 |
|
|
73
|
+
| 辅助连接 ready/退役时更新同步需求 | SDK 随实际连接状态调整;`gateway.sync_demand` 不计为业务活动 |
|
|
74
|
+
| TS/JS 减少重复 Pull/ACK、合并群补拉 | 应用继续按消息和同步生命周期消费,不依赖内部任务次数 |
|
|
75
|
+
|
|
76
|
+
现有同步事件及 `source`、History、已读语义见 [API 手册](06-API手册.md)和 [最佳实践](08-最佳实践.md)。
|
|
77
|
+
|
|
78
|
+
## 4. Echo v3.2:诊断请求与结果
|
|
79
|
+
|
|
80
|
+
SDK 去掉首行前导空白后,按最长前缀识别 `echo.ecdiag`、`echo.ask`、`echo`,大小写不敏感。这类诊断强制明文,应用不要把敏感正文放入 Echo 请求。
|
|
81
|
+
|
|
82
|
+
控制字段统一为 `hop`,默认 100。payload 中有效整数优先于首行 `hop=N`;安全整数范围为 ±9007199254740991。去程递减到 0 后立即返程,负数表示回程并继续递减;旧 `max_hop`/`rhop` 不再控制转发。
|
|
83
|
+
|
|
84
|
+
本版保留完整正文及重复经过节点的 trace,回程耗时采用本地单调时钟。本地提前返回和服务返回的 `echo_return` 都通过既有 `message.received`/`group.message_created` 入口交付;群接收端的提前返回定向原发送者。
|
|
85
|
+
|
|
86
|
+
| 结果字段 | 应用解释 |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `reason=timeout`/`send_failed` | 本地发送超时或失败的诊断原因 |
|
|
89
|
+
| `delivery_state=not_delivered` | 该诊断判断未完成投递 |
|
|
90
|
+
| `delivery_state=unknown` | 远端是否收到尚不确定,不应直接判为丢失并盲目重发 |
|
|
91
|
+
| `echo_error` | 原发送错误的诊断信息 |
|
|
92
|
+
|
|
93
|
+
认证错误和密文发送不转换为上述本地诊断;业务回调抛错不会重复生成一条诊断。完整格式见 [Echo SDK 规范](../protocol/echo-probe-sdk.md),本文不宣称外部 App/Rust/EvolCore 链路已完成验收。
|
|
94
|
+
|
|
95
|
+
## 5. UDP 待机:何时可以释放 WebSocket
|
|
96
|
+
|
|
97
|
+
### 5.1 协商与准入
|
|
98
|
+
|
|
99
|
+
Python、Node TS、Go 的主长连接只有在服务端同时返回严格布尔值 `negotiated_capabilities.udp_standby_v1=true`、`udp_standby.enabled=true` 时才启用。Gateway 缺省关闭;未协商、短连接、辅助连接及 Browser 保持原连接方式。Node 可通过 `connect({ udp_standby: false })` 退出该能力,此选项写法不要套用于其他语言。
|
|
100
|
+
|
|
101
|
+
空闲准入仍受名片 `type=human`、未完成 RPC、ACK、同步/交付、关闭和迁移等状态约束。待机执行 prepare → UDP 路径验证 → commit,成功后释放 WebSocket;正常切换不作为应用离线。
|
|
102
|
+
|
|
103
|
+
### 5.2 区分两套订阅
|
|
104
|
+
|
|
105
|
+
Gateway 的协议级 `event.subscribe` 控制连接接收哪些通知;`EventService.subscribe` 控制 Bus 事件订阅。两者不是同一套订阅。
|
|
106
|
+
|
|
107
|
+
默认全事件、queue/stream 或不在待机白名单的订阅会保持 WebSocket;SDK 不会为省连接擅自缩窄订阅。只有应用确认无需其他通知时,才可显式设置所需集合,例如:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
await client.call("event.subscribe", {
|
|
111
|
+
"events": ["message.received", "group.message_created"],
|
|
112
|
+
})
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
SDK 使用 prepare 返回的 `event_subscriptions` 快照,在恢复认证时写回 `auth.connect.options.event_subscriptions`。应用修改通知集合时应重新核对待机资格。
|
|
116
|
+
|
|
117
|
+
### 5.3 唤醒和心跳
|
|
118
|
+
|
|
119
|
+
新业务请求、消息提示、ticket/lease/对账期限以及连续心跳故障会恢复 WebSocket。并发唤醒会合并,各请求保留自己的超时和取消边界;SDK 不自动重放已经发出的写请求。
|
|
120
|
+
|
|
121
|
+
UDP 只承载控制提示,不传消息正文;`WAKE_ACK` 不代表应用已消费,不延长业务 TTL,也不能唤醒已经退出的进程。
|
|
122
|
+
|
|
123
|
+
三端均采用当前有效 `HEARTBEAT_ACK` 返回的新心跳周期,下一轮按新周期执行 ±20% 抖动。Python 在收包匹配当前请求后更新策略,再由心跳循环读取;默认策略约为 25 秒周期、5 秒等待,连续三次失败回到 WebSocket,实际以服务端协商策略为准。
|
|
124
|
+
|
|
125
|
+
## 6. 原生 MailClient:独立接线和恢复
|
|
126
|
+
|
|
127
|
+
### 6.1 与 Gateway 客户端分开配置
|
|
128
|
+
|
|
129
|
+
原生 MailClient 直接连接独立 SMTP STARTTLS(默认 587)和 IMAPS(默认 993),默认主机为 `mail.{issuer}`。认证使用 AID 证书、TLS 和 SASL EXTERNAL,不使用 Gateway JWT。旧 `client.mail`/Go `Mail()` RPC 门面继续兼容,但不能用它代替原生客户端的部署与认证配置。
|
|
130
|
+
|
|
131
|
+
| SDK | 构造入口 | 凭据 provider 返回值 | 自定义服务端信任根 |
|
|
132
|
+
| --- | --- | --- | --- |
|
|
133
|
+
| Python | `aun_core.MailClient(issuer, credential_provider=...)` | `cert_pem`/`private_key_pem`,或 `cert_file`/`key_file` | `server_trust_bundle` 为 CA 文件路径 |
|
|
134
|
+
| Node TS | `new MailClient({ issuer, credentialProvider, serverTrustBundle })` | `{ cert, key }`,内容为 string/Buffer,可异步提供 | CA 内容,string/Buffer |
|
|
135
|
+
| Go | `NewMailClient(MailClientOptions{...})` | `func(context.Context) (tls.Certificate, error)` | `ServerTrustBundle []byte` |
|
|
136
|
+
|
|
137
|
+
连接会准备 SMTP 和 IMAP 两条连接,默认连接超时 10 秒、命令超时 30 秒。provider 应提供当前身份凭据;轮换后客户端重建连接。关闭时使用各语言的客户端关闭入口,Browser 不提供这些原生网络能力。
|
|
138
|
+
|
|
139
|
+
### 6.2 分开处理发送与 Sent 结果
|
|
140
|
+
|
|
141
|
+
支持结构化 MIME、附件或 raw MIME,并返回逐收件人状态。`accepted` 仅代表 SMTP 接受,不能当作最终送达回执。
|
|
142
|
+
|
|
143
|
+
| 状态维度 | 返回值 | 应用处理 |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| 发送 | `accepted`/`partial`/`rejected`/`accepted_unknown` | 按收件人结果展示;未知状态应先核对,避免重复邮件 |
|
|
146
|
+
| Sent 副本 | `not_requested`/`saved`/`failed`/`unknown` | 独立于发送结果;副本失败不代表 SMTP 一定未接受 |
|
|
147
|
+
|
|
148
|
+
Python raw MIME 保留原始头部和正文,仅补缺失的 Date/Message-ID;投递时剥离 Bcc 及折行,Sent 保留完整副本。Node 会复制并规范化信封、去重收件人,不修改调用者传入的信封。
|
|
149
|
+
|
|
150
|
+
### 6.3 用 UIDVALIDITY/UID 恢复监听
|
|
151
|
+
|
|
152
|
+
IMAP 提供 UID 查询/修改、流式读取和 watch。检查点应连同邮箱保存 `UIDVALIDITY`/UID,不能在 UIDVALIDITY 变化后复用旧 UID。
|
|
153
|
+
|
|
154
|
+
| SDK | 监听入口与变化事件 | UIDVALIDITY 改变后的行为 |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| Python | `watch(mailbox, uidvalidity, uid=0)` 异步迭代;`change` | 产出 `resync_required` 后结束迭代 |
|
|
157
|
+
| Node TS | `watch(mailbox, { uidValidity, uid }, signal?)` 异步生成器;`changes` | 产出 `resync_required`,重置 UID 后继续 |
|
|
158
|
+
| Go | `Watch(ctx, mailbox, checkpoint, consume)` 回调;初始 `sync`,后续 `changed` | 回调 `resync_required` 后结束当前 Watch,返回 nil |
|
|
159
|
+
|
|
160
|
+
应用收到 `resync_required` 后重建该邮箱的索引和检查点,并按所在语言决定继续消费或重新启动 watch。流式读取对应 Python `fetch_stream`、Node `fetchStream`、Go `FetchStream`,按各自接口管理流的生命周期。
|
|
161
|
+
|
|
162
|
+
Mail SDK 能力不等于独立邮件服务整体可用。本次 Mail 端到端验收未完成,默认 Go 运行镜像 `AUN_INCLUDE_MAIL=0` 不启用 Mail;构建阶段仍编译 Mail,不能据此忽略其构建依赖。
|
|
163
|
+
|
|
164
|
+
## 7. Python/Go 专属接入变化
|
|
165
|
+
|
|
166
|
+
Python 修正 Windows 长路径下的 pending 身份、名片缓存和 group index 写入,并在 HTTP 上传结束时清理会话。应用沿用原存储和上传入口,无需迁移数据格式。
|
|
167
|
+
|
|
168
|
+
Python CLI 新增闭环容量工具,区分 RPC 接受和完整投递的吞吐/P99,支持有限 pending、阶梯并发、持续复验及断点恢复。仅查看计划可运行:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
aun bench capacity closed-loop example.com --case p2p-plain --run-id sdk035 --dry-run
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
场景包括 `p2p-plain`、`p2p-online`、`group-plain`、`group-online`;实际压测前按 [测试运行指南](../aun测试运行指南.md)准备环境。命令存在不代表已测得服务器容量。
|
|
175
|
+
|
|
176
|
+
Go 新增 `NewReadOnlyIdentityClient`,接收已有 P-256 证书/私钥、明确的 WSS 地址、device/slot 和可选 CA,状态在实例内存中隔离。“只读”指凭据存储,不限制为只读 RPC。相同证书 PEM 首尾空白可接受,实际换证书会被拒绝;DNS IP 回退仍保留原域名和显式端口 Host。
|
|
177
|
+
|
|
178
|
+
## 8. 升级验收清单
|
|
179
|
+
|
|
180
|
+
| 范围 | 应用验收重点 |
|
|
181
|
+
| --- | --- |
|
|
182
|
+
| 版本与服务 | 四 SDK 实际产物版本、配套服务版本、单实例部署边界 |
|
|
183
|
+
| EventService | 具体事件授权、通配展开、过滤替换、重启恢复、取消后的排队事件、本地与网络路径 |
|
|
184
|
+
| 消息恢复 | 后台 ACK 重试、重连重复消息幂等、30–60 秒恢复窗口、历史背压 |
|
|
185
|
+
| Echo | 明文、唯一 hop、现有回调入口、未知投递状态分支 |
|
|
186
|
+
| UDP(三端) | 未协商保持 WS、human/忙碌阻止入睡、订阅恢复、周期更新、故障唤醒 |
|
|
187
|
+
| Mail(按需) | 独立服务与凭据轮换、逐收件人和 Sent 状态、UIDVALIDITY 变化、断线恢复 |
|
|
188
|
+
|
|
189
|
+
本文核对了当前接口和源码,并定向运行 Python UDP 心跳测试(11 项通过);未执行 Docker、公网、浏览器 live、跨域 E2E 或 Mail 整体验收。其余既有执行记录及限制见 [parity 的核验范围](../../python/CHANGES_FOR_PARITY.md#v0535),不能把文档清单当作完整发布测试报告。
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# 0.5.35 SDK 开发与移植指南
|
|
2
|
+
|
|
3
|
+
本文面向维护四 SDK、实现新语言 SDK 或核对兼容性的开发者,整理已发布 **0.5.34 → 目标 0.5.35** 的协议、状态机与实现增量,依据截至 2026-11-12 的工作区源码。
|
|
4
|
+
|
|
5
|
+
应用调用和升级验收见 [应用集成指南](0.5.35-SDK应用集成指南.md),比较基线、四端落点和已有验证见 [parity 0.5.35](../../python/CHANGES_FOR_PARITY.md#v0535)。既有身份、E2EE、EventService durable outbox、Storage、Group FS 与 Service Proxy 契约继续参考 [0.5.34 开发与移植指南](0.5.34-SDK开发与移植指南.md),本文只展开本版增量。
|
|
6
|
+
|
|
7
|
+
## 1. 实现范围与职责
|
|
8
|
+
|
|
9
|
+
| 范围 | Python | Node TypeScript | Browser JavaScript | Go |
|
|
10
|
+
| --- | --- | --- | --- | --- |
|
|
11
|
+
| EventService 模式、过滤、本地通道 | 支持;SQLite | 支持;SQLite | 支持;IndexedDB | 支持;SQLite |
|
|
12
|
+
| 累计 ACK、同步恢复、Echo v3.2 | 支持 | 支持 | 支持 | 支持 |
|
|
13
|
+
| UDP 待机 | 原生 UDP | 原生 UDP | 无原生实现 | 原生 UDP |
|
|
14
|
+
| 独立 MailClient | SMTP/IMAP | SMTP/IMAP | 无原生实现 | SMTP/IMAP |
|
|
15
|
+
|
|
16
|
+
SDK 负责本地状态、认证请求、投递调度和连接生命周期;Gateway/Message/Group/独立 Mail 服务负责对应服务端事实。本版配套服务按**单实例部署**支持,Redis 缓存不构成多实例一致性契约。移植时不能把 SDK 的进程内能力扩写为服务多副本承诺,也不能将 Mail 客户端实现视为邮件服务整体已验收。
|
|
17
|
+
|
|
18
|
+
## 2. EventService 订阅契约
|
|
19
|
+
|
|
20
|
+
### 2.1 模式先展开,再保存具体事件
|
|
21
|
+
|
|
22
|
+
`subscribe`/`unsubscribe` 的事件模式按 `.` 分层,层内 `*` 不跨点;拒绝空层和 `**`,不执行正则。授权申请、grant scope、publish 保持完整事件名。订阅执行顺序为:
|
|
23
|
+
|
|
24
|
+
1. 校验过滤参数,检查当前 AID/device/slot 的有效租约。
|
|
25
|
+
2. 逐模式在当前 Bus 目录展开,无命中返回 `UNKNOWN_EVENT`;与 Sub 授权求交,无可订阅事件返回 `FORBIDDEN`。
|
|
26
|
+
3. 按具体事件替换订阅条件并持久化。
|
|
27
|
+
4. 返回实际具体事件;以后新增目录项不会自动加入既有订阅。
|
|
28
|
+
|
|
29
|
+
取消订阅的模式在当前订阅集合中匹配,不能按模式扩大或恢复租约授权。
|
|
30
|
+
|
|
31
|
+
### 2.2 过滤 wire 与信任来源
|
|
32
|
+
|
|
33
|
+
| wire/Python | TS/JS | Go |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `publisher_aids` | `publisherAids` | `PublisherAIDs` |
|
|
36
|
+
| `publisher_types` | `publisherTypes` | `PublisherTypes` |
|
|
37
|
+
| `publisher_exttypes` | `publisherExttypes` | `PublisherExtTypes` |
|
|
38
|
+
|
|
39
|
+
每字段为非空数组,1–64 项,每模式 UTF-8 最多 256 字节;省略不限。同字段 OR、跨字段 AND,沿用点分层通配。再次订阅同事件时替换过滤,不能把新条件与旧条件暗中合并。
|
|
40
|
+
|
|
41
|
+
发布者 AID 取认证发送者;类型取验签通过的 `agent.md`,不信事件正文自报。仅在订阅要求类型时解析名片,缓存与并发均有界;读取或验签失败时,不匹配要求该类型的条件,不应连带拒绝仅 AID 或不限类型的订阅。
|
|
42
|
+
|
|
43
|
+
### 2.3 持久化与订阅代次
|
|
44
|
+
|
|
45
|
+
Bus 端和客户端保存具体事件及完整过滤,重授权后逐事件恢复。状态应保持 AID、Bus、角色、device、slot 的既有隔离;Python/Node/Go 的 SQLite 与 Browser 的 IndexedDB 只改变存储介质,不改变过滤语义。
|
|
46
|
+
|
|
47
|
+
修改条件、取消订阅或关闭会改变订阅代次。接收排队与开始回调前复核代次,旧代次事件不能继续按旧条件进入回调;不能据此保证回滚已执行的业务。
|
|
48
|
+
|
|
49
|
+
### 2.4 同 Client 本地通道
|
|
50
|
+
|
|
51
|
+
只有同一个 Client、Bus AID 为本端且 device/slot 匹配时允许本地收发;跨 Client/设备/slot 保持网络路径。投递复制消息后进入原接收处理,不能直接调用业务回调跳过授权与调度。
|
|
52
|
+
|
|
53
|
+
本地路径保留角色授权、注册租约、TTL、去重、容量和关闭代际。容量满时等待容量或原期限,不建立无限队列;本地投递不重复扣网络接收速率。
|
|
54
|
+
|
|
55
|
+
| SDK | 主要落点 |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| Python | [pubsub/client.py](../../python/src/aun_core/pubsub/client.py)、[service.py](../../python/src/aun_core/pubsub/service.py)、[binding.py](../../python/src/aun_core/pubsub/binding.py) |
|
|
58
|
+
| Node TS | [pubsub/types.ts](../../ts/src/pubsub/types.ts)、[client.ts](../../ts/src/pubsub/client.ts)、[service.ts](../../ts/src/pubsub/service.ts)、[channel.ts](../../ts/src/pubsub/channel.ts) |
|
|
59
|
+
| Browser JS | [pubsub/client.ts](../../js/src/pubsub/client.ts)、[service.ts](../../js/src/pubsub/service.ts)、[channel.ts](../../js/src/pubsub/channel.ts) |
|
|
60
|
+
| Go | [pubsub_types.go](../../go/pubsub_types.go)、[pubsub_client.go](../../go/pubsub_client.go)、[pubsub_service.go](../../go/pubsub_service.go)、[pubsub_binding.go](../../go/pubsub_binding.go) |
|
|
61
|
+
|
|
62
|
+
完整事件租约、凭证、fanout 和公平背压继续遵循 [事件开发移植专题](AUN事件发布订阅开发移植指南.md)。
|
|
63
|
+
|
|
64
|
+
## 3. ACK、同步预算与恢复调度
|
|
65
|
+
|
|
66
|
+
### 3.1 累计 ACK 的提交与收尾
|
|
67
|
+
|
|
68
|
+
后台 Pull 在本地提交后异步调度累计 ACK。同 namespace 合并更高确认水位,失败重试;前台 Pull 保持等待 ACK。任务按 AID、device、slot、连接与 namespace 代际隔离,旧任务不能确认新会话的数据。
|
|
69
|
+
|
|
70
|
+
TS/JS 合并任务时同步更新待发送参数。任务成功结束前先移除当前 ACK job,使随后更高水位可创建新任务;最终清理须检查任务身份,不能把同 key 下的新 job 一并删除。
|
|
71
|
+
|
|
72
|
+
关闭仅有限等待后台 ACK。协议确认不表示业务完成,重连重复投递和应用幂等仍遵循既有消息契约。
|
|
73
|
+
|
|
74
|
+
### 3.2 历史同步与连接需求
|
|
75
|
+
|
|
76
|
+
移除 `history_bytes_per_second` 主动字节速率节流,保留并发、`max_page_bytes`、在途内存预留和压力背压;volatile 继续独立游标,不与持久消息历史进度混用。TS/JS 避免重复补拉已被在线交付覆盖的范围,并合并群补拉责任。
|
|
77
|
+
|
|
78
|
+
辅助连接 ready/退役后按实际可用连接重新发布同步需求。`gateway.sync_demand` 属于同步控制通知,不增加业务活动或因此阻止 UDP 空闲待机。
|
|
79
|
+
|
|
80
|
+
自动连接后的补拉、组织身份和待上传名片恢复随机延后 30–60 秒。执行前复核身份和连接代际,关闭后台同步时不调度;显式 Pull 与消息通知仍由各自入口触发,不能将所有入口统一加延时。
|
|
81
|
+
|
|
82
|
+
落点:Python [delivery.py](../../python/src/aun_core/_client/delivery.py)、[sync_channels.py](../../python/src/aun_core/_client/sync_channels.py)、[client.py](../../python/src/aun_core/client.py);TS/JS 各自 `src/client/{delivery,sync-channels,v2-e2ee,lifecycle}.ts`;Go [client_delivery.go](../../go/client_delivery.go)、[sync_channels.go](../../go/sync_channels.go)、[client_lifecycle.go](../../go/client_lifecycle.go)、[org_facades.go](../../go/org_facades.go)。
|
|
83
|
+
|
|
84
|
+
## 4. Echo v3.2 处理契约
|
|
85
|
+
|
|
86
|
+
完整 wire 以 [Echo SDK 规范](../protocol/echo-probe-sdk.md)为准。四端移植应保持以下行为:
|
|
87
|
+
|
|
88
|
+
| 环节 | 契约 |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| 识别 | 首行去前导空白,大小写不敏感,最长前缀顺序为 `echo.ecdiag`、`echo.ask`、`echo` |
|
|
91
|
+
| 传输 | 强制明文;认证错误和密文发送不转换成本地发送失败诊断 |
|
|
92
|
+
| hop | 唯一字段,默认 100;payload 有效安全整数优先于首行 `hop=N`;范围 ±9007199254740991 |
|
|
93
|
+
| 转向 | 去程递减到 0 立即返程,负数是回程并继续减;旧 `max_hop`/`rhop` 不控制状态 |
|
|
94
|
+
| trace | 保留完整正文和重复节点,携带版本、epoch、时区等;回程耗时取本地单调时钟 |
|
|
95
|
+
| 交付 | 本地提前返回和服务端 `echo_return` 复用 `message.received`/`group.message_created`;群提前返回定向原发送者 |
|
|
96
|
+
| 错误 | 本地发送失败/超时带 `reason=send_failed\|timeout`、`delivery_state=not_delivered\|unknown`、`echo_error` |
|
|
97
|
+
|
|
98
|
+
`unknown` 不能缩减为确定未投递。交付队列关闭后不为诊断重新打开,回调失败不能再次生成同一诊断;不能把四 SDK 的实现核对扩写为外部 App/Rust/EvolCore 全链路已通过。
|
|
99
|
+
|
|
100
|
+
## 5. UDP 待机状态机与报文
|
|
101
|
+
|
|
102
|
+
### 5.1 协商、prepare 与恢复
|
|
103
|
+
|
|
104
|
+
能力只用于 Python/Node TS/Go 的主长连接,必须同时严格匹配两个布尔值:`negotiated_capabilities.udp_standby_v1=true` 与 `udp_standby.enabled=true`。缺省关闭或未协商则保持 WS;辅助连接和短连接不声明此能力。
|
|
105
|
+
|
|
106
|
+
状态顺序为 active → preparing → UDP 验证 → commit → standby → waking → active。human 名片、未完成 RPC/ACK/同步/交付、迁移与关闭会阻止或中断入睡;不能使用注册意图替代当前名片类型判断。
|
|
107
|
+
|
|
108
|
+
prepare 返回的 `event_subscriptions` 必须保存为快照;恢复时写回 `auth.connect.options.event_subscriptions`。这是 Gateway 协议通知订阅,区别于 EventService 的 Bus 订阅。默认全事件、queue/stream 及非白名单订阅保持 WS,SDK 不擅自改变应用订阅。
|
|
109
|
+
|
|
110
|
+
业务请求和 UDP 提示可合并触发恢复,但各请求的 deadline/cancel 独立。ticket/lease/对账期限和心跳连续失败也触发恢复;关闭和身份代际切换应终止旧等待,已经发出的写请求不自动重放。
|
|
111
|
+
|
|
112
|
+
### 5.2 认证与心跳格式
|
|
113
|
+
|
|
114
|
+
UDP 报文使用 HMAC-SHA256,`c2s`/`s2c` 方向域分离;使用 64 位序号和 64 位窗口防重放,总包长最多 256 字节。UDP 只传控制信息;WAKE_ACK 不代表业务消费,也不改变消息 TTL。
|
|
115
|
+
|
|
116
|
+
`HEARTBEAT_ACK` 正文固定 **20 字节**,多字节整数使用网络字节序:
|
|
117
|
+
|
|
118
|
+
| 偏移 | 字段 | 类型 |
|
|
119
|
+
| --- | --- | --- |
|
|
120
|
+
| 0 | `lease_remaining_ms` | uint32 |
|
|
121
|
+
| 4 | `pending_generation` | uint64 |
|
|
122
|
+
| 12 | `reason_mask` | uint32 |
|
|
123
|
+
| 16 | `heartbeat_interval_ms` | uint32 |
|
|
124
|
+
|
|
125
|
+
只接受当前 ticket/epoch、通过认证与重放检查、匹配当前未完成心跳且在期限内的 ACK。新周期决定下一轮调度并保留 ±20% 抖动;成功应重置连续失败计数,pending/reason 触发唤醒。默认策略约为 25 秒周期、5 秒等待、连续三次失败回 WS,实际以协商策略及租约/ticket/对账期限为准。
|
|
126
|
+
|
|
127
|
+
| SDK | 当前新周期处理与实现 |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| Python | [_receive](../../python/src/aun_core/_client/udp_standby.py) 在通过认证和请求匹配后更新 policy,心跳循环下一轮读取 |
|
|
130
|
+
| Node TS | [udp-standby.ts](../../ts/src/udp-standby.ts) 读取偏移 16,更新 policy 并重新安排 timer |
|
|
131
|
+
| Go | [udp_standby.go](../../go/udp_standby.go) 更新本轮策略并计算下一次心跳时间 |
|
|
132
|
+
|
|
133
|
+
验证应通过实际收包入口进入循环,不能仅用绕过收包处理的 `_exchange` mock 判断周期更新。Python 现有回归覆盖当前/过期/已完成/已取消 ACK、零周期、下一轮新周期及抖动、成功后重新累计三次超时。
|
|
134
|
+
|
|
135
|
+
编解码落点:Python [udp_standby_codec.py](../../python/src/aun_core/_client/udp_standby_codec.py)、Go [udp_standby_codec.go](../../go/udp_standby_codec.go);设计背景见 [AID 空闲 UDP 待机详细设计](../../../docs/AUN文档/AID空闲UDP待机详细设计.md)。
|
|
136
|
+
|
|
137
|
+
## 6. 原生 MailClient 的三端移植
|
|
138
|
+
|
|
139
|
+
### 6.1 认证、凭据和依赖
|
|
140
|
+
|
|
141
|
+
原生客户端直连独立 SMTP STARTTLS/IMAPS,默认 `mail.{issuer}:587`/`mail.{issuer}:993`,使用 AID 证书、TLS 和 SASL EXTERNAL。连接准备 SMTP 与 IMAP,默认连接超时 10 秒、命令超时 30 秒;不能复用 Gateway JWT 替代证书认证。
|
|
142
|
+
|
|
143
|
+
| SDK | 凭据与信任根 | 实现/依赖 |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| Python | provider 提供 PEM 或证书/私钥文件;`server_trust_bundle` 为 CA 文件路径 | [mail_client.py](../../python/src/aun_core/mail_client.py) |
|
|
146
|
+
| Node TS | provider 返回 `{cert, key}` string/Buffer;信任根是 CA 内容 | [mail-client.ts](../../ts/src/mail-client.ts);Nodemailer/ImapFlow |
|
|
147
|
+
| Go | provider 返回 `tls.Certificate`;信任根为 `[]byte` | [mail_client.go](../../go/mail_client.go);emersion SMTP/IMAP/SASL |
|
|
148
|
+
|
|
149
|
+
每次使用当前 provider 快照,凭据变化后重建连接。Python 的 provider/文件读取失败归为 `identity_unavailable` 并断开旧连接;TLS、认证、协议错误保留原分层。Browser 没有原生 MailClient,旧 RPC 门面继续兼容。
|
|
150
|
+
|
|
151
|
+
### 6.2 MIME、信封和发送结果
|
|
152
|
+
|
|
153
|
+
结构化 MIME/附件与 raw MIME 都要保留独立信封、逐收件人结果和可选 Sent 副本。发送结果为 `accepted`/`partial`/`rejected`/`accepted_unknown`,Sent 状态独立为 `not_requested`/`saved`/`failed`/`unknown`;SMTP 接受不等于最终送达,Sent 失败不能回写成全部收件人拒绝。
|
|
154
|
+
|
|
155
|
+
Python raw MIME 保留原始头和正文字节,仅补缺失 Date/Message-ID;实际投递剥离 Bcc 及折行,Sent 保留完整副本。邮箱名使用 modified UTF-7,LIST 仅去一对协议引号。
|
|
156
|
+
|
|
157
|
+
Node 复制并规范化信封、去重收件人,不修改调用者对象。[ImapFlow 适配脚本](../../ts/scripts/patch-imapflow-external.mjs) 同时覆盖 ESM/CJS 的 SEARCH、COPY、MOVE、EXPUNGE、STORE;协议错误向上传播,合法空查询仍可成功,不能把查询失败吞成空结果。
|
|
158
|
+
|
|
159
|
+
### 6.3 IMAP UID 与 watch 生命周期
|
|
160
|
+
|
|
161
|
+
UID 操作与流式读取应保持邮箱选择、UIDVALIDITY 和 UID 的关联。检查点字段、事件名和终止方式按各语言真实接口适配,不能只做大小写替换:
|
|
162
|
+
|
|
163
|
+
| SDK | watch 接口 | 变化事件/UIDVALIDITY 变化 |
|
|
164
|
+
| --- | --- | --- |
|
|
165
|
+
| Python | `watch(mailbox, uidvalidity, uid=0)` → AsyncIterator | `change`;`resync_required` 后结束迭代 |
|
|
166
|
+
| Node TS | `watch(mailbox, {uidValidity: bigint, uid: number}, signal?)` → AsyncGenerator | `changes`;`resync_required` 后重置 UID 并继续 |
|
|
167
|
+
| Go | `Watch(ctx, mailbox, MailWatchCheckpoint, consume)` | 初始 `sync`,后续 `changed`;`resync_required` 后内部结束 session,外层 Watch 返回 nil |
|
|
168
|
+
|
|
169
|
+
收到 `resync_required` 应让应用重新建立该邮箱索引;不得跨 UIDVALIDITY 复用旧 UID。Python `fetch_stream`、Node `fetchStream`、Go `FetchStream` 的返回类型及关闭方式按源码接口实现。Go 回调错误向调用者返回,应用取消与内部重建信号不能误写为所有错误都无限重连。
|
|
170
|
+
|
|
171
|
+
本版 Mail 整体验收尚未完成。默认 Go 运行镜像 `AUN_INCLUDE_MAIL=0` 未启用 Mail,但 build 阶段仍编译 Mail 代码,依赖裁剪不能只看运行镜像开关。
|
|
172
|
+
|
|
173
|
+
## 7. 语言专属实现落点
|
|
174
|
+
|
|
175
|
+
| SDK | 本版内容 | 参考源码 |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| Python | Windows extended path、pending 身份、名片缓存、group index 原子写入 | [keystore/_utils.py](../../python/src/aun_core/keystore/_utils.py)、[local_identity_store.py](../../python/src/aun_core/keystore/local_identity_store.py)、[agent_md.py](../../python/src/aun_core/agent_md.py)、[group_index.py](../../python/src/aun_core/group_index.py) |
|
|
178
|
+
| Python | HTTP 上传在 finally 关闭会话;闭环容量测试分离接受/投递指标并支持恢复 | [aid_store.py](../../python/src/aun_core/aid_store.py)、[bench_capacity.py](../../python/src/aun_cli/commands/bench_capacity.py)、[benchmark/runner.py](../../python/src/aun_cli/benchmark/runner.py) |
|
|
179
|
+
| Go | 已有 P-256 凭据只读接入、实例状态内存隔离;相同 PEM 空白变化可接受,实际换证书拒绝 | [client_readonly.go](../../go/client_readonly.go) |
|
|
180
|
+
| Go | DNS IP 回退保留原域名及显式端口 Host,HTTP/WS 自定义 CA | [transport.go](../../go/transport.go) |
|
|
181
|
+
| Go | busy timeout 先于 WAL 初始化;Ownership 归属恢复冲突详情 | [aid_db.go](../../go/keystore/aid_db.go)、[ownership_v21.go](../../go/ownership_v21.go) |
|
|
182
|
+
|
|
183
|
+
只读身份的“只读”约束凭据存储,不限制网络 RPC 为只读。Python 闭环工具的阶梯上限、每路 pending、完整投递吞吐/P99、持续复验及 `--resume` 属于工具契约,不是 SDK 已证明的服务端容量。
|
|
184
|
+
|
|
185
|
+
## 8. 定向回归与证据边界
|
|
186
|
+
|
|
187
|
+
| 范围 | 已有测试入口 | 核对重点 |
|
|
188
|
+
| --- | --- | --- |
|
|
189
|
+
| EventService | Python `tests/unit/test_pubsub_*.py`;TS/JS `tests/unit/pubsub-*.test.ts`;Go `pubsub_*_test.go` | 模式/授权求交、过滤替换与持久化、可信名片、本地容量/TTL、订阅代次 |
|
|
190
|
+
| ACK/同步 | Python `test_message_windows.py`/`test_client.py`;TS/JS client/delivery;Go `forward_commit_test.go` | 提交后 ACK、合并及失败重试、任务收尾、身份/连接隔离、背压和延迟恢复 |
|
|
191
|
+
| Echo | [规范](../protocol/echo-probe-sdk.md);TS/JS `tests/integration/echo.test.ts`;Go `integration_echo_test.go` | hop/trace、提前回送、未知投递、回调失败不重复诊断 |
|
|
192
|
+
| UDP | Python [test_udp_standby.py](../../python/tests/unit/test_udp_standby.py)/[codec 测试](../../python/tests/unit/test_udp_standby_codec.py);TS [udp-standby.test.ts](../../ts/tests/unit/udp-standby.test.ts);Go [udp_standby_test.go](../../go/udp_standby_test.go) | 严格协商、忙碌准入、订阅恢复、当前 ACK 新周期与抖动、超时和关闭 |
|
|
193
|
+
| Mail | Python [test_mail_client.py](../../python/tests/unit/test_mail_client.py);TS [mail-client.test.ts](../../ts/tests/unit/mail-client.test.ts);Go [mail_client_test.go](../../go/mail_client_test.go) | MIME/信封、逐收件人、Sent、错误分层、凭据轮换、UIDVALIDITY/watch |
|
|
194
|
+
| 语言专属 | Python `test_bench_capacity*.py` 及存储测试;Go [client_readonly_test.go](../../go/client_readonly_test.go) 与 transport 测试 | 工具指标/断点、Windows 路径、凭据只读、Host/CA、SQLite 初始化 |
|
|
195
|
+
|
|
196
|
+
当前 Python 心跳行为可在 `aun-sdk-core/python/` 定向验证,临时输出应放在当前会话的临时目录:
|
|
197
|
+
|
|
198
|
+
```powershell
|
|
199
|
+
python -X utf8 -m pytest tests/unit/test_udp_standby.py -k heartbeat -q -x -p no:cacheprovider --basetemp "$env:TMPDIR\pytest-udp-heartbeat"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
本次上述命令 **11 项通过**,覆盖真实编解码收包路径下的周期更新。其余条目是现有测试入口,不表示本轮全部执行。此前版本一致性、JS conformance、Go E2EE 定向测试和 TS/JS 类型检查的记录见 [parity](../../python/CHANGES_FOR_PARITY.md#v0535),不能替代新功能全量验证。
|
|
203
|
+
|
|
204
|
+
本次未启动 Kite/Docker,未运行公网、浏览器 live、跨域 E2E 或独立 Mail 整体验收;按单实例发布范围交付文档,不补做多实例实现或 Mail 服务功能。
|