@bolloon/bolloon-agent 0.4.5 → 0.4.7

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 (208) hide show
  1. package/README.md +135 -135
  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/constraint-layer.js +19 -19
  6. package/dist/agents/judgment-protocol.js +14 -14
  7. package/dist/agents/pi-sdk-tools.js +128 -46
  8. package/dist/agents/pi-sdk-types.js +12 -12
  9. package/dist/agents/pi-sdk.js +103 -90
  10. package/dist/agents/process-runner.js +105 -0
  11. package/dist/agents/skill-organizer.js +19 -19
  12. package/dist/agents/skill-writer.js +15 -3
  13. package/dist/agents/workflow-pivot-loop.js +13 -3
  14. package/dist/agents/write-staging.js +85 -0
  15. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  16. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  17. package/dist/bollharness-integration/context-router.js +292 -292
  18. package/dist/bollharness-integration/gate-state-machine.js +13 -13
  19. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  20. package/dist/bollharness-integration/skill-adapter.js +21 -21
  21. package/dist/bootstrap/chat-archiver.js +14 -14
  22. package/dist/bootstrap/context-os.js +24 -24
  23. package/dist/bootstrap/memory-compressor.js +14 -14
  24. package/dist/cli/ink-app.js +18 -0
  25. package/dist/cli-entry.js +36 -36
  26. package/dist/context-compaction/auto-compact.js +7 -7
  27. package/dist/electron/first-run.js +54 -54
  28. package/dist/electron-build/electron/first-run.js +54 -54
  29. package/dist/electron-preload.js.map +1 -1
  30. package/dist/electron.js.map +1 -1
  31. package/dist/index.js +230 -137
  32. package/dist/llm/llm-judgment-client.js +102 -102
  33. package/dist/llm/pi-ai.js +48 -48
  34. package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
  35. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  36. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  37. package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
  38. package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
  39. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  40. package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
  41. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  42. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  43. package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
  44. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  45. package/dist/llm/system-prompt/layers/core/identity.md +48 -48
  46. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  47. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  48. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  49. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  50. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  51. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  52. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  53. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  54. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  55. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  56. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  57. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  58. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  59. package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
  60. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  61. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  62. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  63. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  64. package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
  65. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  66. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  67. package/dist/llm/tool-manifest/bash.js +3 -3
  68. package/dist/llm/tool-manifest/create_file.js +4 -4
  69. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  70. package/dist/llm/tool-manifest/image_search.js +2 -2
  71. package/dist/llm/tool-manifest/index.js +0 -59
  72. package/dist/llm/tool-manifest/mcp.js +2 -2
  73. package/dist/llm/tool-manifest/message_compose.js +3 -3
  74. package/dist/llm/tool-manifest/places.js +2 -2
  75. package/dist/llm/tool-manifest/present_files.js +1 -1
  76. package/dist/llm/tool-manifest/recipe.js +2 -2
  77. package/dist/llm/tool-manifest/str_replace.js +5 -5
  78. package/dist/llm/tool-manifest/view.js +3 -3
  79. package/dist/llm/tool-manifest/weather.js +4 -4
  80. package/dist/llm/tool-manifest/web.js +4 -4
  81. package/dist/orbitdb/agent-tools.js +139 -0
  82. package/dist/orbitdb/kanban-store.js +259 -0
  83. package/dist/orbitdb/task-store.js +112 -0
  84. package/dist/pi-ecosystem-colony/index.js +365 -0
  85. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  86. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  87. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  88. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  89. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  90. package/dist/security/context-router-tool.js +15 -15
  91. package/dist/security/tool-gate.js +2 -0
  92. package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
  93. package/dist/social/ant-colony/PheromoneEngine.js +227 -0
  94. package/dist/social/ant-colony/index.js +6 -0
  95. package/dist/social/ant-colony/types.js +24 -0
  96. package/dist/storage/trajectory.js +101 -0
  97. package/dist/test/ai-judgment-test.js +80 -0
  98. package/dist/test/bollharness-integration.test.js +318 -0
  99. package/dist/test/channel-agent-multi-dialogue.js +205 -0
  100. package/dist/test/channel-heartbeat-agent-test.js +201 -0
  101. package/dist/test/constraint-layer.test.js +164 -0
  102. package/dist/test/diap-identity-test.js +172 -0
  103. package/dist/test/diap-quick-test.js +62 -0
  104. package/dist/test/global-shared-context.test.js +315 -0
  105. package/dist/test/harness-judgment-injection.test.js +246 -0
  106. package/dist/test/harness-workflow-integrator-test.js +228 -0
  107. package/dist/test/human-value-store.test.js +243 -0
  108. package/dist/test/hybrid-integration-test.js +118 -0
  109. package/dist/test/hybrid-messenger-verify.js +55 -0
  110. package/dist/test/iroh-bistream-debug.js +38 -0
  111. package/dist/test/iroh-communication.test.js +66 -0
  112. package/dist/test/iroh-debug-test.js +57 -0
  113. package/dist/test/iroh-diap-test.js +71 -0
  114. package/dist/test/iroh-direct-connect.js +55 -0
  115. package/dist/test/iroh-e2e-fixed.js +89 -0
  116. package/dist/test/iroh-e2e-same-process.js +63 -0
  117. package/dist/test/iroh-e2e.js +66 -0
  118. package/dist/test/iroh-final-e2e.js +72 -0
  119. package/dist/test/iroh-relay-test.js +37 -0
  120. package/dist/test/iroh-simple-test.js +41 -0
  121. package/dist/test/iroh-transport-verify.js +54 -0
  122. package/dist/test/iroh-transport.test.js +37 -0
  123. package/dist/test/iroh-two-nodes.js +70 -0
  124. package/dist/test/iroh-verify.js +44 -0
  125. package/dist/test/judgment-decision.test.js +219 -0
  126. package/dist/test/llm-judgment-integration.test.js +220 -0
  127. package/dist/test/p2p-agent-complex-dialogue.js +385 -0
  128. package/dist/test/p2p-agent-dialogue.js +341 -0
  129. package/dist/test/p2p-agent-full-bidirectional.js +510 -0
  130. package/dist/test/p2p-agent-harness-flow.js +437 -0
  131. package/dist/test/p2p-agent-harness-single.js +143 -0
  132. package/dist/test/p2p-ai-dialogue-test.js +318 -0
  133. package/dist/test/p2p-cid-connect-test.js +195 -0
  134. package/dist/test/p2p-connect-receiver.js +69 -0
  135. package/dist/test/p2p-doc-transfer.js +110 -0
  136. package/dist/test/p2p-identity-page-test.js +77 -0
  137. package/dist/test/p2p-iroh-test.js +171 -0
  138. package/dist/test/p2p-minimal-test.js +241 -0
  139. package/dist/test/p2p-node-1.js +148 -0
  140. package/dist/test/p2p-node-2.js +148 -0
  141. package/dist/test/p2p-server.js +281 -0
  142. package/dist/test/p2p-two-nodes-test.js +438 -0
  143. package/dist/test/pi-sdk.test.js +44 -0
  144. package/dist/test/set-persona.js +40 -0
  145. package/dist/test/simple.test.js +9 -0
  146. package/dist/test/storage-integration.test.js +150 -0
  147. package/dist/test/subagent-manager.test.js +276 -0
  148. package/dist/test/test-gate-flow.test.js +81 -0
  149. package/dist/test/workflow-engine.test.js +87 -0
  150. package/dist/test/workflow-pivot-loop.test.js +246 -0
  151. package/dist/web/api-config.html +779 -779
  152. package/dist/web/client-hearth.js +10 -10
  153. package/dist/web/components/wallet-viem.mjs +118 -118
  154. package/dist/web/index.html +472 -472
  155. package/dist/web/manifest.json +20 -20
  156. package/dist/web/server-storage.js +29 -0
  157. package/dist/web/server.js +30 -14
  158. package/dist/web/style.css +4946 -4946
  159. package/package.json +195 -195
  160. package/scripts/build-cli.js +215 -215
  161. package/scripts/build-web.ts +130 -130
  162. package/scripts/postinstall.js +152 -152
  163. package/bin/bolloon-daemon.sh +0 -207
  164. package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +0 -63
  165. package/dist/constraint-runtime/reference_data/commands_snapshot.json +0 -1037
  166. package/dist/constraint-runtime/reference_data/subsystems/assistant.json +0 -8
  167. package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +0 -8
  168. package/dist/constraint-runtime/reference_data/subsystems/bridge.json +0 -32
  169. package/dist/constraint-runtime/reference_data/subsystems/buddy.json +0 -13
  170. package/dist/constraint-runtime/reference_data/subsystems/cli.json +0 -26
  171. package/dist/constraint-runtime/reference_data/subsystems/components.json +0 -32
  172. package/dist/constraint-runtime/reference_data/subsystems/constants.json +0 -28
  173. package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +0 -8
  174. package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +0 -15
  175. package/dist/constraint-runtime/reference_data/subsystems/hooks.json +0 -32
  176. package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +0 -21
  177. package/dist/constraint-runtime/reference_data/subsystems/memdir.json +0 -15
  178. package/dist/constraint-runtime/reference_data/subsystems/migrations.json +0 -18
  179. package/dist/constraint-runtime/reference_data/subsystems/moreright.json +0 -8
  180. package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +0 -11
  181. package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +0 -8
  182. package/dist/constraint-runtime/reference_data/subsystems/plugins.json +0 -9
  183. package/dist/constraint-runtime/reference_data/subsystems/remote.json +0 -11
  184. package/dist/constraint-runtime/reference_data/subsystems/schemas.json +0 -8
  185. package/dist/constraint-runtime/reference_data/subsystems/screens.json +0 -10
  186. package/dist/constraint-runtime/reference_data/subsystems/server.json +0 -10
  187. package/dist/constraint-runtime/reference_data/subsystems/services.json +0 -32
  188. package/dist/constraint-runtime/reference_data/subsystems/skills.json +0 -27
  189. package/dist/constraint-runtime/reference_data/subsystems/state.json +0 -13
  190. package/dist/constraint-runtime/reference_data/subsystems/types.json +0 -18
  191. package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +0 -9
  192. package/dist/constraint-runtime/reference_data/subsystems/utils.json +0 -32
  193. package/dist/constraint-runtime/reference_data/subsystems/vim.json +0 -12
  194. package/dist/constraint-runtime/reference_data/subsystems/voice.json +0 -8
  195. package/dist/constraint-runtime/reference_data/tools_snapshot.json +0 -922
  196. package/dist/electron/config.js.map +0 -1
  197. package/dist/electron/dialogs.js.map +0 -1
  198. package/dist/electron/first-run.js.map +0 -1
  199. package/dist/electron/ipc.js.map +0 -1
  200. package/dist/electron/logger.js.map +0 -1
  201. package/dist/electron/main.js.map +0 -1
  202. package/dist/electron/menu.js.map +0 -1
  203. package/dist/electron/paths.js.map +0 -1
  204. package/dist/electron/server.js.map +0 -1
  205. package/dist/electron/tray.js.map +0 -1
  206. package/dist/electron/window.js.map +0 -1
  207. package/dist/utils/auto-update.js.map +0 -1
  208. package/dist/web/client.js.map +0 -7
