| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import { describe, expect, test } from "bun:test"
- import { isContextOverflow } from "../src"
- import { classifyProviderFailure } from "../src/provider-error"
- describe("provider error classification", () => {
- test("classifies provider token limit messages as context overflow", () => {
- const messages = [
- "tokens in request more than max tokens allowed",
- '{"error":{"type":"request_too_large","message":"Request exceeds the maximum size"}}',
- "Requested token count exceeds the model's maximum context length of 131072 tokens.",
- "Input length (265330) exceeds model's maximum context length (262144).",
- "Input length 131393 exceeds the maximum allowed input length of 131040 tokens.",
- "The input (516368 tokens) is longer than the model's context length (262144 tokens).",
- "Prompt has 5,958,968 tokens, but the configured context size is 256,000 tokens",
- "Too many tokens",
- "Token limit exceeded",
- ]
- expect(messages.every(isContextOverflow)).toBe(true)
- })
- test("does not classify rate limits as context overflow", () => {
- const messages = [
- "Throttling error: Too many tokens, please wait before trying again.",
- "Rate limit exceeded, please retry after 30 seconds.",
- "Too many requests. Please slow down.",
- ]
- expect(messages.some(isContextOverflow)).toBe(false)
- })
- test("classifies V1 plain-text rate limit fallbacks", () => {
- expect(
- [
- "Request rate increased too quickly",
- "Rate limit exceeded, please try again later",
- "Too many requests, please slow down",
- ].map((message) => classifyProviderFailure({ message })._tag),
- ).toEqual(["RateLimit", "RateLimit", "RateLimit"])
- })
- test("classifies V1 JSON rate limit fallbacks", () => {
- expect(
- [
- '{"type":"error","error":{"type":"too_many_requests"}}',
- '{"type":"error","error":{"code":"rate_limit_exceeded"}}',
- '{"code":"bad_request","error":{"code":"rate_limit_exceeded"}}',
- '{"type":"error","error":{"code":"unknown","type":"too_many_requests"}}',
- ].map((message) => classifyProviderFailure({ message })._tag),
- ).toEqual(["RateLimit", "RateLimit", "RateLimit", "RateLimit"])
- })
- test("classifies V1 overloaded provider codes", () => {
- expect(
- ['{"code":"resource_exhausted"}', '{"code":"service_unavailable"}'].map(
- (message) => classifyProviderFailure({ message })._tag,
- ),
- ).toEqual(["ProviderInternal", "ProviderInternal"])
- })
- test("classifies nested provider codes when a top-level code is also present", () => {
- expect(
- [
- '{"code":"bad_request","error":{"code":"usage_not_included"}}',
- '{"code":"bad_request","error":{"code":"server_error"}}',
- '{"code":"bad_request","error":{"type":"invalid_request_error"}}',
- ].map((message) => classifyProviderFailure({ message })._tag),
- ).toEqual(["QuotaExceeded", "ProviderInternal", "InvalidRequest"])
- })
- test("keeps unknown and malformed provider payloads non-retryable", () => {
- expect(classifyProviderFailure({ message: '{"error":{"message":"no_kv_space"}}' })._tag).toBe("UnknownProvider")
- expect(classifyProviderFailure({ message: '{"type":"error","error":{"code":123}}' })._tag).toBe("UnknownProvider")
- expect(classifyProviderFailure({ message: "not-json" })._tag).toBe("UnknownProvider")
- })
- })
|