fix(core): preserve provider session failures

This commit is contained in:
Kit Langton 2026-06-24 22:43:18 -04:00
commit f8e5b12f41
13 changed files with 359 additions and 22 deletions

View file

@ -891,6 +891,8 @@ const providerError = (event: OpenAIResponsesEvent, fallback: string) => {
return LLMEvent.providerError({
message,
classification: code === "context_length_exceeded" || isContextOverflow(message) ? "context-overflow" : undefined,
category: code === "rate_limit_exceeded" ? "rate-limit" : undefined,
retryable: code === "rate_limit_exceeded" ? true : undefined,
})
}

View file

@ -4,6 +4,20 @@ import { ModelID, ProviderID, ProviderMetadata, RouteID } from "./ids"
export const ProviderFailureClassification = Schema.Literal("context-overflow")
export type ProviderFailureClassification = typeof ProviderFailureClassification.Type
export const ProviderFailureCategory = Schema.Literals([
"invalid-request",
"no-route",
"authentication",
"rate-limit",
"quota-exceeded",
"content-policy",
"provider-internal",
"transport",
"invalid-provider-output",
"unknown",
])
export type ProviderFailureCategory = typeof ProviderFailureCategory.Type
export class HttpRequestDetails extends Schema.Class<HttpRequestDetails>("LLM.HttpRequestDetails")({
method: Schema.String,
url: Schema.String,

View file

@ -2,7 +2,7 @@ import { Schema } from "effect"
import { ContentBlockID, FinishReason, ProtocolID, ProviderMetadata, RouteID, ToolCallID } from "./ids"
import { ModelSchema } from "./options"
import { ToolOutput, ToolResultValue } from "./messages"
import { ProviderFailureClassification } from "./errors"
import { ProviderFailureCategory, ProviderFailureClassification } from "./errors"
/**
* Token usage reported by an LLM provider.
@ -201,6 +201,8 @@ export const ProviderErrorEvent = Schema.Struct({
type: Schema.tag("provider-error"),
message: Schema.String,
classification: Schema.optional(ProviderFailureClassification),
category: Schema.optional(ProviderFailureCategory),
status: Schema.optional(Schema.Number),
retryable: Schema.optional(Schema.Boolean),
providerMetadata: Schema.optional(ProviderMetadata),
}).annotate({ identifier: "LLM.Event.ProviderError" })

View file

@ -1326,7 +1326,14 @@ describe("OpenAI Responses route", () => {
// sometimes-generic provider message. The bare message alone meant
// production errors like rate limits were indistinguishable from
// unrelated stream failures.
expect(response.events).toEqual([{ type: "provider-error", message: "rate_limit_exceeded: Slow down" }])
expect(response.events).toEqual([
{
type: "provider-error",
message: "rate_limit_exceeded: Slow down",
category: "rate-limit",
retryable: true,
},
])
}),
)