| <!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> |