minimal-agent 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +503 -0
  103. package/src/advisor/advisorCoordinator.ts +657 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/streamJson.js +5 -6
  108. package/src/cli/streamJson.ts +8 -4
  109. package/src/cli/wizards/advisorWizard.js +4 -2
  110. package/src/cli/wizards/advisorWizard.tsx +8 -2
  111. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  112. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  113. package/src/collaboration/taskFlow.js +115 -0
  114. package/src/collaboration/taskFlow.ts +169 -0
  115. package/src/config/configDefaults.js +41 -1
  116. package/src/config/configDefaults.ts +43 -1
  117. package/src/config/configDiagnostics.ts +2 -2
  118. package/src/config/configFile.js +40 -9
  119. package/src/config/configFile.ts +60 -11
  120. package/src/config/configService.js +419 -74
  121. package/src/config/configService.ts +703 -145
  122. package/src/config/numericLimits.js +22 -0
  123. package/src/config/numericLimits.ts +24 -0
  124. package/src/config.js +1 -0
  125. package/src/config.ts +3 -2
  126. package/src/context/budgetPlan.js +1 -1
  127. package/src/context/budgetPlan.ts +1 -1
  128. package/src/context/compact.js +7 -2
  129. package/src/context/compact.ts +9 -2
  130. package/src/context/microCompactLite.js +212 -13
  131. package/src/context/microCompactLite.ts +261 -12
  132. package/src/context/sessionRegistry.js +8 -1
  133. package/src/context/sessionRegistry.ts +18 -5
  134. package/src/context/toolResultArchive.js +72 -0
  135. package/src/context/toolResultArchive.ts +95 -0
  136. package/src/goal/errors.js +8 -0
  137. package/src/goal/errors.ts +18 -0
  138. package/src/goal/goalRuntime.js +344 -0
  139. package/src/goal/goalRuntime.ts +466 -0
  140. package/src/goal/goalStore.js +200 -0
  141. package/src/goal/goalStore.ts +219 -0
  142. package/src/goal/index.js +4 -0
  143. package/src/goal/index.ts +4 -0
  144. package/src/goal/statusMapping.js +71 -0
  145. package/src/goal/statusMapping.ts +95 -0
  146. package/src/goal/types.js +7 -0
  147. package/src/goal/types.ts +179 -0
  148. package/src/goal/workflowController.js +306 -0
  149. package/src/goal/workflowController.ts +360 -0
  150. package/src/harness/evidenceLedger.js +2 -0
  151. package/src/harness/evidenceLedger.ts +1 -0
  152. package/src/harness/stallGuard.js +9 -3
  153. package/src/harness/stallGuard.ts +7 -3
  154. package/src/images/imageResolver.js +161 -0
  155. package/src/images/imageResolver.ts +189 -0
  156. package/src/infra/verification.js +34 -5
  157. package/src/infra/verification.ts +39 -4
  158. package/src/llm/client.js +79 -21
  159. package/src/llm/client.ts +182 -35
  160. package/src/llm/gatewayClient.js +201 -0
  161. package/src/llm/gatewayClient.ts +299 -0
  162. package/src/llm/messageProvenance.js +46 -0
  163. package/src/llm/messageProvenance.ts +58 -0
  164. package/src/llm/modelProvider.js +1 -0
  165. package/src/llm/modelProvider.ts +22 -0
  166. package/src/llm/providers/anthropicFormat.js +108 -1
  167. package/src/llm/providers/anthropicFormat.ts +115 -4
  168. package/src/llm/providers/openaiFormat.js +9 -0
  169. package/src/llm/providers/openaiFormat.ts +12 -3
  170. package/src/loop.js +319 -54
  171. package/src/loop.ts +373 -57
  172. package/src/main.js +4 -1
  173. package/src/main.tsx +4 -1
  174. package/src/managedExecution/index.js +2 -0
  175. package/src/managedExecution/index.ts +2 -0
  176. package/src/managedExecution/registry.js +15 -0
  177. package/src/managedExecution/registry.ts +20 -0
  178. package/src/managedExecution/types.js +1 -0
  179. package/src/managedExecution/types.ts +86 -0
  180. package/src/modelRef.js +9 -0
  181. package/src/modelRef.ts +31 -0
  182. package/src/multimodal.js +14 -28
  183. package/src/multimodal.ts +17 -33
  184. package/src/net/lanDiscovery.js +65 -0
  185. package/src/net/lanDiscovery.ts +82 -0
  186. package/src/plugin-sdk.js +28 -3
  187. package/src/plugin-sdk.ts +39 -6
  188. package/src/plugins/pluginApi.ts +16 -1
  189. package/src/plugins/pluginLoader.js +4 -0
  190. package/src/plugins/pluginLoader.ts +6 -0
  191. package/src/plugins/pluginRunner.js +139 -7
  192. package/src/plugins/pluginRunner.ts +173 -9
  193. package/src/plugins/slashFallback.js +113 -0
  194. package/src/plugins/slashFallback.ts +137 -0
  195. package/src/prompts/policyRegistry.js +12 -32
  196. package/src/prompts/policyRegistry.ts +15 -32
  197. package/src/prompts/promptAssembly.js +103 -12
  198. package/src/prompts/promptAssembly.ts +114 -12
  199. package/src/prompts/skillList.js +21 -3
  200. package/src/prompts/skillList.ts +27 -2
  201. package/src/prompts/stableSystemPrompt.js +18 -0
  202. package/src/prompts/stableSystemPrompt.ts +33 -0
  203. package/src/runtime/agentRuntimeContext.js +8 -2
  204. package/src/runtime/agentRuntimeContext.ts +17 -4
  205. package/src/session/runAgentTurn.js +78 -12
  206. package/src/session/runAgentTurn.ts +105 -23
  207. package/src/session/runTurn.js +10 -9
  208. package/src/session/runTurn.ts +17 -8
  209. package/src/session/sessionState.ts +2 -0
  210. package/src/team/auth.js +186 -0
  211. package/src/team/auth.ts +298 -0
  212. package/src/team/cli.js +105 -0
  213. package/src/team/cli.ts +122 -0
  214. package/src/team/onlineToolContract.js +64 -0
  215. package/src/team/onlineToolContract.ts +109 -0
  216. package/src/team/toolPolicy.js +36 -0
  217. package/src/team/toolPolicy.ts +75 -0
  218. package/src/tools/advisor/advisor.js +90 -46
  219. package/src/tools/advisor/advisor.ts +100 -47
  220. package/src/tools/advisor/advisorDecision.js +71 -0
  221. package/src/tools/advisor/advisorDecision.ts +85 -0
  222. package/src/tools/agent/agent.js +18 -5
  223. package/src/tools/agent/agent.ts +21 -7
  224. package/src/tools/agent/agentControl.js +246 -0
  225. package/src/tools/agent/agentControl.ts +284 -0
  226. package/src/tools/agent/agentTaskService.js +40 -1
  227. package/src/tools/agent/agentTaskService.ts +44 -1
  228. package/src/tools/agent/agentTypes.js +14 -2
  229. package/src/tools/agent/agentTypes.ts +15 -2
  230. package/src/tools/applypatch/applyPatch.js +362 -0
  231. package/src/tools/applypatch/applyPatch.ts +428 -0
  232. package/src/tools/bash/bash.js +22 -15
  233. package/src/tools/bash/bash.ts +23 -17
  234. package/src/tools/capabilities.js +10 -5
  235. package/src/tools/capabilities.ts +10 -5
  236. package/src/tools/computeruse/computerIntent.js +32 -0
  237. package/src/tools/computeruse/computerIntent.ts +46 -0
  238. package/src/tools/computeruse/telemetryLog.js +12 -0
  239. package/src/tools/computeruse/telemetryLog.ts +16 -0
  240. package/src/tools/computeruse/vision/telemetry.js +1 -0
  241. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  242. package/src/tools/effectiveToolSet.js +4 -0
  243. package/src/tools/effectiveToolSet.ts +4 -0
  244. package/src/tools/index.js +21 -2
  245. package/src/tools/index.ts +33 -2
  246. package/src/tools/presentresult/presentresult.js +6 -15
  247. package/src/tools/presentresult/presentresult.ts +6 -15
  248. package/src/tools/read/read.js +62 -9
  249. package/src/tools/read/read.ts +63 -9
  250. package/src/tools/shared/fileUtils.js +1 -2
  251. package/src/tools/shared/fileUtils.ts +1 -2
  252. package/src/tools/shared/toolOutputStore.js +23 -1
  253. package/src/tools/shared/toolOutputStore.ts +22 -1
  254. package/src/tools/skill/skill.js +9 -3
  255. package/src/tools/skill/skill.ts +8 -4
  256. package/src/tools/toolPromptGuides.js +117 -0
  257. package/src/tools/toolPromptGuides.ts +137 -0
  258. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  259. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  260. package/src/tools/webbrowser/browser.js +27 -11
  261. package/src/tools/webbrowser/browser.ts +68 -24
  262. package/src/tools/webbrowser/browserAutomation.js +329 -0
  263. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  264. package/src/tools/webbrowser/browserAxState.js +97 -0
  265. package/src/tools/webbrowser/browserAxState.ts +142 -0
  266. package/src/tools/webbrowser/browserBatch.js +1578 -0
  267. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  268. package/src/tools/webbrowser/browserCdp.js +208 -0
  269. package/src/tools/webbrowser/browserCdp.ts +255 -0
  270. package/src/tools/webbrowser/browserConditions.js +24 -0
  271. package/src/tools/webbrowser/browserConditions.ts +45 -0
  272. package/src/tools/webbrowser/browserContent.js +281 -0
  273. package/src/tools/webbrowser/browserContent.ts +438 -0
  274. package/src/tools/webbrowser/browserControl.js +131 -34
  275. package/src/tools/webbrowser/browserControl.ts +210 -56
  276. package/src/tools/webbrowser/browserDaemon.js +22 -14
  277. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  278. package/src/tools/webbrowser/browserFrames.js +47 -0
  279. package/src/tools/webbrowser/browserFrames.ts +54 -0
  280. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  281. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  282. package/src/tools/webbrowser/browserLocator.js +140 -0
  283. package/src/tools/webbrowser/browserLocator.ts +194 -0
  284. package/src/tools/webbrowser/browserOutcome.js +10 -17
  285. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  286. package/src/tools/webbrowser/browserRecovery.js +58 -0
  287. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  288. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  289. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  290. package/src/tools/webbrowser/browserService.js +28 -2
  291. package/src/tools/webbrowser/browserService.ts +49 -9
  292. package/src/tools/webbrowser/browserStream.js +132 -33
  293. package/src/tools/webbrowser/browserStream.ts +224 -50
  294. package/src/tools/webbrowser/browserTabs.js +48 -15
  295. package/src/tools/webbrowser/browserTabs.ts +178 -96
  296. package/src/tools/webbrowser/webbrowser.js +679 -144
  297. package/src/tools/webbrowser/webbrowser.ts +975 -236
  298. package/src/tools/webfetch/preapproved.js +0 -2
  299. package/src/tools/webfetch/preapproved.ts +0 -2
  300. package/src/tools/websearch/websearch.js +129 -8
  301. package/src/tools/websearch/websearch.ts +138 -6
  302. package/src/types.ts +440 -38
  303. package/src/ui/App.js +377 -58
  304. package/src/ui/App.tsx +576 -111
  305. package/src/ui/LiveArea.js +14 -8
  306. package/src/ui/LiveArea.tsx +14 -10
  307. package/src/ui/MessageList.js +63 -20
  308. package/src/ui/MessageList.tsx +101 -16
  309. package/src/ui/ModelPicker.js +7 -4
  310. package/src/ui/ModelPicker.tsx +55 -8
  311. package/src/ui/hooks/useChat.js +152 -163
  312. package/src/ui/hooks/useChat.ts +396 -334
  313. package/src/ui/loginCommand.js +56 -0
  314. package/src/ui/loginCommand.ts +63 -0
  315. package/src/ui/toolProgress.js +41 -0
  316. package/src/ui/toolProgress.ts +44 -0
  317. package/src/web/browserBridge.js +20 -2
  318. package/src/web/browserBridge.ts +20 -2
  319. package/src/web/protocol.ts +1897 -194
  320. package/workflows/adaptive-research/workflow.mjs +86 -0
  321. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  322. package/workflows/e2e-llm/workflow.mjs +52 -0
  323. package/workflows/e2e-smoke/workflow.mjs +59 -0
  324. package/workflows/e2e-vision-schema/README.md +48 -0
  325. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  326. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  327. package/workflows/file-census/README.md +14 -0
  328. package/workflows/file-census/scripts/.gitkeep +2 -0
  329. package/workflows/file-census/workflow.mjs +110 -0
  330. package/workflows/goal/README.md +166 -0
  331. package/workflows/goal/prompts/audit.md +57 -0
  332. package/workflows/goal/prompts/contract.md +56 -0
  333. package/workflows/goal/prompts/iterate.md +37 -0
  334. package/workflows/goal/workflow.mjs +501 -0
  335. package/workflows/illustrate/README.md +90 -0
  336. package/workflows/illustrate/assets/engines.json +20 -0
  337. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  338. package/workflows/illustrate/assets/extract-bing.js +33 -0
  339. package/workflows/illustrate/assets/extract-google.js +31 -0
  340. package/workflows/illustrate/workflow.mjs +301 -0
  341. package/workflows/plan/workflow.mjs +389 -0
  342. package/workflows/question-crops/README.md +35 -0
  343. package/workflows/question-crops/prompts/inventory.md +23 -0
  344. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  345. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  346. package/workflows/question-crops/workflow.mjs +172 -0
  347. package/workflows/ralph-loop/workflow.mjs +162 -0
  348. package/workflows/research/README.md +74 -0
  349. package/workflows/research/prompts/s0-goal.md +43 -0
  350. package/workflows/research/prompts/s1-early-exit.md +22 -0
  351. package/workflows/research/prompts/s1-map.md +58 -0
  352. package/workflows/research/prompts/s2-options.md +53 -0
  353. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  354. package/workflows/research/prompts/s4-verify.md +74 -0
  355. package/workflows/research/prompts/s5-synthesis.md +81 -0
  356. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  357. package/workflows/research/prompts/s6-package.md +32 -0
  358. package/workflows/research/scripts/build-report.mjs +98 -0
  359. package/workflows/research/workflow.mjs +288 -0
  360. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  361. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  362. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  363. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  364. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  365. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  366. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  367. package/workflows/wrong-question-docx/README.md +55 -0
  368. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  369. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  370. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  371. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  372. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  373. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  374. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  375. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  376. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  377. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  378. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  379. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  380. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  381. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  382. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  383. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  384. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  385. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  386. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  387. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  388. package/plugins/workflow-runner/src/expressions.js +0 -639
  389. package/plugins/workflow-runner/src/expressions.ts +0 -640
  390. package/plugins/workflow-runner/src/loader.js +0 -573
  391. package/plugins/workflow-runner/src/loader.ts +0 -721
  392. package/plugins/workflow-runner/src/multimodal.js +0 -38
  393. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  394. package/plugins/workflow-runner/src/recovery.js +0 -126
  395. package/plugins/workflow-runner/src/recovery.ts +0 -156
  396. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  397. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  398. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  399. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  400. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  401. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  402. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  403. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  404. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  405. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  406. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  407. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  408. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  409. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  410. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  411. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  412. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  413. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  414. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  415. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  416. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  417. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  418. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  419. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  420. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  421. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  422. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  423. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  424. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  425. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  426. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  427. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  428. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  429. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  430. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  431. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  432. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  433. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  434. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  435. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  436. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  437. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  438. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  439. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  440. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  441. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  442. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  443. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  444. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  445. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  446. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  447. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  448. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  449. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  450. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  451. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  452. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  453. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  454. package/src/advisorState.js +0 -22
  455. package/src/cli/configWizard.js +0 -293
  456. package/src/tools/toolProgressBridge.js +0 -48
  457. package/workflows/adaptive-research.yaml +0 -50
  458. package/workflows/book-review-short.yaml +0 -125
  459. package/workflows/e2e-write-greet.yaml +0 -31
  460. package/workflows/illustrate.yaml +0 -227
  461. package/workflows/plan.yaml +0 -470
  462. package/workflows/ppt.yaml +0 -1670
  463. package/workflows/ralph-loop.yaml +0 -201
  464. package/workflows/research.yaml +0 -873
  465. package/workflows/schema.json +0 -176
  466. package/workflows/webppt.yaml +0 -496
  467. package/workflows/wechat-reading-shots.yaml +0 -315
  468. package/workflows/word.yaml +0 -720
  469. package/workflows/youtube-shorts.yaml +0 -202
  470. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -0,0 +1,294 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+
