minimal-agent 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
package/src/plugin-sdk.ts CHANGED
@@ -76,13 +76,17 @@ export { dlog } from './utils/debugLog.js';
76
76
  // <think> 思维链剥离:内核与 workflow-runner 共享(原住 agentCommon.ts,
77
77
  // Agent 子任务工具也需要 → 上移内核,插件经此 re-export)。
78
78
  export { stripThinkBlocks } from './utils/stripThink.js';
79
- // buildFullSystemPrompt is retained for compatibility. New long-running hosts should keep
80
- // buildBaseSystemPrompt stable and pass buildTransientContext separately for each turn.
79
+ // 长驻宿主保持 buildBaseSystemPrompt 稳定,每回合单独传 transient bundle。
80
+ // (`buildTransientContext` 曾也在这里 re-export,唯一消费者是已删除的 yaml 引擎;
81
+ // 门面每多一个导出就多一条不能自由重构的边,没消费者就先不导出。)
81
82
  export {
82
83
  buildBaseSystemPrompt,
83
- buildTransientContext,
84
84
  buildTransientPromptBundle,
85
85
  } from './prompts/system.js';
86
+ export {
87
+ refreshStableSystemPrompt,
88
+ upsertStableSystemMessage,
89
+ } from './prompts/stableSystemPrompt.js';
86
90
  export type { PromptEnvelope, PromptSurface } from './prompts/promptAssembly.js';
87
91
  export type { ContextBundle } from './context/contextBundle.js';
