umairali64488's picture
Update frontend/index.html
f4188b9 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>⚡ CodeDebug</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;700&family=Syne:wght@600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script>
<style>
/* ════════════════════════════════════════
BASE - PROFESSIONAL MONOCHROME
════════════════════════════════════════ */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
/* Professional grayscale palette */
--bg: #ffffff;
--bg2: #f8f9fa;
--bg3: #f1f3f4;
--bg4: #e8eaed;
--bg5: #dadce0;
--line: #dadce0;
--line2: #c6c9ce;
--ink: #202124;
--ink2: #5f6368;
--ink3: #80868b;
/* Single accent: Deep Navy */
--accent: #1a73e8;
--accent-light: rgba(26,115,232,0.08);
--accent-glow: rgba(26,115,232,0.15);
/* Status colors - muted */
--green: #137333;
--red: #d93025;
--amber: #f9ab00;
--mono:'JetBrains Mono',monospace;
--sans:'Syne',sans-serif;
--r:4px;
}
html,body{height:100%;overflow:hidden}
body{
background:var(--bg);color:var(--ink);
font-family:var(--mono);font-size:13px;
display:flex;flex-direction:column;
}
/* Subtle grid pattern instead of scanlines */
body::after{
content:'';position:fixed;inset:0;pointer-events:none;z-index:9999;
background-image:
linear-gradient(var(--bg5) 1px, transparent 1px),
linear-gradient(90deg, var(--bg5) 1px, transparent 1px);
background-size: 50px 50px;
opacity: 0.3;
}
/* ════════════════════════════════════════
HEADER BAR
════════════════════════════════════════ */
.hdr{
flex-shrink:0;height:48px;
background:var(--bg);border-bottom:1px solid var(--line);
display:flex;align-items:center;padding:0 20px;gap:16px;
box-shadow: 0 1px 2px rgba(60,64,67,0.1);
}
.logo{display:flex;align-items:center;gap:10px}
.logo-gem{
width:28px;height:28px;border-radius:6px;
background:var(--accent);
display:flex;align-items:center;justify-content:center;font-size:14px;
color: white;
}
.logo-txt{font-family:var(--sans);font-size:16px;font-weight:700;letter-spacing:-0.3px;color:var(--ink)}
.logo-txt b{color:var(--accent);font-weight:800}
.hdr-sep{width:1px;height:20px;background:var(--line)}
.hdr-pills{display:flex;gap:8px}
.hp{padding:4px 12px;border-radius:4px;font-size:11px;border:1px solid var(--line);white-space:nowrap;background:var(--bg2);color:var(--ink2);font-weight:500}
.hp1{color:var(--accent);border-color:var(--accent);background:var(--accent-light)}
.hdr-right{margin-left:auto;font-size:11px;color:var(--ink2)}
.hdr-right b{color:var(--accent);font-weight:600}
/* ════════════════════════════════════════
STATUS STRIP
════════════════════════════════════════ */
.sbar{
flex-shrink:0;height:32px;
background:var(--bg2);border-bottom:1px solid var(--line);
display:flex;align-items:center;padding:0 20px;gap:12px;
font-size:12px;color:var(--ink2);
}
.sdot{width:6px;height:6px;border-radius:50%;background:var(--ink3);flex-shrink:0;transition:background .3s}
.sdot.idle {background:var(--ink3)}
.sdot.run {background:var(--accent);animation:pulse 1.5s ease-in-out infinite}
.sdot.done {background:var(--green)}
.sdot.err {background:var(--red)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
#sMsg{flex:1;font-weight:500}
#sTime{color:var(--accent);font-weight:600}
/* ════════════════════════════════════════
3-COLUMN BODY 25 | 50 | 25
════════════════════════════════════════ */
.body{
flex:1;display:grid;
grid-template-columns:25% 50% 25%;
overflow:hidden;min-height:0;
}
/* shared column chrome */
.col{display:flex;flex-direction:column;overflow:hidden;min-height:0}
.col+.col{border-left:1px solid var(--line)}
.col-hdr{
flex-shrink:0;padding:10px 16px;
background:var(--bg);border-bottom:1px solid var(--line);
font-size:11px;text-transform:uppercase;letter-spacing:1px;
color:var(--ink2);display:flex;align-items:center;gap:8px;
font-weight:600;
}
.chd{width:6px;height:6px;border-radius:50%;flex-shrink:0;background:var(--accent)}
.col-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}
/* ════════════════════════════════════════
LEFT 25% — INPUT
════════════════════════════════════════ */
.query-wrap{position:relative}
.q-prompt{
position:absolute;left:12px;top:12px;
color:var(--accent);font-size:14px;font-weight:700;pointer-events:none;z-index:1
}
#qInput{
width:100%;min-height:140px;max-height:360px;
padding:12px 12px 12px 28px;
background:var(--bg);border:1px solid var(--line2);border-radius:var(--r);
color:var(--ink);font-family:var(--mono);font-size:13px;
resize:vertical;outline:none;line-height:1.6;
transition:border-color .2s,box-shadow .2s;
}
#qInput:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
#qInput::placeholder{color:var(--ink3)}
.field-lbl{font-size:11px;color:var(--ink2);margin-bottom:6px;text-transform:uppercase;letter-spacing:0.5px;font-weight:600}
.temp-row{display:flex;align-items:center;gap:12px;font-size:12px;color:var(--ink2)}
.temp-row input[type=range]{flex:1;accent-color:var(--accent);cursor:pointer;height:4px;border-radius:2px}
#tVal{color:var(--accent);min-width:32px;text-align:right;font-weight:600}
.btn-run{
width:100%;padding:12px;
background:var(--accent);
color:#fff;border:none;border-radius:var(--r);
font-family:var(--sans);font-size:13px;font-weight:700;
letter-spacing:0.5px;text-transform:uppercase;cursor:pointer;
transition:all .2s;box-shadow:0 1px 3px rgba(26,115,232,0.3);
}
.btn-run:hover{background:#1557b0;transform:translateY(-1px);box-shadow:0 4px 8px rgba(26,115,232,0.25)}
.btn-run:active{transform:translateY(0)}
.btn-run:disabled{background:var(--bg5);color:var(--ink3);cursor:not-allowed;box-shadow:none;transform:none}
.hint-txt{font-size:11px;color:var(--ink3);text-align:center}
kbd{background:var(--bg3);border:1px solid var(--line2);border-radius:3px;padding:2px 6px;font-size:10px;color:var(--ink2);font-family:var(--mono)}
/* divider line in left col */
.field-sep{height:1px;background:var(--line);margin:8px 0}
/* previous queries list */
.q-history{display:flex;flex-direction:column;gap:8px}
.q-hist-item{
padding:10px 12px;background:var(--bg);border:1px solid var(--line);
border-radius:var(--r);font-size:12px;color:var(--ink2);
cursor:pointer;line-height:1.5;transition:all .15s;
overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
}
.q-hist-item:hover{border-color:var(--accent);color:var(--ink);background:var(--bg2);box-shadow:0 1px 2px rgba(0,0,0,0.05)}
/* ════════════════════════════════════════
MIDDLE 50% — JUDGE OUTPUT
════════════════════════════════════════ */
.judge-panel{
background:var(--bg);border:1px solid var(--line);
border-radius:var(--r);display:flex;flex-direction:column;
flex:1;min-height:0;overflow:hidden;transition:border-color .3s;
box-shadow: 0 1px 3px rgba(60,64,67,0.08);
}
.judge-panel.done{border-color:var(--green);background:var(--bg)}
.jp-head{
flex-shrink:0;display:flex;align-items:center;gap:12px;
padding:12px 16px;
background:var(--bg2);border-bottom:1px solid var(--line);
}
.jp-icon{
width:28px;height:28px;border-radius:6px;flex-shrink:0;
background:var(--accent);
display:flex;align-items:center;justify-content:center;font-size:14px;
color: white;
}
.jp-title{font-family:var(--sans);font-size:14px;font-weight:700;color:var(--ink)}
.jp-sub {font-size:11px;color:var(--ink2);margin-top:2px}
.jp-lat {
margin-left:auto;font-size:11px;color:var(--accent);
padding:4px 10px;background:var(--accent-light);
border:1px solid var(--accent-glow);border-radius:12px;
font-weight:600;
}
/* error analysis box */
.err-box{
flex-shrink:0;margin:16px 16px 0;
background:var(--bg2);border:1px solid var(--line2);
border-radius:var(--r);overflow:hidden;
}
.err-box-hdr{
padding:10px 14px;background:var(--bg3);
font-size:11px;text-transform:uppercase;letter-spacing:0.5px;
color:var(--red);border-bottom:1px solid var(--line);
display:flex;align-items:center;gap:8px;font-weight:600;
}
.err-box-body{padding:14px;font-size:13px;line-height:1.7;color:var(--ink)}
/* corrected code box */
.code-box{
flex:1;display:flex;flex-direction:column;
margin:12px 16px 16px;min-height:0;
background:var(--bg);border:1px solid var(--line2);border-radius:var(--r);
overflow:hidden;
}
.code-box-hdr{
flex-shrink:0;padding:10px 14px;background:var(--bg2);
font-size:11px;text-transform:uppercase;letter-spacing:0.5px;
color:var(--green);border-bottom:1px solid var(--line);
display:flex;align-items:center;gap:8px;font-weight:600;
}
.copy-code-btn{
margin-left:auto;padding:4px 12px;background:var(--bg);
border:1px solid var(--line2);border-radius:3px;
color:var(--ink2);font-size:10px;font-family:var(--mono);cursor:pointer;transition:all .15s;font-weight:500;
}
.copy-code-btn:hover{color:var(--accent);border-color:var(--accent);background:var(--bg3)}
.code-box-body{flex:1;overflow-y:auto;padding:0}
.code-box-body pre{margin:0;border-radius:0;border:none !important;height:100%;background:var(--bg3) !important}
.code-box-body pre code{font-size:13px;line-height:1.6}
/* judge placeholder / skeleton */
.jp-placeholder{
flex:1;display:flex;flex-direction:column;
align-items:center;justify-content:center;
gap:16px;color:var(--ink3);text-align:center;padding:60px 24px;
}
.jp-ph-icon{font-size:48px;opacity:0.2}
.jp-ph-txt{font-size:13px;line-height:1.7;max-width:320px}
.jp-skel{padding:20px 16px;display:flex;flex-direction:column;gap:12px}
.jsk{
height:12px;border-radius:3px;
background:linear-gradient(90deg,var(--bg3) 25%,var(--bg4) 50%,var(--bg3) 75%);
background-size:200% 100%;animation:shim 2s infinite;
}
@keyframes shim{0%{background-position:200% 0}100%{background-position:-200% 0}}
/* ════════════════════════════════════════
RIGHT 25% — PANEL MODELS
════════════════════════════════════════ */
.model-card{
background:var(--bg);border:1px solid var(--line);
border-radius:var(--r);overflow:hidden;transition:all .3s;
box-shadow: 0 1px 2px rgba(60,64,67,0.05);
}
.model-card[data-s="d1"]{border-color:var(--accent);box-shadow:0 2px 8px var(--accent-glow)}
.model-card[data-s="d2"]{border-color:var(--ink2)}
.model-card[data-s="er"]{border-color:var(--red)}
.mc-hdr{
display:flex;align-items:center;gap:12px;padding:12px 14px;
background:var(--bg2);border-bottom:1px solid var(--line);
cursor:pointer;user-select:none;
}
.mc-hdr:hover{background:var(--bg3)}
.mc-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;transition:all .3s}
.mcd1{background:var(--accent)} .mcd2{background:var(--ink2)}
.model-card[data-s="d1"] .mcd1{box-shadow:0 0 0 3px var(--accent-glow)}
.model-card[data-s="d2"] .mcd2{box-shadow:0 0 0 3px rgba(95,99,104,0.15)}
.mc-info{flex:1}
.mc-name{font-family:var(--sans);font-size:12px;font-weight:700;color:var(--ink)}
.mc-id{font-size:10px;color:var(--ink2);margin-top:2px}
.mc-lat{font-size:11px;padding:4px 10px;border-radius:12px;background:var(--bg3);min-width:42px;text-align:center;font-weight:600;color:var(--ink2)}
.model-card[data-s="d1"] .mc-lat{color:var(--accent);background:var(--accent-light)}
.mc-chev{color:var(--ink2);font-size:10px;transition:transform .2s;flex-shrink:0}
.model-card.coll .mc-chev{transform:rotate(-90deg)}
.mc-body{overflow:hidden;transition:max-height .3s ease;max-height:480px}
.model-card.coll .mc-body{max-height:0!important}
.mc-inner{padding:14px;max-height:430px;overflow-y:auto}
/* skeleton */
.skel{display:flex;flex-direction:column;gap:8px;padding:14px}
.sk{
height:10px;border-radius:2px;
background:linear-gradient(90deg,var(--bg3) 25%,var(--bg4) 50%,var(--bg3) 75%);
background-size:200% 100%;animation:shim 1.6s infinite;
}
.sk:nth-child(2){width:78%;animation-delay:.15s}
.sk:nth-child(3){width:62%;animation-delay:.3s}
.sk:nth-child(4){width:85%;animation-delay:.45s}
.mc-empty{padding:28px 14px;text-align:center;color:var(--ink2);font-size:12px}
.mc-eicon{font-size:24px;margin-bottom:8px;opacity:0.3}
.mc-err{color:var(--red);font-size:12px;padding:14px;font-style:italic;background:var(--bg2);border-radius:var(--r)}
/* ════════════════════════════════════════
MARKDOWN RENDERER
════════════════════════════════════════ */
.md p{margin-bottom:10px;line-height:1.7}
.md ul,.md ol{padding-left:20px;margin-bottom:10px}
.md li{margin-bottom:4px}
.md h1,.md h2,.md h3{font-family:var(--sans);font-weight:700;margin:16px 0 8px;color:var(--ink)}
.md h1{font-size:16px;border-bottom:1px solid var(--line);padding-bottom:8px}
.md h2{font-size:14px;color:var(--accent)}
.md h3{font-size:13px;color:var(--ink2)}
.md code{
font-family:var(--mono);font-size:12px;
background:var(--bg3);border:1px solid var(--line2);
padding:2px 6px;border-radius:3px;color:var(--accent);
}
.md pre{
background:var(--bg3)!important;border:1px solid var(--line2);
border-radius:var(--r);padding:14px;overflow-x:auto;margin:12px 0;
}
.md pre code{background:none!important;border:none!important;padding:0!important;color:inherit!important}
.md blockquote{border-left:3px solid var(--accent);padding-left:14px;color:var(--ink2);font-style:italic;margin:12px 0;background:var(--bg2);padding:12px 14px;border-radius:0 var(--r) var(--r) 0}
.md strong{color:var(--ink);font-weight:700}
.md em{color:var(--ink2)}
.md hr{border:none;border-top:1px solid var(--line);margin:16px 0}
.md a{color:var(--accent);text-decoration:none;font-weight:500}
.md a:hover{text-decoration:underline}
.md table{width:100%;border-collapse:collapse;margin:12px 0;font-size:12px;border:1px solid var(--line)}
.md th{background:var(--bg2);color:var(--ink);padding:10px 12px;text-align:left;border:1px solid var(--line);font-weight:600}
.md td{padding:8px 12px;border:1px solid var(--line)}
/* ════════════════════════════════════════
SCROLLBARS
════════════════════════════════════════ */
::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-track{background:var(--bg2)}
::-webkit-scrollbar-thumb{background:var(--line2);border-radius:3px}
::-webkit-scrollbar-thumb:hover{background:var(--ink3)}
/* ════════════════════════════════════════
UTILS
════════════════════════════════════════ */
@keyframes fadeUp{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}
.fu{animation:fadeUp .3s ease forwards}
@media(max-width:800px){
.body{grid-template-columns:1fr;grid-template-rows:auto auto auto;overflow-y:auto}
html,body{overflow-y:auto;height:auto}
.col{overflow:visible;min-height:auto}
.col-body{overflow:visible}
.judge-panel{min-height:300px}
}
</style>
</head>
<body>
<!-- HEADER -->
<div class="hdr">
<div class="logo">
<div class="logo-gem"></div>
<div class="logo-txt"><b>Code</b>Debug</div>
</div>
<div class="hdr-sep"></div>
<div class="hdr-pills">
<span class="hp hp1">Trinity Large</span>
<span class="hp">Nemotron Nano</span>
<span class="hp">StepFun Judge</span>
</div>
<div class="hdr-right">Queries: <b id="qCnt">0</b></div>
</div>
<!-- STATUS -->
<div class="sbar">
<div class="sdot idle" id="sDot"></div>
<span id="sMsg">Ready — enter your code or describe the bug</span>
<span id="sTime"></span>
</div>
<!-- 3-COLUMN BODY -->
<div class="body">
<!-- ══ LEFT 25%: INPUT ══ -->
<div class="col">
<div class="col-hdr"><div class="chd"></div>Input</div>
<div class="col-body">
<div>
<div class="field-lbl">Your code / question</div>
<div class="query-wrap">
<div class="q-prompt">&gt;</div>
<textarea id="qInput" rows="5"
placeholder="Paste buggy code or describe the issue…&#10;&#10;e.g.&#10;def divide(a,b):&#10; return a/b&#10;divide(10,0)"></textarea>
</div>
</div>
<div>
<div class="field-lbl">Temperature</div>
<div class="temp-row">
<input type="range" id="tSlider" min="0" max="1" step="0.05" value="0.3"
oninput="document.getElementById('tVal').textContent=this.value">
<span id="tVal">0.3</span>
</div>
</div>
<button class="btn-run" id="runBtn" onclick="runDebug()">▶ Run Debug</button>
<div class="hint-txt"><kbd>Ctrl</kbd>+<kbd>Enter</kbd> to submit</div>
<div class="field-sep"></div>
<!-- history -->
<div id="histWrap" style="display:none">
<div class="field-lbl" style="margin-bottom:7px">Recent</div>
<div class="q-history" id="histList"></div>
</div>
</div>
</div>
<!-- ══ MIDDLE 50%: JUDGE OUTPUT ══ -->
<div class="col">
<div class="col-hdr">
<div class="chd" style="background:var(--green)"></div>
Judge Output — StepFun Flash
</div>
<div class="col-body">
<div class="judge-panel" id="jPanel">
<div class="jp-head">
<div class="jp-icon"></div>
<div>
<div class="jp-title">StepFun Flash Judge</div>
<div class="jp-sub">stepfun/step-3.5-flash:free · synthesized verdict</div>
</div>
<div class="jp-lat" id="jLat"></div>
</div>
<div id="jBody" style="display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden">
<div class="jp-placeholder" id="jPlaceholder">
<div class="jp-ph-icon">⚖️</div>
<div class="jp-ph-txt">
The judge analyzes both model responses<br>
and returns the exact bug + corrected code.
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ══ RIGHT 25%: PANEL MODELS ══ -->
<div class="col">
<div class="col-hdr"><div class="chd" style="background:var(--ink2)"></div>Debugger Models</div>
<div class="col-body">
<!-- Card 1: Trinity -->
<div class="model-card" id="c0" data-s="idle">
<div class="mc-hdr" onclick="toggleCard(0)">
<div class="mc-dot mcd1"></div>
<div class="mc-info">
<div class="mc-name">Trinity Large</div>
<div class="mc-id">arcee-ai/trinity-large-preview</div>
</div>
<div class="mc-lat" id="l0"></div>
<div class="mc-chev"></div>
</div>
<div class="mc-body">
<div class="mc-empty"><div class="mc-eicon">🔵</div>Awaiting query…</div>
</div>
</div>
<!-- Card 2: Nemotron -->
<div class="model-card" id="c1" data-s="idle">
<div class="mc-hdr" onclick="toggleCard(1)">
<div class="mc-dot mcd2"></div>
<div class="mc-info">
<div class="mc-name">Nemotron Nano</div>
<div class="mc-id">nvidia/nemotron-3-nano-30b-a3b</div>
</div>
<div class="mc-lat" id="l1"></div>
<div class="mc-chev"></div>
</div>
<div class="mc-body">
<div class="mc-empty"><div class="mc-eicon">🟡</div>Awaiting query…</div>
</div>
</div>
</div>
</div>
</div><!-- /.body -->
<script>
/* ── Config ── */
const API = '';
marked.setOptions({breaks:true,gfm:true});
/* ── State ── */
let running = false;
let qCount = 0;
const coll = [false, false];
const hist = [];
/* ── Utils ── */
function esc(s){ return String(s??'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') }
function md(text){
if(!text) return '<em style="color:var(--ink3)">—</em>';
return `<div class="md">${marked.parse(text)}</div>`;
}
function hlCode(el){
el.querySelectorAll('pre code').forEach(b => hljs.highlightElement(b));
}
function setStatus(state, msg, time=''){
document.getElementById('sDot').className = `sdot ${state}`;
document.getElementById('sMsg').textContent = msg;
document.getElementById('sTime').textContent = time;
}
function toggleCard(i){
coll[i] = !coll[i];
document.getElementById(`c${i}`).classList.toggle('coll', coll[i]);
}
/* ── Panel card rendering ── */
function panelSkel(i){
document.getElementById(`c${i}`).dataset.s = 'loading';
document.getElementById(`l${i}`).textContent = '…';
document.querySelector(`#c${i} .mc-body`).innerHTML =
'<div class="skel"><div class="sk"></div><div class="sk"></div><div class="sk"></div><div class="sk"></div></div>';
}
function panelResult(i, r){
const card = document.getElementById(`c${i}`);
const body = document.querySelector(`#c${i} .mc-body`);
document.getElementById(`l${i}`).textContent = `${r.latency_ms}ms`;
if(r.error){
card.dataset.s = 'er';
body.innerHTML = `<div class="mc-err">⚠ ${esc(r.error)}</div>`;
return;
}
card.dataset.s = `d${i+1}`;
body.innerHTML = `<div class="mc-inner fu">${md(r.response)}</div>`;
hlCode(body);
}
/* ── Judge rendering ── */
function judgeSkel(){
document.getElementById('jLat').textContent = '…';
document.getElementById('jPanel').className = 'judge-panel';
document.getElementById('jBody').innerHTML = `
<div class="jp-skel">
<div class="jsk" style="width:55%"></div><div class="jsk"></div>
<div class="jsk" style="width:78%"></div><div class="jsk" style="width:40%"></div>
<div class="jsk"></div><div class="jsk" style="width:68%"></div>
</div>`;
}
function judgeResult(r){
const jb = document.getElementById('jBody');
const jp = document.getElementById('jPanel');
document.getElementById('jLat').textContent = `${r.latency_ms}ms`;
if(r.error){
jp.className = 'judge-panel';
jb.innerHTML = `<div style="padding:16px 14px"><div class="mc-err">⚠ ${esc(r.error)}</div></div>`;
return;
}
jp.className = 'judge-panel done';
/* Extract raw code from corrected_code field (strip fences for display) */
let rawCode = r.corrected_code || '';
let lang = 'python';
const fenceMatch = rawCode.match(/^```(\w+)?\n?([\s\S]*?)```$/s);
if(fenceMatch){ lang = fenceMatch[1] || 'python'; rawCode = fenceMatch[2].trim(); }
const errHtml = r.error_analysis
? `<div class="err-box">
<div class="err-box-hdr">🐛 Error Analysis</div>
<div class="err-box-body fu">${md(r.error_analysis)}</div>
</div>`
: '';
const codeHtml = rawCode
? `<div class="code-box">
<div class="code-box-hdr">
✅ Corrected Code
<button class="copy-code-btn" id="copyCodeBtn" onclick="copyCode()">Copy</button>
</div>
<div class="code-box-body">
<pre><code id="correctedCode" class="language-${esc(lang)}">${esc(rawCode)}</code></pre>
</div>
</div>`
: `<div style="padding:14px;color:var(--ink2)">No corrected code returned.</div>`;
jb.innerHTML = errHtml + codeHtml;
/* highlight */
const codeEl = document.getElementById('correctedCode');
if(codeEl) hljs.highlightElement(codeEl);
/* highlight err-box md code blocks */
if(r.error_analysis) hlCode(jb);
}
function copyCode(){
const el = document.getElementById('correctedCode');
if(!el) return;
navigator.clipboard.writeText(el.textContent);
const btn = document.getElementById('copyCodeBtn');
if(btn){ btn.textContent = 'Copied ✓'; setTimeout(()=>btn.textContent='Copy', 1800); }
}
/* ── History ── */
function addHistory(q){
if(hist.includes(q)) return;
hist.unshift(q);
if(hist.length > 6) hist.pop();
renderHistory();
}
function renderHistory(){
const list = document.getElementById('histList');
const wrap = document.getElementById('histWrap');
if(!hist.length){ wrap.style.display='none'; return; }
wrap.style.display = '';
list.innerHTML = hist.map(q =>
`<div class="q-hist-item" onclick="fillQuery(this)" title="${esc(q)}">${esc(q)}</div>`
).join('');
}
function fillQuery(el){
const ta = document.getElementById('qInput');
ta.value = el.title;
ta.style.height='auto';
ta.style.height = Math.min(ta.scrollHeight,340)+'px';
ta.focus();
}
/* ── Main ── */
async function runDebug(){
if(running) return;
const q = document.getElementById('qInput').value.trim();
const temp = parseFloat(document.getElementById('tSlider').value);
if(!q){ document.getElementById('qInput').focus(); return; }
running = true;
document.getElementById('runBtn').disabled = true;
const t0 = Date.now();
setStatus('run','Querying Trinity Large + Nemotron Nano in parallel…');
panelSkel(0); panelSkel(1);
judgeSkel();
try{
const res = await fetch(`${API}/api/v1/debug`,{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({question:q, temperature:temp})
});
if(!res.ok){
const e = await res.json().catch(()=>({}));
throw new Error(e.detail || e.error || `HTTP ${res.status}`);
}
const data = await res.json();
const ms = Date.now()-t0;
data.panel.forEach((r,i)=>panelResult(i,r));
await new Promise(r=>setTimeout(r,150));
judgeResult(data.judge);
const ok = data.panel.filter(p=>!p.error).length;
setStatus('done',`Done — ${ok}/2 models + judge completed`, `${ms}ms`);
qCount++;
document.getElementById('qCnt').textContent = qCount;
addHistory(q);
}catch(err){
setStatus('err',`Error: ${err.message}`);
document.getElementById('jBody').innerHTML =
`<div style="padding:16px 14px"><div class="mc-err">⚠ ${esc(err.message)}</div></div>`;
[0,1].forEach(i=>{
document.getElementById(`c${i}`).dataset.s='er';
document.querySelector(`#c${i} .mc-body`).innerHTML='<div class="mc-err">Request failed</div>';
});
}
running=false;
document.getElementById('runBtn').disabled=false;
}
/* ── textarea auto-resize ── */
const ta = document.getElementById('qInput');
ta.addEventListener('input',()=>{
ta.style.height='auto';
ta.style.height=Math.min(ta.scrollHeight,340)+'px';
});
/* ── Ctrl+Enter ── */
ta.addEventListener('keydown',e=>{
if((e.ctrlKey||e.metaKey)&&e.key==='Enter'){e.preventDefault();runDebug();}
});
</script>
</body>
</html>