@google/gemini-cli-core 0.30.0-preview.6 → 0.31.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (687) hide show
  1. package/README.md +1 -1
  2. package/dist/docs/CONTRIBUTING.md +6 -7
  3. package/dist/docs/changelogs/index.md +22 -2
  4. package/dist/docs/changelogs/latest.md +359 -293
  5. package/dist/docs/changelogs/preview.md +300 -349
  6. package/dist/docs/cli/cli-reference.md +23 -23
  7. package/dist/docs/cli/enterprise.md +7 -7
  8. package/dist/docs/cli/gemini-md.md +1 -1
  9. package/dist/docs/cli/model.md +1 -1
  10. package/dist/docs/cli/plan-mode.md +180 -80
  11. package/dist/docs/cli/sandbox.md +3 -3
  12. package/dist/docs/cli/settings.md +59 -51
  13. package/dist/docs/cli/telemetry.md +4 -1
  14. package/dist/docs/cli/themes.md +3 -3
  15. package/dist/docs/cli/trusted-folders.md +31 -0
  16. package/dist/docs/cli/tutorials/memory-management.md +2 -2
  17. package/dist/docs/cli/tutorials/session-management.md +1 -1
  18. package/dist/docs/core/index.md +7 -7
  19. package/dist/docs/core/subagents.md +155 -39
  20. package/dist/docs/extensions/reference.md +38 -14
  21. package/dist/docs/get-started/authentication.md +4 -4
  22. package/dist/docs/get-started/examples.md +2 -2
  23. package/dist/docs/get-started/gemini-3.md +17 -3
  24. package/dist/docs/get-started/index.md +11 -2
  25. package/dist/docs/hooks/best-practices.md +1 -1
  26. package/dist/docs/hooks/reference.md +8 -0
  27. package/dist/docs/ide-integration/index.md +14 -0
  28. package/dist/docs/index.md +62 -67
  29. package/dist/docs/redirects.json +19 -0
  30. package/dist/docs/{cli → reference}/commands.md +67 -11
  31. package/dist/docs/{get-started → reference}/configuration.md +93 -24
  32. package/dist/docs/{cli → reference}/keyboard-shortcuts.md +3 -3
  33. package/dist/docs/{core → reference}/policy-engine.md +63 -27
  34. package/dist/docs/{faq.md → resources/faq.md} +1 -1
  35. package/dist/docs/{quota-and-pricing.md → resources/quota-and-pricing.md} +12 -5
  36. package/dist/docs/{tos-privacy.md → resources/tos-privacy.md} +2 -2
  37. package/dist/docs/{troubleshooting.md → resources/troubleshooting.md} +1 -1
  38. package/dist/docs/sidebar.json +203 -166
  39. package/dist/docs/tools/file-system.md +7 -4
  40. package/dist/docs/tools/index.md +5 -2
  41. package/dist/docs/tools/internal-docs.md +5 -5
  42. package/dist/docs/tools/mcp-server.md +62 -2
  43. package/dist/docs/tools/planning.md +2 -0
  44. package/dist/docs/tools/shell.md +3 -3
  45. package/dist/src/agents/a2a-client-manager.test.js +1 -2
  46. package/dist/src/agents/a2a-client-manager.test.js.map +1 -1
  47. package/dist/src/agents/a2aUtils.d.ts +1 -5
  48. package/dist/src/agents/a2aUtils.js +1 -1
  49. package/dist/src/agents/a2aUtils.js.map +1 -1
  50. package/dist/src/agents/acknowledgedAgents.js +1 -0
  51. package/dist/src/agents/acknowledgedAgents.js.map +1 -1
  52. package/dist/src/agents/agent-scheduler.js +1 -0
  53. package/dist/src/agents/agent-scheduler.js.map +1 -1
  54. package/dist/src/agents/agentLoader.d.ts +0 -1
  55. package/dist/src/agents/agentLoader.js +22 -21
  56. package/dist/src/agents/agentLoader.js.map +1 -1
  57. package/dist/src/agents/agentLoader.test.js +1 -5
  58. package/dist/src/agents/agentLoader.test.js.map +1 -1
  59. package/dist/src/agents/auth-provider/api-key-provider.d.ts +30 -0
  60. package/dist/src/agents/auth-provider/api-key-provider.js +66 -0
  61. package/dist/src/agents/auth-provider/api-key-provider.js.map +1 -0
  62. package/dist/src/agents/auth-provider/api-key-provider.test.d.ts +6 -0
  63. package/dist/src/agents/auth-provider/api-key-provider.test.js +130 -0
  64. package/dist/src/agents/auth-provider/api-key-provider.test.js.map +1 -0
  65. package/dist/src/agents/auth-provider/base-provider.d.ts +2 -2
  66. package/dist/src/agents/auth-provider/base-provider.js.map +1 -1
  67. package/dist/src/agents/auth-provider/factory.js +6 -3
  68. package/dist/src/agents/auth-provider/factory.js.map +1 -1
  69. package/dist/src/agents/auth-provider/factory.test.js +12 -0
  70. package/dist/src/agents/auth-provider/factory.test.js.map +1 -1
  71. package/dist/src/agents/auth-provider/types.d.ts +2 -4
  72. package/dist/src/agents/browser/analyzeScreenshot.d.ts +35 -0
  73. package/dist/src/agents/browser/analyzeScreenshot.js +183 -0
  74. package/dist/src/agents/browser/analyzeScreenshot.js.map +1 -0
  75. package/dist/src/agents/browser/analyzeScreenshot.test.d.ts +6 -0
  76. package/dist/src/agents/browser/analyzeScreenshot.test.js +161 -0
  77. package/dist/src/agents/browser/analyzeScreenshot.test.js.map +1 -0
  78. package/dist/src/agents/browser/browserAgentDefinition.d.ts +50 -0
  79. package/dist/src/agents/browser/browserAgentDefinition.js +141 -0
  80. package/dist/src/agents/browser/browserAgentDefinition.js.map +1 -0
  81. package/dist/src/agents/browser/browserAgentFactory.d.ts +42 -0
  82. package/dist/src/agents/browser/browserAgentFactory.js +107 -0
  83. package/dist/src/agents/browser/browserAgentFactory.js.map +1 -0
  84. package/dist/src/agents/browser/browserAgentFactory.test.d.ts +6 -0
  85. package/dist/src/agents/browser/browserAgentFactory.test.js +186 -0
  86. package/dist/src/agents/browser/browserAgentFactory.test.js.map +1 -0
  87. package/dist/src/agents/browser/browserAgentInvocation.d.ts +44 -0
  88. package/dist/src/agents/browser/browserAgentInvocation.js +109 -0
  89. package/dist/src/agents/browser/browserAgentInvocation.js.map +1 -0
  90. package/dist/src/agents/browser/browserAgentInvocation.test.d.ts +6 -0
  91. package/dist/src/agents/browser/browserAgentInvocation.test.js +87 -0
  92. package/dist/src/agents/browser/browserAgentInvocation.test.js.map +1 -0
  93. package/dist/src/agents/browser/browserManager.d.ts +110 -0
  94. package/dist/src/agents/browser/browserManager.js +323 -0
  95. package/dist/src/agents/browser/browserManager.js.map +1 -0
  96. package/dist/src/agents/browser/browserManager.test.d.ts +6 -0
  97. package/dist/src/agents/browser/browserManager.test.js +314 -0
  98. package/dist/src/agents/browser/browserManager.test.js.map +1 -0
  99. package/dist/src/agents/browser/mcpToolWrapper.d.ts +45 -0
  100. package/dist/src/agents/browser/mcpToolWrapper.js +356 -0
  101. package/dist/src/agents/browser/mcpToolWrapper.js.map +1 -0
  102. package/dist/src/agents/browser/mcpToolWrapper.test.d.ts +6 -0
  103. package/dist/src/agents/browser/mcpToolWrapper.test.js +126 -0
  104. package/dist/src/agents/browser/mcpToolWrapper.test.js.map +1 -0
  105. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.d.ts +6 -0
  106. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js +57 -0
  107. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js.map +1 -0
  108. package/dist/src/agents/browser/modelAvailability.d.ts +23 -0
  109. package/dist/src/agents/browser/modelAvailability.js +23 -0
  110. package/dist/src/agents/browser/modelAvailability.js.map +1 -0
  111. package/dist/src/agents/local-executor.js +73 -31
  112. package/dist/src/agents/local-executor.js.map +1 -1
  113. package/dist/src/agents/local-executor.test.js +157 -4
  114. package/dist/src/agents/local-executor.test.js.map +1 -1
  115. package/dist/src/agents/local-invocation.test.js.map +1 -1
  116. package/dist/src/agents/registry.js +8 -0
  117. package/dist/src/agents/registry.js.map +1 -1
  118. package/dist/src/agents/registry.test.js.map +1 -1
  119. package/dist/src/agents/remote-invocation.d.ts +2 -1
  120. package/dist/src/agents/remote-invocation.js +3 -3
  121. package/dist/src/agents/remote-invocation.js.map +1 -1
  122. package/dist/src/agents/subagent-tool-wrapper.js +6 -0
  123. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
  124. package/dist/src/agents/subagent-tool.d.ts +3 -0
  125. package/dist/src/agents/subagent-tool.js +62 -3
  126. package/dist/src/agents/subagent-tool.js.map +1 -1
  127. package/dist/src/agents/subagent-tool.test.js +143 -0
  128. package/dist/src/agents/subagent-tool.test.js.map +1 -1
  129. package/dist/src/availability/fallbackIntegration.test.js +4 -1
  130. package/dist/src/availability/fallbackIntegration.test.js.map +1 -1
  131. package/dist/src/availability/policyHelpers.js +3 -1
  132. package/dist/src/availability/policyHelpers.js.map +1 -1
  133. package/dist/src/availability/policyHelpers.test.js +51 -5
  134. package/dist/src/availability/policyHelpers.test.js.map +1 -1
  135. package/dist/src/code_assist/admin/admin_controls.js +1 -0
  136. package/dist/src/code_assist/admin/admin_controls.js.map +1 -1
  137. package/dist/src/code_assist/converter.js +8 -2
  138. package/dist/src/code_assist/converter.js.map +1 -1
  139. package/dist/src/code_assist/converter.test.js.map +1 -1
  140. package/dist/src/code_assist/experiments/experiments.js +1 -1
  141. package/dist/src/code_assist/experiments/experiments.js.map +1 -1
  142. package/dist/src/code_assist/oauth-credential-storage.js +1 -1
  143. package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
  144. package/dist/src/code_assist/oauth-credential-storage.test.js +5 -0
  145. package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
  146. package/dist/src/code_assist/oauth2.js +11 -8
  147. package/dist/src/code_assist/oauth2.js.map +1 -1
  148. package/dist/src/code_assist/oauth2.test.js +55 -0
  149. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  150. package/dist/src/code_assist/server.js +22 -13
  151. package/dist/src/code_assist/server.js.map +1 -1
  152. package/dist/src/code_assist/server.test.js +26 -0
  153. package/dist/src/code_assist/server.test.js.map +1 -1
  154. package/dist/src/code_assist/telemetry.js +16 -3
  155. package/dist/src/code_assist/telemetry.js.map +1 -1
  156. package/dist/src/code_assist/telemetry.test.js +10 -0
  157. package/dist/src/code_assist/telemetry.test.js.map +1 -1
  158. package/dist/src/code_assist/types.d.ts +13 -12
  159. package/dist/src/code_assist/types.js.map +1 -1
  160. package/dist/src/config/config.d.ts +83 -8
  161. package/dist/src/config/config.js +127 -23
  162. package/dist/src/config/config.js.map +1 -1
  163. package/dist/src/config/config.test.js +285 -10
  164. package/dist/src/config/config.test.js.map +1 -1
  165. package/dist/src/config/projectRegistry.js +1 -0
  166. package/dist/src/config/projectRegistry.js.map +1 -1
  167. package/dist/src/config/storage.d.ts +17 -1
  168. package/dist/src/config/storage.js +82 -2
  169. package/dist/src/config/storage.js.map +1 -1
  170. package/dist/src/config/storage.test.js +149 -2
  171. package/dist/src/config/storage.test.js.map +1 -1
  172. package/dist/src/config/userHintService.d.ts +46 -0
  173. package/dist/src/config/userHintService.js +81 -0
  174. package/dist/src/config/userHintService.js.map +1 -0
  175. package/dist/src/config/userHintService.test.d.ts +6 -0
  176. package/dist/src/config/userHintService.test.js +62 -0
  177. package/dist/src/config/userHintService.test.js.map +1 -0
  178. package/dist/src/confirmation-bus/message-bus.js +15 -3
  179. package/dist/src/confirmation-bus/message-bus.js.map +1 -1
  180. package/dist/src/confirmation-bus/message-bus.test.js +15 -0
  181. package/dist/src/confirmation-bus/message-bus.test.js.map +1 -1
  182. package/dist/src/confirmation-bus/types.d.ts +7 -0
  183. package/dist/src/confirmation-bus/types.js.map +1 -1
  184. package/dist/src/core/baseLlmClient.d.ts +2 -3
  185. package/dist/src/core/baseLlmClient.js +7 -5
  186. package/dist/src/core/baseLlmClient.js.map +1 -1
  187. package/dist/src/core/baseLlmClient.test.js +45 -20
  188. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  189. package/dist/src/core/client.js +18 -7
  190. package/dist/src/core/client.js.map +1 -1
  191. package/dist/src/core/coreToolHookTriggers.d.ts +2 -3
  192. package/dist/src/core/coreToolHookTriggers.js +8 -3
  193. package/dist/src/core/coreToolHookTriggers.js.map +1 -1
  194. package/dist/src/core/coreToolScheduler.js +2 -1
  195. package/dist/src/core/coreToolScheduler.js.map +1 -1
  196. package/dist/src/core/coreToolScheduler.test.js +10 -3
  197. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  198. package/dist/src/core/fakeContentGenerator.js +2 -0
  199. package/dist/src/core/fakeContentGenerator.js.map +1 -1
  200. package/dist/src/core/geminiChat.d.ts +1 -1
  201. package/dist/src/core/geminiChat.js +5 -5
  202. package/dist/src/core/geminiChat.js.map +1 -1
  203. package/dist/src/core/geminiChat.test.js +1 -0
  204. package/dist/src/core/geminiChat.test.js.map +1 -1
  205. package/dist/src/core/geminiChat_network_retry.test.js +1 -0
  206. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
  207. package/dist/src/core/logger.js +2 -0
  208. package/dist/src/core/logger.js.map +1 -1
  209. package/dist/src/core/loggingContentGenerator.d.ts +14 -2
  210. package/dist/src/core/loggingContentGenerator.js +98 -4
  211. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  212. package/dist/src/core/loggingContentGenerator.test.js +275 -1
  213. package/dist/src/core/loggingContentGenerator.test.js.map +1 -1
  214. package/dist/src/core/prompts.test.js +55 -27
  215. package/dist/src/core/prompts.test.js.map +1 -1
  216. package/dist/src/core/recordingContentGenerator.test.js +5 -0
  217. package/dist/src/core/recordingContentGenerator.test.js.map +1 -1
  218. package/dist/src/core/turn.d.ts +4 -2
  219. package/dist/src/core/turn.js +2 -0
  220. package/dist/src/core/turn.js.map +1 -1
  221. package/dist/src/core/turn.test.js +4 -1
  222. package/dist/src/core/turn.test.js.map +1 -1
  223. package/dist/src/generated/git-commit.d.ts +2 -2
  224. package/dist/src/generated/git-commit.js +2 -2
  225. package/dist/src/hooks/hookAggregator.d.ts +1 -2
  226. package/dist/src/hooks/hookAggregator.js +1 -2
  227. package/dist/src/hooks/hookAggregator.js.map +1 -1
  228. package/dist/src/hooks/hookEventHandler.d.ts +2 -2
  229. package/dist/src/hooks/hookEventHandler.js +13 -4
  230. package/dist/src/hooks/hookEventHandler.js.map +1 -1
  231. package/dist/src/hooks/hookEventHandler.test.js +1 -2
  232. package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
  233. package/dist/src/hooks/hookPlanner.d.ts +1 -2
  234. package/dist/src/hooks/hookPlanner.js.map +1 -1
  235. package/dist/src/hooks/hookRegistry.d.ts +8 -0
  236. package/dist/src/hooks/hookRegistry.js +31 -3
  237. package/dist/src/hooks/hookRegistry.js.map +1 -1
  238. package/dist/src/hooks/hookRegistry.test.js.map +1 -1
  239. package/dist/src/hooks/hookRunner.d.ts +5 -2
  240. package/dist/src/hooks/hookRunner.js +52 -2
  241. package/dist/src/hooks/hookRunner.js.map +1 -1
  242. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  243. package/dist/src/hooks/hookSystem.d.ts +11 -3
  244. package/dist/src/hooks/hookSystem.js +10 -4
  245. package/dist/src/hooks/hookSystem.js.map +1 -1
  246. package/dist/src/hooks/hookSystem.test.js +1 -0
  247. package/dist/src/hooks/hookSystem.test.js.map +1 -1
  248. package/dist/src/hooks/runtimeHooks.test.d.ts +6 -0
  249. package/dist/src/hooks/runtimeHooks.test.js +100 -0
  250. package/dist/src/hooks/runtimeHooks.test.js.map +1 -0
  251. package/dist/src/hooks/trustedHooks.js +6 -1
  252. package/dist/src/hooks/trustedHooks.js.map +1 -1
  253. package/dist/src/hooks/trustedHooks.test.js +17 -9
  254. package/dist/src/hooks/trustedHooks.test.js.map +1 -1
  255. package/dist/src/hooks/types.d.ts +49 -8
  256. package/dist/src/hooks/types.js +20 -1
  257. package/dist/src/hooks/types.js.map +1 -1
  258. package/dist/src/ide/detect-ide.d.ts +0 -1
  259. package/dist/src/ide/detect-ide.js +1 -1
  260. package/dist/src/ide/detect-ide.js.map +1 -1
  261. package/dist/src/ide/ide-client.js +3 -2
  262. package/dist/src/ide/ide-client.js.map +1 -1
  263. package/dist/src/ide/ide-connection-utils.js +90 -14
  264. package/dist/src/ide/ide-connection-utils.js.map +1 -1
  265. package/dist/src/ide/ide-connection-utils.test.js +78 -0
  266. package/dist/src/ide/ide-connection-utils.test.js.map +1 -1
  267. package/dist/src/ide/ide-installer.test.js +1 -2
  268. package/dist/src/ide/ide-installer.test.js.map +1 -1
  269. package/dist/src/ide/process-utils.d.ts +7 -0
  270. package/dist/src/ide/process-utils.js +20 -0
  271. package/dist/src/ide/process-utils.js.map +1 -1
  272. package/dist/src/ide/process-utils.test.js +30 -0
  273. package/dist/src/ide/process-utils.test.js.map +1 -1
  274. package/dist/src/index.d.ts +6 -1
  275. package/dist/src/index.js +6 -1
  276. package/dist/src/index.js.map +1 -1
  277. package/dist/src/mcp/oauth-provider.d.ts +1 -1
  278. package/dist/src/mcp/oauth-provider.js +8 -7
  279. package/dist/src/mcp/oauth-provider.js.map +1 -1
  280. package/dist/src/mcp/oauth-provider.test.js +34 -2
  281. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  282. package/dist/src/mcp/oauth-utils.js +2 -0
  283. package/dist/src/mcp/oauth-utils.js.map +1 -1
  284. package/dist/src/mcp/oauth-utils.test.js +12 -0
  285. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  286. package/dist/src/mcp/token-storage/file-token-storage.js +4 -1
  287. package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
  288. package/dist/src/mcp/token-storage/file-token-storage.test.js +40 -2
  289. package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -1
  290. package/dist/src/mcp/token-storage/keychain-token-storage.js +2 -0
  291. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  292. package/dist/src/policy/config.d.ts +18 -9
  293. package/dist/src/policy/config.js +75 -54
  294. package/dist/src/policy/config.js.map +1 -1
  295. package/dist/src/policy/config.test.js +26 -26
  296. package/dist/src/policy/integrity.d.ts +45 -0
  297. package/dist/src/policy/integrity.js +121 -0
  298. package/dist/src/policy/integrity.js.map +1 -0
  299. package/dist/src/policy/integrity.test.d.ts +6 -0
  300. package/dist/src/policy/integrity.test.js +132 -0
  301. package/dist/src/policy/integrity.test.js.map +1 -0
  302. package/dist/src/policy/persistence.test.js +29 -19
  303. package/dist/src/policy/persistence.test.js.map +1 -1
  304. package/dist/src/policy/policies/conseca.toml +6 -0
  305. package/dist/src/policy/policies/plan.toml +28 -12
  306. package/dist/src/policy/policies/read-only.toml +11 -10
  307. package/dist/src/policy/policies/write.toml +11 -10
  308. package/dist/src/policy/policies/yolo.toml +11 -10
  309. package/dist/src/policy/policy-engine.d.ts +16 -3
  310. package/dist/src/policy/policy-engine.js +154 -29
  311. package/dist/src/policy/policy-engine.js.map +1 -1
  312. package/dist/src/policy/policy-engine.test.js +480 -9
  313. package/dist/src/policy/policy-engine.test.js.map +1 -1
  314. package/dist/src/policy/policy-updater.test.js +11 -6
  315. package/dist/src/policy/policy-updater.test.js.map +1 -1
  316. package/dist/src/policy/toml-loader.d.ts +13 -2
  317. package/dist/src/policy/toml-loader.js +55 -34
  318. package/dist/src/policy/toml-loader.js.map +1 -1
  319. package/dist/src/policy/toml-loader.test.js +115 -7
  320. package/dist/src/policy/toml-loader.test.js.map +1 -1
  321. package/dist/src/policy/types.d.ts +18 -1
  322. package/dist/src/policy/types.js +1 -0
  323. package/dist/src/policy/types.js.map +1 -1
  324. package/dist/src/policy/workspace-policy.test.d.ts +6 -0
  325. package/dist/src/policy/workspace-policy.test.js +231 -0
  326. package/dist/src/policy/workspace-policy.test.js.map +1 -0
  327. package/dist/src/prompts/promptProvider.js +11 -13
  328. package/dist/src/prompts/promptProvider.js.map +1 -1
  329. package/dist/src/prompts/promptProvider.test.js +64 -3
  330. package/dist/src/prompts/promptProvider.test.js.map +1 -1
  331. package/dist/src/prompts/snippets.js +41 -10
  332. package/dist/src/prompts/snippets.js.map +1 -1
  333. package/dist/src/prompts/snippets.legacy.js +1 -0
  334. package/dist/src/prompts/snippets.legacy.js.map +1 -1
  335. package/dist/src/routing/modelRouterService.js +3 -1
  336. package/dist/src/routing/modelRouterService.js.map +1 -1
  337. package/dist/src/routing/modelRouterService.test.js +12 -6
  338. package/dist/src/routing/modelRouterService.test.js.map +1 -1
  339. package/dist/src/routing/strategies/approvalModeStrategy.d.ts +18 -0
  340. package/dist/src/routing/strategies/approvalModeStrategy.js +58 -0
  341. package/dist/src/routing/strategies/approvalModeStrategy.js.map +1 -0
  342. package/dist/src/routing/strategies/approvalModeStrategy.test.d.ts +6 -0
  343. package/dist/src/routing/strategies/approvalModeStrategy.test.js +110 -0
  344. package/dist/src/routing/strategies/approvalModeStrategy.test.js.map +1 -0
  345. package/dist/src/safety/checker-runner.js +1 -0
  346. package/dist/src/safety/checker-runner.js.map +1 -1
  347. package/dist/src/safety/conseca/conseca.d.ts +31 -0
  348. package/dist/src/safety/conseca/conseca.js +105 -0
  349. package/dist/src/safety/conseca/conseca.js.map +1 -0
  350. package/dist/src/safety/conseca/conseca.test.d.ts +6 -0
  351. package/dist/src/safety/conseca/conseca.test.js +226 -0
  352. package/dist/src/safety/conseca/conseca.test.js.map +1 -0
  353. package/dist/src/safety/conseca/integration.test.d.ts +6 -0
  354. package/dist/src/safety/conseca/integration.test.js +19 -0
  355. package/dist/src/safety/conseca/integration.test.js.map +1 -0
  356. package/dist/src/safety/conseca/policy-enforcer.d.ts +13 -0
  357. package/dist/src/safety/conseca/policy-enforcer.js +135 -0
  358. package/dist/src/safety/conseca/policy-enforcer.js.map +1 -0
  359. package/dist/src/safety/conseca/policy-enforcer.test.d.ts +6 -0
  360. package/dist/src/safety/conseca/policy-enforcer.test.js +141 -0
  361. package/dist/src/safety/conseca/policy-enforcer.test.js.map +1 -0
  362. package/dist/src/safety/conseca/policy-generator.d.ts +15 -0
  363. package/dist/src/safety/conseca/policy-generator.js +144 -0
  364. package/dist/src/safety/conseca/policy-generator.js.map +1 -0
  365. package/dist/src/safety/conseca/policy-generator.test.d.ts +6 -0
  366. package/dist/src/safety/conseca/policy-generator.test.js +84 -0
  367. package/dist/src/safety/conseca/policy-generator.test.js.map +1 -0
  368. package/dist/src/safety/conseca/types.d.ts +15 -0
  369. package/dist/src/safety/conseca/types.js +7 -0
  370. package/dist/src/safety/conseca/types.js.map +1 -0
  371. package/dist/src/safety/context-builder.d.ts +3 -3
  372. package/dist/src/safety/context-builder.js +60 -4
  373. package/dist/src/safety/context-builder.js.map +1 -1
  374. package/dist/src/safety/context-builder.test.js +98 -18
  375. package/dist/src/safety/context-builder.test.js.map +1 -1
  376. package/dist/src/safety/protocol.d.ts +4 -0
  377. package/dist/src/safety/registry.d.ts +2 -1
  378. package/dist/src/safety/registry.js +14 -4
  379. package/dist/src/safety/registry.js.map +1 -1
  380. package/dist/src/safety/registry.test.js +5 -2
  381. package/dist/src/safety/registry.test.js.map +1 -1
  382. package/dist/src/scheduler/confirmation.d.ts +0 -13
  383. package/dist/src/scheduler/confirmation.js +1 -1
  384. package/dist/src/scheduler/confirmation.js.map +1 -1
  385. package/dist/src/scheduler/policy.js +6 -2
  386. package/dist/src/scheduler/policy.js.map +1 -1
  387. package/dist/src/scheduler/policy.test.js +4 -3
  388. package/dist/src/scheduler/policy.test.js.map +1 -1
  389. package/dist/src/scheduler/scheduler.d.ts +3 -1
  390. package/dist/src/scheduler/scheduler.js +148 -28
  391. package/dist/src/scheduler/scheduler.js.map +1 -1
  392. package/dist/src/scheduler/scheduler.test.js +341 -242
  393. package/dist/src/scheduler/scheduler.test.js.map +1 -1
  394. package/dist/src/scheduler/scheduler_parallel.test.d.ts +6 -0
  395. package/dist/src/scheduler/scheduler_parallel.test.js +309 -0
  396. package/dist/src/scheduler/scheduler_parallel.test.js.map +1 -0
  397. package/dist/src/scheduler/state-manager.d.ts +8 -0
  398. package/dist/src/scheduler/state-manager.js +30 -2
  399. package/dist/src/scheduler/state-manager.js.map +1 -1
  400. package/dist/src/scheduler/state-manager.test.js +61 -0
  401. package/dist/src/scheduler/state-manager.test.js.map +1 -1
  402. package/dist/src/scheduler/tool-executor.js +15 -7
  403. package/dist/src/scheduler/tool-executor.js.map +1 -1
  404. package/dist/src/scheduler/tool-executor.test.js +1 -1
  405. package/dist/src/scheduler/tool-executor.test.js.map +1 -1
  406. package/dist/src/scheduler/types.d.ts +23 -0
  407. package/dist/src/services/FolderTrustDiscoveryService.d.ts +32 -0
  408. package/dist/src/services/FolderTrustDiscoveryService.js +167 -0
  409. package/dist/src/services/FolderTrustDiscoveryService.js.map +1 -0
  410. package/dist/src/services/FolderTrustDiscoveryService.test.d.ts +6 -0
  411. package/dist/src/services/FolderTrustDiscoveryService.test.js +118 -0
  412. package/dist/src/services/FolderTrustDiscoveryService.test.js.map +1 -0
  413. package/dist/src/services/chatCompressionService.d.ts +0 -14
  414. package/dist/src/services/chatCompressionService.js +29 -7
  415. package/dist/src/services/chatCompressionService.js.map +1 -1
  416. package/dist/src/services/chatCompressionService.test.js +3 -1
  417. package/dist/src/services/chatCompressionService.test.js.map +1 -1
  418. package/dist/src/services/chatRecordingService.d.ts +7 -1
  419. package/dist/src/services/chatRecordingService.js +12 -1
  420. package/dist/src/services/chatRecordingService.js.map +1 -1
  421. package/dist/src/services/chatRecordingService.test.js +34 -0
  422. package/dist/src/services/chatRecordingService.test.js.map +1 -1
  423. package/dist/src/services/loopDetectionService.js +1 -2
  424. package/dist/src/services/loopDetectionService.js.map +1 -1
  425. package/dist/src/services/sessionSummaryUtils.js +3 -0
  426. package/dist/src/services/sessionSummaryUtils.js.map +1 -1
  427. package/dist/src/services/shellExecutionService.js +6 -0
  428. package/dist/src/services/shellExecutionService.js.map +1 -1
  429. package/dist/src/skills/skillLoader.js +2 -2
  430. package/dist/src/skills/skillLoader.js.map +1 -1
  431. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +3 -1
  432. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +35 -4
  433. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  434. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +0 -1
  435. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +19 -5
  436. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  437. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +14 -1
  438. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +29 -1
  439. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  440. package/dist/src/telemetry/conseca-logger.d.ts +9 -0
  441. package/dist/src/telemetry/conseca-logger.js +91 -0
  442. package/dist/src/telemetry/conseca-logger.js.map +1 -0
  443. package/dist/src/telemetry/conseca-logger.test.d.ts +6 -0
  444. package/dist/src/telemetry/conseca-logger.test.js +89 -0
  445. package/dist/src/telemetry/conseca-logger.test.js.map +1 -0
  446. package/dist/src/telemetry/gcp-exporters.js +1 -2
  447. package/dist/src/telemetry/gcp-exporters.js.map +1 -1
  448. package/dist/src/telemetry/index.d.ts +2 -1
  449. package/dist/src/telemetry/index.js +2 -1
  450. package/dist/src/telemetry/index.js.map +1 -1
  451. package/dist/src/telemetry/integration.test.circular.js +3 -0
  452. package/dist/src/telemetry/integration.test.circular.js.map +1 -1
  453. package/dist/src/telemetry/loggers.d.ts +1 -2
  454. package/dist/src/telemetry/loggers.js +3 -13
  455. package/dist/src/telemetry/loggers.js.map +1 -1
  456. package/dist/src/telemetry/loggers.test.circular.js +3 -0
  457. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  458. package/dist/src/telemetry/loggers.test.js +6 -5
  459. package/dist/src/telemetry/loggers.test.js.map +1 -1
  460. package/dist/src/telemetry/metrics.d.ts +1 -3
  461. package/dist/src/telemetry/metrics.js +3 -2
  462. package/dist/src/telemetry/metrics.js.map +1 -1
  463. package/dist/src/telemetry/metrics.test.js +7 -3
  464. package/dist/src/telemetry/metrics.test.js.map +1 -1
  465. package/dist/src/telemetry/sanitize.test.js +19 -18
  466. package/dist/src/telemetry/sanitize.test.js.map +1 -1
  467. package/dist/src/telemetry/semantic.d.ts +7 -9
  468. package/dist/src/telemetry/semantic.js +8 -8
  469. package/dist/src/telemetry/semantic.js.map +1 -1
  470. package/dist/src/telemetry/types.d.ts +42 -4
  471. package/dist/src/telemetry/types.js +87 -2
  472. package/dist/src/telemetry/types.js.map +1 -1
  473. package/dist/src/telemetry/uiTelemetry.d.ts +1 -2
  474. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  475. package/dist/src/telemetry/uiTelemetry.test.js +1 -2
  476. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  477. package/dist/src/tools/ask-user.test.js +1 -19
  478. package/dist/src/tools/ask-user.test.js.map +1 -1
  479. package/dist/src/tools/confirmation-policy.test.js +14 -17
  480. package/dist/src/tools/confirmation-policy.test.js.map +1 -1
  481. package/dist/src/tools/definitions/dynamic-declaration-helpers.js +1 -1
  482. package/dist/src/tools/definitions/dynamic-declaration-helpers.js.map +1 -1
  483. package/dist/src/tools/definitions/model-family-sets/default-legacy.js +14 -16
  484. package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
  485. package/dist/src/tools/definitions/model-family-sets/gemini-3.js +24 -59
  486. package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
  487. package/dist/src/tools/diff-utils.d.ts +9 -0
  488. package/dist/src/tools/diff-utils.js +66 -0
  489. package/dist/src/tools/diff-utils.js.map +1 -0
  490. package/dist/src/tools/diff-utils.test.d.ts +6 -0
  491. package/dist/src/tools/diff-utils.test.js +53 -0
  492. package/dist/src/tools/diff-utils.test.js.map +1 -0
  493. package/dist/src/tools/edit.d.ts +9 -4
  494. package/dist/src/tools/edit.js +203 -34
  495. package/dist/src/tools/edit.js.map +1 -1
  496. package/dist/src/tools/edit.test.js +225 -10
  497. package/dist/src/tools/edit.test.js.map +1 -1
  498. package/dist/src/tools/enter-plan-mode.js +1 -1
  499. package/dist/src/tools/enter-plan-mode.js.map +1 -1
  500. package/dist/src/tools/enter-plan-mode.test.js +1 -1
  501. package/dist/src/tools/enter-plan-mode.test.js.map +1 -1
  502. package/dist/src/tools/exit-plan-mode.js +10 -24
  503. package/dist/src/tools/exit-plan-mode.js.map +1 -1
  504. package/dist/src/tools/exit-plan-mode.test.js +1 -1
  505. package/dist/src/tools/exit-plan-mode.test.js.map +1 -1
  506. package/dist/src/tools/grep-utils.d.ts +49 -0
  507. package/dist/src/tools/grep-utils.js +139 -0
  508. package/dist/src/tools/grep-utils.js.map +1 -0
  509. package/dist/src/tools/grep.js +4 -44
  510. package/dist/src/tools/grep.js.map +1 -1
  511. package/dist/src/tools/grep.test.js +21 -2
  512. package/dist/src/tools/grep.test.js.map +1 -1
  513. package/dist/src/tools/ls.js +6 -1
  514. package/dist/src/tools/ls.js.map +1 -1
  515. package/dist/src/tools/ls.test.js +2 -2
  516. package/dist/src/tools/ls.test.js.map +1 -1
  517. package/dist/src/tools/mcp-client-manager.js +16 -18
  518. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  519. package/dist/src/tools/mcp-client-manager.test.js +51 -0
  520. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  521. package/dist/src/tools/mcp-client.d.ts +22 -1
  522. package/dist/src/tools/mcp-client.js +95 -36
  523. package/dist/src/tools/mcp-client.js.map +1 -1
  524. package/dist/src/tools/mcp-client.test.js +148 -20
  525. package/dist/src/tools/mcp-client.test.js.map +1 -1
  526. package/dist/src/tools/mcp-tool.d.ts +15 -5
  527. package/dist/src/tools/mcp-tool.js +36 -8
  528. package/dist/src/tools/mcp-tool.js.map +1 -1
  529. package/dist/src/tools/memoryTool.js +1 -1
  530. package/dist/src/tools/memoryTool.js.map +1 -1
  531. package/dist/src/tools/memoryTool.test.js +5 -0
  532. package/dist/src/tools/memoryTool.test.js.map +1 -1
  533. package/dist/src/tools/omissionPlaceholderDetector.d.ts +15 -0
  534. package/dist/src/tools/omissionPlaceholderDetector.js +90 -0
  535. package/dist/src/tools/omissionPlaceholderDetector.js.map +1 -0
  536. package/dist/src/tools/omissionPlaceholderDetector.test.d.ts +6 -0
  537. package/dist/src/tools/omissionPlaceholderDetector.test.js +49 -0
  538. package/dist/src/tools/omissionPlaceholderDetector.test.js.map +1 -0
  539. package/dist/src/tools/read-file.d.ts +4 -4
  540. package/dist/src/tools/read-file.js +17 -10
  541. package/dist/src/tools/read-file.js.map +1 -1
  542. package/dist/src/tools/read-file.test.js +20 -10
  543. package/dist/src/tools/read-file.test.js.map +1 -1
  544. package/dist/src/tools/ripGrep.js +49 -46
  545. package/dist/src/tools/ripGrep.js.map +1 -1
  546. package/dist/src/tools/ripGrep.test.js +52 -37
  547. package/dist/src/tools/ripGrep.test.js.map +1 -1
  548. package/dist/src/tools/shell.d.ts +2 -2
  549. package/dist/src/tools/shell.js +2 -2
  550. package/dist/src/tools/shell.js.map +1 -1
  551. package/dist/src/tools/shell.test.js +1 -2
  552. package/dist/src/tools/shell.test.js.map +1 -1
  553. package/dist/src/tools/tool-names.d.ts +0 -6
  554. package/dist/src/tools/tool-names.js +0 -15
  555. package/dist/src/tools/tool-names.js.map +1 -1
  556. package/dist/src/tools/tool-registry.d.ts +1 -0
  557. package/dist/src/tools/tool-registry.js +33 -6
  558. package/dist/src/tools/tool-registry.js.map +1 -1
  559. package/dist/src/tools/tool-registry.test.js +47 -0
  560. package/dist/src/tools/tool-registry.test.js.map +1 -1
  561. package/dist/src/tools/tools.d.ts +21 -1
  562. package/dist/src/tools/tools.js +19 -3
  563. package/dist/src/tools/tools.js.map +1 -1
  564. package/dist/src/tools/tools.test.js +24 -0
  565. package/dist/src/tools/tools.test.js.map +1 -1
  566. package/dist/src/tools/web-fetch.d.ts +9 -1
  567. package/dist/src/tools/web-fetch.js +273 -34
  568. package/dist/src/tools/web-fetch.js.map +1 -1
  569. package/dist/src/tools/web-fetch.test.js +303 -30
  570. package/dist/src/tools/web-fetch.test.js.map +1 -1
  571. package/dist/src/tools/write-file.js +14 -10
  572. package/dist/src/tools/write-file.js.map +1 -1
  573. package/dist/src/tools/write-file.test.js +75 -0
  574. package/dist/src/tools/write-file.test.js.map +1 -1
  575. package/dist/src/tools/write-todos.d.ts +2 -2
  576. package/dist/src/tools/write-todos.js +1 -1
  577. package/dist/src/tools/write-todos.js.map +1 -1
  578. package/dist/src/tools/xcode-mcp-fix-transport.js +4 -1
  579. package/dist/src/tools/xcode-mcp-fix-transport.js.map +1 -1
  580. package/dist/src/utils/approvalModeUtils.d.ts +14 -0
  581. package/dist/src/utils/approvalModeUtils.js +35 -0
  582. package/dist/src/utils/approvalModeUtils.js.map +1 -0
  583. package/dist/src/utils/approvalModeUtils.test.d.ts +6 -0
  584. package/dist/src/utils/approvalModeUtils.test.js +36 -0
  585. package/dist/src/utils/approvalModeUtils.test.js.map +1 -0
  586. package/dist/src/utils/authConsent.d.ts +1 -1
  587. package/dist/src/utils/authConsent.js +10 -8
  588. package/dist/src/utils/authConsent.js.map +1 -1
  589. package/dist/src/utils/authConsent.test.js +89 -44
  590. package/dist/src/utils/authConsent.test.js.map +1 -1
  591. package/dist/src/utils/compatibility.d.ts +41 -0
  592. package/dist/src/utils/compatibility.js +112 -0
  593. package/dist/src/utils/compatibility.js.map +1 -0
  594. package/dist/src/utils/compatibility.test.d.ts +6 -0
  595. package/dist/src/utils/compatibility.test.js +233 -0
  596. package/dist/src/utils/compatibility.test.js.map +1 -0
  597. package/dist/src/utils/editCorrector.js +22 -29
  598. package/dist/src/utils/editCorrector.js.map +1 -1
  599. package/dist/src/utils/editCorrector.test.js.map +1 -1
  600. package/dist/src/utils/envExpansion.d.ts +18 -0
  601. package/dist/src/utils/envExpansion.js +46 -0
  602. package/dist/src/utils/envExpansion.js.map +1 -0
  603. package/dist/src/utils/envExpansion.test.d.ts +6 -0
  604. package/dist/src/utils/envExpansion.test.js +110 -0
  605. package/dist/src/utils/envExpansion.test.js.map +1 -0
  606. package/dist/src/utils/errors.d.ts +1 -0
  607. package/dist/src/utils/errors.js +55 -10
  608. package/dist/src/utils/errors.js.map +1 -1
  609. package/dist/src/utils/errors.test.js +27 -1
  610. package/dist/src/utils/errors.test.js.map +1 -1
  611. package/dist/src/utils/events.d.ts +17 -0
  612. package/dist/src/utils/events.js +12 -0
  613. package/dist/src/utils/events.js.map +1 -1
  614. package/dist/src/utils/events.test.d.ts +1 -1
  615. package/dist/src/utils/events.test.js +50 -3
  616. package/dist/src/utils/events.test.js.map +1 -1
  617. package/dist/src/utils/fastAckHelper.js +2 -1
  618. package/dist/src/utils/fastAckHelper.js.map +1 -1
  619. package/dist/src/utils/fetch.d.ts +1 -1
  620. package/dist/src/utils/fetch.js +15 -2
  621. package/dist/src/utils/fetch.js.map +1 -1
  622. package/dist/src/utils/fileDiffUtils.d.ts +2 -2
  623. package/dist/src/utils/fileDiffUtils.js +1 -2
  624. package/dist/src/utils/fileDiffUtils.js.map +1 -1
  625. package/dist/src/utils/fileUtils.d.ts +5 -3
  626. package/dist/src/utils/fileUtils.js +25 -16
  627. package/dist/src/utils/fileUtils.js.map +1 -1
  628. package/dist/src/utils/fileUtils.test.js +14 -13
  629. package/dist/src/utils/fileUtils.test.js.map +1 -1
  630. package/dist/src/utils/filesearch/fileSearch.js +4 -1
  631. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  632. package/dist/src/utils/getFolderStructure.test.js +4 -5
  633. package/dist/src/utils/getFolderStructure.test.js.map +1 -1
  634. package/dist/src/utils/getPty.js +4 -0
  635. package/dist/src/utils/getPty.js.map +1 -1
  636. package/dist/src/utils/googleErrors.js +29 -5
  637. package/dist/src/utils/googleErrors.js.map +1 -1
  638. package/dist/src/utils/googleQuotaErrors.js +10 -0
  639. package/dist/src/utils/googleQuotaErrors.js.map +1 -1
  640. package/dist/src/utils/googleQuotaErrors.test.js +16 -1
  641. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
  642. package/dist/src/utils/memoryDiscovery.js +2 -0
  643. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  644. package/dist/src/utils/memoryDiscovery.test.js +1 -2
  645. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  646. package/dist/src/utils/retry.d.ts +1 -1
  647. package/dist/src/utils/retry.js +9 -4
  648. package/dist/src/utils/retry.js.map +1 -1
  649. package/dist/src/utils/retry.test.js +15 -12
  650. package/dist/src/utils/retry.test.js.map +1 -1
  651. package/dist/src/utils/safeJsonStringify.js +3 -0
  652. package/dist/src/utils/safeJsonStringify.js.map +1 -1
  653. package/dist/src/utils/schemaValidator.js +5 -3
  654. package/dist/src/utils/schemaValidator.js.map +1 -1
  655. package/dist/src/utils/session.d.ts +1 -0
  656. package/dist/src/utils/session.js +3 -0
  657. package/dist/src/utils/session.js.map +1 -1
  658. package/dist/src/utils/sessionUtils.d.ts +14 -0
  659. package/dist/src/utils/sessionUtils.js +113 -0
  660. package/dist/src/utils/sessionUtils.js.map +1 -0
  661. package/dist/src/utils/sessionUtils.test.d.ts +1 -0
  662. package/dist/src/utils/sessionUtils.test.js +137 -0
  663. package/dist/src/utils/sessionUtils.test.js.map +1 -0
  664. package/dist/src/utils/shell-utils.js +1 -0
  665. package/dist/src/utils/shell-utils.js.map +1 -1
  666. package/dist/src/utils/stdio.js +6 -0
  667. package/dist/src/utils/stdio.js.map +1 -1
  668. package/dist/src/utils/textUtils.d.ts +9 -0
  669. package/dist/src/utils/textUtils.js +15 -0
  670. package/dist/src/utils/textUtils.js.map +1 -1
  671. package/dist/src/utils/textUtils.test.js +42 -1
  672. package/dist/src/utils/textUtils.test.js.map +1 -1
  673. package/dist/src/utils/toolCallContext.d.ts +0 -5
  674. package/dist/src/utils/toolCallContext.js +1 -1
  675. package/dist/src/utils/toolCallContext.js.map +1 -1
  676. package/dist/src/utils/userAccountManager.js +3 -0
  677. package/dist/src/utils/userAccountManager.js.map +1 -1
  678. package/dist/tsconfig.tsbuildinfo +1 -1
  679. package/package.json +6 -3
  680. package/dist/docs/architecture.md +0 -80
  681. package/dist/docs/cli/index.md +0 -123
  682. package/dist/docs/core/concepts.md +0 -137
  683. package/dist/docs/get-started/configuration-v1.md +0 -882
  684. package/dist/google-gemini-cli-core-0.30.0-preview.5.tgz +0 -0
  685. /package/dist/docs/{core → reference}/memport.md +0 -0
  686. /package/dist/docs/{core → reference}/tools-api.md +0 -0
  687. /package/dist/docs/{cli → resources}/uninstall.md +0 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as Diff from 'diff';
