| | <!doctype html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="utf-8"/> |
| | <title>Brain UI – Test Panel</title> |
| | <meta name="viewport" content="width=device-width, initial-scale=1"/> |
| | <style> |
| | body{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif;margin:0;background:#0b0f19;color:#e5e7eb} |
| | header{padding:16px 20px;background:#111827;position:sticky;top:0} |
| | h1{margin:0;font-size:18px} |
| | main{padding:20px;display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(320px,1fr))} |
| | section{background:#111827;border:1px solid #1f2937;border-radius:12px;padding:16px} |
| | h2{margin:0 0 12px 0;font-size:16px} |
| | label{display:block;margin:8px 0 4px 0} |
| | input[type="text"],textarea{width:100%;padding:10px;border-radius:8px;border:1px solid #374151;background:#0b1220;color:#e5e7eb} |
| | input[type="file"]{margin:8px 0 12px 0} |
| | button{background:#2563eb;border:none;color:white;padding:10px 14px;border-radius:8px;cursor:pointer} |
| | button:disabled{opacity:0.6;cursor:not-allowed} |
| | .row{display:flex;gap:8px;flex-wrap:wrap} |
| | pre{white-space:pre-wrap;background:#0b1220;border:1px solid #1f2937;color:#cbd5e1;border-radius:8px;padding:10px;max-height:220px;overflow:auto} |
| | audio{width:100%;margin-top:8px} |
| | small{opacity:.7} |
| | </style> |
| | </head> |
| | <body> |
| | <header><h1>Brain UI · TTS · STT · Code Help · Memory</h1></header> |
| | <main> |
| |
|
| | <section id="warmup"> |
| | <h2>Warmup / Health</h2> |
| | <div class="row"> |
| | <button onclick="doHealth()">GET /health</button> |
| | <button onclick="doWarmup()">POST /warmup</button> |
| | </div> |
| | <pre id="healthOut"></pre> |
| | </section> |
| |
|
| | <section id="tts"> |
| | <h2>TTS</h2> |
| | <label>Text</label> |
| | <textarea id="ttsText" rows="3">Hello from Brain through ActualTTS.</textarea> |
| | <div class="row"><button id="ttsBtn" onclick="doTTS()">POST /speak</button></div> |
| | <audio id="ttsAudio" controls></audio> |
| | <pre id="ttsOut"></pre> |
| | </section> |
| |
|
| | <section id="stt"> |
| | <h2>STT</h2> |
| | <label>Audio file (.wav recommended)</label> |
| | <input type="file" id="sttFile" accept="audio/*"/> |
| | <div class="row"><button id="sttBtn" onclick="doSTT()">POST /transcribe</button></div> |
| | <pre id="sttOut"></pre> |
| | </section> |
| |
|
| | <section id="codehelp"> |
| | <h2>Code Help</h2> |
| | <label>Viewport text</label> |
| | <textarea id="vp" rows="4">def foo(): return 1 print(reslt)</textarea> |
| | <div class="row"><button id="codeBtn" onclick="doCodeHelp()">POST /code_help</button></div> |
| | <pre id="codeOut"></pre> |
| | </section> |
| |
|
| | <section id="memory"> |
| | <h2>Memory</h2> |
| | <label>Item</label> |
| | <input type="text" id="memItem" placeholder="Something to remember"/> |
| | <div class="row"> |
| | <button onclick="saveMem('short')">Save to short</button> |
| | <button onclick="saveMem('sess')">Save to sess</button> |
| | <button onclick="saveMem('proj')">Save to proj</button> |
| | <button onclick="clearMem('')">Clear ALL</button> |
| | </div> |
| | <div class="row"> |
| | <button onclick="clearMem('short')">Clear short</button> |
| | <button onclick="clearMem('sess')">Clear sess</button> |
| | <button onclick="clearMem('proj')">Clear proj</button> |
| | <button onclick="loadMem()">GET /memory</button> |
| | </div> |
| | <pre id="memOut"></pre> |
| | </section> |
| |
|
| | </main> |
| | <script> |
| | async function doHealth(){ |
| | const r = await fetch('/health'); const j = await r.json(); |
| | document.getElementById('healthOut').textContent = JSON.stringify(j,null,2); |
| | } |
| | async function doWarmup(){ |
| | const r = await fetch('/warmup',{method:'POST'}); const j = await r.json(); |
| | document.getElementById('healthOut').textContent = JSON.stringify(j,null,2); |
| | } |
| | async function doTTS(){ |
| | const btn = document.getElementById('ttsBtn'); btn.disabled=true; |
| | try{ |
| | const text = document.getElementById('ttsText').value; |
| | const r = await fetch('/speak',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({text})}); |
| | const j = await r.json(); |
| | document.getElementById('ttsOut').textContent = JSON.stringify(j,null,2); |
| | if(j.ok && j.audio_url){ |
| | const a = document.getElementById('ttsAudio'); a.src = j.audio_url; a.play().catch(()=>{}); |
| | } |
| | }finally{btn.disabled=false} |
| | } |
| | async function doSTT(){ |
| | const btn = document.getElementById('sttBtn'); btn.disabled=true; |
| | try{ |
| | const f = document.getElementById('sttFile').files[0]; |
| | if(!f){ alert('Pick an audio file'); return; } |
| | const fd = new FormData(); fd.append('file', f, f.name); |
| | const r = await fetch('/transcribe',{method:'POST', body: fd}); |
| | const j = await r.json(); |
| | document.getElementById('sttOut').textContent = JSON.stringify(j,null,2); |
| | }finally{btn.disabled=false} |
| | } |
| | async function doCodeHelp(){ |
| | const btn = document.getElementById('codeBtn'); btn.disabled=true; |
| | try{ |
| | const viewportText = document.getElementById('vp').value; |
| | const payload = { |
| | utterance: "please fix the error and make it run", |
| | telemetry: { |
| | file: "main.py", |
| | lang: "python", |
| | cursor: {l: 1, c: 1}, |
| | viewport: {start: 1, end: viewportText.split('\n').length, text: viewportText}, |
| | diag: [], |
| | term: "" |
| | }, |
| | memory: {short:[], sess:[], proj:[]}, |
| | response_mode: "patch" |
| | }; |
| | const r = await fetch('/code_help',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)}); |
| | const j = await r.json(); |
| | document.getElementById('codeOut').textContent = JSON.stringify(j,null,2); |
| | }finally{btn.disabled=false} |
| | } |
| | async function loadMem(){ |
| | const r = await fetch('/memory'); const j = await r.json(); |
| | document.getElementById('memOut').textContent = JSON.stringify(j,null,2); |
| | } |
| | async function saveMem(bucket){ |
| | const item = document.getElementById('memItem').value; |
| | const r = await fetch('/memory/save',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({bucket, item})}); |
| | const j = await r.json(); |
| | document.getElementById('memOut').textContent = JSON.stringify(j,null,2); |
| | } |
| | async function clearMem(bucket){ |
| | const r = await fetch('/memory/clear',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({bucket})}); |
| | const j = await r.json(); |
| | document.getElementById('memOut').textContent = JSON.stringify(j,null,2); |
| | } |
| | </script> |
| | </body> |
| | </html> |