minimal-agent 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +503 -0
  103. package/src/advisor/advisorCoordinator.ts +657 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/streamJson.js +5 -6
  108. package/src/cli/streamJson.ts +8 -4
  109. package/src/cli/wizards/advisorWizard.js +4 -2
  110. package/src/cli/wizards/advisorWizard.tsx +8 -2
  111. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  112. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  113. package/src/collaboration/taskFlow.js +115 -0
  114. package/src/collaboration/taskFlow.ts +169 -0
  115. package/src/config/configDefaults.js +41 -1
  116. package/src/config/configDefaults.ts +43 -1
  117. package/src/config/configDiagnostics.ts +2 -2
  118. package/src/config/configFile.js +40 -9
  119. package/src/config/configFile.ts +60 -11
  120. package/src/config/configService.js +419 -74
  121. package/src/config/configService.ts +703 -145
  122. package/src/config/numericLimits.js +22 -0
  123. package/src/config/numericLimits.ts +24 -0
  124. package/src/config.js +1 -0
  125. package/src/config.ts +3 -2
  126. package/src/context/budgetPlan.js +1 -1
  127. package/src/context/budgetPlan.ts +1 -1
  128. package/src/context/compact.js +7 -2
  129. package/src/context/compact.ts +9 -2
  130. package/src/context/microCompactLite.js +212 -13
  131. package/src/context/microCompactLite.ts +261 -12
  132. package/src/context/sessionRegistry.js +8 -1
  133. package/src/context/sessionRegistry.ts +18 -5
  134. package/src/context/toolResultArchive.js +72 -0
  135. package/src/context/toolResultArchive.ts +95 -0
  136. package/src/goal/errors.js +8 -0
  137. package/src/goal/errors.ts +18 -0
  138. package/src/goal/goalRuntime.js +344 -0
  139. package/src/goal/goalRuntime.ts +466 -0
  140. package/src/goal/goalStore.js +200 -0
  141. package/src/goal/goalStore.ts +219 -0
  142. package/src/goal/index.js +4 -0
  143. package/src/goal/index.ts +4 -0
  144. package/src/goal/statusMapping.js +71 -0
  145. package/src/goal/statusMapping.ts +95 -0
  146. package/src/goal/types.js +7 -0
  147. package/src/goal/types.ts +179 -0
  148. package/src/goal/workflowController.js +306 -0
  149. package/src/goal/workflowController.ts +360 -0
  150. package/src/harness/evidenceLedger.js +2 -0
  151. package/src/harness/evidenceLedger.ts +1 -0
  152. package/src/harness/stallGuard.js +9 -3
  153. package/src/harness/stallGuard.ts +7 -3
  154. package/src/images/imageResolver.js +161 -0
  155. package/src/images/imageResolver.ts +189 -0
  156. package/src/infra/verification.js +34 -5
  157. package/src/infra/verification.ts +39 -4
  158. package/src/llm/client.js +79 -21
  159. package/src/llm/client.ts +182 -35
  160. package/src/llm/gatewayClient.js +201 -0
  161. package/src/llm/gatewayClient.ts +299 -0
  162. package/src/llm/messageProvenance.js +46 -0
  163. package/src/llm/messageProvenance.ts +58 -0
  164. package/src/llm/modelProvider.js +1 -0
  165. package/src/llm/modelProvider.ts +22 -0
  166. package/src/llm/providers/anthropicFormat.js +108 -1
  167. package/src/llm/providers/anthropicFormat.ts +115 -4
  168. package/src/llm/providers/openaiFormat.js +9 -0
  169. package/src/llm/providers/openaiFormat.ts +12 -3
  170. package/src/loop.js +319 -54
  171. package/src/loop.ts +373 -57
  172. package/src/main.js +4 -1
  173. package/src/main.tsx +4 -1
  174. package/src/managedExecution/index.js +2 -0
  175. package/src/managedExecution/index.ts +2 -0
  176. package/src/managedExecution/registry.js +15 -0
  177. package/src/managedExecution/registry.ts +20 -0
  178. package/src/managedExecution/types.js +1 -0
  179. package/src/managedExecution/types.ts +86 -0
  180. package/src/modelRef.js +9 -0
  181. package/src/modelRef.ts +31 -0
  182. package/src/multimodal.js +14 -28
  183. package/src/multimodal.ts +17 -33
  184. package/src/net/lanDiscovery.js +65 -0
  185. package/src/net/lanDiscovery.ts +82 -0
  186. package/src/plugin-sdk.js +28 -3
  187. package/src/plugin-sdk.ts +39 -6
  188. package/src/plugins/pluginApi.ts +16 -1
  189. package/src/plugins/pluginLoader.js +4 -0
  190. package/src/plugins/pluginLoader.ts +6 -0
  191. package/src/plugins/pluginRunner.js +139 -7
  192. package/src/plugins/pluginRunner.ts +173 -9
  193. package/src/plugins/slashFallback.js +113 -0
  194. package/src/plugins/slashFallback.ts +137 -0
  195. package/src/prompts/policyRegistry.js +12 -32
  196. package/src/prompts/policyRegistry.ts +15 -32
  197. package/src/prompts/promptAssembly.js +103 -12
  198. package/src/prompts/promptAssembly.ts +114 -12
  199. package/src/prompts/skillList.js +21 -3
  200. package/src/prompts/skillList.ts +27 -2
  201. package/src/prompts/stableSystemPrompt.js +18 -0
  202. package/src/prompts/stableSystemPrompt.ts +33 -0
  203. package/src/runtime/agentRuntimeContext.js +8 -2
  204. package/src/runtime/agentRuntimeContext.ts +17 -4
  205. package/src/session/runAgentTurn.js +78 -12
  206. package/src/session/runAgentTurn.ts +105 -23
  207. package/src/session/runTurn.js +10 -9
  208. package/src/session/runTurn.ts +17 -8
  209. package/src/session/sessionState.ts +2 -0
  210. package/src/team/auth.js +186 -0
  211. package/src/team/auth.ts +298 -0
  212. package/src/team/cli.js +105 -0
  213. package/src/team/cli.ts +122 -0
  214. package/src/team/onlineToolContract.js +64 -0
  215. package/src/team/onlineToolContract.ts +109 -0
  216. package/src/team/toolPolicy.js +36 -0
  217. package/src/team/toolPolicy.ts +75 -0
  218. package/src/tools/advisor/advisor.js +90 -46
  219. package/src/tools/advisor/advisor.ts +100 -47
  220. package/src/tools/advisor/advisorDecision.js +71 -0
  221. package/src/tools/advisor/advisorDecision.ts +85 -0
  222. package/src/tools/agent/agent.js +18 -5
  223. package/src/tools/agent/agent.ts +21 -7
  224. package/src/tools/agent/agentControl.js +246 -0
  225. package/src/tools/agent/agentControl.ts +284 -0
  226. package/src/tools/agent/agentTaskService.js +40 -1
  227. package/src/tools/agent/agentTaskService.ts +44 -1
  228. package/src/tools/agent/agentTypes.js +14 -2
  229. package/src/tools/agent/agentTypes.ts +15 -2
  230. package/src/tools/applypatch/applyPatch.js +362 -0
  231. package/src/tools/applypatch/applyPatch.ts +428 -0
  232. package/src/tools/bash/bash.js +22 -15
  233. package/src/tools/bash/bash.ts +23 -17
  234. package/src/tools/capabilities.js +10 -5
  235. package/src/tools/capabilities.ts +10 -5
  236. package/src/tools/computeruse/computerIntent.js +32 -0
  237. package/src/tools/computeruse/computerIntent.ts +46 -0
  238. package/src/tools/computeruse/telemetryLog.js +12 -0
  239. package/src/tools/computeruse/telemetryLog.ts +16 -0
  240. package/src/tools/computeruse/vision/telemetry.js +1 -0
  241. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  242. package/src/tools/effectiveToolSet.js +4 -0
  243. package/src/tools/effectiveToolSet.ts +4 -0
  244. package/src/tools/index.js +21 -2
  245. package/src/tools/index.ts +33 -2
  246. package/src/tools/presentresult/presentresult.js +6 -15
  247. package/src/tools/presentresult/presentresult.ts +6 -15
  248. package/src/tools/read/read.js +62 -9
  249. package/src/tools/read/read.ts +63 -9
  250. package/src/tools/shared/fileUtils.js +1 -2
  251. package/src/tools/shared/fileUtils.ts +1 -2
  252. package/src/tools/shared/toolOutputStore.js +23 -1
  253. package/src/tools/shared/toolOutputStore.ts +22 -1
  254. package/src/tools/skill/skill.js +9 -3
  255. package/src/tools/skill/skill.ts +8 -4
  256. package/src/tools/toolPromptGuides.js +117 -0
  257. package/src/tools/toolPromptGuides.ts +137 -0
  258. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  259. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  260. package/src/tools/webbrowser/browser.js +27 -11
  261. package/src/tools/webbrowser/browser.ts +68 -24
  262. package/src/tools/webbrowser/browserAutomation.js +329 -0
  263. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  264. package/src/tools/webbrowser/browserAxState.js +97 -0
  265. package/src/tools/webbrowser/browserAxState.ts +142 -0
  266. package/src/tools/webbrowser/browserBatch.js +1578 -0
  267. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  268. package/src/tools/webbrowser/browserCdp.js +208 -0
  269. package/src/tools/webbrowser/browserCdp.ts +255 -0
  270. package/src/tools/webbrowser/browserConditions.js +24 -0
  271. package/src/tools/webbrowser/browserConditions.ts +45 -0
  272. package/src/tools/webbrowser/browserContent.js +281 -0
  273. package/src/tools/webbrowser/browserContent.ts +438 -0
  274. package/src/tools/webbrowser/browserControl.js +131 -34
  275. package/src/tools/webbrowser/browserControl.ts +210 -56
  276. package/src/tools/webbrowser/browserDaemon.js +22 -14
  277. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  278. package/src/tools/webbrowser/browserFrames.js +47 -0
  279. package/src/tools/webbrowser/browserFrames.ts +54 -0
  280. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  281. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  282. package/src/tools/webbrowser/browserLocator.js +140 -0
  283. package/src/tools/webbrowser/browserLocator.ts +194 -0
  284. package/src/tools/webbrowser/browserOutcome.js +10 -17
  285. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  286. package/src/tools/webbrowser/browserRecovery.js +58 -0
  287. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  288. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  289. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  290. package/src/tools/webbrowser/browserService.js +28 -2
  291. package/src/tools/webbrowser/browserService.ts +49 -9
  292. package/src/tools/webbrowser/browserStream.js +132 -33
  293. package/src/tools/webbrowser/browserStream.ts +224 -50
  294. package/src/tools/webbrowser/browserTabs.js +48 -15
  295. package/src/tools/webbrowser/browserTabs.ts +178 -96
  296. package/src/tools/webbrowser/webbrowser.js +679 -144
  297. package/src/tools/webbrowser/webbrowser.ts +975 -236
  298. package/src/tools/webfetch/preapproved.js +0 -2
  299. package/src/tools/webfetch/preapproved.ts +0 -2
  300. package/src/tools/websearch/websearch.js +129 -8
  301. package/src/tools/websearch/websearch.ts +138 -6
  302. package/src/types.ts +440 -38
  303. package/src/ui/App.js +377 -58
  304. package/src/ui/App.tsx +576 -111
  305. package/src/ui/LiveArea.js +14 -8
  306. package/src/ui/LiveArea.tsx +14 -10
  307. package/src/ui/MessageList.js +63 -20
  308. package/src/ui/MessageList.tsx +101 -16
  309. package/src/ui/ModelPicker.js +7 -4
  310. package/src/ui/ModelPicker.tsx +55 -8
  311. package/src/ui/hooks/useChat.js +152 -163
  312. package/src/ui/hooks/useChat.ts +396 -334
  313. package/src/ui/loginCommand.js +56 -0
  314. package/src/ui/loginCommand.ts +63 -0
  315. package/src/ui/toolProgress.js +41 -0
  316. package/src/ui/toolProgress.ts +44 -0
  317. package/src/web/browserBridge.js +20 -2
  318. package/src/web/browserBridge.ts +20 -2
  319. package/src/web/protocol.ts +1897 -194
  320. package/workflows/adaptive-research/workflow.mjs +86 -0
  321. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  322. package/workflows/e2e-llm/workflow.mjs +52 -0
  323. package/workflows/e2e-smoke/workflow.mjs +59 -0
  324. package/workflows/e2e-vision-schema/README.md +48 -0
  325. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  326. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  327. package/workflows/file-census/README.md +14 -0
  328. package/workflows/file-census/scripts/.gitkeep +2 -0
  329. package/workflows/file-census/workflow.mjs +110 -0
  330. package/workflows/goal/README.md +166 -0
  331. package/workflows/goal/prompts/audit.md +57 -0
  332. package/workflows/goal/prompts/contract.md +56 -0
  333. package/workflows/goal/prompts/iterate.md +37 -0
  334. package/workflows/goal/workflow.mjs +501 -0
  335. package/workflows/illustrate/README.md +90 -0
  336. package/workflows/illustrate/assets/engines.json +20 -0
  337. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  338. package/workflows/illustrate/assets/extract-bing.js +33 -0
  339. package/workflows/illustrate/assets/extract-google.js +31 -0
  340. package/workflows/illustrate/workflow.mjs +301 -0
  341. package/workflows/plan/workflow.mjs +389 -0
  342. package/workflows/question-crops/README.md +35 -0
  343. package/workflows/question-crops/prompts/inventory.md +23 -0
  344. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  345. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  346. package/workflows/question-crops/workflow.mjs +172 -0
  347. package/workflows/ralph-loop/workflow.mjs +162 -0
  348. package/workflows/research/README.md +74 -0
  349. package/workflows/research/prompts/s0-goal.md +43 -0
  350. package/workflows/research/prompts/s1-early-exit.md +22 -0
  351. package/workflows/research/prompts/s1-map.md +58 -0
  352. package/workflows/research/prompts/s2-options.md +53 -0
  353. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  354. package/workflows/research/prompts/s4-verify.md +74 -0
  355. package/workflows/research/prompts/s5-synthesis.md +81 -0
  356. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  357. package/workflows/research/prompts/s6-package.md +32 -0
  358. package/workflows/research/scripts/build-report.mjs +98 -0
  359. package/workflows/research/workflow.mjs +288 -0
  360. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  361. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  362. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  363. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  364. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  365. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  366. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  367. package/workflows/wrong-question-docx/README.md +55 -0
  368. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  369. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  370. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  371. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  372. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  373. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  374. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  375. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  376. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  377. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  378. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  379. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  380. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  381. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  382. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  383. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  384. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  385. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  386. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  387. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  388. package/plugins/workflow-runner/src/expressions.js +0 -639
  389. package/plugins/workflow-runner/src/expressions.ts +0 -640
  390. package/plugins/workflow-runner/src/loader.js +0 -573
  391. package/plugins/workflow-runner/src/loader.ts +0 -721
  392. package/plugins/workflow-runner/src/multimodal.js +0 -38
  393. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  394. package/plugins/workflow-runner/src/recovery.js +0 -126
  395. package/plugins/workflow-runner/src/recovery.ts +0 -156
  396. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  397. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  398. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  399. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  400. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  401. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  402. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  403. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  404. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  405. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  406. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  407. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  408. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  409. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  410. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  411. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  412. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  413. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  414. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  415. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  416. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  417. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  418. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  419. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  420. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  421. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  422. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  423. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  424. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  425. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  426. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  427. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  428. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  429. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  430. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  431. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  432. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  433. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  434. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  435. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  436. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  437. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  438. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  439. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  440. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  441. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  442. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  443. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  444. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  445. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  446. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  447. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  448. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  449. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  450. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  451. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  452. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  453. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  454. package/src/advisorState.js +0 -22
  455. package/src/cli/configWizard.js +0 -293
  456. package/src/tools/toolProgressBridge.js +0 -48
  457. package/workflows/adaptive-research.yaml +0 -50
  458. package/workflows/book-review-short.yaml +0 -125
  459. package/workflows/e2e-write-greet.yaml +0 -31
  460. package/workflows/illustrate.yaml +0 -227
  461. package/workflows/plan.yaml +0 -470
  462. package/workflows/ppt.yaml +0 -1670
  463. package/workflows/ralph-loop.yaml +0 -201
  464. package/workflows/research.yaml +0 -873
  465. package/workflows/schema.json +0 -176
  466. package/workflows/webppt.yaml +0 -496
  467. package/workflows/wechat-reading-shots.yaml +0 -315
  468. package/workflows/word.yaml +0 -720
  469. package/workflows/youtube-shorts.yaml +0 -202
  470. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -1,274 +0,0 @@
