mindweave 0.0.1 → 2.1.2

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 (481) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +171 -14
  3. package/dist/alternator/chassis/cache.js +47 -0
  4. package/dist/alternator/chassis/cache.js.map +1 -0
  5. package/dist/alternator/chassis/domRefs.js +53 -0
  6. package/dist/alternator/chassis/domRefs.js.map +1 -0
  7. package/dist/alternator/chassis/extractWorker.js +65 -0
  8. package/dist/alternator/chassis/extractWorker.js.map +1 -0
  9. package/dist/alternator/chassis/graph.js +221 -0
  10. package/dist/alternator/chassis/graph.js.map +1 -0
  11. package/dist/alternator/chassis/index.js +463 -0
  12. package/dist/alternator/chassis/index.js.map +1 -0
  13. package/dist/alternator/chassis/isolation.js +336 -0
  14. package/dist/alternator/chassis/isolation.js.map +1 -0
  15. package/dist/alternator/chassis/langCases.js +69 -0
  16. package/dist/alternator/chassis/langCases.js.map +1 -0
  17. package/dist/alternator/chassis/lsp.js +469 -0
  18. package/dist/alternator/chassis/lsp.js.map +1 -0
  19. package/dist/alternator/chassis/markup.js +262 -0
  20. package/dist/alternator/chassis/markup.js.map +1 -0
  21. package/dist/alternator/chassis/provision.js +198 -0
  22. package/dist/alternator/chassis/provision.js.map +1 -0
  23. package/dist/alternator/chassis/rank.js +72 -0
  24. package/dist/alternator/chassis/rank.js.map +1 -0
  25. package/dist/alternator/chassis/servers.js +215 -0
  26. package/dist/alternator/chassis/servers.js.map +1 -0
  27. package/dist/alternator/chassis/treesitter.js +608 -0
  28. package/dist/alternator/chassis/treesitter.js.map +1 -0
  29. package/dist/alternator/chassis/types.js +24 -0
  30. package/dist/alternator/chassis/types.js.map +1 -0
  31. package/dist/alternator/lane.js +67 -0
  32. package/dist/alternator/lane.js.map +1 -0
  33. package/dist/cli/App.js +2586 -0
  34. package/dist/cli/App.js.map +1 -0
  35. package/dist/cli/altScreen.js +67 -0
  36. package/dist/cli/altScreen.js.map +1 -0
  37. package/dist/cli/approvalChannel.js +72 -0
  38. package/dist/cli/approvalChannel.js.map +1 -0
  39. package/dist/cli/attachments.js +188 -0
  40. package/dist/cli/attachments.js.map +1 -0
  41. package/dist/cli/bootstrap.js +279 -0
  42. package/dist/cli/bootstrap.js.map +1 -0
  43. package/dist/cli/chatAnchor.js +94 -0
  44. package/dist/cli/chatAnchor.js.map +1 -0
  45. package/dist/cli/commandArgs.js +79 -0
  46. package/dist/cli/commandArgs.js.map +1 -0
  47. package/dist/cli/commandRoute.js +78 -0
  48. package/dist/cli/commandRoute.js.map +1 -0
  49. package/dist/cli/compaction.js +69 -0
  50. package/dist/cli/compaction.js.map +1 -0
  51. package/dist/cli/components/ApprovalBox.js +100 -0
  52. package/dist/cli/components/ApprovalBox.js.map +1 -0
  53. package/dist/cli/components/BlockView.js +128 -0
  54. package/dist/cli/components/BlockView.js.map +1 -0
  55. package/dist/cli/components/FirstRunFrame.js +41 -0
  56. package/dist/cli/components/FirstRunFrame.js.map +1 -0
  57. package/dist/cli/components/KeyManager.js +197 -0
  58. package/dist/cli/components/KeyManager.js.map +1 -0
  59. package/dist/cli/components/KeySetup.js +125 -0
  60. package/dist/cli/components/KeySetup.js.map +1 -0
  61. package/dist/cli/components/MenuFrame.js +24 -0
  62. package/dist/cli/components/MenuFrame.js.map +1 -0
  63. package/dist/cli/components/Picker.js +82 -0
  64. package/dist/cli/components/Picker.js.map +1 -0
  65. package/dist/cli/components/PromptInput.js +509 -0
  66. package/dist/cli/components/PromptInput.js.map +1 -0
  67. package/dist/cli/components/SubagentView.js +86 -0
  68. package/dist/cli/components/SubagentView.js.map +1 -0
  69. package/dist/cli/components/ToolGroup.js +60 -0
  70. package/dist/cli/components/ToolGroup.js.map +1 -0
  71. package/dist/cli/components/ToolLine.js +123 -0
  72. package/dist/cli/components/ToolLine.js.map +1 -0
  73. package/dist/cli/components/TrustGate.js +37 -0
  74. package/dist/cli/components/TrustGate.js.map +1 -0
  75. package/dist/cli/costView.js +40 -0
  76. package/dist/cli/costView.js.map +1 -0
  77. package/dist/cli/frameRate.js +30 -0
  78. package/dist/cli/frameRate.js.map +1 -0
  79. package/dist/cli/framebuffer/paint.js +165 -0
  80. package/dist/cli/framebuffer/paint.js.map +1 -0
  81. package/dist/cli/framebuffer/parse.js +266 -0
  82. package/dist/cli/framebuffer/parse.js.map +1 -0
  83. package/dist/cli/framebuffer/screen.js +196 -0
  84. package/dist/cli/framebuffer/screen.js.map +1 -0
  85. package/dist/cli/framebuffer/writer.js +139 -0
  86. package/dist/cli/framebuffer/writer.js.map +1 -0
  87. package/dist/cli/groupReveal.js +51 -0
  88. package/dist/cli/groupReveal.js.map +1 -0
  89. package/dist/cli/help.js +55 -0
  90. package/dist/cli/help.js.map +1 -0
  91. package/dist/cli/inputView.js +105 -0
  92. package/dist/cli/inputView.js.map +1 -0
  93. package/dist/cli/keyManager.js +65 -0
  94. package/dist/cli/keyManager.js.map +1 -0
  95. package/dist/cli/keySetup.js +35 -0
  96. package/dist/cli/keySetup.js.map +1 -0
  97. package/dist/cli/keyStore.js +73 -0
  98. package/dist/cli/keyStore.js.map +1 -0
  99. package/dist/cli/markdown.js +460 -0
  100. package/dist/cli/markdown.js.map +1 -0
  101. package/dist/cli/messageQueue.js +96 -0
  102. package/dist/cli/messageQueue.js.map +1 -0
  103. package/dist/cli/modes.js +90 -0
  104. package/dist/cli/modes.js.map +1 -0
  105. package/dist/cli/mouse.js +78 -0
  106. package/dist/cli/mouse.js.map +1 -0
  107. package/dist/cli/pasteAssembler.js +44 -0
  108. package/dist/cli/pasteAssembler.js.map +1 -0
  109. package/dist/cli/pathComplete.js +39 -0
  110. package/dist/cli/pathComplete.js.map +1 -0
  111. package/dist/cli/perfLog.js +90 -0
  112. package/dist/cli/perfLog.js.map +1 -0
  113. package/dist/cli/reveal.js +32 -0
  114. package/dist/cli/reveal.js.map +1 -0
  115. package/dist/cli/revealPace.js +59 -0
  116. package/dist/cli/revealPace.js.map +1 -0
  117. package/dist/cli/sessionCarry.js +19 -0
  118. package/dist/cli/sessionCarry.js.map +1 -0
  119. package/dist/cli/smoothScroll.js +74 -0
  120. package/dist/cli/smoothScroll.js.map +1 -0
  121. package/dist/cli/startupArgs.js +96 -0
  122. package/dist/cli/startupArgs.js.map +1 -0
  123. package/dist/cli/terminalRestore.js +34 -0
  124. package/dist/cli/terminalRestore.js.map +1 -0
  125. package/dist/cli/toolDisplay.js +219 -0
  126. package/dist/cli/toolDisplay.js.map +1 -0
  127. package/dist/cli/toolItems.js +65 -0
  128. package/dist/cli/toolItems.js.map +1 -0
  129. package/dist/cli/transcript.js +351 -0
  130. package/dist/cli/transcript.js.map +1 -0
  131. package/dist/cli/trust.js +79 -0
  132. package/dist/cli/trust.js.map +1 -0
  133. package/dist/cli/updateCheck.js +107 -0
  134. package/dist/cli/updateCheck.js.map +1 -0
  135. package/dist/cli/version.js +39 -0
  136. package/dist/cli/version.js.map +1 -0
  137. package/dist/cli/viewport.js +179 -0
  138. package/dist/cli/viewport.js.map +1 -0
  139. package/dist/cli/virtualWindow.js +103 -0
  140. package/dist/cli/virtualWindow.js.map +1 -0
  141. package/dist/cli/workingVerb.js +37 -0
  142. package/dist/cli/workingVerb.js.map +1 -0
  143. package/dist/cli/wrap.js +145 -0
  144. package/dist/cli/wrap.js.map +1 -0
  145. package/dist/drivers/anthropic/cachePoints.js +77 -0
  146. package/dist/drivers/anthropic/cachePoints.js.map +1 -0
  147. package/dist/drivers/anthropic/client.js +432 -0
  148. package/dist/drivers/anthropic/client.js.map +1 -0
  149. package/dist/drivers/anthropic/index.js +10 -0
  150. package/dist/drivers/anthropic/index.js.map +1 -0
  151. package/dist/drivers/anthropic/manifest.js +221 -0
  152. package/dist/drivers/anthropic/manifest.js.map +1 -0
  153. package/dist/drivers/cerebras/client.js +69 -0
  154. package/dist/drivers/cerebras/client.js.map +1 -0
  155. package/dist/drivers/cerebras/index.js +5 -0
  156. package/dist/drivers/cerebras/index.js.map +1 -0
  157. package/dist/drivers/cerebras/manifest.js +140 -0
  158. package/dist/drivers/cerebras/manifest.js.map +1 -0
  159. package/dist/drivers/clientId.js +41 -0
  160. package/dist/drivers/clientId.js.map +1 -0
  161. package/dist/drivers/contextOverflow.js +77 -0
  162. package/dist/drivers/contextOverflow.js.map +1 -0
  163. package/dist/drivers/deepseek/client.js +168 -0
  164. package/dist/drivers/deepseek/client.js.map +1 -0
  165. package/dist/drivers/deepseek/index.js +16 -0
  166. package/dist/drivers/deepseek/index.js.map +1 -0
  167. package/dist/drivers/deepseek/inlineTools.js +46 -0
  168. package/dist/drivers/deepseek/inlineTools.js.map +1 -0
  169. package/dist/drivers/deepseek/manifest.js +166 -0
  170. package/dist/drivers/deepseek/manifest.js.map +1 -0
  171. package/dist/drivers/gemini/client.js +38 -0
  172. package/dist/drivers/gemini/client.js.map +1 -0
  173. package/dist/drivers/gemini/index.js +5 -0
  174. package/dist/drivers/gemini/index.js.map +1 -0
  175. package/dist/drivers/gemini/manifest.js +150 -0
  176. package/dist/drivers/gemini/manifest.js.map +1 -0
  177. package/dist/drivers/glm/client.js +90 -0
  178. package/dist/drivers/glm/client.js.map +1 -0
  179. package/dist/drivers/glm/index.js +9 -0
  180. package/dist/drivers/glm/index.js.map +1 -0
  181. package/dist/drivers/glm/manifest.js +183 -0
  182. package/dist/drivers/glm/manifest.js.map +1 -0
  183. package/dist/drivers/groq/client.js +80 -0
  184. package/dist/drivers/groq/client.js.map +1 -0
  185. package/dist/drivers/groq/index.js +5 -0
  186. package/dist/drivers/groq/index.js.map +1 -0
  187. package/dist/drivers/groq/manifest.js +160 -0
  188. package/dist/drivers/groq/manifest.js.map +1 -0
  189. package/dist/drivers/kimi/client.js +82 -0
  190. package/dist/drivers/kimi/client.js.map +1 -0
  191. package/dist/drivers/kimi/index.js +9 -0
  192. package/dist/drivers/kimi/index.js.map +1 -0
  193. package/dist/drivers/kimi/manifest.js +168 -0
  194. package/dist/drivers/kimi/manifest.js.map +1 -0
  195. package/dist/drivers/meta/client.js +30 -0
  196. package/dist/drivers/meta/client.js.map +1 -0
  197. package/dist/drivers/meta/index.js +5 -0
  198. package/dist/drivers/meta/index.js.map +1 -0
  199. package/dist/drivers/meta/manifest.js +101 -0
  200. package/dist/drivers/meta/manifest.js.map +1 -0
  201. package/dist/drivers/minimax/client.js +36 -0
  202. package/dist/drivers/minimax/client.js.map +1 -0
  203. package/dist/drivers/minimax/index.js +5 -0
  204. package/dist/drivers/minimax/index.js.map +1 -0
  205. package/dist/drivers/minimax/manifest.js +120 -0
  206. package/dist/drivers/minimax/manifest.js.map +1 -0
  207. package/dist/drivers/mistral/client.js +54 -0
  208. package/dist/drivers/mistral/client.js.map +1 -0
  209. package/dist/drivers/mistral/index.js +5 -0
  210. package/dist/drivers/mistral/index.js.map +1 -0
  211. package/dist/drivers/mistral/manifest.js +118 -0
  212. package/dist/drivers/mistral/manifest.js.map +1 -0
  213. package/dist/drivers/openai/client.js +290 -0
  214. package/dist/drivers/openai/client.js.map +1 -0
  215. package/dist/drivers/openai/index.js +9 -0
  216. package/dist/drivers/openai/index.js.map +1 -0
  217. package/dist/drivers/openai/manifest.js +133 -0
  218. package/dist/drivers/openai/manifest.js.map +1 -0
  219. package/dist/drivers/openaiCompat/wire.js +493 -0
  220. package/dist/drivers/openaiCompat/wire.js.map +1 -0
  221. package/dist/drivers/partialTurn.js +23 -0
  222. package/dist/drivers/partialTurn.js.map +1 -0
  223. package/dist/drivers/providerError.js +181 -0
  224. package/dist/drivers/providerError.js.map +1 -0
  225. package/dist/drivers/qwen/client.js +93 -0
  226. package/dist/drivers/qwen/client.js.map +1 -0
  227. package/dist/drivers/qwen/index.js +9 -0
  228. package/dist/drivers/qwen/index.js.map +1 -0
  229. package/dist/drivers/qwen/manifest.js +146 -0
  230. package/dist/drivers/qwen/manifest.js.map +1 -0
  231. package/dist/drivers/registry.js +177 -0
  232. package/dist/drivers/registry.js.map +1 -0
  233. package/dist/drivers/retryPolicy.js +129 -0
  234. package/dist/drivers/retryPolicy.js.map +1 -0
  235. package/dist/drivers/searchBlocks.js +61 -0
  236. package/dist/drivers/searchBlocks.js.map +1 -0
  237. package/dist/drivers/types.js +2 -0
  238. package/dist/drivers/types.js.map +1 -0
  239. package/dist/drivers/xai/client.js +63 -0
  240. package/dist/drivers/xai/client.js.map +1 -0
  241. package/dist/drivers/xai/index.js +5 -0
  242. package/dist/drivers/xai/index.js.map +1 -0
  243. package/dist/drivers/xai/manifest.js +137 -0
  244. package/dist/drivers/xai/manifest.js.map +1 -0
  245. package/dist/dynamo/_probe.tmp.js +20 -0
  246. package/dist/dynamo/_probe.tmp.js.map +1 -0
  247. package/dist/dynamo/cacheBreak.js +88 -0
  248. package/dist/dynamo/cacheBreak.js.map +1 -0
  249. package/dist/dynamo/contextWindow.js +243 -0
  250. package/dist/dynamo/contextWindow.js.map +1 -0
  251. package/dist/dynamo/engine.js +2011 -0
  252. package/dist/dynamo/engine.js.map +1 -0
  253. package/dist/dynamo/guard.js +132 -0
  254. package/dist/dynamo/guard.js.map +1 -0
  255. package/dist/dynamo/liveMeter.js +58 -0
  256. package/dist/dynamo/liveMeter.js.map +1 -0
  257. package/dist/dynamo/model.js +172 -0
  258. package/dist/dynamo/model.js.map +1 -0
  259. package/dist/dynamo/planArtifact.js +125 -0
  260. package/dist/dynamo/planArtifact.js.map +1 -0
  261. package/dist/dynamo/pricing.js +140 -0
  262. package/dist/dynamo/pricing.js.map +1 -0
  263. package/dist/dynamo/prompt.js +264 -0
  264. package/dist/dynamo/prompt.js.map +1 -0
  265. package/dist/dynamo/spend.js +45 -0
  266. package/dist/dynamo/spend.js.map +1 -0
  267. package/dist/dynamo/verify.js +483 -0
  268. package/dist/dynamo/verify.js.map +1 -0
  269. package/dist/governor/forbidden.js +181 -0
  270. package/dist/governor/forbidden.js.map +1 -0
  271. package/dist/governor/freshness.js +83 -0
  272. package/dist/governor/freshness.js.map +1 -0
  273. package/dist/governor/frontmatter.js +38 -0
  274. package/dist/governor/frontmatter.js.map +1 -0
  275. package/dist/governor/glob.js +75 -0
  276. package/dist/governor/glob.js.map +1 -0
  277. package/dist/governor/index.js +87 -0
  278. package/dist/governor/index.js.map +1 -0
  279. package/dist/governor/rules.js +80 -0
  280. package/dist/governor/rules.js.map +1 -0
  281. package/dist/governor/scope.js +91 -0
  282. package/dist/governor/scope.js.map +1 -0
  283. package/dist/governor/skills.js +176 -0
  284. package/dist/governor/skills.js.map +1 -0
  285. package/dist/governor/types.js +16 -0
  286. package/dist/governor/types.js.map +1 -0
  287. package/dist/governor/write.js +182 -0
  288. package/dist/governor/write.js.map +1 -0
  289. package/dist/index.js +89 -0
  290. package/dist/index.js.map +1 -0
  291. package/dist/mcp/catalog.js +232 -0
  292. package/dist/mcp/catalog.js.map +1 -0
  293. package/dist/mcp/config.js +116 -0
  294. package/dist/mcp/config.js.map +1 -0
  295. package/dist/mcp/configWrite.js +254 -0
  296. package/dist/mcp/configWrite.js.map +1 -0
  297. package/dist/mcp/connection.js +504 -0
  298. package/dist/mcp/connection.js.map +1 -0
  299. package/dist/mcp/deferred.js +104 -0
  300. package/dist/mcp/deferred.js.map +1 -0
  301. package/dist/mcp/discover.js +128 -0
  302. package/dist/mcp/discover.js.map +1 -0
  303. package/dist/mcp/manager.js +679 -0
  304. package/dist/mcp/manager.js.map +1 -0
  305. package/dist/mcp/paramHeaders.js +163 -0
  306. package/dist/mcp/paramHeaders.js.map +1 -0
  307. package/dist/mcp/prompts.js +136 -0
  308. package/dist/mcp/prompts.js.map +1 -0
  309. package/dist/mcp/protocol.js +171 -0
  310. package/dist/mcp/protocol.js.map +1 -0
  311. package/dist/mcp/resources.js +119 -0
  312. package/dist/mcp/resources.js.map +1 -0
  313. package/dist/mcp/resultStore.js +180 -0
  314. package/dist/mcp/resultStore.js.map +1 -0
  315. package/dist/mcp/subscriptions.js +74 -0
  316. package/dist/mcp/subscriptions.js.map +1 -0
  317. package/dist/mcp/transport/headerValue.js +40 -0
  318. package/dist/mcp/transport/headerValue.js.map +1 -0
  319. package/dist/mcp/transport/http.js +321 -0
  320. package/dist/mcp/transport/http.js.map +1 -0
  321. package/dist/mcp/transport/stdio.js +234 -0
  322. package/dist/mcp/transport/stdio.js.map +1 -0
  323. package/dist/mcp/transport/types.js +27 -0
  324. package/dist/mcp/transport/types.js.map +1 -0
  325. package/dist/mcp/trust.js +98 -0
  326. package/dist/mcp/trust.js.map +1 -0
  327. package/dist/mcp/trustStore.js +55 -0
  328. package/dist/mcp/trustStore.js.map +1 -0
  329. package/dist/memory/autoMemory.js +340 -0
  330. package/dist/memory/autoMemory.js.map +1 -0
  331. package/dist/memory/compaction.js +513 -0
  332. package/dist/memory/compaction.js.map +1 -0
  333. package/dist/memory/images.js +173 -0
  334. package/dist/memory/images.js.map +1 -0
  335. package/dist/memory/presence.js +59 -0
  336. package/dist/memory/presence.js.map +1 -0
  337. package/dist/memory/projectNotes.js +247 -0
  338. package/dist/memory/projectNotes.js.map +1 -0
  339. package/dist/memory/restore.js +72 -0
  340. package/dist/memory/restore.js.map +1 -0
  341. package/dist/memory/session.js +472 -0
  342. package/dist/memory/session.js.map +1 -0
  343. package/dist/memory/sessionMemory.js +142 -0
  344. package/dist/memory/sessionMemory.js.map +1 -0
  345. package/dist/memory/sessionMemoryCompact.js +136 -0
  346. package/dist/memory/sessionMemoryCompact.js.map +1 -0
  347. package/dist/memory/store.js +217 -0
  348. package/dist/memory/store.js.map +1 -0
  349. package/dist/memory/types.js +14 -0
  350. package/dist/memory/types.js.map +1 -0
  351. package/dist/memory/workingSet.js +383 -0
  352. package/dist/memory/workingSet.js.map +1 -0
  353. package/dist/project/context.js +425 -0
  354. package/dist/project/context.js.map +1 -0
  355. package/dist/tools/approval.js +189 -0
  356. package/dist/tools/approval.js.map +1 -0
  357. package/dist/tools/askUser.js +103 -0
  358. package/dist/tools/askUser.js.map +1 -0
  359. package/dist/tools/atomicWrite.js +151 -0
  360. package/dist/tools/atomicWrite.js.map +1 -0
  361. package/dist/tools/backgroundShells.js +468 -0
  362. package/dist/tools/backgroundShells.js.map +1 -0
  363. package/dist/tools/captureSweep.js +77 -0
  364. package/dist/tools/captureSweep.js.map +1 -0
  365. package/dist/tools/chassisMux.js +92 -0
  366. package/dist/tools/chassisMux.js.map +1 -0
  367. package/dist/tools/checkpoints.js +328 -0
  368. package/dist/tools/checkpoints.js.map +1 -0
  369. package/dist/tools/codeIntel.js +267 -0
  370. package/dist/tools/codeIntel.js.map +1 -0
  371. package/dist/tools/deferredNative.js +121 -0
  372. package/dist/tools/deferredNative.js.map +1 -0
  373. package/dist/tools/detail.js +135 -0
  374. package/dist/tools/detail.js.map +1 -0
  375. package/dist/tools/diagnostics.js +174 -0
  376. package/dist/tools/diagnostics.js.map +1 -0
  377. package/dist/tools/edit.js +167 -0
  378. package/dist/tools/edit.js.map +1 -0
  379. package/dist/tools/editCore.js +283 -0
  380. package/dist/tools/editCore.js.map +1 -0
  381. package/dist/tools/editFile.js +183 -0
  382. package/dist/tools/editFile.js.map +1 -0
  383. package/dist/tools/editRipple.js +126 -0
  384. package/dist/tools/editRipple.js.map +1 -0
  385. package/dist/tools/editTarget.js +131 -0
  386. package/dist/tools/editTarget.js.map +1 -0
  387. package/dist/tools/editWindow.js +49 -0
  388. package/dist/tools/editWindow.js.map +1 -0
  389. package/dist/tools/eol.js +56 -0
  390. package/dist/tools/eol.js.map +1 -0
  391. package/dist/tools/exitPlan.js +175 -0
  392. package/dist/tools/exitPlan.js.map +1 -0
  393. package/dist/tools/focus.js +42 -0
  394. package/dist/tools/focus.js.map +1 -0
  395. package/dist/tools/gitignore.js +148 -0
  396. package/dist/tools/gitignore.js.map +1 -0
  397. package/dist/tools/glob.js +134 -0
  398. package/dist/tools/glob.js.map +1 -0
  399. package/dist/tools/governorTools.js +258 -0
  400. package/dist/tools/governorTools.js.map +1 -0
  401. package/dist/tools/grep.js +450 -0
  402. package/dist/tools/grep.js.map +1 -0
  403. package/dist/tools/guard.js +220 -0
  404. package/dist/tools/guard.js.map +1 -0
  405. package/dist/tools/killTree.js +215 -0
  406. package/dist/tools/killTree.js.map +1 -0
  407. package/dist/tools/listDir.js +143 -0
  408. package/dist/tools/listDir.js.map +1 -0
  409. package/dist/tools/mcpAdd.js +176 -0
  410. package/dist/tools/mcpAdd.js.map +1 -0
  411. package/dist/tools/mcpResources.js +116 -0
  412. package/dist/tools/mcpResources.js.map +1 -0
  413. package/dist/tools/mcpSearch.js +123 -0
  414. package/dist/tools/mcpSearch.js.map +1 -0
  415. package/dist/tools/multiEdit.js +168 -0
  416. package/dist/tools/multiEdit.js.map +1 -0
  417. package/dist/tools/paths.js +225 -0
  418. package/dist/tools/paths.js.map +1 -0
  419. package/dist/tools/posixShell.js +123 -0
  420. package/dist/tools/posixShell.js.map +1 -0
  421. package/dist/tools/readFile.js +371 -0
  422. package/dist/tools/readFile.js.map +1 -0
  423. package/dist/tools/readSymbol.js +145 -0
  424. package/dist/tools/readSymbol.js.map +1 -0
  425. package/dist/tools/registry.js +120 -0
  426. package/dist/tools/registry.js.map +1 -0
  427. package/dist/tools/replaceSymbol.js +141 -0
  428. package/dist/tools/replaceSymbol.js.map +1 -0
  429. package/dist/tools/results.js +15 -0
  430. package/dist/tools/results.js.map +1 -0
  431. package/dist/tools/ripgrep.js +145 -0
  432. package/dist/tools/ripgrep.js.map +1 -0
  433. package/dist/tools/runCommand.js +633 -0
  434. package/dist/tools/runCommand.js.map +1 -0
  435. package/dist/tools/saveMemory.js +102 -0
  436. package/dist/tools/saveMemory.js.map +1 -0
  437. package/dist/tools/screenshot.js +200 -0
  438. package/dist/tools/screenshot.js.map +1 -0
  439. package/dist/tools/screenshotWin.js +227 -0
  440. package/dist/tools/screenshotWin.js.map +1 -0
  441. package/dist/tools/search.js +121 -0
  442. package/dist/tools/search.js.map +1 -0
  443. package/dist/tools/sessionTools.js +187 -0
  444. package/dist/tools/sessionTools.js.map +1 -0
  445. package/dist/tools/shellCheckpoint.js +123 -0
  446. package/dist/tools/shellCheckpoint.js.map +1 -0
  447. package/dist/tools/shellLint.js +102 -0
  448. package/dist/tools/shellLint.js.map +1 -0
  449. package/dist/tools/shellTools.js +203 -0
  450. package/dist/tools/shellTools.js.map +1 -0
  451. package/dist/tools/spanCore.js +78 -0
  452. package/dist/tools/spanCore.js.map +1 -0
  453. package/dist/tools/subagent.js +224 -0
  454. package/dist/tools/subagent.js.map +1 -0
  455. package/dist/tools/subagentReport.js +114 -0
  456. package/dist/tools/subagentReport.js.map +1 -0
  457. package/dist/tools/tempSweep.js +118 -0
  458. package/dist/tools/tempSweep.js.map +1 -0
  459. package/dist/tools/todo.js +117 -0
  460. package/dist/tools/todo.js.map +1 -0
  461. package/dist/tools/types.js +2 -0
  462. package/dist/tools/types.js.map +1 -0
  463. package/dist/tools/untrusted.js +46 -0
  464. package/dist/tools/untrusted.js.map +1 -0
  465. package/dist/tools/useSkill.js +62 -0
  466. package/dist/tools/useSkill.js.map +1 -0
  467. package/dist/tools/walk.js +152 -0
  468. package/dist/tools/walk.js.map +1 -0
  469. package/dist/tools/web.js +61 -0
  470. package/dist/tools/web.js.map +1 -0
  471. package/dist/tools/webFetch.js +444 -0
  472. package/dist/tools/webFetch.js.map +1 -0
  473. package/dist/tools/webSearch.js +130 -0
  474. package/dist/tools/webSearch.js.map +1 -0
  475. package/dist/tools/workspace.js +212 -0
  476. package/dist/tools/workspace.js.map +1 -0
  477. package/dist/tools/workspaceDiscover.js +216 -0
  478. package/dist/tools/workspaceDiscover.js.map +1 -0
  479. package/dist/tools/writeFile.js +162 -0
  480. package/dist/tools/writeFile.js.map +1 -0
  481. package/package.json +74 -28
