@bolloon/bolloon-agent 0.2.9 → 0.2.11

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,205 @@
1
+ /**
2
+ * Channel Agent Multi-Turn Dialogue Test
3
+ *
4
+ * 测试场景:
5
+ * 1. 两个 Channel Agent (Alice/Bob) 之间的多轮对话
6
+ * 2. 基于判断力的 Harness 调用 (Gate 1-8)
7
+ * 3. 上下文感知的 Gate 选择
8
+ * 4. Persona 设计能力
9
+ *
10
+ * 运行: npx tsx src/test/channel-agent-multi-dialogue.ts
11
+ */
12
+ import { config } from 'dotenv';
13
+ import { createChannelAgent, ChannelAgentRegistry } from '../social/channels/channel-agent-session.js';
14
+ config();
15
+ const PORT_ALICE = 8001;
16
+ const PORT_BOB = 8002;
17
+ async function testMultiTurnDialogue() {
18
+ console.log('\n========================================');
19
+ console.log(' Channel Agent 多轮对话测试');
20
+ console.log(' 场景: 完成一个用户认证系统的需求讨论');
21
+ console.log('========================================\n');
22
+ // 创建 Agent 注册表
23
+ const registry = new ChannelAgentRegistry();
24
+ // 创建 Alice
25
+ const alice = createChannelAgent({
26
+ name: 'Alice',
27
+ port: PORT_ALICE,
28
+ domain: '架构',
29
+ capabilities: ['架构设计', '代码审查', '任务分解']
30
+ });
31
+ // 创建 Bob
32
+ const bob = createChannelAgent({
33
+ name: 'Bob',
34
+ port: PORT_BOB,
35
+ domain: '开发',
36
+ capabilities: ['代码编写', '调试', '测试']
37
+ });
38
+ // 注册
39
+ registry.register(alice);
40
+ registry.register(bob);
41
+ // 设计 persona
42
+ alice.designPersona({
43
+ name: 'Alice',
44
+ type: 'developer',
45
+ domain: '架构',
46
+ tone: 'professional'
47
+ });
48
+ bob.designPersona({
49
+ name: 'Bob',
50
+ type: 'developer',
51
+ domain: '开发',
52
+ tone: 'technical'
53
+ });
54
+ // 启动
55
+ await alice.start();
56
+ await bob.start();
57
+ // 对话脚本
58
+ const script = [
59
+ // 第1轮 - 架构讨论
60
+ { from: 'Alice', to: 'Bob', content: 'Bob,我们需要设计一个新的用户认证系统。', expectHarness: false },
61
+ { from: 'Bob', to: 'Alice', content: '好的,具体需要哪些功能?', expectHarness: false },
62
+ // 第2轮 - 需求讨论
63
+ { from: 'Alice', to: 'Bob', content: '需要登录、注册、找回密码,还要支持社交登录。', expectHarness: false },
64
+ { from: 'Bob', to: 'Alice', content: '明白了。这个系统需要什么级别的安全性?', expectHarness: false },
65
+ // 第3轮 - 安全讨论 → Gate 4
66
+ { from: 'Alice', to: 'Bob', content: '需要处理金融数据,所以安全性很重要。请检查一下架构设计。', expectHarness: true, expectGate: 4 },
67
+ { from: 'Bob', to: 'Alice', content: '好的,我来分析一下架构设计,看看有没有安全风险。', expectHarness: true, expectGate: 1 },
68
+ // 第4轮 - 代码审查 → Gate 2
69
+ { from: 'Alice', to: 'Bob', content: '架构看起来不错。帮我 review 一下登录模块的实现。', expectHarness: true, expectGate: 2 },
70
+ { from: 'Bob', to: 'Alice', content: '好的,让我检查登录模块的代码实现。', expectHarness: true, expectGate: 2 },
71
+ // 第5轮 - 优化讨论
72
+ { from: 'Alice', to: 'Bob', content: '代码审查发现了一些问题,需要优化错误处理。', expectHarness: false },
73
+ { from: 'Bob', to: 'Alice', content: '同意,错误处理需要改进。', expectHarness: false },
74
+ // 第6轮 - 任务分解 → Gate 5
75
+ { from: 'Alice', to: 'Bob', content: '好的,现在我们来分解任务,制定开发计划。', expectHarness: true, expectGate: 5 },
76
+ { from: 'Bob', to: 'Alice', content: '我来帮你把任务分解成可执行的小块。', expectHarness: true, expectGate: 5 },
77
+ // 第7轮 - 开始实现
78
+ { from: 'Alice', to: 'Bob', content: '任务分解得很好。我们开始实现第一个任务吧。', expectHarness: false },
79
+ { from: 'Bob', to: 'Alice', content: '好的,开始实现登录模块。', expectHarness: false },
80
+ // 第8轮 - 代码实现 → Gate 7
81
+ { from: 'Alice', to: 'Bob', content: '实现完成,帮我优化一下代码质量。', expectHarness: true, expectGate: 7 },
82
+ { from: 'Bob', to: 'Alice', content: '好的,我来进行代码优化。', expectHarness: true, expectGate: 7 },
83
+ // 第9轮 - 测试验证 → Gate 8
84
+ { from: 'Alice', to: 'Bob', content: '代码优化完成,帮我验证一下质量。', expectHarness: true, expectGate: 8 },
85
+ { from: 'Bob', to: 'Alice', content: '好的,我来运行测试验证。', expectHarness: true, expectGate: 8 },
86
+ // 第10轮 - 完成
87
+ { from: 'Alice', to: 'Bob', content: '测试通过了!继续下一个任务。', expectHarness: false },
88
+ { from: 'Bob', to: 'Alice', content: '太好了!继续加油。', expectHarness: false },
89
+ ];
90
+ console.log('━━━ 开始多轮对话 ━━━\n');
91
+ let harnessCallCount = 0;
92
+ const gateStats = new Map();
93
+ for (let i = 0; i < script.length; i++) {
94
+ const { from, to, content, expectHarness, expectGate } = script[i];
95
+ const targetPort = from === 'Alice' ? PORT_BOB : PORT_ALICE;
96
+ console.log(`━━━ 第 ${Math.floor(i / 2) + 1} 轮 ━━━`);
97
+ console.log(`[${from}] >>> ${content}`);
98
+ try {
99
+ const resp = await fetch(`http://localhost:${targetPort}/receive`, {
100
+ method: 'POST',
101
+ headers: { 'Content-Type': 'application/json' },
102
+ body: JSON.stringify({ fromName: from, content })
103
+ });
104
+ const result = await resp.json();
105
+ console.log(`\n[${to}] 处理结果:`);
106
+ if (result.harnessCalled) {
107
+ console.log(` 🧠 调用 Harness: Gate ${result.gate}`);
108
+ console.log(` 📋 Skills: ${result.skills?.join(', ') || '无'}`);
109
+ harnessCallCount++;
110
+ gateStats.set(result.gate, (gateStats.get(result.gate) || 0) + 1);
111
+ if (expectHarness && result.gate !== expectGate) {
112
+ console.log(` ⚠️ 期望 Gate ${expectGate},实际 ${result.gate}`);
113
+ }
114
+ }
115
+ else {
116
+ console.log(` 🧠 普通对话 (无需 Harness)`);
117
+ }
118
+ console.log(` 📤 回复: ${result.response?.substring(0, 80)}...`);
119
+ // 等待一下再继续
120
+ await new Promise(r => setTimeout(r, 300));
121
+ }
122
+ catch (err) {
123
+ console.log(` ❌ 发送失败:`, err);
124
+ }
125
+ console.log('');
126
+ }
127
+ // 结果汇总
128
+ console.log('━━━ 结果汇总 ━━━\n');
129
+ console.log(`[Alice] 对话数: ${alice.getDialogHistory().length}`);
130
+ console.log(`[Bob] 对话数: ${bob.getDialogHistory().length}`);
131
+ console.log(`\nHarness 调用次数: ${harnessCallCount}`);
132
+ console.log('\nGate 统计:');
133
+ for (const [gate, count] of Array.from(gateStats.entries()).sort((a, b) => a[0] - b[0])) {
134
+ const gateNames = {
135
+ 1: '架构设计',
136
+ 2: '代码审查',
137
+ 4: '安全检查',
138
+ 5: '任务分解',
139
+ 7: '代码实现',
140
+ 8: '测试验证'
141
+ };
142
+ console.log(` Gate ${gate} (${gateNames[gate] || '未知'}): ${count} 次`);
143
+ }
144
+ // 健康检查
145
+ console.log('\n━━━ 最终状态 ━━━\n');
146
+ const aliceHealth = await fetch(`http://localhost:${PORT_ALICE}/health`).then(r => r.json());
147
+ const bobHealth = await fetch(`http://localhost:${PORT_BOB}/health`).then(r => r.json());
148
+ console.log(`[Alice] DID: ${aliceHealth.id.substring(0, 16)}...`);
149
+ console.log(`[Bob] DID: ${bobHealth.id.substring(0, 16)}...`);
150
+ console.log(`\n对话总数: ${aliceHealth.dialogCount + bobHealth.dialogCount}`);
151
+ console.log(`Harness 调用: ${harnessCallCount} 次`);
152
+ const success = harnessCallCount >= 6;
153
+ console.log(`\n${success ? '✅' : '⚠️'} ${success ? '测试成功' : '测试部分成功'}`);
154
+ // 清理
155
+ registry.clear();
156
+ console.log('\n========================================\n');
157
+ return success;
158
+ }
159
+ async function testPersonaDesign() {
160
+ console.log('\n========================================');
161
+ console.log(' Persona 设计测试');
162
+ console.log('========================================\n');
163
+ const agent = createChannelAgent({
164
+ name: 'TestAgent',
165
+ port: 8010,
166
+ domain: '通用'
167
+ });
168
+ await agent.start();
169
+ // 设计不同类型的 persona
170
+ const personaTypes = [
171
+ { name: 'ArchMaster', type: 'developer', domain: '架构', tone: 'professional' },
172
+ { name: 'CodeReviewer', type: 'reviewer', domain: '安全', tone: 'formal' },
173
+ { name: 'TaskManager', type: 'manager', domain: '项目管理', tone: 'professional' },
174
+ { name: 'CreativeDesigner', type: 'designer', domain: '设计', tone: 'casual' }
175
+ ];
176
+ console.log('━━━ 设计 Persona ━━━\n');
177
+ for (const request of personaTypes) {
178
+ const persona = agent.designPersona(request);
179
+ console.log(`设计 ${request.type} persona:`);
180
+ console.log(` 名称: ${persona.name}`);
181
+ console.log(` 描述: ${persona.description}`);
182
+ console.log(` 性格: ${persona.personality}`);
183
+ console.log(` 能力: ${persona.capabilities.join(', ')}`);
184
+ console.log(` 兴趣: ${persona.interests.join(', ')}`);
185
+ console.log('');
186
+ }
187
+ // 获取当前 persona
188
+ const currentPersona = agent.getPersona();
189
+ console.log('当前 Persona:');
190
+ console.log(JSON.stringify(currentPersona, null, 2));
191
+ agent.shutdown();
192
+ console.log('\n========================================\n');
193
+ }
194
+ async function main() {
195
+ try {
196
+ await testMultiTurnDialogue();
197
+ await testPersonaDesign();
198
+ process.exit(0);
199
+ }
200
+ catch (err) {
201
+ console.error('测试失败:', err);
202
+ process.exit(1);
203
+ }
204
+ }
205
+ main();
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Channel Heartbeat Agent Test
3
+ *
4
+ * 测试场景:
5
+ * 1. Heartbeat Agent 自动发现和解析 DiapDoc
6
+ * 2. 自动心跳发布 persona 到 IPFS
7
+ * 3. 基于判断力的 Harness 调用
8
+ * 4. 多智能体自动对话
9
+ *
10
+ * 运行: npx tsx src/test/channel-heartbeat-agent-test.ts
11
+ */
12
+ import { config } from 'dotenv';
13
+ import { createHeartbeatAgent, HeartbeatAgentRegistry } from '../social/channels/channel-heartbeat-agent.js';
14
+ import { createDiapDocParser } from '../social/channels/diap-doc-parser.js';
15
+ config();
16
+ const PORT_ALICE = 9001;
17
+ const PORT_BOB = 9002;
18
+ async function testDiapDocParser() {
19
+ console.log('\n========================================');
20
+ console.log(' DiapDoc Parser 测试');
21
+ console.log('========================================\n');
22
+ const parser = createDiapDocParser();
23
+ // 测试标准 DiapDoc
24
+ const standardDoc = {
25
+ id: 'did:key:z6MkhaXqE2qVYVJ5V5Z7Z8Z9Z0Z1Z2Z3Z4Z5Z6Z7Z8Z9Z0Z',
26
+ name: 'TestAgent',
27
+ version: '1.0',
28
+ capabilities: ['对话', '分析', '协作'],
29
+ interests: ['AI', '编程'],
30
+ peerId: 'QmTestPeer123',
31
+ channels: [
32
+ { id: 'ch_001', name: 'AI Discussion', topic: 'AI技术讨论' },
33
+ { id: 'ch_002', name: 'Coding Help', topic: '编程帮助' }
34
+ ]
35
+ };
36
+ const result = parser.parse(JSON.stringify(standardDoc));
37
+ if (result.success && result.doc) {
38
+ console.log('✅ 解析成功');
39
+ console.log(` ID: ${result.doc.id}`);
40
+ console.log(` Name: ${result.doc.name}`);
41
+ console.log(` Capabilities: ${result.doc.capabilities.join(', ')}`);
42
+ console.log(` Channels: ${result.doc.channels?.map(c => c.name).join(', ')}`);
43
+ }
44
+ else {
45
+ console.log('❌ 解析失败:', result.error);
46
+ }
47
+ // 测试兼容性格式
48
+ const compatDoc = {
49
+ did: 'did:key:zCompatibleDoc',
50
+ name: 'CompatibleAgent',
51
+ capability: ['代码审查', '架构设计'],
52
+ interest: ['软件开发'],
53
+ peer_id: 'QmCompatPeer',
54
+ channel: [
55
+ { channelId: 'ch_comp_001', channelName: 'Dev Chat' }
56
+ ]
57
+ };
58
+ const compatResult = parser.parse(JSON.stringify(compatDoc));
59
+ if (compatResult.success && compatResult.doc) {
60
+ console.log('\n✅ 兼容性格式解析成功');
61
+ console.log(` ID: ${compatResult.doc.id}`);
62
+ console.log(` Capabilities: ${compatResult.doc.capabilities.join(', ')}`);
63
+ }
64
+ else {
65
+ console.log('\n❌ 兼容性解析失败:', compatResult.error);
66
+ }
67
+ console.log('\n========================================\n');
68
+ }
69
+ async function testHeartbeatAgent() {
70
+ console.log('\n========================================');
71
+ console.log(' Heartbeat Agent 测试');
72
+ console.log('========================================\n');
73
+ const registry = new HeartbeatAgentRegistry();
74
+ // 创建 Alice
75
+ const alice = createHeartbeatAgent({
76
+ name: 'Alice',
77
+ port: PORT_ALICE,
78
+ autoDiscovery: true,
79
+ autoDialogue: false,
80
+ capabilities: ['架构设计', '代码审查']
81
+ });
82
+ // 创建 Bob
83
+ const bob = createHeartbeatAgent({
84
+ name: 'Bob',
85
+ port: PORT_BOB,
86
+ autoDiscovery: true,
87
+ autoDialogue: false,
88
+ capabilities: ['代码编写', '调试']
89
+ });
90
+ // 注册
91
+ registry.register(alice);
92
+ registry.register(bob);
93
+ // 启动
94
+ await alice.start();
95
+ await bob.start();
96
+ console.log('━━━ 模拟发现流程 ━━━\n');
97
+ // 模拟 Alice 发现 Bob
98
+ const announcement = {
99
+ leaderDid: bob.getDid(),
100
+ channelName: 'Bob 的频道',
101
+ channelId: 'ch_bob_001',
102
+ topic: '开发协作',
103
+ capabilities: ['代码编写', '调试'],
104
+ interests: ['编程', '架构']
105
+ };
106
+ alice.handleChannelAnnouncement(announcement);
107
+ console.log(`[Alice] 发现 Bob,存储到已发现列表`);
108
+ // 获取 Bob 的信息
109
+ const alicePeers = alice.getDiscoveredPeers();
110
+ console.log(`\n[Alice] 已发现 ${alicePeers.length} 个对等节点:`);
111
+ for (const peer of alicePeers) {
112
+ console.log(` - ${peer.name} (${peer.did.substring(0, 20)}...)`);
113
+ console.log(` Capabilities: ${peer.capabilities.join(', ')}`);
114
+ }
115
+ // 测试对话
116
+ console.log('\n━━━ 对话测试 ━━━\n');
117
+ const dialogueScript = [
118
+ { from: 'Alice', to: 'Bob', content: 'Bob,我们设计一个新的用户认证系统。' },
119
+ { from: 'Bob', to: 'Alice', content: '好的,需要哪些功能?' },
120
+ { from: 'Alice', to: 'Bob', content: '登录、注册、找回密码,还要支持社交登录。' },
121
+ { from: 'Bob', to: 'Alice', content: '明白了。安全性要求高吗?' },
122
+ { from: 'Alice', to: 'Bob', content: '需要处理金融数据,安全很重要。帮我分析一下架构设计。' },
123
+ { from: 'Bob', to: 'Alice', content: '好的,我来检查架构设计。' },
124
+ { from: 'Alice', to: 'Bob', content: '架构不错。帮我 review 代码。' },
125
+ { from: 'Bob', to: 'Alice', content: '代码审查完成,需要优化错误处理。' },
126
+ { from: 'Alice', to: 'Bob', content: '好的,现在分解任务。' },
127
+ { from: 'Bob', to: 'Alice', content: '任务已分解为 4 个子任务。' }
128
+ ];
129
+ let harnessCallCount = 0;
130
+ const gateStats = new Map();
131
+ for (let i = 0; i < dialogueScript.length; i++) {
132
+ const { from, to, content } = dialogueScript[i];
133
+ const targetAgent = from === 'Alice' ? bob : alice;
134
+ console.log(`[${from}] >>> ${content}`);
135
+ const result = await targetAgent.handleMessage(from === 'Alice' ? alice.getDid() : bob.getDid(), from, content);
136
+ console.log(`[${to}] 处理结果:`);
137
+ if (result.harnessCalled) {
138
+ console.log(` 🧠 调用 Harness: Gate ${result.gate}`);
139
+ harnessCallCount++;
140
+ gateStats.set(result.gate, (gateStats.get(result.gate) || 0) + 1);
141
+ }
142
+ else {
143
+ console.log(` 🧠 普通回复`);
144
+ }
145
+ console.log(` 📤 ${result.response.substring(0, 60)}...`);
146
+ console.log('');
147
+ await new Promise(r => setTimeout(r, 200));
148
+ }
149
+ // 结果汇总
150
+ console.log('━━━ 结果汇总 ━━━\n');
151
+ console.log(`Harness 调用次数: ${harnessCallCount}`);
152
+ console.log('\nGate 统计:');
153
+ for (const [gate, count] of Array.from(gateStats.entries()).sort((a, b) => a[0] - b[0])) {
154
+ const gateNames = {
155
+ 1: '架构设计', 2: '代码审查', 4: '安全检查',
156
+ 5: '任务分解', 7: '代码实现', 8: '测试验证'
157
+ };
158
+ console.log(` Gate ${gate} (${gateNames[gate] || '未知'}): ${count} 次`);
159
+ }
160
+ const success = harnessCallCount >= 3;
161
+ console.log(`\n${success ? '✅' : '⚠️'} ${success ? '测试成功' : '测试部分成功'}`);
162
+ // 清理
163
+ registry.clear();
164
+ console.log('\n========================================\n');
165
+ return success;
166
+ }
167
+ async function testAutoHeartbeat() {
168
+ console.log('\n========================================');
169
+ console.log(' 自动心跳测试');
170
+ console.log('========================================\n');
171
+ const agent = createHeartbeatAgent({
172
+ name: 'AutoHeartbeatTest',
173
+ port: 9010,
174
+ autoDiscovery: true,
175
+ autoDialogue: false
176
+ });
177
+ await agent.start();
178
+ console.log(`[${agent.getName()}] 已启动`);
179
+ console.log(` DID: ${agent.getDid()}`);
180
+ console.log(` CID: ${agent.getOwnCID() || 'N/A'}`);
181
+ // 等待几个心跳周期
182
+ console.log('\n等待自动心跳...');
183
+ await new Promise(r => setTimeout(r, 5000));
184
+ const peers = agent.getDiscoveredPeers();
185
+ console.log(`\n发现的对等节点: ${peers.length}`);
186
+ agent.stop();
187
+ console.log('\n========================================\n');
188
+ }
189
+ async function main() {
190
+ try {
191
+ await testDiapDocParser();
192
+ await testHeartbeatAgent();
193
+ await testAutoHeartbeat();
194
+ process.exit(0);
195
+ }
196
+ catch (err) {
197
+ console.error('测试失败:', err);
198
+ process.exit(1);
199
+ }
200
+ }
201
+ main();
@@ -0,0 +1,164 @@
1
+ /**
2
+ * ConstraintLayer Tests
3
+ */
4
+ import { describe, it, expect, beforeEach } from 'vitest';
5
+ import { ConstraintLayer, AUTONOMOUS_ACTIONS, CONFIRM_REQUIRED_ACTIONS } from '../agents/constraint-layer.js';
6
+ describe('ConstraintLayer', () => {
7
+ let layer;
8
+ beforeEach(() => {
9
+ layer = new ConstraintLayer();
10
+ });
11
+ describe('checkGuardrails', () => {
12
+ it('should pass when no guardrails fail', async () => {
13
+ const context = {
14
+ peers: ['peer1', 'peer2'],
15
+ logs: []
16
+ };
17
+ const result = await layer.checkGuardrails(context);
18
+ expect(result.passed).toBe(true);
19
+ expect(result.blocked).toBeUndefined();
20
+ });
21
+ it('should block send to unknown peer', async () => {
22
+ const context = {
23
+ peers: ['peer1', 'peer2'],
24
+ logs: []
25
+ };
26
+ const step = {
27
+ id: 'send',
28
+ type: 'send',
29
+ config: { peerId: 'unknown-peer' },
30
+ retry: { max: 0, current: 0, backoffMs: 0 },
31
+ onFail: 'block'
32
+ };
33
+ const result = await layer.checkGuardrails(context, step);
34
+ expect(result.passed).toBe(false);
35
+ expect(result.blocked?.name).toBe('validateSendTarget');
36
+ });
37
+ it('should allow send to known peer', async () => {
38
+ const context = {
39
+ peers: ['peer1', 'peer2'],
40
+ logs: []
41
+ };
42
+ const step = {
43
+ id: 'send',
44
+ type: 'send',
45
+ config: { peerId: 'peer1' },
46
+ retry: { max: 0, current: 0, backoffMs: 0 },
47
+ onFail: 'block'
48
+ };
49
+ const result = await layer.checkGuardrails(context, step);
50
+ expect(result.passed).toBe(true);
51
+ });
52
+ it('should warn for low quality summary', async () => {
53
+ const context = {
54
+ peers: [],
55
+ logs: [],
56
+ qualityScore: 0.3
57
+ };
58
+ const result = await layer.checkGuardrails(context);
59
+ expect(result.passed).toBe(false);
60
+ expect(result.blocked?.name).toBe('validateSummaryQuality');
61
+ });
62
+ it('should pass for acceptable quality summary', async () => {
63
+ const context = {
64
+ peers: [],
65
+ logs: [],
66
+ qualityScore: 0.7
67
+ };
68
+ const result = await layer.checkGuardrails(context);
69
+ expect(result.passed).toBe(true);
70
+ });
71
+ });
72
+ describe('isAutonomousAction', () => {
73
+ it('should identify autonomous actions', () => {
74
+ expect(layer.isAutonomousAction('summarize')).toBe(true);
75
+ expect(layer.isAutonomousAction('chunk')).toBe(true);
76
+ expect(layer.isAutonomousAction('improve')).toBe(true);
77
+ });
78
+ it('should return false for non-autonomous actions', () => {
79
+ expect(layer.isAutonomousAction('send')).toBe(false);
80
+ expect(layer.isAutonomousAction('delete')).toBe(false);
81
+ });
82
+ });
83
+ describe('requiresConfirmation', () => {
84
+ it('should identify confirmation-required actions', () => {
85
+ expect(layer.requiresConfirmation('send')).toBe(true);
86
+ expect(layer.requiresConfirmation('delete')).toBe(true);
87
+ });
88
+ it('should return false for non-confirmation-required actions', () => {
89
+ expect(layer.requiresConfirmation('summarize')).toBe(false);
90
+ expect(layer.requiresConfirmation('chunk')).toBe(false);
91
+ });
92
+ });
93
+ describe('logging', () => {
94
+ it('should record operations', () => {
95
+ layer.log('test action', { key: 'value' }, 'success');
96
+ const logs = layer.getLogs();
97
+ expect(logs).toHaveLength(1);
98
+ expect(logs[0].action).toBe('test action');
99
+ expect(logs[0].status).toBe('success');
100
+ expect(logs[0].details).toEqual({ key: 'value' });
101
+ });
102
+ it('should record multiple operations', () => {
103
+ layer.log('action1', {}, 'success');
104
+ layer.log('action2', { data: 123 }, 'warn');
105
+ const logs = layer.getLogs();
106
+ expect(logs).toHaveLength(2);
107
+ });
108
+ it('should clear logs', () => {
109
+ layer.log('action1', {}, 'success');
110
+ layer.log('action2', {}, 'failed');
111
+ layer.clearLogs();
112
+ const logs = layer.getLogs();
113
+ expect(logs).toHaveLength(0);
114
+ });
115
+ it('should track timestamp for logs', () => {
116
+ const before = Date.now();
117
+ layer.log('test', {}, 'success');
118
+ const after = Date.now();
119
+ const logs = layer.getLogs();
120
+ expect(logs[0].timestamp).toBeGreaterThanOrEqual(before);
121
+ expect(logs[0].timestamp).toBeLessThanOrEqual(after);
122
+ });
123
+ });
124
+ describe('registerRule', () => {
125
+ it('should register new rules', () => {
126
+ const rule = {
127
+ id: 'custom-rule',
128
+ description: 'Custom rule',
129
+ guardrails: [{
130
+ name: 'customGuard',
131
+ check: async () => true
132
+ }]
133
+ };
134
+ layer.registerRule(rule);
135
+ expect(layer.getRuleIds()).toContain('custom-rule');
136
+ });
137
+ it('should unregister rules', () => {
138
+ const rule = {
139
+ id: 'temp-rule',
140
+ description: 'Temporary rule',
141
+ guardrails: [{
142
+ name: 'tempGuard',
143
+ check: async () => true
144
+ }]
145
+ };
146
+ layer.registerRule(rule);
147
+ expect(layer.unregisterRule('temp-rule')).toBe(true);
148
+ expect(layer.getRuleIds()).not.toContain('temp-rule');
149
+ });
150
+ });
151
+ describe('AUTONOMOUS_ACTIONS constant', () => {
152
+ it('should contain expected actions', () => {
153
+ expect(AUTONOMOUS_ACTIONS).toContain('summarize');
154
+ expect(AUTONOMOUS_ACTIONS).toContain('chunk');
155
+ expect(AUTONOMOUS_ACTIONS).toContain('improve');
156
+ });
157
+ });
158
+ describe('CONFIRM_REQUIRED_ACTIONS constant', () => {
159
+ it('should contain expected actions', () => {
160
+ expect(CONFIRM_REQUIRED_ACTIONS).toContain('send');
161
+ expect(CONFIRM_REQUIRED_ACTIONS).toContain('delete');
162
+ });
163
+ });
164
+ });