@machina.ai/cell-cli-core 1.13.0-rc5 → 1.16.0-rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/agents/codebase-investigator.test.d.ts +6 -0
- package/dist/src/agents/codebase-investigator.test.js +35 -0
- package/dist/src/agents/codebase-investigator.test.js.map +1 -0
- package/dist/src/agents/executor.d.ts +3 -0
- package/dist/src/agents/executor.js +21 -0
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js +358 -3
- package/dist/src/agents/executor.test.js.map +1 -1
- package/dist/src/code_assist/codeAssist.test.d.ts +6 -0
- package/dist/src/code_assist/codeAssist.test.js +99 -0
- package/dist/src/code_assist/codeAssist.test.js.map +1 -0
- package/dist/src/code_assist/experiments/client_metadata.js +2 -1
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
- package/dist/src/code_assist/experiments/client_metadata.test.d.ts +6 -0
- package/dist/src/code_assist/experiments/client_metadata.test.js +99 -0
- package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.js +2 -2
- package/dist/src/code_assist/experiments/experiments.js.map +1 -1
- package/dist/src/code_assist/experiments/experiments.test.d.ts +6 -0
- package/dist/src/code_assist/experiments/experiments.test.js +92 -0
- package/dist/src/code_assist/experiments/experiments.test.js.map +1 -0
- package/dist/src/code_assist/experiments/flagNames.d.ts +13 -0
- package/dist/src/code_assist/experiments/flagNames.js +13 -0
- package/dist/src/code_assist/experiments/flagNames.js.map +1 -0
- package/dist/src/code_assist/experiments/types.d.ts +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +49 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
- package/dist/src/code_assist/server.js +5 -8
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +109 -28
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/config/config.d.ts +34 -2
- package/dist/src/config/config.js +147 -26
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +436 -19
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/defaultModelConfigs.d.ts +7 -0
- package/dist/src/config/defaultModelConfigs.js +158 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -0
- package/dist/src/config/models.d.ts +22 -1
- package/dist/src/config/models.js +49 -6
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +71 -10
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.d.ts +1 -1
- package/dist/src/confirmation-bus/message-bus.js +2 -2
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.test.js +30 -24
- package/dist/src/confirmation-bus/message-bus.test.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +1 -0
- package/dist/src/core/baseLlmClient.d.ts +4 -8
- package/dist/src/core/baseLlmClient.js +3 -8
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +22 -27
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.d.ts +6 -5
- package/dist/src/core/client.js +33 -33
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +40 -22
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.js +7 -1
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +151 -357
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +6 -4
- package/dist/src/core/geminiChat.js +106 -29
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +317 -16
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/logger.d.ts +7 -2
- package/dist/src/core/logger.js +15 -9
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +31 -16
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.test.d.ts +6 -0
- package/dist/src/core/loggingContentGenerator.test.js +180 -0
- package/dist/src/core/loggingContentGenerator.test.js.map +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +8 -11
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/tokenLimits.test.d.ts +6 -0
- package/dist/src/core/tokenLimits.test.js +26 -0
- package/dist/src/core/tokenLimits.test.js.map +1 -0
- package/dist/src/fallback/handler.js +52 -7
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +69 -16
- package/dist/src/fallback/handler.test.js.map +1 -1
- package/dist/src/fallback/types.d.ts +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookAggregator.d.ts +68 -0
- package/dist/src/hooks/hookAggregator.js +262 -0
- package/dist/src/hooks/hookAggregator.js.map +1 -0
- package/dist/src/hooks/hookAggregator.test.d.ts +6 -0
- package/dist/src/hooks/hookAggregator.test.js +387 -0
- package/dist/src/hooks/hookAggregator.test.js.map +1 -0
- package/dist/src/hooks/hookRunner.d.ts +42 -0
- package/dist/src/hooks/hookRunner.js +272 -0
- package/dist/src/hooks/hookRunner.js.map +1 -0
- package/dist/src/hooks/hookRunner.test.d.ts +6 -0
- package/dist/src/hooks/hookRunner.test.js +468 -0
- package/dist/src/hooks/hookRunner.test.js.map +1 -0
- package/dist/src/hooks/hookTranslator.d.ts +3 -3
- package/dist/src/hooks/types.js +1 -1
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/hooks/types.test.js +280 -2
- package/dist/src/hooks/types.test.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +4 -0
- package/dist/src/ide/detect-ide.js +6 -1
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +5 -0
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +3 -1
- package/dist/src/ide/ide-client.js +66 -59
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +159 -0
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.js +71 -21
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +42 -1
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/process-utils.js +16 -0
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/process-utils.test.js +3 -3
- package/dist/src/ide/process-utils.test.js.map +1 -1
- package/dist/src/ide/types.d.ts +1 -1
- package/dist/src/ide/types.js +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.js +1 -1
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js +2 -2
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +177 -0
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.js +1 -1
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
- package/dist/src/policy/config.js +3 -1
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/config.test.js +135 -1
- package/dist/src/policy/config.test.js.map +1 -1
- package/dist/src/policy/policies/discovered.toml +8 -0
- package/dist/src/policy/policies/write.toml +10 -0
- package/dist/src/policy/policy-engine.d.ts +12 -3
- package/dist/src/policy/policy-engine.js +71 -9
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +460 -76
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/toml-loader.d.ts +2 -1
- package/dist/src/policy/toml-loader.js +103 -6
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +222 -368
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/types.d.ts +65 -0
- package/dist/src/policy/types.js +4 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/prompts/mcp-prompts.test.d.ts +6 -0
- package/dist/src/prompts/mcp-prompts.test.js +40 -0
- package/dist/src/prompts/mcp-prompts.test.js.map +1 -0
- package/dist/src/prompts/prompt-registry.test.d.ts +6 -0
- package/dist/src/prompts/prompt-registry.test.js +111 -0
- package/dist/src/prompts/prompt-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.js +15 -0
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +62 -0
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.d.ts +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +6 -14
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js +13 -10
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.test.js +4 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +2 -2
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.test.js +3 -0
- package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -1
- package/dist/src/safety/built-in.d.ts +21 -0
- package/dist/src/safety/built-in.js +106 -0
- package/dist/src/safety/built-in.js.map +1 -0
- package/dist/src/safety/built-in.test.d.ts +6 -0
- package/dist/src/safety/built-in.test.js +199 -0
- package/dist/src/safety/built-in.test.js.map +1 -0
- package/dist/src/safety/checker-runner.d.ts +48 -0
- package/dist/src/safety/checker-runner.js +208 -0
- package/dist/src/safety/checker-runner.js.map +1 -0
- package/dist/src/safety/checker-runner.test.d.ts +6 -0
- package/dist/src/safety/checker-runner.test.js +238 -0
- package/dist/src/safety/checker-runner.test.js.map +1 -0
- package/dist/src/safety/context-builder.d.ts +23 -0
- package/dist/src/safety/context-builder.js +47 -0
- package/dist/src/safety/context-builder.js.map +1 -0
- package/dist/src/safety/context-builder.test.d.ts +6 -0
- package/dist/src/safety/context-builder.test.js +49 -0
- package/dist/src/safety/context-builder.test.js.map +1 -0
- package/dist/src/safety/protocol.d.ts +88 -0
- package/dist/src/safety/protocol.js +15 -0
- package/dist/src/safety/protocol.js.map +1 -0
- package/dist/src/safety/registry.d.ts +26 -0
- package/dist/src/safety/registry.js +65 -0
- package/dist/src/safety/registry.js.map +1 -0
- package/dist/src/safety/registry.test.d.ts +6 -0
- package/dist/src/safety/registry.test.js +31 -0
- package/dist/src/safety/registry.test.js.map +1 -0
- package/dist/src/services/chatCompressionService.test.js +1 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -1
- package/dist/src/services/gitService.js +1 -1
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +1 -1
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +3 -0
- package/dist/src/services/loopDetectionService.js +81 -42
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +101 -1
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/modelConfig.golden.test.d.ts +6 -0
- package/dist/src/services/modelConfig.golden.test.js +42 -0
- package/dist/src/services/modelConfig.golden.test.js.map +1 -0
- package/dist/src/services/modelConfig.integration.test.d.ts +6 -0
- package/dist/src/services/modelConfig.integration.test.js +213 -0
- package/dist/src/services/modelConfig.integration.test.js.map +1 -0
- package/dist/src/services/modelConfigService.d.ts +46 -0
- package/dist/src/services/modelConfigService.js +146 -0
- package/dist/src/services/modelConfigService.js.map +1 -0
- package/dist/src/services/modelConfigService.test.d.ts +6 -0
- package/dist/src/services/modelConfigService.test.js +509 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -0
- package/dist/src/services/test-data/resolved-aliases.golden.json +169 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +11 -9
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +174 -150
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +76 -20
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +6 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +18 -5
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +2 -2
- package/dist/src/telemetry/index.js +2 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +7 -7
- package/dist/src/telemetry/loggers.js +23 -23
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +0 -1
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +72 -18
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +8 -4
- package/dist/src/telemetry/metrics.js +10 -4
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +42 -0
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/telemetryAttributes.js +1 -0
- package/dist/src/telemetry/telemetryAttributes.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +17 -11
- package/dist/src/telemetry/types.js +53 -28
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/tools/base-tool-invocation.test.d.ts +6 -0
- package/dist/src/tools/base-tool-invocation.test.js +85 -0
- package/dist/src/tools/base-tool-invocation.test.js.map +1 -0
- package/dist/src/tools/edit.d.ts +1 -1
- package/dist/src/tools/edit.js +31 -33
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +31 -20
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +1 -1
- package/dist/src/tools/glob.js +7 -7
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +20 -17
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +1 -1
- package/dist/src/tools/grep.js +9 -9
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +15 -12
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +1 -1
- package/dist/src/tools/ls.js +14 -15
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +32 -33
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client.js +24 -52
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +18 -0
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +1 -0
- package/dist/src/tools/mcp-tool.js +5 -2
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/memoryTool.js +1 -1
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +1 -1
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.d.ts +5 -1
- package/dist/src/tools/modifiable-tool.js +34 -13
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +56 -22
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +2 -2
- package/dist/src/tools/read-file.js +20 -24
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +63 -51
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +2 -9
- package/dist/src/tools/read-many-files.js +10 -21
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +37 -35
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +25 -8
- package/dist/src/tools/ripGrep.js +148 -176
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +383 -58
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +1 -1
- package/dist/src/tools/shell.js +17 -15
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +66 -36
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +6 -1
- package/dist/src/tools/smart-edit.js +18 -17
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +49 -24
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +29 -4
- package/dist/src/tools/tool-registry.js +108 -29
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +134 -4
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +2 -1
- package/dist/src/tools/tools.js +5 -2
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +2 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +11 -4
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.js +1 -2
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +11 -5
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.js +31 -31
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +24 -5
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +29 -0
- package/dist/src/tools/write-todos.js +34 -1
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/utils/editCorrector.js +4 -15
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +16 -0
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +3 -1
- package/dist/src/utils/editor.js +18 -1
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +11 -0
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/environmentContext.js +3 -1
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +6 -0
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/events.d.ts +14 -11
- package/dist/src/utils/events.js +1 -14
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/extensionLoader.d.ts +8 -0
- package/dist/src/utils/extensionLoader.js +61 -15
- package/dist/src/utils/extensionLoader.js.map +1 -1
- package/dist/src/utils/extensionLoader.test.js +83 -19
- package/dist/src/utils/extensionLoader.test.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +75 -60
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +2 -2
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.d.ts +2 -1
- package/dist/src/utils/googleQuotaErrors.js +20 -12
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- package/dist/src/utils/httpErrors.d.ts +18 -0
- package/dist/src/utils/httpErrors.js +36 -0
- package/dist/src/utils/httpErrors.js.map +1 -0
- package/dist/src/utils/llm-edit-fixer.js +1 -2
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.js +16 -1
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +8 -0
- package/dist/src/utils/memoryDiscovery.js +24 -0
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +43 -1
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +1 -2
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +10 -4
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/pathReader.js +4 -4
- package/dist/src/utils/pathReader.js.map +1 -1
- package/dist/src/utils/pathReader.test.js +44 -1
- package/dist/src/utils/pathReader.test.js.map +1 -1
- package/dist/src/utils/paths.d.ts +1 -1
- package/dist/src/utils/paths.js +5 -3
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/retry.d.ts +0 -9
- package/dist/src/utils/retry.js +24 -28
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +51 -0
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/shell-utils.js +5 -3
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +9 -9
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/summarizer.d.ts +4 -2
- package/dist/src/utils/summarizer.js +6 -8
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +32 -11
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/workspaceContext.d.ts +4 -3
- package/dist/src/utils/workspaceContext.js +10 -11
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +1 -1
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
7
|
import { ApiError } from '@google/genai';
|
|
8
|
-
import { GeminiChat, InvalidStreamError, StreamEventType, } from './geminiChat.js';
|
|
8
|
+
import { GeminiChat, InvalidStreamError, StreamEventType, SYNTHETIC_THOUGHT_SIGNATURE, } from './geminiChat.js';
|
|
9
9
|
import { setSimulate429 } from '../utils/testUtils.js';
|
|
10
|
-
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
|
10
|
+
import { DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_MODEL, PREVIEW_GEMINI_MODEL, } from '../config/models.js';
|
|
11
11
|
import { AuthType } from './contentGenerator.js';
|
|
12
|
-
import {} from '../utils/
|
|
12
|
+
import { TerminalQuotaError } from '../utils/googleQuotaErrors.js';
|
|
13
|
+
import { retryWithBackoff } from '../utils/retry.js';
|
|
13
14
|
import { uiTelemetryService } from '../telemetry/uiTelemetry.js';
|
|
14
15
|
// Mock fs module to prevent actual file system operations during tests
|
|
15
16
|
const mockFileSystem = new Map();
|
|
@@ -83,6 +84,7 @@ describe('GeminiChat', () => {
|
|
|
83
84
|
getTelemetryLogPromptsEnabled: () => true,
|
|
84
85
|
getUsageStatisticsEnabled: () => true,
|
|
85
86
|
getDebugMode: () => false,
|
|
87
|
+
getPreviewFeatures: () => false,
|
|
86
88
|
getContentGeneratorConfig: vi.fn().mockReturnValue({
|
|
87
89
|
authType: 'oauth-personal', // Ensure this is set for fallback tests
|
|
88
90
|
model: 'test-model',
|
|
@@ -102,6 +104,11 @@ describe('GeminiChat', () => {
|
|
|
102
104
|
}),
|
|
103
105
|
getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
|
|
104
106
|
getRetryFetchErrors: vi.fn().mockReturnValue(false),
|
|
107
|
+
isPreviewModelBypassMode: vi.fn().mockReturnValue(false),
|
|
108
|
+
setPreviewModelBypassMode: vi.fn(),
|
|
109
|
+
isPreviewModelFallbackMode: vi.fn().mockReturnValue(false),
|
|
110
|
+
setPreviewModelFallbackMode: vi.fn(),
|
|
111
|
+
isInteractive: vi.fn().mockReturnValue(false),
|
|
105
112
|
};
|
|
106
113
|
// Disable 429 simulation for tests
|
|
107
114
|
setSimulate429(false);
|
|
@@ -196,7 +203,7 @@ describe('GeminiChat', () => {
|
|
|
196
203
|
})();
|
|
197
204
|
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithNoFinish);
|
|
198
205
|
// 2. Action & Assert: The stream should fail because there's no finish reason.
|
|
199
|
-
const stream = await chat.sendMessageStream('
|
|
206
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test message' }, 'prompt-id-no-finish-empty-end');
|
|
200
207
|
await expect((async () => {
|
|
201
208
|
for await (const _ of stream) {
|
|
202
209
|
/* consume stream */
|
|
@@ -366,6 +373,84 @@ describe('GeminiChat', () => {
|
|
|
366
373
|
expect(modelTurn?.parts?.length).toBe(1);
|
|
367
374
|
expect(modelTurn?.parts[0].text).toBe('This is the visible text that should not be lost.');
|
|
368
375
|
});
|
|
376
|
+
it('should use maxAttempts=1 for retryWithBackoff when in Preview Model Fallback Mode', async () => {
|
|
377
|
+
vi.mocked(mockConfig.isPreviewModelFallbackMode).mockReturnValue(true);
|
|
378
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue((async function* () {
|
|
379
|
+
yield {
|
|
380
|
+
candidates: [
|
|
381
|
+
{
|
|
382
|
+
content: { parts: [{ text: 'Success' }] },
|
|
383
|
+
finishReason: 'STOP',
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
};
|
|
387
|
+
})());
|
|
388
|
+
const stream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-fast-retry');
|
|
389
|
+
for await (const _ of stream) {
|
|
390
|
+
// consume stream
|
|
391
|
+
}
|
|
392
|
+
expect(mockRetryWithBackoff).toHaveBeenCalledWith(expect.any(Function), expect.objectContaining({
|
|
393
|
+
maxAttempts: 1,
|
|
394
|
+
}));
|
|
395
|
+
});
|
|
396
|
+
it('should NOT use maxAttempts=1 for other models even in Preview Model Fallback Mode', async () => {
|
|
397
|
+
vi.mocked(mockConfig.isPreviewModelFallbackMode).mockReturnValue(true);
|
|
398
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue((async function* () {
|
|
399
|
+
yield {
|
|
400
|
+
candidates: [
|
|
401
|
+
{
|
|
402
|
+
content: { parts: [{ text: 'Success' }] },
|
|
403
|
+
finishReason: 'STOP',
|
|
404
|
+
},
|
|
405
|
+
],
|
|
406
|
+
};
|
|
407
|
+
})());
|
|
408
|
+
const stream = await chat.sendMessageStream(DEFAULT_GEMINI_FLASH_MODEL, { message: 'test' }, 'prompt-id-normal-retry');
|
|
409
|
+
for await (const _ of stream) {
|
|
410
|
+
// consume stream
|
|
411
|
+
}
|
|
412
|
+
expect(mockRetryWithBackoff).toHaveBeenCalledWith(expect.any(Function), expect.objectContaining({
|
|
413
|
+
maxAttempts: undefined, // Should use default
|
|
414
|
+
}));
|
|
415
|
+
});
|
|
416
|
+
it('should pass DEFAULT_GEMINI_MODEL to handleFallback when Preview Model is bypassed (downgraded)', async () => {
|
|
417
|
+
// ARRANGE
|
|
418
|
+
vi.mocked(mockConfig.isPreviewModelBypassMode).mockReturnValue(true);
|
|
419
|
+
// Mock retryWithBackoff to simulate catching the error and calling onPersistent429
|
|
420
|
+
vi.mocked(retryWithBackoff).mockImplementation(async (apiCall, options) => {
|
|
421
|
+
const onPersistent429 = options?.onPersistent429;
|
|
422
|
+
try {
|
|
423
|
+
await apiCall();
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
if (onPersistent429) {
|
|
427
|
+
await onPersistent429(AuthType.LOGIN_WITH_GOOGLE, error);
|
|
428
|
+
}
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
// We need the API call to fail so retryWithBackoff calls the callback.
|
|
433
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(new TerminalQuotaError('Simulated Quota Error', {
|
|
434
|
+
code: 429,
|
|
435
|
+
message: 'Simulated Quota Error',
|
|
436
|
+
details: [],
|
|
437
|
+
}));
|
|
438
|
+
// ACT
|
|
439
|
+
const consumeStream = async () => {
|
|
440
|
+
const stream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-bypass');
|
|
441
|
+
// Consume the stream to trigger execution
|
|
442
|
+
for await (const _ of stream) {
|
|
443
|
+
// do nothing
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
await expect(consumeStream()).rejects.toThrow('Simulated Quota Error');
|
|
447
|
+
expect(retryWithBackoff).toHaveBeenCalled();
|
|
448
|
+
// ASSERT
|
|
449
|
+
// handleFallback is called via onPersistent429Callback
|
|
450
|
+
// We verify it was called with DEFAULT_GEMINI_MODEL
|
|
451
|
+
expect(mockHandleFallback).toHaveBeenCalledWith(expect.anything(), DEFAULT_GEMINI_MODEL, // This is the key assertion
|
|
452
|
+
expect.anything(), expect.anything());
|
|
453
|
+
});
|
|
369
454
|
it('should throw an error when a tool call is followed by an empty stream response', async () => {
|
|
370
455
|
// 1. Setup: A history where the model has just made a function call.
|
|
371
456
|
const initialHistory = [
|
|
@@ -399,7 +484,7 @@ describe('GeminiChat', () => {
|
|
|
399
484
|
})();
|
|
400
485
|
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(emptyStreamResponse);
|
|
401
486
|
// 3. Action: Send the function response back to the model and consume the stream.
|
|
402
|
-
const stream = await chat.sendMessageStream('
|
|
487
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', {
|
|
403
488
|
message: {
|
|
404
489
|
functionResponse: {
|
|
405
490
|
name: 'find_restaurant',
|
|
@@ -461,7 +546,7 @@ describe('GeminiChat', () => {
|
|
|
461
546
|
};
|
|
462
547
|
})();
|
|
463
548
|
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithoutFinishReason);
|
|
464
|
-
const stream = await chat.sendMessageStream('
|
|
549
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-1');
|
|
465
550
|
await expect((async () => {
|
|
466
551
|
for await (const _ of stream) {
|
|
467
552
|
// consume stream
|
|
@@ -484,7 +569,7 @@ describe('GeminiChat', () => {
|
|
|
484
569
|
};
|
|
485
570
|
})();
|
|
486
571
|
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithEmptyResponse);
|
|
487
|
-
const stream = await chat.sendMessageStream('
|
|
572
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-1');
|
|
488
573
|
await expect((async () => {
|
|
489
574
|
for await (const _ of stream) {
|
|
490
575
|
// consume stream
|
|
@@ -515,6 +600,71 @@ describe('GeminiChat', () => {
|
|
|
515
600
|
}
|
|
516
601
|
})()).resolves.not.toThrow();
|
|
517
602
|
});
|
|
603
|
+
it('should throw InvalidStreamError when finishReason is MALFORMED_FUNCTION_CALL', async () => {
|
|
604
|
+
// Setup: Stream with MALFORMED_FUNCTION_CALL finish reason and empty response
|
|
605
|
+
const streamWithMalformedFunctionCall = (async function* () {
|
|
606
|
+
yield {
|
|
607
|
+
candidates: [
|
|
608
|
+
{
|
|
609
|
+
content: {
|
|
610
|
+
role: 'model',
|
|
611
|
+
parts: [], // Empty parts
|
|
612
|
+
},
|
|
613
|
+
finishReason: 'MALFORMED_FUNCTION_CALL',
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
};
|
|
617
|
+
})();
|
|
618
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithMalformedFunctionCall);
|
|
619
|
+
const stream = await chat.sendMessageStream('gemini-2.5-pro', { message: 'test' }, 'prompt-id-malformed');
|
|
620
|
+
// Should throw an error
|
|
621
|
+
await expect((async () => {
|
|
622
|
+
for await (const _ of stream) {
|
|
623
|
+
// consume stream
|
|
624
|
+
}
|
|
625
|
+
})()).rejects.toThrow(InvalidStreamError);
|
|
626
|
+
});
|
|
627
|
+
it('should retry when finishReason is MALFORMED_FUNCTION_CALL', async () => {
|
|
628
|
+
// 1. Mock the API to fail once with MALFORMED_FUNCTION_CALL, then succeed.
|
|
629
|
+
vi.mocked(mockContentGenerator.generateContentStream)
|
|
630
|
+
.mockImplementationOnce(async () => (async function* () {
|
|
631
|
+
yield {
|
|
632
|
+
candidates: [
|
|
633
|
+
{
|
|
634
|
+
content: { parts: [], role: 'model' },
|
|
635
|
+
finishReason: 'MALFORMED_FUNCTION_CALL',
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
};
|
|
639
|
+
})())
|
|
640
|
+
.mockImplementationOnce(async () =>
|
|
641
|
+
// Second attempt succeeds
|
|
642
|
+
(async function* () {
|
|
643
|
+
yield {
|
|
644
|
+
candidates: [
|
|
645
|
+
{
|
|
646
|
+
content: { parts: [{ text: 'Success after retry' }] },
|
|
647
|
+
finishReason: 'STOP',
|
|
648
|
+
},
|
|
649
|
+
],
|
|
650
|
+
};
|
|
651
|
+
})());
|
|
652
|
+
// 2. Send a message
|
|
653
|
+
const stream = await chat.sendMessageStream('gemini-2.5-pro', { message: 'test retry' }, 'prompt-id-retry-malformed');
|
|
654
|
+
const events = [];
|
|
655
|
+
for await (const event of stream) {
|
|
656
|
+
events.push(event);
|
|
657
|
+
}
|
|
658
|
+
// 3. Assertions
|
|
659
|
+
// Should be called twice (initial + retry)
|
|
660
|
+
expect(mockContentGenerator.generateContentStream).toHaveBeenCalledTimes(2);
|
|
661
|
+
// Check for a retry event
|
|
662
|
+
expect(events.some((e) => e.type === StreamEventType.RETRY)).toBe(true);
|
|
663
|
+
// Check for the successful content chunk
|
|
664
|
+
expect(events.some((e) => e.type === StreamEventType.CHUNK &&
|
|
665
|
+
e.value.candidates?.[0]?.content?.parts?.[0]?.text ===
|
|
666
|
+
'Success after retry')).toBe(true);
|
|
667
|
+
});
|
|
518
668
|
it('should call generateContentStream with the correct parameters', async () => {
|
|
519
669
|
const response = (async function* () {
|
|
520
670
|
yield {
|
|
@@ -583,6 +733,23 @@ describe('GeminiChat', () => {
|
|
|
583
733
|
});
|
|
584
734
|
});
|
|
585
735
|
describe('sendMessageStream with retries', () => {
|
|
736
|
+
it('should not retry on invalid content if model does not start with gemini-2', async () => {
|
|
737
|
+
// Mock the stream to fail.
|
|
738
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockImplementation(async () => (async function* () {
|
|
739
|
+
yield {
|
|
740
|
+
candidates: [{ content: { parts: [{ text: '' }] } }],
|
|
741
|
+
};
|
|
742
|
+
})());
|
|
743
|
+
const stream = await chat.sendMessageStream('gemini-1.5-pro', { message: 'test' }, 'prompt-id-no-retry');
|
|
744
|
+
await expect((async () => {
|
|
745
|
+
for await (const _ of stream) {
|
|
746
|
+
// Must loop to trigger the internal logic that throws.
|
|
747
|
+
}
|
|
748
|
+
})()).rejects.toThrow(InvalidStreamError);
|
|
749
|
+
// Should be called only 1 time (no retry)
|
|
750
|
+
expect(mockContentGenerator.generateContentStream).toHaveBeenCalledTimes(1);
|
|
751
|
+
expect(mockLogContentRetry).not.toHaveBeenCalled();
|
|
752
|
+
});
|
|
586
753
|
it('should yield a RETRY event when an invalid stream is encountered', async () => {
|
|
587
754
|
// ARRANGE: Mock the stream to fail once, then succeed.
|
|
588
755
|
vi.mocked(mockContentGenerator.generateContentStream)
|
|
@@ -606,7 +773,7 @@ describe('GeminiChat', () => {
|
|
|
606
773
|
};
|
|
607
774
|
})());
|
|
608
775
|
// ACT: Send a message and collect all events from the stream.
|
|
609
|
-
const stream = await chat.sendMessageStream('
|
|
776
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-yield-retry');
|
|
610
777
|
const events = [];
|
|
611
778
|
for await (const event of stream) {
|
|
612
779
|
events.push(event);
|
|
@@ -638,7 +805,7 @@ describe('GeminiChat', () => {
|
|
|
638
805
|
],
|
|
639
806
|
};
|
|
640
807
|
})());
|
|
641
|
-
const stream = await chat.sendMessageStream('
|
|
808
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-retry-success');
|
|
642
809
|
const chunks = [];
|
|
643
810
|
for await (const chunk of stream) {
|
|
644
811
|
chunks.push(chunk);
|
|
@@ -689,7 +856,7 @@ describe('GeminiChat', () => {
|
|
|
689
856
|
],
|
|
690
857
|
};
|
|
691
858
|
})());
|
|
692
|
-
const stream = await chat.sendMessageStream('
|
|
859
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test', config: { temperature: 0.5 } }, 'prompt-id-retry-temperature');
|
|
693
860
|
for await (const _ of stream) {
|
|
694
861
|
// consume stream
|
|
695
862
|
}
|
|
@@ -720,7 +887,7 @@ describe('GeminiChat', () => {
|
|
|
720
887
|
],
|
|
721
888
|
};
|
|
722
889
|
})());
|
|
723
|
-
const stream = await chat.sendMessageStream('
|
|
890
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-retry-fail');
|
|
724
891
|
await expect(async () => {
|
|
725
892
|
for await (const _ of stream) {
|
|
726
893
|
// Must loop to trigger the internal logic that throws.
|
|
@@ -769,7 +936,7 @@ describe('GeminiChat', () => {
|
|
|
769
936
|
it('should not retry on 400 Bad Request errors', async () => {
|
|
770
937
|
const error400 = new ApiError({ message: 'Bad Request', status: 400 });
|
|
771
938
|
vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(error400);
|
|
772
|
-
const stream = await chat.sendMessageStream('
|
|
939
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-400');
|
|
773
940
|
await expect((async () => {
|
|
774
941
|
for await (const _ of stream) {
|
|
775
942
|
/* consume stream */
|
|
@@ -900,7 +1067,7 @@ describe('GeminiChat', () => {
|
|
|
900
1067
|
};
|
|
901
1068
|
})());
|
|
902
1069
|
// 3. Send a new message
|
|
903
|
-
const stream = await chat.sendMessageStream('
|
|
1070
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'Second question' }, 'prompt-id-retry-existing');
|
|
904
1071
|
for await (const _ of stream) {
|
|
905
1072
|
// consume stream
|
|
906
1073
|
}
|
|
@@ -952,7 +1119,7 @@ describe('GeminiChat', () => {
|
|
|
952
1119
|
};
|
|
953
1120
|
})());
|
|
954
1121
|
// 2. Call the method and consume the stream.
|
|
955
|
-
const stream = await chat.sendMessageStream('
|
|
1122
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test empty stream' }, 'prompt-id-empty-stream');
|
|
956
1123
|
const chunks = [];
|
|
957
1124
|
for await (const chunk of stream) {
|
|
958
1125
|
chunks.push(chunk);
|
|
@@ -1136,7 +1303,7 @@ describe('GeminiChat', () => {
|
|
|
1136
1303
|
vi.mocked(mockConfig.getModel).mockReturnValue('gemini-pro');
|
|
1137
1304
|
vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(error429);
|
|
1138
1305
|
mockHandleFallback.mockResolvedValue(false);
|
|
1139
|
-
const stream = await chat.sendMessageStream('
|
|
1306
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test stop' }, 'prompt-id-fb2');
|
|
1140
1307
|
await expect((async () => {
|
|
1141
1308
|
for await (const _ of stream) {
|
|
1142
1309
|
/* consume stream */
|
|
@@ -1180,7 +1347,7 @@ describe('GeminiChat', () => {
|
|
|
1180
1347
|
};
|
|
1181
1348
|
})());
|
|
1182
1349
|
// Send a message and consume the stream
|
|
1183
|
-
const stream = await chat.sendMessageStream('
|
|
1350
|
+
const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-discard-test');
|
|
1184
1351
|
const events = [];
|
|
1185
1352
|
for await (const event of stream) {
|
|
1186
1353
|
events.push(event);
|
|
@@ -1231,5 +1398,139 @@ describe('GeminiChat', () => {
|
|
|
1231
1398
|
]);
|
|
1232
1399
|
});
|
|
1233
1400
|
});
|
|
1401
|
+
describe('Preview Model Fallback Logic', () => {
|
|
1402
|
+
it('should reset previewModelBypassMode to false at the start of sendMessageStream', async () => {
|
|
1403
|
+
const stream = (async function* () {
|
|
1404
|
+
yield {
|
|
1405
|
+
candidates: [
|
|
1406
|
+
{
|
|
1407
|
+
content: { role: 'model', parts: [{ text: 'Success' }] },
|
|
1408
|
+
finishReason: 'STOP',
|
|
1409
|
+
},
|
|
1410
|
+
],
|
|
1411
|
+
};
|
|
1412
|
+
})();
|
|
1413
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
|
|
1414
|
+
await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-preview-model-reset');
|
|
1415
|
+
expect(mockConfig.setPreviewModelBypassMode).toHaveBeenCalledWith(false);
|
|
1416
|
+
});
|
|
1417
|
+
it('should reset previewModelFallbackMode to false upon successful Preview Model usage', async () => {
|
|
1418
|
+
const stream = (async function* () {
|
|
1419
|
+
yield {
|
|
1420
|
+
candidates: [
|
|
1421
|
+
{
|
|
1422
|
+
content: { role: 'model', parts: [{ text: 'Success' }] },
|
|
1423
|
+
finishReason: 'STOP',
|
|
1424
|
+
},
|
|
1425
|
+
],
|
|
1426
|
+
};
|
|
1427
|
+
})();
|
|
1428
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
|
|
1429
|
+
const resultStream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-preview-model-healing');
|
|
1430
|
+
for await (const _ of resultStream) {
|
|
1431
|
+
// consume stream
|
|
1432
|
+
}
|
|
1433
|
+
expect(mockConfig.setPreviewModelFallbackMode).toHaveBeenCalledWith(false);
|
|
1434
|
+
});
|
|
1435
|
+
it('should NOT reset previewModelFallbackMode if Preview Model was bypassed (downgraded)', async () => {
|
|
1436
|
+
const stream = (async function* () {
|
|
1437
|
+
yield {
|
|
1438
|
+
candidates: [
|
|
1439
|
+
{
|
|
1440
|
+
content: { role: 'model', parts: [{ text: 'Success' }] },
|
|
1441
|
+
finishReason: 'STOP',
|
|
1442
|
+
},
|
|
1443
|
+
],
|
|
1444
|
+
};
|
|
1445
|
+
})();
|
|
1446
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
|
|
1447
|
+
// Simulate bypass mode being active (downgrade happened)
|
|
1448
|
+
vi.mocked(mockConfig.isPreviewModelBypassMode).mockReturnValue(true);
|
|
1449
|
+
const resultStream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-bypass-no-healing');
|
|
1450
|
+
for await (const _ of resultStream) {
|
|
1451
|
+
// consume stream
|
|
1452
|
+
}
|
|
1453
|
+
expect(mockConfig.setPreviewModelFallbackMode).not.toHaveBeenCalled();
|
|
1454
|
+
});
|
|
1455
|
+
});
|
|
1456
|
+
describe('ensureActiveLoopHasThoughtSignatures', () => {
|
|
1457
|
+
it('should add thoughtSignature to the first functionCall in each model turn of the active loop', () => {
|
|
1458
|
+
const chat = new GeminiChat(mockConfig, {}, []);
|
|
1459
|
+
const history = [
|
|
1460
|
+
{ role: 'user', parts: [{ text: 'Old message' }] },
|
|
1461
|
+
{
|
|
1462
|
+
role: 'model',
|
|
1463
|
+
parts: [{ functionCall: { name: 'old_tool', args: {} } }],
|
|
1464
|
+
},
|
|
1465
|
+
{ role: 'user', parts: [{ text: 'Find a restaurant' }] }, // active loop starts here
|
|
1466
|
+
{
|
|
1467
|
+
role: 'model',
|
|
1468
|
+
parts: [
|
|
1469
|
+
{ functionCall: { name: 'find_restaurant', args: {} } }, // This one gets a signature
|
|
1470
|
+
{ functionCall: { name: 'find_restaurant_2', args: {} } }, // This one does NOT
|
|
1471
|
+
],
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
role: 'user',
|
|
1475
|
+
parts: [
|
|
1476
|
+
{ functionResponse: { name: 'find_restaurant', response: {} } },
|
|
1477
|
+
],
|
|
1478
|
+
},
|
|
1479
|
+
{
|
|
1480
|
+
role: 'model',
|
|
1481
|
+
parts: [
|
|
1482
|
+
{
|
|
1483
|
+
functionCall: { name: 'tool_with_sig', args: {} },
|
|
1484
|
+
thoughtSignature: 'existing-sig',
|
|
1485
|
+
},
|
|
1486
|
+
{ functionCall: { name: 'another_tool', args: {} } }, // This one does NOT get a signature
|
|
1487
|
+
],
|
|
1488
|
+
},
|
|
1489
|
+
];
|
|
1490
|
+
const newContents = chat.ensureActiveLoopHasThoughtSignatures(history);
|
|
1491
|
+
// Outside active loop - unchanged
|
|
1492
|
+
expect(newContents[1]?.parts?.[0]).not.toHaveProperty('thoughtSignature');
|
|
1493
|
+
// Inside active loop, first model turn
|
|
1494
|
+
// First function call gets a signature
|
|
1495
|
+
expect(newContents[3]?.parts?.[0]?.thoughtSignature).toBe(SYNTHETIC_THOUGHT_SIGNATURE);
|
|
1496
|
+
// Second function call does NOT
|
|
1497
|
+
expect(newContents[3]?.parts?.[1]).not.toHaveProperty('thoughtSignature');
|
|
1498
|
+
// User functionResponse part - unchanged (this is not a model turn)
|
|
1499
|
+
expect(newContents[4]?.parts?.[0]).not.toHaveProperty('thoughtSignature');
|
|
1500
|
+
// Inside active loop, second model turn
|
|
1501
|
+
// First function call already has a signature, so nothing changes
|
|
1502
|
+
expect(newContents[5]?.parts?.[0]?.thoughtSignature).toBe('existing-sig');
|
|
1503
|
+
// Second function call does NOT get a signature
|
|
1504
|
+
expect(newContents[5]?.parts?.[1]).not.toHaveProperty('thoughtSignature');
|
|
1505
|
+
});
|
|
1506
|
+
it('should not modify contents if there is no user text message', () => {
|
|
1507
|
+
const chat = new GeminiChat(mockConfig, {}, []);
|
|
1508
|
+
const history = [
|
|
1509
|
+
{
|
|
1510
|
+
role: 'user',
|
|
1511
|
+
parts: [{ functionResponse: { name: 'tool1', response: {} } }],
|
|
1512
|
+
},
|
|
1513
|
+
{
|
|
1514
|
+
role: 'model',
|
|
1515
|
+
parts: [{ functionCall: { name: 'tool2', args: {} } }],
|
|
1516
|
+
},
|
|
1517
|
+
];
|
|
1518
|
+
const newContents = chat.ensureActiveLoopHasThoughtSignatures(history);
|
|
1519
|
+
expect(newContents).toEqual(history);
|
|
1520
|
+
expect(newContents[1]?.parts?.[0]).not.toHaveProperty('thoughtSignature');
|
|
1521
|
+
});
|
|
1522
|
+
it('should handle an empty history', () => {
|
|
1523
|
+
const chat = new GeminiChat(mockConfig, {}, []);
|
|
1524
|
+
const history = [];
|
|
1525
|
+
const newContents = chat.ensureActiveLoopHasThoughtSignatures(history);
|
|
1526
|
+
expect(newContents).toEqual([]);
|
|
1527
|
+
});
|
|
1528
|
+
it('should handle history with only a user message', () => {
|
|
1529
|
+
const chat = new GeminiChat(mockConfig, {}, []);
|
|
1530
|
+
const history = [{ role: 'user', parts: [{ text: 'Hello' }] }];
|
|
1531
|
+
const newContents = chat.ensureActiveLoopHasThoughtSignatures(history);
|
|
1532
|
+
expect(newContents).toEqual(history);
|
|
1533
|
+
});
|
|
1534
|
+
});
|
|
1234
1535
|
});
|
|
1235
1536
|
//# sourceMappingURL=geminiChat.test.js.map
|