minimal-agent 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +503 -0
  103. package/src/advisor/advisorCoordinator.ts +657 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/streamJson.js +5 -6
  108. package/src/cli/streamJson.ts +8 -4
  109. package/src/cli/wizards/advisorWizard.js +4 -2
  110. package/src/cli/wizards/advisorWizard.tsx +8 -2
  111. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  112. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  113. package/src/collaboration/taskFlow.js +115 -0
  114. package/src/collaboration/taskFlow.ts +169 -0
  115. package/src/config/configDefaults.js +41 -1
  116. package/src/config/configDefaults.ts +43 -1
  117. package/src/config/configDiagnostics.ts +2 -2
  118. package/src/config/configFile.js +40 -9
  119. package/src/config/configFile.ts +60 -11
  120. package/src/config/configService.js +419 -74
  121. package/src/config/configService.ts +703 -145
  122. package/src/config/numericLimits.js +22 -0
  123. package/src/config/numericLimits.ts +24 -0
  124. package/src/config.js +1 -0
  125. package/src/config.ts +3 -2
  126. package/src/context/budgetPlan.js +1 -1
  127. package/src/context/budgetPlan.ts +1 -1
  128. package/src/context/compact.js +7 -2
  129. package/src/context/compact.ts +9 -2
  130. package/src/context/microCompactLite.js +212 -13
  131. package/src/context/microCompactLite.ts +261 -12
  132. package/src/context/sessionRegistry.js +8 -1
  133. package/src/context/sessionRegistry.ts +18 -5
  134. package/src/context/toolResultArchive.js +72 -0
  135. package/src/context/toolResultArchive.ts +95 -0
  136. package/src/goal/errors.js +8 -0
  137. package/src/goal/errors.ts +18 -0
  138. package/src/goal/goalRuntime.js +344 -0
  139. package/src/goal/goalRuntime.ts +466 -0
  140. package/src/goal/goalStore.js +200 -0
  141. package/src/goal/goalStore.ts +219 -0
  142. package/src/goal/index.js +4 -0
  143. package/src/goal/index.ts +4 -0
  144. package/src/goal/statusMapping.js +71 -0
  145. package/src/goal/statusMapping.ts +95 -0
  146. package/src/goal/types.js +7 -0
  147. package/src/goal/types.ts +179 -0
  148. package/src/goal/workflowController.js +306 -0
  149. package/src/goal/workflowController.ts +360 -0
  150. package/src/harness/evidenceLedger.js +2 -0
  151. package/src/harness/evidenceLedger.ts +1 -0
  152. package/src/harness/stallGuard.js +9 -3
  153. package/src/harness/stallGuard.ts +7 -3
  154. package/src/images/imageResolver.js +161 -0
  155. package/src/images/imageResolver.ts +189 -0
  156. package/src/infra/verification.js +34 -5
  157. package/src/infra/verification.ts +39 -4
  158. package/src/llm/client.js +79 -21
  159. package/src/llm/client.ts +182 -35
  160. package/src/llm/gatewayClient.js +201 -0
  161. package/src/llm/gatewayClient.ts +299 -0
  162. package/src/llm/messageProvenance.js +46 -0
  163. package/src/llm/messageProvenance.ts +58 -0
  164. package/src/llm/modelProvider.js +1 -0
  165. package/src/llm/modelProvider.ts +22 -0
  166. package/src/llm/providers/anthropicFormat.js +108 -1
  167. package/src/llm/providers/anthropicFormat.ts +115 -4
  168. package/src/llm/providers/openaiFormat.js +9 -0
  169. package/src/llm/providers/openaiFormat.ts +12 -3
  170. package/src/loop.js +319 -54
  171. package/src/loop.ts +373 -57
  172. package/src/main.js +4 -1
  173. package/src/main.tsx +4 -1
  174. package/src/managedExecution/index.js +2 -0
  175. package/src/managedExecution/index.ts +2 -0
  176. package/src/managedExecution/registry.js +15 -0
  177. package/src/managedExecution/registry.ts +20 -0
  178. package/src/managedExecution/types.js +1 -0
  179. package/src/managedExecution/types.ts +86 -0
  180. package/src/modelRef.js +9 -0
  181. package/src/modelRef.ts +31 -0
  182. package/src/multimodal.js +14 -28
  183. package/src/multimodal.ts +17 -33
  184. package/src/net/lanDiscovery.js +65 -0
  185. package/src/net/lanDiscovery.ts +82 -0
  186. package/src/plugin-sdk.js +28 -3
  187. package/src/plugin-sdk.ts +39 -6
  188. package/src/plugins/pluginApi.ts +16 -1
  189. package/src/plugins/pluginLoader.js +4 -0
  190. package/src/plugins/pluginLoader.ts +6 -0
  191. package/src/plugins/pluginRunner.js +139 -7
  192. package/src/plugins/pluginRunner.ts +173 -9
  193. package/src/plugins/slashFallback.js +113 -0
  194. package/src/plugins/slashFallback.ts +137 -0
  195. package/src/prompts/policyRegistry.js +12 -32
  196. package/src/prompts/policyRegistry.ts +15 -32
  197. package/src/prompts/promptAssembly.js +103 -12
  198. package/src/prompts/promptAssembly.ts +114 -12
  199. package/src/prompts/skillList.js +21 -3
  200. package/src/prompts/skillList.ts +27 -2
  201. package/src/prompts/stableSystemPrompt.js +18 -0
  202. package/src/prompts/stableSystemPrompt.ts +33 -0
  203. package/src/runtime/agentRuntimeContext.js +8 -2
  204. package/src/runtime/agentRuntimeContext.ts +17 -4
  205. package/src/session/runAgentTurn.js +78 -12
  206. package/src/session/runAgentTurn.ts +105 -23
  207. package/src/session/runTurn.js +10 -9
  208. package/src/session/runTurn.ts +17 -8
  209. package/src/session/sessionState.ts +2 -0
  210. package/src/team/auth.js +186 -0
  211. package/src/team/auth.ts +298 -0
  212. package/src/team/cli.js +105 -0
  213. package/src/team/cli.ts +122 -0
  214. package/src/team/onlineToolContract.js +64 -0
  215. package/src/team/onlineToolContract.ts +109 -0
  216. package/src/team/toolPolicy.js +36 -0
  217. package/src/team/toolPolicy.ts +75 -0
  218. package/src/tools/advisor/advisor.js +90 -46
  219. package/src/tools/advisor/advisor.ts +100 -47
  220. package/src/tools/advisor/advisorDecision.js +71 -0
  221. package/src/tools/advisor/advisorDecision.ts +85 -0
  222. package/src/tools/agent/agent.js +18 -5
  223. package/src/tools/agent/agent.ts +21 -7
  224. package/src/tools/agent/agentControl.js +246 -0
  225. package/src/tools/agent/agentControl.ts +284 -0
  226. package/src/tools/agent/agentTaskService.js +40 -1
  227. package/src/tools/agent/agentTaskService.ts +44 -1
  228. package/src/tools/agent/agentTypes.js +14 -2
  229. package/src/tools/agent/agentTypes.ts +15 -2
  230. package/src/tools/applypatch/applyPatch.js +362 -0
  231. package/src/tools/applypatch/applyPatch.ts +428 -0
  232. package/src/tools/bash/bash.js +22 -15
  233. package/src/tools/bash/bash.ts +23 -17
  234. package/src/tools/capabilities.js +10 -5
  235. package/src/tools/capabilities.ts +10 -5
  236. package/src/tools/computeruse/computerIntent.js +32 -0
  237. package/src/tools/computeruse/computerIntent.ts +46 -0
  238. package/src/tools/computeruse/telemetryLog.js +12 -0
  239. package/src/tools/computeruse/telemetryLog.ts +16 -0
  240. package/src/tools/computeruse/vision/telemetry.js +1 -0
  241. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  242. package/src/tools/effectiveToolSet.js +4 -0
  243. package/src/tools/effectiveToolSet.ts +4 -0
  244. package/src/tools/index.js +21 -2
  245. package/src/tools/index.ts +33 -2
  246. package/src/tools/presentresult/presentresult.js +6 -15
  247. package/src/tools/presentresult/presentresult.ts +6 -15
  248. package/src/tools/read/read.js +62 -9
  249. package/src/tools/read/read.ts +63 -9
  250. package/src/tools/shared/fileUtils.js +1 -2
  251. package/src/tools/shared/fileUtils.ts +1 -2
  252. package/src/tools/shared/toolOutputStore.js +23 -1
  253. package/src/tools/shared/toolOutputStore.ts +22 -1
  254. package/src/tools/skill/skill.js +9 -3
  255. package/src/tools/skill/skill.ts +8 -4
  256. package/src/tools/toolPromptGuides.js +117 -0
  257. package/src/tools/toolPromptGuides.ts +137 -0
  258. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  259. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  260. package/src/tools/webbrowser/browser.js +27 -11
  261. package/src/tools/webbrowser/browser.ts +68 -24
  262. package/src/tools/webbrowser/browserAutomation.js +329 -0
  263. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  264. package/src/tools/webbrowser/browserAxState.js +97 -0
  265. package/src/tools/webbrowser/browserAxState.ts +142 -0
  266. package/src/tools/webbrowser/browserBatch.js +1578 -0
  267. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  268. package/src/tools/webbrowser/browserCdp.js +208 -0
  269. package/src/tools/webbrowser/browserCdp.ts +255 -0
  270. package/src/tools/webbrowser/browserConditions.js +24 -0
  271. package/src/tools/webbrowser/browserConditions.ts +45 -0
  272. package/src/tools/webbrowser/browserContent.js +281 -0
  273. package/src/tools/webbrowser/browserContent.ts +438 -0
  274. package/src/tools/webbrowser/browserControl.js +131 -34
  275. package/src/tools/webbrowser/browserControl.ts +210 -56
  276. package/src/tools/webbrowser/browserDaemon.js +22 -14
  277. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  278. package/src/tools/webbrowser/browserFrames.js +47 -0
  279. package/src/tools/webbrowser/browserFrames.ts +54 -0
  280. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  281. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  282. package/src/tools/webbrowser/browserLocator.js +140 -0
  283. package/src/tools/webbrowser/browserLocator.ts +194 -0
  284. package/src/tools/webbrowser/browserOutcome.js +10 -17
  285. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  286. package/src/tools/webbrowser/browserRecovery.js +58 -0
  287. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  288. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  289. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  290. package/src/tools/webbrowser/browserService.js +28 -2
  291. package/src/tools/webbrowser/browserService.ts +49 -9
  292. package/src/tools/webbrowser/browserStream.js +132 -33
  293. package/src/tools/webbrowser/browserStream.ts +224 -50
  294. package/src/tools/webbrowser/browserTabs.js +48 -15
  295. package/src/tools/webbrowser/browserTabs.ts +178 -96
  296. package/src/tools/webbrowser/webbrowser.js +679 -144
  297. package/src/tools/webbrowser/webbrowser.ts +975 -236
  298. package/src/tools/webfetch/preapproved.js +0 -2
  299. package/src/tools/webfetch/preapproved.ts +0 -2
  300. package/src/tools/websearch/websearch.js +129 -8
  301. package/src/tools/websearch/websearch.ts +138 -6
  302. package/src/types.ts +440 -38
  303. package/src/ui/App.js +377 -58
  304. package/src/ui/App.tsx +576 -111
  305. package/src/ui/LiveArea.js +14 -8
  306. package/src/ui/LiveArea.tsx +14 -10
  307. package/src/ui/MessageList.js +63 -20
  308. package/src/ui/MessageList.tsx +101 -16
  309. package/src/ui/ModelPicker.js +7 -4
  310. package/src/ui/ModelPicker.tsx +55 -8
  311. package/src/ui/hooks/useChat.js +152 -163
  312. package/src/ui/hooks/useChat.ts +396 -334
  313. package/src/ui/loginCommand.js +56 -0
  314. package/src/ui/loginCommand.ts +63 -0
  315. package/src/ui/toolProgress.js +41 -0
  316. package/src/ui/toolProgress.ts +44 -0
  317. package/src/web/browserBridge.js +20 -2
  318. package/src/web/browserBridge.ts +20 -2
  319. package/src/web/protocol.ts +1897 -194
  320. package/workflows/adaptive-research/workflow.mjs +86 -0
  321. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  322. package/workflows/e2e-llm/workflow.mjs +52 -0
  323. package/workflows/e2e-smoke/workflow.mjs +59 -0
  324. package/workflows/e2e-vision-schema/README.md +48 -0
  325. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  326. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  327. package/workflows/file-census/README.md +14 -0
  328. package/workflows/file-census/scripts/.gitkeep +2 -0
  329. package/workflows/file-census/workflow.mjs +110 -0
  330. package/workflows/goal/README.md +166 -0
  331. package/workflows/goal/prompts/audit.md +57 -0
  332. package/workflows/goal/prompts/contract.md +56 -0
  333. package/workflows/goal/prompts/iterate.md +37 -0
  334. package/workflows/goal/workflow.mjs +501 -0
  335. package/workflows/illustrate/README.md +90 -0
  336. package/workflows/illustrate/assets/engines.json +20 -0
  337. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  338. package/workflows/illustrate/assets/extract-bing.js +33 -0
  339. package/workflows/illustrate/assets/extract-google.js +31 -0
  340. package/workflows/illustrate/workflow.mjs +301 -0
  341. package/workflows/plan/workflow.mjs +389 -0
  342. package/workflows/question-crops/README.md +35 -0
  343. package/workflows/question-crops/prompts/inventory.md +23 -0
  344. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  345. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  346. package/workflows/question-crops/workflow.mjs +172 -0
  347. package/workflows/ralph-loop/workflow.mjs +162 -0
  348. package/workflows/research/README.md +74 -0
  349. package/workflows/research/prompts/s0-goal.md +43 -0
  350. package/workflows/research/prompts/s1-early-exit.md +22 -0
  351. package/workflows/research/prompts/s1-map.md +58 -0
  352. package/workflows/research/prompts/s2-options.md +53 -0
  353. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  354. package/workflows/research/prompts/s4-verify.md +74 -0
  355. package/workflows/research/prompts/s5-synthesis.md +81 -0
  356. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  357. package/workflows/research/prompts/s6-package.md +32 -0
  358. package/workflows/research/scripts/build-report.mjs +98 -0
  359. package/workflows/research/workflow.mjs +288 -0
  360. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  361. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  362. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  363. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  364. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  365. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  366. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  367. package/workflows/wrong-question-docx/README.md +55 -0
  368. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  369. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  370. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  371. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  372. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  373. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  374. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  375. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  376. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  377. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  378. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  379. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  380. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  381. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  382. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  383. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  384. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  385. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  386. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  387. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  388. package/plugins/workflow-runner/src/expressions.js +0 -639
  389. package/plugins/workflow-runner/src/expressions.ts +0 -640
  390. package/plugins/workflow-runner/src/loader.js +0 -573
  391. package/plugins/workflow-runner/src/loader.ts +0 -721
  392. package/plugins/workflow-runner/src/multimodal.js +0 -38
  393. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  394. package/plugins/workflow-runner/src/recovery.js +0 -126
  395. package/plugins/workflow-runner/src/recovery.ts +0 -156
  396. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  397. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  398. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  399. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  400. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  401. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  402. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  403. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  404. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  405. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  406. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  407. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  408. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  409. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  410. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  411. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  412. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  413. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  414. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  415. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  416. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  417. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  418. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  419. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  420. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  421. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  422. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  423. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  424. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  425. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  426. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  427. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  428. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  429. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  430. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  431. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  432. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  433. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  434. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  435. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  436. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  437. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  438. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  439. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  440. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  441. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  442. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  443. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  444. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  445. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  446. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  447. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  448. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  449. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  450. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  451. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  452. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  453. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  454. package/src/advisorState.js +0 -22
  455. package/src/cli/configWizard.js +0 -293
  456. package/src/tools/toolProgressBridge.js +0 -48
  457. package/workflows/adaptive-research.yaml +0 -50
  458. package/workflows/book-review-short.yaml +0 -125
  459. package/workflows/e2e-write-greet.yaml +0 -31
  460. package/workflows/illustrate.yaml +0 -227
  461. package/workflows/plan.yaml +0 -470
  462. package/workflows/ppt.yaml +0 -1670
  463. package/workflows/ralph-loop.yaml +0 -201
  464. package/workflows/research.yaml +0 -873
  465. package/workflows/schema.json +0 -176
  466. package/workflows/webppt.yaml +0 -496
  467. package/workflows/wechat-reading-shots.yaml +0 -315
  468. package/workflows/word.yaml +0 -720
  469. package/workflows/youtube-shorts.yaml +0 -202
  470. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -1,11 +1,33 @@
