fix(parser): wrap parseAnthropicTokenLimitError in try/catch
Add outer try/catch to prevent crashes from non-standard error objects returned by proxy providers (e.g., Antigravity). Add parser tests covering edge cases: circular refs, non-object data fields, invalid JSON in responseBody.
This commit is contained in:
parent
dd9eeaa6d6
commit
072b30593e
@ -0,0 +1,97 @@
|
|||||||
|
/// <reference types="bun-types" />
|
||||||
|
import { describe, expect, it } from "bun:test"
|
||||||
|
import { parseAnthropicTokenLimitError } from "./parser"
|
||||||
|
|
||||||
|
describe("parseAnthropicTokenLimitError", () => {
|
||||||
|
it("#given a standard token limit error string #when parsing #then extracts tokens", () => {
|
||||||
|
//#given
|
||||||
|
const error = "prompt is too long: 250000 tokens > 200000 maximum"
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).not.toBeNull()
|
||||||
|
expect(result!.currentTokens).toBe(250000)
|
||||||
|
expect(result!.maxTokens).toBe(200000)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given a non-token-limit error #when parsing #then returns null", () => {
|
||||||
|
//#given
|
||||||
|
const error = { message: "internal server error" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given null input #when parsing #then returns null", () => {
|
||||||
|
//#given
|
||||||
|
const error = null
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given a proxy error with non-standard structure #when parsing #then returns null without crashing", () => {
|
||||||
|
//#given
|
||||||
|
const proxyError = {
|
||||||
|
data: [1, 2, 3],
|
||||||
|
error: "string-not-object",
|
||||||
|
message: "Failed to process error response",
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(proxyError)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given a circular reference error #when parsing #then returns null without crashing", () => {
|
||||||
|
//#given
|
||||||
|
const circular: Record<string, unknown> = { message: "prompt is too long" }
|
||||||
|
circular.self = circular
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(circular)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).not.toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given an error where data.responseBody has invalid JSON #when parsing #then handles gracefully", () => {
|
||||||
|
//#given
|
||||||
|
const error = {
|
||||||
|
data: { responseBody: "not valid json {{{" },
|
||||||
|
message: "prompt is too long with 300000 tokens exceeds 200000",
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).not.toBeNull()
|
||||||
|
expect(result!.currentTokens).toBe(300000)
|
||||||
|
expect(result!.maxTokens).toBe(200000)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given an error with data as a string (not object) #when parsing #then does not crash", () => {
|
||||||
|
//#given
|
||||||
|
const error = {
|
||||||
|
data: "some-string-data",
|
||||||
|
message: "token limit exceeded",
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = parseAnthropicTokenLimitError(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).not.toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -74,6 +74,14 @@ function isTokenLimitError(text: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parseAnthropicTokenLimitError(err: unknown): ParsedTokenLimitError | null {
|
export function parseAnthropicTokenLimitError(err: unknown): ParsedTokenLimitError | null {
|
||||||
|
try {
|
||||||
|
return parseAnthropicTokenLimitErrorUnsafe(err)
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAnthropicTokenLimitErrorUnsafe(err: unknown): ParsedTokenLimitError | null {
|
||||||
if (typeof err === "string") {
|
if (typeof err === "string") {
|
||||||
if (err.toLowerCase().includes("non-empty content")) {
|
if (err.toLowerCase().includes("non-empty content")) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user