minimal-agent 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -0,0 +1,428 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile, realpath, rm } from 'node:fs/promises';
3
+ import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
4
+ import { z } from 'zod';
5
+
6
+ import { getWorkingDir } from '../../bootstrap/workingDir.js';
7
+ import type {
8
+ FileActivityMetadata,
9
+ Tool,
10
+ ToolCallContext,
11
+ ToolResult,
12
+ } from '../../types.js';
13
+ import { buildPatchSummary } from '../shared/diffSummary.js';
14
+ import { fileActivityMetadata } from '../shared/fileActivity.js';
15
+ import { emitFileMutation } from '../shared/fileMutationBus.js';
16
+ import { hashFileBytes, recordRead } from '../shared/fileState.js';
17
+ import {
18
+ type FileBomEncoding,
19
+ applyLineEnding,
20
+ atomicWriteFile,
21
+ encodeTextFile,
22
+ hasBinaryExtension,
23
+ readTextFile,
24
+ } from '../shared/fileUtils.js';
25
+ import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
26
+
27
+ interface PatchHunk {
28
+ header: string;
29
+ oldStart?: number;
30
+ lines: Array<{ kind: 'context' | 'add' | 'delete'; text: string }>;
31
+ }
32
+
33
+ type PatchOperation =
34
+ | { kind: 'add'; path: string; content: string }
35
+ | { kind: 'delete'; path: string }
36
+ | { kind: 'update'; path: string; moveTo?: string; hunks: PatchHunk[] };
37
+
38
+ const schema = z.object({
39
+ patch: z.string().min(1).max(10_000_000),
40
+ });
41
+ type ApplyPatchInput = z.infer<typeof schema>;
42
+
43
+ function fail(message: string): never {
44
+ throw new Error(message);
45
+ }
46
+
47
+ /** Parse the Codex apply_patch envelope without invoking a platform patch binary. */
48
+ export function parseApplyPatch(input: string): PatchOperation[] {
49
+ const lines = input.replaceAll('\r\n', '\n').split('\n');
50
+ if (lines[0] !== '*** Begin Patch') fail('补丁必须以 *** Begin Patch 开始');
51
+ const operations: PatchOperation[] = [];
52
+ let index = 1;
53
+ while (index < lines.length) {
54
+ const line = lines[index]!;
55
+ if (line === '*** End Patch') {
56
+ if (lines.slice(index + 1).some((item) => item.trim()))
57
+ fail('*** End Patch 后不能再有内容');
58
+ if (!operations.length) fail('补丁中没有文件操作');
59
+ return operations;
60
+ }
61
+ if (line.startsWith('*** Add File: ')) {
62
+ const path = line.slice('*** Add File: '.length);
63
+ index += 1;
64
+ const added: string[] = [];
65
+ while (index < lines.length && !lines[index]!.startsWith('*** ')) {
66
+ const contentLine = lines[index]!;
67
+ if (!contentLine.startsWith('+'))
68
+ fail(`Add File ${path} 的内容行必须以 + 开头(第 ${index + 1} 行)`);
69
+ added.push(contentLine.slice(1));
70
+ index += 1;
71
+ }
72
+ operations.push({
73
+ kind: 'add',
74
+ path,
75
+ content: added.length ? `${added.join('\n')}\n` : '',
76
+ });
77
+ continue;
78
+ }
79
+ if (line.startsWith('*** Delete File: ')) {
80
+ operations.push({
81
+ kind: 'delete',
82
+ path: line.slice('*** Delete File: '.length),
83
+ });
84
+ index += 1;
85
+ continue;
86
+ }
87
+ if (line.startsWith('*** Update File: ')) {
88
+ const path = line.slice('*** Update File: '.length);
89
+ index += 1;
90
+ let moveTo: string | undefined;
91
+ if (lines[index]?.startsWith('*** Move to: ')) {
92
+ moveTo = lines[index]!.slice('*** Move to: '.length);
93
+ index += 1;
94
+ }
95
+ const hunks: PatchHunk[] = [];
96
+ while (index < lines.length && !lines[index]!.startsWith('*** ')) {
97
+ const headerLine = lines[index]!;
98
+ if (!headerLine.startsWith('@@'))
99
+ fail(`Update File ${path} 缺少 @@ hunk 头(第 ${index + 1} 行)`);
100
+ const match = /^@@(?: -(\d+)(?:,\d+)? \+\d+(?:,\d+)?)? @@\s*(.*)$/.exec(
101
+ headerLine,
102
+ );
103
+ const header = match
104
+ ? match[2]!
105
+ : headerLine.slice(2).replace(/^\s+|\s+$/g, '');
106
+ const oldStart = match?.[1] ? Number(match[1]) : undefined;
107
+ index += 1;
108
+ const hunkLines: PatchHunk['lines'] = [];
109
+ while (
110
+ index < lines.length &&
111
+ !lines[index]!.startsWith('@@') &&
112
+ (!lines[index]!.startsWith('*** ') ||
113
+ lines[index] === '*** End of File')
114
+ ) {
115
+ const hunkLine = lines[index]!;
116
+ if (hunkLine === '*** End of File') {
117
+ index += 1;
118
+ continue;
119
+ }
120
+ const prefix = hunkLine[0];
121
+ if (prefix !== ' ' && prefix !== '+' && prefix !== '-')
122
+ fail(`hunk 内容行必须以空格、+ 或 - 开头(第 ${index + 1} 行)`);
123
+ hunkLines.push({
124
+ kind:
125
+ prefix === ' ' ? 'context' : prefix === '+' ? 'add' : 'delete',
126
+ text: hunkLine.slice(1),
127
+ });
128
+ index += 1;
129
+ }
130
+ if (!hunkLines.length) fail(`Update File ${path} 包含空 hunk`);
131
+ hunks.push({ header, oldStart, lines: hunkLines });
132
+ }
133
+ if (!hunks.length && !moveTo) fail(`Update File ${path} 没有 hunk`);
134
+ operations.push({
135
+ kind: 'update',
136
+ path,
137
+ ...(moveTo ? { moveTo } : {}),
138
+ hunks,
139
+ });
140
+ continue;
141
+ }
142
+ fail(`无法识别补丁指令(第 ${index + 1} 行):${line}`);
143
+ }
144
+ fail('补丁缺少 *** End Patch');
145
+ }
146
+
147
+ function within(root: string, candidate: string): boolean {
148
+ const rel = relative(root, candidate);
149
+ return (
150
+ rel === '' ||
151
+ (!isAbsolute(rel) && rel !== '..' && !rel.startsWith(`..${sep}`))
152
+ );
153
+ }
154
+
155
+ async function nearestExistingAncestor(path: string): Promise<string> {
156
+ let current = path;
157
+ while (!existsSync(current)) {
158
+ const parent = dirname(current);
159
+ if (parent === current) break;
160
+ current = parent;
161
+ }
162
+ return realpath(current);
163
+ }
164
+
165
+ async function workspacePath(raw: string, cwd: string): Promise<string> {
166
+ if (!raw || isAbsolute(raw) || raw.includes('\0'))
167
+ fail(`补丁路径必须是非空的工作区相对路径:${raw}`);
168
+ const absolute = resolve(cwd, raw);
169
+ const rel = relative(resolve(cwd), absolute);
170
+ if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))
171
+ fail(`补丁路径越过工作区边界:${raw}`);
172
+ const physicalRoot = await realpath(resolve(cwd)).catch(() => resolve(cwd));
173
+ const physicalBoundary = existsSync(absolute)
174
+ ? await realpath(absolute)
175
+ : await nearestExistingAncestor(dirname(absolute));
176
+ if (!within(physicalRoot, physicalBoundary))
177
+ fail(`补丁路径通过符号链接越过工作区边界:${raw}`);
178
+ if (hasBinaryExtension(absolute)) fail(`ApplyPatch 不支持二进制文件:${raw}`);
179
+ return absolute;
180
+ }
181
+
182
+ export function applyHunks(original: string, hunks: PatchHunk[]): string {
183
+ const normalized = original.replaceAll('\r\n', '\n');
184
+ const trailingNewline = normalized.endsWith('\n');
185
+ const lines = normalized.split('\n');
186
+ if (trailingNewline) lines.pop();
187
+ let cursor = 0;
188
+ for (const hunk of hunks) {
189
+ if (hunk.header) {
190
+ const anchor = lines.findIndex(
191
+ (line, index) => index >= cursor && line.includes(hunk.header),
192
+ );
193
+ if (anchor < 0) fail(`找不到 hunk 锚点:${hunk.header}`);
194
+ cursor = anchor;
195
+ }
196
+ const before = hunk.lines
197
+ .filter((line) => line.kind !== 'add')
198
+ .map((line) => line.text);
199
+ const after = hunk.lines
200
+ .filter((line) => line.kind !== 'delete')
201
+ .map((line) => line.text);
202
+ const matchesAt = (start: number) =>
203
+ before.every((line, offset) => lines[start + offset] === line);
204
+ let at = -1;
205
+ if (!before.length) {
206
+ at =
207
+ hunk.oldStart === undefined
208
+ ? cursor
209
+ : Math.max(cursor, Math.min(lines.length, hunk.oldStart - 1));
210
+ } else {
211
+ for (
212
+ let index = cursor;
213
+ index <= lines.length - before.length;
214
+ index += 1
215
+ ) {
216
+ if (matchesAt(index)) {
217
+ at = index;
218
+ break;
219
+ }
220
+ }
221
+ if (at < 0 && cursor > 0) {
222
+ const matches: number[] = [];
223
+ for (let index = 0; index <= lines.length - before.length; index += 1)
224
+ if (matchesAt(index)) matches.push(index);
225
+ if (matches.length === 1) at = matches[0]!;
226
+ }
227
+ }
228
+ if (at < 0)
229
+ fail(`hunk 上下文与当前文件不匹配:${before.join('\n').slice(0, 240)}`);
230
+ lines.splice(at, before.length, ...after);
231
+ cursor = at + after.length;
232
+ }
233
+ return `${lines.join('\n')}${trailingNewline ? '\n' : ''}`;
234
+ }
235
+
236
+ interface StagedFile {
237
+ path: string;
238
+ label: string;
239
+ before?: Buffer;
240
+ beforeText: string;
241
+ after?: string;
242
+ encoding: FileBomEncoding;
243
+ activity: 'created' | 'modified' | 'deleted';
244
+ }
245
+
246
+ async function stagePatch(
247
+ operations: PatchOperation[],
248
+ cwd: string,
249
+ ): Promise<StagedFile[]> {
250
+ const staged: StagedFile[] = [];
251
+ const touched = new Set<string>();
252
+ const claim = (path: string) => {
253
+ if (touched.has(path)) fail(`同一补丁不能重复操作同一路径:${path}`);
254
+ touched.add(path);
255
+ };
256
+ for (const operation of operations) {
257
+ const path = await workspacePath(operation.path, cwd);
258
+ claim(path);
259
+ if (operation.kind === 'add') {
260
+ if (existsSync(path)) fail(`Add File 目标已存在:${operation.path}`);
261
+ staged.push({
262
+ path,
263
+ label: operation.path,
264
+ beforeText: '',
265
+ after: operation.content,
266
+ encoding: 'utf8',
267
+ activity: 'created',
268
+ });
269
+ continue;
270
+ }
271
+ if (!existsSync(path))
272
+ fail(
273
+ `${operation.kind === 'delete' ? 'Delete' : 'Update'} File 不存在:${operation.path}`,
274
+ );
275
+ const snapshot = await readTextFile(path);
276
+ if (operation.kind === 'delete') {
277
+ staged.push({
278
+ path,
279
+ label: operation.path,
280
+ before: snapshot.bytes,
281
+ beforeText: snapshot.content,
282
+ encoding: snapshot.encoding,
283
+ activity: 'deleted',
284
+ });
285
+ continue;
286
+ }
287
+ const updated = applyLineEnding(
288
+ applyHunks(snapshot.content, operation.hunks),
289
+ snapshot.lineEnding,
290
+ );
291
+ if (operation.moveTo) {
292
+ const target = await workspacePath(operation.moveTo, cwd);
293
+ claim(target);
294
+ if (existsSync(target)) fail(`Move to 目标已存在:${operation.moveTo}`);
295
+ staged.push({
296
+ path,
297
+ label: operation.path,
298
+ before: snapshot.bytes,
299
+ beforeText: snapshot.content,
300
+ encoding: snapshot.encoding,
301
+ activity: 'deleted',
302
+ });
303
+ staged.push({
304
+ path: target,
305
+ label: operation.moveTo,
306
+ beforeText: '',
307
+ after: updated,
308
+ encoding: snapshot.encoding,
309
+ activity: 'created',
310
+ });
311
+ } else {
312
+ staged.push({
313
+ path,
314
+ label: operation.path,
315
+ before: snapshot.bytes,
316
+ beforeText: snapshot.content,
317
+ after: updated,
318
+ encoding: snapshot.encoding,
319
+ activity: 'modified',
320
+ });
321
+ }
322
+ }
323
+ return staged;
324
+ }
325
+
326
+ async function commit(staged: StagedFile[]): Promise<void> {
327
+ const committed: StagedFile[] = [];
328
+ try {
329
+ for (const file of staged) {
330
+ if (file.after === undefined) await rm(file.path);
331
+ else await atomicWriteFile(file.path, file.after, file.encoding);
332
+ committed.push(file);
333
+ }
334
+ } catch (error) {
335
+ const rollbackErrors: string[] = [];
336
+ for (const file of committed.reverse()) {
337
+ try {
338
+ if (file.before) await atomicWriteFile(file.path, file.before);
339
+ else await rm(file.path, { force: true });
340
+ } catch (rollbackError) {
341
+ rollbackErrors.push(
342
+ `${file.label}: ${(rollbackError as Error).message}`,
343
+ );
344
+ }
345
+ }
346
+ const suffix = rollbackErrors.length
347
+ ? `;回滚也有失败:${rollbackErrors.join(';')}`
348
+ : ';已回滚本次已落盘文件';
349
+ throw new Error(`${(error as Error).message}${suffix}`);
350
+ }
351
+ }
352
+
353
+ async function call(
354
+ input: ApplyPatchInput,
355
+ context?: ToolCallContext,
356
+ ): Promise<ToolResult> {
357
+ const cwd = context?.cwd ?? getWorkingDir();
358
+ let operations: PatchOperation[];
359
+ let staged: StagedFile[];
360
+ try {
361
+ operations = parseApplyPatch(input.patch);
362
+ staged = await stagePatch(operations, cwd);
363
+ await commit(staged);
364
+ } catch (error) {
365
+ return { ok: false, error: `ApplyPatch 失败:${(error as Error).message}` };
366
+ }
367
+
368
+ const files: FileActivityMetadata['files'] = [];
369
+ const summaries: string[] = [];
370
+ for (const file of staged) {
371
+ const afterText = file.after ?? '';
372
+ const patch = buildPatchSummary(file.beforeText, afterText, file.label);
373
+ const metadata = await fileActivityMetadata(
374
+ file.path,
375
+ file.activity,
376
+ 'not_run',
377
+ 'support',
378
+ cwd,
379
+ patch,
380
+ );
381
+ if (metadata) files.push(...metadata.files);
382
+ if (file.after === undefined)
383
+ context?.sessionState?.fileReads.entries.delete(file.path);
384
+ else
385
+ recordRead(
386
+ file.path,
387
+ {
388
+ contentHash: hashFileBytes(encodeTextFile(file.after, file.encoding)),
389
+ },
390
+ context?.sessionState?.fileReads,
391
+ );
392
+ emitFileMutation(file.path);
393
+ summaries.push(
394
+ `${file.activity}: ${file.label} (+${patch.additions} -${patch.deletions})`,
395
+ );
396
+ }
397
+ return {
398
+ ok: true,
399
+ content: `已应用补丁:\n${summaries.map((line) => `- ${line}`).join('\n')}`,
400
+ ...(files.length
401
+ ? { metadata: { kind: 'file_activity', files } as FileActivityMetadata }
402
+ : {}),
403
+ };
404
+ }
405
+
406
+ export const applyPatchTool: Tool<ApplyPatchInput> = {
407
+ name: 'ApplyPatch',
408
+ description:
409
+ 'Applies one Codex-style *** Begin Patch / *** End Patch transaction across text files. ' +
410
+ 'Supports Add File, Update File, Delete File and Move to. All operations are parsed and validated before writing; runtime failures roll back files already changed by this call. Paths must stay inside the workspace.',
411
+ inputSchema: schema,
412
+ parameters: {
413
+ type: 'object',
414
+ properties: {
415
+ patch: {
416
+ type: 'string',
417
+ description: 'Complete Codex-style patch envelope',
418
+ },
419
+ },
420
+ required: ['patch'],
421
+ },
422
+ isReadOnly: false,
423
+ isConcurrencySafe: false,
424
+ maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
425
+ interruptBehavior: () => 'block',
426
+ call: (input) => call(input),
427
+ callWithContext: (input, _signal, context) => call(input, context),
428
+ };
@@ -115,6 +115,26 @@ const WIN_BASH = detectWindowsBash();
115
115
  function effectiveShellKind() {
116
116
  return process.platform === 'win32' && !WIN_BASH ? 'cmd' : 'bash';
117
117
  }
