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
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from 'node:events';
2
- import { appendFile, mkdir } from 'node:fs/promises';
2
+ import { appendFile, mkdir, readdir } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import type { Message, ToolCallContext, ToolResult } from '../../types.js';
5
5
  import type { AgentWorktree } from './worktree.js';
@@ -28,6 +28,8 @@ export interface LiveAgentTask extends AgentTaskRecord {
28
28
  abort: AbortController;
29
29
  completion: Promise<void>;
30
30
  events: EventEmitter;
31
+ /** Messages accepted before the private history is ready are flushed in order. */
32
+ inbox: string[];
31
33
  }
32
34
  export interface AgentTaskState {
33
35
  tasks: Map<string, LiveAgentTask>;
@@ -100,6 +102,47 @@ export function getLiveAgentTask(
100
102
  ): LiveAgentTask | undefined {
101
103
  return state?.tasks.get(id);
102
104
  }
105
+
106
+ /** List the durable tasks owned by this Session, with process-local state winning. */
107
+ export async function listAgentRecords(
108
+ ctx: ToolCallContext,
109
+ ): Promise<AgentTaskRecord[]> {
110
+ const root = join(sessionRuntimeDir(ctx), 'agents');
111
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
112
+ const records = new Map<string, AgentTaskRecord>();
113
+ for (const entry of entries) {
114
+ if (!entry.isDirectory() || !/^agent_[0-9a-f-]{36}$/i.test(entry.name))
115
+ continue;
116
+ const record = await loadAgentRecord(ctx, entry.name);
117
+ if (record) records.set(record.id, record);
118
+ }
119
+ for (const live of ctx.sessionState?.agentTasks.tasks.values() ?? [])
120
+ records.set(live.id, live);
121
+ return [...records.values()].sort((a, b) => b.updatedAt - a.updatedAt);
122
+ }
123
+
124
+ export function agentMessage(message: string): Message {
125
+ return {
126
+ role: 'user',
127
+ content: `[主 Agent 后续消息]\n${message}`,
128
+ timestamp: Date.now(),
129
+ };
130
+ }
131
+
132
+ /** Deliver at the next model-message boundary without aborting the active turn. */
133
+ export function enqueueAgentMessage(task: LiveAgentTask, message: string): void {
134
+ if (task.history) task.history.push(agentMessage(message));
135
+ else task.inbox.push(message);
136
+ task.updatedAt = Date.now();
137
+ task.events.emit('change');
138
+ }
139
+
140
+ /** Attach the live private history and flush messages accepted during startup. */
141
+ export function attachAgentHistory(task: LiveAgentTask, history: Message[]): void {
142
+ task.history = history;
143
+ for (const message of task.inbox.splice(0)) history.push(agentMessage(message));
144
+ task.events.emit('change');
145
+ }
103
146
  export async function stopAllAgentTasks(state: AgentTaskState): Promise<void> {
104
147
  const running = [...state.tasks.values()].filter(
105
148
  (t) => t.status === 'running',
@@ -13,6 +13,7 @@
13
13
  * (两次规则:真实需要出现两次再议)。
14
14
  * ============================================================
15
15
  */
16
+ import { DEFAULT_SUBAGENTS_CONFIG } from '../../config/configDefaults.js';
16
17
  /**
17
18
  * 任何 agent_type 都排除的工具:
18
19
  * - Agent:防递归 fork(子 agent 再 fork 子 agent,深度失控)。
@@ -20,7 +21,13 @@
20
21
  */
21
22
  export const SUBAGENT_EXCLUDED_TOOLS = [
22
23
  'Agent',
24
+ 'AgentMessage',
25
+ 'AgentList',
26
+ 'AgentWait',
27
+ 'AgentInterrupt',
28
+ 'AgentFollowup',
23
29
  'Advisor',
30
+ 'AdvisorDecision',
24
31
  // 子任务只向主 Agent 汇报;正式用户交付由主 Agent 统一收口,避免重复结果卡。
25
32
  'PresentResult',
26
33
  'RememberMemory',
@@ -41,6 +48,8 @@ export const EXPLORE_ALLOWED_TOOLS = [
41
48
  'WebSearch',
42
49
  'WebFetch',
43
50
  'WebBrowser',
51
+ 'BrowserBatch',
52
+ 'BrowserCDP',
44
53
  'RecallMemory',
45
54
  'ListMemories',
46
55
  'ReviewMemories',
@@ -53,16 +62,19 @@ const EXPLORE_APPENDIX = `# 本次子任务类型:只读调研(explore)
53
62
  严格使用已提供的只读工具。报告给出结论、关键证据和没查到的缺口。`;
54
63
  const GENERAL_APPENDIX = `# 本次子任务类型:读写执行(general)
55
64
  只做任务书范围内的修改;报告列出改动文件和验证结果。`;
65
+ // 轮数上限的**唯一真值**在 configDefaults.ts。这里只是「没有 subagentConfig 时」的
66
+ // 兜底取值,必须与那份一致 —— 曾经两边各写一份字面量(都是 200/100),
67
+ // 改一处漏一处就会出现「有配置时 200、没配置时 50」这种只在缺省路径显形的分裂。
56
68
  const EXPLORE_DEF = {
57
69
  type: 'explore',
58
70
  resolveAllowedTools: (all) => all.filter((n) => EXPLORE_ALLOWED_TOOLS.includes(n)),
59
- maxTurns: 50,
71
+ maxTurns: DEFAULT_SUBAGENTS_CONFIG.exploreMaxTurns,
60
72
  promptAppendix: EXPLORE_APPENDIX,
61
73
  };
62
74
  const GENERAL_DEF = {
63
75
  type: 'general',
64
76
  resolveAllowedTools: (all) => all.filter((n) => !SUBAGENT_EXCLUDED_TOOLS.includes(n)),
65
- maxTurns: 100,
77
+ maxTurns: DEFAULT_SUBAGENTS_CONFIG.generalMaxTurns,
66
78
  promptAppendix: GENERAL_APPENDIX,
67
79
  };
68
80
  /** 未知/缺省一律回落 explore(最安全的默认:只读)。 */
@@ -14,6 +14,8 @@
14
14
  * ============================================================
15
15
  */
16
16
 
17
+ import { DEFAULT_SUBAGENTS_CONFIG } from '../../config/configDefaults.js';
18
+
17
19
  export type AgentTypeName = 'explore' | 'general';
18
20
 
19
21
  export interface AgentTypeDef {
@@ -37,7 +39,13 @@ export interface AgentTypeDef {
37
39
  */
38
40
  export const SUBAGENT_EXCLUDED_TOOLS: readonly string[] = [
39
41
  'Agent',
42
+ 'AgentMessage',
43
+ 'AgentList',
44
+ 'AgentWait',
45
+ 'AgentInterrupt',
46
+ 'AgentFollowup',
40
47
  'Advisor',
48
+ 'AdvisorDecision',
41
49
  // 子任务只向主 Agent 汇报;正式用户交付由主 Agent 统一收口,避免重复结果卡。
42
50
  'PresentResult',
43
51
  'RememberMemory',
@@ -59,6 +67,8 @@ export const EXPLORE_ALLOWED_TOOLS: readonly string[] = [
59
67
  'WebSearch',
60
68
  'WebFetch',
61
69
  'WebBrowser',
70
+ 'BrowserBatch',
71
+ 'BrowserCDP',
62
72
  'RecallMemory',
63
73
  'ListMemories',
64
74
  'ReviewMemories',
@@ -74,17 +84,20 @@ const EXPLORE_APPENDIX = `# 本次子任务类型:只读调研(explore)
74
84
  const GENERAL_APPENDIX = `# 本次子任务类型:读写执行(general)
75
85
  只做任务书范围内的修改;报告列出改动文件和验证结果。`;
76
86
 
87
+ // 轮数上限的**唯一真值**在 configDefaults.ts。这里只是「没有 subagentConfig 时」的
88
+ // 兜底取值,必须与那份一致 —— 曾经两边各写一份字面量(都是 200/100),
89
+ // 改一处漏一处就会出现「有配置时 200、没配置时 50」这种只在缺省路径显形的分裂。
77
90
  const EXPLORE_DEF: AgentTypeDef = {
78
91
  type: 'explore',
79
92
  resolveAllowedTools: (all) => all.filter((n) => EXPLORE_ALLOWED_TOOLS.includes(n)),
80
- maxTurns: 50,
93
+ maxTurns: DEFAULT_SUBAGENTS_CONFIG.exploreMaxTurns,
81
94
  promptAppendix: EXPLORE_APPENDIX,
82
95
  };
83
96
 
84
97
  const GENERAL_DEF: AgentTypeDef = {
85
98
  type: 'general',
86
99
  resolveAllowedTools: (all) => all.filter((n) => !SUBAGENT_EXCLUDED_TOOLS.includes(n)),
87
- maxTurns: 100,
100
+ maxTurns: DEFAULT_SUBAGENTS_CONFIG.generalMaxTurns,
88
101
  promptAppendix: GENERAL_APPENDIX,
89
102
  };
90
103
 
@@ -0,0 +1,362 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { realpath, rm } from 'node:fs/promises';
3
+ import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
4
+ import { z } from 'zod';
5
+ import { getWorkingDir } from '../../bootstrap/workingDir.js';
6
+ import { buildPatchSummary } from '../shared/diffSummary.js';
7
+ import { fileActivityMetadata } from '../shared/fileActivity.js';
8
+ import { emitFileMutation } from '../shared/fileMutationBus.js';
9
+ import { hashFileBytes, recordRead } from '../shared/fileState.js';
10
+ import { applyLineEnding, atomicWriteFile, encodeTextFile, hasBinaryExtension, readTextFile, } from '../shared/fileUtils.js';
11
+ import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
12
+ const schema = z.object({
13
+ patch: z.string().min(1).max(10_000_000),
14
+ });
15
+ function fail(message) {
16
+ throw new Error(message);
17
+ }
18
+ /** Parse the Codex apply_patch envelope without invoking a platform patch binary. */
19
+ export function parseApplyPatch(input) {
20
+ const lines = input.replaceAll('\r\n', '\n').split('\n');
21
+ if (lines[0] !== '*** Begin Patch')
22
+ fail('补丁必须以 *** Begin Patch 开始');
23
+ const operations = [];
24
+ let index = 1;
25
+ while (index < lines.length) {
26
+ const line = lines[index];
27
+ if (line === '*** End Patch') {
28
+ if (lines.slice(index + 1).some((item) => item.trim()))
29
+ fail('*** End Patch 后不能再有内容');
30
+ if (!operations.length)
31
+ fail('补丁中没有文件操作');
32
+ return operations;
33
+ }
34
+ if (line.startsWith('*** Add File: ')) {
35
+ const path = line.slice('*** Add File: '.length);
36
+ index += 1;
37
+ const added = [];
38
+ while (index < lines.length && !lines[index].startsWith('*** ')) {
39
+ const contentLine = lines[index];
40
+ if (!contentLine.startsWith('+'))
41
+ fail(`Add File ${path} 的内容行必须以 + 开头(第 ${index + 1} 行)`);
42
+ added.push(contentLine.slice(1));
43
+ index += 1;
44
+ }
45
+ operations.push({
46
+ kind: 'add',
47
+ path,
48
+ content: added.length ? `${added.join('\n')}\n` : '',
49
+ });
50
+ continue;
51
+ }
52
+ if (line.startsWith('*** Delete File: ')) {
53
+ operations.push({
54
+ kind: 'delete',
55
+ path: line.slice('*** Delete File: '.length),
56
+ });
57
+ index += 1;
58
+ continue;
59
+ }
60
+ if (line.startsWith('*** Update File: ')) {
61
+ const path = line.slice('*** Update File: '.length);
62
+ index += 1;
63
+ let moveTo;
64
+ if (lines[index]?.startsWith('*** Move to: ')) {
65
+ moveTo = lines[index].slice('*** Move to: '.length);
66
+ index += 1;
67
+ }
68
+ const hunks = [];
69
+ while (index < lines.length && !lines[index].startsWith('*** ')) {
70
+ const headerLine = lines[index];
71
+ if (!headerLine.startsWith('@@'))
72
+ fail(`Update File ${path} 缺少 @@ hunk 头(第 ${index + 1} 行)`);
73
+ const match = /^@@(?: -(\d+)(?:,\d+)? \+\d+(?:,\d+)?)? @@\s*(.*)$/.exec(headerLine);
74
+ const header = match
75
+ ? match[2]
76
+ : headerLine.slice(2).replace(/^\s+|\s+$/g, '');
77
+ const oldStart = match?.[1] ? Number(match[1]) : undefined;
78
+ index += 1;
79
+ const hunkLines = [];
80
+ while (index < lines.length &&
81
+ !lines[index].startsWith('@@') &&
82
+ (!lines[index].startsWith('*** ') ||
83
+ lines[index] === '*** End of File')) {
84
+ const hunkLine = lines[index];
85
+ if (hunkLine === '*** End of File') {
86
+ index += 1;
87
+ continue;
88
+ }
89
+ const prefix = hunkLine[0];
90
+ if (prefix !== ' ' && prefix !== '+' && prefix !== '-')
91
+ fail(`hunk 内容行必须以空格、+ 或 - 开头(第 ${index + 1} 行)`);
92
+ hunkLines.push({
93
+ kind: prefix === ' ' ? 'context' : prefix === '+' ? 'add' : 'delete',
94
+ text: hunkLine.slice(1),
95
+ });
96
+ index += 1;
97
+ }
98
+ if (!hunkLines.length)
99
+ fail(`Update File ${path} 包含空 hunk`);
100
+ hunks.push({ header, oldStart, lines: hunkLines });
101
+ }
102
+ if (!hunks.length && !moveTo)
103
+ fail(`Update File ${path} 没有 hunk`);
104
+ operations.push({
105
+ kind: 'update',
106
+ path,
107
+ ...(moveTo ? { moveTo } : {}),
108
+ hunks,
109
+ });
110
+ continue;
111
+ }
112
+ fail(`无法识别补丁指令(第 ${index + 1} 行):${line}`);
113
+ }
114
+ fail('补丁缺少 *** End Patch');
115
+ }
116
+ function within(root, candidate) {
117
+ const rel = relative(root, candidate);
118
+ return (rel === '' ||
119
+ (!isAbsolute(rel) && rel !== '..' && !rel.startsWith(`..${sep}`)));
120
+ }
121
+ async function nearestExistingAncestor(path) {
122
+ let current = path;
123
+ while (!existsSync(current)) {
124
+ const parent = dirname(current);
125
+ if (parent === current)
126
+ break;
127
+ current = parent;
128
+ }
129
+ return realpath(current);
130
+ }
131
+ async function workspacePath(raw, cwd) {
132
+ if (!raw || isAbsolute(raw) || raw.includes('\0'))
133
+ fail(`补丁路径必须是非空的工作区相对路径:${raw}`);
134
+ const absolute = resolve(cwd, raw);
135
+ const rel = relative(resolve(cwd), absolute);
136
+ if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))
137
+ fail(`补丁路径越过工作区边界:${raw}`);
138
+ const physicalRoot = await realpath(resolve(cwd)).catch(() => resolve(cwd));
139
+ const physicalBoundary = existsSync(absolute)
140
+ ? await realpath(absolute)
141
+ : await nearestExistingAncestor(dirname(absolute));
142
+ if (!within(physicalRoot, physicalBoundary))
143
+ fail(`补丁路径通过符号链接越过工作区边界:${raw}`);
144
+ if (hasBinaryExtension(absolute))
145
+ fail(`ApplyPatch 不支持二进制文件:${raw}`);
146
+ return absolute;
147
+ }
148
+ export function applyHunks(original, hunks) {
149
+ const normalized = original.replaceAll('\r\n', '\n');
150
+ const trailingNewline = normalized.endsWith('\n');
151
+ const lines = normalized.split('\n');
152
+ if (trailingNewline)
153
+ lines.pop();
154
+ let cursor = 0;
155
+ for (const hunk of hunks) {
156
+ if (hunk.header) {
157
+ const anchor = lines.findIndex((line, index) => index >= cursor && line.includes(hunk.header));
158
+ if (anchor < 0)
159
+ fail(`找不到 hunk 锚点:${hunk.header}`);
160
+ cursor = anchor;
161
+ }
162
+ const before = hunk.lines
163
+ .filter((line) => line.kind !== 'add')
164
+ .map((line) => line.text);
165
+ const after = hunk.lines
166
+ .filter((line) => line.kind !== 'delete')
167
+ .map((line) => line.text);
168
+ const matchesAt = (start) => before.every((line, offset) => lines[start + offset] === line);
169
+ let at = -1;
170
+ if (!before.length) {
171
+ at =
172
+ hunk.oldStart === undefined
173
+ ? cursor
174
+ : Math.max(cursor, Math.min(lines.length, hunk.oldStart - 1));
175
+ }
176
+ else {
177
+ for (let index = cursor; index <= lines.length - before.length; index += 1) {
178
+ if (matchesAt(index)) {
179
+ at = index;
180
+ break;
181
+ }
182
+ }
183
+ if (at < 0 && cursor > 0) {
184
+ const matches = [];
185
+ for (let index = 0; index <= lines.length - before.length; index += 1)
186
+ if (matchesAt(index))
187
+ matches.push(index);
188
+ if (matches.length === 1)
189
+ at = matches[0];
190
+ }
191
+ }
192
+ if (at < 0)
193
+ fail(`hunk 上下文与当前文件不匹配:${before.join('\n').slice(0, 240)}`);
194
+ lines.splice(at, before.length, ...after);
195
+ cursor = at + after.length;
196
+ }
197
+ return `${lines.join('\n')}${trailingNewline ? '\n' : ''}`;
198
+ }
199
+ async function stagePatch(operations, cwd) {
200
+ const staged = [];
201
+ const touched = new Set();
202
+ const claim = (path) => {
203
+ if (touched.has(path))
204
+ fail(`同一补丁不能重复操作同一路径:${path}`);
205
+ touched.add(path);
206
+ };
207
+ for (const operation of operations) {
208
+ const path = await workspacePath(operation.path, cwd);
209
+ claim(path);
210
+ if (operation.kind === 'add') {
211
+ if (existsSync(path))
212
+ fail(`Add File 目标已存在:${operation.path}`);
213
+ staged.push({
214
+ path,
215
+ label: operation.path,
216
+ beforeText: '',
217
+ after: operation.content,
218
+ encoding: 'utf8',
219
+ activity: 'created',
220
+ });
221
+ continue;
222
+ }
223
+ if (!existsSync(path))
224
+ fail(`${operation.kind === 'delete' ? 'Delete' : 'Update'} File 不存在:${operation.path}`);
225
+ const snapshot = await readTextFile(path);
226
+ if (operation.kind === 'delete') {
227
+ staged.push({
228
+ path,
229
+ label: operation.path,
230
+ before: snapshot.bytes,
231
+ beforeText: snapshot.content,
232
+ encoding: snapshot.encoding,
233
+ activity: 'deleted',
234
+ });
235
+ continue;
236
+ }
237
+ const updated = applyLineEnding(applyHunks(snapshot.content, operation.hunks), snapshot.lineEnding);
238
+ if (operation.moveTo) {
239
+ const target = await workspacePath(operation.moveTo, cwd);
240
+ claim(target);
241
+ if (existsSync(target))
242
+ fail(`Move to 目标已存在:${operation.moveTo}`);
243
+ staged.push({
244
+ path,
245
+ label: operation.path,
246
+ before: snapshot.bytes,
247
+ beforeText: snapshot.content,
248
+ encoding: snapshot.encoding,
249
+ activity: 'deleted',
250
+ });
251
+ staged.push({
252
+ path: target,
253
+ label: operation.moveTo,
254
+ beforeText: '',
255
+ after: updated,
256
+ encoding: snapshot.encoding,
257
+ activity: 'created',
258
+ });
259
+ }
260
+ else {
261
+ staged.push({
262
+ path,
263
+ label: operation.path,
264
+ before: snapshot.bytes,
265
+ beforeText: snapshot.content,
266
+ after: updated,
267
+ encoding: snapshot.encoding,
268
+ activity: 'modified',
269
+ });
270
+ }
271
+ }
272
+ return staged;
273
+ }
274
+ async function commit(staged) {
275
+ const committed = [];
276
+ try {
277
+ for (const file of staged) {
278
+ if (file.after === undefined)
279
+ await rm(file.path);
280
+ else
281
+ await atomicWriteFile(file.path, file.after, file.encoding);
282
+ committed.push(file);
283
+ }
284
+ }
285
+ catch (error) {
286
+ const rollbackErrors = [];
287
+ for (const file of committed.reverse()) {
288
+ try {
289
+ if (file.before)
290
+ await atomicWriteFile(file.path, file.before);
291
+ else
292
+ await rm(file.path, { force: true });
293
+ }
294
+ catch (rollbackError) {
295
+ rollbackErrors.push(`${file.label}: ${rollbackError.message}`);
296
+ }
297
+ }
298
+ const suffix = rollbackErrors.length
299
+ ? `;回滚也有失败:${rollbackErrors.join(';')}`
300
+ : ';已回滚本次已落盘文件';
301
+ throw new Error(`${error.message}${suffix}`);
302
+ }
303
+ }
304
+ async function call(input, context) {
305
+ const cwd = context?.cwd ?? getWorkingDir();
306
+ let operations;
307
+ let staged;
308
+ try {
309
+ operations = parseApplyPatch(input.patch);
310
+ staged = await stagePatch(operations, cwd);
311
+ await commit(staged);
312
+ }
313
+ catch (error) {
314
+ return { ok: false, error: `ApplyPatch 失败:${error.message}` };
315
+ }
316
+ const files = [];
317
+ const summaries = [];
318
+ for (const file of staged) {
319
+ const afterText = file.after ?? '';
320
+ const patch = buildPatchSummary(file.beforeText, afterText, file.label);
321
+ const metadata = await fileActivityMetadata(file.path, file.activity, 'not_run', 'support', cwd, patch);
322
+ if (metadata)
323
+ files.push(...metadata.files);
324
+ if (file.after === undefined)
325
+ context?.sessionState?.fileReads.entries.delete(file.path);
326
+ else
327
+ recordRead(file.path, {
328
+ contentHash: hashFileBytes(encodeTextFile(file.after, file.encoding)),
329
+ }, context?.sessionState?.fileReads);
330
+ emitFileMutation(file.path);
331
+ summaries.push(`${file.activity}: ${file.label} (+${patch.additions} -${patch.deletions})`);
332
+ }
333
+ return {
334
+ ok: true,
335
+ content: `已应用补丁:\n${summaries.map((line) => `- ${line}`).join('\n')}`,
336
+ ...(files.length
337
+ ? { metadata: { kind: 'file_activity', files } }
338
+ : {}),
339
+ };
340
+ }
341
+ export const applyPatchTool = {
342
+ name: 'ApplyPatch',
343
+ description: 'Applies one Codex-style *** Begin Patch / *** End Patch transaction across text files. ' +
344
+ '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.',
345
+ inputSchema: schema,
346
+ parameters: {
347
+ type: 'object',
348
+ properties: {
349
+ patch: {
350
+ type: 'string',
351
+ description: 'Complete Codex-style patch envelope',
352
+ },
353
+ },
354
+ required: ['patch'],
355
+ },
356
+ isReadOnly: false,
357
+ isConcurrencySafe: false,
358
+ maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
359
+ interruptBehavior: () => 'block',
360
+ call: (input) => call(input),
361
+ callWithContext: (input, _signal, context) => call(input, context),
362
+ };