refactor(errors): share api error payload parsing
This commit is contained in:
parent
dbc9d3dd70
commit
d3ffa1e4e7
@ -4,7 +4,9 @@ import {
|
||||
BILLING_ERROR_USER_MESSAGE,
|
||||
formatBillingErrorMessage,
|
||||
formatAssistantErrorText,
|
||||
getApiErrorPayloadFingerprint,
|
||||
formatRawAssistantErrorForUi,
|
||||
isRawApiErrorPayload,
|
||||
} from "./pi-embedded-helpers.js";
|
||||
import { makeAssistantMessageFixture } from "./test-helpers/assistant-message-fixtures.js";
|
||||
|
||||
@ -159,3 +161,14 @@ describe("formatRawAssistantErrorForUi", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("raw API error payload helpers", () => {
|
||||
it("recognizes provider-prefixed JSON payloads for observation fingerprints", () => {
|
||||
const raw =
|
||||
'Ollama API error: {"type":"error","error":{"type":"server_error","message":"Boom"},"request_id":"req_123"}';
|
||||
|
||||
expect(isRawApiErrorPayload(raw)).toBe(true);
|
||||
expect(getApiErrorPayloadFingerprint(raw)).toContain("server_error");
|
||||
expect(getApiErrorPayloadFingerprint(raw)).toContain("req_123");
|
||||
});
|
||||
});
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
extractLeadingHttpStatus,
|
||||
formatRawAssistantErrorForUi,
|
||||
isCloudflareOrHtmlErrorPage,
|
||||
parseApiErrorPayload,
|
||||
} from "../../shared/assistant-error-format.js";
|
||||
export {
|
||||
extractLeadingHttpStatus,
|
||||
@ -223,9 +224,6 @@ export function extractObservedOverflowTokenCount(errorMessage?: string): number
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Allow provider-wrapped API payloads such as "Ollama API error 400: {...}".
|
||||
const ERROR_PAYLOAD_PREFIX_RE =
|
||||
/^(?:error|(?:[a-z][\w-]*\s+)?api\s*error|apierror|openai\s*error|anthropic\s*error|gateway\s*error)(?:\s+\d{3})?[:\s-]+/i;
|
||||
const FINAL_TAG_RE = /<\s*\/?\s*final\s*>/gi;
|
||||
const ERROR_PREFIX_RE =
|
||||
/^(?:error|(?:[a-z][\w-]*\s+)?api\s*error|openai\s*error|anthropic\s*error|gateway\s*error|request failed|failed|exception)(?:\s+\d{3})?[:\s-]+/i;
|
||||
@ -482,63 +480,6 @@ function shouldRewriteContextOverflowText(raw: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
type ErrorPayload = Record<string, unknown>;
|
||||
|
||||
function isErrorPayloadObject(payload: unknown): payload is ErrorPayload {
|
||||
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
||||
return false;
|
||||
}
|
||||
const record = payload as ErrorPayload;
|
||||
if (record.type === "error") {
|
||||
return true;
|
||||
}
|
||||
if (typeof record.request_id === "string" || typeof record.requestId === "string") {
|
||||
return true;
|
||||
}
|
||||
if ("error" in record) {
|
||||
const err = record.error;
|
||||
if (err && typeof err === "object" && !Array.isArray(err)) {
|
||||
const errRecord = err as ErrorPayload;
|
||||
if (
|
||||
typeof errRecord.message === "string" ||
|
||||
typeof errRecord.type === "string" ||
|
||||
typeof errRecord.code === "string"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseApiErrorPayload(raw: string): ErrorPayload | null {
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
const candidates = [trimmed];
|
||||
if (ERROR_PAYLOAD_PREFIX_RE.test(trimmed)) {
|
||||
candidates.push(trimmed.replace(ERROR_PAYLOAD_PREFIX_RE, "").trim());
|
||||
}
|
||||
for (const candidate of candidates) {
|
||||
if (!candidate.startsWith("{") || !candidate.endsWith("}")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const parsed = JSON.parse(candidate) as unknown;
|
||||
if (isErrorPayloadObject(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getApiErrorPayloadFingerprint(raw?: string): string | null {
|
||||
if (!raw) {
|
||||
return null;
|
||||
|
||||
@ -41,7 +41,7 @@ function isErrorPayloadObject(payload: unknown): payload is ErrorPayload {
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseApiErrorPayload(raw: string): ErrorPayload | null {
|
||||
export function parseApiErrorPayload(raw?: string): ErrorPayload | null {
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user