/** `fetch` — reader-mode URL fetch; output is markdown with a metadata header. */ import type { ReactNode } from "react"; import { Badge, InvalidArg, Kv, KvGrid, ResultText } from "../parts"; import type { ToolRenderer, ToolRenderProps } from "../types"; import { detailsRecord, num, str, truncate } from "../util"; /** Subset of the tool's `ReadUrlToolDetails` we render. */ interface FetchDetails { url: string | null; finalUrl: string | null; contentType: string | null; method: string | null; truncated: boolean; notes: string[]; } function fetchDetails(record: Record | null): FetchDetails | null { if (!record) return null; const notes: string[] = []; if (Array.isArray(record.notes)) { for (const note of record.notes) { const text = str(note); if (text) notes.push(text); } } return { url: str(record.url), finalUrl: str(record.finalUrl), contentType: str(record.contentType), method: str(record.method), truncated: record.truncated === true, notes, }; } function Summary({ args, result }: ToolRenderProps): ReactNode { const url = str(args.url) ?? str(args.path); const method = (str(args.method) ?? "").toUpperCase(); const details = fetchDetails(detailsRecord(result)); return ( <> {url ? {truncate(url, 90)} : } {method && method !== "GET" && ( <> {" "} {method} )} {args.raw === true && ( <> {" "} raw )} {details?.truncated && ( <> {" "} truncated )} ); } function Body({ args, result }: ToolRenderProps): ReactNode { const url = str(args.url) ?? str(args.path); const method = (str(args.method) ?? "").toUpperCase(); const timeout = num(args.timeout); const details = fetchDetails(detailsRecord(result)); const redirected = Boolean(details?.finalUrl && details.url && details.finalUrl !== details.url); return ( <> {url ?? } {method && method !== "GET" && {method}} {args.raw === true && raw} {timeout != null && `${timeout}s`} {redirected && details?.finalUrl} {details?.contentType} {details?.method} {details && details.notes.length > 0 && details.notes.join("; ")} {details?.truncated && output truncated} ); } export const fetchRenderer: ToolRenderer = { Summary, Body };