minimal-agent 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -134,9 +134,11 @@ export function buildAnthropicUrl(provider) {
134
134
  return url;
135
135
  }
136
136
  export function buildAnthropicRequest(args) {
137
- const { provider, cleanedMessages, tools } = args;
137
+ const { provider, cleanedMessages, tools, cacheEdits } = args;
138
138
  const { system, messages } = toAnthropicMessages(cleanedMessages);
139
139
  const anthropicTools = toAnthropicTools(tools);
140
+ if (cacheEdits)
141
+ applyCacheEdits(messages, cacheEdits);
140
142
  const body = {
141
143
  model: provider.model,
142
144
  ...(system ? { system } : {}),
@@ -160,6 +162,101 @@ export function buildAnthropicRequest(args) {
160
162
  body: JSON.stringify(body),
161
163
  };
162
164
  }
165
+ // ==================== cache_edits 式回收(对齐 kakadeai Cached MC) ====================
166
+ /**
167
+ * 把 cache_edits 回收决策落到请求体上(原地修改翻译后的 messages)。
168
+ *
169
+ * 处理顺序(顺序即正确性,调整会破坏协议约束):
170
+ * 1. 最后一条消息的最后一个 block 打 cache_control 标记——这是 Anthropic 公开的
171
+ * prompt caching 前提:没有缓存前缀,"在缓存内删除"无从谈起。
172
+ * 2. pinned 批次原位重发:服务端无状态,删除指令必须随每个请求重申;且必须
173
+ * 重发在**原 userMessageIndex**——cache_edits block 自身也是前缀的一部分,
174
+ * 挪位 = 前缀变化 = 它本要保护的缓存被它自己破坏。
175
+ * 3. pendingNew 作为新批次插入当前最后一条 user message,然后 pin 住该下标。
176
+ * 4. 给「严格早于 cache_control 标记消息」的 tool_result 加 cache_reference
177
+ * (协议要求 cache_reference 出现在最后 cache_control 之前;用严格早于规避
178
+ * cache_edits 插入改变 content 数组长度带来的下标边界问题)。
179
+ *
180
+ * 下标稳定性依赖:history append-only + toAnthropicMessages 纯函数。compact 后
181
+ * 必须 resetCacheEdits(loop.ts 已挂钩),否则 pin 的下标指向错误消息。
182
+ *
183
+ * dedup:同一 tool_use_id 全请求只允许出现一次删除指令(跨 pinned 批次去重)。
184
+ */
185
+ function applyCacheEdits(messages, edits) {
186
+ if (messages.length === 0)
187
+ return;
188
+ // 1. 基础 prompt caching:最后一条消息的最后一个 block 打标记
189
+ const lastMsg = messages[messages.length - 1];
190
+ if (lastMsg.content.length > 0) {
191
+ const lastBlock = lastMsg.content[lastMsg.content.length - 1];
192
+ lastBlock.cache_control = { type: 'ephemeral' };
193
+ }
194
+ // 跨批次去重集:同一 cache_reference 不重复删
195
+ const seenDeleteRefs = new Set();
196
+ // wire 形状:整个 {type:'cache_edits', edits:[...]} 作为 user message 里的一个
197
+ // content block 追加(对齐 kakadeai addCacheBreakpoints 的 insertBlockAfterToolResults)。
198
+ const appendEditsBlock = (msg, toolUseIds) => {
199
+ msg.content.push({
200
+ type: 'cache_edits',
201
+ edits: toolUseIds.map((id) => ({ type: 'delete', cache_reference: id })),
202
+ });
203
+ };
204
+ const dedupe = (ids) => {
205
+ const unique = [];
206
+ for (const id of ids) {
207
+ if (seenDeleteRefs.has(id))
208
+ continue;
209
+ seenDeleteRefs.add(id);
210
+ unique.push(id);
211
+ }
212
+ return unique;
213
+ };
214
+ // 2. pinned 批次原位重发
215
+ for (const pinned of edits.pinned) {
216
+ const msg = messages[pinned.userMessageIndex];
217
+ if (!msg || msg.role !== 'user')
218
+ continue; // 下标失位(compact 后未 reset)→ 跳过该批,fail-safe
219
+ const unique = dedupe(pinned.toolUseIds);
220
+ if (unique.length > 0)
221
+ appendEditsBlock(msg, unique);
222
+ }
223
+ // 3. pendingNew:插入当前最后一条 user message 并 pin
224
+ if (edits.pendingNew.length > 0) {
225
+ const unique = dedupe(edits.pendingNew);
226
+ if (unique.length > 0) {
227
+ for (let i = messages.length - 1; i >= 0; i--) {
228
+ if (messages[i].role !== 'user')
229
+ continue;
230
+ appendEditsBlock(messages[i], unique);
231
+ edits.pinned.push({ userMessageIndex: i, toolUseIds: unique });
232
+ break;
233
+ }
234
+ }
235
+ edits.pendingNew.length = 0; // 已消费(无论是否成功插入,都清空防止下轮重复插入)
236
+ }
237
+ // 4. cache_reference 标注:找最后含 cache_control 的消息,给它**严格之前**的 tool_result 加引用
238
+ let lastCCMsgIndex = -1;
239
+ for (let i = 0; i < messages.length; i++) {
240
+ for (const block of messages[i].content) {
241
+ if (block && typeof block === 'object' && 'cache_control' in block) {
242
+ lastCCMsgIndex = i;
243
+ break;
244
+ }
245
+ }
246
+ }
247
+ if (lastCCMsgIndex < 0)
248
+ return;
249
+ for (let i = 0; i < lastCCMsgIndex; i++) {
250
+ const msg = messages[i];
251
+ if (msg.role !== 'user')
252
+ continue;
253
+ for (const block of msg.content) {
254
+ if (block.type === 'tool_result' && typeof block.tool_use_id === 'string') {
255
+ block.cache_reference = block.tool_use_id;
256
+ }
257
+ }
258
+ }
259
+ }
163
260
  /**
164
261
  * 每个请求一个新实例;把逐条 SSE `data:` 行的内容转换成 LlmStreamEvent(0..N 个)。
165
262
  *
@@ -171,6 +268,7 @@ export function buildAnthropicRequest(args) {
171
268
  export function createAnthropicSSEParser() {
172
269
  let stopReason = 'unknown';
173
270
  let usagePromptTokens;
271
+ let usageOutputTokens;
174
272
  let usageCachedTokens;
175
273
  let usageCacheWriteTokens;
176
274
  let promptCacheUsage = { reported: false };
@@ -178,6 +276,7 @@ export function createAnthropicSSEParser() {
178
276
  type: 'done',
179
277
  stopReason,
180
278
  promptTokens: usagePromptTokens,
279
+ outputTokens: usageOutputTokens,
181
280
  ...(promptCacheUsage.reported
182
281
  ? {
183
282
  ...(usageCachedTokens !== undefined ? { cachedPromptTokens: usageCachedTokens } : {}),
@@ -250,6 +349,14 @@ export function createAnthropicSSEParser() {
250
349
  return [];
251
350
  }
252
351
  case 'message_delta': {
352
+ // 输出侧计量:Anthropic 把 output_tokens 放在 message_delta 的**顶层 usage** 下
353
+ // (不在 delta 里),且给的是**到目前为止的累计值** —— 直接覆盖即可,不要累加。
354
+ // 与 input_tokens 不同:那个要把缓存三段相加(见 message_start 分支)。
355
+ // ⚠️ 非有限值/负数一律当「没报」,绝不退化成 0(0 会让预算闸永不触发)。
356
+ const out = data.usage?.output_tokens;
357
+ if (typeof out === 'number' && Number.isFinite(out) && out >= 0) {
358
+ usageOutputTokens = out;
359
+ }
253
360
  // ⚠️ stop_reason 嵌套在 delta.stop_reason 下,不是 message_delta 顶层。
254
361
  const sr = data.delta?.stop_reason;
255
362
  if (sr === 'end_turn' || sr === 'stop_sequence')
@@ -19,7 +19,7 @@
19
19
  * ============================================================
20
20
  */
21
21
 
22
- import type { ChatContentPart, LlmStreamEvent, Message, PromptCacheUsage, Provider, Tool } from '../../types.js';
22
+ import type { CacheEditsState, ChatContentPart, LlmStreamEvent, LocalProvider, Message, PromptCacheUsage, Tool } from '../../types.js';
23
23
 
24
24
  const ANTHROPIC_VERSION = '2023-06-01';
25
25
 
@@ -128,7 +128,7 @@ function looksLikeVersionedBase(url: string): boolean {
128
128
  }
129
129
  }
