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
@@ -1,33 +0,0 @@
1
- /**
2
- * test/maxTurnsRetryDelay.test.ts
3
- * ------------------------------------------------------------
4
- * 锁定 self_heal in-run retry 的延时分类契约:
5
- * - maxTurns 截断默认仍立即续跑(兼容旧行为),但可由
6
- * self_heal.max_turns_retry_delay_ms 单独配置等待。
7
- * - 网络/LLM 错误 = 瞬态故障,仍走 retry_delay_ms 退避。
8
- *
9
- * 测 producer(describeMaxTurnsCutoff)/detector(isMaxTurnsCutoff) 同源契约,
10
- * 以及网络类报错不被误判为 maxTurns(否则退避失效、撞同一拥塞波)。
11
- */
12
-
13
- import { describe, expect, it } from 'bun:test';
14
-
15
- import {
16
- MAX_TURNS_CUTOFF_MARKER,
17
- describeMaxTurnsCutoff,
18
- isMaxTurnsCutoff,
19
- } from '../src/agentCommon.js';
20
-
21
- describe('maxTurns 截断的重试延时分类', () => {
22
- it('describeMaxTurnsCutoff 的文案能被 isMaxTurnsCutoff 识别(同源契约)', () => {
23
- expect(isMaxTurnsCutoff(describeMaxTurnsCutoff('stage0_clarify', 8))).toBe(true);
24
- expect(describeMaxTurnsCutoff('x', 8)).toContain(MAX_TURNS_CUTOFF_MARKER);
25
- });
26
-
27
- it('网络/LLM 类报错不被误判为 maxTurns(仍需退避)', () => {
28
- expect(isMaxTurnsCutoff('Unable to connect to api.minimax.chat')).toBe(false);
29
- expect(isMaxTurnsCutoff('LLM 调用失败:HTTP 429 Too Many Requests')).toBe(false);
30
- expect(isMaxTurnsCutoff('step foo: 工具执行失败')).toBe(false);
31
- expect(isMaxTurnsCutoff('')).toBe(false);
32
- });
33
- });
@@ -1,342 +0,0 @@
1
- /**
2
- * workflow-runner 多模态输入测试:
3
- * llm / agent 步骤声明 images 后,应通过 runQuery 进入 OpenAI 兼容 content blocks。
4
- */
5
-
6
- import { describe, expect, it } from 'bun:test';
7
-
8
- import { ALL_TOOLS } from '../../../src/tools/index.js';
9
- import type {
10
- ChatContentPart,
11
- LlmStreamEvent,
12
- Message,
13
- Provider,
14
- Tool,
15
- } from '../../../src/types.js';
16
- import { execAgentStep } from '../src/stepExecutors/agent.js';
17
- import { execLlmStep } from '../src/stepExecutors/llm.js';
18
- import { VarStack } from '../src/types.js';
19
- import type { RunContext, StepDef } from '../src/types.js';
20
-
21
- const provider: Provider = {
22
- name: 'test',
23
- baseURL: 'https://example.test/v1',
24
- apiKey: 'test',
25
- model: 'fake',
26
- contextWindow: 128_000,
27
- };
28
-
29
- async function drain<R>(gen: AsyncGenerator<unknown, R, void>): Promise<R> {
30
- let r = await gen.next();
31
- while (!r.done) r = await gen.next();
32
- return r.value;
33
- }
34
-
35
- function createContext(captured: Message[][], text = '完成'): RunContext {
36
- const chat = async function* (args: {
37
- provider: Provider;
38
- messages: Message[];
39
- tools: Tool[];
40
- signal?: AbortSignal;
41
- }): AsyncGenerator<LlmStreamEvent> {
42
- captured.push(args.messages);
43
- yield { type: 'text_delta', delta: text };
44
- yield { type: 'done', stopReason: 'stop' };
45
- };
46
- return {
47
- provider,
48
- history: [],
49
- cwd: process.cwd(),
50
- tools: [],
51
- chat,
52
- };
53
- }
54
-
55
- function lastUserContent(messages: Message[]): Message['content'] {
56
- const user = [...messages].reverse().find((m) => m.role === 'user');
57
- if (!user) throw new Error('missing user message');
58
- return user.content;
59
- }
60
-
61
- function messagesContainImage(messages: Message[]): boolean {
62
- return messages.some((msg) => {
63
- if (!Array.isArray(msg.content)) return false;
64
- return msg.content.some((part) => part.type === 'image_url');
65
- });
66
- }
67
-
68
- describe('workflow-runner multimodal images', () => {
69
- it('agent allowed_tools cannot expand the host tool catalog', async () => {
70
- let round = 0;
71
- let executed = 0;
72
- const chat = async function* (): AsyncGenerator<LlmStreamEvent> {
73
- if (round++ === 0) {
74
- yield { type: 'tool_call_delta', index: 0, id: 'hidden', name: 'Bash' };
75
- yield {
76
- type: 'tool_call_delta',
77
- index: 0,
78
- argumentsDelta: '{"command":"echo no"}',
79
- };
80
- yield { type: 'done', stopReason: 'tool_calls' };
81
- return;
82
- }
83
- yield { type: 'text_delta', delta: '已改道。' };
84
- yield { type: 'done', stopReason: 'stop' };
85
- };
86
- const ctx: RunContext = {
87
- provider,
88
- history: [{ role: 'system', content: 'stable' }],
89
- cwd: process.cwd(),
90
- tools: ALL_TOOLS.filter((tool) => tool.name === 'Read'),
91
- chat,
92
- executeTool: async () => {
93
- executed += 1;
94
- return { ok: true, content: 'unexpected' };
95
- },
96
- };
97
- const result = await drain(
98
- execAgentStep(
99
- { id: 'bounded', agent: '完成任务', allowed_tools: ['Bash'] },
100
- new VarStack(),
101
- ctx,
102
- ),
103
- );
104
- expect(executed).toBe(0);
105
- expect(result.raw.text).toBe('已改道。');
106
- });
107
-
108
- it('an empty host tool catalog remains empty instead of restoring global tools', async () => {
109
- let round = 0;
110
- let executed = 0;
111
- const chat = async function* (): AsyncGenerator<LlmStreamEvent> {
112
- if (round++ === 0) {
113
- yield { type: 'tool_call_delta', index: 0, id: 'hidden', name: 'Read' };
114
- yield {
115
- type: 'tool_call_delta',
116
- index: 0,
117
- argumentsDelta: '{"file_path":"README.md"}',
118
- };
119
- yield { type: 'done', stopReason: 'tool_calls' };
120
- return;
121
- }
122
- yield { type: 'text_delta', delta: '没有可用工具。' };
123
- yield { type: 'done', stopReason: 'stop' };
124
- };
125
- const ctx: RunContext = {
126
- provider,
127
- history: [{ role: 'system', content: 'stable' }],
128
- cwd: process.cwd(),
129
- tools: [],
130
- chat,
131
- executeTool: async () => {
132
- executed += 1;
133
- return { ok: true, content: 'unexpected' };
134
- },
135
- };
136
-
137
- const result = await drain(
138
- execAgentStep(
139
- { id: 'empty-bound', agent: '完成任务', allowed_tools: ['Read'] },
140
- new VarStack(),
141
- ctx,
142
- ),
143
- );
144
-
145
- expect(executed).toBe(0);
146
- expect(result.raw.text).toBe('没有可用工具。');
147
- });
148
-
149
- it('execLlmStep 把 images 传成 image_url content block,并支持变量插值', async () => {
150
- const captured: Message[][] = [];
151
- const ctx = createContext(captured);
152
- const vars = new VarStack();
153
- vars.setGlobal('inputs', {
154
- image: 'https://example.com/mockup.png',
155
- });
156
- const step: StepDef = {
157
- id: 'inspect',
158
- llm: '请描述图片',
159
- images: [
160
- {
161
- source: '${inputs.image}',
162
- detail: 'high',
163
- max_long_side_pixel: 1600,
164
- },
165
- ],
166
- };
167
-
168
- await drain(execLlmStep(step, vars, ctx));
169
-
170
- const content = lastUserContent(captured[0]);
171
- expect(Array.isArray(content)).toBe(true);
172
- const parts = content as ChatContentPart[];
173
- expect(parts[0]).toEqual({ type: 'text', text: '请描述图片' });
174
- expect(parts[1]).toEqual({
175
- type: 'image_url',
176
- image_url: {
177
- url: 'https://example.com/mockup.png',
178
- detail: 'high',
179
- max_long_side_pixel: 1600,
180
- },
181
- });
182
- });
183
-
184
- it('parse_inline_images=true 时解析 prompt 内图片引用', async () => {
185
- const captured: Message[][] = [];
186
- const ctx = createContext(captured);
187
- const step: StepDef = {
188
- id: 'inline',
189
- llm: '请看 @https://example.com/a.png 并指出问题',
190
- parse_inline_images: true,
191
- image_detail: 'low',
192
- };
193
-
194
- await drain(execLlmStep(step, new VarStack(), ctx));
195
-
196
- const content = lastUserContent(captured[0]);
197
- expect(Array.isArray(content)).toBe(true);
198
- const parts = content as ChatContentPart[];
199
- expect(parts[0]).toEqual({ type: 'text', text: '请看 并指出问题' });
200
- expect(parts[1]).toEqual({
201
- type: 'image_url',
202
- image_url: { url: 'https://example.com/a.png', detail: 'low' },
203
- });
204
- });
205
-
206
- it('execAgentStep 支持 images,且不影响 agent 验证闸门', async () => {
207
- const captured: Message[][] = [];
208
- const ctx = createContext(captured, '已经完成图片分析。');
209
- const step: StepDef = {
210
- id: 'agent-inspect',
211
- agent: '看图后给出结论',
212
- images: ['https://example.com/design.png'],
213
- image_detail: 'default',
214
- allowed_tools: [],
215
- };
216
-
217
- const result = await drain(execAgentStep(step, new VarStack(), ctx));
218
-
219
- expect(result.raw.text).toBe('已经完成图片分析。');
220
- const content = lastUserContent(captured[0]);
221
- expect(Array.isArray(content)).toBe(true);
222
- const parts = content as ChatContentPart[];
223
- expect(parts.at(-1)).toEqual({
224
- type: 'image_url',
225
- image_url: { url: 'https://example.com/design.png', detail: 'default' },
226
- });
227
- });
228
-
229
- it('history_mode=isolated 的多模态 llm 可 capture 输出,但不污染共享 history', async () => {
230
- const captured: Message[][] = [];
231
- const ctx = createContext(captured, '图片可用');
232
- ctx.history.push({ role: 'system', content: 'workflow system prompt' });
233
- const step: StepDef = {
234
- id: 'review-image',
235
- llm: '复核生成图',
236
- images: ['https://example.com/generated.png'],
237
- image_detail: 'high',
238
- history_mode: 'isolated',
239
- };
240
-
241
- const result = await drain(execLlmStep(step, new VarStack(), ctx));
242
-
243
- expect(result.raw.text).toBe('图片可用');
244
- expect(messagesContainImage(captured[0])).toBe(true);
245
- expect(ctx.history).toEqual([
246
- { role: 'system', content: 'workflow system prompt' },
247
- ]);
248
- });
249
-
250
- it('isolated 多模态步骤之后的普通 agent 不会收到前一步 image_url', async () => {
251
- const captured: Message[][] = [];
252
- const ctx = createContext(captured, '完成');
253
- ctx.history.push({ role: 'system', content: 'workflow system prompt' });
254
-
255
- await drain(
256
- execLlmStep(
257
- {
258
- id: 'review-image',
259
- llm: '复核生成图',
260
- images: ['https://example.com/generated.png'],
261
- history_mode: 'isolated',
262
- },
263
- new VarStack(),
264
- ctx,
265
- ),
266
- );
267
-
268
- await drain(
269
- execAgentStep(
270
- {
271
- id: 'export',
272
- agent: '导出 PPTX',
273
- allowed_tools: [],
274
- },
275
- new VarStack(),
276
- ctx,
277
- ),
278
- );
279
-
280
- expect(messagesContainImage(captured[0])).toBe(true);
281
- expect(messagesContainImage(captured[1])).toBe(false);
282
- });
283
-
284
- it('history_mode=isolated 的 agent 仍可调用工具,但不把工具对话写回共享 history', async () => {
285
- const captured: Message[][] = [];
286
- let calls = 0;
287
- let toolCalled = false;
288
- const chat = async function* (args: {
289
- provider: Provider;
290
- messages: Message[];
291
- tools: Tool[];
292
- signal?: AbortSignal;
293
- }): AsyncGenerator<LlmStreamEvent> {
294
- captured.push(args.messages);
295
- calls++;
296
- if (calls === 1) {
297
- yield {
298
- type: 'tool_call_delta',
299
- index: 0,
300
- id: 'call_1',
301
- name: 'Write',
302
- argumentsDelta: '{"file_path":"./out.txt","content":"ok"}',
303
- };
304
- yield { type: 'done', stopReason: 'tool_calls' };
305
- return;
306
- }
307
- yield { type: 'text_delta', delta: '文件已写好。' };
308
- yield { type: 'done', stopReason: 'stop' };
309
- };
310
- const ctx: RunContext = {
311
- provider,
312
- history: [{ role: 'system', content: 'workflow system prompt' }],
313
- cwd: process.cwd(),
314
- tools: ALL_TOOLS.filter((tool) => tool.name === 'Write'),
315
- chat,
316
- executeTool: async () => {
317
- toolCalled = true;
318
- return { ok: true, content: 'written' };
319
- },
320
- };
321
-
322
- const result = await drain(
323
- execAgentStep(
324
- {
325
- id: 'isolated-export',
326
- agent: '写一个文件并报告',
327
- allowed_tools: ['Write'],
328
- history_mode: 'isolated',
329
- },
330
- new VarStack(),
331
- ctx,
332
- ),
333
- );
334
-
335
- expect(toolCalled).toBe(true);
336
- expect(result.raw.text).toBe('文件已写好。');
337
- expect(ctx.history).toEqual([
338
- { role: 'system', content: 'workflow system prompt' },
339
- ]);
340
- expect(captured.length).toBe(2);
341
- });
342
- });
@@ -1,213 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/output-schema.test.ts —— ADR-05 Wave 2 验证
4
- * ------------------------------------------------------------
5
- * 覆盖 execLlmStep 的 output_schema 行为:
6
- * 1. 带 output_schema → chat() 收到 responseFormat 参数,raw 是 parsed JSON
7
- * 2. capture { findings: items } 能从 structured raw 抽出字段
8
- * 3. JSON.parse 失败 → 抛错含原文前 200 字
9
- * 4. 缺省 output_schema → 走老路径(raw 是 { text, result },无 [json] 前缀)
10
- *
11
- * 策略:
12
- * - mock.module('../../../src/llm/client.js') 拦截 chat
13
- * - 同时把收到的 args 暂存到 module 级数组,用于断言 responseFormat
14
- * - case 2 用 runWorkflow,验证 runner 端 capture 联动 structured raw
15
- * - 其余 case 直接调 execLlmStep
16
- * ============================================================
17
- */
18
-
19
- import { beforeEach, describe, expect, it, mock } from 'bun:test';
20
-
21
- import { execLlmStep } from '../src/stepExecutors/llm.js';
22
- import { runWorkflow } from '../src/runner.js';
23
- import { VarStack } from '../src/types.js';
24
- import type {
25
- LoopEvent,
26
- Provider,
27
- } from '../../../src/types.js';
28
- import type {
29
- RunContext,
30
- StepDef,
31
- WorkflowDef,
32
- WorkflowEvent,
33
- } from '../src/types.js';
34
-
35
- type WfOrLoop = WorkflowEvent | LoopEvent;
36
-
37
- const fakeProvider: Provider = {
38
- name: 'test',
39
- baseURL: '',
40
- apiKey: '',
41
- model: 'm',
42
- contextWindow: 128000,
43
- };
44
-
45
- /** 收集 chat() 收到的参数(每次调用 push 一条);测试 case 切换前 clear */
46
- const capturedChatArgs: unknown[] = [];
47
- /** 测试 case 控制:本轮 chat 应该 yield 的文本 */
48
- let mockChatText = '';
49
-
50
- mock.module('../../../src/llm/client.js', () => ({
51
- chat: async function* (args: unknown) {
52
- capturedChatArgs.push(args);
53
- yield { type: 'text_delta', delta: mockChatText };
54
- yield { type: 'done', stopReason: 'stop' };
55
- },
56
- }));
57
-
58
- async function collect(
59
- gen: AsyncGenerator<WfOrLoop, void, void>,
60
- ): Promise<WfOrLoop[]> {
61
- const out: WfOrLoop[] = [];
62
- for await (const ev of gen) out.push(ev);
63
- return out;
64
- }
65
-
66
- /** execLlmStep 现为 AsyncGenerator:drain 取最终 return 值(yield 的事件直接丢弃)。 */
67
- async function drainLlm<R>(gen: AsyncGenerator<unknown, R, void>): Promise<R> {
68
- let r = await gen.next();
69
- while (!r.done) r = await gen.next();
70
- return r.value;
71
- }
72
-
73
- describe('workflow-runner output_schema (ADR-05)', () => {
74
- let ctx: RunContext;
75
-
76
- beforeEach(() => {
77
- capturedChatArgs.length = 0;
78
- mockChatText = '';
79
- ctx = { provider: fakeProvider, history: [], cwd: process.cwd(), tools: [] };
80
- });
81
-
82
- it('case 1: 带 output_schema → schema 内嵌进 prompt,raw 是 parsed JSON', async () => {
83
- // v0.9 重构:llm 步委托 runQuery(TAOR) 执行,不再走 provider-native responseFormat
84
- // (弱模型多不支持 json_schema),改为把 schema 约束【内嵌进 prompt】+ 上层 extractJsonPayload
85
- // 容错解析。本用例对齐该设计:断言 schema 进了发给模型的 prompt + raw 是解析后的 JSON。
86
- mockChatText = '{"findings":["bug1","bug2"]}';
87
- const schema = {
88
- type: 'object',
89
- properties: {
90
- findings: { type: 'array', items: { type: 'string' } },
91
- },
92
- required: ['findings'],
93
- };
94
- const step: StepDef = {
95
- id: 'analyze',
96
- llm: 'find bugs',
97
- output_schema: schema,
98
- };
99
-
100
- const result = await drainLlm(execLlmStep(step, new VarStack(), ctx));
101
-
102
- // 断言 1: chat 被调一次,schema 约束内嵌进发给模型的 user prompt
103
- expect(capturedChatArgs.length).toBe(1);
104
- const args = capturedChatArgs[0] as {
105
- messages: { role: string; content: string }[];
106
- };
107
- const userMsg = args.messages.find((m) => m.role === 'user');
108
- expect(userMsg).toBeDefined();
109
- expect(userMsg!.content).toContain('JSON Schema');
110
- expect(userMsg!.content).toContain('findings');
111
-
112
- // 断言 2: raw 是 parsed JSON 对象,preview 带 [json] 前缀
113
- expect(result.raw).toEqual({ findings: ['bug1', 'bug2'] });
114
- expect(result.preview.startsWith('[json] ')).toBe(true);
115
- });
116
-
117
- it('case 2: capture 从 structured raw 抽出字段(runner 端联动)', async () => {
118
- mockChatText = '{"findings":["bug1","bug2"]}';
119
- const def: WorkflowDef = {
120
- name: 'cap-struct',
121
- description: 'd',
122
- steps: [
123
- {
124
- id: 'analyze',
125
- llm: 'find bugs',
126
- output_schema: {
127
- type: 'object',
128
- properties: {
129
- findings: { type: 'array', items: { type: 'string' } },
130
- },
131
- required: ['findings'],
132
- },
133
- capture: { findings: 'items' },
134
- },
135
- {
136
- id: 'check',
137
- type: 'assert',
138
- condition: 'length(items) == 2',
139
- },
140
- ],
141
- };
142
-
143
- const events = await collect(runWorkflow(def, {}, ctx));
144
- // workflow 跑完
145
- expect(events.some((e) => e.type === 'workflow_done')).toBe(true);
146
- // 拿到 workflow_done 的 vars 快照
147
- const done = events.find(
148
- (e): e is Extract<WorkflowEvent, { type: 'workflow_done' }> =>
149
- e.type === 'workflow_done',
150
- );
151
- expect(done).toBeDefined();
152
- expect(done!.vars.items).toEqual(['bug1', 'bug2']);
153
- });
154
-
155
- it('case 3: JSON.parse 失败 → 抛错含原文前 200 字', async () => {
156
- mockChatText = 'this is not json';
157
- const step: StepDef = {
158
- id: 'bad',
159
- llm: 'go',
160
- output_schema: { type: 'object' },
161
- };
162
-
163
- let caught: Error | null = null;
164
- try {
165
- await drainLlm(execLlmStep(step, new VarStack(), ctx));
166
- } catch (e) {
167
- caught = e as Error;
168
- }
169
- expect(caught).not.toBeNull();
170
- expect(caught!.message).toContain('output_schema 要求 JSON 输出但解析失败');
171
- expect(caught!.message).toContain('this is not json');
172
- });
173
-
174
- it('case 3b: content 掺 <think> 思维链 → 仍能解析(MiniMax-M2/M3 真实场景)', async () => {
175
- // 思考型模型即便在 strict json_schema 下也会把 <think> 写进 content。
176
- // 这条端到端 case 锁住"解析点确实接了 extractJsonPayload"——纯函数单测覆盖不到接线。
177
- mockChatText =
178
- '<think>用户要 findings。我应该返回 {"findings": [...]} 形状。</think>{"findings":["real"],"open_questions":[]}';
179
- const step: StepDef = {
180
- id: 'thinky',
181
- llm: 'go',
182
- output_schema: {
183
- type: 'object',
184
- properties: { findings: { type: 'array', items: { type: 'string' } } },
185
- required: ['findings'],
186
- },
187
- };
188
-
189
- const result = await drainLlm(execLlmStep(step, new VarStack(), ctx));
190
- expect(result.raw).toEqual({ findings: ['real'], open_questions: [] });
191
- });
192
-
193
- it('case 4: 缺省 output_schema → 老路径(raw {text,result}, preview 无 [json])', async () => {
194
- mockChatText = 'Hello world';
195
- const step: StepDef = {
196
- id: 'plain',
197
- llm: 'say hi',
198
- };
199
-
200
- const result = await drainLlm(execLlmStep(step, new VarStack(), ctx));
201
-
202
- // chat 收到的 responseFormat 必须是 undefined(不破坏老调用方)
203
- expect(capturedChatArgs.length).toBe(1);
204
- const args = capturedChatArgs[0] as { responseFormat?: unknown };
205
- expect(args.responseFormat).toBeUndefined();
206
-
207
- // raw 是 { text, result } 双字段
208
- expect(result.raw).toEqual({ text: 'Hello world', result: 'Hello world' });
209
- // preview 无 [json] 前缀
210
- expect(result.preview.startsWith('[json] ')).toBe(false);
211
- expect(result.preview).toBe('Hello world');
212
- });
213
- });
@@ -1,106 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/parseWorkflowArgs.test.ts —— 边界行为冻结测试
4
- * ------------------------------------------------------------
5
- * parseWorkflowArgs / tokenizeArgs 当前的行为(无转义、引号宽松、未知 flag 跳一个 token)
6
- * 被这些测试冻结。改 tokenizer 语义 → 改这些测试。
7
- * ============================================================
8
- */
9
- import { describe, test, expect } from 'bun:test';
10
- import { parseWorkflowArgs } from '../src/index.js';
11
-
12
- describe('parseWorkflowArgs / tokenizeArgs 边界行为冻结', () => {
13
- test('未闭合引号:剩余部分作为单 token', () => {
14
- const r = parseWorkflowArgs('hello "未闭合');
15
- expect(r.name).toBe('hello');
16
- expect(r.positional).toEqual(['未闭合']);
17
- });
18
-
19
- test('混合引号:双引号内含单引号字面量', () => {
20
- const r = parseWorkflowArgs(`hello "it's fine"`);
21
- expect(r.positional).toEqual([`it's fine`]);
22
- });
23
-
24
- test('反斜杠不转义:原样保留', () => {
25
- const r = parseWorkflowArgs('hello a\\"b');
26
- // 当前行为:\\" 不视为转义;按空白切分得到 'a\\' 然后 '"b'('b' 未闭合)
27
- // 行为冻结测试 —— 用 toBeDefined 而非具体值,保留未来微调空间
28
- expect(r.positional.length).toBeGreaterThan(0);
29
- });
30
-
31
- test('空字符串引号产生空 token', () => {
32
- const r = parseWorkflowArgs('hello ""');
33
- expect(r.positional).toEqual(['']);
34
- });
35
-
36
- test('连续空白合并', () => {
37
- const r = parseWorkflowArgs('hello alice bob');
38
- expect(r.positional).toEqual(['alice', 'bob']);
39
- });
40
-
41
- test('--input 后无 = 的 token:被丢弃不报错', () => {
42
- const r = parseWorkflowArgs('hello --input justkey');
43
- expect(r.inputs).toEqual({});
44
- expect(r.name).toBe('hello');
45
- });
46
-
47
- test('--input 末尾无值:循环 break 不崩', () => {
48
- const r = parseWorkflowArgs('hello --input');
49
- expect(r.inputs).toEqual({});
50
- expect(r.name).toBe('hello');
51
- });
52
-
53
- test('.yaml 后缀大小写不敏感剥离', () => {
54
- expect(parseWorkflowArgs('hello.YAML alice').name).toBe('hello');
55
- expect(parseWorkflowArgs('hello.YML alice').name).toBe('hello');
56
- expect(parseWorkflowArgs('hello.Yaml alice').name).toBe('hello');
57
- });
58
-
59
- test('引号包裹整个 KV:含空格的 value 正确捕获', () => {
60
- const r = parseWorkflowArgs('hello --input "topic=AI 教程"');
61
- expect(r.inputs).toEqual({ topic: 'AI 教程' });
62
- });
63
-
64
- test('引号在 = 后的 KV:value 含空格也完整捕获(回归:曾按空白硬切+引号残留)', () => {
65
- // 用户 shell 习惯 `--input topic="带空格 的值"` —— 引号在 token 内部(= 之后),
66
- // 曾被 tokenizeArgs 按空白切分 → 值截断 + 引号残留 + 散落 positional。
67
- const r = parseWorkflowArgs(
68
- 'hello --input topic="比特币量化 长线 短线策略" --input depth=standard',
69
- );
70
- expect(r.inputs).toEqual({
71
- topic: '比特币量化 长线 短线策略',
72
- depth: 'standard',
73
- });
74
- expect(r.positional).toEqual([]);
75
- });
76
-
77
- test('单引号在 = 后同理支持', () => {
78
- const r = parseWorkflowArgs("hello --input topic='AI 教程 入门'");
79
- expect(r.inputs).toEqual({ topic: 'AI 教程 入门' });
80
- expect(r.positional).toEqual([]);
81
- });
82
-
83
- test('未知 -- flag 跳过其后一个 token(保守解析)', () => {
84
- const r = parseWorkflowArgs('hello --foo bar alice');
85
- // --foo bar 被吃掉,alice 进 positional
86
- expect(r.positional).toEqual(['alice']);
87
- });
88
-
89
- test('单引号也支持引号包裹', () => {
90
- const r = parseWorkflowArgs(`hello 'AI tutorial'`);
91
- expect(r.positional).toEqual(['AI tutorial']);
92
- });
93
-
94
- test('完全空字符串:name 为 null', () => {
95
- const r = parseWorkflowArgs('');
96
- expect(r.name).toBeNull();
97
- expect(r.positional).toEqual([]);
98
- expect(r.inputs).toEqual({});
99
- });
100
-
101
- test('仅有 flag 没有 name:name 仍为 null', () => {
102
- const r = parseWorkflowArgs('--input name=alice');
103
- expect(r.name).toBeNull();
104
- expect(r.inputs).toEqual({ name: 'alice' });
105
- });
106
- });