@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.
- package/README.md +1 -1
- package/dist/docs/CONTRIBUTING.md +6 -7
- package/dist/docs/changelogs/index.md +22 -2
- package/dist/docs/changelogs/latest.md +359 -293
- package/dist/docs/changelogs/preview.md +300 -349
- package/dist/docs/cli/cli-reference.md +23 -23
- package/dist/docs/cli/enterprise.md +7 -7
- package/dist/docs/cli/gemini-md.md +1 -1
- package/dist/docs/cli/model.md +1 -1
- package/dist/docs/cli/plan-mode.md +180 -80
- package/dist/docs/cli/sandbox.md +3 -3
- package/dist/docs/cli/settings.md +59 -51
- package/dist/docs/cli/telemetry.md +4 -1
- package/dist/docs/cli/themes.md +3 -3
- package/dist/docs/cli/trusted-folders.md +31 -0
- package/dist/docs/cli/tutorials/memory-management.md +2 -2
- package/dist/docs/cli/tutorials/session-management.md +1 -1
- package/dist/docs/core/index.md +7 -7
- package/dist/docs/core/subagents.md +155 -39
- package/dist/docs/extensions/reference.md +38 -14
- package/dist/docs/get-started/authentication.md +4 -4
- package/dist/docs/get-started/examples.md +2 -2
- package/dist/docs/get-started/gemini-3.md +17 -3
- package/dist/docs/get-started/index.md +11 -2
- package/dist/docs/hooks/best-practices.md +1 -1
- package/dist/docs/hooks/reference.md +8 -0
- package/dist/docs/ide-integration/index.md +14 -0
- package/dist/docs/index.md +62 -67
- package/dist/docs/redirects.json +19 -0
- package/dist/docs/{cli → reference}/commands.md +67 -11
- package/dist/docs/{get-started → reference}/configuration.md +93 -24
- package/dist/docs/{cli → reference}/keyboard-shortcuts.md +3 -3
- package/dist/docs/{core → reference}/policy-engine.md +63 -27
- package/dist/docs/{faq.md → resources/faq.md} +1 -1
- package/dist/docs/{quota-and-pricing.md → resources/quota-and-pricing.md} +12 -5
- package/dist/docs/{tos-privacy.md → resources/tos-privacy.md} +2 -2
- package/dist/docs/{troubleshooting.md → resources/troubleshooting.md} +1 -1
- package/dist/docs/sidebar.json +203 -166
- package/dist/docs/tools/file-system.md +7 -4
- package/dist/docs/tools/index.md +5 -2
- package/dist/docs/tools/internal-docs.md +5 -5
- package/dist/docs/tools/mcp-server.md +62 -2
- package/dist/docs/tools/planning.md +2 -0
- package/dist/docs/tools/shell.md +3 -3
- package/dist/src/agents/a2a-client-manager.test.js +1 -2
- package/dist/src/agents/a2a-client-manager.test.js.map +1 -1
- package/dist/src/agents/a2aUtils.d.ts +1 -5
- package/dist/src/agents/a2aUtils.js +1 -1
- package/dist/src/agents/a2aUtils.js.map +1 -1
- package/dist/src/agents/acknowledgedAgents.js +1 -0
- package/dist/src/agents/acknowledgedAgents.js.map +1 -1
- package/dist/src/agents/agent-scheduler.js +1 -0
- package/dist/src/agents/agent-scheduler.js.map +1 -1
- package/dist/src/agents/agentLoader.d.ts +0 -1
- package/dist/src/agents/agentLoader.js +22 -21
- package/dist/src/agents/agentLoader.js.map +1 -1
- package/dist/src/agents/agentLoader.test.js +1 -5
- package/dist/src/agents/agentLoader.test.js.map +1 -1
- package/dist/src/agents/auth-provider/api-key-provider.d.ts +30 -0
- package/dist/src/agents/auth-provider/api-key-provider.js +66 -0
- package/dist/src/agents/auth-provider/api-key-provider.js.map +1 -0
- package/dist/src/agents/auth-provider/api-key-provider.test.d.ts +6 -0
- package/dist/src/agents/auth-provider/api-key-provider.test.js +130 -0
- package/dist/src/agents/auth-provider/api-key-provider.test.js.map +1 -0
- package/dist/src/agents/auth-provider/base-provider.d.ts +2 -2
- package/dist/src/agents/auth-provider/base-provider.js.map +1 -1
- package/dist/src/agents/auth-provider/factory.js +6 -3
- package/dist/src/agents/auth-provider/factory.js.map +1 -1
- package/dist/src/agents/auth-provider/factory.test.js +12 -0
- package/dist/src/agents/auth-provider/factory.test.js.map +1 -1
- package/dist/src/agents/auth-provider/types.d.ts +2 -4
- package/dist/src/agents/browser/analyzeScreenshot.d.ts +35 -0
- package/dist/src/agents/browser/analyzeScreenshot.js +183 -0
- package/dist/src/agents/browser/analyzeScreenshot.js.map +1 -0
- package/dist/src/agents/browser/analyzeScreenshot.test.d.ts +6 -0
- package/dist/src/agents/browser/analyzeScreenshot.test.js +161 -0
- package/dist/src/agents/browser/analyzeScreenshot.test.js.map +1 -0
- package/dist/src/agents/browser/browserAgentDefinition.d.ts +50 -0
- package/dist/src/agents/browser/browserAgentDefinition.js +141 -0
- package/dist/src/agents/browser/browserAgentDefinition.js.map +1 -0
- package/dist/src/agents/browser/browserAgentFactory.d.ts +42 -0
- package/dist/src/agents/browser/browserAgentFactory.js +107 -0
- package/dist/src/agents/browser/browserAgentFactory.js.map +1 -0
- package/dist/src/agents/browser/browserAgentFactory.test.d.ts +6 -0
- package/dist/src/agents/browser/browserAgentFactory.test.js +186 -0
- package/dist/src/agents/browser/browserAgentFactory.test.js.map +1 -0
- package/dist/src/agents/browser/browserAgentInvocation.d.ts +44 -0
- package/dist/src/agents/browser/browserAgentInvocation.js +109 -0
- package/dist/src/agents/browser/browserAgentInvocation.js.map +1 -0
- package/dist/src/agents/browser/browserAgentInvocation.test.d.ts +6 -0
- package/dist/src/agents/browser/browserAgentInvocation.test.js +87 -0
- package/dist/src/agents/browser/browserAgentInvocation.test.js.map +1 -0
- package/dist/src/agents/browser/browserManager.d.ts +110 -0
- package/dist/src/agents/browser/browserManager.js +323 -0
- package/dist/src/agents/browser/browserManager.js.map +1 -0
- package/dist/src/agents/browser/browserManager.test.d.ts +6 -0
- package/dist/src/agents/browser/browserManager.test.js +314 -0
- package/dist/src/agents/browser/browserManager.test.js.map +1 -0
- package/dist/src/agents/browser/mcpToolWrapper.d.ts +45 -0
- package/dist/src/agents/browser/mcpToolWrapper.js +356 -0
- package/dist/src/agents/browser/mcpToolWrapper.js.map +1 -0
- package/dist/src/agents/browser/mcpToolWrapper.test.d.ts +6 -0
- package/dist/src/agents/browser/mcpToolWrapper.test.js +126 -0
- package/dist/src/agents/browser/mcpToolWrapper.test.js.map +1 -0
- package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.d.ts +6 -0
- package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js +57 -0
- package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js.map +1 -0
- package/dist/src/agents/browser/modelAvailability.d.ts +23 -0
- package/dist/src/agents/browser/modelAvailability.js +23 -0
- package/dist/src/agents/browser/modelAvailability.js.map +1 -0
- package/dist/src/agents/local-executor.js +73 -31
- package/dist/src/agents/local-executor.js.map +1 -1
- package/dist/src/agents/local-executor.test.js +157 -4
- package/dist/src/agents/local-executor.test.js.map +1 -1
- package/dist/src/agents/local-invocation.test.js.map +1 -1
- package/dist/src/agents/registry.js +8 -0
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/agents/remote-invocation.d.ts +2 -1
- package/dist/src/agents/remote-invocation.js +3 -3
- package/dist/src/agents/remote-invocation.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.js +6 -0
- package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
- package/dist/src/agents/subagent-tool.d.ts +3 -0
- package/dist/src/agents/subagent-tool.js +62 -3
- package/dist/src/agents/subagent-tool.js.map +1 -1
- package/dist/src/agents/subagent-tool.test.js +143 -0
- package/dist/src/agents/subagent-tool.test.js.map +1 -1
- package/dist/src/availability/fallbackIntegration.test.js +4 -1
- package/dist/src/availability/fallbackIntegration.test.js.map +1 -1
- package/dist/src/availability/policyHelpers.js +3 -1
- package/dist/src/availability/policyHelpers.js.map +1 -1
- package/dist/src/availability/policyHelpers.test.js +51 -5
- package/dist/src/availability/policyHelpers.test.js.map +1 -1
- package/dist/src/code_assist/admin/admin_controls.js +1 -0
- package/dist/src/code_assist/admin/admin_controls.js.map +1 -1
- package/dist/src/code_assist/converter.js +8 -2
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/experiments/experiments.js +1 -1
- package/dist/src/code_assist/experiments/experiments.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.js +1 -1
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +5 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.js +11 -8
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +55 -0
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.js +22 -13
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +26 -0
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/telemetry.js +16 -3
- package/dist/src/code_assist/telemetry.js.map +1 -1
- package/dist/src/code_assist/telemetry.test.js +10 -0
- package/dist/src/code_assist/telemetry.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +13 -12
- package/dist/src/code_assist/types.js.map +1 -1
- package/dist/src/config/config.d.ts +83 -8
- package/dist/src/config/config.js +127 -23
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +285 -10
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/projectRegistry.js +1 -0
- package/dist/src/config/projectRegistry.js.map +1 -1
- package/dist/src/config/storage.d.ts +17 -1
- package/dist/src/config/storage.js +82 -2
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +149 -2
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/config/userHintService.d.ts +46 -0
- package/dist/src/config/userHintService.js +81 -0
- package/dist/src/config/userHintService.js.map +1 -0
- package/dist/src/config/userHintService.test.d.ts +6 -0
- package/dist/src/config/userHintService.test.js +62 -0
- package/dist/src/config/userHintService.test.js.map +1 -0
- package/dist/src/confirmation-bus/message-bus.js +15 -3
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.test.js +15 -0
- package/dist/src/confirmation-bus/message-bus.test.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +7 -0
- package/dist/src/confirmation-bus/types.js.map +1 -1
- package/dist/src/core/baseLlmClient.d.ts +2 -3
- package/dist/src/core/baseLlmClient.js +7 -5
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +45 -20
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.js +18 -7
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/coreToolHookTriggers.d.ts +2 -3
- package/dist/src/core/coreToolHookTriggers.js +8 -3
- package/dist/src/core/coreToolHookTriggers.js.map +1 -1
- package/dist/src/core/coreToolScheduler.js +2 -1
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +10 -3
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/fakeContentGenerator.js +2 -0
- package/dist/src/core/fakeContentGenerator.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +1 -1
- package/dist/src/core/geminiChat.js +5 -5
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +1 -0
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiChat_network_retry.test.js +1 -0
- package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
- package/dist/src/core/logger.js +2 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.d.ts +14 -2
- package/dist/src/core/loggingContentGenerator.js +98 -4
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.test.js +275 -1
- package/dist/src/core/loggingContentGenerator.test.js.map +1 -1
- package/dist/src/core/prompts.test.js +55 -27
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/recordingContentGenerator.test.js +5 -0
- package/dist/src/core/recordingContentGenerator.test.js.map +1 -1
- package/dist/src/core/turn.d.ts +4 -2
- package/dist/src/core/turn.js +2 -0
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +4 -1
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookAggregator.d.ts +1 -2
- package/dist/src/hooks/hookAggregator.js +1 -2
- package/dist/src/hooks/hookAggregator.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.d.ts +2 -2
- package/dist/src/hooks/hookEventHandler.js +13 -4
- package/dist/src/hooks/hookEventHandler.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.test.js +1 -2
- package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
- package/dist/src/hooks/hookPlanner.d.ts +1 -2
- package/dist/src/hooks/hookPlanner.js.map +1 -1
- package/dist/src/hooks/hookRegistry.d.ts +8 -0
- package/dist/src/hooks/hookRegistry.js +31 -3
- package/dist/src/hooks/hookRegistry.js.map +1 -1
- package/dist/src/hooks/hookRegistry.test.js.map +1 -1
- package/dist/src/hooks/hookRunner.d.ts +5 -2
- package/dist/src/hooks/hookRunner.js +52 -2
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js.map +1 -1
- package/dist/src/hooks/hookSystem.d.ts +11 -3
- package/dist/src/hooks/hookSystem.js +10 -4
- package/dist/src/hooks/hookSystem.js.map +1 -1
- package/dist/src/hooks/hookSystem.test.js +1 -0
- package/dist/src/hooks/hookSystem.test.js.map +1 -1
- package/dist/src/hooks/runtimeHooks.test.d.ts +6 -0
- package/dist/src/hooks/runtimeHooks.test.js +100 -0
- package/dist/src/hooks/runtimeHooks.test.js.map +1 -0
- package/dist/src/hooks/trustedHooks.js +6 -1
- package/dist/src/hooks/trustedHooks.js.map +1 -1
- package/dist/src/hooks/trustedHooks.test.js +17 -9
- package/dist/src/hooks/trustedHooks.test.js.map +1 -1
- package/dist/src/hooks/types.d.ts +49 -8
- package/dist/src/hooks/types.js +20 -1
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +0 -1
- package/dist/src/ide/detect-ide.js +1 -1
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/ide-client.js +3 -2
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-connection-utils.js +90 -14
- package/dist/src/ide/ide-connection-utils.js.map +1 -1
- package/dist/src/ide/ide-connection-utils.test.js +78 -0
- package/dist/src/ide/ide-connection-utils.test.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +1 -2
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/process-utils.d.ts +7 -0
- package/dist/src/ide/process-utils.js +20 -0
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/process-utils.test.js +30 -0
- package/dist/src/ide/process-utils.test.js.map +1 -1
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.js +6 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +1 -1
- package/dist/src/mcp/oauth-provider.js +8 -7
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +34 -2
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.js +2 -0
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +12 -0
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.js +4 -1
- package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.test.js +40 -2
- package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.js +2 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
- package/dist/src/policy/config.d.ts +18 -9
- package/dist/src/policy/config.js +75 -54
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/config.test.js +26 -26
- package/dist/src/policy/integrity.d.ts +45 -0
- package/dist/src/policy/integrity.js +121 -0
- package/dist/src/policy/integrity.js.map +1 -0
- package/dist/src/policy/integrity.test.d.ts +6 -0
- package/dist/src/policy/integrity.test.js +132 -0
- package/dist/src/policy/integrity.test.js.map +1 -0
- package/dist/src/policy/persistence.test.js +29 -19
- package/dist/src/policy/persistence.test.js.map +1 -1
- package/dist/src/policy/policies/conseca.toml +6 -0
- package/dist/src/policy/policies/plan.toml +28 -12
- package/dist/src/policy/policies/read-only.toml +11 -10
- package/dist/src/policy/policies/write.toml +11 -10
- package/dist/src/policy/policies/yolo.toml +11 -10
- package/dist/src/policy/policy-engine.d.ts +16 -3
- package/dist/src/policy/policy-engine.js +154 -29
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +480 -9
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/policy-updater.test.js +11 -6
- package/dist/src/policy/policy-updater.test.js.map +1 -1
- package/dist/src/policy/toml-loader.d.ts +13 -2
- package/dist/src/policy/toml-loader.js +55 -34
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +115 -7
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/types.d.ts +18 -1
- package/dist/src/policy/types.js +1 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/policy/workspace-policy.test.d.ts +6 -0
- package/dist/src/policy/workspace-policy.test.js +231 -0
- package/dist/src/policy/workspace-policy.test.js.map +1 -0
- package/dist/src/prompts/promptProvider.js +11 -13
- package/dist/src/prompts/promptProvider.js.map +1 -1
- package/dist/src/prompts/promptProvider.test.js +64 -3
- package/dist/src/prompts/promptProvider.test.js.map +1 -1
- package/dist/src/prompts/snippets.js +41 -10
- package/dist/src/prompts/snippets.js.map +1 -1
- package/dist/src/prompts/snippets.legacy.js +1 -0
- package/dist/src/prompts/snippets.legacy.js.map +1 -1
- package/dist/src/routing/modelRouterService.js +3 -1
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +12 -6
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/approvalModeStrategy.d.ts +18 -0
- package/dist/src/routing/strategies/approvalModeStrategy.js +58 -0
- package/dist/src/routing/strategies/approvalModeStrategy.js.map +1 -0
- package/dist/src/routing/strategies/approvalModeStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/approvalModeStrategy.test.js +110 -0
- package/dist/src/routing/strategies/approvalModeStrategy.test.js.map +1 -0
- package/dist/src/safety/checker-runner.js +1 -0
- package/dist/src/safety/checker-runner.js.map +1 -1
- package/dist/src/safety/conseca/conseca.d.ts +31 -0
- package/dist/src/safety/conseca/conseca.js +105 -0
- package/dist/src/safety/conseca/conseca.js.map +1 -0
- package/dist/src/safety/conseca/conseca.test.d.ts +6 -0
- package/dist/src/safety/conseca/conseca.test.js +226 -0
- package/dist/src/safety/conseca/conseca.test.js.map +1 -0
- package/dist/src/safety/conseca/integration.test.d.ts +6 -0
- package/dist/src/safety/conseca/integration.test.js +19 -0
- package/dist/src/safety/conseca/integration.test.js.map +1 -0
- package/dist/src/safety/conseca/policy-enforcer.d.ts +13 -0
- package/dist/src/safety/conseca/policy-enforcer.js +135 -0
- package/dist/src/safety/conseca/policy-enforcer.js.map +1 -0
- package/dist/src/safety/conseca/policy-enforcer.test.d.ts +6 -0
- package/dist/src/safety/conseca/policy-enforcer.test.js +141 -0
- package/dist/src/safety/conseca/policy-enforcer.test.js.map +1 -0
- package/dist/src/safety/conseca/policy-generator.d.ts +15 -0
- package/dist/src/safety/conseca/policy-generator.js +144 -0
- package/dist/src/safety/conseca/policy-generator.js.map +1 -0
- package/dist/src/safety/conseca/policy-generator.test.d.ts +6 -0
- package/dist/src/safety/conseca/policy-generator.test.js +84 -0
- package/dist/src/safety/conseca/policy-generator.test.js.map +1 -0
- package/dist/src/safety/conseca/types.d.ts +15 -0
- package/dist/src/safety/conseca/types.js +7 -0
- package/dist/src/safety/conseca/types.js.map +1 -0
- package/dist/src/safety/context-builder.d.ts +3 -3
- package/dist/src/safety/context-builder.js +60 -4
- package/dist/src/safety/context-builder.js.map +1 -1
- package/dist/src/safety/context-builder.test.js +98 -18
- package/dist/src/safety/context-builder.test.js.map +1 -1
- package/dist/src/safety/protocol.d.ts +4 -0
- package/dist/src/safety/registry.d.ts +2 -1
- package/dist/src/safety/registry.js +14 -4
- package/dist/src/safety/registry.js.map +1 -1
- package/dist/src/safety/registry.test.js +5 -2
- package/dist/src/safety/registry.test.js.map +1 -1
- package/dist/src/scheduler/confirmation.d.ts +0 -13
- package/dist/src/scheduler/confirmation.js +1 -1
- package/dist/src/scheduler/confirmation.js.map +1 -1
- package/dist/src/scheduler/policy.js +6 -2
- package/dist/src/scheduler/policy.js.map +1 -1
- package/dist/src/scheduler/policy.test.js +4 -3
- package/dist/src/scheduler/policy.test.js.map +1 -1
- package/dist/src/scheduler/scheduler.d.ts +3 -1
- package/dist/src/scheduler/scheduler.js +148 -28
- package/dist/src/scheduler/scheduler.js.map +1 -1
- package/dist/src/scheduler/scheduler.test.js +341 -242
- package/dist/src/scheduler/scheduler.test.js.map +1 -1
- package/dist/src/scheduler/scheduler_parallel.test.d.ts +6 -0
- package/dist/src/scheduler/scheduler_parallel.test.js +309 -0
- package/dist/src/scheduler/scheduler_parallel.test.js.map +1 -0
- package/dist/src/scheduler/state-manager.d.ts +8 -0
- package/dist/src/scheduler/state-manager.js +30 -2
- package/dist/src/scheduler/state-manager.js.map +1 -1
- package/dist/src/scheduler/state-manager.test.js +61 -0
- package/dist/src/scheduler/state-manager.test.js.map +1 -1
- package/dist/src/scheduler/tool-executor.js +15 -7
- package/dist/src/scheduler/tool-executor.js.map +1 -1
- package/dist/src/scheduler/tool-executor.test.js +1 -1
- package/dist/src/scheduler/tool-executor.test.js.map +1 -1
- package/dist/src/scheduler/types.d.ts +23 -0
- package/dist/src/services/FolderTrustDiscoveryService.d.ts +32 -0
- package/dist/src/services/FolderTrustDiscoveryService.js +167 -0
- package/dist/src/services/FolderTrustDiscoveryService.js.map +1 -0
- package/dist/src/services/FolderTrustDiscoveryService.test.d.ts +6 -0
- package/dist/src/services/FolderTrustDiscoveryService.test.js +118 -0
- package/dist/src/services/FolderTrustDiscoveryService.test.js.map +1 -0
- package/dist/src/services/chatCompressionService.d.ts +0 -14
- package/dist/src/services/chatCompressionService.js +29 -7
- package/dist/src/services/chatCompressionService.js.map +1 -1
- package/dist/src/services/chatCompressionService.test.js +3 -1
- package/dist/src/services/chatCompressionService.test.js.map +1 -1
- package/dist/src/services/chatRecordingService.d.ts +7 -1
- package/dist/src/services/chatRecordingService.js +12 -1
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/chatRecordingService.test.js +34 -0
- package/dist/src/services/chatRecordingService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.js +1 -2
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/sessionSummaryUtils.js +3 -0
- package/dist/src/services/sessionSummaryUtils.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +6 -0
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/skills/skillLoader.js +2 -2
- package/dist/src/skills/skillLoader.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +3 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +35 -4
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +0 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +19 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +14 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +29 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/conseca-logger.d.ts +9 -0
- package/dist/src/telemetry/conseca-logger.js +91 -0
- package/dist/src/telemetry/conseca-logger.js.map +1 -0
- package/dist/src/telemetry/conseca-logger.test.d.ts +6 -0
- package/dist/src/telemetry/conseca-logger.test.js +89 -0
- package/dist/src/telemetry/conseca-logger.test.js.map +1 -0
- package/dist/src/telemetry/gcp-exporters.js +1 -2
- package/dist/src/telemetry/gcp-exporters.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +2 -1
- package/dist/src/telemetry/index.js +2 -1
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/integration.test.circular.js +3 -0
- package/dist/src/telemetry/integration.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +1 -2
- package/dist/src/telemetry/loggers.js +3 -13
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +3 -0
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +6 -5
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +1 -3
- package/dist/src/telemetry/metrics.js +3 -2
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +7 -3
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sanitize.test.js +19 -18
- package/dist/src/telemetry/sanitize.test.js.map +1 -1
- package/dist/src/telemetry/semantic.d.ts +7 -9
- package/dist/src/telemetry/semantic.js +8 -8
- package/dist/src/telemetry/semantic.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +42 -4
- package/dist/src/telemetry/types.js +87 -2
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -2
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +1 -2
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/tools/ask-user.test.js +1 -19
- package/dist/src/tools/ask-user.test.js.map +1 -1
- package/dist/src/tools/confirmation-policy.test.js +14 -17
- package/dist/src/tools/confirmation-policy.test.js.map +1 -1
- package/dist/src/tools/definitions/dynamic-declaration-helpers.js +1 -1
- package/dist/src/tools/definitions/dynamic-declaration-helpers.js.map +1 -1
- package/dist/src/tools/definitions/model-family-sets/default-legacy.js +14 -16
- package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
- package/dist/src/tools/definitions/model-family-sets/gemini-3.js +24 -59
- package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
- package/dist/src/tools/diff-utils.d.ts +9 -0
- package/dist/src/tools/diff-utils.js +66 -0
- package/dist/src/tools/diff-utils.js.map +1 -0
- package/dist/src/tools/diff-utils.test.d.ts +6 -0
- package/dist/src/tools/diff-utils.test.js +53 -0
- package/dist/src/tools/diff-utils.test.js.map +1 -0
- package/dist/src/tools/edit.d.ts +9 -4
- package/dist/src/tools/edit.js +203 -34
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +225 -10
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/enter-plan-mode.js +1 -1
- package/dist/src/tools/enter-plan-mode.js.map +1 -1
- package/dist/src/tools/enter-plan-mode.test.js +1 -1
- package/dist/src/tools/enter-plan-mode.test.js.map +1 -1
- package/dist/src/tools/exit-plan-mode.js +10 -24
- package/dist/src/tools/exit-plan-mode.js.map +1 -1
- package/dist/src/tools/exit-plan-mode.test.js +1 -1
- package/dist/src/tools/exit-plan-mode.test.js.map +1 -1
- package/dist/src/tools/grep-utils.d.ts +49 -0
- package/dist/src/tools/grep-utils.js +139 -0
- package/dist/src/tools/grep-utils.js.map +1 -0
- package/dist/src/tools/grep.js +4 -44
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +21 -2
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.js +6 -1
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +2 -2
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.js +16 -18
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +51 -0
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +22 -1
- package/dist/src/tools/mcp-client.js +95 -36
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +148 -20
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +15 -5
- package/dist/src/tools/mcp-tool.js +36 -8
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/memoryTool.js +1 -1
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +5 -0
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/omissionPlaceholderDetector.d.ts +15 -0
- package/dist/src/tools/omissionPlaceholderDetector.js +90 -0
- package/dist/src/tools/omissionPlaceholderDetector.js.map +1 -0
- package/dist/src/tools/omissionPlaceholderDetector.test.d.ts +6 -0
- package/dist/src/tools/omissionPlaceholderDetector.test.js +49 -0
- package/dist/src/tools/omissionPlaceholderDetector.test.js.map +1 -0
- package/dist/src/tools/read-file.d.ts +4 -4
- package/dist/src/tools/read-file.js +17 -10
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +20 -10
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/ripGrep.js +49 -46
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +52 -37
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +2 -2
- package/dist/src/tools/shell.js +2 -2
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +1 -2
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +0 -6
- package/dist/src/tools/tool-names.js +0 -15
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +1 -0
- package/dist/src/tools/tool-registry.js +33 -6
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +47 -0
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +21 -1
- package/dist/src/tools/tools.js +19 -3
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.js +24 -0
- package/dist/src/tools/tools.test.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +9 -1
- package/dist/src/tools/web-fetch.js +273 -34
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +303 -30
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/write-file.js +14 -10
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +75 -0
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +2 -2
- package/dist/src/tools/write-todos.js +1 -1
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/tools/xcode-mcp-fix-transport.js +4 -1
- package/dist/src/tools/xcode-mcp-fix-transport.js.map +1 -1
- package/dist/src/utils/approvalModeUtils.d.ts +14 -0
- package/dist/src/utils/approvalModeUtils.js +35 -0
- package/dist/src/utils/approvalModeUtils.js.map +1 -0
- package/dist/src/utils/approvalModeUtils.test.d.ts +6 -0
- package/dist/src/utils/approvalModeUtils.test.js +36 -0
- package/dist/src/utils/approvalModeUtils.test.js.map +1 -0
- package/dist/src/utils/authConsent.d.ts +1 -1
- package/dist/src/utils/authConsent.js +10 -8
- package/dist/src/utils/authConsent.js.map +1 -1
- package/dist/src/utils/authConsent.test.js +89 -44
- package/dist/src/utils/authConsent.test.js.map +1 -1
- package/dist/src/utils/compatibility.d.ts +41 -0
- package/dist/src/utils/compatibility.js +112 -0
- package/dist/src/utils/compatibility.js.map +1 -0
- package/dist/src/utils/compatibility.test.d.ts +6 -0
- package/dist/src/utils/compatibility.test.js +233 -0
- package/dist/src/utils/compatibility.test.js.map +1 -0
- package/dist/src/utils/editCorrector.js +22 -29
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/envExpansion.d.ts +18 -0
- package/dist/src/utils/envExpansion.js +46 -0
- package/dist/src/utils/envExpansion.js.map +1 -0
- package/dist/src/utils/envExpansion.test.d.ts +6 -0
- package/dist/src/utils/envExpansion.test.js +110 -0
- package/dist/src/utils/envExpansion.test.js.map +1 -0
- package/dist/src/utils/errors.d.ts +1 -0
- package/dist/src/utils/errors.js +55 -10
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/errors.test.js +27 -1
- package/dist/src/utils/errors.test.js.map +1 -1
- package/dist/src/utils/events.d.ts +17 -0
- package/dist/src/utils/events.js +12 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/events.test.d.ts +1 -1
- package/dist/src/utils/events.test.js +50 -3
- package/dist/src/utils/events.test.js.map +1 -1
- package/dist/src/utils/fastAckHelper.js +2 -1
- package/dist/src/utils/fastAckHelper.js.map +1 -1
- package/dist/src/utils/fetch.d.ts +1 -1
- package/dist/src/utils/fetch.js +15 -2
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileDiffUtils.d.ts +2 -2
- package/dist/src/utils/fileDiffUtils.js +1 -2
- package/dist/src/utils/fileDiffUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +5 -3
- package/dist/src/utils/fileUtils.js +25 -16
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +14 -13
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.js +4 -1
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/getFolderStructure.test.js +4 -5
- package/dist/src/utils/getFolderStructure.test.js.map +1 -1
- package/dist/src/utils/getPty.js +4 -0
- package/dist/src/utils/getPty.js.map +1 -1
- package/dist/src/utils/googleErrors.js +29 -5
- package/dist/src/utils/googleErrors.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.js +10 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.test.js +16 -1
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.js +2 -0
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +1 -2
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +1 -1
- package/dist/src/utils/retry.js +9 -4
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +15 -12
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/safeJsonStringify.js +3 -0
- package/dist/src/utils/safeJsonStringify.js.map +1 -1
- package/dist/src/utils/schemaValidator.js +5 -3
- package/dist/src/utils/schemaValidator.js.map +1 -1
- package/dist/src/utils/session.d.ts +1 -0
- package/dist/src/utils/session.js +3 -0
- package/dist/src/utils/session.js.map +1 -1
- package/dist/src/utils/sessionUtils.d.ts +14 -0
- package/dist/src/utils/sessionUtils.js +113 -0
- package/dist/src/utils/sessionUtils.js.map +1 -0
- package/dist/src/utils/sessionUtils.test.d.ts +1 -0
- package/dist/src/utils/sessionUtils.test.js +137 -0
- package/dist/src/utils/sessionUtils.test.js.map +1 -0
- package/dist/src/utils/shell-utils.js +1 -0
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/stdio.js +6 -0
- package/dist/src/utils/stdio.js.map +1 -1
- package/dist/src/utils/textUtils.d.ts +9 -0
- package/dist/src/utils/textUtils.js +15 -0
- package/dist/src/utils/textUtils.js.map +1 -1
- package/dist/src/utils/textUtils.test.js +42 -1
- package/dist/src/utils/textUtils.test.js.map +1 -1
- package/dist/src/utils/toolCallContext.d.ts +0 -5
- package/dist/src/utils/toolCallContext.js +1 -1
- package/dist/src/utils/toolCallContext.js.map +1 -1
- package/dist/src/utils/userAccountManager.js +3 -0
- package/dist/src/utils/userAccountManager.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -3
- package/dist/docs/architecture.md +0 -80
- package/dist/docs/cli/index.md +0 -123
- package/dist/docs/core/concepts.md +0 -137
- package/dist/docs/get-started/configuration-v1.md +0 -882
- package/dist/google-gemini-cli-core-0.30.0-preview.5.tgz +0 -0
- /package/dist/docs/{core → reference}/memport.md +0 -0
- /package/dist/docs/{core → reference}/tools-api.md +0 -0
- /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,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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"}
|
package/dist/src/tools/edit.d.ts
CHANGED
|
@@ -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,
|
|
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
|
-
*
|
|
47
|
-
*
|
|
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
|
-
|
|
54
|
+
allow_multiple?: boolean;
|
|
50
55
|
/**
|
|
51
56
|
* The instruction for what needs to be done.
|
|
52
57
|
*/
|
package/dist/src/tools/edit.js
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
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
|
|
175
|
+
const occurrences = matches.length;
|
|
163
176
|
const newLines = normalizedReplace.split('\n');
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
|
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,
|
|
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 !==
|
|
225
|
-
const occurrenceTerm = expectedReplacements === 1 ? 'occurrence' : 'occurrences';
|
|
239
|
+
else if (!params.allow_multiple && occurrences !== 1) {
|
|
226
240
|
error = {
|
|
227
|
-
display: `Failed to edit, expected
|
|
228
|
-
raw: `Failed to edit, Expected
|
|
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,
|
|
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,
|
|
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 (
|
|
473
|
-
|
|
474
|
-
|
|
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
|