| 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<string, unknown>; |
| 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<string, unknown>) : null; |
| const dataObj = data && typeof data === "object" && !Array.isArray(data) ? (data as Record<string, unknown>) : 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<string, unknown>) : 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<string, unknown>) : 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<unknown> { |
| try { |
| return await response.json(); |
| } catch { |
| try { |
| return await response.text(); |
| } catch { |
| return null; |
| } |
| } |
| } |
|
|