'+c.replace(/^\\w*\\n/,'')+'')
@@ -121,7 +128,8 @@
const qd=document.createElement('div'); qd.className='msg q'; qd.textContent=question;
const ad=document.createElement('div'); ad.className='msg';
const body=document.createElement('div'); body.className='a'; ad.appendChild(body);
- log.append(qd,ad); ad.scrollIntoView({block:'end'});
+ log.append(qd,ad);
+ sticky=true; stick(); // a fresh question always jumps to the newest message
let text='', t0=Date.now();
try{
const res=await fetch('ask',{method:'POST',
@@ -139,9 +147,8 @@
const line=p.split('\\n').find(l=>l.startsWith('data:')); if(!line) continue;
const data=line.slice(5).trim(); if(!data||data==='[DONE]') continue;
const ev=JSON.parse(data);
- if(ev.token){text+=ev.token; body.innerHTML=render(text);
- ad.scrollIntoView({block:'end'})}
- if(ev.error){body.innerHTML+=''+esc(ev.error)+'
'}
+ if(ev.token){text+=ev.token; body.innerHTML=render(text); stick()}
+ if(ev.error){body.innerHTML+=''+esc(ev.error)+'
'; stick()}
if(ev.sources){
const s=document.createElement('div'); s.className='src';
s.innerHTML='sources'+ev.sources.map(x=>''+esc(x)+'
').join('');
@@ -150,7 +157,7 @@
m.textContent=`${ev.chunks} chunks searched · retrieval ${ev.retrieve_ms}ms `
+`· first token ${(ev.ttft_ms/1000).toFixed(1)}s · ${ev.tok_per_s} tok/s `
+`· ${ev.prompt_chars} prompt chars · total ${((Date.now()-t0)/1000).toFixed(1)}s`;
- ad.appendChild(m);
+ ad.appendChild(m); stick();
}
}
}