Compare commits

...

6 Commits

Author SHA1 Message Date
celestial-vault b781ef508c changeset 2025-03-21 15:49:01 -07:00
celestial-vault 7620fb18d6 optional chaining for error message check 2025-03-21 15:44:34 -07:00
celestial-vault 8a9a407a7e merge conflicts 2025-03-21 15:43:30 -07:00
celestial-vault dc70dfb588 truncate and retry if we encounter context window exceeded error 2025-03-21 14:23:05 -07:00
celestial-vault c87d9e3e95 changeset 2025-03-21 11:57:27 -07:00
celestial-vault 0215c5cc91 correct calculation of quarter truncation 2025-03-21 11:35:56 -07:00
3 changed files with 37 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": patch
---
Handle openrouter input too large error
+29
View File
@@ -67,6 +67,7 @@ import { telemetryService } from "../services/telemetry/TelemetryService"
import { ConversationTelemetryService, TelemetryChatMessage } from "../services/telemetry/ConversationTelemetryService"
import pTimeout from "p-timeout"
import { GlobalFileNames } from "../global-constants"
import { checkIsOpenRouterContextWindowError } from "./context-management/context-error-handling"
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) ?? path.join(os.homedir(), "Desktop") // may or may not exist but fs checking existence would immediately ask for permission which would be bad UX, need to come up with a better solution
@@ -1431,20 +1432,48 @@ export class Cline {
this.isWaitingForFirstChunk = false
} catch (error) {
const isOpenRouter = this.api instanceof OpenRouterHandler || this.api instanceof ClineHandler
const isOpenRouterContextWindowError = checkIsOpenRouterContextWindowError(error) && isOpenRouter
if (isOpenRouter && !this.didAutomaticallyRetryFailedApiRequest) {
if (isOpenRouterContextWindowError) {
this.conversationHistoryDeletedRange = this.contextManager.getNextTruncationRange(
this.apiConversationHistory,
this.conversationHistoryDeletedRange,
"quarter", // Force aggressive truncation
)
await this.saveClineMessages()
}
console.log("first chunk failed, waiting 1 second before retrying")
await delay(1000)
this.didAutomaticallyRetryFailedApiRequest = true
} else {
// request failed after retrying automatically once, ask user if they want to retry again
// note that this api_req_failed ask is unique in that we only present this option if the api hasn't streamed any content yet (ie it fails on the first chunk due), as it would allow them to hit a retry button. However if the api failed mid-stream, it could be in any arbitrary state where some tools may have executed, so that error is handled differently and requires cancelling the task entirely.
if (isOpenRouterContextWindowError) {
const truncatedConversationHistory = this.contextManager.getTruncatedMessages(
this.apiConversationHistory,
this.conversationHistoryDeletedRange,
)
// If the conversation has more than 3 messages, we can truncate again. If not, then the conversation is bricked.
// ToDo: Allow the user to change their input if this is the case.
if (truncatedConversationHistory.length > 3) {
error = new Error("Context window exceeded. Click retry to truncate the conversation and try again.")
this.didAutomaticallyRetryFailedApiRequest = false
}
}
const errorMessage = this.formatErrorWithStatusCode(error)
const { response } = await this.ask("api_req_failed", errorMessage)
if (response !== "yesButtonClicked") {
// this will never happen since if noButtonClicked, we will clear current task, aborting this instance
throw new Error("API request failed")
}
await this.say("api_req_retried")
}
// delegate generator output from the recursive call
@@ -0,0 +1,3 @@
export function checkIsOpenRouterContextWindowError(error: any): boolean {
return error.code === 400 && error.message?.includes("context length")
}