7
+ /**
8
+ * Generates a snippet of the diff between two strings, including a few lines of context around the changes.
9
+ */
10
+ export function getDiffContextSnippet(originalContent, newContent, contextLines = 5) {
11
+ if (!originalContent) {
12
+ return newContent;
13
+ }
14
+ const changes = Diff.diffLines(originalContent, newContent);
15
+ const newLines = newContent.split(/\r?\n/);
16
+ const ranges = [];
17
+ let newLineIdx = 0;
18
+ for (const change of changes) {
19
+ if (change.added) {
20
+ ranges.push({ start: newLineIdx, end: newLineIdx + (change.count ?? 0) });
21
+ newLineIdx += change.count ?? 0;
22
+ }
23
+ else if (change.removed) {
24
+ ranges.push({ start: newLineIdx, end: newLineIdx });
25
+ }
26
+ else {
27
+ newLineIdx += change.count ?? 0;
28
+ }
29
+ }
30
+ if (ranges.length === 0) {
31
+ return newContent;
32
+ }
33
+ const expandedRanges = ranges.map((r) => ({
34
+ start: Math.max(0, r.start - contextLines),
35
+ end: Math.min(newLines.length, r.end + contextLines),
36
+ }));
37
+ expandedRanges.sort((a, b) => a.start - b.start);
38
+ const mergedRanges = [];
39
+ if (expandedRanges.length > 0) {
40
+ let current = expandedRanges[0];
41
+ for (let i = 1; i < expandedRanges.length; i++) {
42
+ const next = expandedRanges[i];
43
+ if (next.start <= current.end) {
44
+ current.end = Math.max(current.end, next.end);
45
+ }
46
+ else {
47
+ mergedRanges.push(current);
48
+ current = next;
49
+ }
50
+ }
51
+ mergedRanges.push(current);
52
+ }
53
+ const outputParts = [];
54
+ let lastEnd = 0;
55
+ for (const range of mergedRanges) {
56
+ if (range.start > lastEnd)
57
+ outputParts.push('...');
58
+ outputParts.push(newLines.slice(range.start, range.end).join('\n'));
59
+ lastEnd = range.end;
60
+ }
61
+ if (lastEnd < newLines.length) {
62
+ outputParts.push('...');
63
+ }
64
+ return outputParts.join('\n');
65
+ }
66
+ //# sourceMappingURL=diff-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.js","sourceRoot":"","sources":["../../../src/tools/diff-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, expect, it } from 'vitest';
7
+ import { getDiffContextSnippet } from './diff-utils.js';
8
+ describe('getDiffContextSnippet', () => {
9
+ it('should return the whole new content if originalContent is empty', () => {
10
+ const original = '';
11
+ const modified = 'line1\nline2\nline3';
12
+ expect(getDiffContextSnippet(original, modified)).toBe(modified);
13
+ });
14
+ it('should return the whole content if there are no changes', () => {
15
+ const content = 'line1\nline2\nline3';
16
+ expect(getDiffContextSnippet(content, content)).toBe(content);
17
+ });
18
+ it('should show added lines with context', () => {
19
+ const original = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10';
20
+ const modified = '1\n2\n3\n4\n5\nadded\n6\n7\n8\n9\n10';
21
+ // Default context is 5 lines.
22
+ expect(getDiffContextSnippet(original, modified)).toBe(modified);
23
+ });
24
+ it('should use ellipses for changes far apart', () => {
25
+ const original = Array.from({ length: 20 }, (_, i) => `${i + 1}`).join('\n');
26
+ const modified = original
27
+ .replace('2\n', '2\nadded1\n')
28
+ .replace('19', '19\nadded2');
29
+ const snippet = getDiffContextSnippet(original, modified, 2);
30
+ expect(snippet).toContain('1\n2\nadded1\n3\n4');
31
+ expect(snippet).toContain('...');
32
+ expect(snippet).toContain('18\n19\nadded2\n20');
33
+ });
34
+ it('should respect custom contextLines', () => {
35
+ const original = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10';
36
+ const modified = '1\n2\n3\n4\n5\nadded\n6\n7\n8\n9\n10';
37
+ const snippet = getDiffContextSnippet(original, modified, 1);
38
+ expect(snippet).toBe('...\n5\nadded\n6\n...');
39
+ });
40
+ it('should handle multiple changes close together by merging ranges', () => {
41
+ const original = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10';
42
+ const modified = '1\nadded1\n2\nadded2\n3\n4\n5\n6\n7\n8\n9\n10';
43
+ const snippet = getDiffContextSnippet(original, modified, 1);
44
+ expect(snippet).toBe('1\nadded1\n2\nadded2\n3\n...');
45
+ });
46
+ it('should handle removals', () => {
47
+ const original = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10';
48
+ const modified = '1\n2\n3\n4\n6\n7\n8\n9\n10';
49
+ const snippet = getDiffContextSnippet(original, modified, 1);
50
+ expect(snippet).toBe('...\n4\n6\n...');
51
+ });
52
+ });
53
+ //# sourceMappingURL=diff-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-utils.test.js","sourceRoot":"","sources":["../../../src/tools/diff-utils.test.ts"],"names":[],"mappings":"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"}
@@ -18,10 +18,15 @@ interface ReplacementResult {
18
18
  occurrences: number;
19
19
  finalOldString: string;
20
20
  finalNewString: string;
21
+ strategy?: 'exact' | 'flexible' | 'regex' | 'fuzzy';
22
+ matchRanges?: Array<{
23
+ start: number;
24
+ end: number;
25
+ }>;
21
26
  }
22
27
  export declare function applyReplacement(currentContent: string | null, oldString: string, newString: string, isNewFile: boolean): string;
23
28
  export declare function calculateReplacement(config: Config, context: ReplacementContext): Promise<ReplacementResult>;
24
- export declare function getErrorReplaceResult(params: EditToolParams, occurrences: number, expectedReplacements: number, finalOldString: string, finalNewString: string): {
29
+ export declare function getErrorReplaceResult(params: EditToolParams, occurrences: number, finalOldString: string, finalNewString: string): {
25
30
  display: string;
26
31
  raw: string;
27
32
  type: ToolErrorType;
@@ -43,10 +48,10 @@ export interface EditToolParams {
43
48
  */
44
49
  new_string: string;
45
50
  /**
46
- * Number of replacements expected. Defaults to 1 if not specified.
47
- * Use when you want to replace multiple occurrences.
51
+ * If true, the tool will replace all occurrences of `old_string` with `new_string`.
52
+ * If false (default), the tool will only succeed if exactly one occurrence is found.
48
53
  */
49
- expected_replacements?: number;
54
+ allow_multiple?: boolean;
50
55
  /**
51
56
  * The instruction for what needs to be done.
52
57
  */
@@ -8,26 +8,30 @@ import * as path from 'node:path';
8
8
  import * as os from 'node:os';
9
9
  import * as crypto from 'node:crypto';
10
10
  import * as Diff from 'diff';
11
- import { BaseDeclarativeTool, BaseToolInvocation, Kind, ToolConfirmationOutcome, } from './tools.js';
11
+ import { BaseDeclarativeTool, BaseToolInvocation, Kind, } from './tools.js';
12
12
  import { ToolErrorType } from './tool-error.js';
13
13
  import { makeRelative, shortenPath } from '../utils/paths.js';
14
14
  import { isNodeError } from '../utils/errors.js';
15
15
  import { ApprovalMode } from '../policy/types.js';
16
16
  import { CoreToolCallStatus } from '../scheduler/types.js';
17
17
  import { DEFAULT_DIFF_OPTIONS, getDiffStat } from './diffOptions.js';
18
+ import { getDiffContextSnippet } from './diff-utils.js';
18
19
  import {} from './modifiable-tool.js';
19
20
  import { IdeClient } from '../ide/ide-client.js';
20
21
  import { FixLLMEditWithInstruction } from '../utils/llm-edit-fixer.js';
21
22
  import { safeLiteralReplace, detectLineEnding } from '../utils/textUtils.js';
22
- import { EditStrategyEvent } from '../telemetry/types.js';
23
- import { logEditStrategy } from '../telemetry/loggers.js';
24
- import { EditCorrectionEvent } from '../telemetry/types.js';
25
- import { logEditCorrectionEvent } from '../telemetry/loggers.js';
23
+ import { EditStrategyEvent, EditCorrectionEvent } from '../telemetry/types.js';
24
+ import { logEditStrategy, logEditCorrectionEvent, } from '../telemetry/loggers.js';
26
25
  import { correctPath } from '../utils/pathCorrector.js';
27
26
  import { EDIT_TOOL_NAME, READ_FILE_TOOL_NAME, EDIT_DISPLAY_NAME, } from './tool-names.js';
28
27
  import { debugLogger } from '../utils/debugLogger.js';
28
+ import levenshtein from 'fast-levenshtein';
29
29
  import { EDIT_DEFINITION } from './definitions/coreTools.js';
30
30
  import { resolveToolDeclaration } from './definitions/resolver.js';
31
+ import { detectOmissionPlaceholders } from './omissionPlaceholderDetector.js';
32
+ const ENABLE_FUZZY_MATCH_RECOVERY = true;
33
+ const FUZZY_MATCH_THRESHOLD = 0.1; // Allow up to 10% weighted difference
34
+ const WHITESPACE_PENALTY_FACTOR = 0.1; // Whitespace differences cost 10% of a character difference
31
35
  export function applyReplacement(currentContent, oldString, newString, isNewFile) {
32
36
  if (isNewFile) {
33
37
  return newString;
@@ -76,6 +80,14 @@ async function calculateExactReplacement(context) {
76
80
  const normalizedSearch = old_string.replace(/\r\n/g, '\n');
77
81
  const normalizedReplace = new_string.replace(/\r\n/g, '\n');
78
82
  const exactOccurrences = normalizedCode.split(normalizedSearch).length - 1;
83
+ if (!params.allow_multiple && exactOccurrences > 1) {
84
+ return {
85
+ newContent: currentContent,
86
+ occurrences: exactOccurrences,
87
+ finalOldString: normalizedSearch,
88
+ finalNewString: normalizedReplace,
89
+ };
90
+ }
79
91
  if (exactOccurrences > 0) {
80
92
  let modifiedCode = safeLiteralReplace(normalizedCode, normalizedSearch, normalizedReplace);
81
93
  modifiedCode = restoreTrailingNewline(currentContent, modifiedCode);
@@ -110,7 +122,7 @@ async function calculateFlexibleReplacement(context) {
110
122
  const firstLineInMatch = window[0];
111
123
  const indentationMatch = firstLineInMatch.match(/^([ \t]*)/);
112
124
  const indentation = indentationMatch ? indentationMatch[1] : '';
113
- const newBlockWithIndent = replaceLines.map((line) => `${indentation}${line}`);
125
+ const newBlockWithIndent = applyIndentation(replaceLines, indentation);
114
126
  sourceLines.splice(i, searchLinesStripped.length, newBlockWithIndent.join('\n'));
115
127
  i += replaceLines.length;
116
128
  }
@@ -154,22 +166,20 @@ async function calculateRegexReplacement(context) {
154
166
  // The final pattern captures leading whitespace (indentation) and then matches the token pattern.
155
167
  // 'm' flag enables multi-line mode, so '^' matches the start of any line.
156
168
  const finalPattern = `^([ \t]*)${pattern}`;
157
- const flexibleRegex = new RegExp(finalPattern, 'm');
158
- const match = flexibleRegex.exec(currentContent);
159
- if (!match) {
169
+ // Always use a global regex to count all potential occurrences for accurate validation.
170
+ const globalRegex = new RegExp(finalPattern, 'gm');
171
+ const matches = currentContent.match(globalRegex);
172
+ if (!matches) {
160
173
  return null;
161
174
  }
162
- const indentation = match[1] || '';
175
+ const occurrences = matches.length;
163
176
  const newLines = normalizedReplace.split('\n');
164
- const newBlockWithIndent = newLines
165
- .map((line) => `${indentation}${line}`)
166
- .join('\n');
167
- // Use replace with the regex to substitute the matched content.
168
- // Since the regex doesn't have the 'g' flag, it will only replace the first occurrence.
169
- const modifiedCode = currentContent.replace(flexibleRegex, newBlockWithIndent);
177
+ // Use the appropriate regex for replacement based on allow_multiple.
178
+ const replaceRegex = new RegExp(finalPattern, params.allow_multiple ? 'gm' : 'm');
179
+ const modifiedCode = currentContent.replace(replaceRegex, (_match, indentation) => applyIndentation(newLines, indentation || '').join('\n'));
170
180
  return {
171
181
  newContent: restoreTrailingNewline(currentContent, modifiedCode),
172
- occurrences: 1, // This method is designed to find and replace only the first occurrence.
182
+ occurrences,
173
183
  finalOldString: normalizedSearch,
174
184
  finalNewString: normalizedReplace,
175
185
  };
@@ -205,6 +215,11 @@ export async function calculateReplacement(config, context) {
205
215
  logEditStrategy(config, event);
206
216
  return regexResult;
207
217
  }
218
+ let fuzzyResult;
219
+ if (ENABLE_FUZZY_MATCH_RECOVERY &&
220
+ (fuzzyResult = await calculateFuzzyReplacement(config, context))) {
221
+ return fuzzyResult;
222
+ }
208
223
  return {
209
224
  newContent: currentContent,
210
225
  occurrences: 0,
@@ -212,7 +227,7 @@ export async function calculateReplacement(config, context) {
212
227
  finalNewString: normalizedReplace,
213
228
  };
214
229
  }
215
- export function getErrorReplaceResult(params, occurrences, expectedReplacements, finalOldString, finalNewString) {
230
+ export function getErrorReplaceResult(params, occurrences, finalOldString, finalNewString) {
216
231
  let error = undefined;
217
232
  if (occurrences === 0) {
218
233
  error = {
@@ -221,11 +236,10 @@ export function getErrorReplaceResult(params, occurrences, expectedReplacements,
221
236
  type: ToolErrorType.EDIT_NO_OCCURRENCE_FOUND,
222
237
  };
223
238
  }
224
- else if (occurrences !== expectedReplacements) {
225
- const occurrenceTerm = expectedReplacements === 1 ? 'occurrence' : 'occurrences';
239
+ else if (!params.allow_multiple && occurrences !== 1) {
226
240
  error = {
227
- display: `Failed to edit, expected ${expectedReplacements} ${occurrenceTerm} but found ${occurrences}.`,
228
- raw: `Failed to edit, Expected ${expectedReplacements} ${occurrenceTerm} but found ${occurrences} for old_string in file: ${params.file_path}`,
241
+ display: `Failed to edit, expected 1 occurrence but found ${occurrences}.`,
242
+ raw: `Failed to edit, Expected 1 occurrence but found ${occurrences} for old_string in file: ${params.file_path}. If you intended to replace multiple occurrences, set 'allow_multiple' to true.`,
229
243
  type: ToolErrorType.EDIT_EXPECTED_OCCURRENCE_MISMATCH,
230
244
  };
231
245
  }
@@ -298,7 +312,7 @@ class EditToolInvocation extends BaseToolInvocation {
298
312
  currentContent: contentForLlmEditFixer,
299
313
  abortSignal,
300
314
  });
301
- const secondError = getErrorReplaceResult(params, secondAttemptResult.occurrences, params.expected_replacements ?? 1, secondAttemptResult.finalOldString, secondAttemptResult.finalNewString);
315
+ const secondError = getErrorReplaceResult(params, secondAttemptResult.occurrences, secondAttemptResult.finalOldString, secondAttemptResult.finalNewString);
302
316
  if (secondError) {
303
317
  // The fix failed, log failure and return the original error
304
318
  const event = new EditCorrectionEvent('failure');
@@ -321,6 +335,8 @@ class EditToolInvocation extends BaseToolInvocation {
321
335
  isNewFile: false,
322
336
  error: undefined,
323
337
  originalLineEnding,
338
+ strategy: secondAttemptResult.strategy,
339
+ matchRanges: secondAttemptResult.matchRanges,
324
340
  };
325
341
  }
326
342
  /**
@@ -330,7 +346,6 @@ class EditToolInvocation extends BaseToolInvocation {
330
346
  * @throws File system errors if reading the file fails unexpectedly (e.g., permissions)
331
347
  */
332
348
  async calculateEdit(params, abortSignal) {
333
- const expectedReplacements = params.expected_replacements ?? 1;
334
349
  let currentContent = null;
335
350
  let fileExists = false;
336
351
  let originalLineEnding = '\n'; // Default for new files
@@ -407,7 +422,7 @@ class EditToolInvocation extends BaseToolInvocation {
407
422
  currentContent,
408
423
  abortSignal,
409
424
  });
410
- const initialError = getErrorReplaceResult(params, replacementResult.occurrences, expectedReplacements, replacementResult.finalOldString, replacementResult.finalNewString);
425
+ const initialError = getErrorReplaceResult(params, replacementResult.occurrences, replacementResult.finalOldString, replacementResult.finalNewString);
411
426
  if (!initialError) {
412
427
  return {
413
428
  currentContent,
@@ -416,6 +431,8 @@ class EditToolInvocation extends BaseToolInvocation {
416
431
  isNewFile: false,
417
432
  error: undefined,
418
433
  originalLineEnding,
434
+ strategy: replacementResult.strategy,
435
+ matchRanges: replacementResult.matchRanges,
419
436
  };
420
437
  }
421
438
  if (this.config.getDisableLLMCorrection()) {
@@ -469,15 +486,9 @@ class EditToolInvocation extends BaseToolInvocation {
469
486
  fileDiff,
470
487
  originalContent: editData.currentContent,
471
488
  newContent: editData.newContent,
472
- onConfirm: async (outcome) => {
473
- if (outcome === ToolConfirmationOutcome.ProceedAlways) {
474
- // No need to publish a policy update as the default policy for
475
- // AUTO_EDIT already reflects always approving edit.
476
- this.config.setApprovalMode(ApprovalMode.AUTO_EDIT);
477
- }
478
- else {
479
- await this.publishPolicyUpdate(outcome);
480
- }
489
+ onConfirm: async (_outcome) => {
490
+ // Mode transitions (e.g. AUTO_EDIT) and policy updates are now
491
+ // handled centrally by the scheduler.
481
492
  if (ideConfirmation) {
482
493
  const result = await ideConfirmation;
483
494
  if (result.status === 'accepted' && result.content) {
@@ -590,6 +601,15 @@ class EditToolInvocation extends BaseToolInvocation {
590
601
  ? `Created new file: ${this.params.file_path} with provided content.`
591
602
  : `Successfully modified file: ${this.params.file_path} (${editData.occurrences} replacements).`,
592
603
  ];
604
+ // Return a diff of the file before and after the write so that the agent
605
+ // can avoid the need to spend a turn doing a verification read.
606
+ const snippet = getDiffContextSnippet(editData.currentContent ?? '', finalContent, 5);
607
+ llmSuccessMessageParts.push(`Here is the updated code:
608
+ ${snippet}`);
609
+ const fuzzyFeedback = getFuzzyMatchFeedback(editData);
610
+ if (fuzzyFeedback) {
611
+ llmSuccessMessageParts.push(fuzzyFeedback);
612
+ }
593
613
  if (this.params.modified_by_user) {
594
614
  llmSuccessMessageParts.push(`User modified the \`new_string\` content to be: ${this.params.new_string}.`);
595
615
  }
@@ -653,6 +673,15 @@ export class EditTool extends BaseDeclarativeTool {
653
673
  filePath = result.correctedPath;
654
674
  }
655
675
  params.file_path = filePath;
676
+ const newPlaceholders = detectOmissionPlaceholders(params.new_string);
677
+ if (newPlaceholders.length > 0) {
678
+ const oldPlaceholders = new Set(detectOmissionPlaceholders(params.old_string));
679
+ for (const placeholder of newPlaceholders) {
680
+ if (!oldPlaceholders.has(placeholder)) {
681
+ return "`new_string` contains an omission placeholder (for example 'rest of methods ...'). Provide exact literal replacement text.";
682
+ }
683
+ }
684
+ }
656
685
  return this.config.validatePathAccess(params.file_path);
657
686
  }
658
687
  createInvocation(params, messageBus) {
@@ -702,4 +731,144 @@ export class EditTool extends BaseDeclarativeTool {
702
731
  };
703
732
  }
704
733
  }
734
+ function stripWhitespace(str) {
735
+ return str.replace(/\s/g, '');
736
+ }
737
+ /**
738
+ * Applies the target indentation to the lines, while preserving relative indentation.
739
+ * It identifies the common indentation of the provided lines and replaces it with the target indentation.
740
+ */
741
+ function applyIndentation(lines, targetIndentation) {
742
+ if (lines.length === 0)
743
+ return [];
744
+ // Use the first line as the reference for indentation, even if it's empty/whitespace.
745
+ // This is because flexible/fuzzy matching identifies the indentation of the START of the match.
746
+ const referenceLine = lines[0];
747
+ const refIndentMatch = referenceLine.match(/^([ \t]*)/);
748
+ const refIndent = refIndentMatch ? refIndentMatch[1] : '';
749
+ return lines.map((line) => {
750
+ if (line.trim() === '') {
751
+ return '';
752
+ }
753
+ if (line.startsWith(refIndent)) {
754
+ return targetIndentation + line.slice(refIndent.length);
755
+ }
756
+ return targetIndentation + line.trimStart();
757
+ });
758
+ }
759
+ function getFuzzyMatchFeedback(editData) {
760
+ if (editData.strategy === 'fuzzy' &&
761
+ editData.matchRanges &&
762
+ editData.matchRanges.length > 0) {
763
+ const ranges = editData.matchRanges
764
+ .map((r) => (r.start === r.end ? `${r.start}` : `${r.start}-${r.end}`))
765
+ .join(', ');
766
+ return `Applied fuzzy match at line${editData.matchRanges.length > 1 ? 's' : ''} ${ranges}.`;
767
+ }
768
+ return null;
769
+ }
770
+ async function calculateFuzzyReplacement(config, context) {
771
+ const { currentContent, params } = context;
772
+ const { old_string, new_string } = params;
773
+ // Pre-check: Don't fuzzy match very short strings to avoid false positives
774
+ if (old_string.length < 10) {
775
+ return null;
776
+ }
777
+ const normalizedCode = currentContent.replace(/\r\n/g, '\n');
778
+ const normalizedSearch = old_string.replace(/\r\n/g, '\n');
779
+ const normalizedReplace = new_string.replace(/\r\n/g, '\n');
780
+ const sourceLines = normalizedCode.match(/.*(?:\n|$)/g)?.slice(0, -1) ?? [];
781
+ const searchLines = normalizedSearch
782
+ .match(/.*(?:\n|$)/g)
783
+ ?.slice(0, -1)
784
+ .map((l) => l.trimEnd()); // Trim end of search lines to be more robust
785
+ // Limit the scope of the fuzzy match to reduce impact on responsivesness.
786
+ // Each comparison takes roughly O(L^2) time.
787
+ // We perform sourceLines.length comparisons (sliding window).
788
+ // Total complexity proxy: sourceLines.length * old_string.length^2
789
+ // Limit to 4e8 for < 1 second.
790
+ if (sourceLines.length * Math.pow(old_string.length, 2) > 400_000_000) {
791
+ return null;
792
+ }
793
+ if (!searchLines || searchLines.length === 0) {
794
+ return null;
795
+ }
796
+ const N = searchLines.length;
797
+ const candidates = [];
798
+ const searchBlock = searchLines.join('\n');
799
+ // Sliding window
800
+ for (let i = 0; i <= sourceLines.length - N; i++) {
801
+ const windowLines = sourceLines.slice(i, i + N);
802
+ const windowText = windowLines.map((l) => l.trimEnd()).join('\n'); // Normalized join for comparison
803
+ // Length Heuristic Optimization
804
+ const lengthDiff = Math.abs(windowText.length - searchBlock.length);
805
+ if (lengthDiff / searchBlock.length >
806
+ FUZZY_MATCH_THRESHOLD / WHITESPACE_PENALTY_FACTOR) {
807
+ continue;
808
+ }
809
+ // Tiered Scoring
810
+ const d_raw = levenshtein.get(windowText, searchBlock);
811
+ const d_norm = levenshtein.get(stripWhitespace(windowText), stripWhitespace(searchBlock));
812
+ const weightedDist = d_norm + (d_raw - d_norm) * WHITESPACE_PENALTY_FACTOR;
813
+ const score = weightedDist / searchBlock.length;
814
+ if (score <= FUZZY_MATCH_THRESHOLD) {
815
+ candidates.push({ index: i, score });
816
+ }
817
+ }
818
+ if (candidates.length === 0) {
819
+ return null;
820
+ }
821
+ // Select best non-overlapping matches
822
+ // Sort by score ascending. If scores equal, prefer earlier index (stable sort).
823
+ candidates.sort((a, b) => a.score - b.score || a.index - b.index);
824
+ const selectedMatches = [];
825
+ for (const candidate of candidates) {
826
+ // Check for overlap with already selected matches
827
+ // Two windows overlap if their start indices are within N lines of each other
828
+ // (Assuming window size N. Actually overlap is |i - j| < N)
829
+ const overlaps = selectedMatches.some((m) => Math.abs(m.index - candidate.index) < N);
830
+ if (!overlaps) {
831
+ selectedMatches.push(candidate);
832
+ }
833
+ }
834
+ // If we found matches, apply them
835
+ if (selectedMatches.length > 0) {
836
+ const event = new EditStrategyEvent('fuzzy');
837
+ logEditStrategy(config, event);
838
+ // Calculate match ranges before sorting for replacement
839
+ // Indices in selectedMatches are 0-based line indices
840
+ const matchRanges = selectedMatches
841
+ .map((m) => ({ start: m.index + 1, end: m.index + N }))
842
+ .sort((a, b) => a.start - b.start);
843
+ // Sort matches by index descending to apply replacements from bottom to top
844
+ // so that indices remain valid
845
+ selectedMatches.sort((a, b) => b.index - a.index);
846
+ const newLines = normalizedReplace.split('\n');
847
+ for (const match of selectedMatches) {
848
+ // If we want to preserve the indentation of the first line of the match:
849
+ const firstLineMatch = sourceLines[match.index];
850
+ const indentationMatch = firstLineMatch.match(/^([ \t]*)/);
851
+ const indentation = indentationMatch ? indentationMatch[1] : '';
852
+ const indentedReplaceLines = applyIndentation(newLines, indentation);
853
+ let replacementText = indentedReplaceLines.join('\n');
854
+ // If the last line of the match had a newline, preserve it in the replacement
855
+ // to avoid merging with the next line or losing a blank line separator.
856
+ if (sourceLines[match.index + N - 1].endsWith('\n')) {
857
+ replacementText += '\n';
858
+ }
859
+ sourceLines.splice(match.index, N, replacementText);
860
+ }
861
+ let modifiedCode = sourceLines.join('');
862
+ modifiedCode = restoreTrailingNewline(currentContent, modifiedCode);
863
+ return {
864
+ newContent: modifiedCode,
865
+ occurrences: selectedMatches.length,
866
+ finalOldString: normalizedSearch,
867
+ finalNewString: normalizedReplace,
868
+ strategy: 'fuzzy',
869
+ matchRanges,
870
+ };
871
+ }
872
+ return null;
873
+ }
705
874
  //# sourceMappingURL=edit.js.map