@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
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createHyperswarmCommunicator, createTopic, KeyManager, AgentAuthManager, createVerificationManager, } from '@diap/sdk';
|
|
2
|
+
import { irohTransport } from './network/iroh-transport.js';
|
|
3
|
+
import { HybridMessenger } from './network/hybrid-messenger.js';
|
|
2
4
|
import * as ed25519 from '@noble/ed25519';
|
|
3
5
|
import { sha512 } from '@noble/hashes/sha2.js';
|
|
4
6
|
import * as fs from 'fs/promises';
|
|
@@ -7,6 +9,7 @@ import { initMinimax } from './constraints/index.js';
|
|
|
7
9
|
import { createAgentSession } from './agents/pi-sdk.js';
|
|
8
10
|
import { createSubAgentManager } from './agents/subagent-manager.js';
|
|
9
11
|
import { getGlobalSharedContext } from './social/global-shared-context.js';
|
|
12
|
+
import { createBollharnessIntegration } from './bollharness-integration/index.js';
|
|
10
13
|
import * as readline from 'readline';
|
|
11
14
|
const RESET = '\x1b[0m';
|
|
12
15
|
const BOLD = '\x1b[1m';
|
|
@@ -111,7 +114,7 @@ function getUserName() {
|
|
|
111
114
|
return user.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
112
115
|
}
|
|
113
116
|
async function bootstrapIdentity() {
|
|
114
|
-
s.step(1,
|
|
117
|
+
s.step(1, 5, '生成 DIAP 身份', 'loading');
|
|
115
118
|
const kp = KeyManager.generate();
|
|
116
119
|
const did = kp.did;
|
|
117
120
|
const username = getUserName();
|
|
@@ -119,11 +122,11 @@ async function bootstrapIdentity() {
|
|
|
119
122
|
const name = `blln-${username}-${suffix}`;
|
|
120
123
|
console.log(` ${GRAY}DID:${RESET} ${did}`);
|
|
121
124
|
console.log(` ${GRAY}名称:${RESET} ${name}`);
|
|
122
|
-
s.step(1,
|
|
125
|
+
s.step(1, 5, '生成 DIAP 身份', 'ok');
|
|
123
126
|
return { keypair: kp, did, name };
|
|
124
127
|
}
|
|
125
128
|
function publishDID(name, kp) {
|
|
126
|
-
s.step(2,
|
|
129
|
+
s.step(2, 5, '发布 DID → IPFS (后台)', 'loading');
|
|
127
130
|
return new Promise((resolve) => {
|
|
128
131
|
const attempt = async () => {
|
|
129
132
|
let lastLogTime = 0;
|
|
@@ -131,8 +134,8 @@ function publishDID(name, kp) {
|
|
|
131
134
|
try {
|
|
132
135
|
const auth = await AgentAuthManager.newWithRemoteIpfs('http://127.0.0.1:5001', 'http://127.0.0.1:8080');
|
|
133
136
|
const result = await auth.registerAgent({ name, services: [] }, kp, '');
|
|
134
|
-
s.step(2,
|
|
135
|
-
resolve({ cid: result.cid
|
|
137
|
+
s.step(2, 5, '发布 DID → IPFS', 'ok');
|
|
138
|
+
resolve({ cid: result.cid });
|
|
136
139
|
}
|
|
137
140
|
catch (e) {
|
|
138
141
|
const now = Date.now();
|
|
@@ -158,7 +161,7 @@ function publishDID(name, kp) {
|
|
|
158
161
|
// P2P 节点初始化
|
|
159
162
|
// ---------------------------------------------------------------------------
|
|
160
163
|
async function bootstrapP2P(verifier) {
|
|
161
|
-
s.step(3,
|
|
164
|
+
s.step(3, 5, '启动 P2P 网络', 'loading');
|
|
162
165
|
const rawSeed = crypto.getRandomValues(new Uint8Array(32));
|
|
163
166
|
const seed = rawSeed;
|
|
164
167
|
const comm = createHyperswarmCommunicator({ server: true, client: true, autoConnect: true, maxConnections: 50, seed });
|
|
@@ -173,10 +176,6 @@ async function bootstrapP2P(verifier) {
|
|
|
173
176
|
}
|
|
174
177
|
}
|
|
175
178
|
});
|
|
176
|
-
comm.on('disconnection', (conn) => {
|
|
177
|
-
const shortId = conn.publicKey.substring(0, 8);
|
|
178
|
-
s.warn(`🔌 断开: ${shortId}...`);
|
|
179
|
-
});
|
|
180
179
|
comm.on('message', async (msg, conn) => {
|
|
181
180
|
const content = new TextDecoder().decode(msg.content);
|
|
182
181
|
const shortId = conn.publicKey.substring(0, 8);
|
|
@@ -188,13 +187,48 @@ async function bootstrapP2P(verifier) {
|
|
|
188
187
|
const topic = createTopic('bolloon-agent-harness');
|
|
189
188
|
await comm.joinTopic(topic);
|
|
190
189
|
console.log(` ${GRAY}主题:${RESET} ${topic.slice(0, 8).toString('hex')}...`);
|
|
191
|
-
s.step(3,
|
|
190
|
+
s.step(3, 5, '启动 P2P 网络', 'ok');
|
|
192
191
|
return comm;
|
|
193
192
|
}
|
|
194
193
|
// ---------------------------------------------------------------------------
|
|
194
|
+
// iroh/Hybrid P2P 初始化
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
async function bootstrapIroh(keypair, name) {
|
|
197
|
+
s.step(4, 5, '启动 iroh P2P', 'loading');
|
|
198
|
+
try {
|
|
199
|
+
const node = await irohTransport.start();
|
|
200
|
+
console.log(` ${GRAY}iroh:${RESET} ${node.nodeId.substring(0, 16)}...`);
|
|
201
|
+
hybridMessenger = new HybridMessenger({
|
|
202
|
+
preferIrohForLarge: true,
|
|
203
|
+
largeThresholdBytes: 64 * 1024,
|
|
204
|
+
enableRelay: true,
|
|
205
|
+
});
|
|
206
|
+
hybridMessenger.onMessage('task', async (msg) => {
|
|
207
|
+
console.log(`[iroh] Task from ${msg.from.substring(0, 12)}...: ${new TextDecoder().decode(msg.payload).substring(0, 50)}...`);
|
|
208
|
+
});
|
|
209
|
+
hybridMessenger.onMessage('blob', async (msg) => {
|
|
210
|
+
console.log(`[iroh] Blob from ${msg.from.substring(0, 12)}...: ${msg.payload.length} bytes`);
|
|
211
|
+
});
|
|
212
|
+
hybridMessenger.onMessage('response', async (msg) => {
|
|
213
|
+
console.log(`[iroh] Response from ${msg.from.substring(0, 12)}...`);
|
|
214
|
+
});
|
|
215
|
+
if (agentIdentity) {
|
|
216
|
+
agentIdentity.irohNodeId = node.nodeId;
|
|
217
|
+
}
|
|
218
|
+
s.step(4, 5, '启动 iroh P2P', 'ok');
|
|
219
|
+
}
|
|
220
|
+
catch (e) {
|
|
221
|
+
s.step(4, 5, '启动 iroh P2P', 'warn');
|
|
222
|
+
console.log(` ${YELLOW}iroh 启动失败: ${e.message}${RESET}`);
|
|
223
|
+
console.log(` ${GRAY}继续使用 Hyperswarm P2P${RESET}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
195
227
|
// Agent 懒加载
|
|
196
228
|
// ---------------------------------------------------------------------------
|
|
197
229
|
let agent = null;
|
|
230
|
+
let harness = null;
|
|
231
|
+
let hybridMessenger = null;
|
|
198
232
|
let agentIdentity = null;
|
|
199
233
|
async function getAgent() {
|
|
200
234
|
if (!agent) {
|
|
@@ -324,11 +358,15 @@ function startCLI(comm) {
|
|
|
324
358
|
process.stdin.setRawMode(true);
|
|
325
359
|
}
|
|
326
360
|
catch {
|
|
327
|
-
console.log('Warning: Raw mode not available, using fallback input');
|
|
328
361
|
}
|
|
329
362
|
readline.emitKeypressEvents(process.stdin);
|
|
330
363
|
process.stdout.write(CLEAR_LINE);
|
|
331
364
|
showBottomPrompt();
|
|
365
|
+
const promptTimer = setInterval(() => {
|
|
366
|
+
if (isRunning && promptVisible) {
|
|
367
|
+
showBottomPrompt();
|
|
368
|
+
}
|
|
369
|
+
}, 500);
|
|
332
370
|
const handleInput = (chunk, key) => {
|
|
333
371
|
if (!isRunning)
|
|
334
372
|
return;
|
|
@@ -339,6 +377,7 @@ function startCLI(comm) {
|
|
|
339
377
|
process.stdin.setRawMode(false);
|
|
340
378
|
}
|
|
341
379
|
catch { }
|
|
380
|
+
clearInterval(promptTimer);
|
|
342
381
|
process.exit(0);
|
|
343
382
|
return;
|
|
344
383
|
}
|
|
@@ -402,6 +441,19 @@ async function processInput(input, comm) {
|
|
|
402
441
|
}
|
|
403
442
|
return;
|
|
404
443
|
}
|
|
444
|
+
if (trimmed.toLowerCase() === 'iroh') {
|
|
445
|
+
const nodeId = irohTransport.getNodeId();
|
|
446
|
+
const running = irohTransport.isRunning();
|
|
447
|
+
const peers = irohTransport.getPeers();
|
|
448
|
+
process.stdout.write(`${GRAY}iroh 状态:${RESET}\n`);
|
|
449
|
+
process.stdout.write(` ${GRAY}运行中:${RESET} ${running ? '是' : '否'}\n`);
|
|
450
|
+
process.stdout.write(` ${GRAY}Node ID:${RESET} ${nodeId ? nodeId.substring(0, 24) + '...' : 'N/A'}\n`);
|
|
451
|
+
process.stdout.write(` ${GRAY}已知节点:${RESET} ${peers.length}\n`);
|
|
452
|
+
if (hybridMessenger) {
|
|
453
|
+
process.stdout.write(` ${GRAY}HybridMessenger:${RESET} 就绪\n`);
|
|
454
|
+
}
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
405
457
|
try {
|
|
406
458
|
const a = await getAgent();
|
|
407
459
|
const thinking = setInterval(() => {
|
|
@@ -437,6 +489,13 @@ const AVAILABLE_TOOLS = [
|
|
|
437
489
|
{ name: 'global_context', description: '显示全局共享上下文', example: '--context' },
|
|
438
490
|
{ name: 'global_agents', description: '显示全局 Agent 注册表', example: '--global-agents' },
|
|
439
491
|
{ name: 'add_action', description: '添加用户行动到共享上下文', example: '--add-action <content> [importance]' },
|
|
492
|
+
{ name: 'harness_init', description: '初始化 Bollharness 治理框架', example: '--harness-init' },
|
|
493
|
+
{ name: 'harness_gate', description: '显示当前 Gate 状态', example: '--harness-gate' },
|
|
494
|
+
{ name: 'harness_transition', description: '执行 Gate 转移', example: '--harness-transition [PASS|BLOCK]' },
|
|
495
|
+
{ name: 'harness_skill', description: '执行 Harness Skill', example: '--harness-skill <name> [action]' },
|
|
496
|
+
{ name: 'harness_classify', description: '分类变更类型', example: '--harness-classify <description>' },
|
|
497
|
+
{ name: 'harness_context', description: '获取文件上下文', example: '--harness-context <file>' },
|
|
498
|
+
{ name: 'harness_check', description: '执行 Guard 检查', example: '--harness-check <file>' },
|
|
440
499
|
];
|
|
441
500
|
async function runToolCommand(tool, args, outputJson, comm) {
|
|
442
501
|
const a = await getAgent();
|
|
@@ -519,6 +578,18 @@ async function runToolCommand(tool, args, outputJson, comm) {
|
|
|
519
578
|
}
|
|
520
579
|
break;
|
|
521
580
|
}
|
|
581
|
+
case 'iroh': {
|
|
582
|
+
const nodeId = irohTransport.getNodeId();
|
|
583
|
+
const running = irohTransport.isRunning();
|
|
584
|
+
const irohPeers = irohTransport.getPeers();
|
|
585
|
+
const messenger = hybridMessenger ? 'HybridMessenger 就绪' : 'HybridMessenger 未初始化';
|
|
586
|
+
response = `iroh P2P 状态:
|
|
587
|
+
运行中: ${running ? '是' : '否'}
|
|
588
|
+
Node ID: ${nodeId ? nodeId.substring(0, 32) + '...' : 'N/A'}
|
|
589
|
+
已知节点: ${irohPeers.length}
|
|
590
|
+
${messenger}`;
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
522
593
|
case 'identity': {
|
|
523
594
|
const identity = a.getIdentity();
|
|
524
595
|
response = JSON.stringify(identity, null, 2);
|
|
@@ -577,6 +648,165 @@ async function runToolCommand(tool, args, outputJson, comm) {
|
|
|
577
648
|
response = '🛠️ 可用工具:\n\n' + AVAILABLE_TOOLS.map(t => ` ${t.name}\n ${t.description}\n 示例: ${t.example}`).join('\n\n');
|
|
578
649
|
break;
|
|
579
650
|
}
|
|
651
|
+
// ==================== Bollharness Commands ====================
|
|
652
|
+
case 'harness-init': {
|
|
653
|
+
harness = createBollharnessIntegration();
|
|
654
|
+
const skills = harness.listSkills();
|
|
655
|
+
const harnessSkills = harness.listHarnessSkills();
|
|
656
|
+
response = `✅ Bollharness 初始化成功\n\n` +
|
|
657
|
+
`已加载 Skills: ${skills.length}\n` +
|
|
658
|
+
`已加载 Harness Skills: ${harnessSkills.length}\n\n` +
|
|
659
|
+
`Skills:\n${skills.map(s => ` - ${s.name}: ${s.description}`).join('\n')}\n\n` +
|
|
660
|
+
`Gates: 0-8 (8-Gate 工作流)`;
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
case 'harness-gate': {
|
|
664
|
+
if (!harness) {
|
|
665
|
+
harness = createBollharnessIntegration();
|
|
666
|
+
}
|
|
667
|
+
const gate = harness.getCurrentGate();
|
|
668
|
+
const gatePack = harness.getGatePack();
|
|
669
|
+
const blockers = gatePack.blockers || [];
|
|
670
|
+
response = `🚪 当前 Gate: ${gate}\n\n` +
|
|
671
|
+
`Entry: ${gatePack.entry_satisfied ? '✅ 满足' : '❌ 未满足'}\n` +
|
|
672
|
+
`要求产物: ${gatePack.required_artifact}\n` +
|
|
673
|
+
`下一步 Skill: ${gatePack.required_next_skill}\n` +
|
|
674
|
+
`Blockers: ${blockers.length > 0 ? blockers.join(', ') : '无'}`;
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
case 'harness-transition': {
|
|
678
|
+
if (!harness) {
|
|
679
|
+
harness = createBollharnessIntegration();
|
|
680
|
+
}
|
|
681
|
+
const [verdict] = args;
|
|
682
|
+
const result = await harness.transitionGate(verdict ? { verdict: verdict, details: '' } : undefined);
|
|
683
|
+
const transitionBlockers = result.transition?.blockers || [];
|
|
684
|
+
response = `🔄 Gate 转移: ${result.success ? '✅ 成功' : '❌ 失败'}\n` +
|
|
685
|
+
`Blockers: ${transitionBlockers.length > 0 ? transitionBlockers.join(', ') : '无'}`;
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
688
|
+
case 'harness-skill': {
|
|
689
|
+
if (!harness) {
|
|
690
|
+
harness = createBollharnessIntegration();
|
|
691
|
+
}
|
|
692
|
+
const [skillName, action] = args;
|
|
693
|
+
if (!skillName) {
|
|
694
|
+
const skills = harness.listSkills();
|
|
695
|
+
response = `📋 可用 Skills (${skills.length}):\n\n` +
|
|
696
|
+
skills.map(s => ` ${s.name}: ${s.description}`).join('\n');
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
const result = await harness.executeSkill(skillName, { action: action || 'get_gate' });
|
|
700
|
+
response = `🎯 Skill '${skillName}' 执行结果:\n\n${result.result || result.error}`;
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
703
|
+
case 'harness-classify': {
|
|
704
|
+
if (!harness) {
|
|
705
|
+
harness = createBollharnessIntegration();
|
|
706
|
+
}
|
|
707
|
+
const [description] = args;
|
|
708
|
+
if (!description) {
|
|
709
|
+
response = '用法: --harness-classify <变更描述>';
|
|
710
|
+
error = response;
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
const result = harness.classifyChange(description);
|
|
714
|
+
response = `📊 变更分类: ${result.classification}\n` +
|
|
715
|
+
`最小路径: ${result.minimum_gates}\n` +
|
|
716
|
+
`快速通道: ${result.fast_track ? '✅ 可用' : '❌ 不可用'}`;
|
|
717
|
+
break;
|
|
718
|
+
}
|
|
719
|
+
case 'harness-context': {
|
|
720
|
+
if (!harness) {
|
|
721
|
+
harness = createBollharnessIntegration();
|
|
722
|
+
}
|
|
723
|
+
const [filePath] = args;
|
|
724
|
+
if (!filePath) {
|
|
725
|
+
response = '用法: --harness-context <文件路径>';
|
|
726
|
+
error = response;
|
|
727
|
+
break;
|
|
728
|
+
}
|
|
729
|
+
const context = harness.getContext(filePath);
|
|
730
|
+
response = `📄 文件: ${filePath}\n\n上下文:\n${context || '无匹配上下文'}`;
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
case 'harness-check': {
|
|
734
|
+
if (!harness) {
|
|
735
|
+
harness = createBollharnessIntegration();
|
|
736
|
+
}
|
|
737
|
+
const [filePath] = args;
|
|
738
|
+
if (!filePath) {
|
|
739
|
+
response = '用法: --harness-check <文件路径>';
|
|
740
|
+
error = response;
|
|
741
|
+
break;
|
|
742
|
+
}
|
|
743
|
+
const result = await harness.processFileEdit(filePath);
|
|
744
|
+
response = `🔍 Guard 检查: ${filePath}\n\n` +
|
|
745
|
+
`通过: ${result.success ? '✅' : '❌'}\n` +
|
|
746
|
+
`错误: ${result.errors.length > 0 ? result.errors.join('\n') : '无'}`;
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
case 'harness-archive': {
|
|
750
|
+
const a = await getAgent();
|
|
751
|
+
const sessionHarness = a.getHarness?.();
|
|
752
|
+
if (sessionHarness) {
|
|
753
|
+
a.archiveToHarness?.();
|
|
754
|
+
response = `📦 Session 已归档到 Pi SDK Harness`;
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
if (!harness) {
|
|
758
|
+
harness = createBollharnessIntegration();
|
|
759
|
+
}
|
|
760
|
+
const logs = a.getOperationLogs?.() || [];
|
|
761
|
+
const archive = harness.archiveSession(logs);
|
|
762
|
+
response = `📦 Session 已归档:\n` +
|
|
763
|
+
`ID: ${archive.id}\n` +
|
|
764
|
+
`Gate: ${archive.gate}\n` +
|
|
765
|
+
`动作数: ${archive.actionCount}\n` +
|
|
766
|
+
`摘要: ${archive.summary}`;
|
|
767
|
+
}
|
|
768
|
+
break;
|
|
769
|
+
}
|
|
770
|
+
case 'harness-sessions': {
|
|
771
|
+
const a = await getAgent();
|
|
772
|
+
const sessionHarness = a.getHarness?.();
|
|
773
|
+
if (sessionHarness) {
|
|
774
|
+
harness = sessionHarness;
|
|
775
|
+
}
|
|
776
|
+
if (!harness) {
|
|
777
|
+
harness = createBollharnessIntegration();
|
|
778
|
+
}
|
|
779
|
+
const archives = harness.getSessionArchives();
|
|
780
|
+
if (archives.length === 0) {
|
|
781
|
+
response = '暂无 Session 归档记录';
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
response = `📜 Session 归档记录 (${archives.length}):\n\n`;
|
|
785
|
+
for (const archive of archives.slice(-10)) {
|
|
786
|
+
response += `### ${archive.id}\n`;
|
|
787
|
+
response += `Gate: ${archive.gate} | 动作: ${archive.actionCount}\n`;
|
|
788
|
+
response += `摘要: ${archive.summary}\n\n`;
|
|
789
|
+
}
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
case 'harness-session-context': {
|
|
793
|
+
const a = await getAgent();
|
|
794
|
+
const sessionHarness = a.getHarness?.();
|
|
795
|
+
if (sessionHarness) {
|
|
796
|
+
const [sessionId] = args;
|
|
797
|
+
const context = sessionHarness.getSessionContext(sessionId || undefined);
|
|
798
|
+
response = `📄 Pi SDK Session 上下文:\n\n${context}`;
|
|
799
|
+
}
|
|
800
|
+
else {
|
|
801
|
+
if (!harness) {
|
|
802
|
+
harness = createBollharnessIntegration();
|
|
803
|
+
}
|
|
804
|
+
const [sessionId] = args;
|
|
805
|
+
const context = harness.getSessionContext(sessionId || undefined);
|
|
806
|
+
response = `📄 Session 上下文:\n\n${context}`;
|
|
807
|
+
}
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
580
810
|
case 'agents': {
|
|
581
811
|
const manager = await createSubAgentManager();
|
|
582
812
|
const agents = await manager.getAllAgents();
|
|
@@ -657,7 +887,7 @@ async function runToolCommand(tool, args, outputJson, comm) {
|
|
|
657
887
|
break;
|
|
658
888
|
}
|
|
659
889
|
const ctx = await getGlobalSharedContext();
|
|
660
|
-
await ctx.addUserAction(content, parseInt(importance || '5', 10));
|
|
890
|
+
await ctx.addUserAction(content, undefined, undefined, parseInt(importance || '5', 10));
|
|
661
891
|
response = `✅ 已添加用户行动: ${content.substring(0, 50)}...`;
|
|
662
892
|
break;
|
|
663
893
|
}
|
|
@@ -795,6 +1025,10 @@ function parseArgs() {
|
|
|
795
1025
|
result.peers = true;
|
|
796
1026
|
result.tool = 'peers';
|
|
797
1027
|
break;
|
|
1028
|
+
case '--iroh':
|
|
1029
|
+
result.iroh = true;
|
|
1030
|
+
result.tool = 'iroh';
|
|
1031
|
+
break;
|
|
798
1032
|
case '--identity':
|
|
799
1033
|
result.identity = true;
|
|
800
1034
|
result.tool = 'identity';
|
|
@@ -861,6 +1095,69 @@ function parseArgs() {
|
|
|
861
1095
|
}
|
|
862
1096
|
result.toolArgs = actionArgs;
|
|
863
1097
|
break;
|
|
1098
|
+
case '--harness-init':
|
|
1099
|
+
result.tool = 'harness-init';
|
|
1100
|
+
break;
|
|
1101
|
+
case '--harness-gate':
|
|
1102
|
+
result.tool = 'harness-gate';
|
|
1103
|
+
break;
|
|
1104
|
+
case '--harness-transition':
|
|
1105
|
+
result.tool = 'harness-transition';
|
|
1106
|
+
const transitionArgs = [];
|
|
1107
|
+
while (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1108
|
+
transitionArgs.push(args[++i]);
|
|
1109
|
+
}
|
|
1110
|
+
result.toolArgs = transitionArgs;
|
|
1111
|
+
break;
|
|
1112
|
+
case '--harness-skill':
|
|
1113
|
+
result.tool = 'harness-skill';
|
|
1114
|
+
const skillArgs = [];
|
|
1115
|
+
while (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1116
|
+
skillArgs.push(args[++i]);
|
|
1117
|
+
}
|
|
1118
|
+
result.toolArgs = skillArgs;
|
|
1119
|
+
break;
|
|
1120
|
+
case '--harness-classify':
|
|
1121
|
+
result.tool = 'harness-classify';
|
|
1122
|
+
const classifyArgs = [];
|
|
1123
|
+
while (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1124
|
+
classifyArgs.push(args[++i]);
|
|
1125
|
+
}
|
|
1126
|
+
result.toolArgs = classifyArgs;
|
|
1127
|
+
break;
|
|
1128
|
+
case '--harness-context':
|
|
1129
|
+
result.tool = 'harness-context';
|
|
1130
|
+
const contextArgs = [];
|
|
1131
|
+
while (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1132
|
+
contextArgs.push(args[++i]);
|
|
1133
|
+
}
|
|
1134
|
+
result.toolArgs = contextArgs;
|
|
1135
|
+
break;
|
|
1136
|
+
case '--harness-check':
|
|
1137
|
+
result.tool = 'harness-check';
|
|
1138
|
+
const checkArgs = [];
|
|
1139
|
+
while (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1140
|
+
checkArgs.push(args[++i]);
|
|
1141
|
+
}
|
|
1142
|
+
result.toolArgs = checkArgs;
|
|
1143
|
+
break;
|
|
1144
|
+
case '--harness-archive':
|
|
1145
|
+
result.tool = 'harness-archive';
|
|
1146
|
+
break;
|
|
1147
|
+
case '--harness-sessions':
|
|
1148
|
+
result.tool = 'harness-sessions';
|
|
1149
|
+
break;
|
|
1150
|
+
case '--harness-session-context':
|
|
1151
|
+
result.tool = 'harness-session-context';
|
|
1152
|
+
const sessionArgs = [];
|
|
1153
|
+
while (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
1154
|
+
sessionArgs.push(args[++i]);
|
|
1155
|
+
}
|
|
1156
|
+
result.toolArgs = sessionArgs;
|
|
1157
|
+
break;
|
|
1158
|
+
case '--tui':
|
|
1159
|
+
result.tui = true;
|
|
1160
|
+
break;
|
|
864
1161
|
case '--model':
|
|
865
1162
|
result.model = args[++i];
|
|
866
1163
|
break;
|
|
@@ -915,6 +1212,18 @@ function printHelp() {
|
|
|
915
1212
|
--global-agents 显示全局 Agent 注册表
|
|
916
1213
|
--add-action <内容> [重要性] 添加用户行动到共享上下文
|
|
917
1214
|
|
|
1215
|
+
# Bollharness 治理框架
|
|
1216
|
+
--harness-init 初始化 Bollharness 治理框架
|
|
1217
|
+
--harness-gate 显示当前 Gate 状态
|
|
1218
|
+
--harness-transition [PASS|BLOCK] 执行 Gate 转移
|
|
1219
|
+
--harness-skill <name> [action] 执行 Harness Skill
|
|
1220
|
+
--harness-classify <描述> 分类变更类型
|
|
1221
|
+
--harness-context <file> 获取文件上下文
|
|
1222
|
+
--harness-check <file> 执行 Guard 检查
|
|
1223
|
+
--harness-archive 归档当前 Session 到 Harness
|
|
1224
|
+
--harness-sessions 列出 Session 归档记录
|
|
1225
|
+
--harness-session-context [id] 获取 Session 上下文
|
|
1226
|
+
|
|
918
1227
|
# AI 对话
|
|
919
1228
|
--prompt, -p <text> 通用 AI 对话(默认)
|
|
920
1229
|
--model <name> 指定使用的模型
|
|
@@ -965,6 +1274,33 @@ async function main() {
|
|
|
965
1274
|
}
|
|
966
1275
|
const mode = args.web ? 'web' : 'cli';
|
|
967
1276
|
const isNonInteractive = !!(args.tool || args.prompt);
|
|
1277
|
+
const isTuiMode = mode === 'cli' && !isNonInteractive && args.tui;
|
|
1278
|
+
const originalLog = console.log;
|
|
1279
|
+
const originalInfo = console.info;
|
|
1280
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
1281
|
+
const isSdkLog = (msg) => {
|
|
1282
|
+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(msg);
|
|
1283
|
+
};
|
|
1284
|
+
if (isTuiMode) {
|
|
1285
|
+
console.log = (...args) => {
|
|
1286
|
+
const msg = args.join(' ');
|
|
1287
|
+
if (isSdkLog(msg))
|
|
1288
|
+
return;
|
|
1289
|
+
originalLog.apply(console, args);
|
|
1290
|
+
};
|
|
1291
|
+
console.info = (...args) => {
|
|
1292
|
+
const msg = args.join(' ');
|
|
1293
|
+
if (isSdkLog(msg))
|
|
1294
|
+
return;
|
|
1295
|
+
originalInfo.apply(console, args);
|
|
1296
|
+
};
|
|
1297
|
+
process.stdout.write = (chunk, ...args) => {
|
|
1298
|
+
const msg = String(chunk);
|
|
1299
|
+
if (isSdkLog(msg))
|
|
1300
|
+
return true;
|
|
1301
|
+
return originalStdoutWrite(chunk, ...args);
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
968
1304
|
if (isNonInteractive) {
|
|
969
1305
|
console.error = () => { };
|
|
970
1306
|
}
|
|
@@ -993,7 +1329,7 @@ async function main() {
|
|
|
993
1329
|
}
|
|
994
1330
|
}
|
|
995
1331
|
const { keypair, did, name } = await bootstrapIdentity();
|
|
996
|
-
agentIdentity = { did, name, publicKey: keypair.
|
|
1332
|
+
agentIdentity = { did, name, publicKey: Buffer.from(keypair.publicKey).toString('hex') };
|
|
997
1333
|
publishDID(name, keypair).then(({ cid, ipnsName }) => {
|
|
998
1334
|
if (cid)
|
|
999
1335
|
agentIdentity.cid = cid;
|
|
@@ -1002,26 +1338,33 @@ async function main() {
|
|
|
1002
1338
|
}).catch(() => { });
|
|
1003
1339
|
const verifier = createVerificationManager();
|
|
1004
1340
|
let comm = null;
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1341
|
+
try {
|
|
1342
|
+
if (mode === 'web') {
|
|
1343
|
+
bootstrapP2P(verifier).then(c => {
|
|
1344
|
+
comm = c;
|
|
1345
|
+
const connections = c.getConnections();
|
|
1346
|
+
if (connections.length > 0) {
|
|
1347
|
+
agentIdentity.peerId = connections[0].publicKey;
|
|
1348
|
+
agentIdentity.p2pChannel = 'bolloon-agent-harness';
|
|
1349
|
+
}
|
|
1350
|
+
}).catch(err => {
|
|
1351
|
+
s.warn(`P2P Web 模式启动失败: ${err.message}`);
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
else {
|
|
1355
|
+
comm = await bootstrapP2P(verifier);
|
|
1356
|
+
const connections = comm.getConnections();
|
|
1009
1357
|
if (connections.length > 0) {
|
|
1010
1358
|
agentIdentity.peerId = connections[0].publicKey;
|
|
1011
1359
|
agentIdentity.p2pChannel = 'bolloon-agent-harness';
|
|
1012
1360
|
}
|
|
1013
|
-
}).catch(err => {
|
|
1014
|
-
s.warn(`P2P 连接失败: ${err.message}`);
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
else {
|
|
1018
|
-
comm = await bootstrapP2P(verifier);
|
|
1019
|
-
const connections = comm.getConnections();
|
|
1020
|
-
if (connections.length > 0) {
|
|
1021
|
-
agentIdentity.peerId = connections[0].publicKey;
|
|
1022
|
-
agentIdentity.p2pChannel = 'bolloon-agent-harness';
|
|
1023
1361
|
}
|
|
1024
1362
|
}
|
|
1363
|
+
catch (err) {
|
|
1364
|
+
s.warn(`P2P 初始化失败: ${err.message}`);
|
|
1365
|
+
s.warn('将使用无 P2P 模式运行');
|
|
1366
|
+
}
|
|
1367
|
+
await bootstrapIroh(keypair, name);
|
|
1025
1368
|
s.divider();
|
|
1026
1369
|
if (mode === 'web') {
|
|
1027
1370
|
const port = parseInt(process.env.PORT || '54188');
|
|
@@ -1032,6 +1375,9 @@ async function main() {
|
|
|
1032
1375
|
openBrowser(`http://localhost:${port}`);
|
|
1033
1376
|
}
|
|
1034
1377
|
else if (isNonInteractive) {
|
|
1378
|
+
console.log = originalLog;
|
|
1379
|
+
console.info = originalInfo;
|
|
1380
|
+
process.stdout.write = originalStdoutWrite;
|
|
1035
1381
|
s.info('执行命令...');
|
|
1036
1382
|
console.log();
|
|
1037
1383
|
await runNonInteractive(args, comm);
|
|
@@ -1046,7 +1392,14 @@ async function main() {
|
|
|
1046
1392
|
console.log(` ${CYAN}--agents${RESET} ${GRAY}- 查看 SubAgent${RESET}`);
|
|
1047
1393
|
console.log(` ${CYAN}--context${RESET} ${GRAY}- 查看全局上下文${RESET}`);
|
|
1048
1394
|
console.log(` ${CYAN}--delegate 任务 coding${RESET} ${GRAY}- 委派任务${RESET}`);
|
|
1395
|
+
console.log(` ${CYAN}peers${RESET} ${GRAY}- 查看 P2P 节点${RESET}`);
|
|
1396
|
+
console.log(` ${CYAN}iroh${RESET} ${GRAY}- 查看 iroh 状态${RESET}`);
|
|
1049
1397
|
console.log(` ${CYAN}退出${RESET} ${GRAY}- 结束对话${RESET}\n`);
|
|
1398
|
+
if (!isTuiMode) {
|
|
1399
|
+
console.log = originalLog;
|
|
1400
|
+
console.info = originalInfo;
|
|
1401
|
+
process.stdout.write = originalStdoutWrite;
|
|
1402
|
+
}
|
|
1050
1403
|
startCLI(comm);
|
|
1051
1404
|
}
|
|
1052
1405
|
}
|