@0xmaxma/claude-gateway 2.0.5 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/runner.d.ts +14 -0
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +75 -71
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/session-compaction-scheduler.d.ts +22 -0
- package/dist/agent/session-compaction-scheduler.d.ts.map +1 -0
- package/dist/agent/session-compaction-scheduler.js +40 -0
- package/dist/agent/session-compaction-scheduler.js.map +1 -0
- package/dist/api/gateway-router.d.ts.map +1 -1
- package/dist/api/gateway-router.js +100 -10
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/memory-activity.d.ts +18 -0
- package/dist/api/memory-activity.d.ts.map +1 -0
- package/dist/api/memory-activity.js +97 -0
- package/dist/api/memory-activity.js.map +1 -0
- package/dist/orchestration/agent-tool-schemas.js +1 -1
- package/dist/orchestration/agent-tool-schemas.js.map +1 -1
- package/dist/orchestration/bridge.js +1 -1
- package/dist/orchestration/bridge.js.map +1 -1
- package/dist/orchestration/compact-measurements.d.ts +21 -0
- package/dist/orchestration/compact-measurements.d.ts.map +1 -0
- package/dist/orchestration/compact-measurements.js +62 -0
- package/dist/orchestration/compact-measurements.js.map +1 -0
- package/dist/orchestration/config.d.ts +4 -0
- package/dist/orchestration/config.d.ts.map +1 -1
- package/dist/orchestration/config.js +1 -1
- package/dist/orchestration/config.js.map +1 -1
- package/dist/orchestration/context-delivery.d.ts +32 -0
- package/dist/orchestration/context-delivery.d.ts.map +1 -0
- package/dist/orchestration/context-delivery.js +101 -0
- package/dist/orchestration/context-delivery.js.map +1 -0
- package/dist/orchestration/conversation-intake.d.ts +10 -6
- package/dist/orchestration/conversation-intake.d.ts.map +1 -1
- package/dist/orchestration/conversation-intake.js +22 -8
- package/dist/orchestration/conversation-intake.js.map +1 -1
- package/dist/orchestration/dashboard-charts.d.ts +32 -0
- package/dist/orchestration/dashboard-charts.d.ts.map +1 -0
- package/dist/orchestration/dashboard-charts.js +77 -0
- package/dist/orchestration/dashboard-charts.js.map +1 -0
- package/dist/orchestration/dashboard-reader-worker.js +21 -3
- package/dist/orchestration/dashboard-reader-worker.js.map +1 -1
- package/dist/orchestration/dashboard-reader.d.ts +1 -1
- package/dist/orchestration/dashboard-reader.d.ts.map +1 -1
- package/dist/orchestration/dashboard-reader.js +2 -2
- package/dist/orchestration/dashboard-reader.js.map +1 -1
- package/dist/orchestration/decision-context.d.ts +1 -1
- package/dist/orchestration/decision-context.d.ts.map +1 -1
- package/dist/orchestration/decision-context.js +2 -2
- package/dist/orchestration/decision-context.js.map +1 -1
- package/dist/orchestration/mutation-recovery.d.ts +3 -2
- package/dist/orchestration/mutation-recovery.d.ts.map +1 -1
- package/dist/orchestration/mutation-recovery.js +8 -0
- package/dist/orchestration/mutation-recovery.js.map +1 -1
- package/dist/orchestration/native-compact.d.ts +4 -1
- package/dist/orchestration/native-compact.d.ts.map +1 -1
- package/dist/orchestration/native-compact.js +6 -2
- package/dist/orchestration/native-compact.js.map +1 -1
- package/dist/orchestration/process-turn.d.ts +1 -0
- package/dist/orchestration/process-turn.d.ts.map +1 -1
- package/dist/orchestration/process-turn.js +1 -1
- package/dist/orchestration/process-turn.js.map +1 -1
- package/dist/orchestration/runtime.d.ts +13 -1
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +161 -18
- package/dist/orchestration/runtime.js.map +1 -1
- package/dist/orchestration/session-compaction.d.ts +59 -0
- package/dist/orchestration/session-compaction.d.ts.map +1 -0
- package/dist/orchestration/session-compaction.js +212 -0
- package/dist/orchestration/session-compaction.js.map +1 -0
- package/dist/orchestration/tasks/driver.js +1 -1
- package/dist/orchestration/tasks/driver.js.map +1 -1
- package/dist/orchestration/token-ledger.d.ts +7 -0
- package/dist/orchestration/token-ledger.d.ts.map +1 -1
- package/dist/orchestration/token-ledger.js +1 -0
- package/dist/orchestration/token-ledger.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/dashboard-charts.d.ts +3 -0
- package/dist/ui/dashboard-charts.d.ts.map +1 -0
- package/dist/ui/dashboard-charts.js +130 -0
- package/dist/ui/dashboard-charts.js.map +1 -0
- package/dist/ui/dashboard-client.d.ts.map +1 -1
- package/dist/ui/dashboard-client.js +10 -14
- package/dist/ui/dashboard-client.js.map +1 -1
- package/dist/ui/dashboard-controls.d.ts +4 -0
- package/dist/ui/dashboard-controls.d.ts.map +1 -0
- package/dist/ui/dashboard-controls.js +27 -0
- package/dist/ui/dashboard-controls.js.map +1 -0
- package/dist/ui/dashboard-presentation.d.ts +3 -0
- package/dist/ui/dashboard-presentation.d.ts.map +1 -1
- package/dist/ui/dashboard-presentation.js +11 -5
- package/dist/ui/dashboard-presentation.js.map +1 -1
- package/dist/ui/dashboard-range.d.ts +3 -3
- package/dist/ui/dashboard-range.d.ts.map +1 -1
- package/dist/ui/dashboard-range.js +21 -5
- package/dist/ui/dashboard-range.js.map +1 -1
- package/dist/ui/dashboard-theme.d.ts +3 -1
- package/dist/ui/dashboard-theme.d.ts.map +1 -1
- package/dist/ui/dashboard-theme.js +80 -3
- package/dist/ui/dashboard-theme.js.map +1 -1
- package/dist/ui/memory-activity.d.ts +4 -0
- package/dist/ui/memory-activity.d.ts.map +1 -0
- package/dist/ui/memory-activity.js +115 -0
- package/dist/ui/memory-activity.js.map +1 -0
- package/dist/ui/token-report-client.d.ts +1 -1
- package/dist/ui/token-report-client.d.ts.map +1 -1
- package/dist/ui/token-report-client.js +1 -1
- package/dist/ui/token-report.d.ts +1 -0
- package/dist/ui/token-report.d.ts.map +1 -1
- package/dist/ui/token-report.js +18 -15
- package/dist/ui/token-report.js.map +1 -1
- package/dist/ui/web-ui.d.ts +1 -1
- package/dist/ui/web-ui.d.ts.map +1 -1
- package/dist/ui/web-ui.js +15 -238
- package/dist/ui/web-ui.js.map +1 -1
- package/mcp/tools/telegram/receiver-server.ts +31 -17
- package/mcp/tools/telegram/session-browser.ts +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dashboardChartsClient = void 0;
|
|
4
|
+
exports.dashboardChartsHtml = dashboardChartsHtml;
|
|
5
|
+
function dashboardChartsHtml(timezone) {
|
|
6
|
+
const zone = timezone.replace(/[^A-Za-z0-9_+\/.-]/g, '');
|
|
7
|
+
return '<div id="overview-charts" class="overview-chart-grid">' + [
|
|
8
|
+
['activity', 'Token activity'], ['agents', 'Tokens by agent'], ['models', 'Tokens by model'], ['reuse', 'Context reuse'],
|
|
9
|
+
].map(([key, title]) => '<section class="dash-panel overview-chart-card" data-chart="' + key + '"><div class="chart-card-header"><h2>' + title + '</h2><div class="range-toggle chart-range" role="group" aria-label="' + title + ' date range">' + ['24h', '7d', '30d', '90d'].map(range => '<button type="button" data-chart-range="' + range + '" aria-pressed="' + (range === '24h') + '" title="' + (range === '24h' ? 'Today from 00:00 ' : range + ' including today · ') + zone + '">' + range + '</button>').join('') + '</div></div><p class="live-note chart-period"></p><div class="chart-content" id="chart-' + key + '"><p class="empty">Loading recorded usage…</p></div><p class="live-note chart-status" role="status"></p></section>').join('') + '</div>';
|
|
10
|
+
}
|
|
11
|
+
exports.dashboardChartsClient = String.raw `
|
|
12
|
+
const overviewChartRanges={activity:'24h',agents:'24h',models:'24h',reuse:'24h'};
|
|
13
|
+
const overviewChartSnapshots=new Map(),overviewChartInflight=new Map();
|
|
14
|
+
const chartColors=dashboardChartPalette;
|
|
15
|
+
const chartRendered=new WeakMap();
|
|
16
|
+
let chartPointer=null;
|
|
17
|
+
document.addEventListener('pointermove',event=>{chartPointer={x:event.clientX,y:event.clientY};});
|
|
18
|
+
document.addEventListener('pointerout',event=>{if(!event.relatedTarget)chartPointer=null;});
|
|
19
|
+
const chartPreferenceKey='gateway-overview-charts:'+location.pathname.replace(/\/$/,'');
|
|
20
|
+
try{
|
|
21
|
+
const saved=JSON.parse(localStorage.getItem(chartPreferenceKey)||'{}');
|
|
22
|
+
Object.keys(overviewChartRanges).forEach(key=>{if(['24h','7d','30d','90d'].includes(saved?.[key]))overviewChartRanges[key]=saved[key];});
|
|
23
|
+
}catch{}
|
|
24
|
+
// Restore controls before the first fetch, including when Overview is initially hidden.
|
|
25
|
+
Object.keys(overviewChartRanges).forEach(key=>document.querySelectorAll('[data-chart="'+key+'"] [data-chart-range]').forEach(button=>button.setAttribute('aria-pressed',String(button.dataset.chartRange===overviewChartRanges[key]))));
|
|
26
|
+
function chartPeriod(data){const fmt=new Intl.DateTimeFormat('en-GB',{timeZone:data.timezone,day:'numeric',month:'short'});return (data.scope==='24h'?'Today · from 00:00':fmt.format(data.since)+' – '+fmt.format(data.asOf))+' · '+data.timezone;}
|
|
27
|
+
function chartEmpty(){return '<p class="empty">No recorded token usage in this period.</p>';}
|
|
28
|
+
function chartTooltipRow(label,value,color='var(--text)',detail){
|
|
29
|
+
return '<span class="chart-tooltip-row"><span>'+escHtml(label)+'</span><strong style="color:'+color+'">'+escHtml(value)+(detail==null?'':' <span class="chart-tooltip-detail">('+escHtml(detail)+')</span>')+'</strong></span>';
|
|
30
|
+
}
|
|
31
|
+
function chartInputShare(value,total){return total>0?(value/total*100).toFixed(1)+'%':'—';}
|
|
32
|
+
function chartActivity(data,reuse=false){
|
|
33
|
+
const reuseLegend={read:'Reused (Cached Read)',write:'New saved (Cached write)',fresh:'New not cached (Input)'};
|
|
34
|
+
const series=reuse?[['read','Reused','var(--token-agent)'],['write','New · saved','var(--token-worker)'],['fresh','New · not cached','var(--token-report)']]:[['agent','Agent','var(--token-agent)'],['worker','Workers','var(--token-worker)']];
|
|
35
|
+
const blank=()=>Object.fromEntries(series.map(([key])=>[key,0]));
|
|
36
|
+
const slots=new Map();
|
|
37
|
+
if(data.scope==='24h')for(let i=0;i<24;i++)slots.set(String(i).padStart(2,'0'),blank());
|
|
38
|
+
else{
|
|
39
|
+
const fmt=new Intl.DateTimeFormat('en-CA',{timeZone:data.timezone,year:'numeric',month:'2-digit',day:'2-digit'});
|
|
40
|
+
const parts=fmt.formatToParts(data.asOf),v=k=>Number(parts.find(p=>p.type===k).value),end=Date.UTC(v('year'),v('month')-1,v('day'));
|
|
41
|
+
for(let i=Number(data.scope.slice(0,-1))-1;i>=0;i--)slots.set(new Date(end-i*86400000).toISOString().slice(0,10),blank());
|
|
42
|
+
}
|
|
43
|
+
data.agents.forEach(a=>a.buckets.forEach(b=>{if(slots.has(b.key)){const slot=slots.get(b.key);series.forEach(([key])=>slot[key]+=Number(b[key]||0));}}));
|
|
44
|
+
const values=[...slots].map(([key,value])=>({key,...value})),peak=Math.max(0,...values.flatMap(v=>series.map(([key])=>v[key])));
|
|
45
|
+
if(!peak)return chartEmpty();
|
|
46
|
+
const label=key=>data.scope==='24h'?key+':00':key.slice(8,10)+'/'+key.slice(5,7);
|
|
47
|
+
const points=role=>values.map((v,i)=>(i*600/(values.length-1)).toFixed(2)+','+(180-v[role]/peak*170).toFixed(2)).join(' ');
|
|
48
|
+
return '<div class="activity-frame"><div class="chart-y-labels"><span>'+compactNumber(peak)+'</span><span>'+compactNumber(peak/2)+'</span><span>0</span></div><div class="activity-plot"><svg viewBox="0 0 600 190" preserveAspectRatio="none" aria-label="'+(reuse?'Recorded input reuse':'Agent and worker recorded token activity')+'" role="img"><path d="M0 10H600M0 95H600M0 180H600" fill="none" stroke="var(--line)" stroke-dasharray="3 5" vector-effect="non-scaling-stroke"/>'+series.map(([role,label,color])=>'<polyline points="'+points(role)+'" fill="none" stroke="'+color+'" stroke-width="1.5" vector-effect="non-scaling-stroke"/>').join('')+'</svg><div class="chart-hit-grid" style="grid-template-columns:repeat('+values.length+',minmax(0,1fr))">'+values.map((v,i)=>'<div class="chart-hit" data-chart-point="'+escHtml(v.key)+'" tabindex="0" role="img" aria-label="'+escHtml(label(v.key)+': '+series.map(([key,label])=>label+' '+compactNumber(v[key])).join(', '))+'">'+series.map(([role,label,color])=>'<i class="chart-line-dot" style="top:'+((180-v[role]/peak*170)/190*100)+'%;left:'+((i/(values.length-1)*values.length-i)*100)+'%;--dot-color:'+color+'"></i>').join('')+'<span class="chart-popover '+(i>values.length/2?'align-right':'align-left')+'"><strong>'+label(v.key)+'</strong>'+series.map(([key,label,color])=>chartTooltipRow(label,reuse?chartInputShare(v[key],v.read+v.write+v.fresh):compactNumber(v[key]),color,reuse&&v.read+v.write+v.fresh>0?compactNumber(v[key]):undefined)).join('')+chartTooltipRow(reuse?'Total input':'Total',compactNumber(series.reduce((n,[key])=>n+v[key],0)))+'</span></div>').join('')+'</div><div class="chart-x-labels"><span>'+label(values[0].key)+'</span><span>'+label(values[Math.floor(values.length/2)].key)+'</span><span>'+label(values[values.length-1].key)+'</span></div></div></div><div class="chart-key reuse-key">'+series.map(([key,label,color])=>'<span><i style="background:'+color+'"></i>'+(reuse?reuseLegend[key]:label)+'</span>').join('')+'</div><p class="live-note">'+(reuse?'Input tokens only. Not billing savings.':'Recorded tokens, including cache. Not billing cost.')+'</p>';
|
|
49
|
+
}
|
|
50
|
+
function chartAgents(data,element){
|
|
51
|
+
const agents=data.agents.map(a=>({...a,total:a.agent+a.worker})).filter(a=>a.total>0).sort((a,b)=>b.total-a.total||a.id.localeCompare(b.id));
|
|
52
|
+
if(!agents.length)return chartEmpty();
|
|
53
|
+
const capacity=Math.max(2,Math.min(8,Math.floor((element.clientWidth-40)/76))),top=agents.slice(0,capacity),peak=top[0].total;
|
|
54
|
+
return '<div class="agent-column-plot"><div class="chart-y-labels"><span>'+compactNumber(peak)+'</span><span>'+compactNumber(peak/2)+'</span><span>0</span></div><div class="agent-columns">'+top.map(a=>'<div class="agent-column" data-chart-point="'+escHtml(a.id)+'" style="--agent-hue:'+agentHue(a.id)+'" tabindex="0" role="img" aria-label="'+escHtml(a.id+': Agent '+compactNumber(a.agent)+', workers '+compactNumber(a.worker)+', total '+compactNumber(a.total))+'"><div class="agent-bar-space"><div class="agent-bar" style="height:'+Math.max(1,a.total/peak*100)+'%"><span class="agent-bar-total">'+compactNumber(a.total)+'</span></div></div><span class="agent-bar-label" title="'+escHtml(a.id)+'"><i></i><span>'+escHtml(a.id)+'</span></span><span class="chart-popover"><strong>'+escHtml(a.id)+'</strong>'+chartTooltipRow('Agent',compactNumber(a.agent),'var(--token-agent)')+chartTooltipRow('Workers',compactNumber(a.worker),'var(--token-worker)')+chartTooltipRow('Total',compactNumber(a.total),'var(--agent-chart-color)')+'</span></div>').join('')+'</div></div><div class="chart-key"><span>Agent + worker tokens · colors match Agents below</span></div><p class="live-note">Top '+top.length+' of '+agents.length+' active agents · ranked by recorded tokens.</p>';
|
|
55
|
+
}
|
|
56
|
+
function chartModels(data){
|
|
57
|
+
const models=new Map();data.agents.forEach(a=>a.models.forEach(m=>models.set(m.name,(models.get(m.name)||0)+m.tokens)));
|
|
58
|
+
const sorted=[...models].map(([name,tokens])=>({name,tokens})).sort((a,b)=>b.tokens-a.tokens||a.name.localeCompare(b.name));
|
|
59
|
+
const total=sorted.reduce((n,m)=>n+m.tokens,0);if(!total)return chartEmpty();
|
|
60
|
+
const top=sorted.slice(0,5);if(sorted.length>5)top.push({name:'Other models ('+(sorted.length-5)+')',tokens:sorted.slice(5).reduce((n,m)=>n+m.tokens,0)});
|
|
61
|
+
let offset=0;const circumference=2*Math.PI*72;
|
|
62
|
+
const arcs=top.map((m,i)=>{const length=m.tokens/total*circumference,arc='<circle cx="100" cy="100" r="72" fill="none" stroke="'+chartColors[i]+'" stroke-width="22" stroke-dasharray="'+length+' '+(circumference-length)+'" stroke-dashoffset="'+(-offset)+'" transform="rotate(-90 100 100)" tabindex="0" data-chart-point="'+escHtml(m.name)+'" data-model-name="'+escHtml(m.name)+'" data-model-tokens="'+compactNumber(m.tokens)+'" data-model-share="'+(m.tokens/total*100).toFixed(1)+'%" aria-label="'+escHtml(m.name)+' · '+compactNumber(m.tokens)+' · '+(m.tokens/total*100).toFixed(1)+'%"></circle>';offset+=length;return arc;}).join('');
|
|
63
|
+
return '<div class="model-donut-layout"><div class="model-donut"><svg viewBox="0 0 200 200" role="img" aria-label="Recorded tokens by model">'+arcs+'</svg><span class="chart-popover model-tooltip" role="tooltip"></span><div class="donut-center"><strong>'+compactNumber(total)+'</strong><span>Total tokens</span></div></div><ul class="model-chart-legend">'+top.map((m,i)=>'<li><i style="background:'+chartColors[i]+'"></i><span title="'+escHtml(m.name)+'">'+escHtml(m.name)+'</span><strong>'+compactNumber(m.tokens)+'</strong><small>'+(m.tokens/total*100).toFixed(1)+'%</small></li>').join('')+'</ul></div><p class="live-note">Agent + worker tokens · includes cache reads and writes.</p>';
|
|
64
|
+
}
|
|
65
|
+
function chartReuse(data){
|
|
66
|
+
const day=key=>data.agents.reduce((r,a)=>{const value=a.reuseComparison?.[key];if(value)Object.keys(r).forEach(k=>r[k]+=value[k]||0);return r;},{fresh:0,write:0,read:0,missingTurns:0});
|
|
67
|
+
const today=day('today'),yesterday=day('yesterday');
|
|
68
|
+
const rate=d=>{const total=d.fresh+d.write+d.read;return total>0?100*d.read/total:null;};
|
|
69
|
+
const current=rate(today),previous=rate(yesterday),delta=current!==null&&previous!==null?current-previous:null;
|
|
70
|
+
const comparison=delta===null?'Yesterday: no measured input to compare.':(delta===0?'Unchanged':(delta>0?'Up ':'Down ')+Math.abs(delta).toFixed(1)+' percentage points')+' vs yesterday ('+previous.toFixed(1)+'%).';
|
|
71
|
+
return chartActivity(data,true)+'<p class="reuse-summary"><strong>'+(current===null?'—':current.toFixed(1)+'%')+'</strong> of today’s measured input reused</p><p class="live-note">'+(current===null?'No measured input today.':comparison)+' Today so far vs yesterday’s full day · '+escHtml(data.timezone)+(today.missingTurns?' · '+compactNumber(today.missingTurns)+' turns excluded today: incomplete measurements.':'')+'</p>';
|
|
72
|
+
}
|
|
73
|
+
function drawOverviewChart(key,data){
|
|
74
|
+
const card=document.querySelector('[data-chart="'+key+'"]'),element=card.querySelector('.chart-content');
|
|
75
|
+
const sameScope=element.dataset.scope===data.scope;
|
|
76
|
+
const html=key==='activity'?chartActivity(data):key==='agents'?chartAgents(data,element):key==='models'?chartModels(data):chartReuse(data);
|
|
77
|
+
card.querySelector('.chart-period').textContent=chartPeriod(data);
|
|
78
|
+
if(chartRendered.get(element)!==html){
|
|
79
|
+
const active=document.activeElement,hadFocus=element.contains(active);
|
|
80
|
+
const point=hadFocus&&sameScope?active.closest('[data-chart-point]')?.dataset.chartPoint:null;
|
|
81
|
+
element.innerHTML=html;chartRendered.set(element,html);
|
|
82
|
+
if(hadFocus){
|
|
83
|
+
const replacement=point==null?null:[...element.querySelectorAll('[data-chart-point]')].find(node=>node.dataset.chartPoint===point);
|
|
84
|
+
(replacement||card.querySelector('[data-chart-range="'+data.scope+'"]')).focus({preventScroll:true});
|
|
85
|
+
}
|
|
86
|
+
// A stationary pointer does not emit pointerover after replacing SVG nodes.
|
|
87
|
+
if(chartPointer){const hovered=document.elementFromPoint(chartPointer.x,chartPointer.y);if(hovered&&element.contains(hovered))showModelTooltip(hovered);}
|
|
88
|
+
}
|
|
89
|
+
element.dataset.scope=data.scope;
|
|
90
|
+
card.querySelector('.chart-status').textContent='';
|
|
91
|
+
}
|
|
92
|
+
function refreshOverviewCharts(force=false){
|
|
93
|
+
if(document.hidden||document.getElementById('view-overview').style.display==='none')return;
|
|
94
|
+
Object.keys(overviewChartRanges).forEach(key=>document.querySelectorAll('[data-chart="'+key+'"] [data-chart-range]').forEach(b=>b.setAttribute('aria-pressed',String(b.dataset.chartRange===overviewChartRanges[key]))));
|
|
95
|
+
[...new Set(Object.values(overviewChartRanges))].forEach(scope=>{
|
|
96
|
+
const old=overviewChartSnapshots.get(scope);if(!force&&old&&Date.now()-old.at<10000)return;
|
|
97
|
+
if(overviewChartInflight.has(scope))return;
|
|
98
|
+
const request=fetch(apiUrl('/dashboard/charts')+'?scope='+scope,{signal:AbortSignal.timeout(15000)}).then(async response=>{if(!response.ok)throw Error('Chart data temporarily unavailable');return response.json();}).then(data=>{
|
|
99
|
+
overviewChartSnapshots.set(scope,{data,at:Date.now()});Object.keys(overviewChartRanges).forEach(key=>{if(overviewChartRanges[key]===scope)drawOverviewChart(key,data);});
|
|
100
|
+
}).catch(()=>Object.keys(overviewChartRanges).forEach(key=>{if(overviewChartRanges[key]===scope)document.querySelector('[data-chart="'+key+'"] .chart-status').textContent='Could not refresh. Retrying automatically.';})).finally(()=>overviewChartInflight.delete(scope));
|
|
101
|
+
overviewChartInflight.set(scope,request);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function showModelTooltip(target){
|
|
105
|
+
const arc=target.closest('[data-model-name]');if(!arc)return;
|
|
106
|
+
const tip=arc.closest('.model-donut').querySelector('.model-tooltip');
|
|
107
|
+
const color=arc.getAttribute('stroke');
|
|
108
|
+
// Stroke comes only from our fixed chart palette, never provider metadata.
|
|
109
|
+
tip.innerHTML='<strong>'+escHtml(arc.dataset.modelName)+'</strong>'+chartTooltipRow('Tokens',arc.dataset.modelShare,color,arc.dataset.modelTokens);
|
|
110
|
+
tip.style.display='block';
|
|
111
|
+
}
|
|
112
|
+
document.addEventListener('pointerover',event=>showModelTooltip(event.target));
|
|
113
|
+
document.addEventListener('focusin',event=>showModelTooltip(event.target));
|
|
114
|
+
function hideModelTooltip(event){const arc=event.target.closest('[data-model-name]');if(arc)arc.closest('.model-donut').querySelector('.model-tooltip').style.display='none';}
|
|
115
|
+
document.addEventListener('pointerout',hideModelTooltip);
|
|
116
|
+
document.addEventListener('focusout',hideModelTooltip);
|
|
117
|
+
document.addEventListener('click',event=>{
|
|
118
|
+
const button=event.target.closest('[data-chart-range]');if(button){
|
|
119
|
+
const key=button.closest('[data-chart]').dataset.chart,scope=button.dataset.chartRange;overviewChartRanges[key]=scope;
|
|
120
|
+
try{localStorage.setItem(chartPreferenceKey,JSON.stringify(overviewChartRanges));}catch{}
|
|
121
|
+
const cached=overviewChartSnapshots.get(scope);if(cached)drawOverviewChart(key,cached.data);else {chartRendered.delete(document.getElementById('chart-'+key));document.getElementById('chart-'+key).innerHTML='<p class="empty">Loading recorded usage…</p>';document.querySelector('[data-chart="'+key+'"] .chart-period').textContent='';}
|
|
122
|
+
refreshOverviewCharts();
|
|
123
|
+
}else if(event.target.closest('#tab-overview'))refreshOverviewCharts();
|
|
124
|
+
});
|
|
125
|
+
document.addEventListener('DOMContentLoaded',()=>refreshOverviewCharts());
|
|
126
|
+
document.addEventListener('visibilitychange',()=>{if(!document.hidden)refreshOverviewCharts();});
|
|
127
|
+
setInterval(()=>refreshOverviewCharts(true),10000);
|
|
128
|
+
let chartResizeWidth=0;new ResizeObserver(entries=>{const width=Math.round(entries[0].contentRect.width);if(width===chartResizeWidth)return;chartResizeWidth=width;const snapshot=overviewChartSnapshots.get(overviewChartRanges.agents);if(snapshot)drawOverviewChart('agents',snapshot.data);}).observe(document.getElementById('chart-agents'));
|
|
129
|
+
`;
|
|
130
|
+
//# sourceMappingURL=dashboard-charts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-charts.js","sourceRoot":"","sources":["../../src/ui/dashboard-charts.ts"],"names":[],"mappings":";;;AAAA,kDAKC;AALD,SAAgB,mBAAmB,CAAC,QAAgB;IAClD,MAAM,IAAI,GAAC,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAC,EAAE,CAAC,CAAC;IACtD,OAAO,wDAAwD,GAAC;QAC9D,CAAC,UAAU,EAAC,gBAAgB,CAAC,EAAC,CAAC,QAAQ,EAAC,iBAAiB,CAAC,EAAC,CAAC,QAAQ,EAAC,iBAAiB,CAAC,EAAC,CAAC,OAAO,EAAC,eAAe,CAAC;KAClH,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAC,KAAK,CAAC,EAAC,EAAE,CAAA,8DAA8D,GAAC,GAAG,GAAC,uCAAuC,GAAC,KAAK,GAAC,sEAAsE,GAAC,KAAK,GAAC,eAAe,GAAC,CAAC,KAAK,EAAC,IAAI,EAAC,KAAK,EAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAA,EAAE,CAAA,0CAA0C,GAAC,KAAK,GAAC,kBAAkB,GAAC,CAAC,KAAK,KAAG,KAAK,CAAC,GAAC,WAAW,GAAC,CAAC,KAAK,KAAG,KAAK,CAAA,CAAC,CAAA,mBAAmB,CAAA,CAAC,CAAA,KAAK,GAAC,qBAAqB,CAAC,GAAC,IAAI,GAAC,IAAI,GAAC,KAAK,GAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAC,yFAAyF,GAAC,GAAG,GAAC,oHAAoH,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAC,QAAQ,CAAC;AACrrB,CAAC;AAEY,QAAA,qBAAqB,GAAC,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsH5C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-client.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dashboard-client.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":"AAGA,gFAAgF;AAChF,eAAO,MAAM,eAAe,QA+K3B,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.dashboardClient = void 0;
|
|
4
|
+
const dashboard_charts_1 = require("./dashboard-charts");
|
|
4
5
|
const dashboard_range_1 = require("./dashboard-range");
|
|
5
6
|
const dashboard_presentation_1 = require("./dashboard-presentation");
|
|
6
7
|
/** Browser controller: no provider keys or model-generated HTML are trusted. */
|
|
7
|
-
exports.dashboardClient = dashboard_presentation_1.dashboardPresentationClient + dashboard_range_1.dashboardRange.toString() + ';' + dashboard_range_1.dashboardSince.toString() + ';' + String.raw `
|
|
8
|
+
exports.dashboardClient = dashboard_presentation_1.dashboardPresentationClient + dashboard_range_1.dashboardRange.toString() + ';' + dashboard_range_1.dashboardSince.toString() + ';' + dashboard_charts_1.dashboardChartsClient + String.raw `
|
|
8
9
|
let dashboardData = null, dashboardOffset = 0, dashboardBusy = false, dashboardSearch = '', dashboardAgent = '', dashboardScope = '24h';
|
|
9
10
|
const dashboardStateKey='gateway-dashboard-view:'+location.pathname.replace(/\/$/,'');
|
|
10
11
|
let savedDashboardState={};
|
|
@@ -61,15 +62,11 @@ function renderDashboard(data){
|
|
|
61
62
|
const stats=[['Recorded sessions',sessions],['Work in progress',taskCount(['running','starting','queued','interrupting','cancel_requested'])],['Waiting for a decision',taskCount(['waiting_input'])],['Loaded agents',agents.length]];
|
|
62
63
|
document.getElementById('overview-stats').innerHTML=stats.map(([label,n])=>'<div class="dash-stat"><span>'+label+'</span><strong>'+dashCount(n)+'</strong></div>').join('');
|
|
63
64
|
const attention=agents.flatMap(a=>(a.orchestration?.attention||[]).map(t=>({a,s:{sessionId:t.sessionId},t})));
|
|
65
|
+
document.getElementById('overview-attention-panel').hidden=!attention.length;
|
|
64
66
|
document.getElementById('overview-attention').innerHTML=attention.length?dashTable(['Task','Agent','Status'],attention.slice(0,8).map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false"><td>'+dashText(t.title)+'</td><td>'+agentBadge(a.id)+'</td><td>'+dashStatus(t.state)+'</td></tr>')):'<p class="muted">No tasks are waiting for a decision or reconciliation.</p>';
|
|
65
|
-
const hourly=Array.from({length:24},()=>({agent:0,worker:0}));let hasUsage=false;
|
|
66
|
-
agents.forEach(a=>(a.orchestration?.usageToday||[]).forEach(r=>{if(hourly[r.hour]&&['agent','worker'].includes(r.role)){hourly[r.hour][r.role]+=Number(r.tokens||0);hasUsage=true;}}));
|
|
67
|
-
const peak=Math.max(1,...hourly.flatMap(h=>[h.agent,h.worker]));
|
|
68
|
-
const points=role=>hourly.map((h,i)=>(i*600/23).toFixed(1)+','+(160-h[role]/peak*140).toFixed(1)).join(' ');
|
|
69
|
-
document.getElementById('overview-chart').innerHTML=hasUsage?'<svg viewBox="0 0 600 180" role="img" aria-label="Recorded token activity today in UTC" style="width:100%;height:180px"><path d="M0 20H600M0 90H600M0 160H600" fill="none" stroke="var(--line)" stroke-dasharray="4 5"/><polyline points="'+points('worker')+'" fill="none" stroke="var(--accent)" stroke-width="2"/><polyline points="'+points('agent')+'" fill="none" stroke="var(--blue)" stroke-width="2"/></svg><div class="row between muted small"><span>00:00 UTC</span><span>12:00</span><span>23:00 UTC</span></div>':'<p class="empty">No recorded token usage today.</p>';
|
|
70
67
|
const sessionRows=rows.map(({a,s})=>'<tr class="session-row"'+(s.orchestration?dashOpenAttrs(a.id,s.sessionId):'')+' tabindex="0" aria-expanded="false" data-row-key="'+escHtml(a.id+':'+s.sessionId)+'"><td>'+agentBadge(a.id)+'<br>'+channelBadge(s.source)+'</td><td><span class="session-id">'+dashText(s.sessionId)+'</span><br><small class="ts">Chat '+dashText(s.chatId)+'</small></td><td><span class="cell-clip" title="'+dashText(s.model)+'">'+dashText(s.model||'—')+'</span></td><td>'+dashStatus(sessionDisplayStatus(s))+'</td><td>'+ (s.orchestration?dashCount(s.tokenSummary?.agentTokens)+' / '+dashCount(s.tokenSummary?.totalTokens):dashCount(s.tokens))+'<br><small class="ts">'+(s.orchestration?'Agent / total · recorded only':'Legacy process tokens')+'</small></td><td class="dash-tools">'+toolInventory(s.loadedTools,s.usedTools,s.contextTools)+'</td><td>'+ (s.orchestration?'<a class="btn-stream" target="_blank" rel="noopener" href="'+escHtml(dashReportUrl(a.id,s.sessionId))+'">View token report ↗</a>':'')+(s.hasPtyStream&&s.isRunning&&s.mode==='pty-shell'?'<button class="btn-stream" data-agent-id="'+escHtml(a.id)+'" data-session-id="'+escHtml(s.sessionId)+'">Terminal</button>':'')+'</td></tr>');
|
|
71
68
|
document.getElementById('session-results').innerHTML=dashTable(['Agent / Channel','Session / Chat','Model','Status','Tokens','Tools','Inspect'],sessionRows);
|
|
72
|
-
const taskRows=tasks.map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false" data-row-key="'+escHtml(a.id+':'+t.taskId)+'"><td><strong class="dash-task-title">'+dashText(t.title)+'</strong><small class="ts">'+agentBadge(a.id)+' · '+dashId(t.taskId)+'<br>'+channelBadge(s.source)+'</small></td><td>'+dashStatus(t.state)+'</td><td class="session-id">'+dashId(t.workerSessionId)+'<br><small class="ts">Attempt '+dashId(t.attemptId)+'</small></td><td>'+dashCount(t.tokenSummary?.totalTokens)+'<br><small class="ts">Latest attempt</small></td><td>'+dashCount(t.tokenSummary?.allAttemptsTokens)+'<br><small class="ts">All recorded attempts</small></td><td class="dash-tools">'+toolInventory(t.loadedTools,t.usedTools,t.contextTools)+'</td><td><span class="cell-clip" title="'+dashText(t.lastTool?.name)+'">'+dashText(t.lastTool?.name||'No recorded tool')+'</span>'+'<br><small class="ts">'+(t.lastTool?.at?dashText(new Date(t.lastTool.at).toLocaleString()):'')+'</small></td></tr>');
|
|
69
|
+
const taskRows=tasks.map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false" data-row-key="'+escHtml(a.id+':'+t.taskId)+'"><td><strong class="dash-task-title">'+dashText(t.title)+'</strong><small class="ts">'+agentBadge(a.id)+' · '+dashId(t.taskId)+'<br>'+channelBadge(s.source)+'</small></td><td>'+dashStatus(t.state)+'</td><td class="session-id">'+dashId(t.workerSessionId)+'<br><small class="ts">Attempt '+dashId(t.attemptId)+'</small></td><td>'+dashCount(t.tokenSummary?.totalTokens)+'<br><small class="ts">Latest attempt</small></td><td>'+dashCount(t.tokenSummary?.allAttemptsTokens)+'<br><small class="ts">All recorded attempts</small></td><td class="dash-tools">'+toolInventory(t.loadedTools,t.usedTools,t.contextTools)+'</td><td><span class="cell-clip" title="'+dashText(t.lastTool?.name)+'">'+dashText(t.lastTool?.name||'No recorded tool')+'</span>'+'<br><small class="ts">'+(t.lastTool?.at?dashText(new Date(t.lastTool.at).toLocaleString('en-GB',{timeZone:dashboardTimezone})):'')+'</small></td></tr>');
|
|
73
70
|
document.getElementById('task-results').innerHTML=dashTable(['Task / Agent','Status','Worker session / Attempt','Latest tokens','Task tokens','Latest attempt tools','Latest activity'],taskRows);
|
|
74
71
|
const recentWork=agents.flatMap(a=>(a.orchestration?.recentWork||[]).map(t=>({a,s:{sessionId:t.sessionId},t}))).sort((x,y)=>Number(y.t.updatedAt)-Number(x.t.updatedAt)||x.t.taskId.localeCompare(y.t.taskId));
|
|
75
72
|
document.getElementById('overview-tasks').innerHTML=dashTable(['Task','Agent','Status'],recentWork.slice(0,6).map(({a,s,t})=>'<tr'+dashOpenAttrs(a.id,s.sessionId,t.taskId)+' tabindex="0" aria-expanded="false"><td>'+dashText(t.title)+'</td><td>'+agentBadge(a.id)+'</td><td>'+dashStatus(t.state)+'</td></tr>'));
|
|
@@ -100,16 +97,16 @@ async function dashDetail(agentId,sessionId,taskId,offset=0){
|
|
|
100
97
|
if(response.status===401){onUnauthorized();return;}
|
|
101
98
|
if(!response.ok)throw Error('Details unavailable (HTTP '+response.status+').');
|
|
102
99
|
const detail=await response.json();if(dashboardExpanded.get(key)!==record)return;
|
|
103
|
-
let body='<h1>'+dashText(taskId?detail.snapshot.title:'Session details')+'</h1><p class="muted">'+agentBadge(agentId)+' · <span class="session-id">'+dashText(sessionId)+'</span></p><p class="live-note">Recorded snapshot · '+new Date().toLocaleTimeString()+'</p><a class="btn-stream" href="'+escHtml(dashReportUrl(agentId,sessionId))+'" target="_blank" rel="noopener">Open full token report ↗</a>';
|
|
100
|
+
let body='<h1>'+dashText(taskId?detail.snapshot.title:'Session details')+'</h1><p class="muted">'+agentBadge(agentId)+' · <span class="session-id">'+dashText(sessionId)+'</span></p><p class="live-note">Recorded snapshot · '+new Date().toLocaleTimeString('en-GB',{timeZone:dashboardTimezone})+'</p><a class="btn-stream" href="'+escHtml(dashReportUrl(agentId,sessionId))+'" target="_blank" rel="noopener">Open full token report ↗</a>';
|
|
104
101
|
if(taskId){
|
|
105
102
|
body+='<h2>Task</h2>'+dashStatus(detail.snapshot.state)+'<pre>'+dashText(detail.instructions||'No assignment text recorded for this task.')+'</pre>';
|
|
106
103
|
if(detail.snapshot.result)body+='<h2>Latest result</h2><pre>'+dashText(detail.snapshot.result.summary||JSON.stringify(detail.snapshot.result,null,2))+'</pre>';
|
|
107
104
|
body+='<h2>Worker attempts</h2><p class="muted">'+detail.totalAttempts+' attempts · displaying '+(offset+1)+'–'+Math.min(offset+25,detail.totalAttempts)+'</p>';
|
|
108
|
-
body+=detail.attempts.map(a=>'<section class="detail-block"><h3>Attempt '+dashText(a.generation)+' · '+dashText(a.state)+'</h3><dl><dt>Attempt ID</dt><dd>'+dashText(a.attemptId)+'</dd><dt>Worker ID</dt><dd>'+dashText(a.workerId)+'</dd><dt>Worker session</dt><dd>'+dashText(a.sessionId)+'</dd><dt>Model</dt><dd>'+dashText(a.metrics?.model)+'</dd><dt>Recorded tokens</dt><dd>'+dashCount(a.metrics?.usage?.totalTokens)+'</dd></dl>'+toolInventory(a.metrics?.loadedTools,a.metrics?.usedTools,a.metrics?.contextTools)+(a.metrics?.contextTools?'<h3>Loaded tools</h3>'+toolNameList(a.metrics.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(a.metrics?.usedTools)+'<h3>Latest recorded events</h3>'+a.events.map(e=>'<section class="detail-block"><h3>'+dashText(new Date(e.at).toLocaleString())+' · '+dashText(e.type)+'</h3><pre>'+dashText(JSON.stringify(e.payload,null,2))+'</pre></section>').join('')+'</section>').join('');
|
|
105
|
+
body+=detail.attempts.map(a=>'<section class="detail-block"><h3>Attempt '+dashText(a.generation)+' · '+dashText(a.state)+'</h3><dl><dt>Attempt ID</dt><dd>'+dashText(a.attemptId)+'</dd><dt>Worker ID</dt><dd>'+dashText(a.workerId)+'</dd><dt>Worker session</dt><dd>'+dashText(a.sessionId)+'</dd><dt>Model</dt><dd>'+dashText(a.metrics?.model)+'</dd><dt>Recorded tokens</dt><dd>'+dashCount(a.metrics?.usage?.totalTokens)+'</dd></dl>'+toolInventory(a.metrics?.loadedTools,a.metrics?.usedTools,a.metrics?.contextTools)+(a.metrics?.contextTools?'<h3>Loaded tools</h3>'+toolNameList(a.metrics.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(a.metrics?.usedTools)+'<h3>Latest recorded events</h3>'+a.events.map(e=>'<section class="detail-block"><h3>'+dashText(new Date(e.at).toLocaleString('en-GB',{timeZone:dashboardTimezone}))+' · '+dashText(e.type)+'</h3><pre>'+dashText(JSON.stringify(e.payload,null,2))+'</pre></section>').join('')+'</section>').join('');
|
|
109
106
|
if(offset>0)body+='<button data-attempt-page="'+Math.max(0,offset-25)+'">Newer attempts</button>';
|
|
110
107
|
if(offset+25<detail.totalAttempts)body+='<button data-attempt-page="'+(offset+25)+'">Older attempts</button>';
|
|
111
108
|
}else{
|
|
112
|
-
body+='<h2>Session</h2><dl><dt>Channel</dt><dd>'+channelBadge(detail.session?.source)+'</dd><dt>Chat</dt><dd>'+dashText(detail.session?.chatId)+'</dd><dt>Created</dt><dd>'+dashText(detail.session?.createdAt?new Date(detail.session.createdAt).toLocaleString():null)+'</dd></dl>';
|
|
109
|
+
body+='<h2>Session</h2><dl><dt>Channel</dt><dd>'+channelBadge(detail.session?.source)+'</dd><dt>Chat</dt><dd>'+dashText(detail.session?.chatId)+'</dd><dt>Created</dt><dd>'+dashText(detail.session?.createdAt?new Date(detail.session.createdAt).toLocaleString('en-GB',{timeZone:dashboardTimezone}):null)+'</dd></dl>';
|
|
113
110
|
var uBy=detail.usageByRole||[];
|
|
114
111
|
var uAgent=uBy.find(function(u){return u.role==='agent';}),uWorker=uBy.find(function(u){return u.role==='worker';});
|
|
115
112
|
var cachedLineFor=function(u){if(!u)return '';var read=Number(u.cacheReadTokens||0),base=Number(u.inputTokens||0)+read+Number(u.cacheCreationTokens||0);return '<span class="card-cached">Cached: <b>'+(base?(read/base*100).toFixed(2):'0.00')+'%</b></span>';};
|
|
@@ -119,7 +116,7 @@ async function dashDetail(agentId,sessionId,taskId,offset=0){
|
|
|
119
116
|
var cwStopped=detailActivity==='stopped';
|
|
120
117
|
body+='<div class="dash-grid session-token-totals"><div class="dash-stat box-context"><span>Context window</span><strong>'+(cwStopped?'-':(cw?dashCount(cw.used)+' / '+(cw.total==null?'—':windowCap(cw.total)):'—'))+'</strong>'+((!cwStopped&&cw&&cw.model)?'<span class="card-cached">Model: '+escHtml(cw.model)+'</span>':'')+'</div><div class="dash-stat box-agent"><span>Agent tokens</span><strong>'+dashCount(detail.totals.agentTokens)+'</strong>'+cachedLineFor(uAgent)+'</div><div class="dash-stat box-worker"><span>Worker tokens</span><strong>'+dashCount(detail.totals.workerTokens)+'</strong>'+cachedLineFor(uWorker)+'</div></div><p class="live-note">Recorded turns only. Missing measurements are shown as —, not zero. Token volume is not billing cost.</p>';
|
|
121
118
|
body+='<details class="detail-block turn-disclosure session-tasks" data-detail-turn="section:tasks"><summary>Tasks ('+dashCount(detail.totalTasks)+')</summary><div class="dash-mini-list">'+(detail.tasks||[]).map(t=>'<div class="session-task-row"><span class="session-task-title">'+dashText(t.title)+'</span>'+dashStatus(t.state)+'</div>').join('')+(!detail.tasks?.length?'<p class="muted">No tasks recorded.</p>':'')+'</div></details><h2>Turns & worker attempts</h2>';
|
|
122
|
-
body+=detail.turns.map(t=>'<details class="detail-block turn-disclosure" data-detail-turn="'+dashText(t.id)+'"><summary>'+dashText(t.role)+' · '+dashText(t.category)+' · '+dashText(new Date(t.startedAt).toLocaleString())+' · '+dashCount(t.usage?.totalTokens)+' tokens</summary><p class="live-note">'+dashText(t.id)+' · '+dashText(t.model)+' · '+dashText(t.state)+'</p>'+(t.taskId?'<p>Task '+dashText(t.taskId)+'</p>':'')+toolInventory(t.loadedTools,t.usedTools,t.contextTools)+(t.contextTools?'<h3>Loaded tools</h3>'+toolNameList(t.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(t.usedTools)+(t.inputTexts||[]).map(text=>'<pre>'+dashText(text)+'</pre>').join('')+(t.responseText?'<h3>Response / result</h3><pre>'+dashText(t.responseText)+'</pre>':'')+'</details>').join('');
|
|
119
|
+
body+=detail.turns.map(t=>'<details class="detail-block turn-disclosure" data-detail-turn="'+dashText(t.id)+'"><summary>'+dashText(t.role)+' · '+dashText(t.category)+' · '+dashText(new Date(t.startedAt).toLocaleString('en-GB',{timeZone:dashboardTimezone}))+' · '+dashCount(t.usage?.totalTokens)+' tokens</summary><p class="live-note">'+dashText(t.id)+' · '+dashText(t.model)+' · '+dashText(t.state)+'</p>'+(t.taskId?'<p>Task '+dashText(t.taskId)+'</p>':'')+toolInventory(t.loadedTools,t.usedTools,t.contextTools)+(t.contextTools?'<h3>Loaded tools</h3>'+toolNameList(t.contextTools):'')+'<h3>Used tools</h3>'+toolNameList(t.usedTools)+(t.inputTexts||[]).map(text=>'<pre>'+dashText(text)+'</pre>').join('')+(t.responseText?'<h3>Response / result</h3><pre>'+dashText(t.responseText)+'</pre>':'')+'</details>').join('');
|
|
123
120
|
if(!detail.turns.length)body+='<p class="empty">No instrumented turns recorded on this page.</p>';
|
|
124
121
|
if(offset>0)body+='<button data-session-page="'+Math.max(0,offset-50)+'">Previous records</button>';
|
|
125
122
|
if(offset+50<Math.max(detail.totalTasks||0,detail.pagination?.total||0))body+='<button data-session-page="'+(offset+50)+'">Next records</button>';
|
|
@@ -130,10 +127,10 @@ async function dashDetail(agentId,sessionId,taskId,offset=0){
|
|
|
130
127
|
function restoreDashboardDetails(){
|
|
131
128
|
const record=[...dashboardExpanded.values()][0];
|
|
132
129
|
const back=document.getElementById('dash-drawer-back'),panel=document.getElementById('dash-drawer');
|
|
133
|
-
back.classList.toggle('open',Boolean(record));document.body.style.overflow=record?'hidden':'';
|
|
130
|
+
back.classList.toggle('open',Boolean(record));document.body.style.overflow=record||document.getElementById('memory-back')?.classList.contains('open')?'hidden':'';
|
|
134
131
|
document.querySelectorAll('tr[data-dash-agent]').forEach(row=>row.setAttribute('aria-expanded',String(Boolean(record&&row.dataset.dashAgent===record.agentId&&row.dataset.dashSession===record.sessionId&&(row.dataset.dashTask||'')===(record.taskId||'')))));
|
|
135
132
|
if(!record){panel.innerHTML='';delete panel.dataset.html;return;}
|
|
136
|
-
const html='
|
|
133
|
+
const html=dashboardCloseButton('dash')+record.html;
|
|
137
134
|
if(panel.dataset.html!==html){
|
|
138
135
|
const scroll=panel.scrollTop,focused=panel.contains(document.activeElement),closeFocused=document.activeElement?.hasAttribute('data-dash-close');
|
|
139
136
|
const sameDetail=panel.dataset.agent===record.agentId&&panel.dataset.session===record.sessionId&&panel.dataset.task===(record.taskId||'');
|
|
@@ -161,7 +158,6 @@ document.addEventListener('click',function(e){
|
|
|
161
158
|
updateSidebarToggle();
|
|
162
159
|
}
|
|
163
160
|
if(e.target.closest('.tab')){const view=e.target.closest('.tab').dataset.view;document.querySelector('.dash-filter').hidden=['view-overview','view-kb','view-system'].includes(view);document.getElementById('dash-search').hidden=view==='view-dreams';document.getElementById('dash-agent-filter').hidden=view==='view-dreams';document.querySelector('.dash-pager').hidden=['view-overview','view-kb','view-dreams','view-system'].includes(view);document.body.classList.remove('menuopen');updateSidebarToggle();document.getElementById('dash-current-view').textContent=e.target.closest('.tab').textContent.trim();if(e.target.closest('.tab').dataset.view==='view-system')refreshProcesses();}
|
|
164
|
-
if(e.target.closest('#dash-theme')){const root=document.documentElement;root.dataset.theme=root.dataset.theme==='dark'?'light':'dark';}
|
|
165
161
|
});
|
|
166
162
|
document.addEventListener('keydown',function(e){
|
|
167
163
|
if(e.target.id==='sidebar-brand'&&(e.key==='Enter'||e.key===' ')){e.preventDefault();e.target.click();return;}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-client.js","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":";;;AAAA,uDAAmE;AACnE,qEAAuE;AACvE,gFAAgF;AACnE,QAAA,eAAe,GAAG,oDAA2B,GAAG,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAC,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAE,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"dashboard-client.js","sourceRoot":"","sources":["../../src/ui/dashboard-client.ts"],"names":[],"mappings":";;;AAAA,yDAA2D;AAC3D,uDAAmE;AACnE,qEAAuE;AACvE,gFAAgF;AACnE,QAAA,eAAe,GAAG,oDAA2B,GAAG,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAC,gCAAc,CAAC,QAAQ,EAAE,GAAC,GAAG,GAAE,wCAAqB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+K3J,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-controls.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-controls.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,cAAc,GAAG,MAAM,CAEzE;AACD,eAAO,MAAM,uBAAuB,QAiBnC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dashboardControlsClient = void 0;
|
|
4
|
+
exports.themeButtonHtml = themeButtonHtml;
|
|
5
|
+
/** Shared controls for dashboard pages and standalone reports. */
|
|
6
|
+
function themeButtonHtml(id) {
|
|
7
|
+
return `<button type="button" class="theme-toggle" id="${id}" data-theme-toggle aria-label="Switch to dark theme" title="Switch to dark theme"><svg class="theme-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><path d="M20.5 13A8.5 8.5 0 0 1 11 3.5 8.5 8.5 0 1 0 20.5 13Z"/></svg><svg class="theme-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1.5 1.5m11 11L19 19M5 19l1.5-1.5m11-11L19 5"/></svg></button>`;
|
|
8
|
+
}
|
|
9
|
+
exports.dashboardControlsClient = String.raw `
|
|
10
|
+
function dashboardCloseButton(action){
|
|
11
|
+
return '<div class="drawer-actions"><button type="button" class="drawer-close" data-'+action+'-close aria-label="Close details">Close ×</button></div>';
|
|
12
|
+
}
|
|
13
|
+
(function(){
|
|
14
|
+
const key='gateway-dashboard-theme';
|
|
15
|
+
function apply(theme){
|
|
16
|
+
document.documentElement.dataset.theme=theme;
|
|
17
|
+
document.querySelectorAll('[data-theme-toggle]').forEach(button=>{const label=theme==='dark'?'Switch to light theme':'Switch to dark theme';button.setAttribute('aria-label',label);button.title=label;});
|
|
18
|
+
}
|
|
19
|
+
try{const saved=localStorage.getItem(key);apply(saved==='dark'?'dark':'light');}catch{apply(document.documentElement.dataset.theme||'light');}
|
|
20
|
+
document.addEventListener('click',event=>{
|
|
21
|
+
if(!event.target.closest('[data-theme-toggle]'))return;
|
|
22
|
+
const theme=document.documentElement.dataset.theme==='dark'?'light':'dark';apply(theme);try{localStorage.setItem(key,theme);}catch{}
|
|
23
|
+
});
|
|
24
|
+
window.addEventListener('storage',event=>{if(event.key===key)apply(event.newValue==='dark'?'dark':'light');});
|
|
25
|
+
})();
|
|
26
|
+
`;
|
|
27
|
+
//# sourceMappingURL=dashboard-controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-controls.js","sourceRoot":"","sources":["../../src/ui/dashboard-controls.ts"],"names":[],"mappings":";;;AACA,0CAEC;AAHD,kEAAkE;AAClE,SAAgB,eAAe,CAAC,EAAiC;IAC/D,OAAO,kDAAkD,EAAE,sjBAAsjB,CAAC;AACpnB,CAAC;AACY,QAAA,uBAAuB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;CAiBhD,CAAC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
/** Chart palette shared with the Context bootstrap report. */
|
|
2
|
+
export declare const dashboardChartPalette: string[];
|
|
1
3
|
/** Shared display-only formatting; stored values and identifiers remain unchanged. */
|
|
2
4
|
export declare function compactNumber(value: unknown): string;
|
|
3
5
|
export declare function dashboardEscape(value: unknown): string;
|
|
6
|
+
export declare function agentHue(value: string): number;
|
|
4
7
|
export declare function agentBadge(value: string): string;
|
|
5
8
|
export declare function channelBadge(value: string): string;
|
|
6
9
|
export declare function taskStatusBadge(value: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-presentation.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMpD;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"dashboard-presentation.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB,UAAsG,CAAC;AACzI,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMpD;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AACD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG9C;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAIvE;AACD,eAAO,MAAM,2BAA2B,QAAuU,CAAC"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dashboardPresentationClient = void 0;
|
|
3
|
+
exports.dashboardPresentationClient = exports.dashboardChartPalette = void 0;
|
|
4
4
|
exports.compactNumber = compactNumber;
|
|
5
5
|
exports.dashboardEscape = dashboardEscape;
|
|
6
|
+
exports.agentHue = agentHue;
|
|
6
7
|
exports.agentBadge = agentBadge;
|
|
7
8
|
exports.channelBadge = channelBadge;
|
|
8
9
|
exports.taskStatusBadge = taskStatusBadge;
|
|
9
10
|
exports.toolNameList = toolNameList;
|
|
11
|
+
/** Chart palette shared with the Context bootstrap report. */
|
|
12
|
+
exports.dashboardChartPalette = ['#e98524', '#8e65d1', '#258fca', '#cf528b', '#359986', '#c19527', '#5c78d2', '#b66645', '#77843f', '#986499'];
|
|
10
13
|
/** Shared display-only formatting; stored values and identifiers remain unchanged. */
|
|
11
14
|
function compactNumber(value) {
|
|
12
15
|
if (value == null)
|
|
@@ -27,11 +30,14 @@ const channelIcons = { "telegram": "<svg role=\"img\" viewBox=\"0 0 24 24\" xmln
|
|
|
27
30
|
function dashboardEscape(value) {
|
|
28
31
|
return String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
|
29
32
|
}
|
|
30
|
-
function
|
|
33
|
+
function agentHue(value) {
|
|
31
34
|
let hash = 0;
|
|
32
35
|
for (const ch of value)
|
|
33
36
|
hash = (hash * 31 + ch.charCodeAt(0)) >>> 0;
|
|
34
|
-
return
|
|
37
|
+
return hash % 360;
|
|
38
|
+
}
|
|
39
|
+
function agentBadge(value) {
|
|
40
|
+
return '<span class="identity-badge" style="--agent-hue:' + agentHue(value) + '" title="' + dashboardEscape(value) + '">' + dashboardEscape(value) + '</span>';
|
|
35
41
|
}
|
|
36
42
|
function channelBadge(value) {
|
|
37
43
|
const key = String(value || 'unknown').toLowerCase();
|
|
@@ -41,7 +47,7 @@ function channelBadge(value) {
|
|
|
41
47
|
}
|
|
42
48
|
function taskStatusBadge(value) {
|
|
43
49
|
const state = String(value || 'unknown');
|
|
44
|
-
const colors = { running: '#e07a1e', working: '#e07a1e', thinking: '#d6459b', completed: '#24834a', succeeded: '#24834a', success: '#24834a', failed: '#c73946', queued: '#a16c11', starting: '#4d63c9', recovering: '#188b80', ended: '#607244', waiting_input: '#ba681c', needs_reconciliation: '#b345a4', cancel_requested: '#8c603c', interrupting: '#9e4d76', interrupted: '#7c6352', cancelled: '#657080', stopped: '#65605a', idle: '#287fc2', compacting: '#7655bd', unknown: '#737373' };
|
|
50
|
+
const colors = { pending: '#a16c11', skipped: '#657080', accepted: '#24834a', partial_failure: '#c73946', running: '#e07a1e', working: '#e07a1e', thinking: '#d6459b', completed: '#24834a', succeeded: '#24834a', success: '#24834a', failed: '#c73946', queued: '#a16c11', starting: '#4d63c9', recovering: '#188b80', ended: '#607244', waiting_input: '#ba681c', needs_reconciliation: '#b345a4', cancel_requested: '#8c603c', interrupting: '#9e4d76', interrupted: '#7c6352', cancelled: '#657080', stopped: '#65605a', idle: '#287fc2', compacting: '#7655bd', unknown: '#737373' };
|
|
45
51
|
const color = colors[state] || '#737373';
|
|
46
52
|
return '<span class="badge status-badge" style="--status-color:' + color + '">' + dashboardEscape(state.replace(/_/g, ' ').replace(/^./, c => c.toUpperCase())) + '</span>';
|
|
47
53
|
}
|
|
@@ -52,5 +58,5 @@ function toolNameList(names) {
|
|
|
52
58
|
return '<p class="muted">None</p>';
|
|
53
59
|
return '<ul class="tool-name-list">' + [...new Set(names)].sort().map(name => '<li><code>' + dashboardEscape(name) + '</code></li>').join('') + '</ul>';
|
|
54
60
|
}
|
|
55
|
-
exports.dashboardPresentationClient = compactNumber.toString() + ';' + 'const channelIcons=' + JSON.stringify(channelIcons) + ';' + dashboardEscape.toString() + ';' + agentBadge.toString() + ';' + channelBadge.toString() + ';' + taskStatusBadge.toString() + ';' + toolNameList.toString() + ';';
|
|
61
|
+
exports.dashboardPresentationClient = 'const dashboardChartPalette=' + JSON.stringify(exports.dashboardChartPalette) + ';' + compactNumber.toString() + ';' + 'const channelIcons=' + JSON.stringify(channelIcons) + ';' + dashboardEscape.toString() + ';' + agentHue.toString() + ';' + agentBadge.toString() + ';' + channelBadge.toString() + ';' + taskStatusBadge.toString() + ';' + toolNameList.toString() + ';';
|
|
56
62
|
//# sourceMappingURL=dashboard-presentation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-presentation.js","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"dashboard-presentation.js","sourceRoot":"","sources":["../../src/ui/dashboard-presentation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** Calendar windows include today, starting at 00:00 UTC. */
|
|
1
|
+
/** Calendar windows include today, starting at 00:00 in the configured timezone (UTC by default). */
|
|
2
2
|
export declare function dashboardRange(value: unknown): string;
|
|
3
|
-
export declare function dashboardSince(value: unknown, now?: number): number;
|
|
4
|
-
export declare function rangeButtons(id: string, selected: string): string;
|
|
3
|
+
export declare function dashboardSince(value: unknown, now?: number, timezone?: string): number;
|
|
4
|
+
export declare function rangeButtons(id: string, selected: string, timezone?: string): string;
|
|
5
5
|
//# sourceMappingURL=dashboard-range.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-range.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"dashboard-range.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,SAAa,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAmBzF;AACD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAGnF"}
|
|
@@ -3,18 +3,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.dashboardRange = dashboardRange;
|
|
4
4
|
exports.dashboardSince = dashboardSince;
|
|
5
5
|
exports.rangeButtons = rangeButtons;
|
|
6
|
-
/** Calendar windows include today, starting at 00:00 UTC. */
|
|
6
|
+
/** Calendar windows include today, starting at 00:00 in the configured timezone (UTC by default). */
|
|
7
7
|
function dashboardRange(value) {
|
|
8
8
|
return typeof value === 'string' && ['24h', '7d', '30d', '90d', 'all'].includes(value) ? value : '24h';
|
|
9
9
|
}
|
|
10
|
-
function dashboardSince(value, now = Date.now()) {
|
|
10
|
+
function dashboardSince(value, now = Date.now(), timezone = 'UTC') {
|
|
11
11
|
const range = dashboardRange(value);
|
|
12
12
|
if (range === 'all')
|
|
13
13
|
return 0;
|
|
14
14
|
const days = range === '24h' ? 1 : Number(range.slice(0, -1));
|
|
15
|
-
|
|
15
|
+
const parts = new Intl.DateTimeFormat('en-CA', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(now);
|
|
16
|
+
const part = (name) => Number(parts.find(p => p.type === name).value);
|
|
17
|
+
const target = Date.UTC(part('year'), part('month') - 1, part('day') - (days - 1));
|
|
18
|
+
// Resolve midnight in the configured zone, including changes in UTC offset.
|
|
19
|
+
let instant = target;
|
|
20
|
+
const clock = new Intl.DateTimeFormat('en-GB', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h23' });
|
|
21
|
+
for (let i = 0; i < 4; i++) {
|
|
22
|
+
const values = clock.formatToParts(instant);
|
|
23
|
+
const v = (name) => Number(values.find(p => p.type === name).value);
|
|
24
|
+
const local = Date.UTC(v('year'), v('month') - 1, v('day'), v('hour'), v('minute'), v('second'));
|
|
25
|
+
const next = instant + target - local;
|
|
26
|
+
if (next === instant)
|
|
27
|
+
break;
|
|
28
|
+
instant = next;
|
|
29
|
+
}
|
|
30
|
+
return instant;
|
|
16
31
|
}
|
|
17
|
-
function rangeButtons(id, selected) {
|
|
18
|
-
|
|
32
|
+
function rangeButtons(id, selected, timezone = 'UTC') {
|
|
33
|
+
timezone = timezone.replace(/[^A-Za-z0-9_+\/.-]/g, '');
|
|
34
|
+
return '<div id="' + id + '" class="range-toggle" role="group" aria-label="Date range, from midnight ' + timezone + '">' + ['24h', '7d', '30d', '90d', 'all'].map(value => '<button type="button" data-range="' + value + '" aria-pressed="' + (value === selected) + '" title="' + (value === '24h' ? 'Today from 00:00 ' + timezone : value === 'all' ? 'All recorded history' : value + ' including today, from 00:00 ' + timezone) + '">' + value + '</button>').join('') + '</div>';
|
|
19
35
|
}
|
|
20
36
|
//# sourceMappingURL=dashboard-range.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-range.js","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":";;AACA,wCAEC;AACD,
|
|
1
|
+
{"version":3,"file":"dashboard-range.js","sourceRoot":"","sources":["../../src/ui/dashboard-range.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
/** Favicon rendered from the original main-branch brandmark (35px at 4x). */
|
|
2
|
+
export declare const dashboardIconUrl = "data:image/png;base64,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";
|
|
1
3
|
/** Shared tokens from the approved pastel dashboard direction. */
|
|
2
4
|
export declare const dashboardTheme: string;
|
|
3
|
-
export declare const dashboardFontLink
|
|
5
|
+
export declare const dashboardFontLink: string;
|
|
4
6
|
//# sourceMappingURL=dashboard-theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-theme.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-theme.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"dashboard-theme.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard-theme.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,2snBAA2snB,CAAC;AACzunB,kEAAkE;AAClE,eAAO,MAAM,cAAc,QAyiB1B,CAAC;AACF,eAAO,MAAM,iBAAiB,QAA0T,CAAC"}
|