@bolloon/bolloon-agent 0.3.37 → 0.3.39

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.
Files changed (222) hide show
  1. package/README.md +135 -135
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon.cjs +0 -0
  4. package/bin/bolloon.js +157 -0
  5. package/dist/agents/constraint-layer.js +19 -19
  6. package/dist/agents/judgment-protocol.js +14 -14
  7. package/dist/agents/loop-review.js +58 -0
  8. package/dist/agents/pi-sdk-tools.js +107 -0
  9. package/dist/agents/pi-sdk-types.js +12 -12
  10. package/dist/agents/pi-sdk.js +133 -91
  11. package/dist/agents/workflow-pivot-loop.js +2 -2
  12. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  13. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  14. package/dist/bollharness-integration/context-router.js +292 -292
  15. package/dist/bollharness-integration/gate-state-machine.js +13 -13
  16. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  17. package/dist/bollharness-integration/skill-adapter.js +21 -21
  18. package/dist/bootstrap/bootstrap.js +14 -1
  19. package/dist/bootstrap/chat-archiver.js +14 -14
  20. package/dist/bootstrap/context-collector.js +5 -1
  21. package/dist/bootstrap/context-os.js +21 -21
  22. package/dist/bootstrap/memory-compressor.js +13 -13
  23. package/dist/cli/ink-app.js +46 -8
  24. package/dist/cli/loading-tui.js +7 -5
  25. package/dist/cli/mention-data.js +2 -1
  26. package/dist/cli-entry.js +37 -37
  27. package/dist/constraint-runtime/setup.js +1 -1
  28. package/dist/constraint-runtime/tools/PolymarketSDK/cancelOrder.d.ts +3 -13
  29. package/dist/constraint-runtime/tools/PolymarketSDK/cancelOrder.js +4 -16
  30. package/dist/constraint-runtime/tools/PolymarketSDK/createOrder.d.ts +3 -24
  31. package/dist/constraint-runtime/tools/PolymarketSDK/createOrder.js +4 -31
  32. package/dist/constraint-runtime/tools/PolymarketSDK/getMarket.d.ts +0 -1
  33. package/dist/constraint-runtime/tools/PolymarketSDK/getMarket.js +3 -14
  34. package/dist/constraint-runtime/tools/PolymarketSDK/getOrders.d.ts +2 -11
  35. package/dist/constraint-runtime/tools/PolymarketSDK/getOrders.js +4 -23
  36. package/dist/constraint-runtime/tools/PolymarketSDK/listMarkets.d.ts +0 -4
  37. package/dist/constraint-runtime/tools/PolymarketSDK/listMarkets.js +2 -22
  38. package/dist/context-compaction/auto-compact.js +7 -7
  39. package/dist/electron/first-run.js +54 -54
  40. package/dist/electron-build/electron/first-run.js +54 -54
  41. package/dist/electron-build/utils/auto-update.js +8 -0
  42. package/dist/electron-build/utils/auto-update.js.map +1 -1
  43. package/dist/electron-preload.js.map +1 -1
  44. package/dist/electron.js.map +1 -1
  45. package/dist/index.js +246 -143
  46. package/dist/llm/config-store.js +18 -2
  47. package/dist/llm/llm-judgment-client.js +102 -102
  48. package/dist/llm/pi-ai.js +77 -59
  49. package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
  50. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  51. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  52. package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
  53. package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
  54. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  55. package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
  56. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  57. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  58. package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
  59. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  60. package/dist/llm/system-prompt/layers/core/identity.md +48 -48
  61. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  62. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  63. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  64. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  65. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  66. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  67. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  68. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  69. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  70. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  71. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  72. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  73. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  74. package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
  75. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  76. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  77. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  78. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  79. package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
  80. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  81. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  82. package/dist/llm/tool-manifest/bash.js +3 -3
  83. package/dist/llm/tool-manifest/create_file.js +4 -4
  84. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  85. package/dist/llm/tool-manifest/image_search.js +2 -2
  86. package/dist/llm/tool-manifest/index.js +0 -59
  87. package/dist/llm/tool-manifest/mcp.js +2 -2
  88. package/dist/llm/tool-manifest/message_compose.js +3 -3
  89. package/dist/llm/tool-manifest/places.js +2 -2
  90. package/dist/llm/tool-manifest/present_files.js +1 -1
  91. package/dist/llm/tool-manifest/recipe.js +2 -2
  92. package/dist/llm/tool-manifest/str_replace.js +5 -5
  93. package/dist/llm/tool-manifest/view.js +3 -3
  94. package/dist/llm/tool-manifest/weather.js +4 -4
  95. package/dist/llm/tool-manifest/web.js +4 -4
  96. package/dist/migration/external-agent-migrator.js +300 -0
  97. package/dist/pi-ecosystem-colony/index.js +365 -0
  98. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  99. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  100. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  101. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  102. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  103. package/dist/security/context-router-tool.js +15 -15
  104. package/dist/security/tool-gate.js +2 -0
  105. package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
  106. package/dist/social/ant-colony/PheromoneEngine.js +227 -0
  107. package/dist/social/ant-colony/index.js +6 -0
  108. package/dist/social/ant-colony/types.js +24 -0
  109. package/dist/test/ai-judgment-test.js +80 -0
  110. package/dist/test/bollharness-integration.test.js +318 -0
  111. package/dist/test/channel-agent-multi-dialogue.js +205 -0
  112. package/dist/test/channel-heartbeat-agent-test.js +201 -0
  113. package/dist/test/constraint-layer.test.js +164 -0
  114. package/dist/test/diap-identity-test.js +172 -0
  115. package/dist/test/diap-quick-test.js +62 -0
  116. package/dist/test/global-shared-context.test.js +315 -0
  117. package/dist/test/harness-judgment-injection.test.js +246 -0
  118. package/dist/test/harness-workflow-integrator-test.js +228 -0
  119. package/dist/test/human-value-store.test.js +243 -0
  120. package/dist/test/hybrid-integration-test.js +118 -0
  121. package/dist/test/hybrid-messenger-verify.js +55 -0
  122. package/dist/test/iroh-bistream-debug.js +38 -0
  123. package/dist/test/iroh-communication.test.js +66 -0
  124. package/dist/test/iroh-debug-test.js +57 -0
  125. package/dist/test/iroh-diap-test.js +71 -0
  126. package/dist/test/iroh-direct-connect.js +55 -0
  127. package/dist/test/iroh-e2e-fixed.js +89 -0
  128. package/dist/test/iroh-e2e-same-process.js +63 -0
  129. package/dist/test/iroh-e2e.js +66 -0
  130. package/dist/test/iroh-final-e2e.js +72 -0
  131. package/dist/test/iroh-relay-test.js +37 -0
  132. package/dist/test/iroh-simple-test.js +41 -0
  133. package/dist/test/iroh-transport-verify.js +54 -0
  134. package/dist/test/iroh-transport.test.js +37 -0
  135. package/dist/test/iroh-two-nodes.js +70 -0
  136. package/dist/test/iroh-verify.js +44 -0
  137. package/dist/test/judgment-decision.test.js +219 -0
  138. package/dist/test/llm-judgment-integration.test.js +220 -0
  139. package/dist/test/p2p-agent-complex-dialogue.js +385 -0
  140. package/dist/test/p2p-agent-dialogue.js +341 -0
  141. package/dist/test/p2p-agent-full-bidirectional.js +510 -0
  142. package/dist/test/p2p-agent-harness-flow.js +437 -0
  143. package/dist/test/p2p-agent-harness-single.js +143 -0
  144. package/dist/test/p2p-ai-dialogue-test.js +318 -0
  145. package/dist/test/p2p-cid-connect-test.js +195 -0
  146. package/dist/test/p2p-connect-receiver.js +69 -0
  147. package/dist/test/p2p-doc-transfer.js +110 -0
  148. package/dist/test/p2p-identity-page-test.js +77 -0
  149. package/dist/test/p2p-iroh-test.js +171 -0
  150. package/dist/test/p2p-minimal-test.js +241 -0
  151. package/dist/test/p2p-node-1.js +148 -0
  152. package/dist/test/p2p-node-2.js +148 -0
  153. package/dist/test/p2p-server.js +281 -0
  154. package/dist/test/p2p-two-nodes-test.js +438 -0
  155. package/dist/test/pi-sdk.test.js +44 -0
  156. package/dist/test/set-persona.js +40 -0
  157. package/dist/test/simple.test.js +9 -0
  158. package/dist/test/storage-integration.test.js +150 -0
  159. package/dist/test/subagent-manager.test.js +276 -0
  160. package/dist/test/test-gate-flow.test.js +81 -0
  161. package/dist/test/workflow-engine.test.js +87 -0
  162. package/dist/test/workflow-pivot-loop.test.js +246 -0
  163. package/dist/utils/auto-update.js +7 -0
  164. package/dist/web/api-config.html +779 -779
  165. package/dist/web/client-hearth.js +10 -10
  166. package/dist/web/components/wallet-viem.mjs +118 -118
  167. package/dist/web/index.html +424 -424
  168. package/dist/web/manifest.json +20 -20
  169. package/dist/web/server.js +13 -13
  170. package/dist/web/style.css +4914 -4914
  171. package/package.json +193 -193
  172. package/scripts/build-cli.js +215 -215
  173. package/scripts/build-web.ts +130 -130
  174. package/scripts/postinstall.js +152 -152
  175. package/bin/bolloon-daemon.sh +0 -207
  176. package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +0 -63
  177. package/dist/constraint-runtime/reference_data/commands_snapshot.json +0 -1037
  178. package/dist/constraint-runtime/reference_data/subsystems/assistant.json +0 -8
  179. package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +0 -8
  180. package/dist/constraint-runtime/reference_data/subsystems/bridge.json +0 -32
  181. package/dist/constraint-runtime/reference_data/subsystems/buddy.json +0 -13
  182. package/dist/constraint-runtime/reference_data/subsystems/cli.json +0 -26
  183. package/dist/constraint-runtime/reference_data/subsystems/components.json +0 -32
  184. package/dist/constraint-runtime/reference_data/subsystems/constants.json +0 -28
  185. package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +0 -8
  186. package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +0 -15
  187. package/dist/constraint-runtime/reference_data/subsystems/hooks.json +0 -32
  188. package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +0 -21
  189. package/dist/constraint-runtime/reference_data/subsystems/memdir.json +0 -15
  190. package/dist/constraint-runtime/reference_data/subsystems/migrations.json +0 -18
  191. package/dist/constraint-runtime/reference_data/subsystems/moreright.json +0 -8
  192. package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +0 -11
  193. package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +0 -8
  194. package/dist/constraint-runtime/reference_data/subsystems/plugins.json +0 -9
  195. package/dist/constraint-runtime/reference_data/subsystems/remote.json +0 -11
  196. package/dist/constraint-runtime/reference_data/subsystems/schemas.json +0 -8
  197. package/dist/constraint-runtime/reference_data/subsystems/screens.json +0 -10
  198. package/dist/constraint-runtime/reference_data/subsystems/server.json +0 -10
  199. package/dist/constraint-runtime/reference_data/subsystems/services.json +0 -32
  200. package/dist/constraint-runtime/reference_data/subsystems/skills.json +0 -27
  201. package/dist/constraint-runtime/reference_data/subsystems/state.json +0 -13
  202. package/dist/constraint-runtime/reference_data/subsystems/types.json +0 -18
  203. package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +0 -9
  204. package/dist/constraint-runtime/reference_data/subsystems/utils.json +0 -32
  205. package/dist/constraint-runtime/reference_data/subsystems/vim.json +0 -12
  206. package/dist/constraint-runtime/reference_data/subsystems/voice.json +0 -8
  207. package/dist/constraint-runtime/reference_data/tools_snapshot.json +0 -922
  208. package/dist/constraint-runtime/tools/PolymarketSDK/clobShared.d.ts +0 -50
  209. package/dist/constraint-runtime/tools/PolymarketSDK/clobShared.js +0 -78
  210. package/dist/electron/config.js.map +0 -1
  211. package/dist/electron/dialogs.js.map +0 -1
  212. package/dist/electron/first-run.js.map +0 -1
  213. package/dist/electron/ipc.js.map +0 -1
  214. package/dist/electron/logger.js.map +0 -1
  215. package/dist/electron/main.js.map +0 -1
  216. package/dist/electron/menu.js.map +0 -1
  217. package/dist/electron/paths.js.map +0 -1
  218. package/dist/electron/server.js.map +0 -1
  219. package/dist/electron/tray.js.map +0 -1
  220. package/dist/electron/window.js.map +0 -1
  221. package/dist/utils/auto-update.js.map +0 -1
  222. package/dist/web/client.js.map +0 -7
