@bolloon/bolloon-agent 0.3.44 → 0.3.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -135
- package/bin/bolloon-cli.cjs +183 -183
- package/bin/bolloon-daemon.sh +207 -0
- package/bin/bolloon.cjs +0 -0
- package/dist/agents/agent-identity.js +17 -0
- package/dist/agents/constraint-layer.js +19 -19
- package/dist/agents/judgment-protocol.js +14 -14
- package/dist/agents/loop-review.js +21 -5
- package/dist/agents/pi-sdk-types.js +12 -12
- package/dist/agents/pi-sdk.js +197 -102
- package/dist/agents/skill-writer.js +19 -0
- package/dist/agents/workflow-pivot-loop.js +3 -3
- package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
- package/dist/bollharness-integration/context-router-judgment.js +4 -4
- package/dist/bollharness-integration/context-router.js +292 -292
- package/dist/bollharness-integration/gate-state-machine.js +13 -13
- package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
- package/dist/bollharness-integration/skill-adapter.js +21 -21
- package/dist/bootstrap/chat-archiver.js +14 -14
- package/dist/bootstrap/context-os.js +21 -21
- package/dist/bootstrap/memory-compressor.js +29 -13
- package/dist/cli-entry.js +47 -37
- package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +63 -0
- package/dist/constraint-runtime/reference_data/commands_snapshot.json +1037 -0
- package/dist/constraint-runtime/reference_data/subsystems/assistant.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/bridge.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/buddy.json +13 -0
- package/dist/constraint-runtime/reference_data/subsystems/cli.json +26 -0
- package/dist/constraint-runtime/reference_data/subsystems/components.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/constants.json +28 -0
- package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +15 -0
- package/dist/constraint-runtime/reference_data/subsystems/hooks.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +21 -0
- package/dist/constraint-runtime/reference_data/subsystems/memdir.json +15 -0
- package/dist/constraint-runtime/reference_data/subsystems/migrations.json +18 -0
- package/dist/constraint-runtime/reference_data/subsystems/moreright.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +11 -0
- package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/plugins.json +9 -0
- package/dist/constraint-runtime/reference_data/subsystems/remote.json +11 -0
- package/dist/constraint-runtime/reference_data/subsystems/schemas.json +8 -0
- package/dist/constraint-runtime/reference_data/subsystems/screens.json +10 -0
- package/dist/constraint-runtime/reference_data/subsystems/server.json +10 -0
- package/dist/constraint-runtime/reference_data/subsystems/services.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/skills.json +27 -0
- package/dist/constraint-runtime/reference_data/subsystems/state.json +13 -0
- package/dist/constraint-runtime/reference_data/subsystems/types.json +18 -0
- package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +9 -0
- package/dist/constraint-runtime/reference_data/subsystems/utils.json +32 -0
- package/dist/constraint-runtime/reference_data/subsystems/vim.json +12 -0
- package/dist/constraint-runtime/reference_data/subsystems/voice.json +8 -0
- package/dist/constraint-runtime/reference_data/tools_snapshot.json +922 -0
- package/dist/constraint-runtime/setup.js +1 -1
- package/dist/constraint-runtime/tools/PolymarketSDK/cancelOrder.d.ts +13 -3
- package/dist/constraint-runtime/tools/PolymarketSDK/cancelOrder.js +16 -4
- package/dist/constraint-runtime/tools/PolymarketSDK/clobShared.d.ts +50 -0
- package/dist/constraint-runtime/tools/PolymarketSDK/clobShared.js +78 -0
- package/dist/constraint-runtime/tools/PolymarketSDK/createOrder.d.ts +24 -3
- package/dist/constraint-runtime/tools/PolymarketSDK/createOrder.js +31 -4
- package/dist/constraint-runtime/tools/PolymarketSDK/getMarket.d.ts +1 -0
- package/dist/constraint-runtime/tools/PolymarketSDK/getMarket.js +14 -3
- package/dist/constraint-runtime/tools/PolymarketSDK/getOrders.d.ts +11 -2
- package/dist/constraint-runtime/tools/PolymarketSDK/getOrders.js +23 -4
- package/dist/constraint-runtime/tools/PolymarketSDK/listMarkets.d.ts +4 -0
- package/dist/constraint-runtime/tools/PolymarketSDK/listMarkets.js +22 -2
- package/dist/context-compaction/auto-compact.js +7 -7
- package/dist/electron/config.js.map +1 -0
- package/dist/electron/dialogs.js.map +1 -0
- package/dist/electron/first-run.js +54 -54
- package/dist/electron/first-run.js.map +1 -0
- package/dist/electron/ipc.js.map +1 -0
- package/dist/electron/logger.js.map +1 -0
- package/dist/electron/main.js.map +1 -0
- package/dist/electron/menu.js.map +1 -0
- package/dist/electron/paths.js.map +1 -0
- package/dist/electron/server.js.map +1 -0
- package/dist/electron/tray.js.map +1 -0
- package/dist/electron/window.js.map +1 -0
- package/dist/electron-build/electron/first-run.js +54 -54
- package/dist/electron-preload.js.map +1 -1
- package/dist/electron.js.map +1 -1
- package/dist/index.js +113 -113
- package/dist/llm/llm-judgment-client.js +102 -102
- package/dist/llm/pi-ai.js +48 -48
- package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
- package/dist/llm/system-prompt/layers/channel/local.md +14 -14
- package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
- package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
- package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
- package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
- package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
- package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
- package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
- package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
- package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
- package/dist/llm/system-prompt/layers/core/identity.md +48 -48
- package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
- package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
- package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
- package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
- package/dist/llm/system-prompt/layers/core/tone.md +31 -31
- package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
- package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
- package/dist/llm/system-prompt/layers/role/architect.md +20 -20
- package/dist/llm/system-prompt/layers/role/expert.md +19 -19
- package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
- package/dist/llm/system-prompt/layers/role/security.md +15 -15
- package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
- package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
- package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
- package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
- package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
- package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
- package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
- package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
- package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
- package/dist/llm/tool-manifest/ask_user_input.js +1 -1
- package/dist/llm/tool-manifest/bash.js +3 -3
- package/dist/llm/tool-manifest/create_file.js +4 -4
- package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
- package/dist/llm/tool-manifest/image_search.js +2 -2
- package/dist/llm/tool-manifest/index.js +59 -0
- package/dist/llm/tool-manifest/mcp.js +2 -2
- package/dist/llm/tool-manifest/message_compose.js +3 -3
- package/dist/llm/tool-manifest/places.js +2 -2
- package/dist/llm/tool-manifest/present_files.js +1 -1
- package/dist/llm/tool-manifest/recipe.js +2 -2
- package/dist/llm/tool-manifest/str_replace.js +5 -5
- package/dist/llm/tool-manifest/view.js +3 -3
- package/dist/llm/tool-manifest/weather.js +4 -4
- package/dist/llm/tool-manifest/web.js +4 -4
- package/dist/orbitdb/cid-database.js +41 -0
- package/dist/orbitdb/did-catalog-replication.js +199 -0
- package/dist/orbitdb/trajectory-store.js +150 -0
- package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
- package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
- package/dist/pi-ecosystem-judgment/distillation.js +14 -14
- package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
- package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
- package/dist/security/context-router-tool.js +15 -15
- package/dist/storage/did-catalog-bridge.js +271 -0
- package/dist/utils/auto-update.js.map +1 -0
- package/dist/web/api-config.html +779 -779
- package/dist/web/client-hearth.js +10 -10
- package/dist/web/client.js +141 -0
- package/dist/web/client.js.map +7 -0
- package/dist/web/components/wallet-viem.mjs +118 -118
- package/dist/web/index.html +472 -424
- package/dist/web/manifest.json +20 -20
- package/dist/web/server.js +290 -13
- package/dist/web/style.css +4946 -4914
- package/package.json +193 -193
- package/scripts/build-cli.js +215 -215
- package/scripts/build-web.ts +130 -130
- package/scripts/postinstall.js +152 -152
- package/bin/bolloon.js +0 -157
- package/dist/pi-ecosystem-colony/index.js +0 -365
- package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
- package/dist/social/ant-colony/PheromoneEngine.js +0 -227
- package/dist/social/ant-colony/index.js +0 -6
- package/dist/social/ant-colony/types.js +0 -24
- package/dist/test/ai-judgment-test.js +0 -80
- package/dist/test/bollharness-integration.test.js +0 -318
- package/dist/test/channel-agent-multi-dialogue.js +0 -205
- package/dist/test/channel-heartbeat-agent-test.js +0 -201
- package/dist/test/constraint-layer.test.js +0 -164
- package/dist/test/diap-identity-test.js +0 -172
- package/dist/test/diap-quick-test.js +0 -62
- package/dist/test/global-shared-context.test.js +0 -315
- package/dist/test/harness-judgment-injection.test.js +0 -246
- package/dist/test/harness-workflow-integrator-test.js +0 -228
- package/dist/test/human-value-store.test.js +0 -243
- package/dist/test/hybrid-integration-test.js +0 -118
- package/dist/test/hybrid-messenger-verify.js +0 -55
- package/dist/test/iroh-bistream-debug.js +0 -38
- package/dist/test/iroh-communication.test.js +0 -66
- package/dist/test/iroh-debug-test.js +0 -57
- package/dist/test/iroh-diap-test.js +0 -71
- package/dist/test/iroh-direct-connect.js +0 -55
- package/dist/test/iroh-e2e-fixed.js +0 -89
- package/dist/test/iroh-e2e-same-process.js +0 -63
- package/dist/test/iroh-e2e.js +0 -66
- package/dist/test/iroh-final-e2e.js +0 -72
- package/dist/test/iroh-relay-test.js +0 -37
- package/dist/test/iroh-simple-test.js +0 -41
- package/dist/test/iroh-transport-verify.js +0 -54
- package/dist/test/iroh-transport.test.js +0 -37
- package/dist/test/iroh-two-nodes.js +0 -70
- package/dist/test/iroh-verify.js +0 -44
- package/dist/test/judgment-decision.test.js +0 -219
- package/dist/test/llm-judgment-integration.test.js +0 -220
- package/dist/test/p2p-agent-complex-dialogue.js +0 -385
- package/dist/test/p2p-agent-dialogue.js +0 -341
- package/dist/test/p2p-agent-full-bidirectional.js +0 -510
- package/dist/test/p2p-agent-harness-flow.js +0 -437
- package/dist/test/p2p-agent-harness-single.js +0 -143
- package/dist/test/p2p-ai-dialogue-test.js +0 -318
- package/dist/test/p2p-cid-connect-test.js +0 -195
- package/dist/test/p2p-connect-receiver.js +0 -69
- package/dist/test/p2p-doc-transfer.js +0 -110
- package/dist/test/p2p-identity-page-test.js +0 -77
- package/dist/test/p2p-iroh-test.js +0 -171
- package/dist/test/p2p-minimal-test.js +0 -241
- package/dist/test/p2p-node-1.js +0 -148
- package/dist/test/p2p-node-2.js +0 -148
- package/dist/test/p2p-server.js +0 -281
- package/dist/test/p2p-two-nodes-test.js +0 -438
- package/dist/test/pi-sdk.test.js +0 -44
- package/dist/test/set-persona.js +0 -40
- package/dist/test/simple.test.js +0 -9
- package/dist/test/storage-integration.test.js +0 -150
- package/dist/test/subagent-manager.test.js +0 -276
- package/dist/test/test-gate-flow.test.js +0 -81
- package/dist/test/workflow-engine.test.js +0 -87
- package/dist/test/workflow-pivot-loop.test.js +0 -246
package/dist/agents/pi-sdk.js
CHANGED
|
@@ -596,9 +596,57 @@ export class PiAgentSession {
|
|
|
596
596
|
}
|
|
597
597
|
catch { /* 非致命 */ }
|
|
598
598
|
}
|
|
599
|
+
// ============================================================
|
|
600
|
+
// 2026-08-08: 运行轨迹采集 (trajectory) — 每轮运行 → 落盘 + OrbitDB, 失败静默
|
|
601
|
+
// ============================================================
|
|
602
|
+
async createTrajectoryRecorder(input, channelId) {
|
|
603
|
+
try {
|
|
604
|
+
const { TrajectoryRecorder } = await import('../orbitdb/trajectory-store.js');
|
|
605
|
+
const { resolveUserDid } = await import('../storage/did-catalog-bridge.js');
|
|
606
|
+
const did = await resolveUserDid();
|
|
607
|
+
const model = this.llmConfig?.model || this.model || '';
|
|
608
|
+
return new TrajectoryRecorder({
|
|
609
|
+
agentId: this.currentAgentId || 'default',
|
|
610
|
+
input,
|
|
611
|
+
channelId: channelId || this.currentChannelId,
|
|
612
|
+
did: did || undefined,
|
|
613
|
+
model: typeof model === 'string' && model ? model : undefined,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
catch {
|
|
617
|
+
return null; // 轨迹采集失败静默 (增强层)
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
wrapTrajectoryStream(onStream, rec) {
|
|
621
|
+
return (ev) => {
|
|
622
|
+
try {
|
|
623
|
+
rec?.recordStep?.(ev);
|
|
624
|
+
}
|
|
625
|
+
catch { /* 记录失败不影响转发 */ }
|
|
626
|
+
onStream(ev);
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
finishTrajectory(rec, reply, status = 'ok') {
|
|
630
|
+
if (!rec)
|
|
631
|
+
return;
|
|
632
|
+
// fire-and-forget: 不阻塞回复返回
|
|
633
|
+
(async () => {
|
|
634
|
+
try {
|
|
635
|
+
const { recordTrajectory } = await import('../orbitdb/trajectory-store.js');
|
|
636
|
+
const run = rec.endRun(reply, status);
|
|
637
|
+
await recordTrajectory(run, {});
|
|
638
|
+
}
|
|
639
|
+
catch { /* 静默 */ }
|
|
640
|
+
})();
|
|
641
|
+
}
|
|
599
642
|
async prompt(input, options) {
|
|
600
643
|
this.minimaxAvailable = this.checkMinimax();
|
|
601
644
|
this.currentChannelId = options?.channelId ?? this.currentChannelId;
|
|
645
|
+
// 2026-08-08: 运行轨迹采集 (落盘 + OrbitDB, 失败静默) — 包裹 onStream 收集步骤事件
|
|
646
|
+
const trajRec = await this.createTrajectoryRecorder(input, options?.channelId);
|
|
647
|
+
if (trajRec && options?.onStream) {
|
|
648
|
+
options = { ...options, onStream: this.wrapTrajectoryStream(options.onStream, trajRec) };
|
|
649
|
+
}
|
|
602
650
|
this.messageHistory.push({
|
|
603
651
|
role: 'user',
|
|
604
652
|
content: input
|
|
@@ -607,6 +655,7 @@ export class PiAgentSession {
|
|
|
607
655
|
const response = await this.handleFallback(input);
|
|
608
656
|
this.messageHistory.push({ role: 'assistant', content: response });
|
|
609
657
|
this.reportUsageToContextManager();
|
|
658
|
+
this.finishTrajectory(trajRec, response);
|
|
610
659
|
return response;
|
|
611
660
|
}
|
|
612
661
|
// P0 注入门
|
|
@@ -638,6 +687,7 @@ export class PiAgentSession {
|
|
|
638
687
|
if (this.usePivotLoop) {
|
|
639
688
|
try {
|
|
640
689
|
const lr = await this.promptWithPivotLoop(input, undefined, options?.channelId);
|
|
690
|
+
this.finishTrajectory(trajRec, lr.response || '');
|
|
641
691
|
return lr.response || '';
|
|
642
692
|
}
|
|
643
693
|
finally {
|
|
@@ -653,6 +703,7 @@ export class PiAgentSession {
|
|
|
653
703
|
try {
|
|
654
704
|
// 2026-06-16: runReActLoop 现在返回 { reply, aiFailed, aiFailureReason } — 这里只需 reply 字符串
|
|
655
705
|
const loopResult = await this.runReActLoop(this.currentOnStream ?? undefined, options?.signal);
|
|
706
|
+
this.finishTrajectory(trajRec, loopResult.reply, loopResult.aiFailed ? 'error' : 'ok');
|
|
656
707
|
return loopResult.reply;
|
|
657
708
|
}
|
|
658
709
|
finally {
|
|
@@ -673,6 +724,10 @@ export class PiAgentSession {
|
|
|
673
724
|
this.minimaxAvailable = this.checkMinimax();
|
|
674
725
|
console.log(`[PiAgent.promptStream] minimaxAvailable=${this.minimaxAvailable}`);
|
|
675
726
|
this.currentChannelId = channelId ?? this.currentChannelId;
|
|
727
|
+
// 2026-08-08: 运行轨迹采集 (落盘 + OrbitDB, 失败静默) — 包裹 onStream 收集步骤事件
|
|
728
|
+
const trajRec = await this.createTrajectoryRecorder(input, channelId);
|
|
729
|
+
if (trajRec)
|
|
730
|
+
onStream = this.wrapTrajectoryStream(onStream, trajRec);
|
|
676
731
|
// 2026-06-18 (supervisor): web server 把 46K markedPrompt 喂过来
|
|
677
732
|
// (【本轮用户请求】\n<text>\n【请求结束】\n\n<contextHint>).
|
|
678
733
|
// 整个 input 走下游, pivot loop 之前拿 47K buildContext 当 user message 发出去,
|
|
@@ -693,6 +748,7 @@ export class PiAgentSession {
|
|
|
693
748
|
this.messageHistory.push({ role: 'assistant', content: response });
|
|
694
749
|
onStream({ type: 'done', content: '' });
|
|
695
750
|
this.reportUsageToContextManager();
|
|
751
|
+
this.finishTrajectory(trajRec, response);
|
|
696
752
|
return response;
|
|
697
753
|
}
|
|
698
754
|
// P0 注入门: 缓存 onStream + signal, computeJudgmentGate 用 currentOnStream 广播 phase
|
|
@@ -840,6 +896,7 @@ export class PiAgentSession {
|
|
|
840
896
|
this.promptStartTime = 0;
|
|
841
897
|
this.reportUsageToContextManager();
|
|
842
898
|
}
|
|
899
|
+
this.finishTrajectory(trajRec, pivotResult);
|
|
843
900
|
return pivotResult;
|
|
844
901
|
}
|
|
845
902
|
// 2026-06-16: loop 自动重试 — runReActLoop 内部遇到 [AI 服务调用失败] sentinel 时,
|
|
@@ -929,6 +986,8 @@ export class PiAgentSession {
|
|
|
929
986
|
this.currentSignal = null;
|
|
930
987
|
this.bootstrapAddition = '';
|
|
931
988
|
this.promptStartTime = 0;
|
|
989
|
+
// 2026-08-08: 轨迹收尾 — 落盘 + OrbitDB (失败静默, 不阻塞回复)
|
|
990
|
+
this.finishTrajectory(trajRec, result);
|
|
932
991
|
return result;
|
|
933
992
|
}
|
|
934
993
|
async promptWithPivotLoop(input, config, channelId) {
|
|
@@ -972,38 +1031,38 @@ export class PiAgentSession {
|
|
|
972
1031
|
}
|
|
973
1032
|
// M2.4: persona 缓存
|
|
974
1033
|
if (!this.cachedPersonaSection && this.persona) {
|
|
975
|
-
this.cachedPersonaSection = `
|
|
976
|
-
角色描述: ${this.persona.description || '无'}
|
|
977
|
-
性格特点: ${this.persona.personality || '无'}
|
|
978
|
-
问候语: ${this.persona.greeting || '无'}
|
|
1034
|
+
this.cachedPersonaSection = `
|
|
1035
|
+
角色描述: ${this.persona.description || '无'}
|
|
1036
|
+
性格特点: ${this.persona.personality || '无'}
|
|
1037
|
+
问候语: ${this.persona.greeting || '无'}
|
|
979
1038
|
`;
|
|
980
1039
|
}
|
|
981
|
-
const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${this.cachedPersonaSection}
|
|
982
|
-
当前工作目录: ${this.cwd}
|
|
983
|
-
当前身份: ${this.identity.name} (${this.identity.did})
|
|
984
|
-
${this.currentIntentHint}
|
|
985
|
-
|
|
986
|
-
${this.getToolDefinitions()}
|
|
987
|
-
|
|
988
|
-
工作模式:
|
|
989
|
-
1. 理解用户自然语言请求
|
|
990
|
-
2. 分析需要哪些工具来完成
|
|
991
|
-
3. 按顺序调用工具并观察结果
|
|
992
|
-
4. 根据观察结果决定下一步
|
|
993
|
-
5. 最终给出完整回答
|
|
994
|
-
|
|
995
|
-
重要 (一次命中要求):
|
|
996
|
-
- 每次只调用一个工具
|
|
997
|
-
- 仔细分析工具返回结果
|
|
998
|
-
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
999
|
-
- 如果需要更多信息,继续调用工具
|
|
1000
|
-
|
|
1001
|
-
【工具调用格式 (严格遵守, 否则系统无法解析)】
|
|
1002
|
-
- 你只能输出**一个**工具调用, 不要堆叠多个 invoke
|
|
1003
|
-
- 工具调用格式: {"name":"<tool_name>","input":{"arg1":"value1"}}
|
|
1004
|
-
- 用 markdown json code block 包裹: \`\`\`json\n{"name":"X","input":{...}}\n\`\`\`
|
|
1005
|
-
- 工具调用前可以简短思考 (1-2 句话), 但**不要写长篇 thinking** (会撞 max_tokens)
|
|
1006
|
-
- 工具调用后必须等结果, 不要在同一个回复里继续输出
|
|
1040
|
+
const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${this.cachedPersonaSection}
|
|
1041
|
+
当前工作目录: ${this.cwd}
|
|
1042
|
+
当前身份: ${this.identity.name} (${this.identity.did})
|
|
1043
|
+
${this.currentIntentHint}
|
|
1044
|
+
|
|
1045
|
+
${this.getToolDefinitions()}
|
|
1046
|
+
|
|
1047
|
+
工作模式:
|
|
1048
|
+
1. 理解用户自然语言请求
|
|
1049
|
+
2. 分析需要哪些工具来完成
|
|
1050
|
+
3. 按顺序调用工具并观察结果
|
|
1051
|
+
4. 根据观察结果决定下一步
|
|
1052
|
+
5. 最终给出完整回答
|
|
1053
|
+
|
|
1054
|
+
重要 (一次命中要求):
|
|
1055
|
+
- 每次只调用一个工具
|
|
1056
|
+
- 仔细分析工具返回结果
|
|
1057
|
+
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
1058
|
+
- 如果需要更多信息,继续调用工具
|
|
1059
|
+
|
|
1060
|
+
【工具调用格式 (严格遵守, 否则系统无法解析)】
|
|
1061
|
+
- 你只能输出**一个**工具调用, 不要堆叠多个 invoke
|
|
1062
|
+
- 工具调用格式: {"name":"<tool_name>","input":{"arg1":"value1"}}
|
|
1063
|
+
- 用 markdown json code block 包裹: \`\`\`json\n{"name":"X","input":{...}}\n\`\`\`
|
|
1064
|
+
- 工具调用前可以简短思考 (1-2 句话), 但**不要写长篇 thinking** (会撞 max_tokens)
|
|
1065
|
+
- 工具调用后必须等结果, 不要在同一个回复里继续输出
|
|
1007
1066
|
- <final gen> 只在**真完成所有任务**时输出, 不要在工具调用前/中输出${this.judgmentGateAddition}${this.contextHintAddition}`;
|
|
1008
1067
|
// 2026-06-15: 把 currentOnStream 传给 loop, 让 step-timeline 在 pivot 循环里也能 emit step_start/done
|
|
1009
1068
|
// 之前 loop.execute() 不接 streamCallback, 导致 step-timeline 只能看到老 runReActLoop 路径
|
|
@@ -1070,6 +1129,10 @@ ${this.getToolDefinitions()}
|
|
|
1070
1129
|
// 上限=2 次 (用户要求"运行一两次"), 结束后按用户需求为准.
|
|
1071
1130
|
let loopReviewCount = 0;
|
|
1072
1131
|
const loopReviewCompletedTools = new Set();
|
|
1132
|
+
// 2026-08-09: 本轮行动日志 — 每轮工具执行都记录 (args + 结果摘要),
|
|
1133
|
+
// final 前 review 用逐条核查目标; 也注入 system prompt 让 LLM 看到连续进度
|
|
1134
|
+
// (防"每轮都像重启" — 之前 LLM 看不到自己已完成什么, 容易重复 react)
|
|
1135
|
+
const loopActionLog = [];
|
|
1073
1136
|
// 发送循环开始的事件
|
|
1074
1137
|
if (onStream) {
|
|
1075
1138
|
onStream({ type: 'status', content: '🔄 开始 ReAct 循环...', tool: 'system' });
|
|
@@ -1186,32 +1249,47 @@ ${this.getToolDefinitions()}
|
|
|
1186
1249
|
}
|
|
1187
1250
|
// M2.4: persona section 缓存 — persona 在 loadPersona() 时一次设定, 此后不变
|
|
1188
1251
|
if (!this.cachedPersonaSection && this.persona) {
|
|
1189
|
-
this.cachedPersonaSection = `
|
|
1190
|
-
角色描述: ${this.persona.description || '无'}
|
|
1191
|
-
性格特点: ${this.persona.personality || '无'}
|
|
1192
|
-
问候语: ${this.persona.greeting || '无'}
|
|
1252
|
+
this.cachedPersonaSection = `
|
|
1253
|
+
角色描述: ${this.persona.description || '无'}
|
|
1254
|
+
性格特点: ${this.persona.personality || '无'}
|
|
1255
|
+
问候语: ${this.persona.greeting || '无'}
|
|
1193
1256
|
`;
|
|
1194
1257
|
}
|
|
1195
1258
|
const personaSection = this.cachedPersonaSection;
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
1.
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1259
|
+
// 2026-08-09: 循环进度段 — 让 LLM 看到本轮已完成的动作 (连续进度, 不重启)
|
|
1260
|
+
// Hermes 式 Agent Runtime: 循环是状态机, LLM 每次看到的是"第 N 步 + 已完成 X"
|
|
1261
|
+
// (之前每轮都是全新上下文, LLM 不知道做过什么 → 重复 react / 衔接差)
|
|
1262
|
+
let loopProgressSection = '';
|
|
1263
|
+
if (loopActionLog.length > 0) {
|
|
1264
|
+
const actionLines = loopActionLog
|
|
1265
|
+
.map((a, i) => {
|
|
1266
|
+
const args = a.argsPreview ? `(${a.argsPreview.slice(0, 60)})` : '';
|
|
1267
|
+
const res = a.success ? '✓' : '✗';
|
|
1268
|
+
return ` ${i + 1}. ${res} ${a.tool}${args}`;
|
|
1269
|
+
})
|
|
1270
|
+
.join('\n');
|
|
1271
|
+
loopProgressSection = `\n【本轮循环进度】你已完成以下 ${loopActionLog.length} 个动作, 这是连续执行的同一轮任务:\n${actionLines}\n请基于已有结果继续推进, 不要重复执行上面已成功的动作. 全部完成后用 <final gen> 结束.\n`;
|
|
1272
|
+
}
|
|
1273
|
+
const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
|
|
1274
|
+
当前工作目录: ${this.cwd}
|
|
1275
|
+
当前身份: ${this.identity.name} (${this.identity.did})
|
|
1276
|
+
${refineContext}
|
|
1277
|
+
${this.currentIntentHint}
|
|
1278
|
+
${loopProgressSection}
|
|
1279
|
+
|
|
1280
|
+
${toolDefs}
|
|
1281
|
+
|
|
1282
|
+
工作模式:
|
|
1283
|
+
1. 理解用户自然语言请求
|
|
1284
|
+
2. 分析需要哪些工具来完成
|
|
1285
|
+
3. 按顺序调用工具并观察结果
|
|
1286
|
+
4. 根据观察结果决定下一步
|
|
1287
|
+
5. 最终给出完整回答
|
|
1288
|
+
|
|
1289
|
+
重要:
|
|
1290
|
+
- 每次只调用一个工具
|
|
1291
|
+
- 仔细分析工具返回结果
|
|
1292
|
+
- 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
|
|
1215
1293
|
- 如果需要更多信息,继续调用工具${this.judgmentGateAddition}${this.contextHintAddition}`;
|
|
1216
1294
|
// 3 个恢复机制 (Claude Code 论文 9-step pipeline 内部):
|
|
1217
1295
|
// 1. max output token 升级 (最多 3 次, 每次 maxOutputTokens 翻倍)
|
|
@@ -1302,9 +1380,10 @@ ${toolDefs}
|
|
|
1302
1380
|
}
|
|
1303
1381
|
console.log(`[PiAgent] LLM 回复长度: ${reply.length}, 内容预览: "${reply.substring(0, 80)}..."`);
|
|
1304
1382
|
console.log(`[PiAgent] LLM 完整回复:\n${reply}`);
|
|
1305
|
-
// 通知前端:收到 LLM 回复
|
|
1383
|
+
// 通知前端:收到 LLM 回复 (2026-08-09: 不再截断 100 字符 — 前端流式渲染完整内容,
|
|
1384
|
+
// 配合 Hermes 式回复框: 加载中显示完整文本, 完成后封闭底框)
|
|
1306
1385
|
if (onStream) {
|
|
1307
|
-
onStream({ type: 'token', content: reply
|
|
1386
|
+
onStream({ type: 'token', content: reply });
|
|
1308
1387
|
}
|
|
1309
1388
|
// 2026-06-19 架构 fix: parseToolCall 优先于 isFinalResponse
|
|
1310
1389
|
// 之前: 思考块里的 "<final gen>" 触发 isFinalResponse 提前 break, 工具从未真正执行
|
|
@@ -1356,9 +1435,10 @@ ${toolDefs}
|
|
|
1356
1435
|
content: reply,
|
|
1357
1436
|
toolCalls: toolCalls.length > 1 ? toolCalls : [toolCalls[0]],
|
|
1358
1437
|
});
|
|
1359
|
-
//
|
|
1360
|
-
|
|
1361
|
-
|
|
1438
|
+
// 2026-08-09: 并发执行本轮所有工具 (Hermes 式 Agent Runtime: 一轮内多工具并行,
|
|
1439
|
+
// 一轮没跑完之前不中断 — 工具执行不检查 abort, 全部完成才 continue 下一轮)
|
|
1440
|
+
// 旧实现顺序 for 循环, 一个工具等一个, 慢; 且多工具时 LLM 要等全部串完才能看到结果.
|
|
1441
|
+
await Promise.all(toolCalls.map(async (toolCall, ti) => {
|
|
1362
1442
|
const isMulti = toolCalls.length > 1;
|
|
1363
1443
|
// 通知前端
|
|
1364
1444
|
if (onStream) {
|
|
@@ -1391,7 +1471,7 @@ ${toolDefs}
|
|
|
1391
1471
|
const denyResultMsg = { success: false, error: `拒绝: [${denyResult.source}] ${denyResult.reason}` };
|
|
1392
1472
|
this.messageHistory.push({ role: 'tool', content: JSON.stringify(denyResultMsg), toolResult: denyResultMsg });
|
|
1393
1473
|
this.logToHarness(toolCall.name, toolCall.args, denyResultMsg);
|
|
1394
|
-
|
|
1474
|
+
return;
|
|
1395
1475
|
}
|
|
1396
1476
|
if (denyResult.systemAddition) {
|
|
1397
1477
|
this.contextHintAddition += '\n' + denyResult.systemAddition;
|
|
@@ -1410,7 +1490,7 @@ ${toolDefs}
|
|
|
1410
1490
|
if (onStream)
|
|
1411
1491
|
onStream({ type: 'status', content: `💡 Reflection: ${obs.summary}`, tool: 'system' });
|
|
1412
1492
|
console.warn(`[PiAgent] 未知工具: ${toolCall.name} (累计 ${totalErrors}/${this.MAX_TOTAL_ERRORS}),跳过并继续`);
|
|
1413
|
-
|
|
1493
|
+
return;
|
|
1414
1494
|
}
|
|
1415
1495
|
// Bootstrap PreToolUse hook: 调工具前校验 (危险命令拦截)
|
|
1416
1496
|
// 失败静默 — hook 自身挂掉 = 放行
|
|
@@ -1454,7 +1534,7 @@ ${toolDefs}
|
|
|
1454
1534
|
this.messageHistory.push({ role: 'system', content: `[注意] 连续 ${consecutiveErrors} 次工具调用被系统拒绝. 请换其他工具或直接回答用户, 末尾加 <final gen>.` });
|
|
1455
1535
|
consecutiveErrors = 0;
|
|
1456
1536
|
}
|
|
1457
|
-
|
|
1537
|
+
return;
|
|
1458
1538
|
}
|
|
1459
1539
|
}
|
|
1460
1540
|
catch (err) {
|
|
@@ -1491,7 +1571,7 @@ ${toolDefs}
|
|
|
1491
1571
|
this.messageHistory.push({ role: 'system', content: `[注意] 连续 ${consecutiveErrors} 次工具调用被 Harness 拒绝. 请换其他工具或直接回答.` });
|
|
1492
1572
|
consecutiveErrors = 0;
|
|
1493
1573
|
}
|
|
1494
|
-
|
|
1574
|
+
return;
|
|
1495
1575
|
}
|
|
1496
1576
|
}
|
|
1497
1577
|
catch (err) {
|
|
@@ -1528,6 +1608,20 @@ ${toolDefs}
|
|
|
1528
1608
|
}
|
|
1529
1609
|
this.messageHistory.push({ role: 'tool', content: JSON.stringify(result), toolResult: result, toolCallId: toolCall.id || `call_${Date.now()}_${Math.random().toString(36).slice(2, 8)}` });
|
|
1530
1610
|
this.logToHarness(toolCall.name, toolCall.args, result);
|
|
1611
|
+
// 2026-08-09: 记录到本轮行动日志 (循环进度 + final 前目标核查用)
|
|
1612
|
+
// 去重: 同一工具同 args 连续成功只记一次 (防 LLM 重复 react 刷屏)
|
|
1613
|
+
const argsPreview = JSON.stringify(toolCall.args || {}).slice(0, 120);
|
|
1614
|
+
const isDup = loopActionLog.some((a) => a.tool === toolCall.name && a.argsPreview === argsPreview && a.success === !!result.success);
|
|
1615
|
+
if (!isDup) {
|
|
1616
|
+
loopActionLog.push({
|
|
1617
|
+
tool: toolCall.name,
|
|
1618
|
+
argsPreview,
|
|
1619
|
+
resultPreview: result.success
|
|
1620
|
+
? String(result.output || '(无输出)').slice(0, 200)
|
|
1621
|
+
: String(result.error || 'failed').slice(0, 200),
|
|
1622
|
+
success: !!result.success,
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1531
1625
|
if (onStream) {
|
|
1532
1626
|
if (result.success) {
|
|
1533
1627
|
onStream({ type: 'status', content: `✅ ${toolCall.name} 执行成功`, tool: toolCall.name });
|
|
@@ -1585,7 +1679,7 @@ ${toolDefs}
|
|
|
1585
1679
|
lastFailedTool = '';
|
|
1586
1680
|
lastFailedToolCount = 0;
|
|
1587
1681
|
consecutiveErrors = 0;
|
|
1588
|
-
|
|
1682
|
+
return;
|
|
1589
1683
|
}
|
|
1590
1684
|
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
1591
1685
|
this.messageHistory.push({ role: 'system', content: `[注意] 前面的工具调用连续失败。请尝试其他工具或换一种方式完成用户请求, 或用 <final gen> 给出最终回答.` });
|
|
@@ -1606,7 +1700,7 @@ ${toolDefs}
|
|
|
1606
1700
|
onStream({ type: 'status', content: `💡 Reflection: ${obs.summary}`, tool: 'system' });
|
|
1607
1701
|
console.error(`[PiAgent] 工具执行异常 (累计 ${totalErrors}/${this.MAX_TOTAL_ERRORS}): ${execError}`);
|
|
1608
1702
|
}
|
|
1609
|
-
} // end
|
|
1703
|
+
})); // end Promise.all(toolCalls.map(async ...))
|
|
1610
1704
|
// 所有工具执行完毕后, continue while 循环, 让 LLM 看到结果
|
|
1611
1705
|
continue;
|
|
1612
1706
|
}
|
|
@@ -1616,9 +1710,9 @@ ${toolDefs}
|
|
|
1616
1710
|
role: 'assistant',
|
|
1617
1711
|
content: reply
|
|
1618
1712
|
});
|
|
1619
|
-
// 通知前端收到非工具调用回复
|
|
1713
|
+
// 通知前端收到非工具调用回复 (2026-08-09: 完整内容, 不再截断 150)
|
|
1620
1714
|
if (onStream) {
|
|
1621
|
-
onStream({ type: 'token', content: reply
|
|
1715
|
+
onStream({ type: 'token', content: reply });
|
|
1622
1716
|
}
|
|
1623
1717
|
// 2026-06-19 架构 fix: 只有 strip <think> 后才检查 isFinalResponse
|
|
1624
1718
|
// (parseToolCall 已先尝试, 既然没解析出 tool_call, 现在检查 final gen 是否真的在最终回答区)
|
|
@@ -1661,6 +1755,7 @@ ${toolDefs}
|
|
|
1661
1755
|
reviewsDone: loopReviewCount,
|
|
1662
1756
|
userIntent: this.currentIntentHint,
|
|
1663
1757
|
completedTools: Array.from(loopReviewCompletedTools),
|
|
1758
|
+
actionLog: loopActionLog,
|
|
1664
1759
|
}, DEFAULT_MAX_REVIEWS);
|
|
1665
1760
|
if (reviewDecision.kind === 'continue-review') {
|
|
1666
1761
|
loopReviewCount++;
|
|
@@ -2248,37 +2343,37 @@ ${toolDefs}
|
|
|
2248
2343
|
getDefaultResponse(input) {
|
|
2249
2344
|
const operationsRef = PiAgentSession.getOperationsReference();
|
|
2250
2345
|
if (operationsRef) {
|
|
2251
|
-
return `收到了: "${input}"
|
|
2252
|
-
|
|
2253
|
-
我是一个判断力处理智能体,支持自然语言交互。
|
|
2254
|
-
|
|
2255
|
-
可用操作(直接说出即可):
|
|
2256
|
-
${this.extractOperationsFromRef(operationsRef)}
|
|
2257
|
-
|
|
2258
|
-
示例请求:
|
|
2259
|
-
- "读取 src/index.ts 文件"
|
|
2260
|
-
- "总结一下 README.md"
|
|
2261
|
-
- "查看当前连接了哪些节点"
|
|
2346
|
+
return `收到了: "${input}"
|
|
2347
|
+
|
|
2348
|
+
我是一个判断力处理智能体,支持自然语言交互。
|
|
2349
|
+
|
|
2350
|
+
可用操作(直接说出即可):
|
|
2351
|
+
${this.extractOperationsFromRef(operationsRef)}
|
|
2352
|
+
|
|
2353
|
+
示例请求:
|
|
2354
|
+
- "读取 src/index.ts 文件"
|
|
2355
|
+
- "总结一下 README.md"
|
|
2356
|
+
- "查看当前连接了哪些节点"
|
|
2262
2357
|
- "向 QmABC... 发送测试消息"`;
|
|
2263
2358
|
}
|
|
2264
|
-
return `收到了: "${input}"
|
|
2265
|
-
|
|
2266
|
-
我是一个判断力处理智能体,支持自然语言交互。
|
|
2267
|
-
|
|
2268
|
-
可用操作(直接说出即可):
|
|
2269
|
-
- "读取 README.md" - 读取并分析文档
|
|
2270
|
-
- "总结文档" - 总结文档内容
|
|
2271
|
-
- "改进文档,按照X要求" - 改进文档
|
|
2272
|
-
- "查看节点" - 查看已连接的对等节点
|
|
2273
|
-
- "向X发送消息Y" - 向对等节点发送消息
|
|
2274
|
-
- "广播消息X" - 广播消息到所有节点
|
|
2275
|
-
- "查看身份" - 查看当前智能体身份
|
|
2276
|
-
- "查看日志" - 查看最近操作日志
|
|
2277
|
-
|
|
2278
|
-
示例请求:
|
|
2279
|
-
- "读取 src/index.ts 文件"
|
|
2280
|
-
- "总结一下 README.md"
|
|
2281
|
-
- "查看当前连接了哪些节点"
|
|
2359
|
+
return `收到了: "${input}"
|
|
2360
|
+
|
|
2361
|
+
我是一个判断力处理智能体,支持自然语言交互。
|
|
2362
|
+
|
|
2363
|
+
可用操作(直接说出即可):
|
|
2364
|
+
- "读取 README.md" - 读取并分析文档
|
|
2365
|
+
- "总结文档" - 总结文档内容
|
|
2366
|
+
- "改进文档,按照X要求" - 改进文档
|
|
2367
|
+
- "查看节点" - 查看已连接的对等节点
|
|
2368
|
+
- "向X发送消息Y" - 向对等节点发送消息
|
|
2369
|
+
- "广播消息X" - 广播消息到所有节点
|
|
2370
|
+
- "查看身份" - 查看当前智能体身份
|
|
2371
|
+
- "查看日志" - 查看最近操作日志
|
|
2372
|
+
|
|
2373
|
+
示例请求:
|
|
2374
|
+
- "读取 src/index.ts 文件"
|
|
2375
|
+
- "总结一下 README.md"
|
|
2376
|
+
- "查看当前连接了哪些节点"
|
|
2282
2377
|
- "向 QmABC... 发送测试消息"`;
|
|
2283
2378
|
}
|
|
2284
2379
|
extractOperationsFromRef(ref) {
|
|
@@ -2303,13 +2398,13 @@ ${this.extractOperationsFromRef(operationsRef)}
|
|
|
2303
2398
|
}
|
|
2304
2399
|
}
|
|
2305
2400
|
return operationLines.length > 0 ? operationLines.join('\n') :
|
|
2306
|
-
` - "读取 README.md" - 读取并分析文档
|
|
2307
|
-
- "总结文档" - 总结文档内容
|
|
2308
|
-
- "改进文档,按照X要求" - 改进文档
|
|
2309
|
-
- "查看节点" - 查看已连接的对等节点
|
|
2310
|
-
- "向X发送消息Y" - 向对等节点发送消息
|
|
2311
|
-
- "广播消息X" - 广播消息到所有节点
|
|
2312
|
-
- "查看身份" - 查看当前智能体身份
|
|
2401
|
+
` - "读取 README.md" - 读取并分析文档
|
|
2402
|
+
- "总结文档" - 总结文档内容
|
|
2403
|
+
- "改进文档,按照X要求" - 改进文档
|
|
2404
|
+
- "查看节点" - 查看已连接的对等节点
|
|
2405
|
+
- "向X发送消息Y" - 向对等节点发送消息
|
|
2406
|
+
- "广播消息X" - 广播消息到所有节点
|
|
2407
|
+
- "查看身份" - 查看当前智能体身份
|
|
2313
2408
|
- "查看日志" - 查看最近操作日志`;
|
|
2314
2409
|
}
|
|
2315
2410
|
async suggestRename(messages) {
|
|
@@ -61,6 +61,8 @@ export async function createSkill(name, description, body, opts = {}) {
|
|
|
61
61
|
try {
|
|
62
62
|
await fs.mkdir(skillDir, { recursive: true });
|
|
63
63
|
await fs.writeFile(file, content, 'utf-8');
|
|
64
|
+
// 2026-08-08 (DID 目录写穿): skill 落盘同步进 DID 目录 skills 表 (失败静默)
|
|
65
|
+
catalogSkillUpsert(`skill/${safeName}`, { name: safeName, kind: 'skill', description, file, size: content.length, updatedAt: Date.now() });
|
|
64
66
|
return { ok: true, path: file };
|
|
65
67
|
}
|
|
66
68
|
catch (e) {
|
|
@@ -115,6 +117,8 @@ export async function updateSkill(name, opts) {
|
|
|
115
117
|
}
|
|
116
118
|
const content = '---\n' + fmLines.join('\n') + '\n---\n\n' + body + '\n';
|
|
117
119
|
await fs.writeFile(file, content, 'utf-8');
|
|
120
|
+
// 2026-08-08 (DID 目录写穿): skill 更新同步进 DID 目录 skills 表 (失败静默)
|
|
121
|
+
catalogSkillUpsert(`skill/${safeName}`, { name: safeName, kind: 'skill', description: String(opts.description || ''), file, size: content.length, updatedAt: Date.now() });
|
|
118
122
|
return { ok: true, path: file };
|
|
119
123
|
}
|
|
120
124
|
catch (e) {
|
|
@@ -166,8 +170,23 @@ export async function writeSkillCandidate(c) {
|
|
|
166
170
|
catch { /* 新文件 */ }
|
|
167
171
|
const merged = { ...c, runs, body, timestamp: c.timestamp || new Date().toISOString() };
|
|
168
172
|
await fs.writeFile(file, JSON.stringify(merged, null, 2), 'utf-8');
|
|
173
|
+
// 2026-08-08 (DID 目录写穿): 候选同步进 DID 目录 skills 表 (失败静默)
|
|
174
|
+
catalogSkillUpsert(`candidate/${safeName}`, {
|
|
175
|
+
name: safeName, kind: 'candidate', description: c.description,
|
|
176
|
+
file, runs, signature: c.signature, size: merged.body.length, updatedAt: Date.now(),
|
|
177
|
+
});
|
|
169
178
|
return file;
|
|
170
179
|
}
|
|
180
|
+
/** 2026-08-08: skill 写入 → DID 目录 skills 表写穿 (WAL 事件 → 多设备同步/OrbitDB 复制). 失败静默. */
|
|
181
|
+
function catalogSkillUpsert(key, data) {
|
|
182
|
+
(async () => {
|
|
183
|
+
try {
|
|
184
|
+
const { catalogUpsertQuiet } = await import('../storage/did-catalog-bridge.js');
|
|
185
|
+
await catalogUpsertQuiet('skills', key, data);
|
|
186
|
+
}
|
|
187
|
+
catch { /* 静默 */ }
|
|
188
|
+
})();
|
|
189
|
+
}
|
|
171
190
|
export async function listSkillCandidates(home = os.homedir()) {
|
|
172
191
|
const dir = getCandidateDir(home);
|
|
173
192
|
let entries;
|
|
@@ -260,7 +260,7 @@ export class WorkflowPivotLoop {
|
|
|
260
260
|
const llmResponse = await llm.chat(context, headerForThisIter, signal, openAITools);
|
|
261
261
|
const reply = (llmResponse.reply || '').trim();
|
|
262
262
|
this.vlog(`[pivot] iter=${this.state.iteration} LLM took=${Date.now() - t0}ms reply=${reply.length} nativeToolCalls=${llmResponse.toolCalls?.length ?? 0} head=${reply.substring(0, 80).replace(/\n/g, ' ')}`);
|
|
263
|
-
this.emit({ type: 'token', content: reply
|
|
263
|
+
this.emit({ type: 'token', content: reply });
|
|
264
264
|
// 2026-07-06: 把完整 reply 推给前端 — 前端按需更新临时气泡
|
|
265
265
|
// 之前只 emit token(100B 截断), 前端拿到 100B 看不清. 现在 emit preview 带完整 content.
|
|
266
266
|
// 折叠 / 清洗交给前端的 message-renderer.addMessage (类型 ai 入口统一 strip).
|
|
@@ -778,8 +778,8 @@ export class WorkflowPivotLoop {
|
|
|
778
778
|
// 完整重装只在 iter=1 和 compact 之后两次
|
|
779
779
|
const lines = fullSystemPrompt.split('\n');
|
|
780
780
|
const identityLine = lines.find((l) => l.includes('你是') && !l.includes('(续)')) ?? '';
|
|
781
|
-
return `[continuation] 你的 persona + tools + judgments 已在首轮 messageHistory 中.
|
|
782
|
-
${identityLine ? identityLine + '\n' : ''}当前 step 别再读 persona 全文, 继续推进任务即可.
|
|
781
|
+
return `[continuation] 你的 persona + tools + judgments 已在首轮 messageHistory 中.
|
|
782
|
+
${identityLine ? identityLine + '\n' : ''}当前 step 别再读 persona 全文, 继续推进任务即可.
|
|
783
783
|
> <final gen> 只在真完成时输出.`;
|
|
784
784
|
}
|
|
785
785
|
/**
|
|
@@ -104,17 +104,17 @@ function checkRsync(cmd) {
|
|
|
104
104
|
function block(reason, host = null) {
|
|
105
105
|
let guidance;
|
|
106
106
|
if (host === PROD_IP) {
|
|
107
|
-
guidance = `请使用标准部署流程:
|
|
108
|
-
后端: bash scripts/deploy.sh --yes
|
|
109
|
-
Demo 正式: bash scripts/deploy-demo.sh <name> --channel prod --yes
|
|
110
|
-
Demo 内测: bash scripts/deploy-demo.sh <name> --channel preview --yes
|
|
111
|
-
Edge/Nginx: bash scripts/deploy-edge.sh --yes
|
|
107
|
+
guidance = `请使用标准部署流程:
|
|
108
|
+
后端: bash scripts/deploy.sh --yes
|
|
109
|
+
Demo 正式: bash scripts/deploy-demo.sh <name> --channel prod --yes
|
|
110
|
+
Demo 内测: bash scripts/deploy-demo.sh <name> --channel preview --yes
|
|
111
|
+
Edge/Nginx: bash scripts/deploy-edge.sh --yes
|
|
112
112
|
详见 Bolloon.md Development Commands。`;
|
|
113
113
|
}
|
|
114
114
|
else if (BRIDGE_VPS_HOSTS.includes(host ?? "")) {
|
|
115
|
-
guidance = `Bridge VPS 必须走 git pull 更新路径:
|
|
116
|
-
ssh root@${host} 'sudo -u boll git -C /opt/boll pull --ff-only'
|
|
117
|
-
scp/rsync 直传会重新制造 orphan worktree。
|
|
115
|
+
guidance = `Bridge VPS 必须走 git pull 更新路径:
|
|
116
|
+
ssh root@${host} 'sudo -u boll git -C /opt/boll pull --ff-only'
|
|
117
|
+
scp/rsync 直传会重新制造 orphan worktree。
|
|
118
118
|
详见 docs/issues/guard-20260408-0445-bridge-vps-orphan-worktree.md。`;
|
|
119
119
|
}
|
|
120
120
|
else {
|
|
@@ -253,9 +253,9 @@ export async function generateJudgmentInjection(filePath, gate, options = {}) {
|
|
|
253
253
|
const header = gate === 3
|
|
254
254
|
? '# Plan Freeze - Decision Principles'
|
|
255
255
|
: `# Gate ${gate} - Active Judgments`;
|
|
256
|
-
return `${header}
|
|
257
|
-
# Path: ${filePath}
|
|
258
|
-
# Confidence: ${(result.confidence * 100).toFixed(0)}%
|
|
259
|
-
|
|
256
|
+
return `${header}
|
|
257
|
+
# Path: ${filePath}
|
|
258
|
+
# Confidence: ${(result.confidence * 100).toFixed(0)}%
|
|
259
|
+
|
|
260
260
|
${result.contextYaml}`;
|
|
261
261
|
}
|