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,221 +0,0 @@
1
- /**
2
- * ============================================================
3
- * plugins/workflow-runner/test/ralphLoop.e2e.test.ts
4
- * ------------------------------------------------------------
5
- * ralph-loop.yaml 端到端(真实 yaml 文件 + 脚本化 DI chat,零网络)。
6
- *
7
- * 背景:重写前的 ralph-loop 有 5 处独立缺陷且 while/fresh_context 零测试覆盖
8
- * (从未被端到端跑通过):max_iterations 模板不插值→静默 0 次迭代、裸 ${goal}
9
- * 插空、${phase.toUpperCase()} 必抛错、llm 步当赋值用、哨兵 includes 误判
10
- * (learning-only 输出直接终止循环 / "incomplete" 含 "complete" 误判完成 /
11
- * auto_advance 吞掉 replan)。本文件以「学习一轮 → 完成一轮」的剧本钉死全链路。
12
- * ============================================================
13
- */
14
-
15
- import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
16
- import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
17
- import { tmpdir } from 'node:os';
18
- import { join } from 'node:path';
19
-
20
- import { _resetWorkingDir } from '../../../src/bootstrap/workingDir.js';
21
- import { ALL_TOOLS } from '../../../src/tools/index.js';
22
- import type { LoopEvent, Message, Provider } from '../../../src/types.js';
23
- import { parseWorkflowFile } from '../src/loader.js';
24
- import { runWorkflow } from '../src/runner.js';
25
- import type { RunContext, WorkflowEvent } from '../src/types.js';
26
-
27
- type WfOrLoop = WorkflowEvent | LoopEvent;
28
-
29
- const YAML_PATH = join(import.meta.dir, '..', '..', '..', 'workflows', 'ralph-loop.yaml');
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('ralph-loop.yaml 端到端(while + fresh_context + 哨兵协议)', () => {
48
- let tmp: string;
49
- let ctx: RunContext;
50
-
51
- beforeEach(() => {
52
- tmp = mkdtempSync(join(tmpdir(), 'wf-ralph-'));
53
- process.env.MINIMAL_AGENT_CWD = tmp;
54
- _resetWorkingDir();
55
- mock.module('../../../src/bootstrap/workingDir.js', () => ({
56
- getWorkingDir: () => tmp,
57
- initWorkingDir: () => tmp,
58
- _resetWorkingDir: () => {},
59
- }));
60
- ctx = { provider: fakeProvider, history: [], cwd: tmp, tools: ALL_TOOLS };
61
- });
62
-
63
- afterEach(() => {
64
- delete process.env.MINIMAL_AGENT_CWD;
65
- _resetWorkingDir();
66
- rmSync(tmp, { recursive: true, force: true });
67
- });
68
-
69
- it('学习一轮 → 完成一轮:恰 2 次迭代 break、教训存档不重复、目标/阶段/教训进 prompt', async () => {
70
- const def = await parseWorkflowFile(YAML_PATH); // 真实 yaml 必须能加载
71
- def.self_heal = { ...def.self_heal, retry_delay_ms: 0 }; // 测试不等退避
72
-
73
- // 脚本化 chat(按调用顺序)——教训提取已是确定性 set(extract/join 内置函数),
74
- // 不再占一次 LLM 调用:
75
- // #1 work(iter0) → learning-only 输出(无 promise 哨兵——不得终止循环!)
76
- // #2 work(iter1) → 完成哨兵
77
- // #3 final_summary
78
- // ⚠️ messages 是 runQuery 原地 mutate 的共享 history 引用,必须在调用时快照成文本
79
- const calls: string[] = [];
80
- let n = 0;
81
- ctx.chat = async function* (args: { messages: Message[] }) {
82
- calls.push(args.messages.map((m) => String(m.content ?? '')).join('\n'));
83
- n++;
84
- const reply =
85
- n === 1
86
- ? '我做了规划,发现 <learning>边界条件要先写测试</learning>,下一轮开始实现。'
87
- : n === 2
88
- ? '已全部实现并自测通过。<promise>DONE</promise>'
89
- : '总结:目标完成。';
90
- yield { type: 'text_delta', delta: reply };
91
- yield { type: 'done', stopReason: 'stop' };
92
- };
93
-
94
- const events = await collect(
95
- runWorkflow(def, { goal: '实现登录模块', max_iterations: 5, verify_checks: '' }, ctx),
96
- );
97
-
98
- // 整链成功
99
- expect(events.some((e) => e.type === 'workflow_done')).toBe(true);
100
- expect(
101
- events.some((e) => e.type === 'error' && e.error.includes('Workflow halted')),
102
- ).toBe(false);
103
-
104
- // 恰 2 次迭代后 break(R1 回归锚:max_iterations 模板曾静默 0 次迭代)
105
- const loopEnd = events.find(
106
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_end' }> =>
107
- e.type === 'workflow_step_end' && e.id === 'main_loop',
108
- );
109
- expect(loopEnd?.output).toContain('2 iterations');
110
- expect(loopEnd?.output).toContain('break');
111
-
112
- // chat 恰 3 次(多了说明循环失控/少了说明被误终止;教训提取零 LLM)
113
- expect(n).toBe(3);
114
-
115
- // iter0 的 work prompt:目标原文(R2 锚)、阶段 PLAN 大写(R3 锚)、哨兵协议
116
- const p0 = calls[0];
117
- expect(p0).toContain('实现登录模块');
118
- expect(p0).toContain('当前阶段: PLAN');
119
- expect(p0).toContain('<promise>DONE</promise>');
120
-
121
- // iter1 的 work prompt:auto_advance 推进到 BUILD(learning 不是流程哨兵,不阻止推进),
122
- // 且上一轮教训进了「关键教训」节
123
- const p2 = calls[1];
124
- expect(p2).toContain('当前阶段: BUILD');
125
- expect(p2).toContain('关键教训');
126
- expect(p2).toContain('边界条件要先写测试');
127
- // fresh_context:iter1 的消息里不应携带 iter0 的对话产物
128
- expect(p2).not.toContain('我做了规划');
129
-
130
- // 教训档案恰好一条、不重复(iter1 无 learning 标签时 extract → '' 不得重复累积)
131
- // learnings 是 workflow 级共享存档,写在 ralph-loop/ 下(Phase 2 父目录不参与归档改名;
132
- // 状态实例归档为 ralph-loop/<taskId>.done/)
133
- const learningsPath = join(
134
- tmp,
135
- '.minimal-agent-workflow',
136
- 'ralph-loop',
137
- 'learnings.md',
138
- );
139
- expect(existsSync(learningsPath)).toBe(true);
140
- const learnings = readFileSync(learningsPath, 'utf8');
141
- expect(learnings).toContain('边界条件要先写测试');
142
- expect(learnings.match(/边界条件要先写测试/g)?.length).toBe(1);
143
- });
144
-
145
- it('R5 锚:输出含 "incomplete" 等普通词 + learning 标签 → 不被误判完成/不误终止', async () => {
146
- const def = await parseWorkflowFile(YAML_PATH);
147
- def.self_heal = { ...def.self_heal, retry_delay_ms: 0 };
148
-
149
- // iter0: 含 "incomplete"(曾因 includes(complete) 误判 DONE)+ learning(提取零 LLM);
150
- // iter1: NEED_REPLAN(auto_advance 有 <promise> 守卫,phase 应回 PLAN 且不被推进吞掉);
151
- // iter2: 真 DONE。
152
- let n = 0;
153
- ctx.chat = async function* () {
154
- n++;
155
- const reply =
156
- n === 1
157
- ? 'work is incomplete, still analyzing. <learning>先列验收标准</learning>'
158
- : n === 2
159
- ? '这个方案走不通。<promise>NEED_REPLAN</promise>'
160
- : n === 3
161
- ? '换方案后完成。<promise>DONE</promise>'
162
- : '总结。';
163
- yield { type: 'text_delta', delta: reply };
164
- yield { type: 'done', stopReason: 'stop' };
165
- };
166
-
167
- const events = await collect(
168
- runWorkflow(def, { goal: 'G', max_iterations: 6, verify_checks: '' }, ctx),
169
- );
170
-
171
- expect(events.some((e) => e.type === 'workflow_done')).toBe(true);
172
- const loopEnd = events.find(
173
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_end' }> =>
174
- e.type === 'workflow_step_end' && e.id === 'main_loop',
175
- );
176
- // 3 轮迭代(incomplete 轮没有被误判完成、NEED_REPLAN 轮没有终止循环)
177
- expect(loopEnd?.output).toContain('3 iterations');
178
- expect(loopEnd?.output).toContain('break');
179
- });
180
-
181
- it('验证门:DONE 哨兵但 verify 失败 → 不 break、回 BUILD 继续(模型谎报拦截)', async () => {
182
- const def = await parseWorkflowFile(YAML_PATH);
183
- def.self_heal = { ...def.self_heal, retry_delay_ms: 0 };
184
-
185
- let n = 0;
186
- ctx.chat = async function* () {
187
- n++;
188
- const reply =
189
- n === 1
190
- ? '我说完成了。<promise>DONE</promise>' // 谎报:验证门会拦
191
- : n === 2
192
- ? '这次真完成了。<promise>DONE</promise>'
193
- : '总结。';
194
- yield { type: 'text_delta', delta: reply };
195
- yield { type: 'done', stopReason: 'stop' };
196
- };
197
-
198
- const events = await collect(
199
- runWorkflow(
200
- def,
201
- {
202
- goal: 'G',
203
- // verify 永远失败(文件不存在)+ 上限 2 轮:两轮谎报 DONE 都被验证门
204
- // 拦下回 BUILD(不 break),最终以「达到上限」退出而非误判完成。
205
- max_iterations: 2,
206
- verify_checks: 'file_exists:./definitely-not-exists.txt',
207
- },
208
- ctx,
209
- ),
210
- );
211
-
212
- // 两轮都谎报 DONE 但验证门都拦下 → 不 break,达上限退出
213
- const loopEnd = events.find(
214
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_end' }> =>
215
- e.type === 'workflow_step_end' && e.id === 'main_loop',
216
- );
217
- expect(loopEnd?.output).toContain('达到上限');
218
- // 工作流本身正常收尾(验证门拦截不是 halt)
219
- expect(events.some((e) => e.type === 'workflow_done')).toBe(true);
220
- });
221
- });
@@ -1,265 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/workflows/recovery.test.ts —— onError:'recover' 自适应恢复
4
- * ------------------------------------------------------------
5
- * 验证「确定性工作流 × 随机应变 agent」的结合点:
6
- * - 动作 step 失败 + onError:'recover' → 起恢复 agent(miniReAct)救回
7
- * → 用同一 capture 绑定结果 → workflow 继续到 done
8
- * - 恢复也失败 → honest halt(error + 无 done)
9
- * - onError 默认(halt) → 不触发恢复(recover 是 opt-in,老行为不变)
10
- *
11
- * 策略(同 runner.test.ts):
12
- * - 失败触发器:未知工具 NoSuchTool9999(execToolStep 直接 throw)
13
- * - 恢复路径最终经 runRecovery → miniReAct → chat,mock client.js 控制其输出
14
- * ============================================================
15
- */
16
-
17
- import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
18
- import { mkdtempSync, rmSync } from 'node:fs';
19
- import { tmpdir } from 'node:os';
20
- import { join } from 'node:path';
21
-
22
- import { _resetWorkingDir } from '../../../src/bootstrap/workingDir.js';
23
- import type { LoopEvent, Provider } from '../../../src/types.js';
24
- import { runWorkflow } from '../src/runner.js';
25
- import type { RunContext, WorkflowDef, WorkflowEvent } from '../src/types.js';
26
-
27
- type WfOrLoop = WorkflowEvent | LoopEvent;
28
-
29
- const fakeProvider: Provider = {
30
- name: 'test',
31
- baseURL: '',
32
- apiKey: '',
33
- model: 'm',
34
- contextWindow: 128000,
35
- };
36
-
37
- async function collect(
38
- gen: AsyncGenerator<WfOrLoop, void, void>,
39
- ): Promise<WfOrLoop[]> {
40
- const out: WfOrLoop[] = [];
41
- for await (const ev of gen) out.push(ev);
42
- return out;
43
- }
44
-
45
- describe('workflows/recovery (onError:recover)', () => {
46
- let tmp: string;
47
- let ctx: RunContext;
48
-
49
- beforeEach(() => {
50
- tmp = mkdtempSync(join(tmpdir(), 'wf-recover-'));
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
- ctx = { provider: fakeProvider, history: [], cwd: tmp, tools: [] };
59
- });
60
-
61
- afterEach(() => {
62
- delete process.env.MINIMAL_AGENT_CWD;
63
- _resetWorkingDir();
64
- rmSync(tmp, { recursive: true, force: true });
65
- });
66
-
67
- it('tool 失败 → 恢复 agent 救回 → workflow 继续到 done + capture 绑定', async () => {
68
- // 恢复 agent 的 LLM:无 tool_calls,直接给出最终文本 'fixed-it'
69
- mock.module('../../../src/llm/client.js', () => ({
70
- chat: async function* () {
71
- yield { type: 'text_delta', delta: 'fixed-' };
72
- yield { type: 'text_delta', delta: 'it' };
73
- yield { type: 'done', stopReason: 'stop' };
74
- },
75
- }));
76
-
77
- const def: WorkflowDef = {
78
- name: 'recover-ok',
79
- description: '让一个失败的步骤被恢复 agent 救回',
80
- steps: [
81
- {
82
- id: 's1',
83
- tool: 'NoSuchTool9999',
84
- onError: 'recover',
85
- capture: { content: 'msg' },
86
- },
87
- // capture 绑定成功(msg='fixed-it')则此 assert 通过
88
- { id: 'check', type: 'assert', condition: 'msg == "fixed-it"' },
89
- ],
90
- };
91
- const events = await collect(runWorkflow(def, {}, ctx));
92
-
93
- // 恢复成功 → 工作流跑完
94
- expect(events.some((e) => e.type === 'workflow_done')).toBe(true);
95
- // 全程无致命 error(恢复吸收了失败 + check 通过)
96
- expect(events.some((e) => e.type === 'error')).toBe(false);
97
- // 恢复前响亮告知:一条 warning 说明在自适应恢复
98
- const warn = events.find(
99
- (e): e is { type: 'warning'; message: string } => e.type === 'warning',
100
- );
101
- expect(warn).toBeDefined();
102
- expect(warn!.message).toContain('自适应恢复');
103
- // s1 的 step_end 是 ok:true 且 output 标注 recovered
104
- const s1End = events.find(
105
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_end' }> =>
106
- e.type === 'workflow_step_end' && e.id === 's1',
107
- );
108
- expect(s1End?.ok).toBe(true);
109
- expect(s1End?.output).toContain('recovered');
110
- });
111
-
112
- it('恢复也失败 → honest halt(error + 无 done,后续步骤不跑)', async () => {
113
- // 恢复 agent 的 LLM 直接抛错 → miniReAct 抛 → runRecovery 返回 null → halt
114
- mock.module('../../../src/llm/client.js', () => ({
115
- chat: async function* () {
116
- throw new Error('llm 暂时不可用');
117
- // eslint-disable-next-line no-unreachable
118
- yield { type: 'done', stopReason: 'stop' };
119
- },
120
- }));
121
-
122
- const def: WorkflowDef = {
123
- name: 'recover-fail',
124
- description: '恢复也救不回',
125
- steps: [
126
- { id: 's1', tool: 'NoSuchTool9999', onError: 'recover' },
127
- { id: 'after', type: 'assert', condition: 'true' }, // 不应执行
128
- ],
129
- };
130
- const events = await collect(runWorkflow(def, {}, ctx));
131
-
132
- expect(events.some((e) => e.type === 'error')).toBe(true);
133
- expect(events.some((e) => e.type === 'workflow_done')).toBe(false);
134
- // 尝试过恢复(有 warning)
135
- expect(
136
- events.some((e) => e.type === 'warning' && e.message.includes('自适应恢复')),
137
- ).toBe(true);
138
- // 恢复失败后 halt,后续步骤 after 从未 start
139
- const startedIds = events
140
- .filter(
141
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_start' }> =>
142
- e.type === 'workflow_step_start',
143
- )
144
- .map((e) => e.id);
145
- expect(startedIds).not.toContain('after');
146
- });
147
-
148
- it('onError 默认(halt) → 不触发恢复(recover 是 opt-in,老行为不变)', async () => {
149
- const def: WorkflowDef = {
150
- name: 'default-halt',
151
- description: '默认 halt 不应起恢复',
152
- steps: [
153
- { id: 's1', tool: 'NoSuchTool9999' }, // 无 onError
154
- { id: 'after', type: 'assert', condition: 'true' },
155
- ],
156
- };
157
- const events = await collect(runWorkflow(def, {}, ctx));
158
-
159
- expect(events.some((e) => e.type === 'error')).toBe(true);
160
- expect(events.some((e) => e.type === 'workflow_done')).toBe(false);
161
- // 关键:没有任何「自适应恢复」warning → 证明恢复未被触发
162
- expect(
163
- events.some((e) => e.type === 'warning' && e.message.includes('自适应恢复')),
164
- ).toBe(false);
165
- });
166
-
167
- it('恢复 agent 显式放弃(__RECOVERY_GIVEUP__)→ honest halt 且错误带原因', async () => {
168
- // 恢复 agent 没真做成、按约定输出唯一放弃标记 + 原因
169
- mock.module('../../../src/llm/client.js', () => ({
170
- chat: async function* () {
171
- yield {
172
- type: 'text_delta',
173
- delta: '__AGENT_GIVEUP__: 端口被占且无法更换',
174
- };
175
- yield { type: 'done', stopReason: 'stop' };
176
- },
177
- }));
178
-
179
- const def: WorkflowDef = {
180
- name: 'recover-giveup',
181
- description: '恢复 agent 诚实放弃',
182
- steps: [
183
- {
184
- id: 's1',
185
- tool: 'NoSuchTool9999',
186
- onError: 'recover',
187
- capture: { content: 'msg' },
188
- },
189
- { id: 'after', type: 'assert', condition: 'true' }, // 不应执行
190
- ],
191
- };
192
- const events = await collect(runWorkflow(def, {}, ctx));
193
-
194
- // 显式放弃 → halt(不绑脏值、不继续)
195
- expect(events.some((e) => e.type === 'workflow_done')).toBe(false);
196
- const err = events.find(
197
- (e): e is { type: 'error'; error: string } => e.type === 'error',
198
- );
199
- expect(err).toBeDefined();
200
- // 放弃原因透传进 halt 文案,且标注是自适应恢复未成功
201
- expect(err!.error).toContain('端口被占');
202
- expect(err!.error).toContain('自适应恢复未成功');
203
- // 确实尝试过恢复
204
- expect(
205
- events.some((e) => e.type === 'warning' && e.message.includes('自适应恢复')),
206
- ).toBe(true);
207
- // s1 落 ok:false;after 从未 start
208
- const s1End = events.find(
209
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_end' }> =>
210
- e.type === 'workflow_step_end' && e.id === 's1',
211
- );
212
- expect(s1End?.ok).toBe(false);
213
- const startedIds = events
214
- .filter(
215
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_start' }> =>
216
- e.type === 'workflow_step_start',
217
- )
218
- .map((e) => e.id);
219
- expect(startedIds).not.toContain('after');
220
- });
221
-
222
- it('恢复 agent 产出为空 → 不绑脏值、honest halt(禁伪造闸门)', async () => {
223
- // 既不调工具、也不给任何文本 → 空产出。验证闸门必须拦下,不能当「救回」。
224
- mock.module('../../../src/llm/client.js', () => ({
225
- chat: async function* () {
226
- yield { type: 'done', stopReason: 'stop' };
227
- },
228
- }));
229
-
230
- const def: WorkflowDef = {
231
- name: 'recover-empty',
232
- description: '空产出不该被当成救回',
233
- steps: [
234
- {
235
- id: 's1',
236
- tool: 'NoSuchTool9999',
237
- onError: 'recover',
238
- capture: { content: 'msg' },
239
- },
240
- { id: 'after', type: 'assert', condition: 'true' }, // 不应执行
241
- ],
242
- };
243
- const events = await collect(runWorkflow(def, {}, ctx));
244
-
245
- expect(events.some((e) => e.type === 'workflow_done')).toBe(false);
246
- const err = events.find(
247
- (e): e is { type: 'error'; error: string } => e.type === 'error',
248
- );
249
- expect(err).toBeDefined();
250
- expect(err!.error).toContain('没有产出');
251
- // s1 ok:false;空串没有被绑进 msg 后继续(after 从未 start)
252
- const s1End = events.find(
253
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_end' }> =>
254
- e.type === 'workflow_step_end' && e.id === 's1',
255
- );
256
- expect(s1End?.ok).toBe(false);
257
- const startedIds = events
258
- .filter(
259
- (e): e is Extract<WorkflowEvent, { type: 'workflow_step_start' }> =>
260
- e.type === 'workflow_step_start',
261
- )
262
- .map((e) => e.id);
263
- expect(startedIds).not.toContain('after');
264
- });
265
- });