@bolloon/bolloon-agent 0.1.1 → 0.1.2
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 +157 -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/agents/pi-sdk.js
CHANGED
|
@@ -1,60 +1,23 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Pi-SDK - Agent Session for Document Processing
|
|
4
3
|
* Part of OpenClaw dual-layer architecture
|
|
5
4
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}) : function(o, v) {
|
|
20
|
-
o["default"] = v;
|
|
21
|
-
});
|
|
22
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
-
var ownKeys = function(o) {
|
|
24
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
-
var ar = [];
|
|
26
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
-
return ar;
|
|
28
|
-
};
|
|
29
|
-
return ownKeys(o);
|
|
30
|
-
};
|
|
31
|
-
return function (mod) {
|
|
32
|
-
if (mod && mod.__esModule) return mod;
|
|
33
|
-
var result = {};
|
|
34
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
-
__setModuleDefault(result, mod);
|
|
36
|
-
return result;
|
|
37
|
-
};
|
|
38
|
-
})();
|
|
39
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.PiSessionManager = void 0;
|
|
41
|
-
exports.createAgentSession = createAgentSession;
|
|
42
|
-
exports.getAgentSession = getAgentSession;
|
|
43
|
-
exports.resetAgentSession = resetAgentSession;
|
|
44
|
-
const fs = __importStar(require("fs/promises"));
|
|
45
|
-
const path = __importStar(require("path"));
|
|
46
|
-
const reader_js_1 = require("../documents/reader.js");
|
|
47
|
-
const index_js_1 = require("../constraints/index.js");
|
|
48
|
-
const p2p_js_1 = require("../network/p2p.js");
|
|
49
|
-
const constraint_layer_js_1 = require("./constraint-layer.js");
|
|
50
|
-
const workflow_engine_js_1 = require("./workflow-engine.js");
|
|
51
|
-
const constraint_runtime_1 = require("@bolloon/constraint-runtime");
|
|
52
|
-
const heartbeat_js_1 = require("../social/heartbeat.js");
|
|
53
|
-
const global_shared_context_js_1 = require("../social/global-shared-context.js");
|
|
54
|
-
const constraint_runtime_2 = require("@bolloon/constraint-runtime");
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as fsSync from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { documentReader } from '../documents/reader.js';
|
|
9
|
+
import { getMinimax } from '../constraints/index.js';
|
|
10
|
+
import { p2pNetwork } from '../network/p2p.js';
|
|
11
|
+
import { ConstraintLayer } from './constraint-layer.js';
|
|
12
|
+
import { WorkflowEngine } from './workflow-engine.js';
|
|
13
|
+
import { DeepThinkingEngine, AgentCoordinator } from '@bolloon/constraint-runtime';
|
|
14
|
+
import { WorkflowPivotLoop, createDefaultPivotConfig } from './workflow-pivot-loop.js';
|
|
15
|
+
import { DiscoveredAgentsManager, createSocialHeartbeat } from '../social/heartbeat.js';
|
|
16
|
+
import { getGlobalSharedContext } from '../social/global-shared-context.js';
|
|
17
|
+
import { Session, SkillRegistry, saveSession, loadSession } from '@bolloon/constraint-runtime';
|
|
55
18
|
const SHARED_SESSION_PATH = path.join(process.env.HOME || '/tmp', '.bolloon', 'sessions');
|
|
56
19
|
const PERSONA_PATH = path.join(process.env.HOME || '/tmp', '.bolloon', 'persona.json');
|
|
57
|
-
class PiSessionManager {
|
|
20
|
+
export class PiSessionManager {
|
|
58
21
|
session;
|
|
59
22
|
state;
|
|
60
23
|
memory;
|
|
@@ -71,7 +34,7 @@ class PiSessionManager {
|
|
|
71
34
|
this.sessionDir = path.join(cwd, '.port_sessions');
|
|
72
35
|
this.agentId = agentId;
|
|
73
36
|
const sessionId = `pi-session-${Date.now()}`;
|
|
74
|
-
this.session = new
|
|
37
|
+
this.session = new Session(sessionId);
|
|
75
38
|
this.state = {
|
|
76
39
|
id: sessionId,
|
|
77
40
|
agentId,
|
|
@@ -85,7 +48,7 @@ class PiSessionManager {
|
|
|
85
48
|
fileContext: new Map()
|
|
86
49
|
};
|
|
87
50
|
this.channelsPath = path.join(SHARED_SESSION_PATH, 'pi-channels.json');
|
|
88
|
-
this.sharedContext =
|
|
51
|
+
this.sharedContext = getGlobalSharedContext();
|
|
89
52
|
}
|
|
90
53
|
get sessionId() {
|
|
91
54
|
return this.session.sessionId;
|
|
@@ -115,7 +78,7 @@ class PiSessionManager {
|
|
|
115
78
|
inputTokens: 0,
|
|
116
79
|
outputTokens: 0
|
|
117
80
|
};
|
|
118
|
-
|
|
81
|
+
saveSession(stored);
|
|
119
82
|
}
|
|
120
83
|
catch (e) {
|
|
121
84
|
console.warn('Failed to persist session:', e);
|
|
@@ -124,7 +87,7 @@ class PiSessionManager {
|
|
|
124
87
|
loadPersistedSession() {
|
|
125
88
|
try {
|
|
126
89
|
const sessionId = this.state.id;
|
|
127
|
-
const stored =
|
|
90
|
+
const stored = loadSession(sessionId);
|
|
128
91
|
for (const msg of stored.messages) {
|
|
129
92
|
this.session.addMessage(msg);
|
|
130
93
|
}
|
|
@@ -338,7 +301,6 @@ class PiSessionManager {
|
|
|
338
301
|
await this.sharedContext.updateAgentStatus(this.agentId, status);
|
|
339
302
|
}
|
|
340
303
|
}
|
|
341
|
-
exports.PiSessionManager = PiSessionManager;
|
|
342
304
|
const TOOL_DEFINITIONS = `
|
|
343
305
|
可用工具:
|
|
344
306
|
1. read_document(path) - 读取文档内容,支持 .txt, .md, .pdf, .docx
|
|
@@ -366,28 +328,34 @@ class PiAgentSession {
|
|
|
366
328
|
socialHeartbeat = null;
|
|
367
329
|
messageHistory = [];
|
|
368
330
|
tools = new Map();
|
|
369
|
-
skillRegistry = new
|
|
370
|
-
MAX_REACT_ITERATIONS =
|
|
371
|
-
|
|
372
|
-
|
|
331
|
+
skillRegistry = new SkillRegistry();
|
|
332
|
+
MAX_REACT_ITERATIONS = 100;
|
|
333
|
+
MAX_REFINE_ATTEMPTS = 3;
|
|
334
|
+
QUALITY_THRESHOLD = 0.6;
|
|
335
|
+
thinkingEngine = new DeepThinkingEngine(3);
|
|
336
|
+
coordinator = new AgentCoordinator(3);
|
|
373
337
|
harness = null;
|
|
374
338
|
harnessEnabled = false;
|
|
339
|
+
usePivotLoop = false;
|
|
340
|
+
pivotLoopConfig;
|
|
375
341
|
constructor(config) {
|
|
376
342
|
this.cwd = config.cwd;
|
|
377
343
|
this.peerId = config.peerId || 'local';
|
|
378
344
|
this.identity = config.identityDoc || this.createDefaultIdentity();
|
|
379
345
|
this.minimaxAvailable = this.checkMinimax();
|
|
380
|
-
this.constraintLayer = new
|
|
381
|
-
this.workflowEngine = new
|
|
346
|
+
this.constraintLayer = new ConstraintLayer();
|
|
347
|
+
this.workflowEngine = new WorkflowEngine(this.constraintLayer);
|
|
382
348
|
this.sessionManager = new PiSessionManager(this.identity.did, this.cwd);
|
|
383
|
-
this.agentsManager = new
|
|
349
|
+
this.agentsManager = new DiscoveredAgentsManager();
|
|
350
|
+
this.usePivotLoop = config.usePivotLoop ?? false;
|
|
351
|
+
this.pivotLoopConfig = config.pivotLoopConfig;
|
|
384
352
|
this.initSession();
|
|
385
353
|
this.registerTools();
|
|
386
354
|
this.initHarness();
|
|
387
355
|
}
|
|
388
356
|
async initHarness() {
|
|
389
357
|
try {
|
|
390
|
-
const { createBollharnessIntegration } = await
|
|
358
|
+
const { createBollharnessIntegration } = await import('../bollharness-integration/index.js');
|
|
391
359
|
this.harness = createBollharnessIntegration();
|
|
392
360
|
this.harnessEnabled = true;
|
|
393
361
|
}
|
|
@@ -403,7 +371,7 @@ class PiAgentSession {
|
|
|
403
371
|
parameters: { path: '文件路径' },
|
|
404
372
|
execute: async (args) => {
|
|
405
373
|
try {
|
|
406
|
-
const content = await
|
|
374
|
+
const content = await documentReader.read(args.path);
|
|
407
375
|
return {
|
|
408
376
|
success: true,
|
|
409
377
|
output: `📄 ${content.metadata.filename}\n大小: ${content.metadata.size} 字节\n\n${content.text.substring(0, 1000)}${content.text.length > 1000 ? '...' : ''}`
|
|
@@ -462,7 +430,7 @@ class PiAgentSession {
|
|
|
462
430
|
description: '列出已连接的对等节点',
|
|
463
431
|
parameters: {},
|
|
464
432
|
execute: async () => {
|
|
465
|
-
const peers =
|
|
433
|
+
const peers = p2pNetwork.getPeers();
|
|
466
434
|
if (peers.length === 0) {
|
|
467
435
|
return { success: true, output: '当前无连接的对等节点' };
|
|
468
436
|
}
|
|
@@ -475,7 +443,7 @@ class PiAgentSession {
|
|
|
475
443
|
parameters: { peer_id: '对等节点ID', message: '消息内容' },
|
|
476
444
|
execute: async (args) => {
|
|
477
445
|
try {
|
|
478
|
-
await
|
|
446
|
+
await p2pNetwork.sendMessage(args.peer_id, 'message', args.message);
|
|
479
447
|
return { success: true, output: `消息已发送到 ${args.peer_id}` };
|
|
480
448
|
}
|
|
481
449
|
catch (e) {
|
|
@@ -489,7 +457,7 @@ class PiAgentSession {
|
|
|
489
457
|
parameters: { message: '消息内容' },
|
|
490
458
|
execute: async (args) => {
|
|
491
459
|
try {
|
|
492
|
-
await
|
|
460
|
+
await p2pNetwork.broadcast('message', args.message);
|
|
493
461
|
return { success: true, output: '消息已广播到所有节点' };
|
|
494
462
|
}
|
|
495
463
|
catch (e) {
|
|
@@ -556,6 +524,59 @@ class PiAgentSession {
|
|
|
556
524
|
};
|
|
557
525
|
}
|
|
558
526
|
});
|
|
527
|
+
// 添加文件列表工具
|
|
528
|
+
this.tools.set('list_files', {
|
|
529
|
+
name: 'list_files',
|
|
530
|
+
description: '列出目录中的文件',
|
|
531
|
+
parameters: { path: '目录路径(可选,默认为当前目录)' },
|
|
532
|
+
execute: async (args) => {
|
|
533
|
+
try {
|
|
534
|
+
const fs = await import('fs');
|
|
535
|
+
const path = args.path || this.cwd;
|
|
536
|
+
const files = fs.readdirSync(path);
|
|
537
|
+
return {
|
|
538
|
+
success: true,
|
|
539
|
+
output: `📁 目录 ${path} 中的文件 (${files.length} 个):\n${files.slice(0, 20).map(f => ` - ${f}`).join('\n')}${files.length > 20 ? '\n ...' : ''}`
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
catch (e) {
|
|
543
|
+
return { success: false, error: String(e) };
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
// 添加目录读取工具(更完整的实现)
|
|
548
|
+
this.tools.set('read_directory', {
|
|
549
|
+
name: 'read_directory',
|
|
550
|
+
description: '读取目录内容,返回文件列表和目录结构',
|
|
551
|
+
parameters: { path: '目录路径(可选,默认为当前目录)' },
|
|
552
|
+
execute: async (args) => {
|
|
553
|
+
try {
|
|
554
|
+
const fs = await import('fs');
|
|
555
|
+
const pathModule = await import('path');
|
|
556
|
+
const targetPath = args.path || this.cwd;
|
|
557
|
+
const items = fs.readdirSync(targetPath);
|
|
558
|
+
const result = [];
|
|
559
|
+
for (const item of items.slice(0, 30)) {
|
|
560
|
+
const fullPath = pathModule.join(targetPath, item);
|
|
561
|
+
try {
|
|
562
|
+
const stat = fs.statSync(fullPath);
|
|
563
|
+
const type = stat.isDirectory() ? '📁' : '📄';
|
|
564
|
+
result.push(`${type} ${item}${stat.isDirectory() ? '/' : ''}`);
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
result.push(`📄 ${item}`);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
success: true,
|
|
572
|
+
output: `📂 ${targetPath} (${items.length} 项):\n${result.join('\n')}${items.length > 30 ? '\n... 还有更多文件' : ''}`
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
catch (e) {
|
|
576
|
+
return { success: false, error: `无法读取目录: ${String(e)}` };
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
});
|
|
559
580
|
}
|
|
560
581
|
getToolDefinitions() {
|
|
561
582
|
const defs = ['可用工具:'];
|
|
@@ -583,7 +604,7 @@ class PiAgentSession {
|
|
|
583
604
|
}
|
|
584
605
|
checkMinimax() {
|
|
585
606
|
try {
|
|
586
|
-
|
|
607
|
+
getMinimax();
|
|
587
608
|
return true;
|
|
588
609
|
}
|
|
589
610
|
catch {
|
|
@@ -609,25 +630,104 @@ class PiAgentSession {
|
|
|
609
630
|
role: 'user',
|
|
610
631
|
content: input
|
|
611
632
|
});
|
|
612
|
-
onStream({ type: 'thinking', content: '🤔
|
|
633
|
+
onStream({ type: 'thinking', content: '🤔 开始思考...' });
|
|
613
634
|
if (!this.minimaxAvailable) {
|
|
614
635
|
const response = await this.handleFallback(input);
|
|
615
636
|
this.messageHistory.push({ role: 'assistant', content: response });
|
|
616
637
|
onStream({ type: 'done', content: '' });
|
|
617
638
|
return response;
|
|
618
639
|
}
|
|
619
|
-
const result = await this.runReActLoop();
|
|
640
|
+
const result = await this.runReActLoop(onStream);
|
|
620
641
|
onStream({ type: 'done', content: '' });
|
|
621
642
|
return result;
|
|
622
643
|
}
|
|
623
|
-
async
|
|
624
|
-
|
|
644
|
+
async promptWithPivotLoop(input, config) {
|
|
645
|
+
if (!this.minimaxAvailable) {
|
|
646
|
+
const response = await this.handleFallback(input);
|
|
647
|
+
return {
|
|
648
|
+
success: false,
|
|
649
|
+
response,
|
|
650
|
+
iterations: 0,
|
|
651
|
+
toolCalls: 0,
|
|
652
|
+
qualityScore: 0,
|
|
653
|
+
exitReason: 'error',
|
|
654
|
+
state: {
|
|
655
|
+
iteration: 0,
|
|
656
|
+
totalTokens: 0,
|
|
657
|
+
toolCallsCount: 0,
|
|
658
|
+
consecutiveNoProgress: 0,
|
|
659
|
+
qualityScores: [],
|
|
660
|
+
pendingToolUses: [],
|
|
661
|
+
lastMeaningfulWork: 0
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
const llm = getMinimax();
|
|
666
|
+
const loopConfig = config || this.pivotLoopConfig || createDefaultPivotConfig();
|
|
667
|
+
const loop = new WorkflowPivotLoop(loopConfig);
|
|
668
|
+
for (const tool of this.tools.values()) {
|
|
669
|
+
loop.registerTool(tool);
|
|
670
|
+
}
|
|
671
|
+
const personaSection = this.persona ? `
|
|
672
|
+
角色描述: ${this.persona.description || '无'}
|
|
673
|
+
性格特点: ${this.persona.personality || '无'}
|
|
674
|
+
问候语: ${this.persona.greeting || '无'}
|
|
675
|
+
` : '';
|
|
676
|
+
const systemPrompt = `你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
|
|
677
|
+
当前工作目录: ${this.cwd}
|
|
678
|
+
当前身份: ${this.identity.name} (${this.identity.did})
|
|
679
|
+
|
|
680
|
+
${this.getToolDefinitions()}
|
|
681
|
+
|
|
682
|
+
工作模式:
|
|
683
|
+
1. 理解用户自然语言请求
|
|
684
|
+
2. 分析需要哪些工具来完成
|
|
685
|
+
3. 按顺序调用工具并观察结果
|
|
686
|
+
4. 根据观察结果决定下一步
|
|
687
|
+
5. 最终给出完整回答
|
|
688
|
+
|
|
689
|
+
重要:
|
|
690
|
+
- 每次只调用一个工具
|
|
691
|
+
- 仔细分析工具返回结果
|
|
692
|
+
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
693
|
+
- 如果需要更多信息,继续调用工具`;
|
|
694
|
+
const result = await loop.execute(input, llm, systemPrompt);
|
|
695
|
+
this.messageHistory.push({ role: 'user', content: input });
|
|
696
|
+
if (result.response) {
|
|
697
|
+
this.messageHistory.push({ role: 'assistant', content: result.response });
|
|
698
|
+
}
|
|
699
|
+
return result;
|
|
700
|
+
}
|
|
701
|
+
async runReActLoop(onStream) {
|
|
702
|
+
const llm = getMinimax();
|
|
625
703
|
let iteration = 0;
|
|
626
704
|
let finalResponse = '';
|
|
705
|
+
let lastQualityScore = 0;
|
|
706
|
+
let refineAttempts = 0;
|
|
707
|
+
let consecutiveErrors = 0;
|
|
708
|
+
const MAX_CONSECUTIVE_ERRORS = 3;
|
|
709
|
+
// 发送循环开始的事件
|
|
710
|
+
if (onStream) {
|
|
711
|
+
onStream({ type: 'status', content: '🔄 开始 ReAct 循环...', tool: 'system' });
|
|
712
|
+
}
|
|
627
713
|
while (iteration < this.MAX_REACT_ITERATIONS) {
|
|
628
714
|
iteration++;
|
|
715
|
+
// 调试日志:显示每次循环开始
|
|
716
|
+
console.log(`[PiAgent] 循环 ${iteration}/${this.MAX_REACT_ITERATIONS} 开始`);
|
|
717
|
+
if (onStream) {
|
|
718
|
+
onStream({ type: 'status', content: `🔄 循环 ${iteration}/${this.MAX_REACT_ITERATIONS}`, tool: 'loop' });
|
|
719
|
+
}
|
|
629
720
|
const context = this.buildContext();
|
|
630
721
|
const toolDefs = this.getToolDefinitions();
|
|
722
|
+
// 动态构建 refine 上下文
|
|
723
|
+
let refineContext = '';
|
|
724
|
+
if (refineAttempts > 0 && lastQualityScore < this.QUALITY_THRESHOLD) {
|
|
725
|
+
refineContext = `\n【改进提示】上轮结果质量分 ${(lastQualityScore * 10).toFixed(1)}/10,请改进回答。`;
|
|
726
|
+
}
|
|
727
|
+
// 连续错误时的额外提示
|
|
728
|
+
if (consecutiveErrors > 0) {
|
|
729
|
+
refineContext += `\n【错误提示】上轮发生 ${consecutiveErrors} 次错误,请重新分析问题或换一种方式处理。`;
|
|
730
|
+
}
|
|
631
731
|
const personaSection = this.persona ? `
|
|
632
732
|
角色描述: ${this.persona.description || '无'}
|
|
633
733
|
性格特点: ${this.persona.personality || '无'}
|
|
@@ -636,6 +736,7 @@ class PiAgentSession {
|
|
|
636
736
|
const systemPrompt = `你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
|
|
637
737
|
当前工作目录: ${this.cwd}
|
|
638
738
|
当前身份: ${this.identity.name} (${this.identity.did})
|
|
739
|
+
${refineContext}
|
|
639
740
|
|
|
640
741
|
${toolDefs}
|
|
641
742
|
|
|
@@ -649,11 +750,24 @@ ${toolDefs}
|
|
|
649
750
|
重要:
|
|
650
751
|
- 每次只调用一个工具
|
|
651
752
|
- 仔细分析工具返回结果
|
|
652
|
-
-
|
|
753
|
+
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
653
754
|
- 如果需要更多信息,继续调用工具`;
|
|
654
755
|
const response = await llm.chat(context, systemPrompt);
|
|
655
756
|
const reply = response.reply.trim();
|
|
757
|
+
console.log(`[PiAgent] LLM 回复长度: ${reply.length}, 内容预览: "${reply.substring(0, 80)}..."`);
|
|
758
|
+
// 通知前端:收到 LLM 回复
|
|
759
|
+
if (onStream) {
|
|
760
|
+
onStream({ type: 'token', content: reply.substring(0, 100) });
|
|
761
|
+
}
|
|
656
762
|
if (this.isFinalResponse(reply)) {
|
|
763
|
+
// 检查质量分数
|
|
764
|
+
lastQualityScore = this.estimateResponseQuality(reply);
|
|
765
|
+
// 如果质量太低且还有改进机会,进入改进循环
|
|
766
|
+
if (lastQualityScore < this.QUALITY_THRESHOLD && refineAttempts < this.MAX_REFINE_ATTEMPTS) {
|
|
767
|
+
refineAttempts++;
|
|
768
|
+
console.log(`[PiAgent] 质量评分 ${(lastQualityScore * 10).toFixed(1)}/10 < ${(this.QUALITY_THRESHOLD * 10).toFixed(1)}/10,自动改进中 (${refineAttempts}/${this.MAX_REFINE_ATTEMPTS})`);
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
657
771
|
finalResponse = this.extractFinalAnswer(reply);
|
|
658
772
|
break;
|
|
659
773
|
}
|
|
@@ -664,28 +778,123 @@ ${toolDefs}
|
|
|
664
778
|
content: reply,
|
|
665
779
|
toolCall
|
|
666
780
|
});
|
|
781
|
+
// 通知前端:检测到工具调用
|
|
782
|
+
if (onStream) {
|
|
783
|
+
onStream({ type: 'tool', content: `🔧 调用工具: ${toolCall.name}`, tool: toolCall.name });
|
|
784
|
+
if (toolCall.args && Object.keys(toolCall.args).length > 0) {
|
|
785
|
+
onStream({ type: 'status', content: `📋 参数: ${JSON.stringify(toolCall.args)}`, tool: toolCall.name });
|
|
786
|
+
}
|
|
787
|
+
}
|
|
667
788
|
const tool = this.tools.get(toolCall.name);
|
|
668
789
|
if (!tool) {
|
|
790
|
+
consecutiveErrors++;
|
|
669
791
|
const errorResult = { success: false, error: `未知工具: ${toolCall.name}` };
|
|
670
792
|
this.messageHistory.push({ role: 'tool', content: JSON.stringify(errorResult), toolResult: errorResult });
|
|
671
793
|
this.logToHarness(toolCall.name, toolCall.args, errorResult);
|
|
794
|
+
console.warn(`[PiAgent] 未知工具: ${toolCall.name},跳过并继续`);
|
|
672
795
|
continue;
|
|
673
796
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
797
|
+
try {
|
|
798
|
+
const result = await tool.execute(toolCall.args);
|
|
799
|
+
console.log(`[PiAgent] 工具 ${toolCall.name} 执行完成: success=${result.success}`);
|
|
800
|
+
this.messageHistory.push({ role: 'tool', content: JSON.stringify(result), toolResult: result });
|
|
801
|
+
this.logToHarness(toolCall.name, toolCall.args, result);
|
|
802
|
+
// 通知前端工具执行结果
|
|
803
|
+
if (onStream) {
|
|
804
|
+
if (result.success) {
|
|
805
|
+
onStream({ type: 'status', content: `✅ ${toolCall.name} 执行成功`, tool: toolCall.name });
|
|
806
|
+
if (result.output) {
|
|
807
|
+
const outputPreview = result.output.substring(0, 200);
|
|
808
|
+
onStream({ type: 'tool', content: `📤 结果: ${outputPreview}${result.output.length > 200 ? '...' : ''}`, tool: toolCall.name });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
onStream({ type: 'error', content: `❌ ${toolCall.name} 执行失败: ${result.error}`, tool: toolCall.name });
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (result.success) {
|
|
816
|
+
consecutiveErrors = 0; // 重置连续错误计数
|
|
817
|
+
// 检查工具执行质量
|
|
818
|
+
lastQualityScore = this.estimateToolResultQuality(result);
|
|
819
|
+
if (lastQualityScore < this.QUALITY_THRESHOLD && refineAttempts < this.MAX_REFINE_ATTEMPTS) {
|
|
820
|
+
refineAttempts++;
|
|
821
|
+
console.log(`[PiAgent] 工具结果质量低,自动重试 (${refineAttempts}/${this.MAX_REFINE_ATTEMPTS})`);
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
console.log(`[PiAgent] 工具执行成功,质量评分: ${(lastQualityScore * 10).toFixed(1)}/10`);
|
|
825
|
+
}
|
|
826
|
+
// 工具执行成功后,继续循环获取下一个 LLM 响应
|
|
827
|
+
if (onStream) {
|
|
828
|
+
onStream({ type: 'status', content: `🔄 工具执行完成,继续循环...`, tool: 'loop' });
|
|
829
|
+
}
|
|
830
|
+
// 不 break,继续下一次循环
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
consecutiveErrors++;
|
|
834
|
+
console.warn(`[PiAgent] 工具执行失败 (${consecutiveErrors}/${MAX_CONSECUTIVE_ERRORS}): ${result.error}`);
|
|
835
|
+
// 连续错误达到上限,尝试换一种方式
|
|
836
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
837
|
+
console.log(`[PiAgent] 连续 ${MAX_CONSECUTIVE_ERRORS} 次错误,尝试换一种方式处理`);
|
|
838
|
+
// 添加错误上下文,让 LLM 换一种方式
|
|
839
|
+
this.messageHistory.push({
|
|
840
|
+
role: 'system',
|
|
841
|
+
content: `[注意] 前面的工具调用连续失败。请尝试其他工具或换一种方式完成用户请求。`
|
|
842
|
+
});
|
|
843
|
+
consecutiveErrors = 0; // 重置以继续尝试
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
catch (execError) {
|
|
848
|
+
consecutiveErrors++;
|
|
849
|
+
const errorResult = { success: false, error: String(execError) };
|
|
850
|
+
this.messageHistory.push({ role: 'tool', content: JSON.stringify(errorResult), toolResult: errorResult });
|
|
851
|
+
this.logToHarness(toolCall.name, toolCall.args, errorResult);
|
|
852
|
+
console.error(`[PiAgent] 工具执行异常: ${execError}`);
|
|
679
853
|
}
|
|
680
854
|
}
|
|
681
855
|
else {
|
|
682
|
-
|
|
856
|
+
// LLM 返回的不是 tool call 格式
|
|
857
|
+
this.messageHistory.push({
|
|
858
|
+
role: 'assistant',
|
|
859
|
+
content: reply
|
|
860
|
+
});
|
|
861
|
+
// 通知前端收到非工具调用回复
|
|
862
|
+
if (onStream) {
|
|
863
|
+
onStream({ type: 'token', content: reply.substring(0, 150) });
|
|
864
|
+
}
|
|
865
|
+
// 检查是否需要继续循环处理
|
|
866
|
+
// 更严格的判断:只有当回复明确表示需要更多信息时才继续
|
|
867
|
+
const containsToolCallIntent = reply.includes('调用工具') || reply.includes('tool(') ||
|
|
868
|
+
reply.includes('使用工具') || reply.includes('需要获取') || reply.includes('需要查看');
|
|
869
|
+
const hasError = ['不存在', '找不到', '无法找到', 'not found', 'does not exist',
|
|
870
|
+
'错误', 'error', '失败', 'failed'].some(k => reply.includes(k));
|
|
871
|
+
const isTooShort = reply.length < 50 && reply.length > 0;
|
|
872
|
+
const hasQuestion = reply.includes('?') && (reply.includes('怎么') || reply.includes('如何') || reply.includes('什么'));
|
|
873
|
+
const needsMoreWork = hasError || containsToolCallIntent || isTooShort || hasQuestion;
|
|
874
|
+
if (needsMoreWork && iteration < this.MAX_REACT_ITERATIONS) {
|
|
875
|
+
console.log(`[PiAgent] 继续循环处理 (${iteration}/${this.MAX_REACT_ITERATIONS}): needsMoreWork=${needsMoreWork}, hasError=${hasError}, containsToolCallIntent=${containsToolCallIntent}`);
|
|
876
|
+
if (onStream) {
|
|
877
|
+
onStream({ type: 'status', content: `🔄 继续处理,循环 ${iteration}...`, tool: 'loop' });
|
|
878
|
+
}
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
// 否则把这个当作可能的最终回答
|
|
683
882
|
finalResponse = reply;
|
|
883
|
+
if (onStream) {
|
|
884
|
+
onStream({ type: 'status', content: `📝 提取最终回答,长度 ${reply.length}`, tool: 'system' });
|
|
885
|
+
}
|
|
684
886
|
break;
|
|
685
887
|
}
|
|
686
888
|
}
|
|
687
889
|
if (!finalResponse) {
|
|
688
890
|
finalResponse = '任务处理超时,请尝试更具体的请求。';
|
|
891
|
+
if (onStream) {
|
|
892
|
+
onStream({ type: 'error', content: '⚠️ 任务处理超时', tool: 'system' });
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
// 通知前端循环完成
|
|
896
|
+
if (onStream) {
|
|
897
|
+
onStream({ type: 'status', content: `✅ 处理完成,共 ${iteration - 1} 次循环`, tool: 'system' });
|
|
689
898
|
}
|
|
690
899
|
const now = new Date().toISOString();
|
|
691
900
|
const identityPrefix = `${this.identity.name} | bolloon 智能体
|
|
@@ -757,17 +966,23 @@ Workspace root folder: ${this.cwd}
|
|
|
757
966
|
}).join('\n');
|
|
758
967
|
}
|
|
759
968
|
isFinalResponse(content) {
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
return finalMarkers.some(m => lower.includes(m)) || (content.includes('✅') && content.length < 500);
|
|
969
|
+
// 只有明确输出 <final gen> 才认为是最终回答
|
|
970
|
+
return content.includes('<final gen>');
|
|
763
971
|
}
|
|
764
972
|
extractFinalAnswer(content) {
|
|
765
|
-
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
973
|
+
// 提取 <final gen> 后的内容作为最终回答
|
|
974
|
+
const marker = '<final gen>';
|
|
975
|
+
const markerIndex = content.indexOf(marker);
|
|
976
|
+
if (markerIndex !== -1) {
|
|
977
|
+
content = content.substring(markerIndex + marker.length).trim();
|
|
769
978
|
}
|
|
770
|
-
|
|
979
|
+
// 移除任何 tool call 标记
|
|
980
|
+
let cleaned = content
|
|
981
|
+
.replace(/调用工具[::]\s*\w+\s*\([^)]*\)/g, '')
|
|
982
|
+
.replace(/使用工具[::]\s*\w+\s*\([^)]*\)/g, '')
|
|
983
|
+
.replace(/tool[_\w]*[::]\s*\w+\s*\([^)]*\)/gi, '')
|
|
984
|
+
.trim();
|
|
985
|
+
return cleaned;
|
|
771
986
|
}
|
|
772
987
|
parseToolCall(content) {
|
|
773
988
|
const patterns = [
|
|
@@ -796,6 +1011,46 @@ Workspace root folder: ${this.cwd}
|
|
|
796
1011
|
}
|
|
797
1012
|
return null;
|
|
798
1013
|
}
|
|
1014
|
+
estimateResponseQuality(response) {
|
|
1015
|
+
let score = 0.5;
|
|
1016
|
+
if (response.length > 50)
|
|
1017
|
+
score += 0.1;
|
|
1018
|
+
if (response.length > 200)
|
|
1019
|
+
score += 0.1;
|
|
1020
|
+
if (response.length < 20)
|
|
1021
|
+
score -= 0.3;
|
|
1022
|
+
if (response.includes('\n'))
|
|
1023
|
+
score += 0.1;
|
|
1024
|
+
if (response.includes('-') || response.includes('•'))
|
|
1025
|
+
score += 0.05;
|
|
1026
|
+
if (response.includes('```'))
|
|
1027
|
+
score += 0.1;
|
|
1028
|
+
const conclusionWords = ['完成', '结果', '总结', '所以', '因此', '答案', '推荐'];
|
|
1029
|
+
if (conclusionWords.some(w => response.includes(w)))
|
|
1030
|
+
score += 0.1;
|
|
1031
|
+
if (response.includes('调用工具') || response.includes('tool('))
|
|
1032
|
+
score -= 0.2;
|
|
1033
|
+
return Math.max(0, Math.min(1, score));
|
|
1034
|
+
}
|
|
1035
|
+
estimateToolResultQuality(result) {
|
|
1036
|
+
let score = 0.5;
|
|
1037
|
+
if (!result.success)
|
|
1038
|
+
return 0.2;
|
|
1039
|
+
if (result.output) {
|
|
1040
|
+
score += 0.2;
|
|
1041
|
+
if (result.output.length > 50)
|
|
1042
|
+
score += 0.1;
|
|
1043
|
+
if (result.output.length < 10)
|
|
1044
|
+
score -= 0.1;
|
|
1045
|
+
if (result.output.includes('❌') || result.output.includes('error'))
|
|
1046
|
+
score -= 0.2;
|
|
1047
|
+
if (result.output.includes('✅') || result.output.includes('success'))
|
|
1048
|
+
score += 0.1;
|
|
1049
|
+
}
|
|
1050
|
+
if (result.error)
|
|
1051
|
+
score -= 0.3;
|
|
1052
|
+
return Math.max(0, Math.min(1, score));
|
|
1053
|
+
}
|
|
799
1054
|
async handleFallback(input) {
|
|
800
1055
|
const lowerInput = input.toLowerCase();
|
|
801
1056
|
const parts = input.trim().split(/\s+/);
|
|
@@ -829,10 +1084,38 @@ Workspace root folder: ${this.cwd}
|
|
|
829
1084
|
}
|
|
830
1085
|
return this.getDefaultResponse(input);
|
|
831
1086
|
}
|
|
1087
|
+
static OPERATIONS_REFERENCE = null;
|
|
1088
|
+
static getOperationsReference() {
|
|
1089
|
+
if (this.OPERATIONS_REFERENCE === null) {
|
|
1090
|
+
try {
|
|
1091
|
+
const refPath = path.join(process.cwd(), 'src', 'bollharness', 'scripts', 'context-fragments', 'pi-agent-operations.md');
|
|
1092
|
+
this.OPERATIONS_REFERENCE = fsSync.readFileSync(refPath, 'utf-8');
|
|
1093
|
+
}
|
|
1094
|
+
catch {
|
|
1095
|
+
this.OPERATIONS_REFERENCE = '';
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
return this.OPERATIONS_REFERENCE;
|
|
1099
|
+
}
|
|
832
1100
|
getDefaultResponse(input) {
|
|
1101
|
+
const operationsRef = PiAgentSession.getOperationsReference();
|
|
1102
|
+
if (operationsRef) {
|
|
1103
|
+
return `收到了: "${input}"
|
|
1104
|
+
|
|
1105
|
+
我是一个判断力处理智能体,支持自然语言交互。
|
|
1106
|
+
|
|
1107
|
+
可用操作(直接说出即可):
|
|
1108
|
+
${this.extractOperationsFromRef(operationsRef)}
|
|
1109
|
+
|
|
1110
|
+
示例请求:
|
|
1111
|
+
- "读取 src/index.ts 文件"
|
|
1112
|
+
- "总结一下 README.md"
|
|
1113
|
+
- "查看当前连接了哪些节点"
|
|
1114
|
+
- "向 QmABC... 发送测试消息"`;
|
|
1115
|
+
}
|
|
833
1116
|
return `收到了: "${input}"
|
|
834
1117
|
|
|
835
|
-
|
|
1118
|
+
我是一个判断力处理智能体,支持自然语言交互。
|
|
836
1119
|
|
|
837
1120
|
可用操作(直接说出即可):
|
|
838
1121
|
- "读取 README.md" - 读取并分析文档
|
|
@@ -849,13 +1132,44 @@ Workspace root folder: ${this.cwd}
|
|
|
849
1132
|
- "总结一下 README.md"
|
|
850
1133
|
- "查看当前连接了哪些节点"
|
|
851
1134
|
- "向 QmABC... 发送测试消息"`;
|
|
1135
|
+
}
|
|
1136
|
+
extractOperationsFromRef(ref) {
|
|
1137
|
+
const lines = ref.split('\n');
|
|
1138
|
+
const inOperationsSection = false;
|
|
1139
|
+
const operationLines = [];
|
|
1140
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1141
|
+
const line = lines[i];
|
|
1142
|
+
if (line.startsWith('## 可用操作')) {
|
|
1143
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
1144
|
+
const opLine = lines[j];
|
|
1145
|
+
if (opLine.startsWith('## ') || opLine.startsWith('#'))
|
|
1146
|
+
break;
|
|
1147
|
+
if (opLine.includes('|') && !opLine.startsWith('|')) {
|
|
1148
|
+
const parts = opLine.split('|').map(p => p.trim());
|
|
1149
|
+
if (parts.length >= 3 && parts[1] && parts[2]) {
|
|
1150
|
+
operationLines.push(` - "${parts[1]}" - ${parts[2]}`);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
break;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return operationLines.length > 0 ? operationLines.join('\n') :
|
|
1158
|
+
` - "读取 README.md" - 读取并分析文档
|
|
1159
|
+
- "总结文档" - 总结文档内容
|
|
1160
|
+
- "改进文档,按照X要求" - 改进文档
|
|
1161
|
+
- "查看节点" - 查看已连接的对等节点
|
|
1162
|
+
- "向X发送消息Y" - 向对等节点发送消息
|
|
1163
|
+
- "广播消息X" - 广播消息到所有节点
|
|
1164
|
+
- "查看身份" - 查看当前智能体身份
|
|
1165
|
+
- "查看日志" - 查看最近操作日志`;
|
|
852
1166
|
}
|
|
853
1167
|
async suggestRename(messages) {
|
|
854
1168
|
if (!this.minimaxAvailable || messages.length < 2) {
|
|
855
1169
|
return null;
|
|
856
1170
|
}
|
|
857
1171
|
const conversation = messages.map(m => `${m.type === 'user' ? '用户' : '助手'}: ${m.content}`).join('\n');
|
|
858
|
-
const llm =
|
|
1172
|
+
const llm = getMinimax();
|
|
859
1173
|
try {
|
|
860
1174
|
const response = await llm.chat(`根据以下对话内容,为这个对话生成一个简短的名称(不超过20个字):\n\n${conversation}\n\n直接输出名称,不要其他解释。`, '命名建议');
|
|
861
1175
|
const name = response.reply.trim();
|
|
@@ -872,12 +1186,12 @@ Workspace root folder: ${this.cwd}
|
|
|
872
1186
|
if (!this.minimaxAvailable) {
|
|
873
1187
|
return '⚠️ LLM未初始化,请设置 MINIMAX_API_KEY 环境变量';
|
|
874
1188
|
}
|
|
875
|
-
const llm =
|
|
1189
|
+
const llm = getMinimax();
|
|
876
1190
|
const result = await llm.summarize(text);
|
|
877
1191
|
return `📝 摘要:\n${result.summary}\n\n质量评分: ${(result.qualityScore * 10).toFixed(1)}/10`;
|
|
878
1192
|
}
|
|
879
1193
|
async readDocument(filePath) {
|
|
880
|
-
const content = await
|
|
1194
|
+
const content = await documentReader.read(filePath);
|
|
881
1195
|
this.sessionManager.addFileContext(filePath, content.text.substring(0, 1000));
|
|
882
1196
|
return `📄 ${content.metadata.filename}\n大小: ${content.metadata.size} 字节\n\n${content.text.substring(0, 500)}...`;
|
|
883
1197
|
}
|
|
@@ -888,10 +1202,10 @@ Workspace root folder: ${this.cwd}
|
|
|
888
1202
|
qualityScore: 0
|
|
889
1203
|
};
|
|
890
1204
|
}
|
|
891
|
-
const content = await
|
|
1205
|
+
const content = await documentReader.read(filePath);
|
|
892
1206
|
this.sessionManager.addFileContext(filePath, content.text.substring(0, 1000));
|
|
893
|
-
const llm =
|
|
894
|
-
const chunks =
|
|
1207
|
+
const llm = getMinimax();
|
|
1208
|
+
const chunks = documentReader.chunk(content.text);
|
|
895
1209
|
const summaries = [];
|
|
896
1210
|
let totalQuality = 0;
|
|
897
1211
|
for (const chunk of chunks) {
|
|
@@ -913,8 +1227,8 @@ Workspace root folder: ${this.cwd}
|
|
|
913
1227
|
shouldAutoSend: false
|
|
914
1228
|
};
|
|
915
1229
|
}
|
|
916
|
-
const content = await
|
|
917
|
-
const llm =
|
|
1230
|
+
const content = await documentReader.read(request.originalPath);
|
|
1231
|
+
const llm = getMinimax();
|
|
918
1232
|
const improvedResult = await llm.summarize(content.text + '\n\n改进要求: ' + request.requirements, request.context);
|
|
919
1233
|
const shouldAutoSend = await llm.shouldAutoSend(improvedResult.qualityScore, 0.7);
|
|
920
1234
|
return {
|
|
@@ -994,20 +1308,20 @@ Workspace root folder: ${this.cwd}
|
|
|
994
1308
|
return this.constraintLayer.getLogs();
|
|
995
1309
|
}
|
|
996
1310
|
listPeers() {
|
|
997
|
-
const peers =
|
|
1311
|
+
const peers = p2pNetwork.getPeers();
|
|
998
1312
|
if (peers.length === 0) {
|
|
999
1313
|
return '当前无连接的对等节点';
|
|
1000
1314
|
}
|
|
1001
1315
|
return `已连接节点 (${peers.length}):\n${peers.map(p => ` - ${p}`).join('\n')}`;
|
|
1002
1316
|
}
|
|
1003
1317
|
getPeers() {
|
|
1004
|
-
return
|
|
1318
|
+
return p2pNetwork.getPeers();
|
|
1005
1319
|
}
|
|
1006
1320
|
async sendMessage(peerId, message) {
|
|
1007
|
-
await
|
|
1321
|
+
await p2pNetwork.sendMessage(peerId, 'message', message);
|
|
1008
1322
|
}
|
|
1009
1323
|
async broadcast(message) {
|
|
1010
|
-
await
|
|
1324
|
+
await p2pNetwork.broadcast('message', message);
|
|
1011
1325
|
}
|
|
1012
1326
|
getIdentity() {
|
|
1013
1327
|
return { ...this.identity };
|
|
@@ -1070,7 +1384,7 @@ Workspace root folder: ${this.cwd}
|
|
|
1070
1384
|
if (this.socialHeartbeat) {
|
|
1071
1385
|
return;
|
|
1072
1386
|
}
|
|
1073
|
-
this.socialHeartbeat = await
|
|
1387
|
+
this.socialHeartbeat = await createSocialHeartbeat(this.sessionManager, this.agentsManager, config);
|
|
1074
1388
|
this.socialHeartbeat.setOnAgentDiscovered((agent) => {
|
|
1075
1389
|
console.log(`[Agent] 发现新智能体: ${agent.name}`);
|
|
1076
1390
|
});
|
|
@@ -1163,8 +1477,22 @@ Workspace root folder: ${this.cwd}
|
|
|
1163
1477
|
}
|
|
1164
1478
|
let sessionInstance = null;
|
|
1165
1479
|
let lastIdentityDid = null;
|
|
1166
|
-
|
|
1480
|
+
// 独立的 session 实例缓存(用于多 session 支持)
|
|
1481
|
+
const independentSessions = new Map();
|
|
1482
|
+
export async function createAgentSession(config, forceNew) {
|
|
1167
1483
|
const incomingDid = config.identityDoc?.did;
|
|
1484
|
+
const sessionKey = config.peerId || 'default';
|
|
1485
|
+
// 如果指定了 forceNew 或有独立的 session key,创建独立实例
|
|
1486
|
+
if (forceNew || (config.peerId && config.peerId.includes(':'))) {
|
|
1487
|
+
const key = `${sessionKey}:${forceNew ? Date.now() : ''}`;
|
|
1488
|
+
if (!forceNew && independentSessions.has(key)) {
|
|
1489
|
+
return independentSessions.get(key);
|
|
1490
|
+
}
|
|
1491
|
+
const session = new PiAgentSession(config);
|
|
1492
|
+
independentSessions.set(key, session);
|
|
1493
|
+
console.log(`[createAgentSession] 创建独立 session, key=${key}, DID=${incomingDid}`);
|
|
1494
|
+
return session;
|
|
1495
|
+
}
|
|
1168
1496
|
// 如果有新的 DID,强制重建 session
|
|
1169
1497
|
if (sessionInstance && lastIdentityDid && incomingDid && lastIdentityDid !== incomingDid) {
|
|
1170
1498
|
console.log(`[createAgentSession] DID 变化 ${lastIdentityDid} -> ${incomingDid},重建 session`);
|
|
@@ -1189,11 +1517,10 @@ async function createAgentSession(config) {
|
|
|
1189
1517
|
console.log(`[createAgentSession] 新建 session, DID=${lastIdentityDid}`);
|
|
1190
1518
|
return sessionInstance;
|
|
1191
1519
|
}
|
|
1192
|
-
function getAgentSession() {
|
|
1520
|
+
export function getAgentSession() {
|
|
1193
1521
|
return sessionInstance;
|
|
1194
1522
|
}
|
|
1195
|
-
function resetAgentSession() {
|
|
1523
|
+
export function resetAgentSession() {
|
|
1196
1524
|
sessionInstance = null;
|
|
1197
1525
|
lastIdentityDid = null;
|
|
1198
1526
|
}
|
|
1199
|
-
//# sourceMappingURL=pi-sdk.js.map
|