@agentunion/fastaun-browser 0.3.6 → 0.4.1

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/345/256/236/346/226/275/350/256/241/345/210/222.md +596 -0
  3. package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/350/256/276/350/256/241/346/226/271/346/241/210_v3.md +1697 -0
  4. package/_packed_docs/CHANGELOG.md +24 -0
  5. package/_packed_docs/INDEX.md +17 -11
  6. package/_packed_docs/KITE_DOCS_GUIDE.md +11 -10
  7. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +134 -158
  8. package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +11 -7
  9. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +98 -119
  10. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +147 -374
  11. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +153 -153
  12. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +168 -1383
  13. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +71 -91
  14. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +76 -63
  15. package/_packed_docs/sdk/09-custody-api-manual.md +7 -6
  16. package/_packed_docs/sdk/09-meta-rpc-manual.md +13 -14
  17. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +37 -49
  18. package/_packed_docs/sdk/INDEX.md +72 -98
  19. package/_packed_docs/sdk/README.md +85 -266
  20. package/dist/aid-store.d.ts +125 -0
  21. package/dist/aid-store.d.ts.map +1 -0
  22. package/dist/aid-store.js +841 -0
  23. package/dist/aid-store.js.map +1 -0
  24. package/dist/aid.d.ts +56 -0
  25. package/dist/aid.d.ts.map +1 -0
  26. package/dist/aid.js +112 -0
  27. package/dist/aid.js.map +1 -0
  28. package/dist/auth.js +1 -1
  29. package/dist/auth.js.map +1 -1
  30. package/dist/bundle.js +1630 -1901
  31. package/dist/cert-utils.d.ts +26 -0
  32. package/dist/cert-utils.d.ts.map +1 -0
  33. package/dist/cert-utils.js +221 -0
  34. package/dist/cert-utils.js.map +1 -0
  35. package/dist/client.d.ts +89 -60
  36. package/dist/client.d.ts.map +1 -1
  37. package/dist/client.js +568 -160
  38. package/dist/client.js.map +1 -1
  39. package/dist/config.d.ts +0 -2
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +0 -2
  42. package/dist/config.js.map +1 -1
  43. package/dist/error-codes.d.ts +25 -0
  44. package/dist/error-codes.d.ts.map +1 -0
  45. package/dist/error-codes.js +31 -0
  46. package/dist/error-codes.js.map +1 -0
  47. package/dist/errors.d.ts +4 -0
  48. package/dist/errors.d.ts.map +1 -1
  49. package/dist/errors.js +4 -0
  50. package/dist/errors.js.map +1 -1
  51. package/dist/index.d.ts +6 -6
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +5 -5
  54. package/dist/index.js.map +1 -1
  55. package/dist/keystore/index.d.ts +1 -1
  56. package/dist/keystore/index.d.ts.map +1 -1
  57. package/dist/result.d.ts +19 -0
  58. package/dist/result.d.ts.map +1 -0
  59. package/dist/result.js +10 -0
  60. package/dist/result.js.map +1 -0
  61. package/dist/transport.d.ts +3 -0
  62. package/dist/transport.d.ts.map +1 -1
  63. package/dist/transport.js +16 -1
  64. package/dist/transport.js.map +1 -1
  65. package/dist/types.d.ts +13 -2
  66. package/dist/types.d.ts.map +1 -1
  67. package/dist/types.js +22 -0
  68. package/dist/types.js.map +1 -1
  69. package/dist/v2/e2ee/encrypt-p2p.js +1 -1
  70. package/dist/v2/e2ee/encrypt-p2p.js.map +1 -1
  71. package/dist/version.d.ts +2 -0
  72. package/dist/version.d.ts.map +1 -0
  73. package/dist/version.js +5 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +2 -1
@@ -48,142 +48,142 @@ SDK 优先使用 prekey_ecdh_v2,并默认要求前向保密:
48
48
 
49
49
  > Python SDK 默认 `require_forward_secrecy=true`,当加密结果不满足前向保密(无论是因为无 prekey 还是 prekey 加密失败降级到 long_term_key)时拒绝发送并抛出错误。需显式配置 `require_forward_secrecy=false` 才允许降级。
50
50
 
