@vybestack/llxprt-code-core 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -2
- package/dist/src/code_assist/converter.d.ts +2 -1
- package/dist/src/code_assist/converter.js +2 -1
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +13 -10
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.d.ts +1 -1
- package/dist/src/code_assist/oauth2.test.js +15 -15
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +2 -2
- package/dist/src/code_assist/server.js +4 -4
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +9 -9
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.js +1 -1
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js +2 -2
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/config/config.d.ts +37 -5
- package/dist/src/config/config.js +85 -15
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +33 -0
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/flashFallback.test.js +23 -47
- package/dist/src/config/flashFallback.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -0
- package/dist/src/config/models.js +1 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/profileManager.d.ts +42 -0
- package/dist/src/config/profileManager.js +114 -0
- package/dist/src/config/profileManager.js.map +1 -0
- package/dist/src/core/client.d.ts +15 -1
- package/dist/src/core/client.js +161 -45
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +291 -42
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +2 -2
- package/dist/src/core/contentGenerator.js +2 -7
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +6 -2
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -3
- package/dist/src/core/coreToolScheduler.js +48 -19
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +90 -18
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +35 -2
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +2 -2
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/googleGenAIWrapper.d.ts +21 -0
- package/dist/src/core/googleGenAIWrapper.js +36 -0
- package/dist/src/core/googleGenAIWrapper.js.map +1 -0
- package/dist/src/core/googleGenAIWrapper.test.d.ts +6 -0
- package/dist/src/core/googleGenAIWrapper.test.js +104 -0
- package/dist/src/core/googleGenAIWrapper.test.js.map +1 -0
- package/dist/src/core/logger.d.ts +1 -0
- package/dist/src/core/logger.js +22 -8
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +60 -9
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.js +19 -4
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +8 -3
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts-async.test.d.ts +6 -0
- package/dist/src/core/prompts-async.test.js +115 -0
- package/dist/src/core/prompts-async.test.js.map +1 -0
- package/dist/src/core/prompts.d.ts +8 -1
- package/dist/src/core/prompts.js +97 -377
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +46 -192
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/tokenLimits.d.ts +1 -1
- package/dist/src/core/tokenLimits.js +6 -1
- package/dist/src/core/tokenLimits.js.map +1 -1
- package/dist/src/core/turn.d.ts +5 -1
- package/dist/src/core/turn.js +7 -2
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +2 -2
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +10 -0
- package/dist/src/ide/detect-ide.js +24 -0
- package/dist/src/ide/detect-ide.js.map +1 -0
- package/dist/src/ide/ide-client.d.ts +19 -7
- package/dist/src/ide/ide-client.js +110 -37
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-installer.d.ts +15 -0
- package/dist/src/ide/ide-installer.js +111 -0
- package/dist/src/ide/ide-installer.js.map +1 -0
- package/dist/src/ide/ide-installer.test.d.ts +6 -0
- package/dist/src/ide/ide-installer.test.js +78 -0
- package/dist/src/ide/ide-installer.test.js.map +1 -0
- package/dist/src/ide/ideContext.d.ts +212 -107
- package/dist/src/ide/ideContext.js +45 -44
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/ideContext.test.js +254 -100
- package/dist/src/ide/ideContext.test.js.map +1 -1
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +20 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/{providers/IProviderConfig.js → integration-tests/todo-system.test.d.ts} +0 -1
- package/dist/src/integration-tests/todo-system.test.js +610 -0
- package/dist/src/integration-tests/todo-system.test.js.map +1 -0
- package/dist/src/mcp/oauth-provider.d.ts +5 -1
- package/dist/src/mcp/oauth-provider.js +39 -14
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +11 -10
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +3 -1
- package/dist/src/mcp/oauth-token-storage.js +3 -1
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-utils.js +2 -2
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +1 -1
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/parsers/TextToolCallParser.d.ts +1 -0
- package/dist/src/parsers/TextToolCallParser.js +45 -3
- package/dist/src/parsers/TextToolCallParser.js.map +1 -1
- package/dist/src/parsers/TextToolCallParser.multibyte.test.d.ts +1 -0
- package/dist/src/parsers/TextToolCallParser.multibyte.test.js +42 -0
- package/dist/src/parsers/TextToolCallParser.multibyte.test.js.map +1 -0
- package/dist/src/prompt-config/TemplateEngine.d.ts +35 -0
- package/dist/src/prompt-config/TemplateEngine.js +149 -0
- package/dist/src/prompt-config/TemplateEngine.js.map +1 -0
- package/dist/src/prompt-config/TemplateEngine.test.d.ts +1 -0
- package/dist/src/prompt-config/TemplateEngine.test.js +494 -0
- package/dist/src/prompt-config/TemplateEngine.test.js.map +1 -0
- package/dist/src/prompt-config/defaults/compression.md +58 -0
- package/dist/src/prompt-config/defaults/core-defaults.d.ts +5 -0
- package/dist/src/prompt-config/defaults/core-defaults.js +332 -0
- package/dist/src/prompt-config/defaults/core-defaults.js.map +1 -0
- package/dist/src/prompt-config/defaults/core.md +267 -0
- package/dist/src/prompt-config/defaults/env/git-repository.md +15 -0
- package/dist/src/prompt-config/defaults/env/ide-mode.md +3 -0
- package/dist/src/prompt-config/defaults/env/macos-seatbelt.md +3 -0
- package/dist/src/prompt-config/defaults/env/outside-of-sandbox.md +3 -0
- package/dist/src/prompt-config/defaults/env/sandbox.md +3 -0
- package/dist/src/prompt-config/defaults/index.d.ts +14 -0
- package/dist/src/prompt-config/defaults/index.js +21 -0
- package/dist/src/prompt-config/defaults/index.js.map +1 -0
- package/dist/src/prompt-config/defaults/provider-defaults.d.ts +5 -0
- package/dist/src/prompt-config/defaults/provider-defaults.js +26 -0
- package/dist/src/prompt-config/defaults/provider-defaults.js.map +1 -0
- package/dist/src/prompt-config/defaults/providers/gemini/models/gemini-2.5-flash/core.md +10 -0
- package/dist/src/prompt-config/defaults/service-defaults.d.ts +5 -0
- package/dist/src/prompt-config/defaults/service-defaults.js +52 -0
- package/dist/src/prompt-config/defaults/service-defaults.js.map +1 -0
- package/dist/src/prompt-config/defaults/tool-defaults.d.ts +5 -0
- package/dist/src/prompt-config/defaults/tool-defaults.js +81 -0
- package/dist/src/prompt-config/defaults/tool-defaults.js.map +1 -0
- package/dist/src/prompt-config/defaults/tools/edit.md +2 -0
- package/dist/src/prompt-config/defaults/tools/glob.md +2 -0
- package/dist/src/prompt-config/defaults/tools/grep.md +2 -0
- package/dist/src/prompt-config/defaults/tools/ls.md +1 -0
- package/dist/src/prompt-config/defaults/tools/memory.md +1 -0
- package/dist/src/prompt-config/defaults/tools/read-file.md +4 -0
- package/dist/src/prompt-config/defaults/tools/read-many-files.md +2 -0
- package/dist/src/prompt-config/defaults/tools/shell.md +5 -0
- package/dist/src/prompt-config/defaults/tools/todo-read.md +3 -0
- package/dist/src/prompt-config/defaults/tools/todo-write.md +50 -0
- package/dist/src/prompt-config/defaults/tools/web-fetch.md +3 -0
- package/dist/src/prompt-config/defaults/tools/web-search.md +3 -0
- package/dist/src/prompt-config/defaults/tools/write-file.md +4 -0
- package/dist/src/prompt-config/index.d.ts +16 -0
- package/dist/src/prompt-config/index.js +11 -0
- package/dist/src/prompt-config/index.js.map +1 -0
- package/dist/src/prompt-config/prompt-cache.d.ts +72 -0
- package/dist/src/prompt-config/prompt-cache.js +271 -0
- package/dist/src/prompt-config/prompt-cache.js.map +1 -0
- package/dist/src/prompt-config/prompt-cache.test.d.ts +6 -0
- package/dist/src/prompt-config/prompt-cache.test.js +437 -0
- package/dist/src/prompt-config/prompt-cache.test.js.map +1 -0
- package/dist/src/prompt-config/prompt-installer.d.ts +118 -0
- package/dist/src/prompt-config/prompt-installer.js +723 -0
- package/dist/src/prompt-config/prompt-installer.js.map +1 -0
- package/dist/src/prompt-config/prompt-installer.test.d.ts +7 -0
- package/dist/src/prompt-config/prompt-installer.test.js +503 -0
- package/dist/src/prompt-config/prompt-installer.test.js.map +1 -0
- package/dist/src/prompt-config/prompt-loader.d.ts +49 -0
- package/dist/src/prompt-config/prompt-loader.js +331 -0
- package/dist/src/prompt-config/prompt-loader.js.map +1 -0
- package/dist/src/prompt-config/prompt-loader.test.d.ts +5 -0
- package/dist/src/prompt-config/prompt-loader.test.js +413 -0
- package/dist/src/prompt-config/prompt-loader.test.js.map +1 -0
- package/dist/src/prompt-config/prompt-resolver.d.ts +74 -0
- package/dist/src/prompt-config/prompt-resolver.js +600 -0
- package/dist/src/prompt-config/prompt-resolver.js.map +1 -0
- package/dist/src/prompt-config/prompt-resolver.test.d.ts +1 -0
- package/dist/src/prompt-config/prompt-resolver.test.js +529 -0
- package/dist/src/prompt-config/prompt-resolver.test.js.map +1 -0
- package/dist/src/prompt-config/prompt-service.d.ts +108 -0
- package/dist/src/prompt-config/prompt-service.js +435 -0
- package/dist/src/prompt-config/prompt-service.js.map +1 -0
- package/dist/src/prompt-config/prompt-service.test.d.ts +1 -0
- package/dist/src/prompt-config/prompt-service.test.js +811 -0
- package/dist/src/prompt-config/prompt-service.test.js.map +1 -0
- package/dist/src/prompt-config/types.d.ts +30 -0
- package/dist/src/prompt-config/types.js +10 -0
- package/dist/src/prompt-config/types.js.map +1 -0
- package/dist/src/prompts/mcp-prompts.d.ts +8 -0
- package/dist/src/prompts/mcp-prompts.js +13 -0
- package/dist/src/prompts/mcp-prompts.js.map +1 -0
- package/dist/src/prompts/prompt-registry.d.ts +26 -0
- package/dist/src/prompts/prompt-registry.js +47 -0
- package/dist/src/prompts/prompt-registry.js.map +1 -0
- package/dist/src/providers/IProvider.d.ts +10 -0
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.js +24 -9
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.js.map +1 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js +1 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js.map +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.d.ts +14 -1
- package/dist/src/providers/anthropic/AnthropicProvider.js +28 -2
- package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.modelParams.test.d.ts +1 -0
- package/dist/src/providers/anthropic/AnthropicProvider.modelParams.test.js +48 -0
- package/dist/src/providers/anthropic/AnthropicProvider.modelParams.test.js.map +1 -0
- package/dist/src/providers/anthropic/AnthropicProvider.test.js +2 -1
- package/dist/src/providers/anthropic/AnthropicProvider.test.js.map +1 -1
- package/dist/src/providers/gemini/GeminiProvider.d.ts +11 -2
- package/dist/src/providers/gemini/GeminiProvider.integration.test.js +1 -1
- package/dist/src/providers/gemini/GeminiProvider.js +42 -25
- package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.d.ts +11 -0
- package/dist/src/providers/openai/OpenAIProvider.js +141 -24
- package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.responses.test.js +27 -3
- package/dist/src/providers/openai/OpenAIProvider.responses.test.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.js +2 -1
- package/dist/src/providers/openai/OpenAIProvider.shouldUseResponses.test.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.test.js +307 -7
- package/dist/src/providers/openai/OpenAIProvider.test.js.map +1 -1
- package/dist/src/providers/openai/buildResponsesRequest.js +19 -2
- package/dist/src/providers/openai/buildResponsesRequest.js.map +1 -1
- package/dist/src/providers/test-utils/providerTestConfig.d.ts +21 -0
- package/dist/src/providers/test-utils/providerTestConfig.js +23 -0
- package/dist/src/providers/test-utils/providerTestConfig.js.map +1 -0
- package/dist/src/providers/types/IProviderConfig.d.ts +6 -0
- package/dist/src/services/complexity-analyzer.d.ts +92 -0
- package/dist/src/services/complexity-analyzer.js +287 -0
- package/dist/src/services/complexity-analyzer.js.map +1 -0
- package/dist/src/services/fileDiscoveryService.test.js +101 -60
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
- package/dist/src/services/gitService.test.d.ts +1 -1
- package/dist/src/services/gitService.test.js +65 -102
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/index.d.ts +9 -0
- package/dist/src/services/index.js +8 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/loopDetectionService.d.ts +12 -0
- package/dist/src/services/loopDetectionService.js +62 -12
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +90 -11
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.d.ts +34 -0
- package/dist/src/services/shellExecutionService.js +121 -0
- package/dist/src/services/shellExecutionService.js.map +1 -0
- package/dist/src/services/shellExecutionService.multibyte.test.d.ts +6 -0
- package/dist/src/services/shellExecutionService.multibyte.test.js +72 -0
- package/dist/src/services/shellExecutionService.multibyte.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.test.d.ts +6 -0
- package/dist/src/services/shellExecutionService.test.js +264 -0
- package/dist/src/services/shellExecutionService.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.windows.multibyte.test.d.ts +6 -0
- package/dist/src/services/shellExecutionService.windows.multibyte.test.js +98 -0
- package/dist/src/services/shellExecutionService.windows.multibyte.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.windows.test.d.ts +6 -0
- package/dist/src/services/shellExecutionService.windows.test.js +79 -0
- package/dist/src/services/shellExecutionService.windows.test.js.map +1 -0
- package/dist/src/services/todo-reminder-service.d.ts +42 -0
- package/dist/src/services/todo-reminder-service.js +77 -0
- package/dist/src/services/todo-reminder-service.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +4 -2
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +81 -34
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +6 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +19 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +2 -1
- package/dist/src/telemetry/constants.js +2 -1
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/file-exporters.d.ts +2 -2
- package/dist/src/telemetry/file-exporters.js +47 -20
- package/dist/src/telemetry/file-exporters.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +2 -2
- package/dist/src/telemetry/index.js +2 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +3 -2
- package/dist/src/telemetry/loggers.js +30 -6
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +2 -0
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +13 -3
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/sdk.d.ts +1 -1
- package/dist/src/telemetry/sdk.js +71 -73
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/telemetry.test.js +7 -5
- package/dist/src/telemetry/telemetry.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +19 -4
- package/dist/src/telemetry/types.js +30 -4
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +3 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/mockWorkspaceContext.d.ts +13 -0
- package/dist/src/test-utils/mockWorkspaceContext.js +24 -0
- package/dist/src/test-utils/mockWorkspaceContext.js.map +1 -0
- package/dist/src/tools/edit.js +29 -4
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +104 -1
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.js +53 -17
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +32 -6
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +1 -1
- package/dist/src/tools/grep.js +81 -29
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +76 -9
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.js +4 -3
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.d.ts +6 -0
- package/dist/src/tools/ls.test.js +356 -0
- package/dist/src/tools/ls.test.js.map +1 -0
- package/dist/src/tools/mcp-client.d.ts +26 -2
- package/dist/src/tools/mcp-client.js +72 -24
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +87 -1
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +17 -2
- package/dist/src/tools/memoryTool.js +130 -13
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +88 -3
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +51 -62
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.js +8 -6
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +30 -2
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.js +22 -12
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +35 -2
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +8 -3
- package/dist/src/tools/shell.js +185 -114
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.multibyte.test.d.ts +6 -0
- package/dist/src/tools/shell.multibyte.test.js +74 -0
- package/dist/src/tools/shell.multibyte.test.js.map +1 -0
- package/dist/src/tools/shell.test.d.ts +1 -1
- package/dist/src/tools/shell.test.js +323 -138
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/todo-read.d.ts +4 -1
- package/dist/src/tools/todo-read.js +136 -20
- package/dist/src/tools/todo-read.js.map +1 -1
- package/dist/src/tools/todo-read.test.js +10 -6
- package/dist/src/tools/todo-read.test.js.map +1 -1
- package/dist/src/tools/todo-schemas.d.ts +4 -4
- package/dist/src/tools/todo-write.d.ts +3 -0
- package/dist/src/tools/todo-write.js +96 -9
- package/dist/src/tools/todo-write.js.map +1 -1
- package/dist/src/tools/todo-write.test.js +17 -13
- package/dist/src/tools/todo-write.test.js.map +1 -1
- package/dist/src/tools/tool-context.d.ts +14 -0
- package/dist/src/tools/tool-context.js +7 -0
- package/dist/src/tools/tool-context.js.map +1 -0
- package/dist/src/tools/tool-error.d.ts +22 -0
- package/dist/src/tools/tool-error.js +27 -0
- package/dist/src/tools/tool-error.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +4 -1
- package/dist/src/tools/tool-registry.js +14 -5
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +10 -2
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +16 -1
- package/dist/src/tools/tools.js +2 -0
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +18 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/write-file.js +5 -3
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +36 -2
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/types/modelParams.d.ts +62 -0
- package/dist/src/types/modelParams.js +7 -0
- package/dist/src/types/modelParams.js.map +1 -0
- package/dist/src/utils/bfsFileSearch.js +51 -27
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +59 -0
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/editCorrector.js +2 -2
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editor.d.ts +1 -1
- package/dist/src/utils/editor.js +9 -0
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +21 -1
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/fileUtils.js +12 -1
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +29 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.integration.test.js +8 -0
- package/dist/src/utils/flashFallback.integration.test.js.map +1 -1
- package/dist/src/utils/formatters.d.ts +6 -0
- package/dist/src/utils/formatters.js +16 -0
- package/dist/src/utils/formatters.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.d.ts +1 -1
- package/dist/src/utils/memoryDiscovery.js +61 -73
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +4 -3
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.d.ts +19 -12
- package/dist/src/utils/memoryImportProcessor.js +241 -82
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.test.js +595 -50
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +12 -27
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +8 -4
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +3 -0
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/sanitization.d.ts +20 -0
- package/dist/src/utils/sanitization.js +66 -0
- package/dist/src/utils/sanitization.js.map +1 -0
- package/dist/src/utils/sanitization.test.d.ts +6 -0
- package/dist/src/utils/sanitization.test.js +81 -0
- package/dist/src/utils/sanitization.test.js.map +1 -0
- package/dist/src/utils/secure-browser-launcher.d.ts +23 -0
- package/dist/src/utils/secure-browser-launcher.js +164 -0
- package/dist/src/utils/secure-browser-launcher.js.map +1 -0
- package/dist/src/utils/secure-browser-launcher.test.d.ts +6 -0
- package/dist/src/utils/secure-browser-launcher.test.js +149 -0
- package/dist/src/utils/secure-browser-launcher.test.js.map +1 -0
- package/dist/src/utils/shell-utils.d.ts +37 -3
- package/dist/src/utils/shell-utils.js +110 -47
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +146 -396
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/summarizer.js +2 -2
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/textUtils.d.ts +13 -0
- package/dist/src/utils/textUtils.js +28 -0
- package/dist/src/utils/textUtils.js.map +1 -0
- package/dist/src/utils/unicodeUtils.d.ts +44 -0
- package/dist/src/utils/unicodeUtils.js +93 -0
- package/dist/src/utils/unicodeUtils.js.map +1 -0
- package/dist/src/utils/unicodeUtils.test.d.ts +6 -0
- package/dist/src/utils/unicodeUtils.test.js +120 -0
- package/dist/src/utils/unicodeUtils.test.js.map +1 -0
- package/dist/src/utils/workspaceContext.d.ts +47 -0
- package/dist/src/utils/workspaceContext.js +106 -0
- package/dist/src/utils/workspaceContext.js.map +1 -0
- package/dist/src/utils/workspaceContext.test.d.ts +6 -0
- package/dist/src/utils/workspaceContext.test.js +209 -0
- package/dist/src/utils/workspaceContext.test.js.map +1 -0
- package/package.json +3 -2
- package/dist/src/providers/IProviderConfig.d.ts +0 -31
- package/dist/src/providers/IProviderConfig.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -4,447 +4,197 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { expect, describe, it, beforeEach } from 'vitest';
|
|
7
|
-
import { getCommandRoots, isCommandAllowed, stripShellWrapper, } from './shell-utils.js';
|
|
7
|
+
import { checkCommandPermissions, getCommandRoots, isCommandAllowed, stripShellWrapper, } from './shell-utils.js';
|
|
8
|
+
let config;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
config = {
|
|
11
|
+
getCoreTools: () => [],
|
|
12
|
+
getExcludeTools: () => [],
|
|
13
|
+
};
|
|
14
|
+
});
|
|
8
15
|
describe('isCommandAllowed', () => {
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
config = {
|
|
12
|
-
getCoreTools: () => undefined,
|
|
13
|
-
getExcludeTools: () => undefined,
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
it('should allow a command if no restrictions are provided', async () => {
|
|
16
|
+
it('should allow a command if no restrictions are provided', () => {
|
|
17
17
|
const result = isCommandAllowed('ls -l', config);
|
|
18
18
|
expect(result.allowed).toBe(true);
|
|
19
19
|
});
|
|
20
|
-
it('should allow a command if it is in the
|
|
21
|
-
config =
|
|
22
|
-
getCoreTools: () => ['ShellTool(ls -l)'],
|
|
23
|
-
getExcludeTools: () => undefined,
|
|
24
|
-
};
|
|
20
|
+
it('should allow a command if it is in the global allowlist', () => {
|
|
21
|
+
config.getCoreTools = () => ['ShellTool(ls)'];
|
|
25
22
|
const result = isCommandAllowed('ls -l', config);
|
|
26
23
|
expect(result.allowed).toBe(true);
|
|
27
24
|
});
|
|
28
|
-
it('should block a command if it is not in
|
|
29
|
-
config =
|
|
30
|
-
getCoreTools: () => ['ShellTool(ls -l)'],
|
|
31
|
-
getExcludeTools: () => undefined,
|
|
32
|
-
};
|
|
25
|
+
it('should block a command if it is not in a strict global allowlist', () => {
|
|
26
|
+
config.getCoreTools = () => ['ShellTool(ls -l)'];
|
|
33
27
|
const result = isCommandAllowed('rm -rf /', config);
|
|
34
28
|
expect(result.allowed).toBe(false);
|
|
35
|
-
expect(result.reason).toBe(
|
|
29
|
+
expect(result.reason).toBe(`Command(s) not in the allowed commands list.`);
|
|
36
30
|
});
|
|
37
|
-
it('should block a command if it is in the blocked list',
|
|
38
|
-
config =
|
|
39
|
-
getCoreTools: () => undefined,
|
|
40
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
41
|
-
};
|
|
31
|
+
it('should block a command if it is in the blocked list', () => {
|
|
32
|
+
config.getExcludeTools = () => ['ShellTool(rm -rf /)'];
|
|
42
33
|
const result = isCommandAllowed('rm -rf /', config);
|
|
43
34
|
expect(result.allowed).toBe(false);
|
|
44
|
-
expect(result.reason).toBe(
|
|
35
|
+
expect(result.reason).toBe(`Command 'rm -rf /' is blocked by configuration`);
|
|
45
36
|
});
|
|
46
|
-
it('should
|
|
47
|
-
config =
|
|
48
|
-
|
|
49
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
50
|
-
};
|
|
51
|
-
const result = isCommandAllowed('ls -l', config);
|
|
52
|
-
expect(result.allowed).toBe(true);
|
|
53
|
-
});
|
|
54
|
-
it('should block a command if it is in both the allowed and blocked lists', async () => {
|
|
55
|
-
config = {
|
|
56
|
-
getCoreTools: () => ['ShellTool(rm -rf /)'],
|
|
57
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
58
|
-
};
|
|
37
|
+
it('should prioritize the blocklist over the allowlist', () => {
|
|
38
|
+
config.getCoreTools = () => ['ShellTool(rm -rf /)'];
|
|
39
|
+
config.getExcludeTools = () => ['ShellTool(rm -rf /)'];
|
|
59
40
|
const result = isCommandAllowed('rm -rf /', config);
|
|
60
41
|
expect(result.allowed).toBe(false);
|
|
61
|
-
expect(result.reason).toBe(
|
|
42
|
+
expect(result.reason).toBe(`Command 'rm -rf /' is blocked by configuration`);
|
|
62
43
|
});
|
|
63
|
-
it('should allow any command when
|
|
64
|
-
config =
|
|
65
|
-
|
|
66
|
-
getExcludeTools: () => [],
|
|
67
|
-
};
|
|
68
|
-
const result = isCommandAllowed('any command', config);
|
|
44
|
+
it('should allow any command when a wildcard is in coreTools', () => {
|
|
45
|
+
config.getCoreTools = () => ['ShellTool'];
|
|
46
|
+
const result = isCommandAllowed('any random command', config);
|
|
69
47
|
expect(result.allowed).toBe(true);
|
|
70
48
|
});
|
|
71
|
-
it('should block any command when
|
|
72
|
-
config =
|
|
73
|
-
|
|
74
|
-
getExcludeTools: () => ['ShellTool'],
|
|
75
|
-
};
|
|
76
|
-
const result = isCommandAllowed('any command', config);
|
|
49
|
+
it('should block any command when a wildcard is in excludeTools', () => {
|
|
50
|
+
config.getExcludeTools = () => ['run_shell_command'];
|
|
51
|
+
const result = isCommandAllowed('any random command', config);
|
|
77
52
|
expect(result.allowed).toBe(false);
|
|
78
53
|
expect(result.reason).toBe('Shell tool is globally disabled in configuration');
|
|
79
54
|
});
|
|
80
|
-
it('should
|
|
81
|
-
config =
|
|
82
|
-
|
|
83
|
-
getExcludeTools: () => undefined,
|
|
84
|
-
};
|
|
85
|
-
const result = isCommandAllowed('ls -l', config);
|
|
86
|
-
expect(result.allowed).toBe(true);
|
|
87
|
-
});
|
|
88
|
-
it('should block a command if it is in the blocked list using the public-facing name', async () => {
|
|
89
|
-
config = {
|
|
90
|
-
getCoreTools: () => undefined,
|
|
91
|
-
getExcludeTools: () => ['run_shell_command(rm -rf /)'],
|
|
92
|
-
};
|
|
55
|
+
it('should block a command on the blocklist even with a wildcard allow', () => {
|
|
56
|
+
config.getCoreTools = () => ['ShellTool'];
|
|
57
|
+
config.getExcludeTools = () => ['ShellTool(rm -rf /)'];
|
|
93
58
|
const result = isCommandAllowed('rm -rf /', config);
|
|
94
59
|
expect(result.allowed).toBe(false);
|
|
95
|
-
expect(result.reason).toBe(
|
|
96
|
-
});
|
|
97
|
-
it('should block any command when ShellTool is in excludeTools using the public-facing name', async () => {
|
|
98
|
-
config = {
|
|
99
|
-
getCoreTools: () => [],
|
|
100
|
-
getExcludeTools: () => ['run_shell_command'],
|
|
101
|
-
};
|
|
102
|
-
const result = isCommandAllowed('any command', config);
|
|
103
|
-
expect(result.allowed).toBe(false);
|
|
104
|
-
expect(result.reason).toBe('Shell tool is globally disabled in configuration');
|
|
105
|
-
});
|
|
106
|
-
it('should block any command if coreTools contains an empty ShellTool command list using the public-facing name', async () => {
|
|
107
|
-
config = {
|
|
108
|
-
getCoreTools: () => ['run_shell_command()'],
|
|
109
|
-
getExcludeTools: () => [],
|
|
110
|
-
};
|
|
111
|
-
const result = isCommandAllowed('any command', config);
|
|
112
|
-
expect(result.allowed).toBe(false);
|
|
113
|
-
expect(result.reason).toBe("Command 'any command' is not in the allowed commands list");
|
|
114
|
-
});
|
|
115
|
-
it('should block any command if coreTools contains an empty ShellTool command list', async () => {
|
|
116
|
-
config = {
|
|
117
|
-
getCoreTools: () => ['ShellTool()'],
|
|
118
|
-
getExcludeTools: () => [],
|
|
119
|
-
};
|
|
120
|
-
const result = isCommandAllowed('any command', config);
|
|
121
|
-
expect(result.allowed).toBe(false);
|
|
122
|
-
expect(result.reason).toBe("Command 'any command' is not in the allowed commands list");
|
|
123
|
-
});
|
|
124
|
-
it('should block a command with extra whitespace if it is in the blocked list', async () => {
|
|
125
|
-
config = {
|
|
126
|
-
getCoreTools: () => undefined,
|
|
127
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
128
|
-
};
|
|
129
|
-
const result = isCommandAllowed(' rm -rf / ', config);
|
|
130
|
-
expect(result.allowed).toBe(false);
|
|
131
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
132
|
-
});
|
|
133
|
-
it('should allow any command when ShellTool is in present with specific commands', async () => {
|
|
134
|
-
config = {
|
|
135
|
-
getCoreTools: () => ['ShellTool', 'ShellTool(ls)'],
|
|
136
|
-
getExcludeTools: () => [],
|
|
137
|
-
};
|
|
138
|
-
const result = isCommandAllowed('any command', config);
|
|
139
|
-
expect(result.allowed).toBe(true);
|
|
140
|
-
});
|
|
141
|
-
it('should block a command on the blocklist even with a wildcard allow', async () => {
|
|
142
|
-
config = {
|
|
143
|
-
getCoreTools: () => ['ShellTool'],
|
|
144
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
145
|
-
};
|
|
146
|
-
const result = isCommandAllowed('rm -rf /', config);
|
|
147
|
-
expect(result.allowed).toBe(false);
|
|
148
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
149
|
-
});
|
|
150
|
-
it('should allow a command that starts with an allowed command prefix', async () => {
|
|
151
|
-
config = {
|
|
152
|
-
getCoreTools: () => ['ShellTool(gh issue edit)'],
|
|
153
|
-
getExcludeTools: () => [],
|
|
154
|
-
};
|
|
155
|
-
const result = isCommandAllowed('gh issue edit 1 --add-label "kind/feature"', config);
|
|
156
|
-
expect(result.allowed).toBe(true);
|
|
157
|
-
});
|
|
158
|
-
it('should allow a command that starts with an allowed command prefix using the public-facing name', async () => {
|
|
159
|
-
config = {
|
|
160
|
-
getCoreTools: () => ['run_shell_command(gh issue edit)'],
|
|
161
|
-
getExcludeTools: () => [],
|
|
162
|
-
};
|
|
163
|
-
const result = isCommandAllowed('gh issue edit 1 --add-label "kind/feature"', config);
|
|
164
|
-
expect(result.allowed).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
it('should not allow a command that starts with an allowed command prefix but is chained with another command', async () => {
|
|
167
|
-
config = {
|
|
168
|
-
getCoreTools: () => ['run_shell_command(gh issue edit)'],
|
|
169
|
-
getExcludeTools: () => [],
|
|
170
|
-
};
|
|
171
|
-
const result = isCommandAllowed('gh issue edit&&rm -rf /', config);
|
|
172
|
-
expect(result.allowed).toBe(false);
|
|
173
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
174
|
-
});
|
|
175
|
-
it('should not allow a command that is a prefix of an allowed command', async () => {
|
|
176
|
-
config = {
|
|
177
|
-
getCoreTools: () => ['run_shell_command(gh issue edit)'],
|
|
178
|
-
getExcludeTools: () => [],
|
|
179
|
-
};
|
|
180
|
-
const result = isCommandAllowed('gh issue', config);
|
|
181
|
-
expect(result.allowed).toBe(false);
|
|
182
|
-
expect(result.reason).toBe("Command 'gh issue' is not in the allowed commands list");
|
|
183
|
-
});
|
|
184
|
-
it('should not allow a command that is a prefix of a blocked command', async () => {
|
|
185
|
-
config = {
|
|
186
|
-
getCoreTools: () => [],
|
|
187
|
-
getExcludeTools: () => ['run_shell_command(gh issue edit)'],
|
|
188
|
-
};
|
|
189
|
-
const result = isCommandAllowed('gh issue', config);
|
|
190
|
-
expect(result.allowed).toBe(true);
|
|
60
|
+
expect(result.reason).toBe(`Command 'rm -rf /' is blocked by configuration`);
|
|
191
61
|
});
|
|
192
|
-
it('should
|
|
193
|
-
config =
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const result = isCommandAllowed('gh issue list | rm -rf /', config);
|
|
198
|
-
expect(result.allowed).toBe(false);
|
|
199
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
200
|
-
});
|
|
201
|
-
it('should not allow a command that is chained with a semicolon', async () => {
|
|
202
|
-
config = {
|
|
203
|
-
getCoreTools: () => ['run_shell_command(gh issue list)'],
|
|
204
|
-
getExcludeTools: () => [],
|
|
205
|
-
};
|
|
206
|
-
const result = isCommandAllowed('gh issue list; rm -rf /', config);
|
|
207
|
-
expect(result.allowed).toBe(false);
|
|
208
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
209
|
-
});
|
|
210
|
-
it('should block a chained command if any part is blocked', async () => {
|
|
211
|
-
config = {
|
|
212
|
-
getCoreTools: () => ['run_shell_command(echo "hello")'],
|
|
213
|
-
getExcludeTools: () => ['run_shell_command(rm)'],
|
|
214
|
-
};
|
|
215
|
-
const result = isCommandAllowed('echo "hello" && rm -rf /', config);
|
|
216
|
-
expect(result.allowed).toBe(false);
|
|
217
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
218
|
-
});
|
|
219
|
-
it('should block a command if its prefix is on the blocklist, even if the command itself is on the allowlist', async () => {
|
|
220
|
-
config = {
|
|
221
|
-
getCoreTools: () => ['run_shell_command(git push)'],
|
|
222
|
-
getExcludeTools: () => ['run_shell_command(git)'],
|
|
223
|
-
};
|
|
224
|
-
const result = isCommandAllowed('git push', config);
|
|
225
|
-
expect(result.allowed).toBe(false);
|
|
226
|
-
expect(result.reason).toBe("Command 'git push' is blocked by configuration");
|
|
227
|
-
});
|
|
228
|
-
it('should be case-sensitive in its matching', async () => {
|
|
229
|
-
config = {
|
|
230
|
-
getCoreTools: () => ['run_shell_command(echo)'],
|
|
231
|
-
getExcludeTools: () => [],
|
|
232
|
-
};
|
|
233
|
-
const result = isCommandAllowed('ECHO "hello"', config);
|
|
234
|
-
expect(result.allowed).toBe(false);
|
|
235
|
-
expect(result.reason).toBe('Command \'ECHO "hello"\' is not in the allowed commands list');
|
|
236
|
-
});
|
|
237
|
-
it('should correctly handle commands with extra whitespace around chaining operators', async () => {
|
|
238
|
-
config = {
|
|
239
|
-
getCoreTools: () => ['run_shell_command(ls -l)'],
|
|
240
|
-
getExcludeTools: () => ['run_shell_command(rm)'],
|
|
241
|
-
};
|
|
242
|
-
const result = isCommandAllowed('ls -l ; rm -rf /', config);
|
|
243
|
-
expect(result.allowed).toBe(false);
|
|
244
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
245
|
-
});
|
|
246
|
-
it('should allow a chained command if all parts are allowed', async () => {
|
|
247
|
-
config = {
|
|
248
|
-
getCoreTools: () => [
|
|
249
|
-
'run_shell_command(echo)',
|
|
250
|
-
'run_shell_command(ls -l)',
|
|
251
|
-
],
|
|
252
|
-
getExcludeTools: () => [],
|
|
253
|
-
};
|
|
62
|
+
it('should allow a chained command if all parts are on the global allowlist', () => {
|
|
63
|
+
config.getCoreTools = () => [
|
|
64
|
+
'run_shell_command(echo)',
|
|
65
|
+
'run_shell_command(ls)',
|
|
66
|
+
];
|
|
254
67
|
const result = isCommandAllowed('echo "hello" && ls -l', config);
|
|
255
68
|
expect(result.allowed).toBe(true);
|
|
256
69
|
});
|
|
257
|
-
it('should block a command
|
|
258
|
-
config =
|
|
259
|
-
|
|
260
|
-
getExcludeTools: () => [],
|
|
261
|
-
};
|
|
262
|
-
const result = isCommandAllowed('echo `rm -rf /`', config);
|
|
263
|
-
expect(result.allowed).toBe(false);
|
|
264
|
-
expect(result.reason).toBe('Command substitution using $(), <(), or >() is not allowed for security reasons');
|
|
265
|
-
});
|
|
266
|
-
it('should block a command with command substitution using $()', async () => {
|
|
267
|
-
config = {
|
|
268
|
-
getCoreTools: () => ['run_shell_command(echo)'],
|
|
269
|
-
getExcludeTools: () => [],
|
|
270
|
-
};
|
|
271
|
-
const result = isCommandAllowed('echo $(rm -rf /)', config);
|
|
272
|
-
expect(result.allowed).toBe(false);
|
|
273
|
-
expect(result.reason).toBe('Command substitution using $(), <(), or >() is not allowed for security reasons');
|
|
274
|
-
});
|
|
275
|
-
it('should block a command with process substitution using <()', async () => {
|
|
276
|
-
config = {
|
|
277
|
-
getCoreTools: () => ['run_shell_command(diff)'],
|
|
278
|
-
getExcludeTools: () => [],
|
|
279
|
-
};
|
|
280
|
-
const result = isCommandAllowed('diff <(ls) <(ls -a)', config);
|
|
70
|
+
it('should block a chained command if any part is blocked', () => {
|
|
71
|
+
config.getExcludeTools = () => ['run_shell_command(rm)'];
|
|
72
|
+
const result = isCommandAllowed('echo "hello" && rm -rf /', config);
|
|
281
73
|
expect(result.allowed).toBe(false);
|
|
282
|
-
expect(result.reason).toBe(
|
|
74
|
+
expect(result.reason).toBe(`Command 'rm -rf /' is blocked by configuration`);
|
|
75
|
+
});
|
|
76
|
+
describe('command substitution', () => {
|
|
77
|
+
it('should block command substitution using `$(...)`', () => {
|
|
78
|
+
const result = isCommandAllowed('echo $(rm -rf /)', config);
|
|
79
|
+
expect(result.allowed).toBe(false);
|
|
80
|
+
expect(result.reason).toContain('Command substitution');
|
|
81
|
+
});
|
|
82
|
+
it('should block command substitution using `<(...)`', () => {
|
|
83
|
+
const result = isCommandAllowed('diff <(ls) <(ls -a)', config);
|
|
84
|
+
expect(result.allowed).toBe(false);
|
|
85
|
+
expect(result.reason).toContain('Command substitution');
|
|
86
|
+
});
|
|
87
|
+
it('should block command substitution using backticks', () => {
|
|
88
|
+
const result = isCommandAllowed('echo `rm -rf /`', config);
|
|
89
|
+
expect(result.allowed).toBe(false);
|
|
90
|
+
expect(result.reason).toContain('Command substitution');
|
|
91
|
+
});
|
|
92
|
+
it('should allow substitution-like patterns inside single quotes', () => {
|
|
93
|
+
config.getCoreTools = () => ['ShellTool(echo)'];
|
|
94
|
+
const result = isCommandAllowed("echo '$(pwd)'", config);
|
|
95
|
+
expect(result.allowed).toBe(true);
|
|
96
|
+
});
|
|
283
97
|
});
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
getExcludeTools
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
98
|
+
});
|
|
99
|
+
describe('checkCommandPermissions', () => {
|
|
100
|
+
describe('in "Default Allow" mode (no sessionAllowlist)', () => {
|
|
101
|
+
it('should return a detailed success object for an allowed command', () => {
|
|
102
|
+
const result = checkCommandPermissions('ls -l', config);
|
|
103
|
+
expect(result).toEqual({
|
|
104
|
+
allAllowed: true,
|
|
105
|
+
disallowedCommands: [],
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
it('should return a detailed failure object for a blocked command', () => {
|
|
109
|
+
config.getExcludeTools = () => ['ShellTool(rm)'];
|
|
110
|
+
const result = checkCommandPermissions('rm -rf /', config);
|
|
111
|
+
expect(result).toEqual({
|
|
112
|
+
allAllowed: false,
|
|
113
|
+
disallowedCommands: ['rm -rf /'],
|
|
114
|
+
blockReason: `Command 'rm -rf /' is blocked by configuration`,
|
|
115
|
+
isHardDenial: true,
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
it('should return a detailed failure object for a command not on a strict allowlist', () => {
|
|
119
|
+
config.getCoreTools = () => ['ShellTool(ls)'];
|
|
120
|
+
const result = checkCommandPermissions('git status && ls', config);
|
|
121
|
+
expect(result).toEqual({
|
|
122
|
+
allAllowed: false,
|
|
123
|
+
disallowedCommands: ['git status'],
|
|
124
|
+
blockReason: `Command(s) not in the allowed commands list.`,
|
|
125
|
+
isHardDenial: false,
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('in "Default Deny" mode (with sessionAllowlist)', () => {
|
|
130
|
+
it('should allow a command on the sessionAllowlist', () => {
|
|
131
|
+
const result = checkCommandPermissions('ls -l', config, new Set(['ls -l']));
|
|
132
|
+
expect(result.allAllowed).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
it('should block a command not on the sessionAllowlist or global allowlist', () => {
|
|
135
|
+
const result = checkCommandPermissions('rm -rf /', config, new Set(['ls -l']));
|
|
136
|
+
expect(result.allAllowed).toBe(false);
|
|
137
|
+
expect(result.blockReason).toContain('not on the global or session allowlist');
|
|
138
|
+
expect(result.disallowedCommands).toEqual(['rm -rf /']);
|
|
139
|
+
});
|
|
140
|
+
it('should allow a command on the global allowlist even if not on the session allowlist', () => {
|
|
141
|
+
config.getCoreTools = () => ['ShellTool(git status)'];
|
|
142
|
+
const result = checkCommandPermissions('git status', config, new Set(['ls -l']));
|
|
143
|
+
expect(result.allAllowed).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
it('should allow a chained command if parts are on different allowlists', () => {
|
|
146
|
+
config.getCoreTools = () => ['ShellTool(git status)'];
|
|
147
|
+
const result = checkCommandPermissions('git status && git commit', config, new Set(['git commit']));
|
|
148
|
+
expect(result.allAllowed).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
it('should block a command on the sessionAllowlist if it is also globally blocked', () => {
|
|
151
|
+
config.getExcludeTools = () => ['run_shell_command(rm)'];
|
|
152
|
+
const result = checkCommandPermissions('rm -rf /', config, new Set(['rm -rf /']));
|
|
153
|
+
expect(result.allAllowed).toBe(false);
|
|
154
|
+
expect(result.blockReason).toContain('is blocked by configuration');
|
|
155
|
+
});
|
|
156
|
+
it('should block a chained command if one part is not on any allowlist', () => {
|
|
157
|
+
config.getCoreTools = () => ['run_shell_command(echo)'];
|
|
158
|
+
const result = checkCommandPermissions('echo "hello" && rm -rf /', config, new Set(['echo']));
|
|
159
|
+
expect(result.allAllowed).toBe(false);
|
|
160
|
+
expect(result.disallowedCommands).toEqual(['rm -rf /']);
|
|
161
|
+
});
|
|
300
162
|
});
|
|
301
163
|
});
|
|
302
164
|
describe('getCommandRoots', () => {
|
|
303
165
|
it('should return a single command', () => {
|
|
304
|
-
|
|
305
|
-
expect(result).toEqual(['ls']);
|
|
166
|
+
expect(getCommandRoots('ls -l')).toEqual(['ls']);
|
|
306
167
|
});
|
|
307
|
-
it('should return
|
|
308
|
-
|
|
309
|
-
expect(result).toEqual(['ls', 'grep']);
|
|
168
|
+
it('should handle paths and return the binary name', () => {
|
|
169
|
+
expect(getCommandRoots('/usr/local/bin/node script.js')).toEqual(['node']);
|
|
310
170
|
});
|
|
311
|
-
it('should
|
|
312
|
-
|
|
313
|
-
expect(result).toEqual(['npm', 'npm']);
|
|
314
|
-
});
|
|
315
|
-
it('should handle multiple commands with ;', () => {
|
|
316
|
-
const result = getCommandRoots('echo "hello"; echo "world"');
|
|
317
|
-
expect(result).toEqual(['echo', 'echo']);
|
|
171
|
+
it('should return an empty array for an empty string', () => {
|
|
172
|
+
expect(getCommandRoots('')).toEqual([]);
|
|
318
173
|
});
|
|
319
174
|
it('should handle a mix of operators', () => {
|
|
320
|
-
const result = getCommandRoots('
|
|
321
|
-
expect(result).toEqual(['
|
|
322
|
-
});
|
|
323
|
-
it('should handle commands with paths', () => {
|
|
324
|
-
const result = getCommandRoots('/usr/local/bin/node script.js');
|
|
325
|
-
expect(result).toEqual(['node']);
|
|
175
|
+
const result = getCommandRoots('a;b|c&&d||e&f');
|
|
176
|
+
expect(result).toEqual(['a', 'b', 'c', 'd', 'e', 'f']);
|
|
326
177
|
});
|
|
327
|
-
it('should
|
|
328
|
-
const result = getCommandRoots('');
|
|
329
|
-
expect(result).toEqual([]);
|
|
178
|
+
it('should correctly parse a chained command with quotes', () => {
|
|
179
|
+
const result = getCommandRoots('echo "hello" && git commit -m "feat"');
|
|
180
|
+
expect(result).toEqual(['echo', 'git']);
|
|
330
181
|
});
|
|
331
182
|
});
|
|
332
183
|
describe('stripShellWrapper', () => {
|
|
333
|
-
it('should strip sh -c
|
|
334
|
-
|
|
335
|
-
expect(result).toEqual('ls -l');
|
|
336
|
-
});
|
|
337
|
-
it('should strip bash -c from the beginning of the command', () => {
|
|
338
|
-
const result = stripShellWrapper('bash -c "ls -l"');
|
|
339
|
-
expect(result).toEqual('ls -l');
|
|
340
|
-
});
|
|
341
|
-
it('should strip zsh -c from the beginning of the command', () => {
|
|
342
|
-
const result = stripShellWrapper('zsh -c "ls -l"');
|
|
343
|
-
expect(result).toEqual('ls -l');
|
|
344
|
-
});
|
|
345
|
-
it('should not strip anything if the command does not start with a shell wrapper', () => {
|
|
346
|
-
const result = stripShellWrapper('ls -l');
|
|
347
|
-
expect(result).toEqual('ls -l');
|
|
348
|
-
});
|
|
349
|
-
it('should handle extra whitespace', () => {
|
|
350
|
-
const result = stripShellWrapper(' sh -c "ls -l" ');
|
|
351
|
-
expect(result).toEqual('ls -l');
|
|
352
|
-
});
|
|
353
|
-
it('should handle commands without quotes', () => {
|
|
354
|
-
const result = stripShellWrapper('sh -c ls -l');
|
|
355
|
-
expect(result).toEqual('ls -l');
|
|
356
|
-
});
|
|
357
|
-
it('should strip cmd.exe /c from the beginning of the command', () => {
|
|
358
|
-
const result = stripShellWrapper('cmd.exe /c "dir"');
|
|
359
|
-
expect(result).toEqual('dir');
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
describe('getCommandRoots', () => {
|
|
363
|
-
it('should handle multiple commands with &', () => {
|
|
364
|
-
const result = getCommandRoots('echo "hello" & echo "world"');
|
|
365
|
-
expect(result).toEqual(['echo', 'echo']);
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
describe('command substitution', () => {
|
|
369
|
-
let config;
|
|
370
|
-
beforeEach(() => {
|
|
371
|
-
config = {
|
|
372
|
-
getCoreTools: () => ['run_shell_command(echo)', 'run_shell_command(gh)'],
|
|
373
|
-
getExcludeTools: () => [],
|
|
374
|
-
};
|
|
375
|
-
});
|
|
376
|
-
it('should block unquoted command substitution `$(...)`', () => {
|
|
377
|
-
const result = isCommandAllowed('echo $(pwd)', config);
|
|
378
|
-
expect(result.allowed).toBe(false);
|
|
184
|
+
it('should strip sh -c with quotes', () => {
|
|
185
|
+
expect(stripShellWrapper('sh -c "ls -l"')).toEqual('ls -l');
|
|
379
186
|
});
|
|
380
|
-
it('should
|
|
381
|
-
|
|
382
|
-
expect(result.allowed).toBe(false);
|
|
383
|
-
});
|
|
384
|
-
it('should allow command substitution in single quotes', () => {
|
|
385
|
-
const result = isCommandAllowed("echo '$(pwd)'", config);
|
|
386
|
-
expect(result.allowed).toBe(true);
|
|
187
|
+
it('should strip bash -c with extra whitespace', () => {
|
|
188
|
+
expect(stripShellWrapper(' bash -c "ls -l" ')).toEqual('ls -l');
|
|
387
189
|
});
|
|
388
|
-
it('should
|
|
389
|
-
|
|
390
|
-
expect(result.allowed).toBe(true);
|
|
190
|
+
it('should strip zsh -c without quotes', () => {
|
|
191
|
+
expect(stripShellWrapper('zsh -c ls -l')).toEqual('ls -l');
|
|
391
192
|
});
|
|
392
|
-
it('should
|
|
393
|
-
|
|
394
|
-
expect(result.allowed).toBe(false);
|
|
395
|
-
});
|
|
396
|
-
it('should allow escaped command substitution', () => {
|
|
397
|
-
const result = isCommandAllowed('echo \\$(pwd)', config);
|
|
398
|
-
expect(result.allowed).toBe(true);
|
|
399
|
-
});
|
|
400
|
-
it('should allow complex commands with quoted substitution-like patterns', () => {
|
|
401
|
-
const command = "gh pr comment 4795 --body 'This is a test comment with $(pwd) style text'";
|
|
402
|
-
const result = isCommandAllowed(command, config);
|
|
403
|
-
expect(result.allowed).toBe(true);
|
|
404
|
-
});
|
|
405
|
-
it('should block complex commands with unquoted substitution-like patterns', () => {
|
|
406
|
-
const command = 'gh pr comment 4795 --body "This is a test comment with $(pwd) style text"';
|
|
407
|
-
const result = isCommandAllowed(command, config);
|
|
408
|
-
expect(result.allowed).toBe(false);
|
|
409
|
-
});
|
|
410
|
-
it('should allow a command with markdown content using proper quoting', () => {
|
|
411
|
-
// Simple test with safe content in single quotes
|
|
412
|
-
const result = isCommandAllowed("gh pr comment 4795 --body 'This is safe markdown content'", config);
|
|
413
|
-
expect(result.allowed).toBe(true);
|
|
193
|
+
it('should strip cmd.exe /c', () => {
|
|
194
|
+
expect(stripShellWrapper('cmd.exe /c "dir"')).toEqual('dir');
|
|
414
195
|
});
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
it('should correctly parse a simple command', () => {
|
|
418
|
-
const result = getCommandRoots('git status');
|
|
419
|
-
expect(result).toEqual(['git']);
|
|
420
|
-
});
|
|
421
|
-
it('should correctly parse a command with a quoted argument', () => {
|
|
422
|
-
const result = getCommandRoots('git commit -m "feat: new feature"');
|
|
423
|
-
expect(result).toEqual(['git']);
|
|
424
|
-
});
|
|
425
|
-
it('should correctly parse a command with single quotes', () => {
|
|
426
|
-
const result = getCommandRoots("echo 'hello world'");
|
|
427
|
-
expect(result).toEqual(['echo']);
|
|
428
|
-
});
|
|
429
|
-
it('should correctly parse a chained command with quotes', () => {
|
|
430
|
-
const result = getCommandRoots('echo "hello" && git status');
|
|
431
|
-
expect(result).toEqual(['echo', 'git']);
|
|
432
|
-
});
|
|
433
|
-
it('should correctly parse a complex chained command', () => {
|
|
434
|
-
const result = getCommandRoots('git commit -m "feat: new feature" && echo "done"');
|
|
435
|
-
expect(result).toEqual(['git', 'echo']);
|
|
436
|
-
});
|
|
437
|
-
it('should handle escaped quotes', () => {
|
|
438
|
-
const result = getCommandRoots('echo "this is a "quote""');
|
|
439
|
-
expect(result).toEqual(['echo']);
|
|
440
|
-
});
|
|
441
|
-
it('should handle commands with no spaces', () => {
|
|
442
|
-
const result = getCommandRoots('command');
|
|
443
|
-
expect(result).toEqual(['command']);
|
|
444
|
-
});
|
|
445
|
-
it('should handle multiple separators', () => {
|
|
446
|
-
const result = getCommandRoots('a;b|c&&d||e&f');
|
|
447
|
-
expect(result).toEqual(['a', 'b', 'c', 'd', 'e', 'f']);
|
|
196
|
+
it('should not strip anything if no wrapper is present', () => {
|
|
197
|
+
expect(stripShellWrapper('ls -l')).toEqual('ls -l');
|
|
448
198
|
});
|
|
449
199
|
});
|
|
450
200
|
//# sourceMappingURL=shell-utils.test.js.map
|