@machina.ai/cell-cli-core 1.10.0-rc1 → 1.13.0-rc1
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 +5 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/package.json +13 -5
- package/dist/src/agents/codebase-investigator.js +2 -5
- package/dist/src/agents/codebase-investigator.js.map +1 -1
- package/dist/src/agents/executor.d.ts +19 -0
- package/dist/src/agents/executor.js +234 -46
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js +371 -40
- package/dist/src/agents/executor.test.js.map +1 -1
- package/dist/src/agents/registry.js +4 -3
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.test.js +2 -4
- package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
- package/dist/src/agents/types.d.ts +2 -1
- package/dist/src/agents/types.js +1 -0
- package/dist/src/agents/types.js.map +1 -1
- package/dist/src/code_assist/converter.d.ts +1 -0
- package/dist/src/code_assist/converter.js +1 -0
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +19 -0
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/experiments/client_metadata.d.ts +12 -0
- package/dist/src/code_assist/experiments/client_metadata.js +49 -0
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.d.ts +17 -0
- package/dist/src/code_assist/experiments/experiments.js +36 -0
- package/dist/src/code_assist/experiments/experiments.js.map +1 -0
- package/dist/src/code_assist/experiments/types.d.ts +35 -0
- package/dist/src/code_assist/experiments/types.js +7 -0
- package/dist/src/code_assist/experiments/types.js.map +1 -0
- package/dist/src/code_assist/oauth-credential-storage.js +5 -4
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +15 -3
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -2
- package/dist/src/code_assist/oauth2.js +64 -51
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +65 -33
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +6 -4
- package/dist/src/code_assist/server.js +11 -0
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +17 -0
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.d.ts +2 -2
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +1 -1
- package/dist/src/code_assist/types.js.map +1 -1
- package/dist/src/commands/extensions.d.ts +7 -0
- package/dist/src/commands/extensions.js +9 -0
- package/dist/src/commands/extensions.js.map +1 -0
- package/dist/src/commands/extensions.test.js +19 -0
- package/dist/src/commands/extensions.test.js.map +1 -0
- package/dist/src/config/config.d.ts +81 -32
- package/dist/src/config/config.js +193 -66
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +115 -36
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -1
- package/dist/src/config/models.js +2 -2
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/storage.d.ts +3 -0
- package/dist/src/config/storage.js +20 -0
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.d.ts +2 -1
- package/dist/src/confirmation-bus/message-bus.js +7 -1
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +12 -2
- package/dist/src/confirmation-bus/types.js +1 -0
- package/dist/src/confirmation-bus/types.js.map +1 -1
- package/dist/src/core/apiKeyCredentialStorage.d.ts +17 -0
- package/dist/src/core/apiKeyCredentialStorage.js +64 -0
- package/dist/src/core/apiKeyCredentialStorage.js.map +1 -0
- package/dist/src/core/apiKeyCredentialStorage.test.d.ts +6 -0
- package/dist/src/core/apiKeyCredentialStorage.test.js +71 -0
- package/dist/src/core/apiKeyCredentialStorage.test.js.map +1 -0
- package/dist/src/core/client.d.ts +2 -11
- package/dist/src/core/client.js +31 -170
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +107 -429
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +64 -59
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +38 -4
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +8 -2
- package/dist/src/core/coreToolScheduler.js +337 -172
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +363 -12
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/fakeContentGenerator.d.ts +33 -0
- package/dist/src/core/fakeContentGenerator.js +58 -0
- package/dist/src/core/fakeContentGenerator.js.map +1 -0
- package/dist/src/core/fakeContentGenerator.test.d.ts +6 -0
- package/dist/src/core/fakeContentGenerator.test.js +127 -0
- package/dist/src/core/fakeContentGenerator.test.js.map +1 -0
- package/dist/src/core/geminiChat.d.ts +2 -0
- package/dist/src/core/geminiChat.js +7 -2
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +15 -3
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/logger.js +21 -19
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.d.ts +1 -0
- package/dist/src/core/loggingContentGenerator.js +113 -33
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.js +5 -4
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +3 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +115 -72
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +30 -108
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/recordingContentGenerator.d.ts +18 -0
- package/dist/src/core/recordingContentGenerator.js +77 -0
- package/dist/src/core/recordingContentGenerator.js.map +1 -0
- package/dist/src/core/recordingContentGenerator.test.d.ts +6 -0
- package/dist/src/core/recordingContentGenerator.test.js +101 -0
- package/dist/src/core/recordingContentGenerator.test.js.map +1 -0
- package/dist/src/core/turn.d.ts +2 -0
- package/dist/src/core/turn.js +3 -1
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +48 -0
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/fallback/handler.js +2 -0
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookPlanner.d.ts +46 -0
- package/dist/src/hooks/hookPlanner.js +108 -0
- package/dist/src/hooks/hookPlanner.js.map +1 -0
- package/dist/src/hooks/hookPlanner.test.d.ts +6 -0
- package/dist/src/hooks/hookPlanner.test.js +255 -0
- package/dist/src/hooks/hookPlanner.test.js.map +1 -0
- package/dist/src/hooks/hookRegistry.d.ts +87 -0
- package/dist/src/hooks/hookRegistry.js +198 -0
- package/dist/src/hooks/hookRegistry.js.map +1 -0
- package/dist/src/hooks/hookRegistry.test.d.ts +6 -0
- package/dist/src/hooks/hookRegistry.test.js +341 -0
- package/dist/src/hooks/hookRegistry.test.js.map +1 -0
- package/dist/src/hooks/hookTranslator.d.ts +113 -0
- package/dist/src/hooks/hookTranslator.js +232 -0
- package/dist/src/hooks/hookTranslator.js.map +1 -0
- package/dist/src/hooks/hookTranslator.test.d.ts +6 -0
- package/dist/src/hooks/hookTranslator.test.js +192 -0
- package/dist/src/hooks/hookTranslator.test.js.map +1 -0
- package/dist/src/hooks/types.d.ts +384 -0
- package/dist/src/hooks/types.js +284 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/hooks/types.test.d.ts +6 -0
- package/dist/src/hooks/types.test.js +35 -0
- package/dist/src/hooks/types.test.js.map +1 -0
- package/dist/src/ide/ide-client.js +2 -1
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.d.ts +2 -0
- package/dist/src/mcp/google-auth-provider.js +21 -3
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.test.js +42 -9
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/mcpLauncher.d.ts +26 -0
- package/dist/src/mcp/mcpLauncher.js +238 -0
- package/dist/src/mcp/mcpLauncher.js.map +1 -0
- package/dist/src/mcp/oauth-provider.d.ts +8 -5
- package/dist/src/mcp/oauth-provider.js +140 -55
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +191 -2
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.js +5 -4
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.test.js +17 -11
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.d.ts +7 -0
- package/dist/src/mcp/oauth-utils.js +28 -8
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +45 -2
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.d.ts +0 -6
- package/dist/src/mcp/sa-impersonation-provider.js +6 -23
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
- package/dist/src/mcp/token-storage/base-token-storage.test.js +75 -84
- package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.test.js +7 -5
- package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js +2 -2
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +6 -2
- package/dist/src/mcp/token-storage/keychain-token-storage.js +63 -7
- package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js +54 -3
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/types.d.ts +6 -0
- package/dist/src/mcp/token-storage/types.js.map +1 -1
- package/dist/src/output/stream-json-formatter.d.ts +32 -0
- package/dist/src/output/stream-json-formatter.js +52 -0
- package/dist/src/output/stream-json-formatter.js.map +1 -0
- package/dist/src/output/stream-json-formatter.test.d.ts +6 -0
- package/dist/src/output/stream-json-formatter.test.js +479 -0
- package/dist/src/output/stream-json-formatter.test.js.map +1 -0
- package/dist/src/output/types.d.ts +63 -1
- package/dist/src/output/types.js +11 -0
- package/dist/src/output/types.js.map +1 -1
- package/dist/src/policy/config.d.ts +31 -0
- package/dist/src/policy/config.js +197 -0
- package/dist/src/policy/config.js.map +1 -0
- package/dist/src/policy/config.test.d.ts +6 -0
- package/dist/src/policy/config.test.js +404 -0
- package/dist/src/policy/config.test.js.map +1 -0
- package/dist/src/policy/index.d.ts +2 -0
- package/dist/src/policy/index.js +2 -0
- package/dist/src/policy/index.js.map +1 -1
- package/dist/src/policy/policies/read-only.toml +56 -0
- package/dist/src/policy/policies/write.toml +63 -0
- package/dist/src/policy/policies/yolo.toml +31 -0
- package/dist/src/policy/policy-engine.js +4 -0
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/toml-loader.d.ts +46 -0
- package/dist/src/policy/toml-loader.js +314 -0
- package/dist/src/policy/toml-loader.js.map +1 -0
- package/dist/src/policy/toml-loader.test.d.ts +6 -0
- package/dist/src/policy/toml-loader.test.js +522 -0
- package/dist/src/policy/toml-loader.test.js.map +1 -0
- package/dist/src/policy/types.d.ts +18 -0
- package/dist/src/policy/types.js +6 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/prompts/prompt-registry.js +2 -1
- package/dist/src/prompts/prompt-registry.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +3 -2
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/services/chatCompressionService.d.ts +32 -0
- package/dist/src/services/chatCompressionService.js +162 -0
- package/dist/src/services/chatCompressionService.js.map +1 -0
- package/dist/src/services/chatCompressionService.test.d.ts +6 -0
- package/dist/src/services/chatCompressionService.test.js +209 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -0
- package/dist/src/services/chatRecordingService.js +9 -8
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.d.ts +2 -14
- package/dist/src/services/fileDiscoveryService.js +19 -55
- package/dist/src/services/fileDiscoveryService.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.test.js +91 -11
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +1 -1
- package/dist/src/services/loopDetectionService.js +27 -13
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +119 -11
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +50 -23
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +82 -15
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/activity-monitor.d.ts +116 -0
- package/dist/src/telemetry/activity-monitor.js +209 -0
- package/dist/src/telemetry/activity-monitor.js.map +1 -0
- package/dist/src/telemetry/activity-monitor.test.d.ts +6 -0
- package/dist/src/telemetry/activity-monitor.test.js +248 -0
- package/dist/src/telemetry/activity-monitor.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +5 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +135 -57
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +43 -75
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +7 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +13 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.js +0 -1
- package/dist/src/telemetry/gcp-exporters.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.test.js +1 -1
- package/dist/src/telemetry/gcp-exporters.test.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +4 -2
- package/dist/src/telemetry/index.js +5 -3
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +37 -26
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +215 -56
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +55 -6
- package/dist/src/telemetry/metrics.js +89 -1
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +172 -213
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.js +3 -2
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/semantic.d.ts +82 -0
- package/dist/src/telemetry/semantic.js +269 -0
- package/dist/src/telemetry/semantic.js.map +1 -0
- package/dist/src/telemetry/semantic.test.d.ts +6 -0
- package/dist/src/telemetry/semantic.test.js +387 -0
- package/dist/src/telemetry/semantic.test.js.map +1 -0
- package/dist/src/telemetry/telemetry-utils.test.js +29 -28
- package/dist/src/telemetry/telemetry-utils.test.js.map +1 -1
- package/dist/src/telemetry/trace.d.ts +46 -0
- package/dist/src/telemetry/trace.js +121 -0
- package/dist/src/telemetry/trace.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +79 -34
- package/dist/src/telemetry/types.js +191 -61
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.js +6 -6
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +88 -66
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/tools/edit.d.ts +3 -2
- package/dist/src/tools/edit.js +24 -19
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +78 -2
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +3 -2
- package/dist/src/tools/glob.js +15 -19
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +203 -199
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +3 -2
- package/dist/src/tools/grep.js +22 -16
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/ls.d.ts +3 -2
- package/dist/src/tools/ls.js +15 -20
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +2 -9
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +49 -11
- package/dist/src/tools/mcp-client-manager.js +209 -31
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +132 -25
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +5 -1
- package/dist/src/tools/mcp-client.js +85 -104
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +65 -6
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +5 -2
- package/dist/src/tools/mcp-tool.js +16 -8
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +6 -4
- package/dist/src/tools/memoryTool.js +13 -10
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/message-bus-integration.test.js +14 -1
- package/dist/src/tools/message-bus-integration.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.js +3 -2
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +4 -3
- package/dist/src/tools/read-file.js +16 -11
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +25 -2
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +4 -3
- package/dist/src/tools/read-many-files.js +19 -37
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +0 -1
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +3 -2
- package/dist/src/tools/ripGrep.js +47 -17
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +106 -60
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +7 -5
- package/dist/src/tools/shell.js +39 -68
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +69 -9
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +3 -2
- package/dist/src/tools/smart-edit.js +30 -18
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +62 -2
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +8 -0
- package/dist/src/tools/tool-names.js +8 -5
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +6 -19
- package/dist/src/tools/tool-registry.js +14 -49
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +2 -24
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +22 -8
- package/dist/src/tools/tools.js +65 -36
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +4 -3
- package/dist/src/tools/web-fetch.js +37 -25
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +262 -1
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.d.ts +4 -3
- package/dist/src/tools/web-search.js +8 -6
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +3 -2
- package/dist/src/tools/write-file.js +8 -8
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +1 -2
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +4 -8
- package/dist/src/tools/write-todos.js +15 -6
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/tools/write-todos.test.js +2 -2
- package/dist/src/tools/write-todos.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.js +3 -2
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/channel.d.ts +19 -0
- package/dist/src/utils/channel.js +49 -0
- package/dist/src/utils/channel.js.map +1 -0
- package/dist/src/utils/channel.test.d.ts +6 -0
- package/dist/src/utils/channel.test.js +170 -0
- package/dist/src/utils/channel.test.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +25 -0
- package/dist/src/utils/debugLogger.js +33 -0
- package/dist/src/utils/debugLogger.js.map +1 -0
- package/dist/src/utils/debugLogger.test.d.ts +6 -0
- package/dist/src/utils/debugLogger.test.js +67 -0
- package/dist/src/utils/debugLogger.test.js.map +1 -0
- package/dist/src/utils/delay.d.ts +16 -0
- package/dist/src/utils/delay.js +43 -0
- package/dist/src/utils/delay.js.map +1 -0
- package/dist/src/utils/delay.test.d.ts +6 -0
- package/dist/src/utils/delay.test.js +88 -0
- package/dist/src/utils/delay.test.js.map +1 -0
- package/dist/src/utils/editCorrector.js +5 -9
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +3 -5
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.js +33 -38
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +2 -1
- package/dist/src/utils/environmentContext.js +18 -33
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +0 -34
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/errorParsing.d.ts +1 -1
- package/dist/src/utils/errorParsing.js +5 -33
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +0 -88
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/errors.d.ts +3 -0
- package/dist/src/utils/errors.js +6 -0
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/events.d.ts +88 -0
- package/dist/src/utils/events.js +77 -0
- package/dist/src/utils/events.js.map +1 -0
- package/dist/src/utils/events.test.d.ts +6 -0
- package/dist/src/utils/events.test.js +131 -0
- package/dist/src/utils/events.test.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +78 -0
- package/dist/src/utils/extensionLoader.js +162 -0
- package/dist/src/utils/extensionLoader.js.map +1 -0
- package/dist/src/utils/extensionLoader.test.d.ts +6 -0
- package/dist/src/utils/extensionLoader.test.js +90 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +1 -0
- package/dist/src/utils/fetch.js +4 -0
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +4 -0
- package/dist/src/utils/fileUtils.js +34 -2
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +12 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +26 -45
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/getFolderStructure.js +9 -17
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.d.ts +4 -1
- package/dist/src/utils/gitIgnoreParser.js +28 -10
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.test.js +58 -0
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/googleErrors.d.ts +104 -0
- package/dist/src/utils/googleErrors.js +152 -0
- package/dist/src/utils/googleErrors.js.map +1 -0
- package/dist/src/utils/googleErrors.test.d.ts +6 -0
- package/dist/src/utils/googleErrors.test.js +301 -0
- package/dist/src/utils/googleErrors.test.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.d.ts +36 -0
- package/dist/src/utils/googleQuotaErrors.js +149 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
- package/dist/src/utils/googleQuotaErrors.test.js +311 -0
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
- package/dist/src/utils/ignorePatterns.test.js +26 -30
- package/dist/src/utils/ignorePatterns.test.js.map +1 -1
- package/dist/src/utils/installationManager.js +2 -1
- package/dist/src/utils/installationManager.js.map +1 -1
- package/dist/src/utils/installationManager.test.js +3 -3
- package/dist/src/utils/installationManager.test.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.d.ts +1 -1
- package/dist/src/utils/llm-edit-fixer.js +29 -4
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.js +21 -0
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +11 -1
- package/dist/src/utils/memoryDiscovery.js +150 -11
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +157 -19
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +3 -2
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +2 -1
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/package.d.ts +12 -0
- package/dist/src/utils/package.js +15 -0
- package/dist/src/utils/package.js.map +1 -0
- package/dist/src/utils/paths.js +126 -26
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/paths.test.js +200 -68
- package/dist/src/utils/paths.test.js.map +1 -1
- package/dist/src/utils/quotaErrorDetection.d.ts +0 -2
- package/dist/src/utils/quotaErrorDetection.js +0 -46
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/retry.d.ts +1 -0
- package/dist/src/utils/retry.js +57 -158
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +48 -109
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/safeJsonStringify.d.ts +4 -4
- package/dist/src/utils/safeJsonStringify.js +31 -7
- package/dist/src/utils/safeJsonStringify.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +14 -2
- package/dist/src/utils/shell-utils.js +381 -136
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +242 -60
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/summarizer.js +2 -1
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +0 -1
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/systemEncoding.js +5 -4
- package/dist/src/utils/systemEncoding.js.map +1 -1
- package/dist/src/utils/tool-utils.d.ts +2 -2
- package/dist/src/utils/tool-utils.js +14 -5
- package/dist/src/utils/tool-utils.js.map +1 -1
- package/dist/src/utils/userAccountManager.js +5 -4
- package/dist/src/utils/userAccountManager.js.map +1 -1
- package/dist/src/utils/workspaceContext.js +3 -2
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +2 -2
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -5
- package/dist/src/core/subagent.d.ts +0 -236
- package/dist/src/core/subagent.js +0 -482
- package/dist/src/core/subagent.js.map +0 -1
- package/dist/src/core/subagent.test.js +0 -556
- package/dist/src/core/subagent.test.js.map +0 -1
- /package/dist/src/{core/subagent.test.d.ts → commands/extensions.test.d.ts} +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
|
|
7
|
-
import {
|
|
7
|
+
import { isThinkingDefault, isThinkingSupported, GeminiClient, } from './client.js';
|
|
8
8
|
import { AuthType, } from './contentGenerator.js';
|
|
9
9
|
import {} from './geminiChat.js';
|
|
10
10
|
import { CompressionStatus, GeminiEventType, Turn, } from './turn.js';
|
|
@@ -14,8 +14,9 @@ import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
|
|
14
14
|
import { setSimulate429 } from '../utils/testUtils.js';
|
|
15
15
|
import { tokenLimit } from './tokenLimits.js';
|
|
16
16
|
import { ideContextStore } from '../ide/ideContext.js';
|
|
17
|
-
import { ClearcutLogger } from '../telemetry/clearcut-logger/clearcut-logger.js';
|
|
18
17
|
import { uiTelemetryService } from '../telemetry/uiTelemetry.js';
|
|
18
|
+
import { ChatCompressionService } from '../services/chatCompressionService.js';
|
|
19
|
+
vi.mock('../services/chatCompressionService.js');
|
|
19
20
|
// Mock fs module to prevent actual file system operations during tests
|
|
20
21
|
const mockFileSystem = new Map();
|
|
21
22
|
vi.mock('node:fs', () => {
|
|
@@ -95,70 +96,6 @@ async function fromAsync(promise) {
|
|
|
95
96
|
}
|
|
96
97
|
return results;
|
|
97
98
|
}
|
|
98
|
-
describe('findCompressSplitPoint', () => {
|
|
99
|
-
it('should throw an error for non-positive numbers', () => {
|
|
100
|
-
expect(() => findCompressSplitPoint([], 0)).toThrow('Fraction must be between 0 and 1');
|
|
101
|
-
});
|
|
102
|
-
it('should throw an error for a fraction greater than or equal to 1', () => {
|
|
103
|
-
expect(() => findCompressSplitPoint([], 1)).toThrow('Fraction must be between 0 and 1');
|
|
104
|
-
});
|
|
105
|
-
it('should handle an empty history', () => {
|
|
106
|
-
expect(findCompressSplitPoint([], 0.5)).toBe(0);
|
|
107
|
-
});
|
|
108
|
-
it('should handle a fraction in the middle', () => {
|
|
109
|
-
const history = [
|
|
110
|
-
{ role: 'user', parts: [{ text: 'This is the first message.' }] }, // JSON length: 66 (19%)
|
|
111
|
-
{ role: 'model', parts: [{ text: 'This is the second message.' }] }, // JSON length: 68 (40%)
|
|
112
|
-
{ role: 'user', parts: [{ text: 'This is the third message.' }] }, // JSON length: 66 (60%)
|
|
113
|
-
{ role: 'model', parts: [{ text: 'This is the fourth message.' }] }, // JSON length: 68 (80%)
|
|
114
|
-
{ role: 'user', parts: [{ text: 'This is the fifth message.' }] }, // JSON length: 65 (100%)
|
|
115
|
-
];
|
|
116
|
-
expect(findCompressSplitPoint(history, 0.5)).toBe(4);
|
|
117
|
-
});
|
|
118
|
-
it('should handle a fraction of last index', () => {
|
|
119
|
-
const history = [
|
|
120
|
-
{ role: 'user', parts: [{ text: 'This is the first message.' }] }, // JSON length: 66 (19%)
|
|
121
|
-
{ role: 'model', parts: [{ text: 'This is the second message.' }] }, // JSON length: 68 (40%)
|
|
122
|
-
{ role: 'user', parts: [{ text: 'This is the third message.' }] }, // JSON length: 66 (60%)
|
|
123
|
-
{ role: 'model', parts: [{ text: 'This is the fourth message.' }] }, // JSON length: 68 (80%)
|
|
124
|
-
{ role: 'user', parts: [{ text: 'This is the fifth message.' }] }, // JSON length: 65 (100%)
|
|
125
|
-
];
|
|
126
|
-
expect(findCompressSplitPoint(history, 0.9)).toBe(4);
|
|
127
|
-
});
|
|
128
|
-
it('should handle a fraction of after last index', () => {
|
|
129
|
-
const history = [
|
|
130
|
-
{ role: 'user', parts: [{ text: 'This is the first message.' }] }, // JSON length: 66 (24%%)
|
|
131
|
-
{ role: 'model', parts: [{ text: 'This is the second message.' }] }, // JSON length: 68 (50%)
|
|
132
|
-
{ role: 'user', parts: [{ text: 'This is the third message.' }] }, // JSON length: 66 (74%)
|
|
133
|
-
{ role: 'model', parts: [{ text: 'This is the fourth message.' }] }, // JSON length: 68 (100%)
|
|
134
|
-
];
|
|
135
|
-
expect(findCompressSplitPoint(history, 0.8)).toBe(4);
|
|
136
|
-
});
|
|
137
|
-
it('should return earlier splitpoint if no valid ones are after threshhold', () => {
|
|
138
|
-
const history = [
|
|
139
|
-
{ role: 'user', parts: [{ text: 'This is the first message.' }] },
|
|
140
|
-
{ role: 'model', parts: [{ text: 'This is the second message.' }] },
|
|
141
|
-
{ role: 'user', parts: [{ text: 'This is the third message.' }] },
|
|
142
|
-
{ role: 'model', parts: [{ functionCall: {} }] },
|
|
143
|
-
];
|
|
144
|
-
// Can't return 4 because the previous item has a function call.
|
|
145
|
-
expect(findCompressSplitPoint(history, 0.99)).toBe(2);
|
|
146
|
-
});
|
|
147
|
-
it('should handle a history with only one item', () => {
|
|
148
|
-
const historyWithEmptyParts = [
|
|
149
|
-
{ role: 'user', parts: [{ text: 'Message 1' }] },
|
|
150
|
-
];
|
|
151
|
-
expect(findCompressSplitPoint(historyWithEmptyParts, 0.5)).toBe(0);
|
|
152
|
-
});
|
|
153
|
-
it('should handle history with weird parts', () => {
|
|
154
|
-
const historyWithEmptyParts = [
|
|
155
|
-
{ role: 'user', parts: [{ text: 'Message 1' }] },
|
|
156
|
-
{ role: 'model', parts: [{ fileData: { fileUri: 'derp' } }] },
|
|
157
|
-
{ role: 'user', parts: [{ text: 'Message 2' }] },
|
|
158
|
-
];
|
|
159
|
-
expect(findCompressSplitPoint(historyWithEmptyParts, 0.5)).toBe(2);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
99
|
describe('isThinkingSupported', () => {
|
|
163
100
|
it('should return true for gemini-2.5', () => {
|
|
164
101
|
expect(isThinkingSupported('gemini-2.5')).toBe(true);
|
|
@@ -194,6 +131,14 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
194
131
|
beforeEach(async () => {
|
|
195
132
|
vi.resetAllMocks();
|
|
196
133
|
vi.mocked(uiTelemetryService.setLastPromptTokenCount).mockClear();
|
|
134
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValue({
|
|
135
|
+
newHistory: null,
|
|
136
|
+
info: {
|
|
137
|
+
originalTokenCount: 0,
|
|
138
|
+
newTokenCount: 0,
|
|
139
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
197
142
|
mockGenerateContentFn = vi.fn().mockResolvedValue({
|
|
198
143
|
candidates: [{ content: { parts: [{ text: '{"key": "value"}' }] } }],
|
|
199
144
|
});
|
|
@@ -228,7 +173,6 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
228
173
|
getVertexAI: vi.fn().mockReturnValue(false),
|
|
229
174
|
getUserAgent: vi.fn().mockReturnValue('test-agent'),
|
|
230
175
|
getUserMemory: vi.fn().mockReturnValue(''),
|
|
231
|
-
getFullContext: vi.fn().mockReturnValue(false),
|
|
232
176
|
getSessionId: vi.fn().mockReturnValue('test-session-id'),
|
|
233
177
|
getProxy: vi.fn().mockReturnValue(undefined),
|
|
234
178
|
getWorkingDir: vi.fn().mockReturnValue('/test/dir'),
|
|
@@ -270,6 +214,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
270
214
|
client = new GeminiClient(mockConfig);
|
|
271
215
|
await client.initialize();
|
|
272
216
|
vi.mocked(mockConfig.getGeminiClient).mockReturnValue(client);
|
|
217
|
+
vi.mocked(uiTelemetryService.setLastPromptTokenCount).mockClear();
|
|
273
218
|
});
|
|
274
219
|
afterEach(() => {
|
|
275
220
|
vi.restoreAllMocks();
|
|
@@ -320,87 +265,64 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
320
265
|
getHistory: mockGetHistory,
|
|
321
266
|
addHistory: vi.fn(),
|
|
322
267
|
setHistory: vi.fn(),
|
|
268
|
+
getLastPromptTokenCount: vi.fn(),
|
|
323
269
|
};
|
|
324
270
|
});
|
|
325
271
|
function setup({ chatHistory = [
|
|
326
272
|
{ role: 'user', parts: [{ text: 'Long conversation' }] },
|
|
327
273
|
{ role: 'model', parts: [{ text: 'Long response' }] },
|
|
328
|
-
], originalTokenCount = 1000,
|
|
274
|
+
], originalTokenCount = 1000, newTokenCount = 500, compressionStatus = CompressionStatus.COMPRESSED, } = {}) {
|
|
329
275
|
const mockOriginalChat = {
|
|
330
276
|
getHistory: vi.fn((_curated) => chatHistory),
|
|
331
277
|
setHistory: vi.fn(),
|
|
278
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(originalTokenCount),
|
|
332
279
|
};
|
|
333
280
|
client['chat'] = mockOriginalChat;
|
|
334
281
|
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
content: {
|
|
339
|
-
role: 'model',
|
|
340
|
-
parts: [{ text: summaryText }],
|
|
341
|
-
},
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
});
|
|
345
|
-
// Calculate what the new history will be
|
|
346
|
-
const splitPoint = findCompressSplitPoint(chatHistory, 0.7); // 1 - 0.3
|
|
347
|
-
const historyToKeep = chatHistory.slice(splitPoint);
|
|
348
|
-
// This is the history that the new chat will have.
|
|
349
|
-
// It includes the default startChat history + the extra history from tryCompressChat
|
|
350
|
-
const newCompressedHistory = [
|
|
351
|
-
// Mocked envParts + canned response from startChat
|
|
352
|
-
{
|
|
353
|
-
role: 'user',
|
|
354
|
-
parts: [{ text: 'Mocked env context' }],
|
|
355
|
-
},
|
|
356
|
-
{
|
|
357
|
-
role: 'model',
|
|
358
|
-
parts: [{ text: 'Got it. Thanks for the context!' }],
|
|
359
|
-
},
|
|
360
|
-
// extraHistory from tryCompressChat
|
|
361
|
-
{
|
|
362
|
-
role: 'user',
|
|
363
|
-
parts: [{ text: summaryText }],
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
role: 'model',
|
|
367
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
368
|
-
},
|
|
369
|
-
...historyToKeep,
|
|
282
|
+
const newHistory = [
|
|
283
|
+
{ role: 'user', parts: [{ text: 'Summary' }] },
|
|
284
|
+
{ role: 'model', parts: [{ text: 'Got it' }] },
|
|
370
285
|
];
|
|
286
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValue({
|
|
287
|
+
newHistory: compressionStatus === CompressionStatus.COMPRESSED
|
|
288
|
+
? newHistory
|
|
289
|
+
: null,
|
|
290
|
+
info: {
|
|
291
|
+
originalTokenCount,
|
|
292
|
+
newTokenCount,
|
|
293
|
+
compressionStatus,
|
|
294
|
+
},
|
|
295
|
+
});
|
|
371
296
|
const mockNewChat = {
|
|
372
|
-
getHistory: vi.fn().mockReturnValue(
|
|
297
|
+
getHistory: vi.fn().mockReturnValue(newHistory),
|
|
373
298
|
setHistory: vi.fn(),
|
|
299
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(newTokenCount),
|
|
374
300
|
};
|
|
375
301
|
client['startChat'] = vi
|
|
376
302
|
.fn()
|
|
377
303
|
.mockResolvedValue(mockNewChat);
|
|
378
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
379
|
-
const estimatedNewTokenCount = Math.floor(totalChars / 4);
|
|
380
304
|
return {
|
|
381
305
|
client,
|
|
382
306
|
mockOriginalChat,
|
|
383
307
|
mockNewChat,
|
|
384
|
-
estimatedNewTokenCount,
|
|
308
|
+
estimatedNewTokenCount: newTokenCount,
|
|
385
309
|
};
|
|
386
310
|
}
|
|
387
311
|
describe('when compression inflates the token count', () => {
|
|
388
312
|
it('allows compression to be forced/manual after a failure', async () => {
|
|
389
|
-
// Call 1 (Fails): Setup with
|
|
390
|
-
|
|
391
|
-
const { client, estimatedNewTokenCount: inflatedTokenCount } = setup({
|
|
313
|
+
// Call 1 (Fails): Setup with inflated tokens
|
|
314
|
+
setup({
|
|
392
315
|
originalTokenCount: 100,
|
|
393
|
-
|
|
316
|
+
newTokenCount: 200,
|
|
317
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
394
318
|
});
|
|
395
|
-
expect(inflatedTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
396
319
|
await client.tryCompressChat('prompt-id-4', false); // Fails
|
|
397
|
-
// Call 2 (Forced): Re-setup with
|
|
398
|
-
const shortSummary = 'short';
|
|
320
|
+
// Call 2 (Forced): Re-setup with compressed tokens
|
|
399
321
|
const { estimatedNewTokenCount: compressedTokenCount } = setup({
|
|
400
322
|
originalTokenCount: 100,
|
|
401
|
-
|
|
323
|
+
newTokenCount: 50,
|
|
324
|
+
compressionStatus: CompressionStatus.COMPRESSED,
|
|
402
325
|
});
|
|
403
|
-
expect(compressedTokenCount).toBeLessThanOrEqual(100); // Ensure setup is correct
|
|
404
326
|
const result = await client.tryCompressChat('prompt-id-4', true); // Forced
|
|
405
327
|
expect(result).toEqual({
|
|
406
328
|
compressionStatus: CompressionStatus.COMPRESSED,
|
|
@@ -409,12 +331,11 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
409
331
|
});
|
|
410
332
|
});
|
|
411
333
|
it('yields the result even if the compression inflated the tokens', async () => {
|
|
412
|
-
const longSummary = 'long summary '.repeat(100);
|
|
413
334
|
const { client, estimatedNewTokenCount } = setup({
|
|
414
335
|
originalTokenCount: 100,
|
|
415
|
-
|
|
336
|
+
newTokenCount: 200,
|
|
337
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
416
338
|
});
|
|
417
|
-
expect(estimatedNewTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
418
339
|
const result = await client.tryCompressChat('prompt-id-4', false);
|
|
419
340
|
expect(result).toEqual({
|
|
420
341
|
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
@@ -425,47 +346,52 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
425
346
|
expect(uiTelemetryService.setLastPromptTokenCount).not.toHaveBeenCalled();
|
|
426
347
|
});
|
|
427
348
|
it('does not manipulate the source chat', async () => {
|
|
428
|
-
const
|
|
429
|
-
const { client, mockOriginalChat, estimatedNewTokenCount } = setup({
|
|
349
|
+
const { client, mockOriginalChat } = setup({
|
|
430
350
|
originalTokenCount: 100,
|
|
431
|
-
|
|
351
|
+
newTokenCount: 200,
|
|
352
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
432
353
|
});
|
|
433
|
-
expect(estimatedNewTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
434
354
|
await client.tryCompressChat('prompt-id-4', false);
|
|
435
355
|
// On failure, the chat should NOT be replaced
|
|
436
356
|
expect(client['chat']).toBe(mockOriginalChat);
|
|
437
357
|
});
|
|
438
|
-
it('will not attempt to compress context after a failure', async () => {
|
|
439
|
-
const
|
|
440
|
-
const { client, estimatedNewTokenCount } = setup({
|
|
358
|
+
it.skip('will not attempt to compress context after a failure', async () => {
|
|
359
|
+
const { client } = setup({
|
|
441
360
|
originalTokenCount: 100,
|
|
442
|
-
|
|
361
|
+
newTokenCount: 200,
|
|
362
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
443
363
|
});
|
|
444
|
-
expect(estimatedNewTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
445
364
|
await client.tryCompressChat('prompt-id-4', false); // This fails and sets hasFailedCompressionAttempt = true
|
|
365
|
+
// Mock the next call to return NOOP
|
|
366
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValueOnce({
|
|
367
|
+
newHistory: null,
|
|
368
|
+
info: {
|
|
369
|
+
originalTokenCount: 0,
|
|
370
|
+
newTokenCount: 0,
|
|
371
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
372
|
+
},
|
|
373
|
+
});
|
|
446
374
|
// This call should now be a NOOP
|
|
447
375
|
const result = await client.tryCompressChat('prompt-id-5', false);
|
|
448
|
-
|
|
449
|
-
expect(
|
|
450
|
-
expect(
|
|
451
|
-
compressionStatus: CompressionStatus.NOOP,
|
|
452
|
-
newTokenCount: 0,
|
|
453
|
-
originalTokenCount: 0,
|
|
454
|
-
});
|
|
376
|
+
expect(result.compressionStatus).toBe(CompressionStatus.NOOP);
|
|
377
|
+
expect(ChatCompressionService.prototype.compress).toHaveBeenCalledTimes(2);
|
|
378
|
+
expect(ChatCompressionService.prototype.compress).toHaveBeenLastCalledWith(expect.anything(), 'prompt-id-5', false, expect.anything(), expect.anything(), true);
|
|
455
379
|
});
|
|
456
380
|
});
|
|
457
381
|
it('should not trigger summarization if token count is below threshold', async () => {
|
|
458
382
|
const MOCKED_TOKEN_LIMIT = 1000;
|
|
459
|
-
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
460
|
-
mockGetHistory.mockReturnValue([
|
|
461
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
462
|
-
]);
|
|
463
383
|
const originalTokenCount = MOCKED_TOKEN_LIMIT * 0.699;
|
|
464
|
-
vi.mocked(
|
|
384
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValue({
|
|
385
|
+
newHistory: null,
|
|
386
|
+
info: {
|
|
387
|
+
originalTokenCount,
|
|
388
|
+
newTokenCount: originalTokenCount,
|
|
389
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
390
|
+
},
|
|
391
|
+
});
|
|
465
392
|
const initialChat = client.getChat();
|
|
466
393
|
const result = await client.tryCompressChat('prompt-id-2', false);
|
|
467
394
|
const newChat = client.getChat();
|
|
468
|
-
expect(tokenLimit).toHaveBeenCalled();
|
|
469
395
|
expect(result).toEqual({
|
|
470
396
|
compressionStatus: CompressionStatus.NOOP,
|
|
471
397
|
newTokenCount: originalTokenCount,
|
|
@@ -477,6 +403,8 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
477
403
|
const { client } = setup({
|
|
478
404
|
chatHistory: [{ role: 'user', parts: [{ text: 'hi' }] }],
|
|
479
405
|
originalTokenCount: 50,
|
|
406
|
+
newTokenCount: 50,
|
|
407
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
480
408
|
});
|
|
481
409
|
const result = await client.tryCompressChat('prompt-id-noop', false);
|
|
482
410
|
expect(result).toEqual({
|
|
@@ -484,270 +412,6 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
484
412
|
originalTokenCount: 50,
|
|
485
413
|
newTokenCount: 50,
|
|
486
414
|
});
|
|
487
|
-
expect(mockGenerateContentFn).not.toHaveBeenCalled();
|
|
488
|
-
});
|
|
489
|
-
it('logs a telemetry event when compressing', async () => {
|
|
490
|
-
vi.spyOn(ClearcutLogger.prototype, 'logChatCompressionEvent');
|
|
491
|
-
const MOCKED_TOKEN_LIMIT = 1000;
|
|
492
|
-
const MOCKED_CONTEXT_PERCENTAGE_THRESHOLD = 0.5;
|
|
493
|
-
vi.spyOn(client['config'], 'getChatCompression').mockReturnValue({
|
|
494
|
-
contextPercentageThreshold: MOCKED_CONTEXT_PERCENTAGE_THRESHOLD,
|
|
495
|
-
});
|
|
496
|
-
const history = [
|
|
497
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
498
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
499
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
500
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
501
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
502
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
503
|
-
];
|
|
504
|
-
mockGetHistory.mockReturnValue(history);
|
|
505
|
-
const originalTokenCount = MOCKED_TOKEN_LIMIT * MOCKED_CONTEXT_PERCENTAGE_THRESHOLD;
|
|
506
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
507
|
-
// We need to control the estimated new token count.
|
|
508
|
-
// We mock startChat to return a chat with a known history.
|
|
509
|
-
const summaryText = 'This is a summary.';
|
|
510
|
-
const splitPoint = findCompressSplitPoint(history, 0.7);
|
|
511
|
-
const historyToKeep = history.slice(splitPoint);
|
|
512
|
-
const newCompressedHistory = [
|
|
513
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
514
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
515
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
516
|
-
{
|
|
517
|
-
role: 'model',
|
|
518
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
519
|
-
},
|
|
520
|
-
...historyToKeep,
|
|
521
|
-
];
|
|
522
|
-
const mockNewChat = {
|
|
523
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
524
|
-
};
|
|
525
|
-
client['startChat'] = vi
|
|
526
|
-
.fn()
|
|
527
|
-
.mockResolvedValue(mockNewChat);
|
|
528
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
529
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
530
|
-
// Mock the summary response from the chat
|
|
531
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
532
|
-
candidates: [
|
|
533
|
-
{
|
|
534
|
-
content: {
|
|
535
|
-
role: 'model',
|
|
536
|
-
parts: [{ text: summaryText }],
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
],
|
|
540
|
-
});
|
|
541
|
-
await client.tryCompressChat('prompt-id-3', false);
|
|
542
|
-
expect(ClearcutLogger.prototype.logChatCompressionEvent).toHaveBeenCalledWith(expect.objectContaining({
|
|
543
|
-
tokens_before: originalTokenCount,
|
|
544
|
-
tokens_after: newTokenCount,
|
|
545
|
-
}));
|
|
546
|
-
expect(uiTelemetryService.setLastPromptTokenCount).toHaveBeenCalledWith(newTokenCount);
|
|
547
|
-
expect(uiTelemetryService.setLastPromptTokenCount).toHaveBeenCalledTimes(1);
|
|
548
|
-
});
|
|
549
|
-
it('should trigger summarization if token count is at threshold with contextPercentageThreshold setting', async () => {
|
|
550
|
-
const MOCKED_TOKEN_LIMIT = 1000;
|
|
551
|
-
const MOCKED_CONTEXT_PERCENTAGE_THRESHOLD = 0.5;
|
|
552
|
-
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
553
|
-
vi.spyOn(client['config'], 'getChatCompression').mockReturnValue({
|
|
554
|
-
contextPercentageThreshold: MOCKED_CONTEXT_PERCENTAGE_THRESHOLD,
|
|
555
|
-
});
|
|
556
|
-
const history = [
|
|
557
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
558
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
559
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
560
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
561
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
562
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
563
|
-
];
|
|
564
|
-
mockGetHistory.mockReturnValue(history);
|
|
565
|
-
const originalTokenCount = MOCKED_TOKEN_LIMIT * MOCKED_CONTEXT_PERCENTAGE_THRESHOLD;
|
|
566
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
567
|
-
// Mock summary and new chat
|
|
568
|
-
const summaryText = 'This is a summary.';
|
|
569
|
-
const splitPoint = findCompressSplitPoint(history, 0.7);
|
|
570
|
-
const historyToKeep = history.slice(splitPoint);
|
|
571
|
-
const newCompressedHistory = [
|
|
572
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
573
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
574
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
575
|
-
{
|
|
576
|
-
role: 'model',
|
|
577
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
578
|
-
},
|
|
579
|
-
...historyToKeep,
|
|
580
|
-
];
|
|
581
|
-
const mockNewChat = {
|
|
582
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
583
|
-
};
|
|
584
|
-
client['startChat'] = vi
|
|
585
|
-
.fn()
|
|
586
|
-
.mockResolvedValue(mockNewChat);
|
|
587
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
588
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
589
|
-
// Mock the summary response from the chat
|
|
590
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
591
|
-
candidates: [
|
|
592
|
-
{
|
|
593
|
-
content: {
|
|
594
|
-
role: 'model',
|
|
595
|
-
parts: [{ text: summaryText }],
|
|
596
|
-
},
|
|
597
|
-
},
|
|
598
|
-
],
|
|
599
|
-
});
|
|
600
|
-
const initialChat = client.getChat();
|
|
601
|
-
const result = await client.tryCompressChat('prompt-id-3', false);
|
|
602
|
-
const newChat = client.getChat();
|
|
603
|
-
expect(tokenLimit).toHaveBeenCalled();
|
|
604
|
-
expect(mockGenerateContentFn).toHaveBeenCalled();
|
|
605
|
-
// Assert that summarization happened and returned the correct stats
|
|
606
|
-
expect(result).toEqual({
|
|
607
|
-
compressionStatus: CompressionStatus.COMPRESSED,
|
|
608
|
-
originalTokenCount,
|
|
609
|
-
newTokenCount,
|
|
610
|
-
});
|
|
611
|
-
// Assert that the chat was reset
|
|
612
|
-
expect(newChat).not.toBe(initialChat);
|
|
613
|
-
});
|
|
614
|
-
it('should not compress across a function call response', async () => {
|
|
615
|
-
const MOCKED_TOKEN_LIMIT = 1000;
|
|
616
|
-
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
617
|
-
const history = [
|
|
618
|
-
{ role: 'user', parts: [{ text: '...history 1...' }] },
|
|
619
|
-
{ role: 'model', parts: [{ text: '...history 2...' }] },
|
|
620
|
-
{ role: 'user', parts: [{ text: '...history 3...' }] },
|
|
621
|
-
{ role: 'model', parts: [{ text: '...history 4...' }] },
|
|
622
|
-
{ role: 'user', parts: [{ text: '...history 5...' }] },
|
|
623
|
-
{ role: 'model', parts: [{ text: '...history 6...' }] },
|
|
624
|
-
{ role: 'user', parts: [{ text: '...history 7...' }] },
|
|
625
|
-
{ role: 'model', parts: [{ text: '...history 8...' }] },
|
|
626
|
-
// Normally we would break here, but we have a function response.
|
|
627
|
-
{
|
|
628
|
-
role: 'user',
|
|
629
|
-
parts: [{ functionResponse: { name: '...history 8...' } }],
|
|
630
|
-
},
|
|
631
|
-
{ role: 'model', parts: [{ text: '...history 10...' }] },
|
|
632
|
-
// Instead we will break here.
|
|
633
|
-
{ role: 'user', parts: [{ text: '...history 10...' }] },
|
|
634
|
-
];
|
|
635
|
-
mockGetHistory.mockReturnValue(history);
|
|
636
|
-
const originalTokenCount = 1000 * 0.7;
|
|
637
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
638
|
-
// Mock summary and new chat
|
|
639
|
-
const summaryText = 'This is a summary.';
|
|
640
|
-
const splitPoint = findCompressSplitPoint(history, 0.7); // This should be 10
|
|
641
|
-
expect(splitPoint).toBe(10); // Verify split point logic
|
|
642
|
-
const historyToKeep = history.slice(splitPoint); // Should keep last user message
|
|
643
|
-
expect(historyToKeep).toEqual([
|
|
644
|
-
{ role: 'user', parts: [{ text: '...history 10...' }] },
|
|
645
|
-
]);
|
|
646
|
-
const newCompressedHistory = [
|
|
647
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
648
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
649
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
650
|
-
{
|
|
651
|
-
role: 'model',
|
|
652
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
653
|
-
},
|
|
654
|
-
...historyToKeep,
|
|
655
|
-
];
|
|
656
|
-
const mockNewChat = {
|
|
657
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
658
|
-
};
|
|
659
|
-
client['startChat'] = vi
|
|
660
|
-
.fn()
|
|
661
|
-
.mockResolvedValue(mockNewChat);
|
|
662
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
663
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
664
|
-
// Mock the summary response from the chat
|
|
665
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
666
|
-
candidates: [
|
|
667
|
-
{
|
|
668
|
-
content: {
|
|
669
|
-
role: 'model',
|
|
670
|
-
parts: [{ text: summaryText }],
|
|
671
|
-
},
|
|
672
|
-
},
|
|
673
|
-
],
|
|
674
|
-
});
|
|
675
|
-
const initialChat = client.getChat();
|
|
676
|
-
const result = await client.tryCompressChat('prompt-id-3', false);
|
|
677
|
-
const newChat = client.getChat();
|
|
678
|
-
expect(tokenLimit).toHaveBeenCalled();
|
|
679
|
-
expect(mockGenerateContentFn).toHaveBeenCalled();
|
|
680
|
-
// Assert that summarization happened and returned the correct stats
|
|
681
|
-
expect(result).toEqual({
|
|
682
|
-
compressionStatus: CompressionStatus.COMPRESSED,
|
|
683
|
-
originalTokenCount,
|
|
684
|
-
newTokenCount,
|
|
685
|
-
});
|
|
686
|
-
// Assert that the chat was reset
|
|
687
|
-
expect(newChat).not.toBe(initialChat);
|
|
688
|
-
// 1. standard start context message (env)
|
|
689
|
-
// 2. standard canned model response
|
|
690
|
-
// 3. compressed summary message (user)
|
|
691
|
-
// 4. standard canned model response
|
|
692
|
-
// 5. The last user message (historyToKeep)
|
|
693
|
-
expect(newChat.getHistory().length).toEqual(5);
|
|
694
|
-
});
|
|
695
|
-
it('should always trigger summarization when force is true, regardless of token count', async () => {
|
|
696
|
-
const history = [
|
|
697
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
698
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
699
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
700
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
701
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
702
|
-
{ role: 'model', parts: [{ text: '...history...' }] },
|
|
703
|
-
];
|
|
704
|
-
mockGetHistory.mockReturnValue(history);
|
|
705
|
-
const originalTokenCount = 100; // Well below threshold, but > estimated new count
|
|
706
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
707
|
-
// Mock summary and new chat
|
|
708
|
-
const summaryText = 'This is a summary.';
|
|
709
|
-
const splitPoint = findCompressSplitPoint(history, 0.7);
|
|
710
|
-
const historyToKeep = history.slice(splitPoint);
|
|
711
|
-
const newCompressedHistory = [
|
|
712
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
713
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
714
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
715
|
-
{
|
|
716
|
-
role: 'model',
|
|
717
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
718
|
-
},
|
|
719
|
-
...historyToKeep,
|
|
720
|
-
];
|
|
721
|
-
const mockNewChat = {
|
|
722
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
723
|
-
};
|
|
724
|
-
client['startChat'] = vi
|
|
725
|
-
.fn()
|
|
726
|
-
.mockResolvedValue(mockNewChat);
|
|
727
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
728
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
729
|
-
// Mock the summary response from the chat
|
|
730
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
731
|
-
candidates: [
|
|
732
|
-
{
|
|
733
|
-
content: {
|
|
734
|
-
role: 'model',
|
|
735
|
-
parts: [{ text: summaryText }],
|
|
736
|
-
},
|
|
737
|
-
},
|
|
738
|
-
],
|
|
739
|
-
});
|
|
740
|
-
const initialChat = client.getChat();
|
|
741
|
-
const result = await client.tryCompressChat('prompt-id-1', true); // force = true
|
|
742
|
-
const newChat = client.getChat();
|
|
743
|
-
expect(mockGenerateContentFn).toHaveBeenCalled();
|
|
744
|
-
expect(result).toEqual({
|
|
745
|
-
compressionStatus: CompressionStatus.COMPRESSED,
|
|
746
|
-
originalTokenCount,
|
|
747
|
-
newTokenCount,
|
|
748
|
-
});
|
|
749
|
-
// Assert that the chat was reset
|
|
750
|
-
expect(newChat).not.toBe(initialChat);
|
|
751
415
|
});
|
|
752
416
|
});
|
|
753
417
|
describe('sendMessageStream', () => {
|
|
@@ -832,6 +496,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
832
496
|
const mockChat = {
|
|
833
497
|
addHistory: vi.fn(),
|
|
834
498
|
getHistory: vi.fn().mockReturnValue([]),
|
|
499
|
+
getLastPromptTokenCount: vi.fn(),
|
|
835
500
|
};
|
|
836
501
|
client['chat'] = mockChat;
|
|
837
502
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -879,6 +544,7 @@ ${JSON.stringify({
|
|
|
879
544
|
const mockChat = {
|
|
880
545
|
addHistory: vi.fn(),
|
|
881
546
|
getHistory: vi.fn().mockReturnValue([]),
|
|
547
|
+
getLastPromptTokenCount: vi.fn(),
|
|
882
548
|
};
|
|
883
549
|
client['chat'] = mockChat;
|
|
884
550
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -923,6 +589,7 @@ ${JSON.stringify({
|
|
|
923
589
|
const mockChat = {
|
|
924
590
|
addHistory: vi.fn(),
|
|
925
591
|
getHistory: vi.fn().mockReturnValue([]),
|
|
592
|
+
getLastPromptTokenCount: vi.fn(),
|
|
926
593
|
};
|
|
927
594
|
client['chat'] = mockChat;
|
|
928
595
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -983,6 +650,7 @@ ${JSON.stringify({
|
|
|
983
650
|
const mockChat = {
|
|
984
651
|
addHistory: vi.fn(),
|
|
985
652
|
getHistory: vi.fn().mockReturnValue([]),
|
|
653
|
+
getLastPromptTokenCount: vi.fn(),
|
|
986
654
|
};
|
|
987
655
|
client['chat'] = mockChat;
|
|
988
656
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -1016,6 +684,7 @@ ${JSON.stringify({
|
|
|
1016
684
|
const mockChat = {
|
|
1017
685
|
addHistory: vi.fn(),
|
|
1018
686
|
getHistory: vi.fn().mockReturnValue([]),
|
|
687
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1019
688
|
};
|
|
1020
689
|
client['chat'] = mockChat;
|
|
1021
690
|
// Act
|
|
@@ -1049,6 +718,7 @@ ${JSON.stringify({
|
|
|
1049
718
|
const mockChat = {
|
|
1050
719
|
addHistory: vi.fn(),
|
|
1051
720
|
getHistory: vi.fn().mockReturnValue([]),
|
|
721
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1052
722
|
};
|
|
1053
723
|
client['chat'] = mockChat;
|
|
1054
724
|
// Use a signal that never gets aborted
|
|
@@ -1075,27 +745,10 @@ ${JSON.stringify({
|
|
|
1075
745
|
}
|
|
1076
746
|
// Assert
|
|
1077
747
|
expect(finalResult).toBeInstanceOf(Turn);
|
|
1078
|
-
// Debug: Check how many times checkNextSpeaker was called
|
|
1079
|
-
const callCount = mockCheckNextSpeaker.mock.calls.length;
|
|
1080
748
|
// If infinite loop protection is working, checkNextSpeaker should be called many times
|
|
1081
749
|
// but stop at MAX_TURNS (100). Since each recursive call should trigger checkNextSpeaker,
|
|
1082
750
|
// we expect it to be called multiple times before hitting the limit
|
|
1083
751
|
expect(mockCheckNextSpeaker).toHaveBeenCalled();
|
|
1084
|
-
// The test should demonstrate that the infinite loop protection works:
|
|
1085
|
-
// - If checkNextSpeaker is called many times (close to MAX_TURNS), it shows the loop was happening
|
|
1086
|
-
// - If it's only called once, the recursive behavior might not be triggered
|
|
1087
|
-
if (callCount === 0) {
|
|
1088
|
-
throw new Error('checkNextSpeaker was never called - the recursive condition was not met');
|
|
1089
|
-
}
|
|
1090
|
-
else if (callCount === 1) {
|
|
1091
|
-
// This might be expected behavior if the turn has pending tool calls or other conditions prevent recursion
|
|
1092
|
-
console.log('checkNextSpeaker called only once - no infinite loop occurred');
|
|
1093
|
-
}
|
|
1094
|
-
else {
|
|
1095
|
-
console.log(`checkNextSpeaker called ${callCount} times - infinite loop protection worked`);
|
|
1096
|
-
// If called multiple times, we expect it to be stopped before MAX_TURNS
|
|
1097
|
-
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
|
1098
|
-
}
|
|
1099
752
|
// The stream should produce events and eventually terminate
|
|
1100
753
|
expect(eventCount).toBeGreaterThanOrEqual(1);
|
|
1101
754
|
expect(eventCount).toBeLessThan(200); // Should not exceed our safety limit
|
|
@@ -1111,6 +764,7 @@ ${JSON.stringify({
|
|
|
1111
764
|
const mockChat = {
|
|
1112
765
|
addHistory: vi.fn(),
|
|
1113
766
|
getHistory: vi.fn().mockReturnValue([]),
|
|
767
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1114
768
|
};
|
|
1115
769
|
client['chat'] = mockChat;
|
|
1116
770
|
// Act & Assert
|
|
@@ -1149,6 +803,7 @@ ${JSON.stringify({
|
|
|
1149
803
|
const mockChat = {
|
|
1150
804
|
addHistory: vi.fn(),
|
|
1151
805
|
getHistory: vi.fn().mockReturnValue([]),
|
|
806
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1152
807
|
};
|
|
1153
808
|
client['chat'] = mockChat;
|
|
1154
809
|
// Use a signal that never gets aborted
|
|
@@ -1176,9 +831,8 @@ ${JSON.stringify({
|
|
|
1176
831
|
}
|
|
1177
832
|
}
|
|
1178
833
|
}
|
|
1179
|
-
catch (
|
|
834
|
+
catch (_) {
|
|
1180
835
|
// If the test framework times out, that also demonstrates the infinite loop
|
|
1181
|
-
console.error('Test timed out or errored:', error);
|
|
1182
836
|
}
|
|
1183
837
|
// Assert that the fix works - the loop should stop at MAX_TURNS
|
|
1184
838
|
const callCount = mockCheckNextSpeaker.mock.calls.length;
|
|
@@ -1186,8 +840,6 @@ ${JSON.stringify({
|
|
|
1186
840
|
// the loop should stop at MAX_TURNS (100)
|
|
1187
841
|
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
|
1188
842
|
expect(eventCount).toBeLessThanOrEqual(200); // Should have reasonable number of events
|
|
1189
|
-
console.log(`Infinite loop protection working: checkNextSpeaker called ${callCount} times, ` +
|
|
1190
|
-
`${eventCount} events generated (properly bounded by MAX_TURNS)`);
|
|
1191
843
|
});
|
|
1192
844
|
it('should yield ContextWindowWillOverflow when the context window is about to overflow', async () => {
|
|
1193
845
|
// Arrange
|
|
@@ -1195,7 +847,11 @@ ${JSON.stringify({
|
|
|
1195
847
|
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
1196
848
|
// Set last prompt token count
|
|
1197
849
|
const lastPromptTokenCount = 900;
|
|
1198
|
-
|
|
850
|
+
const mockChat = {
|
|
851
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(lastPromptTokenCount),
|
|
852
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
853
|
+
};
|
|
854
|
+
client['chat'] = mockChat;
|
|
1199
855
|
// Remaining = 100. Threshold (95%) = 95.
|
|
1200
856
|
// We need a request > 95 tokens.
|
|
1201
857
|
// A string of length 400 is roughly 100 tokens.
|
|
@@ -1238,7 +894,11 @@ ${JSON.stringify({
|
|
|
1238
894
|
client['currentSequenceModel'] = STICKY_MODEL;
|
|
1239
895
|
// Set token count
|
|
1240
896
|
const lastPromptTokenCount = 900;
|
|
1241
|
-
|
|
897
|
+
const mockChat = {
|
|
898
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(lastPromptTokenCount),
|
|
899
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
900
|
+
};
|
|
901
|
+
client['chat'] = mockChat;
|
|
1242
902
|
// Remaining (sticky) = 100. Threshold (95%) = 95.
|
|
1243
903
|
// We need a request > 95 tokens.
|
|
1244
904
|
const longText = 'a'.repeat(400);
|
|
@@ -1277,6 +937,12 @@ ${JSON.stringify({
|
|
|
1277
937
|
mockTurnRunFn.mockReturnValue((async function* () {
|
|
1278
938
|
yield { type: 'content', value: 'Hello' };
|
|
1279
939
|
})());
|
|
940
|
+
const mockChat = {
|
|
941
|
+
addHistory: vi.fn(),
|
|
942
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
943
|
+
getLastPromptTokenCount: vi.fn(),
|
|
944
|
+
};
|
|
945
|
+
client['chat'] = mockChat;
|
|
1280
946
|
});
|
|
1281
947
|
it('should use the model router service to select a model on the first turn', async () => {
|
|
1282
948
|
const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-1');
|
|
@@ -1365,6 +1031,7 @@ ${JSON.stringify({
|
|
|
1365
1031
|
const mockChat = {
|
|
1366
1032
|
addHistory: vi.fn(),
|
|
1367
1033
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1034
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1368
1035
|
};
|
|
1369
1036
|
client['chat'] = mockChat;
|
|
1370
1037
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -1395,6 +1062,7 @@ ${JSON.stringify({
|
|
|
1395
1062
|
const mockChat = {
|
|
1396
1063
|
addHistory: vi.fn(),
|
|
1397
1064
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1065
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1398
1066
|
};
|
|
1399
1067
|
client['chat'] = mockChat;
|
|
1400
1068
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -1418,6 +1086,7 @@ ${JSON.stringify({
|
|
|
1418
1086
|
const mockChat = {
|
|
1419
1087
|
addHistory: vi.fn(),
|
|
1420
1088
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1089
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1421
1090
|
};
|
|
1422
1091
|
client['chat'] = mockChat;
|
|
1423
1092
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -1455,6 +1124,7 @@ ${JSON.stringify({
|
|
|
1455
1124
|
.mockReturnValue([
|
|
1456
1125
|
{ role: 'user', parts: [{ text: 'previous message' }] },
|
|
1457
1126
|
]),
|
|
1127
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1458
1128
|
};
|
|
1459
1129
|
client['chat'] = mockChat;
|
|
1460
1130
|
});
|
|
@@ -1575,7 +1245,11 @@ ${JSON.stringify({
|
|
|
1575
1245
|
vi.mocked(ideContextStore.get).mockReturnValue({
|
|
1576
1246
|
workspaceState: {
|
|
1577
1247
|
openFiles: [
|
|
1578
|
-
{
|
|
1248
|
+
{
|
|
1249
|
+
...currentActiveFile,
|
|
1250
|
+
isActive: true,
|
|
1251
|
+
timestamp: Date.now(),
|
|
1252
|
+
},
|
|
1579
1253
|
],
|
|
1580
1254
|
},
|
|
1581
1255
|
});
|
|
@@ -1663,6 +1337,7 @@ ${JSON.stringify({
|
|
|
1663
1337
|
addHistory: vi.fn(),
|
|
1664
1338
|
getHistory: vi.fn().mockReturnValue([]), // Default empty history
|
|
1665
1339
|
setHistory: vi.fn(),
|
|
1340
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1666
1341
|
};
|
|
1667
1342
|
client['chat'] = mockChat;
|
|
1668
1343
|
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
@@ -1926,6 +1601,7 @@ ${JSON.stringify({
|
|
|
1926
1601
|
const mockChat = {
|
|
1927
1602
|
addHistory: vi.fn(),
|
|
1928
1603
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1604
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1929
1605
|
};
|
|
1930
1606
|
client['chat'] = mockChat;
|
|
1931
1607
|
// Act
|
|
@@ -1951,6 +1627,7 @@ ${JSON.stringify({
|
|
|
1951
1627
|
const mockChat = {
|
|
1952
1628
|
addHistory: vi.fn(),
|
|
1953
1629
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1630
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1954
1631
|
};
|
|
1955
1632
|
client['chat'] = mockChat;
|
|
1956
1633
|
// Act
|
|
@@ -1978,6 +1655,7 @@ ${JSON.stringify({
|
|
|
1978
1655
|
const mockChat = {
|
|
1979
1656
|
addHistory: vi.fn(),
|
|
1980
1657
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1658
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1981
1659
|
};
|
|
1982
1660
|
client['chat'] = mockChat;
|
|
1983
1661
|
// Act
|