@bolloon/bolloon-agent 0.2.9 โ†’ 0.2.10

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 (268) hide show
  1. package/README.md +467 -467
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon.cjs +0 -0
  4. package/bin/bolloon.js +157 -0
  5. package/dist/agents/agent-manifest-protocol.js +0 -52
  6. package/dist/agents/constraint-layer.js +19 -19
  7. package/dist/agents/pi-sdk.js +287 -1213
  8. package/dist/agents/shell-guard.js +2 -2
  9. package/dist/agents/workflow-pivot-loop.js +2 -81
  10. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  11. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  12. package/dist/bollharness-integration/context-router.js +292 -292
  13. package/dist/bollharness-integration/gate-state-machine.js +13 -26
  14. package/dist/bollharness-integration/integration.js +0 -71
  15. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  16. package/dist/bollharness-integration/skill-adapter.js +127 -52
  17. package/dist/bootstrap/context-collector.js +3 -6
  18. package/dist/bootstrap/lifecycle-hooks.js +1 -15
  19. package/dist/cli-entry.js +35 -39
  20. package/dist/constraint-runtime/src/_archive_helper.js +9 -0
  21. package/dist/constraint-runtime/src/agent/coordinator.js +48 -0
  22. package/dist/constraint-runtime/src/agent/index.js +1 -0
  23. package/dist/constraint-runtime/src/assistant/index.js +12 -0
  24. package/dist/constraint-runtime/src/bootstrap/index.js +12 -0
  25. package/dist/constraint-runtime/src/bootstrap_graph.js +13 -0
  26. package/dist/constraint-runtime/src/bridge/index.js +12 -0
  27. package/dist/constraint-runtime/src/buddy/index.js +12 -0
  28. package/dist/constraint-runtime/src/cli/index.js +12 -0
  29. package/dist/constraint-runtime/src/command_graph.js +10 -0
  30. package/dist/constraint-runtime/src/commands.js +60 -0
  31. package/dist/constraint-runtime/src/components/index.js +12 -0
  32. package/dist/constraint-runtime/src/constants/index.js +12 -0
  33. package/dist/constraint-runtime/src/constraint/budget.js +22 -0
  34. package/dist/constraint-runtime/src/constraint/index.js +2 -0
  35. package/dist/constraint-runtime/src/constraint/permission.js +20 -0
  36. package/dist/constraint-runtime/src/context.js +30 -0
  37. package/dist/constraint-runtime/src/coordinator/index.js +12 -0
  38. package/dist/constraint-runtime/src/cost_hook.js +4 -0
  39. package/dist/constraint-runtime/src/cost_tracker.js +8 -0
  40. package/dist/constraint-runtime/src/deferred_init.js +10 -0
  41. package/dist/constraint-runtime/src/direct_modes.js +6 -0
  42. package/dist/constraint-runtime/src/dynamic-tool-loader.js +85 -0
  43. package/dist/constraint-runtime/src/entrypoints/index.js +12 -0
  44. package/dist/constraint-runtime/src/execution_registry.js +44 -0
  45. package/dist/constraint-runtime/src/history.js +9 -0
  46. package/dist/constraint-runtime/src/hooks/index.js +12 -0
  47. package/dist/constraint-runtime/src/index.js +26 -0
  48. package/dist/constraint-runtime/src/ink.js +4 -0
  49. package/dist/constraint-runtime/src/keybindings/index.js +12 -0
  50. package/dist/constraint-runtime/src/memdir/index.js +12 -0
  51. package/dist/constraint-runtime/src/migrations/index.js +12 -0
  52. package/dist/constraint-runtime/src/models.js +1 -0
  53. package/dist/constraint-runtime/src/moreright/index.js +12 -0
  54. package/dist/constraint-runtime/src/native_ts/index.js +12 -0
  55. package/dist/constraint-runtime/src/output_styles/index.js +12 -0
  56. package/dist/constraint-runtime/src/parity_audit.js +12 -0
  57. package/dist/constraint-runtime/src/plugins/index.js +12 -0
  58. package/dist/constraint-runtime/src/port_manifest.js +11 -0
  59. package/dist/constraint-runtime/src/prefetch.js +9 -0
  60. package/dist/constraint-runtime/src/query.js +1 -0
  61. package/dist/constraint-runtime/src/remote/index.js +12 -0
  62. package/dist/constraint-runtime/src/remote_runtime.js +9 -0
  63. package/dist/constraint-runtime/src/runtime/index.js +1 -0
  64. package/dist/constraint-runtime/src/runtime/session.js +35 -0
  65. package/dist/constraint-runtime/src/schemas/index.js +12 -0
  66. package/dist/constraint-runtime/src/screens/index.js +12 -0
  67. package/dist/constraint-runtime/src/server/index.js +12 -0
  68. package/dist/constraint-runtime/src/services/index.js +12 -0
  69. package/dist/constraint-runtime/src/session_store.js +22 -0
  70. package/dist/constraint-runtime/src/setup.js +30 -0
  71. package/dist/constraint-runtime/src/skills/index.js +1 -0
  72. package/dist/constraint-runtime/src/skills/skill-registry.js +28 -0
  73. package/dist/constraint-runtime/src/state/index.js +12 -0
  74. package/dist/constraint-runtime/src/system_init.js +20 -0
  75. package/dist/constraint-runtime/src/thinking/engine.js +42 -0
  76. package/dist/constraint-runtime/src/thinking/index.js +1 -0
  77. package/dist/constraint-runtime/src/tool_pool.js +8 -0
  78. package/dist/constraint-runtime/src/tools/OpenCLI/execAdapter.js +7 -0
  79. package/dist/constraint-runtime/src/tools/OpenCLI/listAdapters.js +7 -0
  80. package/dist/constraint-runtime/src/tools/OpenCLI/runCommand.js +7 -0
  81. package/dist/constraint-runtime/src/tools/SafeSDK/confirmTransaction.js +6 -0
  82. package/dist/constraint-runtime/src/tools/SafeSDK/createTransaction.js +8 -0
  83. package/dist/constraint-runtime/src/tools/SafeSDK/executeTransaction.js +6 -0
  84. package/dist/constraint-runtime/src/tools/SafeSDK/getBalance.js +6 -0
  85. package/dist/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.js +6 -0
  86. package/dist/constraint-runtime/src/tools/SafeSDK/proposeTransaction.js +6 -0
  87. package/dist/constraint-runtime/src/tools.js +80 -0
  88. package/dist/constraint-runtime/src/transcript.js +19 -0
  89. package/dist/constraint-runtime/src/types/index.js +12 -0
  90. package/dist/constraint-runtime/src/upstream_proxy/index.js +12 -0
  91. package/dist/constraint-runtime/src/utils/index.js +12 -0
  92. package/dist/constraint-runtime/src/vim/index.js +12 -0
  93. package/dist/constraint-runtime/src/voice/index.js +12 -0
  94. package/dist/constraint-runtime/tests/agent.test.js +16 -0
  95. package/dist/constraint-runtime/tests/constraint.test.js +41 -0
  96. package/dist/constraint-runtime/tests/skill.test.js +19 -0
  97. package/dist/constraint-runtime/tests/thinking.test.js +22 -0
  98. package/dist/context-compaction/auto-compact.js +7 -7
  99. package/dist/electron-preload.js +1 -18
  100. package/dist/electron-preload.js.map +1 -1
  101. package/dist/electron.js +168 -3
  102. package/dist/electron.js.map +1 -1
  103. package/dist/index.js +116 -136
  104. package/dist/llm/config-store.js +8 -24
  105. package/dist/llm/llm-judgment-client.js +102 -102
  106. package/dist/llm/pi-ai.js +85 -126
  107. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  108. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  109. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  110. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  111. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  112. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  113. package/dist/llm/system-prompt/layers/core/identity.md +37 -37
  114. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  115. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  116. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  117. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  118. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  119. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  120. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  121. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  122. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  123. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  124. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  125. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  126. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  127. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  128. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  129. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  130. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  131. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  132. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  133. package/dist/llm/tool-manifest/bash.js +3 -3
  134. package/dist/llm/tool-manifest/create_file.js +4 -4
  135. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  136. package/dist/llm/tool-manifest/image_search.js +2 -2
  137. package/dist/llm/tool-manifest/mcp.js +2 -2
  138. package/dist/llm/tool-manifest/message_compose.js +3 -3
  139. package/dist/llm/tool-manifest/places.js +2 -2
  140. package/dist/llm/tool-manifest/present_files.js +1 -1
  141. package/dist/llm/tool-manifest/recipe.js +2 -2
  142. package/dist/llm/tool-manifest/str_replace.js +5 -5
  143. package/dist/llm/tool-manifest/view.js +3 -3
  144. package/dist/llm/tool-manifest/weather.js +4 -4
  145. package/dist/llm/tool-manifest/web.js +4 -4
  146. package/dist/pi-ecosystem-colony/index.js +365 -0
  147. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  148. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  149. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  150. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  151. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  152. package/dist/security/context-router-tool.js +15 -15
  153. package/dist/security/tool-gate.js +0 -11
  154. package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
  155. package/dist/social/ant-colony/PheromoneEngine.js +227 -0
  156. package/dist/social/ant-colony/index.js +6 -0
  157. package/dist/social/ant-colony/types.js +24 -0
  158. package/dist/test/ai-judgment-test.js +80 -0
  159. package/dist/test/bollharness-integration.test.js +318 -0
  160. package/dist/test/channel-agent-multi-dialogue.js +205 -0
  161. package/dist/test/channel-heartbeat-agent-test.js +201 -0
  162. package/dist/test/constraint-layer.test.js +164 -0
  163. package/dist/test/diap-identity-test.js +172 -0
  164. package/dist/test/diap-quick-test.js +62 -0
  165. package/dist/test/global-shared-context.test.js +315 -0
  166. package/dist/test/harness-judgment-injection.test.js +246 -0
  167. package/dist/test/harness-workflow-integrator-test.js +228 -0
  168. package/dist/test/human-value-store.test.js +243 -0
  169. package/dist/test/hybrid-integration-test.js +118 -0
  170. package/dist/test/hybrid-messenger-verify.js +55 -0
  171. package/dist/test/iroh-bistream-debug.js +38 -0
  172. package/dist/test/iroh-communication.test.js +66 -0
  173. package/dist/test/iroh-debug-test.js +57 -0
  174. package/dist/test/iroh-diap-test.js +71 -0
  175. package/dist/test/iroh-direct-connect.js +55 -0
  176. package/dist/test/iroh-e2e-fixed.js +89 -0
  177. package/dist/test/iroh-e2e-same-process.js +63 -0
  178. package/dist/test/iroh-e2e.js +66 -0
  179. package/dist/test/iroh-final-e2e.js +72 -0
  180. package/dist/test/iroh-relay-test.js +37 -0
  181. package/dist/test/iroh-simple-test.js +41 -0
  182. package/dist/test/iroh-transport-verify.js +54 -0
  183. package/dist/test/iroh-transport.test.js +37 -0
  184. package/dist/test/iroh-two-nodes.js +70 -0
  185. package/dist/test/iroh-verify.js +44 -0
  186. package/dist/test/judgment-decision.test.js +219 -0
  187. package/dist/test/llm-judgment-integration.test.js +220 -0
  188. package/dist/test/p2p-agent-complex-dialogue.js +385 -0
  189. package/dist/test/p2p-agent-dialogue.js +341 -0
  190. package/dist/test/p2p-agent-full-bidirectional.js +510 -0
  191. package/dist/test/p2p-agent-harness-flow.js +437 -0
  192. package/dist/test/p2p-agent-harness-single.js +143 -0
  193. package/dist/test/p2p-ai-dialogue-test.js +318 -0
  194. package/dist/test/p2p-cid-connect-test.js +195 -0
  195. package/dist/test/p2p-connect-receiver.js +69 -0
  196. package/dist/test/p2p-doc-transfer.js +110 -0
  197. package/dist/test/p2p-identity-page-test.js +77 -0
  198. package/dist/test/p2p-iroh-test.js +171 -0
  199. package/dist/test/p2p-minimal-test.js +241 -0
  200. package/dist/test/p2p-node-1.js +148 -0
  201. package/dist/test/p2p-node-2.js +148 -0
  202. package/dist/test/p2p-server.js +281 -0
  203. package/dist/test/p2p-two-nodes-test.js +438 -0
  204. package/dist/test/pi-sdk.test.js +44 -0
  205. package/dist/test/set-persona.js +40 -0
  206. package/dist/test/simple.test.js +9 -0
  207. package/dist/test/storage-integration.test.js +150 -0
  208. package/dist/test/subagent-manager.test.js +276 -0
  209. package/dist/test/test-gate-flow.test.js +81 -0
  210. package/dist/test/workflow-engine.test.js +87 -0
  211. package/dist/test/workflow-pivot-loop.test.js +246 -0
  212. package/dist/web/api-config.html +520 -520
  213. package/dist/web/client.js +2917 -3791
  214. package/dist/web/components/p2p/index.js +234 -276
  215. package/dist/web/components/wallet-viem.mjs +118 -118
  216. package/dist/web/index.html +374 -373
  217. package/dist/web/manifest.json +20 -20
  218. package/dist/web/server.js +23 -775
  219. package/dist/web/style.css +4737 -4737
  220. package/dist/web/ui/message-renderer.js +373 -451
  221. package/dist/web/ui/step-timeline.js +255 -351
  222. package/package.json +160 -160
  223. package/scripts/build-cli.js +215 -215
  224. package/scripts/build-web.ts +125 -125
  225. package/scripts/postinstall.js +152 -152
  226. package/bin/bolloon-daemon.sh +0 -207
  227. package/bin/ipfs +0 -0
  228. package/dist/agents/chat-segmenter.js +0 -298
  229. package/dist/agents/judgment-protocol.js +0 -479
  230. package/dist/agents/parse-tool-call.js +0 -304
  231. package/dist/agents/peer-manifest-loader.js +0 -210
  232. package/dist/agents/react-loop.js +0 -120
  233. package/dist/agents/session-store.js +0 -171
  234. package/dist/agents/tool-registry.js +0 -136
  235. package/dist/bootstrap/chat-archiver.js +0 -276
  236. package/dist/bootstrap/memory-compressor.js +0 -170
  237. package/dist/bootstrap/persona-loader.js +0 -94
  238. package/dist/electron/config.js +0 -16
  239. package/dist/electron/config.js.map +0 -1
  240. package/dist/electron/dialogs.js +0 -71
  241. package/dist/electron/dialogs.js.map +0 -1
  242. package/dist/electron/first-run.js +0 -129
  243. package/dist/electron/first-run.js.map +0 -1
  244. package/dist/electron/ipc.js +0 -16
  245. package/dist/electron/ipc.js.map +0 -1
  246. package/dist/electron/logger.js +0 -77
  247. package/dist/electron/logger.js.map +0 -1
  248. package/dist/electron/main.js +0 -60
  249. package/dist/electron/main.js.map +0 -1
  250. package/dist/electron/menu.js +0 -140
  251. package/dist/electron/menu.js.map +0 -1
  252. package/dist/electron/paths.js +0 -33
  253. package/dist/electron/paths.js.map +0 -1
  254. package/dist/electron/server.js +0 -74
  255. package/dist/electron/server.js.map +0 -1
  256. package/dist/electron/tray.js +0 -73
  257. package/dist/electron/tray.js.map +0 -1
  258. package/dist/electron/window.js +0 -69
  259. package/dist/electron/window.js.map +0 -1
  260. package/dist/network/local-inbox-bus.js +0 -73
  261. package/dist/network/p2p-outbox.js +0 -161
  262. package/dist/network/peer-fs.js +0 -420
  263. package/dist/network/peer-resource-bridge.js +0 -216
  264. package/dist/web/components/p2p/P2PModal.js +0 -188
  265. package/dist/web/components/p2p/p2p-modal.js +0 -664
  266. package/dist/web/components/p2p/p2p-tools.js +0 -248
  267. package/dist/web/input-validator.js +0 -103
  268. package/dist/web/util/safe-name.js +0 -32
