fix: improve OpenAI Compatible rate limit error handling

- Add specific error handling for 429 status codes in BaseOpenAiCompatibleProvider
- Add localized error messages for rate limiting in English and Chinese
- Provide clearer guidance to users when hitting rate limits
- Suggest upgrading plan or reducing request frequency

Fixes #6928
This commit is contained in:
Roo Code 2025-08-11 11:16:59 +00:00
parent f53fd39014
commit 80d052dcec
3 changed files with 62 additions and 16 deletions

View file

@ -6,6 +6,7 @@ import type { ModelInfo } from "@roo-code/types"
import type { ApiHandlerOptions } from "../../shared/api"
import { ApiStream } from "../transform/stream"
import { convertToOpenAiMessages } from "../transform/openai-format"
import { t } from "../../i18n"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { DEFAULT_HEADERS } from "./constants"
@ -83,25 +84,47 @@ export abstract class BaseOpenAiCompatibleProvider<ModelName extends string>
stream_options: { include_usage: true },
}
const stream = await this.client.chat.completions.create(params)
try {
const stream = await this.client.chat.completions.create(params)
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta
if (delta?.content) {
yield {
type: "text",
text: delta.content,
if (delta?.content) {
yield {
type: "text",
text: delta.content,
}
}
if (chunk.usage) {
yield {
type: "usage",
inputTokens: chunk.usage.prompt_tokens || 0,
outputTokens: chunk.usage.completion_tokens || 0,
}
}
}
if (chunk.usage) {
yield {
type: "usage",
inputTokens: chunk.usage.prompt_tokens || 0,
outputTokens: chunk.usage.completion_tokens || 0,
}
} catch (error: any) {
// Handle rate limiting errors specifically
if (error?.status === 429 || error?.response?.status === 429) {
const errorMessage = t("common:errors.openaiCompatible.rateLimitExceeded", {
provider: this.providerName,
})
throw new Error(errorMessage)
}
// Handle other errors
if (error instanceof Error) {
throw new Error(
t("common:errors.openaiCompatible.genericError", {
provider: this.providerName,
error: error.message,
}),
)
}
throw error
}
}
@ -115,9 +138,22 @@ export abstract class BaseOpenAiCompatibleProvider<ModelName extends string>
})
return response.choices[0]?.message.content || ""
} catch (error) {
} catch (error: any) {
// Handle rate limiting errors specifically
if (error?.status === 429 || error?.response?.status === 429) {
const errorMessage = t("common:errors.openaiCompatible.rateLimitExceeded", {
provider: this.providerName,
})
throw new Error(errorMessage)
}
if (error instanceof Error) {
throw new Error(`${this.providerName} completion error: ${error.message}`)
throw new Error(
t("common:errors.openaiCompatible.completionError", {
provider: this.providerName,
error: error.message,
}),
)
}
throw error

View file

@ -100,6 +100,11 @@
"genericError": "Cerebras API Error ({{status}}): {{message}}",
"noResponseBody": "Cerebras API Error: No response body",
"completionError": "Cerebras completion error: {{error}}"
},
"openaiCompatible": {
"rateLimitExceeded": "{{provider}} API rate limit exceeded. Please wait a moment before making another request. If using a free tier, consider upgrading your plan or reducing request frequency.",
"genericError": "{{provider}} API error: {{error}}",
"completionError": "{{provider}} completion error: {{error}}"
}
},
"warnings": {

View file

@ -105,6 +105,11 @@
"genericError": "Cerebras API 错误 ({{status}}){{message}}",
"noResponseBody": "Cerebras API 错误:无响应主体",
"completionError": "Cerebras 完成错误:{{error}}"
},
"openaiCompatible": {
"rateLimitExceeded": "{{provider}} API 速率限制已超出。请稍等片刻后再发起请求。如果您使用的是免费套餐,请考虑升级您的计划或降低请求频率。",
"genericError": "{{provider}} API 错误:{{error}}",
"completionError": "{{provider}} 完成错误:{{error}}"
}
},
"warnings": {