Spaces:
Running
Running
File size: 6,427 Bytes
0f3c25b 4163d36 0f3c25b 4163d36 0f3c25b 4163d36 c53286a 0f3c25b 4163d36 b819eec 4163d36 0f3c25b 4163d36 0f3c25b 4163d36 b819eec 4163d36 0f3c25b 4163d36 0f3c25b 4163d36 0f3c25b cb1c42d 0f3c25b b819eec 0f3c25b b819eec 0f3c25b 4163d36 259107b 0f3c25b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | // debug-panel.jsx — floating developer panel shared across all variants.
// Surfaces: recent exchanges, fact-match status, backend, latency, and the
// full keyword-lookup table from the Python reference.
function DebugPanel({ debug, onClose, palette, font }) {
const [tab, setTab] = React.useState("turns");
return (
<div style={{
position: "absolute", right: 16, bottom: 16, top: 16,
width: 380, maxWidth: "44vw",
background: palette.bg, color: palette.fg,
border: `1px solid ${palette.muted}`,
borderRadius: 10,
fontFamily: font, fontSize: 12,
display: "flex", flexDirection: "column",
boxShadow: "0 10px 30px rgba(0,0,0,.35)",
zIndex: 50,
overflow: "hidden",
}}>
<div style={{
padding: "8px 12px",
borderBottom: `1px solid ${palette.muted}`,
display: "flex", alignItems: "center", justifyContent: "space-between",
}}>
<div style={{ display: "flex", gap: 10, alignItems: "center" }}>
<span style={{ color: palette.accent }}>●</span>
<span style={{ letterSpacing: 0.8, textTransform: "uppercase", fontSize: 11 }}>
fetch pup / debug
</span>
</div>
<button onClick={onClose} aria-label="Close debug panel" style={{
background: "transparent", border: "none", color: palette.dim,
cursor: "pointer", fontSize: 14, padding: "0 4px",
}}>×</button>
</div>
<div style={{
display: "flex", gap: 2,
padding: "6px 10px 0",
borderBottom: `1px solid ${palette.muted}`,
}}>
{[
{ id: "turns", label: "turns" },
{ id: "intents", label: "intents" },
{ id: "keywords", label: "keywords" },
{ id: "about", label: "about" },
].map(t => (
<button key={t.id} onClick={() => setTab(t.id)} style={{
background: "transparent",
color: tab === t.id ? palette.fg : palette.dim,
borderBottom: tab === t.id ? `2px solid ${palette.accent}` : "2px solid transparent",
border: "none", borderRadius: 0,
padding: "6px 8px",
fontFamily: "inherit", fontSize: 12, cursor: "pointer",
}}>{t.label}</button>
))}
</div>
<div style={{ flex: 1, overflowY: "auto", padding: 12 }}>
{tab === "turns" && <DebugLog debug={debug} palette={palette} />}
{tab === "intents" && <DebugIntents palette={palette} />}
{tab === "keywords" && <DebugKB palette={palette} />}
{tab === "about" && <DebugAbout palette={palette} />}
</div>
</div>
);
}
function DebugLog({ debug, palette }) {
if (debug.length === 0) {
return (
<div style={{ color: palette.dim, fontStyle: "italic", padding: "8px 4px" }}>
No turns yet. Ask Fetch something.
</div>
);
}
return (
<div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
{debug.map((d, i) => (
<div key={i} style={{
border: `1px solid ${palette.muted}`,
borderRadius: 6,
padding: 8,
}}>
<div style={{ color: palette.dim, fontSize: 11, display: "flex", justifyContent: "space-between", marginBottom: 4 }}>
<span>{new Date(d.t).toLocaleTimeString()}</span>
<span>{d.backend} · {d.ms}ms</span>
</div>
<div style={{ marginBottom: 4 }}>
<span style={{ color: palette.dim }}>user> </span>
{d.user}
</div>
<div style={{ marginBottom: 4 }}>
<span style={{ color: palette.accent }}>fetch> </span>
{d.reply}
</div>
<div style={{ color: palette.dim, fontSize: 11 }}>
{"source: "}
<span style={{
color: d.source === "error" ? "#ff6b6b"
: d.source === "fallback" ? palette.dim
: palette.accent,
}}>
{d.source === "fact" ? `fact · ${d.fact?.keyword}`
: d.source === "intent" ? `intent · ${d.label}`
: d.source || "unknown"}
</span>
</div>
</div>
))}
</div>
);
}
function DebugKB({ palette }) {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div style={{ color: palette.dim, marginBottom: 4 }}>
{FETCH_KNOWLEDGE_BASE.length} keywords · first match wins
</div>
{FETCH_KNOWLEDGE_BASE.map(([k, v]) => (
<div key={k} style={{
border: `1px solid ${palette.muted}`,
borderRadius: 6,
padding: 8,
}}>
<div style={{ color: palette.accent, marginBottom: 3 }}>{k}</div>
<div style={{ color: palette.fg, lineHeight: 1.4 }}>{v}</div>
</div>
))}
</div>
);
}
function DebugIntents({ palette }) {
return (
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<div style={{ color: palette.dim, marginBottom: 4 }}>
{FETCH_INTENTS.length} intents · first match wins
</div>
{FETCH_INTENTS.map(intent => (
<div key={intent.label} style={{
border: `1px solid ${palette.muted}`,
borderRadius: 6,
padding: 8,
}}>
<div style={{ color: palette.accent, marginBottom: 3 }}>{intent.label}</div>
<div style={{ color: palette.fg, lineHeight: 1.4 }}>{intent.response}</div>
</div>
))}
</div>
);
}
function DebugAbout({ palette }) {
return (
<div style={{ lineHeight: 1.6, color: palette.fg, display: "flex", flexDirection: "column", gap: 10 }}>
<div>Fetch Pup is a static browser demo — there is no model running.</div>
<div>Responses come from two layers: an intent matcher that handles greetings and small talk, and a keyword lookup table that returns dog facts verbatim. If neither matches, you get one of three fallback replies.</div>
<div>The generative version, powered by Meta's BlenderBot-400M-distill, runs separately as a <a href="https://huggingface.co/spaces/ElisaTrippetti/Fetch-Good-Boi" target="_blank" rel="noopener noreferrer" style={{ color: palette.accent, textDecoration: "underline" }}>Docker Space</a>.</div>
<div style={{ color: palette.dim }}>Designed with Claude Design · Built with Claude Code</div>
</div>
);
}
Object.assign(window, { DebugPanel });
|