import React, { useEffect, useRef, useState } from "react"; import { http } from "../lib/api"; import { X, Play, Trash2, Bug, Activity, Check, AlertCircle, Loader2, ChevronRight, Filter } from "lucide-react"; const TABS = [ { id: "events", label: "Événements", icon: Activity }, { id: "selftest", label: "Auto-test", icon: Bug }, ]; const FILTER_OPTS = [ { id: "all", label: "Tout" }, { id: "tool", label: "Tools" }, { id: "delta", label: "Deltas" }, { id: "error", label: "Erreurs" }, ]; export default function DebugWindow({ events, onClose, onClearEvents }) { const [tab, setTab] = useState("events"); const [filter, setFilter] = useState("all"); const [running, setRunning] = useState(false); const [results, setResults] = useState(null); const scrollRef = useRef(null); useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [events]); const runSelftest = async () => { setRunning(true); setResults(null); try { const r = await http.post("/agent/selftest"); setResults(r.data); } catch (e) { setResults({ ok: false, error: e?.response?.data?.detail || e.message }); } finally { setRunning(false); } }; const filteredEvents = events.filter((e) => { if (filter === "all") return true; if (filter === "tool") return e.type?.startsWith("tool_"); if (filter === "delta") return e.type === "delta"; if (filter === "error") return e.type === "error"; return true; }); return (
{/* Header */}
Console debug temps réel
{/* Tabs */}
{TABS.map((t) => { const Icon = t.icon; const active = t.id === tab; return ( ); })}
{/* Body */} {tab === "events" && ( <>
{FILTER_OPTS.map((f) => ( ))} {filteredEvents.length}/{events.length}
{filteredEvents.length === 0 && (

En attente d'évènements…

Lance une conversation pour voir les SSE / tool calls en live.

)} {filteredEvents.map((e, i) => ( ))}
)} {tab === "selftest" && (
{results && (
{results.error && (
{results.error}
)} {results.steps?.map((s, i) => ( ))} {results.steps && (
{results.ok ? "✓ Tous les tests passent — agent opérationnel." : "✗ Au moins un test échoue — vérifie l'agent local."}
)}
)}
)}
); } const StepCard = ({ step, index }) => { const [open, setOpen] = useState(false); return (
{open && (
{JSON.stringify(step.result, null, 2)}
        
)}
); }; const EventLine = ({ evt }) => { const meta = TYPE_META[evt.type] || { color: "#6D5F82", icon: "·" }; return (
{evt._t || "--:--:--"} {meta.icon} {evt.type} {compact(evt)}
); }; const TYPE_META = { delta: { color: "#A89BBD", icon: "·" }, tool_start: { color: "#06B6D4", icon: "▸" }, tool_executing: { color: "#06B6D4", icon: "▶" }, tool_result: { color: "#34D399", icon: "✓" }, done: { color: "#A855F7", icon: "■" }, error: { color: "#EF4444", icon: "✗" }, }; function compact(evt) { const { type, _t, ...rest } = evt; if (type === "delta") return `"${(rest.content || "").slice(0, 100)}"`; if (type === "tool_start") return `${rest.name} #${rest.id?.slice(-6)}`; if (type === "tool_executing") return `${rest.name} ${JSON.stringify(rest.arguments).slice(0, 100)}`; if (type === "tool_result") return `${rest.name} → ${rest.result?.ok === false ? "ERR: " + (rest.result?.error || "").slice(0, 60) : "ok"}`; if (type === "done") return `mood=${rest.mood} verified=${rest.verified || "-"}`; if (type === "error") return rest.content; return JSON.stringify(rest).slice(0, 100); }