51
- 每条消息独立生成临时 ECDH 密钥对,实现一消息一密钥。
52
-
53
- ## ProtectedHeaders 与可验证上下文
54
-
55
- `protected_headers` 是 E2EE 信封里的可选元数据字典,语义接近 HTTP headers:适合放 `device_id`、`slot_id`、`device_name`、`os`、`sdk_version`、`app_name` 等需要被接收端识别、且需要防篡改的非业务内容。`payload` 仍然类似 HTTP body,业务内容应放在 `payload` 内。
56
-
57
- `protected_headers` 会随 E2EE 信封发送,接收端可以读取,因此它提供完整性保护,不提供机密性保护。不要把访问令牌、私钥、隐私正文或其他只允许端到端可见的内容放入 `protected_headers`;这类内容应放进加密的 `payload`。
58
-
59
- 发送方可以在以下 SDK 调用中传入 `protected_headers`,各 SDK 也兼容别名 `headers`:
60
-
61
- - `message.send`
62
- - `message.thought.put`
63
- - `group.send`
64
- - `group.thought.put`
65
-
66
- `payload_type` 不需要应用层传入。SDK 会读取加密前 `payload.type`,自动写入 `protected_headers.payload_type`,接收端解密后会校验它与明文 `payload.type` 一致。
67
-
68
- 示例:
69
-
70
- ```python
71
- from aun_core import ProtectedHeaders
72
-
73
- headers = (
74
- ProtectedHeaders()
75
- .set("device_id", "dev-123")
76
- .set("slot_id", "desktop")
77
- .set("sdk_version", "0.2.8")
78
- .set("app_name", "my-agent")
79
- )
80
-
81
- await client.call("message.send", {
82
- "to": "bob.agentid.pub",
83
- "payload": {"type": "text", "text": "秘密消息"},
84
- "protected_headers": headers,
85
- })
86
- ```
87
-
88
- 应用层也可以直接传普通字典:
89
-
90
- ```python
91
- await client.call("group.send", {
92
- "group_id": "10001.example.com",
93
- "payload": {"type": "text", "text": "群组消息"},
94
- "protected_headers": {"device_id": "dev-123", "slot_id": "desktop"},
95
- })
96
- ```
97
-
98
- ### 防篡改机制
99
-
100
- 为兼容旧 E2EE 信封,`protected_headers` 和 `context` 不加入原有信封整体 AAD。它们各自带一个 `_auth` 字段,自包含完整性校验信息:
101
-
102
- ```json
103
- {
104
- "type": "e2ee.encrypted",
105
- "ciphertext": "...",
106
- "protected_headers": {
107
- "device_id": "dev-123",
108
- "slot_id": "desktop",
109
- "payload_type": "text",
110
- "_auth": {
111
- "alg": "HMAC-SHA256",
112
- "tag": "base64..."
113
- }
114
- },
115
- "context": {
116
- "type": "run",
117
- "id": "run-xxx",
118
- "_auth": {
119
- "alg": "HMAC-SHA256",
120
- "tag": "base64..."
121
- }
122
- }
123
- }
124
- ```
125
-
126
- 计算规则:
127
-
128
- 1. 解密流程会派生出本条消息的 `message_key`。
129
- 2. `metadata_key = HMAC-SHA256(message_key, "aun-envelope-metadata-key-v1")`。
130
- 3. 对字典去掉 `_auth` 后做 canonical JSON:UTF-8、key 排序、紧凑分隔符。
131
- 4. `tag = HMAC-SHA256(metadata_key, domain + "\0" + canonical_json(body))`。
132
- 5. `domain` 对 `protected_headers` 为 `aun-protected-headers-v1`,对 `context` 为 `aun-protected-context-v1`。
133
-
134
- 只有持有本条消息密钥的发送端和接收端能生成或验证 `_auth.tag`。中间服务可以看到这些元数据,但不能在不破坏校验的情况下修改它们。
135
-
136
- 兼容策略:
137
-
138
- - 老消息没有 `protected_headers` / `context` 时照常解密。
139
- - 新消息一旦携带 `protected_headers` 或 E2EE 信封内的 `context`,就必须携带对应 `_auth`。
140
- - `_auth` 校验失败、`payload_type` 与解密后 `payload.type` 不一致,或信封内 `context` 与外层 thought selector 不一致时,SDK 视为解密失败。
141
-
142
- ### 接收端读取
143
-
144
- SDK 会在验签/验 `_auth` 后,把 `_auth` 去掉,只把业务可见字段回传给应用层:
145
-
146
- ```python
147
- msg = result["messages"][0]
148
- headers = msg.get("e2ee", {}).get("protected_headers", {})
149
- device_id = headers.get("device_id")
150
- payload_type = headers.get("payload_type")
151
- ```
152
-
153
- 对于 thought,顶层 `context.type + context.id` 仍是服务端定位 thought head 的 selector;E2EE 信封内的 `context` 只是对这个 selector 的端到端完整性绑定。
154
-
155
- ## P2P 思考内容
156
-
157
- P2P 思考内容不是普通消息,不广播、不进 `message.pull`、不分配 seq、无需 ack,也不持久化。它只通过 `message.thought.put/get` 读写,并强制使用 P2P E2EE。
158
-
159
- thought selector 只使用顶层 `context.type + context.id`,推荐 `{"type": "run", "id": "run-xxx"}`。如果需要展示被引用消息摘要,应放在加密后的 `payload.quote` 或 `payload.client_context` 中,不作为服务端 selector。
160
-
161
- ```python
162
- await client.call("message.thought.put", {
163
- "to": "bob.agentid.pub",
164
- "context": {"type": "run", "id": "run-xxx"},
165
- "payload": {"type": "thought", "text": "先核对 Bob 的约束,再输出答复"},
166
- })
167
- ```
168
-
169
- 读取对方写给当前用户的 thought 时,指定 `sender_aid` 和同一个 `context`:
170
-
171
- ```python
172
- result = await client.call("message.thought.get", {
173
- "sender_aid": "bob.agentid.pub",
174
- "context": {"type": "run", "id": "run-xxx"},
175
- })
176
- ```
51
+ 每条消息独立生成临时 ECDH 密钥对,实现一消息一密钥。
52
+
53
+ ## ProtectedHeaders 与可验证上下文
54
+
55
+ `protected_headers` 是 E2EE 信封里的可选元数据字典,语义接近 HTTP headers:适合放 `device_id`、`slot_id`、`device_name`、`os`、`sdk_version`、`app_name` 等需要被接收端识别、且需要防篡改的非业务内容。`payload` 仍然类似 HTTP body,业务内容应放在 `payload` 内。
56
+
57
+ `protected_headers` 会随 E2EE 信封发送,接收端可以读取,因此它提供完整性保护,不提供机密性保护。不要把访问令牌、私钥、隐私正文或其他只允许端到端可见的内容放入 `protected_headers`;这类内容应放进加密的 `payload`。
58
+
59
+ 发送方可以在以下 SDK 调用中传入 `protected_headers`,各 SDK 也兼容别名 `headers`:
60
+
61
+ - `message.send`
62
+ - `message.thought.put`
63
+ - `group.send`
64
+ - `group.thought.put`
65
+
66
+ `payload_type` 不需要应用层传入。SDK 会读取加密前 `payload.type`,自动写入 `protected_headers.payload_type`,接收端解密后会校验它与明文 `payload.type` 一致。
67
+
68
+ 示例:
69
+
70
+ ```python
71
+ from aun_core import ProtectedHeaders
72
+
73
+ headers = (
74
+ ProtectedHeaders()
75
+ .set("device_id", "dev-123")
76
+ .set("slot_id", "desktop")
77
+ .set("sdk_version", "0.4.0")
78
+ .set("app_name", "my-agent")
79
+ )
80
+
81
+ await client.call("message.send", {
82
+ "to": "bob.agentid.pub",
83
+ "payload": {"type": "text", "text": "秘密消息"},
84
+ "protected_headers": headers,
85
+ })
86
+ ```
87
+
88
+ 应用层也可以直接传普通字典:
89
+
90
+ ```python
91
+ await client.call("group.send", {
92
+ "group_id": "10001.example.com",
93
+ "payload": {"type": "text", "text": "群组消息"},
94
+ "protected_headers": {"device_id": "dev-123", "slot_id": "desktop"},
95
+ })
96
+ ```
97
+
98
+ ### 防篡改机制
99
+
100
+ 为兼容旧 E2EE 信封,`protected_headers` 和 `context` 不加入原有信封整体 AAD。它们各自带一个 `_auth` 字段,自包含完整性校验信息:
101
+
102
+ ```json
103
+ {
104
+ "type": "e2ee.encrypted",
105
+ "ciphertext": "...",
106
+ "protected_headers": {
107
+ "device_id": "dev-123",
108
+ "slot_id": "desktop",
109
+ "payload_type": "text",
110
+ "_auth": {
111
+ "alg": "HMAC-SHA256",
112
+ "tag": "base64..."
113
+ }
114
+ },
115
+ "context": {
116
+ "type": "run",
117
+ "id": "run-xxx",
118
+ "_auth": {
119
+ "alg": "HMAC-SHA256",
120
+ "tag": "base64..."
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ 计算规则:
127
+
128
+ 1. 解密流程会派生出本条消息的 `message_key`。
129
+ 2. `metadata_key = HMAC-SHA256(message_key, "aun-envelope-metadata-key-v1")`。
130
+ 3. 对字典去掉 `_auth` 后做 canonical JSON:UTF-8、key 排序、紧凑分隔符。
131
+ 4. `tag = HMAC-SHA256(metadata_key, domain + "\0" + canonical_json(body))`。
132
+ 5. `domain` 对 `protected_headers` 为 `aun-protected-headers-v1`,对 `context` 为 `aun-protected-context-v1`。
133
+
134
+ 只有持有本条消息密钥的发送端和接收端能生成或验证 `_auth.tag`。中间服务可以看到这些元数据,但不能在不破坏校验的情况下修改它们。
135
+
136
+ 兼容策略:
137
+
138
+ - 老消息没有 `protected_headers` / `context` 时照常解密。
139
+ - 新消息一旦携带 `protected_headers` 或 E2EE 信封内的 `context`,就必须携带对应 `_auth`。
140
+ - `_auth` 校验失败、`payload_type` 与解密后 `payload.type` 不一致,或信封内 `context` 与外层 thought selector 不一致时,SDK 视为解密失败。
141
+
142
+ ### 接收端读取
143
+
144
+ SDK 会在验签/验 `_auth` 后,把 `_auth` 去掉,只把业务可见字段回传给应用层:
145
+
146
+ ```python
147
+ msg = result["messages"][0]
148
+ headers = msg.get("e2ee", {}).get("protected_headers", {})
149
+ device_id = headers.get("device_id")
150
+ payload_type = headers.get("payload_type")
151
+ ```
152
+
153
+ 对于 thought,顶层 `context.type + context.id` 仍是服务端定位 thought head 的 selector;E2EE 信封内的 `context` 只是对这个 selector 的端到端完整性绑定。
154
+
155
+ ## P2P 思考内容
156
+
157
+ P2P 思考内容不是普通消息,不广播、不进 `message.pull`、不分配 seq、无需 ack,也不持久化。它只通过 `message.thought.put/get` 读写,并强制使用 P2P E2EE。
158
+
159
+ thought selector 只使用顶层 `context.type + context.id`,推荐 `{"type": "run", "id": "run-xxx"}`。如果需要展示被引用消息摘要,应放在加密后的 `payload.quote` 或 `payload.client_context` 中,不作为服务端 selector。
160
+
161
+ ```python
162
+ await client.call("message.thought.put", {
163
+ "to": "bob.agentid.pub",
164
+ "context": {"type": "run", "id": "run-xxx"},
165
+ "payload": {"type": "thought", "text": "先核对 Bob 的约束,再输出答复"},
166
+ })
167
+ ```
168
+
169
+ 读取对方写给当前用户的 thought 时,指定 `sender_aid` 和同一个 `context`:
170
+
171
+ ```python
172
+ result = await client.call("message.thought.get", {
173
+ "sender_aid": "bob.agentid.pub",
174
+ "context": {"type": "run", "id": "run-xxx"},
175
+ })
176
+ ```
177
177
 
178
178
  读取自己写给对方的 thought 时,还需要指定 `peer_aid` 或 `to`:
179
179
 
180
180
  ```python
