minimal-agent 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
@@ -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,87 +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('未知 -- flag 跳过其后一个 token(保守解析)', () => {
65
- const r = parseWorkflowArgs('hello --foo bar alice');
66
- // --foo bar 被吃掉,alice 进 positional
67
- expect(r.positional).toEqual(['alice']);
68
- });
69
-
70
- test('单引号也支持引号包裹', () => {
71
- const r = parseWorkflowArgs(`hello 'AI tutorial'`);
72
- expect(r.positional).toEqual(['AI tutorial']);
73
- });
74
-
75
- test('完全空字符串:name 为 null', () => {
76
- const r = parseWorkflowArgs('');
77
- expect(r.name).toBeNull();
78
- expect(r.positional).toEqual([]);
79
- expect(r.inputs).toEqual({});
80
- });
81
-
82
- test('仅有 flag 没有 name:name 仍为 null', () => {
83
- const r = parseWorkflowArgs('--input name=alice');
84
- expect(r.name).toBeNull();
85
- expect(r.inputs).toEqual({ name: 'alice' });
86
- });
87
- });