@machina.ai/cell-cli-core 1.20.2-rc1 → 1.22.5-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/agents/delegate-to-agent-tool.d.ts +19 -0
- package/dist/src/agents/delegate-to-agent-tool.js +111 -0
- package/dist/src/agents/delegate-to-agent-tool.js.map +1 -0
- package/dist/src/agents/delegate-to-agent-tool.test.d.ts +6 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js +133 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -0
- package/dist/src/agents/executor.js +1 -1
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js.map +1 -1
- package/dist/src/agents/registry.d.ts +15 -0
- package/dist/src/agents/registry.js +58 -2
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js +61 -0
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/availability/errorClassification.d.ts +7 -0
- package/dist/src/availability/errorClassification.js +20 -0
- package/dist/src/availability/errorClassification.js.map +1 -0
- package/dist/src/availability/modelAvailabilityService.d.ts +1 -0
- package/dist/src/availability/modelAvailabilityService.js +3 -0
- package/dist/src/availability/modelAvailabilityService.js.map +1 -1
- package/dist/src/availability/modelPolicy.d.ts +8 -1
- package/dist/src/availability/policyCatalog.d.ts +1 -0
- package/dist/src/availability/policyCatalog.js +6 -7
- package/dist/src/availability/policyCatalog.js.map +1 -1
- package/dist/src/availability/policyCatalog.test.js +2 -2
- package/dist/src/availability/policyCatalog.test.js.map +1 -1
- package/dist/src/availability/policyHelpers.d.ts +33 -3
- package/dist/src/availability/policyHelpers.js +113 -13
- package/dist/src/availability/policyHelpers.js.map +1 -1
- package/dist/src/availability/policyHelpers.test.js +133 -13
- package/dist/src/availability/policyHelpers.test.js.map +1 -1
- package/dist/src/availability/testUtils.d.ts +10 -0
- package/dist/src/availability/testUtils.js +22 -0
- package/dist/src/availability/testUtils.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.js +7 -10
- package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -0
- package/dist/src/code_assist/oauth2.js +38 -12
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +113 -6
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.js +53 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/init.test.d.ts +6 -0
- package/dist/src/commands/init.test.js +25 -0
- package/dist/src/commands/init.test.js.map +1 -0
- package/dist/src/commands/restore.d.ts +9 -0
- package/dist/src/commands/restore.js +46 -0
- package/dist/src/commands/restore.js.map +1 -0
- package/dist/src/commands/restore.test.d.ts +6 -0
- package/dist/src/commands/restore.test.js +137 -0
- package/dist/src/commands/restore.test.js.map +1 -0
- package/dist/src/commands/types.d.ts +41 -0
- package/dist/src/commands/types.js +7 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/config/config.d.ts +29 -3
- package/dist/src/config/config.js +146 -29
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +203 -9
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/defaultModelConfigs.js +21 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -1
- package/dist/src/config/models.d.ts +33 -11
- package/dist/src/config/models.js +82 -24
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +70 -76
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.js +1 -0
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +4 -0
- package/dist/src/core/baseLlmClient.d.ts +3 -1
- package/dist/src/core/baseLlmClient.js +40 -3
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +184 -7
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.js +47 -13
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +133 -6
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +5 -3
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +29 -22
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -1
- package/dist/src/core/coreToolScheduler.js +76 -34
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +135 -37
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +60 -29
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +236 -188
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiChat_network_retry.test.d.ts +6 -0
- package/dist/src/core/geminiChat_network_retry.test.js +198 -0
- package/dist/src/core/geminiChat_network_retry.test.js.map +1 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +4 -5
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +13 -11
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +19 -8
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/sessionHookTriggers.d.ts +28 -0
- package/dist/src/core/sessionHookTriggers.js +68 -0
- package/dist/src/core/sessionHookTriggers.js.map +1 -0
- package/dist/src/core/turn.d.ts +1 -0
- package/dist/src/core/turn.js +1 -1
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/fallback/handler.js +56 -115
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +124 -278
- package/dist/src/fallback/handler.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookEventHandler.js +59 -1
- package/dist/src/hooks/hookEventHandler.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.test.js +8 -1
- package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
- package/dist/src/hooks/hookRegistry.d.ts +0 -7
- package/dist/src/hooks/hookRegistry.js +8 -21
- package/dist/src/hooks/hookRegistry.js.map +1 -1
- package/dist/src/hooks/hookRegistry.test.js +2 -7
- package/dist/src/hooks/hookRegistry.test.js.map +1 -1
- package/dist/src/hooks/hookRunner.js +12 -2
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js +1 -1
- package/dist/src/hooks/hookRunner.test.js.map +1 -1
- package/dist/src/hooks/hookSystem.d.ts +0 -8
- package/dist/src/hooks/hookSystem.js +0 -18
- package/dist/src/hooks/hookSystem.js.map +1 -1
- package/dist/src/hooks/hookSystem.test.js +123 -18
- package/dist/src/hooks/hookSystem.test.js.map +1 -1
- package/dist/src/hooks/index.d.ts +3 -1
- package/dist/src/hooks/index.js +3 -0
- package/dist/src/hooks/index.js.map +1 -1
- package/dist/src/hooks/types.d.ts +1 -2
- package/dist/src/hooks/types.js +0 -1
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +32 -1
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.js +2 -0
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +1 -1
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/output/json-formatter.d.ts +2 -2
- package/dist/src/output/json-formatter.js +6 -3
- package/dist/src/output/json-formatter.js.map +1 -1
- package/dist/src/output/json-formatter.test.js +37 -9
- package/dist/src/output/json-formatter.test.js.map +1 -1
- package/dist/src/output/stream-json-formatter.js +6 -0
- package/dist/src/output/stream-json-formatter.js.map +1 -1
- package/dist/src/output/stream-json-formatter.test.js +98 -100
- package/dist/src/output/stream-json-formatter.test.js.map +1 -1
- package/dist/src/output/types.d.ts +3 -0
- package/dist/src/output/types.js.map +1 -1
- package/dist/src/policy/config.js +97 -11
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/persistence.test.d.ts +6 -0
- package/dist/src/policy/persistence.test.js +154 -0
- package/dist/src/policy/persistence.test.js.map +1 -0
- package/dist/src/policy/policies/agent.toml +31 -0
- package/dist/src/policy/policy-engine.d.ts +10 -1
- package/dist/src/policy/policy-engine.js +79 -5
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +26 -2
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/policy-updater.test.d.ts +6 -0
- package/dist/src/policy/policy-updater.test.js +116 -0
- package/dist/src/policy/policy-updater.test.js.map +1 -0
- package/dist/src/policy/shell-safety.test.d.ts +6 -0
- package/dist/src/policy/shell-safety.test.js +75 -0
- package/dist/src/policy/shell-safety.test.js.map +1 -0
- package/dist/src/policy/toml-loader.d.ts +11 -5
- package/dist/src/policy/toml-loader.js +38 -23
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +28 -7
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/types.d.ts +15 -0
- package/dist/src/resources/resource-registry.d.ts +30 -0
- package/dist/src/resources/resource-registry.js +57 -0
- package/dist/src/resources/resource-registry.js.map +1 -0
- package/dist/src/resources/resource-registry.test.d.ts +6 -0
- package/dist/src/resources/resource-registry.test.js +54 -0
- package/dist/src/resources/resource-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.js +0 -15
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +0 -62
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +10 -21
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js +2 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js +23 -12
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.test.js +69 -39
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +4 -3
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/safety/checker-runner.js +17 -6
- package/dist/src/safety/checker-runner.js.map +1 -1
- package/dist/src/services/chatCompressionService.js +15 -1
- package/dist/src/services/chatCompressionService.js.map +1 -1
- package/dist/src/services/chatCompressionService.test.js +2 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -1
- package/dist/src/services/chatRecordingService.d.ts +14 -0
- package/dist/src/services/chatRecordingService.js +37 -0
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/fileSystemService.d.ts +0 -9
- package/dist/src/services/fileSystemService.js +0 -11
- package/dist/src/services/fileSystemService.js.map +1 -1
- package/dist/src/services/gitService.js +5 -0
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +28 -0
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.js +2 -2
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/modelConfig.golden.test.js +32 -0
- package/dist/src/services/modelConfig.golden.test.js.map +1 -1
- package/dist/src/services/modelConfigService.d.ts +3 -0
- package/dist/src/services/modelConfigService.js +3 -2
- package/dist/src/services/modelConfigService.js.map +1 -1
- package/dist/src/services/modelConfigService.test.js +110 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -1
- package/dist/src/services/modelConfigServiceTestUtils.d.ts +10 -0
- package/dist/src/services/modelConfigServiceTestUtils.js +17 -0
- package/dist/src/services/modelConfigServiceTestUtils.js.map +1 -0
- package/dist/src/services/sessionSummaryService.d.ts +28 -0
- package/dist/src/services/sessionSummaryService.js +131 -0
- package/dist/src/services/sessionSummaryService.js.map +1 -0
- package/dist/src/services/sessionSummaryService.test.d.ts +6 -0
- package/dist/src/services/sessionSummaryService.test.js +785 -0
- package/dist/src/services/sessionSummaryService.test.js.map +1 -0
- package/dist/src/services/sessionSummaryUtils.d.ts +16 -0
- package/dist/src/services/sessionSummaryUtils.js +129 -0
- package/dist/src/services/sessionSummaryUtils.js.map +1 -0
- package/dist/src/services/sessionSummaryUtils.test.d.ts +6 -0
- package/dist/src/services/sessionSummaryUtils.test.js +137 -0
- package/dist/src/services/sessionSummaryUtils.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.js +28 -22
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +46 -4
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/services/test-data/resolved-aliases-retry.golden.json +238 -0
- package/dist/src/services/test-data/resolved-aliases.golden.json +16 -0
- package/dist/src/telemetry/activity-detector.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +28 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +67 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +3 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/config.js +2 -0
- package/dist/src/telemetry/config.js.map +1 -1
- package/dist/src/telemetry/config.test.js +25 -0
- package/dist/src/telemetry/config.test.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.d.ts +4 -3
- package/dist/src/telemetry/gcp-exporters.js +8 -4
- package/dist/src/telemetry/gcp-exporters.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +1 -1
- package/dist/src/telemetry/index.js +1 -1
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +345 -335
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +20 -5
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.d.ts +9 -2
- package/dist/src/telemetry/sdk.js +143 -17
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/sdk.test.js +130 -28
- package/dist/src/telemetry/sdk.test.js.map +1 -1
- package/dist/src/telemetry/startupProfiler.js +26 -3
- package/dist/src/telemetry/startupProfiler.js.map +1 -1
- package/dist/src/telemetry/startupProfiler.test.js +49 -7
- package/dist/src/telemetry/startupProfiler.test.js.map +1 -1
- package/dist/src/telemetry/telemetry.test.js +10 -3
- package/dist/src/telemetry/telemetry.test.js.map +1 -1
- package/dist/src/telemetry/trace.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +31 -6
- package/dist/src/telemetry/types.js +47 -8
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
- package/dist/src/telemetry/uiTelemetry.js +2 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +4 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/mock-message-bus.js.map +1 -1
- package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
- package/dist/src/tools/confirmation-policy.test.js +152 -0
- package/dist/src/tools/confirmation-policy.test.js.map +1 -0
- package/dist/src/tools/edit.js +5 -0
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +2 -1
- package/dist/src/tools/mcp-client-manager.js +20 -4
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +13 -10
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +39 -3
- package/dist/src/tools/mcp-client.js +433 -168
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +648 -28
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.js +13 -0
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +25 -0
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.js +1 -0
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +22 -13
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.js +1 -1
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.js +6 -4
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +1 -1
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +2 -1
- package/dist/src/tools/shell.js +15 -1
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +2 -1
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.js +5 -0
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +2 -0
- package/dist/src/tools/tool-names.js +2 -0
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tools.d.ts +19 -0
- package/dist/src/tools/tools.js +29 -8
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +17 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +1 -0
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/write-file.js +5 -0
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.d.ts +8 -0
- package/dist/src/utils/bfsFileSearch.js +63 -23
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +65 -1
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/checkpointUtils.d.ts +82 -0
- package/dist/src/utils/checkpointUtils.js +117 -0
- package/dist/src/utils/checkpointUtils.js.map +1 -0
- package/dist/src/utils/checkpointUtils.test.d.ts +6 -0
- package/dist/src/utils/checkpointUtils.test.js +229 -0
- package/dist/src/utils/checkpointUtils.test.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +3 -0
- package/dist/src/utils/debugLogger.js +27 -0
- package/dist/src/utils/debugLogger.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +4 -0
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +9 -1
- package/dist/src/utils/editor.js +23 -14
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/errors.d.ts +8 -0
- package/dist/src/utils/errors.js +39 -2
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/errors.test.d.ts +6 -0
- package/dist/src/utils/errors.test.js +155 -0
- package/dist/src/utils/errors.test.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +2 -2
- package/dist/src/utils/extensionLoader.js +5 -6
- package/dist/src/utils/extensionLoader.js.map +1 -1
- package/dist/src/utils/extensionLoader.test.js +11 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -1
- package/dist/src/utils/fetch.d.ts +1 -1
- package/dist/src/utils/fetch.js +3 -3
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +15 -0
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +1 -1
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/googleErrors.js +31 -18
- package/dist/src/utils/googleErrors.js.map +1 -1
- package/dist/src/utils/googleErrors.test.js +10 -2
- package/dist/src/utils/googleErrors.test.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.d.ts +3 -3
- package/dist/src/utils/googleQuotaErrors.js +32 -6
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.test.js +94 -2
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +4 -0
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/pathCorrector.js +12 -2
- package/dist/src/utils/pathCorrector.js.map +1 -1
- package/dist/src/utils/pathCorrector.test.js +6 -2
- package/dist/src/utils/pathCorrector.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +11 -0
- package/dist/src/utils/retry.js +54 -13
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +170 -10
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/shell-permissions.d.ts +52 -0
- package/dist/src/utils/shell-permissions.js +188 -0
- package/dist/src/utils/shell-permissions.js.map +1 -0
- package/dist/src/utils/shell-permissions.test.d.ts +6 -0
- package/dist/src/utils/shell-permissions.test.js +347 -0
- package/dist/src/utils/shell-permissions.test.js.map +1 -0
- package/dist/src/utils/shell-utils.d.ts +10 -47
- package/dist/src/utils/shell-utils.js +1 -182
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +1 -288
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/terminalSerializer.test.js +17 -0
- package/dist/src/utils/terminalSerializer.test.js.map +1 -1
- package/dist/src/utils/tool-utils.js.map +1 -1
- package/dist/src/utils/version.d.ts +6 -0
- package/dist/src/utils/version.js +15 -0
- package/dist/src/utils/version.js.map +1 -0
- package/dist/src/utils/version.test.d.ts +6 -0
- package/dist/src/utils/version.test.js +39 -0
- package/dist/src/utils/version.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -7,13 +7,16 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
|
7
7
|
import { ApiError, ThinkingLevel } from '@google/genai';
|
|
8
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,
|
|
10
|
+
import { DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_THINKING_MODE, PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_FLASH_MODEL, } from '../config/models.js';
|
|
11
11
|
import { AuthType } from './contentGenerator.js';
|
|
12
12
|
import { TerminalQuotaError } from '../utils/googleQuotaErrors.js';
|
|
13
|
-
import {
|
|
13
|
+
import {} from '../utils/retry.js';
|
|
14
14
|
import { uiTelemetryService } from '../telemetry/uiTelemetry.js';
|
|
15
15
|
import { HookSystem } from '../hooks/hookSystem.js';
|
|
16
16
|
import { createMockMessageBus } from '../test-utils/mock-message-bus.js';
|
|
17
|
+
import { createAvailabilityServiceMock } from '../availability/testUtils.js';
|
|
18
|
+
import * as policyHelpers from '../availability/policyHelpers.js';
|
|
19
|
+
import { makeResolvedModelConfig } from '../services/modelConfigServiceTestUtils.js';
|
|
17
20
|
// Mock fs module to prevent actual file system operations during tests
|
|
18
21
|
const mockFileSystem = new Map();
|
|
19
22
|
vi.mock('node:fs', () => {
|
|
@@ -31,6 +34,10 @@ vi.mock('node:fs', () => {
|
|
|
31
34
|
});
|
|
32
35
|
}),
|
|
33
36
|
existsSync: vi.fn((path) => mockFileSystem.has(path)),
|
|
37
|
+
createWriteStream: vi.fn(() => ({
|
|
38
|
+
write: vi.fn(),
|
|
39
|
+
on: vi.fn(),
|
|
40
|
+
})),
|
|
34
41
|
};
|
|
35
42
|
return {
|
|
36
43
|
default: fsModule,
|
|
@@ -44,9 +51,13 @@ const { mockHandleFallback } = vi.hoisted(() => ({
|
|
|
44
51
|
const { mockRetryWithBackoff } = vi.hoisted(() => ({
|
|
45
52
|
mockRetryWithBackoff: vi.fn(),
|
|
46
53
|
}));
|
|
47
|
-
vi.mock('../utils/retry.js', () =>
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
vi.mock('../utils/retry.js', async (importOriginal) => {
|
|
55
|
+
const actual = await importOriginal();
|
|
56
|
+
return {
|
|
57
|
+
...actual,
|
|
58
|
+
retryWithBackoff: mockRetryWithBackoff,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
50
61
|
vi.mock('../fallback/handler.js', () => ({
|
|
51
62
|
handleFallback: mockHandleFallback,
|
|
52
63
|
}));
|
|
@@ -79,19 +90,32 @@ describe('GeminiChat', () => {
|
|
|
79
90
|
};
|
|
80
91
|
mockHandleFallback.mockClear();
|
|
81
92
|
// Default mock implementation for tests that don't care about retry logic
|
|
82
|
-
mockRetryWithBackoff.mockImplementation(async (apiCall) =>
|
|
93
|
+
mockRetryWithBackoff.mockImplementation(async (apiCall, options) => {
|
|
94
|
+
const result = await apiCall();
|
|
95
|
+
const context = options?.getAvailabilityContext?.();
|
|
96
|
+
if (context) {
|
|
97
|
+
context.service.markHealthy(context.policy.model);
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
});
|
|
101
|
+
let currentModel = 'gemini-pro';
|
|
102
|
+
let currentActiveModel = 'gemini-pro';
|
|
83
103
|
mockConfig = {
|
|
84
104
|
getSessionId: () => 'test-session-id',
|
|
85
105
|
getTelemetryLogPromptsEnabled: () => true,
|
|
86
106
|
getUsageStatisticsEnabled: () => true,
|
|
87
107
|
getDebugMode: () => false,
|
|
88
108
|
getPreviewFeatures: () => false,
|
|
89
|
-
getContentGeneratorConfig: vi.fn().
|
|
90
|
-
authType: 'oauth-personal',
|
|
91
|
-
model:
|
|
109
|
+
getContentGeneratorConfig: vi.fn().mockImplementation(() => ({
|
|
110
|
+
authType: 'oauth-personal',
|
|
111
|
+
model: currentModel,
|
|
112
|
+
})),
|
|
113
|
+
getModel: vi.fn().mockImplementation(() => currentModel),
|
|
114
|
+
setModel: vi.fn().mockImplementation((m) => {
|
|
115
|
+
currentModel = m;
|
|
116
|
+
// When model is explicitly set, active model usually resets or updates to it
|
|
117
|
+
currentActiveModel = m;
|
|
92
118
|
}),
|
|
93
|
-
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
|
94
|
-
setModel: vi.fn(),
|
|
95
119
|
isInFallbackMode: vi.fn().mockReturnValue(false),
|
|
96
120
|
getQuotaErrorOccurred: vi.fn().mockReturnValue(false),
|
|
97
121
|
setQuotaErrorOccurred: vi.fn(),
|
|
@@ -105,9 +129,11 @@ describe('GeminiChat', () => {
|
|
|
105
129
|
}),
|
|
106
130
|
getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
|
|
107
131
|
getRetryFetchErrors: vi.fn().mockReturnValue(false),
|
|
132
|
+
getUserTier: vi.fn().mockReturnValue(undefined),
|
|
108
133
|
modelConfigService: {
|
|
109
134
|
getResolvedConfig: vi.fn().mockImplementation((modelConfigKey) => {
|
|
110
|
-
const
|
|
135
|
+
const model = modelConfigKey.model ?? mockConfig.getModel();
|
|
136
|
+
const thinkingConfig = model.startsWith('gemini-3')
|
|
111
137
|
? {
|
|
112
138
|
thinkingLevel: ThinkingLevel.HIGH,
|
|
113
139
|
}
|
|
@@ -115,7 +141,7 @@ describe('GeminiChat', () => {
|
|
|
115
141
|
thinkingBudget: DEFAULT_THINKING_MODE,
|
|
116
142
|
};
|
|
117
143
|
return {
|
|
118
|
-
model
|
|
144
|
+
model,
|
|
119
145
|
generateContentConfig: {
|
|
120
146
|
temperature: 0,
|
|
121
147
|
thinkingConfig,
|
|
@@ -129,6 +155,12 @@ describe('GeminiChat', () => {
|
|
|
129
155
|
setPreviewModelFallbackMode: vi.fn(),
|
|
130
156
|
isInteractive: vi.fn().mockReturnValue(false),
|
|
131
157
|
getEnableHooks: vi.fn().mockReturnValue(false),
|
|
158
|
+
isModelAvailabilityServiceEnabled: vi.fn().mockReturnValue(false),
|
|
159
|
+
getActiveModel: vi.fn().mockImplementation(() => currentActiveModel),
|
|
160
|
+
setActiveModel: vi
|
|
161
|
+
.fn()
|
|
162
|
+
.mockImplementation((m) => (currentActiveModel = m)),
|
|
163
|
+
getModelAvailabilityService: vi.fn(),
|
|
132
164
|
};
|
|
133
165
|
// Use proper MessageBus mocking for Phase 3 preparation
|
|
134
166
|
const mockMessageBus = createMockMessageBus();
|
|
@@ -421,6 +453,26 @@ describe('GeminiChat', () => {
|
|
|
421
453
|
maxAttempts: 1,
|
|
422
454
|
}));
|
|
423
455
|
});
|
|
456
|
+
it('should use maxAttempts=1 for retryWithBackoff when in Preview Model Fallback Mode (Flash)', async () => {
|
|
457
|
+
vi.mocked(mockConfig.isPreviewModelFallbackMode).mockReturnValue(true);
|
|
458
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue((async function* () {
|
|
459
|
+
yield {
|
|
460
|
+
candidates: [
|
|
461
|
+
{
|
|
462
|
+
content: { parts: [{ text: 'Success' }] },
|
|
463
|
+
finishReason: 'STOP',
|
|
464
|
+
},
|
|
465
|
+
],
|
|
466
|
+
};
|
|
467
|
+
})());
|
|
468
|
+
const stream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_FLASH_MODEL }, 'test', 'prompt-id-fast-retry-flash', new AbortController().signal);
|
|
469
|
+
for await (const _ of stream) {
|
|
470
|
+
// consume stream
|
|
471
|
+
}
|
|
472
|
+
expect(mockRetryWithBackoff).toHaveBeenCalledWith(expect.any(Function), expect.objectContaining({
|
|
473
|
+
maxAttempts: 1,
|
|
474
|
+
}));
|
|
475
|
+
});
|
|
424
476
|
it('should NOT use maxAttempts=1 for other models even in Preview Model Fallback Mode', async () => {
|
|
425
477
|
vi.mocked(mockConfig.isPreviewModelFallbackMode).mockReturnValue(true);
|
|
426
478
|
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue((async function* () {
|
|
@@ -441,44 +493,6 @@ describe('GeminiChat', () => {
|
|
|
441
493
|
maxAttempts: undefined, // Should use default
|
|
442
494
|
}));
|
|
443
495
|
});
|
|
444
|
-
it('should pass DEFAULT_GEMINI_MODEL to handleFallback when Preview Model is bypassed (downgraded)', async () => {
|
|
445
|
-
// ARRANGE
|
|
446
|
-
vi.mocked(mockConfig.isPreviewModelBypassMode).mockReturnValue(true);
|
|
447
|
-
// Mock retryWithBackoff to simulate catching the error and calling onPersistent429
|
|
448
|
-
vi.mocked(retryWithBackoff).mockImplementation(async (apiCall, options) => {
|
|
449
|
-
const onPersistent429 = options?.onPersistent429;
|
|
450
|
-
try {
|
|
451
|
-
await apiCall();
|
|
452
|
-
}
|
|
453
|
-
catch (error) {
|
|
454
|
-
if (onPersistent429) {
|
|
455
|
-
await onPersistent429(AuthType.LOGIN_WITH_GOOGLE, error);
|
|
456
|
-
}
|
|
457
|
-
throw error;
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
// We need the API call to fail so retryWithBackoff calls the callback.
|
|
461
|
-
vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(new TerminalQuotaError('Simulated Quota Error', {
|
|
462
|
-
code: 429,
|
|
463
|
-
message: 'Simulated Quota Error',
|
|
464
|
-
details: [],
|
|
465
|
-
}));
|
|
466
|
-
// ACT
|
|
467
|
-
const consumeStream = async () => {
|
|
468
|
-
const stream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-bypass', new AbortController().signal);
|
|
469
|
-
// Consume the stream to trigger execution
|
|
470
|
-
for await (const _ of stream) {
|
|
471
|
-
// do nothing
|
|
472
|
-
}
|
|
473
|
-
};
|
|
474
|
-
await expect(consumeStream()).rejects.toThrow('Simulated Quota Error');
|
|
475
|
-
expect(retryWithBackoff).toHaveBeenCalled();
|
|
476
|
-
// ASSERT
|
|
477
|
-
// handleFallback is called via onPersistent429Callback
|
|
478
|
-
// We verify it was called with DEFAULT_GEMINI_MODEL
|
|
479
|
-
expect(mockHandleFallback).toHaveBeenCalledWith(expect.anything(), DEFAULT_GEMINI_MODEL, // This is the key assertion
|
|
480
|
-
expect.anything(), expect.anything());
|
|
481
|
-
});
|
|
482
496
|
it('should throw an error when a tool call is followed by an empty stream response', async () => {
|
|
483
497
|
// 1. Setup: A history where the model has just made a function call.
|
|
484
498
|
const initialHistory = [
|
|
@@ -1295,30 +1309,6 @@ describe('GeminiChat', () => {
|
|
|
1295
1309
|
}
|
|
1296
1310
|
expect(turn4.parts[0].text).toBe('second response');
|
|
1297
1311
|
});
|
|
1298
|
-
describe('Model Resolution', () => {
|
|
1299
|
-
const mockResponse = {
|
|
1300
|
-
candidates: [
|
|
1301
|
-
{
|
|
1302
|
-
content: { parts: [{ text: 'response' }], role: 'model' },
|
|
1303
|
-
finishReason: 'STOP',
|
|
1304
|
-
},
|
|
1305
|
-
],
|
|
1306
|
-
};
|
|
1307
|
-
it('should use the FLASH model when in fallback mode (sendMessageStream)', async () => {
|
|
1308
|
-
vi.mocked(mockConfig.getModel).mockReturnValue('gemini-pro');
|
|
1309
|
-
vi.mocked(mockConfig.isInFallbackMode).mockReturnValue(true);
|
|
1310
|
-
vi.mocked(mockContentGenerator.generateContentStream).mockImplementation(async () => (async function* () {
|
|
1311
|
-
yield mockResponse;
|
|
1312
|
-
})());
|
|
1313
|
-
const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-res3', new AbortController().signal);
|
|
1314
|
-
for await (const _ of stream) {
|
|
1315
|
-
// consume stream
|
|
1316
|
-
}
|
|
1317
|
-
expect(mockContentGenerator.generateContentStream).toHaveBeenCalledWith(expect.objectContaining({
|
|
1318
|
-
model: DEFAULT_GEMINI_FLASH_MODEL,
|
|
1319
|
-
}), 'prompt-id-res3');
|
|
1320
|
-
});
|
|
1321
|
-
});
|
|
1322
1312
|
describe('Fallback Integration (Retries)', () => {
|
|
1323
1313
|
const error429 = new ApiError({
|
|
1324
1314
|
message: 'API Error 429: Quota exceeded',
|
|
@@ -1385,64 +1375,6 @@ describe('GeminiChat', () => {
|
|
|
1385
1375
|
const modelTurn = history[1];
|
|
1386
1376
|
expect(modelTurn.parts[0].text).toBe('Success on retry');
|
|
1387
1377
|
});
|
|
1388
|
-
it('should switch to DEFAULT_GEMINI_FLASH_MODEL and use thinkingBudget when falling back from a gemini-3 model', async () => {
|
|
1389
|
-
// ARRANGE
|
|
1390
|
-
const authType = AuthType.LOGIN_WITH_GOOGLE;
|
|
1391
|
-
vi.mocked(mockConfig.getContentGeneratorConfig).mockReturnValue({
|
|
1392
|
-
authType,
|
|
1393
|
-
});
|
|
1394
|
-
// Initial state: Not in fallback mode
|
|
1395
|
-
const isInFallbackModeSpy = vi.spyOn(mockConfig, 'isInFallbackMode');
|
|
1396
|
-
isInFallbackModeSpy.mockReturnValue(false);
|
|
1397
|
-
// Mock API calls:
|
|
1398
|
-
// 1. Fails with 429 (simulating gemini-3 failure)
|
|
1399
|
-
// 2. Succeeds (simulating fallback success)
|
|
1400
|
-
vi.mocked(mockContentGenerator.generateContentStream)
|
|
1401
|
-
.mockRejectedValueOnce(error429)
|
|
1402
|
-
.mockResolvedValueOnce((async function* () {
|
|
1403
|
-
yield {
|
|
1404
|
-
candidates: [
|
|
1405
|
-
{
|
|
1406
|
-
content: { parts: [{ text: 'Fallback success' }] },
|
|
1407
|
-
finishReason: 'STOP',
|
|
1408
|
-
},
|
|
1409
|
-
],
|
|
1410
|
-
};
|
|
1411
|
-
})());
|
|
1412
|
-
// Mock handleFallback to enable fallback mode and signal retry
|
|
1413
|
-
mockHandleFallback.mockImplementation(async () => {
|
|
1414
|
-
isInFallbackModeSpy.mockReturnValue(true); // Next call will see fallback mode = true
|
|
1415
|
-
return true;
|
|
1416
|
-
});
|
|
1417
|
-
// ACT
|
|
1418
|
-
const stream = await chat.sendMessageStream({ model: 'gemini-3-test-model' }, // Start with a gemini-3 model
|
|
1419
|
-
'test fallback thinking', 'prompt-id-fb3', new AbortController().signal);
|
|
1420
|
-
for await (const _ of stream) {
|
|
1421
|
-
// consume stream
|
|
1422
|
-
}
|
|
1423
|
-
// ASSERT
|
|
1424
|
-
expect(mockContentGenerator.generateContentStream).toHaveBeenCalledTimes(2);
|
|
1425
|
-
// First call: gemini-3 model, thinkingLevel set
|
|
1426
|
-
expect(mockContentGenerator.generateContentStream).toHaveBeenNthCalledWith(1, expect.objectContaining({
|
|
1427
|
-
model: 'gemini-3-test-model',
|
|
1428
|
-
config: expect.objectContaining({
|
|
1429
|
-
thinkingConfig: {
|
|
1430
|
-
thinkingBudget: undefined,
|
|
1431
|
-
thinkingLevel: ThinkingLevel.HIGH,
|
|
1432
|
-
},
|
|
1433
|
-
}),
|
|
1434
|
-
}), 'prompt-id-fb3');
|
|
1435
|
-
// Second call: DEFAULT_GEMINI_FLASH_MODEL (due to fallback), thinkingBudget set (due to fix)
|
|
1436
|
-
expect(mockContentGenerator.generateContentStream).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
|
1437
|
-
model: DEFAULT_GEMINI_FLASH_MODEL,
|
|
1438
|
-
config: expect.objectContaining({
|
|
1439
|
-
thinkingConfig: {
|
|
1440
|
-
thinkingBudget: DEFAULT_THINKING_MODE,
|
|
1441
|
-
thinkingLevel: undefined,
|
|
1442
|
-
},
|
|
1443
|
-
}),
|
|
1444
|
-
}), 'prompt-id-fb3');
|
|
1445
|
-
});
|
|
1446
1378
|
it('should stop retrying if handleFallback returns false (e.g., auth intent)', async () => {
|
|
1447
1379
|
vi.mocked(mockConfig.getModel).mockReturnValue('gemini-pro');
|
|
1448
1380
|
vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(error429);
|
|
@@ -1542,61 +1474,6 @@ describe('GeminiChat', () => {
|
|
|
1542
1474
|
]);
|
|
1543
1475
|
});
|
|
1544
1476
|
});
|
|
1545
|
-
describe('Preview Model Fallback Logic', () => {
|
|
1546
|
-
it('should reset previewModelBypassMode to false at the start of sendMessageStream', async () => {
|
|
1547
|
-
const stream = (async function* () {
|
|
1548
|
-
yield {
|
|
1549
|
-
candidates: [
|
|
1550
|
-
{
|
|
1551
|
-
content: { role: 'model', parts: [{ text: 'Success' }] },
|
|
1552
|
-
finishReason: 'STOP',
|
|
1553
|
-
},
|
|
1554
|
-
],
|
|
1555
|
-
};
|
|
1556
|
-
})();
|
|
1557
|
-
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
|
|
1558
|
-
await chat.sendMessageStream({ model: 'test-model' }, 'test', 'prompt-id-preview-model-reset', new AbortController().signal);
|
|
1559
|
-
expect(mockConfig.setPreviewModelBypassMode).toHaveBeenCalledWith(false);
|
|
1560
|
-
});
|
|
1561
|
-
it('should reset previewModelFallbackMode to false upon successful Preview Model usage', async () => {
|
|
1562
|
-
const stream = (async function* () {
|
|
1563
|
-
yield {
|
|
1564
|
-
candidates: [
|
|
1565
|
-
{
|
|
1566
|
-
content: { role: 'model', parts: [{ text: 'Success' }] },
|
|
1567
|
-
finishReason: 'STOP',
|
|
1568
|
-
},
|
|
1569
|
-
],
|
|
1570
|
-
};
|
|
1571
|
-
})();
|
|
1572
|
-
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
|
|
1573
|
-
const resultStream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-preview-model-healing', new AbortController().signal);
|
|
1574
|
-
for await (const _ of resultStream) {
|
|
1575
|
-
// consume stream
|
|
1576
|
-
}
|
|
1577
|
-
expect(mockConfig.setPreviewModelFallbackMode).toHaveBeenCalledWith(false);
|
|
1578
|
-
});
|
|
1579
|
-
it('should NOT reset previewModelFallbackMode if Preview Model was bypassed (downgraded)', async () => {
|
|
1580
|
-
const stream = (async function* () {
|
|
1581
|
-
yield {
|
|
1582
|
-
candidates: [
|
|
1583
|
-
{
|
|
1584
|
-
content: { role: 'model', parts: [{ text: 'Success' }] },
|
|
1585
|
-
finishReason: 'STOP',
|
|
1586
|
-
},
|
|
1587
|
-
],
|
|
1588
|
-
};
|
|
1589
|
-
})();
|
|
1590
|
-
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
|
|
1591
|
-
// Simulate bypass mode being active (downgrade happened)
|
|
1592
|
-
vi.mocked(mockConfig.isPreviewModelBypassMode).mockReturnValue(true);
|
|
1593
|
-
const resultStream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-bypass-no-healing', new AbortController().signal);
|
|
1594
|
-
for await (const _ of resultStream) {
|
|
1595
|
-
// consume stream
|
|
1596
|
-
}
|
|
1597
|
-
expect(mockConfig.setPreviewModelFallbackMode).not.toHaveBeenCalled();
|
|
1598
|
-
});
|
|
1599
|
-
});
|
|
1600
1477
|
describe('ensureActiveLoopHasThoughtSignatures', () => {
|
|
1601
1478
|
it('should add thoughtSignature to the first functionCall in each model turn of the active loop', () => {
|
|
1602
1479
|
const chat = new GeminiChat(mockConfig, '', [], []);
|
|
@@ -1676,5 +1553,176 @@ describe('GeminiChat', () => {
|
|
|
1676
1553
|
expect(newContents).toEqual(history);
|
|
1677
1554
|
});
|
|
1678
1555
|
});
|
|
1556
|
+
describe('Availability Service Integration', () => {
|
|
1557
|
+
let mockAvailabilityService;
|
|
1558
|
+
beforeEach(async () => {
|
|
1559
|
+
mockAvailabilityService = createAvailabilityServiceMock();
|
|
1560
|
+
vi.mocked(mockConfig.getModelAvailabilityService).mockReturnValue(mockAvailabilityService);
|
|
1561
|
+
vi.mocked(mockConfig.isModelAvailabilityServiceEnabled).mockReturnValue(true);
|
|
1562
|
+
// Stateful mock for activeModel
|
|
1563
|
+
let activeModel = 'model-a';
|
|
1564
|
+
vi.mocked(mockConfig.getActiveModel).mockImplementation(() => activeModel);
|
|
1565
|
+
vi.mocked(mockConfig.setActiveModel).mockImplementation((model) => {
|
|
1566
|
+
activeModel = model;
|
|
1567
|
+
});
|
|
1568
|
+
vi.spyOn(policyHelpers, 'resolvePolicyChain').mockReturnValue([
|
|
1569
|
+
{
|
|
1570
|
+
model: 'model-a',
|
|
1571
|
+
isLastResort: false,
|
|
1572
|
+
actions: {},
|
|
1573
|
+
stateTransitions: {},
|
|
1574
|
+
},
|
|
1575
|
+
{
|
|
1576
|
+
model: 'model-b',
|
|
1577
|
+
isLastResort: false,
|
|
1578
|
+
actions: {},
|
|
1579
|
+
stateTransitions: {},
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
model: 'model-c',
|
|
1583
|
+
isLastResort: true,
|
|
1584
|
+
actions: {},
|
|
1585
|
+
stateTransitions: {},
|
|
1586
|
+
},
|
|
1587
|
+
]);
|
|
1588
|
+
});
|
|
1589
|
+
it('should mark healthy on successful stream', async () => {
|
|
1590
|
+
vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
|
|
1591
|
+
selectedModel: 'model-b',
|
|
1592
|
+
skipped: [],
|
|
1593
|
+
});
|
|
1594
|
+
// Simulate selection happening upstream
|
|
1595
|
+
mockConfig.setActiveModel('model-b');
|
|
1596
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue((async function* () {
|
|
1597
|
+
yield {
|
|
1598
|
+
candidates: [
|
|
1599
|
+
{
|
|
1600
|
+
content: { parts: [{ text: 'Response' }], role: 'model' },
|
|
1601
|
+
finishReason: 'STOP',
|
|
1602
|
+
},
|
|
1603
|
+
],
|
|
1604
|
+
};
|
|
1605
|
+
})());
|
|
1606
|
+
const stream = await chat.sendMessageStream({ model: 'gemini-pro' }, 'test', 'prompt-healthy', new AbortController().signal);
|
|
1607
|
+
for await (const _ of stream) {
|
|
1608
|
+
// consume
|
|
1609
|
+
}
|
|
1610
|
+
expect(mockAvailabilityService.markHealthy).toHaveBeenCalledWith('model-b');
|
|
1611
|
+
});
|
|
1612
|
+
it('caps retries to a single attempt when selection is sticky', async () => {
|
|
1613
|
+
vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
|
|
1614
|
+
selectedModel: 'model-a',
|
|
1615
|
+
attempts: 1,
|
|
1616
|
+
skipped: [],
|
|
1617
|
+
});
|
|
1618
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue((async function* () {
|
|
1619
|
+
yield {
|
|
1620
|
+
candidates: [
|
|
1621
|
+
{
|
|
1622
|
+
content: { parts: [{ text: 'Response' }], role: 'model' },
|
|
1623
|
+
finishReason: 'STOP',
|
|
1624
|
+
},
|
|
1625
|
+
],
|
|
1626
|
+
};
|
|
1627
|
+
})());
|
|
1628
|
+
const stream = await chat.sendMessageStream({ model: 'gemini-pro' }, 'test', 'prompt-sticky-once', new AbortController().signal);
|
|
1629
|
+
for await (const _ of stream) {
|
|
1630
|
+
// consume
|
|
1631
|
+
}
|
|
1632
|
+
expect(mockRetryWithBackoff).toHaveBeenCalledWith(expect.any(Function), expect.objectContaining({ maxAttempts: 1 }));
|
|
1633
|
+
expect(mockAvailabilityService.consumeStickyAttempt).toHaveBeenCalledWith('model-a');
|
|
1634
|
+
});
|
|
1635
|
+
it('should pass attempted model to onPersistent429 callback which calls handleFallback', async () => {
|
|
1636
|
+
vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
|
|
1637
|
+
selectedModel: 'model-a',
|
|
1638
|
+
skipped: [],
|
|
1639
|
+
});
|
|
1640
|
+
// Simulate selection happening upstream
|
|
1641
|
+
mockConfig.setActiveModel('model-a');
|
|
1642
|
+
// Simulate retry logic behavior: catch error, call onPersistent429
|
|
1643
|
+
const error = new TerminalQuotaError('Quota', {
|
|
1644
|
+
code: 429,
|
|
1645
|
+
message: 'quota',
|
|
1646
|
+
details: [],
|
|
1647
|
+
});
|
|
1648
|
+
vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(error);
|
|
1649
|
+
// We need retryWithBackoff to trigger the callback
|
|
1650
|
+
mockRetryWithBackoff.mockImplementation(async (apiCall, options) => {
|
|
1651
|
+
try {
|
|
1652
|
+
await apiCall();
|
|
1653
|
+
}
|
|
1654
|
+
catch (e) {
|
|
1655
|
+
if (options?.onPersistent429) {
|
|
1656
|
+
await options.onPersistent429(AuthType.LOGIN_WITH_GOOGLE, e);
|
|
1657
|
+
}
|
|
1658
|
+
throw e; // throw anyway to end test
|
|
1659
|
+
}
|
|
1660
|
+
});
|
|
1661
|
+
const consume = async () => {
|
|
1662
|
+
const stream = await chat.sendMessageStream({ model: 'gemini-pro' }, 'test', 'prompt-fallback-arg', new AbortController().signal);
|
|
1663
|
+
for await (const _ of stream) {
|
|
1664
|
+
// consume
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
await expect(consume()).rejects.toThrow();
|
|
1668
|
+
// handleFallback is called with the ATTEMPTED model (model-a), not the requested one (gemini-pro)
|
|
1669
|
+
expect(mockHandleFallback).toHaveBeenCalledWith(expect.anything(), 'model-a', expect.anything(), error);
|
|
1670
|
+
});
|
|
1671
|
+
it('re-resolves generateContentConfig when active model changes between retries', async () => {
|
|
1672
|
+
// Availability enabled with stateful active model
|
|
1673
|
+
let activeModel = 'model-a';
|
|
1674
|
+
vi.mocked(mockConfig.getActiveModel).mockImplementation(() => activeModel);
|
|
1675
|
+
vi.mocked(mockConfig.setActiveModel).mockImplementation((model) => {
|
|
1676
|
+
activeModel = model;
|
|
1677
|
+
});
|
|
1678
|
+
// Different configs per model
|
|
1679
|
+
vi.mocked(mockConfig.modelConfigService.getResolvedConfig)
|
|
1680
|
+
.mockReturnValueOnce(makeResolvedModelConfig('model-a', { temperature: 0.1 }))
|
|
1681
|
+
.mockReturnValueOnce(makeResolvedModelConfig('model-b', { temperature: 0.9 }));
|
|
1682
|
+
// First attempt uses model-a, then simulate availability switching to model-b
|
|
1683
|
+
mockRetryWithBackoff.mockImplementation(async (apiCall) => {
|
|
1684
|
+
await apiCall(); // first attempt
|
|
1685
|
+
activeModel = 'model-b'; // simulate switch before retry
|
|
1686
|
+
return apiCall(); // second attempt
|
|
1687
|
+
});
|
|
1688
|
+
// Generators for each attempt
|
|
1689
|
+
const firstResponse = (async function* () {
|
|
1690
|
+
yield {
|
|
1691
|
+
candidates: [
|
|
1692
|
+
{
|
|
1693
|
+
content: { parts: [{ text: 'first' }], role: 'model' },
|
|
1694
|
+
finishReason: 'STOP',
|
|
1695
|
+
},
|
|
1696
|
+
],
|
|
1697
|
+
};
|
|
1698
|
+
})();
|
|
1699
|
+
const secondResponse = (async function* () {
|
|
1700
|
+
yield {
|
|
1701
|
+
candidates: [
|
|
1702
|
+
{
|
|
1703
|
+
content: { parts: [{ text: 'second' }], role: 'model' },
|
|
1704
|
+
finishReason: 'STOP',
|
|
1705
|
+
},
|
|
1706
|
+
],
|
|
1707
|
+
};
|
|
1708
|
+
})();
|
|
1709
|
+
vi.mocked(mockContentGenerator.generateContentStream)
|
|
1710
|
+
.mockResolvedValueOnce(firstResponse)
|
|
1711
|
+
.mockResolvedValueOnce(secondResponse);
|
|
1712
|
+
const stream = await chat.sendMessageStream({ model: 'gemini-pro' }, 'test', 'prompt-config-refresh', new AbortController().signal);
|
|
1713
|
+
// Consume to drive both attempts
|
|
1714
|
+
for await (const _ of stream) {
|
|
1715
|
+
// consume
|
|
1716
|
+
}
|
|
1717
|
+
expect(mockContentGenerator.generateContentStream).toHaveBeenNthCalledWith(1, expect.objectContaining({
|
|
1718
|
+
model: 'model-a',
|
|
1719
|
+
config: expect.objectContaining({ temperature: 0.1 }),
|
|
1720
|
+
}), expect.any(String));
|
|
1721
|
+
expect(mockContentGenerator.generateContentStream).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
|
1722
|
+
model: 'model-b',
|
|
1723
|
+
config: expect.objectContaining({ temperature: 0.9 }),
|
|
1724
|
+
}), expect.any(String));
|
|
1725
|
+
});
|
|
1726
|
+
});
|
|
1679
1727
|
});
|
|
1680
1728
|
//# sourceMappingURL=geminiChat.test.js.map
|