Просмотр исходного кода

fix: account for additional openai retry case (#24063)

Aiden Cline 3 месяцев назад
Родитель
Сommit
334ab4707c

+ 10 - 2
packages/opencode/src/provider/error.ts

@@ -111,12 +111,13 @@ export type ParsedStreamError =
   | {
       type: "api_error"
       message: string
-      isRetryable: false
+      isRetryable: boolean
       responseBody: string
     }
 
 export function parseStreamError(input: unknown): ParsedStreamError | undefined {
-  const body = json(input)
+  const raw = json(input)
+  const body = typeof raw?.message === "string" ? (json(raw.message) ?? raw) : raw
   if (!body) return
 
   const responseBody = JSON.stringify(body)
@@ -150,6 +151,13 @@ export function parseStreamError(input: unknown): ParsedStreamError | undefined
         isRetryable: false,
         responseBody,
       }
+    case "server_error":
+      return {
+        type: "api_error",
+        message: typeof body?.error?.message === "string" ? body?.error?.message : "Server error.",
+        isRetryable: true,
+        responseBody,
+      }
   }
 }
 

+ 24 - 0
packages/opencode/test/session/message-v2.test.ts

@@ -1075,6 +1075,30 @@ describe("session.message-v2.fromError", () => {
     })
   })
 
+  test("serializes OpenAI response server_error stream chunks as retryable APIError", () => {
+    const body = {
+      type: "error",
+      sequence_number: 2,
+      error: {
+        type: "server_error",
+        code: "server_error",
+        message:
+          "An error occurred while processing your request. You can retry your request, or contact us through our help center at help.openai.com if the error persists. Please include the request ID req_77eccd008d984bf6bf82d1b2c2b68715 in your message.",
+        param: null,
+      },
+    }
+    const result = MessageV2.fromError({ message: JSON.stringify(body) }, { providerID })
+
+    expect(result).toStrictEqual({
+      name: "APIError",
+      data: {
+        message: body.error.message,
+        isRetryable: true,
+        responseBody: JSON.stringify(body),
+      },
+    })
+  })
+
   test("detects context overflow from APICallError provider messages", () => {
     const cases = [
       "prompt is too long: 213462 tokens > 200000 maximum",

+ 22 - 0
packages/opencode/test/session/retry.test.ts

@@ -294,4 +294,26 @@ describe("session.message-v2.fromError", () => {
     const result = MessageV2.fromError(error, { providerID: ProviderID.make("openai") }) as MessageV2.APIError
     expect(result.data.isRetryable).toBe(true)
   })
+
+  test("converts OpenAI server_error stream chunks to retryable APIError", () => {
+    const result = MessageV2.fromError(
+      {
+        message: JSON.stringify({
+          type: "error",
+          sequence_number: 2,
+          error: {
+            type: "server_error",
+            code: "server_error",
+            message: "An error occurred while processing your request.",
+            param: null,
+          },
+        }),
+      },
+      { providerID: ProviderID.make("openai") },
+    )
+
+    expect(MessageV2.APIError.isInstance(result)).toBe(true)
+    expect((result as MessageV2.APIError).data.isRetryable).toBe(true)
+    expect(SessionRetry.retryable(result)).toBe("An error occurred while processing your request.")
+  })
 })