summaryrefslogtreecommitdiff
path: root/packages/core/src/utils/quotaErrorDetection.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/core/src/utils/quotaErrorDetection.ts')
-rw-r--r--packages/core/src/utils/quotaErrorDetection.ts82
1 files changed, 82 insertions, 0 deletions
diff --git a/packages/core/src/utils/quotaErrorDetection.ts b/packages/core/src/utils/quotaErrorDetection.ts
new file mode 100644
index 00000000..ec77f5ee
--- /dev/null
+++ b/packages/core/src/utils/quotaErrorDetection.ts
@@ -0,0 +1,82 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export interface ApiError {
+ error: {
+ code: number;
+ message: string;
+ status: string;
+ details: unknown[];
+ };
+}
+
+interface StructuredError {
+ message: string;
+ status?: number;
+}
+
+export function isApiError(error: unknown): error is ApiError {
+ return (
+ typeof error === 'object' &&
+ error !== null &&
+ 'error' in error &&
+ typeof (error as ApiError).error === 'object' &&
+ 'message' in (error as ApiError).error
+ );
+}
+
+export function isStructuredError(error: unknown): error is StructuredError {
+ return (
+ typeof error === 'object' &&
+ error !== null &&
+ 'message' in error &&
+ typeof (error as StructuredError).message === 'string'
+ );
+}
+
+export function isProQuotaExceededError(error: unknown): boolean {
+ // Check for Pro quota exceeded errors by looking for the specific pattern
+ // This will match patterns like:
+ // - "Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'"
+ // - "Quota exceeded for quota metric 'Gemini 1.5-preview Pro Requests'"
+ // - "Quota exceeded for quota metric 'Gemini beta-3.0 Pro Requests'"
+ // - "Quota exceeded for quota metric 'Gemini experimental-v2 Pro Requests'"
+ // We use string methods instead of regex to avoid ReDoS vulnerabilities
+
+ const checkMessage = (message: string): boolean =>
+ message.includes("Quota exceeded for quota metric 'Gemini") &&
+ message.includes("Pro Requests'");
+
+ if (typeof error === 'string') {
+ return checkMessage(error);
+ }
+
+ if (isStructuredError(error)) {
+ return checkMessage(error.message);
+ }
+
+ if (isApiError(error)) {
+ return checkMessage(error.error.message);
+ }
+
+ return false;
+}
+
+export function isGenericQuotaExceededError(error: unknown): boolean {
+ if (typeof error === 'string') {
+ return error.includes('Quota exceeded for quota metric');
+ }
+
+ if (isStructuredError(error)) {
+ return error.message.includes('Quota exceeded for quota metric');
+ }
+
+ if (isApiError(error)) {
+ return error.error.message.includes('Quota exceeded for quota metric');
+ }
+
+ return false;
+}