minimal-agent 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +503 -0
  103. package/src/advisor/advisorCoordinator.ts +657 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/streamJson.js +5 -6
  108. package/src/cli/streamJson.ts +8 -4
  109. package/src/cli/wizards/advisorWizard.js +4 -2
  110. package/src/cli/wizards/advisorWizard.tsx +8 -2
  111. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  112. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  113. package/src/collaboration/taskFlow.js +115 -0
  114. package/src/collaboration/taskFlow.ts +169 -0
  115. package/src/config/configDefaults.js +41 -1
  116. package/src/config/configDefaults.ts +43 -1
  117. package/src/config/configDiagnostics.ts +2 -2
  118. package/src/config/configFile.js +40 -9
  119. package/src/config/configFile.ts +60 -11
  120. package/src/config/configService.js +419 -74
  121. package/src/config/configService.ts +703 -145
  122. package/src/config/numericLimits.js +22 -0
  123. package/src/config/numericLimits.ts +24 -0
  124. package/src/config.js +1 -0
  125. package/src/config.ts +3 -2
  126. package/src/context/budgetPlan.js +1 -1
  127. package/src/context/budgetPlan.ts +1 -1
  128. package/src/context/compact.js +7 -2
  129. package/src/context/compact.ts +9 -2
  130. package/src/context/microCompactLite.js +212 -13
  131. package/src/context/microCompactLite.ts +261 -12
  132. package/src/context/sessionRegistry.js +8 -1
  133. package/src/context/sessionRegistry.ts +18 -5
  134. package/src/context/toolResultArchive.js +72 -0
  135. package/src/context/toolResultArchive.ts +95 -0
  136. package/src/goal/errors.js +8 -0
  137. package/src/goal/errors.ts +18 -0
  138. package/src/goal/goalRuntime.js +344 -0
  139. package/src/goal/goalRuntime.ts +466 -0
  140. package/src/goal/goalStore.js +200 -0
  141. package/src/goal/goalStore.ts +219 -0
  142. package/src/goal/index.js +4 -0
  143. package/src/goal/index.ts +4 -0
  144. package/src/goal/statusMapping.js +71 -0
  145. package/src/goal/statusMapping.ts +95 -0
  146. package/src/goal/types.js +7 -0
  147. package/src/goal/types.ts +179 -0
  148. package/src/goal/workflowController.js +306 -0
  149. package/src/goal/workflowController.ts +360 -0
  150. package/src/harness/evidenceLedger.js +2 -0
  151. package/src/harness/evidenceLedger.ts +1 -0
  152. package/src/harness/stallGuard.js +9 -3
  153. package/src/harness/stallGuard.ts +7 -3
  154. package/src/images/imageResolver.js +161 -0
  155. package/src/images/imageResolver.ts +189 -0
  156. package/src/infra/verification.js +34 -5
  157. package/src/infra/verification.ts +39 -4
  158. package/src/llm/client.js +79 -21
  159. package/src/llm/client.ts +182 -35
  160. package/src/llm/gatewayClient.js +201 -0
  161. package/src/llm/gatewayClient.ts +299 -0
  162. package/src/llm/messageProvenance.js +46 -0
  163. package/src/llm/messageProvenance.ts +58 -0
  164. package/src/llm/modelProvider.js +1 -0
  165. package/src/llm/modelProvider.ts +22 -0
  166. package/src/llm/providers/anthropicFormat.js +108 -1
  167. package/src/llm/providers/anthropicFormat.ts +115 -4
  168. package/src/llm/providers/openaiFormat.js +9 -0
  169. package/src/llm/providers/openaiFormat.ts +12 -3
  170. package/src/loop.js +319 -54
  171. package/src/loop.ts +373 -57
  172. package/src/main.js +4 -1
  173. package/src/main.tsx +4 -1
  174. package/src/managedExecution/index.js +2 -0
  175. package/src/managedExecution/index.ts +2 -0
  176. package/src/managedExecution/registry.js +15 -0
  177. package/src/managedExecution/registry.ts +20 -0
  178. package/src/managedExecution/types.js +1 -0
  179. package/src/managedExecution/types.ts +86 -0
  180. package/src/modelRef.js +9 -0
  181. package/src/modelRef.ts +31 -0
  182. package/src/multimodal.js +14 -28
  183. package/src/multimodal.ts +17 -33
  184. package/src/net/lanDiscovery.js +65 -0
  185. package/src/net/lanDiscovery.ts +82 -0
  186. package/src/plugin-sdk.js +28 -3
  187. package/src/plugin-sdk.ts +39 -6
  188. package/src/plugins/pluginApi.ts +16 -1
  189. package/src/plugins/pluginLoader.js +4 -0
  190. package/src/plugins/pluginLoader.ts +6 -0
  191. package/src/plugins/pluginRunner.js +139 -7
  192. package/src/plugins/pluginRunner.ts +173 -9
  193. package/src/plugins/slashFallback.js +113 -0
  194. package/src/plugins/slashFallback.ts +137 -0
  195. package/src/prompts/policyRegistry.js +12 -32
  196. package/src/prompts/policyRegistry.ts +15 -32
  197. package/src/prompts/promptAssembly.js +103 -12
  198. package/src/prompts/promptAssembly.ts +114 -12
  199. package/src/prompts/skillList.js +21 -3
  200. package/src/prompts/skillList.ts +27 -2
  201. package/src/prompts/stableSystemPrompt.js +18 -0
  202. package/src/prompts/stableSystemPrompt.ts +33 -0
  203. package/src/runtime/agentRuntimeContext.js +8 -2
  204. package/src/runtime/agentRuntimeContext.ts +17 -4
  205. package/src/session/runAgentTurn.js +78 -12
  206. package/src/session/runAgentTurn.ts +105 -23
  207. package/src/session/runTurn.js +10 -9
  208. package/src/session/runTurn.ts +17 -8
  209. package/src/session/sessionState.ts +2 -0
  210. package/src/team/auth.js +186 -0
  211. package/src/team/auth.ts +298 -0
  212. package/src/team/cli.js +105 -0
  213. package/src/team/cli.ts +122 -0
  214. package/src/team/onlineToolContract.js +64 -0
  215. package/src/team/onlineToolContract.ts +109 -0
  216. package/src/team/toolPolicy.js +36 -0
  217. package/src/team/toolPolicy.ts +75 -0
  218. package/src/tools/advisor/advisor.js +90 -46
  219. package/src/tools/advisor/advisor.ts +100 -47
  220. package/src/tools/advisor/advisorDecision.js +71 -0
  221. package/src/tools/advisor/advisorDecision.ts +85 -0
  222. package/src/tools/agent/agent.js +18 -5
  223. package/src/tools/agent/agent.ts +21 -7
  224. package/src/tools/agent/agentControl.js +246 -0
  225. package/src/tools/agent/agentControl.ts +284 -0
  226. package/src/tools/agent/agentTaskService.js +40 -1
  227. package/src/tools/agent/agentTaskService.ts +44 -1
  228. package/src/tools/agent/agentTypes.js +14 -2
  229. package/src/tools/agent/agentTypes.ts +15 -2
  230. package/src/tools/applypatch/applyPatch.js +362 -0
  231. package/src/tools/applypatch/applyPatch.ts +428 -0
  232. package/src/tools/bash/bash.js +22 -15
  233. package/src/tools/bash/bash.ts +23 -17
  234. package/src/tools/capabilities.js +10 -5
  235. package/src/tools/capabilities.ts +10 -5
  236. package/src/tools/computeruse/computerIntent.js +32 -0
  237. package/src/tools/computeruse/computerIntent.ts +46 -0
  238. package/src/tools/computeruse/telemetryLog.js +12 -0
  239. package/src/tools/computeruse/telemetryLog.ts +16 -0
  240. package/src/tools/computeruse/vision/telemetry.js +1 -0
  241. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  242. package/src/tools/effectiveToolSet.js +4 -0
  243. package/src/tools/effectiveToolSet.ts +4 -0
  244. package/src/tools/index.js +21 -2
  245. package/src/tools/index.ts +33 -2
  246. package/src/tools/presentresult/presentresult.js +6 -15
  247. package/src/tools/presentresult/presentresult.ts +6 -15
  248. package/src/tools/read/read.js +62 -9
  249. package/src/tools/read/read.ts +63 -9
  250. package/src/tools/shared/fileUtils.js +1 -2
  251. package/src/tools/shared/fileUtils.ts +1 -2
  252. package/src/tools/shared/toolOutputStore.js +23 -1
  253. package/src/tools/shared/toolOutputStore.ts +22 -1
  254. package/src/tools/skill/skill.js +9 -3
  255. package/src/tools/skill/skill.ts +8 -4
  256. package/src/tools/toolPromptGuides.js +117 -0
  257. package/src/tools/toolPromptGuides.ts +137 -0
  258. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  259. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  260. package/src/tools/webbrowser/browser.js +27 -11
  261. package/src/tools/webbrowser/browser.ts +68 -24
  262. package/src/tools/webbrowser/browserAutomation.js +329 -0
  263. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  264. package/src/tools/webbrowser/browserAxState.js +97 -0
  265. package/src/tools/webbrowser/browserAxState.ts +142 -0
  266. package/src/tools/webbrowser/browserBatch.js +1578 -0
  267. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  268. package/src/tools/webbrowser/browserCdp.js +208 -0
  269. package/src/tools/webbrowser/browserCdp.ts +255 -0
  270. package/src/tools/webbrowser/browserConditions.js +24 -0
  271. package/src/tools/webbrowser/browserConditions.ts +45 -0
  272. package/src/tools/webbrowser/browserContent.js +281 -0
  273. package/src/tools/webbrowser/browserContent.ts +438 -0
  274. package/src/tools/webbrowser/browserControl.js +131 -34
  275. package/src/tools/webbrowser/browserControl.ts +210 -56
  276. package/src/tools/webbrowser/browserDaemon.js +22 -14
  277. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  278. package/src/tools/webbrowser/browserFrames.js +47 -0
  279. package/src/tools/webbrowser/browserFrames.ts +54 -0
  280. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  281. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  282. package/src/tools/webbrowser/browserLocator.js +140 -0
  283. package/src/tools/webbrowser/browserLocator.ts +194 -0
  284. package/src/tools/webbrowser/browserOutcome.js +10 -17
  285. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  286. package/src/tools/webbrowser/browserRecovery.js +58 -0
  287. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  288. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  289. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  290. package/src/tools/webbrowser/browserService.js +28 -2
  291. package/src/tools/webbrowser/browserService.ts +49 -9
  292. package/src/tools/webbrowser/browserStream.js +132 -33
  293. package/src/tools/webbrowser/browserStream.ts +224 -50
  294. package/src/tools/webbrowser/browserTabs.js +48 -15
  295. package/src/tools/webbrowser/browserTabs.ts +178 -96
  296. package/src/tools/webbrowser/webbrowser.js +679 -144
  297. package/src/tools/webbrowser/webbrowser.ts +975 -236
  298. package/src/tools/webfetch/preapproved.js +0 -2
  299. package/src/tools/webfetch/preapproved.ts +0 -2
  300. package/src/tools/websearch/websearch.js +129 -8
  301. package/src/tools/websearch/websearch.ts +138 -6
  302. package/src/types.ts +440 -38
  303. package/src/ui/App.js +377 -58
  304. package/src/ui/App.tsx +576 -111
  305. package/src/ui/LiveArea.js +14 -8
  306. package/src/ui/LiveArea.tsx +14 -10
  307. package/src/ui/MessageList.js +63 -20
  308. package/src/ui/MessageList.tsx +101 -16
  309. package/src/ui/ModelPicker.js +7 -4
  310. package/src/ui/ModelPicker.tsx +55 -8
  311. package/src/ui/hooks/useChat.js +152 -163
  312. package/src/ui/hooks/useChat.ts +396 -334
  313. package/src/ui/loginCommand.js +56 -0
  314. package/src/ui/loginCommand.ts +63 -0
  315. package/src/ui/toolProgress.js +41 -0
  316. package/src/ui/toolProgress.ts +44 -0
  317. package/src/web/browserBridge.js +20 -2
  318. package/src/web/browserBridge.ts +20 -2
  319. package/src/web/protocol.ts +1897 -194
  320. package/workflows/adaptive-research/workflow.mjs +86 -0
  321. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  322. package/workflows/e2e-llm/workflow.mjs +52 -0
  323. package/workflows/e2e-smoke/workflow.mjs +59 -0
  324. package/workflows/e2e-vision-schema/README.md +48 -0
  325. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  326. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  327. package/workflows/file-census/README.md +14 -0
  328. package/workflows/file-census/scripts/.gitkeep +2 -0
  329. package/workflows/file-census/workflow.mjs +110 -0
  330. package/workflows/goal/README.md +166 -0
  331. package/workflows/goal/prompts/audit.md +57 -0
  332. package/workflows/goal/prompts/contract.md +56 -0
  333. package/workflows/goal/prompts/iterate.md +37 -0
  334. package/workflows/goal/workflow.mjs +501 -0
  335. package/workflows/illustrate/README.md +90 -0
  336. package/workflows/illustrate/assets/engines.json +20 -0
  337. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  338. package/workflows/illustrate/assets/extract-bing.js +33 -0
  339. package/workflows/illustrate/assets/extract-google.js +31 -0
  340. package/workflows/illustrate/workflow.mjs +301 -0
  341. package/workflows/plan/workflow.mjs +389 -0
  342. package/workflows/question-crops/README.md +35 -0
  343. package/workflows/question-crops/prompts/inventory.md +23 -0
  344. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  345. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  346. package/workflows/question-crops/workflow.mjs +172 -0
  347. package/workflows/ralph-loop/workflow.mjs +162 -0
  348. package/workflows/research/README.md +74 -0
  349. package/workflows/research/prompts/s0-goal.md +43 -0
  350. package/workflows/research/prompts/s1-early-exit.md +22 -0
  351. package/workflows/research/prompts/s1-map.md +58 -0
  352. package/workflows/research/prompts/s2-options.md +53 -0
  353. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  354. package/workflows/research/prompts/s4-verify.md +74 -0
  355. package/workflows/research/prompts/s5-synthesis.md +81 -0
  356. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  357. package/workflows/research/prompts/s6-package.md +32 -0
  358. package/workflows/research/scripts/build-report.mjs +98 -0
  359. package/workflows/research/workflow.mjs +288 -0
  360. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  361. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  362. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  363. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  364. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  365. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  366. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  367. package/workflows/wrong-question-docx/README.md +55 -0
  368. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  369. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  370. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  371. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  372. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  373. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  374. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  375. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  376. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  377. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  378. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  379. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  380. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  381. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  382. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  383. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  384. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  385. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  386. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  387. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  388. package/plugins/workflow-runner/src/expressions.js +0 -639
  389. package/plugins/workflow-runner/src/expressions.ts +0 -640
  390. package/plugins/workflow-runner/src/loader.js +0 -573
  391. package/plugins/workflow-runner/src/loader.ts +0 -721
  392. package/plugins/workflow-runner/src/multimodal.js +0 -38
  393. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  394. package/plugins/workflow-runner/src/recovery.js +0 -126
  395. package/plugins/workflow-runner/src/recovery.ts +0 -156
  396. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  397. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  398. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  399. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  400. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  401. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  402. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  403. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  404. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  405. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  406. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  407. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  408. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  409. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  410. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  411. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  412. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  413. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  414. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  415. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  416. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  417. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  418. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  419. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  420. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  421. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  422. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  423. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  424. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  425. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  426. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  427. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  428. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  429. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  430. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  431. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  432. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  433. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  434. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  435. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  436. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  437. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  438. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  439. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  440. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  441. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  442. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  443. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  444. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  445. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  446. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  447. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  448. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  449. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  450. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  451. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  452. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  453. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  454. package/src/advisorState.js +0 -22
  455. package/src/cli/configWizard.js +0 -293
  456. package/src/tools/toolProgressBridge.js +0 -48
  457. package/workflows/adaptive-research.yaml +0 -50
  458. package/workflows/book-review-short.yaml +0 -125
  459. package/workflows/e2e-write-greet.yaml +0 -31
  460. package/workflows/illustrate.yaml +0 -227
  461. package/workflows/plan.yaml +0 -470
  462. package/workflows/ppt.yaml +0 -1670
  463. package/workflows/ralph-loop.yaml +0 -201
  464. package/workflows/research.yaml +0 -873
  465. package/workflows/schema.json +0 -176
  466. package/workflows/webppt.yaml +0 -496
  467. package/workflows/wechat-reading-shots.yaml +0 -315
  468. package/workflows/word.yaml +0 -720
  469. package/workflows/youtube-shorts.yaml +0 -202
  470. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -1,83 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/jsonPayload.test.ts —— extractJsonPayload 纯函数验证
