@bastani/atomic 0.9.2-alpha.1 → 0.9.3-alpha.1

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 (455) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/cursor/CHANGELOG.md +6 -0
  4. package/dist/builtin/cursor/package.json +2 -2
  5. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  6. package/dist/builtin/intercom/package.json +1 -1
  7. package/dist/builtin/mcp/CHANGELOG.md +12 -0
  8. package/dist/builtin/mcp/direct-tools.ts +4 -2
  9. package/dist/builtin/mcp/package.json +1 -1
  10. package/dist/builtin/mcp/proxy-call.ts +3 -1
  11. package/dist/builtin/mcp/utils.ts +18 -7
  12. package/dist/builtin/subagents/CHANGELOG.md +17 -0
  13. package/dist/builtin/subagents/README.md +6 -6
  14. package/dist/builtin/subagents/agents/code-simplifier.md +7 -6
  15. package/dist/builtin/subagents/agents/codebase-analyzer.md +5 -4
  16. package/dist/builtin/subagents/agents/codebase-locator.md +3 -3
  17. package/dist/builtin/subagents/agents/codebase-online-researcher.md +10 -10
  18. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +4 -4
  19. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +3 -3
  20. package/dist/builtin/subagents/agents/codebase-research-locator.md +4 -4
  21. package/dist/builtin/subagents/agents/debugger.md +5 -5
  22. package/dist/builtin/subagents/agents/worker.md +56 -0
  23. package/dist/builtin/subagents/package.json +1 -1
  24. package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
  25. package/dist/builtin/subagents/src/agents/agent-loaders.ts +3 -5
  26. package/dist/builtin/subagents/src/agents/agent-management-helpers.ts +3 -3
  27. package/dist/builtin/subagents/src/extension/schemas.ts +2 -2
  28. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -3
  29. package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +2 -2
  31. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -1
  32. package/dist/builtin/subagents/src/shared/types-depth.ts +5 -5
  33. package/dist/builtin/subagents/src/shared/types-runtime.ts +2 -1
  34. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -2
  35. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  36. package/dist/builtin/web-access/package.json +1 -1
  37. package/dist/builtin/workflows/CHANGELOG.md +21 -0
  38. package/dist/builtin/workflows/README.md +2 -2
  39. package/dist/builtin/workflows/builtin/goal-artifacts.ts +11 -6
  40. package/dist/builtin/workflows/builtin/goal-ledger.ts +33 -1
  41. package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -28
  42. package/dist/builtin/workflows/builtin/goal-reducer.ts +2 -2
  43. package/dist/builtin/workflows/builtin/goal-reports.ts +2 -5
  44. package/dist/builtin/workflows/builtin/goal-review.ts +1 -1
  45. package/dist/builtin/workflows/builtin/goal-runner.ts +10 -17
  46. package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +3 -3
  47. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +1 -3
  48. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +1 -1
  49. package/dist/builtin/workflows/builtin/ralph-core.ts +7 -17
  50. package/dist/builtin/workflows/builtin/ralph-runner.ts +11 -18
  51. package/dist/builtin/workflows/builtin/shared-prompts.ts +1 -1
  52. package/dist/builtin/workflows/package.json +1 -1
  53. package/dist/builtin/workflows/src/extension/config-loader.ts +35 -15
  54. package/dist/builtin/workflows/src/extension/discovery.ts +20 -8
  55. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +1 -2
  56. package/dist/builtin/workflows/src/extension/wiring.ts +1 -1
  57. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +11 -10
  58. package/dist/cli/args.d.ts.map +1 -1
  59. package/dist/cli/args.js +9 -9
  60. package/dist/cli/args.js.map +1 -1
  61. package/dist/config-self-update.d.ts.map +1 -1
  62. package/dist/config-self-update.js +3 -4
  63. package/dist/config-self-update.js.map +1 -1
  64. package/dist/config.d.ts.map +1 -1
  65. package/dist/config.js +4 -5
  66. package/dist/config.js.map +1 -1
  67. package/dist/core/agent-session-bash.d.ts +1 -0
  68. package/dist/core/agent-session-bash.d.ts.map +1 -1
  69. package/dist/core/agent-session-bash.js +1 -0
  70. package/dist/core/agent-session-bash.js.map +1 -1
  71. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  72. package/dist/core/agent-session-tool-registry.js +23 -0
  73. package/dist/core/agent-session-tool-registry.js.map +1 -1
  74. package/dist/core/bash-executor.d.ts +2 -0
  75. package/dist/core/bash-executor.d.ts.map +1 -1
  76. package/dist/core/bash-executor.js +1 -0
  77. package/dist/core/bash-executor.js.map +1 -1
  78. package/dist/core/compaction/compaction.d.ts +29 -0
  79. package/dist/core/compaction/compaction.d.ts.map +1 -1
  80. package/dist/core/compaction/compaction.js +36 -1
  81. package/dist/core/compaction/compaction.js.map +1 -1
  82. package/dist/core/compaction/context-compaction-metrics.d.ts +14 -2
  83. package/dist/core/compaction/context-compaction-metrics.d.ts.map +1 -1
  84. package/dist/core/compaction/context-compaction-metrics.js +50 -1
  85. package/dist/core/compaction/context-compaction-metrics.js.map +1 -1
  86. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  87. package/dist/core/compaction/context-compaction-prompt.js +2 -0
  88. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  89. package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
  90. package/dist/core/compaction/context-compaction-runner.js +1 -1
  91. package/dist/core/compaction/context-compaction-runner.js.map +1 -1
  92. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  93. package/dist/core/compaction/context-deletion-application.js +5 -5
  94. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  95. package/dist/core/compaction/context-deletion-targets.d.ts +2 -0
  96. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  97. package/dist/core/compaction/context-deletion-targets.js +23 -3
  98. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  99. package/dist/core/compaction/context-deletion-tool-definitions.d.ts +6 -0
  100. package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +1 -1
  101. package/dist/core/compaction/context-deletion-tool-definitions.js.map +1 -1
  102. package/dist/core/compaction/context-deletion-tools.d.ts.map +1 -1
  103. package/dist/core/compaction/context-deletion-tools.js +18 -10
  104. package/dist/core/compaction/context-deletion-tools.js.map +1 -1
  105. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  106. package/dist/core/compaction/context-transcript-analysis.js +2 -4
  107. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  108. package/dist/core/copilot-gemini-tool-arguments.d.ts.map +1 -1
  109. package/dist/core/copilot-gemini-tool-arguments.js +2 -60
  110. package/dist/core/copilot-gemini-tool-arguments.js.map +1 -1
  111. package/dist/core/extensions/context-types.d.ts +2 -0
  112. package/dist/core/extensions/context-types.d.ts.map +1 -1
  113. package/dist/core/extensions/context-types.js.map +1 -1
  114. package/dist/core/extensions/index.d.ts +2 -2
  115. package/dist/core/extensions/index.d.ts.map +1 -1
  116. package/dist/core/extensions/index.js +1 -1
  117. package/dist/core/extensions/index.js.map +1 -1
  118. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  119. package/dist/core/extensions/loader-virtual-modules.js +11 -3
  120. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  121. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  122. package/dist/core/extensions/runner-context.js +11 -0
  123. package/dist/core/extensions/runner-context.js.map +1 -1
  124. package/dist/core/extensions/tool-events.d.ts +13 -13
  125. package/dist/core/extensions/tool-events.d.ts.map +1 -1
  126. package/dist/core/extensions/tool-events.js +3 -3
  127. package/dist/core/extensions/tool-events.js.map +1 -1
  128. package/dist/core/extensions/types.d.ts +1 -1
  129. package/dist/core/extensions/types.d.ts.map +1 -1
  130. package/dist/core/extensions/types.js +1 -1
  131. package/dist/core/extensions/types.js.map +1 -1
  132. package/dist/core/flattened-tool-arguments.d.ts +18 -0
  133. package/dist/core/flattened-tool-arguments.d.ts.map +1 -1
  134. package/dist/core/flattened-tool-arguments.js +104 -0
  135. package/dist/core/flattened-tool-arguments.js.map +1 -1
  136. package/dist/core/sdk-exports.d.ts +1 -1
  137. package/dist/core/sdk-exports.d.ts.map +1 -1
  138. package/dist/core/sdk-exports.js +1 -1
  139. package/dist/core/sdk-exports.js.map +1 -1
  140. package/dist/core/sdk-types.d.ts +2 -2
  141. package/dist/core/sdk-types.d.ts.map +1 -1
  142. package/dist/core/sdk-types.js.map +1 -1
  143. package/dist/core/settings-manager-basic-accessors.d.ts +4 -0
  144. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  145. package/dist/core/settings-manager-basic-accessors.js +18 -0
  146. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  147. package/dist/core/settings-manager-resource-accessors.d.ts +4 -0
  148. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  149. package/dist/core/settings-manager-resource-accessors.js +15 -0
  150. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  151. package/dist/core/settings-types.d.ts +11 -0
  152. package/dist/core/settings-types.d.ts.map +1 -1
  153. package/dist/core/settings-types.js.map +1 -1
  154. package/dist/core/system-prompt.d.ts +1 -1
  155. package/dist/core/system-prompt.d.ts.map +1 -1
  156. package/dist/core/system-prompt.js +3 -2
  157. package/dist/core/system-prompt.js.map +1 -1
  158. package/dist/core/tools/artifact-protocol.d.ts +11 -0
  159. package/dist/core/tools/artifact-protocol.d.ts.map +1 -0
  160. package/dist/core/tools/artifact-protocol.js +76 -0
  161. package/dist/core/tools/artifact-protocol.js.map +1 -0
  162. package/dist/core/tools/artifacts.d.ts +18 -0
  163. package/dist/core/tools/artifacts.d.ts.map +1 -0
  164. package/dist/core/tools/artifacts.js +90 -0
  165. package/dist/core/tools/artifacts.js.map +1 -0
  166. package/dist/core/tools/bash-async-jobs.d.ts +20 -0
  167. package/dist/core/tools/bash-async-jobs.d.ts.map +1 -0
  168. package/dist/core/tools/bash-async-jobs.js +59 -0
  169. package/dist/core/tools/bash-async-jobs.js.map +1 -0
  170. package/dist/core/tools/bash-async-output.d.ts +10 -0
  171. package/dist/core/tools/bash-async-output.d.ts.map +1 -0
  172. package/dist/core/tools/bash-async-output.js +80 -0
  173. package/dist/core/tools/bash-async-output.js.map +1 -0
  174. package/dist/core/tools/bash-interceptor.d.ts +10 -0
  175. package/dist/core/tools/bash-interceptor.d.ts.map +1 -0
  176. package/dist/core/tools/bash-interceptor.js +39 -0
  177. package/dist/core/tools/bash-interceptor.js.map +1 -0
  178. package/dist/core/tools/bash-leading-cd.d.ts +7 -0
  179. package/dist/core/tools/bash-leading-cd.d.ts.map +1 -0
  180. package/dist/core/tools/bash-leading-cd.js +59 -0
  181. package/dist/core/tools/bash-leading-cd.js.map +1 -0
  182. package/dist/core/tools/bash-pty-native.d.ts +14 -0
  183. package/dist/core/tools/bash-pty-native.d.ts.map +1 -0
  184. package/dist/core/tools/bash-pty-native.js +71 -0
  185. package/dist/core/tools/bash-pty-native.js.map +1 -0
  186. package/dist/core/tools/bash.d.ts +28 -17
  187. package/dist/core/tools/bash.d.ts.map +1 -1
  188. package/dist/core/tools/bash.js +152 -35
  189. package/dist/core/tools/bash.js.map +1 -1
  190. package/dist/core/tools/block-resolver.d.ts +16 -0
  191. package/dist/core/tools/block-resolver.d.ts.map +1 -0
  192. package/dist/core/tools/block-resolver.js +74 -0
  193. package/dist/core/tools/block-resolver.js.map +1 -0
  194. package/dist/core/tools/conflict-registry.d.ts +16 -0
  195. package/dist/core/tools/conflict-registry.d.ts.map +1 -0
  196. package/dist/core/tools/conflict-registry.js +44 -0
  197. package/dist/core/tools/conflict-registry.js.map +1 -0
  198. package/dist/core/tools/directory-tree.d.ts +13 -0
  199. package/dist/core/tools/directory-tree.d.ts.map +1 -0
  200. package/dist/core/tools/directory-tree.js +81 -0
  201. package/dist/core/tools/directory-tree.js.map +1 -0
  202. package/dist/core/tools/edit.d.ts +4 -29
  203. package/dist/core/tools/edit.d.ts.map +1 -1
  204. package/dist/core/tools/edit.js +136 -228
  205. package/dist/core/tools/edit.js.map +1 -1
  206. package/dist/core/tools/fetch-url.d.ts +74 -0
  207. package/dist/core/tools/fetch-url.d.ts.map +1 -0
  208. package/dist/core/tools/fetch-url.js +518 -0
  209. package/dist/core/tools/fetch-url.js.map +1 -0
  210. package/dist/core/tools/find.d.ts +27 -9
  211. package/dist/core/tools/find.d.ts.map +1 -1
  212. package/dist/core/tools/find.js +400 -176
  213. package/dist/core/tools/find.js.map +1 -1
  214. package/dist/core/tools/glob-path-utils.d.ts +8 -0
  215. package/dist/core/tools/glob-path-utils.d.ts.map +1 -0
  216. package/dist/core/tools/glob-path-utils.js +26 -0
  217. package/dist/core/tools/glob-path-utils.js.map +1 -0
  218. package/dist/core/tools/grep.d.ts +12 -0
  219. package/dist/core/tools/grep.d.ts.map +1 -1
  220. package/dist/core/tools/grep.js +141 -17
  221. package/dist/core/tools/grep.js.map +1 -1
  222. package/dist/core/tools/hashline-engine/apply.d.ts +11 -0
  223. package/dist/core/tools/hashline-engine/apply.d.ts.map +1 -0
  224. package/dist/core/tools/hashline-engine/apply.js +752 -0
  225. package/dist/core/tools/hashline-engine/apply.js.map +1 -0
  226. package/dist/core/tools/hashline-engine/block.d.ts +40 -0
  227. package/dist/core/tools/hashline-engine/block.d.ts.map +1 -0
  228. package/dist/core/tools/hashline-engine/block.js +117 -0
  229. package/dist/core/tools/hashline-engine/block.js.map +1 -0
  230. package/dist/core/tools/hashline-engine/diff-preview.d.ts +15 -0
  231. package/dist/core/tools/hashline-engine/diff-preview.d.ts.map +1 -0
  232. package/dist/core/tools/hashline-engine/diff-preview.js +98 -0
  233. package/dist/core/tools/hashline-engine/diff-preview.js.map +1 -0
  234. package/dist/core/tools/hashline-engine/format.d.ts +71 -0
  235. package/dist/core/tools/hashline-engine/format.d.ts.map +1 -0
  236. package/dist/core/tools/hashline-engine/format.js +178 -0
  237. package/dist/core/tools/hashline-engine/format.js.map +1 -0
  238. package/dist/core/tools/hashline-engine/fs.d.ts +81 -0
  239. package/dist/core/tools/hashline-engine/fs.d.ts.map +1 -0
  240. package/dist/core/tools/hashline-engine/fs.js +143 -0
  241. package/dist/core/tools/hashline-engine/fs.js.map +1 -0
  242. package/dist/core/tools/hashline-engine/index.d.ts +18 -0
  243. package/dist/core/tools/hashline-engine/index.d.ts.map +1 -0
  244. package/dist/core/tools/hashline-engine/index.js +20 -0
  245. package/dist/core/tools/hashline-engine/index.js.map +1 -0
  246. package/dist/core/tools/hashline-engine/input.d.ts +101 -0
  247. package/dist/core/tools/hashline-engine/input.d.ts.map +1 -0
  248. package/dist/core/tools/hashline-engine/input.js +398 -0
  249. package/dist/core/tools/hashline-engine/input.js.map +1 -0
  250. package/dist/core/tools/hashline-engine/messages.d.ts +99 -0
  251. package/dist/core/tools/hashline-engine/messages.d.ts.map +1 -0
  252. package/dist/core/tools/hashline-engine/messages.js +144 -0
  253. package/dist/core/tools/hashline-engine/messages.js.map +1 -0
  254. package/dist/core/tools/hashline-engine/mismatch.d.ts +45 -0
  255. package/dist/core/tools/hashline-engine/mismatch.d.ts.map +1 -0
  256. package/dist/core/tools/hashline-engine/mismatch.js +90 -0
  257. package/dist/core/tools/hashline-engine/mismatch.js.map +1 -0
  258. package/dist/core/tools/hashline-engine/normalize.d.ts +21 -0
  259. package/dist/core/tools/hashline-engine/normalize.d.ts.map +1 -0
  260. package/dist/core/tools/hashline-engine/normalize.js +33 -0
  261. package/dist/core/tools/hashline-engine/normalize.js.map +1 -0
  262. package/dist/core/tools/hashline-engine/parser.d.ts +24 -0
  263. package/dist/core/tools/hashline-engine/parser.d.ts.map +1 -0
  264. package/dist/core/tools/hashline-engine/parser.js +381 -0
  265. package/dist/core/tools/hashline-engine/parser.js.map +1 -0
  266. package/dist/core/tools/hashline-engine/patcher.d.ts +118 -0
  267. package/dist/core/tools/hashline-engine/patcher.d.ts.map +1 -0
  268. package/dist/core/tools/hashline-engine/patcher.js +341 -0
  269. package/dist/core/tools/hashline-engine/patcher.js.map +1 -0
  270. package/dist/core/tools/hashline-engine/prefixes.d.ts +43 -0
  271. package/dist/core/tools/hashline-engine/prefixes.d.ts.map +1 -0
  272. package/dist/core/tools/hashline-engine/prefixes.js +135 -0
  273. package/dist/core/tools/hashline-engine/prefixes.js.map +1 -0
  274. package/dist/core/tools/hashline-engine/recovery.d.ts +41 -0
  275. package/dist/core/tools/hashline-engine/recovery.d.ts.map +1 -0
  276. package/dist/core/tools/hashline-engine/recovery.js +168 -0
  277. package/dist/core/tools/hashline-engine/recovery.js.map +1 -0
  278. package/dist/core/tools/hashline-engine/snapshots.d.ts +65 -0
  279. package/dist/core/tools/hashline-engine/snapshots.d.ts.map +1 -0
  280. package/dist/core/tools/hashline-engine/snapshots.js +108 -0
  281. package/dist/core/tools/hashline-engine/snapshots.js.map +1 -0
  282. package/dist/core/tools/hashline-engine/stream.d.ts +3 -0
  283. package/dist/core/tools/hashline-engine/stream.d.ts.map +1 -0
  284. package/dist/core/tools/hashline-engine/stream.js +111 -0
  285. package/dist/core/tools/hashline-engine/stream.js.map +1 -0
  286. package/dist/core/tools/hashline-engine/tokenizer.d.ts +69 -0
  287. package/dist/core/tools/hashline-engine/tokenizer.d.ts.map +1 -0
  288. package/dist/core/tools/hashline-engine/tokenizer.js +430 -0
  289. package/dist/core/tools/hashline-engine/tokenizer.js.map +1 -0
  290. package/dist/core/tools/hashline-engine/types.d.ts +166 -0
  291. package/dist/core/tools/hashline-engine/types.d.ts.map +1 -0
  292. package/dist/core/tools/hashline-engine/types.js +9 -0
  293. package/dist/core/tools/hashline-engine/types.js.map +1 -0
  294. package/dist/core/tools/hashline.d.ts +29 -0
  295. package/dist/core/tools/hashline.d.ts.map +1 -0
  296. package/dist/core/tools/hashline.js +110 -0
  297. package/dist/core/tools/hashline.js.map +1 -0
  298. package/dist/core/tools/index.d.ts +6 -4
  299. package/dist/core/tools/index.d.ts.map +1 -1
  300. package/dist/core/tools/index.js +52 -35
  301. package/dist/core/tools/index.js.map +1 -1
  302. package/dist/core/tools/notebook.d.ts +38 -0
  303. package/dist/core/tools/notebook.d.ts.map +1 -0
  304. package/dist/core/tools/notebook.js +125 -0
  305. package/dist/core/tools/notebook.js.map +1 -0
  306. package/dist/core/tools/read-document-extract.d.ts +9 -0
  307. package/dist/core/tools/read-document-extract.d.ts.map +1 -0
  308. package/dist/core/tools/read-document-extract.js +212 -0
  309. package/dist/core/tools/read-document-extract.js.map +1 -0
  310. package/dist/core/tools/read-selectors.d.ts +24 -0
  311. package/dist/core/tools/read-selectors.d.ts.map +1 -0
  312. package/dist/core/tools/read-selectors.js +277 -0
  313. package/dist/core/tools/read-selectors.js.map +1 -0
  314. package/dist/core/tools/read-url.d.ts +37 -0
  315. package/dist/core/tools/read-url.d.ts.map +1 -0
  316. package/dist/core/tools/read-url.js +39 -0
  317. package/dist/core/tools/read-url.js.map +1 -0
  318. package/dist/core/tools/read.d.ts +11 -11
  319. package/dist/core/tools/read.d.ts.map +1 -1
  320. package/dist/core/tools/read.js +224 -94
  321. package/dist/core/tools/read.js.map +1 -1
  322. package/dist/core/tools/resource-selectors.d.ts +44 -0
  323. package/dist/core/tools/resource-selectors.d.ts.map +1 -0
  324. package/dist/core/tools/resource-selectors.js +808 -0
  325. package/dist/core/tools/resource-selectors.js.map +1 -0
  326. package/dist/core/tools/search-details.d.ts +26 -0
  327. package/dist/core/tools/search-details.d.ts.map +1 -0
  328. package/dist/core/tools/search-details.js +24 -0
  329. package/dist/core/tools/search-details.js.map +1 -0
  330. package/dist/core/tools/search-line-ranges.d.ts +11 -0
  331. package/dist/core/tools/search-line-ranges.d.ts.map +1 -0
  332. package/dist/core/tools/search-line-ranges.js +65 -0
  333. package/dist/core/tools/search-line-ranges.js.map +1 -0
  334. package/dist/core/tools/search-native.d.ts +97 -0
  335. package/dist/core/tools/search-native.d.ts.map +1 -0
  336. package/dist/core/tools/search-native.js +27 -0
  337. package/dist/core/tools/search-native.js.map +1 -0
  338. package/dist/core/tools/search.d.ts +24 -0
  339. package/dist/core/tools/search.d.ts.map +1 -0
  340. package/dist/core/tools/search.js +573 -0
  341. package/dist/core/tools/search.js.map +1 -0
  342. package/dist/core/tools/truncate.d.ts +4 -4
  343. package/dist/core/tools/truncate.d.ts.map +1 -1
  344. package/dist/core/tools/truncate.js +3 -3
  345. package/dist/core/tools/truncate.js.map +1 -1
  346. package/dist/core/tools/url-ip-guards.d.ts +4 -0
  347. package/dist/core/tools/url-ip-guards.d.ts.map +1 -0
  348. package/dist/core/tools/url-ip-guards.js +126 -0
  349. package/dist/core/tools/url-ip-guards.js.map +1 -0
  350. package/dist/core/tools/write.d.ts +12 -2
  351. package/dist/core/tools/write.d.ts.map +1 -1
  352. package/dist/core/tools/write.js +166 -14
  353. package/dist/core/tools/write.js.map +1 -1
  354. package/dist/core/trust-manager.d.ts.map +1 -1
  355. package/dist/core/trust-manager.js +2 -3
  356. package/dist/core/trust-manager.js.map +1 -1
  357. package/dist/index-extensions.d.ts +2 -2
  358. package/dist/index-extensions.d.ts.map +1 -1
  359. package/dist/index-extensions.js +1 -1
  360. package/dist/index-extensions.js.map +1 -1
  361. package/dist/index.d.ts +3 -3
  362. package/dist/index.d.ts.map +1 -1
  363. package/dist/index.js +3 -3
  364. package/dist/index.js.map +1 -1
  365. package/dist/modes/interactive/components/custom-editor.d.ts +1 -0
  366. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/custom-editor.js +9 -2
  368. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  369. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  370. package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
  371. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  372. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/settings-selector-items.js +7 -0
  374. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  375. package/dist/modes/interactive/components/settings-selector-types.d.ts +2 -0
  376. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  378. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  379. package/dist/modes/interactive/components/tree-selector-content.js +0 -5
  380. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  381. package/dist/modes/interactive/interactive-auth-login.d.ts.map +1 -1
  382. package/dist/modes/interactive/interactive-auth-login.js +1 -0
  383. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  384. package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  385. package/dist/modes/interactive/interactive-autocomplete.js +80 -2
  386. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  387. package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
  388. package/dist/modes/interactive/interactive-hotkeys-debug.js +3 -0
  389. package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
  390. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  391. package/dist/modes/interactive/interactive-input-handling.js +51 -0
  392. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  393. package/dist/modes/interactive/interactive-mode-base.d.ts +5 -0
  394. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  395. package/dist/modes/interactive/interactive-mode-base.js +5 -0
  396. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  397. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  398. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  399. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  400. package/dist/modes/interactive/interactive-mode-surface.d.ts +12 -0
  401. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  402. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  403. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  404. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  405. package/dist/modes/interactive/interactive-mode.js +1 -0
  406. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  407. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  408. package/dist/modes/interactive/interactive-model-routing.js +4 -1
  409. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  410. package/dist/modes/interactive/interactive-onboarding.d.ts +11 -0
  411. package/dist/modes/interactive/interactive-onboarding.d.ts.map +1 -0
  412. package/dist/modes/interactive/interactive-onboarding.js +220 -0
  413. package/dist/modes/interactive/interactive-onboarding.js.map +1 -0
  414. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  415. package/dist/modes/interactive/interactive-selectors.js +4 -0
  416. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  417. package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
  418. package/dist/modes/interactive/interactive-session-routing.js +6 -0
  419. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  420. package/dist/modes/interactive/interactive-slash-commands.d.ts.map +1 -1
  421. package/dist/modes/interactive/interactive-slash-commands.js +9 -4
  422. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  423. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  424. package/dist/modes/interactive/interactive-startup.js +28 -0
  425. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  426. package/dist/utils/child-process.d.ts.map +1 -1
  427. package/dist/utils/child-process.js +21 -1
  428. package/dist/utils/child-process.js.map +1 -1
  429. package/dist/utils/markit.d.ts +8 -0
  430. package/dist/utils/markit.d.ts.map +1 -0
  431. package/dist/utils/markit.js +53 -0
  432. package/dist/utils/markit.js.map +1 -0
  433. package/dist/utils/paths.d.ts +2 -1
  434. package/dist/utils/paths.d.ts.map +1 -1
  435. package/dist/utils/paths.js +14 -1
  436. package/dist/utils/paths.js.map +1 -1
  437. package/docs/compaction.md +16 -1
  438. package/docs/containerization.md +1 -1
  439. package/docs/docs.json +1 -0
  440. package/docs/extensions.md +25 -36
  441. package/docs/quickstart.md +11 -6
  442. package/docs/sdk.md +5 -5
  443. package/docs/settings.md +7 -0
  444. package/docs/subagents.md +3 -2
  445. package/docs/tools.md +49 -0
  446. package/docs/usage.md +3 -3
  447. package/docs/workflows.md +7 -5
  448. package/examples/extensions/subagent/README.md +5 -5
  449. package/examples/extensions/subagent/agents/planner.md +1 -1
  450. package/examples/extensions/subagent/agents/reviewer.md +1 -1
  451. package/examples/extensions/subagent/agents/scout.md +2 -2
  452. package/examples/extensions/subagent/display.ts +3 -3
  453. package/examples/sdk/05-tools.ts +3 -3
  454. package/examples/sdk/README.md +1 -1
  455. package/package.json +3 -2
