From 21dacf814a6e7dc82312a71cce4ca3308562cc80 Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Thu, 26 Feb 2026 16:23:43 +0800 Subject: [PATCH 1/3] Add .gitignore for Java SDK to ignore IDE/jdtls config files --- packages/sdk-java/.gitignore | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 packages/sdk-java/.gitignore diff --git a/packages/sdk-java/.gitignore b/packages/sdk-java/.gitignore new file mode 100644 index 00000000000..47eb60ccf23 --- /dev/null +++ b/packages/sdk-java/.gitignore @@ -0,0 +1,43 @@ +# Eclipse IDE files (auto-generated by jdtls) +.classpath +.project +.settings/ + +# IntelliJ IDEA files +.idea/ +*.iml +*.ipr +*.iws + +# VS Code files +.vscode/ + +# Build output +target/ +build/ +out/ +*.class + +# Maven +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# Gradle +.gradle/ +gradle-app.setting +!gradle-wrapper.jar +.gradletasknamecache + +# Logs +*.log + +# OS files +.DS_Store +Thumbs.db From a4ad255ccabb64ad3e997a04145773c126005116 Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Fri, 27 Feb 2026 10:26:28 +0800 Subject: [PATCH 2/3] Support for user-defined error codes --- packages/core/src/core/contentGenerator.ts | 3 ++- packages/core/src/core/geminiChat.ts | 17 ++++++++++------- packages/core/src/models/constants.ts | 1 + packages/core/src/models/types.ts | 1 + packages/core/src/utils/rateLimit.test.ts | 15 +++++++++++++++ packages/core/src/utils/rateLimit.ts | 14 ++++++++++++-- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/packages/core/src/core/contentGenerator.ts b/packages/core/src/core/contentGenerator.ts index f3af06bda2b..ad2326de3f1 100644 --- a/packages/core/src/core/contentGenerator.ts +++ b/packages/core/src/core/contentGenerator.ts @@ -70,7 +70,8 @@ export type ContentGeneratorConfig = { enableOpenAILogging?: boolean; openAILoggingDir?: string; timeout?: number; // Timeout configuration in milliseconds - maxRetries?: number; // Maximum retries for failed requests + maxRetries?: number; // Maximum retries for rate-limit errors + retryErrorCodes?: number[]; // Additional error codes that trigger rate-limit retry enableCacheControl?: boolean; // Enable cache control for DashScope providers samplingParams?: { top_p?: number; diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index 0bac7066fea..2e192335515 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -286,6 +286,12 @@ export class GeminiChat { let lastError: unknown = new Error('Request failed after all retries.'); let rateLimitRetryCount = 0; + // Read per-config overrides; fall back to built-in defaults. + const cgConfig = self.config.getContentGeneratorConfig(); + const maxRateLimitRetries = + cgConfig?.maxRetries ?? RATE_LIMIT_RETRY_OPTIONS.maxRetries; + const extraRetryErrorCodes = cgConfig?.retryErrorCodes; + for ( let attempt = 0; attempt < INVALID_CONTENT_RETRY_OPTIONS.maxAttempts; @@ -316,18 +322,15 @@ export class GeminiChat { // These arrive as StreamContentError with finish_reason="error_finish" // from the pipeline, containing the throttling message in the content. // Covers TPM throttling, GLM rate limits, and other provider throttling. - const isRateLimit = isRateLimitError(error); - if ( - isRateLimit && - rateLimitRetryCount < RATE_LIMIT_RETRY_OPTIONS.maxRetries - ) { + const isRateLimit = isRateLimitError(error, extraRetryErrorCodes); + if (isRateLimit && rateLimitRetryCount < maxRateLimitRetries) { rateLimitRetryCount++; const delayMs = RATE_LIMIT_RETRY_OPTIONS.delayMs; const message = parseAndFormatApiError( error instanceof Error ? error.message : String(error), ); debugLogger.warn( - `Rate limit throttling detected (retry ${rateLimitRetryCount}/${RATE_LIMIT_RETRY_OPTIONS.maxRetries}). ` + + `Rate limit throttling detected (retry ${rateLimitRetryCount}/${maxRateLimitRetries}). ` + `Waiting ${delayMs / 1000}s before retrying...`, ); yield { @@ -335,7 +338,7 @@ export class GeminiChat { retryInfo: { message, attempt: rateLimitRetryCount, - maxRetries: RATE_LIMIT_RETRY_OPTIONS.maxRetries, + maxRetries: maxRateLimitRetries, delayMs, }, }; diff --git a/packages/core/src/models/constants.ts b/packages/core/src/models/constants.ts index 9e5d15009ec..317d9d7ed49 100644 --- a/packages/core/src/models/constants.ts +++ b/packages/core/src/models/constants.ts @@ -22,6 +22,7 @@ export const MODEL_GENERATION_CONFIG_FIELDS = [ 'samplingParams', 'timeout', 'maxRetries', + 'retryErrorCodes', 'enableCacheControl', 'schemaCompliance', 'reasoning', diff --git a/packages/core/src/models/types.ts b/packages/core/src/models/types.ts index 69c286729f9..61509c44bd7 100644 --- a/packages/core/src/models/types.ts +++ b/packages/core/src/models/types.ts @@ -29,6 +29,7 @@ export type ModelGenerationConfig = Pick< | 'samplingParams' | 'timeout' | 'maxRetries' + | 'retryErrorCodes' | 'enableCacheControl' | 'schemaCompliance' | 'reasoning' diff --git a/packages/core/src/utils/rateLimit.test.ts b/packages/core/src/utils/rateLimit.test.ts index 48605db20e1..f48c277d1d4 100644 --- a/packages/core/src/utils/rateLimit.test.ts +++ b/packages/core/src/utils/rateLimit.test.ts @@ -52,6 +52,21 @@ describe('isRateLimitError — detection paths', () => { ).toBe(false); }); + it('should detect custom error code passed via extraCodes', () => { + expect( + isRateLimitError( + { error: { code: 1305, message: 'Custom rate limit' } }, + [1305], + ), + ).toBe(true); + }); + + it('should not detect custom code when extraCodes is not provided', () => { + expect( + isRateLimitError({ error: { code: 1305, message: 'Custom rate limit' } }), + ).toBe(false); + }); + it('should return null for invalid inputs', () => { expect(isRateLimitError(null)).toBe(false); expect(isRateLimitError(undefined)).toBe(false); diff --git a/packages/core/src/utils/rateLimit.ts b/packages/core/src/utils/rateLimit.ts index 559cb26fb84..cc4761703f7 100644 --- a/packages/core/src/utils/rateLimit.ts +++ b/packages/core/src/utils/rateLimit.ts @@ -25,10 +25,20 @@ export interface RetryInfo { /** * Detects rate-limit / throttling errors and returns retry info. + * + * @param error - The error to check. + * @param extraCodes - Additional error codes to treat as rate-limit errors, + * merged with the built-in set at call time (not mutating the default set). */ -export function isRateLimitError(error: unknown): boolean { +export function isRateLimitError( + error: unknown, + extraCodes?: readonly number[], +): boolean { const code = getErrorCode(error); - return code !== null && RATE_LIMIT_ERROR_CODES.has(code); + if (code === null) return false; + if (RATE_LIMIT_ERROR_CODES.has(code)) return true; + if (extraCodes && extraCodes.includes(code)) return true; + return false; } /** From 3fc9cb48d16c2711d69dd143a7659650a15f0342 Mon Sep 17 00:00:00 2001 From: yiliang114 <1204183885@qq.com> Date: Sat, 28 Feb 2026 11:05:41 +0800 Subject: [PATCH 3/3] fix(core/rateLimit): add support for IdealTalk rate limit error code 1305 - Add error code 1305 to RATE_LIMIT_ERROR_CODES for DashScope/IdealTalk internal rate limit detection (issue #1918) - Add test case for 1305 error code detection - Update existing test cases to use 9999 as custom error code to avoid conflict - Remove unused sdk-java/.gitignore file Co-authored-by: Qwen-Coder --- packages/core/src/utils/rateLimit.test.ts | 13 +++++-- packages/core/src/utils/rateLimit.ts | 3 +- packages/sdk-java/.gitignore | 43 ----------------------- 3 files changed, 12 insertions(+), 47 deletions(-) delete mode 100644 packages/sdk-java/.gitignore diff --git a/packages/core/src/utils/rateLimit.test.ts b/packages/core/src/utils/rateLimit.test.ts index f48c277d1d4..a342a4a0b00 100644 --- a/packages/core/src/utils/rateLimit.test.ts +++ b/packages/core/src/utils/rateLimit.test.ts @@ -33,6 +33,13 @@ describe('isRateLimitError — detection paths', () => { expect(info).toBe(true); }); + it('should detect 1305 code from ApiError (issue #1918)', () => { + const info = isRateLimitError({ + error: { code: 1305, message: 'IdealTalk rate limit' }, + }); + expect(info).toBe(true); + }); + it('should detect rate-limit from StructuredError.status', () => { const error: StructuredError = { message: 'Rate limited', status: 429 }; const info = isRateLimitError(error); @@ -55,15 +62,15 @@ describe('isRateLimitError — detection paths', () => { it('should detect custom error code passed via extraCodes', () => { expect( isRateLimitError( - { error: { code: 1305, message: 'Custom rate limit' } }, - [1305], + { error: { code: 9999, message: 'Custom rate limit' } }, + [9999], ), ).toBe(true); }); it('should not detect custom code when extraCodes is not provided', () => { expect( - isRateLimitError({ error: { code: 1305, message: 'Custom rate limit' } }), + isRateLimitError({ error: { code: 9999, message: 'Custom rate limit' } }), ).toBe(false); }); diff --git a/packages/core/src/utils/rateLimit.ts b/packages/core/src/utils/rateLimit.ts index cc4761703f7..19466e90f6c 100644 --- a/packages/core/src/utils/rateLimit.ts +++ b/packages/core/src/utils/rateLimit.ts @@ -10,7 +10,8 @@ import { isApiError, isStructuredError } from './quotaErrorDetection.js'; // 429 - Standard HTTP "Too Many Requests" (DashScope TPM, OpenAI, etc.) // 503 - Provider throttling/overload (treated as rate-limit for retry UI) // 1302 - Z.AI GLM rate limit (https://docs.z.ai/api-reference/api-code) -const RATE_LIMIT_ERROR_CODES = new Set([429, 503, 1302]); +// 1305 - DashScope/IdealTalk internal rate limit (issue #1918) +const RATE_LIMIT_ERROR_CODES = new Set([429, 503, 1302, 1305]); export interface RetryInfo { /** Formatted error message for display, produced by parseAndFormatApiError. */ diff --git a/packages/sdk-java/.gitignore b/packages/sdk-java/.gitignore deleted file mode 100644 index 47eb60ccf23..00000000000 --- a/packages/sdk-java/.gitignore +++ /dev/null @@ -1,43 +0,0 @@ -# Eclipse IDE files (auto-generated by jdtls) -.classpath -.project -.settings/ - -# IntelliJ IDEA files -.idea/ -*.iml -*.ipr -*.iws - -# VS Code files -.vscode/ - -# Build output -target/ -build/ -out/ -*.class - -# Maven -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar - -# Gradle -.gradle/ -gradle-app.setting -!gradle-wrapper.jar -.gradletasknamecache - -# Logs -*.log - -# OS files -.DS_Store -Thumbs.db