@cjhyy/code-shell-core 0.5.0-rc.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 (484) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/dist/agent/coordinator.d.ts +49 -0
  4. package/dist/agent/coordinator.js +77 -0
  5. package/dist/arena/arena.d.ts +43 -0
  6. package/dist/arena/arena.js +334 -0
  7. package/dist/arena/context/context-tools.d.ts +16 -0
  8. package/dist/arena/context/context-tools.js +231 -0
  9. package/dist/arena/detect-mode.d.ts +20 -0
  10. package/dist/arena/detect-mode.js +78 -0
  11. package/dist/arena/digest-builder.d.ts +25 -0
  12. package/dist/arena/digest-builder.js +120 -0
  13. package/dist/arena/index.d.ts +29 -0
  14. package/dist/arena/index.js +29 -0
  15. package/dist/arena/iterate/convergence.d.ts +25 -0
  16. package/dist/arena/iterate/convergence.js +103 -0
  17. package/dist/arena/iterate/formats/index.d.ts +22 -0
  18. package/dist/arena/iterate/formats/index.js +283 -0
  19. package/dist/arena/iterate/index.d.ts +11 -0
  20. package/dist/arena/iterate/index.js +9 -0
  21. package/dist/arena/iterate/iterative-arena.d.ts +23 -0
  22. package/dist/arena/iterate/iterative-arena.js +237 -0
  23. package/dist/arena/iterate/parse.d.ts +42 -0
  24. package/dist/arena/iterate/parse.js +123 -0
  25. package/dist/arena/iterate/phases/argue.d.ts +22 -0
  26. package/dist/arena/iterate/phases/argue.js +159 -0
  27. package/dist/arena/iterate/phases/revise.d.ts +16 -0
  28. package/dist/arena/iterate/phases/revise.js +62 -0
  29. package/dist/arena/iterate/phases/tournament.d.ts +34 -0
  30. package/dist/arena/iterate/phases/tournament.js +113 -0
  31. package/dist/arena/iterate/tools/web-tools.d.ts +13 -0
  32. package/dist/arena/iterate/tools/web-tools.js +54 -0
  33. package/dist/arena/iterate/types.d.ts +152 -0
  34. package/dist/arena/iterate/types.js +8 -0
  35. package/dist/arena/ledger.d.ts +47 -0
  36. package/dist/arena/ledger.js +151 -0
  37. package/dist/arena/lenses/architecture.d.ts +5 -0
  38. package/dist/arena/lenses/architecture.js +22 -0
  39. package/dist/arena/lenses/engineering.d.ts +5 -0
  40. package/dist/arena/lenses/engineering.js +22 -0
  41. package/dist/arena/lenses/general.d.ts +5 -0
  42. package/dist/arena/lenses/general.js +20 -0
  43. package/dist/arena/lenses/index.d.ts +16 -0
  44. package/dist/arena/lenses/index.js +47 -0
  45. package/dist/arena/lenses/product.d.ts +5 -0
  46. package/dist/arena/lenses/product.js +22 -0
  47. package/dist/arena/model-presets.d.ts +23 -0
  48. package/dist/arena/model-presets.js +44 -0
  49. package/dist/arena/phases/adjudication.d.ts +24 -0
  50. package/dist/arena/phases/adjudication.js +144 -0
  51. package/dist/arena/phases/build-consensus.d.ts +29 -0
  52. package/dist/arena/phases/build-consensus.js +86 -0
  53. package/dist/arena/phases/claim-registry.d.ts +26 -0
  54. package/dist/arena/phases/claim-registry.js +60 -0
  55. package/dist/arena/phases/cross-review.d.ts +45 -0
  56. package/dist/arena/phases/cross-review.js +224 -0
  57. package/dist/arena/phases/debate-rounds.d.ts +27 -0
  58. package/dist/arena/phases/debate-rounds.js +162 -0
  59. package/dist/arena/phases/participant-research.d.ts +38 -0
  60. package/dist/arena/phases/participant-research.js +317 -0
  61. package/dist/arena/phases/planning-detail-expansion.d.ts +38 -0
  62. package/dist/arena/phases/planning-detail-expansion.js +121 -0
  63. package/dist/arena/planner.d.ts +27 -0
  64. package/dist/arena/planner.js +312 -0
  65. package/dist/arena/providers/docs.d.ts +6 -0
  66. package/dist/arena/providers/docs.js +108 -0
  67. package/dist/arena/providers/git.d.ts +8 -0
  68. package/dist/arena/providers/git.js +174 -0
  69. package/dist/arena/providers/index.d.ts +32 -0
  70. package/dist/arena/providers/index.js +132 -0
  71. package/dist/arena/providers/none.d.ts +7 -0
  72. package/dist/arena/providers/none.js +11 -0
  73. package/dist/arena/providers/repo.d.ts +6 -0
  74. package/dist/arena/providers/repo.js +255 -0
  75. package/dist/arena/render/session.d.ts +17 -0
  76. package/dist/arena/render/session.js +190 -0
  77. package/dist/arena/render/terminal.d.ts +34 -0
  78. package/dist/arena/render/terminal.js +286 -0
  79. package/dist/arena/strategies/discussion.d.ts +25 -0
  80. package/dist/arena/strategies/discussion.js +143 -0
  81. package/dist/arena/strategies/index.d.ts +15 -0
  82. package/dist/arena/strategies/index.js +28 -0
  83. package/dist/arena/strategies/language-wrapper.d.ts +17 -0
  84. package/dist/arena/strategies/language-wrapper.js +102 -0
  85. package/dist/arena/strategies/lens-wrapper.d.ts +16 -0
  86. package/dist/arena/strategies/lens-wrapper.js +236 -0
  87. package/dist/arena/strategies/planning.d.ts +30 -0
  88. package/dist/arena/strategies/planning.js +225 -0
  89. package/dist/arena/strategies/review.d.ts +26 -0
  90. package/dist/arena/strategies/review.js +168 -0
  91. package/dist/arena/strategies/utils.d.ts +39 -0
  92. package/dist/arena/strategies/utils.js +647 -0
  93. package/dist/arena/tools/selector.d.ts +17 -0
  94. package/dist/arena/tools/selector.js +61 -0
  95. package/dist/arena/transitions.d.ts +48 -0
  96. package/dist/arena/transitions.js +92 -0
  97. package/dist/arena/types.d.ts +508 -0
  98. package/dist/arena/types.js +27 -0
  99. package/dist/cli/agent-server-stdio.d.ts +32 -0
  100. package/dist/cli/agent-server-stdio.js +116 -0
  101. package/dist/colorizer.d.ts +23 -0
  102. package/dist/colorizer.js +12 -0
  103. package/dist/context/compaction.d.ts +116 -0
  104. package/dist/context/compaction.js +534 -0
  105. package/dist/context/manager.d.ts +145 -0
  106. package/dist/context/manager.js +423 -0
  107. package/dist/context/token-counter.d.ts +27 -0
  108. package/dist/context/token-counter.js +91 -0
  109. package/dist/context/tool-result-storage.d.ts +96 -0
  110. package/dist/context/tool-result-storage.js +296 -0
  111. package/dist/cost-tracker.d.ts +64 -0
  112. package/dist/cost-tracker.js +314 -0
  113. package/dist/cron/scheduler.d.ts +34 -0
  114. package/dist/cron/scheduler.js +115 -0
  115. package/dist/data/deepseek-models.json +46 -0
  116. package/dist/data/gemini-models.json +67 -0
  117. package/dist/data/openai-models.json +175 -0
  118. package/dist/data/openrouter-models.d.ts +35 -0
  119. package/dist/data/openrouter-models.js +36 -0
  120. package/dist/data/openrouter-models.json +4626 -0
  121. package/dist/data/openrouter-sync.d.ts +16 -0
  122. package/dist/data/openrouter-sync.js +53 -0
  123. package/dist/data/static-catalogs.d.ts +25 -0
  124. package/dist/data/static-catalogs.js +26 -0
  125. package/dist/data/zai-models.json +56 -0
  126. package/dist/engine/cost-store.d.ts +22 -0
  127. package/dist/engine/cost-store.js +15 -0
  128. package/dist/engine/engine.d.ts +295 -0
  129. package/dist/engine/engine.js +1467 -0
  130. package/dist/engine/model-facade.d.ts +24 -0
  131. package/dist/engine/model-facade.js +194 -0
  132. package/dist/engine/parse-task.d.ts +59 -0
  133. package/dist/engine/parse-task.js +135 -0
  134. package/dist/engine/patch-orphaned-tools.d.ts +52 -0
  135. package/dist/engine/patch-orphaned-tools.js +95 -0
  136. package/dist/engine/query.d.ts +50 -0
  137. package/dist/engine/query.js +107 -0
  138. package/dist/engine/runtime.d.ts +50 -0
  139. package/dist/engine/runtime.js +59 -0
  140. package/dist/engine/streaming-tool-queue.d.ts +34 -0
  141. package/dist/engine/streaming-tool-queue.js +61 -0
  142. package/dist/engine/token-budget.d.ts +22 -0
  143. package/dist/engine/token-budget.js +40 -0
  144. package/dist/engine/tool-summary.d.ts +13 -0
  145. package/dist/engine/tool-summary.js +35 -0
  146. package/dist/engine/turn-loop.d.ts +122 -0
  147. package/dist/engine/turn-loop.js +602 -0
  148. package/dist/engine/turn-state.d.ts +20 -0
  149. package/dist/engine/turn-state.js +17 -0
  150. package/dist/exceptions.d.ts +61 -0
  151. package/dist/exceptions.js +116 -0
  152. package/dist/git/utils.d.ts +35 -0
  153. package/dist/git/utils.js +98 -0
  154. package/dist/git/worktree.d.ts +36 -0
  155. package/dist/git/worktree.js +139 -0
  156. package/dist/hooks/events.d.ts +114 -0
  157. package/dist/hooks/events.js +4 -0
  158. package/dist/hooks/inject.d.ts +19 -0
  159. package/dist/hooks/inject.js +29 -0
  160. package/dist/hooks/registry.d.ts +15 -0
  161. package/dist/hooks/registry.js +84 -0
  162. package/dist/hooks/shell-runner.d.ts +45 -0
  163. package/dist/hooks/shell-runner.js +173 -0
  164. package/dist/index.d.ts +117 -0
  165. package/dist/index.js +145 -0
  166. package/dist/llm/api-key-sanitize.d.ts +22 -0
  167. package/dist/llm/api-key-sanitize.js +81 -0
  168. package/dist/llm/capabilities/index.d.ts +20 -0
  169. package/dist/llm/capabilities/index.js +39 -0
  170. package/dist/llm/capabilities/rules.d.ts +26 -0
  171. package/dist/llm/capabilities/rules.js +215 -0
  172. package/dist/llm/capabilities/types.d.ts +114 -0
  173. package/dist/llm/capabilities/types.js +24 -0
  174. package/dist/llm/client-base.d.ts +29 -0
  175. package/dist/llm/client-base.js +137 -0
  176. package/dist/llm/client-factory.d.ts +10 -0
  177. package/dist/llm/client-factory.js +29 -0
  178. package/dist/llm/model-cache.d.ts +21 -0
  179. package/dist/llm/model-cache.js +46 -0
  180. package/dist/llm/model-fetcher.d.ts +29 -0
  181. package/dist/llm/model-fetcher.js +282 -0
  182. package/dist/llm/model-pool.d.ts +95 -0
  183. package/dist/llm/model-pool.js +246 -0
  184. package/dist/llm/provider-catalog.d.ts +32 -0
  185. package/dist/llm/provider-catalog.js +50 -0
  186. package/dist/llm/provider-kinds.d.ts +21 -0
  187. package/dist/llm/provider-kinds.js +132 -0
  188. package/dist/llm/providers/anthropic.d.ts +19 -0
  189. package/dist/llm/providers/anthropic.js +267 -0
  190. package/dist/llm/providers/openai.d.ts +64 -0
  191. package/dist/llm/providers/openai.js +606 -0
  192. package/dist/llm/retry.d.ts +12 -0
  193. package/dist/llm/retry.js +17 -0
  194. package/dist/llm/stream-watchdog.d.ts +42 -0
  195. package/dist/llm/stream-watchdog.js +70 -0
  196. package/dist/llm/token-counter.d.ts +17 -0
  197. package/dist/llm/token-counter.js +36 -0
  198. package/dist/llm/types.d.ts +37 -0
  199. package/dist/llm/types.js +4 -0
  200. package/dist/logging/logger.d.ts +109 -0
  201. package/dist/logging/logger.js +390 -0
  202. package/dist/logging/sanitize-messages.d.ts +42 -0
  203. package/dist/logging/sanitize-messages.js +150 -0
  204. package/dist/logging/session-recorder.d.ts +90 -0
  205. package/dist/logging/session-recorder.js +304 -0
  206. package/dist/lsp/client.d.ts +41 -0
  207. package/dist/lsp/client.js +166 -0
  208. package/dist/lsp/manager.d.ts +40 -0
  209. package/dist/lsp/manager.js +124 -0
  210. package/dist/lsp/servers.d.ts +16 -0
  211. package/dist/lsp/servers.js +60 -0
  212. package/dist/migrate-models.d.ts +45 -0
  213. package/dist/migrate-models.js +179 -0
  214. package/dist/onboarding.d.ts +189 -0
  215. package/dist/onboarding.js +625 -0
  216. package/dist/plugins/gitOps.d.ts +32 -0
  217. package/dist/plugins/gitOps.js +62 -0
  218. package/dist/plugins/installedPlugins.d.ts +15 -0
  219. package/dist/plugins/installedPlugins.js +56 -0
  220. package/dist/plugins/knownMarketplaces.d.ts +10 -0
  221. package/dist/plugins/knownMarketplaces.js +46 -0
  222. package/dist/plugins/loadPluginHooks.d.ts +52 -0
  223. package/dist/plugins/loadPluginHooks.js +162 -0
  224. package/dist/plugins/marketplaceManager.d.ts +49 -0
  225. package/dist/plugins/marketplaceManager.js +142 -0
  226. package/dist/plugins/parseMarketplaceInput.d.ts +16 -0
  227. package/dist/plugins/parseMarketplaceInput.js +73 -0
  228. package/dist/plugins/pluginCommandHook.d.ts +54 -0
  229. package/dist/plugins/pluginCommandHook.js +180 -0
  230. package/dist/plugins/pluginCommandsLoader.d.ts +25 -0
  231. package/dist/plugins/pluginCommandsLoader.js +114 -0
  232. package/dist/plugins/pluginInstaller.d.ts +36 -0
  233. package/dist/plugins/pluginInstaller.js +228 -0
  234. package/dist/plugins/schemas.d.ts +9 -0
  235. package/dist/plugins/schemas.js +136 -0
  236. package/dist/plugins/types.d.ts +75 -0
  237. package/dist/plugins/types.js +7 -0
  238. package/dist/plugins/varRewrite.d.ts +42 -0
  239. package/dist/plugins/varRewrite.js +129 -0
  240. package/dist/preset/index.d.ts +60 -0
  241. package/dist/preset/index.js +159 -0
  242. package/dist/product/define.d.ts +60 -0
  243. package/dist/product/define.js +123 -0
  244. package/dist/product/index.d.ts +5 -0
  245. package/dist/product/index.js +4 -0
  246. package/dist/product/types.d.ts +111 -0
  247. package/dist/product/types.js +21 -0
  248. package/dist/prompt/composer.d.ts +49 -0
  249. package/dist/prompt/composer.js +168 -0
  250. package/dist/prompt/instruction-scanner.d.ts +54 -0
  251. package/dist/prompt/instruction-scanner.js +187 -0
  252. package/dist/prompt/section-cache.d.ts +15 -0
  253. package/dist/prompt/section-cache.js +31 -0
  254. package/dist/prompt/section-loader.d.ts +26 -0
  255. package/dist/prompt/section-loader.js +53 -0
  256. package/dist/prompt/sections/base.md +35 -0
  257. package/dist/prompt/sections/coding.md +31 -0
  258. package/dist/prompt/sections/orchestration.md +16 -0
  259. package/dist/prompt/sections/tone.md +9 -0
  260. package/dist/protocol/chat-session-manager.d.ts +33 -0
  261. package/dist/protocol/chat-session-manager.js +65 -0
  262. package/dist/protocol/chat-session.d.ts +49 -0
  263. package/dist/protocol/chat-session.js +86 -0
  264. package/dist/protocol/client.d.ts +104 -0
  265. package/dist/protocol/client.js +260 -0
  266. package/dist/protocol/factories.d.ts +93 -0
  267. package/dist/protocol/factories.js +64 -0
  268. package/dist/protocol/helpers.d.ts +42 -0
  269. package/dist/protocol/helpers.js +55 -0
  270. package/dist/protocol/index.d.ts +4 -0
  271. package/dist/protocol/index.js +4 -0
  272. package/dist/protocol/server.d.ts +80 -0
  273. package/dist/protocol/server.js +855 -0
  274. package/dist/protocol/transport.d.ts +37 -0
  275. package/dist/protocol/transport.js +85 -0
  276. package/dist/protocol/types.d.ts +221 -0
  277. package/dist/protocol/types.js +61 -0
  278. package/dist/remote/bridge.d.ts +37 -0
  279. package/dist/remote/bridge.js +103 -0
  280. package/dist/run/ArtifactTracker.d.ts +38 -0
  281. package/dist/run/ArtifactTracker.js +132 -0
  282. package/dist/run/CheckpointWriter.d.ts +53 -0
  283. package/dist/run/CheckpointWriter.js +135 -0
  284. package/dist/run/EngineRunner.d.ts +72 -0
  285. package/dist/run/EngineRunner.js +119 -0
  286. package/dist/run/Evaluator.d.ts +56 -0
  287. package/dist/run/Evaluator.js +62 -0
  288. package/dist/run/FileRunStore.d.ts +39 -0
  289. package/dist/run/FileRunStore.js +176 -0
  290. package/dist/run/Heartbeat.d.ts +54 -0
  291. package/dist/run/Heartbeat.js +123 -0
  292. package/dist/run/RunApprovalBackend.d.ts +53 -0
  293. package/dist/run/RunApprovalBackend.js +85 -0
  294. package/dist/run/RunLock.d.ts +40 -0
  295. package/dist/run/RunLock.js +98 -0
  296. package/dist/run/RunManager.d.ts +82 -0
  297. package/dist/run/RunManager.js +587 -0
  298. package/dist/run/RunQueue.d.ts +27 -0
  299. package/dist/run/RunQueue.js +73 -0
  300. package/dist/run/RunStore.d.ts +25 -0
  301. package/dist/run/RunStore.js +9 -0
  302. package/dist/run/factory.d.ts +63 -0
  303. package/dist/run/factory.js +51 -0
  304. package/dist/run/index.d.ts +17 -0
  305. package/dist/run/index.js +23 -0
  306. package/dist/run/types.d.ts +136 -0
  307. package/dist/run/types.js +28 -0
  308. package/dist/runtime/safe-spawn.d.ts +118 -0
  309. package/dist/runtime/safe-spawn.js +268 -0
  310. package/dist/services/analytics.d.ts +29 -0
  311. package/dist/services/analytics.js +84 -0
  312. package/dist/services/auto-dream.d.ts +49 -0
  313. package/dist/services/auto-dream.js +124 -0
  314. package/dist/services/diagnostics.d.ts +41 -0
  315. package/dist/services/diagnostics.js +99 -0
  316. package/dist/services/extract-memories.d.ts +31 -0
  317. package/dist/services/extract-memories.js +71 -0
  318. package/dist/services/index.d.ts +11 -0
  319. package/dist/services/index.js +17 -0
  320. package/dist/services/memory-orchestrator.d.ts +60 -0
  321. package/dist/services/memory-orchestrator.js +133 -0
  322. package/dist/services/notifier.d.ts +25 -0
  323. package/dist/services/notifier.js +69 -0
  324. package/dist/services/oauth.d.ts +27 -0
  325. package/dist/services/oauth.js +153 -0
  326. package/dist/services/session-memory.d.ts +37 -0
  327. package/dist/services/session-memory.js +81 -0
  328. package/dist/session/file-history.d.ts +41 -0
  329. package/dist/session/file-history.js +115 -0
  330. package/dist/session/memory.d.ts +104 -0
  331. package/dist/session/memory.js +310 -0
  332. package/dist/session/session-manager.d.ts +41 -0
  333. package/dist/session/session-manager.js +261 -0
  334. package/dist/session/transcript.d.ts +39 -0
  335. package/dist/session/transcript.js +186 -0
  336. package/dist/settings/manager.d.ts +36 -0
  337. package/dist/settings/manager.js +187 -0
  338. package/dist/settings/schema.d.ts +1219 -0
  339. package/dist/settings/schema.js +246 -0
  340. package/dist/skills/frontmatter.d.ts +13 -0
  341. package/dist/skills/frontmatter.js +70 -0
  342. package/dist/skills/index.d.ts +7 -0
  343. package/dist/skills/index.js +6 -0
  344. package/dist/skills/scanner.d.ts +31 -0
  345. package/dist/skills/scanner.js +171 -0
  346. package/dist/state.d.ts +160 -0
  347. package/dist/state.js +267 -0
  348. package/dist/tool-system/builtin/agent-notifications.d.ts +84 -0
  349. package/dist/tool-system/builtin/agent-notifications.js +197 -0
  350. package/dist/tool-system/builtin/agent-registry.d.ts +67 -0
  351. package/dist/tool-system/builtin/agent-registry.js +126 -0
  352. package/dist/tool-system/builtin/agent-transcript-translator.d.ts +22 -0
  353. package/dist/tool-system/builtin/agent-transcript-translator.js +160 -0
  354. package/dist/tool-system/builtin/agent.d.ts +16 -0
  355. package/dist/tool-system/builtin/agent.js +364 -0
  356. package/dist/tool-system/builtin/apply-patch/applier.d.ts +26 -0
  357. package/dist/tool-system/builtin/apply-patch/applier.js +250 -0
  358. package/dist/tool-system/builtin/apply-patch/index.d.ts +20 -0
  359. package/dist/tool-system/builtin/apply-patch/index.js +101 -0
  360. package/dist/tool-system/builtin/apply-patch/parser.d.ts +17 -0
  361. package/dist/tool-system/builtin/apply-patch/parser.js +212 -0
  362. package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +18 -0
  363. package/dist/tool-system/builtin/apply-patch/seek-sequence.js +123 -0
  364. package/dist/tool-system/builtin/apply-patch/types.d.ts +49 -0
  365. package/dist/tool-system/builtin/apply-patch/types.js +13 -0
  366. package/dist/tool-system/builtin/arena.d.ts +31 -0
  367. package/dist/tool-system/builtin/arena.js +416 -0
  368. package/dist/tool-system/builtin/ask-user.d.ts +20 -0
  369. package/dist/tool-system/builtin/ask-user.js +99 -0
  370. package/dist/tool-system/builtin/bash.d.ts +21 -0
  371. package/dist/tool-system/builtin/bash.js +149 -0
  372. package/dist/tool-system/builtin/brief.d.ts +6 -0
  373. package/dist/tool-system/builtin/brief.js +41 -0
  374. package/dist/tool-system/builtin/config.d.ts +6 -0
  375. package/dist/tool-system/builtin/config.js +67 -0
  376. package/dist/tool-system/builtin/cron.d.ts +10 -0
  377. package/dist/tool-system/builtin/cron.js +61 -0
  378. package/dist/tool-system/builtin/edit.d.ts +6 -0
  379. package/dist/tool-system/builtin/edit.js +100 -0
  380. package/dist/tool-system/builtin/file-cache.d.ts +11 -0
  381. package/dist/tool-system/builtin/file-cache.js +39 -0
  382. package/dist/tool-system/builtin/glob.d.ts +7 -0
  383. package/dist/tool-system/builtin/glob.js +76 -0
  384. package/dist/tool-system/builtin/grep.d.ts +7 -0
  385. package/dist/tool-system/builtin/grep.js +150 -0
  386. package/dist/tool-system/builtin/index.d.ts +20 -0
  387. package/dist/tool-system/builtin/index.js +449 -0
  388. package/dist/tool-system/builtin/lsp.d.ts +6 -0
  389. package/dist/tool-system/builtin/lsp.js +141 -0
  390. package/dist/tool-system/builtin/mcp-tools.d.ts +10 -0
  391. package/dist/tool-system/builtin/mcp-tools.js +102 -0
  392. package/dist/tool-system/builtin/memory.d.ts +26 -0
  393. package/dist/tool-system/builtin/memory.js +226 -0
  394. package/dist/tool-system/builtin/notebook-edit.d.ts +6 -0
  395. package/dist/tool-system/builtin/notebook-edit.js +124 -0
  396. package/dist/tool-system/builtin/plan.d.ts +15 -0
  397. package/dist/tool-system/builtin/plan.js +55 -0
  398. package/dist/tool-system/builtin/powershell.d.ts +11 -0
  399. package/dist/tool-system/builtin/powershell.js +64 -0
  400. package/dist/tool-system/builtin/read.d.ts +6 -0
  401. package/dist/tool-system/builtin/read.js +70 -0
  402. package/dist/tool-system/builtin/remote-trigger.d.ts +6 -0
  403. package/dist/tool-system/builtin/remote-trigger.js +54 -0
  404. package/dist/tool-system/builtin/repl.d.ts +11 -0
  405. package/dist/tool-system/builtin/repl.js +82 -0
  406. package/dist/tool-system/builtin/send-message.d.ts +6 -0
  407. package/dist/tool-system/builtin/send-message.js +47 -0
  408. package/dist/tool-system/builtin/skill-prompt.d.ts +20 -0
  409. package/dist/tool-system/builtin/skill-prompt.js +52 -0
  410. package/dist/tool-system/builtin/skill.d.ts +9 -0
  411. package/dist/tool-system/builtin/skill.js +55 -0
  412. package/dist/tool-system/builtin/sleep.d.ts +6 -0
  413. package/dist/tool-system/builtin/sleep.js +33 -0
  414. package/dist/tool-system/builtin/task.d.ts +48 -0
  415. package/dist/tool-system/builtin/task.js +139 -0
  416. package/dist/tool-system/builtin/tool-search.d.ts +11 -0
  417. package/dist/tool-system/builtin/tool-search.js +90 -0
  418. package/dist/tool-system/builtin/web-fetch.d.ts +10 -0
  419. package/dist/tool-system/builtin/web-fetch.js +328 -0
  420. package/dist/tool-system/builtin/web-search.d.ts +25 -0
  421. package/dist/tool-system/builtin/web-search.js +174 -0
  422. package/dist/tool-system/builtin/worktree.d.ts +10 -0
  423. package/dist/tool-system/builtin/worktree.js +95 -0
  424. package/dist/tool-system/builtin/write.d.ts +6 -0
  425. package/dist/tool-system/builtin/write.js +36 -0
  426. package/dist/tool-system/context.d.ts +165 -0
  427. package/dist/tool-system/context.js +18 -0
  428. package/dist/tool-system/executor.d.ts +49 -0
  429. package/dist/tool-system/executor.js +495 -0
  430. package/dist/tool-system/investigation-guard.d.ts +46 -0
  431. package/dist/tool-system/investigation-guard.js +155 -0
  432. package/dist/tool-system/mcp-manager.d.ts +67 -0
  433. package/dist/tool-system/mcp-manager.js +249 -0
  434. package/dist/tool-system/permission.d.ts +111 -0
  435. package/dist/tool-system/permission.js +774 -0
  436. package/dist/tool-system/registry.d.ts +32 -0
  437. package/dist/tool-system/registry.js +131 -0
  438. package/dist/tool-system/sandbox/bwrap.d.ts +13 -0
  439. package/dist/tool-system/sandbox/bwrap.js +63 -0
  440. package/dist/tool-system/sandbox/index.d.ts +78 -0
  441. package/dist/tool-system/sandbox/index.js +222 -0
  442. package/dist/tool-system/sandbox/off.d.ts +2 -0
  443. package/dist/tool-system/sandbox/off.js +8 -0
  444. package/dist/tool-system/sandbox/seatbelt.d.ts +18 -0
  445. package/dist/tool-system/sandbox/seatbelt.js +109 -0
  446. package/dist/tool-system/task-guard.d.ts +29 -0
  447. package/dist/tool-system/task-guard.js +70 -0
  448. package/dist/tool-system/validation.d.ts +5 -0
  449. package/dist/tool-system/validation.js +39 -0
  450. package/dist/types.d.ts +376 -0
  451. package/dist/types.js +4 -0
  452. package/dist/updater.d.ts +65 -0
  453. package/dist/updater.js +405 -0
  454. package/dist/utils/debug.d.ts +41 -0
  455. package/dist/utils/debug.js +110 -0
  456. package/dist/utils/earlyInput.d.ts +43 -0
  457. package/dist/utils/earlyInput.js +166 -0
  458. package/dist/utils/env.d.ts +24 -0
  459. package/dist/utils/env.js +104 -0
  460. package/dist/utils/envUtils.d.ts +51 -0
  461. package/dist/utils/envUtils.js +135 -0
  462. package/dist/utils/execFileNoThrow.d.ts +39 -0
  463. package/dist/utils/execFileNoThrow.js +74 -0
  464. package/dist/utils/format.d.ts +44 -0
  465. package/dist/utils/format.js +236 -0
  466. package/dist/utils/intl.d.ts +22 -0
  467. package/dist/utils/intl.js +83 -0
  468. package/dist/utils/lockfile.d.ts +15 -0
  469. package/dist/utils/lockfile.js +30 -0
  470. package/dist/utils/memoize.d.ts +19 -0
  471. package/dist/utils/memoize.js +14 -0
  472. package/dist/utils/semver.d.ts +6 -0
  473. package/dist/utils/semver.js +13 -0
  474. package/dist/utils/sliceAnsi.d.ts +12 -0
  475. package/dist/utils/sliceAnsi.js +62 -0
  476. package/dist/utils/systemTheme.d.ts +40 -0
  477. package/dist/utils/systemTheme.js +108 -0
  478. package/dist/utils/task-sanitizer.d.ts +6 -0
  479. package/dist/utils/task-sanitizer.js +24 -0
  480. package/dist/utils/theme.d.ts +93 -0
  481. package/dist/utils/theme.js +544 -0
  482. package/dist/utils/toolDisplay.d.ts +31 -0
  483. package/dist/utils/toolDisplay.js +188 -0
  484. package/package.json +72 -0
@@ -0,0 +1,364 @@
1
+ /**
2
+ * Built-in Agent tool — spawn a sub-agent to handle a task.
3
+ *
4
+ * Creates a new Engine instance with its own transcript,
5
+ * runs the task to completion, and returns the result text.
6
+ * Supports AbortSignal for cascading cancellation.
7
+ * Supports onStream for real-time output passthrough.
8
+ */
9
+ import { asyncAgentRegistry } from "./agent-registry.js";
10
+ import { createTranscriptTranslator } from "./agent-transcript-translator.js";
11
+ import { notificationQueue } from "./agent-notifications.js";
12
+ import { nanoid } from "nanoid";
13
+ import { logger } from "../../logging/logger.js";
14
+ /**
15
+ * Invoke a stream callback that came from outside the engine's own
16
+ * TurnLoop wrap (e.g. `subAgentSpawner.parentStream`, which is the
17
+ * parent Engine.run's caller-supplied onStream forwarded straight
18
+ * through). A throw here would otherwise bubble out of the Agent tool
19
+ * and abort the parent turn, even though the underlying emit is a UI
20
+ * marker the parent doesn't need to succeed.
21
+ */
22
+ function safeEmit(sink, event) {
23
+ if (!sink)
24
+ return;
25
+ try {
26
+ sink(event);
27
+ }
28
+ catch (err) {
29
+ logger.warn("agent.stream_handler_threw", {
30
+ eventType: event.type,
31
+ error: err.message,
32
+ });
33
+ }
34
+ }
35
+ export const agentToolDef = {
36
+ name: "Agent",
37
+ description: "Launch a sub-agent to handle a complex task autonomously. " +
38
+ "The sub-agent has access to the same tools and runs independently. " +
39
+ "Use this for tasks that can be delegated, parallelized, or require deep exploration. " +
40
+ "Provide a clear, complete description of what the agent should do.\n\n" +
41
+ "When you launch multiple agents for independent work, send them in a single " +
42
+ "message with multiple tool uses so they run concurrently.\n\n" +
43
+ "You can optionally run agents in the background using the run_in_background " +
44
+ "parameter. When an agent runs in the background, you will be automatically " +
45
+ "notified when it completes — do NOT sleep, poll, or proactively check on its " +
46
+ "progress. Continue with other work or respond to the user instead.",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ name: {
51
+ type: "string",
52
+ description: "Short label for the agent kind (e.g. 'Explore', 'Plan', 'Research'). " +
53
+ "Shown in the agent dock to identify what kind of work this sub-agent is doing. " +
54
+ "Keep it 1-2 words. Defaults to 'Agent' if omitted.",
55
+ },
56
+ description: {
57
+ type: "string",
58
+ description: "A short (3-5 word) description of the task",
59
+ },
60
+ prompt: {
61
+ type: "string",
62
+ description: "The detailed task for the agent to perform",
63
+ },
64
+ max_turns: {
65
+ type: "number",
66
+ description: "Maximum turns for the sub-agent (default: 15)",
67
+ },
68
+ run_in_background: {
69
+ type: "boolean",
70
+ description: "Set to true to run this agent in the background. " +
71
+ "You will be notified automatically when it completes — do NOT sleep, poll, " +
72
+ "or proactively check on its progress. Use AgentCancel(agent_id) to stop it. " +
73
+ "The agent runs in this process; restarting loses its state. " +
74
+ "Default: false (synchronous wait).",
75
+ },
76
+ },
77
+ required: ["description", "prompt"],
78
+ },
79
+ };
80
+ /**
81
+ * Build and run a sub-agent. Returns the produced text or throws.
82
+ * Used by both the synchronous and background paths.
83
+ */
84
+ async function runSubAgent(spawner, opts,
85
+ /**
86
+ * Optional sink for the user-visible `agent_start` / `agent_end` markers.
87
+ * Background path passes the parent's real onStream here; sync calls leave
88
+ * it undefined and we fall back to `spawner.parentStream`.
89
+ */
90
+ uiStream,
91
+ /**
92
+ * Optional override for the spawned child Engine's per-event stream.
93
+ * Background path passes a transcriptSink here so per-event detail is
94
+ * captured into the agent's transcript rather than the main feed. Sync
95
+ * calls leave undefined; engine.ts falls back to `spawner.parentStream`
96
+ * (the parent UI), preserving the inline rendering of synchronous
97
+ * sub-agents.
98
+ */
99
+ streamOverride) {
100
+ const { agentId, name, description } = opts;
101
+ const startEndSink = uiStream ?? spawner.parentStream;
102
+ safeEmit(startEndSink, { type: "agent_start", agentId, name, description });
103
+ // `resetPlanMode` / `restorePlanMode` operated on a module-level singleton
104
+ // that no longer exists. The child Engine is a fresh instance; plan-mode
105
+ // isolation between parent and child is enforced via separate Engine
106
+ // instances (finalized in T6).
107
+ const text = await spawner.spawn({ ...opts, streamOverride });
108
+ const finalText = text || `Agent completed but produced no text output.`;
109
+ safeEmit(startEndSink, { type: "agent_end", agentId, name, description, text: finalText });
110
+ return finalText;
111
+ }
112
+ export async function agentTool(args, ctx) {
113
+ const prompt = args.prompt;
114
+ const description = args.description || "sub-agent";
115
+ const rawName = args.name?.trim();
116
+ const name = rawName && rawName.length > 0 ? rawName : undefined;
117
+ if (!prompt)
118
+ return "Error: prompt is required";
119
+ if (!ctx?.subAgentSpawner) {
120
+ return "Error: Agent tool is not configured (no subAgentSpawner in ctx).";
121
+ }
122
+ // Belt-and-suspenders: the spawner already strips Agent / AgentStatus /
123
+ // AgentCancel from a child Engine's tool pool (see engine.ts spawn()), so
124
+ // a sub-agent's LLM should never see this tool. If it does call it anyway
125
+ // (registry regression, custom-tools injection, future refactor), refuse
126
+ // here — no grandchildren. Matches Claude Code's flat-hierarchy rule.
127
+ if (ctx.isSubAgent === true) {
128
+ return "Error: nested agents are not supported. Sub-agents cannot spawn their own sub-agents. Complete the task directly using your available tools.";
129
+ }
130
+ const spawner = ctx.subAgentSpawner;
131
+ const parentSignal = args.__signal;
132
+ if (parentSignal?.aborted) {
133
+ return "Agent aborted before starting.";
134
+ }
135
+ const maxTurns = args.max_turns || 15;
136
+ const runInBackground = args.run_in_background === true;
137
+ const agentId = nanoid(8);
138
+ const parentStream = spawner.parentStream;
139
+ // ─── Background path ───────────────────────────────────────────
140
+ // Register the agent, kick off execution detached from the current turn,
141
+ // return immediately with the agent_id. Parent abort does NOT cascade
142
+ // (background agents survive the spawning turn). Cancellation goes
143
+ // through AgentCancel(agent_id).
144
+ if (runInBackground) {
145
+ const controller = new AbortController();
146
+ asyncAgentRegistry.register({
147
+ agentId,
148
+ name,
149
+ description,
150
+ status: "running",
151
+ startedAt: Date.now(),
152
+ abort: () => controller.abort(),
153
+ });
154
+ // Translate this background agent's per-event stream into ChatEntry-
155
+ // shaped rows inside its own transcript. The dock detail view reuses
156
+ // App.renderEntry which only understands ChatEntry types — storing
157
+ // raw StreamEvents would render as blanks. The translator mirrors
158
+ // App.tsx#handleStreamEvent's reduction but is scoped to one agent
159
+ // (per-instance closure state), so it doesn't interleave with other
160
+ // agents.
161
+ //
162
+ // Sub-agent runs detached from the parent turn — the parent feed only
163
+ // sees the agent_start / agent_end markers via `parentStream` (the
164
+ // 4th arg to runSubAgent); per-event detail goes through the
165
+ // `streamOverride` (5th arg → SubAgentSpawnRequest.streamOverride →
166
+ // engine.ts spawn closure routes to it instead of the main UI).
167
+ const transcriptSink = createTranscriptTranslator(agentId);
168
+ void runSubAgent(spawner, {
169
+ agentId,
170
+ name,
171
+ description,
172
+ prompt,
173
+ maxTurns,
174
+ signal: controller.signal,
175
+ }, parentStream, // uiStream: agent_start/end → main feed
176
+ transcriptSink)
177
+ .then((text) => {
178
+ asyncAgentRegistry.markCompleted(agentId);
179
+ // B2 / Gate 1: attribute completion to the session that spawned
180
+ // this agent so concurrent sessions don't drain each other's
181
+ // notifications. Engine.run() always populates ctx.sessionId; the
182
+ // missing-session branch is only reachable from ad-hoc tool calls
183
+ // outside Engine.run() (notably tests) — we log and drop rather
184
+ // than crash the agent path.
185
+ if (ctx?.sessionId) {
186
+ notificationQueue.enqueue({
187
+ agentId,
188
+ name,
189
+ description,
190
+ status: "completed",
191
+ finalText: text,
192
+ enqueuedAt: Date.now(),
193
+ }, ctx.sessionId);
194
+ }
195
+ else {
196
+ logger.warn("agent_completion_without_session", {
197
+ agentId,
198
+ name,
199
+ status: "completed",
200
+ });
201
+ }
202
+ // notification hook: fire-and-forget. ctx.hooks may be absent in
203
+ // legacy callers; treat as opt-in observability rather than a
204
+ // required publish step. We deliberately do not await — bg-agent
205
+ // bookkeeping should never block on a slow handler.
206
+ void ctx?.hooks?.emit("notification", {
207
+ kind: "agent_completed",
208
+ agentId,
209
+ name,
210
+ description,
211
+ finalText: text,
212
+ });
213
+ })
214
+ .catch((err) => {
215
+ if (controller.signal.aborted) {
216
+ // User-initiated cancel: mark status but do NOT enqueue —
217
+ // the main agent doesn't need a follow-up turn. Dock still
218
+ // shows the "cancelled" badge for the fade window.
219
+ asyncAgentRegistry.markCancelled(agentId);
220
+ void ctx?.hooks?.emit("notification", {
221
+ kind: "agent_cancelled",
222
+ agentId,
223
+ name,
224
+ description,
225
+ });
226
+ return;
227
+ }
228
+ asyncAgentRegistry.markFailed(agentId);
229
+ if (ctx?.sessionId) {
230
+ notificationQueue.enqueue({
231
+ agentId,
232
+ name,
233
+ description,
234
+ status: "failed",
235
+ error: err.message,
236
+ enqueuedAt: Date.now(),
237
+ }, ctx.sessionId);
238
+ }
239
+ else {
240
+ logger.warn("agent_completion_without_session", {
241
+ agentId,
242
+ name,
243
+ status: "failed",
244
+ });
245
+ }
246
+ void ctx?.hooks?.emit("notification", {
247
+ kind: "agent_failed",
248
+ agentId,
249
+ name,
250
+ description,
251
+ error: err.message,
252
+ });
253
+ });
254
+ return [
255
+ `Async agent launched successfully.`,
256
+ `agent_id: ${agentId} (internal — do not show to user)`,
257
+ `description: ${description}`,
258
+ ``,
259
+ `The agent is working in the background. You will be notified automatically when it completes.`,
260
+ `Briefly tell the user what you launched and end your response. Do not generate any other text — agent results will arrive in a subsequent message.`,
261
+ `If you need to stop it: AgentCancel(agent_id="${agentId}").`,
262
+ ].join("\n");
263
+ }
264
+ // ─── Synchronous path ──────────────────────────────────────────
265
+ try {
266
+ return await runSubAgent(spawner, {
267
+ agentId,
268
+ name,
269
+ description,
270
+ prompt,
271
+ maxTurns,
272
+ signal: parentSignal ?? new AbortController().signal,
273
+ });
274
+ }
275
+ catch (err) {
276
+ safeEmit(parentStream, { type: "agent_end", agentId, name, description, error: err.message });
277
+ if (parentSignal?.aborted)
278
+ return "Agent was aborted.";
279
+ return `Agent error: ${err.message}`;
280
+ }
281
+ }
282
+ // ─── AgentStatus / AgentCancel — companions to run_in_background ─
283
+ export const agentStatusToolDef = {
284
+ name: "AgentStatus",
285
+ description: "Check the status of a background agent launched with Agent(run_in_background=true). " +
286
+ "Returns running / completed / failed / cancelled, plus the result text once finished. " +
287
+ "Omit agent_id to list all background agents in this process.",
288
+ inputSchema: {
289
+ type: "object",
290
+ properties: {
291
+ agent_id: {
292
+ type: "string",
293
+ description: "The agent_id returned by Agent(run_in_background=true). Omit to list all.",
294
+ },
295
+ },
296
+ },
297
+ };
298
+ export async function agentStatusTool(args) {
299
+ const agentId = args.agent_id;
300
+ if (!agentId) {
301
+ const all = asyncAgentRegistry.list();
302
+ if (all.length === 0)
303
+ return "No background agents in this process.";
304
+ return all
305
+ .map((e) => {
306
+ const dur = ((e.finishedAt ?? Date.now()) - e.startedAt) / 1000;
307
+ return `${e.agentId} [${e.status}] ${e.description} (${dur.toFixed(1)}s)`;
308
+ })
309
+ .join("\n");
310
+ }
311
+ const e = asyncAgentRegistry.get(agentId);
312
+ if (!e)
313
+ return `Error: agent_id "${agentId}" not found.`;
314
+ const dur = ((e.finishedAt ?? Date.now()) - e.startedAt) / 1000;
315
+ const lines = [
316
+ `agent_id: ${e.agentId}`,
317
+ `status: ${e.status}`,
318
+ `description: ${e.description}`,
319
+ `duration: ${dur.toFixed(1)}s`,
320
+ ];
321
+ if (e.status === "completed") {
322
+ lines.push("", "(completed — result was delivered to the conversation when the agent finished)");
323
+ }
324
+ else if (e.status === "failed") {
325
+ lines.push("", "(failed — error was delivered to the conversation when the agent finished)");
326
+ }
327
+ else if (e.status === "cancelled") {
328
+ lines.push("", "(cancelled — no result delivered)");
329
+ }
330
+ else if (e.status === "running") {
331
+ lines.push("", "(still running — call AgentStatus again later)");
332
+ }
333
+ return lines.join("\n");
334
+ }
335
+ export const agentCancelToolDef = {
336
+ name: "AgentCancel",
337
+ description: "Cancel a background agent launched with Agent(run_in_background=true). " +
338
+ "The agent's current LLM call and any in-flight tools will be aborted.",
339
+ inputSchema: {
340
+ type: "object",
341
+ properties: {
342
+ agent_id: {
343
+ type: "string",
344
+ description: "The agent_id to cancel.",
345
+ },
346
+ },
347
+ required: ["agent_id"],
348
+ },
349
+ };
350
+ export async function agentCancelTool(args) {
351
+ const agentId = args.agent_id;
352
+ if (!agentId)
353
+ return "Error: agent_id is required.";
354
+ const e = asyncAgentRegistry.get(agentId);
355
+ if (!e)
356
+ return `Error: agent_id "${agentId}" not found.`;
357
+ if (e.status !== "running") {
358
+ return `Agent ${agentId} is already ${e.status}; nothing to cancel.`;
359
+ }
360
+ const ok = asyncAgentRegistry.cancel(agentId);
361
+ return ok
362
+ ? `Agent ${agentId} cancelled.`
363
+ : `Failed to cancel agent ${agentId}.`;
364
+ }
@@ -0,0 +1,26 @@
1
+ import { Hunk } from "./types.js";
2
+ export interface ApplyPatchOptions {
3
+ /** Working directory for resolving relative paths in the patch. */
4
+ cwd: string;
5
+ /**
6
+ * If true, skip the snapshot/rollback safety net and apply each planned
7
+ * change one at a time, leaving partial work on disk if a later write
8
+ * fails. Mostly useful for codex-parity testing. Default: false.
9
+ */
10
+ allowPartialOnCommit?: boolean;
11
+ }
12
+ export interface ApplyPatchResult {
13
+ added: string[];
14
+ modified: string[];
15
+ deleted: string[];
16
+ }
17
+ /**
18
+ * Plan and commit the patch atomically.
19
+ *
20
+ * Phase 1 (plan): walk every hunk, compute the resulting file content in
21
+ * memory. Throws if any hunk cannot be applied; nothing is written.
22
+ *
23
+ * Phase 2 (commit): write all planned changes. If any write fails, restore
24
+ * from the in-memory snapshot captured in phase 1 and rethrow.
25
+ */
26
+ export declare function applyPatch(hunks: Hunk[], options: ApplyPatchOptions): Promise<ApplyPatchResult>;
@@ -0,0 +1,250 @@
1
+ // Atomic patch applier — dry-runs all hunks, then commits all-or-nothing.
2
+ //
3
+ // This deliberately diverges from codex-rs/apply-patch which applies hunks
4
+ // one-by-one and leaves partial changes on disk if a later hunk fails (see
5
+ // fixture 015_failure_after_partial_success_leaves_changes for codex's
6
+ // behavior). We treat the patch as a transaction: either every hunk applies
7
+ // or none do. Set `allowPartialOnCommit` to mimic codex semantics for the
8
+ // rare case where you want it.
9
+ //
10
+ // Algorithm uses code adapted from codex-rs/apply-patch/src/lib.rs (Apache-2.0)
11
+ // for the chunk-replacement phase (compute_replacements, apply_replacements).
12
+ import { mkdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
13
+ import { existsSync } from "node:fs";
14
+ import { dirname, isAbsolute, resolve } from "node:path";
15
+ import { seekSequence } from "./seek-sequence.js";
16
+ /**
17
+ * Plan and commit the patch atomically.
18
+ *
19
+ * Phase 1 (plan): walk every hunk, compute the resulting file content in
20
+ * memory. Throws if any hunk cannot be applied; nothing is written.
21
+ *
22
+ * Phase 2 (commit): write all planned changes. If any write fails, restore
23
+ * from the in-memory snapshot captured in phase 1 and rethrow.
24
+ */
25
+ export async function applyPatch(hunks, options) {
26
+ if (hunks.length === 0) {
27
+ throw new Error("No files were modified.");
28
+ }
29
+ const planned = await planHunks(hunks, options.cwd);
30
+ return commitPlanned(planned, !!options.allowPartialOnCommit);
31
+ }
32
+ async function planHunks(hunks, cwd) {
33
+ const set = {
34
+ byPath: new Map(),
35
+ added: [],
36
+ modified: [],
37
+ deleted: [],
38
+ };
39
+ function schedule(path, change) {
40
+ if (set.byPath.has(path)) {
41
+ throw new Error(`Patch references ${path} more than once. Combine the operations into a single hunk.`);
42
+ }
43
+ set.byPath.set(path, change);
44
+ }
45
+ for (const hunk of hunks) {
46
+ const original = hunk.path;
47
+ const sourcePath = resolveAgainst(original, cwd);
48
+ if (hunk.kind === "add") {
49
+ const existed = await readIfExists(sourcePath);
50
+ schedule(sourcePath, {
51
+ path: sourcePath,
52
+ newContent: hunk.contents,
53
+ originalContent: existed,
54
+ });
55
+ set.added.push(original);
56
+ continue;
57
+ }
58
+ if (hunk.kind === "delete") {
59
+ const stats = await safeStat(sourcePath);
60
+ if (!stats)
61
+ throw new Error(`Failed to delete file: ${sourcePath} not found`);
62
+ if (stats.isDirectory()) {
63
+ throw new Error(`Failed to delete file: ${sourcePath} is a directory`);
64
+ }
65
+ const content = await readFile(sourcePath, "utf-8");
66
+ schedule(sourcePath, {
67
+ path: sourcePath,
68
+ newContent: null,
69
+ originalContent: content,
70
+ });
71
+ set.deleted.push(original);
72
+ continue;
73
+ }
74
+ // Update (with optional rename).
75
+ const stats = await safeStat(sourcePath);
76
+ if (!stats) {
77
+ throw new Error(`Failed to update file: ${sourcePath} does not exist`);
78
+ }
79
+ const originalText = await readFile(sourcePath, "utf-8");
80
+ const newText = applyChunksToText(originalText, hunk.chunks, sourcePath);
81
+ if (hunk.movePath !== undefined) {
82
+ const destPath = resolveAgainst(hunk.movePath, cwd);
83
+ if (destPath === sourcePath) {
84
+ // Rename to self → degenerate update.
85
+ schedule(sourcePath, {
86
+ path: sourcePath,
87
+ newContent: newText,
88
+ originalContent: originalText,
89
+ });
90
+ }
91
+ else {
92
+ const destOriginal = await readIfExists(destPath);
93
+ schedule(sourcePath, {
94
+ path: sourcePath,
95
+ newContent: null,
96
+ originalContent: originalText,
97
+ });
98
+ schedule(destPath, {
99
+ path: destPath,
100
+ newContent: newText,
101
+ originalContent: destOriginal,
102
+ });
103
+ }
104
+ set.modified.push(original);
105
+ }
106
+ else {
107
+ schedule(sourcePath, {
108
+ path: sourcePath,
109
+ newContent: newText,
110
+ originalContent: originalText,
111
+ });
112
+ set.modified.push(original);
113
+ }
114
+ }
115
+ return set;
116
+ }
117
+ /** Apply the chunk list to a file's text and return the new text. */
118
+ function applyChunksToText(original, chunks, pathForError) {
119
+ // split('\n') leaves an empty trailing element when the file ends with \n;
120
+ // drop it so line indices match standard diff semantics. We re-add the
121
+ // trailing newline at the end.
122
+ const lines = original.split("\n");
123
+ if (lines.length > 0 && lines[lines.length - 1] === "") {
124
+ lines.pop();
125
+ }
126
+ // Each replacement: [startIndex, oldLen, newLines]
127
+ const replacements = [];
128
+ let lineIndex = 0;
129
+ for (const chunk of chunks) {
130
+ if (chunk.changeContext !== undefined) {
131
+ const found = seekSequence(lines, [chunk.changeContext], lineIndex, false);
132
+ if (found === null) {
133
+ throw new Error(`Failed to find context '${chunk.changeContext}' in ${pathForError}`);
134
+ }
135
+ lineIndex = found + 1;
136
+ }
137
+ if (chunk.oldLines.length === 0) {
138
+ // Pure addition — append at end. Mirrors codex behavior: even when the
139
+ // chunk has a `@@ <context>` anchor, pure additions are inserted at
140
+ // EOF rather than near the anchor. Models should include at least one
141
+ // `-` or ` ` line if they want positional insertion.
142
+ const insertionIdx = lines.length > 0 && lines[lines.length - 1] === ""
143
+ ? lines.length - 1
144
+ : lines.length;
145
+ replacements.push([insertionIdx, 0, [...chunk.newLines]]);
146
+ continue;
147
+ }
148
+ let pattern = chunk.oldLines;
149
+ let newSlice = chunk.newLines;
150
+ let found = seekSequence(lines, pattern, lineIndex, chunk.isEndOfFile);
151
+ if (found === null && pattern.length > 0 && pattern[pattern.length - 1] === "") {
152
+ // Retry without trailing empty sentinel that represents the file's final newline.
153
+ pattern = pattern.slice(0, -1);
154
+ if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "") {
155
+ newSlice = newSlice.slice(0, -1);
156
+ }
157
+ found = seekSequence(lines, pattern, lineIndex, chunk.isEndOfFile);
158
+ }
159
+ if (found === null) {
160
+ throw new Error(`Failed to find expected lines in ${pathForError}:\n${chunk.oldLines.join("\n")}`);
161
+ }
162
+ replacements.push([found, pattern.length, [...newSlice]]);
163
+ lineIndex = found + pattern.length;
164
+ }
165
+ // Apply in descending start-index order so indices stay valid.
166
+ replacements.sort((a, b) => a[0] - b[0]);
167
+ const working = lines.slice();
168
+ for (let i = replacements.length - 1; i >= 0; i--) {
169
+ const [start, oldLen, newSeg] = replacements[i];
170
+ working.splice(start, oldLen, ...newSeg);
171
+ }
172
+ // Always end with a trailing newline.
173
+ if (working.length === 0 || working[working.length - 1] !== "") {
174
+ working.push("");
175
+ }
176
+ return working.join("\n");
177
+ }
178
+ // ─── Phase 2: commit ──────────────────────────────────────────────
179
+ async function commitPlanned(set, allowPartial) {
180
+ // Iterate insertion order (Map iteration is spec-guaranteed).
181
+ const ordered = [...set.byPath.values()];
182
+ if (allowPartial) {
183
+ for (const change of ordered) {
184
+ await writeChange(change);
185
+ }
186
+ return { added: set.added, modified: set.modified, deleted: set.deleted };
187
+ }
188
+ // Track which writes have completed so rollback only touches them. We use
189
+ // the originalContent captured during plan() rather than re-reading from
190
+ // disk — this avoids a TOCTOU window between planning and committing.
191
+ const committed = [];
192
+ try {
193
+ for (const change of ordered) {
194
+ await writeChange(change);
195
+ committed.push(change);
196
+ }
197
+ }
198
+ catch (err) {
199
+ for (let i = committed.length - 1; i >= 0; i--) {
200
+ const c = committed[i];
201
+ try {
202
+ if (c.originalContent === null) {
203
+ // File did not exist before we wrote it — remove our write.
204
+ if (existsSync(c.path))
205
+ await unlink(c.path);
206
+ }
207
+ else {
208
+ await writeFile(c.path, c.originalContent, "utf-8");
209
+ }
210
+ }
211
+ catch {
212
+ // Best-effort restore — surface the original error to the caller.
213
+ }
214
+ }
215
+ throw err;
216
+ }
217
+ return { added: set.added, modified: set.modified, deleted: set.deleted };
218
+ }
219
+ async function writeChange(change) {
220
+ if (change.newContent === null) {
221
+ if (existsSync(change.path))
222
+ await unlink(change.path);
223
+ return;
224
+ }
225
+ const parent = dirname(change.path);
226
+ if (!existsSync(parent)) {
227
+ await mkdir(parent, { recursive: true });
228
+ }
229
+ await writeFile(change.path, change.newContent, "utf-8");
230
+ }
231
+ // ─── helpers ──────────────────────────────────────────────────────
232
+ function resolveAgainst(p, cwd) {
233
+ return isAbsolute(p) ? p : resolve(cwd, p);
234
+ }
235
+ async function safeStat(path) {
236
+ try {
237
+ return await stat(path);
238
+ }
239
+ catch {
240
+ return null;
241
+ }
242
+ }
243
+ async function readIfExists(path) {
244
+ try {
245
+ return await readFile(path, "utf-8");
246
+ }
247
+ catch {
248
+ return null;
249
+ }
250
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * ApplyPatch tool — atomic, multi-file V4A patch application.
3
+ *
4
+ * Adapted from openai/codex codex-rs/apply-patch (Apache-2.0). See LICENSE-codex.
5
+ *
6
+ * Compared to Codex's reference implementation:
7
+ * - We dry-run all hunks first; nothing is written until every hunk
8
+ * successfully resolves.
9
+ * - On commit we snapshot every target file, so a write failure rolls back
10
+ * to the pre-patch state instead of leaving partial changes.
11
+ *
12
+ * Compared to CodeShell's existing Edit:
13
+ * - Multi-file in one call (cuts LLM round-trips for large changes).
14
+ * - Supports create / update / delete / rename in one transaction.
15
+ * - Context-anchor matching tolerates whitespace and Unicode quirks.
16
+ */
17
+ import type { ToolDefinition } from "../../../types.js";
18
+ import type { ToolContext } from "../../context.js";
19
+ export declare const applyPatchToolDef: ToolDefinition;
20
+ export declare function applyPatchTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;