118
+ /**
119
+ * 每台机器不同、只能运行时探测的 shell 方言警告(K1 事故修复的核心内容)。
120
+ * 单一出处:完整 description(下方)和 toolPromptGuides.ts 的压缩 override
121
+ * 都调这个函数,不允许各自抄一份文案——否则「压缩省 token」的那份会在
122
+ * 无 Git Bash 的机器上悄悄丢掉这条警告,模型照抄 POSIX 语法必挂
123
+ * (`mkdir -p` 在 cmd.exe 下不生成中间目录、`$VAR`/`export` 不存在)。
124
+ */
125
+ export function bashShellNotice() {
126
+ if (process.platform !== 'win32')
127
+ return '';
128
+ return WIN_BASH
129
+ ? `# Shell (this machine)
130
+ Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
131
+ : `# Shell (this machine) — IMPORTANT
132
+ No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
133
+ - NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
134
+ - NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
135
+ - Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
136
+ \`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`;
137
+ }
118
138
  /**
119
139
  * G1:stdout / stderr 即时缓冲上限(各自)。命令狂输出(如 cat 大文件 / yes)时,
120
140
  * 在最终统一截断之前先把内存封顶,防 OOM。取最终展示截断阈值的 2 倍 —— 正常输出不受影响,
@@ -278,6 +298,7 @@ const parameters = toToolParameters(inputSchema);
278
298
  // - 先点明"专用工具优先"的原则,把每类操作映射到对应工具
279
299
  // - 再列 Bash 自身的使用规范(绝对路径 / 不 cd / 超时 / 多命令并行...)
280
300
  // - 最后强调安全黑名单(让模型知道哪些命令会被拒,避免反复试)
301
+ const shellNotice = bashShellNotice();
281
302
  const description = `Executes a given bash command and returns its output.
282
303
 
283
304
  The working directory persists between commands, but shell state does not. The shell environment is initialized from the user's profile.
@@ -363,21 +384,7 @@ These execute normally; a \`⚠️ 警告:\` line is prepended to the output as
363
384
  - \`DELETE FROM ...\` (SQL row deletion; DROP/TRUNCATE are in level 2)
364
385
  - \`kubectl delete\`, \`terraform destroy\`
365
386
 
366
- Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${process.platform !== 'win32'
367
- ? ''
368
- : WIN_BASH
369
- ? `
370
-
371
- # Shell (this machine)
372
- Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
373
- : `
374
-
375
- # Shell (this machine) — IMPORTANT
376
- No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
377
- - NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
378
- - NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
379
- - Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
380
- \`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`}`;
387
+ Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${shellNotice ? `\n\n${shellNotice}` : ''}`;
381
388
  // ---------------- 4. call() —— 真正干活 ----------------
382
389
  async function call(input, signal, context) {
383
390
  const command = input.command;
@@ -126,6 +126,26 @@ function effectiveShellKind(): ShellKind {
126
126
  return process.platform === 'win32' && !WIN_BASH ? 'cmd' : 'bash';
127
127
  }
128
128
 
129
+ /**
130
+ * 每台机器不同、只能运行时探测的 shell 方言警告(K1 事故修复的核心内容)。
131
+ * 单一出处:完整 description(下方)和 toolPromptGuides.ts 的压缩 override
132
+ * 都调这个函数,不允许各自抄一份文案——否则「压缩省 token」的那份会在
133
+ * 无 Git Bash 的机器上悄悄丢掉这条警告,模型照抄 POSIX 语法必挂
134
+ * (`mkdir -p` 在 cmd.exe 下不生成中间目录、`$VAR`/`export` 不存在)。
135
+ */
136
+ export function bashShellNotice(): string {
137
+ if (process.platform !== 'win32') return '';
138
+ return WIN_BASH
139
+ ? `# Shell (this machine)
140
+ Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
141
+ : `# Shell (this machine) — IMPORTANT
142
+ No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
143
+ - NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
144
+ - NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
145
+ - Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
146
+ \`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`;
147
+ }
148
+
129
149
  /**
130
150
  * G1:stdout / stderr 即时缓冲上限(各自)。命令狂输出(如 cat 大文件 / yes)时,
131
151
  * 在最终统一截断之前先把内存封顶,防 OOM。取最终展示截断阈值的 2 倍 —— 正常输出不受影响,
@@ -303,6 +323,8 @@ const parameters = toToolParameters(inputSchema);
303
323
  // - 先点明"专用工具优先"的原则,把每类操作映射到对应工具
304
324
  // - 再列 Bash 自身的使用规范(绝对路径 / 不 cd / 超时 / 多命令并行...)
305
325
  // - 最后强调安全黑名单(让模型知道哪些命令会被拒,避免反复试)
326
+ const shellNotice = bashShellNotice();
327
+
306
328
  const description = `Executes a given bash command and returns its output.
307
329
 
308
330
  The working directory persists between commands, but shell state does not. The shell environment is initialized from the user's profile.
@@ -388,23 +410,7 @@ These execute normally; a \`⚠️ 警告:\` line is prepended to the output as
388
410
  - \`DELETE FROM ...\` (SQL row deletion; DROP/TRUNCATE are in level 2)
389
411
  - \`kubectl delete\`, \`terraform destroy\`
390
412
 
391
- Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${
392
- process.platform !== 'win32'
393
- ? ''
394
- : WIN_BASH
395
- ? `
396
-
397
- # Shell (this machine)
398
- Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
399
- : `
400
-
401
- # Shell (this machine) — IMPORTANT
402
- No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
403
- - NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
404
- - NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
405
- - Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
406
- \`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`
407
- }`;
413
+ Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${shellNotice ? `\n\n${shellNotice}` : ''}`;
408
414
 
409
415
  // ---------------- 4. call() —— 真正干活 ----------------
410
416
  async function call(input: BashInput, signal?: AbortSignal, context?: ToolCallContext): Promise<ToolResult> {
@@ -1,7 +1,7 @@
1
1
  const TOOL_CAPABILITIES = Object.freeze({
2
2
  Read: 'files.read', Glob: 'files.read', Grep: 'files.read',
3
3
  Snip: 'files.read',
4
- Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write',
4
+ Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write', ApplyPatch: 'files.write',
5
5
  Bash: 'shell',
6
6
  PowerShell: 'shell', TaskOutput: 'background.process', TaskStop: 'background.process',
7
7
  Trash: 'files.trash',
@@ -9,9 +9,11 @@ const TOOL_CAPABILITIES = Object.freeze({
9
9
  Skill: 'skill.invoke', EnterWorktree: 'worktree.session', ExitWorktree: 'worktree.session',
10
10
  TerminalCapture: 'terminal.capture',
11
11
  LSP: 'code.intelligence', NotebookEdit: 'files.write',
12
- WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser',
12
+ WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser', BrowserBatch: 'web.browser', BrowserCDP: 'web.browser',
13
13
  Download: 'network.download',
14
- ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor', Agent: 'subagent',
14
+ ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor', AdvisorDecision: 'advisor',
15
+ Agent: 'subagent', AgentMessage: 'subagent', AgentList: 'subagent', AgentWait: 'subagent',
16
+ AgentInterrupt: 'subagent', AgentFollowup: 'subagent',
15
17
  PresentResult: 'delivery', GenerateImage: 'media', GenerateSpeech: 'media',
16
18
  RecallMemory: 'memory', RememberMemory: 'memory', UpdateMemory: 'memory',
17
19
  ListMemories: 'memory', ForgetMemory: 'memory', SetPersona: 'memory',
@@ -19,9 +21,12 @@ const TOOL_CAPABILITIES = Object.freeze({
19
21
  SearchConversations: 'memory',
20
22
  });
21
23
  const CORE_TOOLS = new Set([
22
- 'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'NotebookEdit', 'Bash',
24
+ 'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'ApplyPatch', 'NotebookEdit', 'Bash',
25
+ ]);
26
+ const AUXILIARY_TOOLS = new Set([
27
+ 'Advisor', 'AdvisorDecision', 'Agent', 'AgentMessage', 'AgentList',
28
+ 'AgentWait', 'AgentInterrupt', 'AgentFollowup',
23
29
  ]);
24
- const AUXILIARY_TOOLS = new Set(['Advisor', 'Agent']);
25
30
  export function budgetClassForToolName(name) {
26
31
  if (CORE_TOOLS.has(name))
27
32
  return 'core';
@@ -26,7 +26,7 @@ export type ToolBudgetClass = 'core' | 'task' | 'auxiliary';
26
26
  const TOOL_CAPABILITIES: Readonly<Record<string, CapabilityId>> = Object.freeze({
27
27
  Read: 'files.read', Glob: 'files.read', Grep: 'files.read',
28
28
  Snip: 'files.read',
29
- Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write',
29
+ Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write', ApplyPatch: 'files.write',
30
30
  Bash: 'shell',
31
31
  PowerShell: 'shell', TaskOutput: 'background.process', TaskStop: 'background.process',
32
32
  Trash: 'files.trash',
@@ -34,9 +34,11 @@ const TOOL_CAPABILITIES: Readonly<Record<string, CapabilityId>> = Object.freeze(
34
34
  Skill: 'skill.invoke', EnterWorktree: 'worktree.session', ExitWorktree: 'worktree.session',
35
35
  TerminalCapture: 'terminal.capture',
36
36
  LSP: 'code.intelligence', NotebookEdit: 'files.write',
37
- WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser',
37
+ WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser', BrowserBatch: 'web.browser', BrowserCDP: 'web.browser',
38
38
  Download: 'network.download',
39
- ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor', Agent: 'subagent',
39
+ ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor', AdvisorDecision: 'advisor',
40
+ Agent: 'subagent', AgentMessage: 'subagent', AgentList: 'subagent', AgentWait: 'subagent',
41
+ AgentInterrupt: 'subagent', AgentFollowup: 'subagent',
40
42
  PresentResult: 'delivery', GenerateImage: 'media', GenerateSpeech: 'media',
41
43
  RecallMemory: 'memory', RememberMemory: 'memory', UpdateMemory: 'memory',
42
44
  ListMemories: 'memory', ForgetMemory: 'memory', SetPersona: 'memory',
@@ -45,9 +47,12 @@ const TOOL_CAPABILITIES: Readonly<Record<string, CapabilityId>> = Object.freeze(
45
47
  });
46
48
 
47
49
  const CORE_TOOLS = new Set([
48
- 'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'NotebookEdit', 'Bash',
50
+ 'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'ApplyPatch', 'NotebookEdit', 'Bash',
51
+ ]);
52
+ const AUXILIARY_TOOLS = new Set([
53
+ 'Advisor', 'AdvisorDecision', 'Agent', 'AgentMessage', 'AgentList',
54
+ 'AgentWait', 'AgentInterrupt', 'AgentFollowup',
49
55
  ]);
50
- const AUXILIARY_TOOLS = new Set(['Advisor', 'Agent']);
51
56
 
52
57
  export function budgetClassForToolName(name: string): ToolBudgetClass {
53
58
  if (CORE_TOOLS.has(name)) return 'core';
@@ -0,0 +1,32 @@
1
+ const CONTINUATION_WINDOW_MS = 30 * 60_000;
2
+ const CONTINUATION_ONLY = /^(?:请)?(?:继续|接着(?:做|操作)?|重试|再试一次|往下做|恢复操作)[。!!\s]*$/i;
3
+ const DIRECT_DESKTOP = /(?:操作(?:电脑|桌面|屏幕|窗口|系统|本机)|电脑自动化|桌面自动化|查看(?:当前)?(?:桌面|屏幕|前台窗口)|截(?:取)?(?:当前)?屏|系统设置|控制面板|任务管理器|资源管理器|访达|Finder)/i;
4
+ const GUI_ACTION = /(?:点击|双击|右键|拖拽|滚动|输入|粘贴|按(?:键|快捷键)|切换|激活|关闭|移动|调整窗口|发送|发布|上传)/i;
5
+ const APP_TARGET = /(?:在|用|打开|切换到|进入)[^,。\n]{0,28}(?:应用|软件|客户端|微信|WeChat|钉钉|飞书|Slack|QQ|邮件|Outlook|Word|Excel|PowerPoint|设置|窗口)(?:里|中|上|内|给|向|并|,|。|\s|$)/i;
6
+ const DISCUSSION_ONLY = /(?:解释|介绍|讨论|分析|评审|代码|源码|实现|设计|为什么|是什么|如何实现|测试.*ComputerUse|ComputerUse.*测试)/i;
7
+ const DIRECT_TOOL_TASK = /(?:读取|分析|查看|理解).{0,12}(?:图片|照片|截图文件|PDF|文件|附件)|(?:搜索|修改|编写|重构|构建|运行测试|查找).{0,12}(?:代码|文件|网页)|(?:搜索网页|打开网址|访问网站|网页中)/i;
8
+ /**
9
+ * Conservative, deterministic exposure classifier. It only consumes the
10
+ * current human input and a short-lived record of a real prior ComputerUse
11
+ * call; model output, page content, and tool arguments can never enable it.
12
+ */
13
+ export function classifyComputerAutomationIntent(input, continuation, now = Date.now()) {
14
+ const text = input.trim();
15
+ if (continuation
16
+ && now - continuation.lastUsedAt <= CONTINUATION_WINDOW_MS
17
+ && CONTINUATION_ONLY.test(text)) {
18
+ return { needed: true, source: 'continuation', reason: '继续最近一次桌面自动化任务' };
19
+ }
20
+ if (!text)
21
+ return { needed: false, source: 'none', reason: '没有桌面操作请求' };
22
+ if (DIRECT_TOOL_TASK.test(text) && !DIRECT_DESKTOP.test(text)) {
23
+ return { needed: false, source: 'none', reason: '专用文件、图片或 Web 工具可直接完成' };
24
+ }
25
+ if (DISCUSSION_ONLY.test(text) && !DIRECT_DESKTOP.test(text) && !GUI_ACTION.test(text)) {
26
+ return { needed: false, source: 'none', reason: '仅讨论桌面能力,没有要求实际操作' };
27
+ }
28
+ if (DIRECT_DESKTOP.test(text) || (GUI_ACTION.test(text) && APP_TARGET.test(text))) {
29
+ return { needed: true, source: 'explicit-current', reason: '用户明确要求操作原生桌面界面' };
30
+ }
31
+ return { needed: false, source: 'none', reason: '未发现明确的原生桌面操作意图' };
32
+ }