export type ResponseMessageShell = { result: string; why: string[]; next_action: string[]; }; function asTrimmedString(value: unknown): string { return typeof value === "string" ? value.trim() : ""; } function asTrimmedStringList(value: unknown): string[] { if (!Array.isArray(value)) return []; return value.map((v) => asTrimmedString(v)).filter(Boolean); } export function parseMessageShell(value: unknown): ResponseMessageShell | null { if (!value || typeof value !== "object" || Array.isArray(value)) return null; const obj = value as Record; const result = asTrimmedString(obj.result); const why = asTrimmedStringList(obj.why); const nextAction = asTrimmedStringList(obj.next_action ?? obj.next_actions); if (!result && why.length === 0 && nextAction.length === 0) return null; return { result: result || "Request complete.", why, next_action: nextAction, }; } export function resolveMessageShell(data: unknown, detail?: unknown): ResponseMessageShell | null { const detailObj = detail && typeof detail === "object" && !Array.isArray(detail) ? (detail as Record) : null; const dataObj = data && typeof data === "object" && !Array.isArray(data) ? (data as Record) : null; const fromDetail = parseMessageShell(detailObj?.message_shell); if (fromDetail) return fromDetail; return parseMessageShell(dataObj?.message_shell); } export function normalizeResultShell(result: string, why: string[] = [], nextAction: string[] = []): ResponseMessageShell { return { result: asTrimmedString(result) || "Request complete.", why: asTrimmedStringList(why), next_action: asTrimmedStringList(nextAction), }; } export function resolveApiErrorInfo(data: unknown, fallback: string): { shell: ResponseMessageShell | null; text: string } { const dataObj = data && typeof data === "object" && !Array.isArray(data) ? (data as Record) : null; const detail = dataObj?.detail; const shell = resolveMessageShell(data, detail); if (shell) return { shell, text: shell.result }; const detailText = asTrimmedString(detail); if (detailText) return { shell: null, text: detailText }; const detailObj = detail && typeof detail === "object" && !Array.isArray(detail) ? (detail as Record) : null; const detailObjMessage = asTrimmedString(detailObj?.message) || asTrimmedString(detailObj?.error); if (detailObjMessage) return { shell: null, text: detailObjMessage }; const message = asTrimmedString(dataObj?.message) || asTrimmedString(dataObj?.error); if (message) return { shell: null, text: message }; return { shell: null, text: fallback }; } export async function parseResponseBody(response: Response): Promise { try { return await response.json(); } catch { try { return await response.text(); } catch { return null; } } }