minimal-agent 0.13.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 (470) 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 +503 -0
  103. package/src/advisor/advisorCoordinator.ts +657 -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/streamJson.js +5 -6
  108. package/src/cli/streamJson.ts +8 -4
  109. package/src/cli/wizards/advisorWizard.js +4 -2
  110. package/src/cli/wizards/advisorWizard.tsx +8 -2
  111. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  112. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  113. package/src/collaboration/taskFlow.js +115 -0
  114. package/src/collaboration/taskFlow.ts +169 -0
  115. package/src/config/configDefaults.js +41 -1
  116. package/src/config/configDefaults.ts +43 -1
  117. package/src/config/configDiagnostics.ts +2 -2
  118. package/src/config/configFile.js +40 -9
  119. package/src/config/configFile.ts +60 -11
  120. package/src/config/configService.js +419 -74
  121. package/src/config/configService.ts +703 -145
  122. package/src/config/numericLimits.js +22 -0
  123. package/src/config/numericLimits.ts +24 -0
  124. package/src/config.js +1 -0
  125. package/src/config.ts +3 -2
  126. package/src/context/budgetPlan.js +1 -1
  127. package/src/context/budgetPlan.ts +1 -1
  128. package/src/context/compact.js +7 -2
  129. package/src/context/compact.ts +9 -2
  130. package/src/context/microCompactLite.js +212 -13
  131. package/src/context/microCompactLite.ts +261 -12
  132. package/src/context/sessionRegistry.js +8 -1
  133. package/src/context/sessionRegistry.ts +18 -5
  134. package/src/context/toolResultArchive.js +72 -0
  135. package/src/context/toolResultArchive.ts +95 -0
  136. package/src/goal/errors.js +8 -0
  137. package/src/goal/errors.ts +18 -0
  138. package/src/goal/goalRuntime.js +344 -0
  139. package/src/goal/goalRuntime.ts +466 -0
  140. package/src/goal/goalStore.js +200 -0
  141. package/src/goal/goalStore.ts +219 -0
  142. package/src/goal/index.js +4 -0
  143. package/src/goal/index.ts +4 -0
  144. package/src/goal/statusMapping.js +71 -0
  145. package/src/goal/statusMapping.ts +95 -0
  146. package/src/goal/types.js +7 -0
  147. package/src/goal/types.ts +179 -0
  148. package/src/goal/workflowController.js +306 -0
  149. package/src/goal/workflowController.ts +360 -0
  150. package/src/harness/evidenceLedger.js +2 -0
  151. package/src/harness/evidenceLedger.ts +1 -0
  152. package/src/harness/stallGuard.js +9 -3
  153. package/src/harness/stallGuard.ts +7 -3
  154. package/src/images/imageResolver.js +161 -0
  155. package/src/images/imageResolver.ts +189 -0
  156. package/src/infra/verification.js +34 -5
  157. package/src/infra/verification.ts +39 -4
  158. package/src/llm/client.js +79 -21
  159. package/src/llm/client.ts +182 -35
  160. package/src/llm/gatewayClient.js +201 -0
  161. package/src/llm/gatewayClient.ts +299 -0
  162. package/src/llm/messageProvenance.js +46 -0
  163. package/src/llm/messageProvenance.ts +58 -0
  164. package/src/llm/modelProvider.js +1 -0
  165. package/src/llm/modelProvider.ts +22 -0
  166. package/src/llm/providers/anthropicFormat.js +108 -1
  167. package/src/llm/providers/anthropicFormat.ts +115 -4
  168. package/src/llm/providers/openaiFormat.js +9 -0
  169. package/src/llm/providers/openaiFormat.ts +12 -3
  170. package/src/loop.js +319 -54
  171. package/src/loop.ts +373 -57
  172. package/src/main.js +4 -1
  173. package/src/main.tsx +4 -1
  174. package/src/managedExecution/index.js +2 -0
  175. package/src/managedExecution/index.ts +2 -0
  176. package/src/managedExecution/registry.js +15 -0
  177. package/src/managedExecution/registry.ts +20 -0
  178. package/src/managedExecution/types.js +1 -0
  179. package/src/managedExecution/types.ts +86 -0
  180. package/src/modelRef.js +9 -0
  181. package/src/modelRef.ts +31 -0
  182. package/src/multimodal.js +14 -28
  183. package/src/multimodal.ts +17 -33
  184. package/src/net/lanDiscovery.js +65 -0
  185. package/src/net/lanDiscovery.ts +82 -0
  186. package/src/plugin-sdk.js +28 -3
  187. package/src/plugin-sdk.ts +39 -6
  188. package/src/plugins/pluginApi.ts +16 -1
  189. package/src/plugins/pluginLoader.js +4 -0
  190. package/src/plugins/pluginLoader.ts +6 -0
  191. package/src/plugins/pluginRunner.js +139 -7
  192. package/src/plugins/pluginRunner.ts +173 -9
  193. package/src/plugins/slashFallback.js +113 -0
  194. package/src/plugins/slashFallback.ts +137 -0
  195. package/src/prompts/policyRegistry.js +12 -32
  196. package/src/prompts/policyRegistry.ts +15 -32
  197. package/src/prompts/promptAssembly.js +103 -12
  198. package/src/prompts/promptAssembly.ts +114 -12
  199. package/src/prompts/skillList.js +21 -3
  200. package/src/prompts/skillList.ts +27 -2
  201. package/src/prompts/stableSystemPrompt.js +18 -0
  202. package/src/prompts/stableSystemPrompt.ts +33 -0
  203. package/src/runtime/agentRuntimeContext.js +8 -2
  204. package/src/runtime/agentRuntimeContext.ts +17 -4
  205. package/src/session/runAgentTurn.js +78 -12
  206. package/src/session/runAgentTurn.ts +105 -23
  207. package/src/session/runTurn.js +10 -9
  208. package/src/session/runTurn.ts +17 -8
  209. package/src/session/sessionState.ts +2 -0
  210. package/src/team/auth.js +186 -0
  211. package/src/team/auth.ts +298 -0
  212. package/src/team/cli.js +105 -0
  213. package/src/team/cli.ts +122 -0
  214. package/src/team/onlineToolContract.js +64 -0
  215. package/src/team/onlineToolContract.ts +109 -0
  216. package/src/team/toolPolicy.js +36 -0
  217. package/src/team/toolPolicy.ts +75 -0
  218. package/src/tools/advisor/advisor.js +90 -46
  219. package/src/tools/advisor/advisor.ts +100 -47
  220. package/src/tools/advisor/advisorDecision.js +71 -0
  221. package/src/tools/advisor/advisorDecision.ts +85 -0
  222. package/src/tools/agent/agent.js +18 -5
  223. package/src/tools/agent/agent.ts +21 -7
  224. package/src/tools/agent/agentControl.js +246 -0
  225. package/src/tools/agent/agentControl.ts +284 -0
  226. package/src/tools/agent/agentTaskService.js +40 -1
  227. package/src/tools/agent/agentTaskService.ts +44 -1
  228. package/src/tools/agent/agentTypes.js +14 -2
  229. package/src/tools/agent/agentTypes.ts +15 -2
  230. package/src/tools/applypatch/applyPatch.js +362 -0
  231. package/src/tools/applypatch/applyPatch.ts +428 -0
  232. package/src/tools/bash/bash.js +22 -15
  233. package/src/tools/bash/bash.ts +23 -17
  234. package/src/tools/capabilities.js +10 -5
  235. package/src/tools/capabilities.ts +10 -5
  236. package/src/tools/computeruse/computerIntent.js +32 -0
  237. package/src/tools/computeruse/computerIntent.ts +46 -0
  238. package/src/tools/computeruse/telemetryLog.js +12 -0
  239. package/src/tools/computeruse/telemetryLog.ts +16 -0
  240. package/src/tools/computeruse/vision/telemetry.js +1 -0
  241. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  242. package/src/tools/effectiveToolSet.js +4 -0
  243. package/src/tools/effectiveToolSet.ts +4 -0
  244. package/src/tools/index.js +21 -2
  245. package/src/tools/index.ts +33 -2
  246. package/src/tools/presentresult/presentresult.js +6 -15
  247. package/src/tools/presentresult/presentresult.ts +6 -15
  248. package/src/tools/read/read.js +62 -9
  249. package/src/tools/read/read.ts +63 -9
  250. package/src/tools/shared/fileUtils.js +1 -2
  251. package/src/tools/shared/fileUtils.ts +1 -2
  252. package/src/tools/shared/toolOutputStore.js +23 -1
  253. package/src/tools/shared/toolOutputStore.ts +22 -1
  254. package/src/tools/skill/skill.js +9 -3
  255. package/src/tools/skill/skill.ts +8 -4
  256. package/src/tools/toolPromptGuides.js +117 -0
  257. package/src/tools/toolPromptGuides.ts +137 -0
  258. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  259. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  260. package/src/tools/webbrowser/browser.js +27 -11
  261. package/src/tools/webbrowser/browser.ts +68 -24
  262. package/src/tools/webbrowser/browserAutomation.js +329 -0
  263. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  264. package/src/tools/webbrowser/browserAxState.js +97 -0
  265. package/src/tools/webbrowser/browserAxState.ts +142 -0
  266. package/src/tools/webbrowser/browserBatch.js +1578 -0
  267. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  268. package/src/tools/webbrowser/browserCdp.js +208 -0
  269. package/src/tools/webbrowser/browserCdp.ts +255 -0
  270. package/src/tools/webbrowser/browserConditions.js +24 -0
  271. package/src/tools/webbrowser/browserConditions.ts +45 -0
  272. package/src/tools/webbrowser/browserContent.js +281 -0
  273. package/src/tools/webbrowser/browserContent.ts +438 -0
  274. package/src/tools/webbrowser/browserControl.js +131 -34
  275. package/src/tools/webbrowser/browserControl.ts +210 -56
  276. package/src/tools/webbrowser/browserDaemon.js +22 -14
  277. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  278. package/src/tools/webbrowser/browserFrames.js +47 -0
  279. package/src/tools/webbrowser/browserFrames.ts +54 -0
  280. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  281. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  282. package/src/tools/webbrowser/browserLocator.js +140 -0
  283. package/src/tools/webbrowser/browserLocator.ts +194 -0
  284. package/src/tools/webbrowser/browserOutcome.js +10 -17
  285. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  286. package/src/tools/webbrowser/browserRecovery.js +58 -0
  287. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  288. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  289. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  290. package/src/tools/webbrowser/browserService.js +28 -2
  291. package/src/tools/webbrowser/browserService.ts +49 -9
  292. package/src/tools/webbrowser/browserStream.js +132 -33
  293. package/src/tools/webbrowser/browserStream.ts +224 -50
  294. package/src/tools/webbrowser/browserTabs.js +48 -15
  295. package/src/tools/webbrowser/browserTabs.ts +178 -96
  296. package/src/tools/webbrowser/webbrowser.js +679 -144
  297. package/src/tools/webbrowser/webbrowser.ts +975 -236
  298. package/src/tools/webfetch/preapproved.js +0 -2
  299. package/src/tools/webfetch/preapproved.ts +0 -2
  300. package/src/tools/websearch/websearch.js +129 -8
  301. package/src/tools/websearch/websearch.ts +138 -6
  302. package/src/types.ts +440 -38
  303. package/src/ui/App.js +377 -58
  304. package/src/ui/App.tsx +576 -111
  305. package/src/ui/LiveArea.js +14 -8
  306. package/src/ui/LiveArea.tsx +14 -10
  307. package/src/ui/MessageList.js +63 -20
  308. package/src/ui/MessageList.tsx +101 -16
  309. package/src/ui/ModelPicker.js +7 -4
  310. package/src/ui/ModelPicker.tsx +55 -8
  311. package/src/ui/hooks/useChat.js +152 -163
  312. package/src/ui/hooks/useChat.ts +396 -334
  313. package/src/ui/loginCommand.js +56 -0
  314. package/src/ui/loginCommand.ts +63 -0
  315. package/src/ui/toolProgress.js +41 -0
  316. package/src/ui/toolProgress.ts +44 -0
  317. package/src/web/browserBridge.js +20 -2
  318. package/src/web/browserBridge.ts +20 -2
  319. package/src/web/protocol.ts +1897 -194
  320. package/workflows/adaptive-research/workflow.mjs +86 -0
  321. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  322. package/workflows/e2e-llm/workflow.mjs +52 -0
  323. package/workflows/e2e-smoke/workflow.mjs +59 -0
  324. package/workflows/e2e-vision-schema/README.md +48 -0
  325. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  326. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  327. package/workflows/file-census/README.md +14 -0
  328. package/workflows/file-census/scripts/.gitkeep +2 -0
  329. package/workflows/file-census/workflow.mjs +110 -0
  330. package/workflows/goal/README.md +166 -0
  331. package/workflows/goal/prompts/audit.md +57 -0
  332. package/workflows/goal/prompts/contract.md +56 -0
  333. package/workflows/goal/prompts/iterate.md +37 -0
  334. package/workflows/goal/workflow.mjs +501 -0
  335. package/workflows/illustrate/README.md +90 -0
  336. package/workflows/illustrate/assets/engines.json +20 -0
  337. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  338. package/workflows/illustrate/assets/extract-bing.js +33 -0
  339. package/workflows/illustrate/assets/extract-google.js +31 -0
  340. package/workflows/illustrate/workflow.mjs +301 -0
  341. package/workflows/plan/workflow.mjs +389 -0
  342. package/workflows/question-crops/README.md +35 -0
  343. package/workflows/question-crops/prompts/inventory.md +23 -0
  344. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  345. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  346. package/workflows/question-crops/workflow.mjs +172 -0
  347. package/workflows/ralph-loop/workflow.mjs +162 -0
  348. package/workflows/research/README.md +74 -0
  349. package/workflows/research/prompts/s0-goal.md +43 -0
  350. package/workflows/research/prompts/s1-early-exit.md +22 -0
  351. package/workflows/research/prompts/s1-map.md +58 -0
  352. package/workflows/research/prompts/s2-options.md +53 -0
  353. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  354. package/workflows/research/prompts/s4-verify.md +74 -0
  355. package/workflows/research/prompts/s5-synthesis.md +81 -0
  356. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  357. package/workflows/research/prompts/s6-package.md +32 -0
  358. package/workflows/research/scripts/build-report.mjs +98 -0
  359. package/workflows/research/workflow.mjs +288 -0
  360. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  361. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  362. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  363. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  364. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  365. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  366. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  367. package/workflows/wrong-question-docx/README.md +55 -0
  368. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  369. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  370. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  371. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  372. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  373. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  374. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  375. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  376. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  377. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  378. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  379. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  380. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  381. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  382. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  383. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  384. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  385. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  386. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  387. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  388. package/plugins/workflow-runner/src/expressions.js +0 -639
  389. package/plugins/workflow-runner/src/expressions.ts +0 -640
  390. package/plugins/workflow-runner/src/loader.js +0 -573
  391. package/plugins/workflow-runner/src/loader.ts +0 -721
  392. package/plugins/workflow-runner/src/multimodal.js +0 -38
  393. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  394. package/plugins/workflow-runner/src/recovery.js +0 -126
  395. package/plugins/workflow-runner/src/recovery.ts +0 -156
  396. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  397. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  398. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  399. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  400. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  401. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  402. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  403. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  404. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  405. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  406. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  407. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  408. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  409. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  410. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  411. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  412. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  413. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  414. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  415. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  416. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  417. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  418. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  419. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  420. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  421. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  422. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  423. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  424. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  425. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  426. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  427. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  428. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  429. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  430. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  431. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  432. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  433. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  434. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  435. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  436. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  437. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  438. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  439. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  440. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  441. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  442. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  443. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  444. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  445. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  446. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  447. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  448. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  449. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  450. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  451. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  452. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  453. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  454. package/src/advisorState.js +0 -22
  455. package/src/cli/configWizard.js +0 -293
  456. package/src/tools/toolProgressBridge.js +0 -48
  457. package/workflows/adaptive-research.yaml +0 -50
  458. package/workflows/book-review-short.yaml +0 -125
  459. package/workflows/e2e-write-greet.yaml +0 -31
  460. package/workflows/illustrate.yaml +0 -227
  461. package/workflows/plan.yaml +0 -470
  462. package/workflows/ppt.yaml +0 -1670
  463. package/workflows/ralph-loop.yaml +0 -201
  464. package/workflows/research.yaml +0 -873
  465. package/workflows/schema.json +0 -176
  466. package/workflows/webppt.yaml +0 -496
  467. package/workflows/wechat-reading-shots.yaml +0 -315
  468. package/workflows/word.yaml +0 -720
  469. package/workflows/youtube-shorts.yaml +0 -202
  470. /package/workflows/{research.md → research/DESIGN.md} +0 -0
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。
package/src/llm/client.ts CHANGED
@@ -24,7 +24,14 @@
24
24
  * ============================================================
