"use client"; import { useState } from "react"; import { ExternalLink, ChevronDown, ChevronUp } from "lucide-react"; import { cn } from "@/lib/utils"; import { ToolUseBlock } from "./ToolUseBlock"; interface ToolWebFetchProps { input: { url: string; prompt?: string; }; result?: string; isError?: boolean; isRunning?: boolean; startedAt?: number; completedAt?: number; } // Very rough HTTP status parsing from result text function parseStatus(result: string): number | null { const m = result.match(/^(?:HTTP[^\n]*\s)?(\d{3})\b/m); if (m) return parseInt(m[1], 10); return null; } function StatusBadge({ code }: { code: number | null }) { if (!code) return null; const isOk = code >= 200 && code < 300; return ( {code} ); } const MAX_VISIBLE = 80; export function ToolWebFetch({ input, result, isError = false, isRunning = false, startedAt, completedAt, }: ToolWebFetchProps) { const [showFull, setShowFull] = useState(false); const status = result ? parseStatus(result) : null; const isTruncated = !showFull && result && result.length > MAX_VISIBLE * 10; return ( {/* URL header */} e.stopPropagation()} className="font-mono text-xs text-brand-400 hover:text-brand-300 hover:underline truncate flex-1 flex items-center gap-1" > {input.url} {status && } {/* Prompt if any */} {input.prompt && ( Prompt: {input.prompt} )} {/* Response body */} {isRunning ? ( Fetching… ) : isError ? ( {result} ) : result ? ( {isTruncated ? result.slice(0, MAX_VISIBLE * 10) : result} {isTruncated && ( setShowFull(true)} className="flex items-center gap-1 mx-3 mb-2 text-xs text-brand-400 hover:text-brand-300" > Show full response ({Math.round(result.length / 1024)}KB) )} {showFull && ( setShowFull(false)} className="flex items-center gap-1 mx-3 mb-2 text-xs text-surface-400 hover:text-surface-200" > Collapse )} ) : null} ); }