@machina.ai/cell-cli-core 1.13.0-rc5 → 1.16.0-rc2
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 +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/agents/codebase-investigator.test.d.ts +6 -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 +3 -0
- package/dist/src/agents/executor.js +21 -0
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js +358 -3
- package/dist/src/agents/executor.test.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/experiments/client_metadata.js +2 -1
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
- 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.js +2 -2
- package/dist/src/code_assist/experiments/experiments.js.map +1 -1
- 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 +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +49 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
- package/dist/src/code_assist/server.js +5 -8
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +109 -28
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/config/config.d.ts +34 -2
- package/dist/src/config/config.js +147 -26
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +436 -19
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/defaultModelConfigs.d.ts +7 -0
- package/dist/src/config/defaultModelConfigs.js +158 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -0
- package/dist/src/config/models.d.ts +22 -1
- package/dist/src/config/models.js +49 -6
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +71 -10
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.d.ts +1 -1
- package/dist/src/confirmation-bus/message-bus.js +2 -2
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.test.js +30 -24
- package/dist/src/confirmation-bus/message-bus.test.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +1 -0
- package/dist/src/core/baseLlmClient.d.ts +4 -8
- package/dist/src/core/baseLlmClient.js +3 -8
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +22 -27
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.d.ts +6 -5
- package/dist/src/core/client.js +33 -33
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +40 -22
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.js +7 -1
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +151 -357
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +6 -4
- package/dist/src/core/geminiChat.js +106 -29
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +317 -16
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/logger.d.ts +7 -2
- package/dist/src/core/logger.js +15 -9
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +31 -16
- package/dist/src/core/logger.test.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.test.js +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +8 -11
- package/dist/src/core/prompts.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/fallback/handler.js +52 -7
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +69 -16
- package/dist/src/fallback/handler.test.js.map +1 -1
- package/dist/src/fallback/types.d.ts +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookAggregator.d.ts +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/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 +3 -3
- package/dist/src/hooks/types.js +1 -1
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/hooks/types.test.js +280 -2
- package/dist/src/hooks/types.test.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +4 -0
- package/dist/src/ide/detect-ide.js +6 -1
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +5 -0
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +3 -1
- package/dist/src/ide/ide-client.js +66 -59
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +159 -0
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.js +71 -21
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +42 -1
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/process-utils.js +16 -0
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/process-utils.test.js +3 -3
- package/dist/src/ide/process-utils.test.js.map +1 -1
- package/dist/src/ide/types.d.ts +1 -1
- package/dist/src/ide/types.js +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.js +1 -1
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js +2 -2
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +177 -0
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.js +1 -1
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
- package/dist/src/policy/config.js +3 -1
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/config.test.js +135 -1
- package/dist/src/policy/config.test.js.map +1 -1
- package/dist/src/policy/policies/discovered.toml +8 -0
- package/dist/src/policy/policies/write.toml +10 -0
- package/dist/src/policy/policy-engine.d.ts +12 -3
- package/dist/src/policy/policy-engine.js +71 -9
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +460 -76
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/toml-loader.d.ts +2 -1
- package/dist/src/policy/toml-loader.js +103 -6
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +222 -368
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/types.d.ts +65 -0
- package/dist/src/policy/types.js +4 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/prompts/mcp-prompts.test.d.ts +6 -0
- package/dist/src/prompts/mcp-prompts.test.js +40 -0
- package/dist/src/prompts/mcp-prompts.test.js.map +1 -0
- package/dist/src/prompts/prompt-registry.test.d.ts +6 -0
- package/dist/src/prompts/prompt-registry.test.js +111 -0
- package/dist/src/prompts/prompt-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.js +15 -0
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +62 -0
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.d.ts +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +6 -14
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js +13 -10
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.test.js +4 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +2 -2
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.test.js +3 -0
- package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -1
- 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.test.js +1 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -1
- package/dist/src/services/gitService.js +1 -1
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +1 -1
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +3 -0
- package/dist/src/services/loopDetectionService.js +81 -42
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +101 -1
- 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 +213 -0
- package/dist/src/services/modelConfig.integration.test.js.map +1 -0
- package/dist/src/services/modelConfigService.d.ts +46 -0
- package/dist/src/services/modelConfigService.js +146 -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 +509 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -0
- package/dist/src/services/test-data/resolved-aliases.golden.json +169 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +11 -9
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +174 -150
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +76 -20
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.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 +18 -5
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.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 +7 -7
- package/dist/src/telemetry/loggers.js +23 -23
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +0 -1
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +72 -18
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +8 -4
- package/dist/src/telemetry/metrics.js +10 -4
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +42 -0
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/telemetryAttributes.js +1 -0
- package/dist/src/telemetry/telemetryAttributes.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +17 -11
- package/dist/src/telemetry/types.js +53 -28
- package/dist/src/telemetry/types.js.map +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/edit.d.ts +1 -1
- package/dist/src/tools/edit.js +31 -33
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +31 -20
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +1 -1
- package/dist/src/tools/glob.js +7 -7
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +20 -17
- 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 +9 -9
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +15 -12
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +1 -1
- package/dist/src/tools/ls.js +14 -15
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +32 -33
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client.js +24 -52
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +18 -0
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +1 -0
- package/dist/src/tools/mcp-tool.js +5 -2
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/memoryTool.js +1 -1
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +1 -1
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.d.ts +5 -1
- package/dist/src/tools/modifiable-tool.js +34 -13
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +56 -22
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +2 -2
- package/dist/src/tools/read-file.js +20 -24
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +63 -51
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +2 -9
- package/dist/src/tools/read-many-files.js +10 -21
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +37 -35
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +25 -8
- package/dist/src/tools/ripGrep.js +148 -176
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +383 -58
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +1 -1
- package/dist/src/tools/shell.js +17 -15
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +66 -36
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +6 -1
- package/dist/src/tools/smart-edit.js +18 -17
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +49 -24
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +29 -4
- package/dist/src/tools/tool-registry.js +108 -29
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +134 -4
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +2 -1
- package/dist/src/tools/tools.js +5 -2
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +2 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +11 -4
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.js +1 -2
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +11 -5
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.js +31 -31
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +24 -5
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +29 -0
- package/dist/src/tools/write-todos.js +34 -1
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/utils/editCorrector.js +4 -15
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +16 -0
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +3 -1
- package/dist/src/utils/editor.js +18 -1
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +11 -0
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/environmentContext.js +3 -1
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +6 -0
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/events.d.ts +14 -11
- package/dist/src/utils/events.js +1 -14
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/extensionLoader.d.ts +8 -0
- package/dist/src/utils/extensionLoader.js +61 -15
- package/dist/src/utils/extensionLoader.js.map +1 -1
- package/dist/src/utils/extensionLoader.test.js +83 -19
- package/dist/src/utils/extensionLoader.test.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +75 -60
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +2 -2
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.d.ts +2 -1
- package/dist/src/utils/googleQuotaErrors.js +20 -12
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- 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/llm-edit-fixer.js +1 -2
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.js +16 -1
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +8 -0
- package/dist/src/utils/memoryDiscovery.js +24 -0
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +43 -1
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +1 -2
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +10 -4
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/pathReader.js +4 -4
- package/dist/src/utils/pathReader.js.map +1 -1
- package/dist/src/utils/pathReader.test.js +44 -1
- package/dist/src/utils/pathReader.test.js.map +1 -1
- package/dist/src/utils/paths.d.ts +1 -1
- package/dist/src/utils/paths.js +5 -3
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/retry.d.ts +0 -9
- package/dist/src/utils/retry.js +24 -28
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +51 -0
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/shell-utils.js +5 -3
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +9 -9
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/summarizer.d.ts +4 -2
- package/dist/src/utils/summarizer.js +6 -8
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +32 -11
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/workspaceContext.d.ts +4 -3
- package/dist/src/utils/workspaceContext.js +10 -11
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +1 -1
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -3,97 +3,57 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { describe, it, expect,
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
7
|
import { ApprovalMode, PolicyDecision } from './types.js';
|
|
8
|
-
import
|
|
8
|
+
import * as fs from 'node:fs/promises';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import * as os from 'node:os';
|
|
11
|
+
import { loadPoliciesFromToml } from './toml-loader.js';
|
|
9
12
|
describe('policy-toml-loader', () => {
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
let tempDir;
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'policy-test-'));
|
|
12
16
|
});
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
afterEach(async () => {
|
|
18
|
+
if (tempDir) {
|
|
19
|
+
await fs.rm(tempDir, {
|
|
20
|
+
recursive: true,
|
|
21
|
+
force: true,
|
|
22
|
+
maxRetries: 3,
|
|
23
|
+
retryDelay: 10,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
16
26
|
});
|
|
27
|
+
async function runLoadPoliciesFromToml(tomlContent, fileName = 'test.toml') {
|
|
28
|
+
await fs.writeFile(path.join(tempDir, fileName), tomlContent);
|
|
29
|
+
const getPolicyTier = (_dir) => 1;
|
|
30
|
+
return loadPoliciesFromToml(ApprovalMode.DEFAULT, [tempDir], getPolicyTier);
|
|
31
|
+
}
|
|
17
32
|
describe('loadPoliciesFromToml', () => {
|
|
18
33
|
it('should load and parse a simple policy file', async () => {
|
|
19
|
-
const
|
|
20
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
21
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
22
|
-
return [
|
|
23
|
-
{
|
|
24
|
-
name: 'test.toml',
|
|
25
|
-
isFile: () => true,
|
|
26
|
-
isDirectory: () => false,
|
|
27
|
-
},
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
|
-
return [];
|
|
31
|
-
});
|
|
32
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
33
|
-
if (nodePath.normalize(path) ===
|
|
34
|
-
nodePath.normalize(nodePath.join('/policies', 'test.toml'))) {
|
|
35
|
-
return `
|
|
34
|
+
const result = await runLoadPoliciesFromToml(`
|
|
36
35
|
[[rule]]
|
|
37
36
|
toolName = "glob"
|
|
38
37
|
decision = "allow"
|
|
39
38
|
priority = 100
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
throw new Error('File not found');
|
|
43
|
-
});
|
|
44
|
-
vi.doMock('node:fs/promises', () => ({
|
|
45
|
-
...actualFs,
|
|
46
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
47
|
-
readFile: mockReadFile,
|
|
48
|
-
readdir: mockReaddir,
|
|
49
|
-
}));
|
|
50
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
51
|
-
const getPolicyTier = (_dir) => 1;
|
|
52
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
39
|
+
`);
|
|
53
40
|
expect(result.rules).toHaveLength(1);
|
|
54
41
|
expect(result.rules[0]).toEqual({
|
|
55
42
|
toolName: 'glob',
|
|
56
43
|
decision: PolicyDecision.ALLOW,
|
|
57
44
|
priority: 1.1, // tier 1 + 100/1000
|
|
58
45
|
});
|
|
46
|
+
expect(result.checkers).toHaveLength(0);
|
|
59
47
|
expect(result.errors).toHaveLength(0);
|
|
60
48
|
});
|
|
61
49
|
it('should expand commandPrefix array to multiple rules', async () => {
|
|
62
|
-
const
|
|
63
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
64
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
65
|
-
return [
|
|
66
|
-
{
|
|
67
|
-
name: 'shell.toml',
|
|
68
|
-
isFile: () => true,
|
|
69
|
-
isDirectory: () => false,
|
|
70
|
-
},
|
|
71
|
-
];
|
|
72
|
-
}
|
|
73
|
-
return [];
|
|
74
|
-
});
|
|
75
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
76
|
-
if (nodePath.normalize(path) ===
|
|
77
|
-
nodePath.normalize(nodePath.join('/policies', 'shell.toml'))) {
|
|
78
|
-
return `
|
|
50
|
+
const result = await runLoadPoliciesFromToml(`
|
|
79
51
|
[[rule]]
|
|
80
52
|
toolName = "run_shell_command"
|
|
81
53
|
commandPrefix = ["git status", "git log"]
|
|
82
54
|
decision = "allow"
|
|
83
55
|
priority = 100
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
throw new Error('File not found');
|
|
87
|
-
});
|
|
88
|
-
vi.doMock('node:fs/promises', () => ({
|
|
89
|
-
...actualFs,
|
|
90
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
91
|
-
readFile: mockReadFile,
|
|
92
|
-
readdir: mockReaddir,
|
|
93
|
-
}));
|
|
94
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
95
|
-
const getPolicyTier = (_dir) => 2;
|
|
96
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
56
|
+
`);
|
|
97
57
|
expect(result.rules).toHaveLength(2);
|
|
98
58
|
expect(result.rules[0].toolName).toBe('run_shell_command');
|
|
99
59
|
expect(result.rules[1].toolName).toBe('run_shell_command');
|
|
@@ -102,41 +62,13 @@ priority = 100
|
|
|
102
62
|
expect(result.errors).toHaveLength(0);
|
|
103
63
|
});
|
|
104
64
|
it('should transform commandRegex to argsPattern', async () => {
|
|
105
|
-
const
|
|
106
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
107
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
108
|
-
return [
|
|
109
|
-
{
|
|
110
|
-
name: 'shell.toml',
|
|
111
|
-
isFile: () => true,
|
|
112
|
-
isDirectory: () => false,
|
|
113
|
-
},
|
|
114
|
-
];
|
|
115
|
-
}
|
|
116
|
-
return [];
|
|
117
|
-
});
|
|
118
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
119
|
-
if (nodePath.normalize(path) ===
|
|
120
|
-
nodePath.normalize(nodePath.join('/policies', 'shell.toml'))) {
|
|
121
|
-
return `
|
|
65
|
+
const result = await runLoadPoliciesFromToml(`
|
|
122
66
|
[[rule]]
|
|
123
67
|
toolName = "run_shell_command"
|
|
124
68
|
commandRegex = "git (status|log).*"
|
|
125
69
|
decision = "allow"
|
|
126
70
|
priority = 100
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
throw new Error('File not found');
|
|
130
|
-
});
|
|
131
|
-
vi.doMock('node:fs/promises', () => ({
|
|
132
|
-
...actualFs,
|
|
133
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
134
|
-
readFile: mockReadFile,
|
|
135
|
-
readdir: mockReaddir,
|
|
136
|
-
}));
|
|
137
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
138
|
-
const getPolicyTier = (_dir) => 2;
|
|
139
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
71
|
+
`);
|
|
140
72
|
expect(result.rules).toHaveLength(1);
|
|
141
73
|
expect(result.rules[0].argsPattern?.test('{"command":"git status"}')).toBe(true);
|
|
142
74
|
expect(result.rules[0].argsPattern?.test('{"command":"git log --all"}')).toBe(true);
|
|
@@ -144,40 +76,12 @@ priority = 100
|
|
|
144
76
|
expect(result.errors).toHaveLength(0);
|
|
145
77
|
});
|
|
146
78
|
it('should expand toolName array', async () => {
|
|
147
|
-
const
|
|
148
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
149
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
150
|
-
return [
|
|
151
|
-
{
|
|
152
|
-
name: 'tools.toml',
|
|
153
|
-
isFile: () => true,
|
|
154
|
-
isDirectory: () => false,
|
|
155
|
-
},
|
|
156
|
-
];
|
|
157
|
-
}
|
|
158
|
-
return [];
|
|
159
|
-
});
|
|
160
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
161
|
-
if (nodePath.normalize(path) ===
|
|
162
|
-
nodePath.normalize(nodePath.join('/policies', 'tools.toml'))) {
|
|
163
|
-
return `
|
|
79
|
+
const result = await runLoadPoliciesFromToml(`
|
|
164
80
|
[[rule]]
|
|
165
81
|
toolName = ["glob", "grep", "read"]
|
|
166
82
|
decision = "allow"
|
|
167
83
|
priority = 100
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
throw new Error('File not found');
|
|
171
|
-
});
|
|
172
|
-
vi.doMock('node:fs/promises', () => ({
|
|
173
|
-
...actualFs,
|
|
174
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
175
|
-
readFile: mockReadFile,
|
|
176
|
-
readdir: mockReaddir,
|
|
177
|
-
}));
|
|
178
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
179
|
-
const getPolicyTier = (_dir) => 1;
|
|
180
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
84
|
+
`);
|
|
181
85
|
expect(result.rules).toHaveLength(3);
|
|
182
86
|
expect(result.rules.map((r) => r.toolName)).toEqual([
|
|
183
87
|
'glob',
|
|
@@ -187,64 +91,20 @@ priority = 100
|
|
|
187
91
|
expect(result.errors).toHaveLength(0);
|
|
188
92
|
});
|
|
189
93
|
it('should transform mcpName to composite toolName', async () => {
|
|
190
|
-
const
|
|
191
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
192
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
193
|
-
return [
|
|
194
|
-
{
|
|
195
|
-
name: 'mcp.toml',
|
|
196
|
-
isFile: () => true,
|
|
197
|
-
isDirectory: () => false,
|
|
198
|
-
},
|
|
199
|
-
];
|
|
200
|
-
}
|
|
201
|
-
return [];
|
|
202
|
-
});
|
|
203
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
204
|
-
if (nodePath.normalize(path) ===
|
|
205
|
-
nodePath.normalize(nodePath.join('/policies', 'mcp.toml'))) {
|
|
206
|
-
return `
|
|
94
|
+
const result = await runLoadPoliciesFromToml(`
|
|
207
95
|
[[rule]]
|
|
208
96
|
mcpName = "google-workspace"
|
|
209
97
|
toolName = ["calendar.list", "calendar.get"]
|
|
210
98
|
decision = "allow"
|
|
211
99
|
priority = 100
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
throw new Error('File not found');
|
|
215
|
-
});
|
|
216
|
-
vi.doMock('node:fs/promises', () => ({
|
|
217
|
-
...actualFs,
|
|
218
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
219
|
-
readFile: mockReadFile,
|
|
220
|
-
readdir: mockReaddir,
|
|
221
|
-
}));
|
|
222
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
223
|
-
const getPolicyTier = (_dir) => 2;
|
|
224
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
100
|
+
`);
|
|
225
101
|
expect(result.rules).toHaveLength(2);
|
|
226
102
|
expect(result.rules[0].toolName).toBe('google-workspace__calendar.list');
|
|
227
103
|
expect(result.rules[1].toolName).toBe('google-workspace__calendar.get');
|
|
228
104
|
expect(result.errors).toHaveLength(0);
|
|
229
105
|
});
|
|
230
106
|
it('should filter rules by mode', async () => {
|
|
231
|
-
const
|
|
232
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
233
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
234
|
-
return [
|
|
235
|
-
{
|
|
236
|
-
name: 'modes.toml',
|
|
237
|
-
isFile: () => true,
|
|
238
|
-
isDirectory: () => false,
|
|
239
|
-
},
|
|
240
|
-
];
|
|
241
|
-
}
|
|
242
|
-
return [];
|
|
243
|
-
});
|
|
244
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
245
|
-
if (nodePath.normalize(path) ===
|
|
246
|
-
nodePath.normalize(nodePath.join('/policies', 'modes.toml'))) {
|
|
247
|
-
return `
|
|
107
|
+
const result = await runLoadPoliciesFromToml(`
|
|
248
108
|
[[rule]]
|
|
249
109
|
toolName = "glob"
|
|
250
110
|
decision = "allow"
|
|
@@ -256,267 +116,261 @@ toolName = "grep"
|
|
|
256
116
|
decision = "allow"
|
|
257
117
|
priority = 100
|
|
258
118
|
modes = ["yolo"]
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
throw new Error('File not found');
|
|
262
|
-
});
|
|
263
|
-
vi.doMock('node:fs/promises', () => ({
|
|
264
|
-
...actualFs,
|
|
265
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
266
|
-
readFile: mockReadFile,
|
|
267
|
-
readdir: mockReaddir,
|
|
268
|
-
}));
|
|
269
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
270
|
-
const getPolicyTier = (_dir) => 1;
|
|
271
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
119
|
+
`);
|
|
272
120
|
// Only the first rule should be included (modes includes "default")
|
|
273
121
|
expect(result.rules).toHaveLength(1);
|
|
274
122
|
expect(result.rules[0].toolName).toBe('glob');
|
|
275
123
|
expect(result.errors).toHaveLength(0);
|
|
276
124
|
});
|
|
277
125
|
it('should handle TOML parse errors', async () => {
|
|
278
|
-
const
|
|
279
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
280
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
281
|
-
return [
|
|
282
|
-
{
|
|
283
|
-
name: 'invalid.toml',
|
|
284
|
-
isFile: () => true,
|
|
285
|
-
isDirectory: () => false,
|
|
286
|
-
},
|
|
287
|
-
];
|
|
288
|
-
}
|
|
289
|
-
return [];
|
|
290
|
-
});
|
|
291
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
292
|
-
if (nodePath.normalize(path) ===
|
|
293
|
-
nodePath.normalize(nodePath.join('/policies', 'invalid.toml'))) {
|
|
294
|
-
return `
|
|
126
|
+
const result = await runLoadPoliciesFromToml(`
|
|
295
127
|
[[rule]
|
|
296
128
|
toolName = "glob"
|
|
297
129
|
decision = "allow"
|
|
298
130
|
priority = 100
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
throw new Error('File not found');
|
|
302
|
-
});
|
|
303
|
-
vi.doMock('node:fs/promises', () => ({
|
|
304
|
-
...actualFs,
|
|
305
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
306
|
-
readFile: mockReadFile,
|
|
307
|
-
readdir: mockReaddir,
|
|
308
|
-
}));
|
|
309
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
310
|
-
const getPolicyTier = (_dir) => 1;
|
|
311
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
131
|
+
`);
|
|
312
132
|
expect(result.rules).toHaveLength(0);
|
|
313
133
|
expect(result.errors).toHaveLength(1);
|
|
314
134
|
expect(result.errors[0].errorType).toBe('toml_parse');
|
|
315
|
-
expect(result.errors[0].fileName).toBe('
|
|
135
|
+
expect(result.errors[0].fileName).toBe('test.toml');
|
|
316
136
|
});
|
|
317
137
|
it('should handle schema validation errors', async () => {
|
|
318
|
-
const
|
|
319
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
320
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
321
|
-
return [
|
|
322
|
-
{
|
|
323
|
-
name: 'invalid.toml',
|
|
324
|
-
isFile: () => true,
|
|
325
|
-
isDirectory: () => false,
|
|
326
|
-
},
|
|
327
|
-
];
|
|
328
|
-
}
|
|
329
|
-
return [];
|
|
330
|
-
});
|
|
331
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
332
|
-
if (nodePath.normalize(path) ===
|
|
333
|
-
nodePath.normalize(nodePath.join('/policies', 'invalid.toml'))) {
|
|
334
|
-
return `
|
|
138
|
+
const result = await runLoadPoliciesFromToml(`
|
|
335
139
|
[[rule]]
|
|
336
140
|
toolName = "glob"
|
|
337
141
|
priority = 100
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
throw new Error('File not found');
|
|
341
|
-
});
|
|
342
|
-
vi.doMock('node:fs/promises', () => ({
|
|
343
|
-
...actualFs,
|
|
344
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
345
|
-
readFile: mockReadFile,
|
|
346
|
-
readdir: mockReaddir,
|
|
347
|
-
}));
|
|
348
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
349
|
-
const getPolicyTier = (_dir) => 1;
|
|
350
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
142
|
+
`);
|
|
351
143
|
expect(result.rules).toHaveLength(0);
|
|
352
144
|
expect(result.errors).toHaveLength(1);
|
|
353
145
|
expect(result.errors[0].errorType).toBe('schema_validation');
|
|
354
146
|
expect(result.errors[0].details).toContain('decision');
|
|
355
147
|
});
|
|
356
148
|
it('should reject commandPrefix without run_shell_command', async () => {
|
|
357
|
-
const
|
|
358
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
359
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
360
|
-
return [
|
|
361
|
-
{
|
|
362
|
-
name: 'invalid.toml',
|
|
363
|
-
isFile: () => true,
|
|
364
|
-
isDirectory: () => false,
|
|
365
|
-
},
|
|
366
|
-
];
|
|
367
|
-
}
|
|
368
|
-
return [];
|
|
369
|
-
});
|
|
370
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
371
|
-
if (nodePath.normalize(path) ===
|
|
372
|
-
nodePath.normalize(nodePath.join('/policies', 'invalid.toml'))) {
|
|
373
|
-
return `
|
|
149
|
+
const result = await runLoadPoliciesFromToml(`
|
|
374
150
|
[[rule]]
|
|
375
151
|
toolName = "glob"
|
|
376
152
|
commandPrefix = "git status"
|
|
377
153
|
decision = "allow"
|
|
378
154
|
priority = 100
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
throw new Error('File not found');
|
|
382
|
-
});
|
|
383
|
-
vi.doMock('node:fs/promises', () => ({
|
|
384
|
-
...actualFs,
|
|
385
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
386
|
-
readFile: mockReadFile,
|
|
387
|
-
readdir: mockReaddir,
|
|
388
|
-
}));
|
|
389
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
390
|
-
const getPolicyTier = (_dir) => 1;
|
|
391
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
155
|
+
`);
|
|
392
156
|
expect(result.errors).toHaveLength(1);
|
|
393
157
|
expect(result.errors[0].errorType).toBe('rule_validation');
|
|
394
158
|
expect(result.errors[0].details).toContain('run_shell_command');
|
|
395
159
|
});
|
|
396
160
|
it('should reject commandPrefix + argsPattern combination', async () => {
|
|
397
|
-
const
|
|
398
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
399
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
400
|
-
return [
|
|
401
|
-
{
|
|
402
|
-
name: 'invalid.toml',
|
|
403
|
-
isFile: () => true,
|
|
404
|
-
isDirectory: () => false,
|
|
405
|
-
},
|
|
406
|
-
];
|
|
407
|
-
}
|
|
408
|
-
return [];
|
|
409
|
-
});
|
|
410
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
411
|
-
if (nodePath.normalize(path) ===
|
|
412
|
-
nodePath.normalize(nodePath.join('/policies', 'invalid.toml'))) {
|
|
413
|
-
return `
|
|
161
|
+
const result = await runLoadPoliciesFromToml(`
|
|
414
162
|
[[rule]]
|
|
415
163
|
toolName = "run_shell_command"
|
|
416
164
|
commandPrefix = "git status"
|
|
417
165
|
argsPattern = "test"
|
|
418
166
|
decision = "allow"
|
|
419
167
|
priority = 100
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
throw new Error('File not found');
|
|
423
|
-
});
|
|
424
|
-
vi.doMock('node:fs/promises', () => ({
|
|
425
|
-
...actualFs,
|
|
426
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
427
|
-
readFile: mockReadFile,
|
|
428
|
-
readdir: mockReaddir,
|
|
429
|
-
}));
|
|
430
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
431
|
-
const getPolicyTier = (_dir) => 1;
|
|
432
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
168
|
+
`);
|
|
433
169
|
expect(result.errors).toHaveLength(1);
|
|
434
170
|
expect(result.errors[0].errorType).toBe('rule_validation');
|
|
435
171
|
expect(result.errors[0].details).toContain('mutually exclusive');
|
|
436
172
|
});
|
|
437
173
|
it('should handle invalid regex patterns', async () => {
|
|
438
|
-
const
|
|
439
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
440
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
441
|
-
return [
|
|
442
|
-
{
|
|
443
|
-
name: 'invalid.toml',
|
|
444
|
-
isFile: () => true,
|
|
445
|
-
isDirectory: () => false,
|
|
446
|
-
},
|
|
447
|
-
];
|
|
448
|
-
}
|
|
449
|
-
return [];
|
|
450
|
-
});
|
|
451
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
452
|
-
if (nodePath.normalize(path) ===
|
|
453
|
-
nodePath.normalize(nodePath.join('/policies', 'invalid.toml'))) {
|
|
454
|
-
return `
|
|
174
|
+
const result = await runLoadPoliciesFromToml(`
|
|
455
175
|
[[rule]]
|
|
456
176
|
toolName = "run_shell_command"
|
|
457
177
|
commandRegex = "git (status|branch"
|
|
458
178
|
decision = "allow"
|
|
459
179
|
priority = 100
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
throw new Error('File not found');
|
|
463
|
-
});
|
|
464
|
-
vi.doMock('node:fs/promises', () => ({
|
|
465
|
-
...actualFs,
|
|
466
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
467
|
-
readFile: mockReadFile,
|
|
468
|
-
readdir: mockReaddir,
|
|
469
|
-
}));
|
|
470
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
471
|
-
const getPolicyTier = (_dir) => 1;
|
|
472
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
180
|
+
`);
|
|
473
181
|
expect(result.rules).toHaveLength(0);
|
|
474
182
|
expect(result.errors).toHaveLength(1);
|
|
475
183
|
expect(result.errors[0].errorType).toBe('regex_compilation');
|
|
476
184
|
expect(result.errors[0].details).toContain('git (status|branch');
|
|
477
185
|
});
|
|
478
186
|
it('should escape regex special characters in commandPrefix', async () => {
|
|
479
|
-
const
|
|
480
|
-
const mockReaddir = vi.fn(async (path, _options) => {
|
|
481
|
-
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
|
|
482
|
-
return [
|
|
483
|
-
{
|
|
484
|
-
name: 'shell.toml',
|
|
485
|
-
isFile: () => true,
|
|
486
|
-
isDirectory: () => false,
|
|
487
|
-
},
|
|
488
|
-
];
|
|
489
|
-
}
|
|
490
|
-
return [];
|
|
491
|
-
});
|
|
492
|
-
const mockReadFile = vi.fn(async (path) => {
|
|
493
|
-
if (nodePath.normalize(path) ===
|
|
494
|
-
nodePath.normalize(nodePath.join('/policies', 'shell.toml'))) {
|
|
495
|
-
return `
|
|
187
|
+
const result = await runLoadPoliciesFromToml(`
|
|
496
188
|
[[rule]]
|
|
497
189
|
toolName = "run_shell_command"
|
|
498
190
|
commandPrefix = "git log *.txt"
|
|
499
191
|
decision = "allow"
|
|
500
192
|
priority = 100
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
throw new Error('File not found');
|
|
504
|
-
});
|
|
505
|
-
vi.doMock('node:fs/promises', () => ({
|
|
506
|
-
...actualFs,
|
|
507
|
-
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
|
|
508
|
-
readFile: mockReadFile,
|
|
509
|
-
readdir: mockReaddir,
|
|
510
|
-
}));
|
|
511
|
-
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
|
|
512
|
-
const getPolicyTier = (_dir) => 1;
|
|
513
|
-
const result = await load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
|
|
193
|
+
`);
|
|
514
194
|
expect(result.rules).toHaveLength(1);
|
|
515
195
|
// The regex should have escaped the * and .
|
|
516
196
|
expect(result.rules[0].argsPattern?.test('{"command":"git log file.txt"}')).toBe(false);
|
|
517
197
|
expect(result.rules[0].argsPattern?.test('{"command":"git log *.txt"}')).toBe(true);
|
|
518
198
|
expect(result.errors).toHaveLength(0);
|
|
519
199
|
});
|
|
200
|
+
it('should handle a mix of valid and invalid policy files', async () => {
|
|
201
|
+
await fs.writeFile(path.join(tempDir, 'valid.toml'), `
|
|
202
|
+
[[rule]]
|
|
203
|
+
toolName = "glob"
|
|
204
|
+
decision = "allow"
|
|
205
|
+
priority = 100
|
|
206
|
+
`);
|
|
207
|
+
await fs.writeFile(path.join(tempDir, 'invalid.toml'), `
|
|
208
|
+
[[rule]]
|
|
209
|
+
toolName = "grep"
|
|
210
|
+
decision = "allow"
|
|
211
|
+
priority = -1
|
|
212
|
+
`);
|
|
213
|
+
const getPolicyTier = (_dir) => 1;
|
|
214
|
+
const result = await loadPoliciesFromToml(ApprovalMode.DEFAULT, [tempDir], getPolicyTier);
|
|
215
|
+
expect(result.rules).toHaveLength(1);
|
|
216
|
+
expect(result.rules[0].toolName).toBe('glob');
|
|
217
|
+
expect(result.errors).toHaveLength(1);
|
|
218
|
+
expect(result.errors[0].fileName).toBe('invalid.toml');
|
|
219
|
+
expect(result.errors[0].errorType).toBe('schema_validation');
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe('Negative Tests', () => {
|
|
223
|
+
it('should return a schema_validation error if priority is missing', async () => {
|
|
224
|
+
const result = await runLoadPoliciesFromToml(`
|
|
225
|
+
[[rule]]
|
|
226
|
+
toolName = "test"
|
|
227
|
+
decision = "allow"
|
|
228
|
+
`);
|
|
229
|
+
expect(result.errors).toHaveLength(1);
|
|
230
|
+
const error = result.errors[0];
|
|
231
|
+
expect(error.errorType).toBe('schema_validation');
|
|
232
|
+
expect(error.details).toContain('priority');
|
|
233
|
+
});
|
|
234
|
+
it('should return a schema_validation error if priority is a float', async () => {
|
|
235
|
+
const result = await runLoadPoliciesFromToml(`
|
|
236
|
+
[[rule]]
|
|
237
|
+
toolName = "test"
|
|
238
|
+
decision = "allow"
|
|
239
|
+
priority = 1.5
|
|
240
|
+
`);
|
|
241
|
+
expect(result.errors).toHaveLength(1);
|
|
242
|
+
const error = result.errors[0];
|
|
243
|
+
expect(error.errorType).toBe('schema_validation');
|
|
244
|
+
expect(error.details).toContain('priority');
|
|
245
|
+
expect(error.details).toContain('integer');
|
|
246
|
+
});
|
|
247
|
+
it('should return a schema_validation error if priority is negative', async () => {
|
|
248
|
+
const result = await runLoadPoliciesFromToml(`
|
|
249
|
+
[[rule]]
|
|
250
|
+
toolName = "test"
|
|
251
|
+
decision = "allow"
|
|
252
|
+
priority = -1
|
|
253
|
+
`);
|
|
254
|
+
expect(result.errors).toHaveLength(1);
|
|
255
|
+
const error = result.errors[0];
|
|
256
|
+
expect(error.errorType).toBe('schema_validation');
|
|
257
|
+
expect(error.details).toContain('priority');
|
|
258
|
+
expect(error.details).toContain('>= 0');
|
|
259
|
+
});
|
|
260
|
+
it('should return a schema_validation error if priority is much lower than 0', async () => {
|
|
261
|
+
const result = await runLoadPoliciesFromToml(`
|
|
262
|
+
[[rule]]
|
|
263
|
+
toolName = "test"
|
|
264
|
+
decision = "allow"
|
|
265
|
+
priority = -9999
|
|
266
|
+
`);
|
|
267
|
+
expect(result.errors).toHaveLength(1);
|
|
268
|
+
const error = result.errors[0];
|
|
269
|
+
expect(error.errorType).toBe('schema_validation');
|
|
270
|
+
expect(error.details).toContain('priority');
|
|
271
|
+
expect(error.details).toContain('>= 0');
|
|
272
|
+
});
|
|
273
|
+
it('should return a schema_validation error if priority is >= 1000', async () => {
|
|
274
|
+
const result = await runLoadPoliciesFromToml(`
|
|
275
|
+
[[rule]]
|
|
276
|
+
toolName = "test"
|
|
277
|
+
decision = "allow"
|
|
278
|
+
priority = 1000
|
|
279
|
+
`);
|
|
280
|
+
expect(result.errors).toHaveLength(1);
|
|
281
|
+
const error = result.errors[0];
|
|
282
|
+
expect(error.errorType).toBe('schema_validation');
|
|
283
|
+
expect(error.details).toContain('priority');
|
|
284
|
+
expect(error.details).toContain('<= 999');
|
|
285
|
+
});
|
|
286
|
+
it('should return a schema_validation error if priority is much higher than 1000', async () => {
|
|
287
|
+
const result = await runLoadPoliciesFromToml(`
|
|
288
|
+
[[rule]]
|
|
289
|
+
toolName = "test"
|
|
290
|
+
decision = "allow"
|
|
291
|
+
priority = 9999
|
|
292
|
+
`);
|
|
293
|
+
expect(result.errors).toHaveLength(1);
|
|
294
|
+
const error = result.errors[0];
|
|
295
|
+
expect(error.errorType).toBe('schema_validation');
|
|
296
|
+
expect(error.details).toContain('priority');
|
|
297
|
+
expect(error.details).toContain('<= 999');
|
|
298
|
+
});
|
|
299
|
+
it('should return a schema_validation error if decision is invalid', async () => {
|
|
300
|
+
const result = await runLoadPoliciesFromToml(`
|
|
301
|
+
[[rule]]
|
|
302
|
+
toolName = "test"
|
|
303
|
+
decision = "maybe"
|
|
304
|
+
priority = 100
|
|
305
|
+
`);
|
|
306
|
+
expect(result.errors).toHaveLength(1);
|
|
307
|
+
const error = result.errors[0];
|
|
308
|
+
expect(error.errorType).toBe('schema_validation');
|
|
309
|
+
expect(error.details).toContain('decision');
|
|
310
|
+
});
|
|
311
|
+
it('should return a schema_validation error if toolName is not a string or array', async () => {
|
|
312
|
+
const result = await runLoadPoliciesFromToml(`
|
|
313
|
+
[[rule]]
|
|
314
|
+
toolName = 123
|
|
315
|
+
decision = "allow"
|
|
316
|
+
priority = 100
|
|
317
|
+
`);
|
|
318
|
+
expect(result.errors).toHaveLength(1);
|
|
319
|
+
const error = result.errors[0];
|
|
320
|
+
expect(error.errorType).toBe('schema_validation');
|
|
321
|
+
expect(error.details).toContain('toolName');
|
|
322
|
+
});
|
|
323
|
+
it('should return a rule_validation error if commandRegex is used with wrong toolName', async () => {
|
|
324
|
+
const result = await runLoadPoliciesFromToml(`
|
|
325
|
+
[[rule]]
|
|
326
|
+
toolName = "not_shell"
|
|
327
|
+
commandRegex = ".*"
|
|
328
|
+
decision = "allow"
|
|
329
|
+
priority = 100
|
|
330
|
+
`);
|
|
331
|
+
expect(result.errors).toHaveLength(1);
|
|
332
|
+
const error = result.errors[0];
|
|
333
|
+
expect(error.errorType).toBe('rule_validation');
|
|
334
|
+
expect(error.details).toContain('run_shell_command');
|
|
335
|
+
});
|
|
336
|
+
it('should return a rule_validation error if commandPrefix and commandRegex are combined', async () => {
|
|
337
|
+
const result = await runLoadPoliciesFromToml(`
|
|
338
|
+
[[rule]]
|
|
339
|
+
toolName = "run_shell_command"
|
|
340
|
+
commandPrefix = "git"
|
|
341
|
+
commandRegex = ".*"
|
|
342
|
+
decision = "allow"
|
|
343
|
+
priority = 100
|
|
344
|
+
`);
|
|
345
|
+
expect(result.errors).toHaveLength(1);
|
|
346
|
+
const error = result.errors[0];
|
|
347
|
+
expect(error.errorType).toBe('rule_validation');
|
|
348
|
+
expect(error.details).toContain('mutually exclusive');
|
|
349
|
+
});
|
|
350
|
+
it('should return a regex_compilation error for invalid argsPattern', async () => {
|
|
351
|
+
const result = await runLoadPoliciesFromToml(`
|
|
352
|
+
[[rule]]
|
|
353
|
+
toolName = "test"
|
|
354
|
+
argsPattern = "([a-z)"
|
|
355
|
+
decision = "allow"
|
|
356
|
+
priority = 100
|
|
357
|
+
`);
|
|
358
|
+
expect(result.errors).toHaveLength(1);
|
|
359
|
+
const error = result.errors[0];
|
|
360
|
+
expect(error.errorType).toBe('regex_compilation');
|
|
361
|
+
expect(error.message).toBe('Invalid regex pattern');
|
|
362
|
+
});
|
|
363
|
+
it('should return a file_read error if readdir fails', async () => {
|
|
364
|
+
// Create a file and pass it as a directory to trigger ENOTDIR
|
|
365
|
+
const filePath = path.join(tempDir, 'not-a-dir');
|
|
366
|
+
await fs.writeFile(filePath, 'content');
|
|
367
|
+
const getPolicyTier = (_dir) => 1;
|
|
368
|
+
const result = await loadPoliciesFromToml(ApprovalMode.DEFAULT, [filePath], getPolicyTier);
|
|
369
|
+
expect(result.errors).toHaveLength(1);
|
|
370
|
+
const error = result.errors[0];
|
|
371
|
+
expect(error.errorType).toBe('file_read');
|
|
372
|
+
expect(error.message).toContain('Failed to read policy directory');
|
|
373
|
+
});
|
|
520
374
|
});
|
|
521
375
|
});
|
|
522
376
|
//# sourceMappingURL=toml-loader.test.js.map
|