"use client"; import { useState } from "react"; import { ChevronRight, Globe, Code2, FileSearch, Image as ImageIcon, Brain, Loader2, CheckCircle2, XCircle, ShieldAlert, Wrench } from "lucide-react"; import type { Part } from "@/lib/client/types"; import { cn, Button } from "../ui"; const ICONS: Record> = { web_search: Globe, fetch_page: Globe, python: Code2, search_documents: FileSearch, generate_image: ImageIcon, save_memory: Brain }; const LABELS: Record) => string> = { web_search: i => `Recherche web : « ${i.query} »`, fetch_page: i => `Lecture de ${String(i.url).replace(/^https?:\/\//, "").slice(0, 60)}`, python: () => "Exécution Python", search_documents: i => `Recherche dans les documents : « ${i.query} »`, generate_image: i => `Génération d'image : « ${String(i.prompt).slice(0, 60)} »`, save_memory: i => `Mémoire proposée : « ${String(i.content).slice(0, 60)} »`, }; export function ToolCallCard({ part, onApprove }: { part: Extract; onApprove?: (approve: boolean) => void }) { const [open, setOpen] = useState(false); const Icon = ICONS[part.name] ?? Wrench; const input = (part.input ?? {}) as Record; const label = LABELS[part.name]?.(input) ?? part.name; const out = part.output as Record | string | undefined; return (
{part.status === "pending_approval" && onApprove &&
Cet outil requiert ton approbation.
} {open && (
Entrée
{part.name === "python" ?
{String(input.code ?? "")}
:
{JSON.stringify(input, null, 2)}
}
{part.error &&
{part.error}
} {out !== undefined &&
Résultat
}
)}
); } function ToolOutput({ name, out }: { name: string; out: Record | string }) { if (typeof out === "string") return
{out}
; if (name === "web_search" && Array.isArray(out.results)) return
    {(out.results as { title: string; url: string; snippet: string }[]).map((r, i) =>
  • {r.title}
    {r.url}
    {r.snippet}
  • )}
; if (name === "python") return
{!!out.stdout &&
{String(out.stdout)}
}{!!out.stderr &&
{String(out.stderr)}
}
code de sortie {String(out.exitCode)} · {String(out.durationMs)} ms{out.timedOut ? " · délai dépassé" : ""}
; if (name === "search_documents" && Array.isArray(out.passages)) return
    {(out.passages as { file: string; page: number | null; score: number; text: string }[]).map((p, i) =>
  • {p.file}{p.page ? ` · p. ${p.page}` : ""} · score {p.score}
    {p.text}
  • )}
; if (name === "fetch_page" && typeof out.text === "string") return
{String(out.title ?? out.url)}
{(out.text as string).slice(0, 3000)}{(out.text as string).length > 3000 ? "…" : ""}
; return
{JSON.stringify(out, null, 2).slice(0, 6000)}
; }