minimal-agent 0.12.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 (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  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 +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  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 +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  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 +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  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 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  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 +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  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/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  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 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
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
 
@@ -9,13 +9,14 @@
9
9
  * 2) / 输入 → discoverPlugins → resolveCommand
10
10
  * a) 命中插件且其 plugin.ts 暴露 runCommand → 让 plugin.ts 接管
11
11
  * b) 命中插件但只有声明式 commands/*.md → 把 prompt 拼好喂给 runQuery
12
- * c) 未命中 → 静默透传 runQuery(/ 只是激活前缀,不是严格命令系统;
13
- * 未知的 /xxx 当普通用户输入处理,不报错)
12
+ * c) 未命中 -> warning 提示未知命令后透传 runQuery(/ 只是激活前缀,
13
+ * 不是严格命令系统;未知的 /xxx 当普通用户输入处理,不报错)
14
14
  * ============================================================
15
15
  */
16
16
  import { runQuery } from '../loop.js';
17
- import { buildCommandInput, discoverPlugins, resolveCommand, } from './commandRouter.js';
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,18 +57,152 @@ 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。
60
- // / 只是激活前缀(类似 Claude Code 的 / 模式),不是严格命令系统。
61
- // 用户可能输入 /init、/help、/任何东西 —— 不匹配就当普通对话处理,
62
- // 让 LLM 自行理解意图。不报错、不提示、不打断用户体验。
188
+ // 四层都没命中 -> 提示后透传 runQuery。
189
+ // / 只是激活前缀(类似 Claude Code 的 / 模式),不是严格命令系统:
190
+ // 不匹配仍当普通对话处理,让 LLM 自行理解意图。但 -p 等无人值守场景里
191
+ // 拼错的 /reseach 会被静默当文本烧一轮 LLM(实战:用户以为在跑工作流,
192
+ // 实际什么都没发生)--先 warning 列出已注册命令,零成本纠正拼写。
193
+ if (unknownCmd) {
194
+ const available = listAvailableCommands().map((c) => c.command);
195
+ yield {
196
+ type: 'warning',
197
+ message: `未知命令 /${unknownCmd}(找遍了插件命令、工具、skill、工作流都没有;已注册插件命令:${available.length ? available.join('、') : '无'}),已按普通对话处理。`,
198
+ };
199
+ }
63
200
  yield* runQuery(userInput, {
64
201
  provider,
65
202
  history,
66
203
  runtimeContext: options.runtimeContext,
67
204
  allowedTools: options.allowedTools,
205
+ availableTools: options.availableTools,
68
206
  signal,
69
207
  maxTurns: options.maxTurns,
70
208
  sessionState: options.sessionState,
@@ -76,7 +214,9 @@ export async function* runWithPlugins(userInput, options) {
76
214
  transientBundle: options.transientBundle,
77
215
  promptCache: options.promptCache,
78
216
  userAttachments: options.userAttachments,
217
+ inputResources: options.inputResources,
79
218
  userMessageId: options.userMessageId,
219
+ messageProvenance: options.messageProvenance,
80
220
  userBrowserReferences: options.userBrowserReferences,
81
221
  imageInputs: options.imageInputs,
82
222
  parseInlineImages: options.parseInlineImages,
@@ -117,6 +257,7 @@ export async function* runWithPlugins(userInput, options) {
117
257
  computerIntervention: options.computerIntervention,
118
258
  toolGate: options.toolGate,
119
259
  },
260
+ inputResources: options.inputResources,
120
261
  });
121
262
  return;
122
263
  }
@@ -138,7 +279,9 @@ export async function* runWithPlugins(userInput, options) {
138
279
  transientBundle: options.transientBundle,
139
280
  promptCache: options.promptCache,
140
281
  userAttachments: options.userAttachments,
282
+ inputResources: options.inputResources,
141
283
  userMessageId: options.userMessageId,
284
+ messageProvenance: options.messageProvenance,
142
285
  userBrowserReferences: options.userBrowserReferences,
143
286
  imageInputs: options.imageInputs,
144
287
  parseInlineImages: options.parseInlineImages,
@@ -9,8 +9,8 @@
9
9
  * 2) / 输入 → discoverPlugins → resolveCommand
10
10
  * a) 命中插件且其 plugin.ts 暴露 runCommand → 让 plugin.ts 接管
11
11
  * b) 命中插件但只有声明式 commands/*.md → 把 prompt 拼好喂给 runQuery
12
- * c) 未命中 → 静默透传 runQuery(/ 只是激活前缀,不是严格命令系统;
13
- * 未知的 /xxx 当普通用户输入处理,不报错)
12
+ * c) 未命中 -> warning 提示未知命令后透传 runQuery(/ 只是激活前缀,
13
+ * 不是严格命令系统;未知的 /xxx 当普通用户输入处理,不报错)
14
14
  * ============================================================
15
15
  */
16
16
 
@@ -19,16 +19,34 @@ import type { LoopEvent, Message, Provider } from '../types.js';
19
19
  import {
20
20
  buildCommandInput,
21
21
  discoverPlugins,
22
+ listAvailableCommands,
22
23
  resolveCommand,
23
24
  } from './commandRouter.js';
24
25
  import type { PluginEvent } from './pluginApi.js';
25
26
  import { loadPluginApi } from './pluginLoader.js';
