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,109 +1,59 @@
1
1
  /**
2
2
  * ============================================================
3
- * plugins/workflow-runner/src/index.ts —— /workflow 与 /workflows 命令的胶水层
3
+ * plugins/workflow-runner/src/index.ts —— /workflow 与 /workflows 的命令胶水
4
4
  * ------------------------------------------------------------
5
- * 作为 pluginRunner 与 runner 之间的桥:
6
- * - runWorkflowFromCommand:解析 /workflow <name> --input k=v args 调度
7
- * - runWorkflowsList:处理 /workflows 列表展示(yield "text" 事件让 UI 显示)
5
+ * 工作流只有一种形态:`workflows/<name>/workflow.mjs`。
8
6
  *
9
- * R1 红线:本文件只在 pluginRunner 命中 workflow 模式时才被 import。
10
- * 不污染默认 T-A-O-R 路径。
7
+ * 这里曾有一段「找不到就回落到 legacy yaml 引擎」的迁移期分支,随 yaml 引擎
8
+ * 一起删除了 —— 现在找不到就是找不到,直接报错并让用户看 /workflows。
11
9
  * ============================================================
12
10
  */
13
11
 
14
- import {
15
- type LoopEvent,
16
- type Message,
17
- type PluginContext,
18
- type Provider,
19
- type Tool,
20
- buildBaseSystemPrompt,
12
+ import { existsSync } from 'node:fs';
13
+ import { resolve } from 'node:path';
14
+ import { managedCommandController } from '../../../src/managedExecution/registry.js';
15
+ import type {
16
+ AgentRuntimeContext,
17
+ ContextBundle,
18
+ LoopEvent,
19
+ Message,
20
+ PluginContext,
21
+ PromptCacheContext,
22
+ Provider,
23
+ SessionState,
24
+ Tool,
21
25
  } from '../../../src/plugin-sdk.js';
22
- import { findWorkflowByName, listWorkflows } from './loader.js';
23
- import { runWorkflow } from './runner.js';
24
- import type { InputDef, RunContext, WorkflowEvent } from './types.js';
26
+ import { refreshStableSystemPrompt } from '../../../src/plugin-sdk.js';
27
+ import { discoverWorkflows } from './discovery.js';
28
+ import { coerceInputs } from './inputCoercion.js';
29
+ import { bindResourceInputs } from './resourceInputs.js';
30
+ import { runWorkflowScript } from './runner.js';
31
+ import type { InputDef, RunContext } from './types.js';
25
32
 
26
33
  export interface RunWorkflowFromCommandOptions {
27
34
  provider: Provider;
28
- runtimeContext?: import('../../../src/plugin-sdk.js').AgentRuntimeContext;
35
+ runtimeContext?: AgentRuntimeContext;
29
36
  history: Message[];
30
37
  signal?: AbortSignal;
31
- /** 会话状态(驱动 microCompact / reactiveCompact) */
32
- sessionState?: import('../../../src/plugin-sdk.js').SessionState;
33
- /** 当前工作目录(默认 process.cwd()) */
38
+ sessionState?: SessionState;
34
39
  cwd?: string;
35
- /** 宿主过滤后的可用工具列表;缺省为空,绝不在 runner 内恢复全量工具。 */
36
40
  tools?: Tool[];
37
41
  transientContext?: string;
38
- transientBundle?: import('../../../src/plugin-sdk.js').ContextBundle;
39
- promptCache?: import('../../../src/plugin-sdk.js').PromptCacheContext;
42
+ transientBundle?: ContextBundle;
43
+ promptCache?: PromptCacheContext;
40
44
  executeTool?: PluginContext['executeTool'];
41
45
  toolContext?: RunContext['toolContext'];
42
- /**
43
- * 宿主授权上下文(浏览器 / 电脑操控)。
44
- *
45
- * 引擎**不会**无条件把它转给每一步 —— 只有显式写了 `uses:` 的步骤才拿得到对应那片
46
- * (见 `StepDef.uses`)。一份 yaml 无人值守地跑,隐式全权是危险的。
47
- */
48
- host?: import('../../../src/plugin-sdk.js').PluginContext['host'];
46
+ host?: PluginContext['host'];
47
+ inputResources?: PluginContext['inputResources'];
48
+ /** 传给外层控制器的不透明上下文;Workflow Runner 不解释。 */
49
+ managedContext?: unknown;
49
50
  }
50
51
 
51
52
  /**
52
- * 把 "/workflow <name> [pos1 pos2 ...] [--input k=v ...]" 拆成 name + 显式 inputs + 位置参数。
53
- * 简单解析器(不依赖第三方):
54
- * - 第一个非 flag token = name;末尾 ".yaml" / ".yml" 自动剥(便于直接用文件名)
55
- * - 之后所有非 flag token 收进 positional[],由调用方按 def.inputs 声明顺序映射
56
- * - --input k=v 显式 KV,优先级高于位置参数(同名 input 不会被位置参数覆盖)
57
- * - 不识别其他 flag(保守跳过其后一个 token)
58
- */
59
- export function parseWorkflowArgs(rawArgs: string): {
60
- name: string | null;
61
- inputs: Record<string, string>;
62
- positional: string[];
63
- } {
64
- const tokens = tokenizeArgs(rawArgs);
65
- const inputs: Record<string, string> = {};
66
- const positional: string[] = [];
67
- let name: string | null = null;
68
- for (let i = 0; i < tokens.length; i++) {
69
- const t = tokens[i];
70
- if (t === '--input') {
71
- const kv = tokens[i + 1];
72
- if (!kv) break;
73
- const eq = kv.indexOf('=');
74
- if (eq > 0) {
75
- inputs[kv.slice(0, eq)] = kv.slice(eq + 1);
76
- }
77
- i++;
78
- continue;
79
- }
80
- if (t.startsWith('--')) {
81
- // 未知 flag:跳过其后一个 token(保守地认为它带值)
82
- i++;
83
- continue;
84
- }
85
- if (name === null) {
86
- name = t.replace(/\.ya?ml$/i, '');
87
- } else {
88
- positional.push(t);
89
- }
90
- }
91
- return { name, inputs, positional };
92
- }
93
-
94
- /**
95
- * shell 风格 token 化:空白切分 token;引号(' 或 ")在 token **任意位置**(不只开头)
96
- * 出现即进入引号模式——引号内的空白不切分、引号字符本身被剥离。
97
- *
98
- * 修复:`--input topic="带空格的值"`(引号在 `=` 后,token 开头是 `t`)曾被按空白
99
- * 硬切 → 值截断 + 引号残留(实测 inputs.topic 带 `"` 尾,positional 里散落被拆的字)。
100
- * 现在 token 内任意位置的引号都正确分组。
53
+ * shell 风格 token 化:引号在 token **任意位置**出现即进入引号模式。
101
54
  *
102
- * 边界语义(被 parseWorkflowArgs.test.ts 冻结):
103
- * - 未闭合引号:剩余部分并入当前 token(不报错)
104
- * - 双引号内的单引号是字面量(不触发嵌套)
105
- * - 反斜杠不转义(`a\"b` 中 `"` 仍开启引号模式,行为变化但测试用 toBeDefined 容错)
106
- * - 连续空白合并、`""` 产生空 token
55
+ * 自 legacy 移植。`--input topic="带空格的值"` 里引号在 `=` 之后、token 开头是 `t`,
56
+ * 只认「开头引号」的写法会把值截断并留下引号残留 —— 这是实测过的。
107
57
  */
108
58
  function tokenizeArgs(s: string): string[] {
109
59
  const out: string[] = [];
@@ -115,11 +65,10 @@ function tokenizeArgs(s: string): string[] {
115
65
  while (i < s.length) {
116
66
  const c = s[i];
117
67
  if (c === '"' || c === "'") {
118
- // 引号模式:收集到闭合引号,引号内空白保留
119
68
  const q = c;
120
69
  i++;
121
70
  while (i < s.length && s[i] !== q) acc += s[i++];
122
- if (i < s.length) i++; // 跳过闭合引号
71
+ if (i < s.length) i++;
123
72
  } else if (/\s/.test(c)) {
124
73
  break;
125
74
  } else {
@@ -132,172 +81,225 @@ function tokenizeArgs(s: string): string[] {
132
81
  return out;
133
82
  }
134
83
 
84
+ export function parseWorkflowArgs(rawArgs: string): {
85
+ name: string | null;
86
+ inputs: Record<string, string>;
87
+ positional: string[];
88
+ } {
89
+ const tokens = tokenizeArgs(rawArgs);
90
+ const inputs: Record<string, string> = {};
91
+ const positional: string[] = [];
92
+ let name: string | null = null;
93
+ for (let i = 0; i < tokens.length; i++) {
94
+ const t = tokens[i];
95
+ if (t === '--input') {
96
+ const kv = tokens[i + 1];
97
+ if (!kv) break;
98
+ const eq = kv.indexOf('=');
99
+ if (eq > 0) inputs[kv.slice(0, eq)] = kv.slice(eq + 1);
100
+ i++;
101
+ continue;
102
+ }
103
+ if (t.startsWith('--')) {
104
+ i++; // 未知 flag:保守跳过其后一个 token(认为它带值)
105
+ continue;
106
+ }
107
+ if (name === null) name = t.replace(/\.ya?ml$/i, '');
108
+ else positional.push(t);
109
+ }
110
+ return { name, inputs, positional };
111
+ }
112
+
135
113
  /**
136
- * 把字符串形态的 input 值按 InputDef.type 转成合适的 JS 类型 + 校验。
137
- * 校验失败抛 Error,pluginRunner 会把它转成 error event。
114
+ * 位置参数 → inputs 映射。
115
+ * **贪婪首参**(`inputs[0].greedy`):名后全部位置参数空格 join 进首参,不逐位拆。
116
+ * 存在理由是真实事故:不贪婪时用户打一句自然语言会被空格拆碎,第二段撞上
117
+ * number 类型的输入报「必须是数字」。
138
118
  */
139
- function coerceInputs(
140
- raw: Record<string, string>,
119
+ function mapPositional(
120
+ rawInputs: Record<string, string>,
121
+ positional: string[],
141
122
  defs: InputDef[] | undefined,
142
- ): Record<string, unknown> {
143
- const out: Record<string, unknown> = {};
144
- if (!defs) return { ...raw };
123
+ cwd = process.cwd(),
124
+ ): string[] {
125
+ const warnings: string[] = [];
126
+ if (!defs || positional.length === 0) return warnings;
145
127
 
146
- for (const def of defs) {
147
- const rawVal = raw[def.name];
148
- if (rawVal === undefined) {
149
- if (def.required) {
150
- throw new Error(`缺少必填 input: ${def.name}`);
151
- }
152
- if (def.default !== undefined) {
153
- out[def.name] = def.default;
128
+ if (defs[0]?.greedy === true) {
129
+ const name = defs[0].name;
130
+ if (defs[0].type === 'resource' && !(name in rawInputs)) {
131
+ // A Desktop invocation commonly has a natural-language tail after the
132
+ // command and no textual path. Do not mistake that tail for a file.
133
+ const first = positional[0] ?? '';
134
+ const looksLikePath =
135
+ existsSync(resolve(cwd, first)) ||
136
+ first.startsWith('/') ||
137
+ first.startsWith('\\') ||
138
+ /^[A-Za-z]:[\\/]/.test(first) ||
139
+ first.startsWith('~/') ||
140
+ first.startsWith('~\\') ||
141
+ first.startsWith('./') ||
142
+ first.startsWith('.\\') ||
143
+ first.startsWith('../') ||
144
+ first.startsWith('..\\') ||
145
+ /\.[A-Za-z0-9]{1,16}$/.test(first);
146
+ if (!looksLikePath) {
147
+ if (positional.length) rawInputs.requestText = positional.join(' ');
148
+ return warnings;
154
149
  }
155
- continue;
150
+ rawInputs[name] = first;
151
+ if (positional.length > 1)
152
+ rawInputs.requestText = positional.slice(1).join(' ');
153
+ return warnings;
154
+ }
155
+ if (defs[0]?.type === 'resource' && name in rawInputs) {
156
+ if (positional.length) rawInputs.requestText = positional.join(' ');
157
+ return warnings;
158
+ }
159
+ if (name in rawInputs) {
160
+ // 含空格的值没加引号会被 shell 拆开(只有第一段进 KV,其余散落成位置参数)。
161
+ // 静默丢弃曾把整段中文主题截成半句,连锁触发仲裁误判。这里拼回去并告警。
162
+ rawInputs[name] = [rawInputs[name], ...positional].join(' ');
163
+ warnings.push(
164
+ `${name}:--input 值未加引号被拆成 ${positional.length} 段,已自动拼回(下次请写 --input "${name}=完整值")`,
165
+ );
166
+ } else {
167
+ rawInputs[name] = positional.join(' ');
156
168
  }
157
- if (def.type === 'number') {
158
- const n = Number.parseFloat(rawVal);
159
- if (Number.isNaN(n))
160
- throw new Error(`input ${def.name} 必须是数字,收到 "${rawVal}"`);
161
- out[def.name] = n;
162
- } else if (def.type === 'enum') {
163
- if (!def.values?.includes(rawVal)) {
164
- throw new Error(
165
- `input ${def.name} 必须是 [${def.values?.join(', ')}] 之一,收到 "${rawVal}"`,
169
+ return warnings;
170
+ }
171
+
172
+ const max = Math.min(positional.length, defs.length);
173
+ for (let i = 0; i < max; i++) {
174
+ const def = defs[i];
175
+ if (def.name in rawInputs) {
176
+ if (rawInputs[def.name] !== positional[i]) {
177
+ warnings.push(
178
+ `--input 优先级高于位置参数:${def.name} 取 ${JSON.stringify(rawInputs[def.name])},位置参数 ${JSON.stringify(positional[i])} 被忽略`,
166
179
  );
167
180
  }
168
- out[def.name] = rawVal;
169
181
  } else {
170
- out[def.name] = rawVal;
182
+ rawInputs[def.name] = positional[i];
171
183
  }
172
184
  }
173
- // 未声明的 input 也透传(让 yaml 里可以引用 ad-hoc 变量)
174
- for (const k of Object.keys(raw)) {
175
- if (!(k in out)) out[k] = raw[k];
176
- }
177
- return out;
178
- }
179
-
180
- async function refreshWorkflowSystemPrompt(
181
- history: Message[],
182
- cwd: string,
183
- tools: Tool[],
184
- ): Promise<void> {
185
- // 只刷稳定层:workflow 一跑就是几十步,system 消息若含日期/记忆等易变内容,
186
- // 每步都会重写 history[0]、把 provider 前缀缓存打散(见 prompts/system.ts)。
187
- const content = await buildBaseSystemPrompt(cwd, tools);
188
- const systemIndex = history.findIndex(
189
- (m) => m.role === 'system' && !m._ephemeral,
190
- );
191
- const fresh: Message = { role: 'system', content };
192
-
193
- if (systemIndex === 0) {
194
- history[0] = fresh;
195
- return;
185
+ if (positional.length > defs.length) {
186
+ const dropped = positional.slice(defs.length);
187
+ warnings.push(
188
+ `忽略了 ${dropped.length} 个多余位置参数:${dropped.map((d) => JSON.stringify(d)).join(' ')}`,
189
+ );
196
190
  }
197
-
198
- if (systemIndex > 0) history.splice(systemIndex, 1);
199
- history.unshift(fresh);
191
+ return warnings;
200
192
  }
201
193
 
202
- /** /workflow <name> [pos...] [--input k=v] —— 主入口,由 pluginRunner 调用。 */
194
+ /** `/workflow <name> …` 主入口。 */
203
195
  export async function* runWorkflowFromCommand(
204
196
  rawArgs: string,
205
197
  opts: RunWorkflowFromCommandOptions,
206
- ): AsyncGenerator<WorkflowEvent | LoopEvent, void, void> {
198
+ ): AsyncGenerator<LoopEvent, void, void> {
207
199
  const { name, inputs: rawInputs, positional } = parseWorkflowArgs(rawArgs);
208
200
  if (!name) {
209
201
  yield {
210
202
  type: 'error',
211
203
  error:
212
- '/workflow 用法: /workflow <name> [val ...] [--input key=val ...]\n输入 /workflows 查看可用工作流。',
213
- };
214
- return;
215
- }
216
- const def = await findWorkflowByName(name);
217
- if (!def) {
218
- yield {
219
- type: 'error',
220
- error: `未找到 workflow "${name}"。输入 /workflows 查看可用列表。`,
204
+ '/workflow 用法:/workflow <name> [值 ...] [--input key=值 ...]\n输入 /workflows 查看可用工作流。',
221
205
  };
222
206
  return;
223
207
  }
224
208
 
225
209
  const cwd = opts.cwd ?? process.cwd();
226
210
  const tools = opts.tools ?? [];
227
- await refreshWorkflowSystemPrompt(opts.history, cwd, tools);
211
+ const { workflows, failures } = await discoverWorkflows(cwd);
212
+ const script = workflows.find((w) => w.name === name);
228
213
 
229
- // 位置参数映射,两种模式:
230
- // - 贪婪首参(def.inputs[0].greedy===true):把【全部】位置参数用空格 join 成整句写进
231
- // 首个 input(自然语言 brief 不被空格拆碎、也不会撞上后面的 number/enum 输入),
232
- // 其余 input 只走 --input。用户「打一句话」即可(见 webppt.yaml::topic)。
233
- // - 默认:严格按"第 i 个位置参数 ↔ def.inputs[i]"对应。
234
- // --input k=v 显式优先:已显式的 input 不被位置参数覆盖(对应位置参数被丢弃,会 warn)。
235
- const overriddenByKV: string[] = [];
236
- const greedyNotes: string[] = [];
237
- const greedyFirst = def.inputs?.[0]?.greedy === true;
238
- if (greedyFirst && def.inputs && positional.length > 0) {
239
- const greedyName = def.inputs[0].name;
240
- if (greedyName in rawInputs) {
241
- // 首参已由 --input 提供时,位置参数仍按贪婪语义【拼回】首参末尾--
242
- // 含空格的值未加引号时会被 shell 拆开(--input topic=A B C 只有 A 进 KV,
243
- // B C 散落成位置参数),静默丢弃曾把整段中文调研主题截成半句、
244
- // 连锁触发任务仲裁误判 new-task 清空全部产物。
245
- rawInputs[greedyName] = [rawInputs[greedyName], ...positional].join(' ');
246
- greedyNotes.push(
247
- `${greedyName}:--input 值未加引号被拆成 ${positional.length} 段位置参数,已自动拼回(下次请写 --input "${greedyName}=完整值")`,
248
- );
249
- } else {
250
- // 贪婪吸收:整句进首参(空格 join 还原用户原话,不逐位拆映射)
251
- rawInputs[greedyName] = positional.join(' ');
214
+ if (!script) {
215
+ const broken = failures.find((f) => f.name === name);
216
+ if (broken) {
217
+ // 「有但写错了」与「没有」必须区分开 —— 否则用户会去找一个并不存在的拼写问题。
218
+ yield {
219
+ type: 'error',
220
+ error: `工作流「${name}」存在但写错了:\n${broken.errors.map((e) => ` · ${e}`).join('\n')}`,
221
+ };
222
+ return;
252
223
  }
253
- } else if (positional.length > 0 && def.inputs) {
254
- const max = Math.min(positional.length, def.inputs.length);
255
- for (let i = 0; i < max; i++) {
256
- const inputDef = def.inputs[i];
257
- if (inputDef.name in rawInputs) {
258
- // 已被 --input 占位,位置参数被丢弃
259
- if (rawInputs[inputDef.name] !== positional[i]) {
260
- overriddenByKV.push(
261
- `${inputDef.name}=${JSON.stringify(rawInputs[inputDef.name])} (位置参数 ${JSON.stringify(positional[i])} 被忽略)`,
262
- );
263
- }
264
- } else {
265
- rawInputs[inputDef.name] = positional[i];
266
- }
267
- }
268
- }
269
-
270
- // warn:超量位置参数(仅非 greedy 模式;greedy 全部吸收进首参,不算多余)
271
- if (!greedyFirst && def.inputs && positional.length > def.inputs.length) {
272
- const dropped = positional.slice(def.inputs.length);
273
- yield {
274
- type: 'warning',
275
- message: `⚠ 忽略了 ${dropped.length} 个多余位置参数: ${dropped.map((d) => JSON.stringify(d)).join(' ')}(workflow "${name}" 只声明了 ${def.inputs.length} 个 input)`,
276
- };
277
- }
278
- // warn:贪婪首参的 --input 值被 shell 拆开后自动拼回
279
- if (greedyNotes.length > 0) {
280
224
  yield {
281
- type: 'warning',
282
- message: `⚠ ${greedyNotes.join(';')}`,
225
+ type: 'error',
226
+ error: `未找到工作流「${name}」。输入 /workflows 查看可用列表。`,
283
227
  };
228
+ return;
284
229
  }
285
- // warn:位置参数被 --input 覆盖
286
- if (overriddenByKV.length > 0) {
287
- yield {
288
- type: 'warning',
289
- message: `⚠ --input 优先级高于位置参数,以下位置参数被覆盖:${overriddenByKV.join('; ')}`,
290
- };
230
+
231
+ await refreshStableSystemPrompt(opts.history, cwd, tools);
232
+
233
+ for (const w of mapPositional(
234
+ rawInputs,
235
+ positional,
236
+ script.meta.inputs,
237
+ cwd,
238
+ )) {
239
+ yield { type: 'warning', message: `⚠ ${w}` };
291
240
  }
292
241
 
293
- let coerced: Record<string, unknown>;
242
+ const sessionId = opts.runtimeContext?.sessionId ?? 'default';
243
+ let inputs: Record<string, unknown>;
244
+ let inputResourceMap: Record<
245
+ string,
246
+ import('../../../src/plugin-sdk.js').InvocationResource[]
247
+ > = {};
248
+ let resourceFingerprint = '';
294
249
  try {
295
- coerced = coerceInputs(rawInputs, def.inputs);
250
+ const bound = await bindResourceInputs({
251
+ workflowName: script.name,
252
+ sessionId,
253
+ cwd,
254
+ rawInputs,
255
+ defs: script.meta.inputs,
256
+ attachments: opts.inputResources,
257
+ });
258
+ for (const warning of bound.warnings)
259
+ yield {
260
+ type: 'plugin_progress',
261
+ pluginId: 'workflow-runner',
262
+ message: warning,
263
+ };
264
+ inputResourceMap = bound.resourceMap as typeof inputResourceMap;
265
+ resourceFingerprint = bound.resourceIdentity.join('|');
266
+ if (resourceFingerprint)
267
+ bound.inputs.__resource_fingerprint = resourceFingerprint;
268
+ inputs = coerceInputs(
269
+ bound.inputs as Record<string, string>,
270
+ script.meta.inputs,
271
+ );
296
272
  } catch (e) {
297
273
  yield { type: 'error', error: (e as Error).message };
298
274
  return;
299
275
  }
300
276
 
277
+ let preparedManaged:
278
+ | import('../../../src/managedExecution/types.js').PreparedManagedCommand
279
+ | undefined;
280
+ if (script.meta.managedRuntime) {
281
+ const controller = managedCommandController(script.meta.managedRuntime);
282
+ if (!controller) {
283
+ yield {
284
+ type: 'error',
285
+ error: `未知 managedRuntime:${script.meta.managedRuntime}`,
286
+ };
287
+ return;
288
+ }
289
+ preparedManaged = await controller(inputs, {
290
+ cwd,
291
+ runtimeContext: opts.runtimeContext,
292
+ context: opts.managedContext,
293
+ });
294
+ for (const event of preparedManaged.events) yield event;
295
+ if (preparedManaged.handled) return;
296
+ inputs = preparedManaged.inputs;
297
+ // A managed controller may normalize/replace public inputs, but it must not
298
+ // erase the resource component of task identity.
299
+ if (resourceFingerprint && !inputs.__resource_fingerprint)
300
+ inputs.__resource_fingerprint = resourceFingerprint;
301
+ }
302
+
301
303
  const ctx: RunContext = {
302
304
  provider: opts.provider,
303
305
  runtimeContext: opts.runtimeContext,
@@ -312,53 +314,50 @@ export async function* runWorkflowFromCommand(
312
314
  promptCache: opts.promptCache,
313
315
  executeTool: opts.executeTool,
314
316
  toolContext: opts.toolContext,
317
+ managedExecution: preparedManaged?.execution,
318
+ managedBridge: preparedManaged?.bridge,
319
+ inputResources: opts.inputResources,
320
+ inputResourceMap,
315
321
  };
316
322
 
317
- // 透传 runWorkflow 的事件,并观察是否出现终结事件(error / interrupted = 失败或中断,
318
- // 与 gateway broker 的 TERMINAL 判定同一套逻辑)。成功(没见到终结事件)则在末尾补一条
319
- // 通用 `turn_done`,让对外流式协议以通用终结事件收口——否则成功 workflow 只发私有
320
- // workflow_done:gateway TERMINAL 不认它 → 子进程关闭时误补 interrupted;
321
- // `-p --output-format json` 因无 turn_done → stop_reason 兜底 error → ok:false(成功却报失败)。
322
- // 与 runWorkflowsList 末尾的 turn_done 是同一约定;失败/中断不补(error/interrupted 已是终结)。
323
- let sawTerminal = false;
324
- for await (const ev of runWorkflow(def, coerced, ctx)) {
325
- if (ev.type === 'error' || ev.type === 'interrupted') sawTerminal = true;
326
- yield ev;
327
- }
328
- if (!sawTerminal) yield { type: 'turn_done' };
323
+ yield* runWorkflowScript(script, { ctx, inputs });
329
324
  }
330
325
 
331
- /** /workflows —— 列出可用 workflow。yield 一条 text 事件让 UI 显示。 */
332
- export async function* runWorkflowsList(): AsyncGenerator<
333
- LoopEvent,
334
- void,
335
- void
336
- > {
337
- const list = await listWorkflows();
338
- if (list.length === 0) {
339
- yield {
340
- type: 'text',
341
- delta:
342
- '当前没有可用工作流。在 cwd/workflows/ 下放 *.yaml 即可(参考 workflows/schema.json 或 docs/workflow-design.md)。\n',
343
- };
344
- yield { type: 'turn_done' };
345
- return;
326
+ /** `/workflows` —— 列出可用工作流,并如实报出写错的那些。 */
327
+ export async function* runWorkflowsList(
328
+ cwd?: string,
329
+ ): AsyncGenerator<LoopEvent, void, void> {
330
+ const { workflows, failures } = await discoverWorkflows(cwd);
331
+ const lines: string[] = [];
332
+
333
+ if (workflows.length > 0) {
334
+ lines.push('可用工作流:');
335
+ for (const w of workflows) {
336
+ lines.push(
337
+ ` /workflow ${w.name} — ${w.meta.description.split('\n')[0].trim()}`,
338
+ );
339
+ }
346
340
  }
347
- const lines = ['可用工作流:'];
348
- for (const w of list) {
341
+
342
+ if (workflows.length === 0) {
349
343
  lines.push(
350
- ` /workflow ${w.name} — ${w.description.split('\n')[0].trim()}`,
344
+ '当前没有可用工作流。在 workflows/<名字>/workflow.mjs 放一个脚本即可(`/skill workflow-creator` 会带你写)。',
351
345
  );
352
346
  }
347
+
348
+ // 写错的工作流必须报出来 —— 静默消失会让用户以为「我的工作流不见了」。
349
+ if (failures.length > 0) {
350
+ lines.push('');
351
+ lines.push(`⚠ 有 ${failures.length} 个工作流写错了,未能载入:`);
352
+ for (const f of failures) {
353
+ lines.push(` · ${f.name}:${f.errors[0]}`);
354
+ }
355
+ }
356
+
353
357
  lines.push('');
354
- lines.push('运行示例:');
355
- lines.push(
356
- ' /workflow <name> <val> 位置参数(按 inputs 声明顺序,第一个 input 直接写值)',
357
- );
358
- lines.push(' /workflow <name>.yaml <val> .yaml 后缀可省');
359
- lines.push(
360
- ' /workflow <name> --input k=v 显式 KV(多 input 或想跳过中间 input 时用)',
361
- );
358
+ lines.push('运行示例:');
359
+ lines.push(' /workflow <name> <值> 位置参数(按 inputs 声明顺序)');
360
+ lines.push(' /workflow <name> --input k=v 显式 KV');
362
361
  yield { type: 'text', delta: `${lines.join('\n')}\n` };
363
362
  yield { type: 'turn_done' };
364
363
  }
@@ -0,0 +1,40 @@
1
+ export function coerceInputs(raw, defs) {
2
+ const out = {};
3
+ if (!defs)
4
+ return { ...raw };
5
+ for (const def of defs) {
6
+ const rawVal = raw[def.name];
7
+ if (rawVal === undefined) {
8
+ if (def.required)
9
+ throw new Error(`缺少必填 input: ${def.name}`);
10
+ if (def.default !== undefined)
11
+ out[def.name] = def.default;
12
+ continue;
13
+ }
14
+ if (def.type === 'number') {
15
+ const n = typeof rawVal === 'number' || typeof rawVal === 'string'
16
+ ? Number(rawVal)
17
+ : Number.NaN;
18
+ if (!Number.isFinite(n) ||
19
+ (typeof rawVal === 'string' && !rawVal.trim())) {
20
+ throw new Error(`input ${def.name} 必须是数字,收到 "${rawVal}"`);
21
+ }
22
+ out[def.name] = n;
23
+ }
24
+ else if (def.type === 'enum') {
25
+ if (typeof rawVal !== 'string' || !def.values?.includes(rawVal)) {
26
+ throw new Error(`input ${def.name} 必须是 [${def.values?.join(', ')}] 之一,收到 "${rawVal}"`);
27
+ }
28
+ out[def.name] = rawVal;
29
+ }
30
+ else {
31
+ if (typeof rawVal !== 'string')
32
+ throw new Error(`input ${def.name} 必须是字符串`);
33
+ out[def.name] = rawVal;
34
+ }
35
+ }
36
+ for (const k of Object.keys(raw))
37
+ if (!(k in out))
38
+ out[k] = raw[k];
39
+ return out;
40
+ }