1
- import React, { useState } from 'react';
2
1
  import { Box, Text, useInput } from 'ink';
2
+ import React, { useState } from 'react';
3
3
 
4
4
  import type { ModelConfig } from '../config/configFile.js';
5
+ import type { OnlineModelAvailability } from '../team/onlineToolContract.js';
5
6
  import { theme } from './theme.js';
6
7
 
8
+ export interface GatewayPickerModel {
9
+ id: string;
10
+ source: 'gateway';
11
+ apiFormat: 'openai' | 'anthropic';
12
+ displayName: string;
13
+ model: string;
14
+ contextWindow: number;
15
+ maxTokens: number;
16
+ supportsVision: boolean;
17
+ enabled: true;
18
+ isDefault?: boolean;
19
+ availability?: OnlineModelAvailability;
20
+ }
21
+ export type PickerModel =
22
+ | (ModelConfig & {
23
+ source?: 'local';
24
+ isDefault?: boolean;
25
+ availability?: never;
26
+ })
27
+ | GatewayPickerModel;
28
+
7
29
  interface ModelPickerProps {
8
- models: ModelConfig[];
30
+ models: PickerModel[];
9
31
  currentModelId: string | null;
10
32
  title: string;
11
33
  /** null 选项标签(用于顾问模型"不使用");不传则不显示 null 选项 */
@@ -22,7 +44,9 @@ export function ModelPicker({
22
44
  onSelect,
23
45
  onCancel,
24
46
  }: ModelPickerProps): JSX.Element {
25
- const enabledModels = models.filter((m) => m.enabled && m.apiKey);
47
+ const enabledModels = models.filter(
48
+ (m) => m.enabled && (m.source === 'gateway' || m.apiKey),
49
+ );
26
50
  const hasNullOption = Boolean(nullOptionLabel);
27
51
  const nullIndex = hasNullOption ? enabledModels.length : -1;
28
52
  const listLength = enabledModels.length + (hasNullOption ? 1 : 0);
@@ -34,7 +58,9 @@ export function ModelPicker({
34
58
  return 0;
35
59
  })();
36
60
 
37
- const [idx, setIdx] = useState(Math.max(0, Math.min(initialIdx, listLength - 1)));
61
+ const [idx, setIdx] = useState(
62
+ Math.max(0, Math.min(initialIdx, listLength - 1)),
63
+ );
38
64
 
39
65
  useInput((input, key) => {
40
66
  if (key.escape || (key.ctrl && input === 'c')) {
@@ -54,7 +80,13 @@ export function ModelPicker({
54
80
  onSelect(null);
55
81
  } else {
56
82
  const target = enabledModels[idx];
57
- if (target) onSelect(target.id);
83
+ if (
84
+ target &&
85
+ (target.source !== 'gateway' ||
86
+ !target.availability ||
87
+ target.availability.state === 'available')
88
+ )
89
+ onSelect(target.id);
58
90
  }
59
91
  }
60
92
  });
@@ -62,9 +94,13 @@ export function ModelPicker({
62
94
  return (
63
95
  <Box flexDirection="column" paddingX={1}>
64
96
  <Box marginBottom={1}>
65
- <Text color={theme.user} bold>{title}</Text>
97
+ <Text color={theme.user} bold>
98
+ {title}
99
+ </Text>
66
100
  </Box>
67
- <Text color={theme.subtle}>在已配置的模型中选择;选择后立即生效,后续请求使用新模型。</Text>
101
+ <Text color={theme.subtle}>
102
+ 在已配置的模型中选择;选择后立即生效,后续请求使用新模型。
103
+ </Text>
68
104
  <Box flexDirection="column" marginTop={1}>
69
105
  {enabledModels.map((m, i) => {
70
106
  const active = i === idx;
@@ -72,10 +108,21 @@ export function ModelPicker({
72
108
  const displayName = m.displayName || m.model;
73
109
  return (
74
110
  <Box key={m.id} flexDirection="column">
111
+ {i > 0 && enabledModels[i - 1]?.source !== m.source ? (
112
+ <Text color={theme.subtle}>
113
+ {' '}
114
+ ── {m.source === 'gateway' ? '团队在线模型' : '本机模型'} ──
115
+ </Text>
116
+ ) : null}
75
117
  <Text color={active ? theme.user : undefined}>
76
118
  {active ? '> ' : ' '}
77
119
  {isCurrent ? '✓ ' : ' '}
78
- <Text color={active ? theme.user : undefined} bold={isCurrent}>{displayName}</Text>
120
+ <Text color={active ? theme.user : undefined} bold={isCurrent}>
121
+ {m.source === 'gateway' ? '🌐 ' : ''}
122
+ {displayName}
123
+ {m.isDefault ? ' · 默认' : ''}
124
+ {m.availability?.reason ? ` · ${m.availability.reason}` : ''}
125
+ </Text>
79
126
  {isCurrent ? <Text color={theme.subtle}> (当前)</Text> : null}
80
127
  </Text>
81
128
  <Text color={theme.subtle}>
@@ -14,35 +14,37 @@
14
14
  * 用 version 计数器驱动 setState 触发 re-render 是更顺手的写法。
15
15
  * ============================================================
16
16
  */
17
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
18
17
  import { stat } from 'node:fs/promises';
18
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
19
+ import { createAskCoordinator, setAskHandler, } from '../../askBridge.js';
19
20
  import { getWorkingDir, setWorkingDir } from '../../bootstrap/workingDir.js';
21
+ import { createCliComputerRun, createComputerUseHostGate, } from '../../cli/computerUse.js';
20
22
  import { forceCompact } from '../../context/compact.js';
23
+ import { acquireContextLock } from '../../context/contextLock.js';
21
24
  import { clearContext, loadContext, saveContext, } from '../../context/persistContext.js';
22
25
  import { resetReactiveCompactState } from '../../context/reactiveCompact.js';
23
- import { acquireContextLock } from '../../context/contextLock.js';
24
- import { workspaceIndexService } from '../../context/workspaceIndex.js';
25
- import { getActiveSession, setActiveSession, updateSessionMetadata, } from '../../context/sessionRegistry.js';
26
26
  import { resolveSessionFile, sessionFileFor, } from '../../context/sessionPath.js';
27
- import { buildBaseSystemPrompt, buildTransientPromptBundle } from '../../prompts/system.js';
27
+ import { getActiveSession, listSessionSummaries, setActiveSession, updateSessionMetadata, } from '../../context/sessionRegistry.js';
28
+ import { workspaceIndexService } from '../../context/workspaceIndex.js';
29
+ import { HumanInterventionCoordinator, } from '../../humanIntervention.js';
28
30
  import { createPromptCacheContext } from '../../llm/promptCache.js';
31
+ import { startTurnJournal, } from '../../memory/turnJournal.js';
32
+ import { createInputQueue } from '../../messageQueue.js';
33
+ import { runWithPlugins } from '../../plugins/pluginRunner.js';
34
+ import { buildBaseSystemPrompt, buildTransientPromptBundle, } from '../../prompts/system.js';
35
+ import { refreshStableSystemPrompt, upsertStableSystemMessage, } from '../../prompts/stableSystemPrompt.js';
29
36
  import { createAgentRuntimeContext, filterToolsForRuntime, memoryContextFromRuntime, } from '../../runtime/agentRuntimeContext.js';
30
- import { startTurnJournal } from '../../memory/turnJournal.js';
37
+ import { getOrCreateSessionState, sessionStateKey, } from '../../session/sessionState.js';
38
+ import { filterToolsForCategories } from '../../team/toolPolicy.js';
39
+ import { runAdvisor } from '../../tools/advisor/advisor.js';
40
+ import { classifyComputerAutomationIntent } from '../../tools/computeruse/computerIntent.js';
41
+ import { computerUseService } from '../../tools/computeruse/computerUseService.js';
42
+ import { createComputerInterventionAdapter } from '../../tools/computeruse/intervention.js';
31
43
  import { ALL_TOOLS, getToolByName } from '../../tools/index.js';
32
- import { createInputQueue } from '../../messageQueue.js';
33
- import { createAskCoordinator, setAskHandler, } from '../../askBridge.js';
34
- import { createAskSlot } from './askSlot.js';
35
- import { figures } from '../figures.js';
36
44
  import { clearFileState } from '../../tools/shared/fileState.js';
37
- import { getOrCreateSessionState, sessionStateKey } from '../../session/sessionState.js';
38
45
  import { hydrateSessionWorktree } from '../../tools/worktree/sessionWorktree.js';
39
- import { runAdvisor } from '../../tools/advisor/advisor.js';
40
- import { runWithPlugins } from '../../plugins/pluginRunner.js';
41
46
  import { dlog } from '../../utils/debugLog.js';
42
- import { createCliComputerRun, createComputerUseHostGate } from '../../cli/computerUse.js';
43
- import { computerUseService, } from '../../tools/computeruse/computerUseService.js';
44
- import { HumanInterventionCoordinator, } from '../../humanIntervention.js';
45
- import { createComputerInterventionAdapter } from '../../tools/computeruse/intervention.js';
47
+ import { createAskSlot } from './askSlot.js';
46
48
  /**
47
49
  * reasoningPreview 环形 buffer 容量(字符)。
48
50
  * LiveArea 现在多行显示思维链尾部(最近 N 行),需要喂饱足够文本;
@@ -111,7 +113,8 @@ function useThrottledFlush({ delayMs, maxChars, flushEmpty, onFlush, }) {
111
113
  }, [delayMs, flush]);
112
114
  const append = useCallback((delta) => {
113
115
  bufferRef.current += delta;
114
- if (typeof maxChars === 'number' && bufferRef.current.length >= maxChars) {
116
+ if (typeof maxChars === 'number' &&
117
+ bufferRef.current.length >= maxChars) {
115
118
  flush();
116
119
  return;
117
120
  }
@@ -131,18 +134,11 @@ export function useChat(args) {
131
134
  const [error, setError] = useState(null);
132
135
  const [transientError, setTransientError] = useState(null);
133
136
  const [interrupted, setInterrupted] = useState(false);
134
- /**
135
- * 暂态错误状态机的跨事件可变上下文(用 ref,不需要为它单独重渲染)。
136
- * - activeStepId:当前正在执行的 workflow step id(workflow_step_start 记下,
137
- * 该 step 的 workflow_step_end 清除);null = 不在任何 step 内。
138
- * - pendingLlmError:该 step 执行中捕获到的最近一次 llm_error 文案(暂存,
139
- * 等 step 结束才决定丢弃 or 提升为永久红字)。
140
- * handleEvent 通过 setters.workflowCtx 同步读写这个对象(pure 逻辑,测试可注入 stub)。
141
- */
142
- const workflowCtxRef = useRef({ activeStepId: null, pendingLlmError: null });
143
- // 工作流步骤 id → 人话进度名(title)映射:start 记入、end/skipped 回查,
144
- // 让 scrollback 三种进度行(▶/✓/⊘)都显示同一人话名而非 id。跨事件持 ref。
145
- const stepTitlesRef = useRef(new Map());
137
+ // 注:这里曾有 workflowCtxRef(activeStepId / pendingLlmError)与 stepTitlesRef,
138
+ // 服务于 yaml DSL 的 workflow_step_* 事件。那些事件随引擎删除后没有任何发送方,
139
+ // 于是 activeStepId 恒为 null、两条依赖它的暂态错误分支永远走不到 —— 一并删掉。
140
+ // 代码编排引擎把 llm_error / max_turns 在 api.ts 内部消化(不外泄给顶层),
141
+ // 不需要宿主再做这层「暂态还是永久」的裁决。
146
142
  const [pluginProgress, setPluginProgress] = useState(null);
147
143
  // ---- 工作过程显示相关 state ----
148
144
  const [compactGeneration, setCompactGeneration] = useState(0);
@@ -196,7 +192,7 @@ export function useChat(args) {
196
192
  const [pendingAskQueueCount, setPendingAskQueueCount] = useState(0);
197
193
  const [askSlot] = useState(() => createAskSlot((questions, source) => {
198
194
  setPendingAsk(questions);
199
- setPendingAskSource(questions ? source ?? null : null);
195
+ setPendingAskSource(questions ? (source ?? null) : null);
200
196
  }));
201
197
  const streamingFlush = useThrottledFlush({
202
198
  delayMs: STREAM_FLUSH_MS,
@@ -240,7 +236,6 @@ export function useChat(args) {
240
236
  setRunningToolsMap(new Map());
241
237
  // 暂态错误是"过程级"提示,turn 结束 / 切换时一并清掉,不残留到下一轮
242
238
  setTransientError(null);
243
- workflowCtxRef.current = { activeStepId: null, pendingLlmError: null };
244
239
  }, []);
245
240
  /** turn 结束 / 中断 / 切换时一并取消所有节流 buffer 的 pending timer。 */
246
241
  const cancelAllThrottles = useCallback(() => {
@@ -323,19 +318,27 @@ export function useChat(args) {
323
318
  */
324
319
  const runManualAdvisor = useCallback(async (note) => {
325
320
  if (isLoading) {
326
- return { ok: false, error: '当前有任务在执行;等它结束或按 ESC 中断后再咨询顾问。' };
321
+ return {
322
+ ok: false,
323
+ error: '当前有任务在执行;等它结束或按 ESC 中断后再咨询顾问。',
324
+ };
327
325
  }
328
326
  const callId = 'manual-advisor';
329
327
  const ac = new AbortController();
330
328
  abortRef.current = ac;
331
329
  setIsLoading(true);
332
330
  setProgressStage('tool_executing');
333
- setRunningToolsMap(new Map([[callId, {
331
+ setRunningToolsMap(new Map([
332
+ [
333
+ callId,
334
+ {
334
335
  toolName: 'Advisor',
335
336
  argsPreview: note ?? '',
336
337
  status: 'running',
337
338
  argsFriendly: '正在咨询顾问模型',
338
- }]]));
339
+ },
340
+ ],
341
+ ]));
339
342
  try {
340
343
  return await runAdvisor(note ? { note } : {}, ac.signal, {
341
344
  history: historyRef.current,
@@ -347,7 +350,10 @@ export function useChat(args) {
347
350
  const current = prev.get(callId);
348
351
  if (!current)
349
352
  return prev;
350
- return new Map(prev).set(callId, { ...current, progress: message });
353
+ return new Map(prev).set(callId, {
354
+ ...current,
355
+ progress: message,
356
+ });
351
357
  });
352
358
  },
353
359
  });
@@ -363,7 +369,9 @@ export function useChat(args) {
363
369
  // 用户看到「排队 1 条」却永远不执行,直到下次提交才错序跑掉。
364
370
  const queued = inputQueue.dequeue();
365
371
  if (queued)
366
- queueMicrotask(() => { void submitRef.current?.(queued.value); });
372
+ queueMicrotask(() => {
373
+ void submitRef.current?.(queued.value);
374
+ });
367
375
  }
368
376
  }, [isLoading, inputQueue]);
369
377
  const submit = useCallback(async (input) => {
@@ -373,7 +381,7 @@ export function useChat(args) {
373
381
  if (isLoading) {
374
382
  inputQueue.enqueue(trimmed, 'next');
375
383
  const running = Array.from(runningToolsRef.current.values());
376
- const allCancelable = running.length > 0 && running.every(t => t.isCancelable);
384
+ const allCancelable = running.length > 0 && running.every((t) => t.isCancelable);
377
385
  if (allCancelable) {
378
386
  abortRef.current?.abort('interrupt');
379
387
  }
@@ -391,8 +399,6 @@ export function useChat(args) {
391
399
  setProgressStage('idle');
392
400
  setReasoningPreview('');
393
401
  setRunningToolsMap(new Map());
394
- // 重置暂态错误状态机(防上一轮工作流残留)
395
- workflowCtxRef.current = { activeStepId: null, pendingLlmError: null };
396
402
  const ac = new AbortController();
397
403
  abortRef.current = ac;
398
404
  let releaseContextLock = null;
@@ -419,7 +425,9 @@ export function useChat(args) {
419
425
  historyRef.current.length = 0;
420
426
  historyRef.current.push(...latest, ...ephemeral);
421
427
  }
422
- const workspace = await workspaceIndexService.findByPath(getWorkingDir()).catch(() => null);
428
+ const workspace = await workspaceIndexService
429
+ .findByPath(getWorkingDir())
430
+ .catch(() => null);
423
431
  const computerRun = computerUseMode !== 'disabled'
424
432
  ? createCliComputerRun({
425
433
  mode: computerUseMode,
@@ -444,15 +452,20 @@ export function useChat(args) {
444
452
  },
445
453
  })
446
454
  : undefined;
447
- const toolGate = computerRun ? createComputerUseHostGate(computerRun) : undefined;
455
+ const toolGate = computerRun
456
+ ? createComputerUseHostGate(computerRun)
457
+ : undefined;
448
458
  const turnSessionState = getOrCreateSessionState(sessionStateKey({
449
- surface: 'tui', workspaceId: workspace?.id,
459
+ surface: 'tui',
460
+ workspaceId: workspace?.id,
450
461
  cwd: workspace?.id ? undefined : getWorkingDir(),
451
462
  sessionId: activeSessionIdRef.current,
452
463
  }));
453
464
  await hydrateSessionWorktree({
454
- sessionState: turnSessionState, workspaceId: workspace?.id,
455
- sessionId: activeSessionIdRef.current, cwd: getWorkingDir(),
465
+ sessionState: turnSessionState,
466
+ workspaceId: workspace?.id,
467
+ sessionId: activeSessionIdRef.current,
468
+ cwd: getWorkingDir(),
456
469
  });
457
470
  const effectiveCwd = turnSessionState.activeWorktree?.path ?? getWorkingDir();
458
471
  const runtimeContext = createAgentRuntimeContext({
@@ -465,18 +478,33 @@ export function useChat(args) {
465
478
  memoryAccess: 'read-write',
466
479
  interactiveAsk: true,
467
480
  computer: computerRun,
481
+ computerIntent: classifyComputerAutomationIntent(trimmed, turnSessionState.computerAutomation),
468
482
  computerIntervention,
469
483
  toolGate,
470
484
  });
471
- const turnTools = filterToolsForRuntime(ALL_TOOLS, runtimeContext);
485
+ const runtimeTools = filterToolsForRuntime(ALL_TOOLS, runtimeContext);
486
+ const sessionSummary = (await listSessionSummaries(getWorkingDir())).find((session) => session.id === activeSessionIdRef.current);
487
+ const currentProvider = providerRef.current;
488
+ const effectiveGatewayCategories = currentProvider.source === 'gateway'
489
+ ? [
490
+ ...new Set((sessionSummary?.onlineToolCategories ??
491
+ currentProvider.gatewayDefaultToolCategories ??
492
+ currentProvider.gatewayMaxToolCategories ??
493
+ []).filter((category) => currentProvider.gatewayMaxToolCategories?.includes(category) ?? true)),
494
+ ]
495
+ : undefined;
496
+ const turnProvider = currentProvider.source === 'gateway'
497
+ ? {
498
+ ...currentProvider,
499
+ gatewayToolCategories: effectiveGatewayCategories,
500
+ }
501
+ : currentProvider;
502
+ const turnTools = currentProvider.source === 'gateway'
503
+ ? filterToolsForCategories(runtimeTools, effectiveGatewayCategories)
504
+ : runtimeTools;
472
505
  const toolSignature = `${effectiveCwd}\0${turnTools.map((tool) => tool.name).join(',')}`;
473
506
  if (promptToolSignatureRef.current !== toolSignature) {
474
- const stablePrompt = await buildBaseSystemPrompt(effectiveCwd, turnTools);
475
- const rest = historyRef.current[0]?.role === 'system'
476
- ? historyRef.current.slice(1)
477
- : [...historyRef.current];
478
- historyRef.current.length = 0;
479
- historyRef.current.push({ role: 'system', content: stablePrompt }, ...rest);
507
+ await refreshStableSystemPrompt(historyRef.current, effectiveCwd, turnTools);
480
508
  promptToolSignatureRef.current = toolSignature;
481
509
  }
482
510
  // 每回合只刷新易变层;稳定层仅在实际能力目录变化时重建。
@@ -502,11 +530,12 @@ export function useChat(args) {
502
530
  userInput: trimmed,
503
531
  }).catch(() => null);
504
532
  for await (const ev of runWithPlugins(trimmed, {
505
- provider: providerRef.current,
533
+ provider: turnProvider,
506
534
  history: historyRef.current,
507
535
  signal: ac.signal,
508
536
  runtimeContext,
509
537
  allowedTools: turnTools.map((tool) => tool.name),
538
+ availableTools: turnTools,
510
539
  sessionState: turnSessionState,
511
540
  parseInlineImages: true,
512
541
  ...(turnTransient ? { transientBundle: turnTransient } : {}),
@@ -539,9 +568,6 @@ export function useChat(args) {
539
568
  setContextUsage,
540
569
  // 暂态错误(工作流步内 llm_error / 重试进度)→ LiveArea 黄字
541
570
  setTransientError,
542
- workflowCtx: workflowCtxRef.current,
543
- // 步骤 id→人话名映射:scrollback 进度行三态(▶/✓/⊘)统一显示 title
544
- stepTitles: stepTitlesRef.current,
545
571
  // 节流相关 —— buffer 累积 + 100ms timer flush
546
572
  appendStreamingDelta: streamingFlush.append,
547
573
  flushStreamingBuffer: streamingFlush.flush,
@@ -576,7 +602,9 @@ export function useChat(args) {
576
602
  activeComputerRunRef.current = null;
577
603
  runningToolsRef.current.clear();
578
604
  // 记账失败不影响落盘与解锁(它是附加能力,不是功能)。
579
- await turnJournal?.finish(historyRef.current, turnJournalStart).catch(() => undefined);
605
+ await turnJournal
606
+ ?.finish(historyRef.current, turnJournalStart)
607
+ .catch(() => undefined);
580
608
  turnJournal = null;
581
609
  // v2 multi-session:持久化到当前 active session 文件。
582
610
  try {
@@ -598,7 +626,6 @@ export function useChat(args) {
598
626
  }, [
599
627
  bump,
600
628
  isLoading,
601
- sessionFile,
602
629
  streamingFlush,
603
630
  cancelAllThrottles,
604
631
  reasoningFlush,
@@ -626,7 +653,9 @@ export function useChat(args) {
626
653
  if (!context)
627
654
  return '已撤销后续回合授权;当前没有正在运行的 Computer Use。';
628
655
  computerInterventions.abort(context);
629
- const response = await computerUseService.request(context, { action: 'stop' });
656
+ const response = await computerUseService.request(context, {
657
+ action: 'stop',
658
+ });
630
659
  return response.ok
631
660
  ? '已停止当前回合的 Computer Use,并撤销后续回合授权。'
632
661
  : `已撤销后续回合授权;原生停止失败:${response.error?.message ?? '未知错误'}`;
@@ -713,7 +742,9 @@ export function useChat(args) {
713
742
  // 清空磁盘上的持久化文件(防止下次启动又加载损坏数据)
714
743
  await clearContext();
715
744
  // 清空 pre-read guard 状态表(防止跨 session 的 Read 记录污染新会话)
716
- const workspace = await workspaceIndexService.findByPath(getWorkingDir()).catch(() => null);
745
+ const workspace = await workspaceIndexService
746
+ .findByPath(getWorkingDir())
747
+ .catch(() => null);
717
748
  clearFileState(getOrCreateSessionState(sessionStateKey({
718
749
  surface: 'tui',
719
750
  workspaceId: workspace?.id,
@@ -740,7 +771,9 @@ export function useChat(args) {
740
771
  let success = false;
741
772
  try {
742
773
  const cwd = getWorkingDir();
743
- const workspace = await workspaceIndexService.findByPath(cwd).catch(() => null);
774
+ const workspace = await workspaceIndexService
775
+ .findByPath(cwd)
776
+ .catch(() => null);
744
777
  const r = await forceCompact(historyRef.current, args.provider, undefined, undefined, createPromptCacheContext(`workspace:${workspace?.id ?? cwd}:session:${activeSessionIdRef.current}`));
745
778
  historyRef.current.length = 0;
746
779
  historyRef.current.push(...r.messages);
@@ -892,12 +925,12 @@ export function useChat(args) {
892
925
  activeSessionIdRef.current = targetSessionId;
893
926
  setActiveSessionId(targetSessionId);
894
927
  historyRef.current.length = 0;
895
- historyRef.current.push({ role: 'system', content: systemPrompt });
928
+ historyRef.current.push(...(loaded ?? []));
929
+ upsertStableSystemMessage(historyRef.current, systemPrompt);
896
930
  promptToolSignatureRef.current = '';
897
- if (loaded?.length) {
898
- historyRef.current.push(...(loaded[0]?.role === 'system' ? loaded.slice(1) : loaded));
899
- }
900
- const targetWorkspace = await workspaceIndexService.findByPath(targetCwd).catch(() => null);
931
+ const targetWorkspace = await workspaceIndexService
932
+ .findByPath(targetCwd)
933
+ .catch(() => null);
901
934
  clearFileState(getOrCreateSessionState(sessionStateKey({
902
935
  surface: 'tui',
903
936
  workspaceId: targetWorkspace?.id,
@@ -919,6 +952,9 @@ export function useChat(args) {
919
952
  // 返回同一引用,Ink <Static items={history}> 浅比较看不到 prop 变化 → 不 commit
920
953
  // 新增 message → turn 结束 LiveArea 消失后屏幕空白,看起来像"输出被吃掉"。
921
954
  // slice 后元素引用不变,只是数组容器是新的,足够让 Static 检测到 length 增长并 commit。
955
+ // version is an explicit invalidation counter; the callback intentionally
956
+ // reads the ref-backed history rather than the counter itself.
957
+ // biome-ignore lint/correctness/useExhaustiveDependencies: version intentionally invalidates the ref-backed history snapshot
922
958
  const history = useMemo(() => historyRef.current.slice(), [version]);
923
959
  return {
924
960
  history,
@@ -960,79 +996,12 @@ export function useChat(args) {
960
996
  };
961
997
  }
962
998
  export function handleEvent(ev, setters) {
963
- // ---- 工作流进度事件(WorkflowEvent,不在 LoopEvent union 里)----
964
- // 渲染成持久的暗色行落进 scrollback:跑到哪一步、成功/失败/跳过都看得见,
965
- // 且出错后仍停留在屏幕上 —— 解决"工作流执行过程不可见、不知道停在哪"。
966
- const wf = ev;
967
- // 据 id 回查人话进度名:声明了 title 的步走 title,否则回落 id(end/skipped 用)。
968
- const titleOrId = (id) => (id && setters.stepTitles?.get(id)) || id || '?';
969
- switch (wf.type) {
970
- case 'workflow_start':
971
- setters.emitProgressLine?.(`${figures.step} 工作流 ${wf.name} 开始(共 ${wf.totalSteps} 步)`);
972
- // 新工作流开始:清空上一条工作流残留的 title 映射,避免同名步串味。
973
- setters.stepTitles?.clear();
974
- // 工作流开始:立即刷新 token(可能已积累大量前置对话上下文)
975
- setters.bump();
976
- return;
977
- case 'workflow_step_start':
978
- // 声明了 title 的步显示人话名(与状态行一致、不显示块内相对序号——嵌套块
979
- // 的 i/total 拼在一起会被误读成"跳步");未声明 title 的步保持 legacy 格式。
980
- // ⎿ 前缀:step 行挂在「▶ 工作流 x 开始」下的层次连接符(figures.elbow 语汇,
981
- // 与工具结果/蜂群树统一)。ephemeral 是尾部追加消息,不触任何既有前缀字节。
982
- if (wf.title) {
983
- if (wf.id)
984
- setters.stepTitles?.set(wf.id, wf.title);
985
- setters.emitProgressLine?.(` ${figures.elbow} ${figures.step} ${wf.title}`);
986
- }
987
- else {
988
- setters.emitProgressLine?.(` ${figures.elbow} ${figures.step} ${(wf.index ?? 0) + 1}/${wf.total ?? '?'} ${wf.id} (${wf.kind})`);
989
- }
990
- // 暂态错误状态机:记下当前正在执行的 step id,进入"该步内的 llm_error 暂态化"窗口。
991
- // 进新步先清掉上一步可能残留的暂态错误(上一步已 end、不应跨步显示)。
992
- if (setters.workflowCtx) {
993
- setters.workflowCtx.activeStepId = wf.id ?? null;
994
- setters.workflowCtx.pendingLlmError = null;
995
- }
996
- setters.setTransientError?.(null);
997
- return;
998
- case 'workflow_step_end':
999
- setters.emitProgressLine?.(` ${figures.elbow} ${wf.ok ? figures.ok : figures.fail} ${titleOrId(wf.id)}${wf.error ? `:${wf.error}` : ''}`);
1000
- // 暂态错误裁决(仅当 end 的是当前活跃步):
1001
- // ok:true → 重试/恢复成功 → 丢弃 pending llm_error,短暂显示"已恢复"后随刷新消失。
1002
- // ok:false → 该步彻底失败 → 把暂态错误提升为永久红字(chat.error,进 scrollback 上方)。
1003
- if (setters.workflowCtx && setters.workflowCtx.activeStepId === wf.id) {
1004
- const pending = setters.workflowCtx.pendingLlmError;
1005
- if (wf.ok) {
1006
- if (pending) {
1007
- // 成功收回:留一条灰底"已恢复"提示,下一次状态行刷新自然覆盖消失
1008
- setters.setTransientError?.(`${figures.ok} ${wf.id} 已恢复(此前 LLM 调用失败已重试成功)`);
1009
- }
1010
- else {
1011
- setters.setTransientError?.(null);
1012
- }
1013
- }
1014
- else {
1015
- // 彻底失败:暂态升永久红字。优先用 step.error,回落到 pending llm_error。
1016
- const finalMsg = wf.error ?? pending;
1017
- if (finalMsg)
1018
- setters.setError(finalMsg);
1019
- setters.setTransientError?.(null);
1020
- }
1021
- setters.workflowCtx.activeStepId = null;
1022
- setters.workflowCtx.pendingLlmError = null;
1023
- }
1024
- // 步骤完成:强制刷新 token(agent/llm 步骤可能写入大量上下文)
1025
- setters.bump();
1026
- return;
1027
- case 'workflow_step_skipped':
1028
- setters.emitProgressLine?.(` ${figures.elbow} ${figures.skip} ${titleOrId(wf.id)}:${wf.reason ?? ''}`);
1029
- return;
1030
- case 'workflow_done':
1031
- setters.emitProgressLine?.(`${figures.ok} 工作流 ${wf.name} 完成`);
1032
- // 工作流结束:最终刷新(反映完整执行后的上下文量)
1033
- setters.bump();
1034
- return;
1035
- }
999
+ // ⚠️ 这里曾有一整块 `workflow_start` / `workflow_step_start` / `workflow_step_end` /
1000
+ // `workflow_step_skipped` / `workflow_done` 的渲染逻辑(外加一个 activeStepId
1001
+ // 状态机)。那是 yaml DSL 引擎的事件,随引擎一起删除后**一个发送方都不剩**,
1002
+ // 只有测试自己合成它们 —— 纯死代码。
1003
+ //
1004
+ // V2 工作流发结构化 `workflow_progress`;旧插件仍可发 `plugin_progress`。
1036
1005
  // 收口到 LoopEvent:未识别的 PluginEvent type 走 default no-op
1037
1006
  const e = ev;
1038
1007
  switch (e.type) {
@@ -1060,6 +1029,13 @@ export function handleEvent(ev, setters) {
1060
1029
  setters.setRunningToolsMap(() => new Map());
1061
1030
  setters.bump();
1062
1031
  break;
1032
+ case 'assistant_draft_discarded':
1033
+ setters.flushStreamingBuffer();
1034
+ setters.setStreamingText(() => '');
1035
+ setters.cancelReasoningFlush();
1036
+ setters.setReasoningPreview(() => '');
1037
+ setters.setProgressStage('thinking');
1038
+ break;
1063
1039
  case 'tool_start':
1064
1040
  // 把工具加入运行集合;并行多个工具时这里会累积。
1065
1041
  // v2: argsFriendly 是 loop.ts 通过 LoopEvent 扩展字段传过来的人话描述
@@ -1085,7 +1061,11 @@ export function handleEvent(ev, setters) {
1085
1061
  if (!current)
1086
1062
  return prev;
1087
1063
  const next = new Map(prev);
1088
- next.set(e.toolCallId, { ...current, progress: e.message, progressDetail: e.detail });
1064
+ next.set(e.toolCallId, {
1065
+ ...current,
1066
+ progress: e.message,
1067
+ progressDetail: e.detail,
1068
+ });
1089
1069
  return next;
1090
1070
  });
1091
1071
  setters.scheduleToolBump();
@@ -1145,29 +1125,12 @@ export function handleEvent(ev, setters) {
1145
1125
  setters.bump();
1146
1126
  break;
1147
1127
  }
1148
- // 工作流步执行中的 max_turns 是可恢复截断信号:runner 会在共享 history 上续跑。
1149
- // 这里不要落入永久红字错误区;顶层非工作流 max_turns 仍保持原有错误展示。
1150
- if (code === 'max_turns' &&
1151
- setters.workflowCtx &&
1152
- setters.workflowCtx.activeStepId !== null &&
1153
- setters.setTransientError) {
1154
- setters.setTransientError('↻ 当前步骤达到轮数预算,正在续跑…');
1155
- setters.bump();
1156
- break;
1157
- }
1158
- // 工作流步执行中的 llm_error:暂态而非永久红字 ——
1159
- // 该步通常会被重试,这里只暂存 + 喂 LiveArea 黄字,等 step_end 裁决去留。
1160
- // 非工作流场景(无活跃 step,或缺 setTransientError 降级)走原有永久红字路径。
1161
- if (code === 'llm_error' &&
1162
- setters.workflowCtx &&
1163
- setters.workflowCtx.activeStepId !== null &&
1164
- setters.setTransientError) {
1165
- setters.workflowCtx.pendingLlmError = e.error;
1166
- setters.setTransientError(`⚠ LLM 调用失败(重试中):${e.error}`);
1167
- setters.bump();
1168
- break;
1169
- }
1170
- // 其余:顶层 halt(无 code)、非工作流 llm_error、aborted 等 → 永久红字。
1128
+ // 注:这里曾有两条「工作流步内的 max_turns / llm_error 降级成暂态黄字」分支,
1129
+ // 都以 `workflowCtx.activeStepId !== null` 为前提。那个 id 由 yaml DSL 的
1130
+ // workflow_step_start 事件写入,事件删除后恒为 null,两条分支永远走不到。
1131
+ // 代码编排引擎把这两种错误在 `api.ts` 内部就地消化(`continue`,不外泄给顶层),
1132
+ // 顶层根本收不到 —— 所以不是「少了个降级」,而是这层判断已无对象。
1133
+ // 其余:顶层 halt(无 code)、llm_error、aborted 等 → 永久红字。
1171
1134
  setters.setError(e.error);
1172
1135
  setters.bump();
1173
1136
  break;
@@ -1192,6 +1155,14 @@ export function handleEvent(ev, setters) {
1192
1155
  max: e.max,
1193
1156
  message: e.message,
1194
1157
  });
1158
+ // 同时落一行进 scrollback。状态行是**覆盖刷新**的:一条二十步的工作流跑完,
1159
+ // 状态行只剩最后一步,前面十九步去哪了、在哪一步失败的全查不到 —— 而排障
1160
+ // 恰恰总发生在跑完之后。legacy 靠 workflow_step_* 事件做这件事,那套事件随
1161
+ // yaml 引擎删了,这里由 plugin_progress 承担同一职责。
1162
+ // 走 ephemeral 行:只进展示,不进 history、不被 saveContext 持久化。
1163
+ if (typeof e.message === 'string' && e.message.length > 0) {
1164
+ setters.emitProgressLine?.(e.message);
1165
+ }
1195
1166
  // 重试进度也镜像到暂态行(覆盖刷新):runner 在重试时发 "↻ 重试 x N/M…"。
1196
1167
  // 与 warning 分支互为补充(plugin_progress 文案更短,适合状态行下方一行)。
1197
1168
  if (setters.setTransientError &&
@@ -1201,6 +1172,24 @@ export function handleEvent(ev, setters) {
1201
1172
  }
1202
1173
  setters.bump();
1203
1174
  break;
1175
+ case 'workflow_progress': {
1176
+ const indent = ' '.repeat(e.depth ?? 0);
1177
+ const count = e.current !== undefined && e.total !== undefined
1178
+ ? `${e.current}/${e.total} `
1179
+ : '';
1180
+ const message = `${indent}${count}${e.message ?? e.phase}`;
1181
+ setters.setPluginProgress({
1182
+ pluginId: e.workflow,
1183
+ current: e.current,
1184
+ max: e.total,
1185
+ message,
1186
+ });
1187
+ setters.emitProgressLine?.(message);
1188
+ if (e.status === 'warning')
1189
+ setters.setTransientError?.(message);
1190
+ setters.bump();
1191
+ break;
1192
+ }
1204
1193
  case 'reasoning':
1205
1194
  // reasoning delta 频率跟 text delta 一样高(60+/秒),不节流的话每个 delta 立即
1206
1195
  // setReasoningPreview → LiveArea rerender → Ink 重绘扛不住。