@@ -0,0 +1,283 @@
1
+ /**
2
+ * editCore.ts — the pure matching/splice logic shared by the edit tool.
3
+ *
4
+ * One source of truth for HOW a find-and-replace is applied, kept pure (string in,
5
+ * string out — no fs, no EOL handling) so it's unit-tested once and both tools inherit
6
+ * the same guarantees. The tools wrap it with the disk/EOL/approval concerns; deciding
7
+ * WHAT to change stays the model's job.
8
+ *
9
+ * ── Matching is TIERED, and the tiers are deliberately shallow ──────────────────
10
+ *
11
+ * Two failures dominate in practice, and they need opposite treatments:
12
+ *
13
+ * 1. The model's text is right but its INDENTATION drifted (it retyped a block from
14
+ * memory, or copied out of a context where leading space was normalized). An
15
+ * exact matcher rejects this, the model retries with the same mistake, and a turn
16
+ * burns. Tier 2 fixes it: compare line-by-line with each line trimmed.
17
+ * 2. The text genuinely appears more than once. No amount of cleverness resolves
18
+ * that — only more context or an explicit replace_all does.
19
+ *
20
+ * The temptation is to keep adding ever-looser tiers until something always matches.
21
+ * That is what the widely-copied "many replacers, first hit wins" design does, and it
22
+ * has a known, unfixed failure mode: a loose tier silently matches the WRONG block and
23
+ * corrupts the file, because nothing checks whether a stricter reading was ambiguous.
24
+ * A wrong edit applied confidently is far worse than a refused edit, so this module
25
+ * takes the opposite stance:
26
+ *
27
+ * - Tiers run strictest-first and STOP at the first tier that finds anything.
28
+ * A tier that finds 2 matches reports an ambiguity; it never falls through to a
29
+ * looser tier hoping for a cleaner answer, because "looser" only ever means "more
30
+ * ways to be wrong".
31
+ * - Every tier counts matches across the WHOLE text before touching anything, so
32
+ * ambiguity is detected rather than raced past.
33
+ * - No block-anchor tier (match on first/last line, guess the middle). That is the
34
+ * specific mechanism behind the corruption reports, and the cases it rescues are
35
+ * exactly the cases most likely to hit the wrong function.
36
+ *
37
+ * When a match can't be made unambiguously, the failure carries the actual candidate
38
+ * LOCATIONS back to the model (see `describeMatches`), so its retry is informed rather
39
+ * than another guess at the same string.
40
+ */
41
+ /** Normalize CRLF → LF so a model's LF `old_string` matches a CRLF file. */
42
+ export function normalizeLf(s) {
43
+ return s.replace(/\r\n/g, "\n");
44
+ }
45
+ /** Count non-overlapping occurrences of `needle` in `haystack`. */
46
+ export function occurrences(haystack, needle) {
47
+ if (needle === "")
48
+ return 0;
49
+ let count = 0;
50
+ let from = 0;
51
+ for (;;) {
52
+ const at = haystack.indexOf(needle, from);
53
+ if (at === -1)
54
+ return count;
55
+ count++;
56
+ from = at + needle.length;
57
+ }
58
+ }
59
+ /** 1-based line number of a char offset. */
60
+ export function lineAt(text, offset) {
61
+ let line = 1;
62
+ for (let i = 0; i < offset && i < text.length; i++)
63
+ if (text[i] === "\n")
64
+ line++;
65
+ return line;
66
+ }
67
+ /** Every exact occurrence of `needle`, as spans. */
68
+ function exactMatches(haystack, needle) {
69
+ const out = [];
70
+ let from = 0;
71
+ for (;;) {
72
+ const at = haystack.indexOf(needle, from);
73
+ if (at === -1)
74
+ return out;
75
+ out.push({ start: at, end: at + needle.length, line: lineAt(haystack, at) });
76
+ from = at + needle.length;
77
+ }
78
+ }
79
+ /**
80
+ * Every occurrence where each line matches after trimming (pure).
81
+ *
82
+ * This is the one concession to imprecision, and it is a narrow one: the SEQUENCE of
83
+ * lines and their trimmed content must correspond exactly, so only the surrounding
84
+ * whitespace is forgiven. It cannot skip lines, reorder them, or match a different
85
+ * number of them, which is what keeps it from wandering onto the wrong block the way a
86
+ * first-line/last-line anchor does.
87
+ *
88
+ * The span returned covers the file's OWN lines, so the replacement splices against
89
+ * real file text and the file's indentation is never silently rewritten.
90
+ */
91
+ function lineTrimmedMatches(haystack, needle) {
92
+ const needleLines = needle.split("\n");
93
+ // A trailing newline in the needle produces an empty last element that should not be
94
+ // required to correspond to a real line.
95
+ if (needleLines.length > 1 && needleLines[needleLines.length - 1] === "")
96
+ needleLines.pop();
97
+ if (needleLines.length === 0)
98
+ return [];
99
+ const wanted = needleLines.map((l) => l.trim());
100
+ const fileLines = haystack.split("\n");
101
+ // Char offset of the start of each line, so a line index converts back to a span.
102
+ const offsets = [];
103
+ let acc = 0;
104
+ for (const l of fileLines) {
105
+ offsets.push(acc);
106
+ acc += l.length + 1; // +1 for the newline
107
+ }
108
+ const out = [];
109
+ for (let i = 0; i + wanted.length <= fileLines.length; i++) {
110
+ let hit = true;
111
+ for (let j = 0; j < wanted.length; j++) {
112
+ if (fileLines[i + j].trim() !== wanted[j]) {
113
+ hit = false;
114
+ break;
115
+ }
116
+ }
117
+ if (!hit)
118
+ continue;
119
+ const start = offsets[i];
120
+ const lastIdx = i + wanted.length - 1;
121
+ // End at the last matched line's end, excluding its newline — mirrors how an exact
122
+ // match that stops mid-file behaves.
123
+ const end = offsets[lastIdx] + fileLines[lastIdx].length;
124
+ out.push({ start, end, line: i + 1 });
125
+ i = lastIdx; // non-overlapping
126
+ }
127
+ return out;
128
+ }
129
+ /**
130
+ * Locate `needle` in `haystack`, strictest tier first (pure).
131
+ *
132
+ * Stops at the FIRST tier that finds anything at all — including a tier that finds too
133
+ * many. Falling through an ambiguous exact match to a looser tier is precisely how a
134
+ * matcher ends up confidently editing the wrong place.
135
+ */
136
+ export function findMatches(haystack, needle) {
137
+ const exact = exactMatches(haystack, needle);
138
+ if (exact.length > 0)
139
+ return { tier: "exact", matches: exact };
140
+ const trimmed = lineTrimmedMatches(haystack, needle);
141
+ if (trimmed.length > 0)
142
+ return { tier: "line-trimmed", matches: trimmed };
143
+ return { tier: "exact", matches: [] };
144
+ }
145
+ /** Context lines shown around each candidate, and how far that will grow to make the
146
+ * candidates tell each other apart. */
147
+ const CONTEXT_LINES = 2;
148
+ const MAX_CONTEXT_LINES = 10;
149
+ /**
150
+ * Render the candidate locations for the model (pure).
151
+ *
152
+ * The reason this exists: an error that says only "matches 2 places" tells the model
153
+ * which RULE it broke but nothing it can act on, so its retry is another guess about a
154
+ * file it may have read many turns ago. Observed consequence — a retry that differed
155
+ * from the original attempt by a single newline, then failed identically, costing two
156
+ * round trips to reach a string the model could have copied straight out of this text.
157
+ *
158
+ * With the candidates in front of it the model can either lift a unique anchor
159
+ * verbatim, or see that every occurrence should change and pass `replace_all`.
160
+ */
161
+ export function describeMatches(haystack, matches, max = 4) {
162
+ const lines = haystack.split("\n");
163
+ const shown = matches.slice(0, max);
164
+ const window = (m, pad) => ({
165
+ from: Math.max(1, m.line - pad),
166
+ to: Math.min(lines.length, m.line + pad),
167
+ });
168
+ /**
169
+ * The comparable substance of a candidate's window.
170
+ *
171
+ * Line numbers are excluded because they differ by construction, and blank lines and
172
+ * indentation are excluded because differing only in those is not a difference the
173
+ * model can build a unique `old_string` out of. What counts as "distinguishable" here
174
+ * has to mean "gives the model something to anchor on", or the widening loop stops as
175
+ * soon as two windows are technically unequal and hands back two blocks that are, for
176
+ * every practical purpose, the same.
177
+ */
178
+ const contentOf = (m, pad) => {
179
+ const { from, to } = window(m, pad);
180
+ return lines
181
+ .slice(from - 1, to)
182
+ .map((l) => l.trim())
183
+ .filter(Boolean)
184
+ .join("\n");
185
+ };
186
+ // Widen the window until the candidates are actually DISTINGUISHABLE. Duplicated code
187
+ // usually comes with duplicated surroundings — two identical helpers on two similar
188
+ // classes — so a fixed window can render every candidate the same and leave the model
189
+ // exactly where it started, with no unique anchor to lift. Growing until they differ
190
+ // is what makes this report useful rather than merely informative.
191
+ let pad = CONTEXT_LINES;
192
+ while (pad < MAX_CONTEXT_LINES && new Set(shown.map((m) => contentOf(m, pad))).size < shown.length) {
193
+ pad += 2;
194
+ }
195
+ const blocks = shown.map((m, i) => {
196
+ const { from, to } = window(m, pad);
197
+ const body = [];
198
+ for (let n = from; n <= to; n++) {
199
+ // The match line is marked so the model can see which one is the candidate
200
+ // rather than having to count.
201
+ body.push(`${n === m.line ? ">" : " "} ${String(n).padStart(5)} | ${lines[n - 1]}`);
202
+ }
203
+ return ` ${i + 1}. line ${m.line}\n${body.join("\n")}`;
204
+ });
205
+ const more = matches.length > shown.length ? `\n\n … and ${matches.length - shown.length} more.` : "";
206
+ // Stated every time rather than only when the blocks look alike. Deciding "alike" is
207
+ // itself unreliable — a window clipped at the start of the file always differs from
208
+ // one in the middle, whatever the code around them says — and a conditional that
209
+ // cannot be made to fire is worse than a sentence that is always true.
210
+ const hint = "\n\nExtend old_string with a line that differs between them (a class or function name above the block), " +
211
+ "or set replace_all: true if all of them should change.";
212
+ return blocks.join("\n\n") + more + hint;
213
+ }
214
+ /**
215
+ * Apply one exact edit to already-LF-normalized `text`. The `oldString`/`newString`
216
+ * are normalized here too. Returns the updated text and where the change landed, or
217
+ * a `reason` describing why it couldn't apply (identical / not found / ambiguous).
218
+ * Splices by index so a `$` in the replacement is never a special pattern.
219
+ */
220
+ export function applyOneEdit(text, op) {
221
+ // Normalize BOTH sides to LF: the file on disk may be CRLF while the model's
222
+ // old_string (copied from LF text it was shown) is LF. This is a representation
223
+ // fix, not fuzzy matching.
224
+ const haystack = normalizeLf(text);
225
+ const needle = normalizeLf(op.oldString);
226
+ const replacement = normalizeLf(op.newString);
227
+ if (needle === "")
228
+ return { ok: false, reason: "old_string is empty — it must identify the text to replace" };
229
+ if (needle === replacement)
230
+ return { ok: false, reason: "old_string and new_string are identical — nothing to change" };
231
+ const { matches } = findMatches(haystack, needle);
232
+ if (matches.length === 0) {
233
+ return {
234
+ ok: false,
235
+ reason: "old_string not found. It must match the file's text, allowing only for differences in each line's " +
236
+ "leading/trailing whitespace. Re-read the file and copy the target text from what you are shown",
237
+ };
238
+ }
239
+ if (matches.length > 1 && !op.replaceAll) {
240
+ // Hand back WHERE, not just how many. See `describeMatches`.
241
+ return {
242
+ ok: false,
243
+ reason: `old_string matches ${matches.length} places. Either extend it with surrounding lines until it is ` +
244
+ `unique, or set replace_all: true to change every occurrence. The candidates:\n\n` +
245
+ describeMatches(haystack, matches),
246
+ };
247
+ }
248
+ // Splice by index, right-to-left so earlier spans keep their offsets. Never via
249
+ // string.replace: a `$` in the replacement would be read as a pattern reference.
250
+ const targets = op.replaceAll ? matches : [matches[0]];
251
+ let updated = haystack;
252
+ for (let i = targets.length - 1; i >= 0; i--) {
253
+ const m = targets[i];
254
+ updated = updated.slice(0, m.start) + replacement + updated.slice(m.end);
255
+ }
256
+ const changeStart = targets[0].start;
257
+ const changeEnd = targets[targets.length - 1].start + replacement.length;
258
+ return { ok: true, updated, count: targets.length, changeStart, changeEnd };
259
+ }
260
+ /**
261
+ * Apply edits in order to normalized `text`, each seeing the result of the one
262
+ * before (so a later edit can target text an earlier edit produced). ATOMIC: the
263
+ * first failure aborts the whole sequence with the offending edit's index and
264
+ * reason — the caller writes nothing, so a file is never left half-edited.
265
+ */
266
+ export function applyEditSequence(text, ops) {
267
+ let current = normalizeLf(text);
268
+ let total = 0;
269
+ let spanStart = -1;
270
+ let spanEnd = 0;
271
+ for (let i = 0; i < ops.length; i++) {
272
+ const r = applyOneEdit(current, ops[i]);
273
+ if (!r.ok)
274
+ return { ok: false, index: i, reason: r.reason };
275
+ current = r.updated;
276
+ total += r.count;
277
+ if (spanStart < 0 && r.changeStart >= 0)
278
+ spanStart = r.changeStart;
279
+ spanEnd = Math.max(spanEnd, r.changeEnd);
280
+ }
281
+ return { ok: true, updated: current, total, spanStart: Math.max(0, spanStart), spanEnd };
282
+ }
283
+ //# sourceMappingURL=editCore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editCore.js","sourceRoot":"","sources":["../../src/tools/editCore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * editFile.ts — a surgical find-and-replace on one file.
3
+ *
4
+ * The workhorse mutating tool. It replaces an exact `old_string` with
5
+ * `new_string`. Reliability comes from the tool REFUSING bad edits, not from the
6
+ * model being careful — the three refusals below make the classic failure modes
7
+ * (editing a file you never read, a stale/typo'd match, an ambiguous match)
8
+ * structurally impossible:
9
+ *
10
+ * - read-before-edit: the file must have been read this session, so the model's
11
+ * `old_string` is copied from real content, not imagined.
12
+ * - must-exist: zero matches errors instead of silently doing nothing, so the
13
+ * model learns its match was wrong.
14
+ * - unique-match: more than one match (without replace_all) errors and hands back
15
+ * WHERE the candidates are, so an edit never lands in the wrong place and the
16
+ * retry is informed rather than another guess.
17
+ *
18
+ * Matching is exact first, then line-trimmed — and stops there. It is deliberately not
19
+ * a stack of ever-looser matchers: past a point, "looser" only means "more ways to edit
20
+ * the wrong block", which is a corruption bug rather than a convenience. The reasoning,
21
+ * and what is deliberately NOT implemented, lives in editCore.ts.
22
+ * (Deciding *what* to change is the model's job; this tool only applies it.)
23
+ */
24
+ import { promises as fs } from "node:fs";
25
+ import { recordWrite, relativize } from "./paths.js";
26
+ import { editDetail, lineCount, magnitude, rangeLabel, withScope } from "./detail.js";
27
+ import { applyEol } from "./eol.js";
28
+ import { applyOneEdit } from "./editCore.js";
29
+ import { prepareEditTarget, fail, failQuietly, errText } from "./editTarget.js";
30
+ export const editFile = {
31
+ name: "edit_file",
32
+ readOnly: false,
33
+ // The old wording said `old_string` "must match the file's text", which undersold the
34
+ // matcher in a way that costs real work: matching is tiered, so indentation and line
35
+ // endings are already forgiven. A model told it needs the exact bytes re-reads whole
36
+ // files to get them and retries edits that would have applied. What the tiers do NOT
37
+ // forgive is stated just as plainly, because a matcher that sounds infinitely lenient
38
+ // invites the sloppy input that makes a wrong-place edit possible. See editCore.ts.
39
+ description: "Replace a string in a file with another. This is the DEFAULT editing tool: reach for " +
40
+ "it whenever you are changing one place in a file. Read the file first. " +
41
+ "`old_string` has to identify exactly ONE place, and it is matched on content rather " +
42
+ "than on formatting: if an exact match is not found, each line is compared with its " +
43
+ "leading and trailing whitespace ignored, and line endings are normalized on both " +
44
+ "sides. So you do not need to reproduce a file's exact indentation, and a CRLF file " +
45
+ "is not a problem. What is never forgiven is a skipped, reordered, or extra line. " +
46
+ "If `old_string` matches SEVERAL places the file is left untouched and you get the " +
47
+ "candidate locations back with surrounding context: pick one and include enough " +
48
+ "nearby lines to make it unique, or set `replace_all` to change every occurrence. " +
49
+ "If the SAME file needs changing in several separate places, use multi_edit instead " +
50
+ "of calling this repeatedly. Use write_file only to create a new file or replace one " +
51
+ "wholesale.",
52
+ parameters: {
53
+ type: "object",
54
+ additionalProperties: false,
55
+ required: ["path", "old_string", "new_string"],
56
+ properties: {
57
+ path: {
58
+ type: "string",
59
+ description: "Path to the file, absolute or relative to the working directory.",
60
+ },
61
+ old_string: {
62
+ type: "string",
63
+ description: "The exact text to replace. Include enough surrounding lines to make it unique.",
64
+ },
65
+ new_string: {
66
+ type: "string",
67
+ description: "The replacement text. Use an empty string to delete old_string.",
68
+ },
69
+ replace_all: {
70
+ type: "boolean",
71
+ description: "Replace every occurrence instead of requiring a unique match. Default false.",
72
+ },
73
+ },
74
+ },
75
+ async execute(args, ctx) {
76
+ const rawPath = typeof args.path === "string" ? args.path.trim() : "";
77
+ if (!rawPath)
78
+ return fail("`path` is required.");
79
+ if (typeof args.old_string !== "string" || args.old_string === "") {
80
+ return fail("`old_string` is required and must not be empty — it identifies the text to replace.");
81
+ }
82
+ if (typeof args.new_string !== "string") {
83
+ return fail("`new_string` is required (use an empty string to delete old_string).");
84
+ }
85
+ const oldString = args.old_string;
86
+ const newString = args.new_string;
87
+ const replaceAll = args.replace_all === true;
88
+ if (oldString === newString) {
89
+ return fail("`old_string` and `new_string` are identical — nothing to change.");
90
+ }
91
+ const target = await prepareEditTarget(ctx, rawPath, "editing");
92
+ if (!target.ok)
93
+ return target.error;
94
+ const { filePath, content, eol } = target;
95
+ // Match line-ending-agnostically. The file on disk may use CRLF (Windows)
96
+ // while the model's old_string — copied from text it was shown — uses LF; an
97
+ // exact byte match would then fail on every multi-line edit. Normalizing the
98
+ // CR the model can't see is a representation fix, not fuzzy matching: we still
99
+ // match whitespace and indentation exactly (handled in editCore). The file's
100
+ // own line endings are preserved on write.
101
+ const applied = applyOneEdit(content, { oldString, newString, replaceAll });
102
+ // A match that didn't land is the model's to correct — it gets the reason and the
103
+ // candidate locations, and retries. Not the user's business, so it stays off screen.
104
+ if (!applied.ok)
105
+ return failQuietly(`${applied.reason} (in ${rawPath}).`);
106
+ const { updated: updatedNorm, count, changeStart, changeEnd } = applied;
107
+ const updated = applyEol(updatedNorm, eol);
108
+ // Snapshot the pre-edit bytes for /undo before touching disk.
109
+ ctx.checkpoints?.backup(filePath, content, updated);
110
+ try {
111
+ await fs.writeFile(filePath, updated, "utf8");
112
+ }
113
+ catch (error) {
114
+ return fail(`could not write ${rawPath}: ${errText(error)}`);
115
+ }
116
+ // Still seen+touched this session — record the new state (with the edited region
117
+ // as this file's focus, so a large file localizes to it in the working set).
118
+ await recordWrite(ctx, filePath, {
119
+ start: charToLine(updatedNorm, Math.max(0, changeStart)) + 1,
120
+ end: charToLine(updatedNorm, changeEnd) + 1,
121
+ });
122
+ const shown = relativize(ctx, filePath);
123
+ const n = replaceAll ? count : 1;
124
+ const plural = n === 1 ? "" : "s";
125
+ // Hand back the changed region WITH fresh line numbers. This is what stops the
126
+ // model from re-reading the whole file after every edit (the loop that bloats a
127
+ // multi-edit task): it can target its next edit straight from this snippet.
128
+ const window = numberedWindow(updatedNorm, Math.max(0, changeStart), changeEnd);
129
+ const span = replaceAll && n > 1 ? ` (showing the first of ${n} sites)` : "";
130
+ // The scope of the change — WHERE and HOW MUCH — so the row shows more than a bare
131
+ // diff: the line range touched (or "N sites" for a spread replace_all) and ± lines.
132
+ const startLine = charToLine(updatedNorm, Math.max(0, changeStart)) + 1;
133
+ const endLine = charToLine(updatedNorm, changeEnd) + 1;
134
+ const removed = lineCount(oldString) * n;
135
+ const added = lineCount(newString) * n;
136
+ const scope = replaceAll && n > 1
137
+ ? `${n} sites · ${magnitude(removed, added)}`
138
+ : `${rangeLabel(startLine, endLine)} · ${magnitude(removed, added)}`;
139
+ return {
140
+ output: `Edited ${shown}: ${n} replacement${plural}.\n` +
141
+ `Updated region${span} — line-numbered so you can make further edits without re-reading:\n${window}`,
142
+ summary: `edited ${shown} · ${scope}`,
143
+ detail: withScope(scope, editDetail(oldString, newString)),
144
+ };
145
+ },
146
+ };
147
+ /**
148
+ * Render the lines spanning [startChar, endChar] in `text`, plus `pad` lines of
149
+ * context on each side, with 1-based right-aligned line numbers. Pure and indexed
150
+ * on the normalized (LF) text, so it's independent of the file's real EOL. Bounded
151
+ * by `maxLines` so a sweeping replace can't flood the result.
152
+ */
153
+ export function numberedWindow(text, startChar, endChar, pad = 4, maxLines = 30) {
154
+ const lines = text.split("\n");
155
+ const startLine = charToLine(text, startChar);
156
+ const endLine = charToLine(text, endChar);
157
+ const from = Math.max(0, startLine - pad);
158
+ let to = Math.min(lines.length - 1, endLine + pad);
159
+ let truncated = false;
160
+ if (to - from + 1 > maxLines) {
161
+ to = from + maxLines - 1;
162
+ truncated = true;
163
+ }
164
+ const width = String(to + 1).length;
165
+ const out = [];
166
+ for (let i = from; i <= to; i++) {
167
+ out.push(`${String(i + 1).padStart(width)} ${lines[i] ?? ""}`);
168
+ }
169
+ if (truncated)
170
+ out.push(" … (region continues; re-read the file if you need the rest)");
171
+ return out.join("\n");
172
+ }
173
+ /** The 0-based line a character offset falls on (count of newlines before it). */
174
+ export function charToLine(text, charIndex) {
175
+ let line = 0;
176
+ const limit = Math.min(charIndex, text.length);
177
+ for (let i = 0; i < limit; i++) {
178
+ if (text[i] === "\n")
179
+ line++;
180
+ }
181
+ return line;
182
+ }
183
+ //# sourceMappingURL=editFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editFile.js","sourceRoot":"","sources":["../../src/tools/editFile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { chassisForPath } from "./chassisMux.js";
2
+ import { relativize } from "./paths.js";
3
+ /** Edited files checked per step. An edit touching more files than this is a sweeping
4
+ * refactor, where a per-file check is the wrong instrument anyway. */
5
+ export const MAX_EDITED = 8;
6
+ /** Reverse dependents pulled in on top. The point is to catch the broken caller, not to
7
+ * type-check the repo: a widely-imported file has hundreds and checking them all would
8
+ * cost more than the edit did. */
9
+ export const MAX_DEPENDENTS = 12;
10
+ /** Diagnostics quoted into the note. Past this the model needs to look, not read. */
11
+ export const MAX_REPORTED = 20;
12
+ /** Tools whose call means "a file's contents changed on disk". */
13
+ const EDITING_TOOLS = new Set(["edit", "multi_edit", "write_file", "create_file", "apply_patch"]);
14
+ /**
15
+ * The absolute paths an executed round actually edited.
16
+ *
17
+ * Driven off the CALL rather than the result body, because that is the thing that is
18
+ * true regardless of how a tool phrases success. A failed call is skipped: it changed
19
+ * nothing, and checking it would report pre-existing errors as if the edit caused them.
20
+ */
21
+ export function editedPaths(results, resolve) {
22
+ const out = new Set();
23
+ for (const r of results) {
24
+ if (r.isError || !EDITING_TOOLS.has(r.name))
25
+ continue;
26
+ const raw = r.args?.path ?? r.args?.file_path;
27
+ if (typeof raw !== "string" || !raw.trim())
28
+ continue;
29
+ const abs = resolve(raw.trim());
30
+ if (abs)
31
+ out.add(abs);
32
+ }
33
+ return [...out].slice(0, MAX_EDITED);
34
+ }
35
+ /**
36
+ * Edited files plus their reverse dependents, deduped, edited-first.
37
+ *
38
+ * Edited-first is deliberate: if the cap bites, the files the model just touched are
39
+ * the ones it must not lose. Dependents are the bonus that catches the broken caller.
40
+ */
41
+ export async function rippleTargets(ctx, edited) {
42
+ const seen = new Set(edited);
43
+ const extra = [];
44
+ for (const abs of edited) {
45
+ const chassis = chassisForPath(ctx, abs);
46
+ if (!chassis)
47
+ continue;
48
+ let deps = [];
49
+ try {
50
+ deps = await chassis.dependents(abs);
51
+ }
52
+ catch {
53
+ // The graph is an assistant, never a gate: if it cannot answer, the edited files
54
+ // are still checked. A ripple failure must not cost the model its diagnostics.
55
+ continue;
56
+ }
57
+ for (const d of deps) {
58
+ if (seen.has(d) || extra.length >= MAX_DEPENDENTS)
59
+ continue;
60
+ seen.add(d);
61
+ extra.push(d);
62
+ }
63
+ }
64
+ return [...edited, ...extra];
65
+ }
66
+ /**
67
+ * Render the note the model receives, or "" when there is nothing worth saying.
68
+ *
69
+ * Errors first, then warnings — a turn that produced one type error and nine lint
70
+ * warnings should not bury the type error. `edited` is named separately so the model
71
+ * can tell "you broke this file you just wrote" from "you broke a caller over there",
72
+ * which are different problems with different fixes.
73
+ */
74
+ export function formatRippleNote(diags, editedSet, label) {
75
+ if (diags.length === 0)
76
+ return "";
77
+ const rank = (d) => (d.severity === "error" ? 0 : 1);
78
+ const sorted = [...diags].sort((a, b) => rank(a) - rank(b));
79
+ const shown = sorted.slice(0, MAX_REPORTED);
80
+ const lines = shown.map((d) => {
81
+ const where = editedSet.has(d.file) ? "" : " (caller)";
82
+ return `- ${label(d.file)}:${d.line}${where} ${d.severity}: ${d.message}`;
83
+ });
84
+ const hidden = sorted.length - shown.length;
85
+ const more = hidden > 0 ? `\n(${hidden} more not shown)` : "";
86
+ const errors = sorted.filter((d) => d.severity === "error").length;
87
+ return (`[Automatic check after your edit — these are the language server's diagnostics for the ` +
88
+ `files you just changed and the files that import them. ${errors} error` +
89
+ `${errors === 1 ? "" : "s"} across ${new Set(shown.map((d) => d.file)).size} file` +
90
+ `${new Set(shown.map((d) => d.file)).size === 1 ? "" : "s"}. Fix what you caused; a ` +
91
+ `diagnostic in a file marked (caller) means your change broke code elsewhere. If one ` +
92
+ `was already there before your edit, say so rather than silently fixing unrelated ` +
93
+ `code.]\n${lines.join("\n")}${more}`);
94
+ }
95
+ /**
96
+ * The whole pass: what did this round edit, what does that reach, and is anything broken.
97
+ *
98
+ * Returns "" whenever there is nothing to say — no edits, no chassis, no diagnostics.
99
+ * Never throws: this runs inside the turn loop and a failure here must cost the user
100
+ * nothing more than the check itself.
101
+ */
102
+ export async function rippleCheck(ctx, results, resolve) {
103
+ try {
104
+ const edited = editedPaths(results, resolve);
105
+ if (edited.length === 0)
106
+ return "";
107
+ const targets = await rippleTargets(ctx, edited);
108
+ const all = [];
109
+ await Promise.all(targets.map(async (abs) => {
110
+ const chassis = chassisForPath(ctx, abs);
111
+ if (!chassis)
112
+ return;
113
+ try {
114
+ all.push(...(await chassis.diagnostics(abs)));
115
+ }
116
+ catch {
117
+ // One unreachable server must not lose the diagnostics from the others.
118
+ }
119
+ }));
120
+ return formatRippleNote(all, new Set(edited), (abs) => relativize(ctx, abs));
121
+ }
122
+ catch {
123
+ return "";
124
+ }
125
+ }
126
+ //# sourceMappingURL=editRipple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editRipple.js","sourceRoot":"","sources":["../../src/tools/editRipple.ts"],"names":[],"mappings":"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"}