@@ -13,6 +13,10 @@ import * as fsSync from 'fs';
13
13
  import * as os from 'os';
14
14
  import * as path from 'path';
15
15
  import { getContextManager } from '../bootstrap/context-manager.js';
16
+ import { createRequire } from 'module';
17
+ // 2026-08-07: ESM 下裸 require 抛错被 catch 吞掉 → estimateHistoryTokens/maxContextTokens 静默失效
18
+ // (状态栏恒 0 的第二层根因). 统一用 createRequire 加载 CJS 模块.
19
+ const _piRequire = createRequire(import.meta.url);
16
20
  import { documentReader } from '../documents/reader.js';
17
21
  import { getMinimax } from '../constraints/index.js';
18
22
  import { p2pNetwork } from '../network/p2p.js';
@@ -49,6 +53,7 @@ import { buildObservation, buildReflection, formatObservationWithReflection } fr
49
53
  import { sessionStore as defaultSessionStore } from './session-store.js';
50
54
  import { ToolRegistry } from './tool-registry.js';
51
55
  import { decideMaxIterations, decideContextOverflow, shouldCompactBeforeIteration } from './react-loop.js';
56
+ import { decideAfterReview, DEFAULT_MAX_REVIEWS } from './loop-review.js';
52
57
  // PiSessionManager 已抽到 ./pi-sdk-session-manager.ts (2026-07-06)