181
- result = await client.call("message.thought.get", {
182
- "sender_aid": "alice.agentid.pub",
183
- "peer_aid": "bob.agentid.pub",
184
- "context": {"type": "run", "id": "run-xxx"},
185
- })
186
- ```
181
+ result = await client.call("message.thought.get", {
182
+ "sender_aid": "alice.agentid.pub",
183
+ "peer_aid": "bob.agentid.pub",
184
+ "context": {"type": "run", "id": "run-xxx"},
185
+ })
186
+ ```
187
187
 
188
188
  SDK 返回的 `result["thoughts"]` 是已解密数组。`message.thought.get` 是查询操作,重复读取同一条 thought 不按消息 replay 消费处理。
189
189
 
@@ -200,7 +200,7 @@ SDK 的群组 E2EE 编排对使用者透明:
200
200
  群组 E2EE 是必选能力,所有客户端必须支持。当前 Python SDK 固定启用,无需也不能通过配置关闭;成员加入时也固定轮换 epoch,无应用层开关:
201
201
 
202
202
  ```python
203
- client = AUNClient({})
203
+ client = AUNClient(aid)
204
204
  ```
205
205
 
206
206
  **重要**:所有客户端必须声明群组 E2EE 能力。服务端当前仅对在线客户端做能力校验;离线客户端入群时不做强制检查。消息是否加密由发送者自主决定。
