// Real-backend views: API keys + Playground. // Wires against /v1/admin/api-keys and /v1/chat/completions. const { useState: useStateV, useEffect: useEffectV } = React; // ─── API keys view ─────────────────────────────────────── const ApiKeysView = () => { const t = window.t; const [keys, setKeys] = useStateV([]); const [loading, setLoading] = useStateV(false); const [error, setError] = useStateV(''); const [name, setName] = useStateV(''); const [owner, setOwner] = useStateV('platform'); const [env, setEnv] = useStateV('prod'); const [lastCreated, setLastCreated] = useStateV(null); const [creating, setCreating] = useStateV(false); const load = async () => { setLoading(true); setError(''); try { const r = await fetch('/v1/admin/api-keys'); if (!r.ok) throw new Error(`HTTP ${r.status}`); const data = await r.json(); setKeys(Array.isArray(data) ? data : (data.api_keys || data.keys || [])); } catch (e) { setError(e.message); } finally { setLoading(false); } }; useEffectV(() => { load(); }, []); const create = async () => { if (!name.trim()) return; setCreating(true); setError(''); try { const r = await fetch('/v1/admin/api-keys', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: name.trim(), labels: { owner, env } }), }); if (!r.ok) throw new Error(`HTTP ${r.status}: ${await r.text()}`); const data = await r.json(); setLastCreated(data); setName(''); await load(); } catch (e) { setError(e.message); } finally { setCreating(false); } }; const copy = (s) => navigator.clipboard?.writeText(s); return (

{t('keys.proxyKeys') || 'Proxy API keys'}

setName(e.target.value)} />
setOwner(e.target.value)} />
setEnv(e.target.value)} />
{lastCreated && (
{t('keys.oneTimeNote') || 'Shown once. Save it now.'}
{lastCreated.api_key || lastCreated.key || lastCreated.token || JSON.stringify(lastCreated)}
)} {error &&
{error}
}

{t('keys.existing') || 'Existing keys'}

{keys.length}
{keys.length === 0 && (
{loading ? (t('keys.loading') || 'Loading…') : (t('keys.empty') || 'No keys yet.')}
)} {keys.map((k, i) => (
{k.name || k.id}
{k.prefix ? k.prefix + '•••' : (k.id || '').slice(0, 12) + '…'} {k.labels && ' · ' + Object.entries(k.labels).map(([x, y]) => `${x}=${y}`).join(' · ')}
{k.created_at || k.createdAt || ''}
))}
); }; // ─── Playground view ───────────────────────────────────── // Two-pane comparison: AI router (auto-selects model based on prompt analysis) // vs. user-pinned model. Both run in parallel; outputs displayed side-by-side // with full routing rationale, cost, latency, and tokens. const PlaygroundView = () => { const t = window.t; const providers = window.LLMGateData.providers; const availableModels = providers .filter(p => p.enabled) .flatMap(p => p.modelList.map(m => ({ provider: p.id, model: m, full: `${p.id}:${m}` }))); const [router, setRouter] = useStateV('openai:auto'); const [pinned, setPinned] = useStateV('openai:gpt-4o-mini'); const [system, setSystem] = useStateV('You are a helpful assistant.'); const [prompt, setPrompt] = useStateV('Summarize: Quantum entanglement correlates particles non-locally.'); const [token, setToken] = useStateV(''); const [temperature, setTemp] = useStateV(0.7); const [running, setRunning] = useStateV(false); const [routerOut, setRouterOut] = useStateV(null); const [pinnedOut, setPinnedOut] = useStateV(null); const callOne = async (modelId) => { const t0 = performance.now(); const headers = { 'Content-Type': 'application/json' }; if (token.trim()) headers['Authorization'] = 'Bearer ' + token.trim(); try { const r = await fetch('/v1/chat/completions', { method: 'POST', headers, body: JSON.stringify({ model: modelId, messages: [ ...(system.trim() ? [{ role: 'system', content: system.trim() }] : []), { role: 'user', content: prompt.trim() }, ], temperature: Number(temperature), }), }); const elapsed = Math.round(performance.now() - t0); const body = await r.json().catch(() => ({})); if (!r.ok) { return { ok: false, elapsed, error: body.detail || body.error?.message || `HTTP ${r.status}` }; } return { ok: true, elapsed, content: body.choices?.[0]?.message?.content || '(empty)', model: body.model || modelId, finish: body.choices?.[0]?.finish_reason || '-', usage: body.usage || {}, meta: body.control_plane || {}, }; } catch (e) { return { ok: false, elapsed: Math.round(performance.now() - t0), error: e.message }; } }; const run = async () => { if (!prompt.trim()) return; setRunning(true); setRouterOut({ loading: true }); setPinnedOut({ loading: true }); const [a, b] = await Promise.all([callOne(router), callOne(pinned)]); setRouterOut(a); setPinnedOut(b); setRunning(false); }; return (

{t('play.title') || 'Playground'}

side-by-side · POST /v1/chat/completions
setTemp(e.target.value)} />
setToken(e.target.value)} />
); }; const ResponsePane = ({ title, subtitle, icon, data, showRouting }) => { const t = window.t; return (

{title}

{subtitle}
{!data &&
{t('play.idle') || 'Idle. Run a comparison to populate.'}
} {data?.loading &&
{t('play.calling') || 'Calling…'}
} {data && !data.loading && !data.ok && (
{data.error}
{data.elapsed}ms
)} {data && !data.loading && data.ok && ( <>
{showRouting && data.meta && (
{t('play.routingDecision') || 'Routing decision'}
{data.meta.routing?.reason && } {data.meta.routing?.fallback_chain?.length > 0 && ( )}
)}
{data.content}
)}
); }; const Stat = ({ label, value, mono }) => (
{label}
{value}
); const Kv = ({ k, v }) => v == null ? null : (
{k} {String(v)}
); Object.assign(window, { ApiKeysView, PlaygroundView });