import { APICallError } from 'ai'; export type ErrorPayload = { message: string; type: string; details?: Record; }; export function toErrorPayload(err: unknown): ErrorPayload { let actualError = err; if ( err && typeof err === 'object' && 'error' in err && Object.keys(err).length === 1 ) { actualError = (err as { error: unknown }).error; } const asObj = actualError && typeof actualError === 'object' ? (actualError as Record) : undefined; let message = ''; let errorType = 'unknown'; const details: Record = {}; if (APICallError.isInstance(actualError)) { errorType = 'api_error'; message = actualError.message || 'API call failed'; details.name = actualError.name; details.statusCode = actualError.statusCode; details.url = actualError.url; details.isRetryable = actualError.isRetryable; if (actualError.responseBody) { details.responseBody = actualError.responseBody; try { const parsed = JSON.parse(actualError.responseBody); if (parsed.error) { if (typeof parsed.error === 'string') { message = parsed.error; } else if (parsed.error.message) { message = parsed.error.message; } } if (parsed.error?.type) { details.apiErrorType = parsed.error.type; } if (parsed.error?.code) { details.apiErrorCode = parsed.error.code; } } catch {} } if (actualError.requestBodyValues) { details.requestBodyValues = actualError.requestBodyValues; } if (actualError.responseHeaders) { details.responseHeaders = actualError.responseHeaders; } if (actualError.cause) { const cause = actualError.cause as Record | undefined; details.cause = { message: typeof cause?.message === 'string' ? cause.message : undefined, code: cause?.code, status: cause?.status ?? cause?.statusCode, }; } return { message, type: errorType, details }; } if ( asObj && 'type' in asObj && asObj.type === 'error' && 'error' in asObj && typeof asObj.error === 'object' && asObj.error ) { const errorObj = asObj.error as Record; if (typeof errorObj.message === 'string') { message = errorObj.message; } if (typeof errorObj.type === 'string') { errorType = errorObj.type; details.errorType = errorObj.type; } if (typeof errorObj.code === 'string') { details.code = errorObj.code; } if ('param' in errorObj) { details.param = errorObj.param; } return { message, type: errorType, details }; } if (asObj) { if ('name' in asObj && typeof asObj.name === 'string') { errorType = asObj.name; details.name = asObj.name; } if ('type' in asObj && typeof asObj.type === 'string') { errorType = asObj.type; details.type = asObj.type; } if ('code' in asObj && asObj.code != null) { details.code = asObj.code; } if ('status' in asObj && asObj.status != null) { details.status = asObj.status; } if ('statusCode' in asObj && asObj.statusCode != null) { details.statusCode = asObj.statusCode; } } if (asObj && typeof asObj.message === 'string' && asObj.message) { message = asObj.message; } else if (typeof actualError === 'string') { message = actualError; } else if (asObj && typeof asObj.error === 'string' && asObj.error) { message = asObj.error; } else if ( asObj && typeof asObj.responseBody === 'string' && asObj.responseBody ) { details.responseBody = asObj.responseBody; try { const parsed = JSON.parse(asObj.responseBody); if (parsed.error) { if (typeof parsed.error === 'string') { message = parsed.error; } else if (typeof parsed.error.message === 'string') { message = parsed.error.message; } else { message = asObj.responseBody; } } else { message = asObj.responseBody; } } catch { message = asObj.responseBody; } } else if (asObj?.statusCode && asObj.url) { message = `HTTP ${String(asObj.statusCode)} error at ${String(asObj.url)}`; details.url = asObj.url; } else if (asObj?.name) { message = String(asObj.name); } else { message = 'An error occurred'; } if (asObj) { if ('url' in asObj) details.url = asObj.url; if ('isRetryable' in asObj) details.isRetryable = asObj.isRetryable; if ('data' in asObj) details.data = asObj.data; if (asObj.cause) { const c = asObj.cause as Record | undefined; details.cause = { message: typeof c?.message === 'string' ? c.message : undefined, code: c?.code, status: c?.status ?? c?.statusCode, }; } if ( (asObj as { response?: { status?: unknown; statusText?: unknown } }) ?.response?.status ) { details.response = { status: ( asObj as { response?: { status?: unknown; statusText?: unknown } } ).response?.status, statusText: ( asObj as { response?: { status?: unknown; statusText?: unknown } } ).response?.statusText, }; } } return { message, type: errorType, details: Object.keys(details).length ? details : undefined, }; }