fix(session-recovery): detect unavailable_tool errors
This commit is contained in:
parent
51654c1c5e
commit
43b8884db6
@ -1,6 +1,6 @@
|
|||||||
/// <reference types="bun-types" />
|
/// <reference types="bun-types" />
|
||||||
import { describe, expect, it } from "bun:test"
|
import { describe, expect, it } from "bun:test"
|
||||||
import { detectErrorType, extractMessageIndex } from "./detect-error-type"
|
import { detectErrorType, extractMessageIndex, extractUnavailableToolName } from "./detect-error-type"
|
||||||
|
|
||||||
describe("detectErrorType", () => {
|
describe("detectErrorType", () => {
|
||||||
it("#given a tool_use/tool_result error #when detecting #then returns tool_result_missing", () => {
|
it("#given a tool_use/tool_result error #when detecting #then returns tool_result_missing", () => {
|
||||||
@ -101,6 +101,45 @@ describe("detectErrorType", () => {
|
|||||||
//#then
|
//#then
|
||||||
expect(result).toBe("tool_result_missing")
|
expect(result).toBe("tool_result_missing")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("#given a dummy_tool unavailable tool error #when detecting #then returns unavailable_tool", () => {
|
||||||
|
//#given
|
||||||
|
const error = { message: "model tried to call unavailable tool 'invalid'" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = detectErrorType(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBe("unavailable_tool")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given a no such tool error #when detecting #then returns unavailable_tool", () => {
|
||||||
|
//#given
|
||||||
|
const error = { message: "No such tool: grepppp" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = detectErrorType(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBe("unavailable_tool")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given a dummy_tool token in nested error #when detecting #then returns unavailable_tool", () => {
|
||||||
|
//#given
|
||||||
|
const error = {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
message: "dummy_tool Model tried to call unavailable tool 'invalid'",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = detectErrorType(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBe("unavailable_tool")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("extractMessageIndex", () => {
|
describe("extractMessageIndex", () => {
|
||||||
@ -127,3 +166,27 @@ describe("extractMessageIndex", () => {
|
|||||||
expect(result).toBeNull()
|
expect(result).toBeNull()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("extractUnavailableToolName", () => {
|
||||||
|
it("#given unavailable tool error with quoted tool name #when extracting #then returns tool name", () => {
|
||||||
|
//#given
|
||||||
|
const error = { message: "model tried to call unavailable tool 'invalid'" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = extractUnavailableToolName(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBe("invalid")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("#given error without unavailable tool name #when extracting #then returns null", () => {
|
||||||
|
//#given
|
||||||
|
const error = { message: "dummy_tool appeared without tool name" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = extractUnavailableToolName(error)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@ -3,6 +3,7 @@ export type RecoveryErrorType =
|
|||||||
| "thinking_block_order"
|
| "thinking_block_order"
|
||||||
| "thinking_disabled_violation"
|
| "thinking_disabled_violation"
|
||||||
| "assistant_prefill_unsupported"
|
| "assistant_prefill_unsupported"
|
||||||
|
| "unavailable_tool"
|
||||||
| null
|
| null
|
||||||
|
|
||||||
function getErrorMessage(error: unknown): string {
|
function getErrorMessage(error: unknown): string {
|
||||||
@ -43,6 +44,16 @@ export function extractMessageIndex(error: unknown): number | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function extractUnavailableToolName(error: unknown): string | null {
|
||||||
|
try {
|
||||||
|
const message = getErrorMessage(error)
|
||||||
|
const match = message.match(/unavailable tool ['"]?([^'".\s]+)['"]?/)
|
||||||
|
return match ? match[1] : null
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function detectErrorType(error: unknown): RecoveryErrorType {
|
export function detectErrorType(error: unknown): RecoveryErrorType {
|
||||||
try {
|
try {
|
||||||
const message = getErrorMessage(error)
|
const message = getErrorMessage(error)
|
||||||
@ -74,6 +85,16 @@ export function detectErrorType(error: unknown): RecoveryErrorType {
|
|||||||
return "tool_result_missing"
|
return "tool_result_missing"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
message.includes("dummy_tool") ||
|
||||||
|
message.includes("unavailable tool") ||
|
||||||
|
message.includes("model tried to call unavailable") ||
|
||||||
|
message.includes("nosuchtoolarror") ||
|
||||||
|
message.includes("no such tool")
|
||||||
|
) {
|
||||||
|
return "unavailable_tool"
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
} catch {
|
} catch {
|
||||||
return null
|
return null
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user