27
+ import {
28
+ type SlashTarget,
29
+ buildFallbackInput,
30
+ parseExplicitPrefix,
31
+ resolveSlashFallback,
32
+ } from './slashFallback.js';
26
33
 
27
34
  export interface PluginRunnerOptions {
28
35
  provider: Provider;
29
36
  history: Message[];
30
37
  runtimeContext?: RunQueryOptions['runtimeContext'];
31
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'];
32
50
  signal?: AbortSignal;
33
51
  maxTurns?: number;
34
52
  sessionState?: import('../session/sessionState.js').SessionState;
@@ -45,7 +63,9 @@ export interface PluginRunnerOptions {
45
63
  transientBundle?: RunQueryOptions['transientBundle'];
46
64
  promptCache?: RunQueryOptions['promptCache'];
47
65
  userAttachments?: RunQueryOptions['userAttachments'];
66
+ inputResources?: RunQueryOptions['inputResources'];
48
67
  userMessageId?: RunQueryOptions['userMessageId'];
68
+ messageProvenance?: RunQueryOptions['messageProvenance'];
49
69
  userBrowserReferences?: RunQueryOptions['userBrowserReferences'];
50
70
  imageInputs?: RunQueryOptions['imageInputs'];
51
71
  parseInlineImages?: RunQueryOptions['parseInlineImages'];
@@ -73,6 +93,7 @@ export async function* runWithPlugins(
73
93
  history,
74
94
  runtimeContext: options.runtimeContext,
75
95
  allowedTools: options.allowedTools,
96
+ availableTools: options.availableTools,
76
97
  signal,
77
98
  maxTurns: options.maxTurns,
78
99
  sessionState: options.sessionState,
@@ -84,7 +105,9 @@ export async function* runWithPlugins(
84
105
  transientBundle: options.transientBundle,
85
106
  promptCache: options.promptCache,
86
107
  userAttachments: options.userAttachments,
108
+ inputResources: options.inputResources,
87
109
  userMessageId: options.userMessageId,
110
+ messageProvenance: options.messageProvenance,
88
111
  userBrowserReferences: options.userBrowserReferences,
89
112
  imageInputs: options.imageInputs,
90
113
  parseInlineImages: options.parseInlineImages,
@@ -102,19 +125,169 @@ export async function* runWithPlugins(
102
125
  }
103
126
 
104
127
  // 确保插件已发现(resolveCommand 依赖 pluginCache)
105
- await discoverPlugins();
106
- 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
+ }
107
271
 
108
272
  if (!matched) {
109
- // 未命中任何插件命令 → 静默透传 runQuery。
110
- // / 只是激活前缀(类似 Claude Code 的 / 模式),不是严格命令系统。
111
- // 用户可能输入 /init、/help、/任何东西 —— 不匹配就当普通对话处理,
112
- // 让 LLM 自行理解意图。不报错、不提示、不打断用户体验。
273
+ // 四层都没命中 -> 提示后透传 runQuery。
274
+ // / 只是激活前缀(类似 Claude Code 的 / 模式),不是严格命令系统:
275
+ // 不匹配仍当普通对话处理,让 LLM 自行理解意图。但 -p 等无人值守场景里
276
+ // 拼错的 /reseach 会被静默当文本烧一轮 LLM(实战:用户以为在跑工作流,
277
+ // 实际什么都没发生)--先 warning 列出已注册命令,零成本纠正拼写。
278
+ if (unknownCmd) {
279
+ const available = listAvailableCommands().map((c) => c.command);
280
+ yield {
281
+ type: 'warning',
282
+ message: `未知命令 /${unknownCmd}(找遍了插件命令、工具、skill、工作流都没有;已注册插件命令:${available.length ? available.join('、') : '无'}),已按普通对话处理。`,
283
+ };
284
+ }
113
285
  yield* runQuery(userInput, {
114
286
  provider,
115
287
  history,
116
288
  runtimeContext: options.runtimeContext,
117
289
  allowedTools: options.allowedTools,
290
+ availableTools: options.availableTools,
118
291
  signal,
119
292
  maxTurns: options.maxTurns,
120
293
  sessionState: options.sessionState,
@@ -126,7 +299,9 @@ export async function* runWithPlugins(
126
299
  transientBundle: options.transientBundle,
127
300
  promptCache: options.promptCache,
128
301
  userAttachments: options.userAttachments,
302
+ inputResources: options.inputResources,
129
303
  userMessageId: options.userMessageId,
304
+ messageProvenance: options.messageProvenance,
130
305
  userBrowserReferences: options.userBrowserReferences,
131
306
  imageInputs: options.imageInputs,
132
307
  parseInlineImages: options.parseInlineImages,
@@ -168,6 +343,7 @@ export async function* runWithPlugins(
168
343
  computerIntervention: options.computerIntervention,
169
344
  toolGate: options.toolGate,
170
345
  },
346
+ inputResources: options.inputResources,
171
347
  });
172
348
  return;
173
349
  }
@@ -190,7 +366,9 @@ export async function* runWithPlugins(
190
366
  transientBundle: options.transientBundle,
191
367
  promptCache: options.promptCache,
192
368
  userAttachments: options.userAttachments,
369
+ inputResources: options.inputResources,
193
370
  userMessageId: options.userMessageId,
371
+ messageProvenance: options.messageProvenance,
194
372
  userBrowserReferences: options.userBrowserReferences,
195
373
  imageInputs: options.imageInputs,
196
374
  parseInlineImages: options.parseInlineImages,