usage-board 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +16 -7
- package/dist/public/_nuxt/B-CIibMz.js +25 -0
- package/dist/public/_nuxt/BFLIXB9O.js +9 -0
- package/dist/public/_nuxt/{DcPhnO3V.js → BNPuv5_2.js} +18 -18
- package/dist/public/_nuxt/Brp07rVz.js +3 -0
- package/dist/public/_nuxt/Bvg0CuDs.js +258 -0
- package/dist/public/_nuxt/CvpNFEwm.js +1 -0
- package/dist/public/_nuxt/D3pogf62.js +1 -0
- package/dist/public/_nuxt/{DLRBRF52.js → D9KD20BD.js} +1 -1
- package/dist/public/_nuxt/DUfyK9T8.js +21 -0
- package/dist/public/_nuxt/{BKFuB2T3.js → DsWoOjFk.js} +2 -2
- package/dist/public/_nuxt/builds/latest.json +1 -1
- package/dist/public/_nuxt/builds/meta/38460625-fa40-4f13-86da-ddec4bfb4ab8.json +1 -0
- package/dist/public/_nuxt/entry.CJkVK2j6.css +1 -0
- package/dist/public/_nuxt/{CileeSf2.js → f_iPFAtL.js} +1 -1
- package/dist/server/chunks/_/error-500.mjs +14 -0
- package/dist/server/chunks/_/index.min.mjs +348 -0
- package/dist/server/chunks/_/shared.cjs.prod.mjs +1 -1
- package/dist/server/chunks/build/client.precomputed.mjs +1 -1
- package/dist/server/chunks/nitro/nitro.mjs +162 -813
- package/dist/server/chunks/routes/api/payload.json.mjs +10 -348
- package/dist/server/chunks/routes/renderer.mjs +1 -2
- package/dist/server/chunks/routes/ws.mjs +1063 -0
- package/dist/server/index.mjs +1 -2
- package/package.json +6 -2
- package/dist/public/_nuxt/BNf7fR7M.js +0 -282
- package/dist/public/_nuxt/DAg3mJyk.js +0 -1
- package/dist/public/_nuxt/DoxGa6D0.js +0 -9
- package/dist/public/_nuxt/DptRzj9K.js +0 -3
- package/dist/public/_nuxt/builds/meta/b9978cce-47fc-4109-96be-42c2d4ff2464.json +0 -1
- package/dist/public/_nuxt/entry.DrzELaFO.css +0 -1
package/dist/index.mjs
CHANGED
|
@@ -756,23 +756,32 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({ darwin: "Safari"
|
|
|
756
756
|
//#endregion
|
|
757
757
|
//#region package.json
|
|
758
758
|
var name = "usage-board";
|
|
759
|
-
var version = "
|
|
759
|
+
var version = "2.0.0";
|
|
760
760
|
//#endregion
|
|
761
761
|
//#region src/index.ts
|
|
762
762
|
const cli = cac(name);
|
|
763
|
-
async function
|
|
763
|
+
async function loadNitroEntrypoint(outputDir) {
|
|
764
764
|
const mod = await import(resolve(outputDir, "server/index.mjs"));
|
|
765
|
-
return
|
|
765
|
+
return {
|
|
766
|
+
listener: mod.listener ?? mod.middleware ?? mod.handler ?? mod.default,
|
|
767
|
+
websocket: mod.websocket
|
|
768
|
+
};
|
|
766
769
|
}
|
|
767
770
|
cli.command("", "Start tokens usage analysis").option("--host <host>", "Host", { default: "127.0.0.1" }).option("--port <port>", "Port", { default: 7777 }).option("--open", "Open browser", { default: true }).action(async (option) => {
|
|
768
771
|
const port = await getPort({
|
|
769
772
|
port: option.port,
|
|
770
773
|
portRange: [7777, 9e3]
|
|
771
774
|
});
|
|
772
|
-
const
|
|
773
|
-
createServer(async (req, res) => {
|
|
774
|
-
await
|
|
775
|
-
})
|
|
775
|
+
const nitro = await loadNitroEntrypoint(resolve(dirname(fileURLToPath(import.meta.url)), "./"));
|
|
776
|
+
const app = createServer(async (req, res) => {
|
|
777
|
+
await nitro.listener(req, res);
|
|
778
|
+
});
|
|
779
|
+
if (nitro.websocket) {
|
|
780
|
+
const { default: wsAdapter } = await import("crossws/adapters/node");
|
|
781
|
+
const { handleUpgrade } = wsAdapter(nitro.websocket);
|
|
782
|
+
app.on("upgrade", handleUpgrade);
|
|
783
|
+
}
|
|
784
|
+
app.listen(port, option.host, async () => {
|
|
776
785
|
if (option.open) {
|
|
777
786
|
const url = `http://${option.host}:${port}`;
|
|
778
787
|
console.log(`Usage board is running at ${url}`);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import{w as W,S as Z,C as ee,a as J,z as te,A as ne,_ as oe,f as y,d as C}from"./Bvg0CuDs.js";import{z as K,o as u,B as X,w as P,b as _,D as i,a as o,c as f,Y as T,X as $,h as r,E as H,t as m,ae,a5 as O,H as q}from"./BFLIXB9O.js";const se={class:"mt-4 flex flex-wrap items-center justify-center gap-3 text-xs text-muted-foreground"},re={class:"font-medium text-foreground tabular-nums"},le=K({name:"StatisticalAnalysisModelUsagePanel",__name:"ModelUsagePanel",props:{monthlyItems:{},year:{}},setup(D){const g=D,v=["#2563eb","#f97316","#0891b2","#8b5cf6","#059669","#f43f5e"],M={bottom:32,left:56,right:12,top:8},S=[0,void 0],x=r(()=>g.year??A(g.monthlyItems)??new Date().getFullYear()),b=r(()=>Array.from({length:12},(t,e)=>{const s=`${e+1}`.padStart(2,"0");return`${x.value}-${s}`})),U=r(()=>[0,Math.max(b.value.length-1,0)]),p=r(()=>b.value.map((t,e)=>e)),k=r(()=>g.monthlyItems.filter(t=>t.month.startsWith(`${x.value}-`))),h=r(()=>Array.from(new Set(k.value.map(t=>t.model)))),w=r(()=>b.value.map((t,e)=>{const s=Object.fromEntries(h.value.map(c=>[c,k.value.find(d=>d.month===t&&d.model===c)?.tokenTotal??0]));return{month:t,monthIndex:e,tokensByModel:s,totalTokens:Object.values(s).reduce((c,d)=>c+d,0)}})),l=r(()=>h.value.map((t,e)=>{const s=n(e),c=w.value.reduce((d,Q)=>d+(Q.tokensByModel[t]??0),0);return{color:s,model:t,totalLabel:y(c),totalTokens:c}}).sort((t,e)=>e.totalTokens-t.totalTokens)),L=r(()=>l.value.map(t=>e=>e.tokensByModel[t.model]??0)),E=r(()=>Object.fromEntries(l.value.map(t=>[t.model,{color:t.color,label:t.model}]))),G=r(()=>l.value.map(t=>`
|
|
2
|
+
<linearGradient id="${F(t.model)}" x1="0" y1="0" x2="0" y2="1">
|
|
3
|
+
<stop offset="0%" stop-color="${t.color}" stop-opacity="0.45" />
|
|
4
|
+
<stop offset="100%" stop-color="${t.color}" stop-opacity="0.08" />
|
|
5
|
+
</linearGradient>
|
|
6
|
+
`).join(""));function N(t){return t.monthIndex}function I(t,e){const s=l.value[e];return s?`url(#${F(s.model)})`:n(0)}function z(t,e){return l.value[e]?.color??n(0)}function Y(t,e){return l.value[e]?.color??n(0)}function R(t){const e=l.value.map(s=>({...s,tokenTotal:t.tokensByModel[s.model]??0})).sort((s,c)=>c.tokenTotal-s.tokenTotal);return`
|
|
7
|
+
<div class="grid min-w-48 gap-2 rounded-md border bg-background px-3 py-2 text-xs shadow-lg">
|
|
8
|
+
<div class="font-medium text-foreground">${j(t.month)} ${t.month.slice(0,4)}</div>
|
|
9
|
+
<div class="grid gap-1 text-muted-foreground">
|
|
10
|
+
${e.map(s=>`
|
|
11
|
+
<div class="flex items-center justify-between gap-4">
|
|
12
|
+
<span class="flex items-center gap-2">
|
|
13
|
+
<span class="size-2 rounded-sm" style="background-color: ${s.color}"></span>
|
|
14
|
+
${a(s.model)}
|
|
15
|
+
</span>
|
|
16
|
+
<span class="font-mono font-medium text-foreground">${y(s.tokenTotal)}</span>
|
|
17
|
+
</div>
|
|
18
|
+
`).join("")}
|
|
19
|
+
</div>
|
|
20
|
+
<div class="flex justify-between gap-4 border-t pt-2 text-muted-foreground">
|
|
21
|
+
<span>Total</span>
|
|
22
|
+
<span class="font-mono font-semibold text-foreground">${y(t.totalTokens)}</span>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
`}function V(t){if(t instanceof Date)return"";const e=b.value[t];return e?j(e):""}function B(t){return t instanceof Date?"":y(t)}function j(t){const[e,s]=t.split("-"),c=new Date(Number(e),Number(s)-1,1);return new Intl.DateTimeFormat("en-US",{month:"short"}).format(c)}function A(t){const s=[...t].sort((c,d)=>d.month.localeCompare(c.month))[0]?.month?.split("-")[0];return s?Number(s):null}function F(t){return`model-usage-${t.replace(/[^a-z0-9]+/gi,"-").toLowerCase()}`}function n(t){return v[t%v.length]??"#2563eb"}function a(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}return(t,e)=>{const s=oe,c=W;return u(),X(c,{description:"Monthly token trends by model",icon:"solar:cpu-line-duotone",title:"Model Usage"},{default:P(()=>[_(s,{class:"h-72 w-full",config:i(E)},{default:P(()=>[_(i(Z),{"auto-margin":!1,data:i(w),height:288,margin:M,"svg-defs":i(G),"x-domain":i(U),"y-domain":S},{default:P(()=>[_(i(ee),{color:I,line:!0,"line-color":z,"line-width":2.5,opacity:.82,x:N,y:i(L)},null,8,["y"]),_(i(J),{"grid-line":!1,"tick-format":V,"tick-values":i(p),type:"x"},null,8,["tick-values"]),_(i(J),{"num-ticks":4,"tick-format":B,type:"y"}),_(i(te)),_(i(ne),{color:Y,template:R,x:N,"y-stacked":i(L)},null,8,["y-stacked"])]),_:1},8,["data","svg-defs","x-domain"])]),_:1},8,["config"]),o("div",se,[(u(!0),f($,null,T(i(l),d=>(u(),f("div",{key:d.model,class:"flex items-center gap-2"},[o("span",{class:"size-2.5 rounded-sm",style:H({backgroundColor:d.color})},null,4),o("span",null,m(d.model),1),o("span",re,m(d.totalLabel),1)]))),128))])]),_:1})}}}),He=Object.assign(le,{__name:"StatisticalAnalysisModelUsagePanel"}),ce={class:"space-y-3"},de={class:"flex flex-col flex-1"},ie={class:"truncate text-sm font-medium tracking-tight"},ue={class:"mt-1 truncate text-xs text-muted-foreground"},me={class:"text-right"},ge={class:"text-xs font-medium tracking-tight tabular-nums"},pe={class:"mt-1 flex items-center justify-end gap-1"},fe=K({name:"StatisticalAnalysisProjectUsagePanel",__name:"ProjectUsagePanel",props:{items:{}},setup(D){const g=D,v=[{trend:"+12.4%",trendTone:"up"},{trend:"-8.2%",trendTone:"down"},{trend:"+22.1%",trendTone:"up"},{trend:"+15.8%",trendTone:"up"},{trend:"-3.4%",trendTone:"down"},{trend:"+9.6%",trendTone:"up"},{trend:"-5.1%",trendTone:"down"},{trend:"+4.7%",trendTone:"up"}],M=r(()=>g.items.slice(0,6).map((p,k)=>{const h=v[k]??{trend:"+0.0%",trendTone:"up"};return{...p,shortName:U(p.label),trend:h.trend,trendTone:h.trendTone}}));function S(p){return p==="down"?"lucide:trending-down":"lucide:trending-up"}function x(p){return p==="down"?"size-3 text-red-500":"size-3 text-emerald-600 dark:text-emerald-400"}function b(p){return p==="down"?"text-sm font-medium text-red-500 tabular-nums":"text-sm font-medium text-emerald-600 dark:text-emerald-400 tabular-nums"}function U(p){return p.split(/[-_\s]+/).filter(Boolean).slice(0,2).map(k=>k[0]?.toUpperCase()??"").join("")}return(p,k)=>{const h=ae,w=W;return u(),X(w,{description:"Best performers by spend",icon:"lucide:folder-git-2",title:"Top Projects"},{default:P(()=>[o("div",ce,[(u(!0),f($,null,T(i(M),l=>(u(),f("div",{key:l.repository,class:"flex justify-between items-center gap-3 rounded-md transition-colors"},[o("div",de,[o("p",ie,m(l.label),1),o("p",ue,m(l.detail),1)]),o("div",me,[o("p",ge,m(l.value),1),o("div",pe,[_(h,{class:O(x(l.trendTone)),mode:"svg",name:S(l.trendTone)},null,8,["class","name"]),o("span",{class:O(b(l.trendTone))},m(l.trend),3)])])]))),128))])]),_:1})}}}),Oe=Object.assign(fe,{__name:"StatisticalAnalysisProjectUsagePanel"}),be={class:"mb-4 grid grid-cols-1 gap-3 sm:grid-cols-3"},ye={class:"text-xs text-muted-foreground"},ke={class:"mt-1 text-lg font-semibold tabular-nums"},he={class:"border-b pb-4"},_e=["aria-label","tabindex"],ve={class:"sr-only"},xe={key:0,class:"pointer-events-none absolute bottom-full left-1/2 z-30 mb-2 hidden min-w-40 -translate-x-1/2 gap-1 rounded-md border bg-popover px-2.5 py-1.5 text-xs text-popover-foreground shadow-md group-hover:grid group-focus-visible:grid",role:"tooltip"},we={class:"font-medium"},Te={key:0,class:"flex items-center justify-between gap-4 text-muted-foreground"},$e={class:"font-mono font-medium text-foreground"},Ce={class:"flex items-center justify-between gap-4 text-muted-foreground"},De={class:"font-mono font-medium text-foreground"},Me={key:1,class:"flex items-center justify-between gap-4 text-muted-foreground"},Se={class:"font-mono font-medium text-foreground"},Ue={class:"mt-4 flex items-center justify-between gap-4"},Le={class:"text-xs text-muted-foreground"},Be={class:"flex items-center gap-1 text-xs text-muted-foreground"},je={class:"mt-4 grid grid-cols-1 gap-3 sm:grid-cols-3"},Ae={class:"text-xs text-muted-foreground"},Pe={class:"mt-1 flex items-center justify-between gap-2"},Ne={class:"text-sm font-semibold"},Ie={class:"text-xs text-muted-foreground"},ze=K({name:"UsageHeatmapPanel",__name:"UsageHeatmapPanel",props:{heatMetric:{default:"tokens"},items:{},title:{}},setup(D){const g=D,v=["bg-zinc-100 dark:bg-zinc-800/80","bg-emerald-50 dark:bg-emerald-950/70","bg-emerald-100 dark:bg-emerald-900/70","bg-teal-100 dark:bg-teal-900/75","bg-teal-200 dark:bg-teal-800/80","bg-cyan-200 dark:bg-cyan-800/85","bg-cyan-300 dark:bg-cyan-700/90","bg-sky-300 dark:bg-sky-600/90","bg-sky-400 dark:bg-sky-500/95","bg-blue-500 dark:bg-blue-400"],M=[...v],S=[{key:"sun",label:"S",row:"1"},{key:"mon",label:"M",row:"2"},{key:"tue",label:"T",row:"3"},{key:"wed",label:"W",row:"4"},{key:"thu",label:"T",row:"5"},{key:"fri",label:"F",row:"6"},{key:"sat",label:"S",row:"7"}],x=r(()=>B(new Date)),b=r(()=>{const n=B(x.value);return n.setDate(n.getDate()-364),n}),U=r(()=>`${A(b.value)} - ${A(x.value)}`),p=r(()=>g.heatMetric==="cost"?"spend":"tokens"),k=r(()=>`${U.value} ${p.value} heatmap. Darker cells mean higher daily ${p.value}.`),h=r(()=>`Colored by daily ${p.value}`),w=r(()=>{const n=new Map(g.items.map(a=>[j(V(a.date)),a]));return Array.from({length:365},(a,t)=>{const e=B(b.value);return e.setDate(e.getDate()+t),{date:e,usage:n.get(j(e))}})}),l=r(()=>{const n=Math.max(...w.value.map(a=>g.heatMetric==="cost"?a.usage?.costUSD??0:a.usage?.totalTokens??0));return w.value.map(a=>{const t=a.usage?.costUSD??0,e=a.usage?.totalTokens??0,s=g.heatMetric==="cost"?t:e;return{colorClass:v[F(s,n)],costLabel:C(t),costUSD:t,date:A(a.date),hasUsage:!!a.usage,tokenLabel:y(e),totalTokens:e}})}),L=r(()=>{const n=b.value.getDay(),a=(7-(n+l.value.length)%7)%7,t=Array.from({length:n},(c,d)=>({column:String(Math.floor(d/7)+2),colorClass:"bg-transparent",costLabel:"",date:"",isBlank:!0,key:`blank-${d}`,row:String(d%7+1),title:"No date",tokenLabel:""})),e=l.value.map((c,d)=>({...c,column:String(Math.floor((n+d)/7)+2),isBlank:!1,key:c.date,row:String((n+d)%7+1),title:g.heatMetric==="cost"?`${c.date}: ${C(c.costUSD)} / ${y(c.totalTokens)} tokens`:`${c.date}: ${y(c.totalTokens)} tokens / ${C(c.costUSD)}`})),s=Array.from({length:a},(c,d)=>({column:String(Math.floor((n+l.value.length+d)/7)+2),colorClass:"bg-transparent",costLabel:"",date:"",isBlank:!0,key:`trailing-blank-${d}`,row:String((n+l.value.length+d)%7+1),title:"No date",tokenLabel:""}));return[...t,...e,...s]}),E=r(()=>Math.ceil(L.value.length/7)),G=r(()=>({gridTemplateColumns:`max-content repeat(${E.value}, minmax(0, 1fr))`,gridTemplateRows:"repeat(7, minmax(0, 1fr))"})),N=r(()=>l.value.filter(n=>n.hasUsage).slice(-3)),I=r(()=>l.value.filter(n=>n.hasUsage).length),z=r(()=>C(l.value.reduce((n,a)=>n+a.costUSD,0))),Y=r(()=>y(l.value.reduce((n,a)=>n+a.totalTokens,0))),R=r(()=>g.heatMetric==="cost"?[{key:"year-cost",label:"Year Spend",value:z.value},{key:"year-tokens",label:"Year Tokens",value:Y.value},{key:"active-days",label:"Active Days",value:String(I.value)}]:[{key:"year-tokens",label:"Year Tokens",value:Y.value},{key:"year-cost",label:"Year Spend",value:z.value},{key:"active-days",label:"Active Days",value:String(I.value)}]);function V(n){return new Date(n)}function B(n){return new Date(n.getFullYear(),n.getMonth(),n.getDate())}function j(n){const a=n.getFullYear(),t=`${n.getMonth()+1}`.padStart(2,"0"),e=`${n.getDate()}`.padStart(2,"0");return`${a}-${t}-${e}`}function A(n){return new Intl.DateTimeFormat("en-US",{day:"2-digit",month:"short",year:"numeric"}).format(n)}function F(n,a){return n<=0||a<=0?0:Math.min(9,Math.max(1,Math.ceil(n/a*9)))}return(n,a)=>{const t=W;return u(),X(t,{description:k.value,icon:"lucide:calendar-days",title:g.title},{default:P(()=>[o("div",be,[(u(!0),f($,null,T(R.value,e=>(u(),f("div",{key:e.key,class:"rounded-md border px-3 py-2"},[o("p",ye,m(e.label),1),o("p",ke,m(e.value),1)]))),128))]),o("div",he,[o("div",{class:"grid w-full gap-1",style:H(G.value)},[(u(),f($,null,T(S,e=>o("span",{key:e.key,class:"flex items-center justify-end pr-1 text-[10px] text-muted-foreground",style:H({gridColumn:"1",gridRow:e.row})},m(e.label),5)),64)),(u(!0),f($,null,T(L.value,e=>(u(),f("div",{key:e.key,class:O(["group relative aspect-square w-full max-w-3 justify-self-center rounded-sm border border-black/5 outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring/50 dark:border-white/10",[e.colorClass,{"border-transparent opacity-0":e.isBlank}]]),"aria-label":e.title,style:H({gridColumn:e.column,gridRow:e.row}),tabindex:e.isBlank?-1:0},[o("span",ve,m(e.title),1),e.isBlank?q("",!0):(u(),f("div",xe,[o("span",we,m(e.date),1),g.heatMetric==="tokens"?(u(),f("span",Te,[a[0]||(a[0]=o("span",null,"Tokens",-1)),o("span",$e,m(e.tokenLabel),1)])):q("",!0),o("span",Ce,[a[1]||(a[1]=o("span",null,"Cost",-1)),o("span",De,m(e.costLabel),1)]),g.heatMetric==="cost"?(u(),f("span",Me,[a[2]||(a[2]=o("span",null,"Tokens",-1)),o("span",Se,m(e.tokenLabel),1)])):q("",!0),a[3]||(a[3]=o("span",{class:"absolute top-full left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-r border-b border-border bg-popover"},null,-1))]))],14,_e))),128))],4),o("div",Ue,[o("p",Le,m(h.value),1),o("div",Be,[a[4]||(a[4]=o("span",null,"Less",-1)),(u(),f($,null,T(M,e=>o("span",{key:e,class:O(["size-3 rounded-[2px] border border-black/5 dark:border-white/10",e])},null,2)),64)),a[5]||(a[5]=o("span",null,"More",-1))])])]),o("div",je,[(u(!0),f($,null,T(N.value,e=>(u(),f("div",{key:e.date,class:"rounded-md border px-3 py-2"},[o("p",Ae,m(e.date),1),o("div",Pe,[o("span",Ne,m(g.heatMetric==="cost"?("formatCurrency"in n?n.formatCurrency:i(C))(e.costUSD):("formatCompactNumber"in n?n.formatCompactNumber:i(y))(e.totalTokens)),1),o("span",Ie,m(g.heatMetric==="cost"?("formatCompactNumber"in n?n.formatCompactNumber:i(y))(e.totalTokens):("formatCurrency"in n?n.formatCurrency:i(C))(e.costUSD)),1)])]))),128))])]),_:1},8,["description","title"])}}}),Ee=Object.assign(ze,{__name:"UsageHeatmapPanel"});export{He as _,Oe as a,Ee as b};
|