@bolloon/bolloon-agent 0.1.1 → 0.1.3
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/bin/bolloon-cli.cjs +165 -0
- package/bin/bolloon-daemon.sh +207 -0
- package/bin/bolloon.cmd +11 -0
- package/dist/agents/constraint-layer.js +10 -15
- package/dist/agents/pi-sdk.js +433 -106
- package/dist/agents/protocol.js +82 -1
- package/dist/agents/subagent-manager.js +2 -2
- package/dist/agents/workflow-engine.js +15 -20
- package/dist/agents/workflow-pivot-loop.js +541 -0
- package/dist/bollharness/src/index.js +5 -0
- package/dist/bollharness/src/scripts/checks/check_adr_plan_numbering.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_api_types.js +45 -0
- package/dist/bollharness/src/scripts/checks/check_artifact_link.js +146 -0
- package/dist/bollharness/src/scripts/checks/check_bridge_deps.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_bugfix_binding.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_bugfix_binding_ci.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_doc_file_references.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +135 -0
- package/dist/bollharness/src/scripts/checks/check_doc_links.js +31 -0
- package/dist/bollharness/src/scripts/checks/check_file_existence_claims.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_fragment_integrity.js +34 -0
- package/dist/bollharness/src/scripts/checks/check_hook_installed.js +63 -0
- package/dist/bollharness/src/scripts/checks/check_issue_closure.js +41 -0
- package/dist/bollharness/src/scripts/checks/check_mcp_parity.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_security.js +48 -0
- package/dist/bollharness/src/scripts/checks/check_skill_parity.js +6 -0
- package/dist/bollharness/src/scripts/checks/check_versions.js +6 -0
- package/dist/bollharness/src/scripts/checks/finding.js +13 -0
- package/dist/bollharness/src/scripts/checks/next_decision_number.js +20 -0
- package/dist/bollharness/src/scripts/checks/regenerate_magic_docs.js +6 -0
- package/dist/bollharness/src/scripts/ci/detect_rebaseline_triggers.js +8 -0
- package/dist/bollharness/src/scripts/ci/scan_subprocess_cfg.js +8 -0
- package/dist/bollharness/src/scripts/ci/scan_verify_artifacts.js +8 -0
- package/dist/bollharness/src/scripts/ci/scan_yaml_schema.js +8 -0
- package/dist/bollharness/src/scripts/context_router.js +67 -0
- package/dist/bollharness/src/scripts/deploy-guard.js +157 -0
- package/dist/bollharness/src/scripts/guard-feedback.js +192 -0
- package/dist/bollharness/src/scripts/guard_router.js +158 -0
- package/dist/bollharness/src/scripts/hooks/_hook_output.js +6 -0
- package/dist/bollharness/src/scripts/hooks/auto-python3.js +6 -0
- package/dist/bollharness/src/scripts/hooks/deploy-progress-on-session-end.js +6 -0
- package/dist/bollharness/src/scripts/hooks/failure-analyzer.js +6 -0
- package/dist/bollharness/src/scripts/hooks/gate-judgment-inject.js +92 -0
- package/dist/bollharness/src/scripts/hooks/gate-transition-judgment.js +63 -0
- package/dist/bollharness/src/scripts/hooks/inbox-ack.js +6 -0
- package/dist/bollharness/src/scripts/hooks/inbox-inject-on-start.js +6 -0
- package/dist/bollharness/src/scripts/hooks/inbox-validate.js +6 -0
- package/dist/bollharness/src/scripts/hooks/inbox-write-ledger.js +6 -0
- package/dist/bollharness/src/scripts/hooks/initializer-agent.js +6 -0
- package/dist/bollharness/src/scripts/hooks/loop-detection.js +73 -0
- package/dist/bollharness/src/scripts/hooks/owner-guard.js +6 -0
- package/dist/bollharness/src/scripts/hooks/precompact.js +6 -0
- package/dist/bollharness/src/scripts/hooks/review-agent-gatekeeper.js +6 -0
- package/dist/bollharness/src/scripts/hooks/risk-tracker.js +108 -0
- package/dist/bollharness/src/scripts/hooks/sanitize-on-read.js +6 -0
- package/dist/bollharness/src/scripts/hooks/session-reflection.js +7 -0
- package/dist/bollharness/src/scripts/hooks/session-start-magic-docs.js +7 -0
- package/dist/bollharness/src/scripts/hooks/session-start-reset-risk.js +7 -0
- package/dist/bollharness/src/scripts/hooks/session-start-toolkit-reminder.js +7 -0
- package/dist/bollharness/src/scripts/hooks/stop-evaluator.js +157 -0
- package/dist/bollharness/src/scripts/hooks/tool-call-counter.js +6 -0
- package/dist/bollharness/src/scripts/hooks/trace-analyzer.js +10 -0
- package/dist/bollharness/src/scripts/install/install-trust-token.js +7 -0
- package/dist/bollharness/src/scripts/install/multi_project_registry.js +9 -0
- package/dist/bollharness/src/scripts/install/phase2_auto.js +21 -0
- package/dist/bollharness/src/scripts/install/pre_commit_installer.js +6 -0
- package/dist/bollharness/src/scripts/install/tier_selector.js +7 -0
- package/dist/bollharness/src/scripts/install/transcript_miner.js +7 -0
- package/dist/bollharness/src/scripts/lib/claim_patterns.js +10 -0
- package/dist/bollharness/src/scripts/lib/sanitize_patterns.js +12 -0
- package/dist/bollharness/src/scripts/sanitize.js +6 -0
- package/dist/bollharness-integration/channel-judgment-engine.js +530 -0
- package/dist/bollharness-integration/context-chain-router.js +383 -0
- package/dist/bollharness-integration/context-router-judgment.js +13 -21
- package/dist/bollharness-integration/context-router.js +22 -64
- package/dist/bollharness-integration/gate-state-machine.js +14 -19
- package/dist/bollharness-integration/gate-transition-hooks.js +16 -61
- package/dist/bollharness-integration/guard-checker.js +21 -68
- package/dist/bollharness-integration/index.js +14 -124
- package/dist/bollharness-integration/integration.js +13 -20
- package/dist/bollharness-integration/llm-judgment-engine.js +569 -0
- package/dist/bollharness-integration/skill-adapter.js +18 -64
- package/dist/cli-entry.js +261 -0
- package/dist/constraint-runtime/src/commands.js +17 -7
- package/dist/constraint-runtime/src/constraint/budget.js +1 -6
- package/dist/constraint-runtime/src/constraint/permission.js +1 -6
- package/dist/constraint-runtime/src/models.js +1 -3
- package/dist/constraint-runtime/src/tools.js +17 -7
- package/dist/constraints/index.js +1 -7
- package/dist/documents/reader.js +8 -49
- package/dist/heartbeat/DaemonManager.js +242 -0
- package/dist/heartbeat/HealthMonitor.js +285 -0
- package/dist/heartbeat/StartupVerifier.js +205 -0
- package/dist/heartbeat/Watchdog.js +168 -0
- package/dist/heartbeat/index.js +84 -0
- package/dist/heartbeat/types.js +5 -0
- package/dist/index.js +381 -28
- package/dist/llm/config-store.js +31 -57
- package/dist/llm/llm-judgment-client.js +389 -0
- package/dist/llm/pi-ai.js +9 -52
- package/dist/network/agent-network.js +46 -90
- package/dist/network/hybrid-messenger.js +125 -0
- package/dist/network/iroh-bootstrap.js +38 -0
- package/dist/network/iroh-discovery.js +145 -0
- package/dist/network/iroh-integration.js +9 -16
- package/dist/network/iroh-transport.js +10 -48
- package/dist/network/p2p.js +23 -62
- package/dist/network/storage/adapters/json-adapter.js +4 -42
- package/dist/network/storage/index.js +147 -0
- package/dist/network/storage/types.js +14 -0
- package/dist/pi-ecosystem/index.js +233 -0
- package/dist/pi-ecosystem-colony/index.js +29 -90
- package/dist/pi-ecosystem-goals/index.js +20 -74
- package/dist/pi-ecosystem-judgment/decision.js +29 -47
- package/dist/pi-ecosystem-judgment/distillation.js +16 -29
- package/dist/pi-ecosystem-judgment/human-value-store.js +13 -60
- package/dist/pi-ecosystem-judgment/index.js +21 -74
- package/dist/pi-ecosystem-judgment/value-injection.js +26 -72
- package/dist/pi-ecosystem-mcp/index.js +24 -78
- package/dist/pi-ecosystem-subagents/index.js +20 -69
- package/dist/social/ant-colony/AdaptiveHeartbeat.js +3 -8
- package/dist/social/ant-colony/PheromoneEngine.js +11 -49
- package/dist/social/ant-colony/index.js +6 -0
- package/dist/social/ant-colony/types.js +4 -8
- package/dist/social/channels/ChannelManager.js +8 -46
- package/dist/social/channels/DiapChannelBridge.js +9 -47
- package/dist/social/channels/InterestMatcher.js +2 -7
- package/dist/social/channels/channel-agent-session.js +309 -0
- package/dist/social/channels/channel-heartbeat-agent.js +494 -0
- package/dist/social/channels/diap-doc-parser.js +204 -0
- package/dist/social/channels/harness-workflow-integrator.js +446 -0
- package/dist/social/channels/index.js +9 -0
- package/dist/social/channels/types.js +3 -7
- package/dist/social/global-shared-context.js +6 -47
- package/dist/social/heartbeat.js +29 -72
- package/dist/social/persona/enhanced-persona.js +299 -0
- package/dist/web/client.js +302 -136
- package/dist/web/components/p2p/index.js +159 -9
- package/dist/web/components/p2p/p2p-connection.js +136 -0
- package/dist/web/components/p2p/p2p-manager.js +24 -0
- package/dist/web/components/p2p/p2p-store-memory.js +1 -1
- package/dist/web/components/p2p/types.js +7 -0
- package/dist/web/index.html +5 -0
- package/dist/web/style.css +118 -0
- package/package.json +12 -6
- package/scripts/build-cli.js +206 -0
- package/scripts/postinstall.js +153 -0
- package/src/agents/pi-sdk.ts +347 -28
- package/src/agents/protocol.ts +95 -1
- package/src/agents/workflow-pivot-loop.ts +674 -0
- package/src/bollharness/CLAUDE.md +73 -0
- package/src/bollharness/README.md +143 -0
- package/src/bollharness/README.zh-CN.md +131 -0
- package/src/bollharness/reference/boll-reference/scripts/hooks/stop-evaluator.md +57 -0
- package/src/bollharness/scripts/context-fragments/artifact-linkage.md +14 -0
- package/src/bollharness/scripts/context-fragments/auth-consumers.md +17 -0
- package/src/bollharness/scripts/context-fragments/bridge-constitution.md +13 -0
- package/src/bollharness/scripts/context-fragments/catalyst-distributed.md +18 -0
- package/src/bollharness/scripts/context-fragments/closure-checklist.md +13 -0
- package/src/bollharness/scripts/context-fragments/contract-consumers.md +15 -0
- package/src/bollharness/scripts/context-fragments/db-shared-structures.md +15 -0
- package/src/bollharness/scripts/context-fragments/fixed-three-layers.md +19 -0
- package/src/bollharness/scripts/context-fragments/general-dev-principles.md +11 -0
- package/src/bollharness/scripts/context-fragments/issue-first.md +8 -0
- package/src/bollharness/scripts/context-fragments/mcp-parity.md +16 -0
- package/src/bollharness/scripts/context-fragments/pi-agent-operations.md +108 -0
- package/src/bollharness/scripts/context-fragments/protocol-consumers.md +15 -0
- package/src/bollharness/scripts/context-fragments/run-events-consumers.md +15 -0
- package/src/bollharness/scripts/context-fragments/scene-fidelity.md +13 -0
- package/src/bollharness/scripts/context-fragments/truth-source-hierarchy.md +15 -0
- package/src/bollharness/scripts/context-fragments/two-language.md +15 -0
- package/src/bollharness/scripts/context-fragments/version-sources.md +14 -0
- package/src/bollharness/scripts/hooks/stop-evaluator.md +83 -0
- package/src/bollharness/templates/scaffold/CLAUDE.md +89 -0
- package/src/cli-entry.ts +304 -0
- package/src/heartbeat/DaemonManager.ts +283 -0
- package/src/heartbeat/HealthMonitor.ts +316 -0
- package/src/heartbeat/StartupVerifier.ts +223 -0
- package/src/heartbeat/Watchdog.ts +198 -0
- package/src/heartbeat/index.ts +108 -0
- package/src/heartbeat/types.ts +82 -0
- package/src/llm/config-store.ts +23 -5
- package/src/network/iroh-transport.ts +3 -3
- package/src/web/client.js +302 -136
- package/src/web/components/p2p/P2PModal.tsx +91 -3
- package/src/web/components/p2p/index.ts +171 -9
- package/src/web/components/p2p/p2p-connection.ts +153 -1
- package/src/web/components/p2p/p2p-manager.ts +39 -1
- package/src/web/components/p2p/p2p-store-memory.ts +1 -1
- package/src/web/components/p2p/p2p-tools.ts +315 -0
- package/src/web/components/p2p/types.ts +58 -0
- package/src/web/design.md +99 -0
- package/src/web/index.html +5 -0
- package/src/web/server.ts +353 -36
- package/src/web/style.css +118 -0
- package/tsconfig.cli.json +16 -0
- package/tsconfig.electron.json +1 -1
- package/tsconfig.json +1 -2
- package/dist/web/server.js +0 -1647
- package/dist/web/server.js.map +0 -1
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StartupVerifier - 启动自检验证器
|
|
3
|
+
* 在服务启动时验证所有关键组件
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { StartupReport, StartupCheck } from './types.js';
|
|
7
|
+
|
|
8
|
+
export class StartupVerifier {
|
|
9
|
+
private checks: Map<string, StartupCheck> = new Map();
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 添加检查项
|
|
13
|
+
*/
|
|
14
|
+
addCheck(name: string): void {
|
|
15
|
+
this.checks.set(name, { name, status: 'pending' });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 标记检查开始
|
|
20
|
+
*/
|
|
21
|
+
startCheck(name: string): void {
|
|
22
|
+
const check = this.checks.get(name);
|
|
23
|
+
if (check) {
|
|
24
|
+
check.status = 'running';
|
|
25
|
+
check.startTime = Date.now();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 标记检查完成
|
|
31
|
+
*/
|
|
32
|
+
completeCheck(name: string, passed: boolean, message?: string): void {
|
|
33
|
+
const check = this.checks.get(name);
|
|
34
|
+
if (check) {
|
|
35
|
+
check.status = passed ? 'passed' : 'failed';
|
|
36
|
+
check.message = message;
|
|
37
|
+
check.duration_ms = Date.now() - (check.startTime || Date.now());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 运行所有自检
|
|
43
|
+
*/
|
|
44
|
+
async verify(): Promise<StartupReport> {
|
|
45
|
+
const startTime = Date.now();
|
|
46
|
+
const critical_failures: string[] = [];
|
|
47
|
+
|
|
48
|
+
// 1. 检查 Node.js 版本
|
|
49
|
+
this.addCheck('node_version');
|
|
50
|
+
this.startCheck('node_version');
|
|
51
|
+
const nodeVersion = process.version;
|
|
52
|
+
const majorVersion = parseInt(nodeVersion.replace('v', '').split('.')[0], 10);
|
|
53
|
+
if (majorVersion >= 18) {
|
|
54
|
+
this.completeCheck('node_version', true, `Node.js ${nodeVersion}`);
|
|
55
|
+
} else {
|
|
56
|
+
this.completeCheck('node_version', false, `Node.js ${nodeVersion} too old, need >= 18`);
|
|
57
|
+
critical_failures.push('Node.js version too old');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 2. 检查必要目录
|
|
61
|
+
this.addCheck('required_directories');
|
|
62
|
+
this.startCheck('required_directories');
|
|
63
|
+
try {
|
|
64
|
+
const fs = await import('fs/promises');
|
|
65
|
+
const paths = [
|
|
66
|
+
process.env.HOME ? `${process.env.HOME}/.bolloon` : '/tmp/.bolloon',
|
|
67
|
+
'/tmp'
|
|
68
|
+
];
|
|
69
|
+
for (const p of paths) {
|
|
70
|
+
await fs.access(p);
|
|
71
|
+
}
|
|
72
|
+
this.completeCheck('required_directories', true, 'All required directories accessible');
|
|
73
|
+
} catch (err: any) {
|
|
74
|
+
this.completeCheck('required_directories', false, err.message);
|
|
75
|
+
critical_failures.push('Cannot access required directories');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 3. 检查 LLM 配置
|
|
79
|
+
this.addCheck('llm_config');
|
|
80
|
+
this.startCheck('llm_config');
|
|
81
|
+
const hasLlmKey = !!(
|
|
82
|
+
process.env.OPENAI_API_KEY ||
|
|
83
|
+
process.env.ANTHROPIC_API_KEY ||
|
|
84
|
+
process.env.MINIMAX_API_KEY ||
|
|
85
|
+
process.env.OPENROUTER_API_KEY ||
|
|
86
|
+
process.env.GEMINI_API_KEY ||
|
|
87
|
+
process.env.OLLAMA_BASE_URL
|
|
88
|
+
);
|
|
89
|
+
if (hasLlmKey) {
|
|
90
|
+
this.completeCheck('llm_config', true, 'LLM API key found');
|
|
91
|
+
} else {
|
|
92
|
+
this.completeCheck('llm_config', false, 'No LLM API key configured (optional)');
|
|
93
|
+
// LLM 配置不是致命的,只是警告
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 4. 检查 P2P 依赖
|
|
97
|
+
this.addCheck('p2p_modules');
|
|
98
|
+
this.startCheck('p2p_modules');
|
|
99
|
+
try {
|
|
100
|
+
await import('@diap/sdk');
|
|
101
|
+
this.completeCheck('p2p_modules', true, '@diap/sdk available');
|
|
102
|
+
} catch (err: any) {
|
|
103
|
+
this.completeCheck('p2p_modules', false, `@diap/sdk not available: ${err.message}`);
|
|
104
|
+
critical_failures.push('@diap/sdk module not found');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 5. 检查 IPFS 连接
|
|
108
|
+
this.addCheck('ipfs_connection');
|
|
109
|
+
this.startCheck('ipfs_connection');
|
|
110
|
+
try {
|
|
111
|
+
const ipfsRes = await fetch('http://127.0.0.1:5001/api/v0/id', {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
signal: AbortSignal.timeout(3000)
|
|
114
|
+
});
|
|
115
|
+
if (ipfsRes.ok) {
|
|
116
|
+
this.completeCheck('ipfs_connection', true, 'IPFS local node accessible');
|
|
117
|
+
} else {
|
|
118
|
+
this.completeCheck('ipfs_connection', false, 'IPFS returned error');
|
|
119
|
+
}
|
|
120
|
+
} catch (err: any) {
|
|
121
|
+
this.completeCheck('ipfs_connection', false, 'IPFS not accessible (optional)');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 6. 检查内存
|
|
125
|
+
this.addCheck('memory');
|
|
126
|
+
this.startCheck('memory');
|
|
127
|
+
const usage = process.memoryUsage();
|
|
128
|
+
const heapPercent = (usage.heapUsed / usage.heapTotal) * 100;
|
|
129
|
+
if (heapPercent < 90) {
|
|
130
|
+
this.completeCheck('memory', true, `Heap usage ${heapPercent.toFixed(1)}%`);
|
|
131
|
+
} else {
|
|
132
|
+
this.completeCheck('memory', false, `Heap usage critical: ${heapPercent.toFixed(1)}%`);
|
|
133
|
+
critical_failures.push('Memory usage too high at startup');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 7. 检查网络
|
|
137
|
+
this.addCheck('network');
|
|
138
|
+
this.startCheck('network');
|
|
139
|
+
try {
|
|
140
|
+
const res = await fetch('https://www.google.com/generate_204', {
|
|
141
|
+
signal: AbortSignal.timeout(5000)
|
|
142
|
+
});
|
|
143
|
+
this.completeCheck('network', true, 'Internet connection available');
|
|
144
|
+
} catch {
|
|
145
|
+
this.completeCheck('network', false, 'No internet connection (optional)');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const totalDuration = Date.now() - startTime;
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
success: critical_failures.length === 0,
|
|
152
|
+
checks: Array.from(this.checks.values()),
|
|
153
|
+
total_duration_ms: totalDuration,
|
|
154
|
+
critical_failures
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 打印检查报告
|
|
160
|
+
*/
|
|
161
|
+
printReport(report: StartupReport): void {
|
|
162
|
+
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
163
|
+
console.log('🚀 Bolloon 启动自检报告');
|
|
164
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
165
|
+
|
|
166
|
+
for (const check of report.checks) {
|
|
167
|
+
const icon = check.status === 'passed' ? '✅' :
|
|
168
|
+
check.status === 'failed' ? '❌' :
|
|
169
|
+
check.status === 'running' ? '⏳' : '⭕';
|
|
170
|
+
const duration = check.duration_ms ? ` (${check.duration_ms}ms)` : '';
|
|
171
|
+
console.log(` ${icon} ${check.name}${duration}`);
|
|
172
|
+
if (check.message) {
|
|
173
|
+
console.log(` ${check.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
178
|
+
console.log(`总计耗时: ${report.total_duration_ms}ms`);
|
|
179
|
+
|
|
180
|
+
if (report.success) {
|
|
181
|
+
console.log('✅ 所有关键检查通过!');
|
|
182
|
+
} else {
|
|
183
|
+
console.log('❌ 关键检查失败:');
|
|
184
|
+
for (const failure of report.critical_failures) {
|
|
185
|
+
console.log(` · ${failure}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 快速验证(不打印)
|
|
193
|
+
*/
|
|
194
|
+
async quickCheck(): Promise<boolean> {
|
|
195
|
+
const report = await this.verify();
|
|
196
|
+
return report.success;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取检查状态
|
|
201
|
+
*/
|
|
202
|
+
getChecks(): StartupCheck[] {
|
|
203
|
+
return Array.from(this.checks.values());
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 导出便捷函数
|
|
208
|
+
let startupVerifierInstance: StartupVerifier | null = null;
|
|
209
|
+
|
|
210
|
+
export async function runStartupVerification(): Promise<StartupReport> {
|
|
211
|
+
const verifier = new StartupVerifier();
|
|
212
|
+
startupVerifierInstance = verifier;
|
|
213
|
+
const report = await verifier.verify();
|
|
214
|
+
verifier.printReport(report);
|
|
215
|
+
return report;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function getStartupVerifier(): StartupVerifier {
|
|
219
|
+
if (!startupVerifierInstance) {
|
|
220
|
+
startupVerifierInstance = new StartupVerifier();
|
|
221
|
+
}
|
|
222
|
+
return startupVerifierInstance;
|
|
223
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watchdog - 看门狗机制
|
|
3
|
+
* 检测进程卡死、无响应等情况
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { WatchdogConfig, WatchdogState, RestartStrategy, RestartLevel } from './types.js';
|
|
7
|
+
|
|
8
|
+
export interface WatchdogCallbacks {
|
|
9
|
+
onRestart?: (level: RestartLevel, reason: string) => void;
|
|
10
|
+
onLog?: (message: string) => void;
|
|
11
|
+
onHealthCheckFailed?: (failures: number) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Watchdog {
|
|
15
|
+
private config: Required<WatchdogConfig>;
|
|
16
|
+
private state: WatchdogState;
|
|
17
|
+
private checkIntervalId: ReturnType<typeof setInterval> | null = null;
|
|
18
|
+
private restartStrategies: Map<RestartLevel, () => void | Promise<void>> = new Map();
|
|
19
|
+
private restartCount: number = 0;
|
|
20
|
+
private callbacks: WatchdogCallbacks;
|
|
21
|
+
|
|
22
|
+
constructor(config: Partial<WatchdogConfig> = {}, callbacks: WatchdogCallbacks = {}) {
|
|
23
|
+
this.config = {
|
|
24
|
+
silentThresholdMs: config.silentThresholdMs || 300000, // 5 分钟无日志
|
|
25
|
+
maxConsecutiveFailures: config.maxConsecutiveFailures || 3,
|
|
26
|
+
checkIntervalMs: config.checkIntervalMs || 30000 // 30 秒检查一次
|
|
27
|
+
};
|
|
28
|
+
this.state = {
|
|
29
|
+
lastActivityTime: Date.now(),
|
|
30
|
+
consecutiveFailures: 0,
|
|
31
|
+
isTriggered: false
|
|
32
|
+
};
|
|
33
|
+
this.callbacks = callbacks;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 注册重启策略
|
|
38
|
+
*/
|
|
39
|
+
registerRestartStrategy(level: RestartLevel, action: () => void | Promise<void>): void {
|
|
40
|
+
this.restartStrategies.set(level, action);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 记录活动(调用后更新 lastActivityTime)
|
|
45
|
+
*/
|
|
46
|
+
recordActivity(component?: string): void {
|
|
47
|
+
this.state.lastActivityTime = Date.now();
|
|
48
|
+
if (component) {
|
|
49
|
+
this.callbacks.onLog?.(`[Watchdog] Activity from ${component}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 记录日志(同时触发活动检测)
|
|
55
|
+
*/
|
|
56
|
+
log(message: string): void {
|
|
57
|
+
this.recordActivity();
|
|
58
|
+
console.log(`[Watchdog] ${message}`);
|
|
59
|
+
this.callbacks.onLog?.(message);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 开始看门狗监控
|
|
64
|
+
*/
|
|
65
|
+
start(): void {
|
|
66
|
+
if (this.checkIntervalId) return;
|
|
67
|
+
|
|
68
|
+
console.log(`[Watchdog] Started - silent threshold: ${this.config.silentThresholdMs}ms, check interval: ${this.config.checkIntervalMs}ms`);
|
|
69
|
+
|
|
70
|
+
this.checkIntervalId = setInterval(() => {
|
|
71
|
+
this.check();
|
|
72
|
+
}, this.config.checkIntervalMs);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 停止看门狗
|
|
77
|
+
*/
|
|
78
|
+
stop(): void {
|
|
79
|
+
if (this.checkIntervalId) {
|
|
80
|
+
clearInterval(this.checkIntervalId);
|
|
81
|
+
this.checkIntervalId = null;
|
|
82
|
+
}
|
|
83
|
+
console.log('[Watchdog] Stopped');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 报告健康检查结果
|
|
88
|
+
*/
|
|
89
|
+
reportHealthCheck(success: boolean, details?: string): void {
|
|
90
|
+
if (success) {
|
|
91
|
+
this.state.consecutiveFailures = 0;
|
|
92
|
+
this.recordActivity('health_check');
|
|
93
|
+
} else {
|
|
94
|
+
this.state.consecutiveFailures++;
|
|
95
|
+
console.log(`[Watchdog] Health check failed (${this.state.consecutiveFailures}/${this.config.maxConsecutiveFailures}): ${details || 'unknown'}`);
|
|
96
|
+
this.callbacks.onHealthCheckFailed?.(this.state.consecutiveFailures);
|
|
97
|
+
|
|
98
|
+
if (this.state.consecutiveFailures >= this.config.maxConsecutiveFailures) {
|
|
99
|
+
this.triggerRestart(1, `Health check failed ${this.state.consecutiveFailures} times`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 获取当前状态
|
|
106
|
+
*/
|
|
107
|
+
getState(): WatchdogState & { uptime_ms: number; restartCount: number } {
|
|
108
|
+
return {
|
|
109
|
+
...this.state,
|
|
110
|
+
uptime_ms: Date.now() - this.state.lastActivityTime,
|
|
111
|
+
restartCount: this.restartCount
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 执行检查
|
|
117
|
+
*/
|
|
118
|
+
private check(): void {
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
const silentTime = now - this.state.lastActivityTime;
|
|
121
|
+
|
|
122
|
+
// 检查是否沉默太久
|
|
123
|
+
if (silentTime > this.config.silentThresholdMs) {
|
|
124
|
+
console.warn(`[Watchdog] No activity for ${Math.round(silentTime / 1000)}s`);
|
|
125
|
+
this.triggerRestart(1, `No activity for ${Math.round(silentTime / 1000)}s`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 检查内存使用
|
|
130
|
+
const usage = process.memoryUsage();
|
|
131
|
+
const heapUsedPercent = (usage.heapUsed / usage.heapTotal) * 100;
|
|
132
|
+
if (heapUsedPercent > 90) {
|
|
133
|
+
console.warn(`[Watchdog] Memory usage critical: ${heapUsedPercent.toFixed(1)}%`);
|
|
134
|
+
this.triggerRestart(1, `Memory usage ${heapUsedPercent.toFixed(1)}%`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 触发重启
|
|
140
|
+
*/
|
|
141
|
+
private triggerRestart(level: RestartLevel, reason: string): void {
|
|
142
|
+
if (this.state.isTriggered) {
|
|
143
|
+
console.log(`[Watchdog] Already triggered, ignoring restart request: ${reason}`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
this.state.isTriggered = true;
|
|
148
|
+
this.state.triggerReason = reason;
|
|
149
|
+
this.restartCount++;
|
|
150
|
+
|
|
151
|
+
console.error(`[Watchdog] 🔴 TRIGGERED: ${reason} (restart #${this.restartCount})`);
|
|
152
|
+
|
|
153
|
+
const strategy = this.restartStrategies.get(level);
|
|
154
|
+
if (strategy) {
|
|
155
|
+
try {
|
|
156
|
+
this.callbacks.onRestart?.(level, reason);
|
|
157
|
+
const result = strategy();
|
|
158
|
+
if (result instanceof Promise) {
|
|
159
|
+
result.catch(err => {
|
|
160
|
+
console.error('[Watchdog] Restart action failed:', err);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
} catch (err) {
|
|
164
|
+
console.error('[Watchdog] Failed to execute restart strategy:', err);
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
console.warn(`[Watchdog] No restart strategy registered for level ${level}`);
|
|
168
|
+
this.callbacks.onRestart?.(level, reason);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 重置触发状态(允许再次触发)
|
|
174
|
+
*/
|
|
175
|
+
reset(): void {
|
|
176
|
+
this.state.isTriggered = false;
|
|
177
|
+
this.state.triggerReason = undefined;
|
|
178
|
+
this.state.lastActivityTime = Date.now();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 全局实例
|
|
183
|
+
let watchdogInstance: Watchdog | null = null;
|
|
184
|
+
|
|
185
|
+
export function getWatchdog(): Watchdog {
|
|
186
|
+
if (!watchdogInstance) {
|
|
187
|
+
watchdogInstance = new Watchdog();
|
|
188
|
+
}
|
|
189
|
+
return watchdogInstance;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function createWatchdog(
|
|
193
|
+
config?: Partial<WatchdogConfig>,
|
|
194
|
+
callbacks?: WatchdogCallbacks
|
|
195
|
+
): Watchdog {
|
|
196
|
+
watchdogInstance = new Watchdog(config, callbacks);
|
|
197
|
+
return watchdogInstance;
|
|
198
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bolloon 24h Heartbeat Module
|
|
3
|
+
* 24 小时稳定运行心跳闭环
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export * from './HealthMonitor.js';
|
|
8
|
+
export * from './Watchdog.js';
|
|
9
|
+
export * from './DaemonManager.js';
|
|
10
|
+
export * from './StartupVerifier.js';
|
|
11
|
+
|
|
12
|
+
import { createHealthMonitor, getHealthMonitor } from './HealthMonitor.js';
|
|
13
|
+
import { createWatchdog, getWatchdog } from './Watchdog.js';
|
|
14
|
+
import { createDaemonManager, getDaemonManager } from './DaemonManager.js';
|
|
15
|
+
import { StartupVerifier, runStartupVerification, getStartupVerifier } from './StartupVerifier.js';
|
|
16
|
+
import type { HealthStatus } from './types.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 初始化完整的 24h 心跳系统
|
|
20
|
+
*/
|
|
21
|
+
export async function initialize24hHeartbeat(): Promise<{
|
|
22
|
+
healthMonitor: ReturnType<typeof createHealthMonitor>;
|
|
23
|
+
watchdog: ReturnType<typeof createWatchdog>;
|
|
24
|
+
daemonManager: ReturnType<typeof createDaemonManager>;
|
|
25
|
+
startupVerifier: StartupVerifier;
|
|
26
|
+
}> {
|
|
27
|
+
// 1. 启动自检
|
|
28
|
+
const startupReport = await runStartupVerification();
|
|
29
|
+
if (!startupReport.success) {
|
|
30
|
+
console.warn('[24h] Startup verification failed, continuing anyway...');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 2. 初始化健康监控
|
|
34
|
+
const healthMonitor = createHealthMonitor({
|
|
35
|
+
onStatusChange: (status: HealthStatus) => {
|
|
36
|
+
if (status.status !== 'healthy') {
|
|
37
|
+
console.warn(`[24h] Health status: ${status.status}`);
|
|
38
|
+
for (const rec of status.recommendations || []) {
|
|
39
|
+
console.warn(`[24h] → ${rec}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// 3. 初始化看门狗
|
|
46
|
+
const watchdog = createWatchdog(
|
|
47
|
+
{ silentThresholdMs: 300000, maxConsecutiveFailures: 3, checkIntervalMs: 30000 },
|
|
48
|
+
{
|
|
49
|
+
onLog: (msg) => console.log(`[24h-Watchdog] ${msg}`),
|
|
50
|
+
onHealthCheckFailed: (failures) => console.warn(`[24h] Health check failures: ${failures}`),
|
|
51
|
+
onRestart: (level, reason) => {
|
|
52
|
+
console.error(`[24h] Restart triggered (level ${level}): ${reason}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// 4. 连接健康监控和看门狗
|
|
58
|
+
healthMonitor.startPeriodicCheck(60000, (status) => {
|
|
59
|
+
const hasError = Object.values(status.checks).some(c => c.status === 'error');
|
|
60
|
+
watchdog.reportHealthCheck(!hasError, status.status);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// 5. 初始化守护进程管理器
|
|
64
|
+
const daemonManager = createDaemonManager({
|
|
65
|
+
maxRestarts: 5,
|
|
66
|
+
restartDelayMs: 5000
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// 6. 注册看门狗重启策略
|
|
70
|
+
watchdog.registerRestartStrategy(1 as const, () => {
|
|
71
|
+
console.log('[24h] Level 1 restart: Graceful restart...');
|
|
72
|
+
// 可以添加进程重启逻辑
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
watchdog.registerRestartStrategy(2 as const, () => {
|
|
76
|
+
console.log('[24h] Level 2 restart: Process restart...');
|
|
77
|
+
// 可以添加进程重启逻辑
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
watchdog.registerRestartStrategy(3 as const, () => {
|
|
81
|
+
console.log('[24h] Level 3 restart: System notification...');
|
|
82
|
+
// 可以发送通知
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 7. 启动看门狗
|
|
86
|
+
watchdog.start();
|
|
87
|
+
|
|
88
|
+
console.log('[24h] 24h heartbeat system initialized');
|
|
89
|
+
console.log(`[24h] Health checks: every 60s`);
|
|
90
|
+
console.log(`[24h] Watchdog checks: every 30s`);
|
|
91
|
+
console.log(`[24h] Max restarts: 5`);
|
|
92
|
+
|
|
93
|
+
return { healthMonitor, watchdog, daemonManager, startupVerifier: getStartupVerifier() };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 获取健康状态 JSON
|
|
98
|
+
*/
|
|
99
|
+
export async function getHealthStatus(): Promise<HealthStatus> {
|
|
100
|
+
const healthMonitor = getHealthMonitor();
|
|
101
|
+
return healthMonitor.check();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Re-export singleton getters for convenience
|
|
105
|
+
export { getHealthMonitor, createHealthMonitor };
|
|
106
|
+
export { getWatchdog, createWatchdog };
|
|
107
|
+
export { getDaemonManager, createDaemonManager };
|
|
108
|
+
export { getStartupVerifier };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bolloon 24h Heartbeat Types
|
|
3
|
+
* 健康检查、看门狗、守护进程的类型定义
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface HealthCheckResult {
|
|
7
|
+
status: 'ok' | 'error';
|
|
8
|
+
message?: string;
|
|
9
|
+
details?: Record<string, unknown>;
|
|
10
|
+
latency_ms?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface HealthStatus {
|
|
14
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
15
|
+
timestamp: string;
|
|
16
|
+
uptime_seconds: number;
|
|
17
|
+
checks: {
|
|
18
|
+
p2p: HealthCheckResult;
|
|
19
|
+
iroh: HealthCheckResult;
|
|
20
|
+
llm: HealthCheckResult;
|
|
21
|
+
memory: HealthCheckResult;
|
|
22
|
+
heartbeat: HealthCheckResult;
|
|
23
|
+
};
|
|
24
|
+
recommendations?: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface WatchdogConfig {
|
|
28
|
+
/** 无日志时间阈值 (ms) */
|
|
29
|
+
silentThresholdMs: number;
|
|
30
|
+
/** 健康检查失败阈值 */
|
|
31
|
+
maxConsecutiveFailures: number;
|
|
32
|
+
/** 检查间隔 (ms) */
|
|
33
|
+
checkIntervalMs: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface WatchdogState {
|
|
37
|
+
lastActivityTime: number;
|
|
38
|
+
consecutiveFailures: number;
|
|
39
|
+
isTriggered: boolean;
|
|
40
|
+
triggerReason?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface DaemonConfig {
|
|
44
|
+
/** 最大重启次数 */
|
|
45
|
+
maxRestarts: number;
|
|
46
|
+
/** 重启延迟 (ms) */
|
|
47
|
+
restartDelayMs: number;
|
|
48
|
+
/** 日志文件路径 */
|
|
49
|
+
logFile?: string;
|
|
50
|
+
/** PID 文件路径 */
|
|
51
|
+
pidFile?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface StartupCheck {
|
|
55
|
+
name: string;
|
|
56
|
+
status: 'pending' | 'running' | 'passed' | 'failed';
|
|
57
|
+
message?: string;
|
|
58
|
+
duration_ms?: number;
|
|
59
|
+
startTime?: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface StartupReport {
|
|
63
|
+
success: boolean;
|
|
64
|
+
checks: StartupCheck[];
|
|
65
|
+
total_duration_ms: number;
|
|
66
|
+
critical_failures: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type RestartLevel = 1 | 2 | 3;
|
|
70
|
+
|
|
71
|
+
export interface RestartStrategy {
|
|
72
|
+
level: RestartLevel;
|
|
73
|
+
action: () => void | Promise<void>;
|
|
74
|
+
reason: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface HealthCheckProvider {
|
|
78
|
+
checkP2P(): Promise<HealthCheckResult>;
|
|
79
|
+
checkIroh(): Promise<HealthCheckResult>;
|
|
80
|
+
checkLLM(): Promise<HealthCheckResult>;
|
|
81
|
+
checkMemory(): Promise<HealthCheckResult>;
|
|
82
|
+
}
|
package/src/llm/config-store.ts
CHANGED
|
@@ -157,7 +157,23 @@ class LLMConfigStore {
|
|
|
157
157
|
try {
|
|
158
158
|
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
159
159
|
const data = await fs.readFile(CONFIG_PATH, 'utf-8');
|
|
160
|
-
|
|
160
|
+
const loadedConfig = JSON.parse(data);
|
|
161
|
+
|
|
162
|
+
// 确保加载的配置包含所有默认供应商,缺失的用默认值补充
|
|
163
|
+
const defaultProviders = Object.keys(DEFAULT_PROVIDER_CONFIGS) as ModelProvider[];
|
|
164
|
+
for (const provider of defaultProviders) {
|
|
165
|
+
if (!loadedConfig.providers[provider]) {
|
|
166
|
+
loadedConfig.providers[provider] = { ...DEFAULT_PROVIDER_CONFIGS[provider] };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 确保有 activeProvider
|
|
171
|
+
const activeProvider = loadedConfig.activeProvider as ModelProvider;
|
|
172
|
+
if (!activeProvider || !DEFAULT_PROVIDER_CONFIGS[activeProvider]) {
|
|
173
|
+
loadedConfig.activeProvider = 'ollama';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this.config = loadedConfig;
|
|
161
177
|
} catch {
|
|
162
178
|
this.config = getDefaultConfig();
|
|
163
179
|
await this.save();
|
|
@@ -302,11 +318,13 @@ export function getPiSDKConfig(): {
|
|
|
302
318
|
return { provider: 'ollama' };
|
|
303
319
|
}
|
|
304
320
|
|
|
305
|
-
const
|
|
321
|
+
const activeProvider = config.activeProvider as ModelProvider;
|
|
322
|
+
const activeConfig = config.providers[activeProvider] || {};
|
|
323
|
+
const defaultConfig = DEFAULT_PROVIDER_CONFIGS[activeProvider] || { baseUrl: '', model: '' };
|
|
306
324
|
return {
|
|
307
|
-
provider:
|
|
325
|
+
provider: activeProvider,
|
|
308
326
|
apiKey: activeConfig.apiKey || undefined,
|
|
309
|
-
baseUrl: activeConfig.baseUrl !==
|
|
310
|
-
model: activeConfig.model !==
|
|
327
|
+
baseUrl: activeConfig.baseUrl !== defaultConfig.baseUrl ? activeConfig.baseUrl : undefined,
|
|
328
|
+
model: activeConfig.model !== defaultConfig.model ? activeConfig.model : undefined
|
|
311
329
|
};
|
|
312
330
|
}
|
|
@@ -82,11 +82,11 @@ export class IrohTransport {
|
|
|
82
82
|
private requestIdToNodeId: Map<string, string> = new Map();
|
|
83
83
|
|
|
84
84
|
async start(secretKey?: string, enablePersistence = false): Promise<{ nodeId: string; addr: string }> {
|
|
85
|
-
if (this.endpoint) {
|
|
85
|
+
if (this.endpoint && this.ownNodeId) {
|
|
86
86
|
// 已启动,返回当前信息
|
|
87
87
|
return {
|
|
88
88
|
nodeId: this.ownNodeId,
|
|
89
|
-
addr: this.
|
|
89
|
+
addr: this.ownNodeId // iroh 没有 listenAddresses,用 nodeId 作为 addr
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -114,7 +114,7 @@ export class IrohTransport {
|
|
|
114
114
|
|
|
115
115
|
return {
|
|
116
116
|
nodeId: this.endpoint.nodeId(),
|
|
117
|
-
addr: this.
|
|
117
|
+
addr: this.ownNodeId // iroh 没有 addr(),用 nodeId
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
120
|
|