@office-ai/aioncli-core 0.8.1 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +8 -2
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/src/agents/codebase-investigator.d.ts +36 -1
- package/dist/src/agents/codebase-investigator.js +93 -34
- package/dist/src/agents/codebase-investigator.js.map +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 +37 -11
- package/dist/src/agents/executor.js +512 -150
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js +1188 -245
- package/dist/src/agents/executor.test.js.map +1 -1
- package/dist/src/agents/invocation.d.ts +5 -2
- package/dist/src/agents/invocation.js +4 -2
- package/dist/src/agents/invocation.js.map +1 -1
- package/dist/src/agents/invocation.test.js +9 -0
- package/dist/src/agents/invocation.test.js.map +1 -1
- package/dist/src/agents/registry.d.ts +6 -1
- package/dist/src/agents/registry.js +51 -4
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js +30 -16
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.d.ts +3 -1
- package/dist/src/agents/subagent-tool-wrapper.js +4 -3
- package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.test.js +9 -4
- package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
- package/dist/src/agents/types.d.ts +37 -7
- package/dist/src/agents/types.js +2 -0
- package/dist/src/agents/types.js.map +1 -1
- package/dist/src/code_assist/codeAssist.js +1 -1
- package/dist/src/code_assist/codeAssist.test.d.ts +6 -0
- package/dist/src/code_assist/codeAssist.test.js +99 -0
- package/dist/src/code_assist/codeAssist.test.js.map +1 -0
- package/dist/src/code_assist/converter.d.ts +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 +50 -0
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -0
- package/dist/src/code_assist/experiments/client_metadata.test.d.ts +6 -0
- package/dist/src/code_assist/experiments/client_metadata.test.js +99 -0
- package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.d.ts +17 -0
- package/dist/src/code_assist/experiments/experiments.js +36 -0
- package/dist/src/code_assist/experiments/experiments.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.test.d.ts +6 -0
- package/dist/src/code_assist/experiments/experiments.test.js +92 -0
- package/dist/src/code_assist/experiments/experiments.test.js.map +1 -0
- package/dist/src/code_assist/experiments/flagNames.d.ts +13 -0
- package/dist/src/code_assist/experiments/flagNames.js +13 -0
- package/dist/src/code_assist/experiments/flagNames.js.map +1 -0
- package/dist/src/code_assist/experiments/types.d.ts +35 -0
- package/dist/src/code_assist/experiments/types.js +7 -0
- package/dist/src/code_assist/experiments/types.js.map +1 -0
- package/dist/src/code_assist/oauth-credential-storage.js +6 -5
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +65 -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 +161 -93
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +103 -57
- 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 +16 -8
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +126 -28
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.d.ts +2 -2
- package/dist/src/code_assist/setup.js +4 -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.d.ts +6 -0
- package/dist/src/commands/extensions.test.js +19 -0
- package/dist/src/commands/extensions.test.js.map +1 -0
- package/dist/src/config/config.d.ts +169 -43
- package/dist/src/config/config.js +418 -79
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +684 -49
- 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 +185 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -0
- package/dist/src/config/models.d.ts +23 -2
- package/dist/src/config/models.js +50 -7
- 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/config/storage.d.ts +3 -1
- package/dist/src/config/storage.js +22 -2
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +7 -6
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.d.ts +3 -2
- package/dist/src/confirmation-bus/message-bus.js +9 -3
- 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 +13 -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/baseLlmClient.d.ts +4 -8
- package/dist/src/core/baseLlmClient.js +6 -11
- 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 +12 -19
- package/dist/src/core/client.js +104 -206
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +329 -452
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +3 -2
- package/dist/src/core/contentGenerator.js +56 -41
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +49 -1
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +8 -4
- package/dist/src/core/coreToolScheduler.js +348 -179
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +575 -219
- 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 +23 -18
- package/dist/src/core/geminiChat.js +186 -108
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +581 -270
- 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 +35 -27
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +45 -29
- package/dist/src/core/logger.test.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/loggingContentGenerator.test.d.ts +6 -0
- package/dist/src/core/loggingContentGenerator.test.js +180 -0
- package/dist/src/core/loggingContentGenerator.test.js.map +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.d.ts +3 -2
- package/dist/src/core/nonInteractiveToolExecutor.js +12 -7
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +12 -8
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/openaiContentGenerator.js +31 -8
- package/dist/src/core/openaiContentGenerator.js.map +1 -1
- package/dist/src/core/prompts.d.ts +2 -1
- package/dist/src/core/prompts.js +135 -154
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +128 -189
- 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/tokenLimits.test.d.ts +6 -0
- package/dist/src/core/tokenLimits.test.js +26 -0
- package/dist/src/core/tokenLimits.test.js.map +1 -0
- package/dist/src/core/turn.d.ts +23 -3
- package/dist/src/core/turn.js +18 -9
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +98 -104
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/fallback/handler.js +60 -8
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +132 -17
- 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/generated/git-commit.js.map +1 -1
- package/dist/src/hooks/hookAggregator.d.ts +68 -0
- package/dist/src/hooks/hookAggregator.js +262 -0
- package/dist/src/hooks/hookAggregator.js.map +1 -0
- package/dist/src/hooks/hookAggregator.test.d.ts +6 -0
- package/dist/src/hooks/hookAggregator.test.js +387 -0
- package/dist/src/hooks/hookAggregator.test.js.map +1 -0
- package/dist/src/hooks/hookPlanner.d.ts +46 -0
- package/dist/src/hooks/hookPlanner.js +108 -0
- package/dist/src/hooks/hookPlanner.js.map +1 -0
- package/dist/src/hooks/hookPlanner.test.d.ts +6 -0
- package/dist/src/hooks/hookPlanner.test.js +255 -0
- package/dist/src/hooks/hookPlanner.test.js.map +1 -0
- package/dist/src/hooks/hookRegistry.d.ts +87 -0
- package/dist/src/hooks/hookRegistry.js +198 -0
- package/dist/src/hooks/hookRegistry.js.map +1 -0
- package/dist/src/hooks/hookRegistry.test.d.ts +6 -0
- package/dist/src/hooks/hookRegistry.test.js +341 -0
- package/dist/src/hooks/hookRegistry.test.js.map +1 -0
- package/dist/src/hooks/hookRunner.d.ts +42 -0
- package/dist/src/hooks/hookRunner.js +272 -0
- package/dist/src/hooks/hookRunner.js.map +1 -0
- package/dist/src/hooks/hookRunner.test.d.ts +6 -0
- package/dist/src/hooks/hookRunner.test.js +468 -0
- package/dist/src/hooks/hookRunner.test.js.map +1 -0
- package/dist/src/hooks/hookTranslator.d.ts +113 -0
- package/dist/src/hooks/hookTranslator.js +232 -0
- package/dist/src/hooks/hookTranslator.js.map +1 -0
- package/dist/src/hooks/hookTranslator.test.d.ts +6 -0
- package/dist/src/hooks/hookTranslator.test.js +192 -0
- package/dist/src/hooks/hookTranslator.test.js.map +1 -0
- package/dist/src/hooks/types.d.ts +384 -0
- package/dist/src/hooks/types.js +284 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/hooks/types.test.d.ts +6 -0
- package/dist/src/hooks/types.test.js +313 -0
- package/dist/src/hooks/types.test.js.map +1 -0
- package/dist/src/ide/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 +16 -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 +12 -10
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +163 -4
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.js +66 -21
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +54 -1
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/process-utils.js +85 -75
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/process-utils.test.js +83 -90
- 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 +21 -0
- package/dist/src/index.js +24 -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/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 +369 -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 +3 -2
- package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.test.js +11 -8
- package/dist/src/mcp/token-storage/file-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 +199 -0
- package/dist/src/policy/config.js.map +1 -0
- package/dist/src/policy/config.test.d.ts +6 -0
- package/dist/src/policy/config.test.js +538 -0
- package/dist/src/policy/config.test.js.map +1 -0
- package/dist/src/policy/index.d.ts +2 -0
- package/dist/src/policy/index.js +2 -0
- package/dist/src/policy/index.js.map +1 -1
- package/dist/src/policy/policies/discovered.toml +8 -0
- package/dist/src/policy/policies/read-only.toml +56 -0
- package/dist/src/policy/policies/write.toml +73 -0
- package/dist/src/policy/policies/yolo.toml +31 -0
- package/dist/src/policy/policy-engine.d.ts +12 -3
- package/dist/src/policy/policy-engine.js +74 -8
- 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 +47 -0
- package/dist/src/policy/toml-loader.js +411 -0
- package/dist/src/policy/toml-loader.js.map +1 -0
- package/dist/src/policy/toml-loader.test.d.ts +6 -0
- package/dist/src/policy/toml-loader.test.js +376 -0
- package/dist/src/policy/toml-loader.test.js.map +1 -0
- package/dist/src/policy/types.d.ts +83 -0
- package/dist/src/policy/types.js +10 -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 +39 -0
- package/dist/src/prompts/mcp-prompts.test.js.map +1 -0
- package/dist/src/prompts/prompt-registry.js +2 -1
- package/dist/src/prompts/prompt-registry.js.map +1 -1
- package/dist/src/prompts/prompt-registry.test.d.ts +6 -0
- package/dist/src/prompts/prompt-registry.test.js +96 -0
- package/dist/src/prompts/prompt-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.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 +9 -16
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js +17 -13
- 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.d.ts +32 -0
- package/dist/src/services/chatCompressionService.js +162 -0
- package/dist/src/services/chatCompressionService.js.map +1 -0
- package/dist/src/services/chatCompressionService.test.d.ts +6 -0
- package/dist/src/services/chatCompressionService.test.js +210 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -0
- package/dist/src/services/chatRecordingService.d.ts +3 -2
- package/dist/src/services/chatRecordingService.js +11 -9
- 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 +4 -1
- package/dist/src/services/loopDetectionService.js +95 -42
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +220 -12
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/modelConfig.golden.test.d.ts +6 -0
- package/dist/src/services/modelConfig.golden.test.js +42 -0
- package/dist/src/services/modelConfig.golden.test.js.map +1 -0
- package/dist/src/services/modelConfig.integration.test.d.ts +6 -0
- package/dist/src/services/modelConfig.integration.test.js +247 -0
- package/dist/src/services/modelConfig.integration.test.js.map +1 -0
- package/dist/src/services/modelConfigService.d.ts +48 -0
- package/dist/src/services/modelConfigService.js +151 -0
- package/dist/src/services/modelConfigService.js.map +1 -0
- package/dist/src/services/modelConfigService.test.d.ts +6 -0
- package/dist/src/services/modelConfigService.test.js +531 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.d.ts +1 -0
- package/dist/src/services/shellExecutionService.js +195 -92
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +137 -14
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/services/test-data/resolved-aliases.golden.json +202 -0
- package/dist/src/telemetry/activity-monitor.d.ts +116 -0
- package/dist/src/telemetry/activity-monitor.js +209 -0
- package/dist/src/telemetry/activity-monitor.js.map +1 -0
- package/dist/src/telemetry/activity-monitor.test.d.ts +6 -0
- package/dist/src/telemetry/activity-monitor.test.js +251 -0
- package/dist/src/telemetry/activity-monitor.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +25 -7
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +294 -76
- 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 +192 -66
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +25 -3
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +59 -5
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +0 -28
- package/dist/src/telemetry/constants.js +0 -29
- package/dist/src/telemetry/constants.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 +7 -3
- package/dist/src/telemetry/index.js +13 -4
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +14 -7
- package/dist/src/telemetry/loggers.js +197 -320
- 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 +460 -59
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/memory-monitor.d.ts +149 -0
- package/dist/src/telemetry/memory-monitor.js +335 -0
- package/dist/src/telemetry/memory-monitor.js.map +1 -0
- package/dist/src/telemetry/memory-monitor.test.d.ts +6 -0
- package/dist/src/telemetry/memory-monitor.test.js +472 -0
- package/dist/src/telemetry/memory-monitor.test.js.map +1 -0
- package/dist/src/telemetry/metrics.d.ts +180 -4
- package/dist/src/telemetry/metrics.js +270 -6
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +502 -184
- 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/telemetryAttributes.d.ts +8 -0
- package/dist/src/telemetry/telemetryAttributes.js +19 -0
- package/dist/src/telemetry/telemetryAttributes.js.map +1 -0
- package/dist/src/telemetry/trace.d.ts +46 -0
- package/dist/src/telemetry/trace.js +121 -0
- package/dist/src/telemetry/trace.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +227 -29
- package/dist/src/telemetry/types.js +858 -72
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -1
- package/dist/src/telemetry/uiTelemetry.js +7 -7
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +89 -67
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/config.d.ts +1 -1
- package/dist/src/test-utils/config.js +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 +4 -3
- package/dist/src/tools/edit.js +50 -47
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +306 -216
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +4 -3
- package/dist/src/tools/glob.js +24 -27
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +212 -205
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +4 -3
- package/dist/src/tools/grep.js +31 -25
- 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 +4 -3
- package/dist/src/tools/ls.js +29 -35
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +34 -42
- 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 +191 -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 +12 -5
- package/dist/src/tools/mcp-client.js +287 -267
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +352 -45
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +6 -2
- package/dist/src/tools/mcp-tool.js +19 -8
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +186 -273
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +7 -5
- package/dist/src/tools/memoryTool.js +14 -12
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +10 -9
- package/dist/src/tools/memoryTool.test.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.d.ts +5 -1
- package/dist/src/tools/modifiable-tool.js +38 -16
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +66 -31
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +6 -5
- package/dist/src/tools/read-file.js +26 -32
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +68 -33
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +6 -12
- package/dist/src/tools/read-many-files.js +28 -57
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +37 -36
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +28 -10
- package/dist/src/tools/ripGrep.js +195 -193
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +533 -204
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +8 -6
- package/dist/src/tools/shell.js +64 -38
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +134 -43
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +10 -23
- package/dist/src/tools/smart-edit.js +100 -85
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +229 -179
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-error.d.ts +21 -0
- package/dist/src/tools/tool-error.js +27 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +17 -0
- package/dist/src/tools/tool-names.js +21 -0
- package/dist/src/tools/tool-names.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +32 -20
- package/dist/src/tools/tool-registry.js +122 -78
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +167 -90
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +23 -8
- package/dist/src/tools/tools.js +69 -37
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +11 -3
- package/dist/src/tools/web-fetch.js +80 -38
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +338 -9
- 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 +11 -9
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +6 -0
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +3 -2
- package/dist/src/tools/write-file.js +41 -40
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +130 -123
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +34 -9
- package/dist/src/tools/write-todos.js +54 -11
- 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 +69 -0
- package/dist/src/utils/debugLogger.test.js.map +1 -0
- package/dist/src/utils/delay.d.ts +16 -0
- package/dist/src/utils/delay.js +43 -0
- package/dist/src/utils/delay.js.map +1 -0
- package/dist/src/utils/delay.test.d.ts +6 -0
- package/dist/src/utils/delay.test.js +88 -0
- package/dist/src/utils/delay.test.js.map +1 -0
- package/dist/src/utils/editCorrector.js +10 -25
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +19 -5
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +4 -2
- package/dist/src/utils/editor.js +53 -39
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +18 -45
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +2 -1
- package/dist/src/utils/environmentContext.js +20 -33
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +6 -34
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/errorParsing.d.ts +1 -1
- package/dist/src/utils/errorParsing.js +5 -33
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +0 -88
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/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 +121 -0
- package/dist/src/utils/events.js +84 -0
- package/dist/src/utils/events.js.map +1 -0
- package/dist/src/utils/events.test.d.ts +6 -0
- package/dist/src/utils/events.test.js +212 -0
- package/dist/src/utils/events.test.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +86 -0
- package/dist/src/utils/extensionLoader.js +208 -0
- package/dist/src/utils/extensionLoader.js.map +1 -0
- package/dist/src/utils/extensionLoader.test.d.ts +6 -0
- package/dist/src/utils/extensionLoader.test.js +154 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +1 -0
- package/dist/src/utils/fetch.js +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 +87 -61
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.js +1 -1
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +28 -47
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/formatters.d.ts +1 -0
- package/dist/src/utils/formatters.js +2 -1
- package/dist/src/utils/formatters.js.map +1 -1
- package/dist/src/utils/formatters.test.d.ts +6 -0
- package/dist/src/utils/formatters.test.js +26 -0
- package/dist/src/utils/formatters.test.js.map +1 -0
- package/dist/src/utils/getFolderStructure.js +9 -17
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/getFolderStructure.test.js +7 -6
- package/dist/src/utils/getFolderStructure.test.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 +37 -0
- package/dist/src/utils/googleQuotaErrors.js +157 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
- package/dist/src/utils/googleQuotaErrors.test.js +311 -0
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
- package/dist/src/utils/httpErrors.d.ts +18 -0
- package/dist/src/utils/httpErrors.js +36 -0
- package/dist/src/utils/httpErrors.js.map +1 -0
- package/dist/src/utils/ignorePatterns.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 +6 -4
- 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 +33 -9
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.js +38 -1
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +20 -1
- package/dist/src/utils/memoryDiscovery.js +176 -12
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +299 -40
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +4 -3
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.test.js +8 -14
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +3 -3
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +13 -5
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/package.d.ts +12 -0
- package/dist/src/utils/package.js +15 -0
- package/dist/src/utils/package.js.map +1 -0
- package/dist/src/utils/pathCorrector.d.ts +25 -0
- package/dist/src/utils/pathCorrector.js +33 -0
- package/dist/src/utils/pathCorrector.js.map +1 -0
- package/dist/src/utils/pathCorrector.test.d.ts +6 -0
- package/dist/src/utils/pathCorrector.test.js +83 -0
- package/dist/src/utils/pathCorrector.test.js.map +1 -0
- package/dist/src/utils/pathReader.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 +131 -29
- 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 +3 -10
- package/dist/src/utils/retry.js +97 -195
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +179 -145
- 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 +15 -2
- package/dist/src/utils/shell-utils.js +387 -140
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +244 -62
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/stdio.d.ts +32 -0
- package/dist/src/utils/stdio.js +85 -0
- package/dist/src/utils/stdio.js.map +1 -0
- package/dist/src/utils/stdio.test.d.ts +6 -0
- package/dist/src/utils/stdio.test.js +47 -0
- package/dist/src/utils/stdio.test.js.map +1 -0
- package/dist/src/utils/summarizer.d.ts +4 -2
- package/dist/src/utils/summarizer.js +8 -9
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +32 -12
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/systemEncoding.js +5 -4
- package/dist/src/utils/systemEncoding.js.map +1 -1
- package/dist/src/utils/systemEncoding.test.js +2 -1
- package/dist/src/utils/systemEncoding.test.js.map +1 -1
- package/dist/src/utils/terminal.d.ts +14 -0
- package/dist/src/utils/terminal.js +38 -0
- package/dist/src/utils/terminal.js.map +1 -0
- package/dist/src/utils/tool-utils.d.ts +2 -2
- package/dist/src/utils/tool-utils.js +15 -6
- package/dist/src/utils/tool-utils.js.map +1 -1
- package/dist/src/utils/tool-utils.test.js +8 -0
- package/dist/src/utils/tool-utils.test.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/userAccountManager.test.js +9 -7
- package/dist/src/utils/userAccountManager.test.js.map +1 -1
- package/dist/src/utils/workspaceContext.d.ts +4 -3
- package/dist/src/utils/workspaceContext.js +13 -13
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +8 -7
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -7
|
@@ -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 { 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,10 @@ 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
|
+
import { ClearcutLogger } from '../telemetry/clearcut-logger/clearcut-logger.js';
|
|
20
|
+
vi.mock('../services/chatCompressionService.js');
|
|
19
21
|
// Mock fs module to prevent actual file system operations during tests
|
|
20
22
|
const mockFileSystem = new Map();
|
|
21
23
|
vi.mock('node:fs', () => {
|
|
@@ -95,97 +97,6 @@ async function fromAsync(promise) {
|
|
|
95
97
|
}
|
|
96
98
|
return results;
|
|
97
99
|
}
|
|
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
|
-
describe('isThinkingSupported', () => {
|
|
163
|
-
it('should return true for gemini-2.5', () => {
|
|
164
|
-
expect(isThinkingSupported('gemini-2.5')).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
it('should return true for gemini-2.5-pro', () => {
|
|
167
|
-
expect(isThinkingSupported('gemini-2.5-pro')).toBe(true);
|
|
168
|
-
});
|
|
169
|
-
it('should return false for other models', () => {
|
|
170
|
-
expect(isThinkingSupported('gemini-1.5-flash')).toBe(false);
|
|
171
|
-
expect(isThinkingSupported('some-other-model')).toBe(false);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
describe('isThinkingDefault', () => {
|
|
175
|
-
it('should return false for gemini-2.5-flash-lite', () => {
|
|
176
|
-
expect(isThinkingDefault('gemini-2.5-flash-lite')).toBe(false);
|
|
177
|
-
});
|
|
178
|
-
it('should return true for gemini-2.5', () => {
|
|
179
|
-
expect(isThinkingDefault('gemini-2.5')).toBe(true);
|
|
180
|
-
});
|
|
181
|
-
it('should return true for gemini-2.5-pro', () => {
|
|
182
|
-
expect(isThinkingDefault('gemini-2.5-pro')).toBe(true);
|
|
183
|
-
});
|
|
184
|
-
it('should return false for other models', () => {
|
|
185
|
-
expect(isThinkingDefault('gemini-1.5-flash')).toBe(false);
|
|
186
|
-
expect(isThinkingDefault('some-other-model')).toBe(false);
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
100
|
describe('Gemini Client (client.ts)', () => {
|
|
190
101
|
let mockContentGenerator;
|
|
191
102
|
let mockConfig;
|
|
@@ -193,7 +104,16 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
193
104
|
let mockGenerateContentFn;
|
|
194
105
|
beforeEach(async () => {
|
|
195
106
|
vi.resetAllMocks();
|
|
107
|
+
ClearcutLogger.clearInstance();
|
|
196
108
|
vi.mocked(uiTelemetryService.setLastPromptTokenCount).mockClear();
|
|
109
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValue({
|
|
110
|
+
newHistory: null,
|
|
111
|
+
info: {
|
|
112
|
+
originalTokenCount: 0,
|
|
113
|
+
newTokenCount: 0,
|
|
114
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
197
117
|
mockGenerateContentFn = vi.fn().mockResolvedValue({
|
|
198
118
|
candidates: [{ content: { parts: [{ text: '{"key": "value"}' }] } }],
|
|
199
119
|
});
|
|
@@ -228,7 +148,6 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
228
148
|
getVertexAI: vi.fn().mockReturnValue(false),
|
|
229
149
|
getUserAgent: vi.fn().mockReturnValue('test-agent'),
|
|
230
150
|
getUserMemory: vi.fn().mockReturnValue(''),
|
|
231
|
-
getFullContext: vi.fn().mockReturnValue(false),
|
|
232
151
|
getSessionId: vi.fn().mockReturnValue('test-session-id'),
|
|
233
152
|
getProxy: vi.fn().mockReturnValue(undefined),
|
|
234
153
|
getWorkingDir: vi.fn().mockReturnValue('/test/dir'),
|
|
@@ -241,6 +160,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
241
160
|
getIdeModeFeature: vi.fn().mockReturnValue(false),
|
|
242
161
|
getIdeMode: vi.fn().mockReturnValue(true),
|
|
243
162
|
getDebugMode: vi.fn().mockReturnValue(false),
|
|
163
|
+
getPreviewFeatures: vi.fn().mockReturnValue(false),
|
|
244
164
|
getWorkspaceContext: vi.fn().mockReturnValue({
|
|
245
165
|
getDirectories: vi.fn().mockReturnValue(['/test/dir']),
|
|
246
166
|
}),
|
|
@@ -254,6 +174,8 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
254
174
|
getSkipNextSpeakerCheck: vi.fn().mockReturnValue(false),
|
|
255
175
|
getUseSmartEdit: vi.fn().mockReturnValue(false),
|
|
256
176
|
getUseModelRouter: vi.fn().mockReturnValue(false),
|
|
177
|
+
getShowModelInfoInChat: vi.fn().mockReturnValue(false),
|
|
178
|
+
getContinueOnFailedApiCall: vi.fn(),
|
|
257
179
|
getProjectRoot: vi.fn().mockReturnValue('/test/project/root'),
|
|
258
180
|
storage: {
|
|
259
181
|
getProjectTempDir: vi.fn().mockReturnValue('/test/temp'),
|
|
@@ -265,10 +187,23 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
265
187
|
reasoning: 'test',
|
|
266
188
|
}),
|
|
267
189
|
}),
|
|
190
|
+
modelConfigService: {
|
|
191
|
+
getResolvedConfig(modelConfigKey) {
|
|
192
|
+
return {
|
|
193
|
+
model: modelConfigKey.model,
|
|
194
|
+
generateContentConfig: {
|
|
195
|
+
temperature: 0,
|
|
196
|
+
topP: 1,
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
isInteractive: vi.fn().mockReturnValue(false),
|
|
268
202
|
};
|
|
269
203
|
client = new GeminiClient(mockConfig);
|
|
270
204
|
await client.initialize();
|
|
271
205
|
vi.mocked(mockConfig.getGeminiClient).mockReturnValue(client);
|
|
206
|
+
vi.mocked(uiTelemetryService.setLastPromptTokenCount).mockClear();
|
|
272
207
|
});
|
|
273
208
|
afterEach(() => {
|
|
274
209
|
vi.restoreAllMocks();
|
|
@@ -309,6 +244,23 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
309
244
|
expect(JSON.stringify(newHistory)).not.toContain('some old message');
|
|
310
245
|
});
|
|
311
246
|
});
|
|
247
|
+
describe('startChat', () => {
|
|
248
|
+
it('should include environment context when resuming a session', async () => {
|
|
249
|
+
const extraHistory = [
|
|
250
|
+
{ role: 'user', parts: [{ text: 'Old message' }] },
|
|
251
|
+
{ role: 'model', parts: [{ text: 'Old response' }] },
|
|
252
|
+
];
|
|
253
|
+
const chat = await client.startChat(extraHistory);
|
|
254
|
+
const history = chat.getHistory();
|
|
255
|
+
// The first message should be the environment context
|
|
256
|
+
expect(history[0].role).toBe('user');
|
|
257
|
+
expect(history[0].parts?.[0]?.text).toContain('This is the Gemini CLI');
|
|
258
|
+
expect(history[0].parts?.[0]?.text).toContain("The project's temporary directory is:");
|
|
259
|
+
// The subsequent messages should be the extra history
|
|
260
|
+
expect(history[1]).toEqual(extraHistory[0]);
|
|
261
|
+
expect(history[2]).toEqual(extraHistory[1]);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
312
264
|
describe('tryCompressChat', () => {
|
|
313
265
|
const mockGetHistory = vi.fn();
|
|
314
266
|
beforeEach(() => {
|
|
@@ -319,87 +271,64 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
319
271
|
getHistory: mockGetHistory,
|
|
320
272
|
addHistory: vi.fn(),
|
|
321
273
|
setHistory: vi.fn(),
|
|
274
|
+
getLastPromptTokenCount: vi.fn(),
|
|
322
275
|
};
|
|
323
276
|
});
|
|
324
277
|
function setup({ chatHistory = [
|
|
325
278
|
{ role: 'user', parts: [{ text: 'Long conversation' }] },
|
|
326
279
|
{ role: 'model', parts: [{ text: 'Long response' }] },
|
|
327
|
-
], originalTokenCount = 1000,
|
|
280
|
+
], originalTokenCount = 1000, newTokenCount = 500, compressionStatus = CompressionStatus.COMPRESSED, } = {}) {
|
|
328
281
|
const mockOriginalChat = {
|
|
329
282
|
getHistory: vi.fn((_curated) => chatHistory),
|
|
330
283
|
setHistory: vi.fn(),
|
|
284
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(originalTokenCount),
|
|
331
285
|
};
|
|
332
286
|
client['chat'] = mockOriginalChat;
|
|
333
287
|
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
content: {
|
|
338
|
-
role: 'model',
|
|
339
|
-
parts: [{ text: summaryText }],
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
],
|
|
343
|
-
});
|
|
344
|
-
// Calculate what the new history will be
|
|
345
|
-
const splitPoint = findCompressSplitPoint(chatHistory, 0.7); // 1 - 0.3
|
|
346
|
-
const historyToKeep = chatHistory.slice(splitPoint);
|
|
347
|
-
// This is the history that the new chat will have.
|
|
348
|
-
// It includes the default startChat history + the extra history from tryCompressChat
|
|
349
|
-
const newCompressedHistory = [
|
|
350
|
-
// Mocked envParts + canned response from startChat
|
|
351
|
-
{
|
|
352
|
-
role: 'user',
|
|
353
|
-
parts: [{ text: 'Mocked env context' }],
|
|
354
|
-
},
|
|
355
|
-
{
|
|
356
|
-
role: 'model',
|
|
357
|
-
parts: [{ text: 'Got it. Thanks for the context!' }],
|
|
358
|
-
},
|
|
359
|
-
// extraHistory from tryCompressChat
|
|
360
|
-
{
|
|
361
|
-
role: 'user',
|
|
362
|
-
parts: [{ text: summaryText }],
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
role: 'model',
|
|
366
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
367
|
-
},
|
|
368
|
-
...historyToKeep,
|
|
288
|
+
const newHistory = [
|
|
289
|
+
{ role: 'user', parts: [{ text: 'Summary' }] },
|
|
290
|
+
{ role: 'model', parts: [{ text: 'Got it' }] },
|
|
369
291
|
];
|
|
292
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValue({
|
|
293
|
+
newHistory: compressionStatus === CompressionStatus.COMPRESSED
|
|
294
|
+
? newHistory
|
|
295
|
+
: null,
|
|
296
|
+
info: {
|
|
297
|
+
originalTokenCount,
|
|
298
|
+
newTokenCount,
|
|
299
|
+
compressionStatus,
|
|
300
|
+
},
|
|
301
|
+
});
|
|
370
302
|
const mockNewChat = {
|
|
371
|
-
getHistory: vi.fn().mockReturnValue(
|
|
303
|
+
getHistory: vi.fn().mockReturnValue(newHistory),
|
|
372
304
|
setHistory: vi.fn(),
|
|
305
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(newTokenCount),
|
|
373
306
|
};
|
|
374
307
|
client['startChat'] = vi
|
|
375
308
|
.fn()
|
|
376
309
|
.mockResolvedValue(mockNewChat);
|
|
377
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
378
|
-
const estimatedNewTokenCount = Math.floor(totalChars / 4);
|
|
379
310
|
return {
|
|
380
311
|
client,
|
|
381
312
|
mockOriginalChat,
|
|
382
313
|
mockNewChat,
|
|
383
|
-
estimatedNewTokenCount,
|
|
314
|
+
estimatedNewTokenCount: newTokenCount,
|
|
384
315
|
};
|
|
385
316
|
}
|
|
386
317
|
describe('when compression inflates the token count', () => {
|
|
387
318
|
it('allows compression to be forced/manual after a failure', async () => {
|
|
388
|
-
// Call 1 (Fails): Setup with
|
|
389
|
-
|
|
390
|
-
const { client, estimatedNewTokenCount: inflatedTokenCount } = setup({
|
|
319
|
+
// Call 1 (Fails): Setup with inflated tokens
|
|
320
|
+
setup({
|
|
391
321
|
originalTokenCount: 100,
|
|
392
|
-
|
|
322
|
+
newTokenCount: 200,
|
|
323
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
393
324
|
});
|
|
394
|
-
expect(inflatedTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
395
325
|
await client.tryCompressChat('prompt-id-4', false); // Fails
|
|
396
|
-
// Call 2 (Forced): Re-setup with
|
|
397
|
-
const shortSummary = 'short';
|
|
326
|
+
// Call 2 (Forced): Re-setup with compressed tokens
|
|
398
327
|
const { estimatedNewTokenCount: compressedTokenCount } = setup({
|
|
399
328
|
originalTokenCount: 100,
|
|
400
|
-
|
|
329
|
+
newTokenCount: 50,
|
|
330
|
+
compressionStatus: CompressionStatus.COMPRESSED,
|
|
401
331
|
});
|
|
402
|
-
expect(compressedTokenCount).toBeLessThanOrEqual(100); // Ensure setup is correct
|
|
403
332
|
const result = await client.tryCompressChat('prompt-id-4', true); // Forced
|
|
404
333
|
expect(result).toEqual({
|
|
405
334
|
compressionStatus: CompressionStatus.COMPRESSED,
|
|
@@ -408,12 +337,11 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
408
337
|
});
|
|
409
338
|
});
|
|
410
339
|
it('yields the result even if the compression inflated the tokens', async () => {
|
|
411
|
-
const longSummary = 'long summary '.repeat(100);
|
|
412
340
|
const { client, estimatedNewTokenCount } = setup({
|
|
413
341
|
originalTokenCount: 100,
|
|
414
|
-
|
|
342
|
+
newTokenCount: 200,
|
|
343
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
415
344
|
});
|
|
416
|
-
expect(estimatedNewTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
417
345
|
const result = await client.tryCompressChat('prompt-id-4', false);
|
|
418
346
|
expect(result).toEqual({
|
|
419
347
|
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
@@ -424,47 +352,52 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
424
352
|
expect(uiTelemetryService.setLastPromptTokenCount).not.toHaveBeenCalled();
|
|
425
353
|
});
|
|
426
354
|
it('does not manipulate the source chat', async () => {
|
|
427
|
-
const
|
|
428
|
-
const { client, mockOriginalChat, estimatedNewTokenCount } = setup({
|
|
355
|
+
const { client, mockOriginalChat } = setup({
|
|
429
356
|
originalTokenCount: 100,
|
|
430
|
-
|
|
357
|
+
newTokenCount: 200,
|
|
358
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
431
359
|
});
|
|
432
|
-
expect(estimatedNewTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
433
360
|
await client.tryCompressChat('prompt-id-4', false);
|
|
434
361
|
// On failure, the chat should NOT be replaced
|
|
435
362
|
expect(client['chat']).toBe(mockOriginalChat);
|
|
436
363
|
});
|
|
437
|
-
it('will not attempt to compress context after a failure', async () => {
|
|
438
|
-
const
|
|
439
|
-
const { client, estimatedNewTokenCount } = setup({
|
|
364
|
+
it.skip('will not attempt to compress context after a failure', async () => {
|
|
365
|
+
const { client } = setup({
|
|
440
366
|
originalTokenCount: 100,
|
|
441
|
-
|
|
367
|
+
newTokenCount: 200,
|
|
368
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
|
|
442
369
|
});
|
|
443
|
-
expect(estimatedNewTokenCount).toBeGreaterThan(100); // Ensure setup is correct
|
|
444
370
|
await client.tryCompressChat('prompt-id-4', false); // This fails and sets hasFailedCompressionAttempt = true
|
|
371
|
+
// Mock the next call to return NOOP
|
|
372
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValueOnce({
|
|
373
|
+
newHistory: null,
|
|
374
|
+
info: {
|
|
375
|
+
originalTokenCount: 0,
|
|
376
|
+
newTokenCount: 0,
|
|
377
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
378
|
+
},
|
|
379
|
+
});
|
|
445
380
|
// This call should now be a NOOP
|
|
446
381
|
const result = await client.tryCompressChat('prompt-id-5', false);
|
|
447
|
-
|
|
448
|
-
expect(
|
|
449
|
-
expect(
|
|
450
|
-
compressionStatus: CompressionStatus.NOOP,
|
|
451
|
-
newTokenCount: 0,
|
|
452
|
-
originalTokenCount: 0,
|
|
453
|
-
});
|
|
382
|
+
expect(result.compressionStatus).toBe(CompressionStatus.NOOP);
|
|
383
|
+
expect(ChatCompressionService.prototype.compress).toHaveBeenCalledTimes(2);
|
|
384
|
+
expect(ChatCompressionService.prototype.compress).toHaveBeenLastCalledWith(expect.anything(), 'prompt-id-5', false, expect.anything(), expect.anything(), true);
|
|
454
385
|
});
|
|
455
386
|
});
|
|
456
387
|
it('should not trigger summarization if token count is below threshold', async () => {
|
|
457
388
|
const MOCKED_TOKEN_LIMIT = 1000;
|
|
458
|
-
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
459
|
-
mockGetHistory.mockReturnValue([
|
|
460
|
-
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
461
|
-
]);
|
|
462
389
|
const originalTokenCount = MOCKED_TOKEN_LIMIT * 0.699;
|
|
463
|
-
vi.mocked(
|
|
390
|
+
vi.mocked(ChatCompressionService.prototype.compress).mockResolvedValue({
|
|
391
|
+
newHistory: null,
|
|
392
|
+
info: {
|
|
393
|
+
originalTokenCount,
|
|
394
|
+
newTokenCount: originalTokenCount,
|
|
395
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
396
|
+
},
|
|
397
|
+
});
|
|
464
398
|
const initialChat = client.getChat();
|
|
465
399
|
const result = await client.tryCompressChat('prompt-id-2', false);
|
|
466
400
|
const newChat = client.getChat();
|
|
467
|
-
expect(tokenLimit).toHaveBeenCalled();
|
|
468
401
|
expect(result).toEqual({
|
|
469
402
|
compressionStatus: CompressionStatus.NOOP,
|
|
470
403
|
newTokenCount: originalTokenCount,
|
|
@@ -472,248 +405,19 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
472
405
|
});
|
|
473
406
|
expect(newChat).toBe(initialChat);
|
|
474
407
|
});
|
|
475
|
-
it('
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
contextPercentageThreshold: MOCKED_CONTEXT_PERCENTAGE_THRESHOLD,
|
|
482
|
-
});
|
|
483
|
-
const history = [{ role: 'user', parts: [{ text: '...history...' }] }];
|
|
484
|
-
mockGetHistory.mockReturnValue(history);
|
|
485
|
-
const originalTokenCount = MOCKED_TOKEN_LIMIT * MOCKED_CONTEXT_PERCENTAGE_THRESHOLD;
|
|
486
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
487
|
-
// We need to control the estimated new token count.
|
|
488
|
-
// We mock startChat to return a chat with a known history.
|
|
489
|
-
const summaryText = 'This is a summary.';
|
|
490
|
-
const splitPoint = findCompressSplitPoint(history, 0.7);
|
|
491
|
-
const historyToKeep = history.slice(splitPoint);
|
|
492
|
-
const newCompressedHistory = [
|
|
493
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
494
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
495
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
496
|
-
{
|
|
497
|
-
role: 'model',
|
|
498
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
499
|
-
},
|
|
500
|
-
...historyToKeep,
|
|
501
|
-
];
|
|
502
|
-
const mockNewChat = {
|
|
503
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
504
|
-
};
|
|
505
|
-
client['startChat'] = vi
|
|
506
|
-
.fn()
|
|
507
|
-
.mockResolvedValue(mockNewChat);
|
|
508
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
509
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
510
|
-
// Mock the summary response from the chat
|
|
511
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
512
|
-
candidates: [
|
|
513
|
-
{
|
|
514
|
-
content: {
|
|
515
|
-
role: 'model',
|
|
516
|
-
parts: [{ text: summaryText }],
|
|
517
|
-
},
|
|
518
|
-
},
|
|
519
|
-
],
|
|
520
|
-
});
|
|
521
|
-
await client.tryCompressChat('prompt-id-3', false);
|
|
522
|
-
expect(ClearcutLogger.prototype.logChatCompressionEvent).toHaveBeenCalledWith(expect.objectContaining({
|
|
523
|
-
tokens_before: originalTokenCount,
|
|
524
|
-
tokens_after: newTokenCount,
|
|
525
|
-
}));
|
|
526
|
-
expect(uiTelemetryService.setLastPromptTokenCount).toHaveBeenCalledWith(newTokenCount);
|
|
527
|
-
expect(uiTelemetryService.setLastPromptTokenCount).toHaveBeenCalledTimes(1);
|
|
528
|
-
});
|
|
529
|
-
it('should trigger summarization if token count is at threshold with contextPercentageThreshold setting', async () => {
|
|
530
|
-
const MOCKED_TOKEN_LIMIT = 1000;
|
|
531
|
-
const MOCKED_CONTEXT_PERCENTAGE_THRESHOLD = 0.5;
|
|
532
|
-
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
533
|
-
vi.spyOn(client['config'], 'getChatCompression').mockReturnValue({
|
|
534
|
-
contextPercentageThreshold: MOCKED_CONTEXT_PERCENTAGE_THRESHOLD,
|
|
535
|
-
});
|
|
536
|
-
const history = [{ role: 'user', parts: [{ text: '...history...' }] }];
|
|
537
|
-
mockGetHistory.mockReturnValue(history);
|
|
538
|
-
const originalTokenCount = MOCKED_TOKEN_LIMIT * MOCKED_CONTEXT_PERCENTAGE_THRESHOLD;
|
|
539
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
540
|
-
// Mock summary and new chat
|
|
541
|
-
const summaryText = 'This is a summary.';
|
|
542
|
-
const splitPoint = findCompressSplitPoint(history, 0.7);
|
|
543
|
-
const historyToKeep = history.slice(splitPoint);
|
|
544
|
-
const newCompressedHistory = [
|
|
545
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
546
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
547
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
548
|
-
{
|
|
549
|
-
role: 'model',
|
|
550
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
551
|
-
},
|
|
552
|
-
...historyToKeep,
|
|
553
|
-
];
|
|
554
|
-
const mockNewChat = {
|
|
555
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
556
|
-
};
|
|
557
|
-
client['startChat'] = vi
|
|
558
|
-
.fn()
|
|
559
|
-
.mockResolvedValue(mockNewChat);
|
|
560
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
561
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
562
|
-
// Mock the summary response from the chat
|
|
563
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
564
|
-
candidates: [
|
|
565
|
-
{
|
|
566
|
-
content: {
|
|
567
|
-
role: 'model',
|
|
568
|
-
parts: [{ text: summaryText }],
|
|
569
|
-
},
|
|
570
|
-
},
|
|
571
|
-
],
|
|
572
|
-
});
|
|
573
|
-
const initialChat = client.getChat();
|
|
574
|
-
const result = await client.tryCompressChat('prompt-id-3', false);
|
|
575
|
-
const newChat = client.getChat();
|
|
576
|
-
expect(tokenLimit).toHaveBeenCalled();
|
|
577
|
-
expect(mockGenerateContentFn).toHaveBeenCalled();
|
|
578
|
-
// Assert that summarization happened and returned the correct stats
|
|
579
|
-
expect(result).toEqual({
|
|
580
|
-
compressionStatus: CompressionStatus.COMPRESSED,
|
|
581
|
-
originalTokenCount,
|
|
582
|
-
newTokenCount,
|
|
583
|
-
});
|
|
584
|
-
// Assert that the chat was reset
|
|
585
|
-
expect(newChat).not.toBe(initialChat);
|
|
586
|
-
});
|
|
587
|
-
it('should not compress across a function call response', async () => {
|
|
588
|
-
const MOCKED_TOKEN_LIMIT = 1000;
|
|
589
|
-
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
590
|
-
const history = [
|
|
591
|
-
{ role: 'user', parts: [{ text: '...history 1...' }] },
|
|
592
|
-
{ role: 'model', parts: [{ text: '...history 2...' }] },
|
|
593
|
-
{ role: 'user', parts: [{ text: '...history 3...' }] },
|
|
594
|
-
{ role: 'model', parts: [{ text: '...history 4...' }] },
|
|
595
|
-
{ role: 'user', parts: [{ text: '...history 5...' }] },
|
|
596
|
-
{ role: 'model', parts: [{ text: '...history 6...' }] },
|
|
597
|
-
{ role: 'user', parts: [{ text: '...history 7...' }] },
|
|
598
|
-
{ role: 'model', parts: [{ text: '...history 8...' }] },
|
|
599
|
-
// Normally we would break here, but we have a function response.
|
|
600
|
-
{
|
|
601
|
-
role: 'user',
|
|
602
|
-
parts: [{ functionResponse: { name: '...history 8...' } }],
|
|
603
|
-
},
|
|
604
|
-
{ role: 'model', parts: [{ text: '...history 10...' }] },
|
|
605
|
-
// Instead we will break here.
|
|
606
|
-
{ role: 'user', parts: [{ text: '...history 10...' }] },
|
|
607
|
-
];
|
|
608
|
-
mockGetHistory.mockReturnValue(history);
|
|
609
|
-
const originalTokenCount = 1000 * 0.7;
|
|
610
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
611
|
-
// Mock summary and new chat
|
|
612
|
-
const summaryText = 'This is a summary.';
|
|
613
|
-
const splitPoint = findCompressSplitPoint(history, 0.7); // This should be 10
|
|
614
|
-
expect(splitPoint).toBe(10); // Verify split point logic
|
|
615
|
-
const historyToKeep = history.slice(splitPoint); // Should keep last user message
|
|
616
|
-
expect(historyToKeep).toEqual([
|
|
617
|
-
{ role: 'user', parts: [{ text: '...history 10...' }] },
|
|
618
|
-
]);
|
|
619
|
-
const newCompressedHistory = [
|
|
620
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
621
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
622
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
623
|
-
{
|
|
624
|
-
role: 'model',
|
|
625
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
626
|
-
},
|
|
627
|
-
...historyToKeep,
|
|
628
|
-
];
|
|
629
|
-
const mockNewChat = {
|
|
630
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
631
|
-
};
|
|
632
|
-
client['startChat'] = vi
|
|
633
|
-
.fn()
|
|
634
|
-
.mockResolvedValue(mockNewChat);
|
|
635
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
636
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
637
|
-
// Mock the summary response from the chat
|
|
638
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
639
|
-
candidates: [
|
|
640
|
-
{
|
|
641
|
-
content: {
|
|
642
|
-
role: 'model',
|
|
643
|
-
parts: [{ text: summaryText }],
|
|
644
|
-
},
|
|
645
|
-
},
|
|
646
|
-
],
|
|
647
|
-
});
|
|
648
|
-
const initialChat = client.getChat();
|
|
649
|
-
const result = await client.tryCompressChat('prompt-id-3', false);
|
|
650
|
-
const newChat = client.getChat();
|
|
651
|
-
expect(tokenLimit).toHaveBeenCalled();
|
|
652
|
-
expect(mockGenerateContentFn).toHaveBeenCalled();
|
|
653
|
-
// Assert that summarization happened and returned the correct stats
|
|
654
|
-
expect(result).toEqual({
|
|
655
|
-
compressionStatus: CompressionStatus.COMPRESSED,
|
|
656
|
-
originalTokenCount,
|
|
657
|
-
newTokenCount,
|
|
658
|
-
});
|
|
659
|
-
// Assert that the chat was reset
|
|
660
|
-
expect(newChat).not.toBe(initialChat);
|
|
661
|
-
// 1. standard start context message (env)
|
|
662
|
-
// 2. standard canned model response
|
|
663
|
-
// 3. compressed summary message (user)
|
|
664
|
-
// 4. standard canned model response
|
|
665
|
-
// 5. The last user message (historyToKeep)
|
|
666
|
-
expect(newChat.getHistory().length).toEqual(5);
|
|
667
|
-
});
|
|
668
|
-
it('should always trigger summarization when force is true, regardless of token count', async () => {
|
|
669
|
-
const history = [{ role: 'user', parts: [{ text: '...history...' }] }];
|
|
670
|
-
mockGetHistory.mockReturnValue(history);
|
|
671
|
-
const originalTokenCount = 100; // Well below threshold, but > estimated new count
|
|
672
|
-
vi.mocked(uiTelemetryService.getLastPromptTokenCount).mockReturnValue(originalTokenCount);
|
|
673
|
-
// Mock summary and new chat
|
|
674
|
-
const summaryText = 'This is a summary.';
|
|
675
|
-
const splitPoint = findCompressSplitPoint(history, 0.7);
|
|
676
|
-
const historyToKeep = history.slice(splitPoint);
|
|
677
|
-
const newCompressedHistory = [
|
|
678
|
-
{ role: 'user', parts: [{ text: 'Mocked env context' }] },
|
|
679
|
-
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
|
|
680
|
-
{ role: 'user', parts: [{ text: summaryText }] },
|
|
681
|
-
{
|
|
682
|
-
role: 'model',
|
|
683
|
-
parts: [{ text: 'Got it. Thanks for the additional context!' }],
|
|
684
|
-
},
|
|
685
|
-
...historyToKeep,
|
|
686
|
-
];
|
|
687
|
-
const mockNewChat = {
|
|
688
|
-
getHistory: vi.fn().mockReturnValue(newCompressedHistory),
|
|
689
|
-
};
|
|
690
|
-
client['startChat'] = vi
|
|
691
|
-
.fn()
|
|
692
|
-
.mockResolvedValue(mockNewChat);
|
|
693
|
-
const totalChars = newCompressedHistory.reduce((total, content) => total + JSON.stringify(content).length, 0);
|
|
694
|
-
const newTokenCount = Math.floor(totalChars / 4);
|
|
695
|
-
// Mock the summary response from the chat
|
|
696
|
-
mockGenerateContentFn.mockResolvedValue({
|
|
697
|
-
candidates: [
|
|
698
|
-
{
|
|
699
|
-
content: {
|
|
700
|
-
role: 'model',
|
|
701
|
-
parts: [{ text: summaryText }],
|
|
702
|
-
},
|
|
703
|
-
},
|
|
704
|
-
],
|
|
408
|
+
it('should return NOOP if history is too short to compress', async () => {
|
|
409
|
+
const { client } = setup({
|
|
410
|
+
chatHistory: [{ role: 'user', parts: [{ text: 'hi' }] }],
|
|
411
|
+
originalTokenCount: 50,
|
|
412
|
+
newTokenCount: 50,
|
|
413
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
705
414
|
});
|
|
706
|
-
const
|
|
707
|
-
const result = await client.tryCompressChat('prompt-id-1', true); // force = true
|
|
708
|
-
const newChat = client.getChat();
|
|
709
|
-
expect(mockGenerateContentFn).toHaveBeenCalled();
|
|
415
|
+
const result = await client.tryCompressChat('prompt-id-noop', false);
|
|
710
416
|
expect(result).toEqual({
|
|
711
|
-
compressionStatus: CompressionStatus.
|
|
712
|
-
originalTokenCount,
|
|
713
|
-
newTokenCount,
|
|
417
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
418
|
+
originalTokenCount: 50,
|
|
419
|
+
newTokenCount: 50,
|
|
714
420
|
});
|
|
715
|
-
// Assert that the chat was reset
|
|
716
|
-
expect(newChat).not.toBe(initialChat);
|
|
717
421
|
});
|
|
718
422
|
});
|
|
719
423
|
describe('sendMessageStream', () => {
|
|
@@ -798,6 +502,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
798
502
|
const mockChat = {
|
|
799
503
|
addHistory: vi.fn(),
|
|
800
504
|
getHistory: vi.fn().mockReturnValue([]),
|
|
505
|
+
getLastPromptTokenCount: vi.fn(),
|
|
801
506
|
};
|
|
802
507
|
client['chat'] = mockChat;
|
|
803
508
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -845,6 +550,7 @@ ${JSON.stringify({
|
|
|
845
550
|
const mockChat = {
|
|
846
551
|
addHistory: vi.fn(),
|
|
847
552
|
getHistory: vi.fn().mockReturnValue([]),
|
|
553
|
+
getLastPromptTokenCount: vi.fn(),
|
|
848
554
|
};
|
|
849
555
|
client['chat'] = mockChat;
|
|
850
556
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -855,11 +561,7 @@ ${JSON.stringify({
|
|
|
855
561
|
}
|
|
856
562
|
// Assert
|
|
857
563
|
expect(ideContextStore.get).toHaveBeenCalled();
|
|
858
|
-
|
|
859
|
-
// argument. We use `expect.any(String)` because this test is
|
|
860
|
-
// concerned with the IDE context logic, not the model routing,
|
|
861
|
-
// which is tested in its own dedicated suite.
|
|
862
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith(expect.any(String), initialRequest, expect.any(Object));
|
|
564
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'default-routed-model' }, initialRequest, expect.any(AbortSignal));
|
|
863
565
|
});
|
|
864
566
|
it('should add context if ideMode is enabled and there is one active file', async () => {
|
|
865
567
|
// Arrange
|
|
@@ -889,6 +591,7 @@ ${JSON.stringify({
|
|
|
889
591
|
const mockChat = {
|
|
890
592
|
addHistory: vi.fn(),
|
|
891
593
|
getHistory: vi.fn().mockReturnValue([]),
|
|
594
|
+
getLastPromptTokenCount: vi.fn(),
|
|
892
595
|
};
|
|
893
596
|
client['chat'] = mockChat;
|
|
894
597
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -949,6 +652,7 @@ ${JSON.stringify({
|
|
|
949
652
|
const mockChat = {
|
|
950
653
|
addHistory: vi.fn(),
|
|
951
654
|
getHistory: vi.fn().mockReturnValue([]),
|
|
655
|
+
getLastPromptTokenCount: vi.fn(),
|
|
952
656
|
};
|
|
953
657
|
client['chat'] = mockChat;
|
|
954
658
|
const initialRequest = [{ text: 'Hi' }];
|
|
@@ -982,6 +686,7 @@ ${JSON.stringify({
|
|
|
982
686
|
const mockChat = {
|
|
983
687
|
addHistory: vi.fn(),
|
|
984
688
|
getHistory: vi.fn().mockReturnValue([]),
|
|
689
|
+
getLastPromptTokenCount: vi.fn(),
|
|
985
690
|
};
|
|
986
691
|
client['chat'] = mockChat;
|
|
987
692
|
// Act
|
|
@@ -999,6 +704,7 @@ ${JSON.stringify({
|
|
|
999
704
|
expect(finalResult).toBeInstanceOf(Turn);
|
|
1000
705
|
});
|
|
1001
706
|
it('should stop infinite loop after MAX_TURNS when nextSpeaker always returns model', async () => {
|
|
707
|
+
vi.spyOn(client['config'], 'getContinueOnFailedApiCall').mockReturnValue(true);
|
|
1002
708
|
// Get the mocked checkNextSpeaker function and configure it to trigger infinite loop
|
|
1003
709
|
const { checkNextSpeaker } = await import('../utils/nextSpeakerChecker.js');
|
|
1004
710
|
const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
|
|
@@ -1014,6 +720,7 @@ ${JSON.stringify({
|
|
|
1014
720
|
const mockChat = {
|
|
1015
721
|
addHistory: vi.fn(),
|
|
1016
722
|
getHistory: vi.fn().mockReturnValue([]),
|
|
723
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1017
724
|
};
|
|
1018
725
|
client['chat'] = mockChat;
|
|
1019
726
|
// Use a signal that never gets aborted
|
|
@@ -1040,27 +747,10 @@ ${JSON.stringify({
|
|
|
1040
747
|
}
|
|
1041
748
|
// Assert
|
|
1042
749
|
expect(finalResult).toBeInstanceOf(Turn);
|
|
1043
|
-
// Debug: Check how many times checkNextSpeaker was called
|
|
1044
|
-
const callCount = mockCheckNextSpeaker.mock.calls.length;
|
|
1045
750
|
// If infinite loop protection is working, checkNextSpeaker should be called many times
|
|
1046
751
|
// but stop at MAX_TURNS (100). Since each recursive call should trigger checkNextSpeaker,
|
|
1047
752
|
// we expect it to be called multiple times before hitting the limit
|
|
1048
753
|
expect(mockCheckNextSpeaker).toHaveBeenCalled();
|
|
1049
|
-
// The test should demonstrate that the infinite loop protection works:
|
|
1050
|
-
// - If checkNextSpeaker is called many times (close to MAX_TURNS), it shows the loop was happening
|
|
1051
|
-
// - If it's only called once, the recursive behavior might not be triggered
|
|
1052
|
-
if (callCount === 0) {
|
|
1053
|
-
throw new Error('checkNextSpeaker was never called - the recursive condition was not met');
|
|
1054
|
-
}
|
|
1055
|
-
else if (callCount === 1) {
|
|
1056
|
-
// This might be expected behavior if the turn has pending tool calls or other conditions prevent recursion
|
|
1057
|
-
console.log('checkNextSpeaker called only once - no infinite loop occurred');
|
|
1058
|
-
}
|
|
1059
|
-
else {
|
|
1060
|
-
console.log(`checkNextSpeaker called ${callCount} times - infinite loop protection worked`);
|
|
1061
|
-
// If called multiple times, we expect it to be stopped before MAX_TURNS
|
|
1062
|
-
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
|
1063
|
-
}
|
|
1064
754
|
// The stream should produce events and eventually terminate
|
|
1065
755
|
expect(eventCount).toBeGreaterThanOrEqual(1);
|
|
1066
756
|
expect(eventCount).toBeLessThan(200); // Should not exceed our safety limit
|
|
@@ -1076,6 +766,7 @@ ${JSON.stringify({
|
|
|
1076
766
|
const mockChat = {
|
|
1077
767
|
addHistory: vi.fn(),
|
|
1078
768
|
getHistory: vi.fn().mockReturnValue([]),
|
|
769
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1079
770
|
};
|
|
1080
771
|
client['chat'] = mockChat;
|
|
1081
772
|
// Act & Assert
|
|
@@ -1114,6 +805,7 @@ ${JSON.stringify({
|
|
|
1114
805
|
const mockChat = {
|
|
1115
806
|
addHistory: vi.fn(),
|
|
1116
807
|
getHistory: vi.fn().mockReturnValue([]),
|
|
808
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1117
809
|
};
|
|
1118
810
|
client['chat'] = mockChat;
|
|
1119
811
|
// Use a signal that never gets aborted
|
|
@@ -1141,9 +833,8 @@ ${JSON.stringify({
|
|
|
1141
833
|
}
|
|
1142
834
|
}
|
|
1143
835
|
}
|
|
1144
|
-
catch (
|
|
836
|
+
catch (_) {
|
|
1145
837
|
// If the test framework times out, that also demonstrates the infinite loop
|
|
1146
|
-
console.error('Test timed out or errored:', error);
|
|
1147
838
|
}
|
|
1148
839
|
// Assert that the fix works - the loop should stop at MAX_TURNS
|
|
1149
840
|
const callCount = mockCheckNextSpeaker.mock.calls.length;
|
|
@@ -1151,8 +842,90 @@ ${JSON.stringify({
|
|
|
1151
842
|
// the loop should stop at MAX_TURNS (100)
|
|
1152
843
|
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
|
1153
844
|
expect(eventCount).toBeLessThanOrEqual(200); // Should have reasonable number of events
|
|
1154
|
-
|
|
1155
|
-
|
|
845
|
+
});
|
|
846
|
+
it('should yield ContextWindowWillOverflow when the context window is about to overflow', async () => {
|
|
847
|
+
// Arrange
|
|
848
|
+
const MOCKED_TOKEN_LIMIT = 1000;
|
|
849
|
+
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
850
|
+
// Set last prompt token count
|
|
851
|
+
const lastPromptTokenCount = 900;
|
|
852
|
+
const mockChat = {
|
|
853
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(lastPromptTokenCount),
|
|
854
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
855
|
+
};
|
|
856
|
+
client['chat'] = mockChat;
|
|
857
|
+
// Remaining = 100. Threshold (95%) = 95.
|
|
858
|
+
// We need a request > 95 tokens.
|
|
859
|
+
// A string of length 400 is roughly 100 tokens.
|
|
860
|
+
const longText = 'a'.repeat(400);
|
|
861
|
+
const request = [{ text: longText }];
|
|
862
|
+
const estimatedRequestTokenCount = Math.floor(JSON.stringify(request).length / 4);
|
|
863
|
+
const remainingTokenCount = MOCKED_TOKEN_LIMIT - lastPromptTokenCount;
|
|
864
|
+
// Mock tryCompressChat to not compress
|
|
865
|
+
vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
|
|
866
|
+
originalTokenCount: lastPromptTokenCount,
|
|
867
|
+
newTokenCount: lastPromptTokenCount,
|
|
868
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
869
|
+
});
|
|
870
|
+
// Act
|
|
871
|
+
const stream = client.sendMessageStream(request, new AbortController().signal, 'prompt-id-overflow');
|
|
872
|
+
const events = await fromAsync(stream);
|
|
873
|
+
// Assert
|
|
874
|
+
expect(events).toContainEqual({
|
|
875
|
+
type: GeminiEventType.ContextWindowWillOverflow,
|
|
876
|
+
value: {
|
|
877
|
+
estimatedRequestTokenCount,
|
|
878
|
+
remainingTokenCount,
|
|
879
|
+
},
|
|
880
|
+
});
|
|
881
|
+
// Ensure turn.run is not called
|
|
882
|
+
expect(mockTurnRunFn).not.toHaveBeenCalled();
|
|
883
|
+
});
|
|
884
|
+
it("should use the sticky model's token limit for the overflow check", async () => {
|
|
885
|
+
// Arrange
|
|
886
|
+
const STICKY_MODEL = 'gemini-1.5-flash';
|
|
887
|
+
const STICKY_MODEL_LIMIT = 1000;
|
|
888
|
+
const CONFIG_MODEL_LIMIT = 2000;
|
|
889
|
+
// Set up token limits
|
|
890
|
+
vi.mocked(tokenLimit).mockImplementation((model) => {
|
|
891
|
+
if (model === STICKY_MODEL)
|
|
892
|
+
return STICKY_MODEL_LIMIT;
|
|
893
|
+
return CONFIG_MODEL_LIMIT;
|
|
894
|
+
});
|
|
895
|
+
// Set the sticky model
|
|
896
|
+
client['currentSequenceModel'] = STICKY_MODEL;
|
|
897
|
+
// Set token count
|
|
898
|
+
const lastPromptTokenCount = 900;
|
|
899
|
+
const mockChat = {
|
|
900
|
+
getLastPromptTokenCount: vi.fn().mockReturnValue(lastPromptTokenCount),
|
|
901
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
902
|
+
};
|
|
903
|
+
client['chat'] = mockChat;
|
|
904
|
+
// Remaining (sticky) = 100. Threshold (95%) = 95.
|
|
905
|
+
// We need a request > 95 tokens.
|
|
906
|
+
const longText = 'a'.repeat(400);
|
|
907
|
+
const request = [{ text: longText }];
|
|
908
|
+
const estimatedRequestTokenCount = Math.floor(JSON.stringify(request).length / 4);
|
|
909
|
+
const remainingTokenCount = STICKY_MODEL_LIMIT - lastPromptTokenCount;
|
|
910
|
+
vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
|
|
911
|
+
originalTokenCount: lastPromptTokenCount,
|
|
912
|
+
newTokenCount: lastPromptTokenCount,
|
|
913
|
+
compressionStatus: CompressionStatus.NOOP,
|
|
914
|
+
});
|
|
915
|
+
// Act
|
|
916
|
+
const stream = client.sendMessageStream(request, new AbortController().signal, 'test-session-id');
|
|
917
|
+
const events = await fromAsync(stream);
|
|
918
|
+
// Assert
|
|
919
|
+
// Should overflow based on the sticky model's limit
|
|
920
|
+
expect(events).toContainEqual({
|
|
921
|
+
type: GeminiEventType.ContextWindowWillOverflow,
|
|
922
|
+
value: {
|
|
923
|
+
estimatedRequestTokenCount,
|
|
924
|
+
remainingTokenCount,
|
|
925
|
+
},
|
|
926
|
+
});
|
|
927
|
+
expect(tokenLimit).toHaveBeenCalledWith(STICKY_MODEL);
|
|
928
|
+
expect(mockTurnRunFn).not.toHaveBeenCalled();
|
|
1156
929
|
});
|
|
1157
930
|
describe('Model Routing', () => {
|
|
1158
931
|
let mockRouterService;
|
|
@@ -1166,35 +939,40 @@ ${JSON.stringify({
|
|
|
1166
939
|
mockTurnRunFn.mockReturnValue((async function* () {
|
|
1167
940
|
yield { type: 'content', value: 'Hello' };
|
|
1168
941
|
})());
|
|
942
|
+
const mockChat = {
|
|
943
|
+
addHistory: vi.fn(),
|
|
944
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
945
|
+
getLastPromptTokenCount: vi.fn(),
|
|
946
|
+
};
|
|
947
|
+
client['chat'] = mockChat;
|
|
1169
948
|
});
|
|
1170
949
|
it('should use the model router service to select a model on the first turn', async () => {
|
|
1171
950
|
const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-1');
|
|
1172
951
|
await fromAsync(stream); // consume stream
|
|
1173
952
|
expect(mockConfig.getModelRouterService).toHaveBeenCalled();
|
|
1174
953
|
expect(mockRouterService.route).toHaveBeenCalled();
|
|
1175
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith('routed-model',
|
|
1176
|
-
[{ text: 'Hi' }], expect.any(Object));
|
|
954
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'routed-model' }, [{ text: 'Hi' }], expect.any(AbortSignal));
|
|
1177
955
|
});
|
|
1178
956
|
it('should use the same model for subsequent turns in the same prompt (stickiness)', async () => {
|
|
1179
957
|
// First turn
|
|
1180
958
|
let stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-1');
|
|
1181
959
|
await fromAsync(stream);
|
|
1182
960
|
expect(mockRouterService.route).toHaveBeenCalledTimes(1);
|
|
1183
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith('routed-model', [{ text: 'Hi' }], expect.any(
|
|
961
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'routed-model' }, [{ text: 'Hi' }], expect.any(AbortSignal));
|
|
1184
962
|
// Second turn
|
|
1185
963
|
stream = client.sendMessageStream([{ text: 'Continue' }], new AbortController().signal, 'prompt-1');
|
|
1186
964
|
await fromAsync(stream);
|
|
1187
965
|
// Router should not be called again
|
|
1188
966
|
expect(mockRouterService.route).toHaveBeenCalledTimes(1);
|
|
1189
967
|
// Should stick to the first model
|
|
1190
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith('routed-model', [{ text: 'Continue' }], expect.any(
|
|
968
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'routed-model' }, [{ text: 'Continue' }], expect.any(AbortSignal));
|
|
1191
969
|
});
|
|
1192
970
|
it('should reset the sticky model and re-route when the prompt_id changes', async () => {
|
|
1193
971
|
// First prompt
|
|
1194
972
|
let stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-1');
|
|
1195
973
|
await fromAsync(stream);
|
|
1196
974
|
expect(mockRouterService.route).toHaveBeenCalledTimes(1);
|
|
1197
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith('routed-model', [{ text: 'Hi' }], expect.any(
|
|
975
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'routed-model' }, [{ text: 'Hi' }], expect.any(AbortSignal));
|
|
1198
976
|
// New prompt
|
|
1199
977
|
mockRouterService.route.mockResolvedValue({
|
|
1200
978
|
model: 'new-routed-model',
|
|
@@ -1205,7 +983,7 @@ ${JSON.stringify({
|
|
|
1205
983
|
// Router should be called again for the new prompt
|
|
1206
984
|
expect(mockRouterService.route).toHaveBeenCalledTimes(2);
|
|
1207
985
|
// Should use the newly routed model
|
|
1208
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith('new-routed-model', [{ text: 'A new topic' }], expect.any(
|
|
986
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'new-routed-model' }, [{ text: 'A new topic' }], expect.any(AbortSignal));
|
|
1209
987
|
});
|
|
1210
988
|
it('should use the fallback model and bypass routing when in fallback mode', async () => {
|
|
1211
989
|
vi.mocked(mockConfig.isInFallbackMode).mockReturnValue(true);
|
|
@@ -1215,7 +993,7 @@ ${JSON.stringify({
|
|
|
1215
993
|
});
|
|
1216
994
|
const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-1');
|
|
1217
995
|
await fromAsync(stream);
|
|
1218
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith(DEFAULT_GEMINI_FLASH_MODEL, [{ text: 'Hi' }], expect.any(
|
|
996
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: DEFAULT_GEMINI_FLASH_MODEL }, [{ text: 'Hi' }], expect.any(AbortSignal));
|
|
1219
997
|
});
|
|
1220
998
|
it('should stick to the fallback model for the entire sequence even if fallback mode ends', async () => {
|
|
1221
999
|
// Start the sequence in fallback mode
|
|
@@ -1227,7 +1005,7 @@ ${JSON.stringify({
|
|
|
1227
1005
|
let stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-fallback-stickiness');
|
|
1228
1006
|
await fromAsync(stream);
|
|
1229
1007
|
// First call should use fallback model
|
|
1230
|
-
expect(mockTurnRunFn).toHaveBeenCalledWith(DEFAULT_GEMINI_FLASH_MODEL, [{ text: 'Hi' }], expect.any(
|
|
1008
|
+
expect(mockTurnRunFn).toHaveBeenCalledWith({ model: DEFAULT_GEMINI_FLASH_MODEL }, [{ text: 'Hi' }], expect.any(AbortSignal));
|
|
1231
1009
|
// End fallback mode
|
|
1232
1010
|
vi.mocked(mockConfig.isInFallbackMode).mockReturnValue(false);
|
|
1233
1011
|
// Second call in the same sequence
|
|
@@ -1235,10 +1013,102 @@ ${JSON.stringify({
|
|
|
1235
1013
|
await fromAsync(stream);
|
|
1236
1014
|
// Router should still not be called, and it should stick to the fallback model
|
|
1237
1015
|
expect(mockTurnRunFn).toHaveBeenCalledTimes(2); // Ensure it was called again
|
|
1238
|
-
expect(mockTurnRunFn).toHaveBeenLastCalledWith(DEFAULT_GEMINI_FLASH_MODEL, // Still the fallback model
|
|
1239
|
-
[{ text: 'Continue' }], expect.any(
|
|
1016
|
+
expect(mockTurnRunFn).toHaveBeenLastCalledWith({ model: DEFAULT_GEMINI_FLASH_MODEL }, // Still the fallback model
|
|
1017
|
+
[{ text: 'Continue' }], expect.any(AbortSignal));
|
|
1240
1018
|
});
|
|
1241
1019
|
});
|
|
1020
|
+
it('should recursively call sendMessageStream with "Please continue." when InvalidStream event is received', async () => {
|
|
1021
|
+
vi.spyOn(client['config'], 'getContinueOnFailedApiCall').mockReturnValue(true);
|
|
1022
|
+
// Arrange
|
|
1023
|
+
const mockStream1 = (async function* () {
|
|
1024
|
+
yield { type: GeminiEventType.InvalidStream };
|
|
1025
|
+
})();
|
|
1026
|
+
const mockStream2 = (async function* () {
|
|
1027
|
+
yield { type: GeminiEventType.Content, value: 'Continued content' };
|
|
1028
|
+
})();
|
|
1029
|
+
mockTurnRunFn
|
|
1030
|
+
.mockReturnValueOnce(mockStream1)
|
|
1031
|
+
.mockReturnValueOnce(mockStream2);
|
|
1032
|
+
const mockChat = {
|
|
1033
|
+
addHistory: vi.fn(),
|
|
1034
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
1035
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1036
|
+
};
|
|
1037
|
+
client['chat'] = mockChat;
|
|
1038
|
+
const initialRequest = [{ text: 'Hi' }];
|
|
1039
|
+
const promptId = 'prompt-id-invalid-stream';
|
|
1040
|
+
const signal = new AbortController().signal;
|
|
1041
|
+
// Act
|
|
1042
|
+
const stream = client.sendMessageStream(initialRequest, signal, promptId);
|
|
1043
|
+
const events = await fromAsync(stream);
|
|
1044
|
+
// Assert
|
|
1045
|
+
expect(events).toEqual([
|
|
1046
|
+
{ type: GeminiEventType.ModelInfo, value: 'default-routed-model' },
|
|
1047
|
+
{ type: GeminiEventType.InvalidStream },
|
|
1048
|
+
{ type: GeminiEventType.Content, value: 'Continued content' },
|
|
1049
|
+
]);
|
|
1050
|
+
// Verify that turn.run was called twice
|
|
1051
|
+
expect(mockTurnRunFn).toHaveBeenCalledTimes(2);
|
|
1052
|
+
// First call with original request
|
|
1053
|
+
expect(mockTurnRunFn).toHaveBeenNthCalledWith(1, { model: 'default-routed-model' }, initialRequest, expect.any(AbortSignal));
|
|
1054
|
+
// Second call with "Please continue."
|
|
1055
|
+
expect(mockTurnRunFn).toHaveBeenNthCalledWith(2, { model: 'default-routed-model' }, [{ text: 'System: Please continue.' }], expect.any(AbortSignal));
|
|
1056
|
+
});
|
|
1057
|
+
it('should not recursively call sendMessageStream with "Please continue." when InvalidStream event is received and flag is false', async () => {
|
|
1058
|
+
vi.spyOn(client['config'], 'getContinueOnFailedApiCall').mockReturnValue(false);
|
|
1059
|
+
// Arrange
|
|
1060
|
+
const mockStream1 = (async function* () {
|
|
1061
|
+
yield { type: GeminiEventType.InvalidStream };
|
|
1062
|
+
})();
|
|
1063
|
+
mockTurnRunFn.mockReturnValueOnce(mockStream1);
|
|
1064
|
+
const mockChat = {
|
|
1065
|
+
addHistory: vi.fn(),
|
|
1066
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
1067
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1068
|
+
};
|
|
1069
|
+
client['chat'] = mockChat;
|
|
1070
|
+
const initialRequest = [{ text: 'Hi' }];
|
|
1071
|
+
const promptId = 'prompt-id-invalid-stream';
|
|
1072
|
+
const signal = new AbortController().signal;
|
|
1073
|
+
// Act
|
|
1074
|
+
const stream = client.sendMessageStream(initialRequest, signal, promptId);
|
|
1075
|
+
const events = await fromAsync(stream);
|
|
1076
|
+
// Assert
|
|
1077
|
+
expect(events).toEqual([
|
|
1078
|
+
{ type: GeminiEventType.ModelInfo, value: 'default-routed-model' },
|
|
1079
|
+
{ type: GeminiEventType.InvalidStream },
|
|
1080
|
+
]);
|
|
1081
|
+
// Verify that turn.run was called only once
|
|
1082
|
+
expect(mockTurnRunFn).toHaveBeenCalledTimes(1);
|
|
1083
|
+
});
|
|
1084
|
+
it('should stop recursing after one retry when InvalidStream events are repeatedly received', async () => {
|
|
1085
|
+
vi.spyOn(client['config'], 'getContinueOnFailedApiCall').mockReturnValue(true);
|
|
1086
|
+
// Arrange
|
|
1087
|
+
// Always return a new invalid stream
|
|
1088
|
+
mockTurnRunFn.mockImplementation(() => (async function* () {
|
|
1089
|
+
yield { type: GeminiEventType.InvalidStream };
|
|
1090
|
+
})());
|
|
1091
|
+
const mockChat = {
|
|
1092
|
+
addHistory: vi.fn(),
|
|
1093
|
+
getHistory: vi.fn().mockReturnValue([]),
|
|
1094
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1095
|
+
};
|
|
1096
|
+
client['chat'] = mockChat;
|
|
1097
|
+
const initialRequest = [{ text: 'Hi' }];
|
|
1098
|
+
const promptId = 'prompt-id-infinite-invalid-stream';
|
|
1099
|
+
const signal = new AbortController().signal;
|
|
1100
|
+
// Act
|
|
1101
|
+
const stream = client.sendMessageStream(initialRequest, signal, promptId);
|
|
1102
|
+
const events = await fromAsync(stream);
|
|
1103
|
+
// Assert
|
|
1104
|
+
// We expect 3 events (model_info + original + 1 retry)
|
|
1105
|
+
expect(events.length).toBe(3);
|
|
1106
|
+
expect(events
|
|
1107
|
+
.filter((e) => e.type !== GeminiEventType.ModelInfo)
|
|
1108
|
+
.every((e) => e.type === GeminiEventType.InvalidStream)).toBe(true);
|
|
1109
|
+
// Verify that turn.run was called twice
|
|
1110
|
+
expect(mockTurnRunFn).toHaveBeenCalledTimes(2);
|
|
1111
|
+
});
|
|
1242
1112
|
describe('Editor context delta', () => {
|
|
1243
1113
|
const mockStream = (async function* () {
|
|
1244
1114
|
yield { type: 'content', value: 'Hello' };
|
|
@@ -1261,6 +1131,7 @@ ${JSON.stringify({
|
|
|
1261
1131
|
.mockReturnValue([
|
|
1262
1132
|
{ role: 'user', parts: [{ text: 'previous message' }] },
|
|
1263
1133
|
]),
|
|
1134
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1264
1135
|
};
|
|
1265
1136
|
client['chat'] = mockChat;
|
|
1266
1137
|
});
|
|
@@ -1381,7 +1252,11 @@ ${JSON.stringify({
|
|
|
1381
1252
|
vi.mocked(ideContextStore.get).mockReturnValue({
|
|
1382
1253
|
workspaceState: {
|
|
1383
1254
|
openFiles: [
|
|
1384
|
-
{
|
|
1255
|
+
{
|
|
1256
|
+
...currentActiveFile,
|
|
1257
|
+
isActive: true,
|
|
1258
|
+
timestamp: Date.now(),
|
|
1259
|
+
},
|
|
1385
1260
|
],
|
|
1386
1261
|
},
|
|
1387
1262
|
});
|
|
@@ -1469,6 +1344,7 @@ ${JSON.stringify({
|
|
|
1469
1344
|
addHistory: vi.fn(),
|
|
1470
1345
|
getHistory: vi.fn().mockReturnValue([]), // Default empty history
|
|
1471
1346
|
setHistory: vi.fn(),
|
|
1347
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1472
1348
|
};
|
|
1473
1349
|
client['chat'] = mockChat;
|
|
1474
1350
|
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
@@ -1732,6 +1608,7 @@ ${JSON.stringify({
|
|
|
1732
1608
|
const mockChat = {
|
|
1733
1609
|
addHistory: vi.fn(),
|
|
1734
1610
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1611
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1735
1612
|
};
|
|
1736
1613
|
client['chat'] = mockChat;
|
|
1737
1614
|
// Act
|
|
@@ -1757,6 +1634,7 @@ ${JSON.stringify({
|
|
|
1757
1634
|
const mockChat = {
|
|
1758
1635
|
addHistory: vi.fn(),
|
|
1759
1636
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1637
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1760
1638
|
};
|
|
1761
1639
|
client['chat'] = mockChat;
|
|
1762
1640
|
// Act
|
|
@@ -1774,7 +1652,7 @@ ${JSON.stringify({
|
|
|
1774
1652
|
.mockReturnValueOnce(false)
|
|
1775
1653
|
.mockReturnValueOnce(true);
|
|
1776
1654
|
let capturedSignal;
|
|
1777
|
-
mockTurnRunFn.mockImplementation((
|
|
1655
|
+
mockTurnRunFn.mockImplementation((_modelConfigKey, _request, signal) => {
|
|
1778
1656
|
capturedSignal = signal;
|
|
1779
1657
|
return (async function* () {
|
|
1780
1658
|
yield { type: 'content', value: 'First event' };
|
|
@@ -1784,6 +1662,7 @@ ${JSON.stringify({
|
|
|
1784
1662
|
const mockChat = {
|
|
1785
1663
|
addHistory: vi.fn(),
|
|
1786
1664
|
getHistory: vi.fn().mockReturnValue([]),
|
|
1665
|
+
getLastPromptTokenCount: vi.fn(),
|
|
1787
1666
|
};
|
|
1788
1667
|
client['chat'] = mockChat;
|
|
1789
1668
|
// Act
|
|
@@ -1800,15 +1679,14 @@ ${JSON.stringify({
|
|
|
1800
1679
|
describe('generateContent', () => {
|
|
1801
1680
|
it('should call generateContent with the correct parameters', async () => {
|
|
1802
1681
|
const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
|
|
1803
|
-
const generationConfig = { temperature: 0.5 };
|
|
1804
1682
|
const abortSignal = new AbortController().signal;
|
|
1805
|
-
await client.generateContent(
|
|
1683
|
+
await client.generateContent({ model: DEFAULT_GEMINI_FLASH_MODEL }, contents, abortSignal);
|
|
1806
1684
|
expect(mockContentGenerator.generateContent).toHaveBeenCalledWith({
|
|
1807
1685
|
model: DEFAULT_GEMINI_FLASH_MODEL,
|
|
1808
1686
|
config: {
|
|
1809
1687
|
abortSignal,
|
|
1810
|
-
systemInstruction: getCoreSystemPrompt(''),
|
|
1811
|
-
temperature: 0
|
|
1688
|
+
systemInstruction: getCoreSystemPrompt({}, ''),
|
|
1689
|
+
temperature: 0,
|
|
1812
1690
|
topP: 1,
|
|
1813
1691
|
},
|
|
1814
1692
|
contents,
|
|
@@ -1819,7 +1697,7 @@ ${JSON.stringify({
|
|
|
1819
1697
|
const contents = [{ role: 'user', parts: [{ text: 'test' }] }];
|
|
1820
1698
|
const currentModel = initialModel + '-changed';
|
|
1821
1699
|
vi.spyOn(client['config'], 'getModel').mockReturnValueOnce(currentModel);
|
|
1822
|
-
await client.generateContent(
|
|
1700
|
+
await client.generateContent({ model: DEFAULT_GEMINI_FLASH_MODEL }, contents, new AbortController().signal);
|
|
1823
1701
|
expect(mockContentGenerator.generateContent).not.toHaveBeenCalledWith({
|
|
1824
1702
|
model: initialModel,
|
|
1825
1703
|
config: expect.any(Object),
|
|
@@ -1833,12 +1711,11 @@ ${JSON.stringify({
|
|
|
1833
1711
|
});
|
|
1834
1712
|
it('should use the Flash model when fallback mode is active', async () => {
|
|
1835
1713
|
const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
|
|
1836
|
-
const generationConfig = { temperature: 0.5 };
|
|
1837
1714
|
const abortSignal = new AbortController().signal;
|
|
1838
1715
|
const requestedModel = 'gemini-2.5-pro'; // A non-flash model
|
|
1839
1716
|
// Mock config to be in fallback mode
|
|
1840
1717
|
vi.spyOn(client['config'], 'isInFallbackMode').mockReturnValue(true);
|
|
1841
|
-
await client.generateContent(
|
|
1718
|
+
await client.generateContent({ model: requestedModel }, contents, abortSignal);
|
|
1842
1719
|
expect(mockGenerateContentFn).toHaveBeenCalledWith(expect.objectContaining({
|
|
1843
1720
|
model: DEFAULT_GEMINI_FLASH_MODEL,
|
|
1844
1721
|
}), 'test-session-id');
|