6
+ import type { InvocationResource } from '../../../src/plugin-sdk.js';
7
+ import {
8
+ bindResourceInputs,
9
+ materializeResources,
10
+ } from '../src/resourceInputs.js';
11
+
12
+ const imageDef = {
13
+ name: 'source',
14
+ type: 'resource' as const,
15
+ required: true,
16
+ accepts: ['image/*'],
17
+ allowFile: true,
18
+ allowDirectory: true,
19
+ multiple: true,
20
+ attachmentFallback: true,
21
+ };
22
+
23
+ describe('workflow resource inputs', () => {
24
+ test('binds compatible Desktop attachments and materializes multiple files', async () => {
25
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
26
+ try {
27
+ const a = join(root, 'a.jpg');
28
+ const b = join(root, 'b.png');
29
+ await writeFile(a, 'a');
30
+ await writeFile(b, 'b');
31
+ const attachments: InvocationResource[] = [
32
+ {
33
+ id: 'a',
34
+ origin: 'attachment',
35
+ name: 'a.jpg',
36
+ mime: 'image/jpeg',
37
+ size: 1,
38
+ sha256: 'sha-a',
39
+ localPath: a,
40
+ kind: 'file',
41
+ },
42
+ {
43
+ id: 'b',
44
+ origin: 'attachment',
45
+ name: 'b.png',
46
+ mime: 'image/png',
47
+ size: 1,
48
+ sha256: 'sha-b',
49
+ localPath: b,
50
+ kind: 'file',
51
+ },
52
+ ];
53
+ const bound = await bindResourceInputs({
54
+ workflowName: 'wrong-question-docx',
55
+ sessionId: 's1',
56
+ rawInputs: {},
57
+ defs: [imageDef],
58
+ attachments,
59
+ });
60
+ expect(typeof bound.inputs.source).toBe('string');
61
+ expect(bound.resourceMap.source).toHaveLength(2);
62
+ expect(bound.resourceIdentity).toEqual(['source:sha-a', 'source:sha-b']);
63
+ const staged = String(bound.inputs.source);
64
+ expect(await readFile(join(staged, '001-a.jpg'), 'utf8')).toBe('a');
65
+ expect(await readFile(join(staged, '002-b.png'), 'utf8')).toBe('b');
66
+ } finally {
67
+ await rm(root, { recursive: true, force: true });
68
+ }
69
+ });
70
+
71
+ test('explicit path wins over attachments', async () => {
72
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
73
+ try {
74
+ const path = join(root, 'paper.jpg');
75
+ await writeFile(path, 'paper');
76
+ const bound = await bindResourceInputs({
77
+ workflowName: 'wrong-question-docx',
78
+ sessionId: 's1',
79
+ rawInputs: { source: path },
80
+ defs: [imageDef],
81
+ attachments: [
82
+ {
83
+ id: 'other',
84
+ origin: 'attachment',
85
+ name: 'other.jpg',
86
+ mime: 'image/jpeg',
87
+ localPath: path,
88
+ kind: 'file',
89
+ },
90
+ ],
91
+ });
92
+ expect(bound.inputs.source).toBe(path);
93
+ expect(bound.resourceMap.source?.[0]?.origin).toBe('path');
94
+ expect(bound.warnings).toHaveLength(0);
95
+ } finally {
96
+ await rm(root, { recursive: true, force: true });
97
+ }
98
+ });
99
+
100
+ test('relative explicit paths resolve from the workflow cwd', async () => {
101
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
102
+ try {
103
+ await writeFile(join(root, 'paper.jpg'), 'paper');
104
+ const bound = await bindResourceInputs({
105
+ workflowName: 'wrong-question-docx',
106
+ sessionId: 's1',
107
+ cwd: root,
108
+ rawInputs: { source: 'paper.jpg' },
109
+ defs: [imageDef],
110
+ });
111
+ expect(bound.inputs.source).toBe(join(root, 'paper.jpg'));
112
+ } finally {
113
+ await rm(root, { recursive: true, force: true });
114
+ }
115
+ });
116
+
117
+ test('directory materialization stages even one Desktop file', async () => {
118
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
119
+ try {
120
+ const file = join(root, 'one.jpg');
121
+ await writeFile(file, 'one');
122
+ const bound = await bindResourceInputs({
123
+ workflowName: 'e2e-vision-schema',
124
+ sessionId: 's1',
125
+ rawInputs: {},
126
+ defs: [
127
+ {
128
+ ...imageDef,
129
+ name: 'dir',
130
+ allowFile: false,
131
+ materialize: 'directory',
132
+ },
133
+ ],
134
+ attachments: [
135
+ {
136
+ id: 'one',
137
+ origin: 'attachment',
138
+ name: 'one.jpg',
139
+ mime: 'image/jpeg',
140
+ sha256: 'sha-one',
141
+ localPath: file,
142
+ kind: 'file',
143
+ },
144
+ ],
145
+ });
146
+ expect(
147
+ await readFile(join(String(bound.inputs.dir), '001-one.jpg'), 'utf8'),
148
+ ).toBe('one');
149
+ } finally {
150
+ await rm(root, { recursive: true, force: true });
151
+ }
152
+ });
153
+
154
+ test('single Desktop file also uses a stable Runner copy', async () => {
155
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
156
+ try {
157
+ const file = join(root, 'one.jpg');
158
+ await writeFile(file, 'one');
159
+ const bound = await bindResourceInputs({
160
+ workflowName: 'wrong-question-docx',
161
+ sessionId: 's1',
162
+ rawInputs: {},
163
+ defs: [{ ...imageDef, multiple: false }],
164
+ attachments: [
165
+ {
166
+ id: 'one',
167
+ origin: 'attachment',
168
+ name: 'one.jpg',
169
+ mime: 'image/jpeg',
170
+ sha256: 'sha-one',
171
+ localPath: file,
172
+ kind: 'file',
173
+ },
174
+ ],
175
+ });
176
+ expect(bound.inputs.source).not.toBe(file);
177
+ expect(await readFile(String(bound.inputs.source), 'utf8')).toBe('one');
178
+ } finally {
179
+ await rm(root, { recursive: true, force: true });
180
+ }
181
+ });
182
+
183
+ test('reference identity uses resource ids instead of content hashes', async () => {
184
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
185
+ try {
186
+ const path = join(root, 'paper.jpg');
187
+ await writeFile(path, 'paper');
188
+ const bound = await bindResourceInputs({
189
+ workflowName: 'demo',
190
+ sessionId: 's1',
191
+ rawInputs: { source: path },
192
+ defs: [{ ...imageDef, identity: 'reference' }],
193
+ });
194
+ expect(bound.resourceIdentity).toHaveLength(1);
195
+ expect(bound.resourceIdentity[0]).toMatch(/^source:path-[a-f0-9]{24}$/);
196
+ } finally {
197
+ await rm(root, { recursive: true, force: true });
198
+ }
199
+ });
200
+
201
+ test('content identity notices changes inside an explicit directory', async () => {
202
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
203
+ try {
204
+ const source = join(root, 'papers');
205
+ await mkdir(source);
206
+ await writeFile(join(source, 'page.jpg'), 'page-a');
207
+ const options = {
208
+ workflowName: 'wrong-question-docx',
209
+ sessionId: 's1',
210
+ rawInputs: { source },
211
+ defs: [imageDef],
212
+ };
213
+ const first = await bindResourceInputs(options);
214
+ await writeFile(join(source, 'page.jpg'), 'page-b');
215
+ const second = await bindResourceInputs(options);
216
+ expect(first.resourceIdentity).not.toEqual(second.resourceIdentity);
217
+ } finally {
218
+ await rm(root, { recursive: true, force: true });
219
+ }
220
+ });
221
+
222
+ test('rejects incompatible attachments instead of guessing', async () => {
223
+ const bound = await bindResourceInputs({
224
+ workflowName: 'wrong-question-docx',
225
+ sessionId: 's1',
226
+ rawInputs: {},
227
+ defs: [imageDef],
228
+ attachments: [
229
+ {
230
+ id: 'pdf',
231
+ origin: 'attachment',
232
+ name: 'paper.pdf',
233
+ mime: 'application/pdf',
234
+ localPath: '/tmp/paper.pdf',
235
+ kind: 'file',
236
+ },
237
+ ],
238
+ });
239
+ expect(bound.inputs.source).toBeUndefined();
240
+ expect(bound.resourceMap.source).toBeUndefined();
241
+ });
242
+
243
+ test('rejects attachment batches above maxItems', async () => {
244
+ await expect(
245
+ bindResourceInputs({
246
+ workflowName: 'wrong-question-docx',
247
+ sessionId: 's1',
248
+ rawInputs: {},
249
+ defs: [{ ...imageDef, maxItems: 1 }],
250
+ attachments: [
251
+ {
252
+ id: 'a',
253
+ origin: 'attachment',
254
+ name: 'a.jpg',
255
+ mime: 'image/jpeg',
256
+ localPath: '/tmp/a.jpg',
257
+ kind: 'file',
258
+ },
259
+ {
260
+ id: 'b',
261
+ origin: 'attachment',
262
+ name: 'b.jpg',
263
+ mime: 'image/jpeg',
264
+ localPath: '/tmp/b.jpg',
265
+ kind: 'file',
266
+ },
267
+ ],
268
+ }),
269
+ ).rejects.toThrow('最多允许 1 个附件');
270
+ });
271
+
272
+ test('staging path is stable for the same resources', async () => {
273
+ const root = await mkdtemp(join(tmpdir(), 'workflow-resource-'));
274
+ try {
275
+ const file = join(root, 'x.jpg');
276
+ await writeFile(file, 'x');
277
+ const resource: InvocationResource = {
278
+ id: 'x',
279
+ origin: 'attachment',
280
+ name: 'x.jpg',
281
+ mime: 'image/jpeg',
282
+ size: 1,
283
+ sha256: 'sha-x',
284
+ localPath: file,
285
+ kind: 'file',
286
+ };
287
+ expect(await materializeResources('wf', 's', 'source', [resource])).toBe(
288
+ await materializeResources('wf', 's', 'source', [resource]),
289
+ );
290
+ } finally {
291
+ await rm(root, { recursive: true, force: true });
292
+ }
293
+ });
294
+ });
@@ -0,0 +1,126 @@
1
+ import { afterEach, describe, expect, test } from 'bun:test';
2
+ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+
6
+ import { WorkflowScriptError, runScript } from '../src/sandbox.js';
7
+ import { validateScript } from '../src/scriptGuard.mjs';
8
+ import type { WorkflowScript } from '../src/types.js';
9
+
10
+ const dirs: string[] = [];
11
+ afterEach(async () => {
12
+ for (const dir of dirs.splice(0)) await rm(dir, { recursive: true, force: true });
13
+ });
14
+
15
+ async function workflow(source: string, name = 'test-flow'): Promise<WorkflowScript> {
16
+ const root = await mkdtemp(join(tmpdir(), 'wf-esm-'));
17
+ dirs.push(root);
18
+ const dir = join(root, name);
19
+ await mkdir(dir, { recursive: true });
20
+ const scriptPath = join(dir, 'workflow.mjs');
21
+ await writeFile(scriptPath, source);
22
+ const verdict = validateScript(source, { filename: scriptPath });
23
+ if (!verdict.ok || verdict.bodyOffset === undefined) {
24
+ throw new Error(verdict.errors.join('; '));
25
+ }
26
+ return {
27
+ name,
28
+ dir,
29
+ scriptPath,
30
+ source,
31
+ meta: { apiVersion: 2, description: 'test' },
32
+ bodyOffset: verdict.bodyOffset,
33
+ };
34
+ }
35
+
36
+ const head = `export const meta = { apiVersion: 2, description: 'test' };\n`;
37
+
38
+ describe('trusted ESM workflow loader', () => {
39
+ test('default run receives an isolated wf object and returns JSON data', async () => {
40
+ const script = await workflow(
41
+ `${head}export default async function run(wf) { return { value: wf.input.values.x }; }`,
42
+ );
43
+ expect(
44
+ await runScript(script, { input: { values: { x: 42 } } }, 'bundle-a'),
45
+ ).toEqual({ value: 42 });
46
+ });
47
+
48
+ test('native relative imports resolve from the workflow directory', async () => {
49
+ const script = await workflow(
50
+ `${head}import { twice } from './scripts/math.mjs';\nexport default async function run(wf) { return twice(6); }`,
51
+ );
52
+ await mkdir(join(script.dir, 'scripts'), { recursive: true });
53
+ await writeFile(
54
+ join(script.dir, 'scripts', 'math.mjs'),
55
+ 'export const twice = (value) => value * 2;\n',
56
+ );
57
+ expect(await runScript(script, {}, 'bundle-b')).toBe(12);
58
+ });
59
+
60
+ test('bundle hash selects a fresh physical ESM graph when a helper changes', async () => {
61
+ const script = await workflow(
62
+ `${head}import { value } from './scripts/value.mjs';\nexport default async function run(wf) { return value; }`,
63
+ );
64
+ const helper = join(script.dir, 'scripts', 'value.mjs');
65
+ await mkdir(join(script.dir, 'scripts'), { recursive: true });
66
+ await writeFile(helper, 'export const value = 1;\n');
67
+ expect(await runScript(script, {}, 'bundle-helper-v1')).toBe(1);
68
+ await writeFile(helper, 'export const value = 2;\n');
69
+ expect(await runScript(script, {}, 'bundle-helper-v2')).toBe(2);
70
+ });
71
+
72
+ test('concurrent instances do not share run-local state', async () => {
73
+ const script = await workflow(
74
+ `${head}export default async function run(wf) { let value = wf.input.values.value; await Promise.resolve(); value += 1; return value; }`,
75
+ );
76
+ expect(
77
+ await Promise.all([
78
+ runScript(script, { input: { values: { value: 1 } } }, 'bundle-c'),
79
+ runScript(script, { input: { values: { value: 9 } } }, 'bundle-c'),
80
+ ]),
81
+ ).toEqual([2, 10]);
82
+ });
83
+
84
+ test('wide concurrent fan-out sharing one bundle hash does not race the ESM cache rename (Windows EPERM regression)', async () => {
85
+ const script = await workflow(
86
+ `${head}export default async function run(wf) { let value = wf.input.values.value; await Promise.resolve(); value += 1; return value; }`,
87
+ );
88
+ const N = 16;
89
+ const results = await Promise.all(
90
+ Array.from({ length: N }, (_, i) =>
91
+ runScript(script, { input: { values: { value: i } } }, 'bundle-wide'),
92
+ ),
93
+ );
94
+ expect(results).toEqual(Array.from({ length: N }, (_, i) => i + 1));
95
+ });
96
+
97
+ test('runtime errors preserve workflow outcome and cause', async () => {
98
+ const script = await workflow(
99
+ `${head}export default async function run(wf) { throw Object.assign(new Error('budget'), { workflowOutcome: 'budget_limited' }); }`,
100
+ );
101
+ const error = await runScript(script, {}, 'bundle-d').catch((value) => value);
102
+ expect(error).toBeInstanceOf(WorkflowScriptError);
103
+ expect(error).toMatchObject({ workflowOutcome: 'budget_limited' });
104
+ expect((error as WorkflowScriptError).cause).toBeInstanceOf(Error);
105
+ });
106
+
107
+ test('AbortError passes through without workflow-failure wrapping', async () => {
108
+ const script = await workflow(
109
+ `${head}export default async function run(wf) { const e = new Error('stop'); e.name = 'AbortError'; throw e; }`,
110
+ );
111
+ const error = await runScript(script, {}, 'bundle-e').catch((value) => value);
112
+ expect((error as Error).name).toBe('AbortError');
113
+ expect(error).not.toBeInstanceOf(WorkflowScriptError);
114
+ });
115
+
116
+ test('module parse failures are reported as module-load failures', async () => {
117
+ const script = await workflow(
118
+ `${head}export default async function run(wf) { return 1; }`,
119
+ );
120
+ const invalid = `${head}export default async function run( {`;
121
+ await writeFile(script.scriptPath, invalid);
122
+ await expect(
123
+ runScript({ ...script, source: invalid }, {}, 'bundle-f-invalid'),
124
+ ).rejects.toThrow(/模块加载失败/);
125
+ });
126
+ });
@@ -0,0 +1,70 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { readWorkflowRuntimeConfig } from '../src/runtime/config.js';
3
+ import { WorkflowScheduler } from '../src/runtime/scheduler.js';
4
+
5
+ const config = (overrides: Partial<ReturnType<typeof readWorkflowRuntimeConfig>> = {}) => ({
6
+ ...readWorkflowRuntimeConfig({} as NodeJS.ProcessEnv),
7
+ ...overrides,
8
+ });
9
+
10
+ describe('WorkflowScheduler', () => {
11
+ test('进程级资源上限覆盖不同根运行', async () => {
12
+ const scheduler = new WorkflowScheduler(config({ modelConcurrency: 2 }));
13
+ let active = 0;
14
+ let peak = 0;
15
+ await Promise.all(
16
+ Array.from({ length: 12 }, (_, index) =>
17
+ scheduler.run('model', `root-${index % 3}`, async () => {
18
+ active++;
19
+ peak = Math.max(peak, active);
20
+ await new Promise((resolve) => setTimeout(resolve, 4));
21
+ active--;
22
+ }),
23
+ ),
24
+ );
25
+ expect(peak).toBe(2);
26
+ });
27
+
28
+ test('根运行之间轮转,不让一个大队列饿死后来的根', async () => {
29
+ const scheduler = new WorkflowScheduler(config({ toolConcurrency: 1 }));
30
+ const first = await scheduler.acquire('tool', 'root-a');
31
+ const order: string[] = [];
32
+ const queued = [
33
+ scheduler.run('tool', 'root-a', async () => void order.push('a1')),
34
+ scheduler.run('tool', 'root-a', async () => void order.push('a2')),
35
+ scheduler.run('tool', 'root-b', async () => void order.push('b1')),
36
+ scheduler.run('tool', 'root-a', async () => void order.push('a3')),
37
+ ];
38
+ first.release();
39
+ await Promise.all(queued);
40
+ expect(order.indexOf('b1')).toBeLessThan(order.indexOf('a3'));
41
+ });
42
+
43
+ test('取消会移除排队项且不占用槽', async () => {
44
+ const scheduler = new WorkflowScheduler(config({ processConcurrency: 1 }));
45
+ const first = await scheduler.acquire('process', 'root-a');
46
+ const controller = new AbortController();
47
+ const cancelled = scheduler.acquire('process', 'root-b', controller.signal);
48
+ controller.abort(Object.assign(new Error('stop'), { name: 'AbortError' }));
49
+ await expect(cancelled).rejects.toMatchObject({ name: 'AbortError' });
50
+ first.release();
51
+ const lease = await scheduler.acquire('process', 'root-c');
52
+ lease.release();
53
+ });
54
+ });
55
+
56
+ describe('workflow runtime environment', () => {
57
+ test('非法值响亮报错,不静默回默认值', () => {
58
+ expect(() =>
59
+ readWorkflowRuntimeConfig({
60
+ MINIMAL_AGENT_WORKFLOW_MODEL_CONCURRENCY: '0',
61
+ } as NodeJS.ProcessEnv),
62
+ ).toThrow(/MINIMAL_AGENT_WORKFLOW_MODEL_CONCURRENCY/);
63
+ expect(() =>
64
+ readWorkflowRuntimeConfig({
65
+ MINIMAL_AGENT_WORKFLOW_PIPELINE_CONCURRENCY: '10',
66
+ MINIMAL_AGENT_WORKFLOW_PIPELINE_MAX_CONCURRENCY: '5',
67
+ } as NodeJS.ProcessEnv),
68
+ ).toThrow(/不能大于/);
69
+ });
70
+ });