Spaces:
Running
Running
| // 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 }); | |