@@ -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
+ });
@@ -0,0 +1,172 @@
1
+ /**
2
+ * DIAP Identity Test - 测试 DIAP 身份生成和 DID 注册
3
+ *
4
+ * 测试内容:
5
+ * 1. 生成 DIAP 身份 (KeyManager)
6
+ * 2. 创建 DID 文档
7
+ * 3. 模拟发布到 IPFS(不依赖真实 IPFS)
8
+ * 4. 模拟从 IPFS 解析 DID 文档
9
+ *
10
+ * 运行: npx tsx src/test/diap-identity-test.ts
11
+ */
12
+ import { KeyManager } from '@diap/sdk';
13
+ async function main() {
14
+ console.log('\n╔═══════════════════════════════════════════════════════╗');
15
+ console.log('║ DIAP Identity Test - 身份生成与 DID 注册 ║');
16
+ console.log('╚═══════════════════════════════════════════════════════╝\n');
17
+ // ============================================================
18
+ // 测试 1: 生成 DIAP 身份
19
+ // ============================================================
20
+ console.log('[Test 1/4] 生成 DIAP 身份...');
21
+ console.log('─'.repeat(50));
22
+ const keyManager = KeyManager.generate();
23
+ const did = keyManager.did;
24
+ const publicKeyHex = Buffer.from(keyManager.publicKey).toString('hex');
25
+ console.log(` ✅ DID 生成成功`);
26
+ console.log(` DID: ${did}`);
27
+ console.log(` 公钥: ${publicKeyHex.substring(0, 32)}...`);
28
+ // 提取用户名
29
+ const username = process.env.USER || process.env.USERNAME || 'mechrevo';
30
+ const didSuffix = did.split(':').pop() || '';
31
+ const shortSuffix = didSuffix.substring(0, Math.min(4, didSuffix.length));
32
+ const agentName = `blln-${username.toLowerCase()}-${shortSuffix}`;
33
+ console.log(` 名称: ${agentName}`);
34
+ // ============================================================
35
+ // 测试 2: 创建 DID 文档
36
+ // ============================================================
37
+ console.log('\n[Test 2/4] 创建 DID 文档...');
38
+ console.log('─'.repeat(50));
39
+ const diapDoc = {
40
+ id: did,
41
+ name: agentName,
42
+ version: '1.0',
43
+ capabilities: ['chat', 'reasoning', 'judgment-injection', 'harness-workflow'],
44
+ interests: ['ai', 'p2p', 'judgment-system'],
45
+ publicKey: publicKeyHex,
46
+ channels: [
47
+ { id: `ch_${Date.now()}`, name: '主对话' }
48
+ ],
49
+ createdAt: new Date().toISOString(),
50
+ updatedAt: new Date().toISOString()
51
+ };
52
+ const docJson = JSON.stringify(diapDoc, null, 2);
53
+ console.log(` ✅ DID 文档创建成功`);
54
+ console.log(` 文档大小: ${docJson.length} 字节`);
55
+ console.log(` 能力列表: ${diapDoc.capabilities.join(', ')}`);
56
+ console.log(` 兴趣领域: ${diapDoc.interests.join(', ')}`);
57
+ // ============================================================
58
+ // 测试 3: 模拟发布到 IPFS
59
+ // ============================================================
60
+ console.log('\n[Test 3/4] 模拟发布到 IPFS...');
61
+ console.log('─'.repeat(50));
62
+ // 模拟 IPFS CID 生成(使用 DID 的哈希)
63
+ const crypto = await import('crypto');
64
+ const docHash = crypto.createHash('sha256').update(docJson).digest('base64url');
65
+ const simulatedCid = `baf${docHash.substring(0, 50)}`;
66
+ console.log(` ✅ 模拟 IPFS 发布成功`);
67
+ console.log(` 模拟 CID: ${simulatedCid}`);
68
+ // 测试 AgentAuthManager(需要真实 IPFS)
69
+ console.log('\n 📡 尝试连接真实 IPFS...');
70
+ try {
71
+ const { AgentAuthManager } = await import('@diap/sdk');
72
+ const authManager = await AgentAuthManager.newWithRemoteIpfs('http://127.0.0.1:5001', 'http://127.0.0.1:8080');
73
+ const result = await authManager.registerAgent({ name: agentName, services: [] }, keyManager, '');
74
+ console.log(` ✅ 真实 IPFS 注册成功`);
75
+ console.log(` CID: ${result.cid || 'N/A'}`);
76
+ console.log(` IPNS: ${result.ipnsName || 'N/A'}`);
77
+ return {
78
+ did,
79
+ agentName,
80
+ publicKey: publicKeyHex,
81
+ diapDoc,
82
+ cid: result.cid || simulatedCid,
83
+ ipnsName: result.ipnsName
84
+ };
85
+ }
86
+ catch (e) {
87
+ const error = e;
88
+ console.log(` ⚠️ 真实 IPFS 不可用: ${error.message}`);
89
+ console.log(' 将使用模拟数据继续测试');
90
+ return {
91
+ did,
92
+ agentName,
93
+ publicKey: publicKeyHex,
94
+ diapDoc,
95
+ cid: simulatedCid,
96
+ ipnsName: null
97
+ };
98
+ }
99
+ }
100
+ async function testParseDID(doc, cid) {
101
+ // ============================================================
102
+ // 测试 4: 解析 DID 文档
103
+ // ============================================================
104
+ console.log('\n[Test 4/4] 解析 DID 文档...');
105
+ console.log('─'.repeat(50));
106
+ // 从 IPFS 获取内容
107
+ console.log(' 📡 从 IPFS 解析...');
108
+ // 方式1: 使用 IpfsClient
109
+ try {
110
+ const { IpfsClient } = await import('@diap/sdk');
111
+ const ipfs = new IpfsClient('http://127.0.0.1:5001', null);
112
+ console.log(` 尝试从 CID ${cid} 获取...`);
113
+ const content = await ipfs.get(cid);
114
+ const parsedDoc = JSON.parse(content);
115
+ console.log(` ✅ IpfsClient 解析成功`);
116
+ console.log(` DID: ${parsedDoc.id}`);
117
+ console.log(` 创建时间: ${parsedDoc.created}`);
118
+ return;
119
+ }
120
+ catch (e) {
121
+ console.log(` ⚠️ IpfsClient 解析失败: ${e.message}`);
122
+ }
123
+ // 方式2: 直接使用 fetch
124
+ console.log(' 📡 尝试直接使用 fetch...');
125
+ try {
126
+ const response = await fetch(`http://127.0.0.1:5001/api/v0/cat?arg=${cid}`, {
127
+ method: 'POST'
128
+ });
129
+ const text = await response.text();
130
+ const parsedDoc = JSON.parse(text);
131
+ console.log(` ✅ 直接 fetch 解析成功`);
132
+ console.log(` DID: ${parsedDoc.id}`);
133
+ console.log(` 验证方法数: ${parsedDoc.verificationMethod?.length || 0}`);
134
+ if (parsedDoc.service) {
135
+ console.log(` 服务端点数: ${parsedDoc.service.length}`);
136
+ }
137
+ return;
138
+ }
139
+ catch (e) {
140
+ console.log(` ⚠️ 直接 fetch 解析失败: ${e.message}`);
141
+ }
142
+ // 方式3: 使用本地文档模拟
143
+ console.log(` ⚠️ 使用本地文档模拟解析结果`);
144
+ console.log(` ✅ 本地解析成功`);
145
+ console.log(` DID: ${doc.id}`);
146
+ console.log(` 名称: ${doc.name}`);
147
+ console.log(` 公钥: ${doc.publicKey.substring(0, 32)}...`);
148
+ console.log(` 能力: ${doc.capabilities.join(', ')}`);
149
+ console.log(` 频道: ${doc.channels?.map(c => c.name).join(', ')}`);
150
+ }
151
+ // 运行测试
152
+ (async () => {
153
+ try {
154
+ const result = await main();
155
+ console.log('\n' + '═'.repeat(50));
156
+ console.log(' 测试结果摘要');
157
+ console.log('═'.repeat(50));
158
+ console.log(` DID: ${result.did}`);
159
+ console.log(` 名称: ${result.agentName}`);
160
+ console.log(` CID: ${result.cid}`);
161
+ if (result.ipnsName) {
162
+ console.log(` IPNS: ${result.ipnsName}`);
163
+ }
164
+ console.log('═'.repeat(50));
165
+ await testParseDID(result.diapDoc, result.cid);
166
+ console.log('\n✅ 所有测试完成!\n');
167
+ }
168
+ catch (e) {
169
+ console.error('\n❌ 测试失败:', e.message);
170
+ process.exit(1);
171
+ }
172
+ })();
@@ -0,0 +1,62 @@
1
+ /**
2
+ * DIAP Quick Test - 快速验证 DIAP 功能(跳过慢速 IPNS)
3
+ */
4
+ import { KeyManager } from '@diap/sdk';
5
+ async function main() {
6
+ console.log('\n🔑 DIAP 快速验证测试\n');
7
+ // 1. 生成身份
8
+ console.log('[1] 生成 DIAP 身份...');
9
+ const km = KeyManager.generate();
10
+ console.log(` ✅ DID: ${km.did}`);
11
+ // 2. 验证可以直接获取公钥
12
+ console.log('\n[2] 获取公钥...');
13
+ const pkHex = Buffer.from(km.publicKey).toString('hex');
14
+ console.log(` ✅ 公钥: ${pkHex.substring(0, 24)}...`);
15
+ // 3. 测试本地 IPFS
16
+ console.log('\n[3] 测试本地 IPFS...');
17
+ const testContent = JSON.stringify({
18
+ test: true,
19
+ did: km.did,
20
+ timestamp: Date.now()
21
+ });
22
+ try {
23
+ // 上传 - 使用 form-data 格式
24
+ const formData = new FormData();
25
+ const blob = new Blob([testContent], { type: 'application/json' });
26
+ formData.append('file', blob, 'test.json');
27
+ const addResponse = await fetch('http://127.0.0.1:5001/api/v0/add', {
28
+ method: 'POST',
29
+ body: formData
30
+ });
31
+ const addResult = await addResponse.text();
32
+ // IPFS add 返回格式: {"Name":"test.json","Hash":"Qm...","Size":"..."}
33
+ const cidMatch = addResult.match(/"Hash":"([^"]+)"/);
34
+ const cid = cidMatch ? cidMatch[1] : null;
35
+ if (!cid) {
36
+ console.log(` ⚠️ 解析 CID 失败: ${addResult}`);
37
+ throw new Error('CID not found');
38
+ }
39
+ console.log(` ✅ 上传成功: ${cid}`);
40
+ // 下载
41
+ const getResponse = await fetch(`http://127.0.0.1:5001/api/v0/cat?arg=${cid}`, {
42
+ method: 'POST'
43
+ });
44
+ const retrieved = await getResponse.text();
45
+ const parsed = JSON.parse(retrieved);
46
+ console.log(` ✅ 下载成功: test=${parsed.test}`);
47
+ console.log('\n═══════════════════════════════════════');
48
+ console.log(' ✅ DIAP + IPFS 基本功能正常!');
49
+ console.log('═══════════════════════════════════════');
50
+ console.log(`\n 本节点信息:`);
51
+ console.log(` · DID: ${km.did}`);
52
+ console.log(` · CID: ${cid}`);
53
+ console.log(`\n 供另一台电脑使用的连接信息:`);
54
+ console.log(` · DID: ${km.did}`);
55
+ console.log(` · CID: ${cid}`);
56
+ console.log('');
57
+ }
58
+ catch (e) {
59
+ console.log(` ❌ IPFS 操作失败: ${e.message}`);
60
+ }
61
+ }
62
+ main().catch(console.error);