Compare commits

...

3 Commits

Author SHA1 Message Date
Aiden Cline 71ebbc7476 fix(ai): expand transient text matching 2026-08-21 00:20:10 -05:00
Aiden Cline 1c207325bc refactor(ai): combine transient classification 2026-08-21 00:17:45 -05:00
Aiden Cline 726f053f67 fix(ai): classify xAI capacity failures 2026-08-21 00:07:13 -05:00
2 changed files with 25 additions and 2 deletions
+5 -1
View File
@@ -74,6 +74,7 @@ const INVALID_REQUEST_CODES = new Set(["invalid_prompt", "invalid_request_error"
const RATE_LIMIT_TEXT = /rate increased too quickly|rate[-_\s]?limit|too[_\s]?many[_\s]?requests/i
const QUOTA_TEXT = /insufficient[-_\s]?quota|quota[-_\s]?exceeded/i
const CONTENT_POLICY_TEXT = /content[-_\s]?policy|content_filter|safety/i
const TRANSIENT_TEXT = /\btry again (?:later|in\b)|\b(?:currently|temporarily) at capacity\b|\bretry your request\b/i
export interface ProviderFailure {
readonly message: string
@@ -127,7 +128,10 @@ export function classifyProviderFailure(input: ProviderFailure): AIError["reason
retryAfterMs: input.retryAfterMs,
rateLimit: input.rateLimit,
})
if (codes.some((code) => SERVER_CODES.has(code) || code.includes("exhausted") || code.includes("unavailable")))
if (
TRANSIENT_TEXT.test(text) ||
codes.some((code) => SERVER_CODES.has(code) || code.includes("exhausted") || code.includes("unavailable"))
)
return new ProviderInternalReason({
...common,
status: input.status,
+20 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"
import { isContextOverflow } from "../src/index.js"
import { HttpContext, HttpRequestDetails, isContextOverflow } from "../src/index.js"
import { classifyProviderFailure } from "../src/provider-error.js"
describe("provider error classification", () => {
@@ -75,6 +75,25 @@ describe("provider error classification", () => {
).toEqual(["ProviderInternal", "ProviderInternal", "ProviderInternal"])
})
test("classifies transient provider text as provider internal", () => {
const message =
"The model is currently at capacity due to high demand. Please try again in a few minutes, or use a higher service tier for priority processing: https://docs.x.ai/developers/advanced-api-usage/priority-processing"
const http = new HttpContext({
request: new HttpRequestDetails({ method: "POST", url: "https://api.x.ai/v1/responses", headers: {} }),
body: message,
})
expect(
[
message,
"The service is temporarily at capacity.",
"Please try again later.",
"Please retry your request shortly.",
].map((message) => classifyProviderFailure({ message })._tag),
).toEqual(["ProviderInternal", "ProviderInternal", "ProviderInternal", "ProviderInternal"])
expect(classifyProviderFailure({ message: "Provider request failed", http })._tag).toBe("ProviderInternal")
})
test("classifies transient client statuses as provider internal", () => {
expect([408, 409].map((status) => classifyProviderFailure({ message: `HTTP ${status}`, status })._tag)).toEqual([
"ProviderInternal",