@google/gemini-cli-core 0.11.0 → 0.11.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/dist/google-gemini-cli-core-0.11.0.tgz +0 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/utils/errorParsing.d.ts +1 -1
- package/dist/src/utils/errorParsing.js +5 -33
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +0 -88
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +26 -45
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/googleErrors.d.ts +104 -0
- package/dist/src/utils/googleErrors.js +152 -0
- package/dist/src/utils/googleErrors.js.map +1 -0
- package/dist/src/utils/googleErrors.test.d.ts +6 -0
- package/dist/src/utils/googleErrors.test.js +301 -0
- package/dist/src/utils/googleErrors.test.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.d.ts +35 -0
- package/dist/src/utils/googleQuotaErrors.js +131 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
- package/dist/src/utils/googleQuotaErrors.test.js +281 -0
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
- package/dist/src/utils/quotaErrorDetection.d.ts +0 -2
- package/dist/src/utils/quotaErrorDetection.js +0 -46
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/retry.js +41 -145
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +31 -110
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
Binary file
|
package/dist/index.d.ts
CHANGED
|
@@ -15,3 +15,5 @@ export { makeFakeConfig } from './src/test-utils/config.js';
|
|
|
15
15
|
export * from './src/utils/pathReader.js';
|
|
16
16
|
export { ClearcutLogger } from './src/telemetry/clearcut-logger/clearcut-logger.js';
|
|
17
17
|
export { logModelSlashCommand } from './src/telemetry/loggers.js';
|
|
18
|
+
export * from './src/utils/googleQuotaErrors.js';
|
|
19
|
+
export type { GoogleApiError } from './src/utils/googleErrors.js';
|
package/dist/index.js
CHANGED
|
@@ -15,4 +15,5 @@ export { makeFakeConfig } from './src/test-utils/config.js';
|
|
|
15
15
|
export * from './src/utils/pathReader.js';
|
|
16
16
|
export { ClearcutLogger } from './src/telemetry/clearcut-logger/clearcut-logger.js';
|
|
17
17
|
export { logModelSlashCommand } from './src/telemetry/loggers.js';
|
|
18
|
+
export * from './src/utils/googleQuotaErrors.js';
|
|
18
19
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,0BAA0B,EAC1B,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,yBAAyB,GAI1B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,kCAAkC,EAClC,sCAAsC,GACvC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,0BAA0B,EAC1B,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,yBAAyB,GAI1B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,kCAAkC,EAClC,sCAAsC,GACvC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,cAAc,kCAAkC,CAAC"}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
export declare const GIT_COMMIT_INFO = "
|
|
7
|
-
export declare const CLI_VERSION = "0.11.
|
|
6
|
+
export declare const GIT_COMMIT_INFO = "d9f6cebe";
|
|
7
|
+
export declare const CLI_VERSION = "0.11.1";
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// This file is auto-generated by the build script (scripts/generate-git-commit-info.js)
|
|
7
7
|
// Do not edit this file manually.
|
|
8
|
-
export const GIT_COMMIT_INFO = '
|
|
9
|
-
export const CLI_VERSION = '0.11.
|
|
8
|
+
export const GIT_COMMIT_INFO = 'd9f6cebe';
|
|
9
|
+
export const CLI_VERSION = '0.11.1';
|
|
10
10
|
//# sourceMappingURL=git-commit.js.map
|
package/dist/src/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export * from './utils/gitIgnoreParser.js';
|
|
|
37
37
|
export * from './utils/gitUtils.js';
|
|
38
38
|
export * from './utils/editor.js';
|
|
39
39
|
export * from './utils/quotaErrorDetection.js';
|
|
40
|
+
export * from './utils/googleQuotaErrors.js';
|
|
40
41
|
export * from './utils/fileUtils.js';
|
|
41
42
|
export * from './utils/retry.js';
|
|
42
43
|
export * from './utils/shell-utils.js';
|
package/dist/src/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export * from './utils/gitIgnoreParser.js';
|
|
|
40
40
|
export * from './utils/gitUtils.js';
|
|
41
41
|
export * from './utils/editor.js';
|
|
42
42
|
export * from './utils/quotaErrorDetection.js';
|
|
43
|
+
export * from './utils/googleQuotaErrors.js';
|
|
43
44
|
export * from './utils/fileUtils.js';
|
|
44
45
|
export * from './utils/retry.js';
|
|
45
46
|
export * from './utils/shell-utils.js';
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { UserTierId } from '../code_assist/types.js';
|
|
6
|
+
import type { UserTierId } from '../code_assist/types.js';
|
|
7
7
|
import { AuthType } from '../core/contentGenerator.js';
|
|
8
8
|
export declare function parseAndFormatApiError(error: unknown, authType?: AuthType, userTier?: UserTierId, currentModel?: string, fallbackModel?: string): string;
|
|
@@ -3,42 +3,14 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { UserTierId } from '../code_assist/types.js';
|
|
6
|
+
import { isApiError, isStructuredError } from './quotaErrorDetection.js';
|
|
7
|
+
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
|
9
8
|
import { AuthType } from '../core/contentGenerator.js';
|
|
10
|
-
// Free Tier message functions
|
|
11
|
-
const getRateLimitErrorMessageGoogleFree = (fallbackModel = DEFAULT_GEMINI_FLASH_MODEL) => `\nPossible quota limitations in place or slow response times detected. Switching to the ${fallbackModel} model for the rest of this session.`;
|
|
12
|
-
const getRateLimitErrorMessageGoogleProQuotaFree = (currentModel = DEFAULT_GEMINI_MODEL, fallbackModel = DEFAULT_GEMINI_FLASH_MODEL) => `\nYou have reached your daily ${currentModel} quota limit. You will be switched to the ${fallbackModel} model for the rest of this session. To increase your limits, upgrade to get higher limits at https://goo.gle/set-up-gemini-code-assist, or use /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`;
|
|
13
|
-
const getRateLimitErrorMessageGoogleGenericQuotaFree = () => `\nYou have reached your daily quota limit. To increase your limits, upgrade to get higher limits at https://goo.gle/set-up-gemini-code-assist, or use /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`;
|
|
14
|
-
// Legacy/Standard Tier message functions
|
|
15
|
-
const getRateLimitErrorMessageGooglePaid = (fallbackModel = DEFAULT_GEMINI_FLASH_MODEL) => `\nPossible quota limitations in place or slow response times detected. Switching to the ${fallbackModel} model for the rest of this session. We appreciate you for choosing Gemini Code Assist and the Gemini CLI.`;
|
|
16
|
-
const getRateLimitErrorMessageGoogleProQuotaPaid = (currentModel = DEFAULT_GEMINI_MODEL, fallbackModel = DEFAULT_GEMINI_FLASH_MODEL) => `\nYou have reached your daily ${currentModel} quota limit. You will be switched to the ${fallbackModel} model for the rest of this session. We appreciate you for choosing Gemini Code Assist and the Gemini CLI. To continue accessing the ${currentModel} model today, consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`;
|
|
17
|
-
const getRateLimitErrorMessageGoogleGenericQuotaPaid = (currentModel = DEFAULT_GEMINI_MODEL) => `\nYou have reached your daily quota limit. We appreciate you for choosing Gemini Code Assist and the Gemini CLI. To continue accessing the ${currentModel} model today, consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`;
|
|
18
9
|
const RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI = '\nPlease wait and try again later. To increase your limits, request a quota increase through AI Studio, or switch to another /auth method';
|
|
19
10
|
const RATE_LIMIT_ERROR_MESSAGE_VERTEX = '\nPlease wait and try again later. To increase your limits, request a quota increase through Vertex, or switch to another /auth method';
|
|
20
11
|
const getRateLimitErrorMessageDefault = (fallbackModel = DEFAULT_GEMINI_FLASH_MODEL) => `\nPossible quota limitations in place or slow response times detected. Switching to the ${fallbackModel} model for the rest of this session.`;
|
|
21
|
-
function getRateLimitMessage(authType,
|
|
12
|
+
function getRateLimitMessage(authType, fallbackModel) {
|
|
22
13
|
switch (authType) {
|
|
23
|
-
case AuthType.LOGIN_WITH_GOOGLE: {
|
|
24
|
-
// Determine if user is on a paid tier (Legacy or Standard) - default to FREE if not specified
|
|
25
|
-
const isPaidTier = userTier === UserTierId.LEGACY || userTier === UserTierId.STANDARD;
|
|
26
|
-
if (isProQuotaExceededError(error)) {
|
|
27
|
-
return isPaidTier
|
|
28
|
-
? getRateLimitErrorMessageGoogleProQuotaPaid(currentModel || DEFAULT_GEMINI_MODEL, fallbackModel)
|
|
29
|
-
: getRateLimitErrorMessageGoogleProQuotaFree(currentModel || DEFAULT_GEMINI_MODEL, fallbackModel);
|
|
30
|
-
}
|
|
31
|
-
else if (isGenericQuotaExceededError(error)) {
|
|
32
|
-
return isPaidTier
|
|
33
|
-
? getRateLimitErrorMessageGoogleGenericQuotaPaid(currentModel || DEFAULT_GEMINI_MODEL)
|
|
34
|
-
: getRateLimitErrorMessageGoogleGenericQuotaFree();
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
return isPaidTier
|
|
38
|
-
? getRateLimitErrorMessageGooglePaid(fallbackModel)
|
|
39
|
-
: getRateLimitErrorMessageGoogleFree(fallbackModel);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
14
|
case AuthType.USE_GEMINI:
|
|
43
15
|
return RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI;
|
|
44
16
|
case AuthType.USE_VERTEX_AI:
|
|
@@ -51,7 +23,7 @@ export function parseAndFormatApiError(error, authType, userTier, currentModel,
|
|
|
51
23
|
if (isStructuredError(error)) {
|
|
52
24
|
let text = `[API Error: ${error.message}]`;
|
|
53
25
|
if (error.status === 429) {
|
|
54
|
-
text += getRateLimitMessage(authType,
|
|
26
|
+
text += getRateLimitMessage(authType, fallbackModel);
|
|
55
27
|
}
|
|
56
28
|
return text;
|
|
57
29
|
}
|
|
@@ -78,7 +50,7 @@ export function parseAndFormatApiError(error, authType, userTier, currentModel,
|
|
|
78
50
|
}
|
|
79
51
|
let text = `[API Error: ${finalMessage} (Status: ${parsedError.error.status})]`;
|
|
80
52
|
if (parsedError.error.code === 429) {
|
|
81
|
-
text += getRateLimitMessage(authType,
|
|
53
|
+
text += getRateLimitMessage(authType, fallbackModel);
|
|
82
54
|
}
|
|
83
55
|
return text;
|
|
84
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorParsing.js","sourceRoot":"","sources":["../../../src/utils/errorParsing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"errorParsing.js","sourceRoot":"","sources":["../../../src/utils/errorParsing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,MAAM,mCAAmC,GACvC,2IAA2I,CAAC;AAC9I,MAAM,+BAA+B,GACnC,wIAAwI,CAAC;AAC3I,MAAM,+BAA+B,GAAG,CACtC,gBAAwB,0BAA0B,EAClD,EAAE,CACF,2FAA2F,aAAa,sCAAsC,CAAC;AAEjJ,SAAS,mBAAmB,CAC1B,QAAmB,EACnB,aAAsB;IAEtB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,UAAU;YACtB,OAAO,mCAAmC,CAAC;QAC7C,KAAK,QAAQ,CAAC,aAAa;YACzB,OAAO,+BAA+B,CAAC;QACzC;YACE,OAAO,+BAA+B,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAc,EACd,QAAmB,EACnB,QAAqB,EACrB,YAAqB,EACrB,aAAsB;IAEtB,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,IAAI,IAAI,GAAG,eAAe,KAAK,CAAC,OAAO,GAAG,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACzB,IAAI,IAAI,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gEAAgE;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACrB,OAAO,eAAe,KAAK,GAAG,CAAC,CAAC,kCAAkC;QACpE,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAY,CAAC;YACtD,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC5B,IAAI,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC;gBAC7C,IAAI,CAAC;oBACH,8DAA8D;oBAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAY,CAAC;oBACxD,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;wBAC5B,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC;oBAC3C,CAAC;gBACH,CAAC;gBAAC,OAAO,EAAE,EAAE,CAAC;oBACZ,kEAAkE;gBACpE,CAAC;gBACD,IAAI,IAAI,GAAG,eAAe,YAAY,aAAa,WAAW,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC;gBAChF,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;oBACnC,IAAI,IAAI,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;gBACvD,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,kEAAkE;QACpE,CAAC;QACD,OAAO,eAAe,KAAK,GAAG,CAAC;IACjC,CAAC;IAED,OAAO,yCAAyC,CAAC;AACnD,CAAC"}
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect } from 'vitest';
|
|
7
7
|
import { parseAndFormatApiError } from './errorParsing.js';
|
|
8
|
-
import { isProQuotaExceededError } from './quotaErrorDetection.js';
|
|
9
8
|
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
|
10
|
-
import { UserTierId } from '../code_assist/types.js';
|
|
11
9
|
import { AuthType } from '../core/contentGenerator.js';
|
|
12
10
|
describe('parseAndFormatApiError', () => {
|
|
13
11
|
const vertexMessage = 'request a quota increase through Vertex';
|
|
@@ -23,12 +21,6 @@ describe('parseAndFormatApiError', () => {
|
|
|
23
21
|
expect(result).toContain('[API Error: Rate limit exceeded');
|
|
24
22
|
expect(result).toContain('Possible quota limitations in place or slow response times detected. Switching to the gemini-2.5-flash model');
|
|
25
23
|
});
|
|
26
|
-
it('should format a 429 API error with the personal message', () => {
|
|
27
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
|
|
28
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
29
|
-
expect(result).toContain('[API Error: Rate limit exceeded');
|
|
30
|
-
expect(result).toContain('Possible quota limitations in place or slow response times detected. Switching to the gemini-2.5-flash model');
|
|
31
|
-
});
|
|
32
24
|
it('should format a 429 API error with the vertex message', () => {
|
|
33
25
|
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
|
|
34
26
|
const result = parseAndFormatApiError(errorMessage, AuthType.USE_VERTEX_AI);
|
|
@@ -88,85 +80,5 @@ describe('parseAndFormatApiError', () => {
|
|
|
88
80
|
const expected = '[API Error: An unknown error occurred.]';
|
|
89
81
|
expect(parseAndFormatApiError(error)).toBe(expected);
|
|
90
82
|
});
|
|
91
|
-
it('should format a 429 API error with Pro quota exceeded message for Google auth (Free tier)', () => {
|
|
92
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
93
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
94
|
-
expect(result).toContain("[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'");
|
|
95
|
-
expect(result).toContain('You have reached your daily gemini-2.5-pro quota limit');
|
|
96
|
-
expect(result).toContain('upgrade to get higher limits');
|
|
97
|
-
});
|
|
98
|
-
it('should format a regular 429 API error with standard message for Google auth', () => {
|
|
99
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
|
|
100
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
101
|
-
expect(result).toContain('[API Error: Rate limit exceeded');
|
|
102
|
-
expect(result).toContain('Possible quota limitations in place or slow response times detected. Switching to the gemini-2.5-flash model');
|
|
103
|
-
expect(result).not.toContain('You have reached your daily gemini-2.5-pro quota limit');
|
|
104
|
-
});
|
|
105
|
-
it('should format a 429 API error with generic quota exceeded message for Google auth', () => {
|
|
106
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'GenerationRequests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
107
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
108
|
-
expect(result).toContain("[API Error: Quota exceeded for quota metric 'GenerationRequests'");
|
|
109
|
-
expect(result).toContain('You have reached your daily quota limit');
|
|
110
|
-
expect(result).not.toContain('You have reached your daily Gemini 2.5 Pro quota limit');
|
|
111
|
-
});
|
|
112
|
-
it('should prioritize Pro quota message over generic quota message for Google auth', () => {
|
|
113
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
114
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
115
|
-
expect(result).toContain("[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'");
|
|
116
|
-
expect(result).toContain('You have reached your daily gemini-2.5-pro quota limit');
|
|
117
|
-
expect(result).not.toContain('You have reached your daily quota limit');
|
|
118
|
-
});
|
|
119
|
-
it('should format a 429 API error with Pro quota exceeded message for Google auth (Standard tier)', () => {
|
|
120
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
121
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, UserTierId.STANDARD, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
122
|
-
expect(result).toContain("[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'");
|
|
123
|
-
expect(result).toContain('You have reached your daily gemini-2.5-pro quota limit');
|
|
124
|
-
expect(result).toContain('We appreciate you for choosing Gemini Code Assist and the Gemini CLI');
|
|
125
|
-
expect(result).not.toContain('upgrade to get higher limits');
|
|
126
|
-
});
|
|
127
|
-
it('should format a 429 API error with Pro quota exceeded message for Google auth (Legacy tier)', () => {
|
|
128
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
129
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, UserTierId.LEGACY, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
130
|
-
expect(result).toContain("[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'");
|
|
131
|
-
expect(result).toContain('You have reached your daily gemini-2.5-pro quota limit');
|
|
132
|
-
expect(result).toContain('We appreciate you for choosing Gemini Code Assist and the Gemini CLI');
|
|
133
|
-
expect(result).not.toContain('upgrade to get higher limits');
|
|
134
|
-
});
|
|
135
|
-
it('should handle different Gemini 2.5 version strings in Pro quota exceeded errors', () => {
|
|
136
|
-
const errorMessage25 = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
137
|
-
const errorMessagePreview = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5-preview Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
138
|
-
const result25 = parseAndFormatApiError(errorMessage25, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
139
|
-
const resultPreview = parseAndFormatApiError(errorMessagePreview, AuthType.LOGIN_WITH_GOOGLE, undefined, 'gemini-2.5-preview-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
140
|
-
expect(result25).toContain('You have reached your daily gemini-2.5-pro quota limit');
|
|
141
|
-
expect(resultPreview).toContain('You have reached your daily gemini-2.5-preview-pro quota limit');
|
|
142
|
-
expect(result25).toContain('upgrade to get higher limits');
|
|
143
|
-
expect(resultPreview).toContain('upgrade to get higher limits');
|
|
144
|
-
});
|
|
145
|
-
it('should not match non-Pro models with similar version strings', () => {
|
|
146
|
-
// Test that Flash models with similar version strings don't match
|
|
147
|
-
expect(isProQuotaExceededError("Quota exceeded for quota metric 'Gemini 2.5 Flash Requests' and limit")).toBe(false);
|
|
148
|
-
expect(isProQuotaExceededError("Quota exceeded for quota metric 'Gemini 2.5-preview Flash Requests' and limit")).toBe(false);
|
|
149
|
-
// Test other model types
|
|
150
|
-
expect(isProQuotaExceededError("Quota exceeded for quota metric 'Gemini 2.5 Ultra Requests' and limit")).toBe(false);
|
|
151
|
-
expect(isProQuotaExceededError("Quota exceeded for quota metric 'Gemini 2.5 Standard Requests' and limit")).toBe(false);
|
|
152
|
-
// Test generic quota messages
|
|
153
|
-
expect(isProQuotaExceededError("Quota exceeded for quota metric 'GenerationRequests' and limit")).toBe(false);
|
|
154
|
-
expect(isProQuotaExceededError("Quota exceeded for quota metric 'EmbeddingRequests' and limit")).toBe(false);
|
|
155
|
-
});
|
|
156
|
-
it('should format a generic quota exceeded message for Google auth (Standard tier)', () => {
|
|
157
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'GenerationRequests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
|
|
158
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, UserTierId.STANDARD, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
159
|
-
expect(result).toContain("[API Error: Quota exceeded for quota metric 'GenerationRequests'");
|
|
160
|
-
expect(result).toContain('You have reached your daily quota limit');
|
|
161
|
-
expect(result).toContain('We appreciate you for choosing Gemini Code Assist and the Gemini CLI');
|
|
162
|
-
expect(result).not.toContain('upgrade to get higher limits');
|
|
163
|
-
});
|
|
164
|
-
it('should format a regular 429 API error with standard message for Google auth (Standard tier)', () => {
|
|
165
|
-
const errorMessage = 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
|
|
166
|
-
const result = parseAndFormatApiError(errorMessage, AuthType.LOGIN_WITH_GOOGLE, UserTierId.STANDARD, 'gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
167
|
-
expect(result).toContain('[API Error: Rate limit exceeded');
|
|
168
|
-
expect(result).toContain('We appreciate you for choosing Gemini Code Assist and the Gemini CLI');
|
|
169
|
-
expect(result).not.toContain('upgrade to get higher limits');
|
|
170
|
-
});
|
|
171
83
|
});
|
|
172
84
|
//# sourceMappingURL=errorParsing.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorParsing.test.js","sourceRoot":"","sources":["../../../src/utils/errorParsing.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"errorParsing.test.js","sourceRoot":"","sources":["../../../src/utils/errorParsing.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
7
7
|
import { Config } from '../config/config.js';
|
|
8
8
|
import fs from 'node:fs';
|
|
9
|
-
import { setSimulate429, disableSimulationAfterFallback, shouldSimulate429,
|
|
9
|
+
import { setSimulate429, disableSimulationAfterFallback, shouldSimulate429, resetRequestCounter, } from './testUtils.js';
|
|
10
10
|
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
|
11
11
|
import { retryWithBackoff } from './retry.js';
|
|
12
12
|
import { AuthType } from '../core/contentGenerator.js';
|
|
13
|
+
import { TerminalQuotaError } from './googleQuotaErrors.js';
|
|
13
14
|
vi.mock('node:fs');
|
|
14
15
|
// Update the description to reflect that this tests the retry utility's integration
|
|
15
16
|
describe('Retry Utility Fallback Integration', () => {
|
|
16
17
|
let config;
|
|
18
|
+
let mockGoogleApiError;
|
|
17
19
|
beforeEach(() => {
|
|
18
20
|
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
19
21
|
vi.mocked(fs.statSync).mockReturnValue({
|
|
@@ -26,6 +28,11 @@ describe('Retry Utility Fallback Integration', () => {
|
|
|
26
28
|
cwd: '/test',
|
|
27
29
|
model: 'gemini-2.5-pro',
|
|
28
30
|
});
|
|
31
|
+
mockGoogleApiError = {
|
|
32
|
+
code: 429,
|
|
33
|
+
message: 'mock error',
|
|
34
|
+
details: [],
|
|
35
|
+
};
|
|
29
36
|
// Reset simulation state for each test
|
|
30
37
|
setSimulate429(false);
|
|
31
38
|
resetRequestCounter();
|
|
@@ -37,75 +44,49 @@ describe('Retry Utility Fallback Integration', () => {
|
|
|
37
44
|
// Use the generalized setter
|
|
38
45
|
config.setFallbackModelHandler(fallbackHandler);
|
|
39
46
|
// Call the handler directly via the config property
|
|
40
|
-
const result = await config.fallbackModelHandler('gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL);
|
|
47
|
+
const result = await config.fallbackModelHandler('gemini-2.5-pro', DEFAULT_GEMINI_FLASH_MODEL, new Error('test'));
|
|
41
48
|
// Verify it returns the correct intent
|
|
42
49
|
expect(result).toBe('retry');
|
|
43
50
|
});
|
|
44
51
|
// This test validates the retry utility's logic for triggering the callback.
|
|
45
|
-
it('should trigger onPersistent429
|
|
52
|
+
it('should trigger onPersistent429 on TerminalQuotaError for OAuth users', async () => {
|
|
46
53
|
let fallbackCalled = false;
|
|
47
|
-
// Removed fallbackModel variable as it's no longer relevant here.
|
|
48
|
-
// Mock function that simulates exactly 2 429 errors, then succeeds after fallback
|
|
49
54
|
const mockApiCall = vi
|
|
50
55
|
.fn()
|
|
51
|
-
.mockRejectedValueOnce(
|
|
52
|
-
.mockRejectedValueOnce(
|
|
56
|
+
.mockRejectedValueOnce(new TerminalQuotaError('Daily limit', mockGoogleApiError))
|
|
57
|
+
.mockRejectedValueOnce(new TerminalQuotaError('Daily limit', mockGoogleApiError))
|
|
53
58
|
.mockResolvedValueOnce('success after fallback');
|
|
54
|
-
// Mock the onPersistent429 callback (this is what client.ts/geminiChat.ts provides)
|
|
55
59
|
const mockPersistent429Callback = vi.fn(async (_authType) => {
|
|
56
60
|
fallbackCalled = true;
|
|
57
|
-
// Return true to signal retryWithBackoff to reset attempts and continue.
|
|
58
61
|
return true;
|
|
59
62
|
});
|
|
60
|
-
// Test with OAuth personal auth type, with maxAttempts = 2 to ensure fallback triggers
|
|
61
63
|
const result = await retryWithBackoff(mockApiCall, {
|
|
62
64
|
maxAttempts: 2,
|
|
63
65
|
initialDelayMs: 1,
|
|
64
66
|
maxDelayMs: 10,
|
|
65
|
-
shouldRetryOnError: (error) => {
|
|
66
|
-
const status = error.status;
|
|
67
|
-
return status === 429;
|
|
68
|
-
},
|
|
69
67
|
onPersistent429: mockPersistent429Callback,
|
|
70
68
|
authType: AuthType.LOGIN_WITH_GOOGLE,
|
|
71
69
|
});
|
|
72
|
-
// Verify fallback mechanism was triggered
|
|
73
70
|
expect(fallbackCalled).toBe(true);
|
|
74
|
-
expect(mockPersistent429Callback).toHaveBeenCalledWith(AuthType.LOGIN_WITH_GOOGLE, expect.any(
|
|
71
|
+
expect(mockPersistent429Callback).toHaveBeenCalledWith(AuthType.LOGIN_WITH_GOOGLE, expect.any(TerminalQuotaError));
|
|
75
72
|
expect(result).toBe('success after fallback');
|
|
76
|
-
// Should have: 2 failures, then fallback triggered, then 1 success after retry reset
|
|
77
73
|
expect(mockApiCall).toHaveBeenCalledTimes(3);
|
|
78
74
|
});
|
|
79
75
|
it('should not trigger onPersistent429 for API key users', async () => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
const fallbackCallback = vi.fn();
|
|
77
|
+
const mockApiCall = vi
|
|
78
|
+
.fn()
|
|
79
|
+
.mockRejectedValueOnce(new TerminalQuotaError('Daily limit', mockGoogleApiError));
|
|
80
|
+
const promise = retryWithBackoff(mockApiCall, {
|
|
81
|
+
maxAttempts: 2,
|
|
82
|
+
initialDelayMs: 1,
|
|
83
|
+
maxDelayMs: 10,
|
|
84
|
+
onPersistent429: fallbackCallback,
|
|
85
|
+
authType: AuthType.USE_GEMINI, // API key auth type
|
|
87
86
|
});
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
maxAttempts: 5,
|
|
92
|
-
initialDelayMs: 10,
|
|
93
|
-
maxDelayMs: 100,
|
|
94
|
-
shouldRetryOnError: (error) => {
|
|
95
|
-
const status = error.status;
|
|
96
|
-
return status === 429;
|
|
97
|
-
},
|
|
98
|
-
onPersistent429: mockPersistent429Callback,
|
|
99
|
-
authType: AuthType.USE_GEMINI, // API key auth type
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
// Expected to throw after max attempts
|
|
104
|
-
expect(error.message).toContain('Rate limit exceeded');
|
|
105
|
-
}
|
|
106
|
-
// Verify fallback was NOT triggered for API key users
|
|
107
|
-
expect(fallbackCalled).toBe(false);
|
|
108
|
-
expect(mockPersistent429Callback).not.toHaveBeenCalled();
|
|
87
|
+
await expect(promise).rejects.toThrow('Daily limit');
|
|
88
|
+
expect(fallbackCallback).not.toHaveBeenCalled();
|
|
89
|
+
expect(mockApiCall).toHaveBeenCalledTimes(1);
|
|
109
90
|
});
|
|
110
91
|
// This test validates the test utilities themselves.
|
|
111
92
|
it('should properly disable simulation state after fallback (Test Utility)', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flashFallback.test.js","sourceRoot":"","sources":["../../../src/utils/flashFallback.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EACL,cAAc,EACd,8BAA8B,EAC9B,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"flashFallback.test.js","sourceRoot":"","sources":["../../../src/utils/flashFallback.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview
|
|
8
|
+
* This file contains types and functions for parsing structured Google API errors.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Based on google/rpc/error_details.proto
|
|
12
|
+
*/
|
|
13
|
+
export interface ErrorInfo {
|
|
14
|
+
'@type': 'type.googleapis.com/google.rpc.ErrorInfo';
|
|
15
|
+
reason: string;
|
|
16
|
+
domain: string;
|
|
17
|
+
metadata: {
|
|
18
|
+
[key: string]: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface RetryInfo {
|
|
22
|
+
'@type': 'type.googleapis.com/google.rpc.RetryInfo';
|
|
23
|
+
retryDelay: string;
|
|
24
|
+
}
|
|
25
|
+
export interface DebugInfo {
|
|
26
|
+
'@type': 'type.googleapis.com/google.rpc.DebugInfo';
|
|
27
|
+
stackEntries: string[];
|
|
28
|
+
detail: string;
|
|
29
|
+
}
|
|
30
|
+
export interface QuotaFailure {
|
|
31
|
+
'@type': 'type.googleapis.com/google.rpc.QuotaFailure';
|
|
32
|
+
violations: Array<{
|
|
33
|
+
subject?: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
apiService?: string;
|
|
36
|
+
quotaMetric?: string;
|
|
37
|
+
quotaId?: string;
|
|
38
|
+
quotaDimensions?: {
|
|
39
|
+
[key: string]: string;
|
|
40
|
+
};
|
|
41
|
+
quotaValue?: string | number;
|
|
42
|
+
futureQuotaValue?: number;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export interface PreconditionFailure {
|
|
46
|
+
'@type': 'type.googleapis.com/google.rpc.PreconditionFailure';
|
|
47
|
+
violations: Array<{
|
|
48
|
+
type: string;
|
|
49
|
+
subject: string;
|
|
50
|
+
description: string;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
export interface LocalizedMessage {
|
|
54
|
+
'@type': 'type.googleapis.com/google.rpc.LocalizedMessage';
|
|
55
|
+
locale: string;
|
|
56
|
+
message: string;
|
|
57
|
+
}
|
|
58
|
+
export interface BadRequest {
|
|
59
|
+
'@type': 'type.googleapis.com/google.rpc.BadRequest';
|
|
60
|
+
fieldViolations: Array<{
|
|
61
|
+
field: string;
|
|
62
|
+
description: string;
|
|
63
|
+
reason?: string;
|
|
64
|
+
localizedMessage?: LocalizedMessage;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
export interface RequestInfo {
|
|
68
|
+
'@type': 'type.googleapis.com/google.rpc.RequestInfo';
|
|
69
|
+
requestId: string;
|
|
70
|
+
servingData: string;
|
|
71
|
+
}
|
|
72
|
+
export interface ResourceInfo {
|
|
73
|
+
'@type': 'type.googleapis.com/google.rpc.ResourceInfo';
|
|
74
|
+
resourceType: string;
|
|
75
|
+
resourceName: string;
|
|
76
|
+
owner: string;
|
|
77
|
+
description: string;
|
|
78
|
+
}
|
|
79
|
+
export interface Help {
|
|
80
|
+
'@type': 'type.googleapis.com/google.rpc.Help';
|
|
81
|
+
links: Array<{
|
|
82
|
+
description: string;
|
|
83
|
+
url: string;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
export type GoogleApiErrorDetail = ErrorInfo | RetryInfo | DebugInfo | QuotaFailure | PreconditionFailure | BadRequest | RequestInfo | ResourceInfo | Help | LocalizedMessage;
|
|
87
|
+
export interface GoogleApiError {
|
|
88
|
+
code: number;
|
|
89
|
+
message: string;
|
|
90
|
+
details: GoogleApiErrorDetail[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Parses an error object to check if it's a structured Google API error
|
|
94
|
+
* and extracts all details.
|
|
95
|
+
*
|
|
96
|
+
* This function can handle two formats:
|
|
97
|
+
* 1. Standard Google API errors where `details` is a top-level field.
|
|
98
|
+
* 2. Errors where the entire structured error object is stringified inside
|
|
99
|
+
* the `message` field of a wrapper error.
|
|
100
|
+
*
|
|
101
|
+
* @param error The error object to inspect.
|
|
102
|
+
* @returns A GoogleApiError object if the error matches, otherwise null.
|
|
103
|
+
*/
|
|
104
|
+
export declare function parseGoogleApiError(error: unknown): GoogleApiError | null;
|