25
25
  */
26
26
 
27
- import type { LlmStreamEvent, Message, Provider, Tool } from '../types.js';
27
+ import type {
28
+ GatewayProvider,
29
+ LlmStreamEvent,
30
+ LocalProvider,
31
+ Message,
32
+ Provider,
33
+ Tool,
34
+ } from '../types.js';
28
35
  import { dlog } from '../utils/debugLog.js';
29
36
  import {
30
37
  buildOpenAIRequest,
@@ -35,7 +42,13 @@ import {
35
42
  isResponseFormatUnsupported,
36
43
  } from './providers/openaiFormat.js';
37
44
  import { promptMaterialHash, shortCacheScope } from './promptCache.js';
38
- import { buildAnthropicRequest, createAnthropicSSEParser } from './providers/anthropicFormat.js';
45
+ import {
46
+ buildAnthropicRequest,
47
+ createAnthropicSSEParser,
48
+ } from './providers/anthropicFormat.js';
49
+ import { chatGateway } from './gatewayClient.js';
50
+ import type { ModelProvider } from './modelProvider.js';
51
+ import { prepareMessagesForProvider } from './messageProvenance.js';
39
52
 
40
53
  /**
41
54
  * 记住"这个 baseURL::model 不支持 response_format.json_schema",避免每次都先撞 400。
@@ -132,7 +145,8 @@ let backoffTier = 0;
132
145
  * retryAfterMs 有值(429 的 Retry-After 头)时听服务器的(仍封顶 60s、仍抬档)。
133
146
  */
134
147
  function nextRetryDelayMs(retryAfterMs?: number): number {
135
- const tierMs = BACKOFF_TIERS_MS[Math.min(backoffTier, BACKOFF_TIERS_MS.length - 1)];
148
+ const tierMs =
149
+ BACKOFF_TIERS_MS[Math.min(backoffTier, BACKOFF_TIERS_MS.length - 1)];
136
150
  backoffTier = Math.min(backoffTier + 1, BACKOFF_TIERS_MS.length - 1);
137
151
  if (retryAfterMs !== undefined) return Math.min(retryAfterMs, 60_000);
138
152
  const jittered = tierMs * (0.85 + Math.random() * 0.3);
@@ -158,7 +172,12 @@ export function _nextRetryDelayMs(retryAfterMs?: number): number {
158
172
 
159
173
  /** 可重试的 HTTP 状态码。4xx 除 408/425/429 外不重试(重试无意义)。 */
160
174
  function isRetryableStatus(status: number): boolean {
161
- return status === 408 || status === 425 || status === 429 || (status >= 500 && status < 600);
175
+ return (
176
+ status === 408 ||
177
+ status === 425 ||
178
+ status === 429 ||
179
+ (status >= 500 && status < 600)
180
+ );
162
181
  }
163
182
 
164
183
  /** 鉴权类错误:明确告诉用户"key 失效/过期/无权访问",避免重试无意义。 */
@@ -253,7 +272,9 @@ export function createIdleWatchdog(
253
272
  };
254
273
  arm();
255
274
  return {
256
- signal: userSignal ? AbortSignal.any([userSignal, ctrl.signal]) : ctrl.signal,
275
+ signal: userSignal
276
+ ? AbortSignal.any([userSignal, ctrl.signal])
277
+ : ctrl.signal,
257
278
  kick: arm,
258
279
  dispose: () => {
259
280
  if (timer) clearTimeout(timer);
@@ -281,8 +302,42 @@ export function createIdleWatchdog(
281
302
  * }
282
303
  * ```
283
304
  */
284
- export async function* chat(args: {
285
- provider: Provider;
305
+ export function createModelProvider(provider: Provider): ModelProvider {
306
+ return {
307
+ source: provider.source === 'gateway' ? 'gateway' : 'local',
308
+ descriptor: provider,
309
+ stream: (request) => {
310
+ if (provider.source === 'gateway') {
311
+ if (
312
+ request.responseFormat &&
313
+ provider.gatewayCapabilities?.structuredOutput === false
314
+ ) {
315
+ throw new Error('当前在线模型不支持结构化输出');
316
+ }
317
+ return chatGateway({
318
+ provider: provider as GatewayProvider,
319
+ messages: request.messages,
320
+ tools: request.tools,
321
+ signal: request.signal,
322
+ conversationMode: request.conversationMode,
323
+ responseFormat: request.responseFormat,
324
+ });
325
+ }
326
+ return streamLocal({ ...request, provider: provider as LocalProvider });
327
+ },
328
+ };
329
+ }
330
+
331
+ export async function* chat(
332
+ args: Omit<Parameters<typeof streamLocal>[0], 'provider'> & {
333
+ provider: Provider;
334
+ },
335
+ ): AsyncGenerator<LlmStreamEvent, void, void> {
336
+ yield* createModelProvider(args.provider).stream(args);
337
+ }
338
+
339
+ async function* streamLocal(args: {
340
+ provider: LocalProvider;
286
341
  messages: Message[];
287
342
  tools: Tool[];
288
343
  signal?: AbortSignal;
@@ -292,12 +347,36 @@ export async function* chat(args: {
292
347
  * 传了会在发请求前直接抛错,不浪费一次网络往返。*/
293
348
  responseFormat?: {
294
349
  type: 'json_schema';
295
- json_schema: { name: string; schema: Record<string, unknown>; strict?: boolean };
350
+ json_schema: {
351
+ name: string;
352
+ schema: Record<string, unknown>;
353
+ strict?: boolean;
354
+ };
296
355
  };
297
356
  promptCache?: import('../types.js').PromptCacheContext;
357
+ /** 当前调用所在会话模式;群聊下未标注的旧历史按私聊数据处理。 */
358
+ conversationMode?: import('../runtime/agentRuntimeContext.js').ConversationMode;
359
+ /**
360
+ * cache_edits 式回收状态(Anthropic 格式 + provider.cacheEdits 开启时由 loop 传入)。
361
+ * 传入后 buildAnthropicRequest 会随请求发送删除指令并维护 pinned/pendingNew——
362
+ * 该状态有跨轮生命周期(pinned 每轮重发),调用方必须传同一份会话级对象,
363
+ * 并在 compact 后调 resetCacheEdits。OpenAI 格式忽略此参数。
364
+ */
365
+ cacheEdits?: import('../types.js').CacheEditsState;
366
+ visionPolicy?: 'required' | 'optional-history';
298
367
  }): AsyncGenerator<LlmStreamEvent, void, void> {
299
- const { provider, messages, tools, signal, responseFormat, promptCache } = args;
300
- const format: 'openai' | 'anthropic' = provider.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
368
+ const {
369
+ provider,
370
+ messages,
371
+ tools,
372
+ signal,
373
+ responseFormat,
374
+ promptCache,
375
+ conversationMode,
376
+ cacheEdits,
377
+ } = args;
378
+ const format: 'openai' | 'anthropic' =
379
+ provider.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
301
380
 
302
381
  if (format === 'anthropic' && responseFormat) {
303
382
  throw new Error(
@@ -310,12 +389,10 @@ export async function* chat(args: {
310
389
  // 过滤并清洁 messages 数组,剥离 timestamp, id, _ephemeral 等本地渲染元数据。
311
390
  // 两种格式共用同一份清洗后的内部形状——Anthropic 分支的翻译(system 摘除/
312
391
  // tool_calls→tool_use 等)在 buildAnthropicRequest 内部做,不在这里做。
313
- let cleanedMessages: Message[] = messages
314
- .filter((m) => !(m.role === 'system' && (m as { _ephemeral?: boolean })._ephemeral === true))
315
- .map((m) => {
316
- const { id, timestamp, attachments, browserReferences, display_metadata, ...rest } = m as any;
317
- return rest;
318
- });
392
+ let cleanedMessages: Message[] = prepareMessagesForProvider(
393
+ messages,
394
+ conversationMode ?? 'private',
395
+ );
319
396
 
320
397
  const includeUsage = process.env.MINIMAL_AGENT_DISABLE_USAGE !== '1';
321
398
  const rfKey = `${provider.baseURL}::${provider.model}`;
@@ -323,7 +400,9 @@ export async function* chat(args: {
323
400
  // OpenAI 分支专属的「就地退化」状态;Anthropic 无此概念,两个 flag 恒为 false,
324
401
  // 下面的退化 if 分支天然不会进入(不需要额外的 format 判断散落各处)。
325
402
  let wantResponseFormat =
326
- format === 'openai' && responseFormat !== undefined && !rfUnsupported.has(rfKey);
403
+ format === 'openai' &&
404
+ responseFormat !== undefined &&
405
+ !rfUnsupported.has(rfKey);
327
406
  let wantMaxTokens =
328
407
  format === 'openai' &&
329
408
  typeof provider.maxTokens === 'number' &&
@@ -341,9 +420,15 @@ export async function* chat(args: {
341
420
  const c = (m as { content?: unknown }).content;
342
421
  if (!Array.isArray(c)) return m;
343
422
  const textOnly = c.filter((p: any) => p.type === 'text');
344
- const newContent = textOnly.length > 0
345
- ? textOnly.map((p: any) => ({ type: 'text' as const, text: p.text }))
346
- : [{ type: 'text' as const, text: '[图片内容未发送:当前模型不支持图片输入]' }];
423
+ const newContent =
424
+ textOnly.length > 0
425
+ ? textOnly.map((p: any) => ({ type: 'text' as const, text: p.text }))
426
+ : [
427
+ {
428
+ type: 'text' as const,
429
+ text: '[图片内容未发送:当前模型不支持图片输入]',
430
+ },
431
+ ];
347
432
  return { ...m, content: newContent } as Message;
348
433
  });
349
434
 
@@ -354,7 +439,12 @@ export async function* chat(args: {
354
439
  const postChat = (): Promise<Response> => {
355
440
  const req =
356
441
  format === 'anthropic'
357
- ? buildAnthropicRequest({ provider, cleanedMessages, tools })
442
+ ? buildAnthropicRequest({
443
+ provider,
444
+ cleanedMessages,
445
+ tools,
446
+ ...(cacheEdits ? { cacheEdits } : {}),
447
+ })
358
448
  : buildOpenAIRequest({
359
449
  provider,
360
450
  cleanedMessages,
@@ -366,7 +456,12 @@ export async function* chat(args: {
366
456
  withPromptCacheKey: wantPromptCacheKey,
367
457
  responseFormat,
368
458
  });
369
- return fetch(req.url, { method: 'POST', headers: req.headers, body: req.body, signal: watchdog.signal });
459
+ return fetch(req.url, {
460
+ method: 'POST',
461
+ headers: req.headers,
462
+ body: req.body,
463
+ signal: watchdog.signal,
464
+ });
370
465
  };
371
466
 
372
467
  const reqId = ++reqCounter;
@@ -387,7 +482,10 @@ export async function* chat(args: {
387
482
  toolSchemaHash: promptMaterialHash(
388
483
  tools.map((tool) => ({
389
484
  name: tool.name,
390
- description: typeof tool.description === 'function' ? tool.description() : tool.description,
485
+ description:
486
+ typeof tool.description === 'function'
487
+ ? tool.description()
488
+ : tool.description,
391
489
  parameters: tool.parameters,
392
490
  })),
393
491
  ),
@@ -409,11 +507,16 @@ export async function* chat(args: {
409
507
  ): Promise<'break' | 'retry'> => {
410
508
  if (signal?.aborted) throw makeAbortError();
411
509
  const err = e as Error;
412
- lastErr = new Error(`LLM 网络错误 [${err.name ?? 'NetworkError'}]:${err.message}`);
510
+ lastErr = new Error(
511
+ `LLM 网络错误 [${err.name ?? 'NetworkError'}]:${err.message}`,
512
+ );
413
513
  dlog('llm', `req#${reqId} attempt ${attempt} ${label}:`, err.message);
414
514
  if (attempt >= DEFAULT_RETRY.maxAttempts) return 'break';
415
515
  const delay = nextRetryDelayMs();
416
- dlog('llm', `req#${reqId} retry in ${delay}ms (attempt ${attempt + 1}/${DEFAULT_RETRY.maxAttempts}, tier=${backoffTier})`);
516
+ dlog(
517
+ 'llm',
518
+ `req#${reqId} retry in ${delay}ms (attempt ${attempt + 1}/${DEFAULT_RETRY.maxAttempts}, tier=${backoffTier})`,
519
+ );
417
520
  await sleep(delay, signal);
418
521
  return 'retry';
419
522
  };
@@ -435,7 +538,10 @@ export async function* chat(args: {
435
538
  // 1) 用户主动 abort → handleNetworkError 里立刻抛
436
539
  // 2) AbortSignal.timeout 触发的超时(Fetch 空闲超时还没回)
437
540
  // 3) 其它网络错误(ECONNRESET / fetch failed / DNS 失败)→ 全部按"可重试"处理
438
- if ((await handleNetworkError(e, attempt, 'failed (network)')) === 'break') break;
541
+ if (
542
+ (await handleNetworkError(e, attempt, 'failed (network)')) === 'break'
543
+ )
544
+ break;
439
545
  continue;
440
546
  }
441
547
 
@@ -456,7 +562,14 @@ export async function* chat(args: {
456
562
  resp = await postChat();
457
563
  watchdog.kick();
458
564
  } catch (e) {
459
- if ((await handleNetworkError(e, attempt, 'cache-key fallback fetch failed')) === 'break') break;
565
+ if (
566
+ (await handleNetworkError(
567
+ e,
568
+ attempt,
569
+ 'cache-key fallback fetch failed',
570
+ )) === 'break'
571
+ )
572
+ break;
460
573
  continue;
461
574
  }
462
575
  if (resp.ok) break;
@@ -464,7 +577,10 @@ export async function* chat(args: {
464
577
  }
465
578
 
466
579
  // 退化①:response_format.json_schema 不支持
467
- if (wantResponseFormat && isResponseFormatUnsupported(resp.status, errText)) {
580
+ if (
581
+ wantResponseFormat &&
582
+ isResponseFormatUnsupported(resp.status, errText)
583
+ ) {
468
584
  // 记住该 model 不支持,单进程内后续结构化调用直接跳过 response_format(不再撞 400)。
469
585
  rfUnsupported.add(rfKey);
470
586
  console.warn(
@@ -478,7 +594,11 @@ export async function* chat(args: {
478
594
  watchdog.kick();
479
595
  } catch (e) {
480
596
  // 退化二次 fetch 也网络错:把错误外提到外层重试循环
481
- if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) === 'break') break;
597
+ if (
598
+ (await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
599
+ 'break'
600
+ )
601
+ break;
482
602
  continue;
483
603
  }
484
604
  if (resp.ok) break;
@@ -498,7 +618,11 @@ export async function* chat(args: {
498
618
  resp = await postChat();
499
619
  watchdog.kick();
500
620
  } catch (e) {
501
- if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) === 'break') break;
621
+ if (
622
+ (await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
623
+ 'break'
624
+ )
625
+ break;
502
626
  continue;
503
627
  }
504
628
  if (resp.ok) break;
@@ -510,9 +634,18 @@ export async function* chat(args: {
510
634
  if (!imagesStripped && isImageInputRejected(resp.status, errText)) {
511
635
  const hasImages = cleanedMessages.some((m) => {
512
636
  const c = (m as { content?: unknown }).content;
513
- return Array.isArray(c) && c.some((p: any) => p.type === 'image_url' || p.type === 'video_url');
637
+ return (
638
+ Array.isArray(c) &&
639
+ c.some((p: any) => p.type === 'image_url' || p.type === 'video_url')
640
+ );
514
641
  });
515
642
  if (hasImages) {
643
+ if (args.visionPolicy === 'required') {
644
+ throw new Error(
645
+ `当前模型拒绝了本轮必需的图片输入,已停止而未删除图片重试。` +
646
+ `请改用支持视觉的模型或检查模型配置。Provider 返回:${errText.slice(0, 500)}`,
647
+ );
648
+ }
516
649
  console.warn(
517
650
  `[minimal-agent] provider model "${provider.model}" 不支持图片输入,` +
518
651
  `已剥离图片重发(仅保留文本内容)。如该模型实际支持视觉,请在模型设置中确认。`,
@@ -523,7 +656,11 @@ export async function* chat(args: {
523
656
  resp = await postChat();
524
657
  watchdog.kick();
525
658
  } catch (e) {
526
- if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) === 'break') break;
659
+ if (
660
+ (await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
661
+ 'break'
662
+ )
663
+ break;
527
664
  continue;
528
665
  }
529
666
  if (resp.ok) break;
@@ -538,13 +675,20 @@ export async function* chat(args: {
538
675
 
539
676
  // 5xx / 408 / 425 / 429:可重试
540
677
  lastErr = buildChatError(resp, errText);
541
- dlog('llm', `req#${reqId} attempt ${attempt} failed [${resp.status}]:`, errText.slice(0, 200));
678
+ dlog(
679
+ 'llm',
680
+ `req#${reqId} attempt ${attempt} failed [${resp.status}]:`,
681
+ errText.slice(0, 200),
682
+ );
542
683
  if (attempt >= DEFAULT_RETRY.maxAttempts) break;
543
684
 
544
685
  // 429 优先用 Retry-After 头,否则走自适应档位退避
545
686
  const retryAfterMs = parseRetryAfter(resp);
546
687
  const delay = nextRetryDelayMs(retryAfterMs);
547
- dlog('llm', `req#${reqId} retry in ${delay}ms (attempt ${attempt + 1}/${DEFAULT_RETRY.maxAttempts}, tier=${backoffTier}, retryAfter=${retryAfterMs ?? 'tier'})`);
688
+ dlog(
689
+ 'llm',
690
+ `req#${reqId} retry in ${delay}ms (attempt ${attempt + 1}/${DEFAULT_RETRY.maxAttempts}, tier=${backoffTier}, retryAfter=${retryAfterMs ?? 'tier'})`,
691
+ );
548
692
  await sleep(delay, signal);
549
693
  }
550
694
 
@@ -567,7 +711,10 @@ export async function* chat(args: {
567
711
  const decoder = new TextDecoder();
568
712
  /** 临时缓冲:HTTP chunk 不一定按行切,要自己拼 */
569
713
  let buffer = '';
570
- const parser = format === 'anthropic' ? createAnthropicSSEParser() : createOpenAISSEParser();
714
+ const parser =
715
+ format === 'anthropic'
716
+ ? createAnthropicSSEParser()
717
+ : createOpenAISSEParser();
571
718
 
572
719
  try {
573
720
  while (true) {