@bolloon/bolloon-agent 0.4.28 → 0.4.30

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 (473) hide show
  1. package/bin/bolloon.cjs +18 -148
  2. package/bin/bolloon.cmd +6 -3
  3. package/dist/agents/contacts/chain.js +579 -0
  4. package/dist/agents/contacts/cli.js +158 -0
  5. package/dist/agents/contacts/consent.js +124 -0
  6. package/dist/agents/contacts/grant-payload.js +45 -0
  7. package/dist/agents/contacts/grants.js +451 -0
  8. package/dist/agents/contacts/policy.js +264 -0
  9. package/dist/agents/contacts/preview-types.js +6 -0
  10. package/dist/agents/contacts/providers.js +341 -0
  11. package/dist/agents/contacts/store.js +326 -0
  12. package/dist/agents/contacts/tools.js +154 -0
  13. package/dist/agents/contacts/types.js +148 -0
  14. package/dist/agents/pi-sdk-tools.js +3 -1
  15. package/dist/agents/pi-sdk.js +14 -1
  16. package/dist/cli/update-commands.js +349 -0
  17. package/dist/cli-entry.js +41 -55
  18. package/dist/electron-build/agents/agent-gateway.js +169 -0
  19. package/dist/electron-build/agents/agent-gateway.js.map +1 -0
  20. package/dist/electron-build/agents/agent-identity-store.js +212 -0
  21. package/dist/electron-build/agents/agent-identity-store.js.map +1 -0
  22. package/dist/electron-build/agents/agent-identity.js +196 -0
  23. package/dist/electron-build/agents/agent-identity.js.map +1 -0
  24. package/dist/electron-build/agents/agent-manifest-protocol.js +151 -0
  25. package/dist/electron-build/agents/agent-manifest-protocol.js.map +1 -0
  26. package/dist/electron-build/agents/agent-registry.js +217 -0
  27. package/dist/electron-build/agents/agent-registry.js.map +1 -0
  28. package/dist/electron-build/agents/agent-reputation.js +60 -0
  29. package/dist/electron-build/agents/agent-reputation.js.map +1 -0
  30. package/dist/electron-build/agents/agent-service-client.js +186 -0
  31. package/dist/electron-build/agents/agent-service-client.js.map +1 -0
  32. package/dist/electron-build/agents/browser-cdp.js +765 -0
  33. package/dist/electron-build/agents/browser-cdp.js.map +1 -0
  34. package/dist/electron-build/agents/computer-use.js +341 -0
  35. package/dist/electron-build/agents/computer-use.js.map +1 -0
  36. package/dist/electron-build/agents/constraint-layer.js +210 -0
  37. package/dist/electron-build/agents/constraint-layer.js.map +1 -0
  38. package/dist/electron-build/agents/contacts/chain.js +619 -0
  39. package/dist/electron-build/agents/contacts/chain.js.map +1 -0
  40. package/dist/electron-build/agents/contacts/consent.js +163 -0
  41. package/dist/electron-build/agents/contacts/consent.js.map +1 -0
  42. package/dist/electron-build/agents/contacts/grant-payload.js +52 -0
  43. package/dist/electron-build/agents/contacts/grant-payload.js.map +1 -0
  44. package/dist/electron-build/agents/contacts/grants.js +500 -0
  45. package/dist/electron-build/agents/contacts/grants.js.map +1 -0
  46. package/dist/electron-build/agents/contacts/policy.js +271 -0
  47. package/dist/electron-build/agents/contacts/policy.js.map +1 -0
  48. package/dist/electron-build/agents/contacts/preview-types.js +8 -0
  49. package/dist/electron-build/agents/contacts/preview-types.js.map +1 -0
  50. package/dist/electron-build/agents/contacts/providers.js +384 -0
  51. package/dist/electron-build/agents/contacts/providers.js.map +1 -0
  52. package/dist/electron-build/agents/contacts/store.js +370 -0
  53. package/dist/electron-build/agents/contacts/store.js.map +1 -0
  54. package/dist/electron-build/agents/contacts/tools.js +159 -0
  55. package/dist/electron-build/agents/contacts/tools.js.map +1 -0
  56. package/dist/electron-build/agents/contacts/types.js +166 -0
  57. package/dist/electron-build/agents/contacts/types.js.map +1 -0
  58. package/dist/electron-build/agents/decision-store.js +292 -0
  59. package/dist/electron-build/agents/decision-store.js.map +1 -0
  60. package/dist/electron-build/agents/deny-pipeline.js +125 -0
  61. package/dist/electron-build/agents/deny-pipeline.js.map +1 -0
  62. package/dist/electron-build/agents/economic-policy.js +172 -0
  63. package/dist/electron-build/agents/economic-policy.js.map +1 -0
  64. package/dist/electron-build/agents/error-classifier.js +125 -0
  65. package/dist/electron-build/agents/error-classifier.js.map +1 -0
  66. package/dist/electron-build/agents/execution-supervisor.js +539 -0
  67. package/dist/electron-build/agents/execution-supervisor.js.map +1 -0
  68. package/dist/electron-build/agents/external-events.js +171 -0
  69. package/dist/electron-build/agents/external-events.js.map +1 -0
  70. package/dist/electron-build/agents/gateway-join.js +315 -0
  71. package/dist/electron-build/agents/gateway-join.js.map +1 -0
  72. package/dist/electron-build/agents/gateway-network.js +505 -0
  73. package/dist/electron-build/agents/gateway-network.js.map +1 -0
  74. package/dist/electron-build/agents/goal-criteria.js +133 -0
  75. package/dist/electron-build/agents/goal-criteria.js.map +1 -0
  76. package/dist/electron-build/agents/goal-resume.js +364 -0
  77. package/dist/electron-build/agents/goal-resume.js.map +1 -0
  78. package/dist/electron-build/agents/goal-store.js +587 -0
  79. package/dist/electron-build/agents/goal-store.js.map +1 -0
  80. package/dist/electron-build/agents/intent-classifier.js +104 -0
  81. package/dist/electron-build/agents/intent-classifier.js.map +1 -0
  82. package/dist/electron-build/agents/iroh-secret.js +70 -0
  83. package/dist/electron-build/agents/iroh-secret.js.map +1 -0
  84. package/dist/electron-build/agents/loop-review.js +101 -0
  85. package/dist/electron-build/agents/loop-review.js.map +1 -0
  86. package/dist/electron-build/agents/memory-recall.js +154 -0
  87. package/dist/electron-build/agents/memory-recall.js.map +1 -0
  88. package/dist/electron-build/agents/p2p-document-tools.js +328 -0
  89. package/dist/electron-build/agents/p2p-document-tools.js.map +1 -0
  90. package/dist/electron-build/agents/parse-tool-call.js +564 -0
  91. package/dist/electron-build/agents/parse-tool-call.js.map +1 -0
  92. package/dist/electron-build/agents/patch-tool.js +205 -0
  93. package/dist/electron-build/agents/patch-tool.js.map +1 -0
  94. package/dist/electron-build/agents/payment-approval.js +183 -0
  95. package/dist/electron-build/agents/payment-approval.js.map +1 -0
  96. package/dist/electron-build/agents/payment-gate.js +139 -0
  97. package/dist/electron-build/agents/payment-gate.js.map +1 -0
  98. package/dist/electron-build/agents/permission-mode.js +124 -0
  99. package/dist/electron-build/agents/permission-mode.js.map +1 -0
  100. package/dist/electron-build/agents/pi-harness.js +268 -0
  101. package/dist/electron-build/agents/pi-harness.js.map +1 -0
  102. package/dist/electron-build/agents/pi-sdk-session-factory.js +117 -0
  103. package/dist/electron-build/agents/pi-sdk-session-factory.js.map +1 -0
  104. package/dist/electron-build/agents/pi-sdk-session-manager.js +335 -0
  105. package/dist/electron-build/agents/pi-sdk-session-manager.js.map +1 -0
  106. package/dist/electron-build/agents/pi-sdk-tools.js +4042 -0
  107. package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -0
  108. package/dist/electron-build/agents/pi-sdk-types.js +17 -0
  109. package/dist/electron-build/agents/pi-sdk-types.js.map +1 -0
  110. package/dist/electron-build/agents/pi-sdk.js +3335 -0
  111. package/dist/electron-build/agents/pi-sdk.js.map +1 -0
  112. package/dist/electron-build/agents/plan-store.js +212 -0
  113. package/dist/electron-build/agents/plan-store.js.map +1 -0
  114. package/dist/electron-build/agents/pre-tool-validator.js +200 -0
  115. package/dist/electron-build/agents/pre-tool-validator.js.map +1 -0
  116. package/dist/electron-build/agents/process-runner.js +148 -0
  117. package/dist/electron-build/agents/process-runner.js.map +1 -0
  118. package/dist/electron-build/agents/react-loop.js +131 -0
  119. package/dist/electron-build/agents/react-loop.js.map +1 -0
  120. package/dist/electron-build/agents/resource-store.js +180 -0
  121. package/dist/electron-build/agents/resource-store.js.map +1 -0
  122. package/dist/electron-build/agents/resource-token.js +118 -0
  123. package/dist/electron-build/agents/resource-token.js.map +1 -0
  124. package/dist/electron-build/agents/resource-wallet.js +84 -0
  125. package/dist/electron-build/agents/resource-wallet.js.map +1 -0
  126. package/dist/electron-build/agents/run-store.js +854 -0
  127. package/dist/electron-build/agents/run-store.js.map +1 -0
  128. package/dist/electron-build/agents/runner-resolver.js +267 -0
  129. package/dist/electron-build/agents/runner-resolver.js.map +1 -0
  130. package/dist/electron-build/agents/session-store.js +294 -0
  131. package/dist/electron-build/agents/session-store.js.map +1 -0
  132. package/dist/electron-build/agents/shell-guard.js +465 -0
  133. package/dist/electron-build/agents/shell-guard.js.map +1 -0
  134. package/dist/electron-build/agents/shell-tool.js +102 -0
  135. package/dist/electron-build/agents/shell-tool.js.map +1 -0
  136. package/dist/electron-build/agents/skill-loader.js +216 -0
  137. package/dist/electron-build/agents/skill-loader.js.map +1 -0
  138. package/dist/electron-build/agents/skill-readiness.js +174 -0
  139. package/dist/electron-build/agents/skill-readiness.js.map +1 -0
  140. package/dist/electron-build/agents/skill-share.js +394 -0
  141. package/dist/electron-build/agents/skill-share.js.map +1 -0
  142. package/dist/electron-build/agents/skill-supervisor-link.js +75 -0
  143. package/dist/electron-build/agents/skill-supervisor-link.js.map +1 -0
  144. package/dist/electron-build/agents/skill-writer.js +347 -0
  145. package/dist/electron-build/agents/skill-writer.js.map +1 -0
  146. package/dist/electron-build/agents/skills-manager.js +763 -0
  147. package/dist/electron-build/agents/skills-manager.js.map +1 -0
  148. package/dist/electron-build/agents/supervisor-host.js +294 -0
  149. package/dist/electron-build/agents/supervisor-host.js.map +1 -0
  150. package/dist/electron-build/agents/task/local-seller.js +188 -0
  151. package/dist/electron-build/agents/task/local-seller.js.map +1 -0
  152. package/dist/electron-build/agents/task/report-card.js +152 -0
  153. package/dist/electron-build/agents/task/report-card.js.map +1 -0
  154. package/dist/electron-build/agents/task/resource-advisor.js +222 -0
  155. package/dist/electron-build/agents/task/resource-advisor.js.map +1 -0
  156. package/dist/electron-build/agents/task/task-budget.js +111 -0
  157. package/dist/electron-build/agents/task/task-budget.js.map +1 -0
  158. package/dist/electron-build/agents/task/task-runner.js +670 -0
  159. package/dist/electron-build/agents/task/task-runner.js.map +1 -0
  160. package/dist/electron-build/agents/task-state.js +266 -0
  161. package/dist/electron-build/agents/task-state.js.map +1 -0
  162. package/dist/electron-build/agents/tool-registry.js +141 -0
  163. package/dist/electron-build/agents/tool-registry.js.map +1 -0
  164. package/dist/electron-build/agents/treasury-bridge.js +165 -0
  165. package/dist/electron-build/agents/treasury-bridge.js.map +1 -0
  166. package/dist/electron-build/agents/user-questions.js +223 -0
  167. package/dist/electron-build/agents/user-questions.js.map +1 -0
  168. package/dist/electron-build/agents/verify-recipe.js +90 -0
  169. package/dist/electron-build/agents/verify-recipe.js.map +1 -0
  170. package/dist/electron-build/agents/workflow-engine.js +222 -0
  171. package/dist/electron-build/agents/workflow-engine.js.map +1 -0
  172. package/dist/electron-build/agents/workflow-pivot-loop.js +988 -0
  173. package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -0
  174. package/dist/electron-build/agents/write-staging.js +133 -0
  175. package/dist/electron-build/agents/write-staging.js.map +1 -0
  176. package/dist/electron-build/agents/x402/goal-run-bridge.js +115 -0
  177. package/dist/electron-build/agents/x402/goal-run-bridge.js.map +1 -0
  178. package/dist/electron-build/agents/x402/milestone-settlement.js +163 -0
  179. package/dist/electron-build/agents/x402/milestone-settlement.js.map +1 -0
  180. package/dist/electron-build/agents/x402/paid-info-protocol.js +274 -0
  181. package/dist/electron-build/agents/x402/paid-info-protocol.js.map +1 -0
  182. package/dist/electron-build/agents/x402/paid-info-store.js +409 -0
  183. package/dist/electron-build/agents/x402/paid-info-store.js.map +1 -0
  184. package/dist/electron-build/agents/x402/paid-info-tools.js +346 -0
  185. package/dist/electron-build/agents/x402/paid-info-tools.js.map +1 -0
  186. package/dist/electron-build/agents/x402/payment-recovery.js +330 -0
  187. package/dist/electron-build/agents/x402/payment-recovery.js.map +1 -0
  188. package/dist/electron-build/agents/x402/resource-contract.js +533 -0
  189. package/dist/electron-build/agents/x402/resource-contract.js.map +1 -0
  190. package/dist/electron-build/agents/x402/settlement-state.js +432 -0
  191. package/dist/electron-build/agents/x402/settlement-state.js.map +1 -0
  192. package/dist/electron-build/agents/x402/trade.js +294 -0
  193. package/dist/electron-build/agents/x402/trade.js.map +1 -0
  194. package/dist/electron-build/agents/x402/transaction-protocol.js +109 -0
  195. package/dist/electron-build/agents/x402/transaction-protocol.js.map +1 -0
  196. package/dist/electron-build/agents/x402/transaction-store.js +404 -0
  197. package/dist/electron-build/agents/x402/transaction-store.js.map +1 -0
  198. package/dist/electron-build/agents/x402/x402Pay.js +377 -0
  199. package/dist/electron-build/agents/x402/x402Pay.js.map +1 -0
  200. package/dist/electron-build/bollharness-integration/context-router-judgment.js +269 -0
  201. package/dist/electron-build/bollharness-integration/context-router-judgment.js.map +1 -0
  202. package/dist/electron-build/bollharness-integration/context-router.js +584 -0
  203. package/dist/electron-build/bollharness-integration/context-router.js.map +1 -0
  204. package/dist/electron-build/bollharness-integration/gate-state-machine.js +362 -0
  205. package/dist/electron-build/bollharness-integration/gate-state-machine.js.map +1 -0
  206. package/dist/electron-build/bollharness-integration/gate-transition-hooks.js +136 -0
  207. package/dist/electron-build/bollharness-integration/gate-transition-hooks.js.map +1 -0
  208. package/dist/electron-build/bollharness-integration/guard-checker.js +400 -0
  209. package/dist/electron-build/bollharness-integration/guard-checker.js.map +1 -0
  210. package/dist/electron-build/bollharness-integration/index.js +123 -0
  211. package/dist/electron-build/bollharness-integration/index.js.map +1 -0
  212. package/dist/electron-build/bollharness-integration/integration.js +531 -0
  213. package/dist/electron-build/bollharness-integration/integration.js.map +1 -0
  214. package/dist/electron-build/bollharness-integration/skill-adapter.js +608 -0
  215. package/dist/electron-build/bollharness-integration/skill-adapter.js.map +1 -0
  216. package/dist/electron-build/bootstrap/bootstrap.js +173 -0
  217. package/dist/electron-build/bootstrap/bootstrap.js.map +1 -0
  218. package/dist/electron-build/bootstrap/context-collector.js +358 -0
  219. package/dist/electron-build/bootstrap/context-collector.js.map +1 -0
  220. package/dist/electron-build/bootstrap/context-hierarchy.js +262 -0
  221. package/dist/electron-build/bootstrap/context-hierarchy.js.map +1 -0
  222. package/dist/electron-build/bootstrap/context-manager.js +211 -0
  223. package/dist/electron-build/bootstrap/context-manager.js.map +1 -0
  224. package/dist/electron-build/bootstrap/context-os.js +277 -0
  225. package/dist/electron-build/bootstrap/context-os.js.map +1 -0
  226. package/dist/electron-build/bootstrap/event-log.js +203 -0
  227. package/dist/electron-build/bootstrap/event-log.js.map +1 -0
  228. package/dist/electron-build/bootstrap/exhaust-scrubber.js +277 -0
  229. package/dist/electron-build/bootstrap/exhaust-scrubber.js.map +1 -0
  230. package/dist/electron-build/bootstrap/lifecycle-hooks.js +282 -0
  231. package/dist/electron-build/bootstrap/lifecycle-hooks.js.map +1 -0
  232. package/dist/electron-build/bootstrap/memory-compressor.js +377 -0
  233. package/dist/electron-build/bootstrap/memory-compressor.js.map +1 -0
  234. package/dist/electron-build/bootstrap/persona-loader.js +219 -0
  235. package/dist/electron-build/bootstrap/persona-loader.js.map +1 -0
  236. package/dist/electron-build/bootstrap/project-context.js +162 -0
  237. package/dist/electron-build/bootstrap/project-context.js.map +1 -0
  238. package/dist/electron-build/bootstrap/project-state.js +205 -0
  239. package/dist/electron-build/bootstrap/project-state.js.map +1 -0
  240. package/dist/electron-build/bootstrap/session-window.js +162 -0
  241. package/dist/electron-build/bootstrap/session-window.js.map +1 -0
  242. package/dist/electron-build/bootstrap/vector-index.js +291 -0
  243. package/dist/electron-build/bootstrap/vector-index.js.map +1 -0
  244. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +22 -0
  245. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js.map +1 -0
  246. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/clobShared.js +86 -0
  247. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/clobShared.js.map +1 -0
  248. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +37 -0
  249. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/createOrder.js.map +1 -0
  250. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +20 -0
  251. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getMarket.js.map +1 -0
  252. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +29 -0
  253. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/getOrders.js.map +1 -0
  254. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +28 -0
  255. package/dist/electron-build/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js.map +1 -0
  256. package/dist/electron-build/constraint-runtime/src/tools/SafeSDK/deploySafe.js +10 -0
  257. package/dist/electron-build/constraint-runtime/src/tools/SafeSDK/deploySafe.js.map +1 -0
  258. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/autoPay.js +68 -0
  259. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/autoPay.js.map +1 -0
  260. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/createWallet.js +14 -0
  261. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/createWallet.js.map +1 -0
  262. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/getBalance.js +17 -0
  263. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/getBalance.js.map +1 -0
  264. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/importWallet.js +59 -0
  265. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/importWallet.js.map +1 -0
  266. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/sendTransaction.js +29 -0
  267. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/sendTransaction.js.map +1 -0
  268. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/signMessage.js +14 -0
  269. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/signMessage.js.map +1 -0
  270. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/transferToken.js +29 -0
  271. package/dist/electron-build/constraint-runtime/src/tools/WalletTools/transferToken.js.map +1 -0
  272. package/dist/electron-build/constraints/index.js +11 -0
  273. package/dist/electron-build/constraints/index.js.map +1 -0
  274. package/dist/electron-build/context-compaction/auto-compact.js +182 -0
  275. package/dist/electron-build/context-compaction/auto-compact.js.map +1 -0
  276. package/dist/electron-build/context-compaction/budget-gate.js +32 -0
  277. package/dist/electron-build/context-compaction/budget-gate.js.map +1 -0
  278. package/dist/electron-build/context-compaction/budget-reduce.js +39 -0
  279. package/dist/electron-build/context-compaction/budget-reduce.js.map +1 -0
  280. package/dist/electron-build/context-compaction/context-collapse.js +71 -0
  281. package/dist/electron-build/context-compaction/context-collapse.js.map +1 -0
  282. package/dist/electron-build/context-compaction/index.js +38 -0
  283. package/dist/electron-build/context-compaction/index.js.map +1 -0
  284. package/dist/electron-build/context-compaction/microcompact.js +55 -0
  285. package/dist/electron-build/context-compaction/microcompact.js.map +1 -0
  286. package/dist/electron-build/context-compaction/pipeline.js +128 -0
  287. package/dist/electron-build/context-compaction/pipeline.js.map +1 -0
  288. package/dist/electron-build/context-compaction/snip.js +50 -0
  289. package/dist/electron-build/context-compaction/snip.js.map +1 -0
  290. package/dist/electron-build/context-compaction/token-estimator.js +40 -0
  291. package/dist/electron-build/context-compaction/token-estimator.js.map +1 -0
  292. package/dist/electron-build/context-compaction/types.js +21 -0
  293. package/dist/electron-build/context-compaction/types.js.map +1 -0
  294. package/dist/electron-build/cron/tick-lock.js +247 -0
  295. package/dist/electron-build/cron/tick-lock.js.map +1 -0
  296. package/dist/electron-build/documents/reader.js +131 -0
  297. package/dist/electron-build/documents/reader.js.map +1 -0
  298. package/dist/electron-build/documents/store.js +220 -0
  299. package/dist/electron-build/documents/store.js.map +1 -0
  300. package/dist/electron-build/external-engines/delegate-handle.js +76 -0
  301. package/dist/electron-build/external-engines/delegate-handle.js.map +1 -0
  302. package/dist/electron-build/external-engines/delegate.js +225 -0
  303. package/dist/electron-build/external-engines/delegate.js.map +1 -0
  304. package/dist/electron-build/external-engines/discovery.js +448 -0
  305. package/dist/electron-build/external-engines/discovery.js.map +1 -0
  306. package/dist/electron-build/external-engines/types.js +13 -0
  307. package/dist/electron-build/external-engines/types.js.map +1 -0
  308. package/dist/electron-build/hooks/hooks-engine.js +367 -0
  309. package/dist/electron-build/hooks/hooks-engine.js.map +1 -0
  310. package/dist/electron-build/judgeness/reflect.js +100 -0
  311. package/dist/electron-build/judgeness/reflect.js.map +1 -0
  312. package/dist/electron-build/judgeness/store.js +536 -0
  313. package/dist/electron-build/judgeness/store.js.map +1 -0
  314. package/dist/electron-build/judgeness/types.js +21 -0
  315. package/dist/electron-build/judgeness/types.js.map +1 -0
  316. package/dist/electron-build/llm/config-store.js +551 -0
  317. package/dist/electron-build/llm/config-store.js.map +1 -0
  318. package/dist/electron-build/llm/error-lessons.js +76 -0
  319. package/dist/electron-build/llm/error-lessons.js.map +1 -0
  320. package/dist/electron-build/llm/pi-ai.js +830 -0
  321. package/dist/electron-build/llm/pi-ai.js.map +1 -0
  322. package/dist/electron-build/llm/system-prompt/registry.js +318 -0
  323. package/dist/electron-build/llm/system-prompt/registry.js.map +1 -0
  324. package/dist/electron-build/llm/system-prompt/strip-hibsml.js +55 -0
  325. package/dist/electron-build/llm/system-prompt/strip-hibsml.js.map +1 -0
  326. package/dist/electron-build/locales/en.js +32 -0
  327. package/dist/electron-build/locales/en.js.map +1 -0
  328. package/dist/electron-build/locales/zh.js +30 -0
  329. package/dist/electron-build/locales/zh.js.map +1 -0
  330. package/dist/electron-build/lsp/lsp-manager.js +327 -0
  331. package/dist/electron-build/lsp/lsp-manager.js.map +1 -0
  332. package/dist/electron-build/lsp/lsp-tools.js +226 -0
  333. package/dist/electron-build/lsp/lsp-tools.js.map +1 -0
  334. package/dist/electron-build/migration/external-agent-migrator.js +451 -0
  335. package/dist/electron-build/migration/external-agent-migrator.js.map +1 -0
  336. package/dist/electron-build/network/agent-network.js +775 -0
  337. package/dist/electron-build/network/agent-network.js.map +1 -0
  338. package/dist/electron-build/network/goal-event-bridge.js +62 -0
  339. package/dist/electron-build/network/goal-event-bridge.js.map +1 -0
  340. package/dist/electron-build/network/iroh-integration.js +117 -0
  341. package/dist/electron-build/network/iroh-integration.js.map +1 -0
  342. package/dist/electron-build/network/iroh-transport.js +550 -0
  343. package/dist/electron-build/network/iroh-transport.js.map +1 -0
  344. package/dist/electron-build/network/p2p.js +1103 -0
  345. package/dist/electron-build/network/p2p.js.map +1 -0
  346. package/dist/electron-build/network/storage/adapters/json-adapter.js +416 -0
  347. package/dist/electron-build/network/storage/adapters/json-adapter.js.map +1 -0
  348. package/dist/electron-build/network/storage/types.js +18 -0
  349. package/dist/electron-build/network/storage/types.js.map +1 -0
  350. package/dist/electron-build/orbitdb/agent-tools.js +402 -0
  351. package/dist/electron-build/orbitdb/agent-tools.js.map +1 -0
  352. package/dist/electron-build/orbitdb/cid-database.js +284 -0
  353. package/dist/electron-build/orbitdb/cid-database.js.map +1 -0
  354. package/dist/electron-build/orbitdb/context-store.js +99 -0
  355. package/dist/electron-build/orbitdb/context-store.js.map +1 -0
  356. package/dist/electron-build/orbitdb/ipfs-node.js +120 -0
  357. package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -0
  358. package/dist/electron-build/orbitdb/kanban-store.js +299 -0
  359. package/dist/electron-build/orbitdb/kanban-store.js.map +1 -0
  360. package/dist/electron-build/orbitdb/task-store.js +155 -0
  361. package/dist/electron-build/orbitdb/task-store.js.map +1 -0
  362. package/dist/electron-build/orbitdb/trajectory-store.js +194 -0
  363. package/dist/electron-build/orbitdb/trajectory-store.js.map +1 -0
  364. package/dist/electron-build/orbitdb/ui-cid.js +77 -0
  365. package/dist/electron-build/orbitdb/ui-cid.js.map +1 -0
  366. package/dist/electron-build/pi-ecosystem-a2ui/index.js +89 -0
  367. package/dist/electron-build/pi-ecosystem-a2ui/index.js.map +1 -0
  368. package/dist/electron-build/pi-ecosystem-goals/index.js +512 -0
  369. package/dist/electron-build/pi-ecosystem-goals/index.js.map +1 -0
  370. package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js +325 -0
  371. package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js.map +1 -0
  372. package/dist/electron-build/pi-ecosystem-judgment/causal-judge.js +492 -0
  373. package/dist/electron-build/pi-ecosystem-judgment/causal-judge.js.map +1 -0
  374. package/dist/electron-build/pi-ecosystem-judgment/cleanup.js +167 -0
  375. package/dist/electron-build/pi-ecosystem-judgment/cleanup.js.map +1 -0
  376. package/dist/electron-build/pi-ecosystem-judgment/decision.js +321 -0
  377. package/dist/electron-build/pi-ecosystem-judgment/decision.js.map +1 -0
  378. package/dist/electron-build/pi-ecosystem-judgment/detect-hook.js +175 -0
  379. package/dist/electron-build/pi-ecosystem-judgment/detect-hook.js.map +1 -0
  380. package/dist/electron-build/pi-ecosystem-judgment/distill-prompt.js +232 -0
  381. package/dist/electron-build/pi-ecosystem-judgment/distill-prompt.js.map +1 -0
  382. package/dist/electron-build/pi-ecosystem-judgment/distillation.js +304 -0
  383. package/dist/electron-build/pi-ecosystem-judgment/distillation.js.map +1 -0
  384. package/dist/electron-build/pi-ecosystem-judgment/evolve-judgment.js +176 -0
  385. package/dist/electron-build/pi-ecosystem-judgment/evolve-judgment.js.map +1 -0
  386. package/dist/electron-build/pi-ecosystem-judgment/human-value-pipeline.js +65 -0
  387. package/dist/electron-build/pi-ecosystem-judgment/human-value-pipeline.js.map +1 -0
  388. package/dist/electron-build/pi-ecosystem-judgment/human-value-store.js +808 -0
  389. package/dist/electron-build/pi-ecosystem-judgment/human-value-store.js.map +1 -0
  390. package/dist/electron-build/pi-ecosystem-judgment/index.js +508 -0
  391. package/dist/electron-build/pi-ecosystem-judgment/index.js.map +1 -0
  392. package/dist/electron-build/pi-ecosystem-judgment/injection-gate.js +334 -0
  393. package/dist/electron-build/pi-ecosystem-judgment/injection-gate.js.map +1 -0
  394. package/dist/electron-build/pi-ecosystem-judgment/monitor-gate.js +228 -0
  395. package/dist/electron-build/pi-ecosystem-judgment/monitor-gate.js.map +1 -0
  396. package/dist/electron-build/pi-ecosystem-judgment/value-injection.js +598 -0
  397. package/dist/electron-build/pi-ecosystem-judgment/value-injection.js.map +1 -0
  398. package/dist/electron-build/pi-ecosystem-mcp/index.js +643 -0
  399. package/dist/electron-build/pi-ecosystem-mcp/index.js.map +1 -0
  400. package/dist/electron-build/pi-ecosystem-mcp/ui-tools.js +116 -0
  401. package/dist/electron-build/pi-ecosystem-mcp/ui-tools.js.map +1 -0
  402. package/dist/electron-build/pi-ecosystem-subagents/index.js +352 -0
  403. package/dist/electron-build/pi-ecosystem-subagents/index.js.map +1 -0
  404. package/dist/electron-build/security/builtin-guards.js +133 -0
  405. package/dist/electron-build/security/builtin-guards.js.map +1 -0
  406. package/dist/electron-build/security/context-router-tool.js +111 -0
  407. package/dist/electron-build/security/context-router-tool.js.map +1 -0
  408. package/dist/electron-build/security/input-scanner.js +263 -0
  409. package/dist/electron-build/security/input-scanner.js.map +1 -0
  410. package/dist/electron-build/security/react-harness.js +148 -0
  411. package/dist/electron-build/security/react-harness.js.map +1 -0
  412. package/dist/electron-build/security/tool-gate.js +291 -0
  413. package/dist/electron-build/security/tool-gate.js.map +1 -0
  414. package/dist/electron-build/setup/setup-store.js +648 -0
  415. package/dist/electron-build/setup/setup-store.js.map +1 -0
  416. package/dist/electron-build/social/channels/ChannelManager.js +444 -0
  417. package/dist/electron-build/social/channels/ChannelManager.js.map +1 -0
  418. package/dist/electron-build/social/channels/DiapChannelBridge.js +451 -0
  419. package/dist/electron-build/social/channels/DiapChannelBridge.js.map +1 -0
  420. package/dist/electron-build/social/channels/InterestMatcher.js +135 -0
  421. package/dist/electron-build/social/channels/InterestMatcher.js.map +1 -0
  422. package/dist/electron-build/social/channels/types.js +21 -0
  423. package/dist/electron-build/social/channels/types.js.map +1 -0
  424. package/dist/electron-build/social/global-shared-context.js +368 -0
  425. package/dist/electron-build/social/global-shared-context.js.map +1 -0
  426. package/dist/electron-build/social/heartbeat.js +882 -0
  427. package/dist/electron-build/social/heartbeat.js.map +1 -0
  428. package/dist/electron-build/storage/did-catalog-bridge.js +314 -0
  429. package/dist/electron-build/storage/did-catalog-bridge.js.map +1 -0
  430. package/dist/electron-build/storage/did-catalog.js +272 -0
  431. package/dist/electron-build/storage/did-catalog.js.map +1 -0
  432. package/dist/electron-build/utils/auto-update.js +140 -558
  433. package/dist/electron-build/utils/auto-update.js.map +1 -1
  434. package/dist/electron-build/utils/module-context.js +98 -0
  435. package/dist/electron-build/utils/module-context.js.map +1 -0
  436. package/dist/electron-build/utils/runtime-bootstrap.js +745 -0
  437. package/dist/electron-build/utils/runtime-bootstrap.js.map +1 -0
  438. package/dist/electron-build/utils/update-manager.js +770 -0
  439. package/dist/electron-build/utils/update-manager.js.map +1 -0
  440. package/dist/electron-build/utils/update-state.js +406 -0
  441. package/dist/electron-build/utils/update-state.js.map +1 -0
  442. package/dist/electron-build/utils/version-info.js +562 -0
  443. package/dist/electron-build/utils/version-info.js.map +1 -0
  444. package/dist/electron-build/web/i18n.js +146 -0
  445. package/dist/electron-build/web/i18n.js.map +1 -0
  446. package/dist/electron-build/web/routes-x402-info.js +232 -0
  447. package/dist/electron-build/web/routes-x402-info.js.map +1 -0
  448. package/dist/electron-build/web/server-storage.js +390 -0
  449. package/dist/electron-build/web/server-storage.js.map +1 -0
  450. package/dist/electron-build/web/server-types.js +52 -0
  451. package/dist/electron-build/web/server-types.js.map +1 -0
  452. package/dist/electron-build/web/task-deps.js +41 -0
  453. package/dist/electron-build/web/task-deps.js.map +1 -0
  454. package/dist/index.js +58 -27
  455. package/dist/llm/system-prompt/registry.js +6 -3
  456. package/dist/security/tool-gate.js +4 -0
  457. package/dist/utils/auto-update.js +138 -525
  458. package/dist/utils/module-context.js +59 -0
  459. package/dist/utils/runtime-bootstrap.js +682 -0
  460. package/dist/utils/update-cli.js +82 -0
  461. package/dist/utils/update-health.js +401 -0
  462. package/dist/utils/update-manager.js +716 -0
  463. package/dist/utils/update-state.js +353 -0
  464. package/dist/utils/version-info.js +510 -0
  465. package/dist/web/mobile-contacts.js +329 -0
  466. package/dist/web/mobile-core.js +481 -15
  467. package/dist/web/mobile.html +32 -0
  468. package/dist/web/mobile.js +139 -0
  469. package/dist/web/routes-contacts.js +420 -0
  470. package/dist/web/server.js +5 -0
  471. package/package.json +1 -1
  472. package/scripts/build-cli.js +32 -151
  473. package/scripts/postinstall.js +153 -76