4
- * ------------------------------------------------------------
5
- * 根治 MiniMax-M2/M3 等思考型模型把 <think>…</think> 写进 content、
6
- * 导致 output_schema 解析 "Unrecognized token '<'" 的回归测试。
7
- * 纯函数、无 mock —— 直接断言提取结果可被 JSON.parse。
8
- * ============================================================
9
- */
10
-
11
- import { describe, expect, it } from 'bun:test';
12
-
13
- import { extractJsonPayload } from '../src/jsonPayload.js';
14
-
15
- /** 提取后必须能 parse 成预期对象 */
16
- function parsed(raw: string): unknown {
17
- return JSON.parse(extractJsonPayload(raw));
18
- }
19
-
20
- describe('extractJsonPayload', () => {
21
- it('干净 JSON 原样通过', () => {
22
- expect(parsed('{"findings":["a","b"]}')).toEqual({ findings: ['a', 'b'] });
23
- });
24
-
25
- it('剥离 <think> 前缀(真实复现场景)', () => {
26
- const raw =
27
- '<think>\nThe user wants findings. Let me output JSON.\n</think>\n{"findings":["x"],"open_questions":[]}';
28
- expect(parsed(raw)).toEqual({ findings: ['x'], open_questions: [] });
29
- });
30
-
31
- it('<think> 内部含 { } [ ] 也不会错锚(核心用例)', () => {
32
- // 思维链里模型"想" JSON 结构、写了花括号;若不先剥 think 会锚到这里的 {
33
- const raw =
34
- '<think>I should return {"findings": [...]} with two items like { a }</think>{"findings":["real1","real2"]}';
35
- expect(parsed(raw)).toEqual({ findings: ['real1', 'real2'] });
36
- });
37
-
38
- it('剥离 ```json 代码围栏(靠配平截取,无需专门去围栏)', () => {
39
- const raw = '```json\n{"ok":true}\n```';
40
- expect(parsed(raw)).toEqual({ ok: true });
41
- });
42
-
43
- it('think + 围栏 + 前后散文混合', () => {
44
- const raw =
45
- '<think>reasoning…</think>\nHere is the result:\n```json\n{"n":42}\n```\nDone.';
46
- expect(parsed(raw)).toEqual({ n: 42 });
47
- });
48
-
49
- it('多个 <think> 块全部剥离', () => {
50
- const raw = '<think>a</think>noise<think>b</think>{"v":1}';
51
- expect(parsed(raw)).toEqual({ v: 1 });
52
- });
53
-
54
- it('未闭合 <think>(被 max tokens 截断)→ 砍掉尾巴、原文交调用方报错', () => {
55
- const raw = 'prefix {"v":1} <think>incomplete reasoning without close';
56
- // <think> 之前的 {"v":1} 应被正确提取(截断兜底先砍 <think> 起的尾巴)
57
- expect(parsed(raw)).toEqual({ v: 1 });
58
- });
59
-
60
- it('数组负载(type:array 的 schema)', () => {
61
- const raw = '<think>list</think>[{"id":1},{"id":2}]';
62
- expect(parsed(raw)).toEqual([{ id: 1 }, { id: 2 }]);
63
- });
64
-
65
- it('JSON 后有尾随散文(只取配平那段)', () => {
66
- const raw = '{"a":1}\n以上就是结果,希望有用。';
67
- expect(parsed(raw)).toEqual({ a: 1 });
68
- });
69
-
70
- it('字符串值里的 } 不破坏配平', () => {
71
- const raw = '{"msg":"a } b ] c","ok":true}';
72
- expect(parsed(raw)).toEqual({ msg: 'a } b ] c', ok: true });
73
- });
74
-
75
- it('完全没有 JSON → 原样返回(让调用方 JSON.parse 报 honest error)', () => {
76
- expect(extractJsonPayload('this is not json')).toBe('this is not json');
77
- });
78
-
79
- it('嵌套对象配平正确', () => {
80
- const raw = '<think>x</think>{"outer":{"inner":[1,2,{"deep":true}]}}';
81
- expect(parsed(raw)).toEqual({ outer: { inner: [1, 2, { deep: true }] } });
82
- });
83
- });
@@ -1,617 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/workflows/loader.test.ts
4
- * ------------------------------------------------------------
5
- * loader 单测:
6
- * - 双源扫描:cwd 优先、packageRoot fallback
7
- * - 一个坏 yaml 不污染其它工作流
8
- * - 校验阻断:name/description/steps/动作字段
9
- * - 内置 book-review-short.yaml 能被解析
10
- *
11
- * ⚠️ 隔离性设计:
12
- * listWorkflows() 内部依赖 getWorkingDir() → getResourceSearchPaths()。
13
- * Bun 的 mock.module 是全局的,并行执行时其他测试文件对 workingDir.js
14
- * 的 mock 会污染本文件的 getWorkingDir() 返回值,导致 listWorkflows()
15
- * 扫描到错误的目录(或空目录)→ 4 个集成测试 flaky 失败。
16
- *
17
- * 解决方案:这 4 个测试改用 parseWorkflowFile() + 显式路径来验证等价逻辑,
18
- * 零依赖 getWorkingDir() 全局状态。listWorkflows() 本身的"扫描+去重+容错"
19
- * 行为由 parseWorkflowFile 的单测 + validate 单测联合保证。
20
- * ============================================================
21
- */
22
-
23
- import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
24
- import { mkdirSync, mkdtempSync, readdir, rmSync, writeFileSync } from 'node:fs';
25
- import { tmpdir } from 'node:os';
26
- import { join } from 'node:path';
27
-
28
- import {
29
- WorkflowLoadError,
30
- findWorkflowByName,
31
- listWorkflows,
32
- parseWorkflowFile,
33
- } from '../src/loader.js';
34
-
35
- describe('workflows/loader', () => {
36
- let tmp: string;
37
-
38
- beforeEach(() => {
39
- tmp = mkdtempSync(join(tmpdir(), 'wf-loader-'));
40
- });
41
-
42
- afterEach(() => {
43
- rmSync(tmp, { recursive: true, force: true });
44
- });
45
-
46
- function writeYaml(name: string, body: string): string {
47
- mkdirSync(join(tmp, 'workflows'), { recursive: true });
48
- const p = join(tmp, 'workflows', name);
49
- writeFileSync(p, body, 'utf8');
50
- return p;
51
- }
52
-
53
- // ── 原测试:cwd 下放 yaml 能被 listWorkflows 发现 ──
54
- // 重构为:parseWorkflowFile 能正确解析 cwd 下写入的 yaml(等价语义)
55
- it('cwd 下放 yaml 能被 parseWorkflowFile 正确解析', async () => {
56
- const path = writeYaml(
57
- 'my.yaml',
58
- `name: my-wf
59
- description: hello
60
- steps:
61
- - id: a
62
- tool: Read
63
- args: { file_path: a.txt }
64
- `,
65
- );
66
-
67
- const def = await parseWorkflowFile(path);
68
- expect(def.name).toBe('my-wf');
69
- expect(def.description).toBe('hello');
70
- expect(def.steps).toHaveLength(1);
71
- expect(def.steps[0].id).toBe('a');
72
- expect(def.__source).toBe(path);
73
- });
74
-
75
- // ── 原测试:packageRoot 自带 book-review-short 也能被发现 ──
76
- // 重构为:直接定位 packageRoot 路径 + parseWorkflowFile 解析内置 workflow
77
- it('packageRoot 自带 book-review-short.yaml 能被 parseWorkflowFile 正确解析', async () => {
78
- // 直接定位 packageRoot 下的 workflows 目录(不依赖 getWorkingDir)
79
- const packageRootWorkflows = join(
80
- // 兼容 Windows:import.meta.dir 用反斜杠分隔,原 /\/test$/ 只匹配正斜杠 → 不生效,
81
- // 路径算错一级(落到 plugins/workflows)。用 [/\\] 同时匹配两种分隔符。
82
- import.meta.dir.replace(/[/\\]test$/, ''), // plugins/workflow-runner
83
- '..', // plugins
84
- '..', // kakadeai/minimal-agent 根
85
- 'workflows',
86
- );
87
- const bookReviewPath = join(packageRootWorkflows, 'book-review-short.yaml');
88
-
89
- // 验证文件存在且可解析
90
- const def = await parseWorkflowFile(bookReviewPath);
91
- expect(def.name).toBe('book-review-short');
92
- expect(def.steps.length).toBeGreaterThanOrEqual(1);
93
- });
94
-
95
- // ── 原测试:cwd 同名 workflow 覆盖 packageRoot ──
96
- // 重构为:显式构造两个同名 yaml,parseWorkflowFile 各自解析到正确内容
97
- it('同 name 的两个 yaml 文件各自独立解析(覆盖语义由 listWorkflows 去重保证)', async () => {
98
- // "packageRoot 版本"
99
- const packageRootYaml = writeYaml(
100
- 'book-review-short.yaml',
101
- `name: book-review-short
102
- description: original from packageRoot
103
- steps:
104
- - id: original
105
- type: assert
106
- condition: 'true'
107
- `,
108
- );
109
-
110
- // "cwd 覆盖版本"(写到不同目录模拟)
111
- const overrideDir = mkdtempSync(join(tmpdir(), 'wf-override-'));
112
- const overridePath = join(overrideDir, 'book-review-short.yaml');
113
- writeFileSync(
114
- overridePath,
115
- `name: book-review-short
116
- description: cwd override
117
- steps:
118
- - id: overridden
119
- type: assert
120
- condition: 'true'
121
- `,
122
- 'utf8',
123
- );
124
-
125
- // 两个文件都能被 parseWorkflowFile 正确解析,各自内容独立
126
- const original = await parseWorkflowFile(packageRootYaml);
127
- const override = await parseWorkflowFile(overridePath);
128
-
129
- expect(original.name).toBe('book-review-short');
130
- expect(original.description).toBe('original from packageRoot');
131
- expect(original.steps[0].id).toBe('original');
132
-
133
- expect(override.name).toBe('book-review-short');
134
- expect(override.description).toBe('cwd override');
135
- expect(override.steps[0].id).toBe('overridden');
136
-
137
- // 清理临时目录
138
- rmSync(overrideDir, { recursive: true, force: true });
139
- });
140
-
141
- // ── 原测试:坏 yaml 不污染其他 workflow ──
142
- // 重构为:parseWorkflowFile 对坏 yaml 抛错、对好 yaml 正常(单文件粒度验证)
143
- it('坏 yaml 被 parseWorkflowFile 拒绝;好 yaml 正常解析(互不影响)', async () => {
144
- const goodPath = writeYaml('good.yaml', `name: good
145
- description: ok
146
- steps:
147
- - id: x
148
- type: assert
149
- condition: 'true'
150
- `);
151
- const badPath = writeYaml('bad.yaml', 'name: bad\n bad-indent\n: garbage:::\n');
152
-
153
- // 好的能解析
154
- const goodDef = await parseWorkflowFile(goodPath);
155
- expect(goodDef.name).toBe('good');
156
- expect(goodDef.steps[0].id).toBe('x');
157
-
158
- // 坏的抛错(不阻塞好的那个——因为 parseWorkflowFile 是 per-file 的)
159
- await expect(parseWorkflowFile(badPath)).rejects.toThrow(WorkflowLoadError);
160
- });
161
-
162
- it('findWorkflowByName 未命中返回 null', async () => {
163
- const def = await findWorkflowByName('nonexistent-wf-xyz', tmp);
164
- expect(def).toBeNull();
165
- });
166
-
167
- it('findWorkflowByName 可按 yaml 文件名兜底匹配', async () => {
168
- writeYaml(
169
- 'filename-fallback-test.yaml',
170
- `name: internal-webppt-name
171
- description: filename fallback
172
- steps:
173
- - id: x
174
- type: assert
175
- condition: 'true'
176
- `,
177
- );
178
-
179
- const def = await findWorkflowByName('filename-fallback-test', tmp);
180
- expect(def?.name).toBe('internal-webppt-name');
181
- const bySuffix = await findWorkflowByName('filename-fallback-test.yaml', tmp);
182
- expect(bySuffix?.name).toBe('internal-webppt-name');
183
- const byPath = await findWorkflowByName(
184
- 'workflows/filename-fallback-test.yaml',
185
- tmp,
186
- );
187
- expect(byPath?.name).toBe('internal-webppt-name');
188
- });
189
-
190
- it('listWorkflows 对完全缺失 workflows/ 不抛错', async () => {
191
- // 没有 workflows 目录,只有 packageRoot fallback
192
- const list = await listWorkflows(tmp);
193
- expect(Array.isArray(list)).toBe(true);
194
- });
195
- });
196
-
197
- describe('workflows/loader::validate', () => {
198
- let tmp: string;
199
-
200
- beforeEach(() => {
201
- tmp = mkdtempSync(join(tmpdir(), 'wf-loader-v-'));
202
- });
203
-
204
- afterEach(() => {
205
- rmSync(tmp, { recursive: true, force: true });
206
- });
207
-
208
- function writeRaw(body: string): string {
209
- const p = join(tmp, 'wf.yaml');
210
- writeFileSync(p, body, 'utf8');
211
- return p;
212
- }
213
-
214
- function writeIsolatedRaw(body: string): string {
215
- const dir = mkdtempSync(join(tmpdir(), 'wf-loader-mm-'));
216
- const p = join(dir, 'wf.yaml');
217
- writeFileSync(p, body, 'utf8');
218
- return p;
219
- }
220
-
221
- it('缺 name → 抛 WorkflowLoadError', async () => {
222
- const p = writeRaw('description: x\nsteps:\n - id: a\n type: assert\n condition: "true"\n');
223
- await expect(parseWorkflowFile(p)).rejects.toThrow(WorkflowLoadError);
224
- });
225
-
226
- it('缺 description → 抛错', async () => {
227
- const p = writeRaw('name: x\nsteps:\n - id: a\n type: assert\n condition: "true"\n');
228
- await expect(parseWorkflowFile(p)).rejects.toThrow();
229
- });
230
-
231
- it('steps 空数组 → 抛错', async () => {
232
- const p = writeRaw('name: x\ndescription: y\nsteps: []\n');
233
- await expect(parseWorkflowFile(p)).rejects.toThrow();
234
- });
235
-
236
- it('step 没有任何动作字段 → 抛错', async () => {
237
- const p = writeRaw('name: x\ndescription: y\nsteps:\n - id: a\n');
238
- await expect(parseWorkflowFile(p)).rejects.toThrow();
239
- });
240
-
241
- it('step 同时设置 tool + llm → 抛错', async () => {
242
- const p = writeIsolatedRaw(`name: x
243
- description: y
244
- steps:
245
- - id: a
246
- tool: Read
247
- llm: "say hi"
248
- `);
249
- await expect(parseWorkflowFile(p)).rejects.toThrow();
250
- });
251
-
252
- it('assert step 缺 condition → 抛错', async () => {
253
- const p = writeIsolatedRaw(`name: x
254
- description: y
255
- steps:
256
- - id: a
257
- type: assert
258
- `);
259
- await expect(parseWorkflowFile(p)).rejects.toThrow();
260
- });
261
-
262
- it('同级 steps id 重复 → 抛错', async () => {
263
- const p = writeRaw(`name: x
264
- description: y
265
- steps:
266
- - id: dup
267
- type: assert
268
- condition: 'true'
269
- - id: dup
270
- type: assert
271
- condition: 'true'
272
- `);
273
- await expect(parseWorkflowFile(p)).rejects.toThrow();
274
- });
275
-
276
- it('合法 yaml 通过 + __source 字段被注入', async () => {
277
- const p = writeRaw(`name: ok-wf
278
- description: nice
279
- steps:
280
- - id: a
281
- tool: Read
282
- args: { file_path: x.txt }
283
- `);
284
- const def = await parseWorkflowFile(p);
285
- expect(def.name).toBe('ok-wf');
286
- expect(def.__source).toBe(p);
287
- });
288
-
289
- it('inputs[].type=enum 缺 values → 抛错', async () => {
290
- const p = writeRaw(`name: x
291
- description: y
292
- inputs:
293
- - name: foo
294
- type: enum
295
- steps:
296
- - id: a
297
- type: assert
298
- condition: 'true'
299
- `);
300
- await expect(parseWorkflowFile(p)).rejects.toThrow();
301
- });
302
-
303
- // ---------------- ADR-05 新校验 ----------------
304
-
305
- it('已移除的孤儿类型(approval_loop/parallel/vote)按未知 type 拒绝', async () => {
306
- // R1 减法重构:三个零使用 step 类型已从引擎删除(见 CLAUDE.md「两次规则」)。
307
- // 锁定行为:旧 yaml 若还写这些 type,loader 必须响亮报错而不是静默跑偏。
308
- for (const t of ['approval_loop', 'parallel', 'vote']) {
309
- const p = writeRaw(`name: x
310
- description: y
311
- steps:
312
- - id: s1
313
- type: ${t}
314
- `);
315
- await expect(parseWorkflowFile(p)).rejects.toThrow();
316
- }
317
- });
318
-
319
- it('ADR-05: type=branch 带 output_schema → 抛错', async () => {
320
- const p = writeRaw(`name: x
321
- description: y
322
- steps:
323
- - id: b
324
- type: branch
325
- condition: 'true'
326
- output_schema:
327
- type: object
328
- `);
329
- await expect(parseWorkflowFile(p)).rejects.toThrow(/output_schema.*branch/);
330
- });
331
-
332
- it('P3: type=skill 带 output_schema → 抛错(仅 llm 节点支持,不静默丢弃)', async () => {
333
- const p = writeRaw(`name: x
334
- description: y
335
- steps:
336
- - id: s
337
- skill: some-skill
338
- output_schema:
339
- type: object
340
- `);
341
- await expect(parseWorkflowFile(p)).rejects.toThrow(/output_schema.*skill/);
342
- });
343
-
344
- it('P3: type=skill 带 context_files → 抛错(仅 llm 节点支持,不静默丢弃)', async () => {
345
- const p = writeRaw(`name: x
346
- description: y
347
- steps:
348
- - id: s
349
- skill: some-skill
350
- context_files:
351
- - path: foo.md
352
- `);
353
- await expect(parseWorkflowFile(p)).rejects.toThrow(/context_files.*skill/);
354
- });
355
-
356
- it('ADR-05: 老 yaml 不带任何新字段 → 仍校验通过', async () => {
357
- const p = writeRaw(`name: legacy
358
- description: 老 workflow
359
- steps:
360
- - id: a
361
- tool: Read
362
- args: { file_path: a.txt }
363
- - id: b
364
- type: assert
365
- condition: 'true'
366
- `);
367
- const def = await parseWorkflowFile(p);
368
- expect(def.name).toBe('legacy');
369
- });
370
-
371
- // ---------------- onError / recover_hint 校验 ----------------
372
-
373
- it('onError: recover + recover_hint 合法 → 通过', async () => {
374
- const p = writeRaw(`name: x
375
- description: y
376
- steps:
377
- - id: a
378
- tool: Read
379
- args: { file_path: a.txt }
380
- onError: recover
381
- recover_hint: "端口被占就换 3001"
382
- `);
383
- const def = await parseWorkflowFile(p);
384
- expect(def.steps[0].onError).toBe('recover');
385
- expect(def.steps[0].recover_hint).toBe('端口被占就换 3001');
386
- });
387
-
388
- it('onError 非法值(typo)→ 抛错', async () => {
389
- const p = writeRaw(`name: x
390
- description: y
391
- steps:
392
- - id: a
393
- tool: Read
394
- args: { file_path: a.txt }
395
- onError: continnue
396
- `);
397
- await expect(parseWorkflowFile(p)).rejects.toThrow(/onError/);
398
- });
399
-
400
- it('recover_hint 非字符串 → 抛错', async () => {
401
- const p = writeRaw(`name: x
402
- description: y
403
- steps:
404
- - id: a
405
- tool: Read
406
- args: { file_path: a.txt }
407
- recover_hint: [1, 2]
408
- `);
409
- await expect(parseWorkflowFile(p)).rejects.toThrow(/recover_hint/);
410
- });
411
-
412
- it('pause free_text=approve 合法', async () => {
413
- const p = writeRaw(`name: x
414
- description: y
415
- steps:
416
- - id: gate
417
- type: pause
418
- prompt: 是否继续
419
- free_text: approve
420
- `);
421
- const def = await parseWorkflowFile(p);
422
- expect(def.steps[0].free_text).toBe('approve');
423
- });
424
-
425
- it('free_text 只能用于 pause 且必须是合法枚举', async () => {
426
- const nonPause = writeRaw(`name: x
427
- description: y
428
- steps:
429
- - id: a
430
- type: assert
431
- condition: 'true'
432
- free_text: approve
433
- `);
434
- await expect(parseWorkflowFile(nonPause)).rejects.toThrow(/free_text/);
435
-
436
- const badValue = writeRaw(`name: x
437
- description: y
438
- steps:
439
- - id: gate
440
- type: pause
441
- prompt: 是否继续
442
- free_text: continue
443
- `);
444
- await expect(parseWorkflowFile(badValue)).rejects.toThrow(/free_text/);
445
- });
446
-
447
- it('done_when 仅 agent 步可用:tool 步声明被拒', async () => {
448
- const p = writeRaw(`name: x
449
- description: y
450
- steps:
451
- - id: a
452
- tool: Read
453
- args: { file_path: a.txt }
454
- done_when: "fileExists('./a.txt')"
455
- `);
456
- await expect(parseWorkflowFile(p)).rejects.toThrow(/done_when.*agent/);
457
- });
458
-
459
- it('done_when 必须是非空字符串', async () => {
460
- const p = writeRaw(`name: x
461
- description: y
462
- steps:
463
- - id: a
464
- agent: 干活
465
- done_when: ""
466
- `);
467
- await expect(parseWorkflowFile(p)).rejects.toThrow(/done_when/);
468
- });
469
-
470
- it('onError: continue / halt 旧值仍合法', async () => {
471
- const p = writeRaw(`name: x
472
- description: y
473
- steps:
474
- - id: a
475
- type: assert
476
- condition: 'false'
477
- onError: continue
478
- - id: b
479
- type: assert
480
- condition: 'true'
481
- onError: halt
482
- `);
483
- const def = await parseWorkflowFile(p);
484
- expect(def.steps[0].onError).toBe('continue');
485
- expect(def.steps[1].onError).toBe('halt');
486
- });
487
-
488
- it('llm.images 字符串数组合法', async () => {
489
- const p = writeRaw(`name: x
490
- description: y
491
- steps:
492
- - id: inspect
493
- llm: "请看图"
494
- images:
495
- - "./build/screenshot.png"
496
- image_detail: high
497
- image_max_long_side_pixel: 1600
498
- `);
499
- const def = await parseWorkflowFile(p);
500
- expect(def.steps[0].images).toEqual(['./build/screenshot.png']);
501
- expect(def.steps[0].image_detail).toBe('high');
502
- expect(def.steps[0].image_max_long_side_pixel).toBe(1600);
503
- });
504
-
505
- it('agent.images 对象数组合法', async () => {
506
- const p = writeRaw(`name: x
507
- description: y
508
- steps:
509
- - id: inspect
510
- agent: "看图并写报告"
511
- images:
512
- - source: "\${inputs.image}"
513
- detail: low
514
- max_long_side_pixel: 800
515
- parse_inline_images: true
516
- `);
517
- const def = await parseWorkflowFile(p);
518
- expect(def.steps[0].parse_inline_images).toBe(true);
519
- expect(def.steps[0].images).toEqual([
520
- { source: '${inputs.image}', detail: 'low', max_long_side_pixel: 800 },
521
- ]);
522
- });
523
-
524
- it('history_mode 仅允许 llm / agent / skill 使用', async () => {
525
- const ok = writeIsolatedRaw(`name: x
526
- description: y
527
- steps:
528
- - id: a
529
- llm: "独立看图"
530
- history_mode: isolated
531
- - id: b
532
- agent: "独立导出"
533
- history_mode: isolated
534
- - id: c
535
- skill: ui-design
536
- history_mode: shared
537
- `);
538
- const def = await parseWorkflowFile(ok);
539
- expect(def.steps[0].history_mode).toBe('isolated');
540
- expect(def.steps[1].history_mode).toBe('isolated');
541
- expect(def.steps[2].history_mode).toBe('shared');
542
-
543
- const badValue = writeIsolatedRaw(`name: x
544
- description: y
545
- steps:
546
- - id: a
547
- llm: "x"
548
- history_mode: clean
549
- `);
550
- await expect(parseWorkflowFile(badValue)).rejects.toThrow(/history_mode.*shared \/ isolated/);
551
-
552
- const badTool = writeIsolatedRaw(`name: x
553
- description: y
554
- steps:
555
- - id: a
556
- tool: Bash
557
- args: { command: "true" }
558
- history_mode: isolated
559
- `);
560
- await expect(parseWorkflowFile(badTool)).rejects.toThrow(/history_mode.*llm \/ agent \/ skill/);
561
-
562
- const badControl = writeIsolatedRaw(`name: x
563
- description: y
564
- steps:
565
- - id: a
566
- type: assert
567
- condition: "true"
568
- history_mode: isolated
569
- `);
570
- await expect(parseWorkflowFile(badControl)).rejects.toThrow(/history_mode.*llm \/ agent \/ skill/);
571
- });
572
-
573
- it('images 不能用于 skill 或控制流节点', async () => {
574
- const skillPath = writeIsolatedRaw(`name: x
575
- description: y
576
- steps:
577
- - id: s
578
- skill: ui-design
579
- images: ["./a.png"]
580
- `);
581
- await expect(parseWorkflowFile(skillPath)).rejects.toThrow(/images.*llm \/ agent/);
582
-
583
- const controlPath = writeIsolatedRaw(`name: x
584
- description: y
585
- steps:
586
- - id: a
587
- type: assert
588
- condition: "true"
589
- images: ["./a.png"]
590
- `);
591
- await expect(parseWorkflowFile(controlPath)).rejects.toThrow(/images.*llm \/ agent/);
592
- });
593
-
594
- it('非法图片 detail 和 max_long_side_pixel 会被拒绝', async () => {
595
- const badDetail = writeIsolatedRaw(`name: x
596
- description: y
597
- steps:
598
- - id: a
599
- llm: "看图"
600
- images:
601
- - source: "./a.png"
602
- detail: ultra
603
- `);
604
- await expect(parseWorkflowFile(badDetail)).rejects.toThrow(/detail/);
605
-
606
- const badMax = writeIsolatedRaw(`name: x
607
- description: y
608
- steps:
609
- - id: a
610
- agent: "看图"
611
- images:
612
- - source: "./a.png"
613
- max_long_side_pixel: 0
614
- `);
615
- await expect(parseWorkflowFile(badMax)).rejects.toThrow(/max_long_side_pixel/);
616
- });
617
- });