summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/opencode/src/session/message-v2.ts9
-rw-r--r--packages/opencode/test/session/retry.test.ts15
2 files changed, 23 insertions, 1 deletions
diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts
index 7c8689037..650fda6e9 100644
--- a/packages/opencode/src/session/message-v2.ts
+++ b/packages/opencode/src/session/message-v2.ts
@@ -656,6 +656,13 @@ export namespace MessageV2 {
return result
}
+ const isOpenAiErrorRetryable = (e: APICallError) => {
+ const status = e.statusCode
+ if (!status) return e.isRetryable
+ // openai sometimes returns 404 for models that are actually available
+ return status === 404 || e.isRetryable
+ }
+
export function fromError(e: unknown, ctx: { providerID: string }) {
switch (true) {
case e instanceof DOMException && e.name === "AbortError":
@@ -724,7 +731,7 @@ export namespace MessageV2 {
{
message,
statusCode: e.statusCode,
- isRetryable: e.isRetryable,
+ isRetryable: ctx.providerID.startsWith("openai") ? isOpenAiErrorRetryable(e) : e.isRetryable,
responseHeaders: e.responseHeaders,
responseBody: e.responseBody,
metadata,
diff --git a/packages/opencode/test/session/retry.test.ts b/packages/opencode/test/session/retry.test.ts
index b130e927e..10137ed98 100644
--- a/packages/opencode/test/session/retry.test.ts
+++ b/packages/opencode/test/session/retry.test.ts
@@ -1,4 +1,5 @@
import { describe, expect, test } from "bun:test"
+import { APICallError } from "ai"
import { SessionRetry } from "../../src/session/retry"
import { MessageV2 } from "../../src/session/message-v2"
@@ -128,4 +129,18 @@ describe("session.message-v2.fromError", () => {
expect(retryable).toBeDefined()
expect(retryable).toBe("Connection reset by server")
})
+
+ test("marks OpenAI 404 status codes as retryable", () => {
+ const error = new APICallError({
+ message: "boom",
+ url: "https://api.openai.com/v1/chat/completions",
+ requestBodyValues: {},
+ statusCode: 404,
+ responseHeaders: { "content-type": "application/json" },
+ responseBody: "{\"error\":\"boom\"}",
+ isRetryable: false,
+ })
+ const result = MessageV2.fromError(error, { providerID: "openai" }) as MessageV2.APIError
+ expect(result.data.isRetryable).toBe(true)
+ })
})