@bolloon/bolloon-agent 0.4.5 → 0.4.6
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.
- package/README.md +135 -135
- package/bin/bolloon-cli.cjs +183 -183
- package/bin/bolloon.cjs +0 -0
- package/bin/bolloon.js +157 -0
- package/dist/agents/constraint-layer.js +19 -19
- package/dist/agents/judgment-protocol.js +14 -14
- package/dist/agents/pi-sdk-tools.js +62 -45
- package/dist/agents/pi-sdk-types.js +12 -12
- package/dist/agents/pi-sdk.js +103 -90
- package/dist/agents/skill-organizer.js +19 -19
- package/dist/agents/skill-writer.js +15 -3
- package/dist/agents/workflow-pivot-loop.js +13 -3
- package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
- package/dist/bollharness-integration/context-router-judgment.js +4 -4
- package/dist/bollharness-integration/context-router.js +292 -292
- package/dist/bollharness-integration/gate-state-machine.js +13 -13
- package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
- package/dist/bollharness-integration/skill-adapter.js +21 -21
- package/dist/bootstrap/chat-archiver.js +14 -14
- package/dist/bootstrap/context-os.js +24 -24
- package/dist/bootstrap/memory-compressor.js +14 -14
- package/dist/cli/ink-app.js +18 -0
- package/dist/cli-entry.js +36 -36
- package/dist/context-compaction/auto-compact.js +7 -7
- package/dist/electron/first-run.js +54 -54
- package/dist/electron-build/electron/first-run.js +54 -54
- package/dist/electron-preload.js.map +1 -1
- package/dist/electron.js.map +1 -1
- package/dist/index.js +222 -138
- package/dist/llm/llm-judgment-client.js +102 -102
- package/dist/llm/pi-ai.js +48 -48
- package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
- package/dist/llm/system-prompt/layers/channel/local.md +14 -14
- package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
- package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
- package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
- package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
- package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
- package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
- package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
- package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
- package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
- package/dist/llm/system-prompt/layers/core/identity.md +48 -48
- package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
- package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
- package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
- package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
- package/dist/llm/system-prompt/layers/core/tone.md +31 -31
- package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
- package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
- package/dist/llm/system-prompt/layers/role/architect.md +20 -20
- package/dist/llm/system-prompt/layers/role/expert.md +19 -19
- package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
- package/dist/llm/system-prompt/layers/role/security.md +15 -15
- package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
- package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
- package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
- package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
- package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
- package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
- package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
- package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
- package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
- package/dist/llm/tool-manifest/ask_user_input.js +1 -1
- package/dist/llm/tool-manifest/bash.js +3 -3
- package/dist/llm/tool-manifest/create_file.js +4 -4
- package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
- package/dist/llm/tool-manifest/image_search.js +2 -2
- package/dist/llm/tool-manifest/index.js +0 -59
- package/dist/llm/tool-manifest/mcp.js +2 -2
- package/dist/llm/tool-manifest/message_compose.js +3 -3
- package/dist/llm/tool-manifest/places.js +2 -2
- package/dist/llm/tool-manifest/present_files.js +1 -1
- package/dist/llm/tool-manifest/recipe.js +2 -2
- package/dist/llm/tool-manifest/str_replace.js +5 -5
- package/dist/llm/tool-manifest/view.js +3 -3
- package/dist/llm/tool-manifest/weather.js +4 -4
- package/dist/llm/tool-manifest/web.js +4 -4
- package/dist/orbitdb/agent-tools.js +139 -0
- package/dist/orbitdb/kanban-store.js +259 -0
- package/dist/orbitdb/task-store.js +112 -0
- package/dist/pi-ecosystem-colony/index.js +365 -0
- package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
- package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
- package/dist/pi-ecosystem-judgment/distillation.js +14 -14
- package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
- package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
- package/dist/security/context-router-tool.js +15 -15
- package/dist/security/tool-gate.js +2 -0
- package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
- package/dist/social/ant-colony/PheromoneEngine.js +227 -0
- package/dist/social/ant-colony/index.js +6 -0
- package/dist/social/ant-colony/types.js +24 -0
- package/dist/storage/trajectory.js +101 -0
- package/dist/test/ai-judgment-test.js +80 -0
- package/dist/test/bollharness-integration.test.js +318 -0
- package/dist/test/channel-agent-multi-dialogue.js +205 -0
- package/dist/test/channel-heartbeat-agent-test.js +201 -0
- package/dist/test/constraint-layer.test.js +164 -0
- package/dist/test/diap-identity-test.js +172 -0
- package/dist/test/diap-quick-test.js +62 -0
- package/dist/test/global-shared-context.test.js +315 -0
- package/dist/test/harness-judgment-injection.test.js +246 -0
- package/dist/test/harness-workflow-integrator-test.js +228 -0
- package/dist/test/human-value-store.test.js +243 -0
- package/dist/test/hybrid-integration-test.js +118 -0
- package/dist/test/hybrid-messenger-verify.js +55 -0
- package/dist/test/iroh-bistream-debug.js +38 -0
- package/dist/test/iroh-communication.test.js +66 -0
- package/dist/test/iroh-debug-test.js +57 -0
- package/dist/test/iroh-diap-test.js +71 -0
- package/dist/test/iroh-direct-connect.js +55 -0
- package/dist/test/iroh-e2e-fixed.js +89 -0
- package/dist/test/iroh-e2e-same-process.js +63 -0
- package/dist/test/iroh-e2e.js +66 -0
- package/dist/test/iroh-final-e2e.js +72 -0
- package/dist/test/iroh-relay-test.js +37 -0
- package/dist/test/iroh-simple-test.js +41 -0
- package/dist/test/iroh-transport-verify.js +54 -0
- package/dist/test/iroh-transport.test.js +37 -0
- package/dist/test/iroh-two-nodes.js +70 -0
- package/dist/test/iroh-verify.js +44 -0
- package/dist/test/judgment-decision.test.js +219 -0
- package/dist/test/llm-judgment-integration.test.js +220 -0
- package/dist/test/p2p-agent-complex-dialogue.js +385 -0
- package/dist/test/p2p-agent-dialogue.js +341 -0
- package/dist/test/p2p-agent-full-bidirectional.js +510 -0
- package/dist/test/p2p-agent-harness-flow.js +437 -0
- package/dist/test/p2p-agent-harness-single.js +143 -0
- package/dist/test/p2p-ai-dialogue-test.js +318 -0
- package/dist/test/p2p-cid-connect-test.js +195 -0
- package/dist/test/p2p-connect-receiver.js +69 -0
- package/dist/test/p2p-doc-transfer.js +110 -0
- package/dist/test/p2p-identity-page-test.js +77 -0
- package/dist/test/p2p-iroh-test.js +171 -0
- package/dist/test/p2p-minimal-test.js +241 -0
- package/dist/test/p2p-node-1.js +148 -0
- package/dist/test/p2p-node-2.js +148 -0
- package/dist/test/p2p-server.js +281 -0
- package/dist/test/p2p-two-nodes-test.js +438 -0
- package/dist/test/pi-sdk.test.js +44 -0
- package/dist/test/set-persona.js +40 -0
- package/dist/test/simple.test.js +9 -0
- package/dist/test/storage-integration.test.js +150 -0
- package/dist/test/subagent-manager.test.js +276 -0
- package/dist/test/test-gate-flow.test.js +81 -0
- package/dist/test/workflow-engine.test.js +87 -0
- package/dist/test/workflow-pivot-loop.test.js +246 -0
- package/dist/web/api-config.html +779 -779
- package/dist/web/client-hearth.js +10 -10
- package/dist/web/components/wallet-viem.mjs +118 -118
- package/dist/web/index.html +472 -472
- package/dist/web/manifest.json +20 -20
- package/dist/web/server-storage.js +29 -0
- package/dist/web/server.js +30 -14
- package/dist/web/style.css +4946 -4946
- package/package.json +195 -195
- package/scripts/build-cli.js +215 -215
- package/scripts/build-web.ts +130 -130
- package/scripts/postinstall.js +152 -152
- package/bin/bolloon-daemon.sh +0 -207
- package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +0 -63
- package/dist/constraint-runtime/reference_data/commands_snapshot.json +0 -1037
- package/dist/constraint-runtime/reference_data/subsystems/assistant.json +0 -8
- package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +0 -8
- package/dist/constraint-runtime/reference_data/subsystems/bridge.json +0 -32
- package/dist/constraint-runtime/reference_data/subsystems/buddy.json +0 -13
- package/dist/constraint-runtime/reference_data/subsystems/cli.json +0 -26
- package/dist/constraint-runtime/reference_data/subsystems/components.json +0 -32
- package/dist/constraint-runtime/reference_data/subsystems/constants.json +0 -28
- package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +0 -8
- package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +0 -15
- package/dist/constraint-runtime/reference_data/subsystems/hooks.json +0 -32
- package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +0 -21
- package/dist/constraint-runtime/reference_data/subsystems/memdir.json +0 -15
- package/dist/constraint-runtime/reference_data/subsystems/migrations.json +0 -18
- package/dist/constraint-runtime/reference_data/subsystems/moreright.json +0 -8
- package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +0 -11
- package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +0 -8
- package/dist/constraint-runtime/reference_data/subsystems/plugins.json +0 -9
- package/dist/constraint-runtime/reference_data/subsystems/remote.json +0 -11
- package/dist/constraint-runtime/reference_data/subsystems/schemas.json +0 -8
- package/dist/constraint-runtime/reference_data/subsystems/screens.json +0 -10
- package/dist/constraint-runtime/reference_data/subsystems/server.json +0 -10
- package/dist/constraint-runtime/reference_data/subsystems/services.json +0 -32
- package/dist/constraint-runtime/reference_data/subsystems/skills.json +0 -27
- package/dist/constraint-runtime/reference_data/subsystems/state.json +0 -13
- package/dist/constraint-runtime/reference_data/subsystems/types.json +0 -18
- package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +0 -9
- package/dist/constraint-runtime/reference_data/subsystems/utils.json +0 -32
- package/dist/constraint-runtime/reference_data/subsystems/vim.json +0 -12
- package/dist/constraint-runtime/reference_data/subsystems/voice.json +0 -8
- package/dist/constraint-runtime/reference_data/tools_snapshot.json +0 -922
- package/dist/electron/config.js.map +0 -1
- package/dist/electron/dialogs.js.map +0 -1
- package/dist/electron/first-run.js.map +0 -1
- package/dist/electron/ipc.js.map +0 -1
- package/dist/electron/logger.js.map +0 -1
- package/dist/electron/main.js.map +0 -1
- package/dist/electron/menu.js.map +0 -1
- package/dist/electron/paths.js.map +0 -1
- package/dist/electron/server.js.map +0 -1
- package/dist/electron/tray.js.map +0 -1
- package/dist/electron/window.js.map +0 -1
- package/dist/utils/auto-update.js.map +0 -1
- 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);
|