@agentunion/fastaun-browser 0.2.19 → 0.3.0
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 +50 -0
- package/_packed_docs/CHANGELOG.md +50 -0
- package/_packed_docs/agent.md/SCHEMA.md +173 -0
- package/_packed_docs/agent.md/examples/codeagent-claudecode.md +61 -0
- package/_packed_docs/agent.md/examples/human-developer.md +60 -0
- package/_packed_docs/agent.md/examples/openclaw-lobster.md +52 -0
- package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +43 -0
- package/_packed_docs/protocol/00-/346/200/273/350/247/210/344/270/216/345/210/206/345/261/202.md +205 -0
- package/_packed_docs/protocol/00A-/350/256/276/350/256/241/345/216/237/345/210/231-/344/270/272Agent/350/200/214/347/224/237.md +197 -0
- package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +549 -0
- package/_packed_docs/protocol/02-/350/257/201/344/271/246/344/270/216/344/277/241/344/273/273/344/275/223/347/263/273.md +810 -0
- package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +262 -0
- package/_packed_docs/protocol/04-Peer-/345/255/220/345/215/217/350/256/256.md +180 -0
- package/_packed_docs/protocol/05-Relay-/345/255/220/345/215/217/350/256/256.md +164 -0
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1135 -0
- package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +234 -0
- package/_packed_docs/protocol/08-AUN-E2EE-Group.md +900 -0
- package/_packed_docs/protocol/08-AUN-E2EE.md +413 -0
- package/_packed_docs/protocol/09-/345/256/211/345/205/250/350/200/203/350/231/221.md +316 -0
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +804 -0
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +271 -0
- package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +329 -0
- package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +141 -0
- package/_packed_docs/protocol/14-/344/272/244/344/272/222/346/234/272/345/210/266-/345/223/215/345/272/224/346/250/241/345/274/217/344/270/216/350/207/252/344/270/273/346/250/241/345/274/217.md +170 -0
- package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +419 -0
- package/_packed_docs/protocol/README.md +71 -0
- package/_packed_docs/protocol/agent.md/SCHEMA.md +118 -0
- package/_packed_docs/protocol/agent.md/examples/codeagent-claudecode.md +61 -0
- package/_packed_docs/protocol/agent.md/examples/human-developer.md +60 -0
- package/_packed_docs/protocol/agent.md/examples/openclaw-lobster.md +52 -0
- package/_packed_docs/protocol/aun-docs-guide.md +49 -0
- package/_packed_docs/protocol/index.md +124 -0
- package/_packed_docs/protocol//350/215/211/346/241/210-agent.md/347/255/276/345/220/215/345/215/217/350/256/256.md +205 -0
- package/_packed_docs/protocol//350/215/211/346/241/210-/346/213/222/347/273/235/344/277/241/345/217/267/345/215/217/350/256/256.md +249 -0
- package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +337 -0
- package/_packed_docs/protocol//351/231/204/345/275/225B-/346/211/251/345/261/225/346/200/247/346/214/207/345/215/227.md +80 -0
- package/_packed_docs/protocol//351/231/204/345/275/225C-/347/247/201/351/222/245/347/256/241/347/220/206/344/270/216/350/272/253/344/273/275/346/201/242/345/244/215.md +704 -0
- package/_packed_docs/protocol//351/231/204/345/275/225D-Root_CA_/346/262/273/347/220/206/346/234/272/345/210/266.md +620 -0
- package/_packed_docs/protocol//351/231/204/345/275/225E-Root_CA_/345/207/206/345/205/245/346/265/201/347/250/213.md +605 -0
- package/_packed_docs/protocol//351/231/204/345/275/225F-Issuer_CA_/347/224/263/350/257/267/346/265/201/347/250/213.md +548 -0
- package/_packed_docs/protocol//351/231/204/345/275/225G-AID_/345/255/244/345/204/277/351/242/204/351/230/262/344/270/216/346/225/221/346/217/264/346/234/272/345/210/266.md +513 -0
- package/_packed_docs/protocol//351/231/204/345/275/225H-Identity/346/234/215/345/212/241/345/256/236/347/216/260/346/214/207/345/215/227.md +619 -0
- package/_packed_docs/protocol//351/231/204/345/275/225I-/350/267/250/345/237/237/346/266/210/346/201/257/350/267/257/347/224/261/345/256/236/347/216/260/346/214/207/345/215/227.md +492 -0
- package/_packed_docs/protocol//351/231/204/345/275/225J-/345/256/242/346/210/267/347/253/257/346/216/245/345/205/245/347/244/272/344/276/213.md +402 -0
- package/_packed_docs/protocol//351/231/204/345/275/225K-Agent_Web/345/217/221/347/216/260/345/215/217/350/256/256.md +130 -0
- package/_packed_docs/protocol//351/231/204/345/275/225L-E2EE/345/256/236/347/216/260/346/214/207/345/215/227.md +267 -0
- package/_packed_docs/protocol//351/231/204/345/275/225M-JWT/350/256/244/350/257/201/345/256/236/347/216/260/346/214/207/345/215/227.md +367 -0
- package/_packed_docs/python-sdk-v2-only-changelog.md +189 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +223 -0
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +354 -0
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +172 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +396 -0
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +611 -0
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +1203 -0
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +150 -0
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +89 -0
- package/_packed_docs/sdk/09-custody-api-manual.md +445 -0
- package/_packed_docs/sdk/09-group-rpc-manual.md +1895 -0
- package/_packed_docs/sdk/09-message-rpc-manual.md +597 -0
- package/_packed_docs/sdk/09-meta-rpc-manual.md +142 -0
- package/_packed_docs/sdk/09-payload-reference.md +702 -0
- package/_packed_docs/sdk/09-storage-rpc-manual.md +408 -0
- package/_packed_docs/sdk/09-stream-rpc-manual.md +275 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +72 -0
- package/_packed_docs/sdk/INDEX.md +131 -0
- package/_packed_docs/sdk/README.md +307 -0
- package/dist/auth.d.ts +2 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +33 -14
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +14300 -0
- package/dist/client.d.ts +200 -178
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3096 -4019
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +0 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -4
- package/dist/config.js.map +1 -1
- package/dist/crypto.d.ts +8 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +114 -1
- package/dist/crypto.js.map +1 -1
- package/dist/e2ee.d.ts +5 -210
- package/dist/e2ee.d.ts.map +1 -1
- package/dist/e2ee.js +4 -1379
- package/dist/e2ee.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/namespaces/auth.d.ts +1 -0
- package/dist/namespaces/auth.d.ts.map +1 -1
- package/dist/namespaces/auth.js +23 -8
- package/dist/namespaces/auth.js.map +1 -1
- package/dist/protected-headers.d.ts +14 -0
- package/dist/protected-headers.d.ts.map +1 -0
- package/dist/protected-headers.js +47 -0
- package/dist/protected-headers.js.map +1 -0
- package/dist/seq-tracker.d.ts +7 -2
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +31 -10
- package/dist/seq-tracker.js.map +1 -1
- package/dist/transport.d.ts +9 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +24 -0
- package/dist/transport.js.map +1 -1
- package/dist/v2/crypto/aead.d.ts +26 -0
- package/dist/v2/crypto/aead.d.ts.map +1 -0
- package/dist/v2/crypto/aead.js +63 -0
- package/dist/v2/crypto/aead.js.map +1 -0
- package/dist/v2/crypto/canonical.d.ts +21 -0
- package/dist/v2/crypto/canonical.d.ts.map +1 -0
- package/dist/v2/crypto/canonical.js +111 -0
- package/dist/v2/crypto/canonical.js.map +1 -0
- package/dist/v2/crypto/dh-path.d.ts +21 -0
- package/dist/v2/crypto/dh-path.d.ts.map +1 -0
- package/dist/v2/crypto/dh-path.js +50 -0
- package/dist/v2/crypto/dh-path.js.map +1 -0
- package/dist/v2/crypto/ecdh.d.ts +19 -0
- package/dist/v2/crypto/ecdh.d.ts.map +1 -0
- package/dist/v2/crypto/ecdh.js +101 -0
- package/dist/v2/crypto/ecdh.js.map +1 -0
- package/dist/v2/crypto/ecdsa.d.ts +16 -0
- package/dist/v2/crypto/ecdsa.d.ts.map +1 -0
- package/dist/v2/crypto/ecdsa.js +52 -0
- package/dist/v2/crypto/ecdsa.js.map +1 -0
- package/dist/v2/crypto/hkdf.d.ts +21 -0
- package/dist/v2/crypto/hkdf.d.ts.map +1 -0
- package/dist/v2/crypto/hkdf.js +32 -0
- package/dist/v2/crypto/hkdf.js.map +1 -0
- package/dist/v2/crypto/index.d.ts +9 -0
- package/dist/v2/crypto/index.d.ts.map +1 -0
- package/dist/v2/crypto/index.js +8 -0
- package/dist/v2/crypto/index.js.map +1 -0
- package/dist/v2/crypto/recipients.d.ts +43 -0
- package/dist/v2/crypto/recipients.d.ts.map +1 -0
- package/dist/v2/crypto/recipients.js +188 -0
- package/dist/v2/crypto/recipients.js.map +1 -0
- package/dist/v2/e2ee/decrypt.d.ts +13 -0
- package/dist/v2/e2ee/decrypt.d.ts.map +1 -0
- package/dist/v2/e2ee/decrypt.js +176 -0
- package/dist/v2/e2ee/decrypt.js.map +1 -0
- package/dist/v2/e2ee/encrypt-group.d.ts +14 -0
- package/dist/v2/e2ee/encrypt-group.d.ts.map +1 -0
- package/dist/v2/e2ee/encrypt-group.js +196 -0
- package/dist/v2/e2ee/encrypt-group.js.map +1 -0
- package/dist/v2/e2ee/encrypt-p2p.d.ts +15 -0
- package/dist/v2/e2ee/encrypt-p2p.d.ts.map +1 -0
- package/dist/v2/e2ee/encrypt-p2p.js +240 -0
- package/dist/v2/e2ee/encrypt-p2p.js.map +1 -0
- package/dist/v2/e2ee/index.d.ts +9 -0
- package/dist/v2/e2ee/index.d.ts.map +1 -0
- package/dist/v2/e2ee/index.js +9 -0
- package/dist/v2/e2ee/index.js.map +1 -0
- package/dist/v2/e2ee/metadata-auth.d.ts +9 -0
- package/dist/v2/e2ee/metadata-auth.d.ts.map +1 -0
- package/dist/v2/e2ee/metadata-auth.js +60 -0
- package/dist/v2/e2ee/metadata-auth.js.map +1 -0
- package/dist/v2/e2ee/types.d.ts +57 -0
- package/dist/v2/e2ee/types.d.ts.map +1 -0
- package/dist/v2/e2ee/types.js +7 -0
- package/dist/v2/e2ee/types.js.map +1 -0
- package/dist/v2/session/index.d.ts +4 -0
- package/dist/v2/session/index.d.ts.map +1 -0
- package/dist/v2/session/index.js +3 -0
- package/dist/v2/session/index.js.map +1 -0
- package/dist/v2/session/keystore.d.ts +48 -0
- package/dist/v2/session/keystore.d.ts.map +1 -0
- package/dist/v2/session/keystore.js +184 -0
- package/dist/v2/session/keystore.js.map +1 -0
- package/dist/v2/session/session.d.ts +98 -0
- package/dist/v2/session/session.d.ts.map +1 -0
- package/dist/v2/session/session.js +270 -0
- package/dist/v2/session/session.js.map +1 -0
- package/dist/v2/state/commitment.d.ts +10 -0
- package/dist/v2/state/commitment.d.ts.map +1 -0
- package/dist/v2/state/commitment.js +86 -0
- package/dist/v2/state/commitment.js.map +1 -0
- package/dist/v2/state/index.d.ts +2 -0
- package/dist/v2/state/index.d.ts.map +1 -0
- package/dist/v2/state/index.js +2 -0
- package/dist/v2/state/index.js.map +1 -0
- package/package.json +43 -37
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Python SDK V2-Only 改动清单
|
|
2
|
+
|
|
3
|
+
基线:`d8b79f44` (v0.2.20 之后,master_1.0.0 分支)
|
|
4
|
+
日期:2026-05-20
|
|
5
|
+
|
|
6
|
+
## 一、源码改动(`python/src/aun_core/`)
|
|
7
|
+
|
|
8
|
+
### 1. client.py:8588 行 → 4502 行(净删 4086 行)
|
|
9
|
+
|
|
10
|
+
#### 删除的 V1 E2EE 代码(共 ~95 个方法)
|
|
11
|
+
|
|
12
|
+
**V1 P2P 加密:**
|
|
13
|
+
- `_send_encrypted`, `_build_self_sync_copies`, `_build_recipient_device_copies`
|
|
14
|
+
- `_encrypt_copy_payload`, `_ensure_encrypt_result`, `_resolve_self_copy_peer_cert`
|
|
15
|
+
- `_log_e2ee_error`
|
|
16
|
+
|
|
17
|
+
**V1 群组加密:**
|
|
18
|
+
- `_send_group_encrypted`, `_put_group_thought_encrypted`, `_put_message_thought_encrypted`
|
|
19
|
+
- `_call_group_encrypted_rpc`, `_prepare_group_encrypted_rpc_params`
|
|
20
|
+
|
|
21
|
+
**V1 Epoch 管理:**
|
|
22
|
+
- `_recover_group_epoch_key`, `_do_recover_group_epoch_key`, `_try_recover_epoch_key_from_server`
|
|
23
|
+
- `_recover_initial_group_epoch_if_needed`, `_request_group_key_from_candidates`
|
|
24
|
+
- `_request_group_key_from_online`, `_request_group_key_from`
|
|
25
|
+
- `_group_epoch_secret_ready_for_recovery`, `_pending_group_secret_still_current`
|
|
26
|
+
- `_ensure_group_epoch_ready`, `_wait_for_group_membership_epoch_floor`
|
|
27
|
+
- `_committed_group_epoch`, `_committed_group_epoch_state`
|
|
28
|
+
- `_ensure_committed_group_secret_for_send`, `_committed_rotation_membership_gap`
|
|
29
|
+
|
|
30
|
+
**V1 密钥控制面:**
|
|
31
|
+
- `_try_handle_group_key_message`, `_verify_active_group_rotation_distribution`
|
|
32
|
+
- `_verify_group_key_response_epoch`, `_discard_group_distribution_if_stale`
|
|
33
|
+
- `_ack_group_rotation_key`
|
|
34
|
+
|
|
35
|
+
**V1 Epoch 轮换:**
|
|
36
|
+
- `_build_rotation_signature`, `_attach_rotation_id`, `_build_epoch_encrypted_keys`
|
|
37
|
+
- `_distribute_group_epoch_key`, `_heartbeat_group_rotation`, `_abort_group_rotation`
|
|
38
|
+
- `_schedule_group_rotation_retry`, `_sync_epoch_to_server`
|
|
39
|
+
- `_maybe_lead_rotate_group_epoch`, `_ranked_group_rotation_candidates`, `_rotate_group_epoch`
|
|
40
|
+
- `_delayed_rotate_after_join`, `_maybe_backfill_key_to_joined_member`
|
|
41
|
+
- `_distribute_key_to_new_member`, `_start_group_epoch_tasks`
|
|
42
|
+
- `_is_rotation_leader`, `_group_epoch_rotate_loop`, `_group_epoch_cleanup_loop`
|
|
43
|
+
|
|
44
|
+
**V1 解密:**
|
|
45
|
+
- `_decrypt_messages`, `_decrypt_single_message`
|
|
46
|
+
- `_decrypt_group_message`, `_decrypt_group_messages`
|
|
47
|
+
- `_decrypt_group_thoughts`, `_decrypt_message_thoughts`
|
|
48
|
+
|
|
49
|
+
**V1 Pending queue:**
|
|
50
|
+
- `_enqueue_pending_decrypt`, `_schedule_retry_pending_decrypt_msgs`
|
|
51
|
+
- `_retry_pending_decrypt_msgs`, `_schedule_recovery_timeout`, `_cleanup_group_state`
|
|
52
|
+
|
|
53
|
+
**V1 Prekey:**
|
|
54
|
+
- `_upload_prekey`, `_prekey_refresh_loop`, `_start_prekey_refresh_task`
|
|
55
|
+
- `_schedule_prekey_replenish_if_consumed`, `_invalidate_peer_prekey_cache`
|
|
56
|
+
- `_fetch_peer_prekeys`, `_fetch_peer_prekey`, `_normalize_peer_prekeys`
|
|
57
|
+
- `_refresh_peer_prekeys`, `_clear_peer_cert_cache`
|
|
58
|
+
|
|
59
|
+
**V1 错误辅助:**
|
|
60
|
+
- `_is_group_epoch_too_old_error`, `_is_group_epoch_rotation_pending_error`
|
|
61
|
+
- `_is_group_epoch_changed_during_send_error`, `_is_recoverable_group_epoch_error`
|
|
62
|
+
- `_is_expected_group_rotation_skip_error`
|
|
63
|
+
|
|
64
|
+
**V1 成员轮换辅助:**
|
|
65
|
+
- `_membership_rotation_trigger_id`, `_membership_rotation_changed`
|
|
66
|
+
- `_membership_rotation_expected_epoch`, `_extract_group_id_from_result`
|
|
67
|
+
- `_get_group_member_aids`, `_local_group_members_match`, `_extract_group_join_mode`
|
|
68
|
+
- `_group_allows_member_epoch_rotation`, `_group_key_recovery_candidates`
|
|
69
|
+
- `_joined_member_aids_from_payload`
|
|
70
|
+
|
|
71
|
+
**V1 群组推送处理:**
|
|
72
|
+
- `_process_and_publish_group_message`, `_auto_pull_group_messages`, `_fill_group_gap`
|
|
73
|
+
|
|
74
|
+
**V1 公开 API:**
|
|
75
|
+
- `e2ee` property, `group_e2ee` property
|
|
76
|
+
- `send_v2`, `pull_v2`, `ack_v2`, `send_group_v2`, `pull_group_v2`, `ack_group_v2`
|
|
77
|
+
(独立方法合并进 `call()` 路由)
|
|
78
|
+
|
|
79
|
+
#### 删除的 V1 实例变量
|
|
80
|
+
|
|
81
|
+
- `self._e2ee` (E2EEManager)
|
|
82
|
+
- `self._group_e2ee` (GroupE2EEManager)
|
|
83
|
+
- `self._pending_decrypt_msgs`
|
|
84
|
+
- `self._recovery_timeout_scheduled`
|
|
85
|
+
- `self._group_epoch_rotation_inflight`
|
|
86
|
+
- `self._group_epoch_rotation_retry_tasks`
|
|
87
|
+
- `self._group_epoch_recovery_inflight`
|
|
88
|
+
- `self._group_membership_rotation_done`
|
|
89
|
+
- `self._group_member_key_backfill_done`
|
|
90
|
+
|
|
91
|
+
#### 新增/修改的逻辑
|
|
92
|
+
|
|
93
|
+
- `_on_raw_group_message_created`:简化为明文消息透传 + seq 跟踪(不再做 V1 解密)
|
|
94
|
+
- `_process_and_publish_message`:移除 V1 解密调用,明文直接透传
|
|
95
|
+
- `_on_raw_group_changed`:移除 V1 epoch 轮换编排,保留 V2 `_v2_auto_propose_state` + event gap 检测
|
|
96
|
+
- `call()` 中 `message.pull` / `group.pull` 后处理:移除 V1 解密,保留 seq 跟踪 + auto-ack
|
|
97
|
+
- `_stop_background_tasks`:移除 V1 epoch 任务清理
|
|
98
|
+
- `_start_background_tasks`:移除 `_start_group_epoch_tasks()` 调用
|
|
99
|
+
- V2 解密元数据:`e2ee` 字段增加 `encryption_mode` 和 `forward_secrecy`
|
|
100
|
+
- V2 group pull:移除返回值去重(pull 始终返回所有解密成功的消息)
|
|
101
|
+
|
|
102
|
+
### 2. seq_tracker.py:+14 行
|
|
103
|
+
|
|
104
|
+
- `on_pull_result` 新增 `after_seq` 参数
|
|
105
|
+
- gap fill 场景(`after_seq == contiguous_seq`):直接把 pull 到的最大 seq 作为新 `contiguous_seq`,跳过服务端永久空洞
|
|
106
|
+
|
|
107
|
+
### 3. `__init__.py`:无变化(`ProtectedHeaders` 保留)
|
|
108
|
+
|
|
109
|
+
### 4. `e2ee.py`:不动(3544 行保留作为参考)
|
|
110
|
+
|
|
111
|
+
### 5. 保留的 e2ee.py 引用(非 E2EE 加解密)
|
|
112
|
+
|
|
113
|
+
- `from .e2ee import ProtectedHeaders` — 纯数据类,V2 也用
|
|
114
|
+
- `from .e2ee import compute_state_hash` (2处) — 群组 state hash 验证工具函数
|
|
115
|
+
|
|
116
|
+
## 二、测试改动(`python/tests/`)
|
|
117
|
+
|
|
118
|
+
### 删除的测试文件(纯 V1 E2EE)
|
|
119
|
+
|
|
120
|
+
- `e2e_test_epoch_key_server.py` — V1 epoch key 服务端托管
|
|
121
|
+
- `integration_test_e2ee.py` — V1 P2P E2EE 集成
|
|
122
|
+
- `integration_test_multi_device_e2ee.py` — V1 多设备 E2EE
|
|
123
|
+
- `unit/test_client_group_e2ee.py` — V1 群组 E2EE 单元测试(93 个用例)
|
|
124
|
+
|
|
125
|
+
### 删除的测试用例(从现有文件中移除)
|
|
126
|
+
|
|
127
|
+
- `test_client.py`:24 个 V1 测试(prekey、send_encrypted V1、decrypt_group 等)
|
|
128
|
+
- `test_py_issues.py`:`TestPY004PrekeyRefreshLoop`
|
|
129
|
+
- `test_py_issues_batch2.py`:`TestPY001DecryptFailStillAutoAck`、`TestPY002KeyRecoveryRetry`、`TestPY003DissolveCleanup`、`TestPY005RotateLoopLeaderElection`
|
|
130
|
+
- `test_py_issues_batch3.py`:`TestPY002PushedSeqsLimit`、`TestPY005EpochWait`
|
|
131
|
+
|
|
132
|
+
### 修改的测试
|
|
133
|
+
|
|
134
|
+
- `test_client.py`:`test_e2ee_property` 改为断言 `e2ee` 属性不存在
|
|
135
|
+
- `integration_test_storage.py`:自定义 redirect handler 支持 PUT 302 重定向
|
|
136
|
+
|
|
137
|
+
## 三、服务端改动(`extensions/services/`)
|
|
138
|
+
|
|
139
|
+
| 文件 | 改动 |
|
|
140
|
+
|------|------|
|
|
141
|
+
| `gateway/entry.py` | kernel event 订阅补全 V2 事件(fallback);`_handle_event_notification` 路由补全 V2 事件 |
|
|
142
|
+
| `gateway/ws_server.py` | `_dispatch_event_from_service` 白名单补全 `group.state_committed` |
|
|
143
|
+
| `gateway/relay.py` | `_should_forward_event` 补全 `group.state_committed`;`_V2_ONLY_GROUP_METHODS` 补全 `propose_state/confirm_state/get_proposal` |
|
|
144
|
+
| `message/entry.py` | `AUN_DIRECT_EVENT_MESSAGE` 默认改为 True;V2 send 返回 status 对齐 V1 语义(`delivered`/`sent`) |
|
|
145
|
+
| `group/entry.py` | `AUN_DIRECT_EVENT_GROUP` 默认改为 True;`_targets_for_group_event` / `is_client_event` 补全 `group.state_committed`;`_rpc_v2_pull` / `_rpc_v2_ack` 补全成员权限检查 |
|
|
146
|
+
|
|
147
|
+
## 四、Bug 修复(需要其它 SDK 对齐)
|
|
148
|
+
|
|
149
|
+
### BUG-1: gap fill 时 contiguous_seq 卡死
|
|
150
|
+
|
|
151
|
+
**根因:** `on_pull_result` 从 `contiguous_seq` 开始 pull,如果服务端返回的消息跳过了某些 seq(永久空洞:竞态跳跃/未持久化/过期清理),`_try_advance` 逐个检查时会卡在第一个缺失的 seq 上,永远无法推进。新消息被阻塞在 SDK 内部有序队列中,上层收不到。
|
|
152
|
+
|
|
153
|
+
**修复:** `on_pull_result` 新增 `after_seq` 参数。当 `after_seq == contiguous_seq`(gap fill 场景)时,直接把 pull 到的最大 seq 作为新的 `contiguous_seq`。
|
|
154
|
+
|
|
155
|
+
**影响范围:** P2P pull、group pull、event pull 三条路径。
|
|
156
|
+
|
|
157
|
+
### BUG-2: V2 group pull 返回值去重导致手动 pull 拿不到已 push 的消息
|
|
158
|
+
|
|
159
|
+
**根因:** `_pull_group_v2_internal` 中 `_is_published_seq` 去重导致已通过 push 自动 pull 消费的消息在手动 pull 时被跳过,返回空列表。
|
|
160
|
+
|
|
161
|
+
**修复:** pull 返回值不再做 `_is_published_seq` 去重。`_publish_ordered_message` 内部仍做事件投递去重(防止重复触发应用层回调),但 pull 的返回值始终包含所有解密成功的消息。
|
|
162
|
+
|
|
163
|
+
### BUG-3: V2 message.send 返回 status 不对齐 V1 语义
|
|
164
|
+
|
|
165
|
+
**根因:** V2 send 返回 `"status": "accepted"`,但 SDK 和应用层已按 V1 语义(`sent`/`delivered`)实现。
|
|
166
|
+
|
|
167
|
+
**修复:** 服务端 `delivered_count > 0` 时返回 `delivered`,否则返回 `sent`。
|
|
168
|
+
|
|
169
|
+
### BUG-4: V2 解密元数据缺少 encryption_mode
|
|
170
|
+
|
|
171
|
+
**根因:** V2 解密后 `e2ee` 字段只有 `version` + `suite`,缺少 `encryption_mode` 和 `forward_secrecy`,导致依赖这些字段的测试/应用层判断失败。
|
|
172
|
+
|
|
173
|
+
**修复:** 补全 `encryption_mode: "v2_{suite}"` 和 `forward_secrecy: True`。
|
|
174
|
+
|
|
175
|
+
## 五、验证结果
|
|
176
|
+
|
|
177
|
+
| 测试 | 结果 |
|
|
178
|
+
|------|------|
|
|
179
|
+
| 单元测试 | 501 passed |
|
|
180
|
+
| V2 P2P E2EE | 12/12 |
|
|
181
|
+
| V2 Group E2EE | 8/8 |
|
|
182
|
+
| V2 Multi-device | 6/6 |
|
|
183
|
+
| Echo | 5/5 |
|
|
184
|
+
| Message Ack | 4/4 |
|
|
185
|
+
| Storage | 4/4 |
|
|
186
|
+
| 双域明文 | PASS |
|
|
187
|
+
| 双域加密 | PASS |
|
|
188
|
+
| 双域离线 | PASS |
|
|
189
|
+
| 双域群组 | 2/2 |
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# AUN SDK Python - 快速开始
|
|
2
|
+
|
|
3
|
+
**版本**: 0.2.8 | **Python**: >= 3.11
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install fastaun
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 最小示例
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import asyncio, random
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
from aun_core import AUNClient
|
|
21
|
+
from aun_core.errors import AUNError, ConnectionError, AuthError
|
|
22
|
+
|
|
23
|
+
def ts():
|
|
24
|
+
return datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
|
25
|
+
|
|
26
|
+
# ── 配置(按需修改)──
|
|
27
|
+
DOMAIN = "agentid.pub" # 也支持其它 AP,如 agentcp.io
|
|
28
|
+
ALICE = f"alice{random.randint(1000,9999)}.{DOMAIN}"
|
|
29
|
+
BOB = f"bob{random.randint(1000,9999)}.{DOMAIN}"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def create_client(aid: str) -> tuple[AUNClient, dict]:
|
|
33
|
+
"""创建客户端 → 加载或创建 AID → 认证 → 返回 (client, auth)"""
|
|
34
|
+
client = AUNClient() # 默认 aun_path: ~/.aun
|
|
35
|
+
|
|
36
|
+
# 先检查本地是否已有该 AID 的身份
|
|
37
|
+
known = any(item["aid"] == aid for item in client.list_identities())
|
|
38
|
+
if not known:
|
|
39
|
+
# 不存在则创建
|
|
40
|
+
try:
|
|
41
|
+
await client.auth.create_aid({"aid": aid})
|
|
42
|
+
except AuthError as e:
|
|
43
|
+
print(f"[错误] 创建 AID 失败 ({aid}): {e}")
|
|
44
|
+
raise
|
|
45
|
+
except ConnectionError as e:
|
|
46
|
+
print(f"[错误] 网络连接失败: {e}")
|
|
47
|
+
raise
|
|
48
|
+
except Exception as e:
|
|
49
|
+
print(f"[错误] 未知错误: {e}")
|
|
50
|
+
raise
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
auth = await client.auth.authenticate({"aid": aid})
|
|
54
|
+
return client, auth
|
|
55
|
+
except AuthError as e:
|
|
56
|
+
print(f"[错误] 认证失败 ({aid}): {e}")
|
|
57
|
+
raise
|
|
58
|
+
except ConnectionError as e:
|
|
59
|
+
print(f"[错误] 网络连接失败: {e}")
|
|
60
|
+
raise
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def main():
|
|
64
|
+
alice = None
|
|
65
|
+
bob = None
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
# 1. 创建两个客户端
|
|
69
|
+
alice, alice_auth = await create_client(ALICE)
|
|
70
|
+
bob, bob_auth = await create_client(BOB)
|
|
71
|
+
|
|
72
|
+
# 2. Bob 订阅消息事件
|
|
73
|
+
received = asyncio.Event()
|
|
74
|
+
def on_bob_message(event):
|
|
75
|
+
print(f"[{ts()}] [Bob 收到] {event['payload']}")
|
|
76
|
+
received.set()
|
|
77
|
+
|
|
78
|
+
bob.on("message.received", on_bob_message)
|
|
79
|
+
|
|
80
|
+
# 3. 双方连接到网关
|
|
81
|
+
try:
|
|
82
|
+
await alice.connect(alice_auth, {})
|
|
83
|
+
await bob.connect(bob_auth, {})
|
|
84
|
+
print(f"[{ts()}] Alice ({ALICE}) 已连接")
|
|
85
|
+
print(f"[{ts()}] Bob ({BOB}) 已连接")
|
|
86
|
+
except ConnectionError as e:
|
|
87
|
+
print(f"[错误] 连接网关失败: {e}")
|
|
88
|
+
raise
|
|
89
|
+
|
|
90
|
+
# 4. Alice 发消息给 Bob
|
|
91
|
+
try:
|
|
92
|
+
result = await alice.call("message.send", {
|
|
93
|
+
"to": BOB,
|
|
94
|
+
"payload": {"type": "text", "text": "Hello from Alice!"},
|
|
95
|
+
})
|
|
96
|
+
print(f"[{ts()}] [Alice 发送] {result}")
|
|
97
|
+
except AUNError as e:
|
|
98
|
+
print(f"[错误] 发送消息失败: {e}")
|
|
99
|
+
raise
|
|
100
|
+
|
|
101
|
+
# 5. 等待 Bob 收到消息(最多 5 秒)
|
|
102
|
+
try:
|
|
103
|
+
await asyncio.wait_for(received.wait(), timeout=5.0)
|
|
104
|
+
except asyncio.TimeoutError:
|
|
105
|
+
# 事件推送未触发,尝试主动拉取
|
|
106
|
+
try:
|
|
107
|
+
pull = await bob.call("message.pull", {"after_seq": 0, "limit": 10})
|
|
108
|
+
msgs = pull.get("messages", [])
|
|
109
|
+
if msgs:
|
|
110
|
+
print(f"[{ts()}] [Bob 拉取] 收到 {len(msgs)} 条消息:")
|
|
111
|
+
for m in msgs:
|
|
112
|
+
print(f" {m.get('payload')}")
|
|
113
|
+
else:
|
|
114
|
+
print(f"[{ts()}] [Bob] 未收到消息")
|
|
115
|
+
except AUNError as e:
|
|
116
|
+
print(f"[错误] 拉取消息失败: {e}")
|
|
117
|
+
|
|
118
|
+
print(f"[{ts()}] 完成")
|
|
119
|
+
|
|
120
|
+
except KeyboardInterrupt:
|
|
121
|
+
print(f"\n[{ts()}] 用户中断")
|
|
122
|
+
except Exception as e:
|
|
123
|
+
print(f"[{ts()}] 程序异常: {e}")
|
|
124
|
+
raise
|
|
125
|
+
finally:
|
|
126
|
+
# 6. 关闭连接
|
|
127
|
+
if alice:
|
|
128
|
+
try:
|
|
129
|
+
await alice.close()
|
|
130
|
+
except Exception:
|
|
131
|
+
pass
|
|
132
|
+
if bob:
|
|
133
|
+
try:
|
|
134
|
+
await bob.close()
|
|
135
|
+
except Exception:
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
asyncio.run(main())
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 配置
|
|
145
|
+
|
|
146
|
+
### 构造参数
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
client = AUNClient({
|
|
150
|
+
"aun_path": "~/.aun/myapp", # 应用级数据目录(AID 数据在其下的 AIDs/{aid}/ 中)
|
|
151
|
+
"root_ca_path": "/path/to/ca.pem", # 额外 Root CA(可选)
|
|
152
|
+
"seed_password": "seed", # 本地存储保护口令(可选)
|
|
153
|
+
})
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`verify_ssl` 不在构造参数中配置。Python / TS / Go SDK 会根据环境变量自动决定:
|
|
157
|
+
|
|
158
|
+
- `AUN_ENV` 优先,其次 `KITE_ENV`
|
|
159
|
+
- 值为 `development` / `dev` / `local` 时关闭证书校验
|
|
160
|
+
- 其他值或未配置时开启证书校验
|
|
161
|
+
|
|
162
|
+
> **默认行为**:SDK 默认启用 P2P E2EE;Group E2EE 为必选能力并固定启用。`message.send` 和 `group.send` 默认加密发送,`group.thought.put` 强制加密发送;如需发送明文普通消息,显式传入 `encrypt=False`。`slot_id` 和 `delivery_mode` 只在 `connect(...)` 阶段传入。
|
|
163
|
+
|
|
164
|
+
完整参数列表见 [API 手册](06-API手册.md)。
|
|
165
|
+
|
|
166
|
+
### 数据目录布局
|
|
167
|
+
|
|
168
|
+
SDK 使用 `{aun_path}/AIDs/{aid}/` 存储每个 AID 的专属数据:
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
{aun_path}/ # 应用级数据根目录
|
|
172
|
+
├── .device_id # 设备级稳定标识(默认写在 ~/.aun/.device_id)
|
|
173
|
+
└── AIDs/ # AID 数据根
|
|
174
|
+
├── alice.agentid.pub/ # Alice 的全部数据
|
|
175
|
+
│ ├── private/key.json # ECDSA 私钥(加密保护)
|
|
176
|
+
│ ├── public/cert.pem # X.509 证书
|
|
177
|
+
│ └── tokens/meta.json # 令牌 + E2EE 密钥 + 元数据
|
|
178
|
+
└── bob.agentid.pub/ # Bob 的全部数据(多 AID 共存)
|
|
179
|
+
├── private/key.json
|
|
180
|
+
├── public/cert.pem
|
|
181
|
+
└── tokens/meta.json
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**路径模型要点**:
|
|
185
|
+
|
|
186
|
+
- **`aun_path`** 是应用级目录,不是 AID 级目录。一个 `aun_path` 下可管理多个 AID
|
|
187
|
+
- **`aun_path` 不要用 AID 命名**(如 `~/.aun/{aid}`),否则会产生 `~/.aun/{aid}/AIDs/{aid}/` 的冗余嵌套
|
|
188
|
+
- 默认路径为 `~/.aun`
|
|
189
|
+
- 推荐用应用名或用途命名:`~/.aun/myapp`、`~/.aun/testing`
|
|
190
|
+
|
|
191
|
+
### connect 阶段的多实例参数
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
await client.connect(auth, {
|
|
195
|
+
"slot_id": "slot-a",
|
|
196
|
+
"delivery_mode": {
|
|
197
|
+
"mode": "queue",
|
|
198
|
+
"routing": "sender_affinity",
|
|
199
|
+
"affinity_ttl_ms": 300000,
|
|
200
|
+
},
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
- `slot_id` 由应用层传入;空字符串表示该设备只运行一个实例
|
|
205
|
+
- `delivery_mode` 只在 `connect(...)` 传入;同一 AID 的所有在线实例必须保持一致
|
|
206
|
+
|
|
207
|
+
**敏感数据保护**:`private/key.json` 和 `tokens/meta.json` 中的私钥、令牌、群密钥等敏感字段不以明文存储,而是通过平台密钥链(Windows DPAPI / macOS Keychain / Linux libsecret)加密保护。
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 核心流程
|
|
212
|
+
|
|
213
|
+
完整的使用流程见上方"最小示例",核心步骤:
|
|
214
|
+
|
|
215
|
+
1. **创建客户端** - `AUNClient(config)`
|
|
216
|
+
2. **加载或创建 AID** - `load_identity_or_none()` → `create_aid()`
|
|
217
|
+
3. **认证** - `authenticate()` 获取令牌
|
|
218
|
+
4. **订阅事件** - `on("message.received", handler)`
|
|
219
|
+
5. **连接** - `connect(auth, options)`
|
|
220
|
+
6. **业务操作** - `call("message.send", params)`
|
|
221
|
+
7. **关闭** - `close()`
|
|
222
|
+
|
|
223
|
+
详细 API 说明见 [06-API手册.md](06-API手册.md),RPC 方法参数见各领域的 RPC 手册。
|