ccgauge 0.4.0 → 1.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.
Files changed (68) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +42 -42
  3. package/.next/standalone/.next/app-path-routes-manifest.json +7 -7
  4. package/.next/standalone/.next/build-manifest.json +2 -2
  5. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  6. package/.next/standalone/.next/server/app/api/blocks/route.js +1 -1
  7. package/.next/standalone/.next/server/app/api/blocks/route_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/api/export/usage/route.js +1 -1
  9. package/.next/standalone/.next/server/app/api/export/usage/route.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/api/export/usage/route_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/api/pricing/route.js +1 -1
  12. package/.next/standalone/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/api/projects/route.js +1 -1
  14. package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/api/scan/route.js +1 -1
  16. package/.next/standalone/.next/server/app/api/scan/route_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/api/sessions/route.js +1 -1
  18. package/.next/standalone/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/api/usage/route.js +1 -1
  20. package/.next/standalone/.next/server/app/api/usage/route_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/models/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/page.js +2 -2
  23. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/projects/[id]/page_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/projects/page.js +1 -1
  26. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  28. package/.next/standalone/.next/server/app/sessions/page.js +1 -1
  29. package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  30. package/.next/standalone/.next/server/app/settings/page.js +2 -2
  31. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/usage/page.js +2 -2
  33. package/.next/standalone/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app-paths-manifest.json +7 -7
  35. package/.next/standalone/.next/server/chunks/426.js +9 -4
  36. package/.next/standalone/.next/server/chunks/716.js +1 -1
  37. package/.next/standalone/.next/server/chunks/775.js +1 -1
  38. package/.next/standalone/.next/server/functions-config-manifest.json +3 -3
  39. package/.next/standalone/.next/server/pages/500.html +1 -1
  40. package/.next/standalone/.next/static/chunks/148-557ee562aff993b1.js +1 -0
  41. package/.next/standalone/.next/static/chunks/app/{error-89ee9e078058915d.js → error-3e48784f89c5ae8d.js} +1 -1
  42. package/.next/standalone/.next/static/chunks/app/layout-6c973d790f015707.js +1 -0
  43. package/.next/standalone/.next/static/chunks/app/models/page-dff43b9050382020.js +1 -0
  44. package/.next/standalone/.next/static/chunks/app/page-6d87d7a8aa752100.js +1 -0
  45. package/.next/standalone/.next/static/chunks/app/projects/[id]/page-3f812f0e20137f2b.js +1 -0
  46. package/.next/standalone/.next/static/chunks/app/sessions/[id]/page-3f812f0e20137f2b.js +1 -0
  47. package/.next/standalone/.next/static/chunks/app/settings/{page-334168b522eac1b1.js → page-d1af886a5c22af9b.js} +1 -1
  48. package/.next/standalone/.next/static/chunks/app/usage/page-26297e0641d51da8.js +1 -0
  49. package/.next/standalone/.next/static/css/b07523b7c353538d.css +3 -0
  50. package/.next/standalone/node_modules/next/node_modules/postcss/package.json +0 -0
  51. package/.next/standalone/package.json +15 -4
  52. package/CHANGELOG.md +147 -0
  53. package/README.md +41 -2
  54. package/README.zh-CN.md +39 -2
  55. package/bin/cli.mjs +83 -3
  56. package/dist/mcp/server.mjs +71 -29
  57. package/dist/report/index.mjs +2098 -0
  58. package/package.json +26 -17
  59. package/.next/standalone/.next/static/chunks/454-d0e7d0fa6f643c41.js +0 -1
  60. package/.next/standalone/.next/static/chunks/app/layout-a6e30ba3a7f39737.js +0 -1
  61. package/.next/standalone/.next/static/chunks/app/models/page-e0e1b5979547421a.js +0 -1
  62. package/.next/standalone/.next/static/chunks/app/page-9347dfa20dabb24b.js +0 -1
  63. package/.next/standalone/.next/static/chunks/app/projects/[id]/page-5804875e3dc384df.js +0 -1
  64. package/.next/standalone/.next/static/chunks/app/sessions/[id]/page-5804875e3dc384df.js +0 -1
  65. package/.next/standalone/.next/static/chunks/app/usage/page-7789fec27778df9a.js +0 -1
  66. package/.next/standalone/.next/static/css/c34cd36ce5fc39e2.css +0 -3
  67. /package/.next/standalone/.next/static/{w_l54xHgbhALYXmZcmUxC → ZPycmg0NLiIflO5NXMT75}/_buildManifest.js +0 -0
  68. /package/.next/standalone/.next/static/{w_l54xHgbhALYXmZcmUxC → ZPycmg0NLiIflO5NXMT75}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[430],{1189:(e,t,r)=>{"use strict";r.d(t,{V:()=>o});var a=r(95155),n=r(20063),s=r(12115),l=r(25016),i=r(51148);function o(e){let{paramKey:t,defaultValue:r,options:o,ariaLabel:c}=e,d=(0,n.useRouter)(),u=(0,n.usePathname)(),m=(0,n.useSearchParams)(),x=(0,i.kj)(),h=m.get(t)||r,p=o.some(e=>e.value===h)?h:r,b=(0,s.useRef)(null);function g(e){let r=new URLSearchParams(m.toString());r.set(t,e),d.push("".concat(u,"?").concat(r.toString()))}return(0,a.jsx)("div",{ref:b,role:"radiogroup","aria-label":c,onKeyDown:function(e){var t,r;if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;e.preventDefault();let a=(o.findIndex(e=>e.value===p)+("ArrowRight"===e.key?1:-1)+o.length)%o.length;g(o[a].value);let n=null==(t=b.current)?void 0:t.querySelectorAll('button[role="radio"]');null==n||null==(r=n[a])||r.focus()},className:"inline-flex rounded-button border border-border bg-bg-surface p-0.5 gap-0.5",children:o.map(e=>{let t=p===e.value;return(0,a.jsx)("button",{role:"radio","aria-checked":t,tabIndex:t?0:-1,onClick:()=>g(e.value),className:(0,l.cn)("px-2.5 py-1 text-xs rounded transition-all","focus:outline-none focus-visible:ring-2 focus-visible:ring-brand/40",t?"bg-brand text-white font-semibold shadow-sm ring-1 ring-brand/40":"text-text-tertiary font-medium hover:text-text-primary hover:bg-bg-surface-hi"),children:x(e.tk)},e.value)})})}},5248:(e,t,r)=>{"use strict";r.d(t,{OverviewToggle:()=>i});var a=r(95155),n=r(12115),s=r(25016),l=r(51148);function i(){let e=(0,l.kj)(),[t,r]=(0,n.useState)(!1);return(0,n.useEffect)(()=>{r("hidden"===document.documentElement.getAttribute("data-usage-overview"))},[]),(0,a.jsxs)("button",{type:"button",onClick:function(){let e=!t;r(e);try{localStorage.setItem("ccgauge.usage.overview.hidden",e?"1":"0")}catch(e){}e?document.documentElement.setAttribute("data-usage-overview","hidden"):document.documentElement.removeAttribute("data-usage-overview")},"aria-pressed":!t,title:e(t?"usage.overview.show":"usage.overview.hide"),className:(0,s.cn)("inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-button text-xs font-medium","border transition-colors duration-150",t?"border-border bg-bg-surface text-text-secondary hover:text-text-primary hover:bg-bg-surface-hi":"border-brand/40 bg-brand/12 text-brand hover:bg-brand/20 hover:border-brand/60"),children:[(0,a.jsx)(o,{open:!t}),(0,a.jsx)("span",{className:"hidden sm:inline",children:e("usage.overview.label")})]})}function o(e){let{open:t}=e;return(0,a.jsx)("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":!0,children:t?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("path",{d:"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"}),(0,a.jsx)("circle",{cx:"12",cy:"12",r:"3"})]}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("path",{d:"M9.88 9.88a3 3 0 0 0 4.24 4.24"}),(0,a.jsx)("path",{d:"M10.73 5.08A11 11 0 0 1 12 5c6.5 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"}),(0,a.jsx)("path",{d:"M6.61 6.61A13.526 13.526 0 0 0 2 12s3.5 7 10 7a9.74 9.74 0 0 0 5.39-1.61"}),(0,a.jsx)("line",{x1:"2",y1:"2",x2:"22",y2:"22"})]})})}},7152:(e,t,r)=>{"use strict";r.d(t,{RangePicker:()=>i});var a=r(95155),n=r(1189),s=r(51148);let l=[{value:"1d",tk:"range.today"},{value:"7d",tk:"range.7d"},{value:"30d",tk:"range.30d"},{value:"90d",tk:"range.90d"},{value:"all",tk:"range.all"}];function i(e){let{defaultValue:t="7d"}=e,r=(0,s.kj)();return(0,a.jsx)(n.V,{paramKey:"range",defaultValue:t,options:l,ariaLabel:r("range.label")})}},8336:(e,t,r)=>{"use strict";r.d(t,{ModelFilter:()=>i});var a=r(95155),n=r(35850),s=r(25016),l=r(51148);function i(e){let{all:t,selected:r}=e,i=(0,l.kj)();return(0,a.jsx)(n.K,{paramKey:"models",all:t,selected:r,render:s.P6,labelAllKey:"filter.modelAll",labelSingleKey:"filter.modelSingle",labelMultiKey:"filter.modelMulti",ariaLabel:i("filter.modelLabel")})}},14920:(e,t,r)=>{"use strict";r.d(t,{ProjectFilter:()=>i});var a=r(95155),n=r(35850),s=r(25016),l=r(51148);function i(e){let{all:t,selected:r}=e,i=(0,l.kj)();return(0,a.jsx)(n.K,{paramKey:"projects",all:t,selected:r,render:s.PJ,labelAllKey:"filter.projectAll",labelSingleKey:"filter.projectSingle",labelMultiKey:"filter.projectMulti",ariaLabel:i("filter.projectLabel")})}},16633:(e,t,r)=>{"use strict";r.d(t,{GranularityPicker:()=>i});var a=r(95155),n=r(1189),s=r(51148);let l=[{value:"hour",tk:"gran.hour"},{value:"day",tk:"gran.day"},{value:"week",tk:"gran.week"},{value:"month",tk:"gran.month"}];function i(e){let{defaultValue:t="day"}=e,r=(0,s.kj)();return(0,a.jsx)(n.V,{paramKey:"gran",defaultValue:t,options:l,ariaLabel:r("gran.label")})}},20857:(e,t,r)=>{"use strict";r.d(t,{H:()=>l});var a=r(95155),n=r(12115),s=r(25016);function l(e){let{children:t,className:r}=e,l=(0,n.useRef)(null),[i,o]=(0,n.useState)(!1),[c,d]=(0,n.useState)(!1);return(0,n.useEffect)(()=>{let e=l.current;if(!e)return;function t(){if(!e)return;let{scrollLeft:t,scrollWidth:r,clientWidth:a}=e;o(t>4),d(t+a<r-4)}t(),e.addEventListener("scroll",t,{passive:!0});let r=new ResizeObserver(t);return r.observe(e),()=>{e.removeEventListener("scroll",t),r.disconnect()}},[]),(0,a.jsxs)("div",{className:(0,s.cn)("relative",r),children:[(0,a.jsx)("div",{ref:l,className:"overflow-x-auto",children:t}),(0,a.jsx)("div",{"aria-hidden":!0,className:(0,s.cn)("pointer-events-none absolute left-0 top-0 bottom-0 w-8 bg-gradient-to-r from-bg-surface to-transparent transition-opacity duration-150",i?"opacity-100":"opacity-0")}),(0,a.jsx)("div",{"aria-hidden":!0,className:(0,s.cn)("pointer-events-none absolute right-0 top-0 bottom-0 w-8 bg-gradient-to-l from-bg-surface to-transparent transition-opacity duration-150",c?"opacity-100":"opacity-0")})]})}},25016:(e,t,r)=>{"use strict";r.d(t,{BC:()=>x,P6:()=>p,PJ:()=>m,R8:()=>d,az:()=>o,cn:()=>s,jh:()=>i,l7:()=>c,r6:()=>u});var a=r(2821),n=r(75889);function s(){for(var e=arguments.length,t=Array(e),r=0;r<e;r++)t[r]=arguments[r];return(0,n.QP)((0,a.$)(t))}function l(e,t){var r;return new Intl.NumberFormat("en-US",{maximumFractionDigits:null!=(r=null==t?void 0:t.maxFrac)?r:0}).format(e)}function i(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"en";return Number.isFinite(e)?"zh"===t?e>=1e8?(e/1e8).toFixed(2)+"亿":e>=1e4?(e/1e4).toFixed(1)+"万":l(e):e>=1e9?(e/1e9).toFixed(2)+"B":e>=1e6?(e/1e6).toFixed(2)+"M":e>=1e3?(e/1e3).toFixed(1)+"K":l(e):"0"}function o(e,t){var r,a;return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:null!=(r=null==t?void 0:t.minFrac)?r:2,maximumFractionDigits:null!=(a=null==t?void 0:t.maxFrac)?a:2}).format(e)}function c(e){return 0===e?"$0":e<.01?new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:4,maximumFractionDigits:6}).format(e):o(e)}function d(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return Number.isFinite(e)?"".concat((100*e).toFixed(t),"%"):"0%"}function u(e){let t="string"==typeof e||"number"==typeof e?new Date(e):e;if(Number.isNaN(t.getTime()))return"";let r=t.getFullYear(),a=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0"),s=String(t.getHours()).padStart(2,"0"),l=String(t.getMinutes()).padStart(2,"0"),i=String(t.getSeconds()).padStart(2,"0");return"".concat(r,"-").concat(a,"-").concat(n," ").concat(s,":").concat(l,":").concat(i)}function m(e){if(!e)return"(unknown)";let t=e.replace(/[/\\]+$/,"").split(/[/\\]+/);return t[t.length-1]||e}function x(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:8;return e?e.replace(/-/g,"").slice(0,t):""}let h={mini:"Mini",nano:"Nano",pro:"Pro",turbo:"Turbo",preview:"Preview"};function p(e){if(!e)return"(unknown)";let t=e.replace(/^(vertex_ai|bedrock|anthropic|openai)\//,""),r=t.toLowerCase();if(r.startsWith("gpt-")||/^o\d/.test(r))return r.startsWith("gpt-")?"GPT-"+t.slice(4).split("-").map(e=>{var t;return null!=(t=h[e.toLowerCase()])?t:e}).join(" "):t.toUpperCase();let a=t.replace(/-(\d{8})$/,""),n=(a=a.replace(/^claude-/,"")).split("-");if(n.length>=2){let e=n[0],t=n.slice(1).join(".");return b(e)+" "+t}return b(a.replace(/-/g," "))}function b(e){return e.replace(/\b\w/g,e=>e.toUpperCase())}},25577:(e,t,r)=>{"use strict";r.d(t,{UsageTable:()=>h});var a=r(95155),n=r(12115),s=r(20063),l=r(25016),i=r(51148),o=r(47650);function c(e){let{children:t,content:r,className:s,panelClassName:i,align:c="left",delay:d=100,maxWidth:u=360}=e,m=(0,n.useRef)(null),x=(0,n.useRef)(null),h=(0,n.useRef)(null),[p,b]=(0,n.useState)(null),[g,f]=(0,n.useState)(!1),[j,y]=(0,n.useState)(!1);function v(){h.current&&(window.clearTimeout(h.current),h.current=null),j||(x.current=window.setTimeout(()=>{let e=function(){let e,t=m.current;if(!t)return null;let r=t.getBoundingClientRect(),a=Math.min(u,window.innerWidth-16),n=window.innerHeight-r.bottom<200?"top":"bottom";return"right"===c?(e=Math.min(r.right,window.innerWidth-8))-a<8&&(e=a+8):(e=Math.max(r.left,8))+a>window.innerWidth-8&&(e=window.innerWidth-a-8),{x:e,y:"bottom"===n?r.bottom+8:r.top-8,placement:n,align:c}}();e&&(b(e),y(!0))},d))}function w(){x.current&&(window.clearTimeout(x.current),x.current=null),h.current=window.setTimeout(()=>y(!1),80)}return(0,n.useEffect)(()=>f(!0),[]),(0,n.useEffect)(()=>()=>{x.current&&window.clearTimeout(x.current),h.current&&window.clearTimeout(h.current)},[]),(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("span",{ref:m,onMouseEnter:v,onMouseLeave:w,onFocus:v,onBlur:w,className:(0,l.cn)("inline-block",s),children:t}),g&&p&&(0,o.createPortal)((0,a.jsx)("div",{onMouseEnter:()=>{h.current&&(window.clearTimeout(h.current),h.current=null)},onMouseLeave:w,style:{position:"fixed",left:"right"===p.align?void 0:p.x,right:"right"===p.align?window.innerWidth-p.x:void 0,top:"bottom"===p.placement?p.y:void 0,bottom:"top"===p.placement?window.innerHeight-p.y:void 0,maxWidth:u,transform:j?"translateY(0) scale(1)":"bottom"===p.placement?"translateY(-4px) scale(0.98)":"translateY(4px) scale(0.98)",opacity:+!!j,transitionProperty:"opacity, transform",transitionDuration:"120ms",transitionTimingFunction:"cubic-bezier(0.16, 1, 0.3, 1)",transformOrigin:"bottom"===p.placement?"top":"bottom",pointerEvents:j?"auto":"none"},className:(0,l.cn)("z-50 card border-border-hi shadow-xl rounded-button",i),children:r}),document.body)]})}var d=r(20857);let u=[{id:"time",labelKey:"usage.col.time",sortKey:"timestamp",defaultVisible:!0},{id:"prompt",labelKey:"usage.col.userMessage",defaultVisible:!0},{id:"model",labelKey:"usage.col.model",defaultVisible:!0},{id:"project",labelKey:"usage.col.project",defaultVisible:!0},{id:"session",labelKey:"usage.col.session",defaultVisible:!1},{id:"calls",labelKey:"usage.col.calls",align:"right",sortKey:"callCount",defaultVisible:!1},{id:"input",labelKey:"usage.col.input",align:"right",sortKey:"inputTokens",defaultVisible:!1},{id:"output",labelKey:"usage.col.output",align:"right",sortKey:"outputTokens",defaultVisible:!1},{id:"cacheRead",labelKey:"usage.col.cacheRead",align:"right",sortKey:"cacheReadTokens",defaultVisible:!1},{id:"cacheWrite",labelKey:"usage.col.cacheWrite",align:"right",sortKey:"cacheCreationTokens",defaultVisible:!1},{id:"total",labelKey:"usage.col.total",align:"right",sortKey:"totalTokens",defaultVisible:!0},{id:"cost",labelKey:"usage.col.cost",align:"right",sortKey:"cost",defaultVisible:!1},{id:"tools",labelKey:"usage.col.tools",defaultVisible:!0}],m="ccgauge.usage.cols.v3";function x(){return u.reduce((e,t)=>(e[t.id]=t.defaultVisible,e),{})}function h(e){let{rows:t,totalCount:r,page:l,pageCount:o,sort:c,query:h}=e,b=(0,i.kj)(),{locale:f}=(0,i.s9)(),j=(0,s.useRouter)(),y=(0,s.usePathname)(),v=(0,s.useSearchParams)(),[w,N]=(0,n.useState)(new Set),[k,S]=(0,n.useState)(x),[C,K]=(0,n.useState)(!1),[R,T]=(0,n.useState)(h),P=(0,n.useRef)(null),E=(0,n.useRef)(null);function L(e){let t=new URLSearchParams(v.toString());for(let[r,a]of Object.entries(e))void 0===a||""===a?t.delete(r):t.set(r,a);let r=t.toString();j.push(r?"".concat(y,"?").concat(r):y)}function F(e){L({page:e>0?String(e+1):void 0})}(0,n.useEffect)(()=>{S(function(){try{let e=window.localStorage.getItem(m);if(!e)return x();let t=JSON.parse(e),r=x();for(let e of u)"boolean"==typeof t[e.id]&&(r[e.id]=t[e.id]);return r}catch(e){return x()}}())},[]),(0,n.useEffect)(()=>{window.localStorage.setItem(m,JSON.stringify(k))},[k]),(0,n.useEffect)(()=>{T(h)},[h]),(0,n.useEffect)(()=>{function e(e){P.current&&!P.current.contains(e.target)&&K(!1)}return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[]),(0,n.useEffect)(()=>()=>{E.current&&(window.clearTimeout(E.current),E.current=null)},[]);let A=u.filter(e=>k[e.id]),M=A.length+1,I=A.length;return(0,a.jsxs)("div",{children:[(0,a.jsxs)("div",{className:"flex items-center justify-between gap-3 mb-3 flex-wrap",children:[(0,a.jsx)("input",{value:R,onChange:e=>{var t;T(t=e.target.value),E.current&&window.clearTimeout(E.current),E.current=window.setTimeout(()=>{L({q:t.trim()||void 0,page:void 0})},300)},placeholder:b("common.searchPlaceholder"),className:"px-3 py-1.5 text-sm rounded-button border border-border bg-bg-surface focus:outline-none focus:border-border-hi w-72 placeholder:text-text-tertiary text-text-primary"}),(0,a.jsxs)("div",{className:"flex items-center gap-3",children:[(0,a.jsx)("span",{className:"text-xs text-text-tertiary tabular-nums",children:b("common.rows",{count:r.toLocaleString()})}),(0,a.jsxs)("div",{ref:P,className:"relative",children:[(0,a.jsxs)("button",{onClick:()=>K(e=>!e),className:"btn",children:[b("usage.columns.button"),(0,a.jsx)("span",{className:"ml-1 text-text-tertiary tabular-nums",children:I})]}),C&&(0,a.jsxs)("div",{className:"absolute right-0 mt-1 w-56 card border-border-hi shadow-lg p-2 z-30",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between px-1.5 pb-1.5 mb-1 border-b border-border",children:[(0,a.jsx)("span",{className:"text-xs text-text-tertiary uppercase tracking-wide",children:b("usage.columns.title")}),(0,a.jsx)("button",{onClick:()=>S(x()),className:"text-xs text-text-tertiary hover:text-text-primary",children:b("usage.columns.reset")})]}),(0,a.jsx)("div",{className:"max-h-72 overflow-auto",children:u.map(e=>(0,a.jsxs)("label",{className:"flex items-center gap-2 px-1.5 py-1.5 text-sm rounded hover:bg-bg-surface-hi cursor-pointer",children:[(0,a.jsx)("input",{type:"checkbox",checked:!!k[e.id],onChange:t=>S(r=>({...r,[e.id]:t.target.checked})),className:"accent-brand"}),(0,a.jsx)("span",{className:"text-text-secondary",children:b(e.labelKey)})]},e.id))})]})]}),(0,a.jsx)("button",{onClick:function(){let e=new URLSearchParams(v.toString());window.location.href="/api/export/usage?".concat(e.toString())},className:"btn",children:b("common.exportCsv")})]})]}),(0,a.jsx)("div",{className:"card overflow-hidden",children:(0,a.jsx)(d.H,{children:(0,a.jsxs)("table",{className:"w-full text-sm",children:[(0,a.jsx)("thead",{children:(0,a.jsxs)("tr",{className:"border-b border-border bg-bg-surface-hi/30",children:[(0,a.jsx)(g,{children:(0,a.jsx)("span",{className:"sr-only",children:"expand"})}),A.map(e=>(0,a.jsx)(g,{align:e.align,sorted:!!e.sortKey&&c.key===e.sortKey,dir:c.dir,onClick:e.sortKey?()=>{var t;let r;return t=e.sortKey,r="desc",void(c.key===t&&(r="asc"===c.dir?"desc":"asc"),L({sort:"timestamp"===t?void 0:t,dir:"desc"===r?void 0:r,page:void 0}))}:void 0,children:b(e.labelKey)},e.id))]})}),(0,a.jsxs)("tbody",{children:[t.map(e=>{let t=w.has(e.turnId),r=e.userText.trim()||b("usage.turn.noPrompt");return(0,a.jsx)(p,{turn:e,isOpen:t,onToggle:()=>{var t;return t=e.turnId,void N(e=>{let r=new Set(e);return r.has(t)?r.delete(t):r.add(t),r})},userText:r,expandLabel:b("usage.turn.expand"),collapseLabel:b("usage.turn.collapse"),activeColumns:A,locale:f,t:b},e.turnId)}),0===t.length&&(0,a.jsx)("tr",{children:(0,a.jsx)("td",{colSpan:M,className:"px-3 py-8 text-center text-text-tertiary text-sm",children:b("common.noMatchingRows")})})]})]})})}),o>1&&(0,a.jsxs)("div",{className:"flex items-center justify-between mt-3 text-xs text-text-secondary",children:[(0,a.jsx)("span",{children:b("common.pageOf",{page:l+1,total:o})}),(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)("button",{onClick:()=>F(0),disabled:0===l,className:"btn-ghost disabled:opacity-40",children:b("common.first")}),(0,a.jsx)("button",{onClick:()=>F(l-1),disabled:0===l,className:"btn-ghost disabled:opacity-40",children:b("common.prev")}),(0,a.jsx)("button",{onClick:()=>F(l+1),disabled:l>=o-1,className:"btn-ghost disabled:opacity-40",children:b("common.next")}),(0,a.jsx)("button",{onClick:()=>F(o-1),disabled:l>=o-1,className:"btn-ghost disabled:opacity-40",children:b("common.last")})]})]})]})}function p(e){let{turn:t,isOpen:r,onToggle:n,userText:s,expandLabel:i,collapseLabel:o,activeColumns:d,locale:u,t:m}=e,x=(1===t.models.length?(0,l.P6)(t.models[0]):"".concat((0,l.P6)(t.models[0])," +").concat(t.models.length-1))+(t.efforts.length?1===t.efforts.length?" \xb7 ".concat(t.efforts[0]):" \xb7 ".concat(t.efforts[0],"+").concat(t.efforts.length-1):""),h=t.toolNames.length?t.toolNames.slice(0,3).join(", ")+(t.toolNames.length>3?"…":""):"—";return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("tr",{className:"border-b border-border last:border-b-0 hover:bg-bg-surface-hi/40 cursor-pointer",onClick:n,children:[(0,a.jsx)("td",{className:"px-2 py-2 text-text-tertiary w-6 text-center select-none",children:(0,a.jsx)("span",{title:r?o:i,className:"inline-block w-4",children:r?"▾":"▸"})}),d.map(e=>(0,a.jsx)("td",{className:(0,l.cn)("px-3 py-2","right"===e.align?"text-right":"text-left"),children:function(e,t,r,n,s,i,o){switch(e){case"time":return(0,a.jsx)("span",{className:"num-mono text-text-secondary whitespace-nowrap text-xs",children:(0,l.r6)(t.endTimestamp)});case"prompt":return(0,a.jsx)(c,{maxWidth:460,panelClassName:"p-3 text-sm text-text-secondary leading-relaxed",content:(0,a.jsx)("div",{className:"whitespace-pre-wrap break-words",children:s}),children:(0,a.jsx)("span",{className:"block text-text-secondary truncate max-w-[280px]",children:s})});case"model":return(0,a.jsx)("span",{className:"text-text-primary whitespace-nowrap",children:r});case"project":return(0,a.jsx)("span",{className:"block text-text-secondary truncate max-w-[180px]",title:t.cwd,children:t.projectLabel||(0,l.PJ)(t.cwd)});case"session":return(0,a.jsx)("span",{className:"num-mono text-text-tertiary text-xs",title:t.sessionId,children:(0,l.BC)(t.sessionId)});case"calls":return(0,a.jsx)("span",{className:"num-mono text-text-secondary",children:t.callCount});case"input":return(0,a.jsx)("span",{className:"num-mono text-text-secondary",children:(0,l.jh)(t.inputTokens,i)});case"output":return(0,a.jsx)("span",{className:"num-mono text-text-secondary",children:(0,l.jh)(t.outputTokens,i)});case"cacheRead":return(0,a.jsx)("span",{className:"num-mono text-success",children:(0,l.jh)(t.cacheReadTokens,i)});case"cacheWrite":return(0,a.jsx)("span",{className:"num-mono text-text-secondary",children:(0,l.jh)(t.cacheCreationTokens,i)});case"total":return(0,a.jsx)(c,{align:"right",maxWidth:300,panelClassName:"p-0 overflow-hidden",content:(0,a.jsx)(b,{row:t,locale:i,t:o}),children:(0,a.jsx)("span",{className:"num-mono text-text-primary font-medium border-b border-dashed border-border hover:border-text-tertiary cursor-help",children:(0,l.jh)(t.totalTokens,i)})});case"cost":return(0,a.jsx)("span",{className:"num-mono text-text-primary font-medium",children:(0,l.l7)(t.cost)});case"tools":return(0,a.jsx)("span",{className:"block text-xs text-text-tertiary truncate max-w-[160px]",title:t.toolNames.join(", "),children:n})}}(e.id,t,x,h,s,u,m)},e.id))]}),r&&t.children.map(e=>(0,a.jsxs)("tr",{className:"border-b border-border last:border-b-0 bg-bg-surface-hi/20 text-text-tertiary",children:[(0,a.jsx)("td",{className:"px-2 py-1.5 w-6"}),d.map(r=>(0,a.jsx)("td",{className:(0,l.cn)("px-3 py-1.5","right"===r.align?"text-right":"text-left"),children:function(e,t,r,n,s){switch(e){case"time":return(0,a.jsx)("span",{className:"num-mono whitespace-nowrap pl-5 text-xs",children:(0,l.r6)(t.timestamp)});case"prompt":{var i;let e=(null!=(i=t.directPrompt)?i:"").trim();if(e&&e!==r.trim())return(0,a.jsx)("span",{className:"block text-xs text-text-secondary truncate max-w-[320px]",title:e,children:e});if(!t.toolNames.length)return(0,a.jsx)("span",{className:"text-xs text-text-tertiary",children:"—"});let n=t.toolNames.join(", "),s=t.toolNames.slice(0,3).join(", ")+(t.toolNames.length>3?"…":"");return(0,a.jsx)("span",{className:"block text-xs text-text-secondary truncate max-w-[280px]",title:n,children:s})}case"model":return(0,a.jsxs)("span",{className:"whitespace-nowrap",children:[(0,l.P6)(t.model),t.effort?" \xb7 ".concat(t.effort):""]});case"project":return(0,a.jsx)("span",{className:"block truncate max-w-[180px]",title:t.cwd,children:t.projectLabel||(0,l.PJ)(t.cwd)});case"session":return(0,a.jsx)("span",{className:"num-mono text-xs",title:t.sessionId,children:(0,l.BC)(t.sessionId)});case"calls":return(0,a.jsx)("span",{className:"num-mono",children:"1"});case"input":return(0,a.jsx)("span",{className:"num-mono",children:(0,l.jh)(t.inputTokens,n)});case"output":return(0,a.jsx)("span",{className:"num-mono",children:(0,l.jh)(t.outputTokens,n)});case"cacheRead":return(0,a.jsx)("span",{className:"num-mono text-success",children:(0,l.jh)(t.cacheReadTokens,n)});case"cacheWrite":return(0,a.jsx)("span",{className:"num-mono",children:(0,l.jh)(t.cacheCreationTokens,n)});case"total":return(0,a.jsx)(c,{align:"right",maxWidth:300,panelClassName:"p-0 overflow-hidden",content:(0,a.jsx)(b,{row:t,locale:n,t:s}),children:(0,a.jsx)("span",{className:"num-mono border-b border-dashed border-border/60 hover:border-text-tertiary cursor-help",children:(0,l.jh)(t.totalTokens,n)})});case"cost":return(0,a.jsx)("span",{className:"num-mono",children:(0,l.l7)(t.cost)});case"tools":return(0,a.jsx)("span",{className:"block text-xs truncate max-w-[160px]",title:t.toolNames.join(", "),children:t.toolNames.length?t.toolNames.join(", "):"—"})}}(r.id,e,t.userText,u,m)},r.id))]},e.uuid))]})}function b(e){let{row:t,locale:r,t:s}=e,i=[{key:"input",label:s("usage.col.input"),tokens:t.inputTokens,cost:t.costInput,tone:"text-text-primary",dot:"bg-chart-input"},{key:"output",label:s("usage.col.output"),tokens:t.outputTokens,cost:t.costOutput,tone:"text-text-primary",dot:"bg-chart-output"},{key:"cacheRead",label:s("usage.col.cacheRead"),tokens:t.cacheReadTokens,cost:t.costCacheRead,tone:"text-success",dot:"bg-chart-cache-read"},{key:"cacheWrite",label:s("usage.col.cacheWrite"),tokens:t.cacheCreationTokens,cost:t.costCacheWrite,tone:"text-text-primary",dot:"bg-chart-cache-create"}];return(0,a.jsxs)("div",{className:"text-xs",children:[(0,a.jsx)("div",{className:"px-3 py-2 border-b border-border bg-bg-surface-hi/40 text-text-tertiary uppercase tracking-wide font-medium",children:s("usage.breakdown.title")}),(0,a.jsxs)("div",{className:"px-3 py-2",children:[(0,a.jsxs)("div",{className:"grid grid-cols-[auto_1fr_auto] gap-x-3 gap-y-1.5 items-center",children:[(0,a.jsx)("span",{}),(0,a.jsx)("span",{className:"text-text-tertiary text-[10px] uppercase tracking-wide text-right",children:s("usage.breakdown.headerTokens")}),(0,a.jsx)("span",{className:"text-text-tertiary text-[10px] uppercase tracking-wide text-right",children:s("usage.breakdown.headerCost")}),i.map(e=>(0,a.jsxs)(n.Fragment,{children:[(0,a.jsxs)("span",{className:"inline-flex items-center gap-2 text-text-secondary",children:[(0,a.jsx)("span",{className:(0,l.cn)("w-2 h-2 rounded-sm",e.dot)}),e.label]}),(0,a.jsx)("span",{className:(0,l.cn)("num-mono text-right",e.tone),children:(0,l.jh)(e.tokens,r)}),(0,a.jsx)("span",{className:"num-mono text-right text-text-secondary",children:(0,l.l7)(e.cost)}),"output"===e.key&&t.reasoningTokens>0&&(0,a.jsxs)(n.Fragment,{children:[(0,a.jsxs)("span",{className:"inline-flex items-center gap-2 text-text-tertiary pl-4 text-[11px]",children:[(0,a.jsx)("span",{className:"text-text-tertiary",children:"↳"}),s("usage.breakdown.reasoning")]}),(0,a.jsx)("span",{className:"num-mono text-right text-text-tertiary text-[11px]",children:(0,l.jh)(t.reasoningTokens,r)}),(0,a.jsx)("span",{className:"text-right text-text-tertiary text-[11px]",children:s("usage.breakdown.reasoningNote")})]},"reasoning-detail")]},e.key))]}),(0,a.jsxs)("div",{className:"mt-2 pt-2 border-t border-border grid grid-cols-[auto_1fr_auto] gap-x-3 items-center",children:[(0,a.jsx)("span",{className:"text-text-secondary font-medium",children:s("usage.breakdown.total")}),(0,a.jsx)("span",{className:"num-mono text-right text-text-primary font-medium",children:(0,l.jh)(t.totalTokens,r)}),(0,a.jsx)("span",{className:"num-mono text-right text-text-primary font-medium",children:(0,l.l7)(t.cost)})]})]})]})}function g(e){let{children:t,align:r="left",sorted:n,dir:s,onClick:i}=e;return(0,a.jsx)("th",{className:(0,l.cn)("px-3 py-2 text-xs font-medium text-text-tertiary uppercase tracking-wide whitespace-nowrap","right"===r?"text-right":"text-left",i&&"cursor-pointer hover:text-text-primary select-none"),onClick:i,children:(0,a.jsxs)("span",{className:"inline-flex items-center gap-1",children:[t,n&&(0,a.jsx)("span",{className:"text-[10px]",children:"asc"===s?"▲":"▼"})]})})}},35850:(e,t,r)=>{"use strict";r.d(t,{K:()=>o});var a=r(95155),n=r(20063),s=r(12115),l=r(25016),i=r(51148);function o(e){let t,{paramKey:r,all:o,selected:c,render:d=e=>e,labelAllKey:u,labelSingleKey:m,labelMultiKey:x,ariaLabel:h,searchThreshold:p=6}=e,b=(0,n.useRouter)(),g=(0,n.usePathname)(),f=(0,n.useSearchParams)(),j=(0,i.kj)(),[y,v]=(0,s.useState)(!1),[w,N]=(0,s.useState)(""),[k,S]=(0,s.useState)(0),C=(0,s.useRef)(null),K=(0,s.useRef)(null),R=(0,s.useRef)(null),T=(0,s.useRef)(null),P=(0,s.useId)(),E=(0,s.useId)();(0,s.useEffect)(()=>{if(y)return document.addEventListener("mousedown",e),document.addEventListener("keydown",t),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("keydown",t)};function e(e){C.current&&!C.current.contains(e.target)&&v(!1)}function t(e){if("Escape"===e.key){var t;v(!1),null==(t=K.current)||t.focus()}}},[y]),(0,s.useEffect)(()=>{y&&o.length>=p&&requestAnimationFrame(()=>{var e;return null==(e=R.current)?void 0:e.focus()}),y||(N(""),S(0))},[y,o.length,p]);let L=(0,s.useMemo)(()=>{let e=w.trim().toLowerCase();return e?o.filter(t=>d(t).toLowerCase().includes(e)||t.toLowerCase().includes(e)):o},[o,w,d]);function F(e){let t=new URLSearchParams(f.toString());0===e.size?t.delete(r):t.set(r,Array.from(e).join(","));let a=t.toString();b.push(a?"".concat(g,"?").concat(a):g)}function A(e){let t=new Set(c);t.has(e)?t.delete(e):t.add(e),F(t)}function M(e){if("ArrowDown"===e.key)e.preventDefault(),S(e=>Math.min(L.length-1,e+1));else if("ArrowUp"===e.key)e.preventDefault(),S(e=>Math.max(0,e-1));else if("Enter"===e.key){e.preventDefault();let t=L[k];t&&A(t)}else"Home"===e.key?(e.preventDefault(),S(0)):"End"===e.key&&(e.preventDefault(),S(L.length-1))}t=0===c.length?j(u):1===c.length?j(m,{value:d(c[0])}):j(x,{count:c.length});let I=o.length>=p;return(0,a.jsxs)("div",{ref:C,className:"relative",children:[(0,a.jsxs)("button",{ref:K,id:P,onClick:()=>v(e=>!e),className:"btn focus:outline-none focus-visible:ring-2 focus-visible:ring-brand/40","aria-haspopup":"listbox","aria-expanded":y,"aria-controls":E,"aria-label":h,children:[t,(0,a.jsx)("span",{className:"text-text-tertiary ml-1","aria-hidden":!0,children:"▾"})]}),y&&(0,a.jsxs)("div",{id:E,role:"listbox","aria-multiselectable":"true","aria-labelledby":P,className:"absolute right-0 mt-1 w-72 card border-border-hi shadow-lg z-20 overflow-hidden",children:[c.length>0&&(0,a.jsxs)("div",{className:"px-2 pt-2 pb-1.5 border-b border-border flex flex-wrap gap-1 items-center",children:[c.slice(0,6).map(e=>(0,a.jsxs)("button",{onClick:()=>A(e),className:"inline-flex items-center gap-1 max-w-[160px] pl-2 pr-1.5 py-0.5 text-[11px] rounded-full bg-brand/10 text-brand border border-brand/20 hover:bg-brand/15","aria-label":"Remove ".concat(d(e)),title:d(e),children:[(0,a.jsx)("span",{className:"truncate",children:d(e)}),(0,a.jsx)("span",{"aria-hidden":!0,className:"text-brand/70",children:"\xd7"})]},e)),c.length>6&&(0,a.jsxs)("span",{className:"text-[11px] text-text-tertiary px-1",children:["+",c.length-6]}),(0,a.jsx)("button",{onClick:function(){F(new Set)},className:"ml-auto text-[11px] text-text-tertiary hover:text-text-primary px-1.5 py-0.5",children:j("filter.clearAll")})]}),I&&(0,a.jsx)("div",{className:"p-2 border-b border-border",children:(0,a.jsx)("input",{ref:R,value:w,onChange:e=>{N(e.target.value),S(0)},onKeyDown:e=>{("ArrowDown"===e.key||"ArrowUp"===e.key||"Enter"===e.key||"Home"===e.key||"End"===e.key)&&M(e)},placeholder:j("common.searchPlaceholder"),className:"w-full px-2 py-1 text-sm rounded border border-border bg-bg-surface focus:outline-none focus:border-border-hi placeholder:text-text-tertiary text-text-primary"})}),(0,a.jsxs)("div",{ref:T,onKeyDown:M,className:"max-h-64 overflow-y-auto p-1 outline-none",tabIndex:-1,children:[0===L.length&&(0,a.jsx)("div",{className:"text-xs text-text-tertiary px-2 py-3 text-center",children:j("filter.noOptions")}),L.map((e,t)=>{let r=c.includes(e),n=t===k;return(0,a.jsxs)("button",{role:"option","aria-selected":r,onMouseEnter:()=>S(t),onClick:()=>A(e),className:(0,l.cn)("w-full text-left text-sm px-2 py-1.5 rounded flex items-center gap-2 transition-colors",n?"bg-bg-surface-hi":"hover:bg-bg-surface-hi",r&&"text-text-primary"),children:[(0,a.jsx)("span",{className:(0,l.cn)("w-3.5 h-3.5 rounded-sm border flex items-center justify-center text-[10px] flex-shrink-0",r?"bg-brand border-brand text-white":"border-border-hi"),"aria-hidden":!0,children:r?"✓":""}),(0,a.jsx)("span",{className:"truncate",children:d(e)})]},e)})]})]})]})}},36392:(e,t,r)=>{Promise.resolve().then(r.bind(r,77549)),Promise.resolve().then(r.bind(r,38059)),Promise.resolve().then(r.bind(r,16633)),Promise.resolve().then(r.bind(r,8336)),Promise.resolve().then(r.bind(r,5248)),Promise.resolve().then(r.bind(r,14920)),Promise.resolve().then(r.bind(r,7152)),Promise.resolve().then(r.bind(r,25577))},38059:(e,t,r)=>{"use strict";r.d(t,{TokenStackChart:()=>h});var a=r(95155),n=r(26991),s=r(94632),l=r(68425),i=r(47734),o=r(73697),c=r(23508),d=r(26736),u=r(25016),m=r(51148);let x={input:"rgb(var(--chart-input))",output:"rgb(var(--chart-output))",cacheRead:"rgb(var(--chart-cache-read))",cacheCreation:"rgb(var(--chart-cache-create))"};function h(e){let{data:t,height:r="h-72"}=e,h=(0,m.kj)(),{locale:g}=(0,m.s9)();return t.length?(0,a.jsxs)("div",{className:"".concat(r," w-full"),children:[(0,a.jsx)(n.u,{width:"100%",height:"100%",children:(0,a.jsxs)(s.E,{data:t,margin:{top:12,right:8,bottom:4,left:8},barCategoryGap:"22%",children:[(0,a.jsx)(l.d,{stroke:"rgb(var(--chart-grid))",strokeOpacity:.6,strokeDasharray:"3 3",vertical:!1}),(0,a.jsx)(i.W,{dataKey:"label",tick:{fill:"rgb(var(--chart-axis))",fontSize:11},tickLine:!1,axisLine:!1,interval:"preserveStartEnd",minTickGap:32,tickMargin:8}),(0,a.jsx)(o.h,{tickFormatter:e=>(0,u.jh)(Number(e),g),tick:{fill:"rgb(var(--chart-axis))",fontSize:11},tickLine:!1,axisLine:!1,width:56,tickMargin:4}),(0,a.jsx)(c.m,{content:(0,a.jsx)(b,{}),cursor:{fill:"rgb(var(--text-primary) / 0.05)",radius:4}}),(0,a.jsx)(d.y,{dataKey:"input",stackId:"a",fill:x.input,isAnimationActive:!1}),(0,a.jsx)(d.y,{dataKey:"cacheCreation",stackId:"a",fill:x.cacheCreation,isAnimationActive:!1}),(0,a.jsx)(d.y,{dataKey:"cacheRead",stackId:"a",fill:x.cacheRead,isAnimationActive:!1}),(0,a.jsx)(d.y,{dataKey:"output",stackId:"a",fill:x.output,radius:[4,4,0,0],isAnimationActive:!1})]})}),(0,a.jsxs)("div",{className:"flex items-center flex-wrap justify-center gap-4 text-xs text-text-secondary mt-2",children:[(0,a.jsx)(p,{color:x.input,label:h("chart.legend.input")}),(0,a.jsx)(p,{color:x.cacheCreation,label:h("chart.legend.cacheWrite")}),(0,a.jsx)(p,{color:x.cacheRead,label:h("chart.legend.cacheRead")}),(0,a.jsx)(p,{color:x.output,label:h("chart.legend.output")})]})]}):(0,a.jsx)("div",{className:"".concat(r," flex items-center justify-center text-text-tertiary text-sm"),children:h("chart.empty")})}function p(e){let{color:t,label:r}=e;return(0,a.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:[(0,a.jsx)("span",{className:"w-2.5 h-2.5 rounded-sm",style:{background:t}}),(0,a.jsx)("span",{children:r})]})}function b(e){let t=(0,m.kj)(),{locale:r}=(0,m.s9)();if(!e.active||!e.payload||!e.payload.length)return null;let n=e.payload[0].payload,s=n.input+n.output+n.cacheRead+n.cacheCreation;return(0,a.jsxs)("div",{className:"card-elevated border border-border-hi rounded-card p-3 text-xs min-w-[200px]",children:[(0,a.jsx)("div",{className:"font-medium text-text-primary mb-2",children:e.label}),(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)(g,{color:x.input,label:t("chart.legend.input"),value:n.input,locale:r}),(0,a.jsx)(g,{color:x.cacheCreation,label:t("chart.legend.cacheWrite"),value:n.cacheCreation,locale:r}),(0,a.jsx)(g,{color:x.cacheRead,label:t("chart.legend.cacheRead"),value:n.cacheRead,locale:r}),(0,a.jsx)(g,{color:x.output,label:t("chart.legend.output"),value:n.output,locale:r})]}),(0,a.jsxs)("div",{className:"mt-2 pt-2 border-t border-border flex items-center justify-between",children:[(0,a.jsx)("span",{className:"text-text-secondary",children:t("chart.tooltip.total")}),(0,a.jsx)("span",{className:"num-mono text-text-primary",children:(0,u.jh)(s,r)})]}),(0,a.jsxs)("div",{className:"flex items-center justify-between mt-1",children:[(0,a.jsx)("span",{className:"text-text-secondary",children:t("chart.tooltip.cost")}),(0,a.jsx)("span",{className:"num-mono text-brand",children:(0,u.az)(n.cost)})]}),(0,a.jsxs)("div",{className:"flex items-center justify-between mt-1",children:[(0,a.jsx)("span",{className:"text-text-secondary",children:t("chart.tooltip.requests")}),(0,a.jsx)("span",{className:"num-mono text-text-primary",children:n.requests})]})]})}function g(e){let{color:t,label:r,value:n,locale:s}=e;return(0,a.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,a.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-text-secondary",children:[(0,a.jsx)("span",{className:"w-2 h-2 rounded-sm",style:{background:t}}),r]}),(0,a.jsx)("span",{className:"num-mono text-text-primary",children:(0,u.jh)(n,s)})]})}},77549:(e,t,r)=>{"use strict";r.d(t,{AutoRefresh:()=>s});var a=r(12115),n=r(20063);function s(e){let{intervalMs:t=15e3}=e,r=(0,n.useRouter)(),s=(0,a.useRef)(!1);return(0,a.useEffect)(()=>{if(t<=0)return;let e=null;function a(){if(!document.hidden&&!s.current){s.current=!0;try{r.refresh()}finally{Promise.resolve().then(()=>{s.current=!1})}}}return e=window.setInterval(a,t),document.addEventListener("visibilitychange",a),()=>{null!==e&&window.clearInterval(e),document.removeEventListener("visibilitychange",a)}},[r,t]),null}}},e=>{e.O(0,[760,930,148,441,255,358],()=>e(e.s=36392)),_N_E=e.O()}]);
@@ -0,0 +1,3 @@
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246/0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246/0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*
2
+ ! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
3
+ */*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-sans),ui-sans-serif,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:var(--font-mono),ui-monospace,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.card{border-radius:12px;border-width:1px;--tw-border-opacity:1;border-color:rgb(var(--border)/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(var(--bg-surface)/var(--tw-bg-opacity,1));box-shadow:var(--shadow-card)}.card-elevated{background:rgb(var(--bg-elevated));box-shadow:var(--shadow-popover)}.card-pad{padding:1.25rem}@media (min-width:640px){.card-pad{padding:1.5rem}}.label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;--tw-text-opacity:1;color:rgb(var(--text-tertiary)/var(--tw-text-opacity,1))}.num-hero{overflow-wrap:break-word;font-size:1.875rem;line-height:2.25rem;font-weight:600;--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);letter-spacing:-.025em;--tw-text-opacity:1;color:rgb(var(--text-primary)/var(--tw-text-opacity,1))}@media (min-width:640px){.num-hero{font-size:2rem;line-height:2.25rem}}.num-mid{font-size:1.5rem;line-height:2rem;font-weight:600;--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);--tw-text-opacity:1;color:rgb(var(--text-primary)/var(--tw-text-opacity,1))}.num-mono{font-family:var(--font-mono),ui-monospace,monospace;--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.pill{display:inline-flex;align-items:center;border-radius:8px;padding:.125rem .5rem;font-size:.75rem;font-weight:500;line-height:1.25rem}.pill-muted{padding:.125rem .5rem;font-size:.75rem;background-color:rgb(var(--bg-surface-hi)/var(--tw-bg-opacity,1));color:rgb(var(--text-secondary)/var(--tw-text-opacity,1))}.btn,.pill-muted{display:inline-flex;align-items:center;border-radius:8px;font-weight:500;line-height:1.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(var(--border)/var(--tw-border-opacity,1));--tw-bg-opacity:1;--tw-text-opacity:1}.btn{justify-content:center;gap:.375rem;background-color:rgb(var(--bg-surface)/var(--tw-bg-opacity,1));padding:.375rem .75rem;font-size:.875rem;color:rgb(var(--text-primary)/var(--tw-text-opacity,1));transition:background-color .15s,border-color .15s,color .15s,transform .1s,box-shadow .15s}.btn:hover:not(:disabled){background:rgb(var(--bg-surface-hi));border-color:rgb(var(--border-hi))}.btn:active:not(:disabled){transform:translateY(1px)}.btn:disabled{cursor:not-allowed;opacity:.5}.btn-ghost{display:inline-flex;align-items:center;justify-content:center;gap:.375rem;border-radius:8px;padding:.375rem .75rem;font-size:.875rem;line-height:1.25rem;font-weight:500;--tw-text-opacity:1;color:rgb(var(--text-secondary)/var(--tw-text-opacity,1));transition:background-color .15s,color .15s}.btn-ghost:hover:not(:disabled){color:rgb(var(--text-primary));background:rgb(var(--bg-surface-hi))}.btn-ghost:disabled{cursor:not-allowed;opacity:.4}.section-header{background:linear-gradient(to bottom,rgb(var(--bg-surface)) 0,rgb(var(--bg-surface-hi)/.4) 100%)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.\!visible{visibility:visible!important}.visible{visibility:visible}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.-bottom-\[12px\]{bottom:-12px}.bottom-0{bottom:0}.left-0{left:0}.left-2{left:.5rem}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-1{margin-left:.25rem}.ml-1\.5{margin-left:.375rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-auto{margin-top:auto}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.\!hidden{display:none!important}.hidden{display:none}.aspect-square{aspect-ratio:1/1}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-72{height:18rem}.h-8{height:2rem}.h-\[2px\]{height:2px}.h-\[3px\]{height:3px}.h-full{height:100%}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-72{max-height:18rem}.min-h-\[132px\]{min-height:132px}.min-h-\[180px\]{min-height:180px}.min-h-\[280px\]{min-height:280px}.min-h-\[64px\]{min-height:64px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-24{width:6rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[120px\]{min-width:120px}.min-w-\[180px\]{min-width:180px}.min-w-\[200px\]{min-width:200px}.min-w-\[80px\]{min-width:80px}.max-w-2xl{max-width:42rem}.max-w-7xl{max-width:80rem}.max-w-\[160px\]{max-width:160px}.max-w-\[180px\]{max-width:180px}.max-w-\[280px\]{max-width:280px}.max-w-\[320px\]{max-width:320px}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.grid-cols-\[auto_1fr_auto\]{grid-template-columns:auto 1fr auto}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-\[3px\]{gap:3px}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-0\.5{row-gap:.125rem}.gap-y-1\.5{row-gap:.375rem}.gap-y-\[3px\]{row-gap:3px}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-3\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.875rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.875rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-\[3px\]{border-radius:3px}.rounded-button{border-radius:8px}.rounded-card{border-radius:12px}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-border{--tw-border-opacity:1;border-color:rgb(var(--border)/var(--tw-border-opacity,1))}.border-border-hi{--tw-border-opacity:1;border-color:rgb(var(--border-hi)/var(--tw-border-opacity,1))}.border-border\/60{border-color:rgb(var(--border)/.6)}.border-brand{--tw-border-opacity:1;border-color:rgb(var(--brand)/var(--tw-border-opacity,1))}.border-brand\/20{border-color:rgb(var(--brand)/.2)}.border-brand\/40{border-color:rgb(var(--brand)/.4)}.border-danger\/20{border-color:rgb(var(--danger)/.2)}.border-success\/20{border-color:rgb(var(--success)/.2)}.border-warning\/20{border-color:rgb(var(--warning)/.2)}.bg-bg{--tw-bg-opacity:1;background-color:rgb(var(--bg-base)/var(--tw-bg-opacity,1))}.bg-bg-surface{--tw-bg-opacity:1;background-color:rgb(var(--bg-surface)/var(--tw-bg-opacity,1))}.bg-bg-surface-hi{--tw-bg-opacity:1;background-color:rgb(var(--bg-surface-hi)/var(--tw-bg-opacity,1))}.bg-bg-surface-hi\/20{background-color:rgb(var(--bg-surface-hi)/.2)}.bg-bg-surface-hi\/30{background-color:rgb(var(--bg-surface-hi)/.3)}.bg-bg-surface-hi\/40{background-color:rgb(var(--bg-surface-hi)/.4)}.bg-bg-surface-hi\/60{background-color:rgb(var(--bg-surface-hi)/.6)}.bg-brand{--tw-bg-opacity:1;background-color:rgb(var(--brand)/var(--tw-bg-opacity,1))}.bg-brand\/10{background-color:rgb(var(--brand)/.1)}.bg-chart-cache-create{--tw-bg-opacity:1;background-color:rgb(var(--chart-cache-create)/var(--tw-bg-opacity,1))}.bg-chart-cache-create\/15{background-color:rgb(var(--chart-cache-create)/.15)}.bg-chart-cache-read{--tw-bg-opacity:1;background-color:rgb(var(--chart-cache-read)/var(--tw-bg-opacity,1))}.bg-chart-input{--tw-bg-opacity:1;background-color:rgb(var(--chart-input)/var(--tw-bg-opacity,1))}.bg-chart-output{--tw-bg-opacity:1;background-color:rgb(var(--chart-output)/var(--tw-bg-opacity,1))}.bg-danger{--tw-bg-opacity:1;background-color:rgb(var(--danger)/var(--tw-bg-opacity,1))}.bg-danger\/10{background-color:rgb(var(--danger)/.1)}.bg-success{--tw-bg-opacity:1;background-color:rgb(var(--success)/var(--tw-bg-opacity,1))}.bg-success\/10{background-color:rgb(var(--success)/.1)}.bg-warning{--tw-bg-opacity:1;background-color:rgb(var(--warning)/var(--tw-bg-opacity,1))}.bg-warning\/10{background-color:rgb(var(--warning)/.1)}.bg-gradient-to-l{background-image:linear-gradient(to left,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-bg-surface{--tw-gradient-from:rgb(var(--bg-surface)/1) var(--tw-gradient-from-position);--tw-gradient-to:rgb(var(--bg-surface)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-brand{--tw-gradient-from:rgb(var(--brand)/1) var(--tw-gradient-from-position);--tw-gradient-to:rgb(var(--brand)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-brand\/0{--tw-gradient-from:rgb(var(--brand)/0) var(--tw-gradient-from-position);--tw-gradient-to:rgb(var(--brand)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-success\/0{--tw-gradient-from:rgb(var(--success)/0) var(--tw-gradient-from-position);--tw-gradient-to:rgb(var(--success)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-warning\/0{--tw-gradient-from:rgb(var(--warning)/0) var(--tw-gradient-from-position);--tw-gradient-to:rgb(var(--warning)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-brand\/70{--tw-gradient-to:rgb(var(--brand)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgb(var(--brand)/0.7) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-success\/70{--tw-gradient-to:rgb(var(--success)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgb(var(--success)/0.7) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-warning\/70{--tw-gradient-to:rgb(var(--warning)/0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgb(var(--warning)/0.7) var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-brand-hover{--tw-gradient-to:rgb(var(--brand-hover)/1) var(--tw-gradient-to-position)}.to-brand\/0{--tw-gradient-to:rgb(var(--brand)/0) var(--tw-gradient-to-position)}.to-success\/0{--tw-gradient-to:rgb(var(--success)/0) var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.to-warning\/0{--tw-gradient-to:rgb(var(--warning)/0) var(--tw-gradient-to-position)}.fill-brand{fill:rgb(var(--brand)/1)}.fill-white{fill:#fff}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-5{padding:1.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1\.5{padding-bottom:.375rem}.pb-3{padding-bottom:.75rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pr-1\.5{padding-right:.375rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-\[18px\]{padding-top:18px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[15px\]{font-size:15px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[0\.06em\]{letter-spacing:.06em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-brand{--tw-text-opacity:1;color:rgb(var(--brand)/var(--tw-text-opacity,1))}.text-brand\/70{color:rgb(var(--brand)/.7)}.text-chart-cache-create{--tw-text-opacity:1;color:rgb(var(--chart-cache-create)/var(--tw-text-opacity,1))}.text-danger{--tw-text-opacity:1;color:rgb(var(--danger)/var(--tw-text-opacity,1))}.text-success{--tw-text-opacity:1;color:rgb(var(--success)/var(--tw-text-opacity,1))}.text-text-primary{--tw-text-opacity:1;color:rgb(var(--text-primary)/var(--tw-text-opacity,1))}.text-text-secondary{--tw-text-opacity:1;color:rgb(var(--text-secondary)/var(--tw-text-opacity,1))}.text-text-tertiary{--tw-text-opacity:1;color:rgb(var(--text-tertiary)/var(--tw-text-opacity,1))}.text-warning{--tw-text-opacity:1;color:rgb(var(--warning)/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.accent-brand{accent-color:rgb(var(--brand)/1)}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0/0.1),0 4px 6px -4px rgb(0 0 0/0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgb(0 0 0/0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgb(0 0 0/0.1),0 8px 10px -6px rgb(0 0 0/0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-brand\/40{--tw-ring-color:rgb(var(--brand)/0.4)}.ring-white\/40{--tw-ring-color:rgb(255 255 255/0.4)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-filter{backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-500{transition-duration:.5s}.ease-out-soft{transition-timing-function:cubic-bezier(.16,1,.3,1)}.\[ccgauge\:api\]{ccgauge:api}.\[ccgauge\:indexer\]{ccgauge:indexer}.\[grid-template-columns\:auto_1fr\]{grid-template-columns:auto 1fr}.\[grid-template-columns\:repeat\(24\2c minmax\(0\2c 1fr\)\)\]{grid-template-columns:repeat(24,minmax(0,1fr))}.theme-dark,:root{--bg-base:10 10 10;--bg-surface:22 22 22;--bg-surface-hi:32 32 34;--bg-elevated:38 38 42;--border:38 38 42;--border-hi:64 64 70;--text-primary:250 250 250;--text-secondary:168 168 174;--text-tertiary:120 120 128;--brand:129 140 248;--brand-hover:165 180 252;--success:34 197 94;--warning:250 204 21;--danger:248 113 113;--chart-input:96 165 250;--chart-output:251 146 60;--chart-cache-read:52 211 153;--chart-cache-create:167 139 250;--chart-grid:38 38 42;--chart-axis:120 120 128;--shadow-card:0 1px 0 0 rgb(255 255 255/0.02),0 4px 12px -4px rgb(0 0 0/0.4);--shadow-card-hover:0 1px 0 0 rgb(255 255 255/0.04),0 8px 24px -8px rgb(0 0 0/0.6);--shadow-popover:0 4px 12px -2px rgb(0 0 0/0.4),0 16px 48px -8px rgb(0 0 0/0.6);--ring-focus:129 140 248}.theme-light{--bg-base:252 252 253;--bg-surface:255 255 255;--bg-surface-hi:247 247 249;--bg-elevated:250 250 252;--border:226 226 232;--border-hi:200 200 208;--text-primary:17 17 23;--text-secondary:82 82 91;--text-tertiary:145 145 156;--brand:79 70 229;--brand-hover:67 56 202;--success:22 163 74;--warning:217 119 6;--danger:220 38 38;--chart-input:37 99 235;--chart-output:234 88 12;--chart-cache-read:22 163 74;--chart-cache-create:124 58 237;--chart-grid:232 232 238;--chart-axis:113 113 122;--shadow-card:0 1px 2px 0 rgb(15 23 42/0.04),0 1px 3px 0 rgb(15 23 42/0.04);--shadow-card-hover:0 4px 12px -2px rgb(15 23 42/0.08),0 8px 32px -8px rgb(15 23 42/0.06);--shadow-popover:0 8px 24px -4px rgb(15 23 42/0.08),0 16px 48px -8px rgb(15 23 42/0.08);--ring-focus:79 70 229}:root{--font-sans:"Geist Sans","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;--font-mono:"Geist Mono","JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace}*{border-color:rgb(var(--border))}html{overflow-y:scroll;scrollbar-gutter:stable}body,html{background:rgb(var(--bg-base));color:rgb(var(--text-primary));font-family:var(--font-sans);font-feature-settings:"cv11","ss01","ss03";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}body{min-height:100vh}::-moz-selection{background:rgb(var(--brand)/.25);color:rgb(var(--text-primary))}::selection{background:rgb(var(--brand)/.25);color:rgb(var(--text-primary))}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:rgb(var(--border-hi)/.7);border:2px solid transparent;background-clip:padding-box;border-radius:6px}::-webkit-scrollbar-thumb:hover{background:rgb(var(--text-tertiary)/.7);background-clip:padding-box}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-thumb{background:rgb(var(--border-hi)/.5);border:0;border-radius:3px}.nav-scroller{scrollbar-width:none}.nav-scroller::-webkit-scrollbar{display:none;width:0;height:0}:where(button,a,input,select,textarea,[tabindex]):focus-visible{outline:2px solid rgb(var(--ring-focus)/.6);outline-offset:2px;border-radius:6px}@media (prefers-reduced-motion:reduce){*,:after,:before{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}.divider-soft{border-top:1px solid rgb(var(--border))}html[data-usage-overview=hidden] .usage-overview-block{display:none}.placeholder\:text-text-tertiary::-moz-placeholder{--tw-text-opacity:1;color:rgb(var(--text-tertiary)/var(--tw-text-opacity,1))}.placeholder\:text-text-tertiary::placeholder{--tw-text-opacity:1;color:rgb(var(--text-tertiary)/var(--tw-text-opacity,1))}.last\:border-b-0:last-child{border-bottom-width:0}.hover\:z-10:hover{z-index:10}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-border-hi:hover{--tw-border-opacity:1;border-color:rgb(var(--border-hi)/var(--tw-border-opacity,1))}.hover\:border-brand\/60:hover{border-color:rgb(var(--brand)/.6)}.hover\:border-text-tertiary:hover{--tw-border-opacity:1;border-color:rgb(var(--text-tertiary)/var(--tw-border-opacity,1))}.hover\:bg-bg-surface-hi:hover{--tw-bg-opacity:1;background-color:rgb(var(--bg-surface-hi)/var(--tw-bg-opacity,1))}.hover\:bg-bg-surface-hi\/30:hover{background-color:rgb(var(--bg-surface-hi)/.3)}.hover\:bg-bg-surface-hi\/40:hover{background-color:rgb(var(--bg-surface-hi)/.4)}.hover\:bg-bg-surface-hi\/60:hover{background-color:rgb(var(--bg-surface-hi)/.6)}.hover\:bg-brand\/15:hover{background-color:rgb(var(--brand)/.15)}.hover\:bg-brand\/20:hover{background-color:rgb(var(--brand)/.2)}.hover\:text-brand:hover{--tw-text-opacity:1;color:rgb(var(--brand)/var(--tw-text-opacity,1))}.hover\:text-text-primary:hover{--tw-text-opacity:1;color:rgb(var(--text-primary)/var(--tw-text-opacity,1))}.hover\:opacity-90:hover{opacity:.9}.hover\:ring-1:hover{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hover\:ring-brand\/60:hover{--tw-ring-color:rgb(var(--brand)/0.6)}.focus\:border-border-hi:focus{--tw-border-opacity:1;border-color:rgb(var(--border-hi)/var(--tw-border-opacity,1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-brand\/40:focus-visible{--tw-ring-color:rgb(var(--brand)/0.4)}.disabled\:opacity-40:disabled{opacity:.4}.group:hover .group-hover\:text-brand{--tw-text-opacity:1;color:rgb(var(--brand)/var(--tw-text-opacity,1))}.group:hover .group-hover\:brightness-110{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}@media (min-width:640px){.sm\:mt-0{margin-top:0}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:flex-row{flex-direction:row}.sm\:items-start{align-items:flex-start}.sm\:items-end{align-items:flex-end}.sm\:items-baseline{align-items:baseline}.sm\:justify-between{justify-content:space-between}.sm\:gap-2\.5{gap:.625rem}.sm\:gap-4{gap:1rem}.sm\:space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.sm\:p-6{padding:1.5rem}.sm\:px-3{padding-left:.75rem;padding-right:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-16{padding-top:4rem;padding-bottom:4rem}.sm\:py-8{padding-top:2rem;padding-bottom:2rem}.sm\:pt-5{padding-top:1.25rem}.sm\:pt-\[22px\]{padding-top:22px}.sm\:text-\[1\.75rem\]{font-size:1.75rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:inline-flex{display:inline-flex}.md\:w-\[170px\]{width:170px}.md\:shrink-0{flex-shrink:0}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:gap-8{gap:2rem}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:inline{display:inline}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccgauge",
3
- "version": "0.4.0",
3
+ "version": "1.0.0",
4
4
  "description": "Local web dashboard for Claude Code and OpenAI Codex CLI token usage and cost",
5
5
  "keywords": [
6
6
  "claude",
@@ -32,6 +32,15 @@
32
32
  "engines": {
33
33
  "node": ">=20"
34
34
  },
35
+ "os": [
36
+ "darwin",
37
+ "linux",
38
+ "win32"
39
+ ],
40
+ "cpu": [
41
+ "x64",
42
+ "arm64"
43
+ ],
35
44
  "packageManager": "pnpm@10.30.3",
36
45
  "bin": {
37
46
  "ccgauge": "bin/cli.mjs"
@@ -40,22 +49,24 @@
40
49
  "bin/cli.mjs",
41
50
  ".next/standalone",
42
51
  "dist/mcp",
52
+ "dist/report",
43
53
  "README.md",
44
54
  "README.zh-CN.md",
45
55
  "CHANGELOG.md",
46
56
  "LICENSE"
47
57
  ],
48
58
  "scripts": {
49
- "dev": "next dev -p 3737",
50
- "build": "next build && node scripts/build-mcp.mjs && node scripts/postbuild.mjs",
59
+ "dev": "next dev -p 3738",
60
+ "build": "next build && node scripts/build-mcp.mjs && node scripts/build-report.mjs && node scripts/postbuild.mjs",
51
61
  "build:mcp": "node scripts/build-mcp.mjs",
62
+ "build:report": "node scripts/build-report.mjs",
52
63
  "start": "node bin/cli.mjs",
53
64
  "start:next": "next start -p 3737",
54
65
  "lint": "eslint .",
55
66
  "typecheck": "tsc --noEmit",
56
67
  "test": "node --experimental-strip-types --no-warnings scripts/test-codex-parser.mjs",
57
68
  "test:mcp": "node scripts/test-mcp-server.mjs",
58
- "clean": "rm -rf .next node_modules tsconfig.tsbuildinfo",
69
+ "clean": "node -e \"for (const p of ['.next','node_modules','tsconfig.tsbuildinfo']) require('node:fs').rmSync(p,{recursive:true,force:true})\"",
59
70
  "screenshots": "node scripts/screenshots.mjs",
60
71
  "prepack": "pnpm build"
61
72
  },
package/CHANGELOG.md CHANGED
@@ -5,6 +5,153 @@ All notable changes to **ccgauge** are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
6
6
  this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.0] — 2026-05-12
9
+
10
+ A polish release. Everything from 0.x — Claude + Codex parsers, the web
11
+ dashboard, the CLI report, the MCP server — is now considered stable and
12
+ documented. Calling it **1.0** to signal feature-complete: the data layer,
13
+ the cost math, the turn grouping, and the published-tarball shape are all
14
+ settled. Future minor versions will keep the existing surfaces working.
15
+
16
+ ### Highlights
17
+
18
+ - **Overview "Activity" card** — sessions, messages, total tokens, active
19
+ days, current/longest streak, peak hour, favorite model, plus a 7×24
20
+ day-of-week × hour-of-day heatmap with hover tooltips (messages +
21
+ tokens + share-of-total + share-of-peak). Heat-map cells size to the
22
+ container so the card looks right at any width. Includes a tongue-in-
23
+ cheek "you've used ~N× more tokens than _The Little Prince_" comparison.
24
+ - **Conversation-turn grouping handles Skills correctly.** When Claude
25
+ Code invokes a `Skill`, it injects a synthetic `Base directory for this
26
+ skill: ...` user message that previously fragmented a single
27
+ conversation into 2–3 rows in the usage table. We now flag these
28
+ injections (also `<system-reminder>` blocks and `Caveat:` preludes) as
29
+ synthetic — they skip turn-boundary detection but still surface as the
30
+ per-call "prompt" on child rows so you can tell which Skill produced
31
+ each API call.
32
+ - **`ccgauge report` (CLI)** — formatted terminal usage report. Tokens +
33
+ Cost summary, trend bar chart, top-N breakdown table, all 0.2 s end to
34
+ end. Supports `--range`, `--source`, `--by model|project|session`,
35
+ `--since/--until`, `--model/--project` filters, `--json` machine
36
+ output, and `--level call|turn` for CSV-style detail.
37
+ - **MCP-aware ergonomics.** The Codex parser records the `effort` field
38
+ from `turn_context` and surfaces it in the usage table model column
39
+ (e.g. `GPT-5.2 Codex · high`). The 5h-block card now carries a small
40
+ disclaimer ("wall-clock progress of the 5h window — not your plan
41
+ quota") so users don't confuse our local block tracker with Anthropic's
42
+ actual rate-limit counter.
43
+
44
+ ### Added
45
+
46
+ - **Activity stats** — `lib/aggregator/activity.ts` computes streaks /
47
+ heat-map / favorite model / token-comparison; rendered by
48
+ `components/activity-stats.tsx` on the overview.
49
+ - **Silent auto-refresh on the usage page** — `components/auto-refresh.tsx`
50
+ re-runs the server render every 15 s via `router.refresh()`. No spinner,
51
+ no scroll reset, no search/expand state loss; pauses on hidden tabs.
52
+ - **Overview show/hide toggle** on the usage page —
53
+ `components/overview-toggle.tsx` hides the KPI grid + trend chart for
54
+ users who only want the table. State persists to localStorage and is
55
+ applied pre-paint by the no-flash script so collapsed users don't see
56
+ a flash.
57
+ - **Token-breakdown popover** in the usage table — hover the total cell
58
+ to see input / output / cache-read / cache-create tokens with their
59
+ per-component cost.
60
+ - **Codex `effort` field** plumbed from JSONL → AssistantRecord →
61
+ UsageTableRow → model column display.
62
+ - **Per-call "direct prompt"** on child rows — surfaces skill metadata
63
+ (`Base directory for this skill: /Users/.../skills/mf-commit`) on the
64
+ individual API calls inside a Skill block, while the parent turn row
65
+ shows the real human prompt.
66
+ - **CSV export overhaul** (`app/api/export/usage/route.ts`):
67
+ - UTF-8 BOM so Excel for Windows / Mac opens it without mojibake.
68
+ - Expanded column set: `turn_started_at`, `turn_ended_at`, `source`,
69
+ `model_short`, `effort`, `reasoning_tokens`, `project_name`,
70
+ `project_path`, `user_prompt`, etc.
71
+ - `?level=turn` for one row per conversation turn instead of one per
72
+ API call.
73
+ - Filename embeds range + level (e.g.
74
+ `ccgauge-usage-claude-7d-turn-2026-05-12.csv`).
75
+ - **Cross-platform CLI hardening** (`bin/cli.mjs`):
76
+ - `safeKill(pid, signal)` wraps `process.kill` with `ESRCH` tolerance.
77
+ - `windowsHide: true` on the background `spawn` so Windows doesn't flash
78
+ a console window.
79
+ - `restart` inherits the previous session's `port / host / dir / log`
80
+ when the user doesn't override them.
81
+ - `0.0.0.0 / ::` is rewritten to `127.0.0.1` for the browser-open URL.
82
+ - `getPort` candidates widened to 20 ports past the preferred.
83
+ - `waitForUrl` per-attempt `AbortSignal.timeout(500)`.
84
+ - `logs --follow` uses incremental `createReadStream` instead of
85
+ reading the whole file every tick.
86
+ - `state.json` carries a `version` field; readers ignore unknown shapes.
87
+ - **`AGENTS.md`** — working agreement for AI coding agents editing the
88
+ repo. Architecture invariants, common pitfalls, "first file to open"
89
+ table for typical symptoms.
90
+
91
+ ### Changed
92
+
93
+ - **Default theme is `dark`** (previously `system`). Existing users keep
94
+ their explicit choice.
95
+ - **Tools column visible by default** in the usage table; `STORAGE_KEY`
96
+ bumped to `cols.v3` so existing visibility prefs are reset to the new
97
+ defaults.
98
+ - **SegmentedPicker (range / granularity) active state** matches the
99
+ source-switcher: brand-color fill instead of muted gray. Visible in
100
+ both the page header (`今天 / 7天 / 30天 / 90天 / 全部`) and Section
101
+ headers (`小时 / 天 / 周 / 月`).
102
+ - **Page header layout** on the usage page — model / project filters
103
+ moved from the Trend section's right slot up to the page header
104
+ alongside the range picker. They apply to all of KPI / trend / table,
105
+ so they belong at the page level rather than scoped to one card.
106
+ - **Overview header** dropped the `costToday` and `activeSessions` KPI
107
+ cards — they overlapped with the existing trend chart + activity
108
+ stats.
109
+ - **5h block card** — `{pct}% elapsed` renamed to `Time elapsed {pct}%`
110
+ / `时间进度 {pct}%`, with a disclaimer line clarifying it's wall-clock
111
+ progress, not plan quota.
112
+ - **CLI option `-h, --host` → `-H, --host`.** `-h` now reliably resolves
113
+ to `--help` for `ccgauge start` and friends. Long form `--host` is
114
+ unchanged.
115
+ - **CLI auto-open semantics:** foreground opens the browser by default
116
+ (`--no-open` to disable); background never auto-opens (`ccgauge open`
117
+ to open the running one).
118
+ - **Build pipeline:** moved from `prepublishOnly` to `prepack` so
119
+ `pnpm pack` also runs the build. Build now strips `@img/sharp-*`
120
+ binaries + the bundled `typescript` package from `.next/standalone` so
121
+ the published tarball is cross-platform (no `.node` / `.dylib` files
122
+ ship). Tarball is ~6.8 MB compressed.
123
+ - **pnpm `node-linker = hoisted`** in `.npmrc`. Next.js standalone +
124
+ pnpm's default isolated layout produced tarballs missing top-level
125
+ `node_modules/next` (npm pack drops symlinks). Hoisted sidesteps it.
126
+ - **i18n / Chinese day-of-week labels** changed from one-char (`一 / 二`)
127
+ to full `周一 / 周二 / …` for clarity.
128
+
129
+ ### Fixed
130
+
131
+ - **Skill-injection turn splitting** — see Highlights.
132
+ - **5h block height** in the overview row now matches the activity card.
133
+ - **Nav scrollbar artefact** — the nav's `overflow-x-auto` rendered a
134
+ thin gray scrollbar track on macOS even when content didn't overflow,
135
+ which read as a divider against the navbar background. Replaced
136
+ `scrollbar-thin` with a `nav-scroller` rule that hides the bar
137
+ entirely.
138
+ - **Activity heatmap labels** — y-axis now shows every row (was every
139
+ other), x-axis labels every 3 hours (was every 6).
140
+
141
+ ### Notes for users upgrading from 0.4.x
142
+
143
+ - No data-file or storage migration is required. Cached entries are
144
+ re-parsed automatically on first run (`parserVersion` bumped to
145
+ `claude-v3-synthetic-flag` and `codex-v4-effort`).
146
+ - Two localStorage keys you may want to clear if you want pristine
147
+ defaults: `ccgauge.usage.cols.*` (column visibility) and
148
+ `ccgauge.usage.overview.hidden` (overview collapsed). Otherwise we
149
+ honor whatever you had.
150
+ - If you scripted around the CSV column order, note that headers have
151
+ been renamed (`cost` → `cost_usd`, `input` → `input_tokens`, etc.)
152
+ and new columns were added. The metadata header (lines starting with
153
+ `#`) now also lists `level=call|turn`.
154
+
8
155
  ## [0.4.0] — 2026-05-05
9
156
 
10
157
  This release ships an **MCP (Model Context Protocol) server** so any
package/README.md CHANGED
@@ -128,7 +128,46 @@ Background mode persists state under `~/.ccgauge/`:
128
128
  | `ccgauge restart [options]` | Stop and re-start with new options. |
129
129
  | `ccgauge status [--json]` | Inspect the background service. |
130
130
  | `ccgauge open` | Open the running dashboard in your browser. |
131
- | `ccgauge logs [-f] [-n <lines>]` | Print background logs. |
131
+ | `ccgauge logs [-f] [-n <lines>]` | Print background-service log file (the server's stdout). |
132
+ | `ccgauge report [options]` | Print a formatted **usage report** to stdout (one-shot, no server). |
133
+ | `ccgauge mcp` | Start the MCP server on stdio so LLMs can query usage. |
134
+
135
+ ### Report
136
+
137
+ A no-server one-shot summary that reads the same JSONL files the dashboard does
138
+ and prints a colored, aligned report:
139
+
140
+ ```bash
141
+ ccgauge report # last 7d, all sources, top 10 models
142
+ ccgauge report -r 30d -b project # 30 days, broken down by project
143
+ ccgauge report -s codex -m gpt-5.5 # only codex, only gpt-5.5*
144
+ ccgauge report --json # JSON output for scripting
145
+ ccgauge report --since 2026-05-01 --until 2026-05-08
146
+ ```
147
+
148
+ Report options:
149
+
150
+ | Option | Default | Purpose |
151
+ | --- | --- | --- |
152
+ | `-r, --range <range>` | `7d` | `today` / `1d` / `7d` / `30d` / `90d` / `all` |
153
+ | `-s, --source <provider>` | `all` | `claude` / `codex` / `all` |
154
+ | `-b, --by <dim>` | `model` | Breakdown dimension: `model` / `project` / `session` |
155
+ | `-g, --gran <granularity>` | `day` | Trend bucket: `hour` / `day` / `week` / `month` |
156
+ | `-n, --limit <n>` | `10` | Rows in the breakdown table |
157
+ | `--since <date>` | — | Override range start (ISO date or `YYYY-MM-DD`) |
158
+ | `--until <date>` | — | Override range end |
159
+ | `-m, --model <pat>` | — | Filter records whose model contains `<pat>` |
160
+ | `--project <pat>` | — | Filter by project basename / cwd substring |
161
+ | `-j, --json` | off | Machine-readable JSON instead of formatted text |
162
+ | `--no-color` | — | Disable ANSI colors (auto-disabled when piped) |
163
+ | `--no-trend` | — | Skip the trend chart |
164
+ | `--no-breakdown` | — | Skip the breakdown table |
165
+
166
+ Date-only `--since/--until` values use local calendar-day boundaries, so
167
+ `--until 2026-05-08` includes all of May 8.
168
+
169
+ > The name `report` (not `logs`) avoids clashing with `ccgauge logs`, which tails
170
+ > the background server's stdout log file.
132
171
 
133
172
  ### Startup options
134
173
 
@@ -397,7 +436,7 @@ This repo is a working Next.js project — run the dashboard against your live d
397
436
  git clone https://github.com/chengzuopeng/ccgauge.git
398
437
  cd ccgauge
399
438
  pnpm install
400
- pnpm dev # http://localhost:3737
439
+ pnpm dev # http://localhost:3738
401
440
  ```
402
441
 
403
442
  Scripts:
package/README.zh-CN.md CHANGED
@@ -128,7 +128,44 @@ ccgauge stop
128
128
  | `ccgauge restart [options]` | 停止再用新参数启动。 |
129
129
  | `ccgauge status [--json]` | 查看后台状态。 |
130
130
  | `ccgauge open` | 在浏览器打开正在运行的看板。 |
131
- | `ccgauge logs [-f] [-n <lines>]` | 查看后台日志。 |
131
+ | `ccgauge logs [-f] [-n <lines>]` | 查看后台服务的日志(server stdout)。 |
132
+ | `ccgauge report [options]` | 命令行**用量报告**,直接打到终端(一次性,不起服务)。 |
133
+ | `ccgauge mcp` | 起 MCP 服务(stdio),让 LLM 查你的用量。 |
134
+
135
+ ### 命令行报告(report)
136
+
137
+ 不需要起 server,直接读 JSONL,在终端打印漂亮的彩色对齐报告:
138
+
139
+ ```bash
140
+ ccgauge report # 默认:近 7 天 / 所有数据源 / 前 10 个模型
141
+ ccgauge report -r 30d -b project # 30 天,按项目分组
142
+ ccgauge report -s codex -m gpt-5.5 # 只看 codex 的 gpt-5.5*
143
+ ccgauge report --json # 输出 JSON 给脚本用
144
+ ccgauge report --since 2026-05-01 --until 2026-05-08
145
+ ```
146
+
147
+ report 参数:
148
+
149
+ | 参数 | 默认 | 作用 |
150
+ | --- | --- | --- |
151
+ | `-r, --range <range>` | `7d` | `today` / `1d` / `7d` / `30d` / `90d` / `all` |
152
+ | `-s, --source <provider>` | `all` | `claude` / `codex` / `all` |
153
+ | `-b, --by <dim>` | `model` | 分组维度:`model` / `project` / `session` |
154
+ | `-g, --gran <granularity>` | `day` | 趋势粒度:`hour` / `day` / `week` / `month` |
155
+ | `-n, --limit <n>` | `10` | 分组表显示行数 |
156
+ | `--since <date>` | — | 自定义起始日期(覆盖 `--range`,支持 `YYYY-MM-DD`) |
157
+ | `--until <date>` | — | 自定义截止日期 |
158
+ | `-m, --model <pat>` | — | 按模型名子串过滤 |
159
+ | `--project <pat>` | — | 按项目名 / cwd 子串过滤 |
160
+ | `-j, --json` | off | 输出 JSON 而不是格式化文本 |
161
+ | `--no-color` | — | 关掉 ANSI 颜色(管道里会自动关) |
162
+ | `--no-trend` | — | 不画趋势条 |
163
+ | `--no-breakdown` | — | 不打分组表 |
164
+
165
+ 只写日期的 `--since/--until` 会按本地自然日边界处理,所以
166
+ `--until 2026-05-08` 会包含 5 月 8 日整天。
167
+
168
+ > 用 `report` 而不是 `logs` 是为了避免和 `ccgauge logs`(tail 后台 server 的 stdout)混淆。
132
169
 
133
170
  ### 启动参数
134
171
 
@@ -392,7 +429,7 @@ lib/providers/<name>/
392
429
  git clone https://github.com/chengzuopeng/ccgauge.git
393
430
  cd ccgauge
394
431
  pnpm install
395
- pnpm dev # http://localhost:3737
432
+ pnpm dev # http://localhost:3738
396
433
  ```
397
434
 
398
435
  常用脚本:
package/bin/cli.mjs CHANGED
@@ -4,7 +4,7 @@ import { closeSync, createReadStream, existsSync, openSync } from 'node:fs';
4
4
  import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
5
5
  import os from 'node:os';
6
6
  import { dirname, join, resolve } from 'node:path';
7
- import { fileURLToPath } from 'node:url';
7
+ import { fileURLToPath, pathToFileURL } from 'node:url';
8
8
  import { createRequire } from 'node:module';
9
9
 
10
10
  const require = createRequire(import.meta.url);
@@ -25,8 +25,15 @@ const DEFAULT_LOG_FILE = join(STATE_DIR, 'ccgauge.log');
25
25
  const STATE_VERSION = 1;
26
26
  const DEFAULT_PORT = '3737';
27
27
  const DEFAULT_HOST = '127.0.0.1';
28
- const COMMAND_NAMES = new Set(['start', 'stop', 'restart', 'status', 'open', 'logs', 'mcp']);
29
- const VALUE_OPTIONS = new Set(['-p', '--port', '-H', '--host', '--dir', '--log', '-n', '--lines']);
28
+ const COMMAND_NAMES = new Set([
29
+ 'start', 'stop', 'restart', 'status', 'open', 'logs', 'mcp',
30
+ 'report',
31
+ ]);
32
+ const VALUE_OPTIONS = new Set([
33
+ '-p', '--port', '-H', '--host', '--dir', '--log', '-n', '--lines',
34
+ '-r', '--range', '-s', '--source', '-b', '--by', '-g', '--gran',
35
+ '-m', '--model', '--project', '--since', '--until',
36
+ ]);
30
37
 
31
38
  function browserHost(host) {
32
39
  if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') return '127.0.0.1';
@@ -139,6 +146,28 @@ program
139
146
  await startMcp();
140
147
  });
141
148
 
149
+ function addReportOptions(cmd) {
150
+ return cmd
151
+ .option('-r, --range <range>', 'today | 1d | 7d | 30d | 90d | all', '7d')
152
+ .option('-s, --source <provider>', 'claude | codex | all', 'all')
153
+ .option('-b, --by <dim>', 'breakdown dimension: model | project | session', 'model')
154
+ .option('-g, --gran <granularity>', 'trend granularity: hour | day | week | month', 'day')
155
+ .option('-n, --limit <n>', 'rows in breakdown table', '10')
156
+ .option('--since <date>', 'override range start (ISO date or YYYY-MM-DD)')
157
+ .option('--until <date>', 'override range end (ISO date or YYYY-MM-DD)')
158
+ .option('-m, --model <pat>', 'filter by model substring')
159
+ .option('--project <pat>', 'filter by project (cwd basename match)')
160
+ .option('-j, --json', 'output JSON instead of formatted text')
161
+ .option('--no-color', 'disable ANSI colors')
162
+ .option('--no-trend', 'skip the trend chart')
163
+ .option('--no-breakdown', 'skip the breakdown table');
164
+ }
165
+
166
+ addReportOptions(program.command('report').description('print a formatted usage report to stdout'))
167
+ .action(async (opts) => {
168
+ await report(opts);
169
+ });
170
+
142
171
  await program.parseAsync(normalizeArgv(process.argv));
143
172
 
144
173
  function normalizeArgv(argv) {
@@ -228,6 +257,9 @@ async function startBackground(standaloneEntry, opts) {
228
257
  env,
229
258
  detached: true,
230
259
  stdio: ['ignore', out, err],
260
+ // Suppress the fleeting console window that Windows pops up for a
261
+ // detached background child. No-op on macOS/Linux.
262
+ windowsHide: true,
231
263
  });
232
264
  child.unref();
233
265
  // Once spawn() has dup'd these fds into the child, the parent can release them.
@@ -351,6 +383,54 @@ or run the dev server with
351
383
  process.exit(1);
352
384
  }
353
385
 
386
+ async function report(opts) {
387
+ const bundle = join(packageRoot, 'dist', 'report', 'index.mjs');
388
+ if (!existsSync(bundle)) {
389
+ console.error(`
390
+ [ccgauge] Report bundle not found:
391
+ ${bundle}
392
+
393
+ If you installed ccgauge from npm: please reinstall — the published package
394
+ should include the report bundle.
395
+
396
+ If you are running from source: build it first with
397
+ $ pnpm build:report
398
+ or run the full build with
399
+ $ pnpm build
400
+ `);
401
+ process.exit(1);
402
+ }
403
+ const limit = parseInt(String(opts.limit ?? '10'), 10);
404
+ const reportOpts = {
405
+ range: String(opts.range ?? '7d'),
406
+ source: String(opts.source ?? 'all'),
407
+ by: String(opts.by ?? 'model'),
408
+ gran: String(opts.gran ?? 'day'),
409
+ limit: Number.isFinite(limit) && limit > 0 ? limit : 10,
410
+ since: opts.since ? String(opts.since) : undefined,
411
+ until: opts.until ? String(opts.until) : undefined,
412
+ json: Boolean(opts.json),
413
+ color: opts.color !== false && process.stdout.isTTY,
414
+ showTrend: opts.trend !== false,
415
+ showBreakdown: opts.breakdown !== false,
416
+ model: opts.model ? String(opts.model) : undefined,
417
+ project: opts.project ? String(opts.project) : undefined,
418
+ };
419
+ try {
420
+ const mod = await import(pathToFileURL(bundle).href);
421
+ const out = await mod.runReport(reportOpts);
422
+ process.stdout.write(out);
423
+ if (!out.endsWith('\n')) process.stdout.write('\n');
424
+ } catch (err) {
425
+ console.error(`[ccgauge] report failed: ${(err && err.message) || err}`);
426
+ process.exit(1);
427
+ }
428
+ // The indexer keeps fs watchers alive, which would block process exit.
429
+ // For a one-shot report we explicitly exit once stdout is drained.
430
+ process.stdout.once?.('drain', () => process.exit(0));
431
+ if (process.stdout.writableLength === 0) process.exit(0);
432
+ }
433
+
354
434
  async function startMcp() {
355
435
  const bundle = join(packageRoot, 'dist', 'mcp', 'server.mjs');
356
436
  if (!existsSync(bundle)) {