1
- /**
2
- * ============================================================
3
- * plugins/workflow-runner/src/stepExecutors/tool.ts —— tool step 执行
4
- * ------------------------------------------------------------
5
- * 把 step.args 递归 ${var} 插值后 JSON.stringify,转发到 executeTool。
6
- * 失败(ok=false)抛 Error,让 runner 走 onError 处理。
7
- *
8
- * v2(P1 TUI 可见):本执行器改为 AsyncGenerator,在调 executeTool 前后
9
- * yield 通用 tool_start / tool_end LoopEvent —— 这样 workflow 的 tool 步骤
10
- * 在 TUI 里像普通 ReAct 工具调用一样显示(runningTools spinner + 人话描述)。
11
- *
12
- * v0.9.3(上下文统一修复):tool 步骤执行后把工具调用摘要写入 ctx.history,
13
- * 让后续 agent/llm/skill 步骤(走 runQuery → LLM)能自然看到前面步骤的工作成果,
14
- * 不再依赖 VarStack 变量插值作为唯一的信息传递通道。
15
- * 这实现了"一套上下文"架构:workflow 的每一步都在共享的 TAOR history 中留痕。
16
- *
17
- * capture 字段(支持点路径):
18
- * - `{ content: var_name }` 绑 ToolResult.content(工具回执文本)
19
- * - `{ result: var_name }` 同义,给"无结构化字段"工具用
20
- * - `{ args.content: var_name }` 绑插值后传给工具的入参(如真正写入的内容)
21
- * - `{ args.<任意字段>: var_name }` 绑入参的具名字段
22
- * ============================================================
23
- */
24
-
25
- import { randomUUID } from 'node:crypto';
26
- import { existsSync } from 'node:fs';
27
- import { resolve } from 'node:path';
28
-
29
- import {
30
- type LoopEvent,
31
- type ToolResult,
32
- executeTool,
33
- getToolByName,
34
- recordRead,
35
- } from '../../../../src/plugin-sdk.js';
36
- import { interpolateDeep } from '../expressions.js';
37
- import {
38
- buildWorkflowToolContext,
39
- effectiveWorkflowCwd,
40
- } from '../toolRuntime.js';
41
- import { safeArtifactPath, type RunContext, type StepDef, type StepResult, type VarStack } from '../types.js';
42
-
43
- export async function* execToolStep(
44
- step: StepDef,
45
- vars: VarStack,
46
- ctx: RunContext,
47
- ): AsyncGenerator<LoopEvent, StepResult, void> {
48
- if (!step.tool) throw new Error(`step ${step.id}: 缺少 tool 字段`);
49
- const tool = getToolByName(step.tool);
50
- if (!tool) throw new Error(`step ${step.id}: 未知工具 "${step.tool}"`);
51
- if (!ctx.tools.some((available) => available.name === tool.name)) {
52
- throw new Error(
53
- `step ${step.id}: 工具 "${tool.name}" 不在当前宿主授权的 Workflow 工具集中`,
54
- );
55
- }
56
-
57
- // 未定义变量插值可见化(args 里静默空串会让工具拿到空路径/空内容)
58
- const missing: string[] = [];
59
- const args = interpolateDeep(step.args ?? {}, vars, {
60
- onMissing: (e) => missing.push(e),
61
- });
62
- if (missing.length > 0) {
63
- yield {
64
- type: 'warning',
65
- message: `step "${step.id}": 模板变量未定义,已按空串插值:${[...new Set(missing)].map((m) => `\${${m}}`).join('、')}(裸名请用 inputs.<name> 或先 capture/set)`,
66
- };
67
- }
68
- const argsJson = JSON.stringify(args);
69
- const toolCallId = `wf_${step.id}`;
70
- const argsPreview =
71
- argsJson.length > 80 ? `${argsJson.slice(0, 80)}…` : argsJson;
72
-
73
- yield {
74
- type: 'tool_start',
75
- toolName: tool.name,
76
- toolCallId,
77
- argsPreview,
78
- argsFriendly: friendlyToolDesc(tool.name, args as Record<string, unknown>),
79
- };
80
-
81
- // ════ 声明产物覆盖判定(解 Write/Edit 的 pre-read 守卫) ════
82
- // 内核写类工具有「文件已存在必须先 Read」守卫(fileState 按会话隔离,
83
- // 跨进程 / resume / 残留旧产物时可能为空)。确定性 tool 步的 args 是 yaml 作者
84
- // 写死的,模型没有机会先 Read —— 目标文件若是工作流**声明的产物**
85
- // (def 级 + step 级 artifacts:,= 工作流自己拥有、本就要覆盖的文件),
86
- // 这里自动 pre-Read 一次解除守卫(管线动作,不 yield 事件、结果丢弃)。
87
- // 非声明产物的盲写保护原样生效;pre-Read 失败也不拦,让写工具自己报错。
88
- await preReadDeclaredArtifact(
89
- tool,
90
- args as Record<string, unknown>,
91
- step,
92
- ctx,
93
- );
94
-
95
- // 宿主能力按 `uses:` 切片后转发。`executeTool` 的第四参此前从未传过 ——
96
- // 这正是「workflow 里 ComputerUse 恒失败」的末端表现。
97
- const pendingProgress: LoopEvent[] = [];
98
- let wakeProgress: (() => void) | undefined;
99
- const toolContext = buildWorkflowToolContext(
100
- step,
101
- ctx,
102
- toolCallId,
103
- (message, detail) => {
104
- pendingProgress.push({
105
- type: 'tool_progress',
106
- toolName: tool.name,
107
- toolCallId,
108
- message,
109
- detail,
110
- });
111
- wakeProgress?.();
112
- },
113
- );
114
- if ('error' in toolContext) {
115
- throw new Error(`step ${step.id}: ${toolContext.error}`);
116
- }
117
-
118
- const dispatch = ctx.executeTool ?? executeTool;
119
- let settled = false;
120
- let result: ToolResult | undefined;
121
- void dispatch(tool.name, argsJson, ctx.signal, toolContext)
122
- .then((value) => {
123
- result = value;
124
- })
125
- .catch((error: unknown) => {
126
- result = {
127
- ok: false,
128
- error: error instanceof Error ? error.message : String(error),
129
- };
130
- })
131
- .finally(() => {
132
- settled = true;
133
- wakeProgress?.();
134
- });
135
-
136
- while (!settled || pendingProgress.length > 0) {
137
- const progress = pendingProgress.shift();
138
- if (progress) {
139
- yield progress;
140
- continue;
141
- }
142
- await new Promise<void>((resolveWake) => {
143
- wakeProgress = resolveWake;
144
- if (settled || pendingProgress.length > 0) resolveWake();
145
- });
146
- wakeProgress = undefined;
147
- }
148
- if (!result) throw new Error(`step ${step.id}: 工具执行未返回结果`);
149
-
150
- yield {
151
- type: 'tool_end',
152
- toolName: tool.name,
153
- toolCallId,
154
- ok: result.ok,
155
- content: result.ok ? result.content : result.error,
156
- metadata: result.metadata,
157
- };
158
-
159
- if (!result.ok) {
160
- throw new Error(result.error);
161
- }
162
- const content = result.content;
163
-
164
- // ════ v0.9.3:上下文统一 —— 把工具调用写入共享 history ════
165
- // 后续 agent/llm/skill 步骤走 runQuery() 时,LLM 能在上下文中看到
166
- // 这步做了什么(与正常 TAOR 循环中 tool_call → tool_result 的记录方式一致)。
167
- // 只记录精简摘要(不把完整工具回执塞入 history,避免 token 浪费)。
168
- const summary =
169
- content.length > 500
170
- ? `${content.slice(0, 500)}…(已截断,共 ${content.length} 字符)`
171
- : content;
172
- ctx.history.push({
173
- role: 'assistant',
174
- content: `[workflow:${step.id}] ✅ ${tool.name} 执行完成:${summary}`,
175
- timestamp: Date.now(),
176
- id: randomUUID(),
177
- });
178
-
179
- // ⚠️ 工具返回的图片**不能丢**。此前这里只取 content,`visionImages` 被静默丢弃 ——
180
- // 于是任何「截图/看图」类工作流都拿不到产物,而且不会报错,只是后面的评估步没图可看。
181
- // 取路径而不是整个 ImageInputSpec:yaml 侧要的是能 capture、能传给 llm 步 `images:`
182
- // 的字符串;结构体传下去反而要每个消费方各自解包。
183
- const images = (result.visionImages ?? [])
184
- .map((image) => (typeof image.source === 'string' ? image.source : ''))
185
- .filter((path) => path.length > 0);
186
-
187
- return {
188
- raw: {
189
- content,
190
- result: content,
191
- args,
192
- images,
193
- metadata: result.metadata,
194
- recovery: result.recovery,
195
- sensitivity: result.sensitivity,
196
- visionNote: result.visionNote,
197
- },
198
- preview: content.length > 200 ? `${content.slice(0, 200)}...` : content,
199
- };
200
- }
201
-
202
- /**
203
- * 写类 tool 步的目标文件若命中【安全的声明产物】且已存在 → pre-Read 解除内核守卫。
204
- *
205
- * 路径归一化:artifacts 声明相对 cwd;args.file_path 可能是 ./相对 或 绝对,
206
- * 双方都 resolve(cwd, …) 后比较(win32 文件系统大小写不敏感 → lowercase 比较;
207
- * 其余平台保持大小写敏感,避免 Plan.md / plan.md 误判同文件)。
208
- *
209
- * 安全守卫(修复路径遍历):
210
- * · 声明的 artifacts 路径先经 safeArtifactPath 校验【必须落在 cwd 内】,
211
- * 越界声明直接从命中列表移除——不解守卫,让内核写保护照常生效(fail-closed)。
212
- * · args.file_path 目标自身也做 cwd 内校验:目标越界(工作流步骤想写 cwd 外)
213
- * → 同样不解守卫,让写工具在执行时自己报错(通常是权限/文件不存在提示,
214
- * 而不是静默放行盲写,双重保险)。
215
- */
216
- async function preReadDeclaredArtifact(
217
- tool: { name: string; isReadOnly?: boolean },
218
- args: Record<string, unknown>,
219
- step: StepDef,
220
- ctx: RunContext,
221
- ): Promise<void> {
222
- if (tool.isReadOnly !== false) return; // 只对写类工具生效
223
- if (typeof args.file_path !== 'string') return;
224
-
225
- const cwd = effectiveWorkflowCwd(ctx);
226
- const norm = (p: string): string => {
227
- const abs = resolve(cwd, p);
228
- return process.platform === 'win32' ? abs.toLowerCase() : abs;
229
- };
230
-
231
- // 1. 目标文件先过 cwd 安全关(越界直接不解守卫)
232
- const targetRaw = String(args.file_path);
233
- const targetSafe = safeArtifactPath(cwd, targetRaw);
234
- if (targetSafe === null) return;
235
- const target = norm(targetSafe);
236
-
237
- // 2. 声明产物过 cwd 安全关(过滤掉越界的声明)
238
- const rawDeclared = [...(ctx.declaredArtifacts ?? []), ...(step.artifacts ?? [])];
239
- const declaredAbs: string[] = [];
240
- for (const raw of rawDeclared) {
241
- const safe = safeArtifactPath(cwd, raw);
242
- if (safe !== null) declaredAbs.push(norm(safe));
243
- }
244
- if (!declaredAbs.some((a) => a === target)) return;
245
-
246
- const abs = resolve(cwd, targetSafe);
247
- if (!existsSync(abs)) return; // 新建文件不需要解守卫
248
-
249
- // 直接登记一次「完整已读」状态解除内核 pre-read 守卫——不真正 Read 内容:
250
- // 1. 声明产物本就要被本步整体覆盖,旧内容无需进上下文/烧 token;
251
- // 2. 真 Read 大文件会触发字符上限截断(read.ts → recordRead({truncated:true})),
252
- // 反而踩中 Write 的「截断禁写」硬守卫(write.ts: existsSync && wasTruncated → 拒绝),
253
- // 正是本步要解除的同一道墙——曾导致 plan.yaml 回写变长的 PLAN.md 时 halt
254
- // (首轮新建 PLAN.md 不存在直接放行,审批反馈后回写已存在的大 PLAN.md 被挡死)。
255
- // 两道守卫(never-read + truncated)必须一并解除,声明产物的整体覆盖才算真正授权。
256
- // recordRead 内部自带 statSync 失败兜底(返回 1、不抛),无需再包 try/catch。
257
- recordRead(abs, { truncated: false }, ctx.sessionState?.fileReads);
258
- }
259
-
260
- /**
261
- * 给 tool_start 生成人话描述(LiveArea spinner 行用)。
262
- */
263
- function friendlyToolDesc(
264
- toolName: string,
265
- args: Record<string, unknown>,
266
- ): string {
267
- const key = ['file_path', 'command', 'query', 'pattern', 'path', 'url'].find(
268
- (k) => typeof args[k] === 'string',
269
- );
270
- if (!key) return toolName;
271
- const val = String(args[key]);
272
- const short = val.length > 60 ? `${val.slice(0, 60)}…` : val;
273
- return `${toolName} ${short}`;
274
- }
@@ -1,61 +0,0 @@
1
- /**
2
- * ============================================================
3
- * plugins/workflow-runner/src/stepExecutors/verify.ts —— verify step 执行
4
- * ------------------------------------------------------------
5
- * 复用内核共享验证基础设施(经 plugin-sdk 门面取 runVerification/parseCheckString),
6
- * 支持 shell / file_exists / file_contains / test_count 四种检查。
7
- *
8
- * 与 assert 的区别:
9
- * - assert: evalExpr 表达式(轻量,适合简单文件存在判断)
10
- * - verify: 完整检查器(重量,支持命令执行/正则匹配/测试计数)
11
- * ============================================================
12
- */
13
- import { parseCheckString, runVerification } from '../../../../src/plugin-sdk.js';
14
- import { interpolate } from '../expressions.js';
15
- import { effectiveWorkflowCwd } from '../toolRuntime.js';
16
- export async function execVerifyStep(step, vars, ctx) {
17
- // 兼容两种格式:YAML 数组 或逗号分隔字符串。
18
- // 关键:【先插值再按逗号分割】。checks 可能是 "${verify_checks}" 这类模板,插值后才
19
- // 展开成逗号分隔的多项(如 "shell:bun test,file_exists:x")。若先分割再插值,整段模板
20
- // 会被当成一项,解析时 value 混入逗号、多项检查失效(ralph-loop 的 run_verify 即如此)。
21
- let rawChecks;
22
- if (Array.isArray(step.checks) && step.checks.length > 0) {
23
- rawChecks = step.checks
24
- .flatMap((s) => interpolate(s, vars).split(','))
25
- .map((s) => s.trim())
26
- .filter(Boolean);
27
- }
28
- else if (typeof step.checks === 'string' && step.checks.trim() !== '') {
29
- rawChecks = interpolate(step.checks, vars)
30
- .split(',')
31
- .map((s) => s.trim())
32
- .filter(Boolean);
33
- }
34
- else {
35
- throw new Error(`step ${step.id}: verify 缺少 checks(需要数组或逗号分隔字符串)`);
36
- }
37
- // 解析每条已插值的 check 字符串(插值后若整体为空——如 ${verify_checks} 取到空串——
38
- // 则 checks 为空,runVerification 视为"无检查项"通过;ralph-loop 另有 when 守卫不会走到这)
39
- const checks = [];
40
- for (const raw of rawChecks) {
41
- const check = parseCheckString(raw);
42
- if (!check) {
43
- throw new Error(`step ${step.id}: 无法解析 check "${raw}",格式应为 "type:value"`);
44
- }
45
- checks.push(check);
46
- }
47
- // 执行所有检查。
48
- // cwd 必须和写入侧同源:会话进了 session worktree 时产物落在 worktree 里,
49
- // 验收若锚原 workspace 会在空目录找文件,恒判失败并触发无意义的重试。
50
- const result = await runVerification(checks, effectiveWorkflowCwd(ctx));
51
- if (!result.passed) {
52
- const msg = step.onFail
53
- ? interpolate(step.onFail, vars)
54
- : `verify 失败: ${result.summary}`;
55
- throw new Error(msg);
56
- }
57
- return {
58
- raw: { passed: true, summary: result.summary, details: result.details },
59
- preview: result.summary,
60
- };
61
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * ============================================================
3
- * plugins/workflow-runner/src/stepExecutors/verify.ts —— verify step 执行
4
- * ------------------------------------------------------------
5
- * 复用内核共享验证基础设施(经 plugin-sdk 门面取 runVerification/parseCheckString),
6
- * 支持 shell / file_exists / file_contains / test_count 四种检查。
7
- *
8
- * 与 assert 的区别:
9
- * - assert: evalExpr 表达式(轻量,适合简单文件存在判断)
10
- * - verify: 完整检查器(重量,支持命令执行/正则匹配/测试计数)
11
- * ============================================================
12
- */
13
-
14
- import { parseCheckString, runVerification, type Check } from '../../../../src/plugin-sdk.js';
15
- import { interpolate } from '../expressions.js';
16
- import { effectiveWorkflowCwd } from '../toolRuntime.js';
17
- import type { RunContext, StepDef, StepResult, VarStack } from '../types.js';
18
-
19
- export async function execVerifyStep(
20
- step: StepDef,
21
- vars: VarStack,
22
- ctx: RunContext,
23
- ): Promise<StepResult> {
24
- // 兼容两种格式:YAML 数组 或逗号分隔字符串。
25
- // 关键:【先插值再按逗号分割】。checks 可能是 "${verify_checks}" 这类模板,插值后才
26
- // 展开成逗号分隔的多项(如 "shell:bun test,file_exists:x")。若先分割再插值,整段模板
27
- // 会被当成一项,解析时 value 混入逗号、多项检查失效(ralph-loop 的 run_verify 即如此)。
28
- let rawChecks: string[];
29
- if (Array.isArray(step.checks) && step.checks.length > 0) {
30
- rawChecks = (step.checks as string[])
31
- .flatMap((s) => interpolate(s, vars).split(','))
32
- .map((s) => s.trim())
33
- .filter(Boolean);
34
- } else if (typeof step.checks === 'string' && step.checks.trim() !== '') {
35
- rawChecks = interpolate(step.checks as string, vars)
36
- .split(',')
37
- .map((s) => s.trim())
38
- .filter(Boolean);
39
- } else {
40
- throw new Error(`step ${step.id}: verify 缺少 checks(需要数组或逗号分隔字符串)`);
41
- }
42
-
43
- // 解析每条已插值的 check 字符串(插值后若整体为空——如 ${verify_checks} 取到空串——
44
- // 则 checks 为空,runVerification 视为"无检查项"通过;ralph-loop 另有 when 守卫不会走到这)
45
- const checks: Check[] = [];
46
- for (const raw of rawChecks) {
47
- const check = parseCheckString(raw);
48
- if (!check) {
49
- throw new Error(
50
- `step ${step.id}: 无法解析 check "${raw}",格式应为 "type:value"`,
51
- );
52
- }
53
- checks.push(check);
54
- }
55
-
56
- // 执行所有检查。
57
- // cwd 必须和写入侧同源:会话进了 session worktree 时产物落在 worktree 里,
58
- // 验收若锚原 workspace 会在空目录找文件,恒判失败并触发无意义的重试。
59
- const result = await runVerification(checks, effectiveWorkflowCwd(ctx));
60
-
61
- if (!result.passed) {
62
- const msg = step.onFail
63
- ? interpolate(step.onFail, vars)
64
- : `verify 失败: ${result.summary}`;
65
- throw new Error(msg);
66
- }
67
-
68
- return {
69
- raw: { passed: true, summary: result.summary, details: result.details },
70
- preview: result.summary,
71
- };
72
- }
@@ -1,277 +0,0 @@
1
- /**
2
- * ============================================================
3
- * stepPipeline.ts —— 「一步算完成」的唯一实现
4
- * ------------------------------------------------------------
5
- * ⚠️ 这个文件存在的理由是一次真实的架构事故。
6
- *
7
- * 重构前,「提交一步」这套动作(绑 capture → 累加目标补充 → 写 progress →
8
- * 落 vars → 记 checkpoint → 发 step_end)**没有单一实现**,被 `runSteps` 里的
9
- * 各个内联块各抄一份。抄到什么程度:
10
- *
11
- * recordCheckpoint × 7 appendProgress × 17
12
- * writeVars × 7 step_end 事件 × 19
13
- * bindCapture × 3 collectCaptured × 5
14
- *
15
- * 而且**已经漂移出真 bug**:7 处 checkpoint 里,`set` 传 `resolved`、
16
- * `echo` 传 `{}`、其余 5 处传 `collectCaptured(step.capture, vars)`。
17
- * 顺着查下去发现 `echo` / `set` 从不调 `bindCapture` ——
18
- * **它们静默忽略 `capture:`**:yaml 作者写了既不报错也不生效,
19
- * resume 时那个变量也回放不出来。又一次「静默失效」。
20
- *
21
- * 所以这里的规则是硬的:**任何 step 完成后都必须经过 `commitStep`。**
22
- * 新增 step 类型时不要再自己写这套 —— 抄一份就是又埋一颗漂移的种子。
23
- * `plugins/workflow-runner/test/stepPipeline.test.ts` 钉着这条。
24
- * ============================================================
25
- */
26
- import { isMaxTurnsCutoff } from './agentCommon.js';
27
- import { runRecovery } from './recovery.js';
28
- import { normalizeCapture } from './types.js';
29
- const WF_PLUGIN_ID = 'workflow-runner';
30
- /** 读 `a.b.c` 形式的嵌套字段。 */
31
- function readPath(root, path) {
32
- const parts = path.split('.');
33
- let cur = root;
34
- for (const p of parts) {
35
- if (cur == null || typeof cur !== 'object')
36
- return undefined;
37
- cur = cur[p];
38
- }
39
- return cur;
40
- }
41
- /**
42
- * 把本步产出绑到变量上,**并把「绑了个空」响亮说出来**。
43
- *
44
- * ⚠️ `capture` 的写法是 `{ 结果字段: 变量名 }`。写反了(`{ 变量名: 结果字段 }`)
45
- * 语法完全合法、加载期查不出来,运行时只是安静地绑一个 undefined —— 然后:
46
- * · `${varName}` 插值发一条「模板变量未定义」的 warning,但那条指向的是**使用处**,
47
- * 看着像是「后面那步写错了」,而真正错的是**几十行之前的 capture**
48
- * · 更糟的是 assert:条件直接判假,用户看到的是 onFail 里那段业务文案,
49
- * 与真实原因毫无关系,排查方向被彻底带偏
50
- *
51
- * 实测踩过两次(`adaptive-research.yaml` 绑 `content` 而 agent 步只有 `text`;
52
- * `wechat-reading-shots.yaml` 把 `text: pager` 写反成 `pager: text`)。
53
- */
54
- export function bindCapture(captureMap, result, vars, stepId) {
55
- const warnings = [];
56
- for (const [resultField, varName] of Object.entries(normalizeCapture(captureMap))) {
57
- const value = resultField.includes('.')
58
- ? readPath(result.raw, resultField)
59
- : result.raw[resultField];
60
- if (value === undefined) {
61
- const available = Object.keys(result.raw);
62
- warnings.push(`step "${stepId ?? '?'}": capture 取不到字段 \`${resultField}\`,变量 `
63
- + `\`${varName}\` 绑成了 undefined。本步实际可绑的字段:`
64
- + `${available.length ? available.map((k) => `\`${k}\``).join('、') : '(无)'}。`
65
- + `⚠️ 写法是 { 结果字段: 变量名 },检查是否写反了。`);
66
- }
67
- vars.set(varName, value);
68
- }
69
- return warnings;
70
- }
71
- /** 取本步 capture 出的 { varName: value },供 checkpoint 记录(resume 回放用)。 */
72
- export function collectCaptured(captureMap, vars) {
73
- if (!captureMap)
74
- return {};
75
- const out = {};
76
- for (const varName of Object.values(normalizeCapture(captureMap))) {
77
- out[varName] = vars.get(varName);
78
- }
79
- return out;
80
- }
81
- /** 从 StepResult 里取「可当作用户补充要求」的那段文本。 */
82
- function supplementTextOf(result) {
83
- return typeof result.raw.text === 'string' && result.raw.text.trim()
84
- ? result.raw.text
85
- : String(result.raw.result ?? result.preview ?? '');
86
- }
87
- /**
88
- * 提交一步:capture → goal_supplement → progress → vars → checkpoint → step_end。
89
- *
90
- * **所有 step 类型的唯一收口。** 见文件头注:抄第二份就是埋漂移。
91
- */
92
- export async function* commitStep(input) {
93
- const { step, result, kind, vars, state, cp } = input;
94
- if (step.capture) {
95
- for (const message of bindCapture(step.capture, result, vars, step.id)) {
96
- yield { type: 'warning', message };
97
- }
98
- }
99
- // goal_supplement:本步产出作为用户补充要求贯穿后续每一步(如 stage0 澄清结论)
100
- if (step.goal_supplement) {
101
- await input.addGoalSupplement(supplementTextOf(result));
102
- }
103
- await state.appendProgress(input.progressLine ?? `✓ ${step.id} (${kind})`);
104
- await state.writeVars(vars.snapshot());
105
- // checkpoint:记录范围见 CpScope(顶层步 + 顶层 loop 的 do[] 一层)。
106
- //
107
- // 回放变量 = 本步**引入的**变量(`replayVars`,目前只有 set)
108
- // + 作者**显式声明**要捕获的变量(`capture`)。
109
- // 两者不能互相替代:set 步通常没有 capture,只记 collectCaptured 会得到 {} ——
110
- // resume 跳过它之后下游断言就查不到那个变量了(engineRobustness 抓过这个回归)。
111
- if (cp) {
112
- await state.recordCheckpoint(cp.name(step.id), result.preview, { ...(result.replayVars ?? {}), ...collectCaptured(step.capture, vars) }, vars.snapshot());
113
- }
114
- yield {
115
- type: 'workflow_step_end',
116
- id: step.id,
117
- ok: true,
118
- output: result.preview,
119
- };
120
- }
121
- /** 可中断的 sleep:中断时立刻返回,不把整轮退避耗完。 */
122
- function sleepInterruptible(ms, signal) {
123
- return new Promise((res) => {
124
- if (signal?.aborted)
125
- return res();
126
- const t = setTimeout(done, ms);
127
- function done() {
128
- clearTimeout(t);
129
- signal?.removeEventListener('abort', done);
130
- res();
131
- }
132
- signal?.addEventListener('abort', done, { once: true });
133
- });
134
- }
135
- /**
136
- * 执行一个动作步:in-run 重试 → onError 三态 → 统一提交。
137
- *
138
- * 三条语义原样保留(都是实测踩出来的):
139
- * · `max_retries` 是**额外**重试次数,总尝试 = 1 + maxRetries
140
- * · 退避是**线性**的(delayBase × attempt);maxTurns 截断走 `max_turns_retry_delay_ms`,
141
- * 缺省 0 = 立即续跑(长文档类工作流才需要给模型端留恢复窗口)
142
- * · `onError:'recover'` 有**验证闸门**:只有恢复 agent 真正交付才绑 capture 走下去,
143
- * 显式放弃 / 产出不可信一律带原因 honest halt,绝不盲绑脏值
144
- */
145
- export async function* runStepWithRetry(input) {
146
- const { step, kind, vars, ctx, state, cp } = input;
147
- const maxRetries = step.max_retries ?? ctx.selfHealMaxRetries ?? 0;
148
- let attempt = 0;
149
- while (true) {
150
- try {
151
- const result = yield* input.execute();
152
- yield* commitStep({
153
- step,
154
- result,
155
- kind,
156
- vars,
157
- ctx,
158
- state,
159
- ...(cp ? { cp } : {}),
160
- addGoalSupplement: input.addGoalSupplement,
161
- });
162
- return 'ok';
163
- }
164
- catch (e) {
165
- const errMsg = e.message ?? String(e);
166
- // in-run retry:还有重试额度且未中断 → 重跑同一步(不动 onError)。
167
- if (attempt < maxRetries && !ctx.signal?.aborted) {
168
- attempt++;
169
- const isMaxTurns = isMaxTurnsCutoff(errMsg);
170
- const delayBase = isMaxTurns
171
- ? (ctx.maxTurnsRetryDelayMs ?? 0)
172
- : (ctx.retryDelayMs ?? 0);
173
- const delayMs = delayBase * attempt;
174
- const retryKind = isMaxTurns ? '轮数预算用尽,可续跑截断' : '失败';
175
- await state.appendProgress(isMaxTurns
176
- ? `↻ ${step.id}: 阶段轮数预算用尽,正在续跑 ${attempt}/${maxRetries}${delayMs > 0 ? `(${delayMs}ms 后)` : ''}`
177
- : `↻ ${step.id}: ${retryKind},重试 ${attempt}/${maxRetries}${delayMs > 0 ? `(${delayMs}ms 后)` : ''}(${errMsg})`);
178
- yield {
179
- type: 'warning',
180
- message: isMaxTurns
181
- ? `step "${step.id}" 阶段轮数预算用尽,正在续跑 ${attempt}/${maxRetries}${delayMs > 0 ? `(${delayMs}ms 后)` : ''}…`
182
- : `step "${step.id}" 失败:${errMsg};${delayMs > 0 ? `${delayMs}ms 后` : ''}重试 ${attempt}/${maxRetries}…`,
183
- };
184
- yield {
185
- type: 'plugin_progress',
186
- pluginId: WF_PLUGIN_ID,
187
- current: input.index + 1,
188
- max: input.total,
189
- message: isMaxTurns
190
- ? `↻ ${step.id} 阶段轮数预算用尽,正在续跑 ${attempt}/${maxRetries}…`
191
- : `↻ 重试 ${step.id} ${attempt}/${maxRetries}…`,
192
- };
193
- if (delayMs > 0)
194
- await sleepInterruptible(delayMs, ctx.signal);
195
- continue; // 重跑同一步
196
- }
197
- await state.appendProgress(`✗ ${step.id}: ${errMsg}`);
198
- // onError:'recover' —— retry 用尽仍失败,交给有界恢复 agent 随机应变把这一步救回来。
199
- // 「确定性工作流 × TAOR」的结合点:happy path 走刚性 DAG,撞上预料之外的就地
200
- // 降级为 agent 自适应;救回则继续 happy path,救不回才 honest halt。
201
- if (step.onError === 'recover') {
202
- yield {
203
- type: 'warning',
204
- message: `step "${step.id}" 失败:${errMsg};尝试自适应恢复…`,
205
- };
206
- yield {
207
- type: 'plugin_progress',
208
- pluginId: WF_PLUGIN_ID,
209
- current: input.index + 1,
210
- max: input.total,
211
- message: `↻ 恢复 ${step.id}…`,
212
- };
213
- const rec = yield* runRecovery(step, vars, ctx, errMsg);
214
- if (ctx.signal?.aborted) {
215
- yield { type: 'interrupted' };
216
- return 'halted';
217
- }
218
- // 验证闸门:只有恢复 agent 真正交付(rec.ok)才绑 capture 走下去;
219
- // 显式放弃 / 产出不可信(rec.ok=false)则带原因 honest halt,绝不盲绑脏值。
220
- if (rec.ok) {
221
- yield* commitStep({
222
- step,
223
- result: rec.value,
224
- kind,
225
- vars,
226
- ctx,
227
- state,
228
- ...(cp ? { cp } : {}),
229
- progressLine: `⚠→✓ ${step.id} recovered`,
230
- addGoalSupplement: input.addGoalSupplement,
231
- });
232
- return 'ok';
233
- }
234
- const combined = `${errMsg}(自适应恢复未成功:${rec.reason})`;
235
- if (cp)
236
- await state.recordFailure(step.id, combined);
237
- yield { type: 'workflow_step_end', id: step.id, ok: false, error: combined };
238
- yield {
239
- type: 'error',
240
- error: `Workflow halted at step "${step.id}": ${combined}`,
241
- };
242
- return 'halted';
243
- }
244
- if (step.onError === 'continue') {
245
- // 降级时给 capture 变量绑【明确占位文本】而非留空:空串静默内插进下游
246
- // prompt(如「已知需求分析:\n\n」)是更大的最小惊讶违例——模型看到
247
- // 空段会困惑。占位前缀「(上游步骤 」机器可识别;continue 本就是作者
248
- // 显式选择「无此内容也继续」,需要严格闸门的步骤应配 onError:halt 或 assert。
249
- if (step.capture) {
250
- const placeholder = `(上游步骤 ${step.id} 失败已降级(onError:continue),无内容——` +
251
- `请基于用户原始目标自行推断。错误:${errMsg.length > 120 ? `${errMsg.slice(0, 120)}…` : errMsg})`;
252
- for (const varName of Object.values(normalizeCapture(step.capture))) {
253
- vars.setGlobal(varName, placeholder);
254
- }
255
- }
256
- // 降级此前完全静默(仅 progress.md 有 ✗ 行)——补一条 warning 可见化
257
- yield {
258
- type: 'warning',
259
- message: `step "${step.id}" 失败已降级(onError:continue):${errMsg}`,
260
- };
261
- yield { type: 'workflow_step_end', id: step.id, ok: false, error: errMsg };
262
- return 'degraded';
263
- }
264
- const finalErrMsg = isMaxTurnsCutoff(errMsg)
265
- ? `${errMsg};重试额度已用尽,请拆分该步骤或提高 maxTurns。`
266
- : errMsg;
267
- if (cp)
268
- await state.recordFailure(step.id, finalErrMsg);
269
- yield { type: 'workflow_step_end', id: step.id, ok: false, error: finalErrMsg };
270
- yield {
271
- type: 'error',
272
- error: `Workflow halted at step "${step.id}": ${finalErrMsg}`,
273
- };
274
- return 'halted';
275
- }
276
- }
277
- }