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,126 +0,0 @@
1
- /**
2
- * ============================================================
3
- * plugins/workflow-runner/test/foundation.test.ts
4
- * ------------------------------------------------------------
5
- * 锁定 workflow-runner 的两条【地基保证】——yaml 作者不用每步重写:
6
- * B1 目标锚定:引擎在每个 agent/llm/skill 步前自动注入"用户原始目标"
7
- * (buildGoalAnchor → ctx.goalAnchor),即使 yaml 的步 prompt 没手写 ${goal}。
8
- * B2 系统提示(含技能清单)跨 fresh_context 存活:新版 plan.yaml 把 6 阶段套进
9
- * fresh_context while-loop,每轮重置 history——必须保证重置到的是"含技能的入口
10
- * 快照",否则重来轮的步就看不到 skills,正是上次 pptx 翻车的同类病根。
11
- *
12
- * 方法:DI 注入 ctx.chat(真实 runWorkflow/runQuery 跑起来,仅替换最底层 chat),
13
- * 抓每次 chat 调用的完整 messages 快照,断言每轮迭代里 system[0](技能标记)与
14
- * 步 prompt(目标原文)都在。禁用 mock.module(全局泄漏),用 env+reset 隔离 cwd。
15
- * ============================================================
16
- */
17
-
18
- import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
19
- import { mkdtempSync, rmSync } from 'node:fs';
20
- import { tmpdir } from 'node:os';
21
- import { join } from 'node:path';
22
-
23
- import { _resetWorkingDir } from '../../../src/bootstrap/workingDir.js';
24
- import { ALL_TOOLS } from '../../../src/tools/index.js';
25
- import type { LoopEvent, Message, Provider } from '../../../src/types.js';
26
- import { runWorkflow } from '../src/runner.js';
27
- import type { RunContext, WorkflowDef, WorkflowEvent } from '../src/types.js';
28
-
29
- type WfOrLoop = WorkflowEvent | LoopEvent;
30
-
31
- const fakeProvider: Provider = {
32
- name: 'test',
33
- baseURL: '',
34
- apiKey: '',
35
- model: 'm',
36
- contextWindow: 128000,
37
- };
38
-
39
- async function collect(
40
- gen: AsyncGenerator<WfOrLoop, void, void>,
41
- ): Promise<WfOrLoop[]> {
42
- const out: WfOrLoop[] = [];
43
- for await (const ev of gen) out.push(ev);
44
- return out;
45
- }
46
-
47
- describe('workflow-runner 地基保证:目标锚定 + 技能清单跨 fresh_context 存活', () => {
48
- let tmp: string;
49
- let ctx: RunContext;
50
-
51
- beforeEach(() => {
52
- tmp = mkdtempSync(join(tmpdir(), 'wf-found-'));
53
- process.env.MINIMAL_AGENT_CWD = tmp;
54
- _resetWorkingDir();
55
- // 预置一个"含技能清单标记"的系统提示——模拟 refreshWorkflowSystemPrompt 注入后的
56
- // history[0](真注入由 pluginRunner.isolation.test.ts 单独锁定,这里只测"重置后仍在")。
57
- ctx = {
58
- provider: fakeProvider,
59
- history: [
60
- {
61
- role: 'system',
62
- content: '系统提示\n\n## pptx\n- **功能**: 生成 PPT\n- **技能目录**: `skills/pptx`',
63
- },
64
- ],
65
- cwd: tmp,
66
- tools: ALL_TOOLS,
67
- };
68
- });
69
-
70
- afterEach(() => {
71
- delete process.env.MINIMAL_AGENT_CWD;
72
- _resetWorkingDir();
73
- rmSync(tmp, { recursive: true, force: true });
74
- });
75
-
76
- it('fresh_context while-loop 每轮:技能清单仍在 system[0],原始目标经锚定仍在步 prompt(步未手写 goal)', async () => {
77
- const GOAL = '实现哨兵目标_SENTINEL_XYZ';
78
-
79
- // 步 prompt 故意【不】提目标——这样若目标仍出现在消息里,必是 goalAnchor 注入的(B1)。
80
- const def: WorkflowDef = {
81
- name: 'foundcheck',
82
- description: '地基回归',
83
- inputs: [{ name: 'goal', type: 'string', required: true }],
84
- self_heal: { retry_delay_ms: 0 },
85
- steps: [
86
- {
87
- type: 'loop',
88
- id: 'lp',
89
- max_iterations: 2,
90
- fresh_context: true,
91
- as: '_iter',
92
- do: [{ id: 'only_step', llm: '请只输出 OK,不要解释。', max_retries: 0 }],
93
- },
94
- ],
95
- };
96
-
97
- const snapshots: Array<Array<{ role: string; content: string }>> = [];
98
- ctx.chat = async function* (args: { messages: Message[] }) {
99
- // messages 是 runQuery 原地 mutate 的共享引用,必须当场快照成文本
100
- snapshots.push(
101
- args.messages.map((m) => ({ role: m.role, content: String(m.content ?? '') })),
102
- );
103
- yield { type: 'text_delta', delta: 'OK' };
104
- yield { type: 'done', stopReason: 'stop' };
105
- };
106
-
107
- const events = await collect(runWorkflow(def, { goal: GOAL }, ctx));
108
-
109
- // 整链正常收尾(达上限 2 退出,非 halt)
110
- expect(events.some((e) => e.type === 'workflow_done')).toBe(true);
111
- expect(
112
- events.some((e) => e.type === 'error' && e.error.includes('Workflow halted')),
113
- ).toBe(false);
114
-
115
- // 2 轮迭代 → 2 次 chat 调用
116
- expect(snapshots.length).toBe(2);
117
- for (const msgs of snapshots) {
118
- // B2:每轮 system[0] 仍含技能清单(fresh_context 重置到的是"含技能的入口快照")
119
- expect(msgs[0].role).toBe('system');
120
- expect(msgs[0].content).toContain('## pptx');
121
- expect(msgs[0].content).toContain('技能目录');
122
- // B1:步 prompt 没手写 ${inputs.goal},但原始目标经 goalAnchor 注入仍在末条消息里
123
- expect(msgs[msgs.length - 1].content).toContain(GOAL);
124
- }
125
- }, 30000);
126
- });
@@ -1,139 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/workflows/graceful.test.ts
4
- * ------------------------------------------------------------
5
- * 降级契约(R1):
6
- * - workflows/ 不存在 → listWorkflows() 返回包内自带 [包内 yaml],绝不抛错
7
- * - 全是坏 yaml → 跳过坏的,列出好的
8
- * - findWorkflowByName 未命中 → 返回 null(让调用方 yield 友好 error)
9
- * - runWorkflowFromCommand 对未知 name → yield error,不污染 history
10
- * - runWorkflowsList 在空列表时 yield 友好提示
11
- * ============================================================
12
- */
13
-
14
- import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
15
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
16
- import { tmpdir } from 'node:os';
17
- import { join } from 'node:path';
18
-
19
- import { _resetWorkingDir } from '../../../src/bootstrap/workingDir.js';
20
- import { listWorkflows } from '../src/loader.js';
21
- import {
22
- runWorkflowFromCommand,
23
- runWorkflowsList,
24
- } from '../src/index.js';
25
- import type { LoopEvent, Provider } from '../../../src/types.js';
26
- import type { WorkflowEvent } from '../src/types.js';
27
-
28
- type WfOrLoop = WorkflowEvent | LoopEvent;
29
-
30
- const fakeProvider: Provider = {
31
- name: 'test',
32
- baseURL: '',
33
- apiKey: '',
34
- model: 'm',
35
- contextWindow: 128000,
36
- };
37
-
38
- async function collect(
39
- gen: AsyncGenerator<WfOrLoop, void, void>,
40
- ): Promise<WfOrLoop[]> {
41
- const out: WfOrLoop[] = [];
42
- for await (const ev of gen) out.push(ev);
43
- return out;
44
- }
45
-
46
- describe('workflows/graceful', () => {
47
- let tmp: string;
48
-
49
- beforeEach(() => {
50
- tmp = mkdtempSync(join(tmpdir(), 'wf-graceful-'));
51
- process.env.MINIMAL_AGENT_CWD = tmp;
52
- _resetWorkingDir();
53
- mock.module('../../../src/bootstrap/workingDir.js', () => ({
54
- getWorkingDir: () => tmp,
55
- initWorkingDir: () => tmp,
56
- _resetWorkingDir: () => {},
57
- }));
58
- });
59
-
60
- afterEach(() => {
61
- delete process.env.MINIMAL_AGENT_CWD;
62
- _resetWorkingDir();
63
- rmSync(tmp, { recursive: true, force: true });
64
- });
65
-
66
- it('cwd 下无 workflows/ 目录 → listWorkflows() 仍返回(packageRoot fallback 也只是空降级,不抛)', async () => {
67
- const list = await listWorkflows();
68
- // 至少应该包含包内自带的 book-review-short
69
- expect(Array.isArray(list)).toBe(true);
70
- });
71
-
72
- it('cwd 下 workflows/ 全空 → 不抛,不增加任何条目', async () => {
73
- mkdirSync(join(tmp, 'workflows'), { recursive: true });
74
- const list = await listWorkflows();
75
- expect(Array.isArray(list)).toBe(true);
76
- });
77
-
78
- it('cwd 下全是坏 yaml → 不抛,只跳过坏的', async () => {
79
- mkdirSync(join(tmp, 'workflows'), { recursive: true });
80
- writeYamlIn(tmp, 'bad1.yaml', 'name: x\n : weird:::\n');
81
- writeYamlIn(tmp, 'bad2.yaml', '@@@@@@\n');
82
- const list = await listWorkflows();
83
- // 不抛错,至少包内自带的仍然可见
84
- expect(Array.isArray(list)).toBe(true);
85
- });
86
-
87
- it('/workflow unknown-name → yield error,无 workflow_start', async () => {
88
- const events = await collect(
89
- runWorkflowFromCommand('definitely-not-a-real-wf-xyz', {
90
- provider: fakeProvider,
91
- history: [],
92
- }),
93
- );
94
- expect(events.some((e) => e.type === 'error')).toBe(true);
95
- expect(events.some((e) => e.type === 'workflow_start')).toBe(false);
96
- });
97
-
98
- it('/workflow(不带 name)→ yield 用法提示 error', async () => {
99
- const events = await collect(
100
- runWorkflowFromCommand('', {
101
- provider: fakeProvider,
102
- history: [],
103
- }),
104
- );
105
- const err = events.find(
106
- (e): e is Extract<LoopEvent, { type: 'error' }> => e.type === 'error',
107
- );
108
- expect(err).toBeDefined();
109
- expect(err!.error).toContain('/workflow');
110
- });
111
-
112
- it('/workflows 列表 yield text 事件 + turn_done', async () => {
113
- const events = await collect(runWorkflowsList());
114
- expect(events.some((e) => e.type === 'text')).toBe(true);
115
- expect(events[events.length - 1].type).toBe('turn_done');
116
- });
117
-
118
- it('缺必填 input → yield error,不进入 runWorkflow', async () => {
119
- // book-review-short 要求 book 必填
120
- const events = await collect(
121
- runWorkflowFromCommand('book-review-short', {
122
- provider: fakeProvider,
123
- history: [],
124
- }),
125
- );
126
- const err = events.find(
127
- (e): e is Extract<LoopEvent, { type: 'error' }> => e.type === 'error',
128
- );
129
- expect(err).toBeDefined();
130
- expect(err!.error).toContain('book');
131
- // 没有 workflow_start
132
- expect(events.some((e) => e.type === 'workflow_start')).toBe(false);
133
- });
134
- });
135
-
136
- function writeYamlIn(root: string, name: string, body: string) {
137
- mkdirSync(join(root, 'workflows'), { recursive: true });
138
- writeFileSync(join(root, 'workflows', name), body, 'utf8');
139
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * test/greedyInputs.load.test.ts
3
- * ------------------------------------------------------------
4
- * 锁定「自然语言首参」工作流的首个 input 标了 greedy:true——这样命令行里
5
- * workflow 名之后的整句(含空格分隔段)会被 join 进首参、不逐位拆映射、不撞
6
- * 后面的 number/enum 类型。根治「打一句话自然语言 → pos2 撞 number/enum 报错
7
- * 或单输入被静默截断」那一类 footgun(ppt 的 `input pages 必须是数字` 即此类)。
8
- *
9
- * 同时校验 loader 红线:greedy 只能标在第 0 个 input(防误标)。
10
- */
11
-
12
- import { describe, expect, it } from 'bun:test';
13
- import { join } from 'node:path';
14
-
15
- import { parseWorkflowFile } from '../src/loader.js';
16
-
17
- const WF_DIR = join(
18
- import.meta.dir.replace(/[/\\]test$/, ''), // plugins/workflow-runner
19
- '..', // plugins
20
- '..', // 仓库根
21
- 'workflows',
22
- );
23
-
24
- // 所有「首参是自然语言 brief」的工作流——都应让首参 greedy 吸收整句。
25
- const GREEDY_FIRST = [
26
- 'webppt',
27
- 'plan',
28
- 'ralph-loop',
29
- 'youtube-shorts',
30
- 'adaptive-research',
31
- 'book-review-short',
32
- ];
33
-
34
- describe('自然语言首参工作流:首个 input 标 greedy', () => {
35
- for (const name of GREEDY_FIRST) {
36
- it(`${name}.yaml 的首个 input greedy===true`, async () => {
37
- const def = await parseWorkflowFile(join(WF_DIR, `${name}.yaml`));
38
- const first = (def.inputs ?? [])[0];
39
- expect(first).toBeDefined();
40
- expect(first?.greedy).toBe(true);
41
- // greedy 只许标在第 0 位(loader 红线)——后续 input 不得再标。
42
- for (const inp of (def.inputs ?? []).slice(1)) {
43
- expect(inp.greedy).not.toBe(true);
44
- }
45
- });
46
- }
47
- });
@@ -1,108 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { VALID_HOST_CAPABILITIES } from '../src/loader.js';
3
-
4
- /**
5
- * 宿主能力上下文:从框架 → 插件 → workflow → 工具 的四层透传。
6
- *
7
- * ⚠️ 这条链路此前**断在第一层**:`pluginRunner` 有三处把宿主能力往下传,两条 runQuery
8
- * 路径都带了 browserRun/computerRun,**唯独 `api.runCommand(...)` 那一处漏了**。
9
- * 于是 `PluginContext` 比 `RunQueryOptions` 窄,富插件(workflow-runner)永远拿不到
10
- * 宿主授权 —— 表现是 workflow 里调 ComputerUse 恒返回「当前宿主未启用 Computer Use」,
11
- * 而同一个工具在主循环里好好的。症状完全指不向那个漏掉的字段。
12
- *
13
- * 所以这组测试的第一条守的就是那处遗漏本身。
14
- */
15
-
16
- describe('框架侧:runCommand 必须带上 host', () => {
17
- test('★ 回归守卫:pluginRunner 给富插件传 host', async () => {
18
- const source = await Bun.file(
19
- new URL('../../../src/plugins/pluginRunner.ts', import.meta.url),
20
- ).text();
21
- // 定位 api.runCommand(...) 那次调用,确认 host 在它的参数对象里
22
- const at = source.indexOf('api.runCommand(');
23
- expect(at).toBeGreaterThan(-1);
24
- const call = source.slice(at, at + 900);
25
- expect(call).toContain('host:');
26
- expect(call).toContain('computerRun');
27
- expect(call).toContain('browserRun');
28
- expect(call).toContain('executeTool: options.executeTool');
29
- });
30
-
31
- test('PluginContext 用 Pick<ToolCallContext> 绑定,而不是重新声明', async () => {
32
- // 重新声明会和 ToolCallContext 各自漂移;Pick 保证改一处两处同步。
33
- const source = await Bun.file(
34
- new URL('../../../src/plugins/pluginApi.ts', import.meta.url),
35
- ).text();
36
- expect(source).toMatch(/host\?:\s*Pick<\s*ToolCallContext/);
37
- });
38
- });
39
-
40
- describe('能力常量单一来源', () => {
41
- test('loader 的白名单与 types 的 HostCapability 一致', async () => {
42
- // 两处不一致的表现是:yaml 写了某个能力、loader 放行、运行时却识别不了,
43
- // 或反过来 loader 拦掉一个其实支持的能力。都属于静默错。
44
- const types = await Bun.file(
45
- new URL('../src/types.ts', import.meta.url),
46
- ).text();
47
- const declared =
48
- /export type HostCapability =([^;]+);/.exec(types)?.[1] ?? '';
49
- const fromTypes = [...declared.matchAll(/'([a-z]+)'/g)]
50
- .map((m) => m[1])
51
- .sort();
52
- expect(fromTypes).toEqual([...VALID_HOST_CAPABILITIES].sort());
53
- });
54
- });
55
-
56
- describe('loader 对 uses 的加载期校验', () => {
57
- const load = async (stepYaml: string) => {
58
- const { parseWorkflowFile } = await import('../src/loader.js');
59
- const { mkdtemp, writeFile } = await import('node:fs/promises');
60
- const { join } = await import('node:path');
61
- const { tmpdir } = await import('node:os');
62
- const dir = await mkdtemp(join(tmpdir(), 'wf-uses-'));
63
- const file = join(dir, 't.yaml');
64
- await writeFile(
65
- file,
66
- `name: t\ndescription: d\nversion: "0.1"\nsteps:\n${stepYaml}\n`,
67
- );
68
- return parseWorkflowFile(file);
69
- };
70
-
71
- test('合法声明通过', async () => {
72
- await expect(
73
- load(` - id: a
74
- tool: ComputerUse
75
- uses: [computer]
76
- args: { action: observe }`),
77
- ).resolves.toBeDefined();
78
- });
79
-
80
- test('★ 拼错的能力名在**加载期**就拦掉', async () => {
81
- // 不拦的话:yaml 安静地拿不到能力,而工具报的是「当前宿主未启用 Computer Use」——
82
- // 那句话完全指不向拼错的这一行,作者会去查宿主配置而不是查 yaml。
83
- await expect(
84
- load(` - id: a
85
- tool: ComputerUse
86
- uses: [compute]
87
- args: { action: observe }`),
88
- ).rejects.toThrow(/uses 含非法能力/);
89
- });
90
-
91
- test('uses 必须是数组', async () => {
92
- await expect(
93
- load(` - id: a
94
- tool: ComputerUse
95
- uses: computer
96
- args: { action: observe }`),
97
- ).rejects.toThrow(/必须是数组/);
98
- });
99
-
100
- test('uses 只能用在 tool 步 —— 写在 agent/llm 步上是作者的误解', async () => {
101
- // agent/llm/skill 走 runQuery,工具上下文由主循环提供;在这些步上声明既无效也误导。
102
- await expect(
103
- load(` - id: a
104
- agent: "做点事"
105
- uses: [computer]`),
106
- ).rejects.toThrow(/只能用在 tool 步/);
107
- });
108
- });
@@ -1,183 +0,0 @@
1
- /**
2
- * test/illustrate.load.test.ts
3
- * ------------------------------------------------------------
4
- * 锁定 workflows/illustrate.yaml(网上抓图配图:Google→Bing→Baidu 有序降级 → 下载 →
5
- * 逐图识图打分跳广告 → 选 count 张)的「可解析 + 关键骨架」:
6
- * - name=illustrate;inputs: topic(greedy 首位) + count + min_candidates
7
- * - 纯 YAML:WebBrowser(navigate/eval) 抓 URL + parseJson 成数组 + Download 落盘 + llm images: 打分
8
- * - 有序降级:Bing/Baidu 步 when 受 min_candidates 守门;各家 set 用 asArray(parseJson(...))
9
- * - download/score 两个 loop over asArray(urls);select agent done_when illustrations.json
10
- * - 用到本轮新增的两个通用件:parseJson 表达式 + Download 工具
11
- * - 所有 ${} 表达式可被引擎解析
12
- */
13
-
14
- import { describe, expect, it } from 'bun:test';
15
- import { join } from 'node:path';
16
-
17
- import { interpolate } from '../src/expressions.js';
18
- import { parseWorkflowFile } from '../src/loader.js';
19
- import { VarStack } from '../src/types.js';
20
- import type { StepDef } from '../src/types.js';
21
-
22
- const wfPath = join(
23
- import.meta.dir.replace(/[/\\]test$/, ''),
24
- '..',
25
- '..',
26
- 'workflows',
27
- 'illustrate.yaml',
28
- );
29
-
30
- function allStrings(def: unknown): string[] {
31
- const out: string[] = [];
32
- const walk = (v: unknown): void => {
33
- if (typeof v === 'string') out.push(v);
34
- else if (Array.isArray(v)) for (const x of v) walk(x);
35
- else if (v && typeof v === 'object')
36
- for (const x of Object.values(v as Record<string, unknown>)) walk(x);
37
- };
38
- walk(def);
39
- return out;
40
- }
41
-
42
- describe('workflows/illustrate.yaml(网上抓图配图)', () => {
43
- it('解析通过、name=illustrate、inputs 正确', async () => {
44
- const def = await parseWorkflowFile(wfPath);
45
- expect(def.name).toBe('illustrate');
46
- expect(typeof def.description).toBe('string');
47
-
48
- const inputs = def.inputs ?? [];
49
- const names = inputs.map((i) => i.name);
50
- expect(names).toEqual(expect.arrayContaining(['topic', 'count', 'min_candidates']));
51
- expect(names[0]).toBe('topic');
52
- expect(inputs.find((i) => i.name === 'topic')?.greedy).toBe(true);
53
- expect(inputs.find((i) => i.name === 'count')?.default).toBe(3);
54
- expect(inputs.find((i) => i.name === 'min_candidates')?.default).toBe(6);
55
- expect(def.artifacts).toContain('./build/illustrations.json');
56
- });
57
-
58
- it('关键步齐全且顺序正确:三家图搜 → 守门 → 下载 → 打分 → 选优 → 报告', async () => {
59
- const def = await parseWorkflowFile(wfPath);
60
- const ids = def.steps.map((s) => s.id);
61
- for (const id of [
62
- 'init',
63
- 'g_nav',
64
- 'g_eval',
65
- 'g_set',
66
- 'b_nav',
67
- 'b_eval',
68
- 'b_set',
69
- 'd_nav',
70
- 'd_eval',
71
- 'd_set',
72
- 'assert_candidates',
73
- 'download_loop',
74
- 'score_loop',
75
- 'select',
76
- 'report',
77
- ]) {
78
- expect(ids).toContain(id);
79
- }
80
- expect(ids.indexOf('g_eval')).toBeLessThan(ids.indexOf('b_eval'));
81
- expect(ids.indexOf('b_eval')).toBeLessThan(ids.indexOf('d_eval'));
82
- expect(ids.indexOf('assert_candidates')).toBeLessThan(ids.indexOf('download_loop'));
83
- expect(ids.indexOf('download_loop')).toBeLessThan(ids.indexOf('score_loop'));
84
- expect(ids.indexOf('score_loop')).toBeLessThan(ids.indexOf('select'));
85
- expect(ids.indexOf('select')).toBeLessThan(ids.indexOf('report'));
86
- });
87
-
88
- it('有序降级:Google 首选无 when;Bing/Baidu 受 min_candidates 守门;各家 set 用 asArray(parseJson)', async () => {
89
- const def = await parseWorkflowFile(wfPath);
90
- const byId = (id: string) => def.steps.find((s) => s.id === id);
91
-
92
- expect(byId('g_nav')?.when).toBeUndefined(); // 首选无条件跑
93
- expect(String(byId('b_nav')?.when)).toContain('min_candidates');
94
- expect(String(byId('d_nav')?.when)).toContain('min_candidates');
95
-
96
- for (const sid of ['g_set', 'b_set', 'd_set']) {
97
- const s = byId(sid);
98
- expect(s?.type).toBe('set');
99
- const urlsVal = String((s?.set ?? {}).urls);
100
- expect(urlsVal).toContain('asArray');
101
- expect(urlsVal).toContain('parseJson');
102
- }
103
- expect((byId('g_set')?.set ?? {}).engine_used).toBe('google');
104
- expect((byId('b_set')?.set ?? {}).engine_used).toBe('bing');
105
- expect((byId('d_set')?.set ?? {}).engine_used).toBe('baidu');
106
-
107
- // eval 步用 WebBrowser eval 抽 URL、capture 原始输出
108
- const ge = byId('g_eval');
109
- expect(ge?.tool).toBe('WebBrowser');
110
- expect((ge?.args ?? {}).action).toBe('eval');
111
- expect((ge?.capture ?? {})).toHaveProperty('content', 'g_raw');
112
- expect(ge?.onError).toBe('continue');
113
- });
114
-
115
- it('下载 loop:over asArray(urls)、Download 工具落盘 cand_${u_idx}', async () => {
116
- const def = await parseWorkflowFile(wfPath);
117
- const loop = def.steps.find((s) => s.id === 'download_loop');
118
- expect(loop?.type).toBe('loop');
119
- expect(String(loop?.over)).toContain('asArray');
120
- expect(String(loop?.over)).toContain('urls');
121
- expect(loop?.as).toBe('u');
122
- const dl = ((loop?.do ?? []) as StepDef[]).find((s) => s.id === 'dl_one');
123
- expect(dl?.tool).toBe('Download'); // ← 本轮新增的通用工具
124
- expect(String((dl?.args ?? {}).path)).toContain('${u_idx}');
125
- expect(String((dl?.args ?? {}).url)).toContain('${u}');
126
- expect(dl?.onError).toBe('continue'); // 死链跳过
127
- });
128
-
129
- it('打分 loop:逐图 llm images: + 识广告,写 score 分文件', async () => {
130
- const def = await parseWorkflowFile(wfPath);
131
- const loop = def.steps.find((s) => s.id === 'score_loop');
132
- expect(loop?.type).toBe('loop');
133
- const dos = (loop?.do ?? []) as StepDef[];
134
- const score = dos.find((s) => s.id === 'score_one');
135
- expect(Array.isArray(score?.images)).toBe(true);
136
- expect(String((score?.images ?? []).join(','))).toContain('${u_idx}');
137
- expect(score?.image_detail).toBe('high');
138
- const llm = String(score?.llm);
139
- expect(llm).toContain('is_ad'); // 识别广告
140
- expect(llm).toContain('relevance');
141
- const write = dos.find((s) => s.id === 'write_score');
142
- expect(write?.tool).toBe('Write');
143
- expect(String((write?.args ?? {}).content)).toContain('score_text');
144
- });
145
-
146
- it('选优 select:剔广告排序取 count,agent 确定性落盘 illustrations.json', async () => {
147
- const def = await parseWorkflowFile(wfPath);
148
- const sel = def.steps.find((s) => s.id === 'select');
149
- const a = String(sel?.agent);
150
- expect(a).toContain('is_ad'); // 剔除广告
151
- expect(a).toContain('relevance'); // 排序依据
152
- expect(a).toContain('illustrations.json');
153
- expect(String(sel?.done_when)).toContain('illustrations.json');
154
- for (const t of ['Glob', 'Read', 'Write']) expect(sel?.allowed_tools).toContain(t);
155
- expect(sel?.artifacts).toContain('./build/illustrations.json');
156
- });
157
-
158
- it('用到本轮新增通用件:parseJson 表达式 + Download 工具', async () => {
159
- const def = await parseWorkflowFile(wfPath);
160
- const strings = allStrings(def);
161
- expect(strings.some((s) => s.includes('parseJson('))).toBe(true);
162
- expect(def.steps.flatMap((s) => [s, ...((s.do ?? []) as StepDef[])]).some((s) => s.tool === 'Download')).toBe(true);
163
- });
164
-
165
- it('所有 ${} 表达式都能被引擎解析(不含畸形语法)', async () => {
166
- const def = await parseWorkflowFile(wfPath);
167
- const vars = new VarStack();
168
- const inputsObj: Record<string, unknown> = {};
169
- for (const inp of def.inputs ?? []) inputsObj[inp.name] = inp.default ?? '';
170
- vars.setGlobal('inputs', inputsObj);
171
- // 循环变量 u / u_idx(download/score loop 的 as)+ 捕获变量占位
172
- vars.set('u', 'http://x/1.jpg');
173
- vars.set('u_idx', 0);
174
- vars.setGlobal('urls', []);
175
- vars.setGlobal('engine_used', 'google');
176
- vars.setGlobal('score_text', '{}');
177
-
178
- for (const s of allStrings(def)) {
179
- if (!s.includes('${')) continue;
180
- expect(() => interpolate(s, vars)).not.toThrow();
181
- }
182
- });
183
- });