88
92
  export {
@@ -94,6 +98,10 @@ export type {
94
98
  } from './runtime/agentRuntimeContext.js';
95
99
  export { getResourceSearchPaths } from './utils/resourcePaths.js';
96
100
  export type { ResourceName } from './utils/resourcePaths.js';
101
+ // 「这个路径在不在那个目录里」的唯一实现——已经被手写错过好几次(含
102
+ // workflow-runner 自己的两份,Windows 跨盘符时会误判成"在目录内")。插件凡是要
103
+ // 做路径包含判定,一律经这里,不要再手写一遍。
104
+ export { pathContains } from './utils/pathContains.js';
97
105
 
98
106
  // 确定性检查设施:verify 步(shell/file_exists/file_contains/test_count)经此跑校验。
99
107
  export { parseCheckString, runVerification } from './infra/verification.js';
@@ -110,10 +118,35 @@ export type { SessionState } from './session/sessionState.js';
110
118
  // 不要绕过 legacy 回退逻辑自己拼路径。
111
119
  export { resolveSessionFile } from './context/sessionPath.js';
112
120
 
121
+ /**
122
+ * 按模型 id 解析出一个 Provider(工作流的 `agent(..., { model })` 用)。
123
+ *
124
+ * ⚠️ 门面只暴露这一个**语义明确的解析函数**,不暴露整个 ConfigService ——
125
+ * 后者带着读写配置、草稿、顾问设置一大堆能力,插件不该拿到,而门面每多一个
126
+ * 导出就多一条不能自由重构的边(`test/pluginSdkSurface.test.ts` 守这条)。
127
+ *
128
+ * 解析不到(id 不存在 / 该条目没填 apiKey)返回 null —— 调用方**必须**回落到
129
+ * 基座 provider 并如实告警,不能静默换模型。
130
+ */
131
+ export async function resolveProviderForModel(
132
+ modelId: string,
133
+ ): Promise<import('./types.js').Provider | null> {
134
+ const { configService } = await import('./config/configService.js');
135
+ return configService.providerForModel(modelId);
136
+ }
137
+
138
+ /** Resolve a portable workflow capability role through this machine's config. */
139
+ export async function resolveProviderForWorkflowRole(
140
+ role: string,
141
+ ): Promise<import('./types.js').Provider | null> {
142
+ const { configService } = await import('./config/configService.js');
143
+ return configService.providerForWorkflowRole(role);
144
+ }
145
+
113
146
  // --- 类型 ---
114
147
  export type {
115
- ImageDetail,
116
148
  ImageInputSpec,
149
+ InvocationResource,
117
150
  Message,
118
151
  Provider,
119
152
  LoopEvent,
@@ -123,12 +156,12 @@ export type {
123
156
  // 插件需要它来组装 executeTool 的第四参(宿主授权上下文按需切片转发)。
124
157
  // 不导出的话插件只能绕过门面直接 import 内核,那正是门面要避免的。
125
158
  ToolCallContext,
126
- ToolResult,
159
+ // 工作流引擎要把每次 agent()/llm() 的用量记进账本,`budget()` 才有刻度。
160
+ TurnResourceUsage,
127
161
  } from './types.js';
128
162
 
129
163
  export type {
130
164
  PluginApi,
131
165
  PluginContext,
132
- PluginEvent,
133
166
  PluginRuntimeContext,
134
167
  } from './plugins/pluginApi.js';
@@ -50,6 +50,8 @@ export interface PluginContext {
50
50
  maxTurns?: number;
51
51
  /** 当前回合的瞬时外部上下文;插件不得把它持久化到 history。 */
52
52
  transientContext?: string;
53
+ /** 本轮宿主明确授权给命令插件的文件资源;绝对路径仅限本机运行时。 */
54
+ inputResources?: readonly import('../types.js').InvocationResource[];
53
55
  transientBundle?: ContextBundle;
54
56
  promptCache?: PromptCacheContext;
55
57
  /** Canonical host-issued trust context; plugins may narrow it but never elevate it. */
@@ -82,7 +84,7 @@ export interface PluginContext {
82
84
  * 而同一个工具在主循环里好好的。
83
85
  *
84
86
  * 插件**不应**无条件把它转给每一步:能力要由各步显式声明后按需转发
85
- * (见 workflow-runner 的 `StepDef.uses`),否则一份无人值守的脚本就隐式拿到了
87
+ * (见 workflow-runner 的逐次 `uses` 选项),否则一份无人值守的脚本就隐式拿到了
86
88
  * 完整的机器控制权。
87
89
  */
88
90
  host?: Pick<
@@ -113,6 +115,14 @@ export interface PluginEvent {
113
115
  [key: string]: unknown;
114
116
  }
115
117
 
118
+ export interface PluginSlashFallback {
119
+ /** Existing command owned by this plugin, without the leading slash. */
120
+ commandName: string;
121
+ /** Rewritten arguments for that command. */
122
+ args: string;
123
+ message?: string;
124
+ }
125
+
116
126
  /**
117
127
  * 插件 plugin.ts 的 default export 形状。
118
128
  *
@@ -130,4 +140,9 @@ export interface PluginApi {
130
140
  args: string,
131
141
  ctx: PluginContext,
132
142
  ): AsyncGenerator<LoopEvent | PluginEvent, void, void>;
143
+ resolveSlashFallback?(
144
+ commandName: string,
145
+ args: string,
146
+ context: { cwd: string },
147
+ ): Promise<PluginSlashFallback | null> | PluginSlashFallback | null;
133
148
  }
@@ -52,6 +52,10 @@ function isPluginApi(value) {
52
52
  const { runCommand } = value;
53
53
  if (runCommand !== undefined && typeof runCommand !== 'function')
54
54
  return false;
55
+ const { resolveSlashFallback } = value;
56
+ if (resolveSlashFallback !== undefined &&
57
+ typeof resolveSlashFallback !== 'function')
58
+ return false;
55
59
  return true;
56
60
  }
57
61
  /**
@@ -57,6 +57,12 @@ function isPluginApi(value: unknown): value is PluginApi {
57
57
  if (!value || typeof value !== 'object') return false;
58
58
  const { runCommand } = value as { runCommand?: unknown };
59
59
  if (runCommand !== undefined && typeof runCommand !== 'function') return false;
60
+ const { resolveSlashFallback } = value as { resolveSlashFallback?: unknown };
61
+ if (
62
+ resolveSlashFallback !== undefined &&
63
+ typeof resolveSlashFallback !== 'function'
64
+ )
65
+ return false;
60
66
  return true;
61
67
  }
62
68
 
@@ -16,6 +16,7 @@
16
16
  import { runQuery } from '../loop.js';
17
17
  import { buildCommandInput, discoverPlugins, listAvailableCommands, resolveCommand, } from './commandRouter.js';
18
18
  import { loadPluginApi } from './pluginLoader.js';
19
+ import { buildFallbackInput, parseExplicitPrefix, resolveSlashFallback, } from './slashFallback.js';
19
20
  export async function* runWithPlugins(userInput, options) {
20
21
  const { provider, history, signal } = options;
21
22
  const isSlashCommand = userInput.trimStart().startsWith('/');
@@ -25,6 +26,7 @@ export async function* runWithPlugins(userInput, options) {
25
26
  history,
26
27
  runtimeContext: options.runtimeContext,
27
28
  allowedTools: options.allowedTools,
29
+ availableTools: options.availableTools,
28
30
  signal,
29
31
  maxTurns: options.maxTurns,
30
32
  sessionState: options.sessionState,
@@ -36,7 +38,9 @@ export async function* runWithPlugins(userInput, options) {
36
38
  transientBundle: options.transientBundle,
37
39
  promptCache: options.promptCache,
38
40
  userAttachments: options.userAttachments,
41
+ inputResources: options.inputResources,
39
42
  userMessageId: options.userMessageId,
43
+ messageProvenance: options.messageProvenance,
40
44
  userBrowserReferences: options.userBrowserReferences,
41
45
  imageInputs: options.imageInputs,
42
46
  parseInlineImages: options.parseInlineImages,
@@ -53,22 +57,144 @@ export async function* runWithPlugins(userInput, options) {
53
57
  return;
54
58
  }
55
59
  // 确保插件已发现(resolveCommand 依赖 pluginCache)
56
- await discoverPlugins();
57
- const matched = resolveCommand(userInput);
60
+ const discoveredPlugins = await discoverPlugins();
61
+ let matched = resolveCommand(userInput);
62
+ const trimmedUnknown = userInput.trimStart();
63
+ const spaceUnknown = trimmedUnknown.indexOf(' ', 1);
64
+ const unknownCmd = (spaceUnknown >= 0
65
+ ? trimmedUnknown.slice(1, spaceUnknown)
66
+ : trimmedUnknown.slice(1)).trim();
67
+ const unknownArgs = spaceUnknown >= 0 ? trimmedUnknown.slice(spaceUnknown + 1).trim() : '';
68
+ // ── `/` 的解析规则(见 slashFallback.ts)────────────────────────────
69
+ // 显式前缀 → **只**在那一类里找,找不到就明确报错:
70
+ // /tool <名字> … 只查工具
71
+ // /skill <名字> … 只查 skill
72
+ // /workflow <名字> … 只查工作流(它是插件命令,走下面的 resolveCommand)
73
+ // 省略前缀 → 工具 → skill → 插件 fallback;插件冲突必须报错。
74
+ //
75
+ // 为什么要有链式:用户心里的 `/` 是「唤起一个能力」,而能力有三种载体、
76
+ // 名字对用户是平级的。只认插件命令的话,`/pptx`、`/research` 这些**明明存在**
77
+ // 的能力全都会掉进「未知命令,按普通对话处理」—— 用户以为在跑工作流,
78
+ // 实际只烧了一轮 LLM。
79
+ let fallback = null;
80
+ const explicit = matched
81
+ ? null
82
+ : parseExplicitPrefix(unknownCmd, unknownArgs);
83
+ if (explicit) {
84
+ if (!explicit.name) {
85
+ yield {
86
+ type: 'error',
87
+ error: `/${unknownCmd} 用法:/${unknownCmd} <名字> [参数]。省略前缀直接写 /<名字> 也可以(会按 工具 → skill → 工作流 的顺序找)。`,
88
+ };
89
+ return;
90
+ }
91
+ fallback = await resolveSlashFallback(explicit.name, explicit.args, undefined, explicit.kind);
92
+ if (!fallback) {
93
+ // ⚠️ 显式前缀找不到就**明确报错**,不回落成普通对话 ——
94
+ // 用户点名要一个工具/skill,静默当聊天处理只会让他以为跑了但没效果。
95
+ const label = explicit.kind === 'tool' ? '工具' : 'skill';
96
+ yield {
97
+ type: 'error',
98
+ error: `没有名为「${explicit.name}」的${label}。` +
99
+ `跑 \`node skills/workflow-creator/scripts/list-resources.mjs --${explicit.kind}s\` 看全部可用的${label}。`,
100
+ };
101
+ return;
102
+ }
103
+ }
104
+ else if (!matched && unknownCmd) {
105
+ fallback = await resolveSlashFallback(unknownCmd, unknownArgs);
106
+ if (!fallback) {
107
+ const claims = [];
108
+ for (const plugin of discoveredPlugins) {
109
+ const api = await loadPluginApi(plugin.root);
110
+ const claim = await api?.resolveSlashFallback?.(unknownCmd, unknownArgs, { cwd: options.runtimeContext?.cwd ?? process.cwd() });
111
+ if (claim)
112
+ claims.push({ plugin, claim });
113
+ }
114
+ if (claims.length > 1) {
115
+ yield {
116
+ type: 'error',
117
+ error: `/${unknownCmd} 被多个插件同时认领:${claims.map((v) => v.plugin.name).join('、')}。请使用显式插件命令。`,
118
+ };
119
+ return;
120
+ }
121
+ if (claims.length === 1) {
122
+ const [{ claim, plugin }] = claims;
123
+ const rewritten = `/${claim.commandName}${claim.args ? ` ${claim.args}` : ''}`;
124
+ matched = resolveCommand(rewritten);
125
+ if (!matched) {
126
+ yield {
127
+ type: 'error',
128
+ error: `插件「${plugin.name}」认领了 /${unknownCmd},但改写目标 /${claim.commandName} 未注册。`,
129
+ };
130
+ return;
131
+ }
132
+ if (claim.message) {
133
+ yield {
134
+ type: 'plugin_progress',
135
+ pluginId: plugin.name,
136
+ message: claim.message,
137
+ };
138
+ }
139
+ }
140
+ }
141
+ }
142
+ if (!matched && fallback) {
143
+ // 工具 / skill 层:拼一段明确的指令交给模型(工具入参是结构化 schema,
144
+ // 而命令行只有自由文本 —— 让模型做这层映射正是它擅长的)。
145
+ const label = fallback.kind === 'tool' ? '工具' : 'skill';
146
+ yield {
147
+ type: 'plugin_progress',
148
+ pluginId: 'slash-router',
149
+ message: `▸ /${unknownCmd} → ${label}「${fallback.name}」`,
150
+ };
151
+ yield* runQuery(buildFallbackInput(fallback), {
152
+ provider,
153
+ history,
154
+ runtimeContext: options.runtimeContext,
155
+ // 工具层收敛到那一个工具:用户点名要它,不该让模型另选
156
+ allowedTools: fallback.kind === 'tool' ? [fallback.name] : options.allowedTools,
157
+ availableTools: options.availableTools,
158
+ signal,
159
+ maxTurns: options.maxTurns,
160
+ sessionState: options.sessionState,
161
+ chat: options.chat,
162
+ executeTool: options.executeTool,
163
+ commitFormalDelivery: options.commitFormalDelivery,
164
+ toolGate: options.toolGate,
165
+ transientContext: options.transientContext,
166
+ transientBundle: options.transientBundle,
167
+ promptCache: options.promptCache,
168
+ userAttachments: options.userAttachments,
169
+ inputResources: options.inputResources,
170
+ userMessageId: options.userMessageId,
171
+ messageProvenance: options.messageProvenance,
172
+ userBrowserReferences: options.userBrowserReferences,
173
+ imageInputs: options.imageInputs,
174
+ parseInlineImages: options.parseInlineImages,
175
+ imageDetail: options.imageDetail,
176
+ imageMaxLongSidePixel: options.imageMaxLongSidePixel,
177
+ hasQueuedInput: options.hasQueuedInput,
178
+ onToolStart: options.onToolStart,
179
+ onToolEnd: options.onToolEnd,
180
+ browserRun: options.browserRun,
181
+ computerRun: options.computerRun,
182
+ computerIntervention: options.computerIntervention,
183
+ memoryContext: options.memoryContext,
184
+ });
185
+ return;
186
+ }
58
187
  if (!matched) {
59
- // 未命中任何插件命令 -> 提示后透传 runQuery。
188
+ // 四层都没命中 -> 提示后透传 runQuery。
60
189
  // / 只是激活前缀(类似 Claude Code 的 / 模式),不是严格命令系统:
61
190
  // 不匹配仍当普通对话处理,让 LLM 自行理解意图。但 -p 等无人值守场景里
62
191
  // 拼错的 /reseach 会被静默当文本烧一轮 LLM(实战:用户以为在跑工作流,
63
192
  // 实际什么都没发生)--先 warning 列出已注册命令,零成本纠正拼写。
64
- const trimmedUnknown = userInput.trimStart();
65
- const spaceUnknown = trimmedUnknown.indexOf(' ', 1);
66
- const unknownCmd = (spaceUnknown >= 0 ? trimmedUnknown.slice(1, spaceUnknown) : trimmedUnknown.slice(1)).trim();
67
193
  if (unknownCmd) {
68
194
  const available = listAvailableCommands().map((c) => c.command);
69
195
  yield {
70
196
  type: 'warning',
71
- message: `未知命令 /${unknownCmd}(已注册:${available.length ? available.join('、') : '无'}),已按普通对话处理。`,
197
+ message: `未知命令 /${unknownCmd}(找遍了插件命令、工具、skill、工作流都没有;已注册插件命令:${available.length ? available.join('、') : '无'}),已按普通对话处理。`,
72
198
  };
73
199
  }
74
200
  yield* runQuery(userInput, {
@@ -76,6 +202,7 @@ export async function* runWithPlugins(userInput, options) {
76
202
  history,
77
203
  runtimeContext: options.runtimeContext,
78
204
  allowedTools: options.allowedTools,
205
+ availableTools: options.availableTools,
79
206
  signal,
80
207
  maxTurns: options.maxTurns,
81
208
  sessionState: options.sessionState,
@@ -87,7 +214,9 @@ export async function* runWithPlugins(userInput, options) {
87
214
  transientBundle: options.transientBundle,
88
215
  promptCache: options.promptCache,
89
216
  userAttachments: options.userAttachments,
217
+ inputResources: options.inputResources,
90
218
  userMessageId: options.userMessageId,
219
+ messageProvenance: options.messageProvenance,
91
220
  userBrowserReferences: options.userBrowserReferences,
92
221
  imageInputs: options.imageInputs,
93
222
  parseInlineImages: options.parseInlineImages,
@@ -128,6 +257,7 @@ export async function* runWithPlugins(userInput, options) {
128
257
  computerIntervention: options.computerIntervention,
129
258
  toolGate: options.toolGate,
130
259
  },
260
+ inputResources: options.inputResources,
131
261
  });
132
262
  return;
133
263
  }
@@ -149,7 +279,9 @@ export async function* runWithPlugins(userInput, options) {
149
279
  transientBundle: options.transientBundle,
150
280
  promptCache: options.promptCache,
151
281
  userAttachments: options.userAttachments,
282
+ inputResources: options.inputResources,
152
283
  userMessageId: options.userMessageId,
284
+ messageProvenance: options.messageProvenance,
153
285
  userBrowserReferences: options.userBrowserReferences,
154
286
  imageInputs: options.imageInputs,
155
287
  parseInlineImages: options.parseInlineImages,
@@ -24,12 +24,29 @@ import {
24
24
  } from './commandRouter.js';
25
25
  import type { PluginEvent } from './pluginApi.js';
26
26
  import { loadPluginApi } from './pluginLoader.js';
27
+ import {
28
+ type SlashTarget,
29
+ buildFallbackInput,
30
+ parseExplicitPrefix,
31
+ resolveSlashFallback,
32
+ } from './slashFallback.js';
27
33
 
28
34
  export interface PluginRunnerOptions {
29
35
  provider: Provider;
30
36
  history: Message[];
31
37
  runtimeContext?: RunQueryOptions['runtimeContext'];
32
38
  allowedTools?: RunQueryOptions['allowedTools'];
39
+ /**
40
+ * 本回合实际可调用的工具对象池(不只是名字)。缺省时 `loop.ts` 退回 `ALL_TOOLS`——
41
+ * 那是静态全局注册表,装不下按回合动态构造的工具(比如群协作工具,每次都要闭包捕获
42
+ * 当次投递的 owner/群 id/回复回调)。此前这里只转发 `allowedTools`(纯名字数组),
43
+ * 于是系统提示词会写"你有 GetGroupContext 工具"、允许名单里也有这个名字,但 API
44
+ * 实际下发给模型的 tools schema 里从来没有它——模型如实报告"没有这个能力",
45
+ * 比静默瞎猜更诚实,但这条工具从一开始就没进模型能调用的范围(2026-08-21 真实
46
+ * LLM 群回合 E2E 首次跑通时抓到的问题,此前所有测试都 stub 掉了 runAgentTurn,
47
+ * 没有一条测试真的走到过这一层)。
48
+ */
49
+ availableTools?: RunQueryOptions['availableTools'];
33
50
  signal?: AbortSignal;
34
51
  maxTurns?: number;
35
52
  sessionState?: import('../session/sessionState.js').SessionState;
@@ -46,7 +63,9 @@ export interface PluginRunnerOptions {
46
63
  transientBundle?: RunQueryOptions['transientBundle'];
47
64
  promptCache?: RunQueryOptions['promptCache'];
48
65
  userAttachments?: RunQueryOptions['userAttachments'];
66
+ inputResources?: RunQueryOptions['inputResources'];
49
67
  userMessageId?: RunQueryOptions['userMessageId'];
68
+ messageProvenance?: RunQueryOptions['messageProvenance'];
50
69
  userBrowserReferences?: RunQueryOptions['userBrowserReferences'];
51
70
  imageInputs?: RunQueryOptions['imageInputs'];
52
71
  parseInlineImages?: RunQueryOptions['parseInlineImages'];
@@ -74,6 +93,7 @@ export async function* runWithPlugins(
74
93
  history,
75
94
  runtimeContext: options.runtimeContext,
76
95
  allowedTools: options.allowedTools,
96
+ availableTools: options.availableTools,
77
97
  signal,
78
98
  maxTurns: options.maxTurns,
79
99
  sessionState: options.sessionState,
@@ -85,7 +105,9 @@ export async function* runWithPlugins(
85
105
  transientBundle: options.transientBundle,
86
106
  promptCache: options.promptCache,
87
107
  userAttachments: options.userAttachments,
108
+ inputResources: options.inputResources,
88
109
  userMessageId: options.userMessageId,
110
+ messageProvenance: options.messageProvenance,
89
111
  userBrowserReferences: options.userBrowserReferences,
90
112
  imageInputs: options.imageInputs,
91
113
  parseInlineImages: options.parseInlineImages,
@@ -103,25 +125,161 @@ export async function* runWithPlugins(
103
125
  }
104
126
 
105
127
  // 确保插件已发现(resolveCommand 依赖 pluginCache)
106
- await discoverPlugins();
107
- const matched = resolveCommand(userInput);
128
+ const discoveredPlugins = await discoverPlugins();
129
+ let matched = resolveCommand(userInput);
130
+
131
+ const trimmedUnknown = userInput.trimStart();
132
+ const spaceUnknown = trimmedUnknown.indexOf(' ', 1);
133
+ const unknownCmd = (
134
+ spaceUnknown >= 0
135
+ ? trimmedUnknown.slice(1, spaceUnknown)
136
+ : trimmedUnknown.slice(1)
137
+ ).trim();
138
+ const unknownArgs =
139
+ spaceUnknown >= 0 ? trimmedUnknown.slice(spaceUnknown + 1).trim() : '';
140
+
141
+ // ── `/` 的解析规则(见 slashFallback.ts)────────────────────────────
142
+ // 显式前缀 → **只**在那一类里找,找不到就明确报错:
143
+ // /tool <名字> … 只查工具
144
+ // /skill <名字> … 只查 skill
145
+ // /workflow <名字> … 只查工作流(它是插件命令,走下面的 resolveCommand)
146
+ // 省略前缀 → 工具 → skill → 插件 fallback;插件冲突必须报错。
147
+ //
148
+ // 为什么要有链式:用户心里的 `/` 是「唤起一个能力」,而能力有三种载体、
149
+ // 名字对用户是平级的。只认插件命令的话,`/pptx`、`/research` 这些**明明存在**
150
+ // 的能力全都会掉进「未知命令,按普通对话处理」—— 用户以为在跑工作流,
151
+ // 实际只烧了一轮 LLM。
152
+ let fallback: SlashTarget | null = null;
153
+ const explicit = matched
154
+ ? null
155
+ : parseExplicitPrefix(unknownCmd, unknownArgs);
156
+
157
+ if (explicit) {
158
+ if (!explicit.name) {
159
+ yield {
160
+ type: 'error',
161
+ error: `/${unknownCmd} 用法:/${unknownCmd} <名字> [参数]。省略前缀直接写 /<名字> 也可以(会按 工具 → skill → 工作流 的顺序找)。`,
162
+ };
163
+ return;
164
+ }
165
+ fallback = await resolveSlashFallback(
166
+ explicit.name,
167
+ explicit.args,
168
+ undefined,
169
+ explicit.kind,
170
+ );
171
+ if (!fallback) {
172
+ // ⚠️ 显式前缀找不到就**明确报错**,不回落成普通对话 ——
173
+ // 用户点名要一个工具/skill,静默当聊天处理只会让他以为跑了但没效果。
174
+ const label = explicit.kind === 'tool' ? '工具' : 'skill';
175
+ yield {
176
+ type: 'error',
177
+ error:
178
+ `没有名为「${explicit.name}」的${label}。` +
179
+ `跑 \`node skills/workflow-creator/scripts/list-resources.mjs --${explicit.kind}s\` 看全部可用的${label}。`,
180
+ };
181
+ return;
182
+ }
183
+ } else if (!matched && unknownCmd) {
184
+ fallback = await resolveSlashFallback(unknownCmd, unknownArgs);
185
+ if (!fallback) {
186
+ const claims = [];
187
+ for (const plugin of discoveredPlugins) {
188
+ const api = await loadPluginApi(plugin.root);
189
+ const claim = await api?.resolveSlashFallback?.(
190
+ unknownCmd,
191
+ unknownArgs,
192
+ { cwd: options.runtimeContext?.cwd ?? process.cwd() },
193
+ );
194
+ if (claim) claims.push({ plugin, claim });
195
+ }
196
+ if (claims.length > 1) {
197
+ yield {
198
+ type: 'error',
199
+ error: `/${unknownCmd} 被多个插件同时认领:${claims.map((v) => v.plugin.name).join('、')}。请使用显式插件命令。`,
200
+ };
201
+ return;
202
+ }
203
+ if (claims.length === 1) {
204
+ const [{ claim, plugin }] = claims;
205
+ const rewritten = `/${claim.commandName}${claim.args ? ` ${claim.args}` : ''}`;
206
+ matched = resolveCommand(rewritten);
207
+ if (!matched) {
208
+ yield {
209
+ type: 'error',
210
+ error: `插件「${plugin.name}」认领了 /${unknownCmd},但改写目标 /${claim.commandName} 未注册。`,
211
+ };
212
+ return;
213
+ }
214
+ if (claim.message) {
215
+ yield {
216
+ type: 'plugin_progress',
217
+ pluginId: plugin.name,
218
+ message: claim.message,
219
+ };
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ if (!matched && fallback) {
226
+ // 工具 / skill 层:拼一段明确的指令交给模型(工具入参是结构化 schema,
227
+ // 而命令行只有自由文本 —— 让模型做这层映射正是它擅长的)。
228
+ const label = fallback.kind === 'tool' ? '工具' : 'skill';
229
+ yield {
230
+ type: 'plugin_progress',
231
+ pluginId: 'slash-router',
232
+ message: `▸ /${unknownCmd} → ${label}「${fallback.name}」`,
233
+ };
234
+ yield* runQuery(buildFallbackInput(fallback), {
235
+ provider,
236
+ history,
237
+ runtimeContext: options.runtimeContext,
238
+ // 工具层收敛到那一个工具:用户点名要它,不该让模型另选
239
+ allowedTools:
240
+ fallback.kind === 'tool' ? [fallback.name] : options.allowedTools,
241
+ availableTools: options.availableTools,
242
+ signal,
243
+ maxTurns: options.maxTurns,
244
+ sessionState: options.sessionState,
245
+ chat: options.chat,
246
+ executeTool: options.executeTool,
247
+ commitFormalDelivery: options.commitFormalDelivery,
248
+ toolGate: options.toolGate,
249
+ transientContext: options.transientContext,
250
+ transientBundle: options.transientBundle,
251
+ promptCache: options.promptCache,
252
+ userAttachments: options.userAttachments,
253
+ inputResources: options.inputResources,
254
+ userMessageId: options.userMessageId,
255
+ messageProvenance: options.messageProvenance,
256
+ userBrowserReferences: options.userBrowserReferences,
257
+ imageInputs: options.imageInputs,
258
+ parseInlineImages: options.parseInlineImages,
259
+ imageDetail: options.imageDetail,
260
+ imageMaxLongSidePixel: options.imageMaxLongSidePixel,
261
+ hasQueuedInput: options.hasQueuedInput,
262
+ onToolStart: options.onToolStart,
263
+ onToolEnd: options.onToolEnd,
264
+ browserRun: options.browserRun,
265
+ computerRun: options.computerRun,
266
+ computerIntervention: options.computerIntervention,
267
+ memoryContext: options.memoryContext,
268
+ });
269
+ return;
270
+ }
108
271
 
109
272
  if (!matched) {
110
- // 未命中任何插件命令 -> 提示后透传 runQuery。
273
+ // 四层都没命中 -> 提示后透传 runQuery。
111
274
  // / 只是激活前缀(类似 Claude Code 的 / 模式),不是严格命令系统:
112
275
  // 不匹配仍当普通对话处理,让 LLM 自行理解意图。但 -p 等无人值守场景里
113
276
  // 拼错的 /reseach 会被静默当文本烧一轮 LLM(实战:用户以为在跑工作流,
114
277
  // 实际什么都没发生)--先 warning 列出已注册命令,零成本纠正拼写。
115
- const trimmedUnknown = userInput.trimStart();
116
- const spaceUnknown = trimmedUnknown.indexOf(' ', 1);
117
- const unknownCmd = (
118
- spaceUnknown >= 0 ? trimmedUnknown.slice(1, spaceUnknown) : trimmedUnknown.slice(1)
119
- ).trim();
120
278
  if (unknownCmd) {
121
279
  const available = listAvailableCommands().map((c) => c.command);
122
280
  yield {
123
281
  type: 'warning',
124
- message: `未知命令 /${unknownCmd}(已注册:${available.length ? available.join('、') : '无'}),已按普通对话处理。`,
282
+ message: `未知命令 /${unknownCmd}(找遍了插件命令、工具、skill、工作流都没有;已注册插件命令:${available.length ? available.join('、') : '无'}),已按普通对话处理。`,
125
283
  };
126
284
  }
127
285
  yield* runQuery(userInput, {
@@ -129,6 +287,7 @@ export async function* runWithPlugins(
129
287
  history,
130
288
  runtimeContext: options.runtimeContext,
131
289
  allowedTools: options.allowedTools,
290
+ availableTools: options.availableTools,
132
291
  signal,
133
292
  maxTurns: options.maxTurns,
134
293
  sessionState: options.sessionState,
@@ -140,7 +299,9 @@ export async function* runWithPlugins(
140
299
  transientBundle: options.transientBundle,
141
300
  promptCache: options.promptCache,
142
301
  userAttachments: options.userAttachments,
302
+ inputResources: options.inputResources,
143
303
  userMessageId: options.userMessageId,
304
+ messageProvenance: options.messageProvenance,
144
305
  userBrowserReferences: options.userBrowserReferences,
145
306
  imageInputs: options.imageInputs,
146
307
  parseInlineImages: options.parseInlineImages,
@@ -182,6 +343,7 @@ export async function* runWithPlugins(
182
343
  computerIntervention: options.computerIntervention,
183
344
  toolGate: options.toolGate,
184
345
  },
346
+ inputResources: options.inputResources,
185
347
  });
186
348
  return;
187
349
  }
@@ -204,7 +366,9 @@ export async function* runWithPlugins(
204
366
  transientBundle: options.transientBundle,
205
367
  promptCache: options.promptCache,
206
368
  userAttachments: options.userAttachments,
369
+ inputResources: options.inputResources,
207
370
  userMessageId: options.userMessageId,
371
+ messageProvenance: options.messageProvenance,
208
372
  userBrowserReferences: options.userBrowserReferences,
209
373
  imageInputs: options.imageInputs,
210
374
  parseInlineImages: options.parseInlineImages,