@google/gemini-cli-core 0.1.0-development.1
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/LICENSE +202 -0
- package/README.md +156 -0
- package/dist/.last_build +0 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/src/__mocks__/fs/promises.d.ts +11 -0
- package/dist/src/__mocks__/fs/promises.js +17 -0
- package/dist/src/__mocks__/fs/promises.js.map +1 -0
- package/dist/src/code_assist/codeAssist.d.ts +8 -0
- package/dist/src/code_assist/codeAssist.js +19 -0
- package/dist/src/code_assist/codeAssist.js.map +1 -0
- package/dist/src/code_assist/converter.d.ts +68 -0
- package/dist/src/code_assist/converter.js +125 -0
- package/dist/src/code_assist/converter.js.map +1 -0
- package/dist/src/code_assist/converter.test.d.ts +6 -0
- package/dist/src/code_assist/converter.test.js +229 -0
- package/dist/src/code_assist/converter.test.js.map +1 -0
- package/dist/src/code_assist/oauth2.d.ts +26 -0
- package/dist/src/code_assist/oauth2.js +277 -0
- package/dist/src/code_assist/oauth2.js.map +1 -0
- package/dist/src/code_assist/oauth2.test.d.ts +6 -0
- package/dist/src/code_assist/oauth2.test.js +195 -0
- package/dist/src/code_assist/oauth2.test.js.map +1 -0
- package/dist/src/code_assist/server.d.ts +35 -0
- package/dist/src/code_assist/server.js +123 -0
- package/dist/src/code_assist/server.js.map +1 -0
- package/dist/src/code_assist/server.test.d.ts +6 -0
- package/dist/src/code_assist/server.test.js +123 -0
- package/dist/src/code_assist/server.test.js.map +1 -0
- package/dist/src/code_assist/setup.d.ts +15 -0
- package/dist/src/code_assist/setup.js +67 -0
- package/dist/src/code_assist/setup.js.map +1 -0
- package/dist/src/code_assist/types.d.ts +148 -0
- package/dist/src/code_assist/types.js +46 -0
- package/dist/src/code_assist/types.js.map +1 -0
- package/dist/src/config/config.d.ts +175 -0
- package/dist/src/config/config.js +385 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/config/config.test.d.ts +6 -0
- package/dist/src/config/config.test.js +263 -0
- package/dist/src/config/config.test.js.map +1 -0
- package/dist/src/config/flashFallback.test.d.ts +6 -0
- package/dist/src/config/flashFallback.test.js +115 -0
- package/dist/src/config/flashFallback.test.js.map +1 -0
- package/dist/src/config/models.d.ts +8 -0
- package/dist/src/config/models.js +9 -0
- package/dist/src/config/models.js.map +1 -0
- package/dist/src/core/client.d.ts +39 -0
- package/dist/src/core/client.js +386 -0
- package/dist/src/core/client.js.map +1 -0
- package/dist/src/core/client.test.d.ts +6 -0
- package/dist/src/core/client.test.js +630 -0
- package/dist/src/core/client.test.js.map +1 -0
- package/dist/src/core/contentGenerator.d.ts +29 -0
- package/dist/src/core/contentGenerator.js +71 -0
- package/dist/src/core/contentGenerator.js.map +1 -0
- package/dist/src/core/contentGenerator.test.d.ts +6 -0
- package/dist/src/core/contentGenerator.test.js +45 -0
- package/dist/src/core/contentGenerator.test.js.map +1 -0
- package/dist/src/core/coreToolScheduler.d.ts +104 -0
- package/dist/src/core/coreToolScheduler.js +397 -0
- package/dist/src/core/coreToolScheduler.js.map +1 -0
- package/dist/src/core/coreToolScheduler.test.d.ts +6 -0
- package/dist/src/core/coreToolScheduler.test.js +318 -0
- package/dist/src/core/coreToolScheduler.test.js.map +1 -0
- package/dist/src/core/geminiChat.d.ts +116 -0
- package/dist/src/core/geminiChat.js +491 -0
- package/dist/src/core/geminiChat.js.map +1 -0
- package/dist/src/core/geminiChat.test.d.ts +6 -0
- package/dist/src/core/geminiChat.test.js +422 -0
- package/dist/src/core/geminiChat.test.js.map +1 -0
- package/dist/src/core/geminiRequest.d.ts +13 -0
- package/dist/src/core/geminiRequest.js +45 -0
- package/dist/src/core/geminiRequest.js.map +1 -0
- package/dist/src/core/geminiRequest.test.d.ts +6 -0
- package/dist/src/core/geminiRequest.test.js +72 -0
- package/dist/src/core/geminiRequest.test.js.map +1 -0
- package/dist/src/core/logger.d.ts +35 -0
- package/dist/src/core/logger.js +235 -0
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/logger.test.d.ts +6 -0
- package/dist/src/core/logger.test.js +387 -0
- package/dist/src/core/logger.test.js.map +1 -0
- package/dist/src/core/modelCheck.d.ts +14 -0
- package/dist/src/core/modelCheck.js +55 -0
- package/dist/src/core/modelCheck.js.map +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.d.ts +12 -0
- package/dist/src/core/nonInteractiveToolExecutor.js +92 -0
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.d.ts +6 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js +181 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -0
- package/dist/src/core/prompts.d.ts +12 -0
- package/dist/src/core/prompts.js +334 -0
- package/dist/src/core/prompts.js.map +1 -0
- package/dist/src/core/prompts.test.d.ts +6 -0
- package/dist/src/core/prompts.test.js +97 -0
- package/dist/src/core/prompts.test.js.map +1 -0
- package/dist/src/core/tokenLimits.d.ts +10 -0
- package/dist/src/core/tokenLimits.js +27 -0
- package/dist/src/core/tokenLimits.js.map +1 -0
- package/dist/src/core/turn.d.ts +96 -0
- package/dist/src/core/turn.js +125 -0
- package/dist/src/core/turn.js.map +1 -0
- package/dist/src/core/turn.test.d.ts +6 -0
- package/dist/src/core/turn.test.js +236 -0
- package/dist/src/core/turn.test.js.map +1 -0
- package/dist/src/index.d.ts +46 -0
- package/dist/src/index.js +54 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/index.test.d.ts +6 -0
- package/dist/src/index.test.js +12 -0
- package/dist/src/index.test.js.map +1 -0
- package/dist/src/services/fileDiscoveryService.d.ts +35 -0
- package/dist/src/services/fileDiscoveryService.js +91 -0
- package/dist/src/services/fileDiscoveryService.js.map +1 -0
- package/dist/src/services/fileDiscoveryService.test.d.ts +6 -0
- package/dist/src/services/fileDiscoveryService.test.js +102 -0
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -0
- package/dist/src/services/gitService.d.ts +21 -0
- package/dist/src/services/gitService.js +105 -0
- package/dist/src/services/gitService.js.map +1 -0
- package/dist/src/services/gitService.test.d.ts +6 -0
- package/dist/src/services/gitService.test.js +233 -0
- package/dist/src/services/gitService.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +33 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +364 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +43 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +109 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -0
- package/dist/src/telemetry/constants.d.ts +19 -0
- package/dist/src/telemetry/constants.js +20 -0
- package/dist/src/telemetry/constants.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +18 -0
- package/dist/src/telemetry/index.js +20 -0
- package/dist/src/telemetry/index.js.map +1 -0
- package/dist/src/telemetry/loggers.d.ts +13 -0
- package/dist/src/telemetry/loggers.js +187 -0
- package/dist/src/telemetry/loggers.js.map +1 -0
- package/dist/src/telemetry/loggers.test.d.ts +6 -0
- package/dist/src/telemetry/loggers.test.js +525 -0
- package/dist/src/telemetry/loggers.test.js.map +1 -0
- package/dist/src/telemetry/metrics.d.ts +19 -0
- package/dist/src/telemetry/metrics.js +144 -0
- package/dist/src/telemetry/metrics.js.map +1 -0
- package/dist/src/telemetry/metrics.test.d.ts +6 -0
- package/dist/src/telemetry/metrics.test.js +162 -0
- package/dist/src/telemetry/metrics.test.js.map +1 -0
- package/dist/src/telemetry/sdk.d.ts +9 -0
- package/dist/src/telemetry/sdk.js +116 -0
- package/dist/src/telemetry/sdk.js.map +1 -0
- package/dist/src/telemetry/telemetry.test.d.ts +6 -0
- package/dist/src/telemetry/telemetry.test.js +50 -0
- package/dist/src/telemetry/telemetry.test.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +91 -0
- package/dist/src/telemetry/types.js +176 -0
- package/dist/src/telemetry/types.js.map +1 -0
- package/dist/src/telemetry/uiTelemetry.d.ts +67 -0
- package/dist/src/telemetry/uiTelemetry.js +131 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -0
- package/dist/src/telemetry/uiTelemetry.test.d.ts +6 -0
- package/dist/src/telemetry/uiTelemetry.test.js +411 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -0
- package/dist/src/tools/diffOptions.d.ts +7 -0
- package/dist/src/tools/diffOptions.js +10 -0
- package/dist/src/tools/diffOptions.js.map +1 -0
- package/dist/src/tools/edit.d.ts +84 -0
- package/dist/src/tools/edit.js +359 -0
- package/dist/src/tools/edit.js.map +1 -0
- package/dist/src/tools/edit.test.d.ts +6 -0
- package/dist/src/tools/edit.test.js +500 -0
- package/dist/src/tools/edit.test.js.map +1 -0
- package/dist/src/tools/glob.d.ts +71 -0
- package/dist/src/tools/glob.js +215 -0
- package/dist/src/tools/glob.js.map +1 -0
- package/dist/src/tools/glob.test.d.ts +6 -0
- package/dist/src/tools/glob.test.js +293 -0
- package/dist/src/tools/glob.test.js.map +1 -0
- package/dist/src/tools/grep.d.ts +81 -0
- package/dist/src/tools/grep.js +427 -0
- package/dist/src/tools/grep.js.map +1 -0
- package/dist/src/tools/grep.test.d.ts +6 -0
- package/dist/src/tools/grep.test.js +185 -0
- package/dist/src/tools/grep.test.js.map +1 -0
- package/dist/src/tools/ls.d.ts +94 -0
- package/dist/src/tools/ls.js +215 -0
- package/dist/src/tools/ls.js.map +1 -0
- package/dist/src/tools/mcp-client.d.ts +56 -0
- package/dist/src/tools/mcp-client.js +302 -0
- package/dist/src/tools/mcp-client.js.map +1 -0
- package/dist/src/tools/mcp-client.test.d.ts +6 -0
- package/dist/src/tools/mcp-client.test.js +608 -0
- package/dist/src/tools/mcp-client.test.js.map +1 -0
- package/dist/src/tools/mcp-tool.d.ts +23 -0
- package/dist/src/tools/mcp-tool.js +119 -0
- package/dist/src/tools/mcp-tool.js.map +1 -0
- package/dist/src/tools/mcp-tool.test.d.ts +6 -0
- package/dist/src/tools/mcp-tool.test.js +173 -0
- package/dist/src/tools/mcp-tool.test.js.map +1 -0
- package/dist/src/tools/memoryTool.d.ts +28 -0
- package/dist/src/tools/memoryTool.js +171 -0
- package/dist/src/tools/memoryTool.js.map +1 -0
- package/dist/src/tools/memoryTool.test.d.ts +6 -0
- package/dist/src/tools/memoryTool.test.js +181 -0
- package/dist/src/tools/memoryTool.test.js.map +1 -0
- package/dist/src/tools/modifiable-tool.d.ts +29 -0
- package/dist/src/tools/modifiable-tool.js +85 -0
- package/dist/src/tools/modifiable-tool.js.map +1 -0
- package/dist/src/tools/modifiable-tool.test.d.ts +6 -0
- package/dist/src/tools/modifiable-tool.test.js +204 -0
- package/dist/src/tools/modifiable-tool.test.js.map +1 -0
- package/dist/src/tools/read-file.d.ts +36 -0
- package/dist/src/tools/read-file.js +103 -0
- package/dist/src/tools/read-file.js.map +1 -0
- package/dist/src/tools/read-file.test.d.ts +6 -0
- package/dist/src/tools/read-file.test.js +180 -0
- package/dist/src/tools/read-file.test.js.map +1 -0
- package/dist/src/tools/read-many-files.d.ts +65 -0
- package/dist/src/tools/read-many-files.js +344 -0
- package/dist/src/tools/read-many-files.js.map +1 -0
- package/dist/src/tools/read-many-files.test.d.ts +6 -0
- package/dist/src/tools/read-many-files.test.js +300 -0
- package/dist/src/tools/read-many-files.test.js.map +1 -0
- package/dist/src/tools/shell.d.ts +43 -0
- package/dist/src/tools/shell.js +421 -0
- package/dist/src/tools/shell.js.map +1 -0
- package/dist/src/tools/shell.test.d.ts +6 -0
- package/dist/src/tools/shell.test.js +321 -0
- package/dist/src/tools/shell.test.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +67 -0
- package/dist/src/tools/tool-registry.js +326 -0
- package/dist/src/tools/tool-registry.js.map +1 -0
- package/dist/src/tools/tool-registry.test.d.ts +6 -0
- package/dist/src/tools/tool-registry.test.js +353 -0
- package/dist/src/tools/tool-registry.test.js.map +1 -0
- package/dist/src/tools/tools.d.ts +179 -0
- package/dist/src/tools/tools.js +88 -0
- package/dist/src/tools/tools.js.map +1 -0
- package/dist/src/tools/web-fetch.d.ts +29 -0
- package/dist/src/tools/web-fetch.js +240 -0
- package/dist/src/tools/web-fetch.js.map +1 -0
- package/dist/src/tools/web-fetch.test.d.ts +6 -0
- package/dist/src/tools/web-fetch.test.js +70 -0
- package/dist/src/tools/web-fetch.test.js.map +1 -0
- package/dist/src/tools/web-search.d.ts +49 -0
- package/dist/src/tools/web-search.js +119 -0
- package/dist/src/tools/web-search.js.map +1 -0
- package/dist/src/tools/write-file.d.ts +50 -0
- package/dist/src/tools/write-file.js +261 -0
- package/dist/src/tools/write-file.js.map +1 -0
- package/dist/src/tools/write-file.test.d.ts +6 -0
- package/dist/src/tools/write-file.test.js +413 -0
- package/dist/src/tools/write-file.test.js.map +1 -0
- package/dist/src/utils/LruCache.d.ts +13 -0
- package/dist/src/utils/LruCache.js +38 -0
- package/dist/src/utils/LruCache.js.map +1 -0
- package/dist/src/utils/bfsFileSearch.d.ts +22 -0
- package/dist/src/utils/bfsFileSearch.js +62 -0
- package/dist/src/utils/bfsFileSearch.js.map +1 -0
- package/dist/src/utils/bfsFileSearch.test.d.ts +6 -0
- package/dist/src/utils/bfsFileSearch.test.js +129 -0
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -0
- package/dist/src/utils/editCorrector.d.ts +53 -0
- package/dist/src/utils/editCorrector.js +546 -0
- package/dist/src/utils/editCorrector.js.map +1 -0
- package/dist/src/utils/editCorrector.test.d.ts +6 -0
- package/dist/src/utils/editCorrector.test.js +560 -0
- package/dist/src/utils/editCorrector.test.js.map +1 -0
- package/dist/src/utils/editor.d.ts +28 -0
- package/dist/src/utils/editor.js +163 -0
- package/dist/src/utils/editor.js.map +1 -0
- package/dist/src/utils/editor.test.d.ts +6 -0
- package/dist/src/utils/editor.test.js +293 -0
- package/dist/src/utils/editor.test.js.map +1 -0
- package/dist/src/utils/errorReporting.d.ts +14 -0
- package/dist/src/utils/errorReporting.js +88 -0
- package/dist/src/utils/errorReporting.js.map +1 -0
- package/dist/src/utils/errorReporting.test.d.ts +6 -0
- package/dist/src/utils/errorReporting.test.js +124 -0
- package/dist/src/utils/errorReporting.test.js.map +1 -0
- package/dist/src/utils/errors.d.ts +14 -0
- package/dist/src/utils/errors.js +54 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +11 -0
- package/dist/src/utils/fetch.js +51 -0
- package/dist/src/utils/fetch.js.map +1 -0
- package/dist/src/utils/fileUtils.d.ts +49 -0
- package/dist/src/utils/fileUtils.js +284 -0
- package/dist/src/utils/fileUtils.js.map +1 -0
- package/dist/src/utils/fileUtils.test.d.ts +6 -0
- package/dist/src/utils/fileUtils.test.js +321 -0
- package/dist/src/utils/fileUtils.test.js.map +1 -0
- package/dist/src/utils/flashFallback.integration.test.d.ts +6 -0
- package/dist/src/utils/flashFallback.integration.test.js +112 -0
- package/dist/src/utils/flashFallback.integration.test.js.map +1 -0
- package/dist/src/utils/generateContentResponseUtilities.d.ts +14 -0
- package/dist/src/utils/generateContentResponseUtilities.js +92 -0
- package/dist/src/utils/generateContentResponseUtilities.js.map +1 -0
- package/dist/src/utils/generateContentResponseUtilities.test.d.ts +6 -0
- package/dist/src/utils/generateContentResponseUtilities.test.js +273 -0
- package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -0
- package/dist/src/utils/getFolderStructure.d.ts +30 -0
- package/dist/src/utils/getFolderStructure.js +247 -0
- package/dist/src/utils/getFolderStructure.js.map +1 -0
- package/dist/src/utils/getFolderStructure.test.d.ts +6 -0
- package/dist/src/utils/getFolderStructure.test.js +300 -0
- package/dist/src/utils/getFolderStructure.test.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.d.ts +20 -0
- package/dist/src/utils/gitIgnoreParser.js +64 -0
- package/dist/src/utils/gitIgnoreParser.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.test.d.ts +6 -0
- package/dist/src/utils/gitIgnoreParser.test.js +145 -0
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -0
- package/dist/src/utils/gitUtils.d.ts +17 -0
- package/dist/src/utils/gitUtils.js +61 -0
- package/dist/src/utils/gitUtils.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.d.ts +14 -0
- package/dist/src/utils/memoryDiscovery.js +219 -0
- package/dist/src/utils/memoryDiscovery.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.test.d.ts +6 -0
- package/dist/src/utils/memoryDiscovery.test.js +432 -0
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -0
- package/dist/src/utils/memoryImportProcessor.d.ts +35 -0
- package/dist/src/utils/memoryImportProcessor.js +141 -0
- package/dist/src/utils/memoryImportProcessor.js.map +1 -0
- package/dist/src/utils/memoryImportProcessor.test.d.ts +6 -0
- package/dist/src/utils/memoryImportProcessor.test.js +170 -0
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -0
- package/dist/src/utils/messageInspectors.d.ts +8 -0
- package/dist/src/utils/messageInspectors.js +16 -0
- package/dist/src/utils/messageInspectors.js.map +1 -0
- package/dist/src/utils/nextSpeakerChecker.d.ts +12 -0
- package/dist/src/utils/nextSpeakerChecker.js +111 -0
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -0
- package/dist/src/utils/nextSpeakerChecker.test.d.ts +6 -0
- package/dist/src/utils/nextSpeakerChecker.test.js +152 -0
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -0
- package/dist/src/utils/paths.d.ts +47 -0
- package/dist/src/utils/paths.js +136 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/retry.d.ts +21 -0
- package/dist/src/utils/retry.js +220 -0
- package/dist/src/utils/retry.js.map +1 -0
- package/dist/src/utils/retry.test.d.ts +6 -0
- package/dist/src/utils/retry.test.js +322 -0
- package/dist/src/utils/retry.test.js.map +1 -0
- package/dist/src/utils/schemaValidator.d.ts +17 -0
- package/dist/src/utils/schemaValidator.js +50 -0
- package/dist/src/utils/schemaValidator.js.map +1 -0
- package/dist/src/utils/session.d.ts +6 -0
- package/dist/src/utils/session.js +8 -0
- package/dist/src/utils/session.js.map +1 -0
- package/dist/src/utils/testUtils.d.ts +29 -0
- package/dist/src/utils/testUtils.js +70 -0
- package/dist/src/utils/testUtils.js.map +1 -0
- package/dist/src/utils/user_id.d.ts +17 -0
- package/dist/src/utils/user_id.js +70 -0
- package/dist/src/utils/user_id.js.map +1 -0
- package/dist/src/utils/user_id.test.d.ts +6 -0
- package/dist/src/utils/user_id.test.js +42 -0
- package/dist/src/utils/user_id.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
8
|
+
import { retryWithBackoff } from './retry.js';
|
|
9
|
+
import { setSimulate429 } from './testUtils.js';
|
|
10
|
+
// Helper to create a mock function that fails a certain number of times
|
|
11
|
+
const createFailingFunction = (failures, successValue = 'success') => {
|
|
12
|
+
let attempts = 0;
|
|
13
|
+
return vi.fn(async () => {
|
|
14
|
+
attempts++;
|
|
15
|
+
if (attempts <= failures) {
|
|
16
|
+
// Simulate a retryable error
|
|
17
|
+
const error = new Error(`Simulated error attempt ${attempts}`);
|
|
18
|
+
error.status = 500; // Simulate a server error
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
return successValue;
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
// Custom error for testing non-retryable conditions
|
|
25
|
+
class NonRetryableError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'NonRetryableError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
describe('retryWithBackoff', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.useFakeTimers();
|
|
34
|
+
// Disable 429 simulation for tests
|
|
35
|
+
setSimulate429(false);
|
|
36
|
+
// Suppress unhandled promise rejection warnings for tests that expect errors
|
|
37
|
+
console.warn = vi.fn();
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
vi.restoreAllMocks();
|
|
41
|
+
vi.useRealTimers();
|
|
42
|
+
});
|
|
43
|
+
it('should return the result on the first attempt if successful', async () => {
|
|
44
|
+
const mockFn = createFailingFunction(0);
|
|
45
|
+
const result = await retryWithBackoff(mockFn);
|
|
46
|
+
expect(result).toBe('success');
|
|
47
|
+
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
48
|
+
});
|
|
49
|
+
it('should retry and succeed if failures are within maxAttempts', async () => {
|
|
50
|
+
const mockFn = createFailingFunction(2);
|
|
51
|
+
const promise = retryWithBackoff(mockFn, {
|
|
52
|
+
maxAttempts: 3,
|
|
53
|
+
initialDelayMs: 10,
|
|
54
|
+
});
|
|
55
|
+
await vi.runAllTimersAsync(); // Ensure all delays and retries complete
|
|
56
|
+
const result = await promise;
|
|
57
|
+
expect(result).toBe('success');
|
|
58
|
+
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
59
|
+
});
|
|
60
|
+
it('should throw an error if all attempts fail', async () => {
|
|
61
|
+
const mockFn = createFailingFunction(3);
|
|
62
|
+
// 1. Start the retryable operation, which returns a promise.
|
|
63
|
+
const promise = retryWithBackoff(mockFn, {
|
|
64
|
+
maxAttempts: 3,
|
|
65
|
+
initialDelayMs: 10,
|
|
66
|
+
});
|
|
67
|
+
// 2. IMPORTANT: Attach the rejection expectation to the promise *immediately*.
|
|
68
|
+
// This ensures a 'catch' handler is present before the promise can reject.
|
|
69
|
+
// The result is a new promise that resolves when the assertion is met.
|
|
70
|
+
const assertionPromise = expect(promise).rejects.toThrow('Simulated error attempt 3');
|
|
71
|
+
// 3. Now, advance the timers. This will trigger the retries and the
|
|
72
|
+
// eventual rejection. The handler attached in step 2 will catch it.
|
|
73
|
+
await vi.runAllTimersAsync();
|
|
74
|
+
// 4. Await the assertion promise itself to ensure the test was successful.
|
|
75
|
+
await assertionPromise;
|
|
76
|
+
// 5. Finally, assert the number of calls.
|
|
77
|
+
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
78
|
+
});
|
|
79
|
+
it('should not retry if shouldRetry returns false', async () => {
|
|
80
|
+
const mockFn = vi.fn(async () => {
|
|
81
|
+
throw new NonRetryableError('Non-retryable error');
|
|
82
|
+
});
|
|
83
|
+
const shouldRetry = (error) => !(error instanceof NonRetryableError);
|
|
84
|
+
const promise = retryWithBackoff(mockFn, {
|
|
85
|
+
shouldRetry,
|
|
86
|
+
initialDelayMs: 10,
|
|
87
|
+
});
|
|
88
|
+
await expect(promise).rejects.toThrow('Non-retryable error');
|
|
89
|
+
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
90
|
+
});
|
|
91
|
+
it('should use default shouldRetry if not provided, retrying on 429', async () => {
|
|
92
|
+
const mockFn = vi.fn(async () => {
|
|
93
|
+
const error = new Error('Too Many Requests');
|
|
94
|
+
error.status = 429;
|
|
95
|
+
throw error;
|
|
96
|
+
});
|
|
97
|
+
const promise = retryWithBackoff(mockFn, {
|
|
98
|
+
maxAttempts: 2,
|
|
99
|
+
initialDelayMs: 10,
|
|
100
|
+
});
|
|
101
|
+
// Attach the rejection expectation *before* running timers
|
|
102
|
+
const assertionPromise = expect(promise).rejects.toThrow('Too Many Requests');
|
|
103
|
+
// Run timers to trigger retries and eventual rejection
|
|
104
|
+
await vi.runAllTimersAsync();
|
|
105
|
+
// Await the assertion
|
|
106
|
+
await assertionPromise;
|
|
107
|
+
expect(mockFn).toHaveBeenCalledTimes(2);
|
|
108
|
+
});
|
|
109
|
+
it('should use default shouldRetry if not provided, not retrying on 400', async () => {
|
|
110
|
+
const mockFn = vi.fn(async () => {
|
|
111
|
+
const error = new Error('Bad Request');
|
|
112
|
+
error.status = 400;
|
|
113
|
+
throw error;
|
|
114
|
+
});
|
|
115
|
+
const promise = retryWithBackoff(mockFn, {
|
|
116
|
+
maxAttempts: 2,
|
|
117
|
+
initialDelayMs: 10,
|
|
118
|
+
});
|
|
119
|
+
await expect(promise).rejects.toThrow('Bad Request');
|
|
120
|
+
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
121
|
+
});
|
|
122
|
+
it('should respect maxDelayMs', async () => {
|
|
123
|
+
const mockFn = createFailingFunction(3);
|
|
124
|
+
const setTimeoutSpy = vi.spyOn(global, 'setTimeout');
|
|
125
|
+
const promise = retryWithBackoff(mockFn, {
|
|
126
|
+
maxAttempts: 4,
|
|
127
|
+
initialDelayMs: 100,
|
|
128
|
+
maxDelayMs: 250, // Max delay is less than 100 * 2 * 2 = 400
|
|
129
|
+
});
|
|
130
|
+
await vi.advanceTimersByTimeAsync(1000); // Advance well past all delays
|
|
131
|
+
await promise;
|
|
132
|
+
const delays = setTimeoutSpy.mock.calls.map((call) => call[1]);
|
|
133
|
+
// Delays should be around initial, initial*2, maxDelay (due to cap)
|
|
134
|
+
// Jitter makes exact assertion hard, so we check ranges / caps
|
|
135
|
+
expect(delays.length).toBe(3);
|
|
136
|
+
expect(delays[0]).toBeGreaterThanOrEqual(100 * 0.7);
|
|
137
|
+
expect(delays[0]).toBeLessThanOrEqual(100 * 1.3);
|
|
138
|
+
expect(delays[1]).toBeGreaterThanOrEqual(200 * 0.7);
|
|
139
|
+
expect(delays[1]).toBeLessThanOrEqual(200 * 1.3);
|
|
140
|
+
// The third delay should be capped by maxDelayMs (250ms), accounting for jitter
|
|
141
|
+
expect(delays[2]).toBeGreaterThanOrEqual(250 * 0.7);
|
|
142
|
+
expect(delays[2]).toBeLessThanOrEqual(250 * 1.3);
|
|
143
|
+
});
|
|
144
|
+
it('should handle jitter correctly, ensuring varied delays', async () => {
|
|
145
|
+
let mockFn = createFailingFunction(5);
|
|
146
|
+
const setTimeoutSpy = vi.spyOn(global, 'setTimeout');
|
|
147
|
+
// Run retryWithBackoff multiple times to observe jitter
|
|
148
|
+
const runRetry = () => retryWithBackoff(mockFn, {
|
|
149
|
+
maxAttempts: 2, // Only one retry, so one delay
|
|
150
|
+
initialDelayMs: 100,
|
|
151
|
+
maxDelayMs: 1000,
|
|
152
|
+
});
|
|
153
|
+
// We expect rejections as mockFn fails 5 times
|
|
154
|
+
const promise1 = runRetry();
|
|
155
|
+
// Attach the rejection expectation *before* running timers
|
|
156
|
+
const assertionPromise1 = expect(promise1).rejects.toThrow();
|
|
157
|
+
await vi.runAllTimersAsync(); // Advance for the delay in the first runRetry
|
|
158
|
+
await assertionPromise1;
|
|
159
|
+
const firstDelaySet = setTimeoutSpy.mock.calls.map((call) => call[1]);
|
|
160
|
+
setTimeoutSpy.mockClear(); // Clear calls for the next run
|
|
161
|
+
// Reset mockFn to reset its internal attempt counter for the next run
|
|
162
|
+
mockFn = createFailingFunction(5); // Re-initialize with 5 failures
|
|
163
|
+
const promise2 = runRetry();
|
|
164
|
+
// Attach the rejection expectation *before* running timers
|
|
165
|
+
const assertionPromise2 = expect(promise2).rejects.toThrow();
|
|
166
|
+
await vi.runAllTimersAsync(); // Advance for the delay in the second runRetry
|
|
167
|
+
await assertionPromise2;
|
|
168
|
+
const secondDelaySet = setTimeoutSpy.mock.calls.map((call) => call[1]);
|
|
169
|
+
// Check that the delays are not exactly the same due to jitter
|
|
170
|
+
// This is a probabilistic test, but with +/-30% jitter, it's highly likely they differ.
|
|
171
|
+
if (firstDelaySet.length > 0 && secondDelaySet.length > 0) {
|
|
172
|
+
// Check the first delay of each set
|
|
173
|
+
expect(firstDelaySet[0]).not.toBe(secondDelaySet[0]);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// If somehow no delays were captured (e.g. test setup issue), fail explicitly
|
|
177
|
+
throw new Error('Delays were not captured for jitter test');
|
|
178
|
+
}
|
|
179
|
+
// Ensure delays are within the expected jitter range [70, 130] for initialDelayMs = 100
|
|
180
|
+
[...firstDelaySet, ...secondDelaySet].forEach((d) => {
|
|
181
|
+
expect(d).toBeGreaterThanOrEqual(100 * 0.7);
|
|
182
|
+
expect(d).toBeLessThanOrEqual(100 * 1.3);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('Flash model fallback for OAuth users', () => {
|
|
186
|
+
it('should trigger fallback for OAuth personal users after persistent 429 errors', async () => {
|
|
187
|
+
const fallbackCallback = vi.fn().mockResolvedValue('gemini-2.5-flash');
|
|
188
|
+
let fallbackOccurred = false;
|
|
189
|
+
const mockFn = vi.fn().mockImplementation(async () => {
|
|
190
|
+
if (!fallbackOccurred) {
|
|
191
|
+
const error = new Error('Rate limit exceeded');
|
|
192
|
+
error.status = 429;
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
return 'success';
|
|
196
|
+
});
|
|
197
|
+
const promise = retryWithBackoff(mockFn, {
|
|
198
|
+
maxAttempts: 3,
|
|
199
|
+
initialDelayMs: 100,
|
|
200
|
+
onPersistent429: async (authType) => {
|
|
201
|
+
fallbackOccurred = true;
|
|
202
|
+
return await fallbackCallback(authType);
|
|
203
|
+
},
|
|
204
|
+
authType: 'oauth-personal',
|
|
205
|
+
});
|
|
206
|
+
// Advance all timers to complete retries
|
|
207
|
+
await vi.runAllTimersAsync();
|
|
208
|
+
// Should succeed after fallback
|
|
209
|
+
await expect(promise).resolves.toBe('success');
|
|
210
|
+
// Verify callback was called with correct auth type
|
|
211
|
+
expect(fallbackCallback).toHaveBeenCalledWith('oauth-personal');
|
|
212
|
+
// Should retry again after fallback
|
|
213
|
+
expect(mockFn).toHaveBeenCalledTimes(3); // 2 initial attempts + 1 after fallback
|
|
214
|
+
});
|
|
215
|
+
it('should NOT trigger fallback for API key users', async () => {
|
|
216
|
+
const fallbackCallback = vi.fn();
|
|
217
|
+
const mockFn = vi.fn(async () => {
|
|
218
|
+
const error = new Error('Rate limit exceeded');
|
|
219
|
+
error.status = 429;
|
|
220
|
+
throw error;
|
|
221
|
+
});
|
|
222
|
+
const promise = retryWithBackoff(mockFn, {
|
|
223
|
+
maxAttempts: 3,
|
|
224
|
+
initialDelayMs: 100,
|
|
225
|
+
onPersistent429: fallbackCallback,
|
|
226
|
+
authType: 'gemini-api-key',
|
|
227
|
+
});
|
|
228
|
+
// Handle the promise properly to avoid unhandled rejections
|
|
229
|
+
const resultPromise = promise.catch((error) => error);
|
|
230
|
+
await vi.runAllTimersAsync();
|
|
231
|
+
const result = await resultPromise;
|
|
232
|
+
// Should fail after all retries without fallback
|
|
233
|
+
expect(result).toBeInstanceOf(Error);
|
|
234
|
+
expect(result.message).toBe('Rate limit exceeded');
|
|
235
|
+
// Callback should not be called for API key users
|
|
236
|
+
expect(fallbackCallback).not.toHaveBeenCalled();
|
|
237
|
+
});
|
|
238
|
+
it('should reset attempt counter and continue after successful fallback', async () => {
|
|
239
|
+
let fallbackCalled = false;
|
|
240
|
+
const fallbackCallback = vi.fn().mockImplementation(async () => {
|
|
241
|
+
fallbackCalled = true;
|
|
242
|
+
return 'gemini-2.5-flash';
|
|
243
|
+
});
|
|
244
|
+
const mockFn = vi.fn().mockImplementation(async () => {
|
|
245
|
+
if (!fallbackCalled) {
|
|
246
|
+
const error = new Error('Rate limit exceeded');
|
|
247
|
+
error.status = 429;
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
return 'success';
|
|
251
|
+
});
|
|
252
|
+
const promise = retryWithBackoff(mockFn, {
|
|
253
|
+
maxAttempts: 3,
|
|
254
|
+
initialDelayMs: 100,
|
|
255
|
+
onPersistent429: fallbackCallback,
|
|
256
|
+
authType: 'oauth-personal',
|
|
257
|
+
});
|
|
258
|
+
await vi.runAllTimersAsync();
|
|
259
|
+
await expect(promise).resolves.toBe('success');
|
|
260
|
+
expect(fallbackCallback).toHaveBeenCalledOnce();
|
|
261
|
+
});
|
|
262
|
+
it('should continue with original error if fallback is rejected', async () => {
|
|
263
|
+
const fallbackCallback = vi.fn().mockResolvedValue(null); // User rejected fallback
|
|
264
|
+
const mockFn = vi.fn(async () => {
|
|
265
|
+
const error = new Error('Rate limit exceeded');
|
|
266
|
+
error.status = 429;
|
|
267
|
+
throw error;
|
|
268
|
+
});
|
|
269
|
+
const promise = retryWithBackoff(mockFn, {
|
|
270
|
+
maxAttempts: 3,
|
|
271
|
+
initialDelayMs: 100,
|
|
272
|
+
onPersistent429: fallbackCallback,
|
|
273
|
+
authType: 'oauth-personal',
|
|
274
|
+
});
|
|
275
|
+
// Handle the promise properly to avoid unhandled rejections
|
|
276
|
+
const resultPromise = promise.catch((error) => error);
|
|
277
|
+
await vi.runAllTimersAsync();
|
|
278
|
+
const result = await resultPromise;
|
|
279
|
+
// Should fail with original error when fallback is rejected
|
|
280
|
+
expect(result).toBeInstanceOf(Error);
|
|
281
|
+
expect(result.message).toBe('Rate limit exceeded');
|
|
282
|
+
expect(fallbackCallback).toHaveBeenCalledWith('oauth-personal');
|
|
283
|
+
});
|
|
284
|
+
it('should handle mixed error types (only count consecutive 429s)', async () => {
|
|
285
|
+
const fallbackCallback = vi.fn().mockResolvedValue('gemini-2.5-flash');
|
|
286
|
+
let attempts = 0;
|
|
287
|
+
let fallbackOccurred = false;
|
|
288
|
+
const mockFn = vi.fn().mockImplementation(async () => {
|
|
289
|
+
attempts++;
|
|
290
|
+
if (fallbackOccurred) {
|
|
291
|
+
return 'success';
|
|
292
|
+
}
|
|
293
|
+
if (attempts === 1) {
|
|
294
|
+
// First attempt: 500 error (resets consecutive count)
|
|
295
|
+
const error = new Error('Server error');
|
|
296
|
+
error.status = 500;
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
// Remaining attempts: 429 errors
|
|
301
|
+
const error = new Error('Rate limit exceeded');
|
|
302
|
+
error.status = 429;
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
const promise = retryWithBackoff(mockFn, {
|
|
307
|
+
maxAttempts: 5,
|
|
308
|
+
initialDelayMs: 100,
|
|
309
|
+
onPersistent429: async (authType) => {
|
|
310
|
+
fallbackOccurred = true;
|
|
311
|
+
return await fallbackCallback(authType);
|
|
312
|
+
},
|
|
313
|
+
authType: 'oauth-personal',
|
|
314
|
+
});
|
|
315
|
+
await vi.runAllTimersAsync();
|
|
316
|
+
await expect(promise).resolves.toBe('success');
|
|
317
|
+
// Should trigger fallback after 2 consecutive 429s (attempts 2-3)
|
|
318
|
+
expect(fallbackCallback).toHaveBeenCalledWith('oauth-personal');
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
//# sourceMappingURL=retry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.test.js","sourceRoot":"","sources":["../../../src/utils/retry.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAOhD,wEAAwE;AACxE,MAAM,qBAAqB,GAAG,CAC5B,QAAgB,EAChB,eAAuB,SAAS,EAChC,EAAE;IACF,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;QACtB,QAAQ,EAAE,CAAC;QACX,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;YACzB,6BAA6B;YAC7B,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;YAC1E,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,0BAA0B;YAC9C,MAAM,KAAK,CAAC;QACd,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,oDAAoD;AACpD,MAAM,iBAAkB,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,mCAAmC;QACnC,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,6EAA6E;QAC7E,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,eAAe,EAAE,CAAC;QACrB,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACvC,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,EAAE;SACnB,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,yCAAyC;QAEvE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAExC,6DAA6D;QAC7D,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACvC,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,EAAE;SACnB,CAAC,CAAC;QAEH,+EAA+E;QAC/E,8EAA8E;QAC9E,0EAA0E;QAC1E,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CACtD,2BAA2B,CAC5B,CAAC;QAEF,oEAAoE;QACpE,uEAAuE;QACvE,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAE7B,2EAA2E;QAC3E,MAAM,gBAAgB,CAAC;QAEvB,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC9B,MAAM,IAAI,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,CAAC,KAAY,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,YAAY,iBAAiB,CAAC,CAAC;QAE5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACvC,WAAW;YACX,cAAc,EAAE,EAAE;SACnB,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC9B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,mBAAmB,CAAQ,CAAC;YACpD,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;YACnB,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACvC,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,EAAE;SACnB,CAAC,CAAC;QAEH,2DAA2D;QAC3D,MAAM,gBAAgB,GACpB,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAEvD,uDAAuD;QACvD,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAE7B,sBAAsB;QACtB,MAAM,gBAAgB,CAAC;QAEvB,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC9B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,aAAa,CAAQ,CAAC;YAC9C,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;YACnB,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACvC,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,EAAE;SACnB,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,aAAa,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAErD,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;YACvC,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,GAAG;YACnB,UAAU,EAAE,GAAG,EAAE,2CAA2C;SAC7D,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B;QACxE,MAAM,OAAO,CAAC;QAEd,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAW,CAAC,CAAC;QAEzE,oEAAoE;QACpE,+DAA+D;QAC/D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACjD,gFAAgF;QAChF,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,IAAI,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,aAAa,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAErD,wDAAwD;QACxD,MAAM,QAAQ,GAAG,GAAG,EAAE,CACpB,gBAAgB,CAAC,MAAM,EAAE;YACvB,WAAW,EAAE,CAAC,EAAE,+BAA+B;YAC/C,cAAc,EAAE,GAAG;YACnB,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QAEL,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC;QAC5B,2DAA2D;QAC3D,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7D,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,8CAA8C;QAC5E,MAAM,iBAAiB,CAAC;QAExB,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAChD,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAW,CAC5B,CAAC;QACF,aAAa,CAAC,SAAS,EAAE,CAAC,CAAC,+BAA+B;QAE1D,sEAAsE;QACtE,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,gCAAgC;QAEnE,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC;QAC5B,2DAA2D;QAC3D,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7D,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,+CAA+C;QAC7E,MAAM,iBAAiB,CAAC;QAExB,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CACjD,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAW,CAC5B,CAAC;QAEF,+DAA+D;QAC/D,wFAAwF;QACxF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,oCAAoC;YACpC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,8EAA8E;YAC9E,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QAED,wFAAwF;QACxF,CAAC,GAAG,aAAa,EAAE,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAClD,MAAM,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;YAC5C,MAAM,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACpD,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;YAC5F,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;YAEvE,IAAI,gBAAgB,GAAG,KAAK,CAAC;YAC7B,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE;gBACnD,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACtB,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;oBAC1D,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;oBACnB,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;gBACvC,WAAW,EAAE,CAAC;gBACd,cAAc,EAAE,GAAG;gBACnB,eAAe,EAAE,KAAK,EAAE,QAAiB,EAAE,EAAE;oBAC3C,gBAAgB,GAAG,IAAI,CAAC;oBACxB,OAAO,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC1C,CAAC;gBACD,QAAQ,EAAE,gBAAgB;aAC3B,CAAC,CAAC;YAEH,yCAAyC;YACzC,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAE7B,gCAAgC;YAChC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAE/C,oDAAoD;YACpD,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;YAEhE,oCAAoC;YACpC,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,wCAAwC;QACnF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAEjC,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;gBAC9B,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBAC1D,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;gBACnB,MAAM,KAAK,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;gBACvC,WAAW,EAAE,CAAC;gBACd,cAAc,EAAE,GAAG;gBACnB,eAAe,EAAE,gBAAgB;gBACjC,QAAQ,EAAE,gBAAgB;aAC3B,CAAC,CAAC;YAEH,4DAA4D;YAC5D,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;YACtD,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YAEnC,iDAAiD;YACjD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAEnD,kDAAkD;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;YACnF,IAAI,cAAc,GAAG,KAAK,CAAC;YAC3B,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE;gBAC7D,cAAc,GAAG,IAAI,CAAC;gBACtB,OAAO,kBAAkB,CAAC;YAC5B,CAAC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE;gBACnD,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;oBAC1D,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;oBACnB,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;gBACvC,WAAW,EAAE,CAAC;gBACd,cAAc,EAAE,GAAG;gBACnB,eAAe,EAAE,gBAAgB;gBACjC,QAAQ,EAAE,gBAAgB;aAC3B,CAAC,CAAC;YAEH,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAE7B,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC/C,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,yBAAyB;YAEnF,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;gBAC9B,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBAC1D,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;gBACnB,MAAM,KAAK,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;gBACvC,WAAW,EAAE,CAAC;gBACd,cAAc,EAAE,GAAG;gBACnB,eAAe,EAAE,gBAAgB;gBACjC,QAAQ,EAAE,gBAAgB;aAC3B,CAAC,CAAC;YAEH,4DAA4D;YAC5D,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;YACtD,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YAEnC,4DAA4D;YAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACnD,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;YAC7E,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;YACvE,IAAI,QAAQ,GAAG,CAAC,CAAC;YACjB,IAAI,gBAAgB,GAAG,KAAK,CAAC;YAE7B,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE;gBACnD,QAAQ,EAAE,CAAC;gBACX,IAAI,gBAAgB,EAAE,CAAC;oBACrB,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;oBACnB,sDAAsD;oBACtD,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;oBACnD,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;oBACnB,MAAM,KAAK,CAAC;gBACd,CAAC;qBAAM,CAAC;oBACN,iCAAiC;oBACjC,MAAM,KAAK,GAAc,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;oBAC1D,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;oBACnB,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE;gBACvC,WAAW,EAAE,CAAC;gBACd,cAAc,EAAE,GAAG;gBACnB,eAAe,EAAE,KAAK,EAAE,QAAiB,EAAE,EAAE;oBAC3C,gBAAgB,GAAG,IAAI,CAAC;oBACxB,OAAO,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC1C,CAAC;gBACD,QAAQ,EAAE,gBAAgB;aAC3B,CAAC,CAAC;YAEH,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAE7B,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAE/C,kEAAkE;YAClE,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Simple utility to validate objects against JSON Schemas
|
|
8
|
+
*/
|
|
9
|
+
export declare class SchemaValidator {
|
|
10
|
+
/**
|
|
11
|
+
* Validates data against a JSON schema
|
|
12
|
+
* @param schema JSON Schema to validate against
|
|
13
|
+
* @param data Data to validate
|
|
14
|
+
* @returns True if valid, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
static validate(schema: Record<string, unknown>, data: unknown): boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Simple utility to validate objects against JSON Schemas
|
|
8
|
+
*/
|
|
9
|
+
export class SchemaValidator {
|
|
10
|
+
/**
|
|
11
|
+
* Validates data against a JSON schema
|
|
12
|
+
* @param schema JSON Schema to validate against
|
|
13
|
+
* @param data Data to validate
|
|
14
|
+
* @returns True if valid, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
static validate(schema, data) {
|
|
17
|
+
// This is a simplified implementation
|
|
18
|
+
// In a real application, you would use a library like Ajv for proper validation
|
|
19
|
+
// Check for required fields
|
|
20
|
+
if (schema.required && Array.isArray(schema.required)) {
|
|
21
|
+
const required = schema.required;
|
|
22
|
+
const dataObj = data;
|
|
23
|
+
for (const field of required) {
|
|
24
|
+
if (dataObj[field] === undefined) {
|
|
25
|
+
console.error(`Missing required field: ${field}`);
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Check property types if properties are defined
|
|
31
|
+
if (schema.properties && typeof schema.properties === 'object') {
|
|
32
|
+
const properties = schema.properties;
|
|
33
|
+
const dataObj = data;
|
|
34
|
+
for (const [key, prop] of Object.entries(properties)) {
|
|
35
|
+
if (dataObj[key] !== undefined && prop.type) {
|
|
36
|
+
const expectedType = prop.type;
|
|
37
|
+
const actualType = Array.isArray(dataObj[key])
|
|
38
|
+
? 'array'
|
|
39
|
+
: typeof dataObj[key];
|
|
40
|
+
if (expectedType !== actualType) {
|
|
41
|
+
console.error(`Type mismatch for property "${key}": expected ${expectedType}, got ${actualType}`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=schemaValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemaValidator.js","sourceRoot":"","sources":["../../../src/utils/schemaValidator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,MAA+B,EAAE,IAAa;QAC5D,sCAAsC;QACtC,gFAAgF;QAEhF,4BAA4B;QAC5B,IAAI,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAoB,CAAC;YAC7C,MAAM,OAAO,GAAG,IAA+B,CAAC;YAEhD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;gBAC7B,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;oBACjC,OAAO,CAAC,KAAK,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAC;oBAClD,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QAED,iDAAiD;QACjD,IAAI,MAAM,CAAC,UAAU,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC/D,MAAM,UAAU,GAAG,MAAM,CAAC,UAA+C,CAAC;YAC1E,MAAM,OAAO,GAAG,IAA+B,CAAC;YAEhD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;gBACrD,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC;oBAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;wBAC5C,CAAC,CAAC,OAAO;wBACT,CAAC,CAAC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;oBAExB,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;wBAChC,OAAO,CAAC,KAAK,CACX,+BAA+B,GAAG,eAAe,YAAY,SAAS,UAAU,EAAE,CACnF,CAAC;wBACF,OAAO,KAAK,CAAC;oBACf,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/utils/session.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check if we should simulate a 429 error for the current request
|
|
8
|
+
*/
|
|
9
|
+
export declare function shouldSimulate429(authType?: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Reset the request counter (useful for tests)
|
|
12
|
+
*/
|
|
13
|
+
export declare function resetRequestCounter(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Disable 429 simulation after successful fallback
|
|
16
|
+
*/
|
|
17
|
+
export declare function disableSimulationAfterFallback(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Create a simulated 429 error response
|
|
20
|
+
*/
|
|
21
|
+
export declare function createSimulated429Error(): Error;
|
|
22
|
+
/**
|
|
23
|
+
* Reset simulation state when switching auth methods
|
|
24
|
+
*/
|
|
25
|
+
export declare function resetSimulationState(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Enable/disable 429 simulation programmatically (for tests)
|
|
28
|
+
*/
|
|
29
|
+
export declare function setSimulate429(enabled: boolean, afterRequests?: number, forAuthType?: string): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Testing utilities for simulating 429 errors in unit tests
|
|
8
|
+
*/
|
|
9
|
+
let requestCounter = 0;
|
|
10
|
+
let simulate429Enabled = false;
|
|
11
|
+
let simulate429AfterRequests = 0;
|
|
12
|
+
let simulate429ForAuthType;
|
|
13
|
+
let fallbackOccurred = false;
|
|
14
|
+
/**
|
|
15
|
+
* Check if we should simulate a 429 error for the current request
|
|
16
|
+
*/
|
|
17
|
+
export function shouldSimulate429(authType) {
|
|
18
|
+
if (!simulate429Enabled || fallbackOccurred) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// If auth type filter is set, only simulate for that auth type
|
|
22
|
+
if (simulate429ForAuthType && authType !== simulate429ForAuthType) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
requestCounter++;
|
|
26
|
+
// If afterRequests is set, only simulate after that many requests
|
|
27
|
+
if (simulate429AfterRequests > 0) {
|
|
28
|
+
return requestCounter > simulate429AfterRequests;
|
|
29
|
+
}
|
|
30
|
+
// Otherwise, simulate for every request
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reset the request counter (useful for tests)
|
|
35
|
+
*/
|
|
36
|
+
export function resetRequestCounter() {
|
|
37
|
+
requestCounter = 0;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Disable 429 simulation after successful fallback
|
|
41
|
+
*/
|
|
42
|
+
export function disableSimulationAfterFallback() {
|
|
43
|
+
fallbackOccurred = true;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a simulated 429 error response
|
|
47
|
+
*/
|
|
48
|
+
export function createSimulated429Error() {
|
|
49
|
+
const error = new Error('Rate limit exceeded (simulated)');
|
|
50
|
+
error.status = 429;
|
|
51
|
+
return error;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Reset simulation state when switching auth methods
|
|
55
|
+
*/
|
|
56
|
+
export function resetSimulationState() {
|
|
57
|
+
fallbackOccurred = false;
|
|
58
|
+
resetRequestCounter();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Enable/disable 429 simulation programmatically (for tests)
|
|
62
|
+
*/
|
|
63
|
+
export function setSimulate429(enabled, afterRequests = 0, forAuthType) {
|
|
64
|
+
simulate429Enabled = enabled;
|
|
65
|
+
simulate429AfterRequests = afterRequests;
|
|
66
|
+
simulate429ForAuthType = forAuthType;
|
|
67
|
+
fallbackOccurred = false; // Reset fallback state when simulation is re-enabled
|
|
68
|
+
resetRequestCounter();
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=testUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testUtils.js","sourceRoot":"","sources":["../../../src/utils/testUtils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AAEH,IAAI,cAAc,GAAG,CAAC,CAAC;AACvB,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAC/B,IAAI,wBAAwB,GAAG,CAAC,CAAC;AACjC,IAAI,sBAA0C,CAAC;AAC/C,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAiB;IACjD,IAAI,CAAC,kBAAkB,IAAI,gBAAgB,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,+DAA+D;IAC/D,IAAI,sBAAsB,IAAI,QAAQ,KAAK,sBAAsB,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,cAAc,EAAE,CAAC;IAEjB,kEAAkE;IAClE,IAAI,wBAAwB,GAAG,CAAC,EAAE,CAAC;QACjC,OAAO,cAAc,GAAG,wBAAwB,CAAC;IACnD,CAAC;IAED,wCAAwC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,cAAc,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,8BAA8B;IAC5C,gBAAgB,GAAG,IAAI,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,iCAAiC,CAExD,CAAC;IACF,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;IACnB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,gBAAgB,GAAG,KAAK,CAAC;IACzB,mBAAmB,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAgB,EAChB,aAAa,GAAG,CAAC,EACjB,WAAoB;IAEpB,kBAAkB,GAAG,OAAO,CAAC;IAC7B,wBAAwB,GAAG,aAAa,CAAC;IACzC,sBAAsB,GAAG,WAAW,CAAC;IACrC,gBAAgB,GAAG,KAAK,CAAC,CAAC,qDAAqD;IAC/E,mBAAmB,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves the installation ID from a file, creating it if it doesn't exist.
|
|
8
|
+
* This ID is used for unique user installation tracking.
|
|
9
|
+
* @returns A UUID string for the user.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getInstallationId(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Retrieves the obfuscated Google Account ID for the currently authenticated user.
|
|
14
|
+
* When OAuth is available, returns the user's cached Google Account ID. Otherwise, returns the installation ID.
|
|
15
|
+
* @returns A string ID for the user (Google Account ID if available, otherwise installation ID).
|
|
16
|
+
*/
|
|
17
|
+
export declare function getGoogleAccountId(): Promise<string>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import * as os from 'os';
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { randomUUID } from 'crypto';
|
|
10
|
+
import { GEMINI_DIR } from './paths.js';
|
|
11
|
+
const homeDir = os.homedir() ?? '';
|
|
12
|
+
const geminiDir = path.join(homeDir, GEMINI_DIR);
|
|
13
|
+
const installationIdFile = path.join(geminiDir, 'installation_id');
|
|
14
|
+
function ensureGeminiDirExists() {
|
|
15
|
+
if (!fs.existsSync(geminiDir)) {
|
|
16
|
+
fs.mkdirSync(geminiDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function readInstallationIdFromFile() {
|
|
20
|
+
if (fs.existsSync(installationIdFile)) {
|
|
21
|
+
const installationid = fs.readFileSync(installationIdFile, 'utf-8').trim();
|
|
22
|
+
return installationid || null;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function writeInstallationIdToFile(installationId) {
|
|
27
|
+
fs.writeFileSync(installationIdFile, installationId, 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves the installation ID from a file, creating it if it doesn't exist.
|
|
31
|
+
* This ID is used for unique user installation tracking.
|
|
32
|
+
* @returns A UUID string for the user.
|
|
33
|
+
*/
|
|
34
|
+
export function getInstallationId() {
|
|
35
|
+
try {
|
|
36
|
+
ensureGeminiDirExists();
|
|
37
|
+
let installationId = readInstallationIdFromFile();
|
|
38
|
+
if (!installationId) {
|
|
39
|
+
installationId = randomUUID();
|
|
40
|
+
writeInstallationIdToFile(installationId);
|
|
41
|
+
}
|
|
42
|
+
return installationId;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error('Error accessing installation ID file, generating ephemeral ID:', error);
|
|
46
|
+
return '123456789';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Retrieves the obfuscated Google Account ID for the currently authenticated user.
|
|
51
|
+
* When OAuth is available, returns the user's cached Google Account ID. Otherwise, returns the installation ID.
|
|
52
|
+
* @returns A string ID for the user (Google Account ID if available, otherwise installation ID).
|
|
53
|
+
*/
|
|
54
|
+
export async function getGoogleAccountId() {
|
|
55
|
+
// Try to get cached Google Account ID first
|
|
56
|
+
try {
|
|
57
|
+
// Dynamic import to avoid circular dependencies
|
|
58
|
+
const { getCachedGoogleAccountId } = await import('../code_assist/oauth2.js');
|
|
59
|
+
const googleAccountId = getCachedGoogleAccountId();
|
|
60
|
+
if (googleAccountId) {
|
|
61
|
+
return googleAccountId;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// If there's any error accessing Google Account ID, just return empty string
|
|
66
|
+
console.debug('Could not get cached Google Account ID:', error);
|
|
67
|
+
}
|
|
68
|
+
return '';
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=user_id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user_id.js","sourceRoot":"","sources":["../../../src/utils/user_id.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;AACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACjD,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAEnE,SAAS,qBAAqB;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B;IACjC,IAAI,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACtC,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3E,OAAO,cAAc,IAAI,IAAI,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,cAAsB;IACvD,EAAE,CAAC,aAAa,CAAC,kBAAkB,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,qBAAqB,EAAE,CAAC;QACxB,IAAI,cAAc,GAAG,0BAA0B,EAAE,CAAC;QAElD,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,cAAc,GAAG,UAAU,EAAE,CAAC;YAC9B,yBAAyB,CAAC,cAAc,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,gEAAgE,EAChE,KAAK,CACN,CAAC;QACF,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,4CAA4C;IAC5C,IAAI,CAAC;QACH,gDAAgD;QAChD,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAC/C,0BAA0B,CAC3B,CAAC;QACF,MAAM,eAAe,GAAG,wBAAwB,EAAE,CAAC;QACnD,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,eAAe,CAAC;QACzB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,6EAA6E;QAC7E,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|