@office-ai/aioncli-core 0.18.7 → 0.24.0-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/CONTRIBUTING.md +546 -0
- package/dist/docs/architecture.md +80 -0
- package/dist/docs/assets/connected_devtools.png +0 -0
- package/dist/docs/assets/gemini-screenshot.png +0 -0
- package/dist/docs/assets/release_patch.png +0 -0
- package/dist/docs/assets/theme-ansi-light.png +0 -0
- package/dist/docs/assets/theme-ansi.png +0 -0
- package/dist/docs/assets/theme-atom-one.png +0 -0
- package/dist/docs/assets/theme-ayu-light.png +0 -0
- package/dist/docs/assets/theme-ayu.png +0 -0
- package/dist/docs/assets/theme-custom.png +0 -0
- package/dist/docs/assets/theme-default-light.png +0 -0
- package/dist/docs/assets/theme-default.png +0 -0
- package/dist/docs/assets/theme-dracula.png +0 -0
- package/dist/docs/assets/theme-github-light.png +0 -0
- package/dist/docs/assets/theme-github.png +0 -0
- package/dist/docs/assets/theme-google-light.png +0 -0
- package/dist/docs/assets/theme-xcode-light.png +0 -0
- package/dist/docs/changelogs/index.md +592 -0
- package/dist/docs/changelogs/latest.md +225 -0
- package/dist/docs/changelogs/preview.md +129 -0
- package/dist/docs/changelogs/releases.md +896 -0
- package/dist/docs/cli/authentication.md +3 -0
- package/dist/docs/cli/checkpointing.md +94 -0
- package/dist/docs/cli/commands.md +354 -0
- package/dist/docs/cli/configuration.md +780 -0
- package/dist/docs/cli/custom-commands.md +315 -0
- package/dist/docs/cli/enterprise.md +565 -0
- package/dist/docs/cli/gemini-ignore.md +71 -0
- package/dist/docs/cli/gemini-md.md +108 -0
- package/dist/docs/cli/generation-settings.md +210 -0
- package/dist/docs/cli/headless.md +388 -0
- package/dist/docs/cli/index.md +63 -0
- package/dist/docs/cli/keyboard-shortcuts.md +143 -0
- package/dist/docs/cli/model-routing.md +37 -0
- package/dist/docs/cli/model.md +62 -0
- package/dist/docs/cli/sandbox.md +171 -0
- package/dist/docs/cli/session-management.md +158 -0
- package/dist/docs/cli/settings.md +114 -0
- package/dist/docs/cli/skills.md +156 -0
- package/dist/docs/cli/system-prompt.md +93 -0
- package/dist/docs/cli/telemetry.md +791 -0
- package/dist/docs/cli/themes.md +237 -0
- package/dist/docs/cli/token-caching.md +20 -0
- package/dist/docs/cli/trusted-folders.md +95 -0
- package/dist/docs/cli/tutorials/skills-getting-started.md +124 -0
- package/dist/docs/cli/tutorials.md +87 -0
- package/dist/docs/cli/uninstall.md +47 -0
- package/dist/docs/core/index.md +101 -0
- package/dist/docs/core/memport.md +244 -0
- package/dist/docs/core/policy-engine.md +267 -0
- package/dist/docs/core/tools-api.md +131 -0
- package/dist/docs/examples/proxy-script.md +83 -0
- package/dist/docs/extension.md +160 -0
- package/dist/docs/extensions/extension-releasing.md +183 -0
- package/dist/docs/extensions/getting-started-extensions.md +245 -0
- package/dist/docs/extensions/index.md +293 -0
- package/dist/docs/faq.md +154 -0
- package/dist/docs/get-started/authentication.md +321 -0
- package/dist/docs/get-started/configuration-v1.md +888 -0
- package/dist/docs/get-started/configuration.md +1536 -0
- package/dist/docs/get-started/deployment.md +143 -0
- package/dist/docs/get-started/examples.md +219 -0
- package/dist/docs/get-started/gemini-3.md +116 -0
- package/dist/docs/get-started/index.md +71 -0
- package/dist/docs/get-started/installation.md +141 -0
- package/dist/docs/hooks/best-practices.md +856 -0
- package/dist/docs/hooks/index.md +687 -0
- package/dist/docs/hooks/reference.md +168 -0
- package/dist/docs/hooks/writing-hooks.md +1026 -0
- package/dist/docs/ide-integration/ide-companion-spec.md +267 -0
- package/dist/docs/ide-integration/index.md +202 -0
- package/dist/docs/index.md +147 -0
- package/dist/docs/integration-tests.md +211 -0
- package/dist/docs/issue-and-pr-automation.md +134 -0
- package/dist/docs/local-development.md +128 -0
- package/dist/docs/mermaid/context.mmd +103 -0
- package/dist/docs/mermaid/render-path.mmd +64 -0
- package/dist/docs/npm.md +62 -0
- package/dist/docs/quota-and-pricing.md +158 -0
- package/dist/docs/release-confidence.md +164 -0
- package/dist/docs/releases.md +540 -0
- package/dist/docs/sidebar.json +301 -0
- package/dist/docs/tools/file-system.md +217 -0
- package/dist/docs/tools/index.md +95 -0
- package/dist/docs/tools/mcp-server.md +1044 -0
- package/dist/docs/tools/memory.md +54 -0
- package/dist/docs/tools/shell.md +260 -0
- package/dist/docs/tools/todos.md +57 -0
- package/dist/docs/tools/web-fetch.md +59 -0
- package/dist/docs/tools/web-search.md +42 -0
- package/dist/docs/tos-privacy.md +96 -0
- package/dist/docs/troubleshooting.md +158 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/agents/a2a-client-manager.d.ts +78 -0
- package/dist/src/agents/a2a-client-manager.js +295 -0
- package/dist/src/agents/a2a-client-manager.js.map +1 -0
- package/dist/src/agents/a2a-client-manager.test.d.ts +6 -0
- package/dist/src/agents/a2a-client-manager.test.js +237 -0
- package/dist/src/agents/a2a-client-manager.test.js.map +1 -0
- package/dist/src/agents/a2aUtils.d.ts +28 -0
- package/dist/src/agents/a2aUtils.js +111 -0
- package/dist/src/agents/a2aUtils.js.map +1 -0
- package/dist/src/agents/a2aUtils.test.d.ts +6 -0
- package/dist/src/agents/a2aUtils.test.js +147 -0
- package/dist/src/agents/a2aUtils.test.js.map +1 -0
- package/dist/src/agents/codebase-investigator.d.ts +2 -2
- package/dist/src/agents/codebase-investigator.js +5 -4
- package/dist/src/agents/codebase-investigator.js.map +1 -1
- package/dist/src/agents/delegate-to-agent-tool.d.ts +19 -0
- package/dist/src/agents/delegate-to-agent-tool.js +115 -0
- package/dist/src/agents/delegate-to-agent-tool.js.map +1 -0
- package/dist/src/agents/delegate-to-agent-tool.test.d.ts +6 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js +165 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -0
- package/dist/src/agents/introspection-agent.d.ts +23 -0
- package/dist/src/agents/introspection-agent.js +72 -0
- package/dist/src/agents/introspection-agent.js.map +1 -0
- package/dist/src/agents/introspection-agent.test.d.ts +6 -0
- package/dist/src/agents/introspection-agent.test.js +47 -0
- package/dist/src/agents/introspection-agent.test.js.map +1 -0
- package/dist/src/agents/local-executor.d.ts +108 -0
- package/dist/src/agents/local-executor.js +801 -0
- package/dist/src/agents/local-executor.js.map +1 -0
- package/dist/src/agents/local-executor.test.d.ts +6 -0
- package/dist/src/agents/local-executor.test.js +1380 -0
- package/dist/src/agents/local-executor.test.js.map +1 -0
- package/dist/src/agents/local-invocation.d.ts +45 -0
- package/dist/src/agents/local-invocation.js +101 -0
- package/dist/src/agents/local-invocation.js.map +1 -0
- package/dist/src/agents/local-invocation.test.d.ts +6 -0
- package/dist/src/agents/local-invocation.test.js +218 -0
- package/dist/src/agents/local-invocation.test.js.map +1 -0
- package/dist/src/agents/registry.d.ts +25 -1
- package/dist/src/agents/registry.js +149 -5
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js +247 -25
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/agents/remote-invocation.d.ts +35 -0
- package/dist/src/agents/remote-invocation.js +129 -0
- package/dist/src/agents/remote-invocation.js.map +1 -0
- package/dist/src/agents/remote-invocation.test.d.ts +6 -0
- package/dist/src/agents/remote-invocation.test.js +201 -0
- package/dist/src/agents/remote-invocation.test.js.map +1 -0
- package/dist/src/agents/subagent-tool-wrapper.d.ts +2 -2
- package/dist/src/agents/subagent-tool-wrapper.js +11 -6
- package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.test.js +25 -17
- package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
- package/dist/src/agents/toml-loader.d.ts +74 -0
- package/dist/src/agents/toml-loader.js +248 -0
- package/dist/src/agents/toml-loader.js.map +1 -0
- package/dist/src/agents/toml-loader.test.d.ts +6 -0
- package/dist/src/agents/toml-loader.test.js +309 -0
- package/dist/src/agents/toml-loader.test.js.map +1 -0
- package/dist/src/agents/types.d.ts +18 -4
- package/dist/src/availability/errorClassification.d.ts +7 -0
- package/dist/src/availability/errorClassification.js +20 -0
- package/dist/src/availability/errorClassification.js.map +1 -0
- package/dist/src/availability/modelAvailabilityService.d.ts +36 -0
- package/dist/src/availability/modelAvailabilityService.js +87 -0
- package/dist/src/availability/modelAvailabilityService.js.map +1 -0
- package/dist/src/availability/modelAvailabilityService.test.d.ts +6 -0
- package/dist/src/availability/modelAvailabilityService.test.js +140 -0
- package/dist/src/availability/modelAvailabilityService.test.js.map +1 -0
- package/dist/src/availability/modelPolicy.d.ts +49 -0
- package/dist/src/availability/modelPolicy.js +7 -0
- package/dist/src/availability/modelPolicy.js.map +1 -0
- package/dist/src/availability/policyCatalog.d.ts +23 -0
- package/dist/src/availability/policyCatalog.js +82 -0
- package/dist/src/availability/policyCatalog.js.map +1 -0
- package/dist/src/availability/policyCatalog.test.d.ts +6 -0
- package/dist/src/availability/policyCatalog.test.js +70 -0
- package/dist/src/availability/policyCatalog.test.js.map +1 -0
- package/dist/src/availability/policyHelpers.d.ts +52 -0
- package/dist/src/availability/policyHelpers.js +136 -0
- package/dist/src/availability/policyHelpers.js.map +1 -0
- package/dist/src/availability/policyHelpers.test.d.ts +6 -0
- package/dist/src/availability/policyHelpers.test.js +182 -0
- package/dist/src/availability/policyHelpers.test.js.map +1 -0
- package/dist/src/availability/testUtils.d.ts +10 -0
- package/dist/src/availability/testUtils.js +22 -0
- package/dist/src/availability/testUtils.js.map +1 -0
- package/dist/src/code_assist/experiments/client_metadata.js +3 -2
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
- package/dist/src/code_assist/experiments/client_metadata.test.js +7 -10
- package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -1
- package/dist/src/code_assist/experiments/experiments.js +2 -2
- package/dist/src/code_assist/experiments/experiments.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -0
- package/dist/src/code_assist/oauth2.js +73 -17
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +195 -18
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +10 -1
- package/dist/src/code_assist/server.js +81 -15
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +221 -25
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.js +6 -4
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js +63 -0
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/code_assist/telemetry.d.ts +14 -0
- package/dist/src/code_assist/telemetry.js +156 -0
- package/dist/src/code_assist/telemetry.js.map +1 -0
- package/dist/src/code_assist/telemetry.test.d.ts +6 -0
- package/dist/src/code_assist/telemetry.test.js +300 -0
- package/dist/src/code_assist/telemetry.test.js.map +1 -0
- package/dist/src/code_assist/types.d.ts +84 -1
- package/dist/src/code_assist/types.js +21 -0
- package/dist/src/code_assist/types.js.map +1 -1
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.js +53 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/init.test.d.ts +6 -0
- package/dist/src/commands/init.test.js +25 -0
- package/dist/src/commands/init.test.js.map +1 -0
- package/dist/src/commands/restore.d.ts +9 -0
- package/dist/src/commands/restore.js +46 -0
- package/dist/src/commands/restore.js.map +1 -0
- package/dist/src/commands/restore.test.d.ts +6 -0
- package/dist/src/commands/restore.test.js +137 -0
- package/dist/src/commands/restore.test.js.map +1 -0
- package/dist/src/commands/types.d.ts +41 -0
- package/dist/src/commands/types.js +7 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/config/config.d.ts +120 -23
- package/dist/src/config/config.js +336 -116
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +373 -95
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/defaultModelConfigs.js +46 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -1
- package/dist/src/config/flashFallback.test.js +11 -35
- package/dist/src/config/flashFallback.test.js.map +1 -1
- package/dist/src/config/models.d.ts +29 -15
- package/dist/src/config/models.js +78 -28
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +91 -77
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/config/storage.d.ts +4 -0
- package/dist/src/config/storage.js +12 -0
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +16 -0
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.d.ts +6 -0
- package/dist/src/confirmation-bus/message-bus.js +66 -3
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +29 -2
- package/dist/src/confirmation-bus/types.js +3 -0
- package/dist/src/confirmation-bus/types.js.map +1 -1
- package/dist/src/core/baseLlmClient.d.ts +30 -2
- package/dist/src/core/baseLlmClient.js +107 -49
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +271 -13
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.d.ts +5 -1
- package/dist/src/core/client.js +241 -63
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +462 -72
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/clientHookTriggers.d.ts +36 -0
- package/dist/src/core/clientHookTriggers.js +76 -0
- package/dist/src/core/clientHookTriggers.js.map +1 -0
- package/dist/src/core/contentGenerator.js +17 -4
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +132 -3
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolHookTriggers.d.ts +55 -0
- package/dist/src/core/coreToolHookTriggers.js +304 -0
- package/dist/src/core/coreToolHookTriggers.js.map +1 -0
- package/dist/src/core/coreToolHookTriggers.test.d.ts +6 -0
- package/dist/src/core/coreToolHookTriggers.test.js +191 -0
- package/dist/src/core/coreToolHookTriggers.test.js.map +1 -0
- package/dist/src/core/coreToolScheduler.d.ts +6 -85
- package/dist/src/core/coreToolScheduler.js +69 -267
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +161 -346
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +132 -76
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +240 -257
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiChatHookTriggers.d.ts +64 -0
- package/dist/src/core/geminiChatHookTriggers.js +136 -0
- package/dist/src/core/geminiChatHookTriggers.js.map +1 -0
- package/dist/src/core/geminiChat_network_retry.test.d.ts +6 -0
- package/dist/src/core/geminiChat_network_retry.test.js +196 -0
- package/dist/src/core/geminiChat_network_retry.test.js.map +1 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.js +23 -6
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +13 -8
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +82 -26
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +102 -3
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/sessionHookTriggers.d.ts +29 -0
- package/dist/src/core/sessionHookTriggers.js +75 -0
- package/dist/src/core/sessionHookTriggers.js.map +1 -0
- package/dist/src/core/turn.d.ts +34 -21
- package/dist/src/core/turn.js +33 -13
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +0 -5
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/fallback/handler.js +101 -93
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +186 -173
- package/dist/src/fallback/handler.test.js.map +1 -1
- package/dist/src/fallback/types.d.ts +8 -0
- package/dist/src/generated/git-commit.d.ts +3 -3
- package/dist/src/generated/git-commit.js +3 -3
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/hooks/hookAggregator.js +7 -0
- package/dist/src/hooks/hookAggregator.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.d.ts +113 -0
- package/dist/src/hooks/hookEventHandler.js +571 -0
- package/dist/src/hooks/hookEventHandler.js.map +1 -0
- package/dist/src/hooks/hookEventHandler.test.d.ts +6 -0
- package/dist/src/hooks/hookEventHandler.test.js +461 -0
- package/dist/src/hooks/hookEventHandler.test.js.map +1 -0
- package/dist/src/hooks/hookPlanner.d.ts +1 -5
- package/dist/src/hooks/hookPlanner.js +2 -7
- package/dist/src/hooks/hookPlanner.js.map +1 -1
- package/dist/src/hooks/hookPlanner.test.js +62 -2
- package/dist/src/hooks/hookPlanner.test.js.map +1 -1
- package/dist/src/hooks/hookRegistry.d.ts +6 -18
- package/dist/src/hooks/hookRegistry.js +49 -35
- package/dist/src/hooks/hookRegistry.js.map +1 -1
- package/dist/src/hooks/hookRegistry.test.js +167 -8
- package/dist/src/hooks/hookRegistry.test.js.map +1 -1
- package/dist/src/hooks/hookRunner.d.ts +5 -3
- package/dist/src/hooks/hookRunner.js +74 -18
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js +174 -36
- package/dist/src/hooks/hookRunner.test.js.map +1 -1
- package/dist/src/hooks/hookSystem.d.ts +40 -0
- package/dist/src/hooks/hookSystem.js +65 -0
- package/dist/src/hooks/hookSystem.js.map +1 -0
- package/dist/src/hooks/hookSystem.test.d.ts +6 -0
- package/dist/src/hooks/hookSystem.test.js +319 -0
- package/dist/src/hooks/hookSystem.test.js.map +1 -0
- package/dist/src/hooks/index.d.ts +17 -0
- package/dist/src/hooks/index.js +18 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/trustedHooks.d.ts +28 -0
- package/dist/src/hooks/trustedHooks.js +90 -0
- package/dist/src/hooks/trustedHooks.js.map +1 -0
- package/dist/src/hooks/trustedHooks.test.d.ts +6 -0
- package/dist/src/hooks/trustedHooks.test.js +154 -0
- package/dist/src/hooks/trustedHooks.test.js.map +1 -0
- package/dist/src/hooks/types.d.ts +21 -11
- package/dist/src/hooks/types.js +31 -27
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/hooks/types.test.js +5 -24
- package/dist/src/hooks/types.test.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +32 -1
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.js +9 -4
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +17 -0
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +1 -1
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/types.d.ts +4 -4
- package/dist/src/index.d.ts +17 -1
- package/dist/src/index.js +18 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/auth-provider.d.ts +16 -0
- package/dist/src/mcp/auth-provider.js +7 -0
- package/dist/src/mcp/auth-provider.js.map +1 -0
- package/dist/src/mcp/google-auth-provider.d.ts +10 -2
- package/dist/src/mcp/google-auth-provider.js +28 -0
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.test.js +45 -0
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js +6 -2
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +4 -1
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.d.ts +8 -1
- package/dist/src/mcp/oauth-utils.js +31 -2
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +42 -0
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.d.ts +2 -2
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
- package/dist/src/output/json-formatter.d.ts +2 -2
- package/dist/src/output/json-formatter.js +6 -3
- package/dist/src/output/json-formatter.js.map +1 -1
- package/dist/src/output/json-formatter.test.js +37 -9
- package/dist/src/output/json-formatter.test.js.map +1 -1
- package/dist/src/output/stream-json-formatter.js +6 -0
- package/dist/src/output/stream-json-formatter.js.map +1 -1
- package/dist/src/output/stream-json-formatter.test.js +98 -100
- package/dist/src/output/stream-json-formatter.test.js.map +1 -1
- package/dist/src/output/types.d.ts +3 -0
- package/dist/src/output/types.js.map +1 -1
- package/dist/src/policy/config.js +140 -15
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/config.test.js +21 -0
- package/dist/src/policy/config.test.js.map +1 -1
- package/dist/src/policy/persistence.test.d.ts +6 -0
- package/dist/src/policy/persistence.test.js +154 -0
- package/dist/src/policy/persistence.test.js.map +1 -0
- package/dist/src/policy/policies/agent.toml +31 -0
- package/dist/src/policy/policies/read-only.toml +5 -0
- package/dist/src/policy/policies/write.toml +5 -0
- package/dist/src/policy/policies/yolo.toml +1 -0
- package/dist/src/policy/policy-engine.d.ts +30 -1
- package/dist/src/policy/policy-engine.js +192 -5
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +520 -3
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/policy-updater.test.d.ts +6 -0
- package/dist/src/policy/policy-updater.test.js +116 -0
- package/dist/src/policy/policy-updater.test.js.map +1 -0
- package/dist/src/policy/shell-safety.test.d.ts +6 -0
- package/dist/src/policy/shell-safety.test.js +75 -0
- package/dist/src/policy/shell-safety.test.js.map +1 -0
- package/dist/src/policy/toml-loader.d.ts +3 -5
- package/dist/src/policy/toml-loader.js +12 -60
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +38 -7
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/types.d.ts +72 -1
- package/dist/src/policy/types.js +21 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/policy/utils.d.ts +21 -0
- package/dist/src/policy/utils.js +42 -0
- package/dist/src/policy/utils.js.map +1 -0
- package/dist/src/policy/utils.test.d.ts +6 -0
- package/dist/src/policy/utils.test.js +64 -0
- package/dist/src/policy/utils.test.js.map +1 -0
- package/dist/src/resources/resource-registry.d.ts +30 -0
- package/dist/src/resources/resource-registry.js +57 -0
- package/dist/src/resources/resource-registry.js.map +1 -0
- package/dist/src/resources/resource-registry.test.d.ts +6 -0
- package/dist/src/resources/resource-registry.test.js +54 -0
- package/dist/src/resources/resource-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.js +0 -15
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +0 -62
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +10 -21
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js +2 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/compositeStrategy.js +4 -2
- package/dist/src/routing/strategies/compositeStrategy.js.map +1 -1
- package/dist/src/routing/strategies/compositeStrategy.test.js +11 -10
- package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js +20 -12
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.test.js +63 -39
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +3 -2
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/safety/checker-runner.js +17 -6
- package/dist/src/safety/checker-runner.js.map +1 -1
- package/dist/src/scheduler/tool-executor.d.ts +22 -0
- package/dist/src/scheduler/tool-executor.js +198 -0
- package/dist/src/scheduler/tool-executor.js.map +1 -0
- package/dist/src/scheduler/tool-executor.test.d.ts +6 -0
- package/dist/src/scheduler/tool-executor.test.js +231 -0
- package/dist/src/scheduler/tool-executor.test.js.map +1 -0
- package/dist/src/scheduler/types.d.ts +95 -0
- package/dist/src/scheduler/types.js +7 -0
- package/dist/src/scheduler/types.js.map +1 -0
- package/dist/src/services/chatCompressionService.d.ts +1 -0
- package/dist/src/services/chatCompressionService.js +38 -8
- package/dist/src/services/chatCompressionService.js.map +1 -1
- package/dist/src/services/chatCompressionService.test.js +35 -31
- package/dist/src/services/chatCompressionService.test.js.map +1 -1
- package/dist/src/services/chatRecordingService.d.ts +14 -0
- package/dist/src/services/chatRecordingService.js +37 -0
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/contextManager.d.ts +29 -0
- package/dist/src/services/contextManager.js +71 -0
- package/dist/src/services/contextManager.js.map +1 -0
- package/dist/src/services/contextManager.test.d.ts +6 -0
- package/dist/src/services/contextManager.test.js +104 -0
- package/dist/src/services/contextManager.test.js.map +1 -0
- package/dist/src/services/environmentSanitization.d.ts +15 -0
- package/dist/src/services/environmentSanitization.js +141 -0
- package/dist/src/services/environmentSanitization.js.map +1 -0
- package/dist/src/services/environmentSanitization.test.d.ts +6 -0
- package/dist/src/services/environmentSanitization.test.js +284 -0
- package/dist/src/services/environmentSanitization.test.js.map +1 -0
- package/dist/src/services/fileSystemService.d.ts +0 -9
- package/dist/src/services/fileSystemService.js +0 -11
- package/dist/src/services/fileSystemService.js.map +1 -1
- package/dist/src/services/gitService.js +18 -2
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +56 -0
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.js +5 -4
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +14 -8
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/modelConfig.golden.test.js +32 -0
- package/dist/src/services/modelConfig.golden.test.js.map +1 -1
- package/dist/src/services/modelConfig.integration.test.js +1 -1
- package/dist/src/services/modelConfig.integration.test.js.map +1 -1
- package/dist/src/services/modelConfigService.d.ts +4 -0
- package/dist/src/services/modelConfigService.js +8 -3
- package/dist/src/services/modelConfigService.js.map +1 -1
- package/dist/src/services/modelConfigService.test.js +221 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -1
- package/dist/src/services/modelConfigServiceTestUtils.d.ts +10 -0
- package/dist/src/services/modelConfigServiceTestUtils.js +17 -0
- package/dist/src/services/modelConfigServiceTestUtils.js.map +1 -0
- package/dist/src/services/sessionSummaryService.d.ts +28 -0
- package/dist/src/services/sessionSummaryService.js +131 -0
- package/dist/src/services/sessionSummaryService.js.map +1 -0
- package/dist/src/services/sessionSummaryService.test.d.ts +6 -0
- package/dist/src/services/sessionSummaryService.test.js +785 -0
- package/dist/src/services/sessionSummaryService.test.js.map +1 -0
- package/dist/src/services/sessionSummaryUtils.d.ts +16 -0
- package/dist/src/services/sessionSummaryUtils.js +129 -0
- package/dist/src/services/sessionSummaryUtils.js.map +1 -0
- package/dist/src/services/sessionSummaryUtils.test.d.ts +6 -0
- package/dist/src/services/sessionSummaryUtils.test.js +137 -0
- package/dist/src/services/sessionSummaryUtils.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.d.ts +4 -0
- package/dist/src/services/shellExecutionService.js +45 -27
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +240 -8
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/services/test-data/resolved-aliases-retry.golden.json +238 -0
- package/dist/src/services/test-data/resolved-aliases.golden.json +36 -0
- package/dist/src/skills/skillLoader.d.ts +28 -0
- package/dist/src/skills/skillLoader.js +77 -0
- package/dist/src/skills/skillLoader.js.map +1 -0
- package/dist/src/skills/skillLoader.test.d.ts +1 -0
- package/dist/src/skills/skillLoader.test.js +2 -0
- package/dist/src/skills/skillLoader.test.js.map +1 -0
- package/dist/src/skills/skillManager.d.ts +51 -0
- package/dist/src/skills/skillManager.js +89 -0
- package/dist/src/skills/skillManager.js.map +1 -0
- package/dist/src/skills/skillManager.test.d.ts +6 -0
- package/dist/src/skills/skillManager.test.js +128 -0
- package/dist/src/skills/skillManager.test.js.map +1 -0
- package/dist/src/telemetry/activity-detector.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +11 -7
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +127 -47
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +105 -18
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +9 -3
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +20 -5
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/config.js +2 -0
- package/dist/src/telemetry/config.js.map +1 -1
- package/dist/src/telemetry/config.test.js +25 -0
- package/dist/src/telemetry/config.test.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.d.ts +4 -3
- package/dist/src/telemetry/gcp-exporters.js +8 -4
- 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/loggers.d.ts +5 -3
- package/dist/src/telemetry/loggers.js +353 -334
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +1 -0
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +238 -31
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +22 -0
- package/dist/src/telemetry/metrics.js +32 -0
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +64 -0
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sanitize.d.ts +25 -0
- package/dist/src/telemetry/sanitize.js +48 -0
- package/dist/src/telemetry/sanitize.js.map +1 -0
- package/dist/src/telemetry/sanitize.test.d.ts +6 -0
- package/dist/src/telemetry/sanitize.test.js +279 -0
- package/dist/src/telemetry/sanitize.test.js.map +1 -0
- package/dist/src/telemetry/sdk.d.ts +9 -2
- package/dist/src/telemetry/sdk.js +142 -17
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/sdk.test.js +130 -28
- package/dist/src/telemetry/sdk.test.js.map +1 -1
- package/dist/src/telemetry/semantic.js +1 -1
- package/dist/src/telemetry/semantic.js.map +1 -1
- package/dist/src/telemetry/startupProfiler.d.ts +51 -0
- package/dist/src/telemetry/startupProfiler.js +170 -0
- package/dist/src/telemetry/startupProfiler.js.map +1 -0
- package/dist/src/telemetry/startupProfiler.test.d.ts +6 -0
- package/dist/src/telemetry/startupProfiler.test.js +285 -0
- package/dist/src/telemetry/startupProfiler.test.js.map +1 -0
- package/dist/src/telemetry/telemetry.test.js +10 -3
- package/dist/src/telemetry/telemetry.test.js.map +1 -1
- package/dist/src/telemetry/trace.js +2 -2
- package/dist/src/telemetry/trace.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +62 -16
- package/dist/src/telemetry/types.js +157 -27
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
- package/dist/src/telemetry/uiTelemetry.js +2 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +4 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/mock-message-bus.d.ts +61 -0
- package/dist/src/test-utils/mock-message-bus.js +160 -0
- package/dist/src/test-utils/mock-message-bus.js.map +1 -0
- package/dist/src/test-utils/mock-tool.d.ts +5 -3
- package/dist/src/test-utils/mock-tool.js +12 -11
- package/dist/src/test-utils/mock-tool.js.map +1 -1
- package/dist/src/tools/activate-skill.d.ts +27 -0
- package/dist/src/tools/activate-skill.js +120 -0
- package/dist/src/tools/activate-skill.js.map +1 -0
- package/dist/src/tools/activate-skill.test.d.ts +6 -0
- package/dist/src/tools/activate-skill.test.js +95 -0
- package/dist/src/tools/activate-skill.test.js.map +1 -0
- package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
- package/dist/src/tools/confirmation-policy.test.js +142 -0
- package/dist/src/tools/confirmation-policy.test.js.map +1 -0
- package/dist/src/tools/edit.d.ts +27 -5
- package/dist/src/tools/edit.js +449 -137
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +258 -526
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/get-internal-docs.d.ts +27 -0
- package/dist/src/tools/get-internal-docs.js +129 -0
- package/dist/src/tools/get-internal-docs.js.map +1 -0
- package/dist/src/tools/get-internal-docs.test.d.ts +6 -0
- package/dist/src/tools/get-internal-docs.test.js +57 -0
- package/dist/src/tools/get-internal-docs.test.js.map +1 -0
- package/dist/src/tools/glob.d.ts +2 -2
- package/dist/src/tools/glob.js +1 -1
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +2 -1
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +2 -2
- package/dist/src/tools/grep.js +1 -1
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +5 -4
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +2 -2
- package/dist/src/tools/ls.js +2 -2
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +2 -1
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +3 -1
- package/dist/src/tools/mcp-client-manager.js +42 -9
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +66 -10
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +44 -6
- package/dist/src/tools/mcp-client.js +476 -176
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +633 -36
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +2 -2
- package/dist/src/tools/mcp-tool.js +20 -7
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +35 -5
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +3 -3
- package/dist/src/tools/memoryTool.js +3 -4
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +5 -2
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/message-bus-integration.test.js +10 -37
- package/dist/src/tools/message-bus-integration.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +22 -13
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +2 -2
- package/dist/src/tools/read-file.js +2 -2
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +3 -2
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +2 -2
- package/dist/src/tools/read-many-files.js +7 -6
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +4 -3
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +3 -2
- package/dist/src/tools/ripGrep.js +18 -7
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +60 -4
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +5 -7
- package/dist/src/tools/shell.js +77 -51
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +59 -63
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-error.d.ts +2 -1
- package/dist/src/tools/tool-error.js +2 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +17 -0
- package/dist/src/tools/tool-names.js +59 -0
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-names.test.d.ts +6 -0
- package/dist/src/tools/tool-names.test.js +43 -0
- package/dist/src/tools/tool-names.test.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +11 -7
- package/dist/src/tools/tool-registry.js +15 -10
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +16 -11
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +25 -6
- package/dist/src/tools/tools.js +44 -25
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.js +3 -1
- package/dist/src/tools/tools.test.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +2 -2
- package/dist/src/tools/web-fetch.js +22 -9
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +18 -19
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.d.ts +2 -2
- package/dist/src/tools/web-search.js +5 -5
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +2 -1
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +2 -2
- package/dist/src/tools/write-file.js +10 -4
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +4 -1
- 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 +5 -4
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/tools/write-todos.test.js +2 -1
- package/dist/src/tools/write-todos.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.d.ts +8 -0
- package/dist/src/utils/bfsFileSearch.js +63 -23
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +65 -1
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/checkpointUtils.d.ts +82 -0
- package/dist/src/utils/checkpointUtils.js +117 -0
- package/dist/src/utils/checkpointUtils.js.map +1 -0
- package/dist/src/utils/checkpointUtils.test.d.ts +6 -0
- package/dist/src/utils/checkpointUtils.test.js +229 -0
- package/dist/src/utils/checkpointUtils.test.js.map +1 -0
- package/dist/src/utils/customHeaderUtils.d.ts +9 -0
- package/dist/src/utils/customHeaderUtils.js +34 -0
- package/dist/src/utils/customHeaderUtils.js.map +1 -0
- package/dist/src/utils/customHeaderUtils.test.d.ts +6 -0
- package/dist/src/utils/customHeaderUtils.test.js +77 -0
- package/dist/src/utils/customHeaderUtils.test.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +3 -0
- package/dist/src/utils/debugLogger.js +28 -0
- package/dist/src/utils/debugLogger.js.map +1 -1
- package/dist/src/utils/editCorrector.js +6 -5
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +7 -3
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +9 -1
- package/dist/src/utils/editor.js +23 -14
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +1 -0
- package/dist/src/utils/environmentContext.js +4 -0
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +2 -0
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/errorReporting.d.ts +1 -1
- package/dist/src/utils/errorReporting.js +13 -12
- package/dist/src/utils/errorReporting.js.map +1 -1
- package/dist/src/utils/errorReporting.test.js +17 -14
- package/dist/src/utils/errorReporting.test.js.map +1 -1
- package/dist/src/utils/errors.d.ts +8 -0
- package/dist/src/utils/errors.js +39 -2
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/errors.test.d.ts +6 -0
- package/dist/src/utils/errors.test.js +155 -0
- package/dist/src/utils/errors.test.js.map +1 -0
- package/dist/src/utils/events.d.ts +49 -19
- package/dist/src/utils/events.js +21 -9
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/events.test.js +25 -0
- package/dist/src/utils/events.test.js.map +1 -1
- package/dist/src/utils/exitCodes.d.ts +12 -0
- package/dist/src/utils/exitCodes.js +13 -0
- package/dist/src/utils/exitCodes.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +2 -2
- package/dist/src/utils/extensionLoader.js +5 -6
- package/dist/src/utils/extensionLoader.js.map +1 -1
- package/dist/src/utils/extensionLoader.test.js +11 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -1
- package/dist/src/utils/fetch.d.ts +1 -1
- package/dist/src/utils/fetch.js +3 -3
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +4 -0
- package/dist/src/utils/fileUtils.js +53 -0
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +127 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +1 -1
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/geminiIgnoreParser.d.ts +11 -0
- package/dist/src/utils/geminiIgnoreParser.js +20 -0
- package/dist/src/utils/geminiIgnoreParser.js.map +1 -1
- package/dist/src/utils/geminiIgnoreParser.test.js +48 -0
- package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/generateContentResponseUtilities.d.ts +3 -1
- package/dist/src/utils/generateContentResponseUtilities.js +106 -0
- package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
- package/dist/src/utils/generateContentResponseUtilities.test.js +279 -2
- package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
- package/dist/src/utils/getFolderStructure.js +7 -2
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/googleErrors.js +31 -18
- package/dist/src/utils/googleErrors.js.map +1 -1
- package/dist/src/utils/googleErrors.test.js +10 -2
- package/dist/src/utils/googleErrors.test.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.d.ts +3 -3
- package/dist/src/utils/googleQuotaErrors.js +32 -6
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.test.js +94 -2
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +5 -0
- package/dist/src/utils/memoryDiscovery.js +9 -5
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +31 -1
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +4 -0
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/package.d.ts +14 -0
- package/dist/src/utils/package.js +15 -2
- package/dist/src/utils/package.js.map +1 -1
- package/dist/src/utils/pathCorrector.js +12 -2
- package/dist/src/utils/pathCorrector.js.map +1 -1
- package/dist/src/utils/pathCorrector.test.js +6 -2
- package/dist/src/utils/pathCorrector.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +11 -0
- package/dist/src/utils/retry.js +62 -21
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +170 -10
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/schemaValidator.d.ts +1 -1
- package/dist/src/utils/schemaValidator.js +1 -1
- package/dist/src/utils/shell-permissions.d.ts +52 -0
- package/dist/src/utils/shell-permissions.js +188 -0
- package/dist/src/utils/shell-permissions.js.map +1 -0
- package/dist/src/utils/shell-permissions.test.d.ts +6 -0
- package/dist/src/utils/shell-permissions.test.js +369 -0
- package/dist/src/utils/shell-permissions.test.js.map +1 -0
- package/dist/src/utils/shell-utils.d.ts +16 -47
- package/dist/src/utils/shell-utils.js +99 -195
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +99 -288
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/stdio.d.ts +2 -2
- package/dist/src/utils/stdio.js +2 -2
- package/dist/src/utils/stdio.js.map +1 -1
- package/dist/src/utils/stdio.test.js +5 -5
- package/dist/src/utils/stdio.test.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +3 -2
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/terminal.d.ts +4 -0
- package/dist/src/utils/terminal.js +12 -0
- package/dist/src/utils/terminal.js.map +1 -1
- package/dist/src/utils/terminalSerializer.test.js +17 -0
- package/dist/src/utils/terminalSerializer.test.js.map +1 -1
- package/dist/src/utils/tokenCalculation.d.ts +19 -0
- package/dist/src/utils/tokenCalculation.js +85 -0
- package/dist/src/utils/tokenCalculation.js.map +1 -0
- package/dist/src/utils/tokenCalculation.test.d.ts +6 -0
- package/dist/src/utils/tokenCalculation.test.js +87 -0
- package/dist/src/utils/tokenCalculation.test.js.map +1 -0
- package/dist/src/utils/tool-utils.d.ts +9 -0
- package/dist/src/utils/tool-utils.js +29 -0
- package/dist/src/utils/tool-utils.js.map +1 -1
- package/dist/src/utils/tool-utils.test.js +17 -2
- package/dist/src/utils/tool-utils.test.js.map +1 -1
- package/dist/src/utils/version.d.ts +6 -0
- package/dist/src/utils/version.js +15 -0
- package/dist/src/utils/version.js.map +1 -0
- package/dist/src/utils/version.test.d.ts +6 -0
- package/dist/src/utils/version.test.js +39 -0
- package/dist/src/utils/version.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
-
const
|
|
7
|
+
const mockFixLLMEditWithInstruction = vi.hoisted(() => vi.fn());
|
|
8
8
|
const mockGenerateJson = vi.hoisted(() => vi.fn());
|
|
9
9
|
const mockOpenDiff = vi.hoisted(() => vi.fn());
|
|
10
10
|
import { IdeClient } from '../ide/ide-client.js';
|
|
@@ -13,36 +13,38 @@ vi.mock('../ide/ide-client.js', () => ({
|
|
|
13
13
|
getInstance: vi.fn(),
|
|
14
14
|
},
|
|
15
15
|
}));
|
|
16
|
-
vi.mock('../utils/
|
|
17
|
-
|
|
16
|
+
vi.mock('../utils/llm-edit-fixer.js', () => ({
|
|
17
|
+
FixLLMEditWithInstruction: mockFixLLMEditWithInstruction,
|
|
18
18
|
}));
|
|
19
19
|
vi.mock('../core/client.js', () => ({
|
|
20
20
|
GeminiClient: vi.fn().mockImplementation(() => ({
|
|
21
21
|
generateJson: mockGenerateJson,
|
|
22
|
+
getHistory: vi.fn().mockResolvedValue([]),
|
|
22
23
|
})),
|
|
23
24
|
}));
|
|
24
25
|
vi.mock('../utils/editor.js', () => ({
|
|
25
26
|
openDiff: mockOpenDiff,
|
|
26
27
|
}));
|
|
27
|
-
vi
|
|
28
|
-
|
|
29
|
-
}));
|
|
30
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
31
|
-
import { applyReplacement, EditTool } from './edit.js';
|
|
28
|
+
import { describe, it, expect, beforeEach, afterEach, vi, } from 'vitest';
|
|
29
|
+
import { EditTool, applyReplacement, calculateReplacement, } from './edit.js';
|
|
32
30
|
import { ToolConfirmationOutcome } from './tools.js';
|
|
33
31
|
import { ToolErrorType } from './tool-error.js';
|
|
32
|
+
import { createMockMessageBus, getMockMessageBusInstance, } from '../test-utils/mock-message-bus.js';
|
|
34
33
|
import path from 'node:path';
|
|
35
34
|
import fs from 'node:fs';
|
|
36
35
|
import os from 'node:os';
|
|
37
36
|
import { ApprovalMode } from '../policy/types.js';
|
|
37
|
+
import {} from '../config/config.js';
|
|
38
|
+
import {} from '@google/genai';
|
|
39
|
+
import { createMockWorkspaceContext } from '../test-utils/mockWorkspaceContext.js';
|
|
38
40
|
import { StandardFileSystemService } from '../services/fileSystemService.js';
|
|
39
|
-
import { WorkspaceContext } from '../utils/workspaceContext.js';
|
|
40
41
|
describe('EditTool', () => {
|
|
41
42
|
let tool;
|
|
42
43
|
let tempDir;
|
|
43
44
|
let rootDir;
|
|
44
45
|
let mockConfig;
|
|
45
46
|
let geminiClient;
|
|
47
|
+
let fileSystemService;
|
|
46
48
|
let baseLlmClient;
|
|
47
49
|
beforeEach(() => {
|
|
48
50
|
vi.restoreAllMocks();
|
|
@@ -50,23 +52,26 @@ describe('EditTool', () => {
|
|
|
50
52
|
rootDir = path.join(tempDir, 'root');
|
|
51
53
|
fs.mkdirSync(rootDir);
|
|
52
54
|
geminiClient = {
|
|
53
|
-
generateJson: mockGenerateJson,
|
|
55
|
+
generateJson: mockGenerateJson,
|
|
56
|
+
getHistory: vi.fn().mockResolvedValue([]),
|
|
54
57
|
};
|
|
55
58
|
baseLlmClient = {
|
|
56
|
-
generateJson:
|
|
59
|
+
generateJson: mockGenerateJson,
|
|
57
60
|
};
|
|
61
|
+
fileSystemService = new StandardFileSystemService();
|
|
58
62
|
mockConfig = {
|
|
63
|
+
getUsageStatisticsEnabled: vi.fn(() => true),
|
|
64
|
+
getSessionId: vi.fn(() => 'mock-session-id'),
|
|
65
|
+
getContentGeneratorConfig: vi.fn(() => ({ authType: 'mock' })),
|
|
66
|
+
getProxy: vi.fn(() => undefined),
|
|
59
67
|
getGeminiClient: vi.fn().mockReturnValue(geminiClient),
|
|
60
68
|
getBaseLlmClient: vi.fn().mockReturnValue(baseLlmClient),
|
|
61
69
|
getTargetDir: () => rootDir,
|
|
62
70
|
getApprovalMode: vi.fn(),
|
|
63
71
|
setApprovalMode: vi.fn(),
|
|
64
|
-
getWorkspaceContext: () =>
|
|
65
|
-
getFileSystemService: () =>
|
|
72
|
+
getWorkspaceContext: () => createMockWorkspaceContext(rootDir),
|
|
73
|
+
getFileSystemService: () => fileSystemService,
|
|
66
74
|
getIdeMode: () => false,
|
|
67
|
-
// getGeminiConfig: () => ({ apiKey: 'test-api-key' }), // This was not a real Config method
|
|
68
|
-
// Add other properties/methods of Config if EditTool uses them
|
|
69
|
-
// Minimal other methods to satisfy Config type if needed by EditTool constructor or other direct uses:
|
|
70
75
|
getApiKey: () => 'test-api-key',
|
|
71
76
|
getModel: () => 'test-model',
|
|
72
77
|
getSandbox: () => false,
|
|
@@ -81,34 +86,21 @@ describe('EditTool', () => {
|
|
|
81
86
|
setUserMemory: vi.fn(),
|
|
82
87
|
getGeminiMdFileCount: () => 0,
|
|
83
88
|
setGeminiMdFileCount: vi.fn(),
|
|
84
|
-
getToolRegistry: () => ({}),
|
|
89
|
+
getToolRegistry: () => ({}),
|
|
85
90
|
isInteractive: () => false,
|
|
91
|
+
getExperiments: () => { },
|
|
86
92
|
};
|
|
87
|
-
// Reset mocks before each test
|
|
88
93
|
mockConfig.getApprovalMode.mockClear();
|
|
89
|
-
// Default to not skipping confirmation
|
|
90
94
|
mockConfig.getApprovalMode.mockReturnValue(ApprovalMode.DEFAULT);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
let index = currentContent.indexOf(params.old_string);
|
|
98
|
-
while (index !== -1) {
|
|
99
|
-
occurrences++;
|
|
100
|
-
index = currentContent.indexOf(params.old_string, index + 1);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
else if (params.old_string === '') {
|
|
104
|
-
occurrences = 0; // Creating a new file
|
|
105
|
-
}
|
|
106
|
-
return Promise.resolve({ params, occurrences });
|
|
95
|
+
mockFixLLMEditWithInstruction.mockReset();
|
|
96
|
+
mockFixLLMEditWithInstruction.mockResolvedValue({
|
|
97
|
+
noChangesRequired: false,
|
|
98
|
+
search: '',
|
|
99
|
+
replace: '',
|
|
100
|
+
explanation: 'LLM fix failed',
|
|
107
101
|
});
|
|
108
|
-
// Default mock for generateJson to return the snippet unchanged
|
|
109
102
|
mockGenerateJson.mockReset();
|
|
110
103
|
mockGenerateJson.mockImplementation(async (contents, schema) => {
|
|
111
|
-
// The problematic_snippet is the last part of the user's content
|
|
112
104
|
const userContent = contents.find((c) => c.role === 'user');
|
|
113
105
|
let promptText = '';
|
|
114
106
|
if (userContent && userContent.parts) {
|
|
@@ -125,17 +117,17 @@ describe('EditTool', () => {
|
|
|
125
117
|
});
|
|
126
118
|
}
|
|
127
119
|
if (schema.properties?.corrected_new_string) {
|
|
128
|
-
// For new_string correction, we might need more sophisticated logic,
|
|
129
|
-
// but for now, returning original is a safe default if not specified by a test.
|
|
130
120
|
const originalNewStringMatch = promptText.match(/original_new_string \(what was intended to replace original_old_string\):\n```\n([\s\S]*?)\n```/);
|
|
131
121
|
const originalNewString = originalNewStringMatch && originalNewStringMatch[1]
|
|
132
122
|
? originalNewStringMatch[1]
|
|
133
123
|
: '';
|
|
134
124
|
return Promise.resolve({ corrected_new_string: originalNewString });
|
|
135
125
|
}
|
|
136
|
-
return Promise.resolve({});
|
|
126
|
+
return Promise.resolve({});
|
|
137
127
|
});
|
|
138
|
-
|
|
128
|
+
const bus = createMockMessageBus();
|
|
129
|
+
getMockMessageBusInstance(bus).defaultToolDecision = 'ask_user';
|
|
130
|
+
tool = new EditTool(mockConfig, bus);
|
|
139
131
|
});
|
|
140
132
|
afterEach(() => {
|
|
141
133
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
@@ -233,180 +225,85 @@ describe('EditTool', () => {
|
|
|
233
225
|
expect(result).toBe(expected);
|
|
234
226
|
});
|
|
235
227
|
});
|
|
228
|
+
describe('calculateReplacement', () => {
|
|
229
|
+
const abortSignal = new AbortController().signal;
|
|
230
|
+
it.each([
|
|
231
|
+
{
|
|
232
|
+
name: 'perform an exact replacement',
|
|
233
|
+
content: 'hello world',
|
|
234
|
+
old_string: 'world',
|
|
235
|
+
new_string: 'moon',
|
|
236
|
+
expected: 'hello moon',
|
|
237
|
+
occurrences: 1,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: 'perform a flexible, whitespace-insensitive replacement',
|
|
241
|
+
content: ' hello\n world\n',
|
|
242
|
+
old_string: 'hello\nworld',
|
|
243
|
+
new_string: 'goodbye\nmoon',
|
|
244
|
+
expected: ' goodbye\n moon\n',
|
|
245
|
+
occurrences: 1,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'return 0 occurrences if no match is found',
|
|
249
|
+
content: 'hello world',
|
|
250
|
+
old_string: 'nomatch',
|
|
251
|
+
new_string: 'moon',
|
|
252
|
+
expected: 'hello world',
|
|
253
|
+
occurrences: 0,
|
|
254
|
+
},
|
|
255
|
+
])('should $name', async ({ content, old_string, new_string, expected, occurrences }) => {
|
|
256
|
+
const result = await calculateReplacement(mockConfig, {
|
|
257
|
+
params: {
|
|
258
|
+
file_path: 'test.txt',
|
|
259
|
+
instruction: 'test',
|
|
260
|
+
old_string,
|
|
261
|
+
new_string,
|
|
262
|
+
},
|
|
263
|
+
currentContent: content,
|
|
264
|
+
abortSignal,
|
|
265
|
+
});
|
|
266
|
+
expect(result.newContent).toBe(expected);
|
|
267
|
+
expect(result.occurrences).toBe(occurrences);
|
|
268
|
+
});
|
|
269
|
+
it('should perform a regex-based replacement for flexible intra-line whitespace', async () => {
|
|
270
|
+
// This case would fail with the previous exact and line-trimming flexible logic
|
|
271
|
+
// because the whitespace *within* the line is different.
|
|
272
|
+
const content = ' function myFunc( a, b ) {\n return a + b;\n }';
|
|
273
|
+
const result = await calculateReplacement(mockConfig, {
|
|
274
|
+
params: {
|
|
275
|
+
file_path: 'test.js',
|
|
276
|
+
instruction: 'test',
|
|
277
|
+
old_string: 'function myFunc(a, b) {', // Note the normalized whitespace
|
|
278
|
+
new_string: 'const yourFunc = (a, b) => {',
|
|
279
|
+
},
|
|
280
|
+
currentContent: content,
|
|
281
|
+
abortSignal,
|
|
282
|
+
});
|
|
283
|
+
// The indentation from the original line should be preserved and applied to the new string.
|
|
284
|
+
const expectedContent = ' const yourFunc = (a, b) => {\n return a + b;\n }';
|
|
285
|
+
expect(result.newContent).toBe(expectedContent);
|
|
286
|
+
expect(result.occurrences).toBe(1);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
236
289
|
describe('validateToolParams', () => {
|
|
237
290
|
it('should return null for valid params', () => {
|
|
238
291
|
const params = {
|
|
239
292
|
file_path: path.join(rootDir, 'test.txt'),
|
|
293
|
+
instruction: 'An instruction',
|
|
240
294
|
old_string: 'old',
|
|
241
295
|
new_string: 'new',
|
|
242
296
|
};
|
|
243
297
|
expect(tool.validateToolParams(params)).toBeNull();
|
|
244
298
|
});
|
|
245
|
-
it('should return error
|
|
246
|
-
const params = {
|
|
247
|
-
file_path: path.join(tempDir, 'outside-root.txt'),
|
|
248
|
-
old_string: 'old',
|
|
249
|
-
new_string: 'new',
|
|
250
|
-
};
|
|
251
|
-
const error = tool.validateToolParams(params);
|
|
252
|
-
expect(error).toContain('File path must be within one of the workspace directories');
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
describe('shouldConfirmExecute', () => {
|
|
256
|
-
const testFile = 'edit_me.txt';
|
|
257
|
-
let filePath;
|
|
258
|
-
beforeEach(() => {
|
|
259
|
-
filePath = path.join(rootDir, testFile);
|
|
260
|
-
});
|
|
261
|
-
it('should resolve relative path and request confirmation', async () => {
|
|
262
|
-
fs.writeFileSync(filePath, 'some old content here');
|
|
263
|
-
const params = {
|
|
264
|
-
file_path: testFile, // relative path
|
|
265
|
-
old_string: 'old',
|
|
266
|
-
new_string: 'new',
|
|
267
|
-
};
|
|
268
|
-
// ensureCorrectEdit will be called by shouldConfirmExecute
|
|
269
|
-
mockEnsureCorrectEdit.mockResolvedValueOnce({
|
|
270
|
-
params: { ...params, file_path: filePath },
|
|
271
|
-
occurrences: 1,
|
|
272
|
-
});
|
|
273
|
-
const invocation = tool.build(params);
|
|
274
|
-
const confirmation = await invocation.shouldConfirmExecute(new AbortController().signal);
|
|
275
|
-
expect(confirmation).toEqual(expect.objectContaining({
|
|
276
|
-
title: `Confirm Edit: ${testFile}`,
|
|
277
|
-
fileName: testFile,
|
|
278
|
-
fileDiff: expect.any(String),
|
|
279
|
-
}));
|
|
280
|
-
});
|
|
281
|
-
it('should request confirmation for valid edit', async () => {
|
|
282
|
-
fs.writeFileSync(filePath, 'some old content here');
|
|
283
|
-
const params = {
|
|
284
|
-
file_path: filePath,
|
|
285
|
-
old_string: 'old',
|
|
286
|
-
new_string: 'new',
|
|
287
|
-
};
|
|
288
|
-
// ensureCorrectEdit will be called by shouldConfirmExecute
|
|
289
|
-
mockEnsureCorrectEdit.mockResolvedValueOnce({ params, occurrences: 1 });
|
|
290
|
-
const invocation = tool.build(params);
|
|
291
|
-
const confirmation = await invocation.shouldConfirmExecute(new AbortController().signal);
|
|
292
|
-
expect(confirmation).toEqual(expect.objectContaining({
|
|
293
|
-
title: `Confirm Edit: ${testFile}`,
|
|
294
|
-
fileName: testFile,
|
|
295
|
-
fileDiff: expect.any(String),
|
|
296
|
-
}));
|
|
297
|
-
});
|
|
298
|
-
it('should return false if old_string is not found (ensureCorrectEdit returns 0)', async () => {
|
|
299
|
-
fs.writeFileSync(filePath, 'some content here');
|
|
300
|
-
const params = {
|
|
301
|
-
file_path: filePath,
|
|
302
|
-
old_string: 'not_found',
|
|
303
|
-
new_string: 'new',
|
|
304
|
-
};
|
|
305
|
-
mockEnsureCorrectEdit.mockResolvedValueOnce({ params, occurrences: 0 });
|
|
306
|
-
const invocation = tool.build(params);
|
|
307
|
-
const confirmation = await invocation.shouldConfirmExecute(new AbortController().signal);
|
|
308
|
-
expect(confirmation).toBe(false);
|
|
309
|
-
});
|
|
310
|
-
it('should return false if multiple occurrences of old_string are found (ensureCorrectEdit returns > 1)', async () => {
|
|
311
|
-
fs.writeFileSync(filePath, 'old old content here');
|
|
312
|
-
const params = {
|
|
313
|
-
file_path: filePath,
|
|
314
|
-
old_string: 'old',
|
|
315
|
-
new_string: 'new',
|
|
316
|
-
};
|
|
317
|
-
mockEnsureCorrectEdit.mockResolvedValueOnce({ params, occurrences: 2 });
|
|
318
|
-
const invocation = tool.build(params);
|
|
319
|
-
const confirmation = await invocation.shouldConfirmExecute(new AbortController().signal);
|
|
320
|
-
expect(confirmation).toBe(false);
|
|
321
|
-
});
|
|
322
|
-
it('should request confirmation for creating a new file (empty old_string)', async () => {
|
|
323
|
-
const newFileName = 'new_file.txt';
|
|
324
|
-
const newFilePath = path.join(rootDir, newFileName);
|
|
325
|
-
const params = {
|
|
326
|
-
file_path: newFilePath,
|
|
327
|
-
old_string: '',
|
|
328
|
-
new_string: 'new file content',
|
|
329
|
-
};
|
|
330
|
-
// ensureCorrectEdit might not be called if old_string is empty,
|
|
331
|
-
// as shouldConfirmExecute handles this for diff generation.
|
|
332
|
-
// If it is called, it should return 0 occurrences for a new file.
|
|
333
|
-
mockEnsureCorrectEdit.mockResolvedValueOnce({ params, occurrences: 0 });
|
|
334
|
-
const invocation = tool.build(params);
|
|
335
|
-
const confirmation = await invocation.shouldConfirmExecute(new AbortController().signal);
|
|
336
|
-
expect(confirmation).toEqual(expect.objectContaining({
|
|
337
|
-
title: `Confirm Edit: ${newFileName}`,
|
|
338
|
-
fileName: newFileName,
|
|
339
|
-
fileDiff: expect.any(String),
|
|
340
|
-
}));
|
|
341
|
-
});
|
|
342
|
-
it('should use corrected params from ensureCorrectEdit for diff generation', async () => {
|
|
343
|
-
const originalContent = 'This is the original string to be replaced.';
|
|
344
|
-
const originalOldString = 'original string';
|
|
345
|
-
const originalNewString = 'new string';
|
|
346
|
-
const correctedOldString = 'original string to be replaced'; // More specific
|
|
347
|
-
const correctedNewString = 'completely new string'; // Different replacement
|
|
348
|
-
const expectedFinalContent = 'This is the completely new string.';
|
|
349
|
-
fs.writeFileSync(filePath, originalContent);
|
|
350
|
-
const params = {
|
|
351
|
-
file_path: filePath,
|
|
352
|
-
old_string: originalOldString,
|
|
353
|
-
new_string: originalNewString,
|
|
354
|
-
};
|
|
355
|
-
// The main beforeEach already calls mockEnsureCorrectEdit.mockReset()
|
|
356
|
-
// Set a specific mock for this test case
|
|
357
|
-
let mockCalled = false;
|
|
358
|
-
mockEnsureCorrectEdit.mockImplementationOnce(async (_, content, p, client, baseClient) => {
|
|
359
|
-
mockCalled = true;
|
|
360
|
-
expect(content).toBe(originalContent);
|
|
361
|
-
expect(p).toBe(params);
|
|
362
|
-
expect(client).toBe(geminiClient);
|
|
363
|
-
expect(baseClient).toBe(baseLlmClient);
|
|
364
|
-
return {
|
|
365
|
-
params: {
|
|
366
|
-
file_path: filePath,
|
|
367
|
-
old_string: correctedOldString,
|
|
368
|
-
new_string: correctedNewString,
|
|
369
|
-
},
|
|
370
|
-
occurrences: 1,
|
|
371
|
-
};
|
|
372
|
-
});
|
|
373
|
-
const invocation = tool.build(params);
|
|
374
|
-
const confirmation = (await invocation.shouldConfirmExecute(new AbortController().signal));
|
|
375
|
-
expect(mockCalled).toBe(true); // Check if the mock implementation was run
|
|
376
|
-
// expect(mockEnsureCorrectEdit).toHaveBeenCalledWith(originalContent, params, expect.anything()); // Keep this commented for now
|
|
377
|
-
expect(confirmation).toEqual(expect.objectContaining({
|
|
378
|
-
title: `Confirm Edit: ${testFile}`,
|
|
379
|
-
fileName: testFile,
|
|
380
|
-
}));
|
|
381
|
-
// Check that the diff is based on the corrected strings leading to the new state
|
|
382
|
-
expect(confirmation.fileDiff).toContain(`-${originalContent}`);
|
|
383
|
-
expect(confirmation.fileDiff).toContain(`+${expectedFinalContent}`);
|
|
384
|
-
// Verify that applying the correctedOldString and correctedNewString to originalContent
|
|
385
|
-
// indeed produces the expectedFinalContent, which is what the diff should reflect.
|
|
386
|
-
const patchedContent = originalContent.replace(correctedOldString, // This was the string identified by ensureCorrectEdit for replacement
|
|
387
|
-
correctedNewString);
|
|
388
|
-
expect(patchedContent).toBe(expectedFinalContent);
|
|
389
|
-
});
|
|
390
|
-
it('should rethrow calculateEdit errors when the abort signal is triggered', async () => {
|
|
391
|
-
const filePath = path.join(rootDir, 'abort-confirmation.txt');
|
|
299
|
+
it('should return an error if path is outside the workspace', () => {
|
|
392
300
|
const params = {
|
|
393
|
-
file_path:
|
|
301
|
+
file_path: path.join(os.tmpdir(), 'outside.txt'),
|
|
302
|
+
instruction: 'An instruction',
|
|
394
303
|
old_string: 'old',
|
|
395
304
|
new_string: 'new',
|
|
396
305
|
};
|
|
397
|
-
|
|
398
|
-
const abortController = new AbortController();
|
|
399
|
-
const abortError = new Error('Abort requested');
|
|
400
|
-
const calculateSpy = vi
|
|
401
|
-
.spyOn(invocation, 'calculateEdit')
|
|
402
|
-
.mockImplementation(async () => {
|
|
403
|
-
if (!abortController.signal.aborted) {
|
|
404
|
-
abortController.abort();
|
|
405
|
-
}
|
|
406
|
-
throw abortError;
|
|
407
|
-
});
|
|
408
|
-
await expect(invocation.shouldConfirmExecute(abortController.signal)).rejects.toBe(abortError);
|
|
409
|
-
calculateSpy.mockRestore();
|
|
306
|
+
expect(tool.validateToolParams(params)).toMatch(/must be within one of the workspace directories/);
|
|
410
307
|
});
|
|
411
308
|
});
|
|
412
309
|
describe('execute', () => {
|
|
@@ -414,53 +311,17 @@ describe('EditTool', () => {
|
|
|
414
311
|
let filePath;
|
|
415
312
|
beforeEach(() => {
|
|
416
313
|
filePath = path.join(rootDir, testFile);
|
|
417
|
-
// Default for execute tests, can be overridden
|
|
418
|
-
mockEnsureCorrectEdit.mockImplementation(async (_, content, params) => {
|
|
419
|
-
let occurrences = 0;
|
|
420
|
-
if (params.old_string && content) {
|
|
421
|
-
let index = content.indexOf(params.old_string);
|
|
422
|
-
while (index !== -1) {
|
|
423
|
-
occurrences++;
|
|
424
|
-
index = content.indexOf(params.old_string, index + 1);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
else if (params.old_string === '') {
|
|
428
|
-
occurrences = 0;
|
|
429
|
-
}
|
|
430
|
-
return { params, occurrences };
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
it('should resolve relative path and execute successfully', async () => {
|
|
434
|
-
const initialContent = 'This is some old text.';
|
|
435
|
-
const newContent = 'This is some new text.';
|
|
436
|
-
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
437
|
-
const params = {
|
|
438
|
-
file_path: testFile, // relative path
|
|
439
|
-
old_string: 'old',
|
|
440
|
-
new_string: 'new',
|
|
441
|
-
};
|
|
442
|
-
const invocation = tool.build(params);
|
|
443
|
-
const result = await invocation.execute(new AbortController().signal);
|
|
444
|
-
expect(result.llmContent).toMatch(/Successfully modified file/);
|
|
445
|
-
expect(fs.readFileSync(filePath, 'utf8')).toBe(newContent);
|
|
446
|
-
});
|
|
447
|
-
it('should throw error if file path is empty', async () => {
|
|
448
|
-
const params = {
|
|
449
|
-
file_path: '',
|
|
450
|
-
old_string: 'old',
|
|
451
|
-
new_string: 'new',
|
|
452
|
-
};
|
|
453
|
-
expect(() => tool.build(params)).toThrow(/The 'file_path' parameter must be non-empty./);
|
|
454
314
|
});
|
|
455
315
|
it('should reject when calculateEdit fails after an abort signal', async () => {
|
|
456
316
|
const params = {
|
|
457
317
|
file_path: path.join(rootDir, 'abort-execute.txt'),
|
|
318
|
+
instruction: 'Abort during execute',
|
|
458
319
|
old_string: 'old',
|
|
459
320
|
new_string: 'new',
|
|
460
321
|
};
|
|
461
322
|
const invocation = tool.build(params);
|
|
462
323
|
const abortController = new AbortController();
|
|
463
|
-
const abortError = new Error('Abort requested during
|
|
324
|
+
const abortError = new Error('Abort requested during edit execution');
|
|
464
325
|
const calculateSpy = vi
|
|
465
326
|
.spyOn(invocation, 'calculateEdit')
|
|
466
327
|
.mockImplementation(async () => {
|
|
@@ -474,16 +335,14 @@ describe('EditTool', () => {
|
|
|
474
335
|
});
|
|
475
336
|
it('should edit an existing file and return diff with fileName', async () => {
|
|
476
337
|
const initialContent = 'This is some old text.';
|
|
477
|
-
const newContent = 'This is some new text.';
|
|
338
|
+
const newContent = 'This is some new text.';
|
|
478
339
|
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
479
340
|
const params = {
|
|
480
341
|
file_path: filePath,
|
|
342
|
+
instruction: 'Replace old with new',
|
|
481
343
|
old_string: 'old',
|
|
482
344
|
new_string: 'new',
|
|
483
345
|
};
|
|
484
|
-
// Specific mock for this test's execution path in calculateEdit
|
|
485
|
-
// ensureCorrectEdit is NOT called by calculateEdit, only by shouldConfirmExecute
|
|
486
|
-
// So, the default mockEnsureCorrectEdit should correctly return 1 occurrence for 'old' in initialContent
|
|
487
346
|
const invocation = tool.build(params);
|
|
488
347
|
const result = await invocation.execute(new AbortController().signal);
|
|
489
348
|
expect(result.llmContent).toMatch(/Successfully modified file/);
|
|
@@ -493,196 +352,124 @@ describe('EditTool', () => {
|
|
|
493
352
|
expect(display.fileDiff).toMatch(newContent);
|
|
494
353
|
expect(display.fileName).toBe(testFile);
|
|
495
354
|
});
|
|
496
|
-
it('should create a new file if old_string is empty and file does not exist, and return created message', async () => {
|
|
497
|
-
const newFileName = 'brand_new_file.txt';
|
|
498
|
-
const newFilePath = path.join(rootDir, newFileName);
|
|
499
|
-
const fileContent = 'Content for the new file.';
|
|
500
|
-
const params = {
|
|
501
|
-
file_path: newFilePath,
|
|
502
|
-
old_string: '',
|
|
503
|
-
new_string: fileContent,
|
|
504
|
-
};
|
|
505
|
-
mockConfig.getApprovalMode.mockReturnValueOnce(ApprovalMode.AUTO_EDIT);
|
|
506
|
-
const invocation = tool.build(params);
|
|
507
|
-
const result = await invocation.execute(new AbortController().signal);
|
|
508
|
-
expect(result.llmContent).toMatch(/Created new file/);
|
|
509
|
-
expect(fs.existsSync(newFilePath)).toBe(true);
|
|
510
|
-
expect(fs.readFileSync(newFilePath, 'utf8')).toBe(fileContent);
|
|
511
|
-
const display = result.returnDisplay;
|
|
512
|
-
expect(display.fileDiff).toMatch(/\+Content for the new file\./);
|
|
513
|
-
expect(display.fileName).toBe(newFileName);
|
|
514
|
-
expect(result.returnDisplay.diffStat).toStrictEqual({
|
|
515
|
-
model_added_lines: 1,
|
|
516
|
-
model_removed_lines: 0,
|
|
517
|
-
model_added_chars: 25,
|
|
518
|
-
model_removed_chars: 0,
|
|
519
|
-
user_added_lines: 0,
|
|
520
|
-
user_removed_lines: 0,
|
|
521
|
-
user_added_chars: 0,
|
|
522
|
-
user_removed_chars: 0,
|
|
523
|
-
});
|
|
524
|
-
});
|
|
525
355
|
it('should return error if old_string is not found in file', async () => {
|
|
526
356
|
fs.writeFileSync(filePath, 'Some content.', 'utf8');
|
|
527
357
|
const params = {
|
|
528
358
|
file_path: filePath,
|
|
359
|
+
instruction: 'Replace non-existent text',
|
|
529
360
|
old_string: 'nonexistent',
|
|
530
361
|
new_string: 'replacement',
|
|
531
362
|
};
|
|
532
|
-
// The default mockEnsureCorrectEdit will return 0 occurrences for 'nonexistent'
|
|
533
363
|
const invocation = tool.build(params);
|
|
534
364
|
const result = await invocation.execute(new AbortController().signal);
|
|
535
|
-
expect(result.llmContent).toMatch(/0 occurrences found for old_string
|
|
365
|
+
expect(result.llmContent).toMatch(/0 occurrences found for old_string/);
|
|
536
366
|
expect(result.returnDisplay).toMatch(/Failed to edit, could not find the string to replace./);
|
|
367
|
+
expect(mockFixLLMEditWithInstruction).toHaveBeenCalled();
|
|
537
368
|
});
|
|
538
|
-
it('should
|
|
539
|
-
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
old_string: 'old',
|
|
543
|
-
new_string: 'new',
|
|
544
|
-
};
|
|
545
|
-
// The default mockEnsureCorrectEdit will return 2 occurrences for 'old'
|
|
546
|
-
const invocation = tool.build(params);
|
|
547
|
-
const result = await invocation.execute(new AbortController().signal);
|
|
548
|
-
expect(result.llmContent).toMatch(/Expected 1 occurrence but found 2 for old_string in file/);
|
|
549
|
-
expect(result.returnDisplay).toMatch(/Failed to edit, expected 1 occurrence but found 2/);
|
|
550
|
-
});
|
|
551
|
-
it('should successfully replace multiple occurrences when expected_replacements specified', async () => {
|
|
552
|
-
fs.writeFileSync(filePath, 'old text\nold text\nold text', 'utf8');
|
|
369
|
+
it('should succeed if FixLLMEditWithInstruction corrects the params', async () => {
|
|
370
|
+
const initialContent = 'This is some original text.';
|
|
371
|
+
const finalContent = 'This is some brand new text.';
|
|
372
|
+
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
553
373
|
const params = {
|
|
554
374
|
file_path: filePath,
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
375
|
+
instruction: 'Replace original with brand new',
|
|
376
|
+
old_string: 'wrong text', // This will fail first
|
|
377
|
+
new_string: 'brand new text',
|
|
558
378
|
};
|
|
379
|
+
mockFixLLMEditWithInstruction.mockResolvedValueOnce({
|
|
380
|
+
noChangesRequired: false,
|
|
381
|
+
search: 'original text', // The corrected search string
|
|
382
|
+
replace: 'brand new text',
|
|
383
|
+
explanation: 'Corrected the search string to match the file content.',
|
|
384
|
+
});
|
|
559
385
|
const invocation = tool.build(params);
|
|
560
386
|
const result = await invocation.execute(new AbortController().signal);
|
|
387
|
+
expect(result.error).toBeUndefined();
|
|
561
388
|
expect(result.llmContent).toMatch(/Successfully modified file/);
|
|
562
|
-
expect(fs.readFileSync(filePath, 'utf8')).toBe(
|
|
563
|
-
|
|
564
|
-
expect(display.fileDiff).toMatch(/-old text\n-old text\n-old text/);
|
|
565
|
-
expect(display.fileDiff).toMatch(/\+new text\n\+new text\n\+new text/);
|
|
566
|
-
expect(display.fileName).toBe(testFile);
|
|
567
|
-
expect(result.returnDisplay.diffStat).toStrictEqual({
|
|
568
|
-
model_added_lines: 3,
|
|
569
|
-
model_removed_lines: 3,
|
|
570
|
-
model_added_chars: 24,
|
|
571
|
-
model_removed_chars: 24,
|
|
572
|
-
user_added_lines: 0,
|
|
573
|
-
user_removed_lines: 0,
|
|
574
|
-
user_added_chars: 0,
|
|
575
|
-
user_removed_chars: 0,
|
|
576
|
-
});
|
|
389
|
+
expect(fs.readFileSync(filePath, 'utf8')).toBe(finalContent);
|
|
390
|
+
expect(mockFixLLMEditWithInstruction).toHaveBeenCalledTimes(1);
|
|
577
391
|
});
|
|
578
|
-
it('should
|
|
579
|
-
|
|
392
|
+
it('should preserve CRLF line endings when editing a file', async () => {
|
|
393
|
+
const initialContent = 'line one\r\nline two\r\n';
|
|
394
|
+
const newContent = 'line one\r\nline three\r\n';
|
|
395
|
+
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
580
396
|
const params = {
|
|
581
397
|
file_path: filePath,
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
398
|
+
instruction: 'Replace two with three',
|
|
399
|
+
old_string: 'line two',
|
|
400
|
+
new_string: 'line three',
|
|
585
401
|
};
|
|
586
402
|
const invocation = tool.build(params);
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
expect(
|
|
403
|
+
await invocation.execute(new AbortController().signal);
|
|
404
|
+
const finalContent = fs.readFileSync(filePath, 'utf8');
|
|
405
|
+
expect(finalContent).toBe(newContent);
|
|
590
406
|
});
|
|
591
|
-
it('should
|
|
592
|
-
|
|
407
|
+
it('should create a new file with CRLF line endings if new_string has them', async () => {
|
|
408
|
+
const newContentWithCRLF = 'new line one\r\nnew line two\r\n';
|
|
593
409
|
const params = {
|
|
594
410
|
file_path: filePath,
|
|
411
|
+
instruction: 'Create a new file',
|
|
595
412
|
old_string: '',
|
|
596
|
-
new_string:
|
|
413
|
+
new_string: newContentWithCRLF,
|
|
597
414
|
};
|
|
598
415
|
const invocation = tool.build(params);
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
expect(
|
|
416
|
+
await invocation.execute(new AbortController().signal);
|
|
417
|
+
const finalContent = fs.readFileSync(filePath, 'utf8');
|
|
418
|
+
expect(finalContent).toBe(newContentWithCRLF);
|
|
602
419
|
});
|
|
603
|
-
it('should
|
|
604
|
-
const initialContent = '
|
|
420
|
+
it('should return NO_CHANGE if FixLLMEditWithInstruction determines no changes are needed', async () => {
|
|
421
|
+
const initialContent = 'The price is $100.';
|
|
605
422
|
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
606
423
|
const params = {
|
|
607
424
|
file_path: filePath,
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
ai_proposed_content: 'Line 1\nAI line\nLine 3\nLine 4\nLine 5\n',
|
|
425
|
+
instruction: 'Ensure the price is $100',
|
|
426
|
+
old_string: 'price is $50', // Incorrect old string
|
|
427
|
+
new_string: 'price is $100',
|
|
612
428
|
};
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
model_added_lines: 1,
|
|
619
|
-
model_removed_lines: 1,
|
|
620
|
-
model_added_chars: 7,
|
|
621
|
-
model_removed_chars: 8,
|
|
622
|
-
user_added_lines: 1,
|
|
623
|
-
user_removed_lines: 1,
|
|
624
|
-
user_added_chars: 8,
|
|
625
|
-
user_removed_chars: 7,
|
|
429
|
+
mockFixLLMEditWithInstruction.mockResolvedValueOnce({
|
|
430
|
+
noChangesRequired: true,
|
|
431
|
+
search: '',
|
|
432
|
+
replace: '',
|
|
433
|
+
explanation: 'The price is already correctly set to $100.',
|
|
626
434
|
});
|
|
627
|
-
});
|
|
628
|
-
it.each([
|
|
629
|
-
{
|
|
630
|
-
name: 'modified_by_user is false',
|
|
631
|
-
modifiedByUser: false,
|
|
632
|
-
},
|
|
633
|
-
{
|
|
634
|
-
name: 'modified_by_user is not provided',
|
|
635
|
-
modifiedByUser: undefined,
|
|
636
|
-
},
|
|
637
|
-
])('should not include modification message when $name', async ({ modifiedByUser }) => {
|
|
638
|
-
const initialContent = 'This is some old text.';
|
|
639
|
-
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
640
|
-
const params = {
|
|
641
|
-
file_path: filePath,
|
|
642
|
-
old_string: 'old',
|
|
643
|
-
new_string: 'new',
|
|
644
|
-
...(modifiedByUser !== undefined && {
|
|
645
|
-
modified_by_user: modifiedByUser,
|
|
646
|
-
}),
|
|
647
|
-
};
|
|
648
|
-
mockConfig.getApprovalMode.mockReturnValueOnce(ApprovalMode.AUTO_EDIT);
|
|
649
435
|
const invocation = tool.build(params);
|
|
650
436
|
const result = await invocation.execute(new AbortController().signal);
|
|
651
|
-
expect(result.
|
|
437
|
+
expect(result.error?.type).toBe(ToolErrorType.EDIT_NO_CHANGE_LLM_JUDGEMENT);
|
|
438
|
+
expect(result.llmContent).toMatch(/A secondary check by an LLM determined/);
|
|
439
|
+
expect(fs.readFileSync(filePath, 'utf8')).toBe(initialContent); // File is unchanged
|
|
652
440
|
});
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
new_string: 'identical',
|
|
660
|
-
};
|
|
661
|
-
const invocation = tool.build(params);
|
|
662
|
-
const result = await invocation.execute(new AbortController().signal);
|
|
663
|
-
expect(result.llmContent).toMatch(/No changes to apply/);
|
|
664
|
-
expect(result.returnDisplay).toMatch(/No changes to apply/);
|
|
441
|
+
});
|
|
442
|
+
describe('self-correction with content refresh to pull in external edits', () => {
|
|
443
|
+
const testFile = 'test.txt';
|
|
444
|
+
let filePath;
|
|
445
|
+
beforeEach(() => {
|
|
446
|
+
filePath = path.join(rootDir, testFile);
|
|
665
447
|
});
|
|
666
|
-
it('should
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
const initialContent = 'line 1\nline 2\nline 3'; // Note the double space
|
|
448
|
+
it('should use refreshed file content for self-correction if file was modified externally', async () => {
|
|
449
|
+
const initialContent = 'This is the original content.';
|
|
450
|
+
const externallyModifiedContent = 'This is the externally modified content.';
|
|
670
451
|
fs.writeFileSync(filePath, initialContent, 'utf8');
|
|
671
452
|
const params = {
|
|
672
453
|
file_path: filePath,
|
|
673
|
-
|
|
674
|
-
old_string: '
|
|
675
|
-
new_string: '
|
|
454
|
+
instruction: 'Replace "externally modified content" with "externally modified string"',
|
|
455
|
+
old_string: 'externally modified content', // This will fail the first attempt, triggering self-correction.
|
|
456
|
+
new_string: 'externally modified string',
|
|
676
457
|
};
|
|
677
|
-
//
|
|
678
|
-
|
|
679
|
-
|
|
458
|
+
// Spy on `readTextFile` to simulate an external file change between reads.
|
|
459
|
+
const readTextFileSpy = vi
|
|
460
|
+
.spyOn(fileSystemService, 'readTextFile')
|
|
461
|
+
.mockResolvedValueOnce(initialContent) // First call in `calculateEdit`
|
|
462
|
+
.mockResolvedValueOnce(externallyModifiedContent); // Second call in `attemptSelfCorrection`
|
|
680
463
|
const invocation = tool.build(params);
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
expect(
|
|
684
|
-
//
|
|
685
|
-
expect(
|
|
464
|
+
await invocation.execute(new AbortController().signal);
|
|
465
|
+
// Assert that the file was read twice (initial read, then re-read for hash comparison).
|
|
466
|
+
expect(readTextFileSpy).toHaveBeenCalledTimes(2);
|
|
467
|
+
// Assert that the self-correction LLM was called with the updated content and a specific message.
|
|
468
|
+
expect(mockFixLLMEditWithInstruction).toHaveBeenCalledWith(expect.any(String), // instruction
|
|
469
|
+
params.old_string, params.new_string, expect.stringContaining('However, the file has been modified by either the user or an external process'), // errorForLlmEditFixer
|
|
470
|
+
externallyModifiedContent, // The new content for correction
|
|
471
|
+
expect.any(Object), // baseLlmClient
|
|
472
|
+
expect.any(Object));
|
|
686
473
|
});
|
|
687
474
|
});
|
|
688
475
|
describe('Error Scenarios', () => {
|
|
@@ -693,163 +480,85 @@ describe('EditTool', () => {
|
|
|
693
480
|
});
|
|
694
481
|
it.each([
|
|
695
482
|
{
|
|
696
|
-
name: 'FILE_NOT_FOUND
|
|
697
|
-
setup: () => { },
|
|
698
|
-
params: {
|
|
483
|
+
name: 'FILE_NOT_FOUND',
|
|
484
|
+
setup: () => { }, // no file created
|
|
485
|
+
params: { old_string: 'any', new_string: 'new' },
|
|
699
486
|
expectedError: ToolErrorType.FILE_NOT_FOUND,
|
|
700
|
-
isAsyncTest: true,
|
|
701
487
|
},
|
|
702
488
|
{
|
|
703
|
-
name: 'ATTEMPT_TO_CREATE_EXISTING_FILE
|
|
489
|
+
name: 'ATTEMPT_TO_CREATE_EXISTING_FILE',
|
|
704
490
|
setup: (fp) => fs.writeFileSync(fp, 'existing content', 'utf8'),
|
|
705
|
-
params: {
|
|
491
|
+
params: { old_string: '', new_string: 'new content' },
|
|
706
492
|
expectedError: ToolErrorType.ATTEMPT_TO_CREATE_EXISTING_FILE,
|
|
707
|
-
isAsyncTest: true,
|
|
708
493
|
},
|
|
709
494
|
{
|
|
710
|
-
name: 'NO_OCCURRENCE_FOUND
|
|
495
|
+
name: 'NO_OCCURRENCE_FOUND',
|
|
711
496
|
setup: (fp) => fs.writeFileSync(fp, 'content', 'utf8'),
|
|
712
|
-
params: {
|
|
497
|
+
params: { old_string: 'not-found', new_string: 'new' },
|
|
713
498
|
expectedError: ToolErrorType.EDIT_NO_OCCURRENCE_FOUND,
|
|
714
|
-
isAsyncTest: true,
|
|
715
499
|
},
|
|
716
500
|
{
|
|
717
|
-
name: 'EXPECTED_OCCURRENCE_MISMATCH
|
|
501
|
+
name: 'EXPECTED_OCCURRENCE_MISMATCH',
|
|
718
502
|
setup: (fp) => fs.writeFileSync(fp, 'one one two', 'utf8'),
|
|
719
|
-
params: {
|
|
720
|
-
file_path: '',
|
|
721
|
-
old_string: 'one',
|
|
722
|
-
new_string: 'new',
|
|
723
|
-
expected_replacements: 3,
|
|
724
|
-
},
|
|
503
|
+
params: { old_string: 'one', new_string: 'new' },
|
|
725
504
|
expectedError: ToolErrorType.EDIT_EXPECTED_OCCURRENCE_MISMATCH,
|
|
726
|
-
isAsyncTest: true,
|
|
727
|
-
},
|
|
728
|
-
{
|
|
729
|
-
name: 'NO_CHANGE error',
|
|
730
|
-
setup: (fp) => fs.writeFileSync(fp, 'content', 'utf8'),
|
|
731
|
-
params: { file_path: '', old_string: 'content', new_string: 'content' },
|
|
732
|
-
expectedError: ToolErrorType.EDIT_NO_CHANGE,
|
|
733
|
-
isAsyncTest: true,
|
|
734
|
-
},
|
|
735
|
-
{
|
|
736
|
-
name: 'relative path (should not throw)',
|
|
737
|
-
setup: () => { },
|
|
738
|
-
params: {
|
|
739
|
-
file_path: 'relative/path.txt',
|
|
740
|
-
old_string: 'a',
|
|
741
|
-
new_string: 'b',
|
|
742
|
-
},
|
|
743
|
-
expectedError: null,
|
|
744
|
-
isAsyncTest: false,
|
|
745
|
-
},
|
|
746
|
-
{
|
|
747
|
-
name: 'FILE_WRITE_FAILURE on write error',
|
|
748
|
-
setup: (fp) => {
|
|
749
|
-
fs.writeFileSync(fp, 'content', 'utf8');
|
|
750
|
-
fs.chmodSync(fp, '444');
|
|
751
|
-
},
|
|
752
|
-
params: {
|
|
753
|
-
file_path: '',
|
|
754
|
-
old_string: 'content',
|
|
755
|
-
new_string: 'new content',
|
|
756
|
-
},
|
|
757
|
-
expectedError: ToolErrorType.FILE_WRITE_FAILURE,
|
|
758
|
-
isAsyncTest: true,
|
|
759
505
|
},
|
|
760
|
-
])('should return $name', async ({ setup, params, expectedError
|
|
761
|
-
const testParams = {
|
|
762
|
-
...params,
|
|
763
|
-
file_path: params.file_path || filePath,
|
|
764
|
-
};
|
|
506
|
+
])('should return $name error', async ({ setup, params, expectedError }) => {
|
|
765
507
|
setup(filePath);
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
508
|
+
const invocation = tool.build({
|
|
509
|
+
file_path: filePath,
|
|
510
|
+
instruction: 'test',
|
|
511
|
+
...params,
|
|
512
|
+
});
|
|
513
|
+
const result = await invocation.execute(new AbortController().signal);
|
|
514
|
+
expect(result.error?.type).toBe(expectedError);
|
|
774
515
|
});
|
|
775
516
|
});
|
|
776
|
-
describe('
|
|
517
|
+
describe('expected_replacements', () => {
|
|
518
|
+
const testFile = 'replacements_test.txt';
|
|
519
|
+
let filePath;
|
|
520
|
+
beforeEach(() => {
|
|
521
|
+
filePath = path.join(rootDir, testFile);
|
|
522
|
+
});
|
|
777
523
|
it.each([
|
|
778
524
|
{
|
|
779
|
-
name: '
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
},
|
|
785
|
-
{
|
|
786
|
-
name: 'different strings (full)',
|
|
787
|
-
fileName: 'test.txt',
|
|
788
|
-
oldStr: 'this is the old string value',
|
|
789
|
-
newStr: 'this is the new string value',
|
|
790
|
-
expected: 'test.txt: this is the old string value => this is the new string value',
|
|
525
|
+
name: 'succeed when occurrences match expected_replacements',
|
|
526
|
+
content: 'foo foo foo',
|
|
527
|
+
expected: 3,
|
|
528
|
+
shouldSucceed: true,
|
|
529
|
+
finalContent: 'bar bar bar',
|
|
791
530
|
},
|
|
792
531
|
{
|
|
793
|
-
name: '
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
expected: 'short.txt: old => new',
|
|
532
|
+
name: 'fail when occurrences do not match expected_replacements',
|
|
533
|
+
content: 'foo foo foo',
|
|
534
|
+
expected: 2,
|
|
535
|
+
shouldSucceed: false,
|
|
798
536
|
},
|
|
799
537
|
{
|
|
800
|
-
name: '
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
expected: 'long.txt: this is a very long old string... => this is a very long new string...',
|
|
538
|
+
name: 'default to 1 expected replacement if not specified',
|
|
539
|
+
content: 'foo foo',
|
|
540
|
+
expected: undefined,
|
|
541
|
+
shouldSucceed: false,
|
|
805
542
|
},
|
|
806
|
-
])('should
|
|
543
|
+
])('should $name', async ({ content, expected, shouldSucceed, finalContent }) => {
|
|
544
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
807
545
|
const params = {
|
|
808
|
-
file_path:
|
|
809
|
-
|
|
810
|
-
|
|
546
|
+
file_path: filePath,
|
|
547
|
+
instruction: 'Replace all foo with bar',
|
|
548
|
+
old_string: 'foo',
|
|
549
|
+
new_string: 'bar',
|
|
550
|
+
...(expected !== undefined && { expected_replacements: expected }),
|
|
811
551
|
};
|
|
812
552
|
const invocation = tool.build(params);
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
};
|
|
823
|
-
expect(tool.validateToolParams(validPath)).toBeNull();
|
|
824
|
-
});
|
|
825
|
-
it('should reject paths outside workspace root', () => {
|
|
826
|
-
const invalidPath = {
|
|
827
|
-
file_path: '/etc/passwd',
|
|
828
|
-
old_string: 'root',
|
|
829
|
-
new_string: 'hacked',
|
|
830
|
-
};
|
|
831
|
-
const error = tool.validateToolParams(invalidPath);
|
|
832
|
-
expect(error).toContain('File path must be within one of the workspace directories');
|
|
833
|
-
expect(error).toContain(rootDir);
|
|
834
|
-
});
|
|
835
|
-
});
|
|
836
|
-
describe('constructor', () => {
|
|
837
|
-
afterEach(() => {
|
|
838
|
-
vi.restoreAllMocks();
|
|
839
|
-
});
|
|
840
|
-
it('should use windows-style path examples on windows', () => {
|
|
841
|
-
vi.spyOn(process, 'platform', 'get').mockReturnValue('win32');
|
|
842
|
-
const tool = new EditTool({});
|
|
843
|
-
const schema = tool.schema;
|
|
844
|
-
expect(schema.parametersJsonSchema.properties
|
|
845
|
-
.file_path.description).toBe('The path to the file to modify.');
|
|
846
|
-
});
|
|
847
|
-
it('should use unix-style path examples on non-windows platforms', () => {
|
|
848
|
-
vi.spyOn(process, 'platform', 'get').mockReturnValue('linux');
|
|
849
|
-
const tool = new EditTool({});
|
|
850
|
-
const schema = tool.schema;
|
|
851
|
-
expect(schema.parametersJsonSchema.properties
|
|
852
|
-
.file_path.description).toBe('The path to the file to modify.');
|
|
553
|
+
const result = await invocation.execute(new AbortController().signal);
|
|
554
|
+
if (shouldSucceed) {
|
|
555
|
+
expect(result.error).toBeUndefined();
|
|
556
|
+
if (finalContent)
|
|
557
|
+
expect(fs.readFileSync(filePath, 'utf8')).toBe(finalContent);
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
expect(result.error?.type).toBe(ToolErrorType.EDIT_EXPECTED_OCCURRENCE_MISMATCH);
|
|
561
|
+
}
|
|
853
562
|
});
|
|
854
563
|
});
|
|
855
564
|
describe('IDE mode', () => {
|
|
@@ -872,13 +581,10 @@ describe('EditTool', () => {
|
|
|
872
581
|
fs.writeFileSync(filePath, initialContent);
|
|
873
582
|
const params = {
|
|
874
583
|
file_path: filePath,
|
|
584
|
+
instruction: 'test',
|
|
875
585
|
old_string: 'old',
|
|
876
586
|
new_string: 'new',
|
|
877
587
|
};
|
|
878
|
-
mockEnsureCorrectEdit.mockResolvedValueOnce({
|
|
879
|
-
params: { ...params, old_string: 'old', new_string: 'new' },
|
|
880
|
-
occurrences: 1,
|
|
881
|
-
});
|
|
882
588
|
ideClient.openDiff.mockResolvedValueOnce({
|
|
883
589
|
status: 'accepted',
|
|
884
590
|
content: modifiedContent,
|
|
@@ -893,6 +599,30 @@ describe('EditTool', () => {
|
|
|
893
599
|
expect(params.new_string).toBe(modifiedContent);
|
|
894
600
|
});
|
|
895
601
|
});
|
|
602
|
+
describe('shouldConfirmExecute', () => {
|
|
603
|
+
it('should rethrow calculateEdit errors when the abort signal is triggered', async () => {
|
|
604
|
+
const filePath = path.join(rootDir, 'abort-confirmation.txt');
|
|
605
|
+
const params = {
|
|
606
|
+
file_path: filePath,
|
|
607
|
+
instruction: 'Abort during confirmation',
|
|
608
|
+
old_string: 'old',
|
|
609
|
+
new_string: 'new',
|
|
610
|
+
};
|
|
611
|
+
const invocation = tool.build(params);
|
|
612
|
+
const abortController = new AbortController();
|
|
613
|
+
const abortError = new Error('Abort requested during edit confirmation');
|
|
614
|
+
const calculateSpy = vi
|
|
615
|
+
.spyOn(invocation, 'calculateEdit')
|
|
616
|
+
.mockImplementation(async () => {
|
|
617
|
+
if (!abortController.signal.aborted) {
|
|
618
|
+
abortController.abort();
|
|
619
|
+
}
|
|
620
|
+
throw abortError;
|
|
621
|
+
});
|
|
622
|
+
await expect(invocation.shouldConfirmExecute(abortController.signal)).rejects.toBe(abortError);
|
|
623
|
+
calculateSpy.mockRestore();
|
|
624
|
+
});
|
|
625
|
+
});
|
|
896
626
|
describe('multiple file edits', () => {
|
|
897
627
|
it('should perform multiple removals and report correct diff stats', async () => {
|
|
898
628
|
const numFiles = 10;
|
|
@@ -923,8 +653,10 @@ describe('EditTool', () => {
|
|
|
923
653
|
for (const file of files) {
|
|
924
654
|
const params = {
|
|
925
655
|
file_path: file.path,
|
|
656
|
+
instruction: `Remove lines from the file`,
|
|
926
657
|
old_string: file.toRemove,
|
|
927
658
|
new_string: '', // Removing the content
|
|
659
|
+
ai_proposed_content: '',
|
|
928
660
|
};
|
|
929
661
|
const invocation = tool.build(params);
|
|
930
662
|
const result = await invocation.execute(new AbortController().signal);
|
|
@@ -935,7 +667,7 @@ describe('EditTool', () => {
|
|
|
935
667
|
actualLinesRemoved.push(result.returnDisplay.diffStat?.model_removed_lines);
|
|
936
668
|
}
|
|
937
669
|
else if (result.error) {
|
|
938
|
-
|
|
670
|
+
throw result.error;
|
|
939
671
|
}
|
|
940
672
|
}
|
|
941
673
|
// 3. Assert that the content was removed from each file
|