minimal-agent 0.12.0 → 0.14.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 (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  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 +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  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 +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  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 +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  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 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  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 +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  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/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  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 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
@@ -16,16 +16,35 @@
16
16
  * 设计原则:
17
17
  * - 纯工具函数,无全局状态,无副作用(除了 shell 子进程)
18
18
  * - 不依赖任何插件代码,可被 src/ 和 plugins/ 同时导入
19
- * - 工作目录隔离:所有相对路径以 getWorkingDir() 为锚
19
+ * - 工作目录隔离:相对路径以调用方给的 cwd 为锚,缺省 getWorkingDir()
20
+ *
21
+ * ⚠️ cwd 参数不是可有可无的修饰:**验收必须和写入锚在同一个目录**。
22
+ * 会话进入 session worktree 后(EnterWorktree),写文件的工具跟着 worktree 走
23
+ * (loop.ts 按 sessionState.activeWorktree 重定向 cwd),验收若仍锚原 workspace,
24
+ * 就会在空目录里找产物 —— file_exists 恒 false,工作流被判失败并反复重试,
25
+ * 而产物其实好好躺在 worktree 里。调用方拿得到有效 cwd 时务必传进来。
20
26
  * ============================================================
21
27
  */
22
28
 
23
29
  import { existsSync, readFileSync } from 'node:fs';
24
30
  import { spawn } from 'node:child_process';
25
31
  import { sanitizeCredentialEnv } from '../config/configService.js';
32
+ import { CONFIG_LIMITS, normalizeLimited } from '../config/numericLimits.js';
26
33
 
27
34
  import { getWorkingDir } from '../bootstrap/workingDir.js';
28
35
 
36
+ /**
37
+ * `shell:` 检查的默认超时——**唯一真值**。
38
+ *
39
+ * ⚠️ 这个数字此前在本文件里写了两份(`parseCheckString` 的构造处 + `runVerification`
40
+ * 的 `?? 30_000` 兜底),改一处漏一处就会出现「解析时 30s、执行时 60s」这种谁都看不出
41
+ * 的分裂。边界见 `config/numericLimits.ts::CONFIG_LIMITS.verifyShellTimeoutMs`。
42
+ *
43
+ * 为什么默认值不能太大:`verify()` 是工作流硬门,跑不完就阻塞整条流水线。
44
+ * 需要跑全量测试套件的场景应当缩到具体文件,或由调用方显式传 `defaultShellTimeoutMs`。
45
+ */
46
+ export const DEFAULT_SHELL_CHECK_TIMEOUT_MS = 30_000;
47
+
29
48
  export interface Check {
30
49
  type: 'shell' | 'file_contains' | 'file_exists' | 'test_count';
31
50
  command?: string;
@@ -57,7 +76,10 @@ function parseVerifyArg(arg: string): Check | null {
57
76
 
58
77
  switch (type) {
59
78
  case 'shell':
60
- return { type: 'shell', command: value, timeout: 30_000 };
79
+ // ⚠️ 这里**不填** timeout:解析层只管语法,超时是策略、由 runVerification 决定。
80
+ // 曾经在这里写死 30_000,于是 `check.timeout ?? 默认值` 里的默认值永远走不到 ——
81
+ // 调用方传的超时被一个「解析时顺手填上的」值静默盖掉。
82
+ return { type: 'shell', command: value };
61
83
  case 'file_exists':
62
84
  return { type: 'file_exists', file: value };
63
85
  case 'file_contains': {
@@ -128,12 +150,27 @@ interface ShellRunResult {
128
150
  errored: boolean;
129
151
  }
130
152
 
131
- function runShell(command: string, timeout: number): Promise<ShellRunResult> {
153
+ function runShell(
154
+ command: string,
155
+ timeout: number,
156
+ cwd: string,
157
+ ): Promise<ShellRunResult> {
132
158
  return new Promise((resolve) => {
133
159
  const isWin = process.platform === 'win32';
160
+ const opts = { timeout, cwd, env: sanitizeCredentialEnv() };
161
+ // ⚠️ windowsVerbatimArguments: true 是必须的,不是可选优化:Node 给 cmd.exe/
162
+ // .bat 目标默认加一层它自己的参数转义(CVE-2024-27980 之后的安全加固),
163
+ // 会把 command 字符串里模型自己写好的转义(比如内嵌 PowerShell 单行脚本里的
164
+ // `\"..."`)再转义一遍,导致 cmd.exe 转交给子进程的字符串被改写、PowerShell
165
+ // 解析报 UnexpectedToken——文件内容明明字节级正确,check 却稳定失败。
166
+ // 已实测:一段合法的 `powershell -Command "...; Write-Host \"x\"; ..."`
167
+ // 不加这个选项必挂,加了立刻 exitCode 0;简单命令(echo/dir/bun --version)
168
+ // 行为不受影响。verify() 的 shell: 检查类型专供工作流的 hard_checks 使用,
169
+ // 命令来自可信的 LLM 契约草稿或用户输入,不是不可信的外部数据,
170
+ // 关掉这层转义不引入新的注入面。
134
171
  const child = isWin
135
- ? spawn('cmd', ['/c', command], { timeout, env: sanitizeCredentialEnv() })
136
- : spawn('bash', ['-c', command], { timeout, env: sanitizeCredentialEnv() });
172
+ ? spawn('cmd', ['/c', command], { ...opts, windowsVerbatimArguments: true })
173
+ : spawn('bash', ['-c', command], opts);
137
174
 
138
175
  let stdout = '';
139
176
  let stderr = '';
@@ -155,8 +192,12 @@ function runShell(command: string, timeout: number): Promise<ShellRunResult> {
155
192
  });
156
193
  }
157
194
 
158
- export async function verifyShell(command: string, timeout: number): Promise<CheckResult> {
159
- const r = await runShell(command, timeout);
195
+ export async function verifyShell(
196
+ command: string,
197
+ timeout: number,
198
+ cwd: string = getWorkingDir(),
199
+ ): Promise<CheckResult> {
200
+ const r = await runShell(command, timeout, cwd);
160
201
  if (r.errored) {
161
202
  return {
162
203
  check: { type: 'shell', command },
@@ -171,9 +212,12 @@ export async function verifyShell(command: string, timeout: number): Promise<Che
171
212
  };
172
213
  }
173
214
 
174
- export function verifyFileExists(file: string): CheckResult {
175
- // 相对路径以 workingDir 为锚(绝对路径识别含 UNC)
176
- const resolved = isAbsolutePath(file) ? file : `${getWorkingDir()}/${file}`;
215
+ export function verifyFileExists(
216
+ file: string,
217
+ cwd: string = getWorkingDir(),
218
+ ): CheckResult {
219
+ // 相对路径以调用方给的 cwd 为锚(绝对路径识别含 UNC)
220
+ const resolved = isAbsolutePath(file) ? file : `${cwd}/${file}`;
177
221
  const exists = existsSync(resolved);
178
222
  return {
179
223
  check: { type: 'file_exists', file },
@@ -182,8 +226,12 @@ export function verifyFileExists(file: string): CheckResult {
182
226
  };
183
227
  }
184
228
 
185
- export function verifyFileContains(file: string, pattern: string): CheckResult {
186
- const resolved = isAbsolutePath(file) ? file : `${getWorkingDir()}/${file}`;
229
+ export function verifyFileContains(
230
+ file: string,
231
+ pattern: string,
232
+ cwd: string = getWorkingDir(),
233
+ ): CheckResult {
234
+ const resolved = isAbsolutePath(file) ? file : `${cwd}/${file}`;
187
235
  try {
188
236
  const content = readFileSync(resolved, 'utf8');
189
237
  const regex = new RegExp(pattern);
@@ -203,11 +251,14 @@ export function verifyFileContains(file: string, pattern: string): CheckResult {
203
251
  }
204
252
  }
205
253
 
206
- async function verifyTestCount(minCount: number): Promise<CheckResult> {
254
+ async function verifyTestCount(
255
+ minCount: number,
256
+ cwd: string = getWorkingDir(),
257
+ ): Promise<CheckResult> {
207
258
  // 跨运行时:开发用 bun → bun test;npm 全局安装用 Node → npm test --silent
208
259
  // 用 process.versions.bun 探测比 typeof Bun !== 'undefined' 更稳(不依赖全局类型)
209
260
  const cmd = process.versions.bun ? 'bun test' : 'npm test --silent';
210
- const r = await runShell(cmd, 60_000);
261
+ const r = await runShell(cmd, 60_000, cwd);
211
262
  const combined = `${r.stdout}\n${r.stderr}`;
212
263
  if (r.errored) {
213
264
  return {
@@ -232,7 +283,16 @@ async function verifyTestCount(minCount: number): Promise<CheckResult> {
232
283
  * 执行一组检查,返回聚合结果。
233
284
  * 全部通过 → passed=true;任一失败 → passed=false + summary 列出失败项。
234
285
  */
235
- export async function runVerification(checks: Check[]): Promise<VerifyResult> {
286
+ export async function runVerification(
287
+ checks: Check[],
288
+ cwd: string = getWorkingDir(),
289
+ options: { defaultShellTimeoutMs?: number } = {},
290
+ ): Promise<VerifyResult> {
291
+ const shellTimeout = normalizeLimited(
292
+ options.defaultShellTimeoutMs,
293
+ CONFIG_LIMITS.verifyShellTimeoutMs,
294
+ DEFAULT_SHELL_CHECK_TIMEOUT_MS,
295
+ );
236
296
  if (checks.length === 0) {
237
297
  return { passed: true, details: [], summary: '无验证项' };
238
298
  }
@@ -244,16 +304,20 @@ export async function runVerification(checks: Check[]): Promise<VerifyResult> {
244
304
 
245
305
  switch (check.type) {
246
306
  case 'shell':
247
- result = await verifyShell(check.command ?? '', check.timeout ?? 30_000);
307
+ result = await verifyShell(
308
+ check.command ?? '',
309
+ check.timeout ?? shellTimeout,
310
+ cwd,
311
+ );
248
312
  break;
249
313
  case 'file_exists':
250
- result = verifyFileExists(check.file ?? '');
314
+ result = verifyFileExists(check.file ?? '', cwd);
251
315
  break;
252
316
  case 'file_contains':
253
- result = verifyFileContains(check.file ?? '', check.pattern ?? '');
317
+ result = verifyFileContains(check.file ?? '', check.pattern ?? '', cwd);
254
318
  break;
255
319
  case 'test_count':
256
- result = await verifyTestCount(check.minCount ?? 0);
320
+ result = await verifyTestCount(check.minCount ?? 0, cwd);
257
321
  break;
258
322
  default:
259
323
  result = {
@@ -263,7 +327,10 @@ export async function runVerification(checks: Check[]): Promise<VerifyResult> {
263
327
  };
264
328
  }
265
329
 
266
- results.push(result);
330
+ // 回填**原始** check:各 verifier 只收散参(command/file/pattern),返回时会
331
+ // 自己重建一个残缺的 check 对象,把 timeout 这类字段丢掉。details 是给人排障和
332
+ // 给工作流做卡死指纹用的,它必须如实反映「这一条到底是按什么跑的」。
333
+ results.push({ ...result, check });
267
334
  }
268
335
 
269
336
  const allPassed = results.every((r) => r.passed);
package/src/llm/client.js CHANGED
@@ -26,7 +26,9 @@
26
26
  import { dlog } from '../utils/debugLog.js';
27
27
  import { buildOpenAIRequest, createOpenAISSEParser, isImageInputRejected, isMaxTokensRejected, isPromptCacheKeyRejected, isResponseFormatUnsupported, } from './providers/openaiFormat.js';
28
28
  import { promptMaterialHash, shortCacheScope } from './promptCache.js';
29
- import { buildAnthropicRequest, createAnthropicSSEParser } from './providers/anthropicFormat.js';
29
+ import { buildAnthropicRequest, createAnthropicSSEParser, } from './providers/anthropicFormat.js';
30
+ import { chatGateway } from './gatewayClient.js';
31
+ import { prepareMessagesForProvider } from './messageProvenance.js';
30
32
  /**
31
33
  * 记住"这个 baseURL::model 不支持 response_format.json_schema",避免每次都先撞 400。
32
34
  * 单进程内有效;每个 -p 子进程是全新进程 → 首个结构化调用吃一次 400 再退化,可接受。
@@ -133,7 +135,10 @@ export function _nextRetryDelayMs(retryAfterMs) {
133
135
  }
134
136
  /** 可重试的 HTTP 状态码。4xx 除 408/425/429 外不重试(重试无意义)。 */
135
137
  function isRetryableStatus(status) {
136
- return status === 408 || status === 425 || status === 429 || (status >= 500 && status < 600);
138
+ return (status === 408 ||
139
+ status === 425 ||
140
+ status === 429 ||
141
+ (status >= 500 && status < 600));
137
142
  }
138
143
  /** 鉴权类错误:明确告诉用户"key 失效/过期/无权访问",避免重试无意义。 */
139
144
  function isClientAuthError(status) {
@@ -212,7 +217,9 @@ export function createIdleWatchdog(userSignal, timeoutMs = IDLE_TIMEOUT_MS) {
212
217
  };
213
218
  arm();
214
219
  return {
215
- signal: userSignal ? AbortSignal.any([userSignal, ctrl.signal]) : ctrl.signal,
220
+ signal: userSignal
221
+ ? AbortSignal.any([userSignal, ctrl.signal])
222
+ : ctrl.signal,
216
223
  kick: arm,
217
224
  dispose: () => {
218
225
  if (timer)
@@ -240,8 +247,34 @@ export function createIdleWatchdog(userSignal, timeoutMs = IDLE_TIMEOUT_MS) {
240
247
  * }
241
248
  * ```
242
249
  */
250
+ export function createModelProvider(provider) {
251
+ return {
252
+ source: provider.source === 'gateway' ? 'gateway' : 'local',
253
+ descriptor: provider,
254
+ stream: (request) => {
255
+ if (provider.source === 'gateway') {
256
+ if (request.responseFormat &&
257
+ provider.gatewayCapabilities?.structuredOutput === false) {
258
+ throw new Error('当前在线模型不支持结构化输出');
259
+ }
260
+ return chatGateway({
261
+ provider: provider,
262
+ messages: request.messages,
263
+ tools: request.tools,
264
+ signal: request.signal,
265
+ conversationMode: request.conversationMode,
266
+ responseFormat: request.responseFormat,
267
+ });
268
+ }
269
+ return streamLocal({ ...request, provider: provider });
270
+ },
271
+ };
272
+ }
243
273
  export async function* chat(args) {
244
- const { provider, messages, tools, signal, responseFormat, promptCache } = args;
274
+ yield* createModelProvider(args.provider).stream(args);
275
+ }
276
+ async function* streamLocal(args) {
277
+ const { provider, messages, tools, signal, responseFormat, promptCache, conversationMode, cacheEdits, } = args;
245
278
  const format = provider.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
246
279
  if (format === 'anthropic' && responseFormat) {
247
280
  throw new Error('output_schema 结构化输出目前不支持 Anthropic Messages 格式的 provider' +
@@ -251,17 +284,14 @@ export async function* chat(args) {
251
284
  // 过滤并清洁 messages 数组,剥离 timestamp, id, _ephemeral 等本地渲染元数据。
252
285
  // 两种格式共用同一份清洗后的内部形状——Anthropic 分支的翻译(system 摘除/
253
286
  // tool_calls→tool_use 等)在 buildAnthropicRequest 内部做,不在这里做。
254
- let cleanedMessages = messages
255
- .filter((m) => !(m.role === 'system' && m._ephemeral === true))
256
- .map((m) => {
257
- const { id, timestamp, attachments, browserReferences, display_metadata, ...rest } = m;
258
- return rest;
259
- });
287
+ let cleanedMessages = prepareMessagesForProvider(messages, conversationMode ?? 'private');
260
288
  const includeUsage = process.env.MINIMAL_AGENT_DISABLE_USAGE !== '1';
261
289
  const rfKey = `${provider.baseURL}::${provider.model}`;
262
290
  // OpenAI 分支专属的「就地退化」状态;Anthropic 无此概念,两个 flag 恒为 false,
263
291
  // 下面的退化 if 分支天然不会进入(不需要额外的 format 判断散落各处)。
264
- let wantResponseFormat = format === 'openai' && responseFormat !== undefined && !rfUnsupported.has(rfKey);
292
+ let wantResponseFormat = format === 'openai' &&
293
+ responseFormat !== undefined &&
294
+ !rfUnsupported.has(rfKey);
265
295
  let wantMaxTokens = format === 'openai' &&
266
296
  typeof provider.maxTokens === 'number' &&
267
297
  provider.maxTokens > 0 &&
@@ -278,7 +308,12 @@ export async function* chat(args) {
278
308
  const textOnly = c.filter((p) => p.type === 'text');
279
309
  const newContent = textOnly.length > 0
280
310
  ? textOnly.map((p) => ({ type: 'text', text: p.text }))
281
- : [{ type: 'text', text: '[图片内容未发送:当前模型不支持图片输入]' }];
311
+ : [
312
+ {
313
+ type: 'text',
314
+ text: '[图片内容未发送:当前模型不支持图片输入]',
315
+ },
316
+ ];
282
317
  return { ...m, content: newContent };
283
318
  });
284
319
  // 空闲 watchdog:每个 attempt 一只(重试前换新);fetch 等待期自动计时,
@@ -286,7 +321,12 @@ export async function* chat(args) {
286
321
  let watchdog = createIdleWatchdog(signal);
287
322
  const postChat = () => {
288
323
  const req = format === 'anthropic'
289
- ? buildAnthropicRequest({ provider, cleanedMessages, tools })
324
+ ? buildAnthropicRequest({
325
+ provider,
326
+ cleanedMessages,
327
+ tools,
328
+ ...(cacheEdits ? { cacheEdits } : {}),
329
+ })
290
330
  : buildOpenAIRequest({
291
331
  provider,
292
332
  cleanedMessages,
@@ -298,7 +338,12 @@ export async function* chat(args) {
298
338
  withPromptCacheKey: wantPromptCacheKey,
299
339
  responseFormat,
300
340
  });
301
- return fetch(req.url, { method: 'POST', headers: req.headers, body: req.body, signal: watchdog.signal });
341
+ return fetch(req.url, {
342
+ method: 'POST',
343
+ headers: req.headers,
344
+ body: req.body,
345
+ signal: watchdog.signal,
346
+ });
302
347
  };
303
348
  const reqId = ++reqCounter;
304
349
  dlog('llm', `req#${reqId} POST →`, {
@@ -315,7 +360,9 @@ export async function* chat(args) {
315
360
  .map((message) => message.content)),
316
361
  toolSchemaHash: promptMaterialHash(tools.map((tool) => ({
317
362
  name: tool.name,
318
- description: typeof tool.description === 'function' ? tool.description() : tool.description,
363
+ description: typeof tool.description === 'function'
364
+ ? tool.description()
365
+ : tool.description,
319
366
  parameters: tool.parameters,
320
367
  }))),
321
368
  });
@@ -386,7 +433,8 @@ export async function* chat(args) {
386
433
  errText = await resp.text().catch(() => '');
387
434
  }
388
435
  // 退化①:response_format.json_schema 不支持
389
- if (wantResponseFormat && isResponseFormatUnsupported(resp.status, errText)) {
436
+ if (wantResponseFormat &&
437
+ isResponseFormatUnsupported(resp.status, errText)) {
390
438
  // 记住该 model 不支持,单进程内后续结构化调用直接跳过 response_format(不再撞 400)。
391
439
  rfUnsupported.add(rfKey);
392
440
  console.warn(`[minimal-agent] provider model "${provider.model}" 不支持 response_format.json_schema,` +
@@ -399,7 +447,8 @@ export async function* chat(args) {
399
447
  }
400
448
  catch (e) {
401
449
  // 退化二次 fetch 也网络错:把错误外提到外层重试循环
402
- if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) === 'break')
450
+ if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
451
+ 'break')
403
452
  break;
404
453
  continue;
405
454
  }
@@ -419,7 +468,8 @@ export async function* chat(args) {
419
468
  watchdog.kick();
420
469
  }
421
470
  catch (e) {
422
- if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) === 'break')
471
+ if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
472
+ 'break')
423
473
  break;
424
474
  continue;
425
475
  }
@@ -432,9 +482,14 @@ export async function* chat(args) {
432
482
  if (!imagesStripped && isImageInputRejected(resp.status, errText)) {
433
483
  const hasImages = cleanedMessages.some((m) => {
434
484
  const c = m.content;
435
- return Array.isArray(c) && c.some((p) => p.type === 'image_url' || p.type === 'video_url');
485
+ return (Array.isArray(c) &&
486
+ c.some((p) => p.type === 'image_url' || p.type === 'video_url'));
436
487
  });
437
488
  if (hasImages) {
489
+ if (args.visionPolicy === 'required') {
490
+ throw new Error(`当前模型拒绝了本轮必需的图片输入,已停止而未删除图片重试。` +
491
+ `请改用支持视觉的模型或检查模型配置。Provider 返回:${errText.slice(0, 500)}`);
492
+ }
438
493
  console.warn(`[minimal-agent] provider model "${provider.model}" 不支持图片输入,` +
439
494
  `已剥离图片重发(仅保留文本内容)。如该模型实际支持视觉,请在模型设置中确认。`);
440
495
  cleanedMessages = stripImagesFromMessages(cleanedMessages);
@@ -444,7 +499,8 @@ export async function* chat(args) {
444
499
  watchdog.kick();
445
500
  }
446
501
  catch (e) {
447
- if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) === 'break')
502
+ if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
503
+ 'break')
448
504
  break;
449
505
  continue;
450
506
  }
@@ -486,7 +542,9 @@ export async function* chat(args) {
486
542
  const decoder = new TextDecoder();
487
543
  /** 临时缓冲:HTTP chunk 不一定按行切,要自己拼 */
488
544
  let buffer = '';
489
- const parser = format === 'anthropic' ? createAnthropicSSEParser() : createOpenAISSEParser();
545
+ const parser = format === 'anthropic'
546
+ ? createAnthropicSSEParser()
547
+ : createOpenAISSEParser();
490
548
  try {
491
549
  while (true) {
492
550
  // 每次 read 前检查 abort:用户按 ESC/Ctrl+C 时 signal.aborted 为 true。