@@ -0,0 +1,988 @@
1
+ "use strict";
2
+ /**
3
+ * WorkflowPivotLoop - Robust Agent Loop with Adaptive Iteration Control
4
+ *
5
+ * Based on the architecture pattern:
6
+ * 1. Loop interrupted by max iterations
7
+ * 2. Model decides via pending_tool_uses (empty = normal completion)
8
+ * 3. Conditional routing based on tool call presence
9
+ *
10
+ * Key improvements over simple ReAct:
11
+ * - Dynamic loop length based on task complexity
12
+ * - Multi-dimensional exit conditions
13
+ * - Consecutive invalid iteration detection
14
+ * - Token budget awareness
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.WorkflowPivotLoop = exports.TOOL_RESULT_MAX_CHARS = void 0;
18
+ exports.canonicalizeToolCallArguments = canonicalizeToolCallArguments;
19
+ exports.truncateToolOutput = truncateToolOutput;
20
+ exports.createDefaultPivotConfig = createDefaultPivotConfig;
21
+ exports.runPivotLoop = runPivotLoop;
22
+ const loop_review_js_1 = require("./loop-review.js");
23
+ /**
24
+ * 2026-08-11 (借鉴 Hermes `_canonicalize_tool_call_arguments`): 工具参数规范化 —
25
+ * LLM 返回的 arguments 常带尾随散文/尾逗号/代码围栏, 直接 JSON.parse 失败会丢整个工具调用.
26
+ * 策略: 直接解析 → 截到最后一个闭合 } → 去代码围栏, 逐级降级; 结果必须是非数组对象.
27
+ */
28
+ function canonicalizeToolCallArguments(argStr) {
29
+ if (typeof argStr !== 'string')
30
+ return {};
31
+ const s = argStr.trim();
32
+ if (!s)
33
+ return {};
34
+ const tryParse = (text) => {
35
+ try {
36
+ const parsed = JSON.parse(text);
37
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
38
+ return parsed;
39
+ }
40
+ catch { /* 下一级 */ }
41
+ return null;
42
+ };
43
+ const direct = tryParse(s);
44
+ if (direct)
45
+ return direct;
46
+ // LLM 在 JSON 后追加散文 — 截到最后一个闭合 } 再试
47
+ const lastClose = s.lastIndexOf('}');
48
+ if (lastClose > 0) {
49
+ const truncated = tryParse(s.slice(0, lastClose + 1));
50
+ if (truncated)
51
+ return truncated;
52
+ }
53
+ // 代码围栏包裹
54
+ const fenced = s.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/, '').trim();
55
+ if (fenced && fenced !== s) {
56
+ const unfenced = tryParse(fenced);
57
+ if (unfenced)
58
+ return unfenced;
59
+ }
60
+ return {};
61
+ }
62
+ /** 2026-08-11 (Hermes build_worker_context 全限幅): 工具输出进 LLM 上下文的上限 */
63
+ exports.TOOL_RESULT_MAX_CHARS = 12_000;
64
+ /** 截断工具输出 (纯函数, 可单测): 超限 → 保留前 max + 可见省略标记 */
65
+ function truncateToolOutput(output, max = exports.TOOL_RESULT_MAX_CHARS) {
66
+ const s = output ?? '';
67
+ if (s.length <= max)
68
+ return s;
69
+ return s.slice(0, max) + `\n… [truncated, ${s.length - max} chars omitted]`;
70
+ }
71
+ /**
72
+ * Analyze input to determine task complexity
73
+ */
74
+ function analyzeTaskComplexity(input) {
75
+ const inputLower = input.toLowerCase();
76
+ const inputLength = input.length;
77
+ // Simple task indicators
78
+ const simpleIndicators = [
79
+ '读取', '查看', '显示', '列出', '获取', 'what is', 'show me',
80
+ 'list', 'get', 'show', 'read', 'view', 'display'
81
+ ];
82
+ // Complex task indicators
83
+ const complexIndicators = [
84
+ '分析', '比较', '改进', '优化', '重构', '实现', '设计', '创建',
85
+ 'analyze', 'compare', 'improve', 'optimize', 'refactor', 'implement',
86
+ 'design', 'create', 'build', 'develop'
87
+ ];
88
+ // Question patterns suggest moderate complexity
89
+ const questionPatterns = [
90
+ '如何', '怎么', '为什么', '什么', 'which', 'how', 'why', 'what', '?'
91
+ ];
92
+ const simpleCount = simpleIndicators.filter(i => inputLower.includes(i)).length;
93
+ const complexCount = complexIndicators.filter(i => inputLower.includes(i)).length;
94
+ const questionCount = questionPatterns.filter(p => inputLower.includes(p)).length;
95
+ let complexity;
96
+ let estimatedSteps;
97
+ if (complexCount > simpleCount && complexCount > 1) {
98
+ complexity = 'complex';
99
+ estimatedSteps = 5 + complexCount * 2;
100
+ }
101
+ else if (questionCount > 2 || (simpleCount > 0 && complexCount > 0)) {
102
+ complexity = 'moderate';
103
+ estimatedSteps = 3 + questionCount;
104
+ }
105
+ else if (inputLength < 50 && simpleCount > 0) {
106
+ complexity = 'simple';
107
+ estimatedSteps = 1 + simpleCount;
108
+ }
109
+ else if (complexCount > 0) {
110
+ complexity = 'complex';
111
+ estimatedSteps = 4 + complexCount;
112
+ }
113
+ else {
114
+ complexity = 'moderate';
115
+ estimatedSteps = 3;
116
+ }
117
+ // Adjust based on input length (longer inputs often mean more complex tasks)
118
+ if (inputLength > 500 && complexity !== 'complex') {
119
+ complexity = 'moderate';
120
+ estimatedSteps = Math.max(estimatedSteps, 4);
121
+ }
122
+ // Suggested max iterations: 2-3x estimated steps for safety margin
123
+ const suggestedMaxIterations = Math.min(Math.max(estimatedSteps * 3, 10), 100);
124
+ const tokenBudget = estimatedSteps * 800; // ~800 tokens per step estimate
125
+ return { complexity, estimatedSteps, suggestedMaxIterations, tokenBudget };
126
+ }
127
+ /**
128
+ * WorkflowPivotLoop - Main loop controller
129
+ */
130
+ class WorkflowPivotLoop {
131
+ config;
132
+ state;
133
+ tools;
134
+ messageHistory;
135
+ streamCallback;
136
+ // 2026-07-06: pivot 想看内部明细设 BOLLOON_VERBOSE=1 — 默认只保留 status 事件给 UI
137
+ verbose = typeof process !== 'undefined' && process.env?.BOLLOON_VERBOSE === '1';
138
+ vlog(msg) { if (this.verbose)
139
+ console.log(msg); }
140
+ pushContinuationHint(hint) {
141
+ if (!this.continuationHints.includes(hint))
142
+ this.continuationHints.push(hint);
143
+ }
144
+ onApproachingTokenBudget;
145
+ compactedThisRun = false; // 防止 pivot 单次 execute 反复触发 compact
146
+ // 2026-07-06: iter ≥ 2 时用简短 systemHeader 替代完整 systemPrompt
147
+ // pivot 默认 moderate profile 是 30 iter, 每次调 llm 都重复装 11K persona+tools 装 + 25 layer
148
+ // (pi-ai.ts buildSystemPromptAsync 重复读 .md) — 真没必要. 第一轮装全, 后续用锚句占位.
149
+ // compactor 触发后 (旧 systemHeader 代表性弱化) 再重新装一次全量.
150
+ continuationSystemHeader = null;
151
+ // 2026-08-11 (Hermes `_get_continuation_prompt` 模式): 本轮工具执行的结构性问题
152
+ // (未知工具被跳过/输出过大) → 下轮注入显式续跑提示, LLM 不会静默忽略.
153
+ continuationHints = [];
154
+ // 2026-08-11 (循环工作流检测): 最近工具调用记录 (name+argsHash), 连续相同 = 有活动无进展
155
+ recentToolCalls = [];
156
+ constructor(config) {
157
+ this.tools = new Map();
158
+ // Default configuration based on task complexity if not provided
159
+ const defaults = {
160
+ maxIterations: config.maxIterations || 1000, // 2026-07-06: 持久循环 (旧 50)
161
+ minIterations: config.minIterations || 2,
162
+ qualityThreshold: config.qualityThreshold || 0.7,
163
+ maxConsecutiveNoProgress: config.maxConsecutiveNoProgress || 8,
164
+ maxTokenBudget: config.maxTokenBudget || 50000,
165
+ complexity: config.complexity || 'moderate'
166
+ };
167
+ this.config = defaults;
168
+ this.state = this.createInitialState();
169
+ this.messageHistory = [];
170
+ }
171
+ createInitialState() {
172
+ return {
173
+ iteration: 0,
174
+ totalTokens: 0,
175
+ toolCallsCount: 0,
176
+ consecutiveNoProgress: 0,
177
+ qualityScores: [],
178
+ pendingToolUses: [],
179
+ lastMeaningfulWork: 0
180
+ };
181
+ }
182
+ /**
183
+ * Register a tool for use in the loop
184
+ */
185
+ registerTool(tool) {
186
+ this.tools.set(tool.name, tool);
187
+ }
188
+ /**
189
+ * Register multiple tools at once
190
+ */
191
+ registerTools(tools) {
192
+ for (const tool of tools) {
193
+ this.registerTool(tool);
194
+ }
195
+ }
196
+ /**
197
+ * 2026-08-02: 把 this.tools Map 转成 OpenAI 原生 tools 格式 (含参数 schema).
198
+ * pivot loop 之前只把工具描述塞 system prompt, LLM 靠文本 JSON 猜格式
199
+ * (deepseek 输出 {"name":"X","result":{...}} 编造结果), 从不真正执行工具.
200
+ * 传原生 tools + tool_choice auto → LLM 返回结构化 tool_calls.
201
+ */
202
+ buildOpenAITools() {
203
+ // 2026-08-12 (Task3 认知卸载): 核心编码工具加强 description, 提升模型触发率.
204
+ const USAGE_HINT = {
205
+ write_file: '写/创建文件用此工具 (改代码首选). ',
206
+ edit_file: '修改文件指定内容用此工具 (改代码首选). ',
207
+ read_file: '读取文件内容用此工具. ',
208
+ read_directory: '列目录用此工具. ',
209
+ list_files: '列出文件用此工具. ',
210
+ terminal: '跑 shell 命令/脚本/装依赖/查状态用此工具 (不要用它写文件). ',
211
+ delegate_to_engine: '任务过大或复杂时委派给外部编码引擎 (认知卸载). ',
212
+ };
213
+ const out = [];
214
+ for (const [name, tool] of this.tools) {
215
+ const params = tool.parameters || {};
216
+ const properties = {};
217
+ const required = [];
218
+ for (const [pName, pDesc] of Object.entries(params)) {
219
+ properties[pName] = { type: 'string', description: String(pDesc) };
220
+ if (String(pDesc).includes('必填'))
221
+ required.push(pName);
222
+ }
223
+ out.push({
224
+ type: 'function',
225
+ function: {
226
+ name,
227
+ description: (USAGE_HINT[name] || '') + (tool.description || name),
228
+ parameters: { type: 'object', properties, required },
229
+ },
230
+ });
231
+ }
232
+ return out;
233
+ }
234
+ /**
235
+ * 2026-08-02: 把 OpenAI 原生 tool_calls (结构化) 转成 ToolDefinition 数组.
236
+ * 优先于文本 JSON 解析 — LLM 返回 tool_calls 时直接执行, 不再猜格式.
237
+ */
238
+ nativeToolCallsToDefinitions(toolCalls) {
239
+ const out = [];
240
+ for (const tc of toolCalls || []) {
241
+ const fn = tc?.function;
242
+ if (!fn || !fn.name)
243
+ continue;
244
+ const name = fn.name;
245
+ if (!this.tools.has(name)) {
246
+ this.pushContinuationHint(`工具 ${name} 未注册/不存在, 调用已跳过 — 请换用已提供的工具`);
247
+ continue;
248
+ }
249
+ out.push({ name, args: this.normalizeArgs(canonicalizeToolCallArguments(fn.arguments)), description: '', parameters: {} });
250
+ }
251
+ return out;
252
+ }
253
+ /**
254
+ * Execute the pivot loop
255
+ */
256
+ async execute(input, llm, systemPrompt, streamCallback, signal,
257
+ /**
258
+ * 2026-07-06: token 预算接近上限时回调 — 让上层 (PiAgentSession) 跑 compactor
259
+ * 否者单纯报 "Token 预算超支" 直接 break, 用户消息丢失.
260
+ * 回调同步返回值 (newMessageHistory) 时替换 this.messageHistory 后继续.
261
+ * 异步: PiAgent 触发 compactPipeline, 这里 await 等折叠完再继续.
262
+ */
263
+ onApproachingTokenBudget) {
264
+ this.streamCallback = streamCallback;
265
+ this.state = this.createInitialState();
266
+ this.onApproachingTokenBudget = onApproachingTokenBudget;
267
+ // 2026-07-06: 准备短 systemHeader. iter ≥ 2 用它替代完整 systemPrompt
268
+ // LLM 已经在 messageHistory 里看到全部历史, 不需要每次重装. compact 触发后下次再装全量.
269
+ this.continuationSystemHeader = this.buildContinuationHeader(systemPrompt);
270
+ // 重置 compact 状态 — 这次 execute 第一次 iter 仍用全量
271
+ this.compactedThisRun = false;
272
+ this.vlog(`[pivot] execute: input chars=${input.length}, systemPrompt chars=${systemPrompt.length}, signal=${!!signal}, continuationHeader chars=${this.continuationSystemHeader?.length ?? 0}`);
273
+ this.messageHistory = [{ role: 'user', content: input }];
274
+ // Analyze task complexity and adapt config
275
+ const taskProfile = analyzeTaskComplexity(input);
276
+ const effectiveConfig = this.adaptConfigForTask(taskProfile);
277
+ // 2026-06-18 (supervisor): taskProfile 算的 tokenBudget 只看 input 长度, 但 systemPrompt 53K 时不够
278
+ // 把 effectiveConfig.maxTokenBudget 提到 systemPrompt * 1.2 留余量, 简单问题也走完
279
+ // 2026-07-06: 但累计 totalTokens = systemPrompt + sum(replies), 每 iter LLM 反 ~3-10K
280
+ // 旧公式 budget=11K*1.2=13K, 5 iter 累计 5 × 11K + replies = ~70K → 12-13K 处直接 break.
281
+ // 修法: budget = systemPrompt × 1.2 × maxIterations, 容纳 N 次 prompt + N-1 次 reply.
282
+ effectiveConfig.maxTokenBudget = Math.max(effectiveConfig.maxTokenBudget, Math.ceil(systemPrompt.length * 1.2 * effectiveConfig.maxIterations));
283
+ this.emit({
284
+ type: 'status',
285
+ content: `🔍 任务复杂度: ${taskProfile.complexity} (预估 ${taskProfile.estimatedSteps} 步)`,
286
+ tool: 'system'
287
+ });
288
+ this.emit({
289
+ type: 'status',
290
+ content: `⚙️ 动态配置: maxIterations=${effectiveConfig.maxIterations}, tokenBudget=${effectiveConfig.maxTokenBudget}`,
291
+ tool: 'system'
292
+ });
293
+ let response = '';
294
+ while (this.shouldContinue(effectiveConfig)) {
295
+ // 2026-07-04: signal abort 让 pivot 提前退出 (防止 LLM hang)
296
+ if (signal?.aborted) {
297
+ this.emit({
298
+ type: 'status',
299
+ content: `⏹️ pivot loop 被 abort (iter=${this.state.iteration})`,
300
+ tool: 'loop'
301
+ });
302
+ break;
303
+ }
304
+ this.state.iteration++;
305
+ this.emit({
306
+ type: 'status',
307
+ content: `🔄 循环 ${this.state.iteration}/${effectiveConfig.maxIterations}`,
308
+ tool: 'loop'
309
+ });
310
+ // Build context for LLM
311
+ let context = this.buildContext();
312
+ // 2026-08-11: 注入工具续跑提示 (Hermes continuation prompt 模式) — 结构性问题显式告知,
313
+ // 用完即清 (只对下一轮 LLM 可见一次)
314
+ if (this.continuationHints.length > 0) {
315
+ context += `\n\n【工具续跑提示】\n${this.continuationHints.map((h) => `- ${h}`).join('\n')}\n请基于以上信息继续推进任务, 不要重复已失败的调用。`;
316
+ this.continuationHints = [];
317
+ }
318
+ const fullPrompt = `${systemPrompt}\n\n${context}`;
319
+ // 2026-07-06: iter ≥ 2 改用 continuationHeader — messageHistory 已经载过全 persona/tools,
320
+ // 重装 11K + 25 layer 是浪费, 同时让 pi-ai.chat 走 < 2000 分支 (不重新装 system prompt).
321
+ // compact 触发 → 这次 iter 之后下一 iter 恢复用 full.
322
+ let headerForThisIter = systemPrompt;
323
+ let usingContinuation = false;
324
+ const shouldUseContinuation = this.state.iteration >= 2 && !this.compactedThisRun && this.continuationSystemHeader;
325
+ if (shouldUseContinuation) {
326
+ headerForThisIter = this.continuationSystemHeader;
327
+ usingContinuation = true;
328
+ }
329
+ this.vlog(`[pivot] iter=${this.state.iteration} ctx=${context.length} fullPrompt=${fullPrompt.length} budget=${effectiveConfig.maxTokenBudget} iterHeader=${usingContinuation ? 'short' : 'full'} (${headerForThisIter.length}B)`);
330
+ try {
331
+ // Call LLM
332
+ const t0 = Date.now();
333
+ // 2026-08-02: 传原生 OpenAI tools — deepseek 返回结构化 tool_calls,
334
+ // UI 才能显示真实的工具执行 step (之前靠文本 JSON 猜格式, LLM 编造 result)
335
+ const openAITools = this.buildOpenAITools();
336
+ const llmResponse = await llm.chat(context, headerForThisIter, signal, openAITools);
337
+ const reply = (llmResponse.reply || '').trim();
338
+ 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, ' ')}`);
339
+ this.emit({ type: 'token', content: reply });
340
+ // 2026-07-06: 把完整 reply 推给前端 — 前端按需更新临时气泡
341
+ // 之前只 emit token(100B 截断), 前端拿到 100B 看不清. 现在 emit preview 带完整 content.
342
+ // 折叠 / 清洗交给前端的 message-renderer.addMessage (类型 ai 入口统一 strip).
343
+ this.emit({ type: 'reply-preview', content: reply, iteration: this.state.iteration });
344
+ // Estimate token usage
345
+ this.state.totalTokens += this.estimateTokens(headerForThisIter + '\n\n' + context) + this.estimateTokens(reply);
346
+ // 2026-07-06: token 接近预算时先尝试自动压缩, 而不是直接 break — 上层 PiAgentSession
347
+ // 通过 onApproachingTokenBudget 回调触发 compactPipeline (5 层短路)
348
+ const budgetRatio = this.state.totalTokens / effectiveConfig.maxTokenBudget;
349
+ if (budgetRatio > 0.7 && this.onApproachingTokenBudget && !this.compactedThisRun && this.messageHistory.length >= 6) {
350
+ this.compactedThisRun = true;
351
+ this.emit({
352
+ type: 'status',
353
+ content: `🗜️ token ${this.state.totalTokens} 接近预算 (${(budgetRatio * 100).toFixed(0)}%), 尝试自动压缩上下文`,
354
+ tool: 'compactor',
355
+ });
356
+ try {
357
+ await this.onApproachingTokenBudget();
358
+ // 重置 totalTokens 因为 compactor 折叠后本来就不准
359
+ this.state.totalTokens = Math.ceil(systemPrompt.length * 0.5); // 粗略剩余量
360
+ this.emit({
361
+ type: 'status',
362
+ content: `🗜️ 自动压缩完成, 继续循环 (剩余估算 ${this.state.totalTokens} chars)`,
363
+ tool: 'compactor',
364
+ });
365
+ // 继续 loop, 不 break
366
+ continue;
367
+ }
368
+ catch (err) {
369
+ console.warn('[pivot] onApproachingTokenBudget failed (non-fatal, 继续走 token 阈值):', String(err?.message || err).slice(0, 100));
370
+ // compact 失败 → 回到原 check
371
+ }
372
+ }
373
+ // Check token budget
374
+ if (this.state.totalTokens > effectiveConfig.maxTokenBudget) {
375
+ this.emit({
376
+ type: 'error',
377
+ content: '⚠️ Token 预算超支,中断循环'
378
+ });
379
+ return this.createResult(false, response, 'token_budget_exceeded');
380
+ }
381
+ // Check if this is a final response (no tool calls)
382
+ // 2026-08-02: 优先用 OpenAI 原生 tool_calls (结构化, LLM 不会编造 result),
383
+ // 没有才 fallback 到文本 JSON 解析 (extractPendingToolUses)
384
+ const nativeTools = this.nativeToolCallsToDefinitions(llmResponse.toolCalls || []);
385
+ const pendingTools = nativeTools.length > 0 ? nativeTools : this.extractPendingToolUses(reply);
386
+ if (pendingTools.length === 0) {
387
+ // 2026-07-06: LLM 显式 <final gen> 标记 — pivot 立即退出, 不再走 quality/iter 流程
388
+ // 这个 marker 之前和 思考/ 同义被忽略, 害得 "你好" 类问题跑 11 iter 还不见停
389
+ // 加上之后 iter=1 收到 <final gen> 就 accept
390
+ if (/<final\s+gen\s*\/?>|<\/final\s+gen>/i.test(reply)) {
391
+ const cleaned = reply.replace(/<final\s+gen\s*\/?>|<\/final\s+gen>/gi, '').trim();
392
+ response = cleaned || reply;
393
+ this.emit({
394
+ type: 'status',
395
+ content: `✅ 检测到 <final gen> 结束标记, 立即退出 (iter=${this.state.iteration})`,
396
+ tool: 'system',
397
+ });
398
+ return this.createResult(true, response, 'final_gen_marker');
399
+ }
400
+ // Check if the reply contains tool call intent but couldn't be parsed
401
+ // 2026-07-06: 排除合法的 思考/<final gen> 这些 tag (它们是 sentinel 不是 tool call)
402
+ const cleanedForIntentCheck = reply
403
+ .replace(/<final\s+gen\s*\/?>|<\/final\s+gen>/gi, '')
404
+ .replace(/<\/?think(?:ing)?>/gi, ''); // 移除
405
+ const containsToolCallIntent = cleanedForIntentCheck.includes('调用工具') || cleanedForIntentCheck.includes('tool(') ||
406
+ cleanedForIntentCheck.includes('使用工具') || cleanedForIntentCheck.includes('需要获取') || cleanedForIntentCheck.includes('需要查看') ||
407
+ cleanedForIntentCheck.includes('tool =>') || cleanedForIntentCheck.includes('[TOOL_CALL]') ||
408
+ // 仅匹配真工具调用 tag (tool_use / function_calls / tool_call / invoke / tool_code)
409
+ /<\s*(tool_use|tool_call|function_calls?|tool_code|invoke)\s*>/i.test(cleanedForIntentCheck);
410
+ // If there's tool call intent but no parsed tools, continue the loop
411
+ if (containsToolCallIntent && this.state.iteration < effectiveConfig.maxIterations) {
412
+ this.emit({
413
+ type: 'status',
414
+ content: `🔄 检测到工具调用意图但格式无法解析,继续循环...`,
415
+ tool: 'system'
416
+ });
417
+ this.state.consecutiveNoProgress++;
418
+ continue;
419
+ }
420
+ // No pending tool uses - this is a normal completion
421
+ this.state.pendingToolUses = [];
422
+ // Evaluate quality before accepting
423
+ const quality = this.evaluateQuality(reply);
424
+ this.state.qualityScores.push(quality);
425
+ this.emit({
426
+ type: 'status',
427
+ content: `✅ 检测到最终回复 (质量: ${(quality * 10).toFixed(1)}/10)`,
428
+ tool: 'system'
429
+ });
430
+ // Check if quality threshold met
431
+ if (quality >= effectiveConfig.qualityThreshold) {
432
+ response = reply;
433
+ return this.createResult(true, reply, 'quality_threshold_met');
434
+ }
435
+ // Quality not met but no more tools to call
436
+ // Accept response if we've done minimum iterations
437
+ if (this.state.iteration >= effectiveConfig.minIterations) {
438
+ response = reply;
439
+ return this.createResult(true, reply, 'no_pending_tools');
440
+ }
441
+ // Too early, continue to see if we can improve
442
+ this.state.consecutiveNoProgress++;
443
+ this.emit({
444
+ type: 'status',
445
+ content: `📊 质量未达标 (${(quality * 10).toFixed(1)}/${(effectiveConfig.qualityThreshold * 10).toFixed(1)}),继续循环`,
446
+ tool: 'system'
447
+ });
448
+ continue;
449
+ }
450
+ // We have pending tool uses - execute them
451
+ this.state.pendingToolUses = pendingTools;
452
+ this.state.lastMeaningfulWork = this.state.iteration;
453
+ this.state.consecutiveNoProgress = 0;
454
+ for (const toolCall of pendingTools) {
455
+ this.state.toolCallsCount++;
456
+ const tool = this.tools.get(toolCall.name);
457
+ if (!tool) {
458
+ this.emit({
459
+ type: 'error',
460
+ content: `❌ 未知工具: ${toolCall.name}`
461
+ });
462
+ // 2026-06-15: step-timeline — 未知工具也开/关一个 step 节点
463
+ this.emit({
464
+ type: 'step_start',
465
+ content: `未知工具 ${toolCall.name}`,
466
+ tool: toolCall.name,
467
+ args: toolCall.args || {},
468
+ });
469
+ this.emit({
470
+ type: 'step_error',
471
+ content: `未知工具 ${toolCall.name}`,
472
+ tool: toolCall.name,
473
+ error: 'Unknown tool',
474
+ });
475
+ this.messageHistory.push({
476
+ role: 'tool',
477
+ content: JSON.stringify({ success: false, error: `Unknown tool: ${toolCall.name}` })
478
+ });
479
+ continue;
480
+ }
481
+ this.emit({
482
+ type: 'tool',
483
+ content: `🔧 执行: ${toolCall.name}`,
484
+ tool: toolCall.name
485
+ });
486
+ // 2026-06-15: step-timeline — 开节点
487
+ this.emit({
488
+ type: 'step_start',
489
+ content: `调用 ${toolCall.name}`,
490
+ tool: toolCall.name,
491
+ args: toolCall.args || {},
492
+ });
493
+ try {
494
+ // 2026-08-11 (Hermes wedged-loop 检测): 连续 3 次相同工具+相同参数 = 疑似循环工作流 —
495
+ // 计入 no-progress (达到上限由 determineExitReason 中断), 注入续跑提示让 LLM 换策略
496
+ const argsHash = (0, loop_review_js_1.toolCallArgsHash)(toolCall.args);
497
+ this.recentToolCalls.push({ name: toolCall.name, argsHash });
498
+ if (this.recentToolCalls.length > 8)
499
+ this.recentToolCalls.shift();
500
+ const rep = (0, loop_review_js_1.detectRepeatingCalls)(this.recentToolCalls);
501
+ if (rep.repeating) {
502
+ this.state.consecutiveNoProgress++;
503
+ this.pushContinuationHint(`检测到重复工具调用 ${rep.name} (连续 ${this.recentToolCalls.slice(-3).length} 次相同参数) — 疑似循环, 请换一种策略或缩小范围, 不要重复同一调用`);
504
+ this.emit({
505
+ type: 'error',
506
+ content: `⚠ 检测到重复工具调用 ${rep.name} (连续 3 次相同参数) — 疑似循环工作流, 已计入无进展`,
507
+ tool: 'loop-guard',
508
+ });
509
+ }
510
+ const result = await tool.execute(toolCall.args ?? {});
511
+ // 2026-08-11: 输出过大 → 续跑提示 (Hermes dropped-tools continuation 模式),
512
+ // 上下文后续可能被压缩, 提醒 LLM 需要精确数据时缩小范围重查
513
+ const outLen = (result.output || '').length;
514
+ if (outLen > 12_000) {
515
+ this.pushContinuationHint(`工具 ${toolCall.name} 输出过长 (${outLen} 字符), 上下文后续可能被压缩 — 如需精确数据请缩小范围重查`);
516
+ }
517
+ // 2026-06-15: step-timeline — 关闭节点 (success / error)
518
+ this.emit({
519
+ type: result.success ? 'step_done' : 'step_error',
520
+ content: result.success
521
+ ? `${toolCall.name} 成功`
522
+ : `${toolCall.name} 失败: ${result.error}`,
523
+ tool: toolCall.name,
524
+ success: result.success,
525
+ output: result.output,
526
+ error: result.error,
527
+ });
528
+ this.emit({
529
+ type: result.success ? 'status' : 'error',
530
+ content: result.success
531
+ ? `✅ ${toolCall.name} 成功`
532
+ : `❌ ${toolCall.name} 失败: ${result.error}`
533
+ });
534
+ this.messageHistory.push({
535
+ role: 'assistant',
536
+ content: reply,
537
+ toolCall,
538
+ // 2026-08-11 (Hermes 全限幅): 存进 LLM 上下文的工具输出截断到 12K,
539
+ // 前端 step_done emit 仍用完整 output (不影响 UI)
540
+ toolResult: outLen > exports.TOOL_RESULT_MAX_CHARS
541
+ ? { ...result, output: truncateToolOutput(result.output) }
542
+ : result
543
+ });
544
+ // Record quality from tool result
545
+ const toolQuality = this.evaluateToolResult(result);
546
+ this.state.qualityScores.push(toolQuality);
547
+ }
548
+ catch (execError) {
549
+ this.emit({
550
+ type: 'error',
551
+ content: `❌ 工具执行异常: ${execError}`
552
+ });
553
+ this.messageHistory.push({
554
+ role: 'tool',
555
+ content: JSON.stringify({ success: false, error: String(execError) })
556
+ });
557
+ }
558
+ }
559
+ }
560
+ catch (error) {
561
+ this.emit({
562
+ type: 'error',
563
+ content: `❌ 循环异常: ${error}`
564
+ });
565
+ return this.createResult(false, response, 'error');
566
+ }
567
+ }
568
+ // Loop exited - determine reason
569
+ const exitReason = this.determineExitReason(effectiveConfig);
570
+ if (!response && this.messageHistory.length > 0) {
571
+ const lastAssistant = this.messageHistory
572
+ .filter(m => m.role === 'assistant')
573
+ .pop();
574
+ response = lastAssistant?.content || '任务处理超时';
575
+ }
576
+ return this.createResult(exitReason !== 'error', response, exitReason);
577
+ }
578
+ /**
579
+ * Determine if loop should continue
580
+ */
581
+ shouldContinue(config) {
582
+ // Hard stop: max iterations reached
583
+ if (this.state.iteration >= config.maxIterations) {
584
+ this.emit({
585
+ type: 'status',
586
+ content: `🛑 达到最大迭代次数 ${config.maxIterations}`
587
+ });
588
+ return false;
589
+ }
590
+ // Soft stop: consecutive no progress
591
+ if (this.state.consecutiveNoProgress >= config.maxConsecutiveNoProgress) {
592
+ this.emit({
593
+ type: 'status',
594
+ content: `🛑 连续 ${config.maxConsecutiveNoProgress} 次无进展`
595
+ });
596
+ return false;
597
+ }
598
+ return true;
599
+ }
600
+ /**
601
+ * Adapt configuration based on task profile
602
+ */
603
+ adaptConfigForTask(profile) {
604
+ return {
605
+ ...this.config,
606
+ maxIterations: Math.min(this.config.maxIterations, profile.suggestedMaxIterations),
607
+ maxTokenBudget: Math.min(this.config.maxTokenBudget, profile.tokenBudget),
608
+ complexity: profile.complexity
609
+ };
610
+ }
611
+ /**
612
+ * Extract pending tool uses from LLM response
613
+ */
614
+ extractPendingToolUses(content) {
615
+ const pending = [];
616
+ // Pattern 0: <tool_use>{...JSON...}</tool_use> (Anthropic 风格 + minimax 也用)
617
+ // 这次 LLM 输出: <tool_use>\n{"name": "read_document", "arguments": {"path": "/Users/.../README.md"}}\n</tool_use>
618
+ const toolUseRe = /<tool_use>\s*(\{[\s\S]*?\})\s*<\/tool_use>/g;
619
+ let match;
620
+ while ((match = toolUseRe.exec(content)) !== null) {
621
+ try {
622
+ const obj = JSON.parse(match[1]);
623
+ if (obj && obj.name && this.tools.has(obj.name)) {
624
+ const args = this.normalizeArgs(canonicalizeToolCallArguments(obj.arguments));
625
+ pending.push({ name: obj.name, args, description: '', parameters: {} });
626
+ }
627
+ else if (obj && obj.name && !this.tools.has(obj.name)) {
628
+ this.pushContinuationHint(`工具 ${obj.name} 未注册/不存在, 调用已跳过 — 请换用已提供的工具`);
629
+ }
630
+ }
631
+ catch (e) {
632
+ // JSON 解析失败, 继续下一 match
633
+ }
634
+ }
635
+ // Pattern 0b: <function_calls><invoke name="X"><parameter name="k">v</parameter>...</invoke></function_calls>
636
+ // 这次 minimax LLM 用这种 Anthropic 风格 XML
637
+ const fnCallsRe = /<function_calls>([\s\S]*?)<\/function_calls>/g;
638
+ while ((match = fnCallsRe.exec(content)) !== null) {
639
+ const block = match[1];
640
+ // 抓 <invoke name="X">...</invoke>
641
+ const invokeRe = /<invoke\s+name="(\w+)"\s*>([\s\S]*?)<\/invoke>/g;
642
+ let im;
643
+ while ((im = invokeRe.exec(block)) !== null) {
644
+ const name = im[1];
645
+ if (!this.tools.has(name))
646
+ continue;
647
+ // 抓 <parameter name="k">v</parameter> 列表
648
+ const args = {};
649
+ const paramRe = /<parameter\s+name="(\w+)"\s*>([\s\S]*?)<\/parameter>/g;
650
+ let pm;
651
+ while ((pm = paramRe.exec(im[2])) !== null) {
652
+ args[pm[1]] = pm[2].trim().replace(/^["']|['"]$/g, '');
653
+ }
654
+ // 避免重复添加
655
+ if (!pending.some(p => p.name === name)) {
656
+ pending.push({ name, args, description: '', parameters: {} });
657
+ }
658
+ }
659
+ }
660
+ // 2026-06-18 (supervisor): Claude Code 风格 <tool_call><tool_name>...</tool_call>
661
+ // bolloon agent 之前一直被 model 教用这个格式, 但 pivot loop 只认 3 个旧 pattern.
662
+ // 现在加: <tool_call><invoke name="X"><parameter name="k">v</parameter></invoke></tool_call>
663
+ const toolCodeRe = /<tool_code>([\s\S]*?)<\/tool_code>/g;
664
+ while ((match = toolCodeRe.exec(content)) !== null) {
665
+ const block = match[1];
666
+ const invokeRe = /<invoke\s+name="(\w+)"\s*>([\s\S]*?)<\/invoke>/g;
667
+ let im;
668
+ while ((im = invokeRe.exec(block)) !== null) {
669
+ const name = im[1];
670
+ if (!this.tools.has(name))
671
+ continue;
672
+ const args = {};
673
+ const paramRe = /<parameter\s+name="(\w+)"\s*>([\s\S]*?)<\/parameter>/g;
674
+ let pm;
675
+ while ((pm = paramRe.exec(im[2])) !== null) {
676
+ args[pm[1]] = pm[2].trim().replace(/^["']|['"]$/g, '');
677
+ }
678
+ if (!pending.some(p => p.name === name)) {
679
+ pending.push({ name, args, description: '', parameters: {} });
680
+ }
681
+ }
682
+ }
683
+ // Pattern 1: Chinese format "调用工具: tool_name(args)"
684
+ const pattern1 = /调用工具[::]\s*(\w+)\s*\(([^)]*)\)/g;
685
+ while ((match = pattern1.exec(content)) !== null) {
686
+ const name = match[1];
687
+ const argsStr = match[2];
688
+ const args = this.parseArgs(argsStr);
689
+ if (this.tools.has(name)) {
690
+ pending.push({ name, args, description: '', parameters: {} });
691
+ }
692
+ }
693
+ // Pattern 2: tool_name(args) format
694
+ const pattern2 = /(\w+)\s*\(\s*([^)]*)\s*\)/g;
695
+ while ((match = pattern2.exec(content)) !== null) {
696
+ const name = match[1];
697
+ const argsStr = match[2];
698
+ // Skip if already matched or doesn't look like a tool call
699
+ if (pending.some(p => p.name === name))
700
+ continue;
701
+ if (!this.tools.has(name))
702
+ continue;
703
+ const args = this.parseArgs(argsStr);
704
+ pending.push({ name, args, description: '', parameters: {} });
705
+ }
706
+ // Pattern 3: JSON format tool calls
707
+ try {
708
+ const jsonMatch = content.match(/\{[\s\S]*"tool_calls"[\s\S]*\}/);
709
+ if (jsonMatch) {
710
+ const parsed = JSON.parse(jsonMatch[0]);
711
+ if (Array.isArray(parsed.tool_calls)) {
712
+ for (const tc of parsed.tool_calls) {
713
+ if (this.tools.has(tc.name)) {
714
+ pending.push({ name: tc.name, args: tc.args || {}, description: '', parameters: {} });
715
+ }
716
+ }
717
+ }
718
+ }
719
+ }
720
+ catch {
721
+ // JSON parsing failed, ignore
722
+ }
723
+ // Pattern 4: Single JSON tool call format {"name": "tool_name", "arguments": {...}}
724
+ // 2026-08-02 fix: 兼容 system prompt 教的 {"name":"X","input":{...}} 格式 —
725
+ // pi-sdk.ts 工具调用格式说明用 input 字段, 但解析器只认 arguments,
726
+ // 导致 LLM 输出 {"name":"read_document","input":{...}} 解析不到 → 工具永不执行。
727
+ const singleJsonRe = /\{\s*"name"\s*:\s*"(\w+)"\s*,\s*"(?:arguments|input)"\s*:\s*(\{[\s\S]*?\})\s*\}/g;
728
+ let singleMatch;
729
+ while ((singleMatch = singleJsonRe.exec(content)) !== null) {
730
+ const name = singleMatch[1];
731
+ if (pending.some(p => p.name === name))
732
+ continue;
733
+ if (!this.tools.has(name))
734
+ continue;
735
+ try {
736
+ const args = JSON.parse(singleMatch[2]);
737
+ if (args && typeof args === 'object') {
738
+ const normalizedArgs = this.normalizeArgs(args);
739
+ pending.push({ name, args: normalizedArgs, description: '', parameters: {} });
740
+ }
741
+ }
742
+ catch {
743
+ // JSON parsing failed, skip
744
+ }
745
+ }
746
+ return pending;
747
+ }
748
+ /**
749
+ * Parse tool arguments from string
750
+ */
751
+ parseArgs(argsStr) {
752
+ const args = {};
753
+ if (!argsStr || !argsStr.trim())
754
+ return args;
755
+ const pairs = argsStr.split(',').map(s => s.trim()).filter(Boolean);
756
+ for (const pair of pairs) {
757
+ // 2026-06-15: LLM 实际输出 3 种格式 — 全支持
758
+ // 1) JSON 风格: {"key":"value"} (服务器日志显示, 但 LLM 不会真输出完整 JSON)
759
+ // 2) key="value" 含双引号 (本次 read_document(path="/Users/..."))
760
+ // 3) key='value' 含单引号
761
+ // 4) key:value (老 Chinese 格式)
762
+ // 5) key value (positional 兜底)
763
+ let m = pair.match(/^["']?([\w-]+)["']?\s*=\s*["']([^"']*)["']$/);
764
+ if (m) {
765
+ args[m[1]] = m[2];
766
+ continue;
767
+ }
768
+ m = pair.match(/^["']?([\w-]+)["']?\s*[:=]\s*([^,]+)$/);
769
+ if (m) {
770
+ args[m[1]] = m[2].trim().replace(/^['"]|['"]$/g, '');
771
+ continue;
772
+ }
773
+ m = pair.match(/^["']?([\w-]+)["']?\s*[:]\s*["']?([^"']*)["']?$/);
774
+ if (m) {
775
+ args[m[1]] = m[2].trim();
776
+ continue;
777
+ }
778
+ // positional 兜底
779
+ const parts = pair.split(/\s+/);
780
+ if (parts.length >= 2) {
781
+ args[parts[0]] = parts.slice(1).join(' ');
782
+ }
783
+ }
784
+ return args;
785
+ }
786
+ /**
787
+ * 把 tool_use JSON 里的 arguments (已经是对象) 转成 Record<string, string>
788
+ * JSON parser 直接给对象, 但 tool.execute 期望 Record<string, string>
789
+ * 非字符串值 JSON.stringify 一下
790
+ */
791
+ normalizeArgs(args) {
792
+ const out = {};
793
+ for (const [k, v] of Object.entries(args || {})) {
794
+ if (v == null)
795
+ continue;
796
+ if (typeof v === 'string')
797
+ out[k] = v;
798
+ else
799
+ out[k] = JSON.stringify(v);
800
+ }
801
+ return out;
802
+ }
803
+ /**
804
+ * Build context from message history
805
+ */
806
+ buildContext() {
807
+ return this.messageHistory.map(m => {
808
+ if (m.role === 'user')
809
+ return `用户: ${m.content}`;
810
+ if (m.role === 'assistant' && m.toolCall && m.toolResult) {
811
+ // 2026-08-02 fix: 工具调用后的 assistant 消息带 toolCall/toolResult,
812
+ // 之前只输出 content (原生 tool_calls 时 content 为空) → LLM 永远看不到结果 → 无限重试同一工具
813
+ return `工具调用: ${m.toolCall.name}(${JSON.stringify(m.toolCall.args)})\n工具结果: ${JSON.stringify(m.toolResult)}`;
814
+ }
815
+ if (m.role === 'assistant')
816
+ return `助手: ${m.content}`;
817
+ if (m.role === 'tool' && m.toolResult) {
818
+ return `工具结果: ${JSON.stringify(m.toolResult)}`;
819
+ }
820
+ return '';
821
+ }).filter(Boolean).join('\n');
822
+ }
823
+ /**
824
+ * Evaluate response quality
825
+ */
826
+ evaluateQuality(response) {
827
+ let score = 0.7; // 2026-07-06: 起点 0.7 — 短回复不应被当成低质量打回去重跑
828
+ // Length bonus
829
+ if (response.length > 100)
830
+ score += 0.05;
831
+ if (response.length > 500)
832
+ score += 0.1;
833
+ // Structure
834
+ if (response.includes('\n'))
835
+ score += 0.05;
836
+ if (response.includes('```'))
837
+ score += 0.1;
838
+ // Conclusion language
839
+ const conclusionWords = ['完成', '总结', '所以', '因此', '答案', '推荐', '建议'];
840
+ if (conclusionWords.some(w => response.includes(w)))
841
+ score += 0.05;
842
+ // Negative indicators
843
+ if (response.includes('调用工具') || response.includes('tool('))
844
+ score -= 0.15;
845
+ if (response.includes('??') || response.includes('未知'))
846
+ score -= 0.1;
847
+ return Math.max(0, Math.min(1, score));
848
+ }
849
+ /**
850
+ * Evaluate tool result quality
851
+ */
852
+ evaluateToolResult(result) {
853
+ if (!result.success)
854
+ return 0.2;
855
+ let score = 0.6;
856
+ if (result.output) {
857
+ score += 0.2;
858
+ if (result.output.length > 100)
859
+ score += 0.1;
860
+ if (result.output.includes('error') || result.output.includes('❌'))
861
+ score -= 0.2;
862
+ if (result.output.includes('success') || result.output.includes('✅'))
863
+ score += 0.1;
864
+ }
865
+ if (result.error)
866
+ score -= 0.3;
867
+ return Math.max(0, Math.min(1, score));
868
+ }
869
+ /**
870
+ * Estimate token count (rough approximation)
871
+ */
872
+ estimateTokens(text) {
873
+ // Rough estimate: ~4 characters per token for Chinese/English mix
874
+ return Math.ceil(text.length / 4);
875
+ }
876
+ /**
877
+ * 2026-07-06: build continuation header — iter ≥ 2 的短 system 头部
878
+ * LLM 已在 messageHistory 里, 不需要每次 11K persona+tools 重装.
879
+ * 短头告诉 LLM: "你已经看过首轮; 继续 conversation, 详情见历史".
880
+ */
881
+ buildContinuationHeader(fullSystemPrompt) {
882
+ // 从 fullSystemPrompt 提取关键锚句: identity persona 第 1 行 + 工作模式 head 段
883
+ // 完整重装只在 iter=1 和 compact 之后两次
884
+ const lines = fullSystemPrompt.split('\n');
885
+ const identityLine = lines.find((l) => l.includes('你是') && !l.includes('(续)')) ?? '';
886
+ return `[continuation] 你的 persona + tools + judgments 已在首轮 messageHistory 中.
887
+ ${identityLine ? identityLine + '\n' : ''}当前 step 别再读 persona 全文, 继续推进任务即可.
888
+ > <final gen> 只在真完成时输出.`;
889
+ }
890
+ /**
891
+ * Create result object
892
+ */
893
+ createResult(success, response, exitReason) {
894
+ const avgQuality = this.state.qualityScores.length > 0
895
+ ? this.state.qualityScores.reduce((a, b) => a + b, 0) / this.state.qualityScores.length
896
+ : 0;
897
+ return {
898
+ success,
899
+ response,
900
+ iterations: this.state.iteration,
901
+ toolCalls: this.state.toolCallsCount,
902
+ qualityScore: avgQuality,
903
+ exitReason,
904
+ state: { ...this.state }
905
+ };
906
+ }
907
+ /**
908
+ * Determine why loop exited
909
+ */
910
+ determineExitReason(config) {
911
+ if (this.state.iteration >= config.maxIterations) {
912
+ return 'max_iterations';
913
+ }
914
+ if (this.state.consecutiveNoProgress >= config.maxConsecutiveNoProgress) {
915
+ return 'no_progress_exhausted';
916
+ }
917
+ if (this.state.pendingToolUses.length === 0 && this.state.iteration >= config.minIterations) {
918
+ return 'no_pending_tools';
919
+ }
920
+ if (this.state.totalTokens > config.maxTokenBudget) {
921
+ return 'token_budget_exceeded';
922
+ }
923
+ return 'max_iterations';
924
+ }
925
+ /**
926
+ * Emit stream event
927
+ */
928
+ emit(event) {
929
+ if (this.streamCallback) {
930
+ this.streamCallback(event);
931
+ }
932
+ }
933
+ /**
934
+ * Get current state
935
+ */
936
+ getState() {
937
+ return { ...this.state };
938
+ }
939
+ /**
940
+ * Reset the loop state
941
+ */
942
+ reset() {
943
+ this.state = this.createInitialState();
944
+ this.messageHistory = [];
945
+ }
946
+ }
947
+ exports.WorkflowPivotLoop = WorkflowPivotLoop;
948
+ /**
949
+ * Factory to create a default pivot loop configuration
950
+ */
951
+ function createDefaultPivotConfig(complexity) {
952
+ // 2026-07-06: maxIterations 默认大幅上调 — LLM 自己约束结束时机, 持久循环.
953
+ // 真实停止由 LLM emit <final gen> / 质量达标 / 连续无进展 / user abort 触发.
954
+ // 旧 30/60 iter 在长任务 (eg. 大文档改写) 太短, 现在跑到 N 次也不报超时.
955
+ const profiles = {
956
+ simple: {
957
+ maxIterations: 200,
958
+ minIterations: 1,
959
+ qualityThreshold: 0.6,
960
+ maxConsecutiveNoProgress: 5,
961
+ maxTokenBudget: 10000
962
+ },
963
+ moderate: {
964
+ maxIterations: 1000,
965
+ minIterations: 2,
966
+ qualityThreshold: 0.7,
967
+ maxConsecutiveNoProgress: 8,
968
+ maxTokenBudget: 30000
969
+ },
970
+ complex: {
971
+ maxIterations: 2000,
972
+ minIterations: 3,
973
+ qualityThreshold: 0.75,
974
+ maxConsecutiveNoProgress: 12,
975
+ maxTokenBudget: 60000
976
+ }
977
+ };
978
+ return complexity ? profiles[complexity] : profiles.moderate;
979
+ }
980
+ /**
981
+ * Helper to run a simple prompt through the loop
982
+ */
983
+ async function runPivotLoop(input, llm, tools, systemPrompt, config, streamCallback) {
984
+ const loop = new WorkflowPivotLoop(config || createDefaultPivotConfig());
985
+ loop.registerTools(tools);
986
+ return loop.execute(input, llm, systemPrompt, streamCallback);
987
+ }
988
+ //# sourceMappingURL=workflow-pivot-loop.js.map