@machina.ai/cell-cli-core 1.4.0-rc2 → 1.6.1-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 +6 -4
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/package.json +6 -2
- package/dist/src/code_assist/codeAssist.js +1 -1
- package/dist/src/code_assist/codeAssist.js.map +1 -1
- package/dist/src/code_assist/converter.d.ts +1 -0
- package/dist/src/code_assist/converter.js +1 -0
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +10 -0
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.d.ts +25 -0
- package/dist/src/code_assist/oauth-credential-storage.js +109 -0
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js +136 -0
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -0
- package/dist/src/code_assist/oauth2.js +28 -2
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +674 -536
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +1 -1
- package/dist/src/code_assist/server.js +24 -1
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +25 -0
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +17 -2
- package/dist/src/config/config.d.ts +62 -5
- package/dist/src/config/config.js +154 -42
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +235 -137
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/models.d.ts +15 -0
- package/dist/src/config/models.js +27 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.d.ts +6 -0
- package/dist/src/config/models.test.js +55 -0
- package/dist/src/config/models.test.js.map +1 -0
- package/dist/src/config/storage.d.ts +2 -0
- package/dist/src/config/storage.js +6 -1
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +4 -0
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/confirmation-bus/index.d.ts +7 -0
- package/dist/src/confirmation-bus/index.js +8 -0
- package/dist/src/confirmation-bus/index.js.map +1 -0
- package/dist/src/confirmation-bus/message-bus.d.ts +17 -0
- package/dist/src/confirmation-bus/message-bus.js +81 -0
- package/dist/src/confirmation-bus/message-bus.js.map +1 -0
- package/dist/src/confirmation-bus/message-bus.test.d.ts +6 -0
- package/dist/src/confirmation-bus/message-bus.test.js +164 -0
- package/dist/src/confirmation-bus/message-bus.test.js.map +1 -0
- package/dist/src/confirmation-bus/types.d.ts +38 -0
- package/dist/src/confirmation-bus/types.js +15 -0
- package/dist/src/confirmation-bus/types.js.map +1 -0
- package/dist/src/core/baseLlmClient.d.ts +46 -0
- package/dist/src/core/baseLlmClient.js +112 -0
- package/dist/src/core/baseLlmClient.js.map +1 -0
- package/dist/src/core/baseLlmClient.test.d.ts +6 -0
- package/dist/src/core/baseLlmClient.test.js +253 -0
- package/dist/src/core/baseLlmClient.test.js.map +1 -0
- package/dist/src/core/client.d.ts +8 -18
- package/dist/src/core/client.js +108 -227
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +269 -491
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +0 -1
- package/dist/src/core/contentGenerator.js +0 -4
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +1 -3
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +8 -3
- package/dist/src/core/coreToolScheduler.js +118 -8
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +314 -5
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +15 -38
- package/dist/src/core/geminiChat.js +108 -257
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +429 -491
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.js +7 -10
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +57 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.d.ts +5 -0
- package/dist/src/core/prompts.js +64 -43
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +146 -17
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/subagent.js +2 -4
- package/dist/src/core/subagent.js.map +1 -1
- package/dist/src/core/subagent.test.js +12 -13
- package/dist/src/core/subagent.test.js.map +1 -1
- package/dist/src/core/turn.d.ts +3 -1
- package/dist/src/core/turn.js +2 -2
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +18 -18
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/fallback/handler.d.ts +7 -0
- package/dist/src/fallback/handler.js +51 -0
- package/dist/src/fallback/handler.js.map +1 -0
- package/dist/src/fallback/handler.test.d.ts +6 -0
- package/dist/src/fallback/handler.test.js +130 -0
- package/dist/src/fallback/handler.test.js.map +1 -0
- package/dist/src/fallback/types.d.ts +14 -0
- package/dist/src/fallback/types.js +7 -0
- package/dist/src/fallback/types.js.map +1 -0
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/ide/constants.d.ts +3 -0
- package/dist/src/ide/constants.js +3 -0
- package/dist/src/ide/constants.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +51 -13
- package/dist/src/ide/ide-client.js +241 -35
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +236 -0
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.js +8 -2
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +13 -2
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +35 -377
- package/dist/src/ide/ideContext.js +60 -107
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/ideContext.test.js +152 -24
- package/dist/src/ide/ideContext.test.js.map +1 -1
- package/dist/src/ide/process-utils.js +8 -1
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/types.d.ts +486 -0
- package/dist/src/ide/types.js +138 -0
- package/dist/src/ide/types.js.map +1 -0
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.js +6 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +1 -0
- package/dist/src/mcp/oauth-provider.js +22 -17
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +149 -13
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +10 -6
- package/dist/src/mcp/oauth-token-storage.js +48 -16
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.test.js +254 -163
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.js +1 -0
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/token-storage/index.d.ts +11 -0
- package/dist/src/mcp/token-storage/index.js +12 -0
- package/dist/src/mcp/token-storage/index.js.map +1 -0
- package/dist/src/output/json-formatter.d.ts +11 -0
- package/dist/src/output/json-formatter.js +30 -0
- package/dist/src/output/json-formatter.js.map +1 -0
- package/dist/src/output/json-formatter.test.d.ts +6 -0
- package/dist/src/output/json-formatter.test.js +266 -0
- package/dist/src/output/json-formatter.test.js.map +1 -0
- package/dist/src/output/types.d.ts +20 -0
- package/dist/src/output/types.js +11 -0
- package/dist/src/output/types.js.map +1 -0
- package/dist/src/policy/index.d.ts +7 -0
- package/dist/src/policy/index.js +8 -0
- package/dist/src/policy/index.js.map +1 -0
- package/dist/src/policy/policy-engine.d.ts +30 -0
- package/dist/src/policy/policy-engine.js +83 -0
- package/dist/src/policy/policy-engine.js.map +1 -0
- package/dist/src/policy/policy-engine.test.d.ts +6 -0
- package/dist/src/policy/policy-engine.test.js +470 -0
- package/dist/src/policy/policy-engine.test.js.map +1 -0
- package/dist/src/policy/stable-stringify.d.ts +58 -0
- package/dist/src/policy/stable-stringify.js +122 -0
- package/dist/src/policy/stable-stringify.js.map +1 -0
- package/dist/src/policy/types.d.ts +47 -0
- package/dist/src/policy/types.js +12 -0
- package/dist/src/policy/types.js.map +1 -0
- package/dist/src/routing/modelRouterService.d.ts +23 -0
- package/dist/src/routing/modelRouterService.js +70 -0
- package/dist/src/routing/modelRouterService.js.map +1 -0
- package/dist/src/routing/modelRouterService.test.d.ts +6 -0
- package/dist/src/routing/modelRouterService.test.js +98 -0
- package/dist/src/routing/modelRouterService.test.js.map +1 -0
- package/dist/src/routing/routingStrategy.d.ts +62 -0
- package/dist/src/routing/routingStrategy.js +7 -0
- package/dist/src/routing/routingStrategy.js.map +1 -0
- package/dist/src/routing/strategies/classifierStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/classifierStrategy.js +173 -0
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -0
- package/dist/src/routing/strategies/classifierStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/classifierStrategy.test.js +192 -0
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/compositeStrategy.d.ts +26 -0
- package/dist/src/routing/strategies/compositeStrategy.js +67 -0
- package/dist/src/routing/strategies/compositeStrategy.js.map +1 -0
- package/dist/src/routing/strategies/compositeStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/compositeStrategy.test.js +123 -0
- package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/defaultStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/defaultStrategy.js +20 -0
- package/dist/src/routing/strategies/defaultStrategy.js.map +1 -0
- package/dist/src/routing/strategies/defaultStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/defaultStrategy.test.js +26 -0
- package/dist/src/routing/strategies/defaultStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/fallbackStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/fallbackStrategy.js +25 -0
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.js +55 -0
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/overrideStrategy.d.ts +15 -0
- package/dist/src/routing/strategies/overrideStrategy.js +28 -0
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -0
- package/dist/src/routing/strategies/overrideStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/overrideStrategy.test.js +42 -0
- package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -0
- package/dist/src/services/chatRecordingService.d.ts +2 -1
- package/dist/src/services/chatRecordingService.js +3 -3
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/chatRecordingService.test.js +8 -3
- package/dist/src/services/chatRecordingService.test.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.d.ts +10 -0
- package/dist/src/services/fileDiscoveryService.js +31 -17
- package/dist/src/services/fileDiscoveryService.js.map +1 -1
- package/dist/src/services/gitService.js +9 -12
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +10 -20
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +5 -0
- package/dist/src/services/loopDetectionService.js +36 -20
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +41 -12
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.d.ts +34 -2
- package/dist/src/services/shellExecutionService.js +192 -43
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +184 -55
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +14 -2
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +107 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +82 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +13 -2
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +33 -2
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +7 -0
- package/dist/src/telemetry/constants.js +7 -0
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.d.ts +34 -0
- package/dist/src/telemetry/gcp-exporters.js +117 -0
- package/dist/src/telemetry/gcp-exporters.js.map +1 -0
- package/dist/src/telemetry/gcp-exporters.test.d.ts +6 -0
- package/dist/src/telemetry/gcp-exporters.test.js +318 -0
- package/dist/src/telemetry/gcp-exporters.test.js.map +1 -0
- package/dist/src/telemetry/high-water-mark-tracker.d.ts +43 -0
- package/dist/src/telemetry/high-water-mark-tracker.js +88 -0
- package/dist/src/telemetry/high-water-mark-tracker.js.map +1 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.d.ts +6 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.js +152 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +5 -2
- package/dist/src/telemetry/index.js +5 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +8 -1
- package/dist/src/telemetry/loggers.js +114 -7
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +232 -39
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +3 -1
- package/dist/src/telemetry/metrics.js +32 -3
- 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/rate-limiter.d.ts +48 -0
- package/dist/src/telemetry/rate-limiter.js +100 -0
- package/dist/src/telemetry/rate-limiter.js.map +1 -0
- package/dist/src/telemetry/rate-limiter.test.d.ts +6 -0
- package/dist/src/telemetry/rate-limiter.test.js +207 -0
- package/dist/src/telemetry/rate-limiter.test.js.map +1 -0
- package/dist/src/telemetry/sdk.js +19 -1
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/sdk.test.js +95 -0
- package/dist/src/telemetry/sdk.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +60 -3
- package/dist/src/telemetry/types.js +93 -3
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/tools/edit.js +12 -5
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +120 -9
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +5 -1
- package/dist/src/tools/glob.js +24 -17
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +51 -0
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/ls.js +19 -32
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +140 -280
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.js +5 -21
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client.js +5 -5
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-tool.js +30 -2
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +117 -0
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.js +7 -2
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +29 -0
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +1 -1
- package/dist/src/tools/read-many-files.js +17 -49
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +8 -0
- package/dist/src/tools/ripGrep.js +26 -1
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +107 -5
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +12 -2
- package/dist/src/tools/shell.js +20 -27
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +33 -68
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +0 -1
- package/dist/src/tools/smart-edit.js +12 -19
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +68 -9
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-registry.js +1 -0
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tools.d.ts +8 -5
- package/dist/src/tools/tools.js +9 -2
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/write-file.js +4 -5
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +94 -10
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.js +11 -5
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/editCorrector.d.ts +7 -6
- package/dist/src/utils/editCorrector.js +61 -18
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +30 -79
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.js +31 -44
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +61 -75
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/errorParsing.js +2 -2
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +7 -7
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/errors.d.ts +6 -0
- package/dist/src/utils/errors.js +10 -0
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +1 -0
- package/dist/src/utils/fileUtils.js +10 -0
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +34 -9
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawler.test.js +1 -1
- package/dist/src/utils/filesearch/crawler.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.test.js +1 -1
- package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
- package/dist/src/utils/filesearch/ignore.test.js +1 -1
- package/dist/src/utils/filesearch/ignore.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.d.ts +6 -0
- package/dist/src/utils/{flashFallback.integration.test.js → flashFallback.test.js} +31 -27
- package/dist/src/utils/flashFallback.test.js.map +1 -0
- package/dist/src/utils/geminiIgnoreParser.d.ts +18 -0
- package/dist/src/utils/geminiIgnoreParser.js +61 -0
- package/dist/src/utils/geminiIgnoreParser.js.map +1 -0
- package/dist/src/utils/geminiIgnoreParser.test.d.ts +6 -0
- package/dist/src/utils/geminiIgnoreParser.test.js +50 -0
- package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.d.ts +3 -8
- package/dist/src/utils/gitIgnoreParser.js +60 -60
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.test.js +18 -53
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/installationManager.test.js +1 -1
- package/dist/src/utils/installationManager.test.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.d.ts +4 -3
- package/dist/src/utils/llm-edit-fixer.js +19 -10
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.d.ts +6 -0
- package/dist/src/utils/llm-edit-fixer.test.js +105 -0
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.test.js +12 -6
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.d.ts +2 -2
- package/dist/src/utils/nextSpeakerChecker.js +8 -2
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +52 -74
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/promptIdContext.d.ts +7 -0
- package/dist/src/utils/promptIdContext.js +8 -0
- package/dist/src/utils/promptIdContext.js.map +1 -0
- package/dist/src/utils/shell-utils.d.ts +5 -0
- package/dist/src/utils/shell-utils.js +23 -0
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/terminalSerializer.d.ts +28 -0
- package/dist/src/utils/terminalSerializer.js +432 -0
- package/dist/src/utils/terminalSerializer.js.map +1 -0
- package/dist/src/utils/terminalSerializer.test.d.ts +6 -0
- package/dist/src/utils/terminalSerializer.test.js +176 -0
- package/dist/src/utils/terminalSerializer.test.js.map +1 -0
- package/dist/src/utils/textUtils.d.ts +5 -0
- package/dist/src/utils/textUtils.js +14 -0
- package/dist/src/utils/textUtils.js.map +1 -1
- package/dist/src/utils/textUtils.test.d.ts +6 -0
- package/dist/src/utils/textUtils.test.js +59 -0
- package/dist/src/utils/textUtils.test.js.map +1 -0
- package/dist/src/utils/userAccountManager.test.js +1 -1
- package/dist/src/utils/userAccountManager.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -2
- package/dist/src/utils/flashFallback.integration.test.js.map +0 -1
- package/dist/src/utils/ide-trust.d.ts +0 -10
- package/dist/src/utils/ide-trust.js +0 -14
- package/dist/src/utils/ide-trust.js.map +0 -1
- /package/dist/src/{utils/flashFallback.integration.test.d.ts → code_assist/oauth-credential-storage.test.d.ts} +0 -0
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import
|
|
7
|
-
import type { ContentGenerator } from './contentGenerator.js';
|
|
6
|
+
import { GenerateContentResponse, type Content, type GenerateContentConfig, type SendMessageParameters, type Part, type Tool } from '@google/genai';
|
|
8
7
|
import type { Config } from '../config/config.js';
|
|
9
8
|
import type { StructuredError } from './turn.js';
|
|
10
|
-
import type { CompletedToolCall } from './coreToolScheduler.js';
|
|
11
9
|
import { ChatRecordingService } from '../services/chatRecordingService.js';
|
|
12
10
|
export declare enum StreamEventType {
|
|
13
11
|
/** A regular content chunk from the API. */
|
|
@@ -22,6 +20,7 @@ export type StreamEvent = {
|
|
|
22
20
|
} | {
|
|
23
21
|
type: StreamEventType.RETRY;
|
|
24
22
|
};
|
|
23
|
+
export declare function isValidNonThoughtTextPart(part: Part): boolean;
|
|
25
24
|
/**
|
|
26
25
|
* Custom error to signal that a stream completed without valid content,
|
|
27
26
|
* which should trigger a retry.
|
|
@@ -38,39 +37,12 @@ export declare class EmptyStreamError extends Error {
|
|
|
38
37
|
*/
|
|
39
38
|
export declare class GeminiChat {
|
|
40
39
|
private readonly config;
|
|
41
|
-
private readonly contentGenerator;
|
|
42
40
|
private readonly generationConfig;
|
|
43
41
|
private history;
|
|
44
42
|
private sendPromise;
|
|
45
43
|
private readonly chatRecordingService;
|
|
46
|
-
constructor(config: Config,
|
|
47
|
-
/**
|
|
48
|
-
* Handles falling back to Flash model when persistent 429 errors occur for OAuth users.
|
|
49
|
-
* Uses a fallback handler if provided by the config; otherwise, returns null.
|
|
50
|
-
*/
|
|
51
|
-
private handleFlashFallback;
|
|
44
|
+
constructor(config: Config, generationConfig?: GenerateContentConfig, history?: Content[]);
|
|
52
45
|
setSystemInstruction(sysInstr: string): void;
|
|
53
|
-
/**
|
|
54
|
-
* Sends a message to the model and returns the response.
|
|
55
|
-
*
|
|
56
|
-
* @remarks
|
|
57
|
-
* This method will wait for the previous message to be processed before
|
|
58
|
-
* sending the next message.
|
|
59
|
-
*
|
|
60
|
-
* @see {@link Chat#sendMessageStream} for streaming method.
|
|
61
|
-
* @param params - parameters for sending messages within a chat session.
|
|
62
|
-
* @returns The model's response.
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* const chat = ai.chats.create({model: 'gemini-2.0-flash'});
|
|
67
|
-
* const response = await chat.sendMessage({
|
|
68
|
-
* message: 'Why is the sky blue?'
|
|
69
|
-
* });
|
|
70
|
-
* console.log(response.text);
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
sendMessage(params: SendMessageParameters, prompt_id: string): Promise<GenerateContentResponse>;
|
|
74
46
|
/**
|
|
75
47
|
* Sends a message to the model and returns the response in chunks.
|
|
76
48
|
*
|
|
@@ -93,7 +65,7 @@ export declare class GeminiChat {
|
|
|
93
65
|
* }
|
|
94
66
|
* ```
|
|
95
67
|
*/
|
|
96
|
-
sendMessageStream(params: SendMessageParameters, prompt_id: string): Promise<AsyncGenerator<StreamEvent>>;
|
|
68
|
+
sendMessageStream(model: string, params: SendMessageParameters, prompt_id: string): Promise<AsyncGenerator<StreamEvent>>;
|
|
97
69
|
private makeApiCallAndProcessStream;
|
|
98
70
|
/**
|
|
99
71
|
* Returns the chat history.
|
|
@@ -128,23 +100,28 @@ export declare class GeminiChat {
|
|
|
128
100
|
*/
|
|
129
101
|
addHistory(content: Content): void;
|
|
130
102
|
setHistory(history: Content[]): void;
|
|
103
|
+
stripThoughtsFromHistory(): void;
|
|
131
104
|
setTools(tools: Tool[]): void;
|
|
132
105
|
maybeIncludeSchemaDepthContext(error: StructuredError): Promise<void>;
|
|
133
106
|
private processStreamResponse;
|
|
134
|
-
private recordHistory;
|
|
135
107
|
/**
|
|
136
108
|
* Gets the chat recording service instance.
|
|
137
109
|
*/
|
|
138
110
|
getChatRecordingService(): ChatRecordingService;
|
|
139
|
-
/**
|
|
140
|
-
* Records completed tool calls with full metadata.
|
|
141
|
-
* This is called by external components when tool calls complete, before sending responses to Gemini.
|
|
142
|
-
*/
|
|
143
|
-
recordCompletedToolCalls(toolCalls: CompletedToolCall[]): void;
|
|
144
111
|
/**
|
|
145
112
|
* Extracts and records thought from thought content.
|
|
146
113
|
*/
|
|
147
114
|
private recordThoughtFromContent;
|
|
115
|
+
/**
|
|
116
|
+
* Truncates the chunkStream right before the second function call to a
|
|
117
|
+
* function that mutates state. This may involve trimming parts from a chunk
|
|
118
|
+
* as well as omtting some chunks altogether.
|
|
119
|
+
*
|
|
120
|
+
* We do this because it improves tool call quality if the model gets
|
|
121
|
+
* feedback from one mutating function call before it makes the next one.
|
|
122
|
+
*/
|
|
123
|
+
private stopBeforeSecondMutator;
|
|
124
|
+
private isMutatorFunctionCall;
|
|
148
125
|
}
|
|
149
126
|
/** Visible for Testing */
|
|
150
127
|
export declare function isSchemaDepthError(errorMessage: string): boolean;
|
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
// DISCLAIMER: This is a copied version of https://github.com/googleapis/js-genai/blob/main/src/chats.ts with the intention of working around a key bug
|
|
7
|
+
// where function responses are not treated as "valid" responses: https://b.corp.google.com/issues/420354090
|
|
8
|
+
import { GenerateContentResponse, FinishReason, } from '@google/genai';
|
|
6
9
|
import { toParts } from '../code_assist/converter.js';
|
|
7
10
|
import { createUserContent } from '@google/genai';
|
|
8
11
|
import { retryWithBackoff } from '../utils/retry.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { hasCycleInSchema } from '../tools/tools.js';
|
|
12
|
+
import { DEFAULT_GEMINI_FLASH_MODEL, getEffectiveModel, } from '../config/models.js';
|
|
13
|
+
import { hasCycleInSchema, MUTATOR_KINDS } from '../tools/tools.js';
|
|
12
14
|
import { logContentRetry, logContentRetryFailure, logInvalidChunk, } from '../telemetry/loggers.js';
|
|
13
15
|
import { ChatRecordingService } from '../services/chatRecordingService.js';
|
|
14
16
|
import { ContentRetryEvent, ContentRetryFailureEvent, InvalidChunkEvent, } from '../telemetry/types.js';
|
|
17
|
+
import { handleFallback } from '../fallback/handler.js';
|
|
15
18
|
import { isFunctionResponse } from '../utils/messageInspectors.js';
|
|
16
19
|
import { partListUnionToString } from './geminiRequest.js';
|
|
17
20
|
export var StreamEventType;
|
|
@@ -39,6 +42,16 @@ function isValidResponse(response) {
|
|
|
39
42
|
}
|
|
40
43
|
return isValidContent(content);
|
|
41
44
|
}
|
|
45
|
+
export function isValidNonThoughtTextPart(part) {
|
|
46
|
+
return (typeof part.text === 'string' &&
|
|
47
|
+
!part.thought &&
|
|
48
|
+
// Technically, the model should never generate parts that have text and
|
|
49
|
+
// any of these but we don't trust them so check anyways.
|
|
50
|
+
!part.functionCall &&
|
|
51
|
+
!part.functionResponse &&
|
|
52
|
+
!part.inlineData &&
|
|
53
|
+
!part.fileData);
|
|
54
|
+
}
|
|
42
55
|
function isValidContent(content) {
|
|
43
56
|
if (content.parts === undefined || content.parts.length === 0) {
|
|
44
57
|
return false;
|
|
@@ -122,155 +135,23 @@ export class EmptyStreamError extends Error {
|
|
|
122
135
|
*/
|
|
123
136
|
export class GeminiChat {
|
|
124
137
|
config;
|
|
125
|
-
contentGenerator;
|
|
126
138
|
generationConfig;
|
|
127
139
|
history;
|
|
128
140
|
// A promise to represent the current state of the message being sent to the
|
|
129
141
|
// model.
|
|
130
142
|
sendPromise = Promise.resolve();
|
|
131
143
|
chatRecordingService;
|
|
132
|
-
constructor(config,
|
|
144
|
+
constructor(config, generationConfig = {}, history = []) {
|
|
133
145
|
this.config = config;
|
|
134
|
-
this.contentGenerator = contentGenerator;
|
|
135
146
|
this.generationConfig = generationConfig;
|
|
136
147
|
this.history = history;
|
|
137
148
|
validateHistory(history);
|
|
138
149
|
this.chatRecordingService = new ChatRecordingService(config);
|
|
139
150
|
this.chatRecordingService.initialize();
|
|
140
151
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Handles falling back to Flash model when persistent 429 errors occur for OAuth users.
|
|
143
|
-
* Uses a fallback handler if provided by the config; otherwise, returns null.
|
|
144
|
-
*/
|
|
145
|
-
async handleFlashFallback(authType, error) {
|
|
146
|
-
// Only handle fallback for OAuth users
|
|
147
|
-
if (authType !== AuthType.LOGIN_WITH_GOOGLE) {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
const currentModel = this.config.getModel();
|
|
151
|
-
const fallbackModel = DEFAULT_GEMINI_FLASH_MODEL;
|
|
152
|
-
// Don't fallback if already using Flash model
|
|
153
|
-
if (currentModel === fallbackModel) {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
// Check if config has a fallback handler (set by CLI package)
|
|
157
|
-
const fallbackHandler = this.config.flashFallbackHandler;
|
|
158
|
-
if (typeof fallbackHandler === 'function') {
|
|
159
|
-
try {
|
|
160
|
-
const accepted = await fallbackHandler(currentModel, fallbackModel, error);
|
|
161
|
-
if (accepted !== false && accepted !== null) {
|
|
162
|
-
this.config.setModel(fallbackModel);
|
|
163
|
-
this.config.setFallbackMode(true);
|
|
164
|
-
return fallbackModel;
|
|
165
|
-
}
|
|
166
|
-
// Check if the model was switched manually in the handler
|
|
167
|
-
if (this.config.getModel() === fallbackModel) {
|
|
168
|
-
return null; // Model was switched but don't continue with current prompt
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
catch (error) {
|
|
172
|
-
console.warn('Flash fallback handler failed:', error);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
152
|
setSystemInstruction(sysInstr) {
|
|
178
153
|
this.generationConfig.systemInstruction = sysInstr;
|
|
179
154
|
}
|
|
180
|
-
/**
|
|
181
|
-
* Sends a message to the model and returns the response.
|
|
182
|
-
*
|
|
183
|
-
* @remarks
|
|
184
|
-
* This method will wait for the previous message to be processed before
|
|
185
|
-
* sending the next message.
|
|
186
|
-
*
|
|
187
|
-
* @see {@link Chat#sendMessageStream} for streaming method.
|
|
188
|
-
* @param params - parameters for sending messages within a chat session.
|
|
189
|
-
* @returns The model's response.
|
|
190
|
-
*
|
|
191
|
-
* @example
|
|
192
|
-
* ```ts
|
|
193
|
-
* const chat = ai.chats.create({model: 'gemini-2.0-flash'});
|
|
194
|
-
* const response = await chat.sendMessage({
|
|
195
|
-
* message: 'Why is the sky blue?'
|
|
196
|
-
* });
|
|
197
|
-
* console.log(response.text);
|
|
198
|
-
* ```
|
|
199
|
-
*/
|
|
200
|
-
async sendMessage(params, prompt_id) {
|
|
201
|
-
await this.sendPromise;
|
|
202
|
-
const userContent = createUserContent(params.message);
|
|
203
|
-
// Record user input - capture complete message with all parts (text, files, images, etc.)
|
|
204
|
-
// but skip recording function responses (tool call results) as they should be stored in tool call records
|
|
205
|
-
if (!isFunctionResponse(userContent)) {
|
|
206
|
-
const userMessage = Array.isArray(params.message)
|
|
207
|
-
? params.message
|
|
208
|
-
: [params.message];
|
|
209
|
-
this.chatRecordingService.recordMessage({
|
|
210
|
-
type: 'user',
|
|
211
|
-
content: userMessage,
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
const requestContents = this.getHistory(true).concat(userContent);
|
|
215
|
-
let response;
|
|
216
|
-
try {
|
|
217
|
-
const apiCall = () => {
|
|
218
|
-
const modelToUse = this.config.getModel() || DEFAULT_GEMINI_FLASH_MODEL;
|
|
219
|
-
// Prevent Flash model calls immediately after quota error
|
|
220
|
-
if (this.config.getQuotaErrorOccurred() &&
|
|
221
|
-
modelToUse === DEFAULT_GEMINI_FLASH_MODEL) {
|
|
222
|
-
throw new Error('Please submit a new query to continue with the Flash model.');
|
|
223
|
-
}
|
|
224
|
-
return this.contentGenerator.generateContent({
|
|
225
|
-
model: modelToUse,
|
|
226
|
-
contents: requestContents,
|
|
227
|
-
config: { ...this.generationConfig, ...params.config },
|
|
228
|
-
}, prompt_id);
|
|
229
|
-
};
|
|
230
|
-
response = await retryWithBackoff(apiCall, {
|
|
231
|
-
shouldRetry: (error) => {
|
|
232
|
-
// Check for known error messages and codes.
|
|
233
|
-
if (error instanceof Error && error.message) {
|
|
234
|
-
if (isSchemaDepthError(error.message))
|
|
235
|
-
return false;
|
|
236
|
-
if (error.message.includes('429'))
|
|
237
|
-
return true;
|
|
238
|
-
if (error.message.match(/5\d{2}/))
|
|
239
|
-
return true;
|
|
240
|
-
}
|
|
241
|
-
return false; // Don't retry other errors by default
|
|
242
|
-
},
|
|
243
|
-
onPersistent429: async (authType, error) => await this.handleFlashFallback(authType, error),
|
|
244
|
-
authType: this.config.getContentGeneratorConfig()?.authType,
|
|
245
|
-
});
|
|
246
|
-
this.sendPromise = (async () => {
|
|
247
|
-
const outputContent = response.candidates?.[0]?.content;
|
|
248
|
-
const modelOutput = outputContent ? [outputContent] : [];
|
|
249
|
-
// Because the AFC input contains the entire curated chat history in
|
|
250
|
-
// addition to the new user input, we need to truncate the AFC history
|
|
251
|
-
// to deduplicate the existing chat history.
|
|
252
|
-
const fullAutomaticFunctionCallingHistory = response.automaticFunctionCallingHistory;
|
|
253
|
-
const index = this.getHistory(true).length;
|
|
254
|
-
let automaticFunctionCallingHistory = [];
|
|
255
|
-
if (fullAutomaticFunctionCallingHistory != null) {
|
|
256
|
-
automaticFunctionCallingHistory =
|
|
257
|
-
fullAutomaticFunctionCallingHistory.slice(index) ?? [];
|
|
258
|
-
}
|
|
259
|
-
this.recordHistory(userContent, modelOutput, automaticFunctionCallingHistory);
|
|
260
|
-
})();
|
|
261
|
-
await this.sendPromise.catch((error) => {
|
|
262
|
-
// Resets sendPromise to avoid subsequent calls failing
|
|
263
|
-
this.sendPromise = Promise.resolve();
|
|
264
|
-
// Re-throw the error so the caller knows something went wrong.
|
|
265
|
-
throw error;
|
|
266
|
-
});
|
|
267
|
-
return response;
|
|
268
|
-
}
|
|
269
|
-
catch (error) {
|
|
270
|
-
this.sendPromise = Promise.resolve();
|
|
271
|
-
throw error;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
155
|
/**
|
|
275
156
|
* Sends a message to the model and returns the response in chunks.
|
|
276
157
|
*
|
|
@@ -293,7 +174,7 @@ export class GeminiChat {
|
|
|
293
174
|
* }
|
|
294
175
|
* ```
|
|
295
176
|
*/
|
|
296
|
-
async sendMessageStream(params, prompt_id) {
|
|
177
|
+
async sendMessageStream(model, params, prompt_id) {
|
|
297
178
|
await this.sendPromise;
|
|
298
179
|
let streamDoneResolver;
|
|
299
180
|
const streamDonePromise = new Promise((resolve) => {
|
|
@@ -309,6 +190,7 @@ export class GeminiChat {
|
|
|
309
190
|
: [params.message];
|
|
310
191
|
const userMessageContent = partListUnionToString(toParts(userMessage));
|
|
311
192
|
this.chatRecordingService.recordMessage({
|
|
193
|
+
model,
|
|
312
194
|
type: 'user',
|
|
313
195
|
content: userMessageContent,
|
|
314
196
|
});
|
|
@@ -326,7 +208,7 @@ export class GeminiChat {
|
|
|
326
208
|
if (attempt > 0) {
|
|
327
209
|
yield { type: StreamEventType.RETRY };
|
|
328
210
|
}
|
|
329
|
-
const stream = await self.makeApiCallAndProcessStream(requestContents, params, prompt_id
|
|
211
|
+
const stream = await self.makeApiCallAndProcessStream(model, requestContents, params, prompt_id);
|
|
330
212
|
for await (const chunk of stream) {
|
|
331
213
|
yield { type: StreamEventType.CHUNK, value: chunk };
|
|
332
214
|
}
|
|
@@ -364,19 +246,20 @@ export class GeminiChat {
|
|
|
364
246
|
}
|
|
365
247
|
})();
|
|
366
248
|
}
|
|
367
|
-
async makeApiCallAndProcessStream(requestContents, params, prompt_id
|
|
249
|
+
async makeApiCallAndProcessStream(model, requestContents, params, prompt_id) {
|
|
368
250
|
const apiCall = () => {
|
|
369
|
-
const modelToUse = this.config.
|
|
251
|
+
const modelToUse = getEffectiveModel(this.config.isInFallbackMode(), model);
|
|
370
252
|
if (this.config.getQuotaErrorOccurred() &&
|
|
371
253
|
modelToUse === DEFAULT_GEMINI_FLASH_MODEL) {
|
|
372
254
|
throw new Error('Please submit a new query to continue with the Flash model.');
|
|
373
255
|
}
|
|
374
|
-
return this.
|
|
256
|
+
return this.config.getContentGenerator().generateContentStream({
|
|
375
257
|
model: modelToUse,
|
|
376
258
|
contents: requestContents,
|
|
377
259
|
config: { ...this.generationConfig, ...params.config },
|
|
378
260
|
}, prompt_id);
|
|
379
261
|
};
|
|
262
|
+
const onPersistent429Callback = async (authType, error) => await handleFallback(this.config, model, authType, error);
|
|
380
263
|
const streamResponse = await retryWithBackoff(apiCall, {
|
|
381
264
|
shouldRetry: (error) => {
|
|
382
265
|
if (error instanceof Error && error.message) {
|
|
@@ -389,10 +272,10 @@ export class GeminiChat {
|
|
|
389
272
|
}
|
|
390
273
|
return false;
|
|
391
274
|
},
|
|
392
|
-
onPersistent429:
|
|
275
|
+
onPersistent429: onPersistent429Callback,
|
|
393
276
|
authType: this.config.getContentGeneratorConfig()?.authType,
|
|
394
277
|
});
|
|
395
|
-
return this.processStreamResponse(
|
|
278
|
+
return this.processStreamResponse(model, streamResponse);
|
|
396
279
|
}
|
|
397
280
|
/**
|
|
398
281
|
* Returns the chat history.
|
|
@@ -440,6 +323,22 @@ export class GeminiChat {
|
|
|
440
323
|
setHistory(history) {
|
|
441
324
|
this.history = history;
|
|
442
325
|
}
|
|
326
|
+
stripThoughtsFromHistory() {
|
|
327
|
+
this.history = this.history.map((content) => {
|
|
328
|
+
const newContent = { ...content };
|
|
329
|
+
if (newContent.parts) {
|
|
330
|
+
newContent.parts = newContent.parts.map((part) => {
|
|
331
|
+
if (part && typeof part === 'object' && 'thoughtSignature' in part) {
|
|
332
|
+
const newPart = { ...part };
|
|
333
|
+
delete newPart.thoughtSignature;
|
|
334
|
+
return newPart;
|
|
335
|
+
}
|
|
336
|
+
return part;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return newContent;
|
|
340
|
+
});
|
|
341
|
+
}
|
|
443
342
|
setTools(tools) {
|
|
444
343
|
this.generationConfig.tools = tools;
|
|
445
344
|
}
|
|
@@ -465,14 +364,14 @@ export class GeminiChat {
|
|
|
465
364
|
}
|
|
466
365
|
}
|
|
467
366
|
}
|
|
468
|
-
async *processStreamResponse(
|
|
367
|
+
async *processStreamResponse(model, streamResponse) {
|
|
469
368
|
const modelResponseParts = [];
|
|
470
369
|
let hasReceivedAnyChunk = false;
|
|
471
370
|
let hasReceivedValidChunk = false;
|
|
472
371
|
let hasToolCall = false;
|
|
473
372
|
let lastChunk = null;
|
|
474
373
|
let lastChunkIsInvalid = false;
|
|
475
|
-
for await (const chunk of streamResponse) {
|
|
374
|
+
for await (const chunk of this.stopBeforeSecondMutator(streamResponse)) {
|
|
476
375
|
hasReceivedAnyChunk = true;
|
|
477
376
|
lastChunk = chunk;
|
|
478
377
|
if (isValidResponse(chunk)) {
|
|
@@ -487,11 +386,7 @@ export class GeminiChat {
|
|
|
487
386
|
if (content.parts.some((part) => part.functionCall)) {
|
|
488
387
|
hasToolCall = true;
|
|
489
388
|
}
|
|
490
|
-
|
|
491
|
-
modelResponseParts.push(...content.parts);
|
|
492
|
-
if (content.parts.some((part) => part.functionCall)) {
|
|
493
|
-
hasToolCall = true;
|
|
494
|
-
}
|
|
389
|
+
modelResponseParts.push(...content.parts.filter((part) => !part.thought));
|
|
495
390
|
}
|
|
496
391
|
}
|
|
497
392
|
else {
|
|
@@ -522,106 +417,31 @@ export class GeminiChat {
|
|
|
522
417
|
// Record model response text from the collected parts
|
|
523
418
|
if (modelResponseParts.length > 0) {
|
|
524
419
|
const responseText = modelResponseParts
|
|
525
|
-
.filter((part) => part.text
|
|
420
|
+
.filter((part) => part.text)
|
|
526
421
|
.map((part) => part.text)
|
|
527
422
|
.join('');
|
|
528
423
|
if (responseText.trim()) {
|
|
529
424
|
this.chatRecordingService.recordMessage({
|
|
425
|
+
model,
|
|
530
426
|
type: 'gemini',
|
|
531
427
|
content: responseText,
|
|
532
428
|
});
|
|
533
429
|
}
|
|
534
430
|
}
|
|
535
|
-
//
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
// Part 1: Handle the user's turn.
|
|
544
|
-
if (automaticFunctionCallingHistory &&
|
|
545
|
-
automaticFunctionCallingHistory.length > 0) {
|
|
546
|
-
this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory));
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
if (this.history.length === 0 ||
|
|
550
|
-
this.history[this.history.length - 1] !== userInput) {
|
|
551
|
-
const lastTurn = this.history[this.history.length - 1];
|
|
552
|
-
// The only time we don't push is if it's the *exact same* object,
|
|
553
|
-
// which happens in streaming where we add it preemptively.
|
|
554
|
-
if (lastTurn !== userInput) {
|
|
555
|
-
if (lastTurn?.role === 'user') {
|
|
556
|
-
// This is an invalid sequence.
|
|
557
|
-
throw new Error('Cannot add a user turn after another user turn.');
|
|
558
|
-
}
|
|
559
|
-
this.history.push(userInput);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
// Part 2: Process the model output into a final, consolidated list of turns.
|
|
564
|
-
const finalModelTurns = [];
|
|
565
|
-
for (const content of modelOutput) {
|
|
566
|
-
// A. Preserve malformed content that has no 'parts' array.
|
|
567
|
-
if (!content.parts) {
|
|
568
|
-
finalModelTurns.push(content);
|
|
569
|
-
continue;
|
|
570
|
-
}
|
|
571
|
-
// B. Filter out 'thought' parts.
|
|
572
|
-
const visibleParts = content.parts.filter((part) => !part.thought);
|
|
573
|
-
const newTurn = { ...content, parts: visibleParts };
|
|
574
|
-
const lastTurnInFinal = finalModelTurns[finalModelTurns.length - 1];
|
|
575
|
-
// Consolidate this new turn with the PREVIOUS turn if they are adjacent model turns.
|
|
576
|
-
if (lastTurnInFinal &&
|
|
577
|
-
lastTurnInFinal.role === 'model' &&
|
|
578
|
-
newTurn.role === 'model' &&
|
|
579
|
-
lastTurnInFinal.parts && // SAFETY CHECK: Ensure the destination has a parts array.
|
|
580
|
-
newTurn.parts) {
|
|
581
|
-
lastTurnInFinal.parts.push(...newTurn.parts);
|
|
431
|
+
// String thoughts and consolidate text parts.
|
|
432
|
+
const consolidatedParts = [];
|
|
433
|
+
for (const part of modelResponseParts) {
|
|
434
|
+
const lastPart = consolidatedParts[consolidatedParts.length - 1];
|
|
435
|
+
if (lastPart?.text &&
|
|
436
|
+
isValidNonThoughtTextPart(lastPart) &&
|
|
437
|
+
isValidNonThoughtTextPart(part)) {
|
|
438
|
+
lastPart.text += part.text;
|
|
582
439
|
}
|
|
583
440
|
else {
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
// Part 3: Add the processed model turns to the history, with one final consolidation pass.
|
|
588
|
-
if (finalModelTurns.length > 0) {
|
|
589
|
-
// Re-consolidate parts within any turns that were merged in the previous step.
|
|
590
|
-
for (const turn of finalModelTurns) {
|
|
591
|
-
if (turn.parts && turn.parts.length > 1) {
|
|
592
|
-
const consolidatedParts = [];
|
|
593
|
-
for (const part of turn.parts) {
|
|
594
|
-
const lastPart = consolidatedParts[consolidatedParts.length - 1];
|
|
595
|
-
if (lastPart &&
|
|
596
|
-
// Ensure lastPart is a pure text part
|
|
597
|
-
typeof lastPart.text === 'string' &&
|
|
598
|
-
!lastPart.functionCall &&
|
|
599
|
-
!lastPart.functionResponse &&
|
|
600
|
-
!lastPart.inlineData &&
|
|
601
|
-
!lastPart.fileData &&
|
|
602
|
-
!lastPart.thought &&
|
|
603
|
-
// Ensure current part is a pure text part
|
|
604
|
-
typeof part.text === 'string' &&
|
|
605
|
-
!part.functionCall &&
|
|
606
|
-
!part.functionResponse &&
|
|
607
|
-
!part.inlineData &&
|
|
608
|
-
!part.fileData &&
|
|
609
|
-
!part.thought) {
|
|
610
|
-
lastPart.text += part.text;
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
consolidatedParts.push({ ...part });
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
turn.parts = consolidatedParts;
|
|
617
|
-
}
|
|
441
|
+
consolidatedParts.push(part);
|
|
618
442
|
}
|
|
619
|
-
this.history.push(...finalModelTurns);
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
// If, after all processing, there's NO model output, add the placeholder.
|
|
623
|
-
this.history.push({ role: 'model', parts: [] });
|
|
624
443
|
}
|
|
444
|
+
this.history.push({ role: 'model', parts: consolidatedParts });
|
|
625
445
|
}
|
|
626
446
|
/**
|
|
627
447
|
* Gets the chat recording service instance.
|
|
@@ -629,26 +449,6 @@ export class GeminiChat {
|
|
|
629
449
|
getChatRecordingService() {
|
|
630
450
|
return this.chatRecordingService;
|
|
631
451
|
}
|
|
632
|
-
/**
|
|
633
|
-
* Records completed tool calls with full metadata.
|
|
634
|
-
* This is called by external components when tool calls complete, before sending responses to Gemini.
|
|
635
|
-
*/
|
|
636
|
-
recordCompletedToolCalls(toolCalls) {
|
|
637
|
-
const toolCallRecords = toolCalls.map((call) => {
|
|
638
|
-
const resultDisplayRaw = call.response?.resultDisplay;
|
|
639
|
-
const resultDisplay = typeof resultDisplayRaw === 'string' ? resultDisplayRaw : undefined;
|
|
640
|
-
return {
|
|
641
|
-
id: call.request.callId,
|
|
642
|
-
name: call.request.name,
|
|
643
|
-
args: call.request.args,
|
|
644
|
-
result: call.response?.responseParts || null,
|
|
645
|
-
status: call.status,
|
|
646
|
-
timestamp: new Date().toISOString(),
|
|
647
|
-
resultDisplay,
|
|
648
|
-
};
|
|
649
|
-
});
|
|
650
|
-
this.chatRecordingService.recordToolCalls(toolCallRecords);
|
|
651
|
-
}
|
|
652
452
|
/**
|
|
653
453
|
* Extracts and records thought from thought content.
|
|
654
454
|
*/
|
|
@@ -671,6 +471,57 @@ export class GeminiChat {
|
|
|
671
471
|
});
|
|
672
472
|
}
|
|
673
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* Truncates the chunkStream right before the second function call to a
|
|
476
|
+
* function that mutates state. This may involve trimming parts from a chunk
|
|
477
|
+
* as well as omtting some chunks altogether.
|
|
478
|
+
*
|
|
479
|
+
* We do this because it improves tool call quality if the model gets
|
|
480
|
+
* feedback from one mutating function call before it makes the next one.
|
|
481
|
+
*/
|
|
482
|
+
async *stopBeforeSecondMutator(chunkStream) {
|
|
483
|
+
let foundMutatorFunctionCall = false;
|
|
484
|
+
for await (const chunk of chunkStream) {
|
|
485
|
+
const candidate = chunk.candidates?.[0];
|
|
486
|
+
const content = candidate?.content;
|
|
487
|
+
if (!candidate || !content?.parts) {
|
|
488
|
+
yield chunk;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
const truncatedParts = [];
|
|
492
|
+
for (const part of content.parts) {
|
|
493
|
+
if (this.isMutatorFunctionCall(part)) {
|
|
494
|
+
if (foundMutatorFunctionCall) {
|
|
495
|
+
// This is the second mutator call.
|
|
496
|
+
// Truncate and return immedaitely.
|
|
497
|
+
const newChunk = new GenerateContentResponse();
|
|
498
|
+
newChunk.candidates = [
|
|
499
|
+
{
|
|
500
|
+
...candidate,
|
|
501
|
+
content: {
|
|
502
|
+
...content,
|
|
503
|
+
parts: truncatedParts,
|
|
504
|
+
},
|
|
505
|
+
finishReason: FinishReason.STOP,
|
|
506
|
+
},
|
|
507
|
+
];
|
|
508
|
+
yield newChunk;
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
foundMutatorFunctionCall = true;
|
|
512
|
+
}
|
|
513
|
+
truncatedParts.push(part);
|
|
514
|
+
}
|
|
515
|
+
yield chunk;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
isMutatorFunctionCall(part) {
|
|
519
|
+
if (!part?.functionCall?.name) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
const tool = this.config.getToolRegistry().getTool(part.functionCall.name);
|
|
523
|
+
return !!tool && MUTATOR_KINDS.includes(tool.kind);
|
|
524
|
+
}
|
|
674
525
|
}
|
|
675
526
|
/** Visible for Testing */
|
|
676
527
|
export function isSchemaDepthError(errorMessage) {
|