tweak: add new ContextOverflowError type (#12777)

This commit is contained in:
Aiden Cline
2026-02-08 23:54:01 -06:00
committed by GitHub
parent d40dffb854
commit 99ea1351ce
6 changed files with 350 additions and 126 deletions

View File

@@ -1,4 +1,5 @@
import { describe, expect, test } from "bun:test"
import { APICallError } from "ai"
import { MessageV2 } from "../../src/session/message-v2"
import type { Provider } from "../../src/provider/provider"
@@ -786,12 +787,26 @@ describe("session.message-v2.toModelMessage", () => {
})
describe("session.message-v2.fromError", () => {
test("serializes context_length_exceeded as ContextOverflowError", () => {
const input = {
type: "error",
error: {
code: "context_length_exceeded",
},
}
const result = MessageV2.fromError(input, { providerID: "test" })
expect(result).toStrictEqual({
name: "ContextOverflowError",
data: {
message: "Input exceeds context window of this model",
responseBody: JSON.stringify(input),
},
})
})
test("serializes response error codes", () => {
const cases = [
{
code: "context_length_exceeded",
message: "Input exceeds context window of this model",
},
{
code: "insufficient_quota",
message: "Quota exceeded. Check your plan and billing details.",
@@ -827,6 +842,75 @@ describe("session.message-v2.fromError", () => {
})
})
test("maps github-copilot 403 to reauth guidance", () => {
const error = new APICallError({
message: "forbidden",
url: "https://api.githubcopilot.com/v1/chat/completions",
requestBodyValues: {},
statusCode: 403,
responseHeaders: { "content-type": "application/json" },
responseBody: '{"error":"forbidden"}',
isRetryable: false,
})
const result = MessageV2.fromError(error, { providerID: "github-copilot" })
expect(result).toStrictEqual({
name: "APIError",
data: {
message:
"Please reauthenticate with the copilot provider to ensure your credentials work properly with OpenCode.",
statusCode: 403,
isRetryable: false,
responseHeaders: { "content-type": "application/json" },
responseBody: '{"error":"forbidden"}',
metadata: {
url: "https://api.githubcopilot.com/v1/chat/completions",
},
},
})
})
test("detects context overflow from APICallError provider messages", () => {
const cases = [
"prompt is too long: 213462 tokens > 200000 maximum",
"Your input exceeds the context window of this model",
"The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)",
"Please reduce the length of the messages or completion",
"400 status code (no body)",
"413 status code (no body)",
]
cases.forEach((message) => {
const error = new APICallError({
message,
url: "https://example.com",
requestBodyValues: {},
statusCode: 400,
responseHeaders: { "content-type": "application/json" },
isRetryable: false,
})
const result = MessageV2.fromError(error, { providerID: "test" })
expect(MessageV2.ContextOverflowError.isInstance(result)).toBe(true)
})
})
test("does not classify 429 no body as context overflow", () => {
const result = MessageV2.fromError(
new APICallError({
message: "429 status code (no body)",
url: "https://example.com",
requestBodyValues: {},
statusCode: 429,
responseHeaders: { "content-type": "application/json" },
isRetryable: false,
}),
{ providerID: "test" },
)
expect(MessageV2.ContextOverflowError.isInstance(result)).toBe(false)
expect(MessageV2.APIError.isInstance(result)).toBe(true)
})
test("serializes unknown inputs", () => {
const result = MessageV2.fromError(123, { providerID: "test" })