@office-ai/aioncli-core 0.2.3 → 0.18.4
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/index.d.ts +16 -3
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/src/agents/codebase-investigator.d.ts +46 -0
- package/dist/src/agents/codebase-investigator.js +132 -0
- package/dist/src/agents/codebase-investigator.js.map +1 -0
- package/dist/src/agents/codebase-investigator.test.js +35 -0
- package/dist/src/agents/codebase-investigator.test.js.map +1 -0
- package/dist/src/agents/executor.d.ts +114 -0
- package/dist/src/agents/executor.js +779 -0
- package/dist/src/agents/executor.js.map +1 -0
- package/dist/src/agents/executor.test.js +1362 -0
- package/dist/src/agents/executor.test.js.map +1 -0
- package/dist/src/agents/invocation.d.ts +46 -0
- package/dist/src/agents/invocation.js +102 -0
- package/dist/src/agents/invocation.js.map +1 -0
- package/dist/src/agents/invocation.test.js +215 -0
- package/dist/src/agents/invocation.test.js.map +1 -0
- package/dist/src/agents/registry.d.ts +40 -0
- package/dist/src/agents/registry.js +105 -0
- package/dist/src/agents/registry.js.map +1 -0
- package/dist/src/agents/registry.test.d.ts +6 -0
- package/dist/src/agents/registry.test.js +160 -0
- package/dist/src/agents/registry.test.js.map +1 -0
- package/dist/src/agents/schema-utils.d.ts +39 -0
- package/dist/src/agents/schema-utils.js +57 -0
- package/dist/src/agents/schema-utils.js.map +1 -0
- package/dist/src/agents/schema-utils.test.d.ts +6 -0
- package/dist/src/agents/schema-utils.test.js +144 -0
- package/dist/src/agents/schema-utils.test.js.map +1 -0
- package/dist/src/agents/subagent-tool-wrapper.d.ts +38 -0
- package/dist/src/agents/subagent-tool-wrapper.js +48 -0
- package/dist/src/agents/subagent-tool-wrapper.js.map +1 -0
- package/dist/src/agents/subagent-tool-wrapper.test.d.ts +6 -0
- package/dist/src/agents/subagent-tool-wrapper.test.js +110 -0
- package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -0
- package/dist/src/agents/types.d.ts +146 -0
- package/dist/src/agents/types.js +19 -0
- package/dist/src/agents/types.js.map +1 -0
- package/dist/src/agents/utils.d.ts +15 -0
- package/dist/src/agents/utils.js +29 -0
- package/dist/src/agents/utils.js.map +1 -0
- package/dist/src/agents/utils.test.d.ts +6 -0
- package/dist/src/agents/utils.test.js +87 -0
- package/dist/src/agents/utils.test.js.map +1 -0
- package/dist/src/code_assist/codeAssist.d.ts +6 -3
- package/dist/src/code_assist/codeAssist.js +13 -1
- package/dist/src/code_assist/codeAssist.js.map +1 -1
- package/dist/src/code_assist/codeAssist.test.d.ts +6 -0
- package/dist/src/code_assist/codeAssist.test.js +99 -0
- package/dist/src/code_assist/codeAssist.test.js.map +1 -0
- package/dist/src/code_assist/converter.d.ts +5 -1
- package/dist/src/code_assist/converter.js +39 -5
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +112 -0
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/experiments/client_metadata.d.ts +12 -0
- package/dist/src/code_assist/experiments/client_metadata.js +50 -0
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -0
- package/dist/src/code_assist/experiments/client_metadata.test.d.ts +6 -0
- package/dist/src/code_assist/experiments/client_metadata.test.js +99 -0
- package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.d.ts +17 -0
- package/dist/src/code_assist/experiments/experiments.js +36 -0
- package/dist/src/code_assist/experiments/experiments.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.test.d.ts +6 -0
- package/dist/src/code_assist/experiments/experiments.test.js +92 -0
- package/dist/src/code_assist/experiments/experiments.test.js.map +1 -0
- package/dist/src/code_assist/experiments/flagNames.d.ts +13 -0
- package/dist/src/code_assist/experiments/flagNames.js +13 -0
- package/dist/src/code_assist/experiments/flagNames.js.map +1 -0
- package/dist/src/code_assist/experiments/types.d.ts +35 -0
- package/dist/src/code_assist/experiments/types.js +7 -0
- package/dist/src/code_assist/experiments/types.js.map +1 -0
- package/dist/src/code_assist/oauth-credential-storage.d.ts +25 -0
- package/dist/src/code_assist/oauth-credential-storage.js +110 -0
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -0
- package/dist/src/code_assist/oauth-credential-storage.test.d.ts +6 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js +198 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -0
- package/dist/src/code_assist/oauth2.d.ts +3 -3
- package/dist/src/code_assist/oauth2.js +252 -125
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +788 -350
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +8 -6
- package/dist/src/code_assist/server.js +41 -10
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +151 -28
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.d.ts +2 -2
- package/dist/src/code_assist/setup.js +5 -3
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +18 -3
- package/dist/src/code_assist/types.js.map +1 -1
- package/dist/src/commands/extensions.d.ts +7 -0
- package/dist/src/commands/extensions.js +9 -0
- package/dist/src/commands/extensions.js.map +1 -0
- package/dist/src/commands/extensions.test.d.ts +6 -0
- package/dist/src/commands/extensions.test.js +19 -0
- package/dist/src/commands/extensions.test.js.map +1 -0
- package/dist/src/config/config.d.ts +282 -60
- package/dist/src/config/config.js +677 -129
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +1020 -146
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/constants.d.ts +11 -0
- package/dist/src/config/constants.js +16 -0
- package/dist/src/config/constants.js.map +1 -0
- package/dist/src/config/defaultModelConfigs.d.ts +7 -0
- package/dist/src/config/defaultModelConfigs.js +185 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -0
- package/dist/src/config/models.d.ts +37 -0
- package/dist/src/config/models.js +72 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.d.ts +6 -0
- package/dist/src/config/models.test.js +116 -0
- package/dist/src/config/models.test.js.map +1 -0
- package/dist/src/config/storage.d.ts +36 -0
- package/dist/src/config/storage.js +115 -0
- package/dist/src/config/storage.js.map +1 -0
- package/dist/src/config/storage.test.d.ts +6 -0
- package/dist/src/config/storage.test.js +48 -0
- package/dist/src/config/storage.test.js.map +1 -0
- package/dist/src/confirmation-bus/index.d.ts +7 -0
- package/dist/src/confirmation-bus/index.js +8 -0
- package/dist/src/confirmation-bus/index.js.map +1 -0
- package/dist/src/confirmation-bus/message-bus.d.ts +18 -0
- package/dist/src/confirmation-bus/message-bus.js +87 -0
- package/dist/src/confirmation-bus/message-bus.js.map +1 -0
- package/dist/src/confirmation-bus/message-bus.test.d.ts +6 -0
- package/dist/src/confirmation-bus/message-bus.test.js +170 -0
- package/dist/src/confirmation-bus/message-bus.test.js.map +1 -0
- package/dist/src/confirmation-bus/types.d.ts +49 -0
- package/dist/src/confirmation-bus/types.js +16 -0
- package/dist/src/confirmation-bus/types.js.map +1 -0
- package/dist/src/core/apiKeyCredentialStorage.d.ts +17 -0
- package/dist/src/core/apiKeyCredentialStorage.js +64 -0
- package/dist/src/core/apiKeyCredentialStorage.js.map +1 -0
- package/dist/src/core/apiKeyCredentialStorage.test.d.ts +6 -0
- package/dist/src/core/apiKeyCredentialStorage.test.js +71 -0
- package/dist/src/core/apiKeyCredentialStorage.test.js.map +1 -0
- package/dist/src/core/baseLlmClient.d.ts +50 -0
- package/dist/src/core/baseLlmClient.js +185 -0
- package/dist/src/core/baseLlmClient.js.map +1 -0
- package/dist/src/core/baseLlmClient.test.d.ts +6 -0
- package/dist/src/core/baseLlmClient.test.js +311 -0
- package/dist/src/core/baseLlmClient.test.js.map +1 -0
- package/dist/src/core/client.d.ts +30 -42
- package/dist/src/core/client.js +178 -477
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +739 -617
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +7 -6
- package/dist/src/core/contentGenerator.js +59 -45
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +50 -4
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +28 -11
- package/dist/src/core/coreToolScheduler.js +493 -161
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +995 -163
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/fakeContentGenerator.d.ts +33 -0
- package/dist/src/core/fakeContentGenerator.js +58 -0
- package/dist/src/core/fakeContentGenerator.js.map +1 -0
- package/dist/src/core/fakeContentGenerator.test.d.ts +6 -0
- package/dist/src/core/fakeContentGenerator.test.js +127 -0
- package/dist/src/core/fakeContentGenerator.test.js.map +1 -0
- package/dist/src/core/geminiChat.d.ts +61 -55
- package/dist/src/core/geminiChat.js +388 -366
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +1600 -355
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiRequest.js +1 -0
- package/dist/src/core/geminiRequest.js.map +1 -1
- package/dist/src/core/logger.d.ts +11 -4
- package/dist/src/core/logger.js +39 -30
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +62 -45
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.d.ts +4 -3
- package/dist/src/core/loggingContentGenerator.js +116 -37
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.test.d.ts +6 -0
- package/dist/src/core/loggingContentGenerator.test.js +180 -0
- package/dist/src/core/loggingContentGenerator.test.js.map +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.d.ts +4 -5
- package/dist/src/core/nonInteractiveToolExecutor.js +17 -120
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +168 -84
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/openaiContentGenerator.d.ts +4 -3
- package/dist/src/core/openaiContentGenerator.js +49 -19
- package/dist/src/core/openaiContentGenerator.js.map +1 -1
- package/dist/src/core/openaiContentGenerator.test.js +1 -0
- package/dist/src/core/openaiContentGenerator.test.js.map +1 -1
- package/dist/src/core/prompts.d.ts +7 -1
- package/dist/src/core/prompts.js +198 -195
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +172 -104
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/recordingContentGenerator.d.ts +18 -0
- package/dist/src/core/recordingContentGenerator.js +77 -0
- package/dist/src/core/recordingContentGenerator.js.map +1 -0
- package/dist/src/core/recordingContentGenerator.test.d.ts +6 -0
- package/dist/src/core/recordingContentGenerator.test.js +101 -0
- package/dist/src/core/recordingContentGenerator.test.js.map +1 -0
- package/dist/src/core/subagent.d.ts +24 -18
- package/dist/src/core/subagent.js +125 -90
- package/dist/src/core/subagent.js.map +1 -1
- package/dist/src/core/subagent.test.js +59 -44
- package/dist/src/core/subagent.test.js.map +1 -1
- package/dist/src/core/tokenLimits.test.d.ts +6 -0
- package/dist/src/core/tokenLimits.test.js +26 -0
- package/dist/src/core/tokenLimits.test.js.map +1 -0
- package/dist/src/core/turn.d.ts +57 -13
- package/dist/src/core/turn.js +79 -35
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +373 -120
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/fallback/handler.d.ts +7 -0
- package/dist/src/fallback/handler.js +181 -0
- package/dist/src/fallback/handler.js.map +1 -0
- package/dist/src/fallback/handler.test.d.ts +6 -0
- package/dist/src/fallback/handler.test.js +245 -0
- package/dist/src/fallback/handler.test.js.map +1 -0
- package/dist/src/fallback/types.d.ts +14 -0
- package/dist/src/fallback/types.js +7 -0
- package/dist/src/fallback/types.js.map +1 -0
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/hooks/hookAggregator.d.ts +68 -0
- package/dist/src/hooks/hookAggregator.js +262 -0
- package/dist/src/hooks/hookAggregator.js.map +1 -0
- package/dist/src/hooks/hookAggregator.test.d.ts +6 -0
- package/dist/src/hooks/hookAggregator.test.js +387 -0
- package/dist/src/hooks/hookAggregator.test.js.map +1 -0
- package/dist/src/hooks/hookPlanner.d.ts +46 -0
- package/dist/src/hooks/hookPlanner.js +108 -0
- package/dist/src/hooks/hookPlanner.js.map +1 -0
- package/dist/src/hooks/hookPlanner.test.d.ts +6 -0
- package/dist/src/hooks/hookPlanner.test.js +255 -0
- package/dist/src/hooks/hookPlanner.test.js.map +1 -0
- package/dist/src/hooks/hookRegistry.d.ts +87 -0
- package/dist/src/hooks/hookRegistry.js +198 -0
- package/dist/src/hooks/hookRegistry.js.map +1 -0
- package/dist/src/hooks/hookRegistry.test.d.ts +6 -0
- package/dist/src/hooks/hookRegistry.test.js +341 -0
- package/dist/src/hooks/hookRegistry.test.js.map +1 -0
- package/dist/src/hooks/hookRunner.d.ts +42 -0
- package/dist/src/hooks/hookRunner.js +272 -0
- package/dist/src/hooks/hookRunner.js.map +1 -0
- package/dist/src/hooks/hookRunner.test.d.ts +6 -0
- package/dist/src/hooks/hookRunner.test.js +468 -0
- package/dist/src/hooks/hookRunner.test.js.map +1 -0
- package/dist/src/hooks/hookTranslator.d.ts +113 -0
- package/dist/src/hooks/hookTranslator.js +232 -0
- package/dist/src/hooks/hookTranslator.js.map +1 -0
- package/dist/src/hooks/hookTranslator.test.d.ts +6 -0
- package/dist/src/hooks/hookTranslator.test.js +192 -0
- package/dist/src/hooks/hookTranslator.test.js.map +1 -0
- package/dist/src/hooks/types.d.ts +384 -0
- package/dist/src/hooks/types.js +284 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/hooks/types.test.d.ts +6 -0
- package/dist/src/hooks/types.test.js +313 -0
- package/dist/src/hooks/types.test.js.map +1 -0
- package/dist/src/ide/constants.d.ts +3 -0
- package/dist/src/ide/constants.js +3 -0
- package/dist/src/ide/constants.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +52 -12
- package/dist/src/ide/detect-ide.js +51 -65
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +95 -52
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +72 -24
- package/dist/src/ide/ide-client.js +380 -84
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +539 -35
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.d.ts +2 -2
- package/dist/src/ide/ide-installer.js +93 -35
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +157 -26
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +35 -365
- package/dist/src/ide/ideContext.js +60 -106
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/ideContext.test.js +152 -24
- package/dist/src/ide/ideContext.test.js.map +1 -1
- package/dist/src/ide/process-utils.d.ts +7 -5
- package/dist/src/ide/process-utils.js +108 -67
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/process-utils.test.d.ts +6 -0
- package/dist/src/ide/process-utils.test.js +151 -0
- package/dist/src/ide/process-utils.test.js.map +1 -0
- package/dist/src/ide/types.d.ts +486 -0
- package/dist/src/ide/types.js +138 -0
- package/dist/src/ide/types.js.map +1 -0
- package/dist/src/index.d.ts +41 -2
- package/dist/src/index.js +44 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.d.ts +5 -3
- package/dist/src/mcp/google-auth-provider.js +21 -3
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.test.js +42 -9
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +25 -18
- package/dist/src/mcp/oauth-provider.js +194 -97
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +581 -39
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +14 -32
- package/dist/src/mcp/oauth-token-storage.js +58 -28
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.test.js +262 -162
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.d.ts +16 -1
- package/dist/src/mcp/oauth-utils.js +68 -33
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +86 -3
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.d.ts +27 -0
- package/dist/src/mcp/sa-impersonation-provider.js +113 -0
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -0
- package/dist/src/mcp/sa-impersonation-provider.test.d.ts +6 -0
- package/dist/src/mcp/sa-impersonation-provider.test.js +117 -0
- package/dist/src/mcp/sa-impersonation-provider.test.js.map +1 -0
- package/dist/src/mcp/token-storage/base-token-storage.d.ts +19 -0
- package/dist/src/mcp/token-storage/base-token-storage.js +36 -0
- package/dist/src/mcp/token-storage/base-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/base-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/base-token-storage.test.js +151 -0
- package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/file-token-storage.d.ts +24 -0
- package/dist/src/mcp/token-storage/file-token-storage.js +145 -0
- package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/file-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/file-token-storage.test.js +238 -0
- package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.d.ts +23 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.js +78 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js +193 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/index.d.ts +11 -0
- package/dist/src/mcp/token-storage/index.js +12 -0
- package/dist/src/mcp/token-storage/index.js.map +1 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +35 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.js +246 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js +305 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/types.d.ts +44 -0
- package/dist/src/mcp/token-storage/types.js +11 -0
- package/dist/src/mcp/token-storage/types.js.map +1 -0
- package/dist/src/output/json-formatter.d.ts +11 -0
- package/dist/src/output/json-formatter.js +30 -0
- package/dist/src/output/json-formatter.js.map +1 -0
- package/dist/src/output/json-formatter.test.d.ts +6 -0
- package/dist/src/output/json-formatter.test.js +266 -0
- package/dist/src/output/json-formatter.test.js.map +1 -0
- package/dist/src/output/stream-json-formatter.d.ts +32 -0
- package/dist/src/output/stream-json-formatter.js +52 -0
- package/dist/src/output/stream-json-formatter.js.map +1 -0
- package/dist/src/output/stream-json-formatter.test.d.ts +6 -0
- package/dist/src/output/stream-json-formatter.test.js +479 -0
- package/dist/src/output/stream-json-formatter.test.js.map +1 -0
- package/dist/src/output/types.d.ts +82 -0
- package/dist/src/output/types.js +22 -0
- package/dist/src/output/types.js.map +1 -0
- package/dist/src/policy/config.d.ts +31 -0
- package/dist/src/policy/config.js +199 -0
- package/dist/src/policy/config.js.map +1 -0
- package/dist/src/policy/config.test.d.ts +6 -0
- package/dist/src/policy/config.test.js +538 -0
- package/dist/src/policy/config.test.js.map +1 -0
- package/dist/src/policy/index.d.ts +9 -0
- package/dist/src/policy/index.js +10 -0
- package/dist/src/policy/index.js.map +1 -0
- package/dist/src/policy/policies/discovered.toml +8 -0
- package/dist/src/policy/policies/read-only.toml +56 -0
- package/dist/src/policy/policies/write.toml +73 -0
- package/dist/src/policy/policies/yolo.toml +31 -0
- package/dist/src/policy/policy-engine.d.ts +39 -0
- package/dist/src/policy/policy-engine.js +158 -0
- package/dist/src/policy/policy-engine.js.map +1 -0
- package/dist/src/policy/policy-engine.test.d.ts +6 -0
- package/dist/src/policy/policy-engine.test.js +899 -0
- package/dist/src/policy/policy-engine.test.js.map +1 -0
- package/dist/src/policy/stable-stringify.d.ts +58 -0
- package/dist/src/policy/stable-stringify.js +122 -0
- package/dist/src/policy/stable-stringify.js.map +1 -0
- package/dist/src/policy/toml-loader.d.ts +47 -0
- package/dist/src/policy/toml-loader.js +411 -0
- package/dist/src/policy/toml-loader.js.map +1 -0
- package/dist/src/policy/toml-loader.test.d.ts +6 -0
- package/dist/src/policy/toml-loader.test.js +376 -0
- package/dist/src/policy/toml-loader.test.js.map +1 -0
- package/dist/src/policy/types.d.ts +130 -0
- package/dist/src/policy/types.js +22 -0
- package/dist/src/policy/types.js.map +1 -0
- package/dist/src/prompts/mcp-prompts.d.ts +2 -2
- package/dist/src/prompts/mcp-prompts.test.d.ts +6 -0
- package/dist/src/prompts/mcp-prompts.test.js +39 -0
- package/dist/src/prompts/mcp-prompts.test.js.map +1 -0
- package/dist/src/prompts/prompt-registry.d.ts +1 -1
- package/dist/src/prompts/prompt-registry.js +2 -1
- package/dist/src/prompts/prompt-registry.js.map +1 -1
- package/dist/src/prompts/prompt-registry.test.d.ts +6 -0
- package/dist/src/prompts/prompt-registry.test.js +96 -0
- package/dist/src/prompts/prompt-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.d.ts +23 -0
- package/dist/src/routing/modelRouterService.js +85 -0
- package/dist/src/routing/modelRouterService.js.map +1 -0
- package/dist/src/routing/modelRouterService.test.d.ts +6 -0
- package/dist/src/routing/modelRouterService.test.js +160 -0
- package/dist/src/routing/modelRouterService.test.js.map +1 -0
- package/dist/src/routing/routingStrategy.d.ts +62 -0
- package/dist/src/routing/routingStrategy.js +7 -0
- package/dist/src/routing/routingStrategy.js.map +1 -0
- package/dist/src/routing/strategies/classifierStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/classifierStrategy.js +166 -0
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -0
- package/dist/src/routing/strategies/classifierStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/classifierStrategy.test.js +196 -0
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/compositeStrategy.d.ts +26 -0
- package/dist/src/routing/strategies/compositeStrategy.js +68 -0
- package/dist/src/routing/strategies/compositeStrategy.js.map +1 -0
- package/dist/src/routing/strategies/compositeStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/compositeStrategy.test.js +123 -0
- package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/defaultStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/defaultStrategy.js +20 -0
- package/dist/src/routing/strategies/defaultStrategy.js.map +1 -0
- package/dist/src/routing/strategies/defaultStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/defaultStrategy.test.js +26 -0
- package/dist/src/routing/strategies/defaultStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/fallbackStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/fallbackStrategy.js +25 -0
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.js +59 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/overrideStrategy.d.ts +15 -0
- package/dist/src/routing/strategies/overrideStrategy.js +28 -0
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -0
- package/dist/src/routing/strategies/overrideStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/overrideStrategy.test.js +45 -0
- package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -0
- package/dist/src/safety/built-in.d.ts +21 -0
- package/dist/src/safety/built-in.js +106 -0
- package/dist/src/safety/built-in.js.map +1 -0
- package/dist/src/safety/built-in.test.d.ts +6 -0
- package/dist/src/safety/built-in.test.js +199 -0
- package/dist/src/safety/built-in.test.js.map +1 -0
- package/dist/src/safety/checker-runner.d.ts +48 -0
- package/dist/src/safety/checker-runner.js +208 -0
- package/dist/src/safety/checker-runner.js.map +1 -0
- package/dist/src/safety/checker-runner.test.d.ts +6 -0
- package/dist/src/safety/checker-runner.test.js +238 -0
- package/dist/src/safety/checker-runner.test.js.map +1 -0
- package/dist/src/safety/context-builder.d.ts +23 -0
- package/dist/src/safety/context-builder.js +47 -0
- package/dist/src/safety/context-builder.js.map +1 -0
- package/dist/src/safety/context-builder.test.d.ts +6 -0
- package/dist/src/safety/context-builder.test.js +49 -0
- package/dist/src/safety/context-builder.test.js.map +1 -0
- package/dist/src/safety/protocol.d.ts +88 -0
- package/dist/src/safety/protocol.js +15 -0
- package/dist/src/safety/protocol.js.map +1 -0
- package/dist/src/safety/registry.d.ts +26 -0
- package/dist/src/safety/registry.js +65 -0
- package/dist/src/safety/registry.js.map +1 -0
- package/dist/src/safety/registry.test.d.ts +6 -0
- package/dist/src/safety/registry.test.js +31 -0
- package/dist/src/safety/registry.test.js.map +1 -0
- package/dist/src/services/chatCompressionService.d.ts +32 -0
- package/dist/src/services/chatCompressionService.js +162 -0
- package/dist/src/services/chatCompressionService.js.map +1 -0
- package/dist/src/services/chatCompressionService.test.d.ts +6 -0
- package/dist/src/services/chatCompressionService.test.js +210 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -0
- package/dist/src/services/chatRecordingService.d.ts +10 -15
- package/dist/src/services/chatRecordingService.js +43 -29
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/chatRecordingService.test.js +69 -25
- package/dist/src/services/chatRecordingService.test.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.d.ts +8 -10
- package/dist/src/services/fileDiscoveryService.js +31 -53
- package/dist/src/services/fileDiscoveryService.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.test.js +94 -14
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
- package/dist/src/services/fileSystemService.d.ts +9 -0
- package/dist/src/services/fileSystemService.js +12 -1
- package/dist/src/services/fileSystemService.js.map +1 -1
- package/dist/src/services/fileSystemService.test.js +1 -1
- package/dist/src/services/fileSystemService.test.js.map +1 -1
- package/dist/src/services/gitService.d.ts +3 -1
- package/dist/src/services/gitService.js +30 -24
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +30 -37
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +12 -3
- package/dist/src/services/loopDetectionService.js +148 -55
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +280 -21
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/modelConfig.golden.test.d.ts +6 -0
- package/dist/src/services/modelConfig.golden.test.js +42 -0
- package/dist/src/services/modelConfig.golden.test.js.map +1 -0
- package/dist/src/services/modelConfig.integration.test.d.ts +6 -0
- package/dist/src/services/modelConfig.integration.test.js +247 -0
- package/dist/src/services/modelConfig.integration.test.js.map +1 -0
- package/dist/src/services/modelConfigService.d.ts +48 -0
- package/dist/src/services/modelConfigService.js +151 -0
- package/dist/src/services/modelConfigService.js.map +1 -0
- package/dist/src/services/modelConfigService.test.d.ts +6 -0
- package/dist/src/services/modelConfigService.test.js +531 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.d.ts +37 -2
- package/dist/src/services/shellExecutionService.js +361 -67
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +333 -71
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/services/test-data/resolved-aliases.golden.json +202 -0
- package/dist/src/telemetry/activity-detector.d.ts +41 -0
- package/dist/src/telemetry/activity-detector.js +61 -0
- package/dist/src/telemetry/activity-detector.js.map +1 -0
- package/dist/src/telemetry/activity-detector.test.d.ts +6 -0
- package/dist/src/telemetry/activity-detector.test.js +136 -0
- package/dist/src/telemetry/activity-detector.test.js.map +1 -0
- package/dist/src/telemetry/activity-monitor.d.ts +116 -0
- package/dist/src/telemetry/activity-monitor.js +209 -0
- package/dist/src/telemetry/activity-monitor.js.map +1 -0
- package/dist/src/telemetry/activity-monitor.test.d.ts +6 -0
- package/dist/src/telemetry/activity-monitor.test.js +251 -0
- package/dist/src/telemetry/activity-monitor.test.js.map +1 -0
- package/dist/src/telemetry/activity-types.d.ts +19 -0
- package/dist/src/telemetry/activity-types.js +21 -0
- package/dist/src/telemetry/activity-types.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +53 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +581 -56
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +2 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +467 -31
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +75 -4
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +182 -6
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/config.d.ts +31 -0
- package/dist/src/telemetry/config.js +76 -0
- package/dist/src/telemetry/config.js.map +1 -0
- package/dist/src/telemetry/config.test.d.ts +6 -0
- package/dist/src/telemetry/config.test.js +124 -0
- package/dist/src/telemetry/config.test.js.map +1 -0
- package/dist/src/telemetry/constants.d.ts +0 -18
- package/dist/src/telemetry/constants.js +0 -18
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/file-exporters.d.ts +5 -4
- package/dist/src/telemetry/file-exporters.js +1 -1
- package/dist/src/telemetry/file-exporters.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.d.ts +34 -0
- package/dist/src/telemetry/gcp-exporters.js +116 -0
- package/dist/src/telemetry/gcp-exporters.js.map +1 -0
- package/dist/src/telemetry/gcp-exporters.test.d.ts +6 -0
- package/dist/src/telemetry/gcp-exporters.test.js +318 -0
- package/dist/src/telemetry/gcp-exporters.test.js.map +1 -0
- package/dist/src/telemetry/high-water-mark-tracker.d.ts +43 -0
- package/dist/src/telemetry/high-water-mark-tracker.js +88 -0
- package/dist/src/telemetry/high-water-mark-tracker.js.map +1 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.d.ts +6 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.js +152 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +16 -2
- package/dist/src/telemetry/index.js +25 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +25 -3
- package/dist/src/telemetry/loggers.js +333 -154
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +3 -4
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +868 -63
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/memory-monitor.d.ts +149 -0
- package/dist/src/telemetry/memory-monitor.js +335 -0
- package/dist/src/telemetry/memory-monitor.js.map +1 -0
- package/dist/src/telemetry/memory-monitor.test.d.ts +6 -0
- package/dist/src/telemetry/memory-monitor.test.js +472 -0
- package/dist/src/telemetry/memory-monitor.test.js.map +1 -0
- package/dist/src/telemetry/metrics.d.ts +498 -11
- package/dist/src/telemetry/metrics.js +729 -84
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +964 -101
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/rate-limiter.d.ts +48 -0
- package/dist/src/telemetry/rate-limiter.js +100 -0
- package/dist/src/telemetry/rate-limiter.js.map +1 -0
- package/dist/src/telemetry/rate-limiter.test.d.ts +6 -0
- package/dist/src/telemetry/rate-limiter.test.js +207 -0
- package/dist/src/telemetry/rate-limiter.test.js.map +1 -0
- package/dist/src/telemetry/sdk.d.ts +1 -1
- package/dist/src/telemetry/sdk.js +23 -4
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/sdk.test.js +108 -0
- package/dist/src/telemetry/sdk.test.js.map +1 -1
- package/dist/src/telemetry/semantic.d.ts +82 -0
- package/dist/src/telemetry/semantic.js +269 -0
- package/dist/src/telemetry/semantic.js.map +1 -0
- package/dist/src/telemetry/semantic.test.d.ts +6 -0
- package/dist/src/telemetry/semantic.test.js +387 -0
- package/dist/src/telemetry/semantic.test.js.map +1 -0
- package/dist/src/telemetry/telemetry-utils.d.ts +6 -0
- package/dist/src/telemetry/telemetry-utils.js +14 -0
- package/dist/src/telemetry/telemetry-utils.js.map +1 -0
- package/dist/src/telemetry/telemetry-utils.test.d.ts +6 -0
- package/dist/src/telemetry/telemetry-utils.test.js +41 -0
- package/dist/src/telemetry/telemetry-utils.test.js.map +1 -0
- package/dist/src/telemetry/telemetryAttributes.d.ts +8 -0
- package/dist/src/telemetry/telemetryAttributes.js +19 -0
- package/dist/src/telemetry/telemetryAttributes.js.map +1 -0
- package/dist/src/telemetry/trace.d.ts +46 -0
- package/dist/src/telemetry/trace.js +121 -0
- package/dist/src/telemetry/trace.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +351 -25
- package/dist/src/telemetry/types.js +1071 -63
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +4 -4
- package/dist/src/telemetry/uiTelemetry.js +14 -15
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +122 -96
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/config.d.ts +3 -2
- package/dist/src/test-utils/config.js +1 -1
- package/dist/src/test-utils/config.js.map +1 -1
- package/dist/src/test-utils/index.d.ts +6 -0
- package/dist/src/test-utils/index.js +7 -0
- package/dist/src/test-utils/index.js.map +1 -0
- package/dist/src/test-utils/mock-tool.d.ts +66 -0
- package/dist/src/test-utils/{tools.js → mock-tool.js} +45 -29
- package/dist/src/test-utils/mock-tool.js.map +1 -0
- package/dist/src/test-utils/mockWorkspaceContext.d.ts +1 -1
- package/dist/src/tools/base-tool-invocation.test.d.ts +6 -0
- package/dist/src/tools/base-tool-invocation.test.js +85 -0
- package/dist/src/tools/base-tool-invocation.test.js.map +1 -0
- package/dist/src/tools/diffOptions.d.ts +1 -1
- package/dist/src/tools/diffOptions.js +21 -13
- package/dist/src/tools/diffOptions.js.map +1 -1
- package/dist/src/tools/diffOptions.test.js +58 -22
- package/dist/src/tools/diffOptions.test.js.map +1 -1
- package/dist/src/tools/edit.d.ts +10 -8
- package/dist/src/tools/edit.js +100 -79
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +429 -163
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +11 -5
- package/dist/src/tools/glob.js +58 -42
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +249 -166
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +7 -5
- package/dist/src/tools/grep.js +66 -40
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +41 -15
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +7 -5
- package/dist/src/tools/ls.js +54 -68
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +150 -293
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +52 -12
- package/dist/src/tools/mcp-client-manager.js +196 -27
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +139 -13
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +28 -24
- package/dist/src/tools/mcp-client.js +338 -351
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +380 -193
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +11 -5
- package/dist/src/tools/mcp-tool.js +66 -17
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +278 -211
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +10 -7
- package/dist/src/tools/memoryTool.js +28 -49
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +26 -13
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/message-bus-integration.test.d.ts +6 -0
- package/dist/src/tools/message-bus-integration.test.js +196 -0
- package/dist/src/tools/message-bus-integration.test.js.map +1 -0
- package/dist/src/tools/modifiable-tool.d.ts +7 -3
- package/dist/src/tools/modifiable-tool.js +41 -19
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +70 -35
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +9 -7
- package/dist/src/tools/read-file.js +39 -60
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +103 -36
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +9 -14
- package/dist/src/tools/read-many-files.js +71 -155
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +98 -44
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +73 -0
- package/dist/src/tools/ripGrep.js +395 -0
- package/dist/src/tools/ripGrep.js.map +1 -0
- package/dist/src/tools/ripGrep.test.d.ts +6 -0
- package/dist/src/tools/ripGrep.test.js +1305 -0
- package/dist/src/tools/ripGrep.test.js.map +1 -0
- package/dist/src/tools/shell.d.ts +19 -6
- package/dist/src/tools/shell.js +92 -56
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +176 -103
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +78 -0
- package/dist/src/tools/smart-edit.js +717 -0
- package/dist/src/tools/smart-edit.js.map +1 -0
- package/dist/src/tools/smart-edit.test.d.ts +6 -0
- package/dist/src/tools/smart-edit.test.js +592 -0
- package/dist/src/tools/smart-edit.test.js.map +1 -0
- package/dist/src/tools/tool-error.d.ts +39 -1
- package/dist/src/tools/tool-error.js +54 -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 +21 -0
- package/dist/src/tools/tool-names.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +38 -20
- package/dist/src/tools/tool-registry.js +134 -77
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +218 -58
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +49 -17
- package/dist/src/tools/tools.js +150 -8
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.js +1 -2
- package/dist/src/tools/tools.test.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +14 -5
- package/dist/src/tools/web-fetch.js +90 -44
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +388 -20
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.d.ts +8 -6
- package/dist/src/tools/web-search.js +40 -15
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +75 -1
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +7 -5
- package/dist/src/tools/write-file.js +54 -54
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +237 -146
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +50 -0
- package/dist/src/tools/write-todos.js +193 -0
- package/dist/src/tools/write-todos.js.map +1 -0
- package/dist/src/tools/write-todos.test.d.ts +6 -0
- package/dist/src/tools/write-todos.test.js +89 -0
- package/dist/src/tools/write-todos.test.js.map +1 -0
- package/dist/src/utils/bfsFileSearch.d.ts +2 -2
- package/dist/src/utils/bfsFileSearch.js +16 -9
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +3 -3
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/channel.d.ts +19 -0
- package/dist/src/utils/channel.js +49 -0
- package/dist/src/utils/channel.js.map +1 -0
- package/dist/src/utils/channel.test.d.ts +6 -0
- package/dist/src/utils/channel.test.js +170 -0
- package/dist/src/utils/channel.test.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +25 -0
- package/dist/src/utils/debugLogger.js +33 -0
- package/dist/src/utils/debugLogger.js.map +1 -0
- package/dist/src/utils/debugLogger.test.d.ts +6 -0
- package/dist/src/utils/debugLogger.test.js +69 -0
- package/dist/src/utils/debugLogger.test.js.map +1 -0
- package/dist/src/utils/delay.d.ts +16 -0
- package/dist/src/utils/delay.js +43 -0
- package/dist/src/utils/delay.js.map +1 -0
- package/dist/src/utils/delay.test.d.ts +6 -0
- package/dist/src/utils/delay.test.js +88 -0
- package/dist/src/utils/delay.test.js.map +1 -0
- package/dist/src/utils/editCorrector.d.ts +9 -8
- package/dist/src/utils/editCorrector.js +62 -34
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +52 -87
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +4 -2
- package/dist/src/utils/editor.js +56 -55
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +47 -88
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +3 -2
- package/dist/src/utils/environmentContext.js +20 -33
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +6 -34
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/errorParsing.d.ts +1 -1
- package/dist/src/utils/errorParsing.js +5 -33
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +0 -88
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/errorReporting.d.ts +1 -1
- package/dist/src/utils/errors.d.ts +28 -0
- package/dist/src/utils/errors.js +48 -0
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/events.d.ts +121 -0
- package/dist/src/utils/events.js +84 -0
- package/dist/src/utils/events.js.map +1 -0
- package/dist/src/utils/events.test.d.ts +6 -0
- package/dist/src/utils/events.test.js +212 -0
- package/dist/src/utils/events.test.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +86 -0
- package/dist/src/utils/extensionLoader.js +208 -0
- package/dist/src/utils/extensionLoader.js.map +1 -0
- package/dist/src/utils/extensionLoader.test.d.ts +6 -0
- package/dist/src/utils/extensionLoader.test.js +154 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +1 -0
- package/dist/src/utils/fetch.js +5 -1
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +28 -12
- package/dist/src/utils/fileUtils.js +204 -81
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +426 -82
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawler.d.ts +1 -1
- package/dist/src/utils/filesearch/crawler.test.js +2 -2
- package/dist/src/utils/filesearch/crawler.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.d.ts +1 -0
- package/dist/src/utils/filesearch/fileSearch.js +14 -9
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.test.js +90 -0
- package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.d.ts +6 -0
- package/dist/src/utils/flashFallback.test.js +103 -0
- package/dist/src/utils/flashFallback.test.js.map +1 -0
- package/dist/src/utils/formatters.d.ts +1 -0
- package/dist/src/utils/formatters.js +2 -1
- package/dist/src/utils/formatters.js.map +1 -1
- package/dist/src/utils/formatters.test.d.ts +6 -0
- package/dist/src/utils/formatters.test.js +26 -0
- package/dist/src/utils/formatters.test.js.map +1 -0
- package/dist/src/utils/geminiIgnoreParser.d.ts +18 -0
- package/dist/src/utils/geminiIgnoreParser.js +61 -0
- package/dist/src/utils/geminiIgnoreParser.js.map +1 -0
- package/dist/src/utils/geminiIgnoreParser.test.d.ts +6 -0
- package/dist/src/utils/geminiIgnoreParser.test.js +50 -0
- package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -0
- package/dist/src/utils/generateContentResponseUtilities.d.ts +1 -2
- package/dist/src/utils/generateContentResponseUtilities.js +1 -13
- package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
- package/dist/src/utils/generateContentResponseUtilities.test.js +2 -40
- package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
- package/dist/src/utils/getFolderStructure.d.ts +2 -2
- package/dist/src/utils/getFolderStructure.js +12 -20
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/getFolderStructure.test.js +11 -10
- package/dist/src/utils/getFolderStructure.test.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.d.ts +7 -8
- package/dist/src/utils/gitIgnoreParser.js +145 -36
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.test.js +127 -38
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/gitUtils.js +2 -2
- package/dist/src/utils/gitUtils.js.map +1 -1
- package/dist/src/utils/googleErrors.d.ts +104 -0
- package/dist/src/utils/googleErrors.js +152 -0
- package/dist/src/utils/googleErrors.js.map +1 -0
- package/dist/src/utils/googleErrors.test.d.ts +6 -0
- package/dist/src/utils/googleErrors.test.js +301 -0
- package/dist/src/utils/googleErrors.test.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.d.ts +37 -0
- package/dist/src/utils/googleQuotaErrors.js +157 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
- package/dist/src/utils/googleQuotaErrors.test.js +311 -0
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
- package/dist/src/utils/httpErrors.d.ts +18 -0
- package/dist/src/utils/httpErrors.js +36 -0
- package/dist/src/utils/httpErrors.js.map +1 -0
- package/dist/src/utils/ignorePatterns.d.ts +103 -0
- package/dist/src/utils/ignorePatterns.js +220 -0
- package/dist/src/utils/ignorePatterns.js.map +1 -0
- package/dist/src/utils/ignorePatterns.test.d.ts +6 -0
- package/dist/src/utils/ignorePatterns.test.js +246 -0
- package/dist/src/utils/ignorePatterns.test.js.map +1 -0
- package/dist/src/utils/installationManager.d.ts +16 -0
- package/dist/src/utils/installationManager.js +51 -0
- package/dist/src/utils/installationManager.js.map +1 -0
- package/dist/src/utils/installationManager.test.d.ts +6 -0
- package/dist/src/utils/installationManager.test.js +85 -0
- package/dist/src/utils/installationManager.test.js.map +1 -0
- package/dist/src/utils/language-detection.d.ts +6 -0
- package/dist/src/utils/language-detection.js +101 -0
- package/dist/src/utils/language-detection.js.map +1 -0
- package/dist/src/utils/llm-edit-fixer.d.ts +26 -0
- package/dist/src/utils/llm-edit-fixer.js +155 -0
- package/dist/src/utils/llm-edit-fixer.js.map +1 -0
- package/dist/src/utils/llm-edit-fixer.test.d.ts +6 -0
- package/dist/src/utils/llm-edit-fixer.test.js +223 -0
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.d.ts +26 -6
- package/dist/src/utils/memoryDiscovery.js +239 -40
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +365 -44
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +19 -25
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.test.js +24 -155
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
- package/dist/src/utils/messageInspectors.d.ts +1 -1
- package/dist/src/utils/nextSpeakerChecker.d.ts +3 -3
- package/dist/src/utils/nextSpeakerChecker.js +10 -4
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +85 -66
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/package.d.ts +12 -0
- package/dist/src/utils/package.js +15 -0
- package/dist/src/utils/package.js.map +1 -0
- package/dist/src/utils/partUtils.d.ts +22 -1
- package/dist/src/utils/partUtils.js +68 -0
- package/dist/src/utils/partUtils.js.map +1 -1
- package/dist/src/utils/partUtils.test.js +112 -1
- package/dist/src/utils/partUtils.test.js.map +1 -1
- package/dist/src/utils/pathCorrector.d.ts +25 -0
- package/dist/src/utils/pathCorrector.js +33 -0
- package/dist/src/utils/pathCorrector.js.map +1 -0
- package/dist/src/utils/pathCorrector.test.d.ts +6 -0
- package/dist/src/utils/pathCorrector.test.js +83 -0
- package/dist/src/utils/pathCorrector.test.js.map +1 -0
- package/dist/src/utils/pathReader.d.ts +17 -0
- package/dist/src/utils/pathReader.js +92 -0
- package/dist/src/utils/pathReader.js.map +1 -0
- package/dist/src/utils/pathReader.test.d.ts +6 -0
- package/dist/src/utils/pathReader.test.js +406 -0
- package/dist/src/utils/pathReader.test.js.map +1 -0
- package/dist/src/utils/paths.d.ts +1 -18
- package/dist/src/utils/paths.js +133 -57
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/paths.test.js +200 -68
- package/dist/src/utils/paths.test.js.map +1 -1
- package/dist/src/utils/promptIdContext.d.ts +7 -0
- package/dist/src/utils/promptIdContext.js +8 -0
- package/dist/src/utils/promptIdContext.js.map +1 -0
- package/dist/src/utils/quotaErrorDetection.d.ts +1 -3
- package/dist/src/utils/quotaErrorDetection.js +0 -46
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/retry.d.ts +5 -10
- package/dist/src/utils/retry.js +114 -197
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +196 -130
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/safeJsonStringify.d.ts +4 -4
- package/dist/src/utils/safeJsonStringify.js +31 -7
- package/dist/src/utils/safeJsonStringify.js.map +1 -1
- package/dist/src/utils/schemaValidator.js +15 -1
- package/dist/src/utils/schemaValidator.js.map +1 -1
- package/dist/src/utils/schemaValidator.test.d.ts +6 -0
- package/dist/src/utils/schemaValidator.test.js +113 -0
- package/dist/src/utils/schemaValidator.test.js.map +1 -0
- package/dist/src/utils/session.js +1 -1
- package/dist/src/utils/session.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +21 -3
- package/dist/src/utils/shell-utils.js +427 -159
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +250 -59
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/stdio.d.ts +32 -0
- package/dist/src/utils/stdio.js +85 -0
- package/dist/src/utils/stdio.js.map +1 -0
- package/dist/src/utils/stdio.test.d.ts +6 -0
- package/dist/src/utils/stdio.test.js +47 -0
- package/dist/src/utils/stdio.test.js.map +1 -0
- package/dist/src/utils/summarizer.d.ts +6 -4
- package/dist/src/utils/summarizer.js +8 -9
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +32 -12
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/systemEncoding.js +7 -6
- package/dist/src/utils/systemEncoding.js.map +1 -1
- package/dist/src/utils/systemEncoding.test.js +4 -3
- package/dist/src/utils/systemEncoding.test.js.map +1 -1
- package/dist/src/utils/terminal.d.ts +14 -0
- package/dist/src/utils/terminal.js +38 -0
- package/dist/src/utils/terminal.js.map +1 -0
- package/dist/src/utils/terminalSerializer.d.ts +25 -0
- package/dist/src/utils/terminalSerializer.js +432 -0
- package/dist/src/utils/terminalSerializer.js.map +1 -0
- package/dist/src/utils/terminalSerializer.test.d.ts +6 -0
- package/dist/src/utils/terminalSerializer.test.js +176 -0
- package/dist/src/utils/terminalSerializer.test.js.map +1 -0
- package/dist/src/utils/textUtils.d.ts +5 -0
- package/dist/src/utils/textUtils.js +14 -0
- package/dist/src/utils/textUtils.js.map +1 -1
- package/dist/src/utils/textUtils.test.d.ts +6 -0
- package/dist/src/utils/textUtils.test.js +59 -0
- package/dist/src/utils/textUtils.test.js.map +1 -0
- package/dist/src/utils/thoughtUtils.d.ts +21 -0
- package/dist/src/utils/thoughtUtils.js +39 -0
- package/dist/src/utils/thoughtUtils.js.map +1 -0
- package/dist/src/utils/thoughtUtils.test.d.ts +6 -0
- package/dist/src/utils/thoughtUtils.test.js +78 -0
- package/dist/src/utils/thoughtUtils.test.js.map +1 -0
- package/dist/src/utils/tool-utils.d.ts +19 -0
- package/dist/src/utils/tool-utils.js +67 -0
- package/dist/src/utils/tool-utils.js.map +1 -0
- package/dist/src/utils/tool-utils.test.d.ts +6 -0
- package/dist/src/utils/tool-utils.test.js +69 -0
- package/dist/src/utils/tool-utils.test.js.map +1 -0
- package/dist/src/utils/userAccountManager.d.ts +20 -0
- package/dist/src/utils/userAccountManager.js +115 -0
- package/dist/src/utils/userAccountManager.js.map +1 -0
- package/dist/src/utils/userAccountManager.test.d.ts +6 -0
- package/dist/src/utils/{user_account.test.js → userAccountManager.test.js} +41 -36
- package/dist/src/utils/userAccountManager.test.js.map +1 -0
- package/dist/src/utils/workspaceContext.d.ts +4 -3
- package/dist/src/utils/workspaceContext.js +23 -17
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +45 -19
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -10
- package/dist/src/core/modelCheck.d.ts +0 -14
- package/dist/src/core/modelCheck.js +0 -62
- package/dist/src/core/modelCheck.js.map +0 -1
- package/dist/src/test-utils/tools.d.ts +0 -44
- package/dist/src/test-utils/tools.js.map +0 -1
- package/dist/src/utils/flashFallback.integration.test.js +0 -118
- package/dist/src/utils/flashFallback.integration.test.js.map +0 -1
- package/dist/src/utils/user_account.d.ts +0 -9
- package/dist/src/utils/user_account.js +0 -109
- package/dist/src/utils/user_account.js.map +0 -1
- package/dist/src/utils/user_account.test.js.map +0 -1
- package/dist/src/utils/user_id.d.ts +0 -11
- package/dist/src/utils/user_id.js +0 -49
- package/dist/src/utils/user_id.js.map +0 -1
- package/dist/src/utils/user_id.test.js +0 -21
- package/dist/src/utils/user_id.test.js.map +0 -1
- /package/dist/src/{utils/flashFallback.integration.test.d.ts → agents/codebase-investigator.test.d.ts} +0 -0
- /package/dist/src/{utils/user_account.test.d.ts → agents/executor.test.d.ts} +0 -0
- /package/dist/src/{utils/user_id.test.d.ts → agents/invocation.test.d.ts} +0 -0
|
@@ -0,0 +1,1305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach, afterAll, vi, } from 'vitest';
|
|
7
|
+
import { canUseRipgrep, RipGrepTool, ensureRgPath } from './ripGrep.js';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import fs from 'node:fs/promises';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import { Storage } from '../config/storage.js';
|
|
12
|
+
import { createMockWorkspaceContext } from '../test-utils/mockWorkspaceContext.js';
|
|
13
|
+
import { spawn } from 'node:child_process';
|
|
14
|
+
import { downloadRipGrep } from '@joshua.litt/get-ripgrep';
|
|
15
|
+
// Mock dependencies for canUseRipgrep
|
|
16
|
+
vi.mock('@joshua.litt/get-ripgrep', () => ({
|
|
17
|
+
downloadRipGrep: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
// Mock child_process for ripgrep calls
|
|
20
|
+
vi.mock('child_process', () => ({
|
|
21
|
+
spawn: vi.fn(),
|
|
22
|
+
}));
|
|
23
|
+
const mockSpawn = vi.mocked(spawn);
|
|
24
|
+
const downloadRipGrepMock = vi.mocked(downloadRipGrep);
|
|
25
|
+
const originalGetGlobalBinDir = Storage.getGlobalBinDir.bind(Storage);
|
|
26
|
+
const storageSpy = vi.spyOn(Storage, 'getGlobalBinDir');
|
|
27
|
+
function getRipgrepBinaryName() {
|
|
28
|
+
return process.platform === 'win32' ? 'rg.exe' : 'rg';
|
|
29
|
+
}
|
|
30
|
+
describe('canUseRipgrep', () => {
|
|
31
|
+
let tempRootDir;
|
|
32
|
+
let binDir;
|
|
33
|
+
beforeEach(async () => {
|
|
34
|
+
downloadRipGrepMock.mockReset();
|
|
35
|
+
downloadRipGrepMock.mockResolvedValue(undefined);
|
|
36
|
+
tempRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ripgrep-bin-'));
|
|
37
|
+
binDir = path.join(tempRootDir, 'bin');
|
|
38
|
+
await fs.mkdir(binDir, { recursive: true });
|
|
39
|
+
storageSpy.mockImplementation(() => binDir);
|
|
40
|
+
});
|
|
41
|
+
afterEach(async () => {
|
|
42
|
+
storageSpy.mockImplementation(() => originalGetGlobalBinDir());
|
|
43
|
+
await fs.rm(tempRootDir, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
it('should return true if ripgrep already exists', async () => {
|
|
46
|
+
const existingPath = path.join(binDir, getRipgrepBinaryName());
|
|
47
|
+
await fs.writeFile(existingPath, '');
|
|
48
|
+
const result = await canUseRipgrep();
|
|
49
|
+
expect(result).toBe(true);
|
|
50
|
+
expect(downloadRipGrepMock).not.toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
it('should download ripgrep and return true if it does not exist initially', async () => {
|
|
53
|
+
const expectedPath = path.join(binDir, getRipgrepBinaryName());
|
|
54
|
+
downloadRipGrepMock.mockImplementation(async () => {
|
|
55
|
+
await fs.writeFile(expectedPath, '');
|
|
56
|
+
});
|
|
57
|
+
const result = await canUseRipgrep();
|
|
58
|
+
expect(result).toBe(true);
|
|
59
|
+
expect(downloadRipGrep).toHaveBeenCalledWith(binDir);
|
|
60
|
+
await expect(fs.access(expectedPath)).resolves.toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
it('should return false if download fails and file does not exist', async () => {
|
|
63
|
+
const result = await canUseRipgrep();
|
|
64
|
+
expect(result).toBe(false);
|
|
65
|
+
expect(downloadRipGrep).toHaveBeenCalledWith(binDir);
|
|
66
|
+
});
|
|
67
|
+
it('should propagate errors from downloadRipGrep', async () => {
|
|
68
|
+
const error = new Error('Download failed');
|
|
69
|
+
downloadRipGrepMock.mockRejectedValue(error);
|
|
70
|
+
await expect(canUseRipgrep()).rejects.toThrow(error);
|
|
71
|
+
expect(downloadRipGrep).toHaveBeenCalledWith(binDir);
|
|
72
|
+
});
|
|
73
|
+
it('should only download once when called concurrently', async () => {
|
|
74
|
+
const expectedPath = path.join(binDir, getRipgrepBinaryName());
|
|
75
|
+
downloadRipGrepMock.mockImplementation(() => new Promise((resolve, reject) => {
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
fs.writeFile(expectedPath, '')
|
|
78
|
+
.then(() => resolve())
|
|
79
|
+
.catch(reject);
|
|
80
|
+
}, 0);
|
|
81
|
+
}));
|
|
82
|
+
const firstCall = ensureRgPath();
|
|
83
|
+
const secondCall = ensureRgPath();
|
|
84
|
+
const [pathOne, pathTwo] = await Promise.all([firstCall, secondCall]);
|
|
85
|
+
expect(pathOne).toBe(expectedPath);
|
|
86
|
+
expect(pathTwo).toBe(expectedPath);
|
|
87
|
+
expect(downloadRipGrepMock).toHaveBeenCalledTimes(1);
|
|
88
|
+
await expect(fs.access(expectedPath)).resolves.toBeUndefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('ensureRgPath', () => {
|
|
92
|
+
let tempRootDir;
|
|
93
|
+
let binDir;
|
|
94
|
+
beforeEach(async () => {
|
|
95
|
+
downloadRipGrepMock.mockReset();
|
|
96
|
+
downloadRipGrepMock.mockResolvedValue(undefined);
|
|
97
|
+
tempRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ripgrep-bin-'));
|
|
98
|
+
binDir = path.join(tempRootDir, 'bin');
|
|
99
|
+
await fs.mkdir(binDir, { recursive: true });
|
|
100
|
+
storageSpy.mockImplementation(() => binDir);
|
|
101
|
+
});
|
|
102
|
+
afterEach(async () => {
|
|
103
|
+
storageSpy.mockImplementation(() => originalGetGlobalBinDir());
|
|
104
|
+
await fs.rm(tempRootDir, { recursive: true, force: true });
|
|
105
|
+
});
|
|
106
|
+
it('should return rg path if ripgrep already exists', async () => {
|
|
107
|
+
const existingPath = path.join(binDir, getRipgrepBinaryName());
|
|
108
|
+
await fs.writeFile(existingPath, '');
|
|
109
|
+
const rgPath = await ensureRgPath();
|
|
110
|
+
expect(rgPath).toBe(existingPath);
|
|
111
|
+
expect(downloadRipGrep).not.toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
it('should return rg path if ripgrep is downloaded successfully', async () => {
|
|
114
|
+
const expectedPath = path.join(binDir, getRipgrepBinaryName());
|
|
115
|
+
downloadRipGrepMock.mockImplementation(async () => {
|
|
116
|
+
await fs.writeFile(expectedPath, '');
|
|
117
|
+
});
|
|
118
|
+
const rgPath = await ensureRgPath();
|
|
119
|
+
expect(rgPath).toBe(expectedPath);
|
|
120
|
+
expect(downloadRipGrep).toHaveBeenCalledTimes(1);
|
|
121
|
+
await expect(fs.access(expectedPath)).resolves.toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
it('should throw an error if ripgrep cannot be used after download attempt', async () => {
|
|
124
|
+
await expect(ensureRgPath()).rejects.toThrow('Cannot use ripgrep.');
|
|
125
|
+
expect(downloadRipGrep).toHaveBeenCalledTimes(1);
|
|
126
|
+
});
|
|
127
|
+
it('should propagate errors from downloadRipGrep', async () => {
|
|
128
|
+
const error = new Error('Download failed');
|
|
129
|
+
downloadRipGrepMock.mockRejectedValue(error);
|
|
130
|
+
await expect(ensureRgPath()).rejects.toThrow(error);
|
|
131
|
+
expect(downloadRipGrep).toHaveBeenCalledWith(binDir);
|
|
132
|
+
});
|
|
133
|
+
it.runIf(process.platform === 'win32')('should detect ripgrep when only rg.exe exists on Windows', async () => {
|
|
134
|
+
const expectedRgExePath = path.join(binDir, 'rg.exe');
|
|
135
|
+
await fs.writeFile(expectedRgExePath, '');
|
|
136
|
+
const rgPath = await ensureRgPath();
|
|
137
|
+
expect(rgPath).toBe(expectedRgExePath);
|
|
138
|
+
expect(downloadRipGrep).not.toHaveBeenCalled();
|
|
139
|
+
await expect(fs.access(expectedRgExePath)).resolves.toBeUndefined();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
// Helper function to create mock spawn implementations
|
|
143
|
+
function createMockSpawn(options = {}) {
|
|
144
|
+
const { outputData, exitCode = 0, signal } = options;
|
|
145
|
+
return () => {
|
|
146
|
+
const mockProcess = {
|
|
147
|
+
stdout: {
|
|
148
|
+
on: vi.fn(),
|
|
149
|
+
removeListener: vi.fn(),
|
|
150
|
+
},
|
|
151
|
+
stderr: {
|
|
152
|
+
on: vi.fn(),
|
|
153
|
+
removeListener: vi.fn(),
|
|
154
|
+
},
|
|
155
|
+
on: vi.fn(),
|
|
156
|
+
removeListener: vi.fn(),
|
|
157
|
+
kill: vi.fn(),
|
|
158
|
+
};
|
|
159
|
+
// Set up event listeners immediately
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
const stdoutDataHandler = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
162
|
+
const closeHandler = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
163
|
+
if (stdoutDataHandler && outputData) {
|
|
164
|
+
stdoutDataHandler(Buffer.from(outputData));
|
|
165
|
+
}
|
|
166
|
+
if (closeHandler) {
|
|
167
|
+
closeHandler(exitCode, signal);
|
|
168
|
+
}
|
|
169
|
+
}, 0);
|
|
170
|
+
return mockProcess;
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
describe('RipGrepTool', () => {
|
|
174
|
+
let tempRootDir;
|
|
175
|
+
let tempBinRoot;
|
|
176
|
+
let binDir;
|
|
177
|
+
let ripgrepBinaryPath;
|
|
178
|
+
let grepTool;
|
|
179
|
+
const abortSignal = new AbortController().signal;
|
|
180
|
+
const mockConfig = {
|
|
181
|
+
getTargetDir: () => tempRootDir,
|
|
182
|
+
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
|
183
|
+
getDebugMode: () => false,
|
|
184
|
+
};
|
|
185
|
+
beforeEach(async () => {
|
|
186
|
+
downloadRipGrepMock.mockReset();
|
|
187
|
+
downloadRipGrepMock.mockResolvedValue(undefined);
|
|
188
|
+
mockSpawn.mockReset();
|
|
189
|
+
tempBinRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'ripgrep-bin-'));
|
|
190
|
+
binDir = path.join(tempBinRoot, 'bin');
|
|
191
|
+
await fs.mkdir(binDir, { recursive: true });
|
|
192
|
+
const binaryName = process.platform === 'win32' ? 'rg.exe' : 'rg';
|
|
193
|
+
ripgrepBinaryPath = path.join(binDir, binaryName);
|
|
194
|
+
await fs.writeFile(ripgrepBinaryPath, '');
|
|
195
|
+
storageSpy.mockImplementation(() => binDir);
|
|
196
|
+
tempRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'grep-tool-root-'));
|
|
197
|
+
grepTool = new RipGrepTool(mockConfig);
|
|
198
|
+
// Create some test files and directories
|
|
199
|
+
await fs.writeFile(path.join(tempRootDir, 'fileA.txt'), 'hello world\nsecond line with world');
|
|
200
|
+
await fs.writeFile(path.join(tempRootDir, 'fileB.js'), 'const foo = "bar";\nfunction baz() { return "hello"; }');
|
|
201
|
+
await fs.mkdir(path.join(tempRootDir, 'sub'));
|
|
202
|
+
await fs.writeFile(path.join(tempRootDir, 'sub', 'fileC.txt'), 'another world in sub dir');
|
|
203
|
+
await fs.writeFile(path.join(tempRootDir, 'sub', 'fileD.md'), '# Markdown file\nThis is a test.');
|
|
204
|
+
});
|
|
205
|
+
afterEach(async () => {
|
|
206
|
+
storageSpy.mockImplementation(() => originalGetGlobalBinDir());
|
|
207
|
+
await fs.rm(tempRootDir, { recursive: true, force: true });
|
|
208
|
+
await fs.rm(tempBinRoot, { recursive: true, force: true });
|
|
209
|
+
});
|
|
210
|
+
describe('validateToolParams', () => {
|
|
211
|
+
it.each([
|
|
212
|
+
{
|
|
213
|
+
name: 'pattern only',
|
|
214
|
+
params: { pattern: 'hello' },
|
|
215
|
+
expected: null,
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
name: 'pattern and path',
|
|
219
|
+
params: { pattern: 'hello', dir_path: '.' },
|
|
220
|
+
expected: null,
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: 'pattern, path, and include',
|
|
224
|
+
params: { pattern: 'hello', dir_path: '.', include: '*.txt' },
|
|
225
|
+
expected: null,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: 'invalid regex pattern',
|
|
229
|
+
params: { pattern: '[[' },
|
|
230
|
+
expected: null,
|
|
231
|
+
},
|
|
232
|
+
])('should return null for valid params ($name)', ({ params, expected }) => {
|
|
233
|
+
expect(grepTool.validateToolParams(params)).toBe(expected);
|
|
234
|
+
});
|
|
235
|
+
it('should return error if pattern is missing', () => {
|
|
236
|
+
const params = { dir_path: '.' };
|
|
237
|
+
expect(grepTool.validateToolParams(params)).toBe(`params must have required property 'pattern'`);
|
|
238
|
+
});
|
|
239
|
+
it('should return error if path does not exist', () => {
|
|
240
|
+
const params = {
|
|
241
|
+
pattern: 'hello',
|
|
242
|
+
dir_path: 'nonexistent',
|
|
243
|
+
};
|
|
244
|
+
// Check for the core error message, as the full path might vary
|
|
245
|
+
expect(grepTool.validateToolParams(params)).toContain('Path does not exist');
|
|
246
|
+
expect(grepTool.validateToolParams(params)).toContain('nonexistent');
|
|
247
|
+
});
|
|
248
|
+
it('should allow path to be a file', async () => {
|
|
249
|
+
const filePath = path.join(tempRootDir, 'fileA.txt');
|
|
250
|
+
const params = {
|
|
251
|
+
pattern: 'hello',
|
|
252
|
+
dir_path: filePath,
|
|
253
|
+
};
|
|
254
|
+
expect(grepTool.validateToolParams(params)).toBeNull();
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
describe('execute', () => {
|
|
258
|
+
it('should find matches for a simple pattern in all files', async () => {
|
|
259
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
260
|
+
outputData: JSON.stringify({
|
|
261
|
+
type: 'match',
|
|
262
|
+
data: {
|
|
263
|
+
path: { text: 'fileA.txt' },
|
|
264
|
+
line_number: 1,
|
|
265
|
+
lines: { text: 'hello world\n' },
|
|
266
|
+
},
|
|
267
|
+
}) +
|
|
268
|
+
'\n' +
|
|
269
|
+
JSON.stringify({
|
|
270
|
+
type: 'match',
|
|
271
|
+
data: {
|
|
272
|
+
path: { text: 'fileA.txt' },
|
|
273
|
+
line_number: 2,
|
|
274
|
+
lines: { text: 'second line with world\n' },
|
|
275
|
+
},
|
|
276
|
+
}) +
|
|
277
|
+
'\n' +
|
|
278
|
+
JSON.stringify({
|
|
279
|
+
type: 'match',
|
|
280
|
+
data: {
|
|
281
|
+
path: { text: 'sub/fileC.txt' },
|
|
282
|
+
line_number: 1,
|
|
283
|
+
lines: { text: 'another world in sub dir\n' },
|
|
284
|
+
},
|
|
285
|
+
}) +
|
|
286
|
+
'\n',
|
|
287
|
+
exitCode: 0,
|
|
288
|
+
}));
|
|
289
|
+
const params = { pattern: 'world' };
|
|
290
|
+
const invocation = grepTool.build(params);
|
|
291
|
+
const result = await invocation.execute(abortSignal);
|
|
292
|
+
expect(result.llmContent).toContain('Found 3 matches for pattern "world" in path "."');
|
|
293
|
+
expect(result.llmContent).toContain('File: fileA.txt');
|
|
294
|
+
expect(result.llmContent).toContain('L1: hello world');
|
|
295
|
+
expect(result.llmContent).toContain('L2: second line with world');
|
|
296
|
+
expect(result.llmContent).toContain(`File: ${path.join('sub', 'fileC.txt')}`);
|
|
297
|
+
expect(result.llmContent).toContain('L1: another world in sub dir');
|
|
298
|
+
expect(result.returnDisplay).toBe('Found 3 matches');
|
|
299
|
+
});
|
|
300
|
+
it('should find matches in a specific path', async () => {
|
|
301
|
+
// Setup specific mock for this test - searching in 'sub' should only return matches from that directory
|
|
302
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
303
|
+
outputData: JSON.stringify({
|
|
304
|
+
type: 'match',
|
|
305
|
+
data: {
|
|
306
|
+
path: { text: 'fileC.txt' },
|
|
307
|
+
line_number: 1,
|
|
308
|
+
lines: { text: 'another world in sub dir\n' },
|
|
309
|
+
},
|
|
310
|
+
}) + '\n',
|
|
311
|
+
exitCode: 0,
|
|
312
|
+
}));
|
|
313
|
+
const params = { pattern: 'world', dir_path: 'sub' };
|
|
314
|
+
const invocation = grepTool.build(params);
|
|
315
|
+
const result = await invocation.execute(abortSignal);
|
|
316
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "world" in path "sub"');
|
|
317
|
+
expect(result.llmContent).toContain('File: fileC.txt'); // Path relative to 'sub'
|
|
318
|
+
expect(result.llmContent).toContain('L1: another world in sub dir');
|
|
319
|
+
expect(result.returnDisplay).toBe('Found 1 match');
|
|
320
|
+
});
|
|
321
|
+
it('should find matches with an include glob', async () => {
|
|
322
|
+
// Setup specific mock for this test
|
|
323
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
324
|
+
outputData: JSON.stringify({
|
|
325
|
+
type: 'match',
|
|
326
|
+
data: {
|
|
327
|
+
path: { text: 'fileB.js' },
|
|
328
|
+
line_number: 2,
|
|
329
|
+
lines: { text: 'function baz() { return "hello"; }\n' },
|
|
330
|
+
},
|
|
331
|
+
}) + '\n',
|
|
332
|
+
exitCode: 0,
|
|
333
|
+
}));
|
|
334
|
+
const params = { pattern: 'hello', include: '*.js' };
|
|
335
|
+
const invocation = grepTool.build(params);
|
|
336
|
+
const result = await invocation.execute(abortSignal);
|
|
337
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "hello" in path "." (filter: "*.js"):');
|
|
338
|
+
expect(result.llmContent).toContain('File: fileB.js');
|
|
339
|
+
expect(result.llmContent).toContain('L2: function baz() { return "hello"; }');
|
|
340
|
+
expect(result.returnDisplay).toBe('Found 1 match');
|
|
341
|
+
});
|
|
342
|
+
it('should find matches with an include glob and path', async () => {
|
|
343
|
+
await fs.writeFile(path.join(tempRootDir, 'sub', 'another.js'), 'const greeting = "hello";');
|
|
344
|
+
// Setup specific mock for this test - searching for 'hello' in 'sub' with '*.js' filter
|
|
345
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
346
|
+
const mockProcess = {
|
|
347
|
+
stdout: {
|
|
348
|
+
on: vi.fn(),
|
|
349
|
+
removeListener: vi.fn(),
|
|
350
|
+
},
|
|
351
|
+
stderr: {
|
|
352
|
+
on: vi.fn(),
|
|
353
|
+
removeListener: vi.fn(),
|
|
354
|
+
},
|
|
355
|
+
on: vi.fn(),
|
|
356
|
+
removeListener: vi.fn(),
|
|
357
|
+
kill: vi.fn(),
|
|
358
|
+
};
|
|
359
|
+
setTimeout(() => {
|
|
360
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
361
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
362
|
+
if (onData) {
|
|
363
|
+
// Only return match from the .js file in sub directory
|
|
364
|
+
onData(Buffer.from(JSON.stringify({
|
|
365
|
+
type: 'match',
|
|
366
|
+
data: {
|
|
367
|
+
path: { text: 'another.js' },
|
|
368
|
+
line_number: 1,
|
|
369
|
+
lines: { text: 'const greeting = "hello";\n' },
|
|
370
|
+
},
|
|
371
|
+
}) + '\n'));
|
|
372
|
+
}
|
|
373
|
+
if (onClose) {
|
|
374
|
+
onClose(0);
|
|
375
|
+
}
|
|
376
|
+
}, 0);
|
|
377
|
+
return mockProcess;
|
|
378
|
+
});
|
|
379
|
+
const params = {
|
|
380
|
+
pattern: 'hello',
|
|
381
|
+
dir_path: 'sub',
|
|
382
|
+
include: '*.js',
|
|
383
|
+
};
|
|
384
|
+
const invocation = grepTool.build(params);
|
|
385
|
+
const result = await invocation.execute(abortSignal);
|
|
386
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "hello" in path "sub" (filter: "*.js")');
|
|
387
|
+
expect(result.llmContent).toContain('File: another.js');
|
|
388
|
+
expect(result.llmContent).toContain('L1: const greeting = "hello";');
|
|
389
|
+
expect(result.returnDisplay).toBe('Found 1 match');
|
|
390
|
+
});
|
|
391
|
+
it('should return "No matches found" when pattern does not exist', async () => {
|
|
392
|
+
// Setup specific mock for no matches
|
|
393
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
394
|
+
exitCode: 1, // No matches found
|
|
395
|
+
}));
|
|
396
|
+
const params = { pattern: 'nonexistentpattern' };
|
|
397
|
+
const invocation = grepTool.build(params);
|
|
398
|
+
const result = await invocation.execute(abortSignal);
|
|
399
|
+
expect(result.llmContent).toContain('No matches found for pattern "nonexistentpattern" in path ".".');
|
|
400
|
+
expect(result.returnDisplay).toBe('No matches found');
|
|
401
|
+
});
|
|
402
|
+
it('should return an error from ripgrep for invalid regex pattern', async () => {
|
|
403
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
404
|
+
exitCode: 2,
|
|
405
|
+
}));
|
|
406
|
+
const params = { pattern: '[[' };
|
|
407
|
+
const invocation = grepTool.build(params);
|
|
408
|
+
const result = await invocation.execute(abortSignal);
|
|
409
|
+
expect(result.llmContent).toContain('ripgrep exited with code 2');
|
|
410
|
+
expect(result.returnDisplay).toContain('Error: ripgrep exited with code 2');
|
|
411
|
+
});
|
|
412
|
+
it('should handle regex special characters correctly', async () => {
|
|
413
|
+
// Setup specific mock for this test - regex pattern 'foo.*bar' should match 'const foo = "bar";'
|
|
414
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
415
|
+
const mockProcess = {
|
|
416
|
+
stdout: {
|
|
417
|
+
on: vi.fn(),
|
|
418
|
+
removeListener: vi.fn(),
|
|
419
|
+
},
|
|
420
|
+
stderr: {
|
|
421
|
+
on: vi.fn(),
|
|
422
|
+
removeListener: vi.fn(),
|
|
423
|
+
},
|
|
424
|
+
on: vi.fn(),
|
|
425
|
+
removeListener: vi.fn(),
|
|
426
|
+
kill: vi.fn(),
|
|
427
|
+
};
|
|
428
|
+
setTimeout(() => {
|
|
429
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
430
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
431
|
+
if (onData) {
|
|
432
|
+
// Return match for the regex pattern
|
|
433
|
+
onData(Buffer.from(JSON.stringify({
|
|
434
|
+
type: 'match',
|
|
435
|
+
data: {
|
|
436
|
+
path: { text: 'fileB.js' },
|
|
437
|
+
line_number: 1,
|
|
438
|
+
lines: { text: 'const foo = "bar";\n' },
|
|
439
|
+
},
|
|
440
|
+
}) + '\n'));
|
|
441
|
+
}
|
|
442
|
+
if (onClose) {
|
|
443
|
+
onClose(0);
|
|
444
|
+
}
|
|
445
|
+
}, 0);
|
|
446
|
+
return mockProcess;
|
|
447
|
+
});
|
|
448
|
+
const params = { pattern: 'foo.*bar' }; // Matches 'const foo = "bar";'
|
|
449
|
+
const invocation = grepTool.build(params);
|
|
450
|
+
const result = await invocation.execute(abortSignal);
|
|
451
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "foo.*bar" in path ".":');
|
|
452
|
+
expect(result.llmContent).toContain('File: fileB.js');
|
|
453
|
+
expect(result.llmContent).toContain('L1: const foo = "bar";');
|
|
454
|
+
});
|
|
455
|
+
it('should be case-insensitive by default (JS fallback)', async () => {
|
|
456
|
+
// Setup specific mock for this test - case insensitive search for 'HELLO'
|
|
457
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
458
|
+
const mockProcess = {
|
|
459
|
+
stdout: {
|
|
460
|
+
on: vi.fn(),
|
|
461
|
+
removeListener: vi.fn(),
|
|
462
|
+
},
|
|
463
|
+
stderr: {
|
|
464
|
+
on: vi.fn(),
|
|
465
|
+
removeListener: vi.fn(),
|
|
466
|
+
},
|
|
467
|
+
on: vi.fn(),
|
|
468
|
+
removeListener: vi.fn(),
|
|
469
|
+
kill: vi.fn(),
|
|
470
|
+
};
|
|
471
|
+
setTimeout(() => {
|
|
472
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
473
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
474
|
+
if (onData) {
|
|
475
|
+
// Return case-insensitive matches for 'HELLO'
|
|
476
|
+
onData(Buffer.from(JSON.stringify({
|
|
477
|
+
type: 'match',
|
|
478
|
+
data: {
|
|
479
|
+
path: { text: 'fileA.txt' },
|
|
480
|
+
line_number: 1,
|
|
481
|
+
lines: { text: 'hello world\n' },
|
|
482
|
+
},
|
|
483
|
+
}) +
|
|
484
|
+
'\n' +
|
|
485
|
+
JSON.stringify({
|
|
486
|
+
type: 'match',
|
|
487
|
+
data: {
|
|
488
|
+
path: { text: 'fileB.js' },
|
|
489
|
+
line_number: 2,
|
|
490
|
+
lines: { text: 'function baz() { return "hello"; }\n' },
|
|
491
|
+
},
|
|
492
|
+
}) +
|
|
493
|
+
'\n'));
|
|
494
|
+
}
|
|
495
|
+
if (onClose) {
|
|
496
|
+
onClose(0);
|
|
497
|
+
}
|
|
498
|
+
}, 0);
|
|
499
|
+
return mockProcess;
|
|
500
|
+
});
|
|
501
|
+
const params = { pattern: 'HELLO' };
|
|
502
|
+
const invocation = grepTool.build(params);
|
|
503
|
+
const result = await invocation.execute(abortSignal);
|
|
504
|
+
expect(result.llmContent).toContain('Found 2 matches for pattern "HELLO" in path ".":');
|
|
505
|
+
expect(result.llmContent).toContain('File: fileA.txt');
|
|
506
|
+
expect(result.llmContent).toContain('L1: hello world');
|
|
507
|
+
expect(result.llmContent).toContain('File: fileB.js');
|
|
508
|
+
expect(result.llmContent).toContain('L2: function baz() { return "hello"; }');
|
|
509
|
+
});
|
|
510
|
+
it('should throw an error if params are invalid', async () => {
|
|
511
|
+
const params = { dir_path: '.' }; // Invalid: pattern missing
|
|
512
|
+
expect(() => grepTool.build(params)).toThrow(/params must have required property 'pattern'/);
|
|
513
|
+
});
|
|
514
|
+
it('should throw an error if ripgrep is not available', async () => {
|
|
515
|
+
await fs.rm(ripgrepBinaryPath, { force: true });
|
|
516
|
+
downloadRipGrepMock.mockResolvedValue(undefined);
|
|
517
|
+
const params = { pattern: 'world' };
|
|
518
|
+
const invocation = grepTool.build(params);
|
|
519
|
+
expect(await invocation.execute(abortSignal)).toStrictEqual({
|
|
520
|
+
llmContent: 'Error during grep search operation: Cannot use ripgrep.',
|
|
521
|
+
returnDisplay: 'Error: Cannot use ripgrep.',
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
describe('multi-directory workspace', () => {
|
|
526
|
+
it('should search only CWD when no path is specified (default behavior)', async () => {
|
|
527
|
+
// Create additional directory with test files
|
|
528
|
+
const secondDir = await fs.mkdtemp(path.join(os.tmpdir(), 'grep-tool-second-'));
|
|
529
|
+
await fs.writeFile(path.join(secondDir, 'other.txt'), 'hello from second directory\nworld in second');
|
|
530
|
+
await fs.writeFile(path.join(secondDir, 'another.js'), 'function world() { return "test"; }');
|
|
531
|
+
// Create a mock config with multiple directories
|
|
532
|
+
const multiDirConfig = {
|
|
533
|
+
getTargetDir: () => tempRootDir,
|
|
534
|
+
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir, [secondDir]),
|
|
535
|
+
getDebugMode: () => false,
|
|
536
|
+
};
|
|
537
|
+
// Setup specific mock for this test - multi-directory search for 'world'
|
|
538
|
+
// Mock will be called twice - once for each directory
|
|
539
|
+
let callCount = 0;
|
|
540
|
+
mockSpawn.mockImplementation(() => {
|
|
541
|
+
callCount++;
|
|
542
|
+
const mockProcess = {
|
|
543
|
+
stdout: {
|
|
544
|
+
on: vi.fn(),
|
|
545
|
+
removeListener: vi.fn(),
|
|
546
|
+
},
|
|
547
|
+
stderr: {
|
|
548
|
+
on: vi.fn(),
|
|
549
|
+
removeListener: vi.fn(),
|
|
550
|
+
},
|
|
551
|
+
on: vi.fn(),
|
|
552
|
+
removeListener: vi.fn(),
|
|
553
|
+
kill: vi.fn(),
|
|
554
|
+
};
|
|
555
|
+
setTimeout(() => {
|
|
556
|
+
const stdoutDataHandler = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
557
|
+
const closeHandler = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
558
|
+
let outputData = '';
|
|
559
|
+
if (callCount === 1) {
|
|
560
|
+
// First directory (tempRootDir)
|
|
561
|
+
outputData =
|
|
562
|
+
JSON.stringify({
|
|
563
|
+
type: 'match',
|
|
564
|
+
data: {
|
|
565
|
+
path: { text: 'fileA.txt' },
|
|
566
|
+
line_number: 1,
|
|
567
|
+
lines: { text: 'hello world\n' },
|
|
568
|
+
},
|
|
569
|
+
}) +
|
|
570
|
+
'\n' +
|
|
571
|
+
JSON.stringify({
|
|
572
|
+
type: 'match',
|
|
573
|
+
data: {
|
|
574
|
+
path: { text: 'fileA.txt' },
|
|
575
|
+
line_number: 2,
|
|
576
|
+
lines: { text: 'second line with world\n' },
|
|
577
|
+
},
|
|
578
|
+
}) +
|
|
579
|
+
'\n' +
|
|
580
|
+
JSON.stringify({
|
|
581
|
+
type: 'match',
|
|
582
|
+
data: {
|
|
583
|
+
path: { text: 'sub/fileC.txt' },
|
|
584
|
+
line_number: 1,
|
|
585
|
+
lines: { text: 'another world in sub dir\n' },
|
|
586
|
+
},
|
|
587
|
+
}) +
|
|
588
|
+
'\n';
|
|
589
|
+
}
|
|
590
|
+
else if (callCount === 2) {
|
|
591
|
+
// Second directory (secondDir)
|
|
592
|
+
outputData =
|
|
593
|
+
JSON.stringify({
|
|
594
|
+
type: 'match',
|
|
595
|
+
data: {
|
|
596
|
+
path: { text: 'other.txt' },
|
|
597
|
+
line_number: 2,
|
|
598
|
+
lines: { text: 'world in second\n' },
|
|
599
|
+
},
|
|
600
|
+
}) +
|
|
601
|
+
'\n' +
|
|
602
|
+
JSON.stringify({
|
|
603
|
+
type: 'match',
|
|
604
|
+
data: {
|
|
605
|
+
path: { text: 'another.js' },
|
|
606
|
+
line_number: 1,
|
|
607
|
+
lines: { text: 'function world() { return "test"; }\n' },
|
|
608
|
+
},
|
|
609
|
+
}) +
|
|
610
|
+
'\n';
|
|
611
|
+
}
|
|
612
|
+
if (stdoutDataHandler && outputData) {
|
|
613
|
+
stdoutDataHandler(Buffer.from(outputData));
|
|
614
|
+
}
|
|
615
|
+
if (closeHandler) {
|
|
616
|
+
closeHandler(0);
|
|
617
|
+
}
|
|
618
|
+
}, 0);
|
|
619
|
+
return mockProcess;
|
|
620
|
+
});
|
|
621
|
+
const multiDirGrepTool = new RipGrepTool(multiDirConfig);
|
|
622
|
+
const params = { pattern: 'world' };
|
|
623
|
+
const invocation = multiDirGrepTool.build(params);
|
|
624
|
+
const result = await invocation.execute(abortSignal);
|
|
625
|
+
// Should find matches in CWD only (default behavior now)
|
|
626
|
+
expect(result.llmContent).toContain('Found 3 matches for pattern "world" in path "."');
|
|
627
|
+
// Matches from first directory
|
|
628
|
+
expect(result.llmContent).toContain('fileA.txt');
|
|
629
|
+
expect(result.llmContent).toContain('L1: hello world');
|
|
630
|
+
expect(result.llmContent).toContain('L2: second line with world');
|
|
631
|
+
expect(result.llmContent).toContain('fileC.txt');
|
|
632
|
+
expect(result.llmContent).toContain('L1: another world in sub dir');
|
|
633
|
+
// Should NOT find matches from second directory
|
|
634
|
+
expect(result.llmContent).not.toContain('other.txt');
|
|
635
|
+
expect(result.llmContent).not.toContain('world in second');
|
|
636
|
+
expect(result.llmContent).not.toContain('another.js');
|
|
637
|
+
expect(result.llmContent).not.toContain('function world()');
|
|
638
|
+
// Clean up
|
|
639
|
+
await fs.rm(secondDir, { recursive: true, force: true });
|
|
640
|
+
mockSpawn.mockClear();
|
|
641
|
+
});
|
|
642
|
+
it('should search only specified path within workspace directories', async () => {
|
|
643
|
+
// Create additional directory
|
|
644
|
+
const secondDir = await fs.mkdtemp(path.join(os.tmpdir(), 'grep-tool-second-'));
|
|
645
|
+
await fs.mkdir(path.join(secondDir, 'sub'));
|
|
646
|
+
await fs.writeFile(path.join(secondDir, 'sub', 'test.txt'), 'hello from second sub directory');
|
|
647
|
+
// Create a mock config with multiple directories
|
|
648
|
+
const multiDirConfig = {
|
|
649
|
+
getTargetDir: () => tempRootDir,
|
|
650
|
+
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir, [secondDir]),
|
|
651
|
+
getDebugMode: () => false,
|
|
652
|
+
};
|
|
653
|
+
// Setup specific mock for this test - searching in 'sub' should only return matches from that directory
|
|
654
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
655
|
+
const mockProcess = {
|
|
656
|
+
stdout: {
|
|
657
|
+
on: vi.fn(),
|
|
658
|
+
removeListener: vi.fn(),
|
|
659
|
+
},
|
|
660
|
+
stderr: {
|
|
661
|
+
on: vi.fn(),
|
|
662
|
+
removeListener: vi.fn(),
|
|
663
|
+
},
|
|
664
|
+
on: vi.fn(),
|
|
665
|
+
removeListener: vi.fn(),
|
|
666
|
+
kill: vi.fn(),
|
|
667
|
+
};
|
|
668
|
+
setTimeout(() => {
|
|
669
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
670
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
671
|
+
if (onData) {
|
|
672
|
+
onData(Buffer.from(JSON.stringify({
|
|
673
|
+
type: 'match',
|
|
674
|
+
data: {
|
|
675
|
+
path: { text: 'fileC.txt' },
|
|
676
|
+
line_number: 1,
|
|
677
|
+
lines: { text: 'another world in sub dir\n' },
|
|
678
|
+
},
|
|
679
|
+
}) + '\n'));
|
|
680
|
+
}
|
|
681
|
+
if (onClose) {
|
|
682
|
+
onClose(0);
|
|
683
|
+
}
|
|
684
|
+
}, 0);
|
|
685
|
+
return mockProcess;
|
|
686
|
+
});
|
|
687
|
+
const multiDirGrepTool = new RipGrepTool(multiDirConfig);
|
|
688
|
+
// Search only in the 'sub' directory of the first workspace
|
|
689
|
+
const params = { pattern: 'world', dir_path: 'sub' };
|
|
690
|
+
const invocation = multiDirGrepTool.build(params);
|
|
691
|
+
const result = await invocation.execute(abortSignal);
|
|
692
|
+
// Should only find matches in the specified sub directory
|
|
693
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "world" in path "sub"');
|
|
694
|
+
expect(result.llmContent).toContain('File: fileC.txt');
|
|
695
|
+
expect(result.llmContent).toContain('L1: another world in sub dir');
|
|
696
|
+
// Should not contain matches from second directory
|
|
697
|
+
expect(result.llmContent).not.toContain('test.txt');
|
|
698
|
+
// Clean up
|
|
699
|
+
await fs.rm(secondDir, { recursive: true, force: true });
|
|
700
|
+
});
|
|
701
|
+
});
|
|
702
|
+
describe('abort signal handling', () => {
|
|
703
|
+
it('should handle AbortSignal during search', async () => {
|
|
704
|
+
const controller = new AbortController();
|
|
705
|
+
const params = { pattern: 'world' };
|
|
706
|
+
const invocation = grepTool.build(params);
|
|
707
|
+
controller.abort();
|
|
708
|
+
const result = await invocation.execute(controller.signal);
|
|
709
|
+
expect(result).toBeDefined();
|
|
710
|
+
});
|
|
711
|
+
it('should abort streaming search when signal is triggered', async () => {
|
|
712
|
+
// Setup specific mock for this test - simulate process being killed due to abort
|
|
713
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
714
|
+
const mockProcess = {
|
|
715
|
+
stdout: {
|
|
716
|
+
on: vi.fn(),
|
|
717
|
+
removeListener: vi.fn(),
|
|
718
|
+
},
|
|
719
|
+
stderr: {
|
|
720
|
+
on: vi.fn(),
|
|
721
|
+
removeListener: vi.fn(),
|
|
722
|
+
},
|
|
723
|
+
on: vi.fn(),
|
|
724
|
+
removeListener: vi.fn(),
|
|
725
|
+
kill: vi.fn(),
|
|
726
|
+
};
|
|
727
|
+
// Simulate process being aborted - use setTimeout to ensure handlers are registered first
|
|
728
|
+
setTimeout(() => {
|
|
729
|
+
const closeHandler = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
730
|
+
if (closeHandler) {
|
|
731
|
+
// Simulate process killed by signal (code is null, signal is SIGTERM)
|
|
732
|
+
closeHandler(null, 'SIGTERM');
|
|
733
|
+
}
|
|
734
|
+
}, 0);
|
|
735
|
+
return mockProcess;
|
|
736
|
+
});
|
|
737
|
+
const controller = new AbortController();
|
|
738
|
+
const params = { pattern: 'test' };
|
|
739
|
+
const invocation = grepTool.build(params);
|
|
740
|
+
// Abort immediately before starting the search
|
|
741
|
+
controller.abort();
|
|
742
|
+
const result = await invocation.execute(controller.signal);
|
|
743
|
+
expect(result.llmContent).toContain('Error during grep search operation: ripgrep exited with code null');
|
|
744
|
+
expect(result.returnDisplay).toContain('Error: ripgrep exited with code null');
|
|
745
|
+
});
|
|
746
|
+
});
|
|
747
|
+
describe('error handling and edge cases', () => {
|
|
748
|
+
it('should handle workspace boundary violations', () => {
|
|
749
|
+
const params = {
|
|
750
|
+
pattern: 'test',
|
|
751
|
+
dir_path: '../outside',
|
|
752
|
+
};
|
|
753
|
+
expect(() => grepTool.build(params)).toThrow(/Path validation failed/);
|
|
754
|
+
});
|
|
755
|
+
it.each([
|
|
756
|
+
{
|
|
757
|
+
name: 'empty directories',
|
|
758
|
+
setup: async () => {
|
|
759
|
+
const emptyDir = path.join(tempRootDir, 'empty');
|
|
760
|
+
await fs.mkdir(emptyDir);
|
|
761
|
+
return { pattern: 'test', dir_path: 'empty' };
|
|
762
|
+
},
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
name: 'empty files',
|
|
766
|
+
setup: async () => {
|
|
767
|
+
await fs.writeFile(path.join(tempRootDir, 'empty.txt'), '');
|
|
768
|
+
return { pattern: 'anything' };
|
|
769
|
+
},
|
|
770
|
+
},
|
|
771
|
+
])('should handle $name gracefully', async ({ setup }) => {
|
|
772
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({ exitCode: 1 }));
|
|
773
|
+
const params = await setup();
|
|
774
|
+
const invocation = grepTool.build(params);
|
|
775
|
+
const result = await invocation.execute(abortSignal);
|
|
776
|
+
expect(result.llmContent).toContain('No matches found');
|
|
777
|
+
});
|
|
778
|
+
it('should handle special characters in file names', async () => {
|
|
779
|
+
const specialFileName = 'file with spaces & symbols!.txt';
|
|
780
|
+
await fs.writeFile(path.join(tempRootDir, specialFileName), 'hello world with special chars');
|
|
781
|
+
// Setup specific mock for this test - searching for 'world' should find the file with special characters
|
|
782
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
783
|
+
const mockProcess = {
|
|
784
|
+
stdout: {
|
|
785
|
+
on: vi.fn(),
|
|
786
|
+
removeListener: vi.fn(),
|
|
787
|
+
},
|
|
788
|
+
stderr: {
|
|
789
|
+
on: vi.fn(),
|
|
790
|
+
removeListener: vi.fn(),
|
|
791
|
+
},
|
|
792
|
+
on: vi.fn(),
|
|
793
|
+
removeListener: vi.fn(),
|
|
794
|
+
kill: vi.fn(),
|
|
795
|
+
};
|
|
796
|
+
setTimeout(() => {
|
|
797
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
798
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
799
|
+
if (onData) {
|
|
800
|
+
onData(Buffer.from(JSON.stringify({
|
|
801
|
+
type: 'match',
|
|
802
|
+
data: {
|
|
803
|
+
path: { text: specialFileName },
|
|
804
|
+
line_number: 1,
|
|
805
|
+
lines: { text: 'hello world with special chars\n' },
|
|
806
|
+
},
|
|
807
|
+
}) + '\n'));
|
|
808
|
+
}
|
|
809
|
+
if (onClose) {
|
|
810
|
+
onClose(0);
|
|
811
|
+
}
|
|
812
|
+
}, 0);
|
|
813
|
+
return mockProcess;
|
|
814
|
+
});
|
|
815
|
+
const params = { pattern: 'world' };
|
|
816
|
+
const invocation = grepTool.build(params);
|
|
817
|
+
const result = await invocation.execute(abortSignal);
|
|
818
|
+
expect(result.llmContent).toContain(specialFileName);
|
|
819
|
+
expect(result.llmContent).toContain('hello world with special chars');
|
|
820
|
+
});
|
|
821
|
+
it('should handle deeply nested directories', async () => {
|
|
822
|
+
const deepPath = path.join(tempRootDir, 'a', 'b', 'c', 'd', 'e');
|
|
823
|
+
await fs.mkdir(deepPath, { recursive: true });
|
|
824
|
+
await fs.writeFile(path.join(deepPath, 'deep.txt'), 'content in deep directory');
|
|
825
|
+
// Setup specific mock for this test - searching for 'deep' should find the deeply nested file
|
|
826
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
827
|
+
const mockProcess = {
|
|
828
|
+
stdout: {
|
|
829
|
+
on: vi.fn(),
|
|
830
|
+
removeListener: vi.fn(),
|
|
831
|
+
},
|
|
832
|
+
stderr: {
|
|
833
|
+
on: vi.fn(),
|
|
834
|
+
removeListener: vi.fn(),
|
|
835
|
+
},
|
|
836
|
+
on: vi.fn(),
|
|
837
|
+
removeListener: vi.fn(),
|
|
838
|
+
kill: vi.fn(),
|
|
839
|
+
};
|
|
840
|
+
setTimeout(() => {
|
|
841
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
842
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
843
|
+
if (onData) {
|
|
844
|
+
onData(Buffer.from(JSON.stringify({
|
|
845
|
+
type: 'match',
|
|
846
|
+
data: {
|
|
847
|
+
path: { text: 'a/b/c/d/e/deep.txt' },
|
|
848
|
+
line_number: 1,
|
|
849
|
+
lines: { text: 'content in deep directory\n' },
|
|
850
|
+
},
|
|
851
|
+
}) + '\n'));
|
|
852
|
+
}
|
|
853
|
+
if (onClose) {
|
|
854
|
+
onClose(0);
|
|
855
|
+
}
|
|
856
|
+
}, 0);
|
|
857
|
+
return mockProcess;
|
|
858
|
+
});
|
|
859
|
+
const params = { pattern: 'deep' };
|
|
860
|
+
const invocation = grepTool.build(params);
|
|
861
|
+
const result = await invocation.execute(abortSignal);
|
|
862
|
+
expect(result.llmContent).toContain('deep.txt');
|
|
863
|
+
expect(result.llmContent).toContain('content in deep directory');
|
|
864
|
+
});
|
|
865
|
+
});
|
|
866
|
+
describe('regex pattern validation', () => {
|
|
867
|
+
it('should handle complex regex patterns', async () => {
|
|
868
|
+
await fs.writeFile(path.join(tempRootDir, 'code.js'), 'function getName() { return "test"; }\nconst getValue = () => "value";');
|
|
869
|
+
// Setup specific mock for this test - regex pattern should match function declarations
|
|
870
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
871
|
+
const mockProcess = {
|
|
872
|
+
stdout: {
|
|
873
|
+
on: vi.fn(),
|
|
874
|
+
removeListener: vi.fn(),
|
|
875
|
+
},
|
|
876
|
+
stderr: {
|
|
877
|
+
on: vi.fn(),
|
|
878
|
+
removeListener: vi.fn(),
|
|
879
|
+
},
|
|
880
|
+
on: vi.fn(),
|
|
881
|
+
removeListener: vi.fn(),
|
|
882
|
+
kill: vi.fn(),
|
|
883
|
+
};
|
|
884
|
+
setTimeout(() => {
|
|
885
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
886
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
887
|
+
if (onData) {
|
|
888
|
+
onData(Buffer.from(JSON.stringify({
|
|
889
|
+
type: 'match',
|
|
890
|
+
data: {
|
|
891
|
+
path: { text: 'code.js' },
|
|
892
|
+
line_number: 1,
|
|
893
|
+
lines: { text: 'function getName() { return "test"; }\n' },
|
|
894
|
+
},
|
|
895
|
+
}) + '\n'));
|
|
896
|
+
}
|
|
897
|
+
if (onClose) {
|
|
898
|
+
onClose(0);
|
|
899
|
+
}
|
|
900
|
+
}, 0);
|
|
901
|
+
return mockProcess;
|
|
902
|
+
});
|
|
903
|
+
const params = { pattern: 'function\\s+\\w+\\s*\\(' };
|
|
904
|
+
const invocation = grepTool.build(params);
|
|
905
|
+
const result = await invocation.execute(abortSignal);
|
|
906
|
+
expect(result.llmContent).toContain('function getName()');
|
|
907
|
+
expect(result.llmContent).not.toContain('const getValue');
|
|
908
|
+
});
|
|
909
|
+
it('should handle case sensitivity correctly in JS fallback', async () => {
|
|
910
|
+
await fs.writeFile(path.join(tempRootDir, 'case.txt'), 'Hello World\nhello world\nHELLO WORLD');
|
|
911
|
+
// Setup specific mock for this test - case insensitive search should match all variants
|
|
912
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
913
|
+
const mockProcess = {
|
|
914
|
+
stdout: {
|
|
915
|
+
on: vi.fn(),
|
|
916
|
+
removeListener: vi.fn(),
|
|
917
|
+
},
|
|
918
|
+
stderr: {
|
|
919
|
+
on: vi.fn(),
|
|
920
|
+
removeListener: vi.fn(),
|
|
921
|
+
},
|
|
922
|
+
on: vi.fn(),
|
|
923
|
+
removeListener: vi.fn(),
|
|
924
|
+
kill: vi.fn(),
|
|
925
|
+
};
|
|
926
|
+
setTimeout(() => {
|
|
927
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
928
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
929
|
+
if (onData) {
|
|
930
|
+
onData(Buffer.from(JSON.stringify({
|
|
931
|
+
type: 'match',
|
|
932
|
+
data: {
|
|
933
|
+
path: { text: 'case.txt' },
|
|
934
|
+
line_number: 1,
|
|
935
|
+
lines: { text: 'Hello World\n' },
|
|
936
|
+
},
|
|
937
|
+
}) +
|
|
938
|
+
'\n' +
|
|
939
|
+
JSON.stringify({
|
|
940
|
+
type: 'match',
|
|
941
|
+
data: {
|
|
942
|
+
path: { text: 'case.txt' },
|
|
943
|
+
line_number: 2,
|
|
944
|
+
lines: { text: 'hello world\n' },
|
|
945
|
+
},
|
|
946
|
+
}) +
|
|
947
|
+
'\n' +
|
|
948
|
+
JSON.stringify({
|
|
949
|
+
type: 'match',
|
|
950
|
+
data: {
|
|
951
|
+
path: { text: 'case.txt' },
|
|
952
|
+
line_number: 3,
|
|
953
|
+
lines: { text: 'HELLO WORLD\n' },
|
|
954
|
+
},
|
|
955
|
+
}) +
|
|
956
|
+
'\n'));
|
|
957
|
+
}
|
|
958
|
+
if (onClose) {
|
|
959
|
+
onClose(0);
|
|
960
|
+
}
|
|
961
|
+
}, 0);
|
|
962
|
+
return mockProcess;
|
|
963
|
+
});
|
|
964
|
+
const params = { pattern: 'hello' };
|
|
965
|
+
const invocation = grepTool.build(params);
|
|
966
|
+
const result = await invocation.execute(abortSignal);
|
|
967
|
+
expect(result.llmContent).toContain('Hello World');
|
|
968
|
+
expect(result.llmContent).toContain('hello world');
|
|
969
|
+
expect(result.llmContent).toContain('HELLO WORLD');
|
|
970
|
+
});
|
|
971
|
+
it('should handle escaped regex special characters', async () => {
|
|
972
|
+
await fs.writeFile(path.join(tempRootDir, 'special.txt'), 'Price: $19.99\nRegex: [a-z]+ pattern\nEmail: test@example.com');
|
|
973
|
+
// Setup specific mock for this test - escaped regex pattern should match price format
|
|
974
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
975
|
+
const mockProcess = {
|
|
976
|
+
stdout: {
|
|
977
|
+
on: vi.fn(),
|
|
978
|
+
removeListener: vi.fn(),
|
|
979
|
+
},
|
|
980
|
+
stderr: {
|
|
981
|
+
on: vi.fn(),
|
|
982
|
+
removeListener: vi.fn(),
|
|
983
|
+
},
|
|
984
|
+
on: vi.fn(),
|
|
985
|
+
removeListener: vi.fn(),
|
|
986
|
+
kill: vi.fn(),
|
|
987
|
+
};
|
|
988
|
+
setTimeout(() => {
|
|
989
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
990
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
991
|
+
if (onData) {
|
|
992
|
+
onData(Buffer.from(JSON.stringify({
|
|
993
|
+
type: 'match',
|
|
994
|
+
data: {
|
|
995
|
+
path: { text: 'special.txt' },
|
|
996
|
+
line_number: 1,
|
|
997
|
+
lines: { text: 'Price: $19.99\n' },
|
|
998
|
+
},
|
|
999
|
+
}) + '\n'));
|
|
1000
|
+
}
|
|
1001
|
+
if (onClose) {
|
|
1002
|
+
onClose(0);
|
|
1003
|
+
}
|
|
1004
|
+
}, 0);
|
|
1005
|
+
return mockProcess;
|
|
1006
|
+
});
|
|
1007
|
+
const params = { pattern: '\\$\\d+\\.\\d+' };
|
|
1008
|
+
const invocation = grepTool.build(params);
|
|
1009
|
+
const result = await invocation.execute(abortSignal);
|
|
1010
|
+
expect(result.llmContent).toContain('Price: $19.99');
|
|
1011
|
+
expect(result.llmContent).not.toContain('Email: test@example.com');
|
|
1012
|
+
});
|
|
1013
|
+
});
|
|
1014
|
+
describe('include pattern filtering', () => {
|
|
1015
|
+
it('should handle multiple file extensions in include pattern', async () => {
|
|
1016
|
+
await fs.writeFile(path.join(tempRootDir, 'test.ts'), 'typescript content');
|
|
1017
|
+
await fs.writeFile(path.join(tempRootDir, 'test.tsx'), 'tsx content');
|
|
1018
|
+
await fs.writeFile(path.join(tempRootDir, 'test.js'), 'javascript content');
|
|
1019
|
+
await fs.writeFile(path.join(tempRootDir, 'test.txt'), 'text content');
|
|
1020
|
+
// Setup specific mock for this test - include pattern should filter to only ts/tsx files
|
|
1021
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
1022
|
+
const mockProcess = {
|
|
1023
|
+
stdout: {
|
|
1024
|
+
on: vi.fn(),
|
|
1025
|
+
removeListener: vi.fn(),
|
|
1026
|
+
},
|
|
1027
|
+
stderr: {
|
|
1028
|
+
on: vi.fn(),
|
|
1029
|
+
removeListener: vi.fn(),
|
|
1030
|
+
},
|
|
1031
|
+
on: vi.fn(),
|
|
1032
|
+
removeListener: vi.fn(),
|
|
1033
|
+
kill: vi.fn(),
|
|
1034
|
+
};
|
|
1035
|
+
setTimeout(() => {
|
|
1036
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
1037
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
1038
|
+
if (onData) {
|
|
1039
|
+
onData(Buffer.from(JSON.stringify({
|
|
1040
|
+
type: 'match',
|
|
1041
|
+
data: {
|
|
1042
|
+
path: { text: 'test.ts' },
|
|
1043
|
+
line_number: 1,
|
|
1044
|
+
lines: { text: 'typescript content\n' },
|
|
1045
|
+
},
|
|
1046
|
+
}) +
|
|
1047
|
+
'\n' +
|
|
1048
|
+
JSON.stringify({
|
|
1049
|
+
type: 'match',
|
|
1050
|
+
data: {
|
|
1051
|
+
path: { text: 'test.tsx' },
|
|
1052
|
+
line_number: 1,
|
|
1053
|
+
lines: { text: 'tsx content\n' },
|
|
1054
|
+
},
|
|
1055
|
+
}) +
|
|
1056
|
+
'\n'));
|
|
1057
|
+
}
|
|
1058
|
+
if (onClose) {
|
|
1059
|
+
onClose(0);
|
|
1060
|
+
}
|
|
1061
|
+
}, 0);
|
|
1062
|
+
return mockProcess;
|
|
1063
|
+
});
|
|
1064
|
+
const params = {
|
|
1065
|
+
pattern: 'content',
|
|
1066
|
+
include: '*.{ts,tsx}',
|
|
1067
|
+
};
|
|
1068
|
+
const invocation = grepTool.build(params);
|
|
1069
|
+
const result = await invocation.execute(abortSignal);
|
|
1070
|
+
expect(result.llmContent).toContain('test.ts');
|
|
1071
|
+
expect(result.llmContent).toContain('test.tsx');
|
|
1072
|
+
expect(result.llmContent).not.toContain('test.js');
|
|
1073
|
+
expect(result.llmContent).not.toContain('test.txt');
|
|
1074
|
+
});
|
|
1075
|
+
it('should handle directory patterns in include', async () => {
|
|
1076
|
+
await fs.mkdir(path.join(tempRootDir, 'src'), { recursive: true });
|
|
1077
|
+
await fs.writeFile(path.join(tempRootDir, 'src', 'main.ts'), 'source code');
|
|
1078
|
+
await fs.writeFile(path.join(tempRootDir, 'other.ts'), 'other code');
|
|
1079
|
+
// Setup specific mock for this test - include pattern should filter to only src/** files
|
|
1080
|
+
mockSpawn.mockImplementationOnce(() => {
|
|
1081
|
+
const mockProcess = {
|
|
1082
|
+
stdout: {
|
|
1083
|
+
on: vi.fn(),
|
|
1084
|
+
removeListener: vi.fn(),
|
|
1085
|
+
},
|
|
1086
|
+
stderr: {
|
|
1087
|
+
on: vi.fn(),
|
|
1088
|
+
removeListener: vi.fn(),
|
|
1089
|
+
},
|
|
1090
|
+
on: vi.fn(),
|
|
1091
|
+
removeListener: vi.fn(),
|
|
1092
|
+
kill: vi.fn(),
|
|
1093
|
+
};
|
|
1094
|
+
setTimeout(() => {
|
|
1095
|
+
const onData = mockProcess.stdout.on.mock.calls.find((call) => call[0] === 'data')?.[1];
|
|
1096
|
+
const onClose = mockProcess.on.mock.calls.find((call) => call[0] === 'close')?.[1];
|
|
1097
|
+
if (onData) {
|
|
1098
|
+
onData(Buffer.from(JSON.stringify({
|
|
1099
|
+
type: 'match',
|
|
1100
|
+
data: {
|
|
1101
|
+
path: { text: 'src/main.ts' },
|
|
1102
|
+
line_number: 1,
|
|
1103
|
+
lines: { text: 'source code\n' },
|
|
1104
|
+
},
|
|
1105
|
+
}) + '\n'));
|
|
1106
|
+
}
|
|
1107
|
+
if (onClose) {
|
|
1108
|
+
onClose(0);
|
|
1109
|
+
}
|
|
1110
|
+
}, 0);
|
|
1111
|
+
return mockProcess;
|
|
1112
|
+
});
|
|
1113
|
+
const params = {
|
|
1114
|
+
pattern: 'code',
|
|
1115
|
+
include: 'src/**',
|
|
1116
|
+
};
|
|
1117
|
+
const invocation = grepTool.build(params);
|
|
1118
|
+
const result = await invocation.execute(abortSignal);
|
|
1119
|
+
expect(result.llmContent).toContain('main.ts');
|
|
1120
|
+
expect(result.llmContent).not.toContain('other.ts');
|
|
1121
|
+
});
|
|
1122
|
+
});
|
|
1123
|
+
describe('advanced search options', () => {
|
|
1124
|
+
it('should handle case_sensitive parameter', async () => {
|
|
1125
|
+
// Case-insensitive search (default)
|
|
1126
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
1127
|
+
outputData: JSON.stringify({
|
|
1128
|
+
type: 'match',
|
|
1129
|
+
data: {
|
|
1130
|
+
path: { text: 'fileA.txt' },
|
|
1131
|
+
line_number: 1,
|
|
1132
|
+
lines: { text: 'hello world\n' },
|
|
1133
|
+
},
|
|
1134
|
+
}) + '\n',
|
|
1135
|
+
exitCode: 0,
|
|
1136
|
+
}));
|
|
1137
|
+
let params = { pattern: 'HELLO' };
|
|
1138
|
+
let invocation = grepTool.build(params);
|
|
1139
|
+
let result = await invocation.execute(abortSignal);
|
|
1140
|
+
expect(mockSpawn).toHaveBeenLastCalledWith(expect.anything(), expect.arrayContaining(['--ignore-case']), expect.anything());
|
|
1141
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "HELLO"');
|
|
1142
|
+
expect(result.llmContent).toContain('L1: hello world');
|
|
1143
|
+
// Case-sensitive search
|
|
1144
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
1145
|
+
outputData: JSON.stringify({
|
|
1146
|
+
type: 'match',
|
|
1147
|
+
data: {
|
|
1148
|
+
path: { text: 'fileA.txt' },
|
|
1149
|
+
line_number: 1,
|
|
1150
|
+
lines: { text: 'HELLO world\n' },
|
|
1151
|
+
},
|
|
1152
|
+
}) + '\n',
|
|
1153
|
+
exitCode: 0,
|
|
1154
|
+
}));
|
|
1155
|
+
params = { pattern: 'HELLO', case_sensitive: true };
|
|
1156
|
+
invocation = grepTool.build(params);
|
|
1157
|
+
result = await invocation.execute(abortSignal);
|
|
1158
|
+
expect(mockSpawn).toHaveBeenLastCalledWith(expect.anything(), expect.not.arrayContaining(['--ignore-case']), expect.anything());
|
|
1159
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "HELLO"');
|
|
1160
|
+
expect(result.llmContent).toContain('L1: HELLO world');
|
|
1161
|
+
});
|
|
1162
|
+
it.each([
|
|
1163
|
+
{
|
|
1164
|
+
name: 'fixed_strings parameter',
|
|
1165
|
+
params: { pattern: 'hello.world', fixed_strings: true },
|
|
1166
|
+
mockOutput: {
|
|
1167
|
+
path: { text: 'fileA.txt' },
|
|
1168
|
+
line_number: 1,
|
|
1169
|
+
lines: { text: 'hello.world\n' },
|
|
1170
|
+
},
|
|
1171
|
+
expectedArgs: ['--fixed-strings'],
|
|
1172
|
+
expectedPattern: 'hello.world',
|
|
1173
|
+
},
|
|
1174
|
+
])('should handle $name', async ({ params, mockOutput, expectedArgs, expectedPattern }) => {
|
|
1175
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
1176
|
+
outputData: JSON.stringify({ type: 'match', data: mockOutput }) + '\n',
|
|
1177
|
+
exitCode: 0,
|
|
1178
|
+
}));
|
|
1179
|
+
const invocation = grepTool.build(params);
|
|
1180
|
+
const result = await invocation.execute(abortSignal);
|
|
1181
|
+
expect(mockSpawn).toHaveBeenLastCalledWith(expect.anything(), expect.arrayContaining(expectedArgs), expect.anything());
|
|
1182
|
+
expect(result.llmContent).toContain(`Found 1 match for pattern "${expectedPattern}"`);
|
|
1183
|
+
});
|
|
1184
|
+
it('should handle no_ignore parameter', async () => {
|
|
1185
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
1186
|
+
outputData: JSON.stringify({
|
|
1187
|
+
type: 'match',
|
|
1188
|
+
data: {
|
|
1189
|
+
path: { text: 'ignored.log' },
|
|
1190
|
+
line_number: 1,
|
|
1191
|
+
lines: { text: 'secret log entry\n' },
|
|
1192
|
+
},
|
|
1193
|
+
}) + '\n',
|
|
1194
|
+
exitCode: 0,
|
|
1195
|
+
}));
|
|
1196
|
+
const params = { pattern: 'secret', no_ignore: true };
|
|
1197
|
+
const invocation = grepTool.build(params);
|
|
1198
|
+
const result = await invocation.execute(abortSignal);
|
|
1199
|
+
expect(mockSpawn).toHaveBeenLastCalledWith(expect.anything(), expect.arrayContaining(['--no-ignore']), expect.anything());
|
|
1200
|
+
expect(mockSpawn).toHaveBeenLastCalledWith(expect.anything(), expect.not.arrayContaining(['--glob', '!node_modules']), expect.anything());
|
|
1201
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "secret"');
|
|
1202
|
+
expect(result.llmContent).toContain('File: ignored.log');
|
|
1203
|
+
expect(result.llmContent).toContain('L1: secret log entry');
|
|
1204
|
+
});
|
|
1205
|
+
it('should handle context parameters', async () => {
|
|
1206
|
+
mockSpawn.mockImplementationOnce(createMockSpawn({
|
|
1207
|
+
outputData: JSON.stringify({
|
|
1208
|
+
type: 'match',
|
|
1209
|
+
data: {
|
|
1210
|
+
path: { text: 'fileA.txt' },
|
|
1211
|
+
line_number: 2,
|
|
1212
|
+
lines: { text: 'second line with world\n' },
|
|
1213
|
+
lines_before: [{ text: 'hello world\n' }],
|
|
1214
|
+
lines_after: [
|
|
1215
|
+
{ text: 'third line\n' },
|
|
1216
|
+
{ text: 'fourth line\n' },
|
|
1217
|
+
],
|
|
1218
|
+
},
|
|
1219
|
+
}) + '\n',
|
|
1220
|
+
exitCode: 0,
|
|
1221
|
+
}));
|
|
1222
|
+
const params = {
|
|
1223
|
+
pattern: 'world',
|
|
1224
|
+
context: 1,
|
|
1225
|
+
after: 2,
|
|
1226
|
+
before: 1,
|
|
1227
|
+
};
|
|
1228
|
+
const invocation = grepTool.build(params);
|
|
1229
|
+
const result = await invocation.execute(abortSignal);
|
|
1230
|
+
expect(mockSpawn).toHaveBeenLastCalledWith(expect.anything(), expect.arrayContaining([
|
|
1231
|
+
'--context',
|
|
1232
|
+
'1',
|
|
1233
|
+
'--after-context',
|
|
1234
|
+
'2',
|
|
1235
|
+
'--before-context',
|
|
1236
|
+
'1',
|
|
1237
|
+
]), expect.anything());
|
|
1238
|
+
expect(result.llmContent).toContain('Found 1 match for pattern "world"');
|
|
1239
|
+
expect(result.llmContent).toContain('File: fileA.txt');
|
|
1240
|
+
expect(result.llmContent).toContain('L2: second line with world');
|
|
1241
|
+
// Note: Ripgrep JSON output for context lines doesn't include line numbers for context lines directly
|
|
1242
|
+
// The current parsing only extracts the matched line, so we only assert on that.
|
|
1243
|
+
});
|
|
1244
|
+
});
|
|
1245
|
+
describe('getDescription', () => {
|
|
1246
|
+
it.each([
|
|
1247
|
+
{
|
|
1248
|
+
name: 'pattern only',
|
|
1249
|
+
params: { pattern: 'testPattern' },
|
|
1250
|
+
expected: "'testPattern' within ./",
|
|
1251
|
+
},
|
|
1252
|
+
{
|
|
1253
|
+
name: 'pattern and include',
|
|
1254
|
+
params: { pattern: 'testPattern', include: '*.ts' },
|
|
1255
|
+
expected: "'testPattern' in *.ts within ./",
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
name: 'root path in description',
|
|
1259
|
+
params: { pattern: 'testPattern', dir_path: '.' },
|
|
1260
|
+
expected: "'testPattern' within ./",
|
|
1261
|
+
},
|
|
1262
|
+
])('should generate correct description with $name', ({ params, expected }) => {
|
|
1263
|
+
const invocation = grepTool.build(params);
|
|
1264
|
+
expect(invocation.getDescription()).toBe(expected);
|
|
1265
|
+
});
|
|
1266
|
+
it('should generate correct description with pattern and path', async () => {
|
|
1267
|
+
const dirPath = path.join(tempRootDir, 'src', 'app');
|
|
1268
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
1269
|
+
const params = {
|
|
1270
|
+
pattern: 'testPattern',
|
|
1271
|
+
dir_path: path.join('src', 'app'),
|
|
1272
|
+
};
|
|
1273
|
+
const invocation = grepTool.build(params);
|
|
1274
|
+
expect(invocation.getDescription()).toContain("'testPattern' within");
|
|
1275
|
+
expect(invocation.getDescription()).toContain(path.join('src', 'app'));
|
|
1276
|
+
});
|
|
1277
|
+
it('should use ./ when no path is specified (defaults to CWD)', () => {
|
|
1278
|
+
const multiDirConfig = {
|
|
1279
|
+
getTargetDir: () => tempRootDir,
|
|
1280
|
+
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir, ['/another/dir']),
|
|
1281
|
+
getDebugMode: () => false,
|
|
1282
|
+
};
|
|
1283
|
+
const multiDirGrepTool = new RipGrepTool(multiDirConfig);
|
|
1284
|
+
const params = { pattern: 'testPattern' };
|
|
1285
|
+
const invocation = multiDirGrepTool.build(params);
|
|
1286
|
+
expect(invocation.getDescription()).toBe("'testPattern' within ./");
|
|
1287
|
+
});
|
|
1288
|
+
it('should generate correct description with pattern, include, and path', async () => {
|
|
1289
|
+
const dirPath = path.join(tempRootDir, 'src', 'app');
|
|
1290
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
1291
|
+
const params = {
|
|
1292
|
+
pattern: 'testPattern',
|
|
1293
|
+
include: '*.ts',
|
|
1294
|
+
dir_path: path.join('src', 'app'),
|
|
1295
|
+
};
|
|
1296
|
+
const invocation = grepTool.build(params);
|
|
1297
|
+
expect(invocation.getDescription()).toContain("'testPattern' in *.ts within");
|
|
1298
|
+
expect(invocation.getDescription()).toContain(path.join('src', 'app'));
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
});
|
|
1302
|
+
afterAll(() => {
|
|
1303
|
+
storageSpy.mockRestore();
|
|
1304
|
+
});
|
|
1305
|
+
//# sourceMappingURL=ripGrep.test.js.map
|