@@ -242,27 +242,27 @@ for msg in result["messages"]:
242
242
 
243
243
  ### 群思考内容
244
244
 
245
- 群思考内容不是普通群消息,不广播、不进 `group.pull`、不分配 seq、无需 ack,也不持久化。它只通过 `group.thought.put/get` 读写,并强制使用群组 E2EE。
246
-
247
- 群 thought selector 同样只使用顶层 `context.type + context.id`。
245
+ 群思考内容不是普通群消息,不广播、不进 `group.pull`、不分配 seq、无需 ack,也不持久化。它只通过 `group.thought.put/get` 读写,并强制使用群组 E2EE。
246
+
247
+ 群 thought selector 同样只使用顶层 `context.type + context.id`。
248
248
 
249
249
  ```python
250
- await client.call("group.thought.put", {
251
- "group_id": "g-abc123.agentid.pub",
252
- "context": {"type": "run", "id": "run-xxx"},
253
- "payload": {"type": "thought", "text": "正在比较两个候选方案"},
254
- })
255
- ```
250
+ await client.call("group.thought.put", {
251
+ "group_id": "g-abc123.agentid.pub",
252
+ "context": {"type": "run", "id": "run-xxx"},
253
+ "payload": {"type": "thought", "text": "正在比较两个候选方案"},
254
+ })
255
+ ```
256
256
 
257
- 读取时必须指定 thought 作者和同一个 `context`:
257
+ 读取时必须指定 thought 作者和同一个 `context`:
258
258
 
259
259
  ```python
