PageSourceSearch

https://app.lobsterland.ing/assets/UsageTab.be424181.js

js lobsterland.ing collected 2026-10-09 21:47:00 UTC 6,120 bytes, 1 lines download raw bytes

1import{d as O,o as A,c as n,a as s,I as k,J as C,z as U,y as b,h as V,s as q,t as r,r as c,i as v,al as N,p as o,n as P,k as H}from"./index.b2e088d7.js";import{u as J}from"./useToast.042a6fce.js";import{L as R}from"./loader-circle.0aae17ab.js";import{D as G}from"./download.e31c57ca.js";const K={class:"flex items-center justify-between mb-6 flex-wrap gap-3"},Q={class:"flex items-center gap-1 flex-wrap"},W=["onClick"],X=["disabled"],Y={key:0,class:"flex items-center justify-center py-16"},Z={key:1,class:"card py-10 text-center text-sm text-[var(--text-2)]",role:"status"},tt={class:"grid gap-4 sm:grid-cols-3"},et={class:"card"},st={class:"text-lg font-semibold text-[var(--text-0)] mt-1"},at={class:"card"},ot={class:"text-lg font-semibold text-[var(--text-0)] mt-1"},nt={class:"card"},lt={class:"text-lg font-semibold text-[var(--text-0)] mt-1"},rt={class:"card mt-4"},it={key:0,class:"text-sm text-[var(--text-3)] py-8 text-center"},ct={key:1,class:"h-32"},ut={class:"w-full h-full",viewBox:"0 0 300 120",preserveAspectRatio:"none"},dt=["points"],mt={class:"card mt-4"},vt={key:0,class:"text-sm text-[var(--text-3)] py-4 text-center"},pt={key:1,class:"overflow-x-auto"},ft={class:"w-full text-xs"},xt={class:"py-2 pr-4"},gt={class:"py-2 pr-4"},_t={class:"py-2"},Tt=O({__name:"UsageTab",setup(kt){const S=H(),{error:h}=J(),y=v(()=>S.params.id),I=[{label:"24h",value:"24h"},{label:"7d",value:"7d"},{label:"30d",value:"30d"},{label:"All",value:"all"}],i=c("24h"),p=c(!0),u=c(!1),f=c(!1),d=c({total_tokens:0,total_cost:0,total_requests:0}),x=c([]);function g(t){return new Intl.NumberFormat().format(t||0)}function L(){if(i.value==="all")return{};const t=new Date,e=new Date(t.getTime());return i.value==="24h"?e.setHours(t.getHours()-24):i.value==="7d"?e.setDate(t.getDate()-7):i.value==="30d"&&e.setDate(t.getDate()-30),{start_date:e.toISOString(),end_date:t.toISOString()}}function j(t){for(const e of["date","day","timestamp","time","created_at"]){const a=t[e];if(typeof a=="string"||typeof a=="number"){const l=new Date(a);if(!Number.isNaN(l.getTime()))return l}}return null}function w(t){const e=t.total_tokens??t.tokens??t.total??t.usage_tokens;if(typeof e=="number")return e;const a=t.input_tokens,l=t.output_tokens;return typeof a=="number"&&typeof l=="number"?a+l:0}function F(t){const e=t.total_cost??t.cost??t.spend??t.amount;return typeof e=="number"?e:0}function M(t){const e=t.model??t.model_name??t.llm_model;return typeof e=="string"&&e.length>0?e:"Unknown"}const T=v(()=>x.value.map(t=>{const e=j(t);return e?{date:e,tokens:w(t)}:null}).filter(t=>t!==null).sort((t,e)=>t.date.getTime()-e.date.getTime())),$=v(()=>{const t=T.value;if(t.length<2)return"";const e=Math.max(...t.map(a=>a.tokens),1);return t.map((a,l)=>{const _=l/(t.length-1)*280+10,m=110-a.tokens/e*100;return`${_},${m}`}).join(" ")}),D=v(()=>{const t=new Map;return x.value.forEach(e=>{const a=M(e),l=w(e),_=F(e),m=t.get(a)||{tokens:0,cost:0};t.set(a,{tokens:m.tokens+l,cost:m.cost+_})}),Array.from(t.entries()).map(([e,a])=>({model:e,...a})).sort((e,a)=>a.tokens-e.tokens)});async function E(){p.value=!0,f.value=!1;try{const t=L(),e=await N.getSummary(y.value,t);d.value=e.stats,x.value=e.entries||[]}catch(t){f.value=!0,h(t instanceof Error?t.message:"Failed to load usage data.")}finally{p.value=!1}}function z(t){i.value=t,E()}async function B(){u.value=!0;try{const t=await N.exportUsage(y.value),e=window.URL.createObjectURL(t),a=document.createElement("a");a.href=e,a.download=`openclaw-usage-${new Date().toISOString().slice(0,10)}.csv`,a.click(),window.URL.revokeObjectURL(e)}catch(t){h(t instanceof Error?t.message:"Failed to export usage.")}finally{u.value=!1}}return A(E),(t,e)=>(o(),n("div",null,[s("div",K,[e[1]||(e[1]=s("div",null,[s("h1",{class:"section-title"},"Usage"),s("p",{class:"section-subtitle"},"Track tokens, spend, and usage patterns across time.")],-1)),s("div",Q,[(o(),n(k,null,C(I,a=>s("button",{key:a.value,class:P(["px-3 py-1.5 rounded-full text-xs font-medium transition-colors",i.value===a.value?"bg-[var(--brand-10)] text-brand":"text-[var(--text-2)] hover:bg-[var(--surface-1)]"]),onClick:l=>z(a.value)},r(a.label),11,W)),64)),s("button",{class:"btn-secondary btn-sm ml-2",disabled:u.value,onClick:B},[u.value?(o(),U(b(R),{key:0,size:14,class:"animate-spin"})):(o(),U(b(G),{key:1,size:14})),e[0]||(e[0]=V(" CSV ",-1))],8,X)])]),p.value?(o(),n("div",Y,[q(b(R),{size:24,class:"animate-spin text-[var(--text-3)]"})])):f.value?(o(),n("div",Z," Usage data is temporarily unavailable. Try again shortly. ")):(o(),n(k,{key:2},[s("div",tt,[s("div",et,[e[2]||(e[2]=s("p",{class:"text-xs text-[var(--text-3)]"},"Tokens",-1)),s("p",st,r(g(d.value.total_tokens)),1)]),s("div",at,[e[3]||(e[3]=s("p",{class:"text-xs text-[var(--text-3)]"},"Cost",-1)),s("p",ot,"$"+r((d.value.total_cost||0).toFixed(2)),1)]),s("div",nt,[e[4]||(e[4]=s("p",{class:"text-xs text-[var(--text-3)]"},"Requests",-1)),s("p",lt,r(g(d.value.total_requests)),1)])]),s("div",rt,[e[5]||
1(e[5]=s("p",{class:"text-xs font-medium text-[var(--text-3)] uppercase tracking-wider mb-3"},"Tokens over time",-1)),T.value.length<2?(o(),n("div",it," No usage data for this time range. ")):(o(),n("div",ct,[(o(),n("svg",ut,[s("polyline",{points:$.value,fill:"none",stroke:"var(--ok-500)","stroke-width":"2.5","stroke-linecap":"round","stroke-linejoin":"round","vector-effect":"non-scaling-stroke"},null,8,dt)]))]))]),s("div",mt,[e[7]||(e[7]=s("p",{class:"text-xs font-medium text-[var(--text-3)] uppercase tracking-wider mb-3"},"Per-model breakdown",-1)),D.value.length===0?(o(),n("div",vt," No model data available. ")):(o(),n("div",pt,[s("table",ft,[e[6]||(e[6]=s("thead",null,[s("tr",{class:"text-left text-[var(--text-3)]"},[s("th",{class:"pb-2 pr-4 font-medium"},"Model"),s("th",{class:"pb-2 pr-4 font-medium"},"Tokens"),s("th",{class:"pb-2 font-medium"},"Cost")])],-1)),s("tbody",null,[(o(!0),n(k,null,C(D.value,a=>(o(),n("tr",{key:a.model,class:"text-[var(--text-1)] border-t border-[var(--border-0)]"},[s("td",xt,r(a.model),1),s("td",gt,r(g(a.tokens)),1),s("td",_t,"$"+r(a.cost.toFixed(2)),1)]))),128))])])]))])],64))]))}});export{Tt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.