UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

1,270 lines 89 kB
import{h as e,m as t,p as n}from"./lit-runtime-BImxIzGR.js";import{o as r,t as i}from"./string-coerce-Dt6Kt5Fx.js";import{B as a,H as o,J as s,K as c,U as l,yt as u}from"./index-B6YtUsIL.js";function d(e){return!e||e.status!==`refreshing`&&e.status!==`stale`&&e.status!==`partial`?null:r(`usage.cacheStatus.title`,{status:r(`usage.cacheStatus.status.${e.status}`),pending:String(e.pendingFiles),stale:String(e.staleFiles),cached:String(e.cachedFiles)})}var f=new Set([`agent`,`channel`,`chat`,`provider`,`model`,`tool`,`label`,`key`,`session`,`id`,`has`,`mintokens`,`maxtokens`,`mincost`,`maxcost`,`minmessages`,`maxmessages`]),p=e=>i(e),m=e=>{let t=e.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`).replace(/\?/g,`.`);return RegExp(`^${t}$`,`i`)},h=e=>{let t=i(e);if(!t)return null;t.startsWith(`$`)&&(t=t.slice(1));let n=1;if(t.endsWith(`k`)?(n=1e3,t=t.slice(0,-1)):t.endsWith(`m`)&&(n=1e6,t=t.slice(0,-1)),!/^\d+(?:\.\d+)?$/.test(t))return null;let r=Number(t)*n;return!Number.isFinite(r)||!Number.isSafeInteger(Math.round(r))?null:r},g=e=>(e.match(/"[^"]+"|\S+/g)??[]).map(e=>{let t=e.replace(/^"|"$/g,``),n=t.indexOf(`:`);return n>0?{key:t.slice(0,n),value:t.slice(n+1),raw:t}:{value:t,raw:t}}),_=e=>[e.label,e.key,e.sessionId].filter(e=>!!e).map(e=>i(e)),v=e=>{let t=new Set;e.modelProvider&&t.add(i(e.modelProvider)),e.providerOverride&&t.add(i(e.providerOverride)),e.origin?.provider&&t.add(i(e.origin.provider));for(let n of e.usage?.modelUsage??[])n.provider&&t.add(i(n.provider));return Array.from(t)},y=e=>{let t=new Set;e.model&&t.add(i(e.model));for(let n of e.usage?.modelUsage??[])n.model&&t.add(i(n.model));return Array.from(t)},b=e=>(e.usage?.toolUsage?.tools??[]).map(e=>i(e.name)),x=(e,t)=>{let n=p(t.value??``);if(!n)return!0;if(!t.key)return _(e).some(e=>e.includes(n));switch(p(t.key)){case`agent`:return i(e.agentId).includes(n);case`channel`:return i(e.channel).includes(n);case`chat`:return i(e.chatType).includes(n);case`provider`:return v(e).some(e=>e.includes(n));case`model`:return y(e).some(e=>e.includes(n));case`tool`:return b(e).some(e=>e.includes(n));case`label`:return i(e.label).includes(n);case`key`:case`session`:case`id`:if(n.includes(`*`)||n.includes(`?`)){let t=m(n);return t.test(e.key)||(e.sessionId?t.test(e.sessionId):!1)}return i(e.key).includes(n)||i(e.sessionId).includes(n);case`has`:switch(n){case`tools`:return(e.usage?.toolUsage?.totalCalls??0)>0;case`errors`:return(e.usage?.messageCounts?.errors??0)>0;case`context`:return!!e.contextWeight;case`usage`:return!!e.usage;case`model`:return y(e).length>0;case`provider`:return v(e).length>0;default:return!0}case`mintokens`:{let t=h(n);return t===null?!0:(e.usage?.totalTokens??0)>=t}case`maxtokens`:{let t=h(n);return t===null?!0:(e.usage?.totalTokens??0)<=t}case`mincost`:{let t=h(n);return t===null?!0:(e.usage?.totalCost??0)>=t}case`maxcost`:{let t=h(n);return t===null?!0:(e.usage?.totalCost??0)<=t}case`minmessages`:{let t=h(n);return t===null?!0:(e.usage?.messageCounts?.total??0)>=t}case`maxmessages`:{let t=h(n);return t===null?!0:(e.usage?.messageCounts?.total??0)<=t}default:return!0}},ee=(e,t)=>{let n=g(t);if(n.length===0)return{sessions:e,warnings:[]};let r=[];for(let e of n){if(!e.key)continue;let t=p(e.key);if(!f.has(t)){r.push(`Unknown filter: ${e.key}`);continue}if(e.value===``&&r.push(`Missing value for ${e.key}`),t===`has`){let t=new Set([`tools`,`errors`,`context`,`usage`,`model`,`provider`]);e.value&&!t.has(p(e.value))&&r.push(`Unknown has:${e.value}`)}[`mintokens`,`maxtokens`,`mincost`,`maxcost`,`minmessages`,`maxmessages`].includes(t)&&e.value&&h(e.value)===null&&r.push(`Invalid number for ${e.key}`)}return{sessions:e.filter(e=>n.every(t=>x(e,t))),warnings:r}};function S(e){let t=e.split(`
`),n=new Map,r=[];for(let e of t){let t=/^\[Tool:\s*([^\]]+)\]/.exec(e.trim());if(t){let e=t[1];n.set(e,(n.get(e)??0)+1);continue}e.trim().startsWith(`[Tool Result]`)||r.push(e)}let i=Array.from(n.entries()).toSorted((e,t)=>t[1]-e[1]),a=i.reduce((e,[,t])=>e+t,0);return{tools:i,summary:i.length>0?`Tools: ${i.map(([e,t])=>`${e}×${t}`).join(`, `)} (${a} calls)`:``,cleanContent:r.join(`
`).trim()}}function C(e,t){!t||t.count<=0||(e.count+=t.count,e.sum+=t.avgMs*t.count,e.min=Math.min(e.min,t.minMs),e.max=Math.max(e.max,t.maxMs),e.p95Max=Math.max(e.p95Max,t.p95Ms))}function w(e,t){for(let n of t??[]){let t=e.get(n.date)??{date:n.date,count:0,sum:0,min:1/0,max:0,p95Max:0};t.count+=n.count,t.sum+=n.avgMs*n.count,t.min=Math.min(t.min,n.minMs),t.max=Math.max(t.max,n.maxMs),t.p95Max=Math.max(t.p95Max,n.p95Ms),e.set(n.date,t)}}function T(e){return{byChannel:Array.from(e.byChannelMap.entries()).map(([e,t])=>({channel:e,totals:t})).toSorted((e,t)=>t.totals.totalCost-e.totals.totalCost),latency:e.latencyTotals.count>0?{count:e.latencyTotals.count,avgMs:e.latencyTotals.sum/e.latencyTotals.count,minMs:e.latencyTotals.min===1/0?0:e.latencyTotals.min,maxMs:e.latencyTotals.max,p95Ms:e.latencyTotals.p95Max}:void 0,dailyLatency:Array.from(e.dailyLatencyMap.values()).map(e=>({date:e.date,count:e.count,avgMs:e.count?e.sum/e.count:0,minMs:e.min===1/0?0:e.min,maxMs:e.max,p95Ms:e.p95Max})).toSorted((e,t)=>e.date.localeCompare(t.date)),modelDaily:Array.from(e.modelDailyMap.values()).toSorted((e,t)=>e.date.localeCompare(t.date)||t.cost-e.cost),daily:Array.from(e.dailyMap.values()).toSorted((e,t)=>e.date.localeCompare(t.date))}}var E=4;function D(e){return Math.round(e/E)}function O(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:String(e)}function k(e){let t=new Date;return t.setHours(e,0,0,0),t.toLocaleTimeString(void 0,{hour:`numeric`})}function A(e,t,n){let r=e.usage;if(!r)return!1;let i=r.firstActivity??e.updatedAt,a=r.lastActivity??e.updatedAt;if(!i||!a)return!1;let o=Math.min(i,a),s=Math.max(i,a),c=Math.max(s-o,1)/6e4,l=o;for(;l<s;){let e=new Date(l),i=F(e,t),a=Math.min(i.getTime(),s),o=Math.max((a-l)/6e4,0);n({usage:r,hour:j(e,t),weekday:M(e,t),share:o/c}),l=a+1}return!0}function te(e,t){let n=Array.from({length:24},()=>0),a=Array.from({length:24},()=>0);for(let r of e){let e=r.usage;if(!(!e?.messageCounts||e.messageCounts.total===0)){if(e.utcQuarterHourMessageCounts&&e.utcQuarterHourMessageCounts.length>0){for(let r of e.utcQuarterHourMessageCounts){let e=P(r.date,r.quarterIndex,t);e&&(n[e.hour]+=r.errors,a[e.hour]+=r.total)}continue}A(r,t,({hour:t,share:r})=>{n[t]+=e.messageCounts.errors*r,a[t]+=e.messageCounts.total*r})}}return a.map((e,t)=>{let r=n[t];return{hour:t,rate:e>0?r/e:0,errors:r,msgs:e}}).filter(e=>e.msgs>0&&e.errors>0).toSorted((e,t)=>t.rate-e.rate).slice(0,5).map(e=>({label:k(e.hour),value:`${(e.rate*100).toFixed(2)}%`,sub:`${Math.round(e.errors)} ${i(r(`usage.overview.errors`))} · ${Math.round(e.msgs)} ${r(`usage.overview.messagesAbbrev`)}`}))}function j(e,t){return t===`utc`?e.getUTCHours():e.getHours()}function M(e,t){return t===`utc`?e.getUTCDay():e.getDay()}function N(e,t){let n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!n||!Number.isInteger(t)||t<0||t>95)return null;let[,r,i,a]=n,o=Number(r),s=Number(i),c=Number(a),l=new Date(Date.UTC(o,s-1,c,0,t*15));return Number.isNaN(l.valueOf())||l.getUTCFullYear()!==o||l.getUTCMonth()!==s-1||l.getUTCDate()!==c?null:l}function P(e,t,n){let r=N(e,t);return r?{hour:j(r,n),weekday:M(r,n)}:null}function F(e,t){let n=new Date(e);return t===`utc`?n.setUTCMinutes(59,59,999):n.setMinutes(59,59,999),n}function I(e,t,n){let r=e.usage?.utcQuarterHourTokenUsage;if(!r||r.length===0)return!1;let i=!1;for(let e of r){if(e.totalTokens<=0)continue;let r=P(e.date,e.quarterIndex,t);r&&(i=!0,n({hour:r.hour,weekday:r.weekday,tokens:e.totalTokens}))}return i}function L(e,t,n){let r=e.usage,i=r?.firstActivity??e.updatedAt,a=r?.lastActivity??e.updatedAt;if(!i||!a)return!1;let o=Math.min(i,a),s=Math.max(i,a),c=o;for(;c<=s;){let e=new Date(c),r=j(e,n);if(t.includes(r))return!0;let i=F(e,n);c=Math.min(i.getTime(),s)+1}return!1}function ne(e,t,n){if(t.length===0)return!0;let r=!1;return I(e,n,({hour:e})=>{t.includes(e)&&(r=!0)})?r:L(e,t,n)}function R(e,t){let n=Array.from({length:24},()=>0),i=Array.from({length:7},()=>0),a=0,o=!1;for(let r of e){let e=r.usage;if(!(!e||!e.totalTokens||e.totalTokens<=0)){if(a+=e.totalTokens,I(r,t,({hour:e,weekday:t,tokens:r})=>{n[e]+=r,i[t]+=r})){o=!0;continue}A(r,t,({usage:e,hour:t,weekday:r,share:a})=>{n[t]+=e.totalTokens*a,i[r]+=e.totalTokens*a})&&(o=!0)}}let s=[r(`usage.mosaic.sun`),r(`usage.mosaic.mon`),r(`usage.mosaic.tue`),r(`usage.mosaic.wed`),r(`usage.mosaic.thu`),r(`usage.mosaic.fri`),r(`usage.mosaic.sat`)].map((e,t)=>({label:e,tokens:i[t]}));return{hasData:o,totalTokens:a,hourTotals:n,weekdayTotals:s}}function re(e,n,a,o){let s=R(e,n);if(!s.hasData)return t`
      <div class="card usage-mosaic">
        <div class="usage-mosaic-header">
          <div>
            <div class="usage-mosaic-title">${r(`usage.mosaic.title`)}</div>
            <div class="usage-mosaic-sub">${r(`usage.mosaic.subtitleEmpty`)}</div>
          </div>
          <div class="usage-mosaic-total">
            ${O(0)} ${i(r(`usage.metrics.tokens`))}
          </div>
        </div>
        <div class="usage-empty-block usage-empty-block--compact">
          ${r(`usage.mosaic.noTimelineData`)}
        </div>
      </div>
    `;let c=Math.max(...s.hourTotals,1),l=Math.max(...s.weekdayTotals.map(e=>e.tokens),1);return t`
    <div class="card usage-mosaic">
      <div class="usage-mosaic-header">
        <div>
          <div class="usage-mosaic-title">${r(`usage.mosaic.title`)}</div>
          <div class="usage-mosaic-sub">
            ${r(`usage.mosaic.subtitle`,{zone:r(n===`utc`?`usage.filters.timeZoneUtc`:`usage.filters.timeZoneLocal`)})}
          </div>
        </div>
        <div class="usage-mosaic-total">
          ${O(s.totalTokens)}
          ${i(r(`usage.metrics.tokens`))}
        </div>
      </div>
      <div class="usage-mosaic-grid">
        <div class="usage-mosaic-section">
          <div class="usage-mosaic-section-title">${r(`usage.mosaic.dayOfWeek`)}</div>
          <div class="usage-daypart-grid">
            ${s.weekdayTotals.map(e=>{let n=Math.min(e.tokens/l,1);return t`
                <div class="usage-daypart-cell" style="background: ${e.tokens>0?`color-mix(in srgb, var(--accent) ${(12+n*60).toFixed(1)}%, transparent)`:`transparent`};">
                  <div class="usage-daypart-label">${e.label}</div>
                  <div class="usage-daypart-value">${O(e.tokens)}</div>
                </div>
              `})}
          </div>
        </div>
        <div class="usage-mosaic-section">
          <div class="usage-mosaic-section-title">
            <span>${r(`usage.filters.hours`)}</span>
            <span class="usage-mosaic-sub">0 → 23</span>
          </div>
          <div class="usage-hour-grid">
            ${s.hourTotals.map((e,n)=>{let s=Math.min(e/c,1),l=e>0?`color-mix(in srgb, var(--accent) ${(8+s*70).toFixed(1)}%, transparent)`:`transparent`,u=`${n}:00 · ${O(e)} ${i(r(`usage.metrics.tokens`))}`,d=s>.7?`color-mix(in srgb, var(--accent) 60%, transparent)`:`color-mix(in srgb, var(--accent) 24%, transparent)`;return t`
                <div
                  class="usage-hour-cell ${a.includes(n)?`selected`:``}"
                  style="background: ${l}; border-color: ${d};"
                  title="${u}"
                  @click=${e=>o(n,e.shiftKey)}
                ></div>
              `})}
          </div>
          <div class="usage-hour-labels">
            <span>${r(`usage.mosaic.midnight`)}</span>
            <span>${r(`usage.mosaic.fourAm`)}</span>
            <span>${r(`usage.mosaic.eightAm`)}</span>
            <span>${r(`usage.mosaic.noon`)}</span>
            <span>${r(`usage.mosaic.fourPm`)}</span>
            <span>${r(`usage.mosaic.eightPm`)}</span>
          </div>
          <div class="usage-hour-legend">
            <span></span>
            ${r(`usage.mosaic.legend`)}
          </div>
        </div>
      </div>
    </div>
  `}function z(e,t=2){return`$${e.toFixed(t)}`}function ie(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`}function B(e){let t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return null;let[,n,r,i]=t,a=new Date(Date.UTC(Number(n),Number(r)-1,Number(i)));return Number.isNaN(a.valueOf())?null:a}function V(e){let t=B(e);return t?t.toLocaleDateString(void 0,{month:`short`,day:`numeric`}):e}function H(e){let t=B(e);return t?t.toLocaleDateString(void 0,{month:`long`,day:`numeric`,year:`numeric`}):e}var U=()=>({input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,totalCost:0,inputCost:0,outputCost:0,cacheReadCost:0,cacheWriteCost:0,missingCostEntries:0}),W=(e,t)=>{e.input+=t.input??0,e.output+=t.output??0,e.cacheRead+=t.cacheRead??0,e.cacheWrite+=t.cacheWrite??0,e.totalTokens+=t.totalTokens??0,e.totalCost+=t.totalCost??0,e.inputCost+=t.inputCost??0,e.outputCost+=t.outputCost??0,e.cacheReadCost+=t.cacheReadCost??0,e.cacheWriteCost+=t.cacheWriteCost??0,e.missingCostEntries+=t.missingCostEntries??0},G=(e,t)=>{if(e.length===0)return t??{messages:{total:0,user:0,assistant:0,toolCalls:0,toolResults:0,errors:0},tools:{totalCalls:0,uniqueTools:0,tools:[]},byModel:[],byProvider:[],byAgent:[],byChannel:[],daily:[]};let n={total:0,user:0,assistant:0,toolCalls:0,toolResults:0,errors:0},r=new Map,i=new Map,a=new Map,o=new Map,s=new Map,c=new Map,l=new Map,u=new Map,d={count:0,sum:0,min:1/0,max:0,p95Max:0};for(let t of e){let e=t.usage;if(e){if(e.messageCounts&&(n.total+=e.messageCounts.total,n.user+=e.messageCounts.user,n.assistant+=e.messageCounts.assistant,n.toolCalls+=e.messageCounts.toolCalls,n.toolResults+=e.messageCounts.toolResults,n.errors+=e.messageCounts.errors),e.toolUsage)for(let t of e.toolUsage.tools)r.set(t.name,(r.get(t.name)??0)+t.count);if(e.modelUsage)for(let t of e.modelUsage){let e=`${t.provider??`unknown`}::${t.model??`unknown`}`,n=i.get(e)??{provider:t.provider,model:t.model,count:0,totals:U()};n.count+=t.count,W(n.totals,t.totals),i.set(e,n);let r=t.provider??`unknown`,o=a.get(r)??{provider:t.provider,model:void 0,count:0,totals:U()};o.count+=t.count,W(o.totals,t.totals),a.set(r,o)}if(C(d,e.latency),t.agentId){let n=o.get(t.agentId)??U();W(n,e),o.set(t.agentId,n)}if(t.channel){let n=s.get(t.channel)??U();W(n,e),s.set(t.channel,n)}for(let t of e.dailyBreakdown??[]){let e=c.get(t.date)??{date:t.date,tokens:0,cost:0,messages:0,toolCalls:0,errors:0};e.tokens+=t.tokens,e.cost+=t.cost,c.set(t.date,e)}for(let t of e.dailyMessageCounts??[]){let e=c.get(t.date)??{date:t.date,tokens:0,cost:0,messages:0,toolCalls:0,errors:0};e.messages+=t.total,e.toolCalls+=t.toolCalls,e.errors+=t.errors,c.set(t.date,e)}w(l,e.dailyLatency);for(let t of e.dailyModelUsage??[]){let e=`${t.date}::${t.provider??`unknown`}::${t.model??`unknown`}`,n=u.get(e)??{date:t.date,provider:t.provider,model:t.model,tokens:0,cost:0,count:0};n.tokens+=t.tokens,n.cost+=t.cost,n.count+=t.count,u.set(e,n)}}}let f=T({byChannelMap:s,latencyTotals:d,dailyLatencyMap:l,modelDailyMap:u,dailyMap:c});return{messages:n,tools:{totalCalls:Array.from(r.values()).reduce((e,t)=>e+t,0),uniqueTools:r.size,tools:Array.from(r.entries()).map(([e,t])=>({name:e,count:t})).toSorted((e,t)=>t.count-e.count)},byModel:Array.from(i.values()).toSorted((e,t)=>t.totals.totalCost-e.totals.totalCost),byProvider:Array.from(a.values()).toSorted((e,t)=>t.totals.totalCost-e.totals.totalCost),byAgent:Array.from(o.entries()).map(([e,t])=>({agentId:e,totals:t})).toSorted((e,t)=>t.totals.totalCost-e.totals.totalCost),...f}},ae=(e,t,n)=>{let r=0,i=0;for(let t of e){let e=t.usage?.durationMs??0;e>0&&(r+=e,i+=1)}let a=i?r/i:0,o=t&&r>0?t.totalTokens/(r/6e4):void 0,s=t&&r>0?t.totalCost/(r/6e4):void 0,c=n.messages.total?n.messages.errors/n.messages.total:0,l;for(let e of n.daily){if(e.messages<=0||e.errors<=0)continue;let t={date:e.date,errors:e.errors,messages:e.messages,rate:e.errors/e.messages};(!l||t.rate>l.rate||t.rate===l.rate&&t.errors>l.errors)&&(l=t)}return{durationSumMs:r,durationCount:i,avgDurationMs:a,throughputTokensPerMin:o,throughputCostPerMin:s,errorRate:c,peakErrorDay:l}};function oe(e,t,n=`text/plain`){let r=new Blob([t],{type:`${n};charset=utf-8`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=e,a.click(),URL.revokeObjectURL(i)}function se(e){return/[",\n]/.test(e)?`"${e.replaceAll(`"`,`""`)}"`:e}function ce(e){return e.map(e=>e==null?``:se(String(e))).join(`,`)}var le=e=>{let t=[ce([`key`,`label`,`agentId`,`channel`,`provider`,`model`,`updatedAt`,`durationMs`,`messages`,`errors`,`toolCalls`,`inputTokens`,`outputTokens`,`cacheReadTokens`,`cacheWriteTokens`,`totalTokens`,`totalCost`])];for(let n of e){let e=n.usage;t.push(ce([n.key,n.label??``,n.agentId??``,n.channel??``,n.modelProvider??n.providerOverride??``,n.model??n.modelOverride??``,s(n.updatedAt)??``,e?.durationMs??``,e?.messageCounts?.total??``,e?.messageCounts?.errors??``,e?.messageCounts?.toolCalls??``,e?.input??``,e?.output??``,e?.cacheRead??``,e?.cacheWrite??``,e?.totalTokens??``,e?.totalCost??``]))}return t.join(`
`)},ue=e=>{let t=[ce([`date`,`inputTokens`,`outputTokens`,`cacheReadTokens`,`cacheWriteTokens`,`totalTokens`,`inputCost`,`outputCost`,`cacheReadCost`,`cacheWriteCost`,`totalCost`])];for(let n of e)t.push(ce([n.date,n.input,n.output,n.cacheRead,n.cacheWrite,n.totalTokens,n.inputCost??``,n.outputCost??``,n.cacheReadCost??``,n.cacheWriteCost??``,n.totalCost]));return t.join(`
`)},de=(e,t,n)=>{let r=e.trim();if(!r)return[];let a=r.length?r.split(/\s+/):[],o=a.length?a[a.length-1]:``,[s,c]=o.includes(`:`)?[o.slice(0,o.indexOf(`:`)),o.slice(o.indexOf(`:`)+1)]:[``,``],l=i(s),d=i(c),f=e=>u(e.filter(e=>!!e)),p=f(t.map(e=>e.agentId)).slice(0,6),m=f(t.map(e=>e.channel)).slice(0,6),h=f([...t.map(e=>e.modelProvider),...t.map(e=>e.providerOverride),...n?.byProvider.map(e=>e.provider)??[]]).slice(0,6),g=f([...t.map(e=>e.model),...n?.byModel.map(e=>e.model)??[]]).slice(0,6),_=f(n?.tools.tools.map(e=>e.name)??[]).slice(0,6);if(!l)return[{label:`agent:`,value:`agent:`},{label:`channel:`,value:`channel:`},{label:`provider:`,value:`provider:`},{label:`model:`,value:`model:`},{label:`tool:`,value:`tool:`},{label:`has:errors`,value:`has:errors`},{label:`has:tools`,value:`has:tools`},{label:`minTokens:`,value:`minTokens:`},{label:`maxCost:`,value:`maxCost:`}];let v=[],y=(e,t)=>{for(let n of t)(!d||i(n).includes(d))&&v.push({label:`${e}:${n}`,value:`${e}:${n}`})};switch(l){case`agent`:y(`agent`,p);break;case`channel`:y(`channel`,m);break;case`provider`:y(`provider`,h);break;case`model`:y(`model`,g);break;case`tool`:y(`tool`,_);break;case`has`:[`errors`,`tools`,`context`,`usage`,`model`,`provider`].forEach(e=>{(!d||e.includes(d))&&v.push({label:`has:${e}`,value:`has:${e}`})});break;default:break}return v},fe=(e,t)=>{let n=e.trim();if(!n)return`${t} `;let r=n.split(/\s+/);return r[r.length-1]=t,`${r.join(` `)} `},K=e=>i(e),pe=(e,t)=>{let n=e.trim();if(!n)return`${t} `;let r=n.split(/\s+/),i=r[r.length-1]??``,a=t.includes(`:`)?t.split(`:`)[0]:null,o=i.includes(`:`)?i.split(`:`)[0]:null;return i.endsWith(`:`)&&a&&o===a?(r[r.length-1]=t,`${r.join(` `)} `):r.includes(t)?`${r.join(` `)} `:`${r.join(` `)} ${t} `},me=(e,t)=>{let n=e.trim().split(/\s+/).filter(Boolean).filter(e=>e!==t);return n.length?`${n.join(` `)} `:``},he=(e,t,n)=>{let r=K(t),i=[...g(e).filter(e=>K(e.key??``)!==r).map(e=>e.raw),...n.map(e=>`${t}:${e}`)];return i.length?`${i.join(` `)} `:``};function q(e,t){return t===0?0:e/t*100}var ge=8,_e=8,J=null,Y=null,ve=!1,ye=null,be=!1,xe=null;function Se(e,t,n){return Math.min(Math.max(e,t),Math.max(t,n))}function Ce(){return Y||(Y=document.createElement(`div`),Y.className=`daily-bar-tooltip daily-bar-tooltip--floating`),Y.isConnected||document.body.append(Y),Y}function we(e,t){let n=document.createElement(`strong`);n.textContent=t.dateLabel;let r=[n,document.createElement(`br`),document.createTextNode(t.tokensLabel),document.createElement(`br`),document.createTextNode(t.costLabel)];for(let e of t.breakdownLines){let t=document.createElement(`div`);t.textContent=e,r.push(t)}e.replaceChildren(...r)}function Te(){if(!J)return;if(!J.source.isConnected){je();return}let e=Ce(),t=J.source.getBoundingClientRect();e.style.visibility=`hidden`,e.style.left=`0px`,e.style.top=`0px`;let n=e.getBoundingClientRect(),r=window.innerWidth||document.documentElement.clientWidth,i=window.innerHeight||document.documentElement.clientHeight,a=r-n.width-ge,o=i-n.height-ge,s=Se(t.left+t.width/2-n.width/2,ge,a),c=t.top-n.height-_e,l=`above`;c<ge&&(l=`below`,c=t.bottom+_e),e.dataset.placement=l,e.style.left=`${Math.round(s)}px`,e.style.top=`${Math.round(Se(c,ge,o))}px`,e.style.visibility=``}function Ee(){ve||=(window.addEventListener(`resize`,Te),window.addEventListener(`scroll`,Te,!0),!0)}function De(){ve&&=(window.removeEventListener(`resize`,Te),window.removeEventListener(`scroll`,Te,!0),!1)}function Oe(){ye||(ye=new MutationObserver(()=>{J&&!J.source.isConnected&&je()}),ye.observe(document.body,{childList:!0,subtree:!0}))}function ke(){ye?.disconnect(),ye=null}function Ae(e,t,n){(!J||J.source!==e)&&(J={source:e,reasons:new Set,content:t}),J.content=t,J.reasons.add(n),we(Ce(),t),Te(),Ee(),Oe()}function je(e,t){J&&(e&&J.source!==e||t&&(J.reasons.delete(t),J.reasons.size>0)||(J=null,Y?.remove(),De(),ke()))}function Me(){be=!0,xe!==null&&window.clearTimeout(xe),xe=window.setTimeout(()=>{be=!1,xe=null},0)}function Ne(e,t){be||Ae(e,t,`focus`)}function Pe(e,t,n){e.key!==`Enter`&&e.key!==` `||(e.preventDefault(),n(t,e.shiftKey))}function Fe(e){let t=e.totalCost||0;return{input:{tokens:e.input,cost:e.inputCost||0,pct:q(e.inputCost||0,t)},output:{tokens:e.output,cost:e.outputCost||0,pct:q(e.outputCost||0,t)},cacheRead:{tokens:e.cacheRead,cost:e.cacheReadCost||0,pct:q(e.cacheReadCost||0,t)},cacheWrite:{tokens:e.cacheWrite,cost:e.cacheWriteCost||0,pct:q(e.cacheWriteCost||0,t)},totalCost:t}}function Ie(e,i,a,o,s,c,l,u){if(!(e.length>0||i.length>0||a.length>0))return n;let d=a.length===1?o.find(e=>e.key===a[0]):null,f=d?(d.label||d.key).slice(0,20)+((d.label||d.key).length>20?`…`:``):a.length===1?a[0].slice(0,8)+`…`:r(`usage.filters.sessionsCount`,{count:String(a.length)}),p=d?d.label||d.key:a.length===1?a[0]:a.join(`, `),m=e.length===1?e[0]:r(`usage.filters.daysCount`,{count:String(e.length)}),h=i.length===1?`${i[0]}:00`:r(`usage.filters.hoursCount`,{count:String(i.length)});return t`
    <div class="active-filters">
      ${e.length>0?t`
            <div class="filter-chip">
              <span class="filter-chip-label">${r(`usage.filters.days`)}: ${m}</span>
              <button
                class="filter-chip-remove"
                @click=${s}
                title=${r(`usage.filters.remove`)}
                aria-label="Remove days filter"
              >
                ×
              </button>
            </div>
          `:n}
      ${i.length>0?t`
            <div class="filter-chip">
              <span class="filter-chip-label">${r(`usage.filters.hours`)}: ${h}</span>
              <button
                class="filter-chip-remove"
                @click=${c}
                title=${r(`usage.filters.remove`)}
                aria-label="Remove hours filter"
              >
                ×
              </button>
            </div>
          `:n}
      ${a.length>0?t`
            <div class="filter-chip" title="${p}">
              <span class="filter-chip-label">${r(`usage.filters.session`)}: ${f}</span>
              <button
                class="filter-chip-remove"
                @click=${l}
                title=${r(`usage.filters.remove`)}
                aria-label="Remove session filter"
              >
                ×
              </button>
            </div>
          `:n}
      ${(e.length>0||i.length>0)&&a.length>0?t`
            <button class="btn btn--sm" @click=${u}>
              ${r(`usage.filters.clearAll`)}
            </button>
          `:n}
    </div>
  `}function Le(e,a,o,s,c,l){if(!e.length)return t`
      <div class="daily-chart-compact">
        <div class="card-title usage-section-title">${r(`usage.daily.title`)}</div>
        <div class="usage-empty-block">${r(`usage.empty.noData`)}</div>
      </div>
    `;let u=o===`tokens`,d=e.map(e=>u?e.totalTokens:e.totalCost),f=Math.max(...d,u?1:1e-4),p=d.filter(e=>e>0),m=f/(p.length>0?Math.min(...p):f),h=d.map(e=>{if(e<=0)return 0;let t=m>50?Math.sqrt(e/f):e/f;return Math.max(6,t*200)}),g=e.length>30?12:e.length>20?18:e.length>14?24:32,_=e.length<=14;return t`
    <div class="daily-chart-compact">
      <div class="daily-chart-header">
        <div class="chart-toggle small sessions-toggle">
          <button
            class="btn btn--sm toggle-btn ${s===`total`?`active`:``}"
            @click=${()=>c(`total`)}
          >
            ${r(`usage.daily.total`)}
          </button>
          <button
            class="btn btn--sm toggle-btn ${s===`by-type`?`active`:``}"
            @click=${()=>c(`by-type`)}
          >
            ${r(`usage.daily.byType`)}
          </button>
        </div>
        <div class="card-title">
          ${r(u?`usage.daily.tokensTitle`:`usage.daily.costTitle`)}
        </div>
      </div>
      <div class="daily-chart">
        <div class="daily-chart-bars" style="--bar-max-width: ${g}px">
          ${e.map((o,c)=>{let d=h[c],f=a.includes(o.date),p=V(o.date),m=e.length>20?String(Number.parseInt(o.date.slice(8),10)):p,g=e.length>20?`daily-bar-label daily-bar-label--compact`:`daily-bar-label`,v=s===`by-type`?u?[{value:o.output,class:`output`},{value:o.input,class:`input`},{value:o.cacheWrite,class:`cache-write`},{value:o.cacheRead,class:`cache-read`}]:[{value:o.outputCost??0,class:`output`},{value:o.inputCost??0,class:`input`},{value:o.cacheWriteCost??0,class:`cache-write`},{value:o.cacheReadCost??0,class:`cache-read`}]:[],y=s===`by-type`?u?[`${r(`usage.breakdown.output`)} ${O(o.output)}`,`${r(`usage.breakdown.input`)} ${O(o.input)}`,`${r(`usage.breakdown.cacheWrite`)} ${O(o.cacheWrite)}`,`${r(`usage.breakdown.cacheRead`)} ${O(o.cacheRead)}`]:[`${r(`usage.breakdown.output`)} ${z(o.outputCost??0)}`,`${r(`usage.breakdown.input`)} ${z(o.inputCost??0)}`,`${r(`usage.breakdown.cacheWrite`)} ${z(o.cacheWriteCost??0)}`,`${r(`usage.breakdown.cacheRead`)} ${z(o.cacheReadCost??0)}`]:[],b=u?O(o.totalTokens):z(o.totalCost),x={dateLabel:H(o.date),tokensLabel:`${O(o.totalTokens)} ${i(r(`usage.metrics.tokens`))}`.trim(),costLabel:z(o.totalCost),breakdownLines:y};return t`
              <div
                class="daily-bar-wrapper ${f?`selected`:``}"
                role="button"
                tabindex="0"
                aria-pressed=${f?`true`:`false`}
                aria-label=${`${x.dateLabel}: ${x.tokensLabel}, ${x.costLabel}`}
                @pointerdown=${Me}
                @mouseenter=${e=>Ae(e.currentTarget,x,`hover`)}
                @mouseleave=${e=>je(e.currentTarget,`hover`)}
                @focus=${e=>Ne(e.currentTarget,x)}
                @blur=${e=>je(e.currentTarget,`focus`)}
                @keydown=${e=>Pe(e,o.date,l)}
                @click=${e=>l(o.date,e.shiftKey)}
              >
                ${s===`by-type`?t`
                      <div
                        class="daily-bar daily-bar--stacked"
                        style="height: ${d.toFixed(0)}px;"
                      >
                        ${(()=>{let e=v.reduce((e,t)=>e+t.value,0)||1;return v.map(n=>t`
                              <div
                                class="cost-segment ${n.class}"
                                style="height: ${n.value/e*100}%"
                              ></div>
                            `)})()}
                      </div>
                    `:t` <div class="daily-bar" style="height: ${d.toFixed(0)}px"></div> `}
                ${_?t`<div class="daily-bar-total">${b}</div>`:n}
                <div class="${g}">${m}</div>
              </div>
            `})}
        </div>
      </div>
    </div>
  `}function Re(e,n){let i=Fe(e),a=n===`tokens`,o=e.totalTokens||1,s={output:q(e.output,o),input:q(e.input,o),cacheWrite:q(e.cacheWrite,o),cacheRead:q(e.cacheRead,o)};return t`
    <div class="cost-breakdown cost-breakdown-compact">
      <div class="cost-breakdown-header">
        ${r(a?`usage.breakdown.tokensByType`:`usage.breakdown.costByType`)}
      </div>
      <div class="cost-breakdown-bar">
        <div
          class="cost-segment output"
          style="width: ${(a?s.output:i.output.pct).toFixed(1)}%"
          title="${r(`usage.breakdown.output`)}: ${a?O(e.output):z(i.output.cost)}"
        ></div>
        <div
          class="cost-segment input"
          style="width: ${(a?s.input:i.input.pct).toFixed(1)}%"
          title="${r(`usage.breakdown.input`)}: ${a?O(e.input):z(i.input.cost)}"
        ></div>
        <div
          class="cost-segment cache-write"
          style="width: ${(a?s.cacheWrite:i.cacheWrite.pct).toFixed(1)}%"
          title="${r(`usage.breakdown.cacheWrite`)}: ${a?O(e.cacheWrite):z(i.cacheWrite.cost)}"
        ></div>
        <div
          class="cost-segment cache-read"
          style="width: ${(a?s.cacheRead:i.cacheRead.pct).toFixed(1)}%"
          title="${r(`usage.breakdown.cacheRead`)}: ${a?O(e.cacheRead):z(i.cacheRead.cost)}"
        ></div>
      </div>
      <div class="cost-breakdown-legend">
        <span class="legend-item"
          ><span class="legend-dot output"></span>${r(`usage.breakdown.output`)}
          ${a?O(e.output):z(i.output.cost)}</span
        >
        <span class="legend-item"
          ><span class="legend-dot input"></span>${r(`usage.breakdown.input`)}
          ${a?O(e.input):z(i.input.cost)}</span
        >
        <span class="legend-item"
          ><span class="legend-dot cache-write"></span>${r(`usage.breakdown.cacheWrite`)}
          ${a?O(e.cacheWrite):z(i.cacheWrite.cost)}</span
        >
        <span class="legend-item"
          ><span class="legend-dot cache-read"></span>${r(`usage.breakdown.cacheRead`)}
          ${a?O(e.cacheRead):z(i.cacheRead.cost)}</span
        >
      </div>
      <div class="cost-breakdown-total">
        ${r(`usage.breakdown.total`)}:
        ${a?O(e.totalTokens):z(e.totalCost)}
      </div>
    </div>
  `}function ze(e,r,i){return t`
    <div class="usage-insight-card">
      <div class="usage-insight-title">${e}</div>
      ${r.length===0?t`<div class="muted">${i}</div>`:t`
            <div class="usage-list">
              ${r.map(e=>t`
                  <div class="usage-list-item">
                    <span>${e.label}</span>
                    <span class="usage-list-value">
                      <span>${e.value}</span>
                      ${e.sub?t`<span class="usage-list-sub">${e.sub}</span>`:n}
                    </span>
                  </div>
                `)}
            </div>
          `}
    </div>
  `}function Be(e,r,i,a){let o=[`usage-insight-card`,a?.className].filter(Boolean).join(` `),s=[`usage-error-list`,a?.listClassName].filter(Boolean).join(` `);return t`
    <div class=${o}>
      <div class="usage-insight-title">${e}</div>
      ${r.length===0?t`<div class="muted">${i}</div>`:t`
            <div class=${s}>
              ${r.map(e=>t`
                  <div class="usage-error-row">
                    <div class="usage-error-date">${e.label}</div>
                    <div class="usage-error-rate">${e.value}</div>
                    ${e.sub?t`<div class="usage-error-sub">${e.sub}</div>`:n}
                  </div>
                `)}
            </div>
          `}
    </div>
  `}function X(e){let n=[`stat`,`usage-summary-card`,e.className,e.tone?`usage-summary-card--${e.tone}`:``].filter(Boolean).join(` `),r=[`stat-value`,`usage-summary-value`,e.tone??``,e.compactValue?`usage-summary-value--compact`:``].filter(Boolean).join(` `);return t`
    <div class=${n}>
      <div class="usage-summary-title">
        ${e.title}
        <span class="usage-summary-hint" title=${e.hint}>?</span>
      </div>
      <div class=${r}>${e.value}</div>
      <div class="usage-summary-sub">${e.sub}</div>
    </div>
  `}function Ve(e,a,o,s,l,u,d){if(!e)return n;let f=a.messages.total?Math.round(e.totalTokens/a.messages.total):0,p=a.messages.total?e.totalCost/a.messages.total:0,m=e.input+e.cacheRead+e.cacheWrite,h=m>0?e.cacheRead/m:0,g=m>0?`${(h*100).toFixed(1)}%`:r(`usage.common.emptyValue`),_=o.errorRate*100,v=o.throughputTokensPerMin===void 0?r(`usage.common.emptyValue`):`${O(Math.round(o.throughputTokensPerMin))} ${r(`usage.overview.tokensPerMinute`)}`,y=o.throughputCostPerMin===void 0?r(`usage.common.emptyValue`):`${z(o.throughputCostPerMin,4)} ${r(`usage.overview.perMinute`)}`,b=o.durationCount>0?c(o.avgDurationMs,{spaced:!0})??r(`usage.common.emptyValue`):r(`usage.common.emptyValue`),x=r(`usage.overview.cacheHint`),ee=r(`usage.overview.errorHint`),S=r(`usage.overview.throughputHint`),C=r(`usage.overview.avgTokensHint`),w=r(s?`usage.overview.avgCostHintMissing`:`usage.overview.avgCostHint`),T=a.daily.filter(e=>e.messages>0&&e.errors>0).map(e=>{let t=e.errors/e.messages;return{label:V(e.date),value:`${(t*100).toFixed(2)}%`,sub:`${e.errors} ${i(r(`usage.overview.errors`))} · ${e.messages} ${r(`usage.overview.messagesAbbrev`)} · ${O(e.tokens)}`,rate:t}}).toSorted((e,t)=>t.rate-e.rate).slice(0,5).map(({rate:e,...t})=>t),E=a.byModel.slice(0,5).map(e=>({label:e.model??r(`usage.common.unknown`),value:z(e.totals.totalCost),sub:`${O(e.totals.totalTokens)} · ${e.count} ${r(`usage.overview.messagesAbbrev`)}`})),D=a.byProvider.slice(0,5).map(e=>({label:e.provider??r(`usage.common.unknown`),value:z(e.totals.totalCost),sub:`${O(e.totals.totalTokens)} · ${e.count} ${r(`usage.overview.messagesAbbrev`)}`})),k=a.tools.tools.slice(0,6).map(e=>({label:e.name,value:`${e.count}`,sub:r(`usage.overview.calls`)})),A=a.byAgent.slice(0,5).map(e=>({label:e.agentId,value:z(e.totals.totalCost),sub:O(e.totals.totalTokens)})),te=a.byChannel.slice(0,5).map(e=>({label:e.channel,value:z(e.totals.totalCost),sub:O(e.totals.totalTokens)}));return t`
    <section class="card usage-overview-card">
      <div class="card-title">${r(`usage.overview.title`)}</div>
      <div class="usage-overview-layout">
        <div class="usage-summary-grid">
          ${X({title:r(`usage.overview.messages`),hint:r(`usage.overview.messagesHint`),value:a.messages.total,sub:`${a.messages.user} ${i(r(`usage.overview.user`))} · ${a.messages.assistant} ${i(r(`usage.overview.assistant`))}`,className:`usage-summary-card--hero`})}
          ${X({title:r(`usage.overview.throughput`),hint:S,value:v,sub:y,className:`usage-summary-card--hero usage-summary-card--throughput`,compactValue:!0})}
          ${X({title:r(`usage.overview.toolCalls`),hint:r(`usage.overview.toolCallsHint`),value:a.tools.totalCalls,sub:`${a.tools.uniqueTools} ${r(`usage.overview.toolsUsed`)}`,className:`usage-summary-card--half`})}
          ${X({title:r(`usage.overview.avgTokens`),hint:C,value:O(f),sub:r(`usage.overview.acrossMessages`,{count:String(a.messages.total||0)}),className:`usage-summary-card--half`})}
          ${X({title:r(`usage.overview.cacheHitRate`),hint:x,value:g,sub:`${O(e.cacheRead)} ${r(`usage.overview.cached`)} · ${O(m)} ${r(`usage.overview.prompt`)}`,tone:h>.6?`good`:h>.3?`warn`:`bad`,className:`usage-summary-card--medium`})}
          ${X({title:r(`usage.overview.errorRate`),hint:ee,value:`${_.toFixed(2)}%`,sub:`${a.messages.errors} ${i(r(`usage.overview.errors`))} · ${b} ${r(`usage.overview.avgSession`)}`,tone:_>5?`bad`:_>1?`warn`:`good`,className:`usage-summary-card--medium`})}
          ${X({title:r(`usage.overview.avgCost`),hint:w,value:z(p,4),sub:`${z(e.totalCost)} ${i(r(`usage.breakdown.total`))}`,className:`usage-summary-card--compact`})}
          ${X({title:r(`usage.overview.sessions`),hint:r(`usage.overview.sessionsHint`),value:u,sub:r(`usage.overview.sessionsInRange`,{count:String(d)}),className:`usage-summary-card--compact`})}
          ${X({title:r(`usage.overview.errors`),hint:r(`usage.overview.errorsHint`),value:a.messages.errors,sub:`${a.messages.toolResults} ${r(`usage.overview.toolResults`)}`,className:`usage-summary-card--compact`})}
        </div>
        <div class="usage-insights-grid">
          ${ze(r(`usage.overview.topModels`),E,r(`usage.overview.noModelData`))}
          ${ze(r(`usage.overview.topProviders`),D,r(`usage.overview.noProviderData`))}
          ${ze(r(`usage.overview.topTools`),k,r(`usage.overview.noToolCalls`))}
          ${ze(r(`usage.overview.topAgents`),A,r(`usage.overview.noAgentData`))}
          ${ze(r(`usage.overview.topChannels`),te,r(`usage.overview.noChannelData`))}
          ${Be(r(`usage.overview.peakErrorDays`),T,r(`usage.overview.noErrorData`))}
          ${Be(r(`usage.overview.peakErrorHours`),l,r(`usage.overview.noErrorData`),{className:`usage-insight-card--wide`,listClassName:`usage-error-list--hours`})}
        </div>
      </div>
    </section>
  `}function He(e,a,o,s,l,u,d,f,p,m,h,g,_,v,y){let b=e=>_.includes(e),x=e=>{let t=e.label||e.key;return t.startsWith(`agent:`)&&t.includes(`?token=`)?t.slice(0,t.indexOf(`?token=`)):t},ee=async e=>{let t=x(e);try{await navigator.clipboard.writeText(t)}catch{}},S=e=>{let t=[];return b(`channel`)&&e.channel&&t.push(`channel:${e.channel}`),b(`agent`)&&e.agentId&&t.push(`agent:${e.agentId}`),b(`provider`)&&(e.modelProvider||e.providerOverride)&&t.push(`provider:${e.modelProvider??e.providerOverride}`),b(`model`)&&e.model&&t.push(`model:${e.model}`),b(`messages`)&&e.usage?.messageCounts&&t.push(`msgs:${e.usage.messageCounts.total}`),b(`tools`)&&e.usage?.toolUsage&&t.push(`tools:${e.usage.toolUsage.totalCalls}`),b(`errors`)&&e.usage?.messageCounts&&t.push(`errors:${e.usage.messageCounts.errors}`),b(`duration`)&&e.usage?.durationMs&&t.push(`dur:${c(e.usage.durationMs,{spaced:!0})??`—`}`),t},C=new Set(o),w=(e,t)=>{let n=e.usage;return n?C.size>0&&n.dailyBreakdown&&n.dailyBreakdown.length>0?n.dailyBreakdown.reduce((e,n)=>C.has(n.date)?e+(t===`tokens`?n.tokens:n.cost):e,0):t===`tokens`?n.totalTokens??0:n.totalCost??0:0},T=e=>w(e,s?`tokens`:`cost`),E=e=>{switch(l){case`recent`:return e.updatedAt??0;case`messages`:return e.usage?.messageCounts?.total??0;case`errors`:return e.usage?.messageCounts?.errors??0;case`cost`:return w(e,`cost`);case`tokens`:return w(e,`tokens`)}return l},D=[...e].toSorted((e,t)=>{let n=E(t)-E(e);if(n!==0)return n;let r=(t.updatedAt??0)-(e.updatedAt??0);return r===0?x(e).localeCompare(x(t)):r}),k=u===`asc`?D.toReversed():D,A=k.reduce((e,t)=>e+T(t),0),te=k.length?A/k.length:0,j=k.reduce((e,t)=>e+(t.usage?.messageCounts?.errors??0),0),M=(e,i)=>{let a=T(e),o=x(e),c=S(e);return t`
      <div
        class="session-bar-row ${i?`selected`:``}"
        @click=${t=>p(e.key,t.shiftKey)}
        title="${e.key}"
      >
        <div class="session-bar-label">
          <div class="session-bar-title">${o}</div>
          ${c.length>0?t`<div class="session-bar-meta">${c.join(` · `)}</div>`:n}
        </div>
        <div class="session-bar-actions">
          <button
            class="btn btn--sm btn--ghost"
            title=${r(`usage.sessions.copyName`)}
            @click=${t=>{t.stopPropagation(),ee(e)}}
          >
            ${r(`usage.sessions.copy`)}
          </button>
          <div class="session-bar-value">
            ${s?O(a):z(a)}
          </div>
        </div>
      </div>
    `},N=new Set(a),P=k.filter(e=>N.has(e.key)),F=P.length,I=new Map(k.map(e=>[e.key,e])),L=d.map(e=>I.get(e)).filter(e=>!!e);return t`
    <div class="card sessions-card">
      <div class="sessions-card-header">
        <div class="card-title">${r(`usage.sessions.title`)}</div>
        <div class="sessions-card-count">
          ${r(`usage.sessions.shown`,{count:String(e.length)})}
          ${v===e.length?``:` · ${r(`usage.sessions.total`,{count:String(v)})}`}
        </div>
      </div>
      <div class="sessions-card-meta">
        <div class="sessions-card-stats">
          <span>
            ${s?O(te):z(te)}
            ${r(`usage.sessions.avg`)}
          </span>
          <span>${j} ${i(r(`usage.overview.errors`))}</span>
        </div>
        <div class="chart-toggle small">
          <button
            class="btn btn--sm toggle-btn ${f===`all`?`active`:``}"
            @click=${()=>g(`all`)}
          >
            ${r(`usage.sessions.all`)}
          </button>
          <button
            class="btn btn--sm toggle-btn ${f===`recent`?`active`:``}"
            @click=${()=>g(`recent`)}
          >
            ${r(`usage.sessions.recent`)}
          </button>
        </div>
        <label class="sessions-sort">
          <span>${r(`usage.sessions.sort`)}</span>
          <select
            @change=${e=>m(e.target.value)}
          >
            <option value="cost" ?selected=${l===`cost`}>
              ${r(`usage.metrics.cost`)}
            </option>
            <option value="errors" ?selected=${l===`errors`}>
              ${r(`usage.overview.errors`)}
            </option>
            <option value="messages" ?selected=${l===`messages`}>
              ${r(`usage.overview.messages`)}
            </option>
            <option value="recent" ?selected=${l===`recent`}>
              ${r(`usage.sessions.recentShort`)}
            </option>
            <option value="tokens" ?selected=${l===`tokens`}>
              ${r(`usage.metrics.tokens`)}
            </option>
          </select>
        </label>
        <button
          class="btn btn--sm"
          @click=${()=>h(u===`desc`?`asc`:`desc`)}
          title=${r(u===`desc`?`usage.sessions.descending`:`usage.sessions.ascending`)}
        >
          ${u===`desc`?`↓`:`↑`}
        </button>
        ${F>0?t`
              <button class="btn btn--sm" @click=${y}>
                ${r(`usage.sessions.clearSelection`)}
              </button>
            `:n}
      </div>
      ${f===`recent`?L.length===0?t` <div class="usage-empty-block">${r(`usage.sessions.noRecent`)}</div> `:t`
              <div class="session-bars session-bars--recent">
                ${L.map(e=>M(e,N.has(e.key)))}
              </div>
            `:e.length===0?t` <div class="usage-empty-block">${r(`usage.sessions.noneInRange`)}</div> `:t`
              <div class="session-bars">
                ${k.slice(0,50).map(e=>M(e,N.has(e.key)))}
                ${e.length>50?t`
                      <div class="usage-more-sessions">
                        ${r(`usage.sessions.more`,{count:String(e.length-50)})}
                      </div>
                    `:n}
              </div>
            `}
      ${F>1?t`
            <div class="sessions-selected-group">
              <div class="sessions-card-count">
                ${r(`usage.sessions.selected`,{count:String(F)})}
              </div>
              <div class="session-bars session-bars--selected">
                ${P.map(e=>M(e,!0))}
              </div>
            </div>
          `:n}
    </div>
  `}var Ue=.75,We=.06,Ge=5,Z=12,Q=.7;function $(e,t){return!t||t<=0?0:e/t*100}function Ke(e){return e<0xe8d4a51000?e*1e3:e}function qe(e,t,n){let r=Math.min(t,n),i=Math.max(t,n);return e.filter(e=>{if(e.timestamp<=0)return!0;let t=Ke(e.timestamp);return t>=r&&t<=i})}function Je(e,a,s){let l=a||e.usage;if(!l)return t` <div class="usage-empty-block">${r(`usage.details.noUsageData`)}</div> `;let u=e=>e?o(e):r(`usage.common.emptyValue`),d=[];e.channel&&d.push(`channel:${e.channel}`),e.agentId&&d.push(`agent:${e.agentId}`),(e.modelProvider||e.providerOverride)&&d.push(`provider:${e.modelProvider??e.providerOverride}`),e.model&&d.push(`model:${e.model}`);let f=l.toolUsage?.tools.slice(0,6)??[],p,m,h;if(s){let e=new Map;for(let t of s){let{tools:n}=S(t.content);for(let[t]of n)e.set(t,(e.get(t)||0)+1)}h=f.map(t=>({label:t.name,value:`${e.get(t.name)??0}`,sub:r(`usage.overview.calls`)})),p=[...e.values()].reduce((e,t)=>e+t,0),m=e.size}else h=f.map(e=>({label:e.name,value:`${e.count}`,sub:r(`usage.overview.calls`)})),p=l.toolUsage?.totalCalls??0,m=l.toolUsage?.uniqueTools??0;let g=l.modelUsage?.slice(0,6).map(e=>({label:e.model??r(`usage.common.unknown`),value:z(e.totals.totalCost),sub:O(e.totals.totalTokens)}))??[];return t`
    ${d.length>0?t`<div class="usage-badges">
          ${d.map(e=>t`<span class="usage-badge">${e}</span>`)}
        </div>`:n}
    <div class="session-summary-grid">
      <div class="stat session-summary-card">
        <div class="session-summary-title">${r(`usage.overview.messages`)}</div>
        <div class="stat-value session-summary-value">${l.messageCounts?.total??0}</div>
        <div class="session-summary-meta">
          ${l.messageCounts?.user??0}
          ${i(r(`usage.overview.user`))} ·
          ${l.messageCounts?.assistant??0}
          ${i(r(`usage.overview.assistant`))}
        </div>
      </div>
      <div class="stat session-summary-card">
        <div class="session-summary-title">${r(`usage.overview.toolCalls`)}</div>
        <div class="stat-value session-summary-value">${p}</div>
        <div class="session-summary-meta">${m} ${r(`usage.overview.toolsUsed`)}</div>
      </div>
      <div class="stat session-summary-card">
        <div class="session-summary-title">${r(`usage.overview.errors`)}</div>
        <div class="stat-value session-summary-value">${l.messageCounts?.errors??0}</div>
        <div class="session-summary-meta">
          ${l.messageCounts?.toolResults??0} ${r(`usage.overview.toolResults`)}
        </div>
      </div>
      <div class="stat session-summary-card">
        <div class="session-summary-title">${r(`usage.details.duration`)}</div>
        <div class="stat-value session-summary-value">
          ${c(l.durationMs,{spaced:!0})??r(`usage.common.emptyValue`)}
        </div>
        <div class="session-summary-meta">
          ${u(l.firstActivity)} → ${u(l.lastActivity)}
        </div>
      </div>
    </div>
    <div class="usage-insights-grid usage-insights-grid--tight">
      ${ze(r(`usage.overview.topTools`),h,r(`usage.overview.noToolCalls`))}
      ${ze(r(`usage.details.modelMix`),g,r(`usage.overview.noModelData`))}
    </div>
  `}function Ye(e,t,n,r){let i=Math.min(n,r),a=Math.max(n,r),o=t.filter(e=>e.timestamp>=i&&e.timestamp<=a);if(o.length===0)return;let s=0,c=0,l=0,u=0,d=0,f=0,p=0,m=0;for(let e of o)s+=e.totalTokens||0,c+=e.cost||0,d+=e.input||0,f+=e.output||0,p+=e.cacheRead||0,m+=e.cacheWrite||0,e.output>0&&u++,e.input>0&&l++;return{...e,totalTokens:s,totalCost:c,input:d,output:f,cacheRead:p,cacheWrite:m,durationMs:o[o.length-1].timestamp-o[0].timestamp,firstActivity:o[0].timestamp,lastActivity:o[o.length-1].timestamp,messageCounts:{total:o.length,user:l,assistant:u,toolCalls:0,toolResults:0,errors:0}}}function Xe(e,a,o,s,c,l,u,d,f,p,m,h,g,_,v,y,b,x,ee,S,C,w,T,E,D,k){let A=e.label||e.key,te=A.length>50?A.slice(0,50)+`…`:A,j=e.usage,M=d!==null&&f!==null,N=d!==null&&f!==null&&a?.points&&j?Ye(j,a.points,d,f):void 0,P=N?{totalTokens:N.totalTokens,totalCost:N.totalCost}:{totalTokens:j?.totalTokens??0,totalCost:j?.totalCost??0},F=N?r(`usage.details.filtered`):``;return t`
    <div class="card session-detail-panel">
      <div class="session-detail-header">
        <div class="session-detail-header-left">
          <div class="session-detail-title">
            ${te}
            ${F?t`<span class="session-detail-indicator">${F}</span>`:n}
          </div>
        </div>
        <div class="session-detail-stats">
          ${j?t`
                <span
                  ><strong>${O(P.totalTokens)}</strong>
                  ${i(r(`usage.metrics.tokens`))}${F}</span
                >
                <span><strong>${z(P.totalCost)}</strong>${F}</span>
              `:n}
        </div>
        <button
          class="btn btn--sm btn--ghost"
          @click=${k}
          title=${r(`usage.details.close`)}
          aria-label=${r(`usage.details.close`)}
        >
          ×
        </button>
      </div>
      ${e.scope===`family`&&e.includedSessionIds?.length?t`
            <div class="usage-lineage-note">
              ${r(`usage.scope.familyIncluded`,{count:String(e.includedSessionIds.length)})}
            </div>
          `:n}
      <div class="session-detail-content">
        ${Je(e,N,d!=null&&f!=null&&_?qe(_,d,f):void 0)}
        <div class="session-detail-row">
          ${Ze(a,o,s,c,l,u,m,h,g,d,f,p)}
        </div>
        <div class="session-detail-bottom">
          ${$e(_,v,y,b,x,ee,S,C,w,T,M?d:null,M?f:null)}
          ${Qe(e.contextWeight,j,E,D)}
        </div>
      </div>
    </div>
  `}function Ze(o,s,c,u,d,f,p,m,h,g,_,v){if(s)return t`
      <div class="session-timeseries-compact">
        <div class="usage-empty-block">${r(`usage.loading.badge`)}</div>
      </div>
    `;if(!o||o.points.length<2)return t`
      <div class="session-timeseries-compact">
        <div class="usage-empty-block">${r(`usage.details.noTimeline`)}</div>
      </div>
    `;let y=o.points;if(p||m||h&&h.length>0){let e=p?new Date(p+`T00:00:00`).getTime():0,t=m?new Date(m+`T23:59:59`).getTime():1/0;y=o.points.filter(n=>{if(n.timestamp<e||n.timestamp>t)return!1;if(h&&h.length>0){let e=new Date(n.timestamp),t=`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`;return h.includes(t)}return!0})}if(y.length<2)return t`
      <div class="session-timeseries-compact">
        <div class="usage-empty-block">${r(`usage.details.noDataInRange`)}</div>
      </div>
    `;let b=0,x=0,ee=0,S=0,C=0,w=0;y=y.map(e=>(b+=e.totalTokens,x+=e.cost,ee+=e.output,S+=e.input,C+=e.cacheRead,w+=e.cacheWrite,{...e,cumulativeTokens:b,cumulativeCost:x}));let T=g!=null&&_!=null,E=T?Math.min(g,_):0,D=T?Math.max(g,_):1/0,k=0,A=y.length;if(T){k=y.findIndex(e=>e.timestamp>=E),k===-1&&(k=y.length);let e=y.findIndex(e=>e.timestamp>D);A=e===-1?y.length:e}let te=T?y.slice(k,A):y,j=0,M=0,N=0,P=0;for(let e of te)j+=e.output,M+=e.input,N+=e.cacheRead,P+=e.cacheWrite;let F={top:8,right:4,bottom:14,left:30},I=400-F.left-F.right,L=100-F.top-F.bottom,ne=c===`cumulative`,R=c===`per-turn`&&d===`by-type`,re=j+M+N+P,ie=y.map(e=>ne?e.cumulativeTokens:R?e.input+e.output+e.cacheRead+e.cacheWrite:e.totalTokens),B=Math.max(...ie,1),V=I/y.length,H=Math.min(8,Math.max(1,V*Ue)),U=V-H,W=F.left+k*(H+U),G=A>=y.length?F.left+(y.length-1)*(H+U)+H:F.left+(A-1)*(H+U)+H;return t`
    <div class="session-timeseries-compact">
      <div class="timeseries-header-row">
        <div class="card-title usage-section-title">${r(`usage.details.usageOverTime`)}</div>
        <div class="timeseries-controls">
          ${T?t`
                <div class="chart-toggle small">
                  <button
                    class="btn btn--sm toggle-btn active"
                    @click=${()=>v?.(null,null)}
                  >
                    ${r(`usage.details.reset`)}
                  </button>
                </div>
              `:n}
          <div class="chart-toggle small">
            <button
              class="btn btn--sm toggle-btn ${ne?``:`active`}"
              @click=${()=>u(`per-turn`)}
            >
              ${r(`usage.details.perTurn`)}
            </button>
            <button
              class="btn btn--sm toggle-btn ${ne?`active`:``}"
              @click=${()=>u(`cumulative`)}
            >
              ${r(`usage.details.cumulative`)}
            </button>
          </div>
          ${ne?n:t`
                <div class="chart-toggle small">
                  <button
                    class="btn btn--sm toggle-btn ${d===`total`?`active`:``}"
                    @click=${()=>f(`total`)}
                  >
                    ${r(`usage.daily.total`)}
                  </button>
                  <button
                    class="btn btn--sm toggle-btn ${d===`by-type`?`active`:``}"
                    @click=${()=>f(`by-type`)}
                  >
                    ${r(`usage.daily.byType`)}
                  </button>
                </div>
              `}
        </div>
      </div>
      <div class="timeseries-chart-wrapper">
        <svg viewBox="0 0 ${400} ${118}" class="timeseries-svg">
          <!-- Y axis -->
          <line
            x1="${F.left}"
            y1="${F.top}"
            x2="${F.left}"
            y2="${F.top+L}"
            stroke="var(--border)"
          />
          <!-- X axis -->
          <line
            x1="${F.left}"
            y1="${F.top+L}"
            x2="${400-F.right}"
            y2="${F.top+L}"
            stroke="var(--border)"
          />
          <!-- Y axis labels -->
          <text
            x="${F.left-4}"
            y="${F.top+5}"
            text-anchor="end"
            class="ts-axis-label"
          >
            ${O(B)}
          </text>
          <text
            x="${F.left-4}"
            y="${F.top+L}"
            text-anchor="end"
            class="ts-axis-label"
          >
            0
          </text>
          <!-- X axis labels (first and last) -->
          ${y.length>0?e`
            <text x="${F.left}" y="${F.top+L+10}" text-anchor="start" class="ts-axis-label">${l(y[0].timestamp,{hour:`2-digit`,minute:`2-digit`},``)}</text>
            <text x="${400-F.right}" y="${F.top+L+10}" text-anchor="end" class="ts-axis-label">${l(y[y.length-1].timestamp,{hour:`2-digit`,minute:`2-digit`},``)}</text>
          `:n}
          <!-- Bars -->
          ${y.map((t,o)=>{let s=ie[o],c=F.left+o*(H+U),l=s/B*L,u=F.top+L-l,d=[a(t.timestamp,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`},``),`${O(s)} ${i(r(`usage.metrics.tokens`))}`];R&&(d.push(`Out ${O(t.output)}`),d.push(`In ${O(t.input)}`),d.push(`CW ${O(t.cacheWrite)}`),d.push(`CR ${O(t.cacheRead)}`));let f=d.join(` · `),p=T&&(o<k||o>=A);if(!R)return e`<rect x="${c}" y="${u}" width="${H}" height="${l}" class="ts-bar${p?` dimmed`:``}" rx="1"><title>${f}</title></rect>`;let m=[{value:t.output,cls:`output`},{value:t.input,cls:`input`},{value:t.cacheWrite,cls:`cache-write`},{value:t.cacheRead,cls:`cache-read`}],h=F.top+L,g=p?` dimmed`:``;return e`
              ${m.map(t=>{if(t.value<=0||s<=0)return n;let r=l*(t.value/s);return h-=r,e`<rect x="${c}" y="${h}" width="${H}" height="${r}" class="ts-bar ${t.cls}${g}" rx="1"><title>${f}</title></rect>`})}
            `})}
          <!-- Selection highlight overlay (always visible between handles) -->
          ${e`
            <rect 
              x="${W}" 
              y="${F.top}" 
              width="${Math.max(1,G-W)}" 
              height="${L}" 
              fill="var(--accent)" 
              opacity="${We}" 
              pointer-events="none"
            />
          `}
          <!-- Left cursor line + handle -->
          ${e`
            <line x1="${W}" y1="${F.top}" x2="${W}" y2="${F.top+L}" stroke="var(--accent)" stroke-width="0.8" opacity="0.7" />
            <rect x="${W-Ge/2}" y="${F.top+L/2-Z/2}" width="${Ge}" height="${Z}" rx="1.5" fill="var(--accent)" class="cursor-handle" />
            <line x1="${W-Q}" y1="${F.top+L/2-Z/5}" x2="${W-Q}" y2="${F.top+L/2+Z/5}" stroke="var(--bg)" stroke-width="0.4" pointer-events="none" />
            <line x1="${W+Q}" y1="${F.top+L/2-Z/5}" x2="${W+Q}" y2="${F.top+L/2+Z/5}" stroke="var(--bg)" stroke-width="0.4" pointer-events="none" />
          `}
          <!-- Right cursor line + handle -->
          ${e`
            <line x1="${G}" y1="${F.top}" x2="${G}" y2="${F.top+L}" stroke="var(--accent)" stroke-width="0.8" opacity="0.7" />
            <rect x="${G-Ge/2}" y="${F.top+L/2-Z/2}" width="${Ge}" height="${Z}" rx="1.5" fill="var(--accent)" class="cursor-handle" />
            <line x1="${G-Q}" y1="${F.top+L/2-Z/5}" x2="${G-Q}" y2="${F.top+L/2+Z/5}" stroke="var(--bg)" stroke-width="0.4" pointer-events="none" />
            <line x1="${G+Q}" y1="${F.top+L/2-Z/5}" x2="${G+Q}" y2="${F.top+L/2+Z/5}" stroke="var(--bg)" stroke-width="0.4" pointer-events="none" />
          `}
        </svg>
        <!-- Handle drag zones (only on handles, not full chart) -->
        ${(()=>{let e=`${(W/400*100).toFixed(1)}%`,n=`${(G/400*100).toFixed(1)}%`,r=e=>t=>{if(!v)return;t.preventDefault(),t.stopPropagation();let n=t.currentTarget.closest(`.timeseries-chart-wrapper`)?.querySelector(`svg`);if(!n)return;let r=n.getBoundingClientRect(),i=r.width,a=F.left/400*i,o=(400-F.right)/400*i-a,s=e=>{let t=Math.max(0,Math.min(1,(e-r.left-a)/o));return Math.min(Math.floor(t*y.length),y.length-1)},c=e===`left`?W:G,l=r.left+c/400*i,u=t.clientX-l;document.body.style.cursor=`col-resize`;let d=t=>{let n=s(t.clientX-u),r=y[n];if(r)if(e===`left`){let e=_??y[y.length-1].timestamp;v(Math.min(r.timestamp,e),e)}else{let e=g??y[0].timestamp;v(e,Math.max(r.timestamp,e))}},f=()=>{document.body.style.cursor=``,document.removeEventListener(`mousemove`,d),document.removeEventListener(`mouseup`,f)};document.addEventListener(`mousemove`,d),document.addEventListener(`mouseup`,f)};return t`
            <div
              class="chart-handle-zone chart-handle-left"
              style="left: ${e};"
              @mousedown=${r(`left`)}
            ></div>
            <div
              class="chart-handle-zone chart-handle-right"
              style="left: ${n};"
              @mousedown=${r(`right`)}
            ></div>
          `})()}
      </div>
      <div class="timeseries-summary">
        ${T?t`
              <span class="timeseries-summary__range">
                ${r(`usage.details.turnRange`,{start:String(k+1),end:String(A),total:String(y.length)})}
              </span>
              ·
              ${l(E,{hour:`2-digit`,minute:`2-digit`},``)}–${l(D,{hour:`2-digit`,minute:`2-digit`},``)}
              ·
              ${O(j+M+N+P)}
              · ${z(te.reduce((e,t)=>e+(t.cost||0),0))}
            `:t`${y.length} ${r(`usage.overview.messagesAbbrev`)} · ${O(b)}
            · ${z(x)}`}
      </div>
      ${R?t`
            <div class="timeseries-breakdown">
              <div class="card-title usage-section-title">${r(`usage.breakdown.tokensByType`)}</div>
              <div class="cost-breakdown-bar cost-breakdown-bar--compact">
                <div
                  class="cost-segment output"
                  style="width: ${$(j,re).toFixed(1)}%"
                ></div>
                <div
                  class="cost-segment input"
                  style="width: ${$(M,re).toFixed(1)}%"
                ></div>
                <div
                  class="cost-segment cache-write"
                  style="width: ${$(P,re).toFixed(1)}%"
                ></div>
                <div
                  class="cost-segment cache-read"
                  style="width: ${$(N,re).toFixed(1)}%"
                ></div>
              </div>
              <div class="cost-breakdown-legend">
                <div class="legend-item" title=${r(`usage.details.assistantOutputTokens`)}>
                  <span class="legend-dot output"></span>${r(`usage.breakdown.output`)}
                  ${O(j)}
                </div>
                <div class="legend-item" title=${r(`usage.details.userToolInputTokens`)}>
                  <span class="legend-dot input"></span>${r(`usage.breakdown.input`)}
                  ${O(M)}
                </div>
                <div class="legend-item" title=${r(`usage.details.tokensWrittenToCache`)}>
                  <span class="legend-dot cache-write"></span>${r(`usage.breakdown.cacheWrite`)}
                  ${O(P)}
                </div>
                <div class="legend-item" title=${r(`usage.details.tokensReadFromCache`)}>
                  <span class="legend-dot cache-read"></span>${r(`usage.breakdown.cacheRead`)}
                  ${O(N)}
                </div>
              </div>
              <div class="cost-breakdown-total">
                ${r(`usage.breakdown.total`)}: ${O(re)}
              </div>
            </div>
          `:n}
    </div>
  `}function Qe(e,i,a,o){if(!e)return t`
      <div class="context-details-panel">
        <div class="usage-empty-block">${r(`usage.details.noContextData`)}</div>
      </div>
    `;let s=D(e.systemPrompt.chars),c=D(e.skills.promptChars),l=D(e.tools.listChars+e.tools.schemaChars),u=D(e.injectedWorkspaceFiles.reduce((e,t)=>e+t.injectedChars,0)),d=s+c+l+u,f=``;if(i&&i.totalTokens>0){let e=i.input+i.cacheRead;e>0&&(f=`~${Math.min(d/e*100,100).toFixed(0)}% ${r(`usage.details.ofInput`)}`)}let p=e.skills.entries.toSorted((e,t)=>t.blockChars-e.blockChars),m=e.tools.entries.toSorted((e,t)=>t.summaryChars+t.schemaChars-(e.summaryChars+e.schemaChars)),h=e.injectedWorkspaceFiles.toSorted((e,t)=>t.injectedChars-e.injectedChars),g=a,_=g?p:p.slice(0,4),v=g?m:m.slice(0,4),y=g?h:h.slice(0,4),b=p.length>4||m.length>4||h.length>4;return t`
    <div class="context-details-panel">
      <div class="context-breakdown-header">
        <div class="card-title usage-section-title">
          ${r(`usage.details.systemPromptBreakdown`)}
        </div>
        ${b?t`<button class="btn btn--sm" @click=${o}>
              ${r(g?`usage.details.collapse`:`usage.details.expandAll`)}
            </button>`:n}
      </div>
      <p class="context-weight-desc">${f||r(`usage.details.baseContextPerMessage`)}</p>
      <div class="context-stacked-bar">
        <div
          class="context-segment system"
          style="width: ${$(s,d).toFixed(1)}%"
          title="${r(`usage.details.system`)}: ~${O(s)}"
        ></div>
        <div
          class="context-segment skills"
          style="width: ${$(c,d).toFixed(1)}%"
          title="${r(`usage.details.skills`)}: ~${O(c)}"
        ></div>
        <div
          class="context-segment tools"
          style="width: ${$(l,d).toFixed(1)}%"
          title="${r(`usage.details.tools`)}: ~${O(l)}"
        ></div>
        <div
          class="context-segment files"
          style="width: ${$(u,d).toFixed(1)}%"
          title="${r(`usage.details.files`)}: ~${O(u)}"
        ></div>
      </div>
      <div class="context-legend">
        <span class="legend-item"
          ><span class="legend-dot system"></span>${r(`usage.details.systemShort`)}
          ~${O(s)}</span
        >
        <span class="legend-item"
          ><span class="legend-dot skills"></span>${r(`usage.details.skills`)}
          ~${O(c)}</span
        >
        <span class="legend-item"
          ><span class="legend-dot tools"></span>${r(`usage.details.tools`)}
          ~${O(l)}</span
        >
        <span class="legend-item"
          ><span class="legend-dot files"></span>${r(`usage.details.files`)}
          ~${O(u)}</span
        >
      </div>
      <div class="context-total">
        ${r(`usage.breakdown.total`)}: ~${O(d)}
      </div>
      <div class="context-breakdown-grid">
        ${p.length>0?(()=>{let e=p.length-_.length;return t`
                <div class="context-breakdown-card">
                  <div class="context-breakdown-title">
                    ${r(`usage.details.skills`)} (${p.length})
                  </div>
                  <div class="context-breakdown-list">
                    ${_.map(e=>t`
                        <div class="context-breakdown-item">
                          <span class="mono" title=${e.name}>${e.name}</span>
                          <span class="muted">~${O(D(e.blockChars))}</span>
                        </div>
                      `)}
                  </div>
                  ${e>0?t`
                        <div class="context-breakdown-more">
                          ${r(`usage.sessions.more`,{count:String(e)})}
                        </div>
                      `:n}
                </div>
              `})():n}
        ${m.length>0?(()=>{let e=m.length-v.length;return t`
                <div class="context-breakdown-card">
                  <div class="context-breakdown-title">
                    ${r(`usage.details.tools`)} (${m.length})
                  </div>
                  <div class="context-breakdown-list">
                    ${v.map(e=>t`
                        <div class="context-breakdown-item">
                          <span class="mono" title=${e.name}>${e.name}</span>
                          <span class="muted"
                            >~${O(D(e.summaryChars+e.schemaChars))}</span
                          >
                        </div>
                      `)}
                  </div>
                  ${e>0?t`
                        <div class="context-breakdown-more">
                          ${r(`usage.sessions.more`,{count:String(e)})}
                        </div>
                      `:n}
                </div>
              `})():n}
        ${h.length>0?(()=>{let e=h.length-y.length;return t`
                <div class="context-breakdown-card">
                  <div class="context-breakdown-title">
                    ${r(`usage.details.files`)} (${h.length})
                  </div>
                  <div class="context-breakdown-list">
                    ${y.map(e=>t`
                        <div class="context-breakdown-item">
                          <span class="mono" title=${e.name}>${e.name}</span>
                          <span class="muted"
                            >~${O(D(e.injectedChars))}</span
                          >
                        </div>
                      `)}
                  </div>
                  ${e>0?t`
                        <div class="context-breakdown-more">
                          ${r(`usage.sessions.more`,{count:String(e)})}
                        </div>
                      `:n}
                </div>
              `})():n}
      </div>
    </div>
  `}function $e(e,a,s,c,l,u,d,f,p,m,h,g){if(a)return t`
      <div class="session-logs-compact">
        <div class="session-logs-header">${r(`usage.details.conversation`)}</div>
        <div class="usage-empty-block">${r(`usage.loading.badge`)}</div>
      </div>
    `;if(!e||e.length===0)return t`
      <div class="session-logs-compact">
        <div class="session-logs-header">${r(`usage.details.conversation`)}</div>
        <div class="usage-empty-block">${r(`usage.details.noMessages`)}</div>
      </div>
    `;let _=i(l.query),v=e.map(e=>{let t=S(e.content);return{log:e,toolInfo:t,cleanContent:t.cleanContent||e.content}}),y=Array.from(new Set(v.flatMap(e=>e.toolInfo.tools.map(([e])=>e)))).toSorted((e,t)=>e.localeCompare(t)),b=v.filter(e=>{if(h!=null&&g!=null){let t=e.log.timestamp;if(t>0){let e=Math.min(h,g),n=Math.max(h,g),r=Ke(t);if(r<e||r>n)return!1}}return!(l.roles.length>0&&!l.roles.includes(e.log.role)||l.hasTools&&e.toolInfo.tools.length===0||l.tools.length>0&&!e.toolInfo.tools.some(([e])=>l.tools.includes(e))||_&&!i(e.cleanContent).includes(_))}),x=l.roles.length>0||l.tools.length>0||l.hasTools||_,ee=h!=null&&g!=null,C=x||ee?`${b.length} ${r(`usage.details.of`)} ${e.length}${ee?` (${r(`usage.details.timelineFiltered`)})`:``}`:`${e.length}`,w=new Set(l.roles),T=new Set(l.tools);return t`
    <div class="session-logs-compact">
      <div class="session-logs-header">
        <span>
          ${r(`usage.details.conversation`)}
          <span class="session-logs-header-count">
            (${C} ${i(r(`usage.overview.messages`))})
          </span>
        </span>
        <button class="btn btn--sm" @click=${c}>
          ${r(s?`usage.details.collapseAll`:`usage.details.expandAll`)}
        </button>
      </div>
      <div class="usage-filters-inline session-log-filters">
        <select
          multiple
          size="4"
          aria-label="Filter by role"
          @change=${e=>u(Array.from(e.target.selectedOptions).map(e=>e.value))}
        >
          <option value="user" ?selected=${w.has(`user`)}>
            ${r(`usage.overview.user`)}
          </option>
          <option value="assistant" ?selected=${w.has(`assistant`)}>
            ${r(`usage.overview.assistant`)}
          </option>
          <option value="tool" ?selected=${w.has(`tool`)}>
            ${r(`usage.details.tool`)}
          </option>
          <option value="toolResult" ?selected=${w.has(`toolResult`)}>
            ${r(`usage.details.toolResult`)}
          </option>
        </select>
        <select
          multiple
          size="4"
          aria-label="Filter by tool"
          @change=${e=>d(Array.from(e.target.selectedOptions).map(e=>e.value))}
        >
          ${y.map(e=>t`<option value=${e} ?selected=${T.has(e)}>${e}</option>`)}
        </select>
        <label class="usage-filters-inline session-log-has-tools">
          <input
            type="checkbox"
            .checked=${l.hasTools}
            @change=${e=>f(e.target.checked)}
          />
          ${r(`usage.details.hasTools`)}
        </label>
        <input
          type="text"
          placeholder=${r(`usage.details.searchConversation`)}
          aria-label=${r(`usage.details.searchConversation`)}
          .value=${l.query}
          @input=${e=>p(e.target.value)}
        />
        <button class="btn btn--sm" @click=${m}>${r(`usage.filters.clear`)}</button>
      </div>
      <div class="session-logs-list">
        ${b.map(e=>{let{log:i,toolInfo:a,cleanContent:c}=e;return t`
            <div class="session-log-entry ${i.role===`user`?`user`:`assistant`}">
              <div class="session-log-meta">
                <span class="session-log-role">${i.role===`user`?r(`usage.details.you`):i.role===`assistant`?r(`usage.overview.assistant`):r(`usage.details.tool`)}</span>
                <span>${o(i.timestamp)}</span>
                ${i.tokens?t`<span>${O(i.tokens)}</span>`:n}
              </div>
              <div class="session-log-content">${c}</div>
              ${a.tools.length>0?t`
                    <details class="session-log-tools" ?open=${s}>
                      <summary>${a.summary}</summary>
                      <div class="session-log-tools-list">
                        ${a.tools.map(([e,n])=>t`
                            <span class="session-log-tools-pill">${e} × ${n}</span>
                          `)}
                      </div>
                    </details>
                  `:n}
            </div>
          `})}
        ${b.length===0?t`
              <div class="usage-empty-block usage-empty-block--compact">
                ${r(`usage.details.noMessagesMatch`)}
              </div>
            `:n}
      </div>
    </div>
  `}function et(){return{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,totalCost:0,inputCost:0,outputCost:0,cacheReadCost:0,cacheWriteCost:0,missingCostEntries:0}}function tt(e,t){return e.input+=t.input,e.output+=t.output,e.cacheRead+=t.cacheRead,e.cacheWrite+=t.cacheWrite,e.totalTokens+=t.totalTokens,e.totalCost+=t.totalCost,e.inputCost+=t.inputCost??0,e.outputCost+=t.outputCost??0,e.cacheReadCost+=t.cacheReadCost??0,e.cacheWriteCost+=t.cacheWriteCost??0,e.missingCostEntries+=t.missingCostEntries??0,e}function nt(e){return t`
    <section class="card usage-loading-card">
      <div class="usage-loading-header">
        <div class="usage-loading-title-group">
          <div class="card-title usage-section-title">${r(`usage.loading.title`)}</div>
          <span class="usage-loading-badge">
            <span class="usage-loading-spinner" aria-hidden="true"></span>
            ${r(`usage.loading.badge`)}
          </span>
        </div>
        <div class="usage-loading-controls">
          <div class="usage-date-range usage-date-range--loading">
            <input class="usage-date-input" type="date" .value=${e.startDate} disabled />
            <span class="usage-separator">${r(`usage.filters.to`)}</span>
            <input class="usage-date-input" type="date" .value=${e.endDate} disabled />
          </div>
        </div>
      </div>
      <div class="usage-loading-grid">
        <div class="usage-skeleton-block usage-skeleton-block--tall"></div>
        <div class="usage-skeleton-block"></div>
        <div class="usage-skeleton-block"></div>
      </div>
    </section>
  `}function rt(e){return t`
    <section class="card usage-empty-state">
      <div class="usage-empty-state__title">${r(`usage.empty.title`)}</div>
      <div class="card-sub usage-empty-state__subtitle">${r(`usage.empty.subtitle`)}</div>
      <div class="usage-empty-state__features">
        <span class="usage-empty-state__feature">${r(`usage.empty.featureOverview`)}</span>
        <span class="usage-empty-state__feature">${r(`usage.empty.featureSessions`)}</span>
        <span class="usage-empty-state__feature">${r(`usage.empty.featureTimeline`)}</span>
      </div>
      <div class="usage-empty-state__actions">
        <button class="btn primary" @click=${e}>${r(`common.refresh`)}</button>
      </div>
    </section>
  `}function it(e){let{data:i,filters:a,display:o,detail:s,callbacks:c}=e,l=c.filters,u=c.display,f=c.details;if(i.loading&&!i.totals)return t`<div class="usage-page">${nt(a)}</div>`;let p=o.chartMode===`tokens`,m=a.query.trim().length>0,h=a.queryDraft.trim().length>0,_=[...i.sessions].toSorted((e,t)=>{let n=p?e.usage?.totalTokens??0:e.usage?.totalCost??0;return(p?t.usage?.totalTokens??0:t.usage?.totalCost??0)-n}),v=a.agentId?_.filter(e=>K(e.agentId??``)===K(a.agentId??``)):_,y=a.selectedDays.length>0?v.filter(e=>{if(e.usage?.activityDates?.length)return e.usage.activityDates.some(e=>a.selectedDays.includes(e));if(!e.updatedAt)return!1;let t=new Date(e.updatedAt),n=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`;return a.selectedDays.includes(n)}):v,b=ee(a.selectedHours.length>0?y.filter(e=>ne(e,a.selectedHours,a.timeZone)):y,a.query),x=b.sessions,S=b.warnings,C=de(a.queryDraft,v,i.aggregates),w=g(a.query),T=e=>{let t=K(e);return w.filter(e=>K(e.key??``)===t).map(e=>e.value).filter(Boolean)},E=e=>{let t=new Set;for(let n of e)n&&t.add(n);return Array.from(t)},D=E([...i.agents,..._.map(e=>e.agentId)]).slice(0,12),k=E(v.map(e=>e.channel)).slice(0,12),A=E([...v.map(e=>e.modelProvider),...v.map(e=>e.providerOverride),...i.aggregates?.byProvider.map(e=>e.provider)??[]]).slice(0,12),j=E([...v.map(e=>e.model),...i.aggregates?.byModel.map(e=>e.model)??[]]).slice(0,12),M=E(i.aggregates?.tools.tools.map(e=>e.name)??[]).slice(0,12),N=a.selectedSessions.length===1?i.sessions.find(e=>e.key===a.selectedSessions[0])??x.find(e=>e.key===a.selectedSessions[0]):null,P=e=>e.reduce((e,t)=>t.usage?tt(e,t.usage):e,et()),F=e=>i.costDaily.filter(t=>e.includes(t.date)).reduce((e,t)=>tt(e,t),et()),I,L,R=v.length;if(a.selectedSessions.length>0){let e=x.filter(e=>a.selectedSessions.includes(e.key));I=P(e),L=e.length}else a.selectedDays.length>0&&a.selectedHours.length===0?(I=F(a.selectedDays),L=x.length):a.selectedHours.length>0||m?(I=P(x),L=x.length):a.agentId?(I=P(v),L=R):(I=i.totals,L=R);let B=a.selectedSessions.length>0?x.filter(e=>a.selectedSessions.includes(e.key)):m||a.selectedHours.length>0?x:a.selectedDays.length>0?y:_,V=G(B,i.aggregates),H=a.selectedSessions.length>0?(()=>{let e=x.filter(e=>a.selectedSessions.includes(e.key)),t=new Set;for(let n of e)for(let e of n.usage?.activityDates??[])t.add(e);return t.size>0?i.costDaily.filter(e=>t.has(e.date)):i.costDaily})():i.costDaily,U=ae(B,I,V),W=!i.loading&&!i.totals&&i.sessions.length===0,se=d(i.cacheStatus),ce=(I?.missingCostEntries??0)>0||(I?I.totalTokens>0&&I.totalCost===0&&I.input+I.output+I.cacheRead+I.cacheWrite>0:!1),q=[{label:r(`usage.presets.today`),days:1},{label:r(`usage.presets.last7d`),days:7},{label:r(`usage.presets.last30d`),days:30},{label:r(`usage.presets.last90d`),days:90},{label:r(`usage.presets.last1y`),days:365}],ge=e=>{let t=new Date,n=new Date;n.setDate(n.getDate()-(e-1)),l.onStartDateChange(ie(n)),l.onEndDateChange(ie(t))},_e=()=>{l.onStartDateChange(`1970-01-01`),l.onEndDateChange(ie(new Date))},J=(e,i,o)=>{if(o.length===0)return n;let s=T(e),c=new Set(s.map(e=>K(e))),u=o.length>0&&o.every(e=>c.has(K(e))),d=s.length;return t`
      <details
        class="usage-filter-select"
        @toggle=${e=>{let t=e.currentTarget;if(!t.open)return;let n=e=>{e.composedPath().includes(t)||(t.open=!1,window.removeEventListener(`click`,n,!0))};window.addEventListener(`click`,n,!0)}}
      >
        <summary>
          <span>${i}</span>
          ${d>0?t`<span class="usage-filter-badge">${d}</span>`:t` <span class="usage-filter-badge">${r(`usage.filters.all`)}</span> `}
        </summary>
        <div class="usage-filter-popover">
          <div class="usage-filter-actions">
            <button
              class="btn btn--sm"
              @click=${t=>{t.preventDefault(),t.stopPropagation(),l.onQueryDraftChange(he(a.queryDraft,e,o))}}
              ?disabled=${u}
            >
              ${r(`usage.filters.selectAll`)}
            </button>
            <button
              class="btn btn--sm"
              @click=${t=>{t.preventDefault(),t.stopPropagation(),l.onQueryDraftChange(he(a.queryDraft,e,[]))}}
              ?disabled=${d===0}
            >
              ${r(`usage.filters.clear`)}
            </button>
          </div>
          <div class="usage-filter-options">
            ${o.map(n=>t`
                <label class="usage-filter-option">
                  <input
                    type="checkbox"
                    .checked=${c.has(K(n))}
                    @change=${t=>{let r=t.target,i=`${e}:${n}`;l.onQueryDraftChange(r.checked?pe(a.queryDraft,i):me(a.queryDraft,i))}}
                  />
                  <span>${n}</span>
                </label>
              `)}
          </div>
        </div>
      </details>
    `},Y=()=>{let e=a.agentId??``;return t`
      <details class="usage-filter-select">
        <summary>
          <span>${r(`usage.filters.agent`)}</span>
          <span class="usage-filter-badge">${e||r(`usage.filters.all`)}</span>
        </summary>
        <div class="usage-filter-popover">
          <div class="usage-filter-options">
            ${[``,...D].map(n=>t`
                <label class="usage-filter-option">
                  <input
                    type="radio"
                    name="usage-agent-scope"
                    .checked=${e===n}
                    @change=${()=>l.onAgentChange(n||null)}
                  />
                  <span>${n||r(`usage.filters.all`)}</span>
                </label>
              `)}
          </div>
        </div>
      </details>
    `},ve=ie(new Date);return t`
    <div class="usage-page">
      <section class="card usage-header ${o.headerPinned?`pinned`:``}">
        <div class="usage-header-row">
          <div class="usage-header-title">
            <div class="card-title usage-section-title">${r(`usage.filters.title`)}</div>
            ${i.loading||se?t`<span class="usage-refresh-indicator" title=${se??``}>
                  ${r(`usage.loading.badge`)}
                </span>`:n}
            ${W?t`<span class="usage-query-hint">${r(`usage.empty.hint`)}</span>`:n}
          </div>
          <div class="usage-header-metrics">
            ${I?t`
                  <span class="usage-metric-badge">
                    <strong>${O(I.totalTokens)}</strong>
                    ${r(`usage.metrics.tokens`)}
                  </span>
                  <span class="usage-metric-badge">
                    <strong>${z(I.totalCost)}</strong>
                    ${r(`usage.metrics.cost`)}
                  </span>
                  <span class="usage-metric-badge">
                    <strong>${L}</strong>
                    ${r(L===1?`usage.metrics.session`:`usage.metrics.sessions`)}
                  </span>
                `:n}
            <button
              class="btn btn--sm usage-pin-btn ${o.headerPinned?`active`:``}"
              title=${o.headerPinned?r(`usage.filters.unpin`):r(`usage.filters.pin`)}
              @click=${l.onToggleHeaderPinned}
            >
              ${o.headerPinned?r(`usage.filters.pinned`):r(`usage.filters.pin`)}
            </button>
            <details
              class="usage-export-menu"
              @toggle=${e=>{let t=e.currentTarget;if(!t.open)return;let n=e=>{e.composedPath().includes(t)||(t.open=!1,window.removeEventListener(`click`,n,!0))};window.addEventListener(`click`,n,!0)}}
            >
              <summary class="btn btn--sm">${r(`usage.export.label`)} ▾</summary>
              <div class="usage-export-popover">
                <div class="usage-export-list">
                  <button
                    class="usage-export-item"
                    @click=${()=>oe(`openclaw-usage-sessions-${ve}.csv`,le(x),`text/csv`)}
                    ?disabled=${x.length===0}
                  >
                    ${r(`usage.export.sessionsCsv`)}
                  </button>
                  <button
                    class="usage-export-item"
                    @click=${()=>oe(`openclaw-usage-daily-${ve}.csv`,ue(H),`text/csv`)}
                    ?disabled=${H.length===0}
                  >
                    ${r(`usage.export.dailyCsv`)}
                  </button>
                  <button
                    class="usage-export-item"
                    @click=${()=>oe(`openclaw-usage-${ve}.json`,JSON.stringify({totals:I,sessions:x,daily:H,aggregates:V},null,2),`application/json`)}
                    ?disabled=${x.length===0&&H.length===0}
                  >
                    ${r(`usage.export.json`)}
                  </button>
                </div>
              </div>
            </details>
          </div>
        </div>

        <div class="usage-header-row">
          <div class="usage-controls">
            ${Ie(a.selectedDays,a.selectedHours,a.selectedSessions,i.sessions,l.onClearDays,l.onClearHours,l.onClearSessions,l.onClearFilters)}
            <div class="usage-presets">
              ${q.map(e=>t`
                  <button class="btn btn--sm" @click=${()=>ge(e.days)}>
                    ${e.label}
                  </button>
                `)}
              <button class="btn btn--sm" @click=${_e}>${r(`usage.presets.all`)}</button>
            </div>
            <div class="usage-date-range">
              <input
                class="usage-date-input"
                type="date"
                .value=${a.startDate}
                title=${r(`usage.filters.startDate`)}
                aria-label=${r(`usage.filters.startDate`)}
                @change=${e=>l.onStartDateChange(e.target.value)}
              />
              <span class="usage-separator">${r(`usage.filters.to`)}</span>
              <input
                class="usage-date-input"
                type="date"
                .value=${a.endDate}
                title=${r(`usage.filters.endDate`)}
                aria-label=${r(`usage.filters.endDate`)}
                @change=${e=>l.onEndDateChange(e.target.value)}
              />
            </div>
            <select
              class="usage-select"
              title=${r(`usage.filters.timeZone`)}
              aria-label=${r(`usage.filters.timeZone`)}
              .value=${a.timeZone}
              @change=${e=>l.onTimeZoneChange(e.target.value)}
            >
              <option value="local">${r(`usage.filters.timeZoneLocal`)}</option>
              <option value="utc">${r(`usage.filters.timeZoneUtc`)}</option>
            </select>
            <div class="chart-toggle">
              <button
                class="btn btn--sm toggle-btn ${a.scope===`instance`?`active`:``}"
                title=${r(`usage.scope.instanceHint`)}
                @click=${()=>l.onScopeChange(`instance`)}
              >
                ${r(`usage.scope.instance`)}
              </button>
              <button
                class="btn btn--sm toggle-btn ${a.scope===`family`?`active`:``}"
                title=${r(`usage.scope.familyHint`)}
                @click=${()=>l.onScopeChange(`family`)}
              >
                ${r(`usage.scope.family`)}
              </button>
            </div>
            <div class="chart-toggle">
              <button
                class="btn btn--sm toggle-btn ${p?`active`:``}"
                @click=${()=>u.onChartModeChange(`tokens`)}
              >
                ${r(`usage.metrics.tokens`)}
              </button>
              <button
                class="btn btn--sm toggle-btn ${p?``:`active`}"
                @click=${()=>u.onChartModeChange(`cost`)}
              >
                ${r(`usage.metrics.cost`)}
              </button>
            </div>
            <button
              class="btn btn--sm primary"
              @click=${l.onRefresh}
              ?disabled=${i.loading}
            >
              ${r(`common.refresh`)}
            </button>
          </div>
        </div>

        <div class="usage-query-section">
          <div class="usage-query-bar">
            <input
              class="usage-query-input"
              type="text"
              .value=${a.queryDraft}
              placeholder=${r(`usage.query.placeholder`)}
              @input=${e=>l.onQueryDraftChange(e.target.value)}
              @keydown=${e=>{e.key===`Enter`&&(e.preventDefault(),l.onApplyQuery())}}
            />
            <div class="usage-query-actions">
              <button
                class="btn btn--sm"
                @click=${l.onApplyQuery}
                ?disabled=${i.loading||!h&&!m}
              >
                ${r(`usage.query.apply`)}
              </button>
              ${h||m?t`
                    <button class="btn btn--sm" @click=${l.onClearQuery}>
                      ${r(`usage.filters.clear`)}
                    </button>
                  `:n}
              <span class="usage-query-hint">
                ${m?r(`usage.query.matching`,{shown:String(x.length),total:String(R)}):r(`usage.query.inRange`,{total:String(R)})}
              </span>
            </div>
          </div>
          <div class="usage-filter-row">
            ${Y()}
            ${J(`channel`,r(`usage.filters.channel`),k)}
            ${J(`provider`,r(`usage.filters.provider`),A)}
            ${J(`model`,r(`usage.filters.model`),j)}
            ${J(`tool`,r(`usage.filters.tool`),M)}
            <span class="usage-query-hint">${r(`usage.query.tip`)}</span>
          </div>
          ${w.length>0?t`
                <div class="usage-query-chips">
                  ${w.map(e=>{let n=e.raw;return t`
                      <span class="usage-query-chip">
                        ${n}
                        <button
                          title=${r(`usage.filters.remove`)}
                          @click=${()=>l.onQueryDraftChange(me(a.queryDraft,n))}
                        >
                          ×
                        </button>
                      </span>
                    `})}
                </div>
              `:n}
          ${C.length>0?t`
                <div class="usage-query-suggestions">
                  ${C.map(e=>t`
                      <button
                        class="usage-query-suggestion"
                        @click=${()=>l.onQueryDraftChange(fe(a.queryDraft,e.value))}
                      >
                        ${e.label}
                      </button>
                    `)}
                </div>
              `:n}
          ${S.length>0?t`
                <div class="callout warning usage-callout usage-callout--tight">
                  ${S.join(` · `)}
                </div>
              `:n}
        </div>

        ${i.error?t`<div class="callout danger usage-callout">${i.error}</div>`:n}
        ${se?t`
              <div class="callout warning usage-callout usage-cache-warning">
                ${r(`usage.cacheStatus.warning`)} ${se}
              </div>
            `:n}
        ${i.sessionsLimitReached?t`
              <div class="callout warning usage-callout">${r(`usage.sessions.limitReached`)}</div>
            `:n}
      </section>

      ${W?rt(l.onRefresh):t`
            ${Ve(I,V,U,ce,te(B,a.timeZone),L,R)}
            ${re(B,a.timeZone,a.selectedHours,l.onSelectHour)}

            <div class="usage-grid">
              <div class="usage-grid-column">
                <div class="card usage-left-card">
                  ${Le(H,a.selectedDays,o.chartMode,o.dailyChartMode,u.onDailyChartModeChange,l.onSelectDay)}
                  ${I?Re(I,o.chartMode):n}
                </div>
                ${He(x,a.selectedSessions,a.selectedDays,p,o.sessionSort,o.sessionSortDir,o.recentSessions,o.sessionsTab,f.onSelectSession,u.onSessionSortChange,u.onSessionSortDirChange,u.onSessionsTabChange,o.visibleColumns,R,l.onClearSessions)}
              </div>
              ${N?t`<div class="usage-grid-column">
                    ${Xe(N,s.timeSeries,s.timeSeriesLoading,s.timeSeriesMode,f.onTimeSeriesModeChange,s.timeSeriesBreakdownMode,f.onTimeSeriesBreakdownChange,s.timeSeriesCursorStart,s.timeSeriesCursorEnd,f.onTimeSeriesCursorRangeChange,a.startDate,a.endDate,a.selectedDays,s.sessionLogs,s.sessionLogsLoading,s.sessionLogsExpanded,f.onToggleSessionLogsExpanded,s.logFilters,f.onLogFilterRolesChange,f.onLogFilterToolsChange,f.onLogFilterHasToolsChange,f.onLogFilterQueryChange,f.onLogFilterClear,o.contextExpanded,f.onToggleContextExpanded,l.onClearSessions)}
                  </div>`:n}
            </div>
          `}
    </div>
  `}export{it as renderUsage};
//# sourceMappingURL=usage-Bef5VokL.js.map