260
- result = await client.call("group.thought.get", {
261
- "group_id": "g-abc123.agentid.pub",
262
- "sender_aid": "alice.agentid.pub",
263
- "context": {"type": "run", "id": "run-xxx"},
264
- })
265
- ```
260
+ result = await client.call("group.thought.get", {
261
+ "group_id": "g-abc123.agentid.pub",
262
+ "sender_aid": "alice.agentid.pub",
263
+ "context": {"type": "run", "id": "run-xxx"},
264
+ })
265
+ ```
266
266
 
267
267
  SDK 返回的 `result["thoughts"]` 是已解密数组。`group.thought.get` 是查询操作,重复读取同一条 thought 不按消息 replay 消费处理。
268
268
 
@@ -576,10 +576,10 @@ class MyKeyStore:
576
576
  def load_metadata(self, aid: str) -> dict | None: ...
577
577
  def save_metadata(self, aid: str, metadata: dict) -> None: ...
578
578
 
579
- client = AUNClient({"aun_path": "..."})
579
+ client = AUNClient(aid)
580
580
  ```
581
581
 
582
- `AUNClient` 不接收外部 `keystore` 参数。若需替换 `KeyStore`,应按 SDK 内部接口规范扩展实现,再由对应语言 SDK 的内部装配层接入。
582
+ `AUNClient` 不接收外部 `keystore` 参数,也不再通过配置字典选择本地身份。若需替换 `KeyStore`,应按 SDK 内部接口规范扩展实现,再由对应语言 SDK 的内部装配层接入。
583
583
 
584
584
  ---
585
585
 
@@ -593,10 +593,10 @@ class MySecretStore:
593
593
  def reveal(self, scope: str, name: str, record: dict) -> bytes | None: ...
594
594
  def clear(self, scope: str, name: str) -> None: ...
595
595
 
596
- client = AUNClient({"aun_path": "..."})
596
+ client = AUNClient(aid)
597
597
  ```
598
598
 
599
- `AUNClient` 构造函数只保留 `aun_path`、`root_ca_path`、`seed_password`。`SecretStore` / `KeyStore` / `SQLiteBackup` 属于 SDK 内部基础设施,不作为应用层构造参数暴露。
599
+ `AUNClient` 构造函数只接收可选 AID 对象和会话选项。`SecretStore` / `KeyStore` / `SQLiteBackup` 属于 SDK 内部基础设施,不作为应用层构造参数暴露。
600
600
 
601
601
  ---
602
602