53
58
  // Tool / ToolResult / Message / StreamCallback / StreamEvent / HeartbeatConfig / AgentSession / TOOL_DEFINITIONS
54
59
  // 已抽到 ./pi-sdk-types.ts (2026-07-06)
@@ -90,7 +95,7 @@ export class PiAgentSession {
90
95
  /** 2026-08-06: 上下文窗口 (tokens) — 统一走 ContextManager 配置 (1M 默认). */
91
96
  maxContextTokens() {
92
97
  try {
93
- const { getContextManager } = require('../bootstrap/context-manager.js');
98
+ const { getContextManager } = _piRequire('../bootstrap/context-manager.js');
94
99
  const n = getContextManager().getConfig().maxTokens;
95
100
  return Number.isFinite(n) && n > 0 ? n : this.MAX_OUTPUT_TOKEN_ESCALATION_THRESHOLD;
96
101
  }
@@ -574,6 +579,14 @@ export class PiAgentSession {
574
579
  return false;
575
580
  }
576
581
  }
582
+ /** 2026-08-07: prompt 出口统一上报 token 用量到 ContextManager (fallback/pivot/react 全路径覆盖) —
583
+ * 之前只有 runReActLoop 迭代内上报, chitchat/fallback/pivot 路径状态栏恒 0 */
584
+ reportUsageToContextManager() {
585
+ try {
586
+ getContextManager().updateUsage(this.estimateHistoryTokens());
587
+ }
588
+ catch { /* 非致命 */ }
589
+ }
577
590
  async prompt(input, options) {
578
591
  this.minimaxAvailable = this.checkMinimax();
579
592
  this.currentChannelId = options?.channelId ?? this.currentChannelId;
@@ -584,6 +597,7 @@ export class PiAgentSession {
584
597
  if (!this.minimaxAvailable) {
585
598
  const response = await this.handleFallback(input);
586
599
  this.messageHistory.push({ role: 'assistant', content: response });
600
+ this.reportUsageToContextManager();
587
601
  return response;
588
602
  }
589
603
  // P0 注入门
@@ -624,6 +638,7 @@ export class PiAgentSession {
624
638
  this.clearJudgmentGate();
625
639
  this.currentSignal = null;
626
640
  this.currentOnStream = null;
641
+ this.reportUsageToContextManager();
627
642
  }
628
643
  }
629
644
  try {
@@ -641,6 +656,7 @@ export class PiAgentSession {
641
656
  this.clearJudgmentGate();
642
657
  this.currentSignal = null;
643
658
  this.currentOnStream = null;
659
+ this.reportUsageToContextManager();
644
660
  }
645
661
  }
646
662
  async promptStream(input, onStream, signal, channelId) {
@@ -667,6 +683,7 @@ export class PiAgentSession {
667
683
  const response = await this.handleFallback(userText);
668
684
  this.messageHistory.push({ role: 'assistant', content: response });
669
685
  onStream({ type: 'done', content: '' });
686
+ this.reportUsageToContextManager();
670
687
  return response;
671
688
  }
672
689
  // P0 注入门: 缓存 onStream + signal, computeJudgmentGate 用 currentOnStream 广播 phase
@@ -812,6 +829,7 @@ export class PiAgentSession {
812
829
  this.bootstrapAddition = '';
813
830
  this.contextHintAddition = '';
814
831
  this.promptStartTime = 0;
832
+ this.reportUsageToContextManager();
815
833
  }
816
834
  return pivotResult;
817
835
  }
@@ -898,6 +916,7 @@ export class PiAgentSession {
898
916
  // 用完即清, 避免污染下一轮
899
917
  this.clearJudgmentGate();
900
918
  this.currentOnStream = null;
919
+ this.reportUsageToContextManager();
901
920
  this.currentSignal = null;
902
921
  this.bootstrapAddition = '';
903
922
  this.promptStartTime = 0;
@@ -944,38 +963,38 @@ export class PiAgentSession {
944
963
  }
945
964
  // M2.4: persona 缓存
946
965
  if (!this.cachedPersonaSection && this.persona) {
947
- this.cachedPersonaSection = `
948
- 角色描述: ${this.persona.description || '无'}
949
- 性格特点: ${this.persona.personality || '无'}
950
- 问候语: ${this.persona.greeting || '无'}
966
+ this.cachedPersonaSection = `
967
+ 角色描述: ${this.persona.description || '无'}
968
+ 性格特点: ${this.persona.personality || '无'}
969
+ 问候语: ${this.persona.greeting || '无'}
951
970
  `;
952
971
  }
953
- const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${this.cachedPersonaSection}
954
- 当前工作目录: ${this.cwd}
955
- 当前身份: ${this.identity.name} (${this.identity.did})
956
- ${this.currentIntentHint}
957
-
958
- ${this.getToolDefinitions()}
959
-
960
- 工作模式:
961
- 1. 理解用户自然语言请求
962
- 2. 分析需要哪些工具来完成
963
- 3. 按顺序调用工具并观察结果
964
- 4. 根据观察结果决定下一步
965
- 5. 最终给出完整回答
966
-
967
- 重要 (一次命中要求):
968
- - 每次只调用一个工具
969
- - 仔细分析工具返回结果
970
- - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
971
- - 如果需要更多信息,继续调用工具
972
-
973
- 【工具调用格式 (严格遵守, 否则系统无法解析)】
974
- - 你只能输出**一个**工具调用, 不要堆叠多个 invoke
975
- - 工具调用格式: {"name":"<tool_name>","input":{"arg1":"value1"}}
976
- - 用 markdown json code block 包裹: \`\`\`json\n{"name":"X","input":{...}}\n\`\`\`
977
- - 工具调用前可以简短思考 (1-2 句话), 但**不要写长篇 thinking** (会撞 max_tokens)
978
- - 工具调用后必须等结果, 不要在同一个回复里继续输出
972
+ const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${this.cachedPersonaSection}
973
+ 当前工作目录: ${this.cwd}
974
+ 当前身份: ${this.identity.name} (${this.identity.did})
975
+ ${this.currentIntentHint}
976
+
977
+ ${this.getToolDefinitions()}
978
+
979
+ 工作模式:
980
+ 1. 理解用户自然语言请求
981
+ 2. 分析需要哪些工具来完成
982
+ 3. 按顺序调用工具并观察结果
983
+ 4. 根据观察结果决定下一步
984
+ 5. 最终给出完整回答
985
+
986
+ 重要 (一次命中要求):
987
+ - 每次只调用一个工具
988
+ - 仔细分析工具返回结果
989
+ - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
990
+ - 如果需要更多信息,继续调用工具
991
+
992
+ 【工具调用格式 (严格遵守, 否则系统无法解析)】
993
+ - 你只能输出**一个**工具调用, 不要堆叠多个 invoke
994
+ - 工具调用格式: {"name":"<tool_name>","input":{"arg1":"value1"}}
995
+ - 用 markdown json code block 包裹: \`\`\`json\n{"name":"X","input":{...}}\n\`\`\`
996
+ - 工具调用前可以简短思考 (1-2 句话), 但**不要写长篇 thinking** (会撞 max_tokens)
997
+ - 工具调用后必须等结果, 不要在同一个回复里继续输出
979
998
  - <final gen> 只在**真完成所有任务**时输出, 不要在工具调用前/中输出${this.judgmentGateAddition}${this.contextHintAddition}`;
980
999
  // 2026-06-15: 把 currentOnStream 传给 loop, 让 step-timeline 在 pivot 循环里也能 emit step_start/done
981
1000
  // 之前 loop.execute() 不接 streamCallback, 导致 step-timeline 只能看到老 runReActLoop 路径
@@ -1037,6 +1056,11 @@ ${this.getToolDefinitions()}
1037
1056
  const MAX_TOOL_CALLS_PER_LOOP = 25; // 单轮循环总工具调用上限 → 注入 hint
1038
1057
  let totalToolCallsThisLoop = 0;
1039
1058
  const lastNTools = []; // 最近 MAX_IDEMPOTENT_TOOL 次工具名, 检测重复
1059
+ // 2026-08-08: final 前 review 续跑 — 目标对齐 + 需求深挖 (见 loop-review.ts)
1060
+ // 不潦草收尾: LLM 想 <final gen> 时先跑 1-2 次 review, 达成用户需求才放行.
1061
+ // 上限=2 次 (用户要求"运行一两次"), 结束后按用户需求为准.
1062
+ let loopReviewCount = 0;
1063
+ const loopReviewCompletedTools = new Set();
1040
1064
  // 发送循环开始的事件
1041
1065
  if (onStream) {
1042
1066
  onStream({ type: 'status', content: '🔄 开始 ReAct 循环...', tool: 'system' });
@@ -1153,32 +1177,32 @@ ${this.getToolDefinitions()}
1153
1177
  }
1154
1178
  // M2.4: persona section 缓存 — persona 在 loadPersona() 时一次设定, 此后不变
1155
1179
  if (!this.cachedPersonaSection && this.persona) {
1156
- this.cachedPersonaSection = `
1157
- 角色描述: ${this.persona.description || '无'}
1158
- 性格特点: ${this.persona.personality || '无'}
1159
- 问候语: ${this.persona.greeting || '无'}
1180
+ this.cachedPersonaSection = `
1181
+ 角色描述: ${this.persona.description || '无'}
1182
+ 性格特点: ${this.persona.personality || '无'}
1183
+ 问候语: ${this.persona.greeting || '无'}
1160
1184
  `;
1161
1185
  }
1162
1186
  const personaSection = this.cachedPersonaSection;
1163
- const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
1164
- 当前工作目录: ${this.cwd}
1165
- 当前身份: ${this.identity.name} (${this.identity.did})
1166
- ${refineContext}
1167
- ${this.currentIntentHint}
1168
-
1169
- ${toolDefs}
1170
-
1171
- 工作模式:
1172
- 1. 理解用户自然语言请求
1173
- 2. 分析需要哪些工具来完成
1174
- 3. 按顺序调用工具并观察结果
1175
- 4. 根据观察结果决定下一步
1176
- 5. 最终给出完整回答
1177
-
1178
- 重要:
1179
- - 每次只调用一个工具
1180
- - 仔细分析工具返回结果
1181
- - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
1187
+ const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
1188
+ 当前工作目录: ${this.cwd}
1189
+ 当前身份: ${this.identity.name} (${this.identity.did})
1190
+ ${refineContext}
1191
+ ${this.currentIntentHint}
1192
+
1193
+ ${toolDefs}
1194
+
1195
+ 工作模式:
1196
+ 1. 理解用户自然语言请求
1197
+ 2. 分析需要哪些工具来完成
1198
+ 3. 按顺序调用工具并观察结果
1199
+ 4. 根据观察结果决定下一步
1200
+ 5. 最终给出完整回答
1201
+
1202
+ 重要:
1203
+ - 每次只调用一个工具
1204
+ - 仔细分析工具返回结果
1205
+ - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
1182
1206
  - 如果需要更多信息,继续调用工具${this.judgmentGateAddition}${this.contextHintAddition}`;
1183
1207
  // 3 个恢复机制 (Claude Code 论文 9-step pipeline 内部):
1184
1208
  // 1. max output token 升级 (最多 3 次, 每次 maxOutputTokens 翻倍)
@@ -1521,6 +1545,7 @@ ${toolDefs}
1521
1545
  else {
1522
1546
  this.successfulToolResults.push({ tool: toolCall.name, outputPreview: '(无输出)' });
1523
1547
  }
1548
+ loopReviewCompletedTools.add(toolCall.name);
1524
1549
  lastQualityScore = this.estimateToolResultQuality(result);
1525
1550
  if (lastQualityScore < this.QUALITY_THRESHOLD && refineAttempts < this.MAX_REFINE_ATTEMPTS) {
1526
1551
  refineAttempts++;
@@ -1620,6 +1645,23 @@ ${toolDefs}
1620
1645
  refineAttempts++;
1621
1646
  continue;
1622
1647
  }
1648
+ // 2026-08-08: final 前目标对齐 review — 不潦草收尾 (见 loop-review.ts)
1649
+ // LLM 想 <final gen> 时, 先跑 1-2 次「目标对齐 + 需求深挖」review;
1650
+ // 达成用户需求才放行真正结束. 达上限或无需深挖则以用户需求为准结束.
1651
+ const reviewDecision = decideAfterReview({
1652
+ reviewsDone: loopReviewCount,
1653
+ userIntent: this.currentIntentHint,
1654
+ completedTools: Array.from(loopReviewCompletedTools),
1655
+ }, DEFAULT_MAX_REVIEWS);
1656
+ if (reviewDecision.kind === 'continue-review') {
1657
+ loopReviewCount++;
1658
+ console.log(`[PiAgent] review ${loopReviewCount}/${DEFAULT_MAX_REVIEWS}: LLM 想 final 但先对齐需求深挖一次`);
1659
+ this.messageHistory.push({ role: 'system', content: reviewDecision.hint });
1660
+ if (onStream) {
1661
+ onStream({ type: 'status', content: `🔄 目标对齐 review ${loopReviewCount}/${DEFAULT_MAX_REVIEWS}: 深挖续跑`, tool: 'system' });
1662
+ }
1663
+ continue; // 让 LLM 看到 hint, 深挖或确认完成后再次 final
1664
+ }
1623
1665
  finalResponse = this.extractFinalAnswer(reply);
1624
1666
  break;
1625
1667
  }
@@ -1823,7 +1865,7 @@ ${toolDefs}
1823
1865
  */
1824
1866
  estimateHistoryTokens() {
1825
1867
  try {
1826
- const { estimateTokens } = require('../context-compaction/index.js');
1868
+ const { estimateTokens } = _piRequire('../context-compaction/index.js');
1827
1869
  return estimateTokens(this.messageHistory);
1828
1870
  }
1829
1871
  catch {
@@ -2197,37 +2239,37 @@ ${toolDefs}
2197
2239
  getDefaultResponse(input) {
2198
2240
  const operationsRef = PiAgentSession.getOperationsReference();
2199
2241
  if (operationsRef) {
2200
- return `收到了: "${input}"
2201
-
2202
- 我是一个判断力处理智能体,支持自然语言交互。
2203
-
2204
- 可用操作(直接说出即可):
2205
- ${this.extractOperationsFromRef(operationsRef)}
2206
-
2207
- 示例请求:
2208
- - "读取 src/index.ts 文件"
2209
- - "总结一下 README.md"
2210
- - "查看当前连接了哪些节点"
2242
+ return `收到了: "${input}"
2243
+
2244
+ 我是一个判断力处理智能体,支持自然语言交互。
2245
+
2246
+ 可用操作(直接说出即可):
2247
+ ${this.extractOperationsFromRef(operationsRef)}
2248
+
2249
+ 示例请求:
2250
+ - "读取 src/index.ts 文件"
2251
+ - "总结一下 README.md"
2252
+ - "查看当前连接了哪些节点"
2211
2253
  - "向 QmABC... 发送测试消息"`;
2212
2254
  }
2213
- return `收到了: "${input}"
2214
-
2215
- 我是一个判断力处理智能体,支持自然语言交互。
2216
-
2217
- 可用操作(直接说出即可):
2218
- - "读取 README.md" - 读取并分析文档
2219
- - "总结文档" - 总结文档内容
2220
- - "改进文档,按照X要求" - 改进文档
2221
- - "查看节点" - 查看已连接的对等节点
2222
- - "向X发送消息Y" - 向对等节点发送消息
2223
- - "广播消息X" - 广播消息到所有节点
2224
- - "查看身份" - 查看当前智能体身份
2225
- - "查看日志" - 查看最近操作日志
2226
-
2227
- 示例请求:
2228
- - "读取 src/index.ts 文件"
2229
- - "总结一下 README.md"
2230
- - "查看当前连接了哪些节点"
2255
+ return `收到了: "${input}"
2256
+
2257
+ 我是一个判断力处理智能体,支持自然语言交互。
2258
+
2259
+ 可用操作(直接说出即可):
2260
+ - "读取 README.md" - 读取并分析文档
2261
+ - "总结文档" - 总结文档内容
2262
+ - "改进文档,按照X要求" - 改进文档
2263
+ - "查看节点" - 查看已连接的对等节点
2264
+ - "向X发送消息Y" - 向对等节点发送消息
2265
+ - "广播消息X" - 广播消息到所有节点
2266
+ - "查看身份" - 查看当前智能体身份
2267
+ - "查看日志" - 查看最近操作日志
2268
+
2269
+ 示例请求:
2270
+ - "读取 src/index.ts 文件"
2271
+ - "总结一下 README.md"
2272
+ - "查看当前连接了哪些节点"
2231
2273
  - "向 QmABC... 发送测试消息"`;
2232
2274
  }
2233
2275
  extractOperationsFromRef(ref) {
@@ -2252,13 +2294,13 @@ ${this.extractOperationsFromRef(operationsRef)}
2252
2294
  }
2253
2295
  }
2254
2296
  return operationLines.length > 0 ? operationLines.join('\n') :
2255
- ` - "读取 README.md" - 读取并分析文档
2256
- - "总结文档" - 总结文档内容
2257
- - "改进文档,按照X要求" - 改进文档
2258
- - "查看节点" - 查看已连接的对等节点
2259
- - "向X发送消息Y" - 向对等节点发送消息
2260
- - "广播消息X" - 广播消息到所有节点
2261
- - "查看身份" - 查看当前智能体身份
2297
+ ` - "读取 README.md" - 读取并分析文档
2298
+ - "总结文档" - 总结文档内容
2299
+ - "改进文档,按照X要求" - 改进文档
2300
+ - "查看节点" - 查看已连接的对等节点
2301
+ - "向X发送消息Y" - 向对等节点发送消息
2302
+ - "广播消息X" - 广播消息到所有节点
2303
+ - "查看身份" - 查看当前智能体身份
2262
2304
  - "查看日志" - 查看最近操作日志`;
2263
2305
  }
2264
2306
  async suggestRename(messages) {
@@ -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
  }