minimal-agent 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
@@ -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
+ };
@@ -56,7 +56,7 @@ import { requestUserChoice } from '../../askBridge.js';
56
56
  import { classifyCommand } from '../../irreversible/rules.js';
57
57
  import { startBackgroundTask } from '../tasks/backgroundTaskService.js';
58
58
  import { processExecutionMetadata } from '../tasks/processEvidence.js';
59
- import { permanentDeleteReason } from '../shared/permanentDeleteGuard.js';
59
+ import { permanentDeleteReason, } from '../shared/permanentDeleteGuard.js';
60
60
  import { ToolOutputStore } from '../shared/toolOutputStore.js';
61
61
  // ---------------- 0. 常量 ----------------
62
62
  const DEFAULT_TIMEOUT_MS = 120_000; // 2 min
@@ -105,6 +105,36 @@ function detectWindowsBash() {
105
105
  return null;
106
106
  }
107
107
  const WIN_BASH = detectWindowsBash();
108
+ /**
109
+ * 本工具这一刻**真正**把命令交给谁执行。
110
+ *
111
+ * 单一出处:description(告诉模型该写哪种语法)与 permanentDeleteGuard(按哪套动词
112
+ * 匹配删除命令)必须看同一个判断,否则就会出现「description 说这是 cmd、守卫却按
113
+ * bash 匹配」这种两头对不上的裂缝 —— del / rd 会因此直接穿过全部三层防护。
114
+ */
115
+ function effectiveShellKind() {
116
+ return process.platform === 'win32' && !WIN_BASH ? 'cmd' : 'bash';
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
+ }
108
138
  /**
109
139
  * G1:stdout / stderr 即时缓冲上限(各自)。命令狂输出(如 cat 大文件 / yes)时,
110
140
  * 在最终统一截断之前先把内存封顶,防 OOM。取最终展示截断阈值的 2 倍 —— 正常输出不受影响,
@@ -268,6 +298,7 @@ const parameters = toToolParameters(inputSchema);
268
298
  // - 先点明"专用工具优先"的原则,把每类操作映射到对应工具
269
299
  // - 再列 Bash 自身的使用规范(绝对路径 / 不 cd / 超时 / 多命令并行...)
270
300
  // - 最后强调安全黑名单(让模型知道哪些命令会被拒,避免反复试)
301
+ const shellNotice = bashShellNotice();
271
302
  const description = `Executes a given bash command and returns its output.
272
303
 
273
304
  The working directory persists between commands, but shell state does not. The shell environment is initialized from the user's profile.
@@ -311,8 +342,11 @@ Some commands return non-zero exit codes for informational (non-error) reasons.
311
342
  - \`test\` / \`[\` exit 1 → condition is false (the answer to a question, not a failure)
312
343
  Only exit codes ≥ 2 from these commands indicate a real failure. For all other commands, non-zero exit codes are treated as failures normally.
313
344
 
314
- # Safety
315
- The following command patterns are blocked at the tool level and will fail before execution (no need to try them):
345
+ # Safety - three levels, from strict to lenient
346
+
347
+ ## 1. Blocked outright (fails before execution - do NOT retry with variants)
348
+
349
+ Catastrophic commands (no legitimate use):
316
350
  - \`rm -rf /\` and variants targeting root, $HOME, ~, or system directories (/etc, /usr, /bin, /Windows, /Users, /home, ...)
317
351
  - Filesystem destruction: \`mkfs\`, \`format X:\`, \`dd of=/dev/sdX\`, redirects to raw block devices
318
352
  - Power management: \`shutdown\`, \`reboot\`, \`halt\`, \`poweroff\`, \`init 0/6\`
@@ -320,23 +354,37 @@ The following command patterns are blocked at the tool level and will fail befor
320
354
  - Pipe-to-shell from network: \`curl ... | sh\`, \`wget ... | bash\`, etc.
321
355
  - \`chmod 777 /\`, Windows full-disk \`del /s\` / \`rmdir /s\`, \`diskpart\`
322
356
 
323
- If you have a legitimate use case that requires one of the above patterns, ask the user to run the command themselves in their terminal — do not try to bypass the check.
357
+ Permanent deletion (bypasses the OS Trash / Recycle Bin - use the Trash tool instead):
358
+ - \`rm\`, \`unlink\`, \`rmdir\` (any shell-level file/dir deletion, any target)
359
+ - \`find ... -delete\`
360
+ - \`git clean -f\` / \`git clean --force\` (\`-n\` / \`--dry-run\` is fine)
324
361
 
325
- Separately, Bash scans for common destructive-but-recoverable patterns (\`git reset --hard\`, \`git push -f\` / \`--force\` / \`--force-with-lease\`, \`git checkout .\`, \`git restore .\`, \`git clean -f\`, \`git stash drop/clear\`, \`git branch -D\`, \`git commit --amend\` / \`--no-verify\`, \`rm -rf <path>\`, \`DROP TABLE\`, \`TRUNCATE\`, \`DELETE FROM\`, \`kubectl delete\`, \`terraform destroy\`, etc.) and prepends a \`⚠️ 警告:\` line to the output. These commands are NOT blocked — the warning is informational. Treat it as a signal to double-check intent and surface the warning to the user when relevant.${process.platform !== 'win32'
326
- ? ''
327
- : WIN_BASH
328
- ? `
362
+ To delete files or directories use the **Trash** tool (\`action: "move"\` - recoverable); to clean Git untracked files use Trash with \`action: "git-clean"\`.
363
+ Do NOT work around this by switching to \`find -delete\`, Python \`os.remove\`, Node \`fs.rm\`, or other shell variants - they are blocked the same way.
364
+ If a permanent deletion is truly required, ask the user to run it themselves in their terminal.
329
365
 
330
- # Shell (this machine)
331
- 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.`
332
- : `
366
+ ## 2. Requires user confirmation (irreversible)
333
367
 
334
- # Shell (this machine) — IMPORTANT
335
- No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
336
- - NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
337
- - NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
338
- - Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
339
- \`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`}`;
368
+ These have legitimate uses but destroy the last copy - execution pauses and asks the user to confirm. In non-interactive contexts (sub-agents, cron, batch mode) they are automatically cancelled.
369
+ - \`git push --force\` / \`-f\`, and \`git push origin +branch\` (+refspec = force push)
370
+ - \`git push --delete <branch>\` / \`git push :<branch>\` (deleting remote branches)
371
+ - \`git filter-branch\` / \`git filter-repo\` (rewriting history)
372
+ - \`git reflog expire --expire=now\` / \`git gc --prune=now\` (destroying reflog)
373
+ - \`shred -u\` / \`shred --remove\` (overwrite and delete - unrecoverable)
374
+ - SQL data destruction: \`DROP DATABASE\`, \`DROP TABLE\`, \`TRUNCATE TABLE\`
375
+
376
+ ## 3. Warning only (command still runs)
377
+
378
+ These execute normally; a \`⚠️ 警告:\` line is prepended to the output as a reminder. They are NOT blocked.
379
+ - \`git reset --hard\` (reflog keeps it recoverable)
380
+ - \`git push --force-with-lease\` (rejects if the remote has unseen commits - the safe force-push form)
381
+ - \`git checkout -- .\` / \`git restore .\` (discards uncommitted changes)
382
+ - \`git branch -D\`, \`git stash drop\` / \`git stash clear\` (local, recoverable via reflog in most cases)
383
+ - \`git commit --amend\`, \`git commit --no-verify\`
384
+ - \`DELETE FROM ...\` (SQL row deletion; DROP/TRUNCATE are in level 2)
385
+ - \`kubectl delete\`, \`terraform destroy\`
386
+
387
+ Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${shellNotice ? `\n\n${shellNotice}` : ''}`;
340
388
  // ---------------- 4. call() —— 真正干活 ----------------
341
389
  async function call(input, signal, context) {
342
390
  const command = input.command;
@@ -349,7 +397,11 @@ async function call(input, signal, context) {
349
397
  error: `安全检查拒绝执行:${forbiddenReason}\n命令:${command}`,
350
398
  };
351
399
  }
352
- const permanentDelete = permanentDeleteReason(command, 'bash');
400
+ // 传**实际执行命令的 shell**,不是工具名:win32 上找不到 Git Bash 时下面走的是
401
+ // cmd.exe(见 WIN_BASH 探测),description 也会告诉模型「这里是 cmd」,模型于是写
402
+ // del / rd —— 按 'bash' 匹配的话这两个词一个都拦不住(黑名单与 irreversible 规则表
403
+ // 同样只认 POSIX 形态),等于三层全空。
404
+ const permanentDelete = permanentDeleteReason(command, effectiveShellKind());
353
405
  if (permanentDelete)
354
406
  return { ok: false, error: `永久删除检查拒绝执行:${permanentDelete}\n命令:${command}` };
355
407
  // 4a-1. 不可逆动作闸门:毁掉「最后一份副本」的命令要**停下来问人**。