fix(console): parse provider SSE error bodies
This commit is contained in:
parent
a78adb1b09
commit
1e1dc56a09
3 changed files with 61 additions and 1 deletions
|
|
@ -48,6 +48,7 @@ import { localeFromRequest } from "~/lib/language"
|
|||
import { createModelTpmLimiter } from "./modelTpmLimiter"
|
||||
import { createModelTpsLimiter } from "./modelTpsLimiter"
|
||||
import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher"
|
||||
import { readProviderError } from "./providerError"
|
||||
|
||||
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
|
||||
type RetryOptions = {
|
||||
|
|
@ -248,7 +249,7 @@ export async function handler(
|
|||
|
||||
// Handle non-streaming response
|
||||
if (!isStream || [400, 404, 429].includes(res.status)) {
|
||||
const json = await res.json()
|
||||
const json = res.status === 200 ? await res.json() : await readProviderError(res)
|
||||
await rateLimiter?.track()
|
||||
const usage = providerInfo.extractUsage(json)
|
||||
if (usage) {
|
||||
|
|
|
|||
33
packages/console/app/src/routes/zen/util/providerError.ts
Normal file
33
packages/console/app/src/routes/zen/util/providerError.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
export async function readProviderError(res: Response) {
|
||||
const body = await res.text()
|
||||
const json = parseJson(body)
|
||||
if (json && typeof json === "object") return json as Record<string, any>
|
||||
return parseProviderErrorBody(body, res.statusText)
|
||||
}
|
||||
|
||||
export function parseProviderErrorBody(body: string, statusText: string) {
|
||||
const text = body.trim()
|
||||
const sseData = text
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.startsWith("data:"))
|
||||
.map((line) => line.slice(5).trim())
|
||||
.filter((line) => line && line !== "[DONE]")
|
||||
|
||||
const parsed = sseData.map(parseJson).find((item) => item && typeof item === "object")
|
||||
if (parsed) return parsed as Record<string, any>
|
||||
|
||||
return {
|
||||
error: {
|
||||
message: sseData[0] || text || statusText,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function parseJson(value: string) {
|
||||
try {
|
||||
return JSON.parse(value) as unknown
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
26
packages/console/app/test/providerError.test.ts
Normal file
26
packages/console/app/test/providerError.test.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import { parseProviderErrorBody } from "../src/routes/zen/util/providerError"
|
||||
|
||||
describe("provider error parsing", () => {
|
||||
test("parses SSE error bodies from upstream rate limits", () => {
|
||||
expect(
|
||||
parseProviderErrorBody(
|
||||
'event:error\ndata: {"error":{"type":"rate_limit_error","message":"Too many requests"}}\n\n',
|
||||
"Too Many Requests",
|
||||
),
|
||||
).toEqual({
|
||||
error: {
|
||||
type: "rate_limit_error",
|
||||
message: "Too many requests",
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("wraps plain text errors in provider error shape", () => {
|
||||
expect(parseProviderErrorBody("overloaded", "Too Many Requests")).toEqual({
|
||||
error: {
|
||||
message: "overloaded",
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue