@machina.ai/cell-cli-core 1.0.21-rc4 → 1.4.0-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/package.json +25 -11
- package/dist/src/code_assist/codeAssist.d.ts +6 -3
- package/dist/src/code_assist/codeAssist.js +12 -0
- package/dist/src/code_assist/codeAssist.js.map +1 -1
- package/dist/src/code_assist/converter.d.ts +3 -1
- package/dist/src/code_assist/converter.js +37 -5
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +83 -0
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -1
- package/dist/src/code_assist/oauth2.js +85 -49
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +317 -15
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +5 -5
- package/dist/src/code_assist/server.js +1 -1
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/setup.d.ts +1 -1
- package/dist/src/code_assist/setup.js +1 -1
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/config/config.d.ts +53 -15
- package/dist/src/config/config.js +127 -47
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +151 -6
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -0
- package/dist/src/config/models.js +2 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/storage.d.ts +32 -0
- package/dist/src/config/storage.js +90 -0
- package/dist/src/config/storage.js.map +1 -0
- package/dist/src/config/storage.test.js +43 -0
- package/dist/src/config/storage.test.js.map +1 -0
- package/dist/src/core/client.d.ts +21 -11
- package/dist/src/core/client.js +83 -26
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +398 -88
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +6 -6
- package/dist/src/core/contentGenerator.js +4 -3
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +14 -5
- package/dist/src/core/coreToolScheduler.js +120 -49
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +383 -72
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +48 -15
- package/dist/src/core/geminiChat.js +327 -154
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +1041 -257
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiRequest.js +1 -0
- package/dist/src/core/geminiRequest.js.map +1 -1
- package/dist/src/core/logger.d.ts +4 -2
- package/dist/src/core/logger.js +4 -3
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +19 -18
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.d.ts +3 -3
- package/dist/src/core/loggingContentGenerator.js +11 -9
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.d.ts +3 -5
- package/dist/src/core/nonInteractiveToolExecutor.js +15 -123
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +116 -90
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +8 -7
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +21 -21
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/subagent.d.ts +24 -18
- package/dist/src/core/subagent.js +126 -89
- package/dist/src/core/subagent.js.map +1 -1
- package/dist/src/core/subagent.test.js +51 -35
- package/dist/src/core/subagent.test.js.map +1 -1
- package/dist/src/core/turn.d.ts +33 -8
- package/dist/src/core/turn.js +59 -14
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +349 -90
- package/dist/src/core/turn.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/generated/git-commit.js.map +1 -1
- package/dist/src/ide/constants.d.ts +1 -1
- package/dist/src/ide/constants.js +1 -1
- package/dist/src/ide/constants.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +8 -3
- package/dist/src/ide/detect-ide.js +29 -11
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +96 -52
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +18 -9
- package/dist/src/ide/ide-client.js +151 -33
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +147 -25
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.d.ts +1 -1
- package/dist/src/ide/ide-installer.js +31 -22
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +82 -22
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +12 -0
- package/dist/src/ide/ideContext.js +1 -0
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/process-utils.d.ts +13 -6
- package/dist/src/ide/process-utils.js +142 -35
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/process-utils.test.js +158 -0
- package/dist/src/ide/process-utils.test.js.map +1 -0
- package/dist/src/index.d.ts +12 -2
- package/dist/src/index.js +11 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.d.ts +3 -3
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +13 -13
- package/dist/src/mcp/oauth-provider.js +32 -31
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +75 -36
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +9 -31
- package/dist/src/mcp/oauth-token-storage.js +10 -13
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.test.js +30 -27
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.d.ts +9 -1
- package/dist/src/mcp/oauth-utils.js +41 -27
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +41 -1
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/mcp/token-storage/base-token-storage.d.ts +19 -0
- package/dist/src/mcp/token-storage/base-token-storage.js +36 -0
- package/dist/src/mcp/token-storage/base-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/base-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/base-token-storage.test.js +160 -0
- package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/file-token-storage.d.ts +24 -0
- package/dist/src/mcp/token-storage/file-token-storage.js +144 -0
- package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/file-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/file-token-storage.test.js +235 -0
- package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.d.ts +23 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.js +78 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js +193 -0
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +31 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.js +190 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js +254 -0
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js.map +1 -0
- package/dist/src/mcp/token-storage/types.d.ts +38 -0
- package/dist/src/mcp/token-storage/types.js +11 -0
- package/dist/src/mcp/token-storage/types.js.map +1 -0
- package/dist/src/prompts/mcp-prompts.d.ts +2 -2
- package/dist/src/prompts/prompt-registry.d.ts +1 -1
- package/dist/src/services/chatRecordingService.d.ts +6 -13
- package/dist/src/services/chatRecordingService.js +31 -19
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/chatRecordingService.test.js +64 -25
- package/dist/src/services/chatRecordingService.test.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.js +1 -1
- package/dist/src/services/fileDiscoveryService.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.test.js +3 -3
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
- package/dist/src/services/fileSystemService.js +1 -1
- package/dist/src/services/fileSystemService.js.map +1 -1
- package/dist/src/services/fileSystemService.test.js +1 -1
- package/dist/src/services/fileSystemService.test.js.map +1 -1
- package/dist/src/services/gitService.d.ts +3 -1
- package/dist/src/services/gitService.js +21 -12
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +22 -19
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +3 -2
- package/dist/src/services/loopDetectionService.js +28 -4
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +23 -1
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.d.ts +8 -10
- package/dist/src/services/shellExecutionService.js +292 -135
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +277 -42
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +18 -4
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +171 -11
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +103 -11
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +31 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +75 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +9 -0
- package/dist/src/telemetry/constants.js +9 -0
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/file-exporters.d.ts +5 -4
- package/dist/src/telemetry/file-exporters.js +1 -1
- package/dist/src/telemetry/file-exporters.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +5 -2
- package/dist/src/telemetry/index.js +3 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +8 -2
- package/dist/src/telemetry/loggers.js +130 -2
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +105 -9
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +15 -4
- package/dist/src/telemetry/metrics.js +46 -8
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +5 -25
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.d.ts +1 -1
- package/dist/src/telemetry/sdk.js +3 -3
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/telemetry-utils.d.ts +6 -0
- package/dist/src/telemetry/telemetry-utils.js +14 -0
- package/dist/src/telemetry/telemetry-utils.js.map +1 -0
- package/dist/src/telemetry/telemetry-utils.test.d.ts +6 -0
- package/dist/src/telemetry/telemetry-utils.test.js +40 -0
- package/dist/src/telemetry/telemetry-utils.test.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +61 -6
- package/dist/src/telemetry/types.js +105 -4
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +2 -2
- package/dist/src/telemetry/uiTelemetry.js +5 -5
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +20 -16
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/config.d.ts +2 -1
- package/dist/src/test-utils/config.js.map +1 -1
- package/dist/src/test-utils/index.d.ts +6 -0
- package/dist/src/test-utils/index.js +7 -0
- package/dist/src/test-utils/index.js.map +1 -0
- package/dist/src/test-utils/mock-tool.d.ts +41 -0
- package/dist/src/test-utils/mock-tool.js +51 -0
- package/dist/src/test-utils/mock-tool.js.map +1 -0
- package/dist/src/test-utils/mockWorkspaceContext.d.ts +1 -1
- package/dist/src/test-utils/tools.d.ts +3 -2
- package/dist/src/test-utils/tools.js.map +1 -1
- package/dist/src/tools/diffOptions.d.ts +1 -1
- package/dist/src/tools/diffOptions.js +21 -13
- package/dist/src/tools/diffOptions.js.map +1 -1
- package/dist/src/tools/diffOptions.test.js +58 -22
- package/dist/src/tools/diffOptions.test.js.map +1 -1
- package/dist/src/tools/edit.d.ts +6 -5
- package/dist/src/tools/edit.js +47 -36
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +77 -12
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +3 -2
- package/dist/src/tools/glob.js +17 -6
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +29 -4
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +3 -2
- package/dist/src/tools/grep.js +35 -15
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +26 -3
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +3 -2
- package/dist/src/tools/ls.js +12 -7
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +7 -2
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +8 -6
- package/dist/src/tools/mcp-client-manager.js +30 -5
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +20 -1
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +18 -11
- package/dist/src/tools/mcp-client.js +67 -57
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +29 -4
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +6 -4
- package/dist/src/tools/mcp-tool.js +21 -11
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +49 -12
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +4 -3
- package/dist/src/tools/memoryTool.js +15 -38
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +24 -12
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.d.ts +2 -2
- package/dist/src/tools/modifiable-tool.js +3 -3
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +4 -4
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +3 -2
- package/dist/src/tools/read-file.js +12 -34
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +9 -6
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +3 -2
- package/dist/src/tools/read-many-files.js +35 -58
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +64 -11
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +47 -0
- package/dist/src/tools/ripGrep.js +368 -0
- package/dist/src/tools/ripGrep.js.map +1 -0
- package/dist/src/tools/ripGrep.test.d.ts +6 -0
- package/dist/src/tools/ripGrep.test.js +874 -0
- package/dist/src/tools/ripGrep.test.js.map +1 -0
- package/dist/src/tools/shell.d.ts +3 -2
- package/dist/src/tools/shell.js +30 -25
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +34 -25
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +73 -0
- package/dist/src/tools/smart-edit.js +607 -0
- package/dist/src/tools/smart-edit.js.map +1 -0
- package/dist/src/tools/smart-edit.test.d.ts +6 -0
- package/dist/src/tools/smart-edit.test.js +405 -0
- package/dist/src/tools/smart-edit.test.js.map +1 -0
- package/dist/src/tools/tool-error.d.ts +17 -1
- package/dist/src/tools/tool-error.js +26 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +10 -4
- package/dist/src/tools/tool-registry.js +19 -7
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +86 -3
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +15 -9
- package/dist/src/tools/tools.js +12 -0
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.js +1 -2
- package/dist/src/tools/tools.test.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +3 -2
- package/dist/src/tools/web-fetch.js +14 -10
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +55 -16
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.d.ts +4 -3
- package/dist/src/tools/web-search.js +31 -8
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +69 -1
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +4 -3
- package/dist/src/tools/write-file.js +14 -14
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +14 -14
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.d.ts +2 -2
- package/dist/src/utils/bfsFileSearch.js +2 -2
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +3 -3
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/editCorrector.d.ts +2 -2
- package/dist/src/utils/editCorrector.js +1 -1
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +3 -3
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.js +2 -2
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +2 -2
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +2 -2
- package/dist/src/utils/environmentContext.js +1 -1
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +1 -1
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/errorReporting.d.ts +1 -1
- package/dist/src/utils/errors.d.ts +19 -0
- package/dist/src/utils/errors.js +32 -0
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/fetch.js +1 -1
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +23 -12
- package/dist/src/utils/fileUtils.js +160 -79
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +314 -21
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawler.d.ts +1 -1
- package/dist/src/utils/filesearch/crawler.test.js +2 -2
- package/dist/src/utils/filesearch/crawler.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.d.ts +1 -0
- package/dist/src/utils/filesearch/fileSearch.js +14 -9
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.test.js +90 -0
- package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
- package/dist/src/utils/generateContentResponseUtilities.d.ts +1 -2
- package/dist/src/utils/generateContentResponseUtilities.js +1 -13
- package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
- package/dist/src/utils/generateContentResponseUtilities.test.js +2 -40
- package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
- package/dist/src/utils/getFolderStructure.d.ts +2 -2
- package/dist/src/utils/getFolderStructure.js +2 -2
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/getFolderStructure.test.js +13 -13
- package/dist/src/utils/getFolderStructure.test.js.map +1 -1
- package/dist/src/utils/getPty.d.ts +19 -0
- package/dist/src/utils/getPty.js +23 -0
- package/dist/src/utils/getPty.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.d.ts +1 -0
- package/dist/src/utils/gitIgnoreParser.js +104 -13
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.test.js +69 -3
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/gitUtils.js +2 -2
- package/dist/src/utils/gitUtils.js.map +1 -1
- package/dist/src/utils/ide-trust.d.ts +10 -0
- package/dist/src/utils/ide-trust.js +14 -0
- package/dist/src/utils/ide-trust.js.map +1 -0
- package/dist/src/utils/ignorePatterns.d.ts +103 -0
- package/dist/src/utils/ignorePatterns.js +220 -0
- package/dist/src/utils/ignorePatterns.js.map +1 -0
- package/dist/src/utils/ignorePatterns.test.d.ts +6 -0
- package/dist/src/utils/ignorePatterns.test.js +250 -0
- package/dist/src/utils/ignorePatterns.test.js.map +1 -0
- package/dist/src/utils/installationManager.d.ts +16 -0
- package/dist/src/utils/installationManager.js +50 -0
- package/dist/src/utils/installationManager.js.map +1 -0
- package/dist/src/utils/installationManager.test.d.ts +6 -0
- package/dist/src/utils/installationManager.test.js +83 -0
- package/dist/src/utils/installationManager.test.js.map +1 -0
- package/dist/src/utils/language-detection.d.ts +6 -0
- package/dist/src/utils/language-detection.js +101 -0
- package/dist/src/utils/language-detection.js.map +1 -0
- package/dist/src/utils/llm-edit-fixer.d.ts +25 -0
- package/dist/src/utils/llm-edit-fixer.js +112 -0
- package/dist/src/utils/llm-edit-fixer.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.d.ts +7 -6
- package/dist/src/utils/memoryDiscovery.js +68 -33
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +76 -20
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +2 -2
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.test.js +2 -141
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
- package/dist/src/utils/messageInspectors.d.ts +1 -1
- package/dist/src/utils/nextSpeakerChecker.d.ts +2 -2
- package/dist/src/utils/nextSpeakerChecker.test.js +33 -0
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/partUtils.d.ts +22 -1
- package/dist/src/utils/partUtils.js +68 -0
- package/dist/src/utils/partUtils.js.map +1 -1
- package/dist/src/utils/partUtils.test.js +112 -1
- package/dist/src/utils/partUtils.test.js.map +1 -1
- package/dist/src/utils/pathReader.d.ts +17 -0
- package/dist/src/utils/pathReader.js +92 -0
- package/dist/src/utils/pathReader.js.map +1 -0
- package/dist/src/utils/pathReader.test.d.ts +6 -0
- package/dist/src/utils/pathReader.test.js +363 -0
- package/dist/src/utils/pathReader.test.js.map +1 -0
- package/dist/src/utils/paths.d.ts +1 -18
- package/dist/src/utils/paths.js +3 -29
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/quotaErrorDetection.d.ts +1 -1
- package/dist/src/utils/retry.test.js +4 -1
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/schemaValidator.js +4 -0
- package/dist/src/utils/schemaValidator.js.map +1 -1
- package/dist/src/utils/session.js +1 -1
- package/dist/src/utils/session.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +1 -1
- package/dist/src/utils/shell-utils.js +23 -29
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +7 -0
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/summarizer.d.ts +2 -2
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/systemEncoding.js +2 -2
- package/dist/src/utils/systemEncoding.js.map +1 -1
- package/dist/src/utils/systemEncoding.test.js +2 -2
- package/dist/src/utils/systemEncoding.test.js.map +1 -1
- package/dist/src/utils/tool-utils.d.ts +19 -0
- package/dist/src/utils/tool-utils.js +58 -0
- package/dist/src/utils/tool-utils.js.map +1 -0
- package/dist/src/utils/tool-utils.test.d.ts +6 -0
- package/dist/src/utils/tool-utils.test.js +61 -0
- package/dist/src/utils/tool-utils.test.js.map +1 -0
- package/dist/src/utils/userAccountManager.d.ts +20 -0
- package/dist/src/utils/userAccountManager.js +114 -0
- package/dist/src/utils/userAccountManager.js.map +1 -0
- package/dist/src/utils/userAccountManager.test.d.ts +6 -0
- package/dist/src/utils/{user_account.test.js → userAccountManager.test.js} +33 -30
- package/dist/src/utils/userAccountManager.test.js.map +1 -0
- package/dist/src/utils/workspaceContext.js +13 -7
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +41 -16
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -13
- package/dist/src/utils/user_account.d.ts +0 -9
- package/dist/src/utils/user_account.js +0 -109
- package/dist/src/utils/user_account.js.map +0 -1
- package/dist/src/utils/user_account.test.js.map +0 -1
- package/dist/src/utils/user_id.d.ts +0 -11
- package/dist/src/utils/user_id.js +0 -49
- package/dist/src/utils/user_id.js.map +0 -1
- package/dist/src/utils/user_id.test.js +0 -21
- package/dist/src/utils/user_id.test.js.map +0 -1
- /package/dist/src/{utils/user_account.test.d.ts → config/storage.test.d.ts} +0 -0
- /package/dist/src/{utils/user_id.test.d.ts → ide/process-utils.test.d.ts} +0 -0
|
@@ -3,14 +3,29 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { createUserContent, } from '@google/genai';
|
|
6
|
+
import { toParts } from '../code_assist/converter.js';
|
|
7
|
+
import { createUserContent } from '@google/genai';
|
|
9
8
|
import { retryWithBackoff } from '../utils/retry.js';
|
|
10
|
-
import { isFunctionResponse } from '../utils/messageInspectors.js';
|
|
11
9
|
import { AuthType } from './contentGenerator.js';
|
|
12
10
|
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
|
13
11
|
import { hasCycleInSchema } from '../tools/tools.js';
|
|
12
|
+
import { logContentRetry, logContentRetryFailure, logInvalidChunk, } from '../telemetry/loggers.js';
|
|
13
|
+
import { ChatRecordingService } from '../services/chatRecordingService.js';
|
|
14
|
+
import { ContentRetryEvent, ContentRetryFailureEvent, InvalidChunkEvent, } from '../telemetry/types.js';
|
|
15
|
+
import { isFunctionResponse } from '../utils/messageInspectors.js';
|
|
16
|
+
import { partListUnionToString } from './geminiRequest.js';
|
|
17
|
+
export var StreamEventType;
|
|
18
|
+
(function (StreamEventType) {
|
|
19
|
+
/** A regular content chunk from the API. */
|
|
20
|
+
StreamEventType["CHUNK"] = "chunk";
|
|
21
|
+
/** A signal that a retry is about to happen. The UI should discard any partial
|
|
22
|
+
* content from the attempt that just failed. */
|
|
23
|
+
StreamEventType["RETRY"] = "retry";
|
|
24
|
+
})(StreamEventType || (StreamEventType = {}));
|
|
25
|
+
const INVALID_CONTENT_RETRY_OPTIONS = {
|
|
26
|
+
maxAttempts: 3, // 1 initial call + 2 retries
|
|
27
|
+
initialDelayMs: 500,
|
|
28
|
+
};
|
|
14
29
|
/**
|
|
15
30
|
* Returns true if the response is valid, false otherwise.
|
|
16
31
|
*/
|
|
@@ -84,14 +99,20 @@ function extractCuratedHistory(comprehensiveHistory) {
|
|
|
84
99
|
if (isValid) {
|
|
85
100
|
curatedHistory.push(...modelOutput);
|
|
86
101
|
}
|
|
87
|
-
else {
|
|
88
|
-
// Remove the last user input when model content is invalid.
|
|
89
|
-
curatedHistory.pop();
|
|
90
|
-
}
|
|
91
102
|
}
|
|
92
103
|
}
|
|
93
104
|
return curatedHistory;
|
|
94
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Custom error to signal that a stream completed without valid content,
|
|
108
|
+
* which should trigger a retry.
|
|
109
|
+
*/
|
|
110
|
+
export class EmptyStreamError extends Error {
|
|
111
|
+
constructor(message) {
|
|
112
|
+
super(message);
|
|
113
|
+
this.name = 'EmptyStreamError';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
95
116
|
/**
|
|
96
117
|
* Chat session that enables sending messages to the model with previous
|
|
97
118
|
* conversation context.
|
|
@@ -107,12 +128,15 @@ export class GeminiChat {
|
|
|
107
128
|
// A promise to represent the current state of the message being sent to the
|
|
108
129
|
// model.
|
|
109
130
|
sendPromise = Promise.resolve();
|
|
131
|
+
chatRecordingService;
|
|
110
132
|
constructor(config, contentGenerator, generationConfig = {}, history = []) {
|
|
111
133
|
this.config = config;
|
|
112
134
|
this.contentGenerator = contentGenerator;
|
|
113
135
|
this.generationConfig = generationConfig;
|
|
114
136
|
this.history = history;
|
|
115
137
|
validateHistory(history);
|
|
138
|
+
this.chatRecordingService = new ChatRecordingService(config);
|
|
139
|
+
this.chatRecordingService.initialize();
|
|
116
140
|
}
|
|
117
141
|
/**
|
|
118
142
|
* Handles falling back to Flash model when persistent 429 errors occur for OAuth users.
|
|
@@ -168,7 +192,7 @@ export class GeminiChat {
|
|
|
168
192
|
* ```ts
|
|
169
193
|
* const chat = ai.chats.create({model: 'gemini-2.0-flash'});
|
|
170
194
|
* const response = await chat.sendMessage({
|
|
171
|
-
*
|
|
195
|
+
* message: 'Why is the sky blue?'
|
|
172
196
|
* });
|
|
173
197
|
* console.log(response.text);
|
|
174
198
|
* ```
|
|
@@ -176,6 +200,17 @@ export class GeminiChat {
|
|
|
176
200
|
async sendMessage(params, prompt_id) {
|
|
177
201
|
await this.sendPromise;
|
|
178
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
|
+
}
|
|
179
214
|
const requestContents = this.getHistory(true).concat(userContent);
|
|
180
215
|
let response;
|
|
181
216
|
try {
|
|
@@ -210,6 +245,7 @@ export class GeminiChat {
|
|
|
210
245
|
});
|
|
211
246
|
this.sendPromise = (async () => {
|
|
212
247
|
const outputContent = response.candidates?.[0]?.content;
|
|
248
|
+
const modelOutput = outputContent ? [outputContent] : [];
|
|
213
249
|
// Because the AFC input contains the entire curated chat history in
|
|
214
250
|
// addition to the new user input, we need to truncate the AFC history
|
|
215
251
|
// to deduplicate the existing chat history.
|
|
@@ -220,12 +256,13 @@ export class GeminiChat {
|
|
|
220
256
|
automaticFunctionCallingHistory =
|
|
221
257
|
fullAutomaticFunctionCallingHistory.slice(index) ?? [];
|
|
222
258
|
}
|
|
223
|
-
const modelOutput = outputContent ? [outputContent] : [];
|
|
224
259
|
this.recordHistory(userContent, modelOutput, automaticFunctionCallingHistory);
|
|
225
260
|
})();
|
|
226
|
-
await this.sendPromise.catch(() => {
|
|
261
|
+
await this.sendPromise.catch((error) => {
|
|
227
262
|
// Resets sendPromise to avoid subsequent calls failing
|
|
228
263
|
this.sendPromise = Promise.resolve();
|
|
264
|
+
// Re-throw the error so the caller knows something went wrong.
|
|
265
|
+
throw error;
|
|
229
266
|
});
|
|
230
267
|
return response;
|
|
231
268
|
}
|
|
@@ -249,64 +286,113 @@ export class GeminiChat {
|
|
|
249
286
|
* ```ts
|
|
250
287
|
* const chat = ai.chats.create({model: 'gemini-2.0-flash'});
|
|
251
288
|
* const response = await chat.sendMessageStream({
|
|
252
|
-
*
|
|
289
|
+
* message: 'Why is the sky blue?'
|
|
253
290
|
* });
|
|
254
291
|
* for await (const chunk of response) {
|
|
255
|
-
*
|
|
292
|
+
* console.log(chunk.text);
|
|
256
293
|
* }
|
|
257
294
|
* ```
|
|
258
295
|
*/
|
|
259
296
|
async sendMessageStream(params, prompt_id) {
|
|
260
297
|
await this.sendPromise;
|
|
298
|
+
let streamDoneResolver;
|
|
299
|
+
const streamDonePromise = new Promise((resolve) => {
|
|
300
|
+
streamDoneResolver = resolve;
|
|
301
|
+
});
|
|
302
|
+
this.sendPromise = streamDonePromise;
|
|
261
303
|
const userContent = createUserContent(params.message);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
model: modelToUse,
|
|
273
|
-
contents: requestContents,
|
|
274
|
-
config: { ...this.generationConfig, ...params.config },
|
|
275
|
-
}, prompt_id);
|
|
276
|
-
};
|
|
277
|
-
// Note: Retrying streams can be complex. If generateContentStream itself doesn't handle retries
|
|
278
|
-
// for transient issues internally before yielding the async generator, this retry will re-initiate
|
|
279
|
-
// the stream. For simple 429/500 errors on initial call, this is fine.
|
|
280
|
-
// If errors occur mid-stream, this setup won't resume the stream; it will restart it.
|
|
281
|
-
const streamResponse = await retryWithBackoff(apiCall, {
|
|
282
|
-
shouldRetry: (error) => {
|
|
283
|
-
// Check for known error messages and codes.
|
|
284
|
-
if (error instanceof Error && error.message) {
|
|
285
|
-
if (isSchemaDepthError(error.message))
|
|
286
|
-
return false;
|
|
287
|
-
if (error.message.includes('429'))
|
|
288
|
-
return true;
|
|
289
|
-
if (error.message.match(/5\d{2}/))
|
|
290
|
-
return true;
|
|
291
|
-
}
|
|
292
|
-
return false; // Don't retry other errors by default
|
|
293
|
-
},
|
|
294
|
-
onPersistent429: async (authType, error) => await this.handleFlashFallback(authType, error),
|
|
295
|
-
authType: this.config.getContentGeneratorConfig()?.authType,
|
|
304
|
+
// Record user input - capture complete message with all parts (text, files, images, etc.)
|
|
305
|
+
// but skip recording function responses (tool call results) as they should be stored in tool call records
|
|
306
|
+
if (!isFunctionResponse(userContent)) {
|
|
307
|
+
const userMessage = Array.isArray(params.message)
|
|
308
|
+
? params.message
|
|
309
|
+
: [params.message];
|
|
310
|
+
const userMessageContent = partListUnionToString(toParts(userMessage));
|
|
311
|
+
this.chatRecordingService.recordMessage({
|
|
312
|
+
type: 'user',
|
|
313
|
+
content: userMessageContent,
|
|
296
314
|
});
|
|
297
|
-
// Resolve the internal tracking of send completion promise - `sendPromise`
|
|
298
|
-
// for both success and failure response. The actual failure is still
|
|
299
|
-
// propagated by the `await streamResponse`.
|
|
300
|
-
this.sendPromise = Promise.resolve(streamResponse)
|
|
301
|
-
.then(() => undefined)
|
|
302
|
-
.catch(() => undefined);
|
|
303
|
-
const result = this.processStreamResponse(streamResponse, userContent);
|
|
304
|
-
return result;
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
this.sendPromise = Promise.resolve();
|
|
308
|
-
throw error;
|
|
309
315
|
}
|
|
316
|
+
// Add user content to history ONCE before any attempts.
|
|
317
|
+
this.history.push(userContent);
|
|
318
|
+
const requestContents = this.getHistory(true);
|
|
319
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
320
|
+
const self = this;
|
|
321
|
+
return (async function* () {
|
|
322
|
+
try {
|
|
323
|
+
let lastError = new Error('Request failed after all retries.');
|
|
324
|
+
for (let attempt = 0; attempt < INVALID_CONTENT_RETRY_OPTIONS.maxAttempts; attempt++) {
|
|
325
|
+
try {
|
|
326
|
+
if (attempt > 0) {
|
|
327
|
+
yield { type: StreamEventType.RETRY };
|
|
328
|
+
}
|
|
329
|
+
const stream = await self.makeApiCallAndProcessStream(requestContents, params, prompt_id, userContent);
|
|
330
|
+
for await (const chunk of stream) {
|
|
331
|
+
yield { type: StreamEventType.CHUNK, value: chunk };
|
|
332
|
+
}
|
|
333
|
+
lastError = null;
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
lastError = error;
|
|
338
|
+
const isContentError = error instanceof EmptyStreamError;
|
|
339
|
+
if (isContentError) {
|
|
340
|
+
// Check if we have more attempts left.
|
|
341
|
+
if (attempt < INVALID_CONTENT_RETRY_OPTIONS.maxAttempts - 1) {
|
|
342
|
+
logContentRetry(self.config, new ContentRetryEvent(attempt, 'EmptyStreamError', INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs));
|
|
343
|
+
await new Promise((res) => setTimeout(res, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs *
|
|
344
|
+
(attempt + 1)));
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (lastError) {
|
|
352
|
+
if (lastError instanceof EmptyStreamError) {
|
|
353
|
+
logContentRetryFailure(self.config, new ContentRetryFailureEvent(INVALID_CONTENT_RETRY_OPTIONS.maxAttempts, 'EmptyStreamError'));
|
|
354
|
+
}
|
|
355
|
+
// If the stream fails, remove the user message that was added.
|
|
356
|
+
if (self.history[self.history.length - 1] === userContent) {
|
|
357
|
+
self.history.pop();
|
|
358
|
+
}
|
|
359
|
+
throw lastError;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
finally {
|
|
363
|
+
streamDoneResolver();
|
|
364
|
+
}
|
|
365
|
+
})();
|
|
366
|
+
}
|
|
367
|
+
async makeApiCallAndProcessStream(requestContents, params, prompt_id, userContent) {
|
|
368
|
+
const apiCall = () => {
|
|
369
|
+
const modelToUse = this.config.getModel();
|
|
370
|
+
if (this.config.getQuotaErrorOccurred() &&
|
|
371
|
+
modelToUse === DEFAULT_GEMINI_FLASH_MODEL) {
|
|
372
|
+
throw new Error('Please submit a new query to continue with the Flash model.');
|
|
373
|
+
}
|
|
374
|
+
return this.contentGenerator.generateContentStream({
|
|
375
|
+
model: modelToUse,
|
|
376
|
+
contents: requestContents,
|
|
377
|
+
config: { ...this.generationConfig, ...params.config },
|
|
378
|
+
}, prompt_id);
|
|
379
|
+
};
|
|
380
|
+
const streamResponse = await retryWithBackoff(apiCall, {
|
|
381
|
+
shouldRetry: (error) => {
|
|
382
|
+
if (error instanceof Error && error.message) {
|
|
383
|
+
if (isSchemaDepthError(error.message))
|
|
384
|
+
return false;
|
|
385
|
+
if (error.message.includes('429'))
|
|
386
|
+
return true;
|
|
387
|
+
if (error.message.match(/5\d{2}/))
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
return false;
|
|
391
|
+
},
|
|
392
|
+
onPersistent429: async (authType, error) => await this.handleFlashFallback(authType, error),
|
|
393
|
+
authType: this.config.getContentGeneratorConfig()?.authType,
|
|
394
|
+
});
|
|
395
|
+
return this.processStreamResponse(streamResponse, userContent);
|
|
310
396
|
}
|
|
311
397
|
/**
|
|
312
398
|
* Returns the chat history.
|
|
@@ -318,7 +404,7 @@ export class GeminiChat {
|
|
|
318
404
|
* - The `curated history` contains only the valid turns between user and
|
|
319
405
|
* model, which will be included in the subsequent requests sent to the model.
|
|
320
406
|
* - The `comprehensive history` contains all turns, including invalid or
|
|
321
|
-
*
|
|
407
|
+
* empty model outputs, providing a complete record of the history.
|
|
322
408
|
*
|
|
323
409
|
* The history is updated after receiving the response from the model,
|
|
324
410
|
* for streaming response, it means receiving the last chunk of the response.
|
|
@@ -327,9 +413,9 @@ export class GeminiChat {
|
|
|
327
413
|
* history`, set the `curated` parameter to `true`.
|
|
328
414
|
*
|
|
329
415
|
* @param curated - whether to return the curated history or the comprehensive
|
|
330
|
-
*
|
|
416
|
+
* history.
|
|
331
417
|
* @return History contents alternating between user and model for the entire
|
|
332
|
-
*
|
|
418
|
+
* chat session.
|
|
333
419
|
*/
|
|
334
420
|
getHistory(curated = false) {
|
|
335
421
|
const history = curated
|
|
@@ -347,8 +433,6 @@ export class GeminiChat {
|
|
|
347
433
|
}
|
|
348
434
|
/**
|
|
349
435
|
* Adds a new entry to the chat history.
|
|
350
|
-
*
|
|
351
|
-
* @param content - The content to add to the history.
|
|
352
436
|
*/
|
|
353
437
|
addHistory(content) {
|
|
354
438
|
this.history.push(content);
|
|
@@ -364,7 +448,7 @@ export class GeminiChat {
|
|
|
364
448
|
// and include a recommendation to remove potentially problematic tools.
|
|
365
449
|
if (isSchemaDepthError(error.message) ||
|
|
366
450
|
isInvalidArgumentError(error.message)) {
|
|
367
|
-
const tools =
|
|
451
|
+
const tools = this.config.getToolRegistry().getAllTools();
|
|
368
452
|
const cyclicSchemaTools = [];
|
|
369
453
|
for (const tool of tools) {
|
|
370
454
|
if ((tool.schema.parametersJsonSchema &&
|
|
@@ -381,122 +465,211 @@ export class GeminiChat {
|
|
|
381
465
|
}
|
|
382
466
|
}
|
|
383
467
|
}
|
|
384
|
-
async *processStreamResponse(streamResponse,
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
let
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
468
|
+
async *processStreamResponse(streamResponse, userInput) {
|
|
469
|
+
const modelResponseParts = [];
|
|
470
|
+
let hasReceivedAnyChunk = false;
|
|
471
|
+
let hasReceivedValidChunk = false;
|
|
472
|
+
let hasToolCall = false;
|
|
473
|
+
let lastChunk = null;
|
|
474
|
+
let lastChunkIsInvalid = false;
|
|
475
|
+
for await (const chunk of streamResponse) {
|
|
476
|
+
hasReceivedAnyChunk = true;
|
|
477
|
+
lastChunk = chunk;
|
|
478
|
+
if (isValidResponse(chunk)) {
|
|
479
|
+
hasReceivedValidChunk = true;
|
|
480
|
+
lastChunkIsInvalid = false;
|
|
481
|
+
const content = chunk.candidates?.[0]?.content;
|
|
482
|
+
if (content?.parts) {
|
|
483
|
+
if (content.parts.some((part) => part.thought)) {
|
|
484
|
+
// Record thoughts
|
|
485
|
+
this.recordThoughtFromContent(content);
|
|
486
|
+
}
|
|
487
|
+
if (content.parts.some((part) => part.functionCall)) {
|
|
488
|
+
hasToolCall = true;
|
|
489
|
+
}
|
|
490
|
+
// Always add parts - thoughts will be filtered out later in recordHistory
|
|
491
|
+
modelResponseParts.push(...content.parts);
|
|
492
|
+
if (content.parts.some((part) => part.functionCall)) {
|
|
493
|
+
hasToolCall = true;
|
|
399
494
|
}
|
|
400
495
|
}
|
|
401
|
-
yield chunk;
|
|
402
496
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
throw error;
|
|
407
|
-
}
|
|
408
|
-
if (!errorOccurred) {
|
|
409
|
-
const allParts = [];
|
|
410
|
-
for (const content of outputContent) {
|
|
411
|
-
if (content.parts) {
|
|
412
|
-
allParts.push(...content.parts);
|
|
413
|
-
}
|
|
497
|
+
else {
|
|
498
|
+
logInvalidChunk(this.config, new InvalidChunkEvent('Invalid chunk received from stream.'));
|
|
499
|
+
lastChunkIsInvalid = true;
|
|
414
500
|
}
|
|
501
|
+
// Record token usage if this chunk has usageMetadata
|
|
502
|
+
if (chunk.usageMetadata) {
|
|
503
|
+
this.chatRecordingService.recordMessageTokens(chunk.usageMetadata);
|
|
504
|
+
}
|
|
505
|
+
yield chunk; // Yield every chunk to the UI immediately.
|
|
415
506
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) {
|
|
419
|
-
const nonThoughtModelOutput = modelOutput.filter((content) => !this.isThoughtContent(content));
|
|
420
|
-
let outputContents = [];
|
|
421
|
-
if (nonThoughtModelOutput.length > 0 &&
|
|
422
|
-
nonThoughtModelOutput.every((content) => content.role !== undefined)) {
|
|
423
|
-
outputContents = nonThoughtModelOutput;
|
|
507
|
+
if (!hasReceivedAnyChunk) {
|
|
508
|
+
throw new EmptyStreamError('Model stream completed without any chunks.');
|
|
424
509
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
510
|
+
const hasFinishReason = lastChunk?.candidates?.some((candidate) => candidate.finishReason);
|
|
511
|
+
// Stream validation logic: A stream is considered successful if:
|
|
512
|
+
// 1. There's a tool call (tool calls can end without explicit finish reasons), OR
|
|
513
|
+
// 2. There's a finish reason AND the last chunk is valid (or we haven't received any valid chunks)
|
|
514
|
+
//
|
|
515
|
+
// We throw an error only when there's no tool call AND:
|
|
516
|
+
// - No finish reason, OR
|
|
517
|
+
// - Last chunk is invalid after receiving valid content
|
|
518
|
+
if (!hasToolCall &&
|
|
519
|
+
(!hasFinishReason || (lastChunkIsInvalid && !hasReceivedValidChunk))) {
|
|
520
|
+
throw new EmptyStreamError('Model stream ended with an invalid chunk or missing finish reason.');
|
|
428
521
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
522
|
+
// Record model response text from the collected parts
|
|
523
|
+
if (modelResponseParts.length > 0) {
|
|
524
|
+
const responseText = modelResponseParts
|
|
525
|
+
.filter((part) => part.text && !part.thought)
|
|
526
|
+
.map((part) => part.text)
|
|
527
|
+
.join('');
|
|
528
|
+
if (responseText.trim()) {
|
|
529
|
+
this.chatRecordingService.recordMessage({
|
|
530
|
+
type: 'gemini',
|
|
531
|
+
content: responseText,
|
|
437
532
|
});
|
|
438
533
|
}
|
|
439
534
|
}
|
|
535
|
+
// Bundle all streamed parts into a single Content object
|
|
536
|
+
const modelOutput = modelResponseParts.length > 0
|
|
537
|
+
? [{ role: 'model', parts: modelResponseParts }]
|
|
538
|
+
: [];
|
|
539
|
+
// Pass the raw, bundled data to the new, robust recordHistory
|
|
540
|
+
this.recordHistory(userInput, modelOutput);
|
|
541
|
+
}
|
|
542
|
+
recordHistory(userInput, modelOutput, automaticFunctionCallingHistory) {
|
|
543
|
+
// Part 1: Handle the user's turn.
|
|
440
544
|
if (automaticFunctionCallingHistory &&
|
|
441
545
|
automaticFunctionCallingHistory.length > 0) {
|
|
442
546
|
this.history.push(...extractCuratedHistory(automaticFunctionCallingHistory));
|
|
443
547
|
}
|
|
444
548
|
else {
|
|
445
|
-
this.history.
|
|
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
|
+
}
|
|
446
562
|
}
|
|
447
|
-
//
|
|
448
|
-
const
|
|
449
|
-
for (const content of
|
|
450
|
-
|
|
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);
|
|
451
569
|
continue;
|
|
452
570
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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);
|
|
461
582
|
}
|
|
462
583
|
else {
|
|
463
|
-
|
|
584
|
+
finalModelTurns.push(newTurn);
|
|
464
585
|
}
|
|
465
586
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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;
|
|
479
617
|
}
|
|
480
|
-
consolidatedOutputContents.shift(); // Remove the first element as it's merged
|
|
481
618
|
}
|
|
482
|
-
this.history.push(...
|
|
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: [] });
|
|
483
624
|
}
|
|
484
625
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Gets the chat recording service instance.
|
|
628
|
+
*/
|
|
629
|
+
getChatRecordingService() {
|
|
630
|
+
return this.chatRecordingService;
|
|
631
|
+
}
|
|
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);
|
|
492
651
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
652
|
+
/**
|
|
653
|
+
* Extracts and records thought from thought content.
|
|
654
|
+
*/
|
|
655
|
+
recordThoughtFromContent(content) {
|
|
656
|
+
if (!content.parts || content.parts.length === 0) {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
const thoughtPart = content.parts[0];
|
|
660
|
+
if (thoughtPart.text) {
|
|
661
|
+
// Extract subject and description using the same logic as turn.ts
|
|
662
|
+
const rawText = thoughtPart.text;
|
|
663
|
+
const subjectStringMatches = rawText.match(/\*\*(.*?)\*\*/s);
|
|
664
|
+
const subject = subjectStringMatches
|
|
665
|
+
? subjectStringMatches[1].trim()
|
|
666
|
+
: '';
|
|
667
|
+
const description = rawText.replace(/\*\*(.*?)\*\*/s, '').trim();
|
|
668
|
+
this.chatRecordingService.recordThought({
|
|
669
|
+
subject,
|
|
670
|
+
description,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
500
673
|
}
|
|
501
674
|
}
|
|
502
675
|
/** Visible for Testing */
|