minimal-agent 0.13.0 → 0.15.0

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 (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -0,0 +1,82 @@
1
+ import assert from 'node:assert/strict';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+ import test from 'node:test';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const HERE = dirname(fileURLToPath(import.meta.url));
10
+ const SCAFFOLD = join(HERE, 'scaffold.mjs');
11
+ const VALIDATE = join(HERE, 'validate.mjs');
12
+
13
+ function run(script, args) {
14
+ return spawnSync(process.execPath, [script, ...args], {
15
+ encoding: 'utf8',
16
+ });
17
+ }
18
+
19
+ test('scaffold 默认只创建必需文件,可选目录必须显式请求', async (t) => {
20
+ const temp = await mkdtemp(join(tmpdir(), 'workflow-creator-'));
21
+ t.after(() => rm(temp, { recursive: true, force: true }));
22
+ const workflowsRoot = join(temp, 'workflows');
23
+
24
+ const minimal = run(SCAFFOLD, [
25
+ 'minimal-case',
26
+ `--workflows-root=${workflowsRoot}`,
27
+ ]);
28
+ assert.equal(minimal.status, 0, minimal.stderr);
29
+ assert.deepEqual(
30
+ (await readdir(join(workflowsRoot, 'minimal-case'))).sort(),
31
+ ['README.md', 'workflow.mjs'],
32
+ );
33
+
34
+ const verdict = run(VALIDATE, [
35
+ join(workflowsRoot, 'minimal-case', 'workflow.mjs'),
36
+ ]);
37
+ assert.equal(verdict.status, 0, verdict.stderr);
38
+
39
+ const extended = run(SCAFFOLD, [
40
+ 'extended-case',
41
+ '--with=scripts,prompts,assets',
42
+ `--workflows-root=${workflowsRoot}`,
43
+ ]);
44
+ assert.equal(extended.status, 0, extended.stderr);
45
+ assert.deepEqual(
46
+ (await readdir(join(workflowsRoot, 'extended-case'))).sort(),
47
+ ['README.md', 'assets', 'prompts', 'scripts', 'workflow.mjs'],
48
+ );
49
+ assert.match(
50
+ await readFile(
51
+ join(workflowsRoot, 'extended-case', 'scripts', 'README.md'),
52
+ 'utf8',
53
+ ),
54
+ /\$\{workflowDir\}\/scripts/,
55
+ );
56
+ });
57
+
58
+ test('validator 拒绝不存在的配套文件引用', async (t) => {
59
+ const temp = await mkdtemp(join(tmpdir(), 'workflow-validator-'));
60
+ t.after(() => rm(temp, { recursive: true, force: true }));
61
+ const workflowDir = join(temp, 'workflows', 'broken-case');
62
+
63
+ const scaffold = run(SCAFFOLD, [
64
+ 'broken-case',
65
+ `--workflows-root=${join(temp, 'workflows')}`,
66
+ ]);
67
+ assert.equal(scaffold.status, 0, scaffold.stderr);
68
+ await writeFile(
69
+ join(workflowDir, 'workflow.mjs'),
70
+ `export const meta = { description: 'broken reference', artifacts: [] }
71
+
72
+ const prompt = await readText('prompts/missing.md')
73
+ echo(prompt)
74
+ `,
75
+ 'utf8',
76
+ );
77
+
78
+ const verdict = run(VALIDATE, [join(workflowDir, 'workflow.mjs')]);
79
+ assert.equal(verdict.status, 1);
80
+ assert.match(verdict.stderr, /prompts\/missing\.md/);
81
+ assert.match(verdict.stderr, /不存在/);
82
+ });
@@ -0,0 +1,536 @@
1
+ import crypto from 'node:crypto';
2
+ /**
3
+ * 同一个检查点最多连续暂缓几次,超过就降级放行并留痕。
4
+ *
5
+ * 取 3 而不是 1:一次暂缓 + 一次咨询 + 一次记录决策是正常配合的节奏,
6
+ * 留出余量才不会误伤按流程走、只是多绕了一步的模型;取有限值而不是无限,
7
+ * 是因为唯一的替代上界是 maxTurns(200 轮),那不叫闸门叫卡死。
8
+ */
9
+ const MAX_CONSECUTIVE_DEFERRALS = 3;
10
+ const MAX_FREE_RECONCILIATIONS_PER_CHECKPOINT = 1;
11
+ const WRITE_TOOLS = new Set(['Edit', 'MultiEdit', 'Write', 'ApplyPatch', 'NotebookEdit']);
12
+ const INVESTIGATION_TOOLS = new Set([
13
+ 'Read',
14
+ 'Glob',
15
+ 'Grep',
16
+ 'LSP',
17
+ 'WebSearch',
18
+ 'WebFetch',
19
+ 'WebBrowser',
20
+ 'TerminalCapture',
21
+ 'RecallMemory',
22
+ 'SearchConversations',
23
+ ]);
24
+ function textContent(message) {
25
+ if (!message)
26
+ return '';
27
+ if (typeof message.content === 'string')
28
+ return message.content;
29
+ if (Array.isArray(message.content)) {
30
+ return message.content
31
+ .filter((part) => part.type === 'text')
32
+ .map((part) => part.text)
33
+ .join('\n');
34
+ }
35
+ return '';
36
+ }
37
+ function toolNamesByCallId(history) {
38
+ const names = new Map();
39
+ for (const message of history) {
40
+ if (message.role !== 'assistant')
41
+ continue;
42
+ for (const call of message.tool_calls ?? [])
43
+ names.set(call.id, call.function.name);
44
+ }
45
+ return names;
46
+ }
47
+ function advisorMetadata(metadata) {
48
+ if (metadata?.kind === 'advisor_checkpoint' ||
49
+ metadata?.kind === 'advisor_consultation' ||
50
+ metadata?.kind === 'advisor_decision')
51
+ return metadata;
52
+ return undefined;
53
+ }
54
+ function versionsOf(metadata) {
55
+ return {
56
+ taskVersion: metadata.taskVersion,
57
+ workVersion: metadata.workVersion,
58
+ evidenceVersion: metadata.evidenceVersion,
59
+ };
60
+ }
61
+ function checkpointKey(checkpoint, versions, signature) {
62
+ // pre-execution/pre-delivery 的意图是"本任务版本内只问一次"(见 beforeTool()
63
+ // 的 reason 文案"即将进行本任务版本的首次实质写入")。旧实现把 workVersion/
64
+ // evidenceVersion 也编进 key,而这两个计数器在几乎每次成功的工具调用(包括
65
+ // 纯 Read/Grep,见 observeToolResult)后都会变化——"首次"因此从未真正生效,
66
+ // 任务里的每一次不同写入都会重新触发一轮完整 Advisor+AdvisorDecision,同时
67
+ // 让 MAX_CONSECUTIVE_DEFERRALS 的连续暂缓降级网因为 key 很少连续重复而基本
68
+ // 失效。改成只用 taskVersion,让这两个检查点在一个任务版本内真正只问一次。
69
+ if (checkpoint === 'pre-execution' || checkpoint === 'pre-delivery') {
70
+ return `${versions.taskVersion}:${checkpoint}`;
71
+ }
72
+ // high-risk 的意图相反:每个不同的危险动作都该有自己的把关,但不能被"中间
73
+ // 插了一次无关的成功调用"误判成新动作——用动作自身的签名代替会漂移的全局
74
+ // 版本计数器,同一动作的重试才能被正确识别为"同一个"。
75
+ if (checkpoint === 'high-risk') {
76
+ return `${versions.taskVersion}:high-risk:${signature ?? 'unknown'}`;
77
+ }
78
+ return `${versions.taskVersion}:${checkpoint}:${versions.workVersion}:${versions.evidenceVersion}`;
79
+ }
80
+ /**
81
+ * Run-local controller whose durable source of truth is Advisor metadata already
82
+ * stored on tool messages. It owns checkpoint de-duplication and versioning;
83
+ * provider calls remain in tools/advisor/advisor.ts.
84
+ */
85
+ export class AdvisorCoordinator {
86
+ #history;
87
+ #currentRequest;
88
+ #advisorAvailable;
89
+ #completed = new Set();
90
+ #deferredOnce = new Set();
91
+ #deferCounts = new Map();
92
+ #successfulConsultationsByKey = new Map();
93
+ #softAlerts = new Set();
94
+ #taskVersion;
95
+ #taskCommitted = false;
96
+ #workVersion = 0;
97
+ #evidenceVersion = 0;
98
+ #investigationEvidence = 0;
99
+ #mutations = 0;
100
+ #verifications = 0;
101
+ #deliveryProduced = false;
102
+ #required;
103
+ #softCheckpoint;
104
+ #pending;
105
+ #lastDecision;
106
+ #reminders = [];
107
+ constructor(input) {
108
+ this.#history = input.history;
109
+ this.#currentRequest = input.currentRequest;
110
+ this.#advisorAvailable = input.advisorAvailable;
111
+ const names = toolNamesByCallId(input.history);
112
+ let maxTaskVersion = 0;
113
+ let maxWorkVersion = 0;
114
+ let maxEvidenceVersion = 0;
115
+ const decisions = new Set();
116
+ const successfulConsultations = [];
117
+ const currentRequestIndex = input.currentRequestMessageId
118
+ ? input.history.findIndex((message) => message.role === 'user' && message.id === input.currentRequestMessageId)
119
+ : -1;
120
+ for (let index = 0; index < input.history.length; index += 1) {
121
+ const message = input.history[index];
122
+ if (message.role !== 'tool')
123
+ continue;
124
+ const metadata = advisorMetadata(message.display_metadata);
125
+ if (metadata) {
126
+ maxTaskVersion = Math.max(maxTaskVersion, metadata.taskVersion);
127
+ maxWorkVersion = Math.max(maxWorkVersion, metadata.workVersion);
128
+ maxEvidenceVersion = Math.max(maxEvidenceVersion, metadata.evidenceVersion);
129
+ if (metadata.kind === 'advisor_decision') {
130
+ decisions.add(metadata.consultationId);
131
+ this.#completed.add(metadata.checkpointKey);
132
+ this.#lastDecision = metadata;
133
+ }
134
+ else if (metadata.kind === 'advisor_consultation') {
135
+ if (metadata.status === 'failed')
136
+ this.#completed.add(metadata.checkpointKey);
137
+ else {
138
+ this.#successfulConsultationsByKey.set(metadata.checkpointKey, (this.#successfulConsultationsByKey.get(metadata.checkpointKey) ?? 0) + 1);
139
+ successfulConsultations.push({ index, metadata });
140
+ }
141
+ }
142
+ }
143
+ const toolName = names.get(message.tool_call_id);
144
+ const display = message.display_metadata;
145
+ if (display?.kind === 'file_activity') {
146
+ const mutationCount = display.files.filter((file) => ['created', 'modified', 'generated', 'deleted'].includes(file.activity)).length;
147
+ this.#workVersion += mutationCount;
148
+ }
149
+ const failed = message.content.startsWith('Error: ');
150
+ if (toolName &&
151
+ toolName !== 'Advisor' &&
152
+ toolName !== 'AdvisorDecision' &&
153
+ display?.kind !== 'advisor_checkpoint' &&
154
+ (!failed || display?.kind === 'process_execution')) {
155
+ this.#evidenceVersion += 1;
156
+ }
157
+ }
158
+ this.#workVersion = Math.max(this.#workVersion, maxWorkVersion);
159
+ this.#evidenceVersion = Math.max(this.#evidenceVersion, maxEvidenceVersion);
160
+ this.#taskVersion = maxTaskVersion + 1;
161
+ this.#pending = successfulConsultations
162
+ .filter(({ index }) => input.currentRequestMessageId === undefined
163
+ ? true
164
+ : currentRequestIndex >= 0 && index > currentRequestIndex)
165
+ .reverse()
166
+ .map(({ metadata }) => metadata)
167
+ .find((consultation) => !decisions.has(consultation.consultationId));
168
+ }
169
+ get versions() {
170
+ return {
171
+ taskVersion: this.#taskVersion,
172
+ workVersion: this.#workVersion,
173
+ evidenceVersion: this.#evidenceVersion,
174
+ };
175
+ }
176
+ get pendingConsultationId() {
177
+ return this.#pending?.consultationId;
178
+ }
179
+ get canReconcileConsultation() {
180
+ if (!this.#pending)
181
+ return false;
182
+ const successful = this.#successfulConsultationsByKey.get(this.#pending.checkpointKey) ?? 0;
183
+ return successful <= MAX_FREE_RECONCILIATIONS_PER_CHECKPOINT;
184
+ }
185
+ get hasActiveGate() {
186
+ return this.#required !== undefined || this.#softCheckpoint !== undefined;
187
+ }
188
+ setAvailable(available) {
189
+ this.#advisorAvailable = available;
190
+ }
191
+ usageLine(used, max) {
192
+ const pending = this.#pending
193
+ ? `;顾问意见 #${this.#pending.consultationId.slice(-8)} 等待主 Agent 记录采纳决定`
194
+ : '';
195
+ return used === 0
196
+ ? `Advisor 动态:本回合尚未咨询顾问(可用 ${max} 次)${pending}。`
197
+ : `Advisor 动态:本回合已咨询 ${used}/${max} 次${pending}。`;
198
+ }
199
+ transientReminder() {
200
+ return this.#reminders.join('\n\n');
201
+ }
202
+ markTransientDelivered() {
203
+ this.#reminders = [];
204
+ }
205
+ beforeTool(call, semantics) {
206
+ if (!this.#advisorAvailable ||
207
+ call.function.name === 'Advisor' ||
208
+ call.function.name === 'AdvisorDecision') {
209
+ return { allow: true };
210
+ }
211
+ if (this.#pending && (semantics.mutatesWorkspace || semantics.highRisk)) {
212
+ return this.#deferPending('顾问意见已返回,但尚未调用 AdvisorDecision 记录主 Agent 的采纳判断。');
213
+ }
214
+ if (semantics.highRisk) {
215
+ // 用动作自身的签名(工具名+参数的短哈希)代替会被无关调用带动的全局版本
216
+ // 计数器:同一个危险动作的重试仍归到同一个 key,不同的危险动作各自独立
217
+ // 把关,两者都不受"中间插了一次成功的 Read"影响。
218
+ const signature = crypto
219
+ .createHash('sha1')
220
+ .update(`${call.function.name}:${call.function.arguments}`)
221
+ .digest('hex')
222
+ .slice(0, 16);
223
+ return this.requestCheckpoint('high-risk', semantics.riskReason ?? '即将执行不可逆操作', { signature });
224
+ }
225
+ if (semantics.mutatesWorkspace) {
226
+ return this.requestCheckpoint('pre-execution', '即将进行本任务版本的首次实质写入');
227
+ }
228
+ return { allow: true };
229
+ }
230
+ requestCheckpoint(checkpoint, reason, options = {}) {
231
+ if (!this.#advisorAvailable)
232
+ return { allow: true };
233
+ this.#commitTask();
234
+ const key = checkpointKey(checkpoint, this.versions, options.signature);
235
+ if (this.#completed.has(key))
236
+ return { allow: true };
237
+ if (options.oneShot && this.#deferredOnce.has(key)) {
238
+ this.#required = undefined;
239
+ this.#completed.add(key);
240
+ return { allow: true };
241
+ }
242
+ // ── 死锁上界:模型不配合时也必须让路 ──────────────────────────────
243
+ // 顾问**失败**这条路已有降级(finishConsultation 会 #completed.add),
244
+ // 但模型**不配合**(一直不调 Advisor/AdvisorDecision、只管重试写操作)此前无人管:
245
+ // high-risk 与 pre-execution 都不传 oneShot,同一个 key 会被反复 defer,
246
+ // 唯一的界是 maxTurns —— 而它刚从 50 涨到 200,用户看到的就是「agent 卡住不干活」。
247
+ // 本模块自己的原则是「不会死锁」,这里把那条原则补全到第二条路上。
248
+ const seen = (this.#deferCounts.get(key) ?? 0) + 1;
249
+ this.#deferCounts.set(key, seen);
250
+ if (seen > MAX_CONSECUTIVE_DEFERRALS) {
251
+ this.#required = undefined;
252
+ this.#completed.add(key);
253
+ // 绕过了本该经过的检查点就必须留痕:静默放行会让模型以为自己合规了。
254
+ const notice = `Advisor 检查点 ${checkpoint} 已连续暂缓 ${MAX_CONSECUTIVE_DEFERRALS} 次仍未完成咨询,本次降级放行。这一步没有第二意见背书,请自行加倍核实,并在汇报时如实说明。`;
255
+ if (!this.#reminders.includes(notice))
256
+ this.#reminders.push(notice);
257
+ return { allow: true };
258
+ }
259
+ this.#required = { checkpoint, key, reason };
260
+ this.#deferredOnce.add(key);
261
+ return this.#defer(checkpoint, reason, key);
262
+ }
263
+ notifyStalled(signature) {
264
+ if (!this.#advisorAvailable)
265
+ return;
266
+ this.#commitTask();
267
+ const key = `${checkpointKey('stalled', this.versions)}:${signature ?? 'unknown'}`;
268
+ if (this.#softAlerts.has(key))
269
+ return;
270
+ this.#softAlerts.add(key);
271
+ this.#softCheckpoint = {
272
+ checkpoint: 'stalled',
273
+ key: checkpointKey('stalled', this.versions),
274
+ };
275
+ this.#reminders.push('检测到连续同类失败或执行没有进展。继续重试前请优先调用 Advisor 获取第二意见;这是提醒,不阻止只读诊断或切换路径。');
276
+ }
277
+ shouldCheckDelivery() {
278
+ return (this.#mutations > 0 ||
279
+ this.#verifications > 0 ||
280
+ this.#deliveryProduced ||
281
+ this.#investigationEvidence >= 3);
282
+ }
283
+ beforeDelivery() {
284
+ if (this.#pending) {
285
+ const decision = this.#deferPending('提交最终结果前必须先用 AdvisorDecision 记录对当前顾问意见的判断。');
286
+ if (decision.deferred &&
287
+ !decision.deferred.ok &&
288
+ !this.#reminders.includes(decision.deferred.error)) {
289
+ this.#reminders.push(decision.deferred.error);
290
+ }
291
+ return decision;
292
+ }
293
+ if (!this.shouldCheckDelivery())
294
+ return { allow: true };
295
+ const decision = this.requestCheckpoint('pre-delivery', '当前回合已产生实质成果或证据,提交最终结论前进行一次第二意见复核', { oneShot: true });
296
+ if (decision.deferred &&
297
+ !decision.deferred.ok &&
298
+ !this.#reminders.includes(decision.deferred.error)) {
299
+ this.#reminders.push(decision.deferred.error);
300
+ }
301
+ return decision;
302
+ }
303
+ beginConsultation() {
304
+ this.#commitTask();
305
+ // #pending 存在 = 有一个检查点已经问过、还没被 AdvisorDecision 结清。
306
+ // 这种情况下的任何新咨询(模型主动复核、或 notifyStalled 又冒出一个软
307
+ // 检查点)都必须沿用它的身份,不能落到 #required/#softCheckpoint/默认
308
+ // pre-execution ——否则原始检查点的 checkpointKey 永远进不了 #completed,
309
+ // 重试会被误判成"没咨询过"再次拦下,而模型明明已经照工具说明书的要求
310
+ // 做了复核。这与 beforeTool 顶部"#pending 存在就先拦"的语义保持一致:
311
+ // 既然还有检查点没走完决策,新咨询理应服务于把它结清,而不是凭空开新身份。
312
+ const active = this.#pending
313
+ ? { checkpoint: this.#pending.checkpoint, key: this.#pending.checkpointKey }
314
+ : this.#required ??
315
+ this.#softCheckpoint ?? {
316
+ checkpoint: 'pre-execution',
317
+ // 刻意不用 checkpointKey('pre-execution', ...):这个分支只在没有任何
318
+ // 活跃检查点时才会走到,即模型是主动/复核性质地咨询。pre-execution
319
+ // 的 key 现在只随 taskVersion 变化(见 checkpointKey 头注),如果这里
320
+ // 复用同一个 key,一次纯主动咨询 + AdvisorDecision 就会把 #completed
321
+ // 里真正的首次写入检查点提前标记掉,导致它对本任务版本永久失效。
322
+ // 'voluntary' 是任何真实检查点都不会产生的命名空间,两者永远不会撞车。
323
+ key: `${this.versions.taskVersion}:voluntary`,
324
+ };
325
+ return {
326
+ kind: 'advisor_consultation',
327
+ consultationId: crypto.randomUUID(),
328
+ checkpoint: active.checkpoint,
329
+ checkpointKey: active.key,
330
+ status: 'completed',
331
+ ...this.versions,
332
+ };
333
+ }
334
+ finishConsultation(metadata, ok) {
335
+ const finished = {
336
+ ...metadata,
337
+ status: ok ? 'completed' : 'failed',
338
+ };
339
+ if (ok) {
340
+ this.#pending = finished;
341
+ this.#successfulConsultationsByKey.set(finished.checkpointKey, (this.#successfulConsultationsByKey.get(finished.checkpointKey) ?? 0) + 1);
342
+ }
343
+ else {
344
+ this.#completed.add(finished.checkpointKey);
345
+ if (this.#pending?.checkpointKey === finished.checkpointKey)
346
+ this.#pending = undefined;
347
+ }
348
+ this.#required = undefined;
349
+ this.#softCheckpoint = undefined;
350
+ return finished;
351
+ }
352
+ recordDecision(input) {
353
+ if (!this.#pending ||
354
+ this.#pending.consultationId !== input.consultationId) {
355
+ const expected = this.#pending?.consultationId;
356
+ return {
357
+ ok: false,
358
+ error: expected
359
+ ? `顾问咨询 ID 不匹配:收到 ${input.consultationId},当前待处理的完整 consultationId 是 ${expected}。请原样使用该完整 ID 重试一次 AdvisorDecision。`
360
+ : `没有找到待处理的顾问咨询 ${input.consultationId};不要继续重试 AdvisorDecision。`,
361
+ recovery: expected ? 'change-input' : 'none',
362
+ };
363
+ }
364
+ const metadata = {
365
+ kind: 'advisor_decision',
366
+ consultationId: input.consultationId,
367
+ checkpoint: this.#pending.checkpoint,
368
+ checkpointKey: this.#pending.checkpointKey,
369
+ decision: input.decision,
370
+ rationale: input.rationale,
371
+ acceptedPoints: input.acceptedPoints ?? [],
372
+ rejectedPoints: input.rejectedPoints ?? [],
373
+ verificationPlan: input.verificationPlan ?? [],
374
+ ...versionsOf(this.#pending),
375
+ };
376
+ this.#completed.add(metadata.checkpointKey);
377
+ this.#lastDecision = metadata;
378
+ this.#pending = undefined;
379
+ return {
380
+ ok: true,
381
+ content: `已记录顾问意见处理决定:${input.decision}。理由:${input.rationale}`,
382
+ metadata,
383
+ };
384
+ }
385
+ observeToolResult(call, result) {
386
+ if (!result.ok && result.disposition === 'deferred')
387
+ return;
388
+ if (result.metadata?.kind === 'advisor_consultation') {
389
+ if (result.metadata.status === 'completed')
390
+ this.#pending = result.metadata;
391
+ else {
392
+ this.#completed.add(result.metadata.checkpointKey);
393
+ if (this.#pending?.checkpointKey === result.metadata.checkpointKey)
394
+ this.#pending = undefined;
395
+ }
396
+ return;
397
+ }
398
+ if (result.metadata?.kind === 'advisor_decision') {
399
+ this.#completed.add(result.metadata.checkpointKey);
400
+ this.#lastDecision = result.metadata;
401
+ this.#pending = undefined;
402
+ return;
403
+ }
404
+ const metadata = result.metadata;
405
+ const verificationResult = Boolean(metadata?.kind === 'process_execution' &&
406
+ metadata.commandKind !== 'other' &&
407
+ ['completed', 'failed'].includes(metadata.status));
408
+ if (verificationResult) {
409
+ this.#verifications += 1;
410
+ this.#evidenceVersion += 1;
411
+ if (!result.ok)
412
+ return;
413
+ }
414
+ if (!result.ok)
415
+ return;
416
+ if (metadata?.kind === 'file_activity') {
417
+ const mutations = metadata.files.filter((file) => ['created', 'modified', 'generated', 'deleted'].includes(file.activity)).length;
418
+ this.#mutations += mutations;
419
+ this.#workVersion += mutations;
420
+ }
421
+ if (metadata?.kind === 'result_manifest')
422
+ this.#deliveryProduced = true;
423
+ if (INVESTIGATION_TOOLS.has(call.function.name))
424
+ this.#investigationEvidence += 1;
425
+ if (call.function.name !== 'Advisor' &&
426
+ call.function.name !== 'AdvisorDecision' &&
427
+ !verificationResult) {
428
+ this.#evidenceVersion += 1;
429
+ }
430
+ }
431
+ contextPacket(note) {
432
+ const names = toolNamesByCallId(this.#history);
433
+ const changedFiles = new Set();
434
+ const evidence = [];
435
+ let previousAdvice;
436
+ let lastAdvisorIndex = -1;
437
+ for (let index = 0; index < this.#history.length; index += 1) {
438
+ const message = this.#history[index];
439
+ if (message.role !== 'tool')
440
+ continue;
441
+ const toolName = names.get(message.tool_call_id) ?? 'Tool';
442
+ if (message.display_metadata?.kind === 'file_activity') {
443
+ for (const file of message.display_metadata.files)
444
+ changedFiles.add(file.relativePath);
445
+ }
446
+ if (message.display_metadata?.kind === 'process_execution') {
447
+ evidence.push(`${toolName}: ${message.display_metadata.commandKind}/${message.display_metadata.status}`);
448
+ }
449
+ else if (message.display_metadata?.kind === 'result_manifest') {
450
+ evidence.push(`${toolName}: 已生成 ${message.display_metadata.manifest.files.length} 个交付文件`);
451
+ }
452
+ else if (toolName !== 'Advisor' &&
453
+ toolName !== 'AdvisorDecision' &&
454
+ evidence.length < 12) {
455
+ evidence.push(`${toolName}: ${message.content.slice(0, 240)}`);
456
+ }
457
+ if (toolName === 'Advisor' &&
458
+ message.display_metadata?.kind === 'advisor_consultation' &&
459
+ message.display_metadata.status === 'completed') {
460
+ previousAdvice = message.content.slice(0, 4_000);
461
+ lastAdvisorIndex = index;
462
+ }
463
+ }
464
+ const actionsAfterPreviousAdvice = lastAdvisorIndex < 0
465
+ ? []
466
+ : this.#history
467
+ .slice(lastAdvisorIndex + 1)
468
+ .filter((message) => message.role === 'tool')
469
+ .map((message) => names.get(message.tool_call_id) ?? 'Tool')
470
+ .filter((name) => name !== 'AdvisorDecision');
471
+ const firstUser = this.#history.find((message) => message.role === 'user');
472
+ // 与 beginConsultation() 同一条修复:复核调用时顾问看到的 checkpoint 字段
473
+ // 不该被误标成 pre-execution ——它自己就是在评审那个还没结清的检查点。
474
+ const active = this.#pending
475
+ ? { checkpoint: this.#pending.checkpoint }
476
+ : this.#required ?? this.#softCheckpoint;
477
+ return {
478
+ objective: (textContent(firstUser) || this.#currentRequest).slice(0, 8_000),
479
+ currentRequest: this.#currentRequest.slice(0, 8_000),
480
+ checkpoint: active?.checkpoint ?? 'pre-execution',
481
+ versions: this.versions,
482
+ changedFiles: [...changedFiles],
483
+ evidence,
484
+ ...(previousAdvice ? { previousAdvice } : {}),
485
+ actionsAfterPreviousAdvice,
486
+ openQuestions: note ? [note] : [],
487
+ };
488
+ }
489
+ #commitTask() {
490
+ if (this.#taskCommitted)
491
+ return;
492
+ this.#taskCommitted = true;
493
+ }
494
+ #defer(checkpoint, reason, key) {
495
+ this.#commitTask();
496
+ const actualKey = key ?? checkpointKey(checkpoint, this.versions);
497
+ const metadata = {
498
+ kind: 'advisor_checkpoint',
499
+ checkpoint,
500
+ checkpointKey: actualKey,
501
+ status: 'required',
502
+ ...this.versions,
503
+ };
504
+ return {
505
+ allow: false,
506
+ deferred: {
507
+ ok: false,
508
+ disposition: 'deferred',
509
+ recovery: 'change-input',
510
+ sensitivity: 'public',
511
+ metadata,
512
+ error: `Advisor 检查点 ${checkpoint} 暂缓了这一步:${reason}\n请先调用 Advisor 获取第二意见;成功后调用 AdvisorDecision 记录采纳、部分采纳或拒绝及依据,然后重试原操作。若 Advisor 返回不可用/超时/配额不足,本检查点会降级放行,不要循环重试。`,
513
+ },
514
+ };
515
+ }
516
+ #deferPending(reason) {
517
+ const pending = this.#pending;
518
+ if (!pending)
519
+ return { allow: true };
520
+ const key = pending.checkpointKey;
521
+ const seen = (this.#deferCounts.get(key) ?? 0) + 1;
522
+ this.#deferCounts.set(key, seen);
523
+ if (seen > MAX_CONSECUTIVE_DEFERRALS) {
524
+ this.#completed.add(key);
525
+ this.#pending = undefined;
526
+ const notice = `Advisor 检查点 ${pending.checkpoint} 的咨询 ${pending.consultationId} 已连续等待 AdvisorDecision ${MAX_CONSECUTIVE_DEFERRALS} 次,本次降级结清并放行。这一步没有完整的顾问决策记录,请自行核实并在汇报时如实说明。`;
527
+ if (!this.#reminders.includes(notice))
528
+ this.#reminders.push(notice);
529
+ return { allow: true };
530
+ }
531
+ return this.#defer(pending.checkpoint, reason, key);
532
+ }
533
+ }
534
+ export function isWorkspaceMutationTool(name) {
535
+ return WRITE_TOOLS.has(name);
536
+ }