diff --git a/engraphis/classic_assets/dashboard.js b/engraphis/classic_assets/dashboard.js index 76dd4ad0..282692a5 100644 --- a/engraphis/classic_assets/dashboard.js +++ b/engraphis/classic_assets/dashboard.js @@ -131,23 +131,23 @@ function setWS(name){ } async function loadWorkspaceList(){const d=await api('/workspaces');WORKSPACES=d.workspaces||[];if(!WS&&WORKSPACES.length){WORKSPACES.sort((a,b)=>(b.memories||0)-(a.memories||0));setWS(WORKSPACES[0].name)}} -/* overview */ -function formatTokenCount(value){return Math.max(0,Math.round(Number(value)||0)).toLocaleString()} -function savingsPercent(value){return Math.max(0,Math.min(100,Number(value)*100||0))} -function savingsCount(value){return Math.max(0,Math.round(Number(value)||0))} -function savingsNode(tag,cls,text){const n=document.createElement(tag);if(cls)n.className=cls;if(text!=null)n.textContent=text;return n} -function renderOverviewSavings(data,error){ - const el=document.getElementById('ov-savings'); - if(!el)return; - el.replaceChildren(); - if(error){el.append(savingsNode('div','empty','Savings estimate unavailable.'));return} - const e=(data&&data.estimated)||{},eligible=savingsCount(e.eligible_receipt_count),excluded=savingsCount(e.excluded_receipt_count)+savingsCount(e.unclassified_receipt_count)+savingsCount(e.invalid_estimate_count),saved=Number(e.saved_tokens)||0,ratio=Number(e.savings_ratio)||0,counters=Array.isArray(e.by_token_counter)?e.by_token_counter:[]; - if(!eligible){el.append(savingsNode('div','empty','No receipt-backed context savings yet.'),savingsNode('div','field-hint','Eligible deliveries will appear after adaptive context or context-delivery calls. '+excluded+' excluded or unclassified '+(excluded===1?'delivery':'deliveries')+'.'),savingsNode('div','field-hint','Measures estimated prompt-context reduction; it does not measure provider billing.'));return} - const counter=counters.length===1?'Counter: '+(counters[0].token_counter||'unknown'):counters.length?counters.length+' token counters (kept separate)':'Counter: unknown',pct=savingsPercent(ratio),pctLabel=pct.toFixed(1); - const hero=savingsNode('div','savings-hero'),total=savingsNode('div'),rate=savingsNode('div','savings-rate'),progress=document.createElement('progress'); - total.append(savingsNode('div','stat-val savings-number',formatTokenCount(saved)),savingsNode('div','savings-unit','tokens avoided'));rate.append(savingsNode('strong','',pctLabel+'%'),savingsNode('span','','estimated reduction'));hero.append(total,rate);progress.className='savings-progress';progress.max=100;progress.value=pct;progress.setAttribute('aria-label',pctLabel+'% estimated context reduction'); - el.append(hero,progress,savingsNode('div','savings-summary','Across '+eligible+' eligible context deliveries'),savingsNode('div','field-hint','Baseline '+formatTokenCount(e.baseline_tokens)+' → emitted '+formatTokenCount(e.emitted_tokens)+' · confidence: '+(e.confidence||'unknown')),savingsNode('div','field-hint',counter+(excluded?' · '+excluded+' excluded/unclassified':'')),savingsNode('div','field-hint','Measures estimated prompt-context reduction; it does not measure provider billing.')); -} +/* overview */ +function formatTokenCount(value){return Math.max(0,Math.round(Number(value)||0)).toLocaleString()} +function savingsPercent(value){return Math.max(0,Math.min(100,Number(value)*100||0))} +function savingsCount(value){return Math.max(0,Math.round(Number(value)||0))} +function savingsNode(tag,cls,text){const n=document.createElement(tag);if(cls)n.className=cls;if(text!=null)n.textContent=text;return n} +function renderOverviewSavings(data,error){ + const el=document.getElementById('ov-savings'); + if(!el)return; + el.replaceChildren(); + if(error){el.append(savingsNode('div','empty','Savings estimate unavailable.'));return} + const e=(data&&data.estimated)||{},eligible=savingsCount(e.eligible_receipt_count),excluded=savingsCount(e.excluded_receipt_count)+savingsCount(e.unclassified_receipt_count)+savingsCount(e.invalid_estimate_count),saved=Number(e.saved_tokens)||0,ratio=Number(e.savings_ratio)||0,counters=Array.isArray(e.by_token_counter)?e.by_token_counter:[]; + if(!eligible){el.append(savingsNode('div','empty','No receipt-backed context savings yet.'),savingsNode('div','field-hint','Eligible deliveries will appear after adaptive context or context-delivery calls. '+excluded+' excluded or unclassified '+(excluded===1?'delivery':'deliveries')+'.'),savingsNode('div','field-hint','Measures estimated prompt-context reduction; it does not measure provider billing.'));return} + const counter=counters.length===1?'Counter: '+(counters[0].token_counter||'unknown'):counters.length?counters.length+' token counters (kept separate)':'Counter: unknown',pct=savingsPercent(ratio),pctLabel=pct.toFixed(1); + const hero=savingsNode('div','savings-hero'),total=savingsNode('div'),rate=savingsNode('div','savings-rate'),progress=document.createElement('progress'); + total.append(savingsNode('div','stat-val savings-number',formatTokenCount(saved)),savingsNode('div','savings-unit','tokens avoided'));rate.append(savingsNode('strong','',pctLabel+'%'),savingsNode('span','','estimated reduction'));hero.append(total,rate);progress.className='savings-progress';progress.max=100;progress.value=pct;progress.setAttribute('aria-label',pctLabel+'% estimated context reduction'); + el.append(hero,progress,savingsNode('div','savings-summary','Across '+eligible+' eligible context deliveries'),savingsNode('div','field-hint','Baseline '+formatTokenCount(e.baseline_tokens)+' → emitted '+formatTokenCount(e.emitted_tokens)+' · confidence: '+(e.confidence||'unknown')),savingsNode('div','field-hint',counter+(excluded?' · '+excluded+' excluded/unclassified':'')),savingsNode('div','field-hint','Measures estimated prompt-context reduction; it does not measure provider billing.')); +} async function loadOverview(){try{const st=await api('/stats?workspace='+encodeURIComponent(WS||''));setViewDesc('overview',(st.memories||0)+' memories · '+(st.workspaces||0)+' workspaces');const cards=[['Memories',st.memories],['Live rows',st.total_rows],['Workspaces',st.workspaces],['Sessions',st.sessions]];document.getElementById('stat-grid').innerHTML=cards.map(c=>`
'+esc((v.head||'').slice(0,24))+''+esc((r.hash||'').slice(0,20))+' · '+esc(r.status||'ok')+' · '+(r.target_count||0)+' target(s)'+(r.ts_ms?fmtRel(r.ts_ms/1000):'')+'