Download index.html from banao-tech/problem-decoder-client: direct link, hf CLI and curl.
- Browser
- Download file 20.8 kB
-
https://huggingface.co/spaces/banao-tech/problem-decoder-client/resolve/main/index.html
- Command line
-
hf download hf://spaces/banao-tech/problem-decoder-client/index.html
-
curl -L -o index.html https://huggingface.co/spaces/banao-tech/problem-decoder-client/resolve/main/index.html
20.8 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"/> | |
| <meta name="viewport" content="width=device-width,initial-scale=1.0"/> | |
| <title>Problem Solver</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400;0,500;0,600;1,400&display=swap" rel="stylesheet"/> | |
| <style> | |
| *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} | |
| :root{ | |
| --white:#ffffff; | |
| --bg:#f8f9fa; | |
| --bg2:#f1f3f5; | |
| --border:#e9ecef; | |
| --border2:#dee2e6; | |
| --text:#0f1117; | |
| --text2:#343a40; | |
| --text3:#6c757d; | |
| --text4:#adb5bd; | |
| --accent:#2563eb; | |
| --accent-h:#1d4ed8; | |
| --accent-bg:#eff6ff; | |
| --accent-border:#bfdbfe; | |
| --success:#16a34a; | |
| --success-bg:#f0fdf4; | |
| --success-border:#bbf7d0; | |
| --danger:#dc2626; | |
| --radius:10px; | |
| --radius-sm:7px; | |
| --shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04); | |
| --shadow-md:0 4px 6px rgba(0,0,0,.05),0 2px 4px rgba(0,0,0,.04); | |
| } | |
| html,body{height:100%;font-family:'Inter',system-ui,sans-serif;font-size:15px;line-height:1.5;color:var(--text);background:var(--bg);-webkit-font-smoothing:antialiased;} | |
| /* ── Layout ── */ | |
| .app{display:grid;grid-template-rows:57px 1fr;height:100vh;overflow:hidden;} | |
| /* ── Nav ── */ | |
| .nav{ | |
| display:flex;align-items:center;padding:0 28px; | |
| background:var(--white);border-bottom:1px solid var(--border); | |
| box-shadow:var(--shadow);position:relative;z-index:10; | |
| } | |
| .nav-logo{display:flex;align-items:center;gap:9px;} | |
| .nav-mark{ | |
| width:28px;height:28px;background:var(--accent);border-radius:7px; | |
| display:flex;align-items:center;justify-content:center;flex-shrink:0; | |
| } | |
| .nav-mark svg{width:14px;height:14px;stroke:#fff;fill:none;stroke-width:2.5;} | |
| .nav-name{font-size:15px;font-weight:600;color:var(--text);letter-spacing:-.01em;} | |
| /* ── Body ── */ | |
| .body{display:grid;grid-template-columns:380px 1fr;overflow:hidden;} | |
| /* ── Sidebar ── */ | |
| .side{ | |
| background:var(--white);border-right:1px solid var(--border); | |
| display:flex;flex-direction:column;overflow:hidden; | |
| } | |
| .side-scroll{flex:1;overflow-y:auto;padding:28px 24px 0;} | |
| .side-scroll::-webkit-scrollbar{width:0;} | |
| .side-foot{padding:20px 24px;border-top:1px solid var(--border);} | |
| /* Section label */ | |
| .slabel{ | |
| font-size:11px;font-weight:600;color:var(--text4); | |
| letter-spacing:.08em;text-transform:uppercase; | |
| margin-bottom:10px; | |
| } | |
| /* Name field */ | |
| .name-field{margin-bottom:28px;} | |
| .name-field label{display:block;font-size:13px;font-weight:500;color:var(--text3);margin-bottom:6px;} | |
| input[type=text]{ | |
| width:100%;background:var(--bg);border:1.5px solid var(--border); | |
| border-radius:var(--radius-sm);color:var(--text); | |
| font:inherit;font-size:15px;padding:10px 14px; | |
| outline:none;transition:border-color .15s,box-shadow .15s; | |
| } | |
| input[type=text]:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(37,99,235,.1);} | |
| input::placeholder{color:var(--text4);} | |
| /* ── Tabs ── */ | |
| .tabs{ | |
| display:grid;grid-template-columns:1fr 1fr; | |
| gap:0;background:var(--bg2);border-radius:var(--radius); | |
| padding:3px;margin-bottom:16px; | |
| } | |
| .tab{ | |
| padding:9px 12px;text-align:center;font-size:14px;font-weight:500; | |
| color:var(--text3);border-radius:8px;cursor:pointer; | |
| transition:all .18s;user-select:none; | |
| } | |
| .tab.on{ | |
| background:var(--white);color:var(--text);font-weight:600; | |
| box-shadow:var(--shadow); | |
| } | |
| /* ── Panes ── */ | |
| #pp,#up{display:none;} | |
| #pp.on,#up.on{display:block;} | |
| /* Upload — primary */ | |
| .drop{ | |
| border:2px dashed var(--border2);border-radius:var(--radius); | |
| padding:36px 20px;text-align:center;cursor:pointer; | |
| background:var(--bg);transition:border-color .2s,background .2s; | |
| position:relative; | |
| } | |
| .drop:hover,.drop.over{border-color:var(--accent);background:var(--accent-bg);} | |
| .drop-icon{ | |
| width:44px;height:44px;border-radius:11px; | |
| background:var(--white);border:1.5px solid var(--border); | |
| display:flex;align-items:center;justify-content:center; | |
| margin:0 auto 14px;box-shadow:var(--shadow); | |
| } | |
| .drop-icon svg{width:20px;height:20px;stroke:var(--text3);fill:none;stroke-width:1.8;} | |
| .drop h4{font-size:15px;font-weight:600;color:var(--text2);margin-bottom:4px;} | |
| .drop p{font-size:13px;color:var(--text3);line-height:1.5;} | |
| .drop-chips{display:flex;gap:6px;justify-content:center;margin-top:12px;} | |
| .chip{ | |
| font-size:11px;font-weight:500;color:var(--text3); | |
| background:var(--white);border:1px solid var(--border); | |
| border-radius:4px;padding:2px 7px;letter-spacing:.03em; | |
| } | |
| .fbadge{ | |
| display:none;align-items:center;gap:10px; | |
| padding:11px 14px;background:var(--success-bg); | |
| border:1.5px solid var(--success-border);border-radius:var(--radius-sm); | |
| margin-top:12px; | |
| } | |
| .fbadge.on{display:flex;} | |
| .fbadge-icon{width:28px;height:28px;background:var(--success-bg);border:1.5px solid var(--success-border);border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;} | |
| .fbadge-icon svg{width:14px;height:14px;stroke:var(--success);fill:none;stroke-width:2;} | |
| .fbadge-name{flex:1;font-size:13px;font-weight:500;color:var(--success);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;} | |
| .fbadge-clear{cursor:pointer;color:var(--text4);font-size:16px;line-height:1;transition:color .15s;} | |
| .fbadge-clear:hover{color:var(--text2);} | |
| input[type=file]{display:none;} | |
| /* Textarea */ | |
| textarea{ | |
| width:100%;background:var(--bg);border:1.5px solid var(--border); | |
| border-radius:var(--radius);color:var(--text); | |
| font:inherit;font-size:14px;line-height:1.7; | |
| padding:14px;min-height:220px;resize:none;outline:none; | |
| transition:border-color .15s,box-shadow .15s; | |
| } | |
| textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(37,99,235,.1);} | |
| textarea::placeholder{color:var(--text4);} | |
| /* ── Buttons ── */ | |
| .btn-run{ | |
| width:100%;background:var(--accent);color:#fff;border:none; | |
| border-radius:var(--radius-sm);padding:13px 18px; | |
| font:inherit;font-size:15px;font-weight:600;cursor:pointer; | |
| display:flex;align-items:center;justify-content:center;gap:8px; | |
| transition:background .15s,box-shadow .15s,transform .1s; | |
| letter-spacing:-.01em; | |
| } | |
| .btn-run:hover:not(:disabled){background:var(--accent-h);box-shadow:0 4px 14px rgba(37,99,235,.35);} | |
| .btn-run:active:not(:disabled){transform:scale(.985);} | |
| .btn-run:disabled{opacity:.45;cursor:not-allowed;} | |
| .btn-run svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2.5;} | |
| .btn-pdf{ | |
| width:100%;margin-top:8px;background:transparent; | |
| color:var(--text3);border:1.5px solid var(--border); | |
| border-radius:var(--radius-sm);padding:11px 18px; | |
| font:inherit;font-size:14px;font-weight:500;cursor:pointer; | |
| display:flex;align-items:center;justify-content:center;gap:8px; | |
| transition:all .15s; | |
| } | |
| .btn-pdf:hover:not(:disabled){background:var(--success-bg);color:var(--success);border-color:var(--success-border);} | |
| .btn-pdf:disabled{opacity:.3;cursor:not-allowed;} | |
| .btn-pdf svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2;} | |
| /* ── Main output ── */ | |
| .main{display:flex;flex-direction:column;overflow:hidden;background:var(--white);} | |
| .bar{ | |
| display:flex;align-items:center;gap:10px; | |
| padding:0 28px;height:46px;border-bottom:1px solid var(--border);flex-shrink:0; | |
| background:var(--white); | |
| } | |
| .sdot{width:7px;height:7px;border-radius:50%;background:var(--border);flex-shrink:0;transition:background .3s;} | |
| .sdot.run{background:var(--accent);animation:pulse .9s infinite;} | |
| .sdot.done{background:var(--success);} | |
| .sdot.err{background:var(--danger);} | |
| @keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}} | |
| .stxt{font-size:13px;color:var(--text3);} | |
| .pipe{margin-left:auto;display:flex;align-items:center;gap:4px;} | |
| .pn{ | |
| font-size:11.5px;font-weight:500;color:var(--text4); | |
| padding:3px 9px;border-radius:5px; | |
| border:1px solid transparent;background:transparent; | |
| transition:all .2s; | |
| } | |
| .pn.run{color:var(--accent);border-color:var(--accent-border);background:var(--accent-bg);} | |
| .pn.done{color:var(--success);border-color:var(--success-border);background:var(--success-bg);} | |
| .ps{font-size:10px;color:var(--border);} | |
| /* ── Output ── */ | |
| .out{flex:1;overflow-y:auto;background:var(--white);} | |
| .out::-webkit-scrollbar{width:4px;} | |
| .out::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px;} | |
| .empty{ | |
| display:flex;flex-direction:column;align-items:center; | |
| justify-content:center;height:100%;gap:14px; | |
| text-align:center;padding-bottom:60px; | |
| } | |
| .empty-ico{ | |
| width:52px;height:52px;border-radius:13px; | |
| background:var(--bg);border:1.5px solid var(--border); | |
| display:flex;align-items:center;justify-content:center; | |
| } | |
| .empty-ico svg{width:22px;height:22px;stroke:var(--text4);fill:none;stroke-width:1.6;} | |
| .empty h3{font-size:17px;font-weight:600;color:var(--text2);letter-spacing:-.01em;} | |
| .empty p{font-size:14px;color:var(--text3);max-width:280px;line-height:1.65;} | |
| /* ── Output sections ── */ | |
| .section{ | |
| border-bottom:1px solid var(--border); | |
| padding:24px 32px; | |
| opacity:0;transform:translateY(8px); | |
| transition:opacity .35s ease,transform .35s ease; | |
| } | |
| .section.in{opacity:1;transform:translateY(0);} | |
| .section:last-child{border-bottom:none;} | |
| .section-hd{display:flex;align-items:center;gap:10px;margin-bottom:16px;} | |
| .section-badge{ | |
| font-size:11px;font-weight:600;color:var(--text3); | |
| background:var(--bg2);border:1px solid var(--border); | |
| border-radius:5px;padding:2px 8px;letter-spacing:.04em; | |
| text-transform:uppercase;flex-shrink:0; | |
| } | |
| .section-title{font-size:15px;font-weight:600;color:var(--text);letter-spacing:-.01em;flex:1;} | |
| .section-spin{ | |
| width:14px;height:14px;flex-shrink:0; | |
| border:1.8px solid var(--text4);border-top-color:transparent; | |
| border-radius:50%;animation:spin .7s linear infinite; | |
| } | |
| .section-tick{font-size:15px;color:var(--success);flex-shrink:0;} | |
| @keyframes spin{to{transform:rotate(360deg)}} | |
| /* ── Prose ── */ | |
| .prose{font-size:15px;line-height:1.8;color:var(--text2);} | |
| .prose h2{ | |
| font-size:14px;font-weight:600;color:var(--text); | |
| margin:20px 0 8px;letter-spacing:-.01em; | |
| } | |
| .prose h2:first-child{margin-top:0;} | |
| .prose h3{font-size:14px;font-weight:600;color:var(--text2);margin:14px 0 5px;} | |
| .prose strong{font-weight:600;color:var(--text);} | |
| .prose ul,.prose ol{padding-left:20px;margin:6px 0 10px;} | |
| .prose li{margin-bottom:4px;} | |
| .prose br+br{display:none;} | |
| /* ── Toast ── */ | |
| .toast{ | |
| position:fixed;bottom:20px;left:50%;transform:translateX(-50%); | |
| background:var(--text);color:#fff;padding:10px 18px; | |
| border-radius:8px;font-size:14px;display:none;z-index:999; | |
| box-shadow:var(--shadow-md);white-space:nowrap; | |
| } | |
| .toast.err{background:var(--danger);} | |
| @media(max-width:780px){ | |
| .body{grid-template-columns:1fr;} | |
| .side{border-right:none;border-bottom:1px solid var(--border);} | |
| .main{min-height:55vh;} | |
| .pipe{display:none;} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="app"> | |
| <nav class="nav"> | |
| <div class="nav-logo"> | |
| <div class="nav-mark"> | |
| <svg viewBox="0 0 24 24"><path d="M9 12l2 2 4-4M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg> | |
| </div> | |
| <span class="nav-name">Problem Solver</span> | |
| </div> | |
| </nav> | |
| <div class="body"> | |
| <!-- Sidebar --> | |
| <aside class="side"> | |
| <div class="side-scroll"> | |
| <div class="slabel">Your name</div> | |
| <div class="name-field"> | |
| <input type="text" id="iName" placeholder="e.g. Priya Sharma"/> | |
| </div> | |
| <div class="slabel">Input</div> | |
| <div class="tabs"> | |
| <div class="tab on" id="tUpload" onclick="setTab('upload')">Upload file</div> | |
| <div class="tab" id="tPaste" onclick="setTab('paste')">Paste text</div> | |
| </div> | |
| <!-- Upload — default --> | |
| <div id="up" class="on"> | |
| <div class="drop" id="dz" | |
| onclick="document.getElementById('fi').click()" | |
| ondragover="dg(event,true)" ondragleave="dg(event,false)" ondrop="dp(event)"> | |
| <div class="drop-icon"> | |
| <svg viewBox="0 0 24 24"><path d="M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M16 10l-4-4-4 4M12 6v10"/></svg> | |
| </div> | |
| <h4>Upload a file</h4> | |
| <p>Drag & drop or click to browse</p> | |
| <div class="drop-chips"> | |
| <span class="chip">PDF</span> | |
| <span class="chip">TXT</span> | |
| <span class="chip">MD</span> | |
| </div> | |
| </div> | |
| <div class="fbadge" id="fb"> | |
| <div class="fbadge-icon"> | |
| <svg viewBox="0 0 24 24"><path d="M9 12l2 2 4-4"/><rect x="3" y="3" width="18" height="18" rx="3"/></svg> | |
| </div> | |
| <span class="fbadge-name" id="fn">—</span> | |
| <span class="fbadge-clear" onclick="cf()">✕</span> | |
| </div> | |
| <input type="file" id="fi" accept=".pdf,.txt,.md" onchange="pf(event)"/> | |
| </div> | |
| <!-- Paste text --> | |
| <div id="pp"> | |
| <textarea id="tx" placeholder="Paste your transcript, meeting notes, problem description, or any text you want analyzed…"></textarea> | |
| </div> | |
| </div> | |
| <div class="side-foot"> | |
| <button class="btn-run" id="bRun" onclick="run()"> | |
| <svg viewBox="0 0 24 24"><path d="M5 3l14 9-14 9V3z"/></svg> | |
| Analyze | |
| </button> | |
| <button class="btn-pdf" id="bPdf" disabled onclick="getPdf()"> | |
| <svg viewBox="0 0 24 24"><path d="M12 15V3m0 12l-4-4m4 4l4-4M3 17v2a2 2 0 002 2h14a2 2 0 002-2v-2"/></svg> | |
| Download PDF | |
| </button> | |
| </div> | |
| </aside> | |
| <!-- Output --> | |
| <main class="main"> | |
| <div class="bar"> | |
| <div class="sdot" id="sd"></div> | |
| <span class="stxt" id="st">Ready</span> | |
| <div class="pipe"> | |
| <div class="pn" id="pn0">Analysis</div><div class="ps">›</div> | |
| <div class="pn" id="pn1">Root Cause</div><div class="ps">›</div> | |
| <div class="pn" id="pn2">Solutions</div><div class="ps">›</div> | |
| <div class="pn" id="pn3">Action Plan</div><div class="ps">›</div> | |
| <div class="pn" id="pn4">Reflection</div> | |
| </div> | |
| </div> | |
| <div class="out" id="out"> | |
| <div class="empty" id="es"> | |
| <div class="empty-ico"> | |
| <svg viewBox="0 0 24 24"><path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg> | |
| </div> | |
| <h3>Upload or paste your transcript</h3> | |
| <p>Meeting notes, interview recordings, problem descriptions — five agents will break it down and hand you a clear plan.</p> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| </div> | |
| <div class="toast" id="toast"></div> | |
| <script> | |
| const API='https://banao-tech-problem-decoder.hf.space'; | |
| const AG=[ | |
| {key:'analyst', title:'Problem Analysis', n:'01'}, | |
| {key:'root_cause', title:'Root Cause', n:'02'}, | |
| {key:'solutions', title:'Solutions', n:'03'}, | |
| {key:'action_plan', title:'Action Plan', n:'04'}, | |
| {key:'thinking', title:'Reflection', n:'05'}, | |
| ]; | |
| let running=false,selFile=null,lastP=null,tab='upload'; | |
| function setTab(t){ | |
| tab=t; | |
| document.getElementById('tUpload').classList.toggle('on',t==='upload'); | |
| document.getElementById('tPaste').classList.toggle('on',t==='paste'); | |
| document.getElementById('up').classList.toggle('on',t==='upload'); | |
| document.getElementById('pp').classList.toggle('on',t==='paste'); | |
| } | |
| function dg(e,on){e.preventDefault();document.getElementById('dz').classList.toggle('over',on);} | |
| function dp(e){e.preventDefault();document.getElementById('dz').classList.remove('over');const f=e.dataTransfer.files[0];if(f)sf(f);} | |
| function pf(e){const f=e.target.files[0];if(f)sf(f);} | |
| function sf(f){ | |
| selFile=f; | |
| document.getElementById('fn').textContent=f.name; | |
| document.getElementById('fb').classList.add('on'); | |
| } | |
| function cf(){ | |
| selFile=null; | |
| document.getElementById('fn').textContent='—'; | |
| document.getElementById('fb').classList.remove('on'); | |
| document.getElementById('fi').value=''; | |
| } | |
| function toast(m,e=false){ | |
| const t=document.getElementById('toast'); | |
| t.textContent=m;t.className='toast'+(e?' err':''); | |
| t.style.display='block'; | |
| setTimeout(()=>t.style.display='none',3500); | |
| } | |
| function ss(txt,s=''){ | |
| document.getElementById('st').textContent=txt; | |
| document.getElementById('sd').className='sdot '+s; | |
| } | |
| function sp(i,s){const e=document.getElementById('pn'+i);if(e)e.className='pn '+s;} | |
| function rp(){for(let i=0;i<5;i++)sp(i,'');} | |
| function md(s){ | |
| return s | |
| .replace(/^## (.+)$/gm,'<h2>$1</h2>') | |
| .replace(/^### (.+)$/gm,'<h3>$1</h3>') | |
| .replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>') | |
| .replace(/^[-*] (.+)$/gm,'<li>$1</li>') | |
| .replace(/(<li>[^]*?<\/li>\n?)+/g,x=>`<ul>${x}</ul>`) | |
| .replace(/\n/g,'<br>'); | |
| } | |
| async function rf(f){ | |
| if(f.name.endsWith('.pdf')){ | |
| return new Promise((res,rej)=>{ | |
| const r=new FileReader(); | |
| r.onload=()=>res('__PDF_BASE64__'+r.result.split(',')[1]); | |
| r.onerror=rej;r.readAsDataURL(f); | |
| }); | |
| } | |
| return new Promise((res,rej)=>{ | |
| const r=new FileReader(); | |
| r.onload=()=>res(r.result); | |
| r.onerror=rej;r.readAsText(f); | |
| }); | |
| } | |
| async function run(){ | |
| if(running)return; | |
| const name=document.getElementById('iName').value.trim()||'Anonymous'; | |
| let content=''; | |
| if(tab==='upload'){ | |
| if(!selFile){toast('Upload a file first.',true);return;} | |
| try{content=await rf(selFile);}catch{toast('Could not read file.',true);return;} | |
| } else { | |
| content=document.getElementById('tx').value.trim(); | |
| if(!content){toast('Paste something first.',true);return;} | |
| } | |
| running=true; | |
| lastP={content,user_name:name,user_role:'',user_goal:''}; | |
| document.getElementById('bRun').disabled=true; | |
| document.getElementById('bPdf').disabled=true; | |
| rp(); | |
| const out=document.getElementById('out'); | |
| out.innerHTML=''; | |
| ss('Running…','run'); | |
| AG.forEach(a=>{ | |
| const d=document.createElement('div'); | |
| d.className='section'; | |
| d.id='s-'+a.key; | |
| d.innerHTML=` | |
| <div class="section-hd"> | |
| <span class="section-badge">${a.n}</span> | |
| <span class="section-title">${a.title}</span> | |
| <div class="section-spin" id="sp-${a.key}"></div> | |
| </div> | |
| <div class="prose" id="pr-${a.key}"></div>`; | |
| out.appendChild(d); | |
| }); | |
| try{ | |
| const res=await fetch(`${API}/analyze/stream`,{ | |
| method:'POST',headers:{'Content-Type':'application/json'}, | |
| body:JSON.stringify(lastP), | |
| }); | |
| if(!res.ok){const e=await res.json().catch(()=>({detail:res.statusText}));throw new Error(e.detail);} | |
| const reader=res.body.getReader(),dec=new TextDecoder(); | |
| let buf='',cur=null; | |
| while(true){ | |
| const{done,value}=await reader.read(); | |
| if(done)break; | |
| buf+=dec.decode(value,{stream:true}); | |
| const lines=buf.split('\n');buf=lines.pop(); | |
| for(const line of lines){ | |
| if(!line.startsWith('data: '))continue; | |
| try{ | |
| const m=JSON.parse(line.slice(6)); | |
| if(m.event==='agent_start'){ | |
| cur=m.agent; | |
| const i=AG.findIndex(a=>a.key===cur); | |
| sp(i,'run'); | |
| document.getElementById('s-'+cur).classList.add('in'); | |
| ss(m.label+'…','run'); | |
| document.getElementById('s-'+cur).scrollIntoView({behavior:'smooth',block:'nearest'}); | |
| } else if(m.event==='token'&&m.agent===cur){ | |
| const p=document.getElementById('pr-'+m.agent); | |
| if(p){p.dataset.r=(p.dataset.r||'')+m.text;p.innerHTML=md(p.dataset.r);} | |
| } else if(m.event==='agent_done'){ | |
| const sp2=document.getElementById('sp-'+m.agent); | |
| if(sp2)sp2.outerHTML='<span class="section-tick">✓</span>'; | |
| const i=AG.findIndex(a=>a.key===m.agent); | |
| sp(i,'done'); | |
| } else if(m.event==='done'){ | |
| ss('Analysis complete','done'); | |
| document.getElementById('bPdf').disabled=false; | |
| } | |
| }catch{} | |
| } | |
| } | |
| }catch(e){ss('Something went wrong','err');toast(e.message,true);} | |
| running=false; | |
| document.getElementById('bRun').disabled=false; | |
| } | |
| async function getPdf(){ | |
| if(!lastP)return; | |
| const b=document.getElementById('bPdf'); | |
| b.textContent='Generating…';b.disabled=true; | |
| try{ | |
| const res=await fetch(`${API}/analyze/pdf`,{ | |
| method:'POST',headers:{'Content-Type':'application/json'}, | |
| body:JSON.stringify(lastP), | |
| }); | |
| if(!res.ok)throw new Error('PDF generation failed'); | |
| const blob=await res.blob(),a=document.createElement('a'); | |
| a.href=URL.createObjectURL(blob); | |
| a.download=`analysis_${Date.now()}.pdf`; | |
| a.click(); | |
| }catch(e){toast(e.message,true);} | |
| b.innerHTML='<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 15V3m0 12l-4-4m4 4l4-4M3 17v2a2 2 0 002 2h14a2 2 0 002-2v-2"/></svg> Download PDF'; | |
| b.disabled=false; | |
| } | |
| </script> | |
| </body> | |
| </html> |