130
130
 
131
- export function buildAnthropicUrl(provider: Provider): string {
131
+ export function buildAnthropicUrl(provider: LocalProvider): string {
132
132
  // baseURL 是完整端点 URL(以 /v1/messages 结尾)。
133
133
  // 向后兼容:旧格式 baseURL(根域名或版本化基础路径)自动补全 /v1/messages 后缀。
134
134
  const url = provider.baseURL.trim().replace(/\/+$/, '');
@@ -145,15 +145,21 @@ export function buildAnthropicUrl(provider: Provider): string {
145
145
  }
146
146
 
147
147
  export interface AnthropicRequestArgs {
148
- provider: Provider;
148
+ provider: LocalProvider;
149
149
  cleanedMessages: readonly Message[];
150
150
  tools: Tool[];
151
+ /**
152
+ * cache_edits 回收状态(provider.cacheEdits 开启时由 loop 传入)。
153
+ * 传入即进入协议组装:pinned 重发 + pendingNew 发送并 pin + cache_reference 标注。
154
+ */
155
+ cacheEdits?: CacheEditsState;
151
156
  }
152
157
 
153
158
  export function buildAnthropicRequest(args: AnthropicRequestArgs): { url: string; headers: Record<string, string>; body: string } {
154
- const { provider, cleanedMessages, tools } = args;
159
+ const { provider, cleanedMessages, tools, cacheEdits } = args;
155
160
  const { system, messages } = toAnthropicMessages(cleanedMessages);
156
161
  const anthropicTools = toAnthropicTools(tools);
162
+ if (cacheEdits) applyCacheEdits(messages, cacheEdits);
157
163
  const body: Record<string, unknown> = {
158
164
  model: provider.model,
159
165
  ...(system ? { system } : {}),
@@ -177,6 +183,101 @@ export function buildAnthropicRequest(args: AnthropicRequestArgs): { url: string
177
183
  };
178
184
  }
179
185
 
186
+ // ==================== cache_edits 式回收(对齐 kakadeai Cached MC) ====================
187
+
188
+ /**
189
+ * 把 cache_edits 回收决策落到请求体上(原地修改翻译后的 messages)。
190
+ *
191
+ * 处理顺序(顺序即正确性,调整会破坏协议约束):
192
+ * 1. 最后一条消息的最后一个 block 打 cache_control 标记——这是 Anthropic 公开的
193
+ * prompt caching 前提:没有缓存前缀,"在缓存内删除"无从谈起。
194
+ * 2. pinned 批次原位重发:服务端无状态,删除指令必须随每个请求重申;且必须
195
+ * 重发在**原 userMessageIndex**——cache_edits block 自身也是前缀的一部分,
196
+ * 挪位 = 前缀变化 = 它本要保护的缓存被它自己破坏。
197
+ * 3. pendingNew 作为新批次插入当前最后一条 user message,然后 pin 住该下标。
198
+ * 4. 给「严格早于 cache_control 标记消息」的 tool_result 加 cache_reference
199
+ * (协议要求 cache_reference 出现在最后 cache_control 之前;用严格早于规避
200
+ * cache_edits 插入改变 content 数组长度带来的下标边界问题)。
201
+ *
202
+ * 下标稳定性依赖:history append-only + toAnthropicMessages 纯函数。compact 后
203
+ * 必须 resetCacheEdits(loop.ts 已挂钩),否则 pin 的下标指向错误消息。
204
+ *
205
+ * dedup:同一 tool_use_id 全请求只允许出现一次删除指令(跨 pinned 批次去重)。
206
+ */
207
+ function applyCacheEdits(messages: AnthropicMessage[], edits: CacheEditsState): void {
208
+ if (messages.length === 0) return;
209
+
210
+ // 1. 基础 prompt caching:最后一条消息的最后一个 block 打标记
211
+ const lastMsg = messages[messages.length - 1];
212
+ if (lastMsg.content.length > 0) {
213
+ const lastBlock = lastMsg.content[lastMsg.content.length - 1] as Record<string, unknown>;
214
+ lastBlock.cache_control = { type: 'ephemeral' };
215
+ }
216
+
217
+ // 跨批次去重集:同一 cache_reference 不重复删
218
+ const seenDeleteRefs = new Set<string>();
219
+ // wire 形状:整个 {type:'cache_edits', edits:[...]} 作为 user message 里的一个
220
+ // content block 追加(对齐 kakadeai addCacheBreakpoints 的 insertBlockAfterToolResults)。
221
+ const appendEditsBlock = (msg: AnthropicMessage, toolUseIds: string[]): void => {
222
+ msg.content.push({
223
+ type: 'cache_edits',
224
+ edits: toolUseIds.map((id) => ({ type: 'delete', cache_reference: id })),
225
+ });
226
+ };
227
+ const dedupe = (ids: string[]): string[] => {
228
+ const unique: string[] = [];
229
+ for (const id of ids) {
230
+ if (seenDeleteRefs.has(id)) continue;
231
+ seenDeleteRefs.add(id);
232
+ unique.push(id);
233
+ }
234
+ return unique;
235
+ };
236
+
237
+ // 2. pinned 批次原位重发
238
+ for (const pinned of edits.pinned) {
239
+ const msg = messages[pinned.userMessageIndex];
240
+ if (!msg || msg.role !== 'user') continue; // 下标失位(compact 后未 reset)→ 跳过该批,fail-safe
241
+ const unique = dedupe(pinned.toolUseIds);
242
+ if (unique.length > 0) appendEditsBlock(msg, unique);
243
+ }
244
+
245
+ // 3. pendingNew:插入当前最后一条 user message 并 pin
246
+ if (edits.pendingNew.length > 0) {
247
+ const unique = dedupe(edits.pendingNew);
248
+ if (unique.length > 0) {
249
+ for (let i = messages.length - 1; i >= 0; i--) {
250
+ if (messages[i].role !== 'user') continue;
251
+ appendEditsBlock(messages[i], unique);
252
+ edits.pinned.push({ userMessageIndex: i, toolUseIds: unique });
253
+ break;
254
+ }
255
+ }
256
+ edits.pendingNew.length = 0; // 已消费(无论是否成功插入,都清空防止下轮重复插入)
257
+ }
258
+
259
+ // 4. cache_reference 标注:找最后含 cache_control 的消息,给它**严格之前**的 tool_result 加引用
260
+ let lastCCMsgIndex = -1;
261
+ for (let i = 0; i < messages.length; i++) {
262
+ for (const block of messages[i].content) {
263
+ if (block && typeof block === 'object' && 'cache_control' in block) {
264
+ lastCCMsgIndex = i;
265
+ break;
266
+ }
267
+ }
268
+ }
269
+ if (lastCCMsgIndex < 0) return;
270
+ for (let i = 0; i < lastCCMsgIndex; i++) {
271
+ const msg = messages[i];
272
+ if (msg.role !== 'user') continue;
273
+ for (const block of msg.content) {
274
+ if (block.type === 'tool_result' && typeof block.tool_use_id === 'string') {
275
+ block.cache_reference = block.tool_use_id;
276
+ }
277
+ }
278
+ }
279
+ }
280
+
180
281
  /**
181
282
  * 每个请求一个新实例;把逐条 SSE `data:` 行的内容转换成 LlmStreamEvent(0..N 个)。
182
283
  *
@@ -192,6 +293,7 @@ export function createAnthropicSSEParser(): {
192
293
  } {
193
294
  let stopReason: 'stop' | 'tool_calls' | 'length' | 'unknown' = 'unknown';
194
295
  let usagePromptTokens: number | undefined;
296
+ let usageOutputTokens: number | undefined;
195
297
  let usageCachedTokens: number | undefined;
196
298
  let usageCacheWriteTokens: number | undefined;
197
299
  let promptCacheUsage: PromptCacheUsage = { reported: false };
@@ -199,6 +301,7 @@ export function createAnthropicSSEParser(): {
199
301
  type: 'done',
200
302
  stopReason,
201
303
  promptTokens: usagePromptTokens,
304
+ outputTokens: usageOutputTokens,
202
305
  ...(promptCacheUsage.reported
203
306
  ? {
204
307
  ...(usageCachedTokens !== undefined ? { cachedPromptTokens: usageCachedTokens } : {}),
@@ -267,6 +370,14 @@ export function createAnthropicSSEParser(): {
267
370
  return [];
268
371
  }
269
372
  case 'message_delta': {
373
+ // 输出侧计量:Anthropic 把 output_tokens 放在 message_delta 的**顶层 usage** 下
374
+ // (不在 delta 里),且给的是**到目前为止的累计值** —— 直接覆盖即可,不要累加。
375
+ // 与 input_tokens 不同:那个要把缓存三段相加(见 message_start 分支)。
376
+ // ⚠️ 非有限值/负数一律当「没报」,绝不退化成 0(0 会让预算闸永不触发)。
377
+ const out = data.usage?.output_tokens;
378
+ if (typeof out === 'number' && Number.isFinite(out) && out >= 0) {
379
+ usageOutputTokens = out;
380
+ }
270
381
  // ⚠️ stop_reason 嵌套在 delta.stop_reason 下,不是 message_delta 顶层。
271
382
  const sr = data.delta?.stop_reason;
272
383
  if (sr === 'end_turn' || sr === 'stop_sequence') stopReason = 'stop';
@@ -280,6 +280,7 @@ export function extractCachedPromptTokens(usage) {
280
280
  export function createOpenAISSEParser() {
281
281
  let stopReason = 'unknown';
282
282
  let usagePromptTokens;
283
+ let usageOutputTokens;
283
284
  let usageCachedTokens;
284
285
  let usageCacheMissTokens;
285
286
  let promptCacheUsage = { reported: false };
@@ -289,6 +290,7 @@ export function createOpenAISSEParser() {
289
290
  type: 'done',
290
291
  stopReason,
291
292
  promptTokens: usagePromptTokens,
293
+ outputTokens: usageOutputTokens,
292
294
  cachedPromptTokens: usageCachedTokens,
293
295
  cacheMissTokens: usageCacheMissTokens,
294
296
  promptCacheUsage,
@@ -300,6 +302,7 @@ export function createOpenAISSEParser() {
300
302
  type: 'done',
301
303
  stopReason,
302
304
  promptTokens: usagePromptTokens,
305
+ outputTokens: usageOutputTokens,
303
306
  cachedPromptTokens: usageCachedTokens,
304
307
  cacheMissTokens: usageCacheMissTokens,
305
308
  promptCacheUsage,
@@ -326,6 +329,12 @@ export function createOpenAISSEParser() {
326
329
  usageCachedTokens = cacheUsage.cacheReadTokens;
327
330
  if (cacheUsage.cacheMissTokens !== undefined)
328
331
  usageCacheMissTokens = cacheUsage.cacheMissTokens;
332
+ // 输出侧计量。⚠️ 非有限值/负数一律当「没报」,不能退化成 0 ——
333
+ // 0 会被预算刻度读成「这轮没花钱」,预算闸从此永不触发。
334
+ const completion = chunk.usage.completion_tokens;
335
+ if (typeof completion === 'number' && Number.isFinite(completion) && completion >= 0) {
336
+ usageOutputTokens = completion;
337
+ }
329
338
  }
330
339
  const delta = chunk.choices?.[0]?.delta;
331
340
  const finish = chunk.choices?.[0]?.finish_reason;
@@ -12,7 +12,7 @@ import type {
12
12
  Message,
13
13
  PromptCacheContext,
14
14
  PromptCacheUsage,
15
- Provider,
15
+ LocalProvider,
16
16
  Tool,
17
17
  } from '../../types.js';
18
18
 
@@ -112,7 +112,7 @@ export function isPromptCacheKeyRejected(status: number, errText: string): boole
112
112
  }
113
113
 
114
114
  export interface OpenAIRequestArgs {
115
- provider: Provider;
115
+ provider: LocalProvider;
116
116
  cleanedMessages: unknown[];
117
117
  tools: Tool[];
118
118
  withResponseFormat: boolean;
@@ -211,7 +211,7 @@ function looksLikeVersionedBase(url: string): boolean {
211
211
  }
212
212
  }
213
213
 
214
- export function buildOpenAIUrl(provider: Provider): string {
214
+ export function buildOpenAIUrl(provider: LocalProvider): string {
215
215
  // baseURL 是完整端点 URL(以 /chat/completions 结尾)。
216
216
  // 向后兼容:旧格式 baseURL(版本化基础路径,如 /v1)自动补全后缀,并打 warning。
217
217
  const url = provider.baseURL.trim().replace(/\/+$/, '');
@@ -344,6 +344,7 @@ export function createOpenAISSEParser(): {
344
344
  } {
345
345
  let stopReason: 'stop' | 'tool_calls' | 'length' | 'unknown' = 'unknown';
346
346
  let usagePromptTokens: number | undefined;
347
+ let usageOutputTokens: number | undefined;
347
348
  let usageCachedTokens: number | undefined;
348
349
  let usageCacheMissTokens: number | undefined;
349
350
  let promptCacheUsage: PromptCacheUsage = { reported: false };
@@ -353,6 +354,7 @@ export function createOpenAISSEParser(): {
353
354
  type: 'done',
354
355
  stopReason,
355
356
  promptTokens: usagePromptTokens,
357
+ outputTokens: usageOutputTokens,
356
358
  cachedPromptTokens: usageCachedTokens,
357
359
  cacheMissTokens: usageCacheMissTokens,
358
360
  promptCacheUsage,
@@ -364,6 +366,7 @@ export function createOpenAISSEParser(): {
364
366
  type: 'done',
365
367
  stopReason,
366
368
  promptTokens: usagePromptTokens,
369
+ outputTokens: usageOutputTokens,
367
370
  cachedPromptTokens: usageCachedTokens,
368
371
  cacheMissTokens: usageCacheMissTokens,
369
372
  promptCacheUsage,
@@ -386,6 +389,12 @@ export function createOpenAISSEParser(): {
386
389
  if (cacheUsage.promptTokens !== undefined) usagePromptTokens = cacheUsage.promptTokens;
387
390
  if (cacheUsage.cacheReadTokens !== undefined) usageCachedTokens = cacheUsage.cacheReadTokens;
388
391
  if (cacheUsage.cacheMissTokens !== undefined) usageCacheMissTokens = cacheUsage.cacheMissTokens;
392
+ // 输出侧计量。⚠️ 非有限值/负数一律当「没报」,不能退化成 0 ——
393
+ // 0 会被预算刻度读成「这轮没花钱」,预算闸从此永不触发。
394
+ const completion = (chunk.usage as Record<string, unknown>).completion_tokens;
395
+ if (typeof completion === 'number' && Number.isFinite(completion) && completion >= 0) {
396
+ usageOutputTokens = completion;
397
+ }
389
398
  }
390
399
  const delta = chunk.choices?.[0]?.delta;
391
400
  const finish = chunk.choices?.[0]?.finish_reason;