@bolloon/bolloon-agent 0.4.4 → 0.4.5

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 (201) hide show
  1. package/README.md +135 -135
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon-daemon.sh +207 -0
  4. package/bin/bolloon.cjs +0 -0
  5. package/dist/agents/constraint-layer.js +19 -19
  6. package/dist/agents/judgment-protocol.js +14 -14
  7. package/dist/agents/pi-sdk-types.js +12 -12
  8. package/dist/agents/pi-sdk.js +90 -90
  9. package/dist/agents/skill-organizer.js +19 -19
  10. package/dist/agents/workflow-pivot-loop.js +2 -2
  11. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  12. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  13. package/dist/bollharness-integration/context-router.js +292 -292
  14. package/dist/bollharness-integration/gate-state-machine.js +13 -13
  15. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  16. package/dist/bollharness-integration/skill-adapter.js +21 -21
  17. package/dist/bootstrap/chat-archiver.js +14 -14
  18. package/dist/bootstrap/context-os.js +24 -24
  19. package/dist/bootstrap/memory-compressor.js +13 -13
  20. package/dist/cli-entry.js +36 -36
  21. package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +63 -0
  22. package/dist/constraint-runtime/reference_data/commands_snapshot.json +1037 -0
  23. package/dist/constraint-runtime/reference_data/subsystems/assistant.json +8 -0
  24. package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +8 -0
  25. package/dist/constraint-runtime/reference_data/subsystems/bridge.json +32 -0
  26. package/dist/constraint-runtime/reference_data/subsystems/buddy.json +13 -0
  27. package/dist/constraint-runtime/reference_data/subsystems/cli.json +26 -0
  28. package/dist/constraint-runtime/reference_data/subsystems/components.json +32 -0
  29. package/dist/constraint-runtime/reference_data/subsystems/constants.json +28 -0
  30. package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +8 -0
  31. package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +15 -0
  32. package/dist/constraint-runtime/reference_data/subsystems/hooks.json +32 -0
  33. package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +21 -0
  34. package/dist/constraint-runtime/reference_data/subsystems/memdir.json +15 -0
  35. package/dist/constraint-runtime/reference_data/subsystems/migrations.json +18 -0
  36. package/dist/constraint-runtime/reference_data/subsystems/moreright.json +8 -0
  37. package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +11 -0
  38. package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +8 -0
  39. package/dist/constraint-runtime/reference_data/subsystems/plugins.json +9 -0
  40. package/dist/constraint-runtime/reference_data/subsystems/remote.json +11 -0
  41. package/dist/constraint-runtime/reference_data/subsystems/schemas.json +8 -0
  42. package/dist/constraint-runtime/reference_data/subsystems/screens.json +10 -0
  43. package/dist/constraint-runtime/reference_data/subsystems/server.json +10 -0
  44. package/dist/constraint-runtime/reference_data/subsystems/services.json +32 -0
  45. package/dist/constraint-runtime/reference_data/subsystems/skills.json +27 -0
  46. package/dist/constraint-runtime/reference_data/subsystems/state.json +13 -0
  47. package/dist/constraint-runtime/reference_data/subsystems/types.json +18 -0
  48. package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +9 -0
  49. package/dist/constraint-runtime/reference_data/subsystems/utils.json +32 -0
  50. package/dist/constraint-runtime/reference_data/subsystems/vim.json +12 -0
  51. package/dist/constraint-runtime/reference_data/subsystems/voice.json +8 -0
  52. package/dist/constraint-runtime/reference_data/tools_snapshot.json +922 -0
  53. package/dist/context-compaction/auto-compact.js +7 -7
  54. package/dist/electron/config.js.map +1 -0
  55. package/dist/electron/dialogs.js.map +1 -0
  56. package/dist/electron/first-run.js +54 -54
  57. package/dist/electron/first-run.js.map +1 -0
  58. package/dist/electron/ipc.js.map +1 -0
  59. package/dist/electron/logger.js.map +1 -0
  60. package/dist/electron/main.js.map +1 -0
  61. package/dist/electron/menu.js.map +1 -0
  62. package/dist/electron/paths.js.map +1 -0
  63. package/dist/electron/server.js.map +1 -0
  64. package/dist/electron/tray.js.map +1 -0
  65. package/dist/electron/window.js.map +1 -0
  66. package/dist/electron-build/electron/first-run.js +54 -54
  67. package/dist/electron-preload.js.map +1 -1
  68. package/dist/electron.js.map +1 -1
  69. package/dist/index.js +112 -112
  70. package/dist/llm/llm-judgment-client.js +102 -102
  71. package/dist/llm/pi-ai.js +48 -48
  72. package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
  73. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  74. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  75. package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
  76. package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
  77. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  78. package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
  79. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  80. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  81. package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
  82. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  83. package/dist/llm/system-prompt/layers/core/identity.md +48 -48
  84. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  85. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  86. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  87. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  88. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  89. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  90. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  91. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  92. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  93. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  94. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  95. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  96. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  97. package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
  98. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  99. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  100. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  101. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  102. package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
  103. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  104. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  105. package/dist/llm/tool-manifest/bash.js +3 -3
  106. package/dist/llm/tool-manifest/create_file.js +4 -4
  107. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  108. package/dist/llm/tool-manifest/image_search.js +2 -2
  109. package/dist/llm/tool-manifest/index.js +59 -0
  110. package/dist/llm/tool-manifest/mcp.js +2 -2
  111. package/dist/llm/tool-manifest/message_compose.js +3 -3
  112. package/dist/llm/tool-manifest/places.js +2 -2
  113. package/dist/llm/tool-manifest/present_files.js +1 -1
  114. package/dist/llm/tool-manifest/recipe.js +2 -2
  115. package/dist/llm/tool-manifest/str_replace.js +5 -5
  116. package/dist/llm/tool-manifest/view.js +3 -3
  117. package/dist/llm/tool-manifest/weather.js +4 -4
  118. package/dist/llm/tool-manifest/web.js +4 -4
  119. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  120. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  121. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  122. package/dist/pi-ecosystem-judgment/human-value-store.js +1 -1
  123. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  124. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  125. package/dist/pi-ecosystem-mcp/index.js +146 -5
  126. package/dist/security/context-router-tool.js +15 -15
  127. package/dist/utils/auto-update.js.map +1 -0
  128. package/dist/web/api-config.html +779 -779
  129. package/dist/web/client-hearth.js +10 -10
  130. package/dist/web/client.js.map +7 -0
  131. package/dist/web/components/wallet-viem.mjs +118 -118
  132. package/dist/web/edge-auth-client.js +120 -0
  133. package/dist/web/index.html +472 -472
  134. package/dist/web/manifest.json +20 -20
  135. package/dist/web/server.js +34 -67
  136. package/dist/web/style.css +4946 -4946
  137. package/package.json +195 -195
  138. package/scripts/build-cli.js +215 -215
  139. package/scripts/build-web.ts +130 -130
  140. package/scripts/postinstall.js +152 -152
  141. package/bin/bolloon.js +0 -157
  142. package/dist/pi-ecosystem-colony/index.js +0 -365
  143. package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
  144. package/dist/social/ant-colony/PheromoneEngine.js +0 -227
  145. package/dist/social/ant-colony/index.js +0 -6
  146. package/dist/social/ant-colony/types.js +0 -24
  147. package/dist/storage/trajectory.js +0 -101
  148. package/dist/test/ai-judgment-test.js +0 -80
  149. package/dist/test/bollharness-integration.test.js +0 -318
  150. package/dist/test/channel-agent-multi-dialogue.js +0 -205
  151. package/dist/test/channel-heartbeat-agent-test.js +0 -201
  152. package/dist/test/constraint-layer.test.js +0 -164
  153. package/dist/test/diap-identity-test.js +0 -172
  154. package/dist/test/diap-quick-test.js +0 -62
  155. package/dist/test/global-shared-context.test.js +0 -315
  156. package/dist/test/harness-judgment-injection.test.js +0 -246
  157. package/dist/test/harness-workflow-integrator-test.js +0 -228
  158. package/dist/test/human-value-store.test.js +0 -243
  159. package/dist/test/hybrid-integration-test.js +0 -118
  160. package/dist/test/hybrid-messenger-verify.js +0 -55
  161. package/dist/test/iroh-bistream-debug.js +0 -38
  162. package/dist/test/iroh-communication.test.js +0 -66
  163. package/dist/test/iroh-debug-test.js +0 -57
  164. package/dist/test/iroh-diap-test.js +0 -71
  165. package/dist/test/iroh-direct-connect.js +0 -55
  166. package/dist/test/iroh-e2e-fixed.js +0 -89
  167. package/dist/test/iroh-e2e-same-process.js +0 -63
  168. package/dist/test/iroh-e2e.js +0 -66
  169. package/dist/test/iroh-final-e2e.js +0 -72
  170. package/dist/test/iroh-relay-test.js +0 -37
  171. package/dist/test/iroh-simple-test.js +0 -41
  172. package/dist/test/iroh-transport-verify.js +0 -54
  173. package/dist/test/iroh-transport.test.js +0 -37
  174. package/dist/test/iroh-two-nodes.js +0 -70
  175. package/dist/test/iroh-verify.js +0 -44
  176. package/dist/test/judgment-decision.test.js +0 -219
  177. package/dist/test/llm-judgment-integration.test.js +0 -220
  178. package/dist/test/p2p-agent-complex-dialogue.js +0 -385
  179. package/dist/test/p2p-agent-dialogue.js +0 -341
  180. package/dist/test/p2p-agent-full-bidirectional.js +0 -510
  181. package/dist/test/p2p-agent-harness-flow.js +0 -437
  182. package/dist/test/p2p-agent-harness-single.js +0 -143
  183. package/dist/test/p2p-ai-dialogue-test.js +0 -318
  184. package/dist/test/p2p-cid-connect-test.js +0 -195
  185. package/dist/test/p2p-connect-receiver.js +0 -69
  186. package/dist/test/p2p-doc-transfer.js +0 -110
  187. package/dist/test/p2p-identity-page-test.js +0 -77
  188. package/dist/test/p2p-iroh-test.js +0 -171
  189. package/dist/test/p2p-minimal-test.js +0 -241
  190. package/dist/test/p2p-node-1.js +0 -148
  191. package/dist/test/p2p-node-2.js +0 -148
  192. package/dist/test/p2p-server.js +0 -281
  193. package/dist/test/p2p-two-nodes-test.js +0 -438
  194. package/dist/test/pi-sdk.test.js +0 -44
  195. package/dist/test/set-persona.js +0 -40
  196. package/dist/test/simple.test.js +0 -9
  197. package/dist/test/storage-integration.test.js +0 -150
  198. package/dist/test/subagent-manager.test.js +0 -276
  199. package/dist/test/test-gate-flow.test.js +0 -81
  200. package/dist/test/workflow-engine.test.js +0 -87
  201. package/dist/test/workflow-pivot-loop.test.js +0 -246
@@ -1,118 +1,118 @@
1
- // Real-wallet helpers (viem-backed), exposed as window.WalletViem for client.js.
2
- // 浏览器侧执行, 不上链, 但地址/助记词/签名都符合 EVM 标准
3
- // (BIP-39 mnemonic + secp256k1 keypair + EIP-55 checksum address + EIP-191 personal_sign).
4
-
5
- import {
6
- generateMnemonic,
7
- mnemonicToAccount,
8
- privateKeyToAccount,
9
- english,
10
- } from 'https://esm.sh/viem@2.52.0/accounts';
11
-
12
- /**
13
- * 生成一个全新的 EVM 钱包: 12 词助记词 + 派生账户 (BIP-44, m/44'/60'/0'/0/0)
14
- * 返回: { mnemonic, address, privateKey }
15
- * - mnemonic: 12 词英文助记词
16
- * - address: EIP-55 checksum 后的 0x 开头地址
17
- * - privateKey: 0x 开头的 32 字节私钥
18
- */
19
- export function generateEVMWallet() {
20
- const mnemonic = generateMnemonic(english, 128); // 128 bits = 12 words
21
- const account = mnemonicToAccount(mnemonic, { accountIndex: 0 });
22
- return {
23
- mnemonic,
24
- address: account.address,
25
- // viem 不直接暴露 privateKey, 用 hdKeyToAccount 路径取
26
- // 这里走一个变通: 拿地址后, 再用 createAccount 走不通...
27
- // 实际: account.source 包含 HDKey, 我们让它返回 privateKey 字段
28
- // 简化: 直接调一个 helper
29
- };
30
- }
31
-
32
- /**
33
- * 通过私钥恢复账户: 用于"导入已有钱包"流程
34
- */
35
- export function importEVMWallet(privateKeyHex) {
36
- const normalized = privateKeyHex.startsWith('0x') ? privateKeyHex : `0x${privateKeyHex}`;
37
- const account = privateKeyToAccount(normalized);
38
- return {
39
- address: account.address,
40
- privateKey: normalized,
41
- };
42
- }
43
-
44
- /**
45
- * 通过助记词恢复账户
46
- */
47
- export function importEVMMnemonic(mnemonic) {
48
- const account = mnemonicToAccount(mnemonic.trim(), { accountIndex: 0 });
49
- return {
50
- mnemonic: mnemonic.trim(),
51
- address: account.address,
52
- privateKey: extractPrivateKey(account),
53
- };
54
- }
55
-
56
- /**
57
- * 真实生成路径: 先生成助记词, 再恢复出账户, 顺带取出 privateKey
58
- */
59
- export function generateRealWallet() {
60
- const mnemonic = generateMnemonic(english, 128);
61
- const account = mnemonicToAccount(mnemonic, { accountIndex: 0 });
62
- return {
63
- mnemonic,
64
- address: account.address,
65
- privateKey: extractPrivateKey(account),
66
- };
67
- }
68
-
69
- /**
70
- * 对 channel DID 进行 EIP-191 personal_sign 签名, 证明钱包所有权
71
- * 返回 { address, signature, message, did }
72
- * - message: 实际签名的原文, 服务端需用 recoverMessage 校验
73
- * - signature: 0x 开头 65 字节签名 (r||s||v)
74
- */
75
- export async function signDIDChallenge(privateKeyHex, did, channelId) {
76
- const normalized = privateKeyHex.startsWith('0x') ? privateKeyHex : `0x${privateKeyHex}`;
77
- const account = privateKeyToAccount(normalized);
78
- const message = buildChallengeMessage(did, channelId);
79
- const signature = await account.signMessage({ message });
80
- return {
81
- address: account.address,
82
- signature,
83
- message,
84
- did,
85
- };
86
- }
87
-
88
- export function buildChallengeMessage(did, channelId) {
89
- return [
90
- 'Bolloon Agent Wallet Binding',
91
- `Channel ID: ${channelId}`,
92
- `Agent DID: ${did}`,
93
- `Issued At: ${new Date().toISOString()}`,
94
- ].join('\n');
95
- }
96
-
97
- // 从 viem HDKey 账户里取出 privateKey (Uint8Array) 转成 0x 开头 hex
98
- function extractPrivateKey(account) {
99
- const hdKey = account.getHdKey ? account.getHdKey() : null;
100
- if (!hdKey || !hdKey.privateKey) {
101
- throw new Error('无法从助记词派生私钥');
102
- }
103
- return '0x' + Array.from(hdKey.privateKey, (b) => b.toString(16).padStart(2, '0')).join('');
104
- }
105
-
106
- const api = {
107
- generateRealWallet,
108
- importEVMWallet,
109
- importEVMMnemonic,
110
- signDIDChallenge,
111
- buildChallengeMessage,
112
- };
113
-
114
- if (typeof window !== 'undefined') {
115
- window.WalletViem = api;
116
- }
117
-
118
- export default api;
1
+ // Real-wallet helpers (viem-backed), exposed as window.WalletViem for client.js.
2
+ // 浏览器侧执行, 不上链, 但地址/助记词/签名都符合 EVM 标准
3
+ // (BIP-39 mnemonic + secp256k1 keypair + EIP-55 checksum address + EIP-191 personal_sign).
4
+
5
+ import {
6
+ generateMnemonic,
7
+ mnemonicToAccount,
8
+ privateKeyToAccount,
9
+ english,
10
+ } from 'https://esm.sh/viem@2.52.0/accounts';
11
+
12
+ /**
13
+ * 生成一个全新的 EVM 钱包: 12 词助记词 + 派生账户 (BIP-44, m/44'/60'/0'/0/0)
14
+ * 返回: { mnemonic, address, privateKey }
15
+ * - mnemonic: 12 词英文助记词
16
+ * - address: EIP-55 checksum 后的 0x 开头地址
17
+ * - privateKey: 0x 开头的 32 字节私钥
18
+ */
19
+ export function generateEVMWallet() {
20
+ const mnemonic = generateMnemonic(english, 128); // 128 bits = 12 words
21
+ const account = mnemonicToAccount(mnemonic, { accountIndex: 0 });
22
+ return {
23
+ mnemonic,
24
+ address: account.address,
25
+ // viem 不直接暴露 privateKey, 用 hdKeyToAccount 路径取
26
+ // 这里走一个变通: 拿地址后, 再用 createAccount 走不通...
27
+ // 实际: account.source 包含 HDKey, 我们让它返回 privateKey 字段
28
+ // 简化: 直接调一个 helper
29
+ };
30
+ }
31
+
32
+ /**
33
+ * 通过私钥恢复账户: 用于"导入已有钱包"流程
34
+ */
35
+ export function importEVMWallet(privateKeyHex) {
36
+ const normalized = privateKeyHex.startsWith('0x') ? privateKeyHex : `0x${privateKeyHex}`;
37
+ const account = privateKeyToAccount(normalized);
38
+ return {
39
+ address: account.address,
40
+ privateKey: normalized,
41
+ };
42
+ }
43
+
44
+ /**
45
+ * 通过助记词恢复账户
46
+ */
47
+ export function importEVMMnemonic(mnemonic) {
48
+ const account = mnemonicToAccount(mnemonic.trim(), { accountIndex: 0 });
49
+ return {
50
+ mnemonic: mnemonic.trim(),
51
+ address: account.address,
52
+ privateKey: extractPrivateKey(account),
53
+ };
54
+ }
55
+
56
+ /**
57
+ * 真实生成路径: 先生成助记词, 再恢复出账户, 顺带取出 privateKey
58
+ */
59
+ export function generateRealWallet() {
60
+ const mnemonic = generateMnemonic(english, 128);
61
+ const account = mnemonicToAccount(mnemonic, { accountIndex: 0 });
62
+ return {
63
+ mnemonic,
64
+ address: account.address,
65
+ privateKey: extractPrivateKey(account),
66
+ };
67
+ }
68
+
69
+ /**
70
+ * 对 channel DID 进行 EIP-191 personal_sign 签名, 证明钱包所有权
71
+ * 返回 { address, signature, message, did }
72
+ * - message: 实际签名的原文, 服务端需用 recoverMessage 校验
73
+ * - signature: 0x 开头 65 字节签名 (r||s||v)
74
+ */
75
+ export async function signDIDChallenge(privateKeyHex, did, channelId) {
76
+ const normalized = privateKeyHex.startsWith('0x') ? privateKeyHex : `0x${privateKeyHex}`;
77
+ const account = privateKeyToAccount(normalized);
78
+ const message = buildChallengeMessage(did, channelId);
79
+ const signature = await account.signMessage({ message });
80
+ return {
81
+ address: account.address,
82
+ signature,
83
+ message,
84
+ did,
85
+ };
86
+ }
87
+
88
+ export function buildChallengeMessage(did, channelId) {
89
+ return [
90
+ 'Bolloon Agent Wallet Binding',
91
+ `Channel ID: ${channelId}`,
92
+ `Agent DID: ${did}`,
93
+ `Issued At: ${new Date().toISOString()}`,
94
+ ].join('\n');
95
+ }
96
+
97
+ // 从 viem HDKey 账户里取出 privateKey (Uint8Array) 转成 0x 开头 hex
98
+ function extractPrivateKey(account) {
99
+ const hdKey = account.getHdKey ? account.getHdKey() : null;
100
+ if (!hdKey || !hdKey.privateKey) {
101
+ throw new Error('无法从助记词派生私钥');
102
+ }
103
+ return '0x' + Array.from(hdKey.privateKey, (b) => b.toString(16).padStart(2, '0')).join('');
104
+ }
105
+
106
+ const api = {
107
+ generateRealWallet,
108
+ importEVMWallet,
109
+ importEVMMnemonic,
110
+ signDIDChallenge,
111
+ buildChallengeMessage,
112
+ };
113
+
114
+ if (typeof window !== 'undefined') {
115
+ window.WalletViem = api;
116
+ }
117
+
118
+ export default api;
@@ -0,0 +1,120 @@
1
+ // 边缘认证客户端 — 把 WebUI 登录配置托管到 Cloudflare 边缘 (Workers + KV)
2
+ // 2026-08-12: 优先请求边缘 Worker, worker 不可达时降级到本地 accounts.json fallback.
3
+ // Worker 实现见 src/web/workers/auth/.
4
+ /**
5
+ * 边缘认证客户端.
6
+ * 每个 auth 操作先打边缘 Worker; 失败/超时自动降级到本地 accounts.json.
7
+ */
8
+ export class EdgeAuthClient {
9
+ baseUrl;
10
+ timeoutMs;
11
+ fallbackFile;
12
+ log;
13
+ constructor(opts) {
14
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, '');
15
+ this.timeoutMs = opts.timeoutMs ?? 4000;
16
+ this.fallbackFile = opts.fallbackFile;
17
+ this.log = opts.log ?? (() => { });
18
+ }
19
+ // ---- 私有: 边缘 HTTP / 本地文件 ----
20
+ async edgeFetch(path, opts) {
21
+ const ctrl = new AbortController();
22
+ const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);
23
+ try {
24
+ const res = await fetch(`${this.baseUrl}/api/auth${path}`, {
25
+ method: opts?.method ?? 'GET',
26
+ headers: { 'Content-Type': 'application/json' },
27
+ body: opts?.body ? JSON.stringify(opts.body) : undefined,
28
+ signal: ctrl.signal,
29
+ });
30
+ if (!res.ok) {
31
+ const err = await res.text().catch(() => '');
32
+ throw new Error(`边缘认证 ${path} HTTP ${res.status} ${err}`);
33
+ }
34
+ return await res.json();
35
+ }
36
+ finally {
37
+ clearTimeout(timer);
38
+ }
39
+ }
40
+ async loadLocal() {
41
+ try {
42
+ const { readFile } = await import('fs/promises');
43
+ const parsed = JSON.parse(await readFile(this.fallbackFile, 'utf-8'));
44
+ return Array.isArray(parsed) ? parsed : [];
45
+ }
46
+ catch {
47
+ return [];
48
+ }
49
+ }
50
+ async saveLocal(accs) {
51
+ const { mkdir, writeFile } = await import('fs/promises');
52
+ const dir = this.fallbackFile.replace(/[\\/][^\\/]*$/, '');
53
+ await mkdir(dir, { recursive: true });
54
+ await writeFile(this.fallbackFile, JSON.stringify(accs, null, 2), { mode: 0o600 });
55
+ }
56
+ // ---- 公共 API (与 server.ts 原 loadAccounts/saveAccounts 语义一致) ----
57
+ /** 返回脱敏视图 (provider/identifier/loggedAt/skeleton), 供 /api/auth/status 直接用 */
58
+ async loadAccounts() {
59
+ try {
60
+ const data = await this.edgeFetch('/status');
61
+ return Array.isArray(data?.accounts) ? data.accounts : [];
62
+ }
63
+ catch (err) {
64
+ this.log(`[edge-auth] 边缘不可达, 降级本地: ${err?.message ?? err}`);
65
+ return this.loadLocal().then((accs) => accs.map((a) => ({
66
+ provider: a.provider,
67
+ identifier: a.identifier || a.email || a.username || '',
68
+ loggedAt: a.loggedAt,
69
+ skeleton: !!a.skeleton,
70
+ })));
71
+ }
72
+ }
73
+ async login(payload) {
74
+ try {
75
+ return await this.edgeFetch('/login', { method: 'POST', body: payload });
76
+ }
77
+ catch (err) {
78
+ this.log(`[edge-auth] 登录降级本地: ${err?.message ?? err}`);
79
+ const accs = await this.loadLocal();
80
+ const now = new Date().toISOString();
81
+ const exists = accs.find((a) => a.provider === payload.provider &&
82
+ (!payload.identifier || a.identifier === payload.identifier || a.email === payload.identifier));
83
+ if (exists) {
84
+ exists.ownerDid = payload.ownerDid;
85
+ exists.loggedAt = now;
86
+ exists.skeleton = true;
87
+ }
88
+ else {
89
+ const id = payload.identifier || '';
90
+ accs.push({
91
+ provider: payload.provider,
92
+ identifier: id,
93
+ email: payload.provider === 'email' ? id : '',
94
+ phone: payload.provider === 'phone' ? id : '',
95
+ username: id || '',
96
+ token: '',
97
+ ownerDid: payload.ownerDid,
98
+ loggedAt: now,
99
+ skeleton: true,
100
+ });
101
+ }
102
+ await this.saveLocal(accs);
103
+ return { ok: true, provider: payload.provider, identifier: payload.identifier, ownerDid: payload.ownerDid, skeleton: true, degraded: true };
104
+ }
105
+ }
106
+ async logout(payload) {
107
+ try {
108
+ return await this.edgeFetch('/logout', { method: 'POST', body: payload });
109
+ }
110
+ catch (err) {
111
+ this.log(`[edge-auth] 登出降级本地: ${err?.message ?? err}`);
112
+ const before = await this.loadLocal();
113
+ const remaining = before.filter((a) => a.provider !== payload.provider);
114
+ if (remaining.length === before.length)
115
+ throw new Error(`未绑定 ${payload.provider} 账号`);
116
+ await this.saveLocal(remaining);
117
+ return { ok: true, degraded: true };
118
+ }
119
+ }
120
+ }