@google/gemini-cli-core 0.5.0-nightly.20250908.4693137b → 0.5.0-preview
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 +3 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/src/config/config.d.ts +12 -3
- package/dist/src/config/config.js +46 -7
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +118 -1
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/storage.d.ts +1 -0
- package/dist/src/config/storage.js +4 -0
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +4 -0
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/core/baseLlmClient.d.ts +45 -0
- package/dist/src/core/baseLlmClient.js +88 -0
- package/dist/src/core/baseLlmClient.js.map +1 -0
- package/dist/src/core/baseLlmClient.test.js +190 -0
- package/dist/src/core/baseLlmClient.test.js.map +1 -0
- package/dist/src/core/client.d.ts +0 -5
- package/dist/src/core/client.js +41 -58
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +32 -39
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.js +5 -2
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +0 -5
- package/dist/src/core/geminiChat.js +23 -41
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +129 -5
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/fallback/handler.d.ts +7 -0
- package/dist/src/fallback/handler.js +51 -0
- package/dist/src/fallback/handler.js.map +1 -0
- package/dist/src/fallback/handler.test.d.ts +6 -0
- package/dist/src/fallback/handler.test.js +130 -0
- package/dist/src/fallback/handler.test.js.map +1 -0
- package/dist/src/fallback/types.d.ts +14 -0
- package/dist/src/fallback/types.js +7 -0
- package/dist/src/fallback/types.js.map +1 -0
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/ide/constants.d.ts +2 -0
- package/dist/src/ide/constants.js +2 -0
- package/dist/src/ide/constants.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +1 -1
- package/dist/src/ide/ide-client.js +61 -2
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +147 -1
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +1 -264
- package/dist/src/ide/ideContext.js +42 -31
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/ideContext.test.js +154 -24
- package/dist/src/ide/ideContext.test.js.map +1 -1
- package/dist/src/ide/process-utils.js +8 -1
- package/dist/src/ide/process-utils.js.map +1 -1
- package/dist/src/ide/types.d.ts +345 -0
- package/dist/src/ide/types.js +65 -0
- package/dist/src/ide/types.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +6 -2
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +30 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +15 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +5 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +11 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +1 -0
- package/dist/src/telemetry/constants.js +1 -0
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/high-water-mark-tracker.d.ts +43 -0
- package/dist/src/telemetry/high-water-mark-tracker.js +88 -0
- package/dist/src/telemetry/high-water-mark-tracker.js.map +1 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.d.ts +6 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.js +152 -0
- package/dist/src/telemetry/high-water-mark-tracker.test.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +2 -0
- package/dist/src/telemetry/index.js +2 -0
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +18 -1
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +38 -3
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/rate-limiter.d.ts +48 -0
- package/dist/src/telemetry/rate-limiter.js +100 -0
- package/dist/src/telemetry/rate-limiter.js.map +1 -0
- package/dist/src/telemetry/rate-limiter.test.d.ts +6 -0
- package/dist/src/telemetry/rate-limiter.test.js +207 -0
- package/dist/src/telemetry/rate-limiter.test.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +16 -1
- package/dist/src/telemetry/types.js +26 -0
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.js +5 -21
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +4 -0
- package/dist/src/tools/ripGrep.js +17 -2
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +57 -5
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/smart-edit.js +1 -1
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +5 -0
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +1 -0
- package/dist/src/utils/fileUtils.js +10 -0
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +17 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.d.ts +6 -0
- package/dist/src/utils/{flashFallback.integration.test.js → flashFallback.test.js} +31 -27
- package/dist/src/utils/flashFallback.test.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.d.ts +1 -0
- package/dist/src/utils/gitIgnoreParser.js +33 -24
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.d.ts +4 -3
- package/dist/src/utils/llm-edit-fixer.js +19 -10
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.d.ts +6 -0
- package/dist/src/utils/llm-edit-fixer.test.js +105 -0
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -0
- package/dist/src/utils/promptIdContext.d.ts +7 -0
- package/dist/src/utils/promptIdContext.js +8 -0
- package/dist/src/utils/promptIdContext.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist/google-gemini-cli-core-0.3.4.tgz +0 -0
- package/dist/src/utils/flashFallback.integration.test.js.map +0 -1
- /package/dist/src/{utils/flashFallback.integration.test.d.ts → core/baseLlmClient.test.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/config/storage.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/config/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC;AACpC,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAC/D,MAAM,CAAC,MAAM,UAAU,GAAG,kBAAkB,CAAC;AAC7C,MAAM,YAAY,GAAG,KAAK,CAAC;AAC3B,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,MAAM,OAAO,OAAO;IACD,SAAS,CAAS;IAEnC,YAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,kBAAkB;QACvB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,qBAAqB;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,uBAAuB,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,CAAC,qBAAqB;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,eAAe,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,CAAC,qBAAqB;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,iBAAiB,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,CAAC,qBAAqB;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,wBAAwB,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,CAAC,kBAAkB;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,uBAAuB;QAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,WAAW,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,gBAAgB;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,YAAY,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,eAAe;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,YAAY,CAAC,CAAC;IAC7D,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,iBAAiB;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,0BAA0B;QACxB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,iBAAiB;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,eAAe,CAAC,QAAgB;QACtC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC;IAED,aAAa;QACX,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,SAAS,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,wBAAwB;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,eAAe,CAAC,CAAC;IACzD,CAAC;IAED,qBAAqB;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,4BAA4B;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,aAAa,CAAC,CAAC;IAC5D,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,YAAY,CAAC,CAAC;IACtD,CAAC;IAED,uBAAuB;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,uBAAuB,CAAC,CAAC;IACrE,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,eAAe,CAAC,CAAC;IAC9D,CAAC;CACF"}
|
|
@@ -39,5 +39,9 @@ describe('Storage – additional helpers', () => {
|
|
|
39
39
|
const expected = path.join(os.homedir(), '.gemini', 'mcp-oauth-tokens.json');
|
|
40
40
|
expect(Storage.getMcpOAuthTokensPath()).toBe(expected);
|
|
41
41
|
});
|
|
42
|
+
it('getGlobalBinDir returns ~/.gemini/tmp/bin', () => {
|
|
43
|
+
const expected = path.join(os.homedir(), '.gemini', 'tmp', 'bin');
|
|
44
|
+
expect(Storage.getGlobalBinDir()).toBe(expected);
|
|
45
|
+
});
|
|
42
46
|
});
|
|
43
47
|
//# sourceMappingURL=storage.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../../src/config/storage.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACrC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAuB,CAAC;IAC3D,OAAO;QACL,GAAG,MAAM;QACT,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;KACnB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACrE,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;IAEzC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,EAAE,CAAC,OAAO,EAAE,EACZ,SAAS,EACT,uBAAuB,CACxB,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../../src/config/storage.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACrC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAuB,CAAC;IAC3D,OAAO;QACL,GAAG,MAAM;QACT,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;KACnB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACrE,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;IAEzC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,EAAE,CAAC,OAAO,EAAE,EACZ,SAAS,EACT,uBAAuB,CACxB,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAClE,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { Content, GenerateContentConfig, Part } from '@google/genai';
|
|
7
|
+
import type { Config } from '../config/config.js';
|
|
8
|
+
import type { ContentGenerator } from './contentGenerator.js';
|
|
9
|
+
/**
|
|
10
|
+
* Options for the generateJson utility function.
|
|
11
|
+
*/
|
|
12
|
+
export interface GenerateJsonOptions {
|
|
13
|
+
/** The input prompt or history. */
|
|
14
|
+
contents: Content[];
|
|
15
|
+
/** The required JSON schema for the output. */
|
|
16
|
+
schema: Record<string, unknown>;
|
|
17
|
+
/** The specific model to use for this task. */
|
|
18
|
+
model: string;
|
|
19
|
+
/**
|
|
20
|
+
* Task-specific system instructions.
|
|
21
|
+
* If omitted, no system instruction is sent.
|
|
22
|
+
*/
|
|
23
|
+
systemInstruction?: string | Part | Part[] | Content;
|
|
24
|
+
/**
|
|
25
|
+
* Overrides for generation configuration (e.g., temperature).
|
|
26
|
+
*/
|
|
27
|
+
config?: Omit<GenerateContentConfig, 'systemInstruction' | 'responseJsonSchema' | 'responseMimeType' | 'tools' | 'abortSignal'>;
|
|
28
|
+
/** Signal for cancellation. */
|
|
29
|
+
abortSignal: AbortSignal;
|
|
30
|
+
/**
|
|
31
|
+
* A unique ID for the prompt, used for logging/telemetry correlation.
|
|
32
|
+
*/
|
|
33
|
+
promptId: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A client dedicated to stateless, utility-focused LLM calls.
|
|
37
|
+
*/
|
|
38
|
+
export declare class BaseLlmClient {
|
|
39
|
+
private readonly contentGenerator;
|
|
40
|
+
private readonly config;
|
|
41
|
+
private readonly defaultUtilityConfig;
|
|
42
|
+
constructor(contentGenerator: ContentGenerator, config: Config);
|
|
43
|
+
generateJson(options: GenerateJsonOptions): Promise<Record<string, unknown>>;
|
|
44
|
+
private cleanJsonResponse;
|
|
45
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { getResponseText } from '../utils/partUtils.js';
|
|
7
|
+
import { reportError } from '../utils/errorReporting.js';
|
|
8
|
+
import { getErrorMessage } from '../utils/errors.js';
|
|
9
|
+
import { logMalformedJsonResponse } from '../telemetry/loggers.js';
|
|
10
|
+
import { MalformedJsonResponseEvent } from '../telemetry/types.js';
|
|
11
|
+
import { retryWithBackoff } from '../utils/retry.js';
|
|
12
|
+
/**
|
|
13
|
+
* A client dedicated to stateless, utility-focused LLM calls.
|
|
14
|
+
*/
|
|
15
|
+
export class BaseLlmClient {
|
|
16
|
+
contentGenerator;
|
|
17
|
+
config;
|
|
18
|
+
// Default configuration for utility tasks
|
|
19
|
+
defaultUtilityConfig = {
|
|
20
|
+
temperature: 0,
|
|
21
|
+
topP: 1,
|
|
22
|
+
};
|
|
23
|
+
constructor(contentGenerator, config) {
|
|
24
|
+
this.contentGenerator = contentGenerator;
|
|
25
|
+
this.config = config;
|
|
26
|
+
}
|
|
27
|
+
async generateJson(options) {
|
|
28
|
+
const { contents, schema, model, abortSignal, systemInstruction, promptId, } = options;
|
|
29
|
+
const requestConfig = {
|
|
30
|
+
abortSignal,
|
|
31
|
+
...this.defaultUtilityConfig,
|
|
32
|
+
...options.config,
|
|
33
|
+
...(systemInstruction && { systemInstruction }),
|
|
34
|
+
responseJsonSchema: schema,
|
|
35
|
+
responseMimeType: 'application/json',
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
const apiCall = () => this.contentGenerator.generateContent({
|
|
39
|
+
model,
|
|
40
|
+
config: requestConfig,
|
|
41
|
+
contents,
|
|
42
|
+
}, promptId);
|
|
43
|
+
const result = await retryWithBackoff(apiCall);
|
|
44
|
+
let text = getResponseText(result)?.trim();
|
|
45
|
+
if (!text) {
|
|
46
|
+
const error = new Error('API returned an empty response for generateJson.');
|
|
47
|
+
await reportError(error, 'Error in generateJson: API returned an empty response.', contents, 'generateJson-empty-response');
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
text = this.cleanJsonResponse(text, model);
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(text);
|
|
53
|
+
}
|
|
54
|
+
catch (parseError) {
|
|
55
|
+
const error = new Error(`Failed to parse API response as JSON: ${getErrorMessage(parseError)}`);
|
|
56
|
+
await reportError(parseError, 'Failed to parse JSON response from generateJson.', {
|
|
57
|
+
responseTextFailedToParse: text,
|
|
58
|
+
originalRequestContents: contents,
|
|
59
|
+
}, 'generateJson-parse');
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (abortSignal.aborted) {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
if (error instanceof Error &&
|
|
68
|
+
(error.message === 'API returned an empty response for generateJson.' ||
|
|
69
|
+
error.message.startsWith('Failed to parse API response as JSON:'))) {
|
|
70
|
+
// We perform this check so that we don't report these again.
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
await reportError(error, 'Error generating JSON content via API.', contents, 'generateJson-api');
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Failed to generate JSON content: ${getErrorMessage(error)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
cleanJsonResponse(text, model) {
|
|
79
|
+
const prefix = '```json';
|
|
80
|
+
const suffix = '```';
|
|
81
|
+
if (text.startsWith(prefix) && text.endsWith(suffix)) {
|
|
82
|
+
logMalformedJsonResponse(this.config, new MalformedJsonResponseEvent(model));
|
|
83
|
+
return text.substring(prefix.length, text.length - suffix.length).trim();
|
|
84
|
+
}
|
|
85
|
+
return text;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=baseLlmClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseLlmClient.js","sourceRoot":"","sources":["../../../src/core/baseLlmClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
|
|
7
|
+
import { BaseLlmClient } from './baseLlmClient.js';
|
|
8
|
+
import { AuthType } from './contentGenerator.js';
|
|
9
|
+
import { reportError } from '../utils/errorReporting.js';
|
|
10
|
+
import { logMalformedJsonResponse } from '../telemetry/loggers.js';
|
|
11
|
+
import { retryWithBackoff } from '../utils/retry.js';
|
|
12
|
+
import { MalformedJsonResponseEvent } from '../telemetry/types.js';
|
|
13
|
+
import { getErrorMessage } from '../utils/errors.js';
|
|
14
|
+
vi.mock('../utils/errorReporting.js');
|
|
15
|
+
vi.mock('../telemetry/loggers.js');
|
|
16
|
+
vi.mock('../utils/errors.js', async (importOriginal) => {
|
|
17
|
+
const actual = await importOriginal();
|
|
18
|
+
return {
|
|
19
|
+
...actual,
|
|
20
|
+
getErrorMessage: vi.fn((e) => (e instanceof Error ? e.message : String(e))),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
vi.mock('../utils/retry.js', () => ({
|
|
24
|
+
retryWithBackoff: vi.fn(async (fn) => await fn()),
|
|
25
|
+
}));
|
|
26
|
+
const mockGenerateContent = vi.fn();
|
|
27
|
+
const mockContentGenerator = {
|
|
28
|
+
generateContent: mockGenerateContent,
|
|
29
|
+
};
|
|
30
|
+
const mockConfig = {
|
|
31
|
+
getSessionId: vi.fn().mockReturnValue('test-session-id'),
|
|
32
|
+
getContentGeneratorConfig: vi
|
|
33
|
+
.fn()
|
|
34
|
+
.mockReturnValue({ authType: AuthType.USE_GEMINI }),
|
|
35
|
+
};
|
|
36
|
+
// Helper to create a mock GenerateContentResponse
|
|
37
|
+
const createMockResponse = (text) => ({
|
|
38
|
+
candidates: [{ content: { role: 'model', parts: [{ text }] }, index: 0 }],
|
|
39
|
+
});
|
|
40
|
+
describe('BaseLlmClient', () => {
|
|
41
|
+
let client;
|
|
42
|
+
let abortController;
|
|
43
|
+
let defaultOptions;
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
vi.clearAllMocks();
|
|
46
|
+
// Reset the mocked implementation for getErrorMessage for accurate error message assertions
|
|
47
|
+
vi.mocked(getErrorMessage).mockImplementation((e) => e instanceof Error ? e.message : String(e));
|
|
48
|
+
client = new BaseLlmClient(mockContentGenerator, mockConfig);
|
|
49
|
+
abortController = new AbortController();
|
|
50
|
+
defaultOptions = {
|
|
51
|
+
contents: [{ role: 'user', parts: [{ text: 'Give me a color.' }] }],
|
|
52
|
+
schema: { type: 'object', properties: { color: { type: 'string' } } },
|
|
53
|
+
model: 'test-model',
|
|
54
|
+
abortSignal: abortController.signal,
|
|
55
|
+
promptId: 'test-prompt-id',
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
abortController.abort();
|
|
60
|
+
});
|
|
61
|
+
describe('generateJson - Success Scenarios', () => {
|
|
62
|
+
it('should call generateContent with correct parameters, defaults, and utilize retry mechanism', async () => {
|
|
63
|
+
const mockResponse = createMockResponse('{"color": "blue"}');
|
|
64
|
+
mockGenerateContent.mockResolvedValue(mockResponse);
|
|
65
|
+
const result = await client.generateJson(defaultOptions);
|
|
66
|
+
expect(result).toEqual({ color: 'blue' });
|
|
67
|
+
// Ensure the retry mechanism was engaged
|
|
68
|
+
expect(retryWithBackoff).toHaveBeenCalledTimes(1);
|
|
69
|
+
// Validate the parameters passed to the underlying generator
|
|
70
|
+
expect(mockGenerateContent).toHaveBeenCalledTimes(1);
|
|
71
|
+
expect(mockGenerateContent).toHaveBeenCalledWith({
|
|
72
|
+
model: 'test-model',
|
|
73
|
+
contents: defaultOptions.contents,
|
|
74
|
+
config: {
|
|
75
|
+
abortSignal: defaultOptions.abortSignal,
|
|
76
|
+
temperature: 0,
|
|
77
|
+
topP: 1,
|
|
78
|
+
responseJsonSchema: defaultOptions.schema,
|
|
79
|
+
responseMimeType: 'application/json',
|
|
80
|
+
// Crucial: systemInstruction should NOT be in the config object if not provided
|
|
81
|
+
},
|
|
82
|
+
}, 'test-prompt-id');
|
|
83
|
+
});
|
|
84
|
+
it('should respect configuration overrides', async () => {
|
|
85
|
+
const mockResponse = createMockResponse('{"color": "red"}');
|
|
86
|
+
mockGenerateContent.mockResolvedValue(mockResponse);
|
|
87
|
+
const options = {
|
|
88
|
+
...defaultOptions,
|
|
89
|
+
config: { temperature: 0.8, topK: 10 },
|
|
90
|
+
};
|
|
91
|
+
await client.generateJson(options);
|
|
92
|
+
expect(mockGenerateContent).toHaveBeenCalledWith(expect.objectContaining({
|
|
93
|
+
config: expect.objectContaining({
|
|
94
|
+
temperature: 0.8,
|
|
95
|
+
topP: 1, // Default should remain if not overridden
|
|
96
|
+
topK: 10,
|
|
97
|
+
}),
|
|
98
|
+
}), expect.any(String));
|
|
99
|
+
});
|
|
100
|
+
it('should include system instructions when provided', async () => {
|
|
101
|
+
const mockResponse = createMockResponse('{"color": "green"}');
|
|
102
|
+
mockGenerateContent.mockResolvedValue(mockResponse);
|
|
103
|
+
const systemInstruction = 'You are a helpful assistant.';
|
|
104
|
+
const options = {
|
|
105
|
+
...defaultOptions,
|
|
106
|
+
systemInstruction,
|
|
107
|
+
};
|
|
108
|
+
await client.generateJson(options);
|
|
109
|
+
expect(mockGenerateContent).toHaveBeenCalledWith(expect.objectContaining({
|
|
110
|
+
config: expect.objectContaining({
|
|
111
|
+
systemInstruction,
|
|
112
|
+
}),
|
|
113
|
+
}), expect.any(String));
|
|
114
|
+
});
|
|
115
|
+
it('should use the provided promptId', async () => {
|
|
116
|
+
const mockResponse = createMockResponse('{"color": "yellow"}');
|
|
117
|
+
mockGenerateContent.mockResolvedValue(mockResponse);
|
|
118
|
+
const customPromptId = 'custom-id-123';
|
|
119
|
+
const options = {
|
|
120
|
+
...defaultOptions,
|
|
121
|
+
promptId: customPromptId,
|
|
122
|
+
};
|
|
123
|
+
await client.generateJson(options);
|
|
124
|
+
expect(mockGenerateContent).toHaveBeenCalledWith(expect.any(Object), customPromptId);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
describe('generateJson - Response Cleaning', () => {
|
|
128
|
+
it('should clean JSON wrapped in markdown backticks and log telemetry', async () => {
|
|
129
|
+
const malformedResponse = '```json\n{"color": "purple"}\n```';
|
|
130
|
+
mockGenerateContent.mockResolvedValue(createMockResponse(malformedResponse));
|
|
131
|
+
const result = await client.generateJson(defaultOptions);
|
|
132
|
+
expect(result).toEqual({ color: 'purple' });
|
|
133
|
+
expect(logMalformedJsonResponse).toHaveBeenCalledTimes(1);
|
|
134
|
+
expect(logMalformedJsonResponse).toHaveBeenCalledWith(mockConfig, expect.any(MalformedJsonResponseEvent));
|
|
135
|
+
// Validate the telemetry event content
|
|
136
|
+
const event = vi.mocked(logMalformedJsonResponse).mock
|
|
137
|
+
.calls[0][1];
|
|
138
|
+
expect(event.model).toBe('test-model');
|
|
139
|
+
});
|
|
140
|
+
it('should handle extra whitespace correctly without logging malformed telemetry', async () => {
|
|
141
|
+
const responseWithWhitespace = ' \n {"color": "orange"} \n';
|
|
142
|
+
mockGenerateContent.mockResolvedValue(createMockResponse(responseWithWhitespace));
|
|
143
|
+
const result = await client.generateJson(defaultOptions);
|
|
144
|
+
expect(result).toEqual({ color: 'orange' });
|
|
145
|
+
expect(logMalformedJsonResponse).not.toHaveBeenCalled();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('generateJson - Error Handling', () => {
|
|
149
|
+
it('should throw and report error for empty response', async () => {
|
|
150
|
+
mockGenerateContent.mockResolvedValue(createMockResponse(''));
|
|
151
|
+
// The final error message includes the prefix added by the client's outer catch block.
|
|
152
|
+
await expect(client.generateJson(defaultOptions)).rejects.toThrow('Failed to generate JSON content: API returned an empty response for generateJson.');
|
|
153
|
+
// Verify error reporting details
|
|
154
|
+
expect(reportError).toHaveBeenCalledTimes(1);
|
|
155
|
+
expect(reportError).toHaveBeenCalledWith(expect.any(Error), 'Error in generateJson: API returned an empty response.', defaultOptions.contents, 'generateJson-empty-response');
|
|
156
|
+
});
|
|
157
|
+
it('should throw and report error for invalid JSON syntax', async () => {
|
|
158
|
+
const invalidJson = '{"color": "blue"'; // missing closing brace
|
|
159
|
+
mockGenerateContent.mockResolvedValue(createMockResponse(invalidJson));
|
|
160
|
+
await expect(client.generateJson(defaultOptions)).rejects.toThrow(/^Failed to generate JSON content: Failed to parse API response as JSON:/);
|
|
161
|
+
expect(reportError).toHaveBeenCalledTimes(1);
|
|
162
|
+
expect(reportError).toHaveBeenCalledWith(expect.any(Error), 'Failed to parse JSON response from generateJson.', expect.objectContaining({ responseTextFailedToParse: invalidJson }), 'generateJson-parse');
|
|
163
|
+
});
|
|
164
|
+
it('should throw and report generic API errors', async () => {
|
|
165
|
+
const apiError = new Error('Service Unavailable (503)');
|
|
166
|
+
// Simulate the generator failing
|
|
167
|
+
mockGenerateContent.mockRejectedValue(apiError);
|
|
168
|
+
await expect(client.generateJson(defaultOptions)).rejects.toThrow('Failed to generate JSON content: Service Unavailable (503)');
|
|
169
|
+
// Verify generic error reporting
|
|
170
|
+
expect(reportError).toHaveBeenCalledTimes(1);
|
|
171
|
+
expect(reportError).toHaveBeenCalledWith(apiError, 'Error generating JSON content via API.', defaultOptions.contents, 'generateJson-api');
|
|
172
|
+
});
|
|
173
|
+
it('should throw immediately without reporting if aborted', async () => {
|
|
174
|
+
const abortError = new DOMException('Aborted', 'AbortError');
|
|
175
|
+
// Simulate abortion happening during the API call
|
|
176
|
+
mockGenerateContent.mockImplementation(() => {
|
|
177
|
+
abortController.abort(); // Ensure the signal is aborted when the service checks
|
|
178
|
+
throw abortError;
|
|
179
|
+
});
|
|
180
|
+
const options = {
|
|
181
|
+
...defaultOptions,
|
|
182
|
+
abortSignal: abortController.signal,
|
|
183
|
+
};
|
|
184
|
+
await expect(client.generateJson(options)).rejects.toThrow(abortError);
|
|
185
|
+
// Crucially, it should not report a cancellation as an application error
|
|
186
|
+
expect(reportError).not.toHaveBeenCalled();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
//# sourceMappingURL=baseLlmClient.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseLlmClient.test.js","sourceRoot":"","sources":["../../../src/core/baseLlmClient.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,QAAQ,EACR,EAAE,EACF,MAAM,EACN,EAAE,EACF,UAAU,EACV,SAAS,GAEV,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,aAAa,EAA4B,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;AACtC,EAAE,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AACnC,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACrD,MAAM,MAAM,GAAG,MAAM,cAAc,EAAuC,CAAC;IAC3E,OAAO;QACL,GAAG,MAAM;QACT,eAAe,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;KAC5E,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IAClC,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;CAClD,CAAC,CAAC,CAAC;AAEJ,MAAM,mBAAmB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAEpC,MAAM,oBAAoB,GAAG;IAC3B,eAAe,EAAE,mBAAmB;CACE,CAAC;AAEzC,MAAM,UAAU,GAAG;IACjB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,iBAAiB,CAAC;IACxD,yBAAyB,EAAE,EAAE;SAC1B,EAAE,EAAE;SACJ,eAAe,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC;CACzB,CAAC;AAE/B,kDAAkD;AAClD,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAA2B,EAAE,CACnE,CAAC;IACC,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;CAC1E,CAA4B,CAAC;AAEhC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,MAAqB,CAAC;IAC1B,IAAI,eAAgC,CAAC;IACrC,IAAI,cAAmC,CAAC;IAExC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,4FAA4F;QAC5F,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAClD,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAC3C,CAAC;QACF,MAAM,GAAG,IAAI,aAAa,CAAC,oBAAoB,EAAE,UAAU,CAAC,CAAC;QAC7D,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QACxC,cAAc,GAAG;YACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC;YACnE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;YACrE,KAAK,EAAE,YAAY;YACnB,WAAW,EAAE,eAAe,CAAC,MAAM;YACnC,QAAQ,EAAE,gBAAgB;SAC3B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,eAAe,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;YAC1G,MAAM,YAAY,GAAG,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;YAC7D,mBAAmB,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YAEpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAE1C,yCAAyC;YACzC,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAElD,6DAA6D;YAC7D,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAC9C;gBACE,KAAK,EAAE,YAAY;gBACnB,QAAQ,EAAE,cAAc,CAAC,QAAQ;gBACjC,MAAM,EAAE;oBACN,WAAW,EAAE,cAAc,CAAC,WAAW;oBACvC,WAAW,EAAE,CAAC;oBACd,IAAI,EAAE,CAAC;oBACP,kBAAkB,EAAE,cAAc,CAAC,MAAM;oBACzC,gBAAgB,EAAE,kBAAkB;oBACpC,gFAAgF;iBACjF;aACF,EACD,gBAAgB,CACjB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,YAAY,GAAG,kBAAkB,CAAC,kBAAkB,CAAC,CAAC;YAC5D,mBAAmB,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YAEpD,MAAM,OAAO,GAAwB;gBACnC,GAAG,cAAc;gBACjB,MAAM,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE;aACvC,CAAC;YAEF,MAAM,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEnC,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAC9C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC9B,WAAW,EAAE,GAAG;oBAChB,IAAI,EAAE,CAAC,EAAE,0CAA0C;oBACnD,IAAI,EAAE,EAAE;iBACT,CAAC;aACH,CAAC,EACF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CACnB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,YAAY,GAAG,kBAAkB,CAAC,oBAAoB,CAAC,CAAC;YAC9D,mBAAmB,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,iBAAiB,GAAG,8BAA8B,CAAC;YAEzD,MAAM,OAAO,GAAwB;gBACnC,GAAG,cAAc;gBACjB,iBAAiB;aAClB,CAAC;YAEF,MAAM,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEnC,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAC9C,MAAM,CAAC,gBAAgB,CAAC;gBACtB,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC;oBAC9B,iBAAiB;iBAClB,CAAC;aACH,CAAC,EACF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CACnB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,YAAY,GAAG,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;YAC/D,mBAAmB,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,cAAc,GAAG,eAAe,CAAC;YAEvC,MAAM,OAAO,GAAwB;gBACnC,GAAG,cAAc;gBACjB,QAAQ,EAAE,cAAc;aACzB,CAAC;YAEF,MAAM,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEnC,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAC9C,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAClB,cAAc,CACf,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;YACjF,MAAM,iBAAiB,GAAG,mCAAmC,CAAC;YAC9D,mBAAmB,CAAC,iBAAiB,CACnC,kBAAkB,CAAC,iBAAiB,CAAC,CACtC,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,wBAAwB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,wBAAwB,CAAC,CAAC,oBAAoB,CACnD,UAAU,EACV,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CACvC,CAAC;YACF,uCAAuC;YACvC,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,IAAI;iBACnD,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAA+B,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;YAC5F,MAAM,sBAAsB,GAAG,+BAA+B,CAAC;YAC/D,mBAAmB,CAAC,iBAAiB,CACnC,kBAAkB,CAAC,sBAAsB,CAAC,CAC3C,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,wBAAwB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;QAC7C,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,mBAAmB,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC;YAE9D,uFAAuF;YACvF,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC/D,mFAAmF,CACpF,CAAC;YAEF,iCAAiC;YACjC,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CACtC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EACjB,wDAAwD,EACxD,cAAc,CAAC,QAAQ,EACvB,6BAA6B,CAC9B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;YACrE,MAAM,WAAW,GAAG,kBAAkB,CAAC,CAAC,wBAAwB;YAChE,mBAAmB,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC;YAEvE,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC/D,yEAAyE,CAC1E,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CACtC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EACjB,kDAAkD,EAClD,MAAM,CAAC,gBAAgB,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,EACnE,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACxD,iCAAiC;YACjC,mBAAmB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAEhD,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC/D,4DAA4D,CAC7D,CAAC;YAEF,iCAAiC;YACjC,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CACtC,QAAQ,EACR,wCAAwC,EACxC,cAAc,CAAC,QAAQ,EACvB,kBAAkB,CACnB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;YACrE,MAAM,UAAU,GAAG,IAAI,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YAE7D,kDAAkD;YAClD,mBAAmB,CAAC,kBAAkB,CAAC,GAAG,EAAE;gBAC1C,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,uDAAuD;gBAChF,MAAM,UAAU,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG;gBACd,GAAG,cAAc;gBACjB,WAAW,EAAE,eAAe,CAAC,MAAM;aACpC,CAAC;YAEF,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAEvE,yEAAyE;YACzE,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -51,11 +51,6 @@ export declare class GeminiClient {
|
|
|
51
51
|
generateContent(contents: Content[], generationConfig: GenerateContentConfig, abortSignal: AbortSignal, model: string): Promise<GenerateContentResponse>;
|
|
52
52
|
generateEmbedding(texts: string[]): Promise<number[][]>;
|
|
53
53
|
tryCompressChat(prompt_id: string, force?: boolean): Promise<ChatCompressionInfo>;
|
|
54
|
-
/**
|
|
55
|
-
* Handles falling back to Flash model when persistent 429 errors occur for OAuth users.
|
|
56
|
-
* Uses a fallback handler if provided by the config; otherwise, returns null.
|
|
57
|
-
*/
|
|
58
|
-
private handleFlashFallback;
|
|
59
54
|
}
|
|
60
55
|
export declare const TEST_ONLY: {
|
|
61
56
|
COMPRESSION_PRESERVE_THRESHOLD: number;
|
package/dist/src/core/client.js
CHANGED
|
@@ -15,12 +15,12 @@ import { retryWithBackoff } from '../utils/retry.js';
|
|
|
15
15
|
import { getErrorMessage } from '../utils/errors.js';
|
|
16
16
|
import { isFunctionResponse } from '../utils/messageInspectors.js';
|
|
17
17
|
import { tokenLimit } from './tokenLimits.js';
|
|
18
|
-
import { AuthType } from './contentGenerator.js';
|
|
19
18
|
import { DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_THINKING_MODE, } from '../config/models.js';
|
|
20
19
|
import { LoopDetectionService } from '../services/loopDetectionService.js';
|
|
21
20
|
import { ideContext } from '../ide/ideContext.js';
|
|
22
21
|
import { logChatCompression, logNextSpeakerCheck, logMalformedJsonResponse, } from '../telemetry/loggers.js';
|
|
23
22
|
import { makeChatCompressionEvent, MalformedJsonResponseEvent, NextSpeakerCheckEvent, } from '../telemetry/types.js';
|
|
23
|
+
import { handleFallback } from '../fallback/handler.js';
|
|
24
24
|
export function isThinkingSupported(model) {
|
|
25
25
|
if (model.startsWith('gemini-2.5'))
|
|
26
26
|
return true;
|
|
@@ -406,6 +406,7 @@ export class GeminiClient {
|
|
|
406
406
|
return turn;
|
|
407
407
|
}
|
|
408
408
|
async generateJson(contents, schema, abortSignal, model, config = {}) {
|
|
409
|
+
let currentAttemptModel = model;
|
|
409
410
|
try {
|
|
410
411
|
const userMemory = this.config.getUserMemory();
|
|
411
412
|
const systemInstruction = getCoreSystemPrompt(userMemory);
|
|
@@ -414,18 +415,27 @@ export class GeminiClient {
|
|
|
414
415
|
...this.generateContentConfig,
|
|
415
416
|
...config,
|
|
416
417
|
};
|
|
417
|
-
const apiCall = () =>
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
418
|
+
const apiCall = () => {
|
|
419
|
+
const modelToUse = this.config.isInFallbackMode()
|
|
420
|
+
? DEFAULT_GEMINI_FLASH_MODEL
|
|
421
|
+
: model;
|
|
422
|
+
currentAttemptModel = modelToUse;
|
|
423
|
+
return this.getContentGeneratorOrFail().generateContent({
|
|
424
|
+
model: modelToUse,
|
|
425
|
+
config: {
|
|
426
|
+
...requestConfig,
|
|
427
|
+
systemInstruction,
|
|
428
|
+
responseJsonSchema: schema,
|
|
429
|
+
responseMimeType: 'application/json',
|
|
430
|
+
},
|
|
431
|
+
contents,
|
|
432
|
+
}, this.lastPromptId);
|
|
433
|
+
};
|
|
434
|
+
const onPersistent429Callback = async (authType, error) =>
|
|
435
|
+
// Pass the captured model to the centralized handler.
|
|
436
|
+
await handleFallback(this.config, currentAttemptModel, authType, error);
|
|
427
437
|
const result = await retryWithBackoff(apiCall, {
|
|
428
|
-
onPersistent429:
|
|
438
|
+
onPersistent429: onPersistent429Callback,
|
|
429
439
|
authType: this.config.getContentGeneratorConfig()?.authType,
|
|
430
440
|
});
|
|
431
441
|
let text = getResponseText(result);
|
|
@@ -437,7 +447,7 @@ export class GeminiClient {
|
|
|
437
447
|
const prefix = '```json';
|
|
438
448
|
const suffix = '```';
|
|
439
449
|
if (text.startsWith(prefix) && text.endsWith(suffix)) {
|
|
440
|
-
logMalformedJsonResponse(this.config, new MalformedJsonResponseEvent(
|
|
450
|
+
logMalformedJsonResponse(this.config, new MalformedJsonResponseEvent(currentAttemptModel));
|
|
441
451
|
text = text
|
|
442
452
|
.substring(prefix.length, text.length - suffix.length)
|
|
443
453
|
.trim();
|
|
@@ -467,6 +477,7 @@ export class GeminiClient {
|
|
|
467
477
|
}
|
|
468
478
|
}
|
|
469
479
|
async generateContent(contents, generationConfig, abortSignal, model) {
|
|
480
|
+
let currentAttemptModel = model;
|
|
470
481
|
const configToUse = {
|
|
471
482
|
...this.generateContentConfig,
|
|
472
483
|
...generationConfig,
|
|
@@ -479,13 +490,22 @@ export class GeminiClient {
|
|
|
479
490
|
...configToUse,
|
|
480
491
|
systemInstruction,
|
|
481
492
|
};
|
|
482
|
-
const apiCall = () =>
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
493
|
+
const apiCall = () => {
|
|
494
|
+
const modelToUse = this.config.isInFallbackMode()
|
|
495
|
+
? DEFAULT_GEMINI_FLASH_MODEL
|
|
496
|
+
: model;
|
|
497
|
+
currentAttemptModel = modelToUse;
|
|
498
|
+
return this.getContentGeneratorOrFail().generateContent({
|
|
499
|
+
model: modelToUse,
|
|
500
|
+
config: requestConfig,
|
|
501
|
+
contents,
|
|
502
|
+
}, this.lastPromptId);
|
|
503
|
+
};
|
|
504
|
+
const onPersistent429Callback = async (authType, error) =>
|
|
505
|
+
// Pass the captured model to the centralized handler.
|
|
506
|
+
await handleFallback(this.config, currentAttemptModel, authType, error);
|
|
487
507
|
const result = await retryWithBackoff(apiCall, {
|
|
488
|
-
onPersistent429:
|
|
508
|
+
onPersistent429: onPersistent429Callback,
|
|
489
509
|
authType: this.config.getContentGeneratorConfig()?.authType,
|
|
490
510
|
});
|
|
491
511
|
return result;
|
|
@@ -494,11 +514,11 @@ export class GeminiClient {
|
|
|
494
514
|
if (abortSignal.aborted) {
|
|
495
515
|
throw error;
|
|
496
516
|
}
|
|
497
|
-
await reportError(error, `Error generating content via API with model ${
|
|
517
|
+
await reportError(error, `Error generating content via API with model ${currentAttemptModel}.`, {
|
|
498
518
|
requestContents: contents,
|
|
499
519
|
requestConfig: configToUse,
|
|
500
520
|
}, 'generateContent-api');
|
|
501
|
-
throw new Error(`Failed to generate content with model ${
|
|
521
|
+
throw new Error(`Failed to generate content with model ${currentAttemptModel}: ${getErrorMessage(error)}`);
|
|
502
522
|
}
|
|
503
523
|
}
|
|
504
524
|
async generateEmbedding(texts) {
|
|
@@ -578,7 +598,6 @@ export class GeminiClient {
|
|
|
578
598
|
},
|
|
579
599
|
config: {
|
|
580
600
|
systemInstruction: { text: getCompressionPrompt() },
|
|
581
|
-
maxOutputTokens: originalTokenCount,
|
|
582
601
|
},
|
|
583
602
|
}, prompt_id);
|
|
584
603
|
const chat = await this.startChat([
|
|
@@ -629,42 +648,6 @@ export class GeminiClient {
|
|
|
629
648
|
compressionStatus: CompressionStatus.COMPRESSED,
|
|
630
649
|
};
|
|
631
650
|
}
|
|
632
|
-
/**
|
|
633
|
-
* Handles falling back to Flash model when persistent 429 errors occur for OAuth users.
|
|
634
|
-
* Uses a fallback handler if provided by the config; otherwise, returns null.
|
|
635
|
-
*/
|
|
636
|
-
async handleFlashFallback(authType, error) {
|
|
637
|
-
// Only handle fallback for OAuth users
|
|
638
|
-
if (authType !== AuthType.LOGIN_WITH_GOOGLE) {
|
|
639
|
-
return null;
|
|
640
|
-
}
|
|
641
|
-
const currentModel = this.config.getModel();
|
|
642
|
-
const fallbackModel = DEFAULT_GEMINI_FLASH_MODEL;
|
|
643
|
-
// Don't fallback if already using Flash model
|
|
644
|
-
if (currentModel === fallbackModel) {
|
|
645
|
-
return null;
|
|
646
|
-
}
|
|
647
|
-
// Check if config has a fallback handler (set by CLI package)
|
|
648
|
-
const fallbackHandler = this.config.flashFallbackHandler;
|
|
649
|
-
if (typeof fallbackHandler === 'function') {
|
|
650
|
-
try {
|
|
651
|
-
const accepted = await fallbackHandler(currentModel, fallbackModel, error);
|
|
652
|
-
if (accepted !== false && accepted !== null) {
|
|
653
|
-
this.config.setModel(fallbackModel);
|
|
654
|
-
this.config.setFallbackMode(true);
|
|
655
|
-
return fallbackModel;
|
|
656
|
-
}
|
|
657
|
-
// Check if the model was switched manually in the handler
|
|
658
|
-
if (this.config.getModel() === fallbackModel) {
|
|
659
|
-
return null; // Model was switched but don't continue with current prompt
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
catch (error) {
|
|
663
|
-
console.warn('Flash fallback handler failed:', error);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
return null;
|
|
667
|
-
}
|
|
668
651
|
}
|
|
669
652
|
export const TEST_ONLY = {
|
|
670
653
|
COMPRESSION_PRESERVE_THRESHOLD,
|