minimal-agent 0.13.0 → 0.15.0

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