@@ -0,0 +1,110 @@
1
+ import { irohTransport } from '../network/iroh-transport.js';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ const args = process.argv.slice(2);
5
+ const role = args[0];
6
+ const targetNodeId = args[1];
7
+ if (!role || !['server', 'client'].includes(role)) {
8
+ console.log('Usage:');
9
+ console.log(' Server: npx tsx src/test/p2p-doc-transfer.ts server');
10
+ console.log(' Client: npx tsx src/test/p2p-doc-transfer.ts client <server-node-id>');
11
+ process.exit(1);
12
+ }
13
+ async function readDoc(filePath) {
14
+ const content = fs.readFileSync(filePath, 'utf-8');
15
+ return {
16
+ name: path.basename(filePath),
17
+ content,
18
+ size: Buffer.byteLength(content, 'utf-8'),
19
+ };
20
+ }
21
+ async function runServer() {
22
+ console.log('[Server] Starting iroh transport for document transfer test...');
23
+ const node = await irohTransport.start();
24
+ console.log('[Server] Node ID:', node.nodeId);
25
+ console.log('[Server] Waiting for document transfers...\n');
26
+ let docCount = 0;
27
+ irohTransport.onMessage('doc-md', (msg) => {
28
+ docCount++;
29
+ const content = new TextDecoder().decode(msg.payload);
30
+ console.log(`[Server] #${docCount} MD Doc from ${msg.from.substring(0, 16)}...`);
31
+ console.log(`[Server] Size: ${content.length} bytes`);
32
+ console.log(`[Server] Preview: "${content.substring(0, 80)}..."`);
33
+ irohTransport.sendMessage(msg.from, 'ack-md', new TextEncoder().encode('md-received'));
34
+ });
35
+ irohTransport.onMessage('doc-yaml', (msg) => {
36
+ docCount++;
37
+ const content = new TextDecoder().decode(msg.payload);
38
+ console.log(`[Server] #${docCount} YAML Doc from ${msg.from.substring(0, 16)}...`);
39
+ console.log(`[Server] Size: ${content.length} bytes`);
40
+ console.log(`[Server] Preview: "${content.substring(0, 80)}..."`);
41
+ irohTransport.sendMessage(msg.from, 'ack-yaml', new TextEncoder().encode('yaml-received'));
42
+ });
43
+ irohTransport.onMessage('doc-html', (msg) => {
44
+ docCount++;
45
+ const content = new TextDecoder().decode(msg.payload);
46
+ console.log(`[Server] #${docCount} HTML Doc from ${msg.from.substring(0, 16)}...`);
47
+ console.log(`[Server] Size: ${content.length} bytes`);
48
+ console.log(`[Server] Preview: "${content.substring(0, 80)}..."`);
49
+ irohTransport.sendMessage(msg.from, 'ack-html', new TextEncoder().encode('html-received'));
50
+ });
51
+ console.log('[Server] Ready. Press Ctrl+C to stop.');
52
+ await new Promise(() => { });
53
+ }
54
+ async function runClient(targetId) {
55
+ if (!targetId) {
56
+ console.error('[Client] Error: target node ID required');
57
+ process.exit(1);
58
+ }
59
+ console.log('[Client] Starting iroh transport for document transfer test...');
60
+ const node = await irohTransport.start();
61
+ console.log('[Client] Node ID:', node.nodeId);
62
+ console.log('[Client] Target:', targetId);
63
+ console.log('');
64
+ const acks = { md: false, yaml: false, html: false };
65
+ irohTransport.onMessage('ack-md', (msg) => {
66
+ console.log(`[Client] โœ… MD doc acknowledged by server`);
67
+ acks.md = true;
68
+ });
69
+ irohTransport.onMessage('ack-yaml', (msg) => {
70
+ console.log(`[Client] โœ… YAML doc acknowledged by server`);
71
+ acks.yaml = true;
72
+ });
73
+ irohTransport.onMessage('ack-html', (msg) => {
74
+ console.log(`[Client] โœ… HTML doc acknowledged by server`);
75
+ acks.html = true;
76
+ });
77
+ await new Promise(resolve => setTimeout(resolve, 500));
78
+ console.log('[Client] Loading test documents...\n');
79
+ const testDocs = [
80
+ { type: 'doc-md', path: 'src/bollharness/docs/practice.md', label: 'MD' },
81
+ { type: 'doc-yaml', path: 'src/bollharness/.boll/MANIFEST.yaml', label: 'YAML' },
82
+ { type: 'doc-html', path: 'src/web/index.html', label: 'HTML' },
83
+ ];
84
+ for (const doc of testDocs) {
85
+ try {
86
+ const docInfo = await readDoc(doc.path);
87
+ console.log(`[Client] Sending ${doc.label} document: ${docInfo.name} (${docInfo.size} bytes)`);
88
+ const success = await irohTransport.sendMessage(targetId, doc.type, new TextEncoder().encode(docInfo.content));
89
+ console.log(`[Client] Send result: ${success ? 'โœ… SUCCESS' : 'โŒ FAILED'}`);
90
+ }
91
+ catch (e) {
92
+ console.log(`[Client] โŒ Error sending ${doc.label}: ${e.message}`);
93
+ }
94
+ await new Promise(resolve => setTimeout(resolve, 500));
95
+ }
96
+ console.log('\n[Client] Waiting for acknowledgements...');
97
+ await new Promise(resolve => setTimeout(resolve, 3000));
98
+ console.log('\n=== Test Summary ===');
99
+ console.log(` MD document: ${acks.md ? 'โœ… Acknowledged' : 'โŒ Not acknowledged'}`);
100
+ console.log(` YAML document: ${acks.yaml ? 'โœ… Acknowledged' : 'โŒ Not acknowledged'}`);
101
+ console.log(` HTML document: ${acks.html ? 'โœ… Acknowledged' : 'โŒ Not acknowledged'}`);
102
+ await irohTransport.shutdown();
103
+ console.log('[Client] Done');
104
+ }
105
+ if (role === 'server') {
106
+ runServer();
107
+ }
108
+ else {
109
+ runClient(targetNodeId);
110
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * P2P Identity Page Test with Playwright
3
+ * ๆต‹่ฏ• P2P ่บซไปฝ้กต้ข๏ผŒๆ˜พ็คบ DIDใ€CID ็ญ‰ไฟกๆฏ
4
+ */
5
+ import { chromium } from 'playwright';
6
+ async function testP2PIdentityPage() {
7
+ console.log('=== P2P Identity Page Test ===\n');
8
+ const browser = await chromium.launch({ headless: true });
9
+ const context = await browser.newContext();
10
+ const page = await context.newPage();
11
+ try {
12
+ // 1. ๆ‰“ๅผ€ Bolloon ็ฝ‘้กต
13
+ console.log('1. ๆ‰“ๅผ€ Bolloon ็ฝ‘้กต...');
14
+ await page.goto('http://localhost:54188', {
15
+ waitUntil: 'domcontentloaded',
16
+ timeout: 60000
17
+ });
18
+ // 2. ๅˆๅง‹ๅŒ– iroh
19
+ console.log('2. ๅˆๅง‹ๅŒ– iroh...');
20
+ const irohInit = await page.evaluate(async () => {
21
+ const res = await fetch('/api/iroh/init', { method: 'POST' });
22
+ return res.json();
23
+ });
24
+ console.log(' iroh ๅˆๅง‹ๅŒ–็ป“ๆžœ:');
25
+ console.log(' - DID:', irohInit.did?.substring(0, 30) + '...');
26
+ console.log(' - CID:', irohInit.cid);
27
+ console.log(' - Initialized:', irohInit.initialized);
28
+ // 3. ๆ‰“ๅผ€ P2P Modal
29
+ console.log('\n3. ๆ‰“ๅผ€ P2P Modal...');
30
+ // ๅˆๅง‹ๅŒ– iroh๏ผˆ่ฟ™ไผš่งฆๅ‘ CID ็”Ÿๆˆ๏ผ‰
31
+ await page.evaluate(async () => {
32
+ await fetch('/api/iroh/init', { method: 'POST' });
33
+ });
34
+ await page.waitForTimeout(1000);
35
+ // ๆ‰“ๅผ€ P2P Modal ้€š่ฟ‡็‚นๅ‡ปๆŒ‰้’ฎ
36
+ await page.evaluate(() => {
37
+ const btn = document.querySelector('#p2p-network-btn');
38
+ if (btn)
39
+ btn.click();
40
+ });
41
+ await page.waitForTimeout(3000);
42
+ // 4. ่Žทๅ–่บซไปฝไฟกๆฏๆ˜พ็คบ
43
+ console.log('\n4. ่Žทๅ–่บซไปฝไฟกๆฏ...');
44
+ // ่Žทๅ– modal HTML ็ป“ๆž„็”จไบŽ่ฐƒ่ฏ•
45
+ const modalHtml = await page.evaluate(() => {
46
+ const modal = document.querySelector('.p2p-modal');
47
+ return modal ? modal.outerHTML : 'Modal not found';
48
+ });
49
+ console.log('\n Modal HTML:');
50
+ console.log(' ', modalHtml.substring(0, 1000));
51
+ // ๆฃ€ๆŸฅ p2p-info-row ไธญ็š„ label ๅ†…ๅฎน
52
+ const labels = await page.evaluate(() => {
53
+ return Array.from(document.querySelectorAll('.p2p-info-row .label')).map(el => el.textContent);
54
+ });
55
+ console.log('\n Labels found:', labels);
56
+ // ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ CID
57
+ const hasCidRow = await page.evaluate(() => {
58
+ const rows = document.querySelectorAll('.p2p-info-row');
59
+ for (const row of rows) {
60
+ const label = row.querySelector('.label')?.textContent;
61
+ if (label?.includes('CID'))
62
+ return true;
63
+ }
64
+ return false;
65
+ });
66
+ console.log(' CID row exists:', hasCidRow);
67
+ console.log('\n=== ๆต‹่ฏ•ๅฎŒๆˆ ===');
68
+ }
69
+ catch (error) {
70
+ console.error('ๆต‹่ฏ•ๅคฑ่ดฅ:', error);
71
+ }
72
+ finally {
73
+ await browser.close();
74
+ }
75
+ }
76
+ // ่ฟ่กŒๆต‹่ฏ•
77
+ testP2PIdentityPage().catch(console.error);
@@ -0,0 +1,171 @@
1
+ /**
2
+ * P2P iroh ๆต‹่ฏ• - ้€š่ฟ‡ CID ่งฃๆž DID ๆ–‡ๆกฃๅนถไฝฟ็”จ iroh ๅปบ็ซ‹่ฟžๆŽฅ
3
+ *
4
+ * ๆต็จ‹:
5
+ * 1. ็”Ÿๆˆ DID โ†’ ๅ‘ๅธƒๅˆฐ IPFS โ†’ ่Žทๅพ— CID
6
+ * 2. ้€š่ฟ‡ CID ไปŽ IPFS ่งฃๆž DID ๆ–‡ๆกฃ
7
+ * 3. ไฝฟ็”จ iroh ็›ดๆŽฅ้€š่ฟ‡ Node ID ่ฟžๆŽฅ
8
+ */
9
+ import { KeyManager, AgentAuthManager } from '@diap/sdk';
10
+ import { irohTransport } from '../network/iroh-transport.js';
11
+ const IPFS_ENDPOINT = 'http://127.0.0.1:5001';
12
+ // ============================================================
13
+ // ๆญฅ้ชค 1: ๅ‘ๅธƒ DID ๅˆฐ IPFS
14
+ // ============================================================
15
+ async function publishDIDToIPFS(name) {
16
+ console.log('\n[ๆญฅ้ชค 1] ๅ‘ๅธƒ DID ๅˆฐ IPFS...');
17
+ // ็”Ÿๆˆ DID
18
+ const keyPair = KeyManager.generate();
19
+ const did = keyPair.did;
20
+ console.log(` โœ… DID ็”Ÿๆˆ: ${did}`);
21
+ // ่Žทๅ–ๅทฒๆœ‰็š„ iroh Node ID
22
+ const irohNodeId = irohTransport.getNodeId();
23
+ console.log(` โœ… iroh ่Š‚็‚น ID: ${irohNodeId}`);
24
+ // ๅ‘ๅธƒ DID ๅˆฐ IPFS๏ผˆไฝฟ็”จ AgentAuthManager๏ผ‰
25
+ const authManager = await AgentAuthManager.newWithRemoteIpfs(IPFS_ENDPOINT, IPFS_ENDPOINT);
26
+ const result = await authManager.registerAgent({ name, services: [] }, keyPair, '');
27
+ console.log(` โœ… IPFS CID: ${result.cid}`);
28
+ return {
29
+ did,
30
+ name,
31
+ cid: result.cid || '',
32
+ irohNodeId: irohNodeId || '',
33
+ };
34
+ }
35
+ // ============================================================
36
+ // ๆญฅ้ชค 2: ไปŽ CID ่งฃๆž DID ๆ–‡ๆกฃ
37
+ // ============================================================
38
+ async function resolveDIDFromIPFS(cid) {
39
+ console.log('\n[ๆญฅ้ชค 2] ไปŽ IPFS ่งฃๆž DID ๆ–‡ๆกฃ...');
40
+ try {
41
+ // ็›ดๆŽฅไฝฟ็”จ fetch ่Žทๅ–
42
+ const response = await fetch(`${IPFS_ENDPOINT}/api/v0/cat?arg=${cid}`, {
43
+ method: 'POST'
44
+ });
45
+ const content = await response.text();
46
+ const doc = JSON.parse(content);
47
+ console.log(` โœ… DID ๆ–‡ๆกฃ่งฃๆžๆˆๅŠŸ`);
48
+ console.log(` DID: ${doc.id}`);
49
+ console.log(` ๅ็งฐ: ${doc.name || 'N/A'}`);
50
+ return {
51
+ did: doc.id,
52
+ name: doc.name || 'Unknown',
53
+ };
54
+ }
55
+ catch (e) {
56
+ console.log(` โŒ ่งฃๆžๅคฑ่ดฅ: ${e.message}`);
57
+ return null;
58
+ }
59
+ }
60
+ // ============================================================
61
+ // ๆญฅ้ชค 3: ้€š่ฟ‡ iroh ่ฟžๆŽฅๅนถๅ‘้€ๆถˆๆฏ
62
+ // ============================================================
63
+ async function connectAndMessage(targetNodeId, message) {
64
+ console.log('\n[ๆญฅ้ชค 3] ้€š่ฟ‡ iroh ๅ‘้€ๆถˆๆฏ...');
65
+ console.log(` ๐Ÿ“ค ็›ฎๆ ‡่Š‚็‚น: ${targetNodeId.substring(0, 20)}...`);
66
+ console.log(` ๐Ÿ“ ๆถˆๆฏ: ${message}`);
67
+ const success = await irohTransport.sendMessage(targetNodeId, 'chat', new TextEncoder().encode(message));
68
+ if (success) {
69
+ console.log(' โœ… ๆถˆๆฏๅ‘้€ๆˆๅŠŸ');
70
+ }
71
+ else {
72
+ console.log(' โš ๏ธ ๆถˆๆฏๅ‘้€ๅคฑ่ดฅ๏ผˆๅฏนๆ–นๅฏ่ƒฝไธๅœจ็บฟ๏ผ‰');
73
+ }
74
+ }
75
+ // ============================================================
76
+ // ๆŽฅๆ”ถๆถˆๆฏๅค„็†
77
+ // ============================================================
78
+ function setupMessageHandler() {
79
+ console.log('\n[็›‘ๅฌ] ่ฎพ็ฝฎๆถˆๆฏๅค„็†ๅ™จ...');
80
+ irohTransport.onMessage('chat', (msg) => {
81
+ const content = new TextDecoder().decode(msg.payload);
82
+ console.log(`\n ๐Ÿ’ฌ ๆ”ถๅˆฐๆถˆๆฏ from ${msg.from.substring(0, 12)}...: ${content}`);
83
+ // ๅ›žๅค
84
+ const reply = `ACK: ๅทฒๆ”ถๅˆฐ "${content.substring(0, 30)}..."`;
85
+ irohTransport.sendMessage(msg.from, 'chat', new TextEncoder().encode(reply));
86
+ console.log(` ๐Ÿ“ค ๅ‘้€ๅ›žๅค: ${reply}`);
87
+ });
88
+ irohTransport.onMessage('*', (msg) => {
89
+ console.log(`\n ๐Ÿ“ฉ ๆ”ถๅˆฐๆœช็Ÿฅ็ฑปๅž‹ๆถˆๆฏ [${msg.type}] from ${msg.from.substring(0, 12)}...`);
90
+ });
91
+ console.log(' โœ… ๆถˆๆฏๅค„็†ๅ™จๅทฒ่ฎพ็ฝฎ');
92
+ }
93
+ // ============================================================
94
+ // ไธปๆต‹่ฏ•ๆต็จ‹
95
+ // ============================================================
96
+ async function main() {
97
+ console.log('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
98
+ console.log('โ•‘ P2P iroh ๆต‹่ฏ• - CID ่งฃๆž + ็›ดๆŽฅ Node ID ่ฟžๆŽฅ โ•‘');
99
+ console.log('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•');
100
+ const args = process.argv.slice(2);
101
+ const isPublisher = args.includes('--publish');
102
+ const targetCid = args.find(a => a.startsWith('--cid='))?.split('=')[1];
103
+ const targetNodeId = args.find(a => a.startsWith('--node='))?.split('=')[1];
104
+ const testMessage = args.find(a => a.startsWith('--msg='))?.split('=')[1] || 'Hello from iroh!';
105
+ // ๅˆๅง‹ๅŒ– iroh๏ผˆๆ‰€ๆœ‰ๆจกๅผ้ƒฝ้œ€่ฆ๏ผ‰
106
+ console.log('\n[ๅˆๅง‹ๅŒ–] ๅฏๅŠจ iroh transport...');
107
+ try {
108
+ await irohTransport.start(undefined, false);
109
+ console.log(' โœ… iroh transport ๅทฒๅฏๅŠจ');
110
+ }
111
+ catch (e) {
112
+ console.log(` โŒ iroh ๅฏๅŠจๅคฑ่ดฅ: ${e.message}`);
113
+ return;
114
+ }
115
+ // ่ฎพ็ฝฎๆถˆๆฏๅค„็†ๅ™จ
116
+ setupMessageHandler();
117
+ // ๆจกๅผ 1: ๅ‘ๅธƒ DID๏ผˆ็”ต่„‘ A๏ผ‰
118
+ if (isPublisher) {
119
+ const agentName = `bolloon-${Date.now()}`;
120
+ const info = await publishDIDToIPFS(agentName);
121
+ console.log('\nโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•');
122
+ console.log(' ๐Ÿ“‹ ๅˆ†ไบซ็ป™ๅฆไธ€ๅฐ็”ต่„‘็š„ไฟกๆฏ:');
123
+ console.log('โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•');
124
+ console.log(` DID: ${info.did}`);
125
+ console.log(` CID: ${info.cid}`);
126
+ console.log(` iroh Node ID: ${info.irohNodeId}`);
127
+ console.log('โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•');
128
+ console.log('\n ็”จๆณ•:');
129
+ console.log(` ็”ต่„‘ B: npx tsx src/test/p2p-iroh-test.ts --cid=${info.cid} --node=${info.irohNodeId}`);
130
+ console.log('\n ็ญ‰ๅพ…ๆถˆๆฏ... (Ctrl+C ้€€ๅ‡บ)\n');
131
+ // ไฟๆŒ่ฟ่กŒ
132
+ await new Promise(() => { });
133
+ }
134
+ // ๆจกๅผ 2: ่งฃๆž CID ๅนถ่ฟžๆŽฅ๏ผˆ็”ต่„‘ B๏ผ‰
135
+ else if (targetCid) {
136
+ const resolved = await resolveDIDFromIPFS(targetCid);
137
+ if (!resolved) {
138
+ console.log('โŒ ๆ— ๆณ•่งฃๆž DID ๆ–‡ๆกฃ');
139
+ return;
140
+ }
141
+ // ๅฆ‚ๆžœๆไพ›ไบ† Node ID๏ผŒ็›ดๆŽฅ่ฟžๆŽฅ
142
+ if (targetNodeId) {
143
+ console.log(`\n ๐ŸŽฏ ่ฟžๆŽฅๅˆฐ่Š‚็‚น: ${targetNodeId.substring(0, 20)}...`);
144
+ await connectAndMessage(targetNodeId, testMessage);
145
+ console.log('\n ็ญ‰ๅพ…ๅ›žๅค... (5็ง’ๅŽ้€€ๅ‡บ)');
146
+ await new Promise(resolve => setTimeout(resolve, 5000));
147
+ }
148
+ else {
149
+ console.log(`\n โš ๏ธ DID ๆ–‡ๆกฃๅทฒ่งฃๆž๏ผŒไฝ†้œ€่ฆ Node ID ๆ‰่ƒฝ่ฟžๆŽฅ`);
150
+ console.log(` DID: ${resolved.did}`);
151
+ console.log(` ๅ็งฐ: ${resolved.name}`);
152
+ console.log('\n ๆณจๆ„: DID ๆ–‡ๆกฃไธญ้œ€่ฆๅŒ…ๅซ iroh Node ID ไฟกๆฏ');
153
+ console.log(' ่ฏทไฝฟ็”จ --node=<iroh-node-id> ๅ‚ๆ•ฐ็›ดๆŽฅๆŒ‡ๅฎš่Š‚็‚น ID');
154
+ }
155
+ }
156
+ // ๅธฎๅŠฉไฟกๆฏ
157
+ else {
158
+ console.log('\n็”จๆณ•:');
159
+ console.log('');
160
+ console.log(' ็”ต่„‘ A (ๅ‘ๅธƒๆ–น):');
161
+ console.log(' npx tsx src/test/p2p-iroh-test.ts --publish');
162
+ console.log('');
163
+ console.log(' ็”ต่„‘ B (่ฟžๆŽฅๆ–น):');
164
+ console.log(' npx tsx src/test/p2p-iroh-test.ts --cid=<CID> --node=<iroh-node-id> --msg=<ๆถˆๆฏ>');
165
+ console.log('');
166
+ console.log('็คบไพ‹:');
167
+ console.log(' A: npx tsx src/test/p2p-iroh-test.ts --publish');
168
+ console.log(' B: npx tsx src/test/p2p-iroh-test.ts --cid=QmXXX --node=xyz123 --msg="Hello!"');
169
+ }
170
+ }
171
+ main().catch(console.error);
@@ -0,0 +1,241 @@
1
+ /**
2
+ * P2P Minimal Test - ๅˆคๆ–ญๅŠ›ๆ™บ่ƒฝไฝ“ P2P ้€šไฟกๆต‹่ฏ•
3
+ *
4
+ * ่ฟ่กŒๆ–นๅผ:
5
+ * ็”ต่„‘ A: npx tsx src/test/p2p-minimal-test.ts
6
+ * ็”ต่„‘ B: npx tsx src/test/p2p-minimal-test.ts --connect <็”ต่„‘A็š„NodeId>
7
+ *
8
+ * ๆต‹่ฏ•ๆต็จ‹:
9
+ * 1. ็”Ÿๆˆ DIAP ่บซไปฝ
10
+ * 2. ๅ‘ๅธƒ DID ๅˆฐ IPFS
11
+ * 3. ่ฟžๆŽฅๅฏนๆ–น่Š‚็‚น๏ผˆๆˆ–็ญ‰ๅพ…่ฟžๆŽฅ๏ผ‰
12
+ * 4. ไบคๆข AI ๆถˆๆฏ๏ผˆๅธฆๅˆคๆ–ญๅŠ›ๆณจๅ…ฅ๏ผ‰
13
+ */
14
+ import crypto from 'node:crypto';
15
+ import readline from 'node:readline';
16
+ import { KeyManager } from '@diap/sdk';
17
+ import { createHyperswarmCommunicator, createTopic } from '@diap/sdk';
18
+ const IPFS_API = 'http://127.0.0.1:5001';
19
+ const IPFS_GATEWAY = 'http://127.0.0.1:8080';
20
+ function parseArgs() {
21
+ const args = process.argv.slice(2);
22
+ const connectIdx = args.indexOf('--connect');
23
+ return {
24
+ connectTo: connectIdx >= 0 ? args[connectIdx + 1] : undefined
25
+ };
26
+ }
27
+ async function main() {
28
+ console.log('\nโ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
29
+ console.log('โ•‘ P2P Minimal Test - ๅˆคๆ–ญๅŠ›ๆ™บ่ƒฝไฝ“ P2P ้€šไฟก โ•‘');
30
+ console.log('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n');
31
+ const args = parseArgs();
32
+ // 1. ็”Ÿๆˆ DIAP ่บซไปฝ
33
+ console.log('[1/5] ็”Ÿๆˆ DIAP ่บซไปฝ...');
34
+ const keyManager = KeyManager.generate();
35
+ const did = keyManager.did;
36
+ const username = process.env.USER || process.env.USERNAME || 'user';
37
+ const agentName = `blln-${username.toLowerCase()}-${did.split(':').pop()?.substring(0, 4)}`;
38
+ console.log(` DID: ${did}`);
39
+ console.log(` ๅ็งฐ: ${agentName}`);
40
+ // 2. ๆณจๅ†Œๅˆฐ IPFS
41
+ console.log('\n[2/5] ๆณจๅ†Œ DID ๅˆฐ IPFS...');
42
+ let ipfsCid = null;
43
+ try {
44
+ const { AgentAuthManager } = await import('@diap/sdk');
45
+ const authManager = await AgentAuthManager.newWithRemoteIpfs(IPFS_API, IPFS_GATEWAY);
46
+ const result = await authManager.registerAgent({ name: agentName, services: [] }, keyManager, '');
47
+ ipfsCid = result.cid || null;
48
+ console.log(` โœ… IPFS CID: ${ipfsCid || 'ๆœช่Žทๅ–ๅˆฐ'}`);
49
+ }
50
+ catch (e) {
51
+ console.log(` โš ๏ธ IPFS ๆณจๅ†Œๅคฑ่ดฅ๏ผˆๆœฌๅœฐๆจกๅผ็ปง็ปญ๏ผ‰: ${e.message}`);
52
+ }
53
+ // 3. ๅˆ›ๅปบ P2P ้€šไฟกๅ™จ
54
+ console.log('\n[3/5] ๅˆๅง‹ๅŒ– P2P ็ฝ‘็ปœ...');
55
+ const rawSeed = crypto.getRandomValues(new Uint8Array(32));
56
+ const comm = createHyperswarmCommunicator({
57
+ server: true,
58
+ client: true,
59
+ autoConnect: true,
60
+ maxConnections: 10,
61
+ seed: rawSeed
62
+ });
63
+ const topic = createTopic('bolloon-judgment-test-v1');
64
+ await comm.joinTopic(topic);
65
+ console.log(` โœ… ๅทฒๅŠ ๅ…ฅไธป้ข˜: ${topic.slice(0, 8).toString('hex')}...`);
66
+ console.log(` ๐Ÿ“‹ ไฝ ็š„่Š‚็‚น ID: ${comm.publicKey?.substring(0, 16) || '็”Ÿๆˆไธญ...'}`);
67
+ // ๆถˆๆฏๅค„็†
68
+ const messageQueue = [];
69
+ let peerConnection = null;
70
+ comm.on('connection', (conn) => {
71
+ const shortKey = conn.publicKey.substring(0, 8);
72
+ console.log(`\n ๐Ÿ”Œ ๆ–ฐ่ฟžๆŽฅ: ${shortKey}...`);
73
+ if (!peerConnection) {
74
+ peerConnection = conn;
75
+ console.log(' โœ… ๅทฒๅปบ็ซ‹่ฟžๆŽฅ');
76
+ }
77
+ // ๅ‘้€ hello
78
+ const hello = {
79
+ type: 'hello',
80
+ from: agentName,
81
+ content: `ไฝ ๅฅฝ๏ผๆˆ‘ๆ˜ฏ ${agentName}`,
82
+ timestamp: Date.now()
83
+ };
84
+ sendMessage(conn, hello);
85
+ });
86
+ comm.on('message', (msg, conn) => {
87
+ const content = new TextDecoder().decode(msg.content);
88
+ try {
89
+ const data = JSON.parse(content);
90
+ handleMessage(data, conn);
91
+ }
92
+ catch {
93
+ console.log(`\n ๐Ÿ“ฉ ๆ”ถๅˆฐๅŽŸๅง‹ๆถˆๆฏ: ${content.substring(0, 100)}`);
94
+ }
95
+ });
96
+ // ่ฟžๆŽฅ่ฟœ็จ‹่Š‚็‚น
97
+ if (args.connectTo) {
98
+ console.log(`\n[4/5] ่ฟžๆŽฅๅˆฐ่ฟœ็จ‹่Š‚็‚น: ${args.connectTo}...`);
99
+ try {
100
+ await comm.joinPeer(args.connectTo);
101
+ console.log(' โœ… ่ฟžๆŽฅ่ฏทๆฑ‚ๅทฒๅ‘้€๏ผŒ็ญ‰ๅพ…ๅฏนๆ–นๅ“ๅบ”...');
102
+ }
103
+ catch (e) {
104
+ console.log(` โš ๏ธ ่ฟžๆŽฅๅคฑ่ดฅ: ${e.message}`);
105
+ }
106
+ }
107
+ else {
108
+ console.log('\n[4/5] ็ญ‰ๅพ…่ฟžๆŽฅ...');
109
+ }
110
+ // 5. ไบคไบ’็•Œ้ข
111
+ console.log('\n[5/5] P2P ไบคไบ’ๆจกๅผ');
112
+ console.log(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€');
113
+ console.log(' ่พ“ๅ…ฅๆถˆๆฏๅ‘้€ๅˆฐๅฏนๆ–น๏ผŒๆˆ–่พ“ๅ…ฅไปฅไธ‹ๅ‘ฝไปค:');
114
+ console.log(' /peers - ๆŸฅ็œ‹ๅทฒ่ฟžๆŽฅ่Š‚็‚น');
115
+ console.log(' /cid - ๆ˜พ็คบๆœฌๆœบ IPFS CID');
116
+ console.log(' /nodeid - ๆ˜พ็คบๆœฌๆœบ่Š‚็‚น ID');
117
+ console.log(' /quit - ้€€ๅ‡บ');
118
+ console.log(' โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n');
119
+ const rl = readline.createInterface({
120
+ input: process.stdin,
121
+ output: process.stdout
122
+ });
123
+ const prompt = () => {
124
+ rl.question(`[${agentName}] > `, async (input) => {
125
+ const trimmed = input.trim();
126
+ if (trimmed === '/quit') {
127
+ console.log('ๅ†่ง๏ผ');
128
+ rl.close();
129
+ process.exit(0);
130
+ }
131
+ else if (trimmed === '/peers') {
132
+ const connections = comm.connections;
133
+ if (connections) {
134
+ console.log(` ๅทฒ่ฟžๆŽฅ่Š‚็‚นๆ•ฐ: ${connections.size}`);
135
+ for (const [k, v] of connections) {
136
+ console.log(` - ${v.publicKey?.substring(0, 16) || k}...`);
137
+ }
138
+ }
139
+ else {
140
+ console.log(' ๆš‚ๆ— ่ฟžๆŽฅ');
141
+ }
142
+ prompt();
143
+ }
144
+ else if (trimmed === '/cid') {
145
+ console.log(` IPFS CID: ${ipfsCid || 'ๆœชๆณจๅ†Œ'}`);
146
+ prompt();
147
+ }
148
+ else if (trimmed === '/nodeid') {
149
+ const nodeId = comm.publicKey;
150
+ console.log(` ่Š‚็‚น ID: ${nodeId || '็”Ÿๆˆไธญ'}`);
151
+ prompt();
152
+ }
153
+ else if (trimmed) {
154
+ // ๅ‘้€ๆถˆๆฏ
155
+ if (peerConnection) {
156
+ const msg = {
157
+ type: 'message',
158
+ from: agentName,
159
+ content: trimmed,
160
+ timestamp: Date.now()
161
+ };
162
+ sendMessage(peerConnection, msg);
163
+ console.log(` โœ… ๆถˆๆฏๅทฒๅ‘้€`);
164
+ }
165
+ else {
166
+ console.log(' โš ๏ธ ๆš‚ๆ— ่ฟžๆŽฅ๏ผŒๆถˆๆฏๅทฒๅŠ ๅ…ฅ้˜Ÿๅˆ—');
167
+ messageQueue.push({
168
+ type: 'message',
169
+ from: agentName,
170
+ content: trimmed,
171
+ timestamp: Date.now()
172
+ });
173
+ }
174
+ prompt();
175
+ }
176
+ else {
177
+ prompt();
178
+ }
179
+ });
180
+ };
181
+ // ๅฎšๆœŸๆฃ€ๆŸฅ่ฟžๆŽฅ
182
+ setInterval(() => {
183
+ if (!peerConnection) {
184
+ const connections = comm.connections;
185
+ if (connections && connections.size > 0) {
186
+ for (const [k, v] of connections) {
187
+ const conn = v;
188
+ if (conn && conn.publicKey) {
189
+ peerConnection = conn;
190
+ console.log('\n ๐Ÿ”— ๆฃ€ๆต‹ๅˆฐๆ–ฐ่ฟžๆŽฅ๏ผ');
191
+ // ๅ‘้€้˜Ÿๅˆ—ไธญ็š„ๆถˆๆฏ
192
+ while (messageQueue.length > 0) {
193
+ const queued = messageQueue.shift();
194
+ sendMessage(peerConnection, queued);
195
+ }
196
+ break;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }, 2000);
202
+ prompt();
203
+ }
204
+ function sendMessage(conn, msg) {
205
+ const data = JSON.stringify(msg);
206
+ conn.send(new TextEncoder().encode(data));
207
+ }
208
+ function handleMessage(msg, conn) {
209
+ switch (msg.type) {
210
+ case 'hello':
211
+ console.log(`\n ๐Ÿ‘‹ ๆ”ถๅˆฐ้—ฎๅ€™: ${msg.content}`);
212
+ break;
213
+ case 'message':
214
+ console.log(`\n ๐Ÿ’ฌ ${msg.from}: ${msg.content}`);
215
+ // ่‡ชๅŠจๅ›žๅค
216
+ const response = {
217
+ type: 'response',
218
+ from: 'bot',
219
+ content: `[่‡ชๅŠจๅ›žๅค] ๆ”ถๅˆฐไฝ ็š„ๆถˆๆฏ: "${msg.content?.substring(0, 50)}..."`,
220
+ timestamp: Date.now()
221
+ };
222
+ sendMessage(conn, response);
223
+ break;
224
+ case 'response':
225
+ console.log(`\n ๐Ÿค– ${msg.from}: ${msg.content}`);
226
+ break;
227
+ case 'ping':
228
+ console.log(`\n ๐Ÿ“ ๆ”ถๅˆฐ Ping`);
229
+ sendMessage(conn, { type: 'pong', from: 'bot', timestamp: Date.now() });
230
+ break;
231
+ case 'pong':
232
+ console.log(`\n ๐Ÿ“ ๆ”ถๅˆฐ Pong`);
233
+ break;
234
+ default:
235
+ console.log(`\n ๐Ÿ“ฉ ๆ”ถๅˆฐๆถˆๆฏ: ${JSON.stringify(msg)}`);
236
+ }
237
+ }
238
+ main().catch(e => {
239
+ console.error('\nโŒ ้”™่ฏฏ:', e.message);
240
+ process.exit(1);
241
+ });