@@ -0,0 +1,752 @@
1
+ // @generated vendored verbatim from oh-my-pi packages/hashline @ 15b5c1397fc -- DO NOT EDIT.
2
+ // Parity source for the Atomic hashline edit engine (issue #1483); adapted only for Atomic's Node runtime (relative imports, Bun->Node host calls, erasable constructor syntax).
3
+ /**
4
+ * Apply a parsed list of {@link Edit}s to a text body and return the
5
+ * post-edit lines plus any diagnostic warnings. Pure function: no FS, no
6
+ * mutation of the input.
7
+ *
8
+ * Replacement groups are first normalized by {@link repairReplacementBoundaries},
9
+ * which absorbs common model mistakes where a payload restates unchanged range
10
+ * boundaries or duplicates/drops structural closers.
11
+ */
12
+ import { afterInsertLandingShiftWarning, blockInsertLandingShiftWarning, UNRESOLVED_BLOCK_INTERNAL } from "./messages.js";
13
+ import { cloneCursor } from "./tokenizer.js";
14
+ function isReplacementInsert(edit) {
15
+ return edit.kind === "insert" && edit.mode === "replacement";
16
+ }
17
+ function getCursorAnchors(cursor) {
18
+ return cursor.kind === "before_anchor" || cursor.kind === "after_anchor" ? [cursor.anchor] : [];
19
+ }
20
+ function getEditAnchors(edit) {
21
+ if (edit.kind === "delete")
22
+ return [edit.anchor];
23
+ return getCursorAnchors(edit.cursor);
24
+ }
25
+ function trailingPhantomLine(fileLines) {
26
+ // `split("\n")` on a newline-terminated file yields a trailing "" sentinel.
27
+ // It is addressable for inserts (append-past-end), but it is not real
28
+ // content. Deleting it only strips the file's final newline, so ignore delete
29
+ // edits that land there; inclusive ranges ending at EOF then do the intended
30
+ // thing and delete through the last concrete line.
31
+ return fileLines.length > 1 && fileLines[fileLines.length - 1] === "" ? fileLines.length : 0;
32
+ }
33
+ function dropTrailingPhantomDeletes(edits, fileLines) {
34
+ const phantomLine = trailingPhantomLine(fileLines);
35
+ if (phantomLine === 0)
36
+ return edits;
37
+ return edits.filter(edit => edit.kind !== "delete" || edit.anchor.line !== phantomLine);
38
+ }
39
+ /**
40
+ * Verify every anchored edit points at an existing line. File-version binding is
41
+ * checked once per section via the header hash before this function runs.
42
+ */
43
+ function validateLineBounds(edits, fileLines) {
44
+ for (const edit of edits) {
45
+ for (const anchor of getEditAnchors(edit)) {
46
+ if (anchor.line < 1 || anchor.line > fileLines.length) {
47
+ throw new Error(`Line ${anchor.line} does not exist (file has ${fileLines.length} lines)`);
48
+ }
49
+ }
50
+ }
51
+ }
52
+ function cloneAppliedEdit(edit, index) {
53
+ if (edit.kind === "delete")
54
+ return { ...edit, anchor: { ...edit.anchor }, index };
55
+ return { ...edit, cursor: cloneCursor(edit.cursor), index };
56
+ }
57
+ function insertAtStart(fileLines, lineOrigins, lines) {
58
+ if (lines.length === 0)
59
+ return;
60
+ const origins = lines.map(() => "insert");
61
+ if (fileLines.length === 1 && fileLines[0] === "") {
62
+ fileLines.splice(0, 1, ...lines);
63
+ lineOrigins.splice(0, 1, ...origins);
64
+ return;
65
+ }
66
+ fileLines.splice(0, 0, ...lines);
67
+ lineOrigins.splice(0, 0, ...origins);
68
+ }
69
+ function insertAtEnd(fileLines, lineOrigins, lines) {
70
+ if (lines.length === 0)
71
+ return undefined;
72
+ const origins = lines.map(() => "insert");
73
+ if (fileLines.length === 1 && fileLines[0] === "") {
74
+ fileLines.splice(0, 1, ...lines);
75
+ lineOrigins.splice(0, 1, ...origins);
76
+ return 1;
77
+ }
78
+ const hasTrailingNewline = fileLines.length > 0 && fileLines[fileLines.length - 1] === "";
79
+ const insertIndex = hasTrailingNewline ? fileLines.length - 1 : fileLines.length;
80
+ fileLines.splice(insertIndex, 0, ...lines);
81
+ lineOrigins.splice(insertIndex, 0, ...origins);
82
+ return insertIndex + 1;
83
+ }
84
+ function bucketAnchorEditsByLine(edits) {
85
+ const byLine = new Map();
86
+ for (const entry of edits) {
87
+ const line = entry.edit.kind === "delete"
88
+ ? entry.edit.anchor.line
89
+ : entry.edit.cursor.kind === "before_anchor" || entry.edit.cursor.kind === "after_anchor"
90
+ ? entry.edit.cursor.anchor.line
91
+ : 0;
92
+ const bucket = byLine.get(line);
93
+ if (bucket)
94
+ bucket.push(entry);
95
+ else
96
+ byLine.set(line, [entry]);
97
+ }
98
+ return byLine;
99
+ }
100
+ // ═══════════════════════════════════════════════════════════════════════════
101
+ // Replacement-boundary repair
102
+ //
103
+ // Models routinely miscount a replacement range's edges. Sometimes the payload
104
+ // re-states unchanged lines that still live on both sides of the range
105
+ // (duplicating a function header and final statement); sometimes it only
106
+ // re-states or omits a structural closer, which leaves delimiter balance broken.
107
+ //
108
+ // A balance-neutral boundary-echo repair fires only when both the leading and
109
+ // trailing payload edges are exact copies of the surviving lines outside the
110
+ // range. One-sided content echoes are left alone unless delimiter-balance repair
111
+ // proves they are duplicated structural boundaries. This preserves intended
112
+ // duplicate statements while absorbing the common "body includes the unchanged
113
+ // wrapper" mistake.
114
+ /** A line that is nothing but closing delimiters: `}`, `)`, `];`, `})`, `},`. */
115
+ export const STRUCTURAL_CLOSER_RE = /^\s*[)\]}]+[;,]?\s*$/;
116
+ /**
117
+ * Net `()` / `[]` / `{}` delta across `lines`, skipping delimiters inside line
118
+ * comments (`//`), block comments, and string/template literals. Block-comment
119
+ * and backtick-template state carry across lines; `"` / `'` reset at EOL since
120
+ * they cannot span lines. Deliberately language-light: constructs it cannot
121
+ * classify (e.g. regex literals) are counted naively, which can only suppress a
122
+ * repair (the safe direction), never force one.
123
+ */
124
+ function computeDelimiterBalance(lines) {
125
+ const balance = { paren: 0, bracket: 0, brace: 0 };
126
+ let inBlockComment = false;
127
+ let quote = "";
128
+ for (const line of lines) {
129
+ for (let i = 0; i < line.length; i++) {
130
+ const ch = line[i];
131
+ if (inBlockComment) {
132
+ if (ch === "*" && line[i + 1] === "/") {
133
+ inBlockComment = false;
134
+ i++;
135
+ }
136
+ continue;
137
+ }
138
+ if (quote) {
139
+ if (ch === "\\")
140
+ i++;
141
+ else if (ch === quote)
142
+ quote = "";
143
+ continue;
144
+ }
145
+ if (ch === '"' || ch === "'" || ch === "`") {
146
+ quote = ch;
147
+ continue;
148
+ }
149
+ if (ch === "/" && line[i + 1] === "/")
150
+ break;
151
+ if (ch === "/" && line[i + 1] === "*") {
152
+ inBlockComment = true;
153
+ i++;
154
+ continue;
155
+ }
156
+ switch (ch) {
157
+ case "(":
158
+ balance.paren++;
159
+ break;
160
+ case ")":
161
+ balance.paren--;
162
+ break;
163
+ case "[":
164
+ balance.bracket++;
165
+ break;
166
+ case "]":
167
+ balance.bracket--;
168
+ break;
169
+ case "{":
170
+ balance.brace++;
171
+ break;
172
+ case "}":
173
+ balance.brace--;
174
+ break;
175
+ }
176
+ }
177
+ // `"` / `'` cannot span lines; only backtick templates and block comments do.
178
+ if (quote === '"' || quote === "'")
179
+ quote = "";
180
+ }
181
+ return balance;
182
+ }
183
+ function balanceDelta(a, b) {
184
+ return { paren: a.paren - b.paren, bracket: a.bracket - b.bracket, brace: a.brace - b.brace };
185
+ }
186
+ function balanceNegate(a) {
187
+ return { paren: -a.paren, bracket: -a.bracket, brace: -a.brace };
188
+ }
189
+ function balanceEqual(a, b) {
190
+ return a.paren === b.paren && a.bracket === b.bracket && a.brace === b.brace;
191
+ }
192
+ function balanceIsZero(a) {
193
+ return a.paren === 0 && a.bracket === 0 && a.brace === 0;
194
+ }
195
+ /**
196
+ * Detect a replacement group starting at `start`: a run of `before_anchor`
197
+ * replacement inserts sharing one source op line, immediately followed by the
198
+ * contiguous range deletes for that same op. Mirrors how the parser lowers an
199
+ * `replace N..M:` hunk with a body.
200
+ */
201
+ function findReplacementGroup(edits, start) {
202
+ const first = edits[start];
203
+ if (first?.kind !== "insert" || first.mode !== "replacement" || first.cursor.kind !== "before_anchor") {
204
+ return undefined;
205
+ }
206
+ const { lineNum } = first;
207
+ const anchorLine = first.cursor.anchor.line;
208
+ const insertIndices = [];
209
+ const payload = [];
210
+ let i = start;
211
+ for (; i < edits.length; i++) {
212
+ const edit = edits[i];
213
+ if (edit.kind !== "insert" || edit.mode !== "replacement" || edit.lineNum !== lineNum)
214
+ break;
215
+ if (edit.cursor.kind !== "before_anchor" || edit.cursor.anchor.line !== anchorLine)
216
+ break;
217
+ insertIndices.push(i);
218
+ payload.push(edit.text);
219
+ }
220
+ const deleteIndices = [];
221
+ let expectedLine = anchorLine;
222
+ for (; i < edits.length; i++) {
223
+ const edit = edits[i];
224
+ if (edit.kind !== "delete" || edit.lineNum !== lineNum || edit.anchor.line !== expectedLine)
225
+ break;
226
+ deleteIndices.push(i);
227
+ expectedLine++;
228
+ }
229
+ if (deleteIndices.length === 0)
230
+ return undefined;
231
+ return {
232
+ insertIndices,
233
+ deleteIndices,
234
+ payload,
235
+ startLine: anchorLine,
236
+ endLine: anchorLine + deleteIndices.length - 1,
237
+ };
238
+ }
239
+ /**
240
+ * Largest `k` such that the payload's last `k` lines exactly equal the `k`
241
+ * surviving file lines just below the range AND dropping them zeroes `delta`.
242
+ * Requires a non-zero `delta`: a zero-balance candidate can never account for
243
+ * the imbalance, so intentional duplicates of ordinary statements stay intact,
244
+ * while duplicated structural lines (closers like `});`, openers like `foo(`)
245
+ * are dropped when they exactly explain the imbalance.
246
+ */
247
+ function findDuplicateSuffix(group, fileLines, delta) {
248
+ if (balanceIsZero(delta))
249
+ return 0;
250
+ const { payload, endLine } = group;
251
+ const maxK = Math.min(payload.length, fileLines.length - endLine);
252
+ for (let k = maxK; k >= 1; k--) {
253
+ let matches = true;
254
+ for (let t = 0; t < k; t++) {
255
+ if (payload[payload.length - k + t] !== fileLines[endLine + t]) {
256
+ matches = false;
257
+ break;
258
+ }
259
+ }
260
+ if (!matches)
261
+ continue;
262
+ if (balanceEqual(computeDelimiterBalance(payload.slice(payload.length - k)), delta))
263
+ return k;
264
+ }
265
+ return 0;
266
+ }
267
+ /**
268
+ * Largest `j` such that the payload's first `j` lines exactly equal the `j`
269
+ * surviving file lines just above the range AND dropping them zeroes `delta`.
270
+ * Requires a non-zero `delta`; see {@link findDuplicateSuffix}.
271
+ */
272
+ function findDuplicatePrefix(group, fileLines, delta) {
273
+ if (balanceIsZero(delta))
274
+ return 0;
275
+ const { payload, startLine } = group;
276
+ const maxJ = Math.min(payload.length, startLine - 1);
277
+ for (let j = maxJ; j >= 1; j--) {
278
+ let matches = true;
279
+ for (let t = 0; t < j; t++) {
280
+ if (payload[t] !== fileLines[startLine - 1 - j + t]) {
281
+ matches = false;
282
+ break;
283
+ }
284
+ }
285
+ if (!matches)
286
+ continue;
287
+ if (balanceEqual(computeDelimiterBalance(payload.slice(0, j)), delta))
288
+ return j;
289
+ }
290
+ return 0;
291
+ }
292
+ /**
293
+ * Smallest `m` such that the range's last `m` deleted lines are all pure
294
+ * structural closers and sparing them (keeping instead of deleting) zeroes
295
+ * `delta`. The mirror mistake: a range that swallows a closing delimiter the
296
+ * payload never restates.
297
+ */
298
+ function findDroppedSuffixClosers(group, fileLines, delta) {
299
+ const wanted = balanceNegate(delta);
300
+ const maxM = group.deleteIndices.length;
301
+ for (let m = 1; m <= maxM; m++) {
302
+ if (!STRUCTURAL_CLOSER_RE.test(fileLines[group.endLine - m] ?? ""))
303
+ break;
304
+ if (balanceEqual(computeDelimiterBalance(fileLines.slice(group.endLine - m, group.endLine)), wanted))
305
+ return m;
306
+ }
307
+ return 0;
308
+ }
309
+ function hasNonWhitespace(text) {
310
+ for (let i = 0; i < text.length; i++) {
311
+ const code = text.charCodeAt(i);
312
+ if (code !== 9 && code !== 10 && code !== 11 && code !== 12 && code !== 13 && code !== 32)
313
+ return true;
314
+ }
315
+ return false;
316
+ }
317
+ function countDuplicateLeadingBoundaryLines(group, fileLines) {
318
+ const { payload, startLine } = group;
319
+ const max = Math.min(payload.length, startLine - 1);
320
+ for (let count = max; count >= 1; count--) {
321
+ let matches = true;
322
+ let hasContent = false;
323
+ for (let offset = 0; offset < count; offset++) {
324
+ const line = payload[offset];
325
+ if (line !== fileLines[startLine - 1 - count + offset]) {
326
+ matches = false;
327
+ break;
328
+ }
329
+ hasContent ||= hasNonWhitespace(line);
330
+ }
331
+ if (matches && hasContent)
332
+ return count;
333
+ }
334
+ return 0;
335
+ }
336
+ function countDuplicateTrailingBoundaryLines(group, fileLines) {
337
+ const { payload, endLine } = group;
338
+ const max = Math.min(payload.length, fileLines.length - endLine);
339
+ for (let count = max; count >= 1; count--) {
340
+ let matches = true;
341
+ let hasContent = false;
342
+ for (let offset = 0; offset < count; offset++) {
343
+ const line = payload[payload.length - count + offset];
344
+ if (line !== fileLines[endLine + offset]) {
345
+ matches = false;
346
+ break;
347
+ }
348
+ hasContent ||= hasNonWhitespace(line);
349
+ }
350
+ if (matches && hasContent)
351
+ return count;
352
+ }
353
+ return 0;
354
+ }
355
+ function findBoundaryEcho(group, fileLines) {
356
+ const leadingMax = countDuplicateLeadingBoundaryLines(group, fileLines);
357
+ if (leadingMax === 0)
358
+ return undefined;
359
+ const trailingMax = countDuplicateTrailingBoundaryLines(group, fileLines);
360
+ if (trailingMax === 0)
361
+ return undefined;
362
+ // Bail when every payload line could be claimed by a boundary echo: any
363
+ // repair would strip explicit replacement content with no signal that the
364
+ // payload was a mistake rather than an intentional duplication.
365
+ if (leadingMax + trailingMax >= group.payload.length)
366
+ return undefined;
367
+ // Balance-neutrality guard (see header comment): the dropped echo lines must
368
+ // either be delimiter-neutral on their own or exactly cancel the payload/range
369
+ // balance delta. In brace-heavy code where bare closer lines repeat, an
370
+ // "echo" that shifts delimiter balance is structural content the payload
371
+ // placed intentionally — stripping it would corrupt the result.
372
+ const leadingBalance = computeDelimiterBalance(group.payload.slice(0, leadingMax));
373
+ const trailingBalance = computeDelimiterBalance(group.payload.slice(group.payload.length - trailingMax));
374
+ const droppedBalance = balanceDelta(leadingBalance, balanceNegate(trailingBalance));
375
+ if (!balanceIsZero(droppedBalance)) {
376
+ const delta = balanceDelta(computeDelimiterBalance(group.payload), computeDelimiterBalance(fileLines.slice(group.startLine - 1, group.endLine)));
377
+ if (!balanceEqual(droppedBalance, delta))
378
+ return undefined;
379
+ }
380
+ return { leading: leadingMax, trailing: trailingMax };
381
+ }
382
+ function describeBoundaryEchoRepair(group, echo) {
383
+ return (`Auto-repaired a replacement boundary echo at line ${group.startLine}: ` +
384
+ `dropped ${echo.leading} leading and ${echo.trailing} trailing payload line(s) already present outside the range. ` +
385
+ `Issue the payload as the final desired content for the selected range only — never restate unchanged lines bordering the range.`);
386
+ }
387
+ function describeBoundaryRepair(group, action) {
388
+ return (`Auto-repaired a delimiter-balance mismatch in the replacement at line ${group.startLine}: ${action}. ` +
389
+ `Issue the payload as the final desired content only — never restate or omit a closing bracket bordering the range.`);
390
+ }
391
+ /**
392
+ * Normalize replacement groups so common off-by-one boundaries do not duplicate
393
+ * unchanged surrounding lines or structural closers. Returns the repaired edit
394
+ * list plus one warning per repaired group.
395
+ */
396
+ function repairReplacementBoundaries(edits, fileLines) {
397
+ const out = [];
398
+ const warnings = [];
399
+ let i = 0;
400
+ while (i < edits.length) {
401
+ const group = findReplacementGroup(edits, i);
402
+ if (!group) {
403
+ out.push(edits[i]);
404
+ i++;
405
+ continue;
406
+ }
407
+ const inserts = group.insertIndices.map(idx => edits[idx]);
408
+ const deletes = group.deleteIndices.map(idx => edits[idx]);
409
+ i = group.deleteIndices[group.deleteIndices.length - 1] + 1;
410
+ const boundaryEcho = findBoundaryEcho(group, fileLines);
411
+ if (boundaryEcho) {
412
+ warnings.push(describeBoundaryEchoRepair(group, boundaryEcho));
413
+ out.push(...inserts.slice(boundaryEcho.leading, inserts.length - boundaryEcho.trailing), ...deletes);
414
+ continue;
415
+ }
416
+ const delta = balanceDelta(computeDelimiterBalance(group.payload), computeDelimiterBalance(fileLines.slice(group.startLine - 1, group.endLine)));
417
+ if (balanceIsZero(delta)) {
418
+ out.push(...inserts, ...deletes);
419
+ continue;
420
+ }
421
+ const dupSuffix = findDuplicateSuffix(group, fileLines, delta);
422
+ if (dupSuffix > 0) {
423
+ warnings.push(describeBoundaryRepair(group, `dropped ${dupSuffix} duplicated trailing payload line(s) already present below the range`));
424
+ out.push(...inserts.slice(0, inserts.length - dupSuffix), ...deletes);
425
+ continue;
426
+ }
427
+ const dupPrefix = findDuplicatePrefix(group, fileLines, delta);
428
+ if (dupPrefix > 0) {
429
+ warnings.push(describeBoundaryRepair(group, `dropped ${dupPrefix} duplicated leading payload line(s) already present above the range`));
430
+ out.push(...inserts.slice(dupPrefix), ...deletes);
431
+ continue;
432
+ }
433
+ const droppedClosers = findDroppedSuffixClosers(group, fileLines, delta);
434
+ if (droppedClosers > 0) {
435
+ warnings.push(describeBoundaryRepair(group, `kept ${droppedClosers} structural closing line(s) the range deleted without restating`));
436
+ out.push(...inserts, ...deletes.slice(0, deletes.length - droppedClosers));
437
+ continue;
438
+ }
439
+ out.push(...inserts, ...deletes);
440
+ }
441
+ return { edits: out, warnings };
442
+ }
443
+ // ═══════════════════════════════════════════════════════════════════════════
444
+ // After-insert landing correction
445
+ //
446
+ // The body rows of an `insert after N:` hunk carry an implicit depth claim:
447
+ // their leading indentation says how deep the author expects the new lines
448
+ // to sit. Two corrections share that claim, in opposite directions:
449
+ //
450
+ // Outward (any after-insert): when the depth is shallower than line N itself,
451
+ // the hunk is inserting a sibling of some enclosing construct while anchored
452
+ // inside it — the common shape is anchoring on the last statement of a block
453
+ // and writing the body at the parent's depth. Sliding the landing point
454
+ // forward across the structural closer lines that follow (and nothing else —
455
+ // content lines are never crossed) places the body at the depth its
456
+ // indentation names.
457
+ //
458
+ // Inward (block-lowered inserts only): `insert after block N:` anchors on the
459
+ // resolved block's closing line, but a body indented deeper than that closer
460
+ // claims a depth inside the block — the common misreading of the op as
461
+ // "append at the end of block N's body". Sliding the landing point backward
462
+ // across the block's trailing closer lines places the body inside, at its
463
+ // claimed depth. Scoped to block-lowered inserts because there the author
464
+ // named the opener and never saw the closer; a plain `insert after M:` on a
465
+ // closer line stays literal (the escape hatch for genuinely-after content
466
+ // such as method-chain continuations).
467
+ //
468
+ // Both shifts are deliberately conservative: they fire only when the body
469
+ // and anchor indentation are comparable (one is a prefix of the other),
470
+ // cross only pure closing-delimiter lines, stop as soon as depth matches the
471
+ // body's claim, and are abandoned when any other edit in the patch targets a
472
+ // crossed line. Every shift is reported as a warning so the author can
473
+ // re-issue when the original landing was intended.
474
+ /** Leading run of tabs and spaces. */
475
+ function leadingIndent(line) {
476
+ let end = 0;
477
+ while (end < line.length) {
478
+ const code = line.charCodeAt(end);
479
+ if (code !== 9 && code !== 32)
480
+ break;
481
+ end++;
482
+ }
483
+ return line.slice(0, end);
484
+ }
485
+ /** `deeper` strictly extends `shallower` (same indent style, more depth). */
486
+ function isIndentDeeper(deeper, shallower) {
487
+ return deeper.length > shallower.length && deeper.startsWith(shallower);
488
+ }
489
+ /**
490
+ * Depth of an after-insert hunk's body: the shallowest indentation across its
491
+ * non-blank rows. Returns `undefined` when no depth claim can be made — an
492
+ * all-blank or all-closer body, or rows whose indentation styles are not
493
+ * mutually comparable (tabs vs spaces).
494
+ */
495
+ function bodyTargetIndent(rows) {
496
+ const nonBlank = rows.filter(hasNonWhitespace);
497
+ if (nonBlank.length === 0)
498
+ return undefined;
499
+ // A body of pure closers re-balances delimiters; it claims no depth.
500
+ if (nonBlank.every(row => STRUCTURAL_CLOSER_RE.test(row)))
501
+ return undefined;
502
+ let target = leadingIndent(nonBlank[0] ?? "");
503
+ for (const row of nonBlank) {
504
+ const indent = leadingIndent(row);
505
+ if (indent.startsWith(target))
506
+ continue;
507
+ if (target.startsWith(indent))
508
+ target = indent;
509
+ else
510
+ return undefined;
511
+ }
512
+ return target;
513
+ }
514
+ /**
515
+ * Resolve where an after-insert hunk anchored on `group.anchor` should land
516
+ * given its body depth `target`: the last structural closer line in the run
517
+ * directly below the anchor whose indentation still covers `target`. Returns
518
+ * `undefined` when the landing stays put.
519
+ */
520
+ function resolveShiftedLanding(group, target, fileLines, targetedLines) {
521
+ const anchorText = fileLines[group.anchor - 1];
522
+ if (anchorText === undefined || !hasNonWhitespace(anchorText))
523
+ return undefined;
524
+ if (!isIndentDeeper(leadingIndent(anchorText), target))
525
+ return undefined;
526
+ let landing = group.anchor;
527
+ let crossed = 0;
528
+ for (let line = group.anchor + 1; line <= fileLines.length; line++) {
529
+ const text = fileLines[line - 1] ?? "";
530
+ if (!hasNonWhitespace(text))
531
+ continue; // look past blanks, never land on them
532
+ if (!STRUCTURAL_CLOSER_RE.test(text))
533
+ break; // content is never crossed
534
+ const indent = leadingIndent(text);
535
+ if (!indent.startsWith(target))
536
+ break; // shallower than the body — crossing would over-escape
537
+ if (targetedLines.has(line))
538
+ return undefined; // another hunk owns this closer
539
+ landing = line;
540
+ crossed++;
541
+ if (indent.length === target.length)
542
+ break; // depth returned to the body's level
543
+ }
544
+ return landing === group.anchor ? undefined : { line: landing, crossed };
545
+ }
546
+ /**
547
+ * Resolve where a block-lowered after-insert anchored on the block's closing
548
+ * line should land given a body depth `target` deeper than that closer: just
549
+ * above the block's trailing run of closer lines, bounded below by
550
+ * `blockStart` (an empty block lands the body right after its opener).
551
+ * Returns `undefined` when the landing stays put.
552
+ */
553
+ function resolveInwardLanding(group, target, blockStart, fileLines, targetedLines) {
554
+ const anchorText = fileLines[group.anchor - 1];
555
+ if (anchorText === undefined || !hasNonWhitespace(anchorText))
556
+ return undefined;
557
+ // Fires only when the block ends in a pure closer the body out-indents.
558
+ // Blocks ending in content (indentation-only languages) already land the
559
+ // body inside the block — nothing to correct.
560
+ if (!STRUCTURAL_CLOSER_RE.test(anchorText))
561
+ return undefined;
562
+ if (!isIndentDeeper(target, leadingIndent(anchorText)))
563
+ return undefined;
564
+ let landing = group.anchor;
565
+ for (let line = group.anchor; line > blockStart; line--) {
566
+ const text = fileLines[line - 1] ?? "";
567
+ if (!hasNonWhitespace(text)) {
568
+ landing = line - 1; // look past trailing blanks, never land after one
569
+ continue;
570
+ }
571
+ if (!STRUCTURAL_CLOSER_RE.test(text))
572
+ break; // content reached — land right after it
573
+ const indent = leadingIndent(text);
574
+ if (!isIndentDeeper(target, indent))
575
+ break; // closer at the body's depth — land after it
576
+ // Another hunk owns this closer (the group's own rows put the anchor
577
+ // itself in `targetedLines`; that one is ours to cross).
578
+ if (line !== group.anchor && targetedLines.has(line))
579
+ return undefined;
580
+ landing = line - 1;
581
+ }
582
+ return landing === group.anchor ? undefined : landing;
583
+ }
584
+ /**
585
+ * Slide mis-anchored after-insert hunks to the depth their body indentation
586
+ * claims: outward past the structural closer lines that follow the anchor
587
+ * when the body is shallower, or — for `insert after block N:` lowerings —
588
+ * inward across the block's trailing closers when the body is deeper than
589
+ * the block's closing line. Returns the corrected edit list plus one warning
590
+ * per shifted hunk.
591
+ */
592
+ function repairAfterInsertLandings(edits, fileLines) {
593
+ // Group plain (non-replacement) after-anchor inserts per authored hunk:
594
+ // rows of one hunk share the anchor line and the patch header line.
595
+ const groups = new Map();
596
+ edits.forEach((edit, idx) => {
597
+ if (edit.kind !== "insert" || edit.mode === "replacement")
598
+ return;
599
+ if (edit.cursor.kind !== "after_anchor")
600
+ return;
601
+ const key = `${edit.cursor.anchor.line}:${edit.lineNum}`;
602
+ const group = groups.get(key);
603
+ if (group === undefined)
604
+ groups.set(key, { anchor: edit.cursor.anchor.line, members: [idx], blockStart: edit.blockStart });
605
+ else
606
+ group.members.push(idx);
607
+ });
608
+ if (groups.size === 0)
609
+ return { edits, warnings: [] };
610
+ // Lines explicitly targeted by any edit; a shift never crosses them.
611
+ const targetedLines = new Set();
612
+ for (const edit of edits) {
613
+ if (edit.kind === "delete")
614
+ targetedLines.add(edit.anchor.line);
615
+ else if (edit.cursor.kind === "before_anchor" || edit.cursor.kind === "after_anchor")
616
+ targetedLines.add(edit.cursor.anchor.line);
617
+ }
618
+ let out;
619
+ const warnings = [];
620
+ const retarget = (group, line) => {
621
+ out ??= [...edits];
622
+ for (const idx of group.members) {
623
+ const edit = out[idx];
624
+ out[idx] = { ...edit, cursor: { kind: "after_anchor", anchor: { line } } };
625
+ }
626
+ };
627
+ for (const group of groups.values()) {
628
+ const target = bodyTargetIndent(group.members.map(idx => edits[idx].text));
629
+ if (target === undefined)
630
+ continue;
631
+ const outward = resolveShiftedLanding(group, target, fileLines, targetedLines);
632
+ if (outward !== undefined) {
633
+ retarget(group, outward.line);
634
+ warnings.push(afterInsertLandingShiftWarning(group.anchor, outward.line, outward.crossed));
635
+ continue;
636
+ }
637
+ if (group.blockStart === undefined)
638
+ continue;
639
+ const inward = resolveInwardLanding(group, target, group.blockStart, fileLines, targetedLines);
640
+ if (inward === undefined)
641
+ continue;
642
+ retarget(group, inward);
643
+ warnings.push(blockInsertLandingShiftWarning(group.blockStart, group.anchor, inward));
644
+ }
645
+ return { edits: out ?? edits, warnings };
646
+ }
647
+ /**
648
+ * Apply a parsed list of edits to a text body. Pure function — no I/O.
649
+ *
650
+ * Returns the post-edit text and the first changed line number (1-indexed).
651
+ * Throws if an anchor is out of bounds.
652
+ */
653
+ export function applyEdits(text, edits) {
654
+ if (edits.length === 0)
655
+ return { text, firstChangedLine: undefined };
656
+ // Block edits are deferred until `resolveBlockEdits` expands them into
657
+ // concrete inserts + deletes. Reaching the applier with one still present
658
+ // is an internal wiring bug, not authored-input error.
659
+ for (const edit of edits) {
660
+ if (edit.kind === "block")
661
+ throw new Error(UNRESOLVED_BLOCK_INTERNAL);
662
+ }
663
+ const appliedEdits = edits;
664
+ const fileLines = text.split("\n");
665
+ const lineOrigins = fileLines.map(() => "original");
666
+ let firstChangedLine;
667
+ const trackFirstChanged = (line) => {
668
+ if (firstChangedLine === undefined || line < firstChangedLine)
669
+ firstChangedLine = line;
670
+ };
671
+ const targetEdits = dropTrailingPhantomDeletes(appliedEdits.map((edit, index) => cloneAppliedEdit(edit, index)), fileLines);
672
+ validateLineBounds(targetEdits, fileLines);
673
+ const { edits: repaired, warnings: boundaryWarnings } = repairReplacementBoundaries(targetEdits, fileLines);
674
+ const { edits: landed, warnings: landingWarnings } = repairAfterInsertLandings(repaired, fileLines);
675
+ const warnings = [...boundaryWarnings, ...landingWarnings];
676
+ // Partition edits into bof, eof, and anchor-targeted buckets.
677
+ const bofLines = [];
678
+ const eofLines = [];
679
+ const anchorEdits = [];
680
+ landed.forEach((edit, idx) => {
681
+ if (edit.kind === "insert" && edit.cursor.kind === "bof") {
682
+ bofLines.push(edit.text);
683
+ }
684
+ else if (edit.kind === "insert" && edit.cursor.kind === "eof") {
685
+ eofLines.push(edit.text);
686
+ }
687
+ else {
688
+ anchorEdits.push({ edit, idx });
689
+ }
690
+ });
691
+ // Apply per-line buckets bottom-up so earlier indices stay valid.
692
+ const byLine = bucketAnchorEditsByLine(anchorEdits);
693
+ for (const line of [...byLine.keys()].sort((a, b) => b - a)) {
694
+ const bucket = byLine.get(line);
695
+ if (!bucket)
696
+ continue;
697
+ bucket.sort((a, b) => a.idx - b.idx);
698
+ const idx = line - 1;
699
+ const currentLine = fileLines[idx] ?? "";
700
+ const beforeInsertLines = [];
701
+ const afterInsertLines = [];
702
+ const replacementLines = [];
703
+ let deleteLine = false;
704
+ for (const { edit } of bucket) {
705
+ if (isReplacementInsert(edit)) {
706
+ replacementLines.push(edit.text);
707
+ }
708
+ else if (edit.kind === "insert" && edit.cursor.kind === "after_anchor") {
709
+ afterInsertLines.push(edit.text);
710
+ }
711
+ else if (edit.kind === "insert") {
712
+ beforeInsertLines.push(edit.text);
713
+ }
714
+ else if (edit.kind === "delete") {
715
+ deleteLine = true;
716
+ }
717
+ }
718
+ if (beforeInsertLines.length === 0 &&
719
+ replacementLines.length === 0 &&
720
+ afterInsertLines.length === 0 &&
721
+ !deleteLine)
722
+ continue;
723
+ const replacement = deleteLine
724
+ ? [...beforeInsertLines, ...replacementLines, ...afterInsertLines]
725
+ : [...beforeInsertLines, ...replacementLines, currentLine, ...afterInsertLines];
726
+ const origins = [];
727
+ for (let i = 0; i < beforeInsertLines.length; i++)
728
+ origins.push("insert");
729
+ for (let i = 0; i < replacementLines.length; i++)
730
+ origins.push(deleteLine ? "replacement" : "insert");
731
+ if (!deleteLine)
732
+ origins.push(lineOrigins[idx] ?? "original");
733
+ for (let i = 0; i < afterInsertLines.length; i++)
734
+ origins.push("insert");
735
+ fileLines.splice(idx, 1, ...replacement);
736
+ lineOrigins.splice(idx, 1, ...origins);
737
+ trackFirstChanged(line);
738
+ }
739
+ if (bofLines.length > 0) {
740
+ insertAtStart(fileLines, lineOrigins, bofLines);
741
+ trackFirstChanged(1);
742
+ }
743
+ const eofChangedLine = insertAtEnd(fileLines, lineOrigins, eofLines);
744
+ if (eofChangedLine !== undefined)
745
+ trackFirstChanged(eofChangedLine);
746
+ return {
747
+ text: fileLines.join("\n"),
748
+ firstChangedLine,
749
+ ...(warnings.length > 0 ? { warnings } : {}),
750
+ };
751
+ }
752
+ //# sourceMappingURL=apply.js.map