tokentracker-cli 0.2.23 → 0.2.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,11 @@
1
1
  <div align="center">
2
2
 
3
- <img src="dashboard/public/icon-192.png" width="96" alt="Token Tracker Icon" />
4
-
5
3
  # TOKEN TRACKER
6
4
 
7
5
  **Track AI Token Usage Across All Your CLI Tools**
8
6
 
9
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
10
- [![npm version](https://img.shields.io/npm/v/tokentracker.svg)](https://www.npmjs.com/package/tokentracker)
8
+ [![npm version](https://img.shields.io/npm/v/tokentracker-cli.svg)](https://www.npmjs.com/package/tokentracker-cli)
11
9
  [![Node.js Support](https://img.shields.io/badge/Node.js-≥20-brightgreen.svg)](https://nodejs.org/)
12
10
  [![Platform](https://img.shields.io/badge/Platform-macOS-lightgrey.svg)](https://www.apple.com/macos/)
13
11
 
@@ -18,21 +16,17 @@
18
16
  ## Quick Start
19
17
 
20
18
  ```bash
21
- # Set up hooks (one-time)
22
- npx tokentracker init
23
-
24
- # View your dashboard
25
- npx tokentracker
19
+ npx tokentracker-cli
26
20
  ```
27
21
 
28
- That's it! Token usage from all your AI CLI tools is automatically tracked and viewable locally.
22
+ One command does everything: first-time setup hook installation data sync open dashboard.
29
23
 
30
24
  ## Features
31
25
 
32
26
  - **Multi-Source Tracking** — Codex CLI, Claude Code, Gemini CLI, OpenCode, OpenClaw, Every Code
33
27
  - **Local-First** — All data stays on your machine. No cloud account required.
34
- - **Zero-Config Auto-Sync** — Hooks trigger automatically on AI tool usage
35
- - **Local Dashboard** — Built-in web UI at `http://localhost:7890`
28
+ - **Zero-Config** — Hooks auto-detect and configure on first run
29
+ - **Built-in Dashboard** — Web UI at `http://localhost:7890`, no external service needed
36
30
  - **Privacy-First** — Only token counts tracked, never prompts or responses
37
31
 
38
32
  ## Supported CLI Tools
@@ -48,24 +42,18 @@ That's it! Token usage from all your AI CLI tools is automatically tracked and v
48
42
 
49
43
  ## Usage
50
44
 
45
+ After first run via `npx tokentracker-cli`, you can also install globally for shorter commands:
46
+
51
47
  ```bash
52
- # Open local dashboard (default command)
53
- tokentracker
48
+ npm i -g tokentracker-cli
54
49
 
55
- # Serve on a custom port
50
+ # Then use anywhere:
51
+ tokentracker # Open dashboard
56
52
  tokentracker serve --port 3000
57
-
58
- # Manual sync
59
- tokentracker sync
60
-
61
- # Check status
62
- tokentracker status
63
-
64
- # Health check
65
- tokentracker doctor
66
-
67
- # Uninstall hooks
68
- tokentracker uninstall
53
+ tokentracker sync # Manual sync
54
+ tokentracker status # Check hook status
55
+ tokentracker doctor # Health check
56
+ tokentracker uninstall # Remove hooks
69
57
  ```
70
58
 
71
59
  ## How It Works
@@ -93,7 +81,7 @@ Local Dashboard (http://localhost:7890)
93
81
  | Protection | Description |
94
82
  |------------|-------------|
95
83
  | **No Content Upload** | Never uploads prompts or responses — only token counts |
96
- | **Local Aggregation** | All analysis happens on your machine |
84
+ | **Local Only** | All data stays on your machine, all analysis local |
97
85
  | **Transparent** | Audit the sync logic in `src/lib/rollout.js` — only numbers and timestamps |
98
86
 
99
87
  ## Configuration
@@ -102,15 +90,15 @@ Local Dashboard (http://localhost:7890)
102
90
 
103
91
  | Variable | Description | Default |
104
92
  |----------|-------------|---------|
105
- | `VIBEUSAGE_HTTP_TIMEOUT_MS` | HTTP timeout (ms) | `20000` |
106
- | `VIBEUSAGE_DEBUG` | Enable debug output | - |
107
- | `CODEX_HOME` | Codex CLI directory | `~/.codex` |
108
- | `GEMINI_HOME` | Gemini CLI directory | `~/.gemini` |
93
+ | `TOKENTRACKER_DEBUG` | Enable debug output (`1` to enable) | - |
94
+ | `TOKENTRACKER_HTTP_TIMEOUT_MS` | HTTP timeout (ms) | `20000` |
95
+ | `CODEX_HOME` | Codex CLI directory override | `~/.codex` |
96
+ | `GEMINI_HOME` | Gemini CLI directory override | `~/.gemini` |
109
97
 
110
98
  ## Development
111
99
 
112
100
  ```bash
113
- git clone https://github.com/anthropics/tokentracker.git
101
+ git clone https://github.com/mm7894215/tokentracker.git
114
102
  cd tokentracker
115
103
  npm install
116
104
 
@@ -118,7 +106,7 @@ npm install
118
106
  cd dashboard && npm install && npm run build && cd ..
119
107
 
120
108
  # Run locally
121
- node bin/tracker.js serve
109
+ node bin/tracker.js
122
110
 
123
111
  # Run tests
124
112
  npm test
package/bin/tracker.js CHANGED
@@ -5,7 +5,7 @@ const { run } = require('../src/cli');
5
5
  const { stripDebugFlag } = require('../src/lib/debug-flags');
6
6
 
7
7
  const { argv, debug } = stripDebugFlag(process.argv.slice(2));
8
- if (debug) process.env.VIBEUSAGE_DEBUG = '1';
8
+ if (debug) process.env.TOKENTRACKER_DEBUG = '1';
9
9
 
10
10
  run(argv).catch((err) => {
11
11
  console.error(err?.stack || String(err));
@@ -1 +1 @@
1
- import{b as k,ad as Z,d as ue,ae as z,af as L,ag as le,ah as de,ai as fe,aj as me,ak as pe,al as ge,am as ke,_ as ye,an as he,ao as Te,ap as we,m}from"./main-BYPG1_bI.js";const xe="Backend runtime unavailable (InsForge). Please retry later.",p={usageSummary:"vibeusage-usage-summary",usageDaily:"vibeusage-usage-daily",usageHourly:"vibeusage-usage-hourly",usageMonthly:"vibeusage-usage-monthly",usageHeatmap:"vibeusage-usage-heatmap",usageModelBreakdown:"vibeusage-usage-model-breakdown",projectUsageSummary:"vibeusage-project-usage-summary",leaderboard:"vibeusage-leaderboard",leaderboardProfile:"vibeusage-leaderboard-profile",userStatus:"vibeusage-user-status",linkCodeInit:"vibeusage-link-code-init",publicViewProfile:"vibeusage-public-view-profile",publicVisibility:"vibeusage-public-visibility"},J="/functions",be="/api/functions",h={business:"business",probe:"probe"};let D=null;async function f(e){return await ue(e)}async function Ee({baseUrl:e,accessToken:s,signal:t}={}){const a=await f(s),n=we(new Date);return await y({baseUrl:e,accessToken:a,slug:p.usageSummary,params:{from:n,to:n},fetchOptions:{cache:"no-store",signal:t},retry:!1,requestKind:h.probe}),{status:200}}async function Ce({baseUrl:e,accessToken:s,from:t,to:a,source:n,model:r,timeZone:l,tzOffsetMinutes:i,rolling:c=!1}={}){const u=await f(s);if(k())return de({from:t,to:a,seed:u,rolling:c});const o=M({timeZone:l,tzOffsetMinutes:i}),d=P({source:n,model:r}),v=c?{rolling:"1"}:{};return y({baseUrl:e,accessToken:u,slug:p.usageSummary,params:{from:t,to:a,...d,...o,...v}})}async function je({baseUrl:e,accessToken:s,from:t,to:a,source:n,limit:r,timeZone:l,tzOffsetMinutes:i}={}){const c=await f(s);if(k())return me({seed:c,limit:r});const u=M({timeZone:l,tzOffsetMinutes:i}),d={...P({source:n}),...u};return t&&(d.from=t),a&&(d.to=a),r!=null&&(d.limit=String(r)),y({baseUrl:e,accessToken:c,slug:p.projectUsageSummary,params:d})}async function Ie({baseUrl:e,accessToken:s,period:t,metric:a,limit:n,offset:r}={}){const l=await f(s);if(k())return Z({seed:l,period:t,metric:a,limit:n,offset:r});const c=(typeof t=="string"?t:"week").trim().toLowerCase(),o={period:c==="month"||c==="total"||c==="week"?c:"week"};return a&&(o.metric=String(a)),n!=null&&(o.limit=String(n)),r!=null&&(o.offset=String(r)),y({baseUrl:e,accessToken:l,slug:p.leaderboard,params:o})}async function Ne({baseUrl:e,accessToken:s}={}){const t=await f(s);return k()?{enabled:!1,updated_at:null,share_token:null}:y({baseUrl:e,accessToken:t,slug:p.publicVisibility})}async function De({baseUrl:e,accessToken:s,enabled:t}={}){const a=await f(s);return k()?{enabled:!!t,updated_at:new Date().toISOString(),share_token:t?"pv1-mock-token":null}:X({baseUrl:e,accessToken:a,slug:p.publicVisibility,body:{enabled:!!t}})}async function Le({baseUrl:e,accessToken:s,userId:t,period:a}={}){const n=await f(s);if(k()){const r=Z({seed:n,period:a,metric:"all",limit:250,offset:0}),i=(Array.isArray(r?.entries)?r.entries:[]).find(c=>c?.user_id===t)||null;return{period:r?.period??"week",from:r?.from??null,to:r?.to??null,generated_at:r?.generated_at??new Date().toISOString(),entry:i?{user_id:i.user_id??null,display_name:i.display_name??null,avatar_url:i.avatar_url??null,rank:i.rank??null,gpt_tokens:i.gpt_tokens??"0",claude_tokens:i.claude_tokens??"0",other_tokens:i.other_tokens??"0",total_tokens:i.total_tokens??"0"}:null}}return y({baseUrl:e,accessToken:n,slug:p.leaderboardProfile,params:{user_id:String(t||""),period:String(a||"")}})}async function He({baseUrl:e,accessToken:s}={}){const t=await f(s);if(k()){const a=new Date().toISOString();return{user_id:"mock-user",created_at:a,pro:{active:!0,sources:["mock"],expires_at:null,partial:!1,as_of:a},subscriptions:{partial:!1,as_of:a,items:[{tool:"codex",provider:"openai",product:"chatgpt",plan_type:"pro",updated_at:a},{tool:"claude",provider:"anthropic",product:"subscription",plan_type:"max",rate_limit_tier:"default_claude_max_5x",updated_at:a}]},install:{partial:!1,as_of:a,has_active_device_token:!1,has_active_device:!1,active_device_tokens:0,active_devices:0,latest_token_activity_at:null,latest_device_seen_at:null}}}return y({baseUrl:e,accessToken:t,slug:p.userStatus})}async function ze({signal:e}={}){const s=await fetch("/functions/vibeusage-local-sync",{method:"POST",headers:{Accept:"application/json"},cache:"no-store",signal:e}),t=await s.json().catch(()=>({ok:!1,error:`Local sync request failed with HTTP ${s.status}`}));if(!s.ok||t?.ok===!1){const a=t?.error||t?.message||`Local sync request failed with HTTP ${s.status}`,n=new Error(a);throw n.status=s.status,n.statusCode=s.status,n.payload=t,n}return t}async function Ue({baseUrl:e,accessToken:s,from:t,to:a,source:n,timeZone:r,tzOffsetMinutes:l}={}){const i=await f(s);if(k())return fe({from:t,to:a,seed:i});const c=M({timeZone:r,tzOffsetMinutes:l}),u=P({source:n});return y({baseUrl:e,accessToken:i,slug:p.usageModelBreakdown,params:{from:t,to:a,...u,...c}})}async function Be({baseUrl:e,accessToken:s,from:t,to:a,source:n,model:r,timeZone:l,tzOffsetMinutes:i}={}){const c=await f(s);if(k())return le({from:t,to:a,seed:c});const u=M({timeZone:l,tzOffsetMinutes:i}),o=P({source:n,model:r});return y({baseUrl:e,accessToken:c,slug:p.usageDaily,params:{from:t,to:a,...o,...u}})}async function Oe({baseUrl:e,accessToken:s,day:t,source:a,model:n,timeZone:r,tzOffsetMinutes:l}={}){const i=await f(s);if(k())return pe({day:t,seed:i});const c=M({timeZone:r,tzOffsetMinutes:l}),u=P({source:a,model:n});return y({baseUrl:e,accessToken:i,slug:p.usageHourly,params:t?{day:t,...u,...c}:{...u,...c}})}async function Fe({baseUrl:e,accessToken:s,months:t,to:a,source:n,model:r,timeZone:l,tzOffsetMinutes:i}={}){const c=await f(s);if(k())return ge({months:t,to:a,seed:c});const u=M({timeZone:l,tzOffsetMinutes:i}),o=P({source:n,model:r});return y({baseUrl:e,accessToken:c,slug:p.usageMonthly,params:{...t?{months:String(t)}:{},...a?{to:a}:{},...o,...u}})}async function qe({baseUrl:e,accessToken:s,weeks:t,to:a,weekStartsOn:n,source:r,model:l,timeZone:i,tzOffsetMinutes:c}={}){const u=await f(s);if(k())return ke({weeks:t,to:a,weekStartsOn:n,seed:u});const o=M({timeZone:i,tzOffsetMinutes:c}),d=P({source:r,model:l});return y({baseUrl:e,accessToken:u,slug:p.usageHeatmap,params:{weeks:String(t),to:a,week_starts_on:n,...d,...o}})}async function Ve({baseUrl:e,accessToken:s}={}){const t=await f(s);return k()?{link_code:"mock_link_code",expires_at:new Date(Date.now()+10*6e4).toISOString()}:X({baseUrl:e,accessToken:t,slug:p.linkCodeInit,body:{}})}async function $e({baseUrl:e,accessToken:s}={}){const t=await f(s);return y({baseUrl:e,accessToken:t,slug:p.publicViewProfile})}function M({timeZone:e,tzOffsetMinutes:s}={}){const t={},a=typeof e=="string"?e.trim():"";return a&&(t.tz=a),Number.isFinite(s)&&(t.tz_offset_minutes=String(Math.trunc(s))),t}function P({source:e,model:s}={}){const t={},a=typeof e=="string"?e.trim().toLowerCase():"";a&&(t.source=a);const n=typeof s=="string"?s.trim():"";return n&&(t.model=n),t}async function y({baseUrl:e,accessToken:s,slug:t,params:a,fetchOptions:n,errorPrefix:r,retry:l,requestKind:i=h.business,skipSessionExpiry:c=!1,allowRefresh:u=!0}={}){let o=await f(s),d=E(o),v=z({baseUrl:e,accessToken:o??void 0}).getHttpClient();const C=ae(l,"GET"),b=c?h.probe:i;let A=0;const{primaryPath:j,fallbackPath:I}=Q(t);for(;;)try{const S=await G({http:v,primaryPath:j,fallbackPath:I,params:a,fetchOptions:n});return U({hadAccessToken:d,accessToken:o}),S}catch(S){const T=S;if(T?.name==="AbortError")throw S;let w=null;const B=T?.statusCode??T?.status;if(u&&se({status:B,requestKind:b,hadAccessToken:d,accessToken:o})){const g=(await te())?.accessToken??null;if(E(g)){const N=z({baseUrl:e,accessToken:g}).getHttpClient();o=g,d=!0,v=N;try{const x=await G({http:N,primaryPath:j,fallbackPath:I,params:a,fetchOptions:n});return U({hadAccessToken:!0,accessToken:g}),x}catch(x){const F=x?.statusCode??x?.status;$({status:F,hadAccessToken:!0,accessToken:g,skipSessionExpiry:b===h.probe})&&L(),w=R(x,{errorPrefix:r,hadAccessToken:!0,accessToken:g,skipSessionExpiry:!0})}}else H({hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe})&&L();w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:!0})}if(w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe}),!ne({err:w,attempt:A,retryOptions:C}))throw w;const O=re({retryOptions:C,attempt:A});await ie(O),A+=1}}async function X({baseUrl:e,accessToken:s,slug:t,body:a,fetchOptions:n,errorPrefix:r,retry:l,requestKind:i=h.business,skipSessionExpiry:c=!1,allowRefresh:u=!0}={}){let o=await f(s),d=E(o),v=z({baseUrl:e,accessToken:o??void 0}).getHttpClient();const C=ae(l,"POST"),b=c?h.probe:i;let A=0;const{primaryPath:j,fallbackPath:I}=Q(t);for(;;)try{const S=await K({http:v,primaryPath:j,fallbackPath:I,body:a,fetchOptions:n});return U({hadAccessToken:d,accessToken:o}),S}catch(S){const T=S;if(T?.name==="AbortError")throw S;let w=null;const B=T?.statusCode??T?.status;if(u&&se({status:B,requestKind:b,hadAccessToken:d,accessToken:o})){const g=(await te())?.accessToken??null;if(E(g)){const N=z({baseUrl:e,accessToken:g}).getHttpClient();o=g,d=!0,v=N;try{const x=await K({http:N,primaryPath:j,fallbackPath:I,body:a,fetchOptions:n});return U({hadAccessToken:!0,accessToken:g}),x}catch(x){const F=x?.statusCode??x?.status;$({status:F,hadAccessToken:!0,accessToken:g,skipSessionExpiry:b===h.probe})&&L(),w=R(x,{errorPrefix:r,hadAccessToken:!0,accessToken:g,skipSessionExpiry:!0})}}else H({hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe})&&L();w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:!0})}if(w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe}),!ne({err:w,attempt:A,retryOptions:C}))throw w;const O=re({retryOptions:C,attempt:A});await ie(O),A+=1}}function Q(e){const s=Se(e),t=`${V(J)}/${s}`,a=`${V(be)}/${s}`;return{primaryPath:t,fallbackPath:a}}function Se(e){return(typeof e=="string"?e.trim():"").replace(/^\/+/,"")}function V(e){const s=typeof e=="string"?e.trim():"";return s.endsWith("/")?s.slice(0,-1):s}async function G({http:e,primaryPath:s,fallbackPath:t,params:a,fetchOptions:n}={}){try{return await e.get(s,{params:a,...n||{}})}catch(r){if(!Y(r,s))throw r;return await e.get(t,{params:a,...n||{}})}}async function K({http:e,primaryPath:s,fallbackPath:t,body:a,fetchOptions:n}={}){try{return await W({http:e,path:s,body:a,fetchOptions:n})}catch(r){if(!Y(r,s))throw r;return await W({http:e,path:t,body:a,fetchOptions:n})}}async function W({http:e,path:s,body:t,fetchOptions:a}={}){return await e.post(s,t,{...a||{}})}function Y(e,s){return!s||!s.startsWith(`${V(J)}/`)?!1:(e?.statusCode??e?.status)===404}function R(e,{errorPrefix:s,hadAccessToken:t,accessToken:a,skipSessionExpiry:n}={}){const r=typeof e?.message=="string"?e.message.trim():"",l=typeof e?.error=="string"?e.error.trim():"",i=r||l||String(e||"Unknown error"),c=ve(i),u=new Error(s?`${s}: ${c}`:c);u.cause=e;const o=e?.statusCode??e?.status;return $({status:o,hadAccessToken:t,accessToken:a,skipSessionExpiry:n})&&L(),typeof o=="number"&&(u.status=o,u.statusCode=o),u.retryable=Ae(o)||Me(i),c!==i&&(u.originalMessage=i),e?.nextActions&&(u.nextActions=e.nextActions),e?.error&&(u.error=e.error),u}function H({hadAccessToken:e,accessToken:s,skipSessionExpiry:t}={}){return t||!e||!E(s)?!1:Pe(s)}function $({status:e,hadAccessToken:s,accessToken:t,skipSessionExpiry:a}={}){return e!==401?!1:H({hadAccessToken:s,accessToken:t,skipSessionExpiry:a})}function _e({hadAccessToken:e,accessToken:s}={}){return H({hadAccessToken:e,accessToken:s})}function U({hadAccessToken:e,accessToken:s}={}){_e({hadAccessToken:e,accessToken:s})&&he()}function ve(e){return ee(e)?xe:String(e||"Unknown error")}function ee(e){const s=String(e||"").toLowerCase();return s?!!(s.includes("deno:")||s.includes("deno")||s.includes("econnreset")||s.includes("econnrefused")||s.includes("etimedout")||s.includes("timeout")&&s.includes("request")||s.includes("upstream")&&(s.includes("deno")||s.includes("connect"))):!1}function se({status:e,requestKind:s,hadAccessToken:t,accessToken:a}={}){return e!==401||s!==h.business?!1:H({hadAccessToken:t,accessToken:a})}async function te(){return D||(D=Te.auth.getCurrentSession().then(({data:e})=>e?.session??null).catch(()=>null).finally(()=>{D=null}),D)}function Ae(e){return e===502||e===503||e===504}function Me(e){const s=String(e||"").toLowerCase();return s?!!(ee(s)||s.includes("econnreset")||s.includes("econnrefused")||s.includes("etimedout")||s.includes("timeout")||s.includes("networkerror")||s.includes("failed to fetch")||s.includes("socket hang up")||s.includes("connection reset")):!1}function ae(e,s){const a=(s||"GET").toUpperCase()==="GET"?{maxRetries:2,baseDelayMs:300,maxDelayMs:1500,jitterRatio:.2}:{maxRetries:0,baseDelayMs:0,maxDelayMs:0,jitterRatio:0};if(e==null)return a;if(e===!1)return{maxRetries:0,baseDelayMs:0,maxDelayMs:0,jitterRatio:0};const n=q(e.maxRetries??a.maxRetries,0,10),r=q(e.baseDelayMs??a.baseDelayMs,50,6e4),l=q(e.maxDelayMs??a.maxDelayMs,r,12e4),i=typeof e.jitterRatio=="number"?Math.max(0,Math.min(.5,e.jitterRatio)):a.jitterRatio;return{maxRetries:n,baseDelayMs:r,maxDelayMs:l,jitterRatio:i}}function E(e){return!!ye(e)}function Pe(e){if(!E(e))return!1;const s=e.split(".");return s.length!==3?!1:s.every(t=>/^[A-Za-z0-9_-]+$/.test(t))}function ne({err:e,attempt:s,retryOptions:t}={}){return!t||t.maxRetries<=0||s>=t.maxRetries?!1:!!(e&&e.retryable)}function re({retryOptions:e,attempt:s}={}){if(!e||e.maxRetries<=0)return 0;const t=e.baseDelayMs*Math.pow(2,s),a=Math.min(e.maxDelayMs,t),n=a*e.jitterRatio*Math.random();return Math.round(a+n)}function q(e,s,t){const a=Number(e);return Number.isFinite(a)?Math.min(t,Math.max(s,Math.floor(a))):s}function ie(e){return!e||e<=0?Promise.resolve():new Promise(s=>setTimeout(s,e))}const _={TOP_LEFT:"┌",TOP_RIGHT:"┐",BOTTOM_LEFT:"└",BOTTOM_RIGHT:"┘",HORIZONTAL:"─",VERTICAL:"│"};function Ge({title:e,subtitle:s,children:t,className:a="",bodyClassName:n=""}){return m.jsxs("div",{className:`relative flex flex-col matrix-panel ${a}`,children:[m.jsxs("div",{className:"flex items-center leading-none",children:[m.jsx("span",{className:"shrink-0 text-matrix-dim",children:_.TOP_LEFT}),m.jsx("span",{className:"mx-3 shrink-0 text-heading uppercase text-matrix-primary px-2 py-1 bg-matrix-panelStrong border border-matrix-ghost",children:e}),s?m.jsxs("span",{className:"text-caption text-matrix-muted mr-2 uppercase",children:["[",s,"]"]}):null,m.jsx("span",{className:"flex-1 overflow-hidden whitespace-nowrap text-matrix-ghost",children:_.HORIZONTAL.repeat(100)}),m.jsx("span",{className:"shrink-0 text-matrix-dim",children:_.TOP_RIGHT})]}),m.jsxs("div",{className:"flex flex-1",children:[m.jsx("div",{className:"shrink-0 w-3 flex justify-center text-matrix-ghost",children:_.VERTICAL}),m.jsx("div",{className:`flex-1 min-w-0 py-5 px-4 relative z-10 ${n}`,children:t}),m.jsx("div",{className:"shrink-0 w-3 flex justify-center text-matrix-ghost",children:_.VERTICAL})]}),m.jsxs("div",{className:"flex items-center leading-none text-matrix-ghost",children:[m.jsx("span",{className:"shrink-0",children:_.BOTTOM_LEFT}),m.jsx("span",{className:"flex-1 overflow-hidden whitespace-nowrap",children:_.HORIZONTAL.repeat(100)}),m.jsx("span",{className:"shrink-0",children:_.BOTTOM_RIGHT})]})]})}export{Ge as A,Be as a,je as b,Oe as c,Fe as d,Ce as e,Ue as f,qe as g,Ne as h,$e as i,He as j,Ie as k,Le as l,Ee as p,Ve as r,De as s,ze as t};
1
+ import{b as k,ad as Z,d as ue,ae as z,af as L,ag as le,ah as de,ai as fe,aj as me,ak as pe,al as ge,am as ke,_ as ye,an as he,ao as Te,ap as we,m}from"./main-DepLUlUX.js";const xe="Backend runtime unavailable (InsForge). Please retry later.",p={usageSummary:"vibeusage-usage-summary",usageDaily:"vibeusage-usage-daily",usageHourly:"vibeusage-usage-hourly",usageMonthly:"vibeusage-usage-monthly",usageHeatmap:"vibeusage-usage-heatmap",usageModelBreakdown:"vibeusage-usage-model-breakdown",projectUsageSummary:"vibeusage-project-usage-summary",leaderboard:"vibeusage-leaderboard",leaderboardProfile:"vibeusage-leaderboard-profile",userStatus:"vibeusage-user-status",linkCodeInit:"vibeusage-link-code-init",publicViewProfile:"vibeusage-public-view-profile",publicVisibility:"vibeusage-public-visibility"},J="/functions",be="/api/functions",h={business:"business",probe:"probe"};let D=null;async function f(e){return await ue(e)}async function Ee({baseUrl:e,accessToken:s,signal:t}={}){const a=await f(s),n=we(new Date);return await y({baseUrl:e,accessToken:a,slug:p.usageSummary,params:{from:n,to:n},fetchOptions:{cache:"no-store",signal:t},retry:!1,requestKind:h.probe}),{status:200}}async function Ce({baseUrl:e,accessToken:s,from:t,to:a,source:n,model:r,timeZone:l,tzOffsetMinutes:i,rolling:c=!1}={}){const u=await f(s);if(k())return de({from:t,to:a,seed:u,rolling:c});const o=M({timeZone:l,tzOffsetMinutes:i}),d=P({source:n,model:r}),v=c?{rolling:"1"}:{};return y({baseUrl:e,accessToken:u,slug:p.usageSummary,params:{from:t,to:a,...d,...o,...v}})}async function je({baseUrl:e,accessToken:s,from:t,to:a,source:n,limit:r,timeZone:l,tzOffsetMinutes:i}={}){const c=await f(s);if(k())return me({seed:c,limit:r});const u=M({timeZone:l,tzOffsetMinutes:i}),d={...P({source:n}),...u};return t&&(d.from=t),a&&(d.to=a),r!=null&&(d.limit=String(r)),y({baseUrl:e,accessToken:c,slug:p.projectUsageSummary,params:d})}async function Ie({baseUrl:e,accessToken:s,period:t,metric:a,limit:n,offset:r}={}){const l=await f(s);if(k())return Z({seed:l,period:t,metric:a,limit:n,offset:r});const c=(typeof t=="string"?t:"week").trim().toLowerCase(),o={period:c==="month"||c==="total"||c==="week"?c:"week"};return a&&(o.metric=String(a)),n!=null&&(o.limit=String(n)),r!=null&&(o.offset=String(r)),y({baseUrl:e,accessToken:l,slug:p.leaderboard,params:o})}async function Ne({baseUrl:e,accessToken:s}={}){const t=await f(s);return k()?{enabled:!1,updated_at:null,share_token:null}:y({baseUrl:e,accessToken:t,slug:p.publicVisibility})}async function De({baseUrl:e,accessToken:s,enabled:t}={}){const a=await f(s);return k()?{enabled:!!t,updated_at:new Date().toISOString(),share_token:t?"pv1-mock-token":null}:X({baseUrl:e,accessToken:a,slug:p.publicVisibility,body:{enabled:!!t}})}async function Le({baseUrl:e,accessToken:s,userId:t,period:a}={}){const n=await f(s);if(k()){const r=Z({seed:n,period:a,metric:"all",limit:250,offset:0}),i=(Array.isArray(r?.entries)?r.entries:[]).find(c=>c?.user_id===t)||null;return{period:r?.period??"week",from:r?.from??null,to:r?.to??null,generated_at:r?.generated_at??new Date().toISOString(),entry:i?{user_id:i.user_id??null,display_name:i.display_name??null,avatar_url:i.avatar_url??null,rank:i.rank??null,gpt_tokens:i.gpt_tokens??"0",claude_tokens:i.claude_tokens??"0",other_tokens:i.other_tokens??"0",total_tokens:i.total_tokens??"0"}:null}}return y({baseUrl:e,accessToken:n,slug:p.leaderboardProfile,params:{user_id:String(t||""),period:String(a||"")}})}async function He({baseUrl:e,accessToken:s}={}){const t=await f(s);if(k()){const a=new Date().toISOString();return{user_id:"mock-user",created_at:a,pro:{active:!0,sources:["mock"],expires_at:null,partial:!1,as_of:a},subscriptions:{partial:!1,as_of:a,items:[{tool:"codex",provider:"openai",product:"chatgpt",plan_type:"pro",updated_at:a},{tool:"claude",provider:"anthropic",product:"subscription",plan_type:"max",rate_limit_tier:"default_claude_max_5x",updated_at:a}]},install:{partial:!1,as_of:a,has_active_device_token:!1,has_active_device:!1,active_device_tokens:0,active_devices:0,latest_token_activity_at:null,latest_device_seen_at:null}}}return y({baseUrl:e,accessToken:t,slug:p.userStatus})}async function ze({signal:e}={}){const s=await fetch("/functions/vibeusage-local-sync",{method:"POST",headers:{Accept:"application/json"},cache:"no-store",signal:e}),t=await s.json().catch(()=>({ok:!1,error:`Local sync request failed with HTTP ${s.status}`}));if(!s.ok||t?.ok===!1){const a=t?.error||t?.message||`Local sync request failed with HTTP ${s.status}`,n=new Error(a);throw n.status=s.status,n.statusCode=s.status,n.payload=t,n}return t}async function Ue({baseUrl:e,accessToken:s,from:t,to:a,source:n,timeZone:r,tzOffsetMinutes:l}={}){const i=await f(s);if(k())return fe({from:t,to:a,seed:i});const c=M({timeZone:r,tzOffsetMinutes:l}),u=P({source:n});return y({baseUrl:e,accessToken:i,slug:p.usageModelBreakdown,params:{from:t,to:a,...u,...c}})}async function Be({baseUrl:e,accessToken:s,from:t,to:a,source:n,model:r,timeZone:l,tzOffsetMinutes:i}={}){const c=await f(s);if(k())return le({from:t,to:a,seed:c});const u=M({timeZone:l,tzOffsetMinutes:i}),o=P({source:n,model:r});return y({baseUrl:e,accessToken:c,slug:p.usageDaily,params:{from:t,to:a,...o,...u}})}async function Oe({baseUrl:e,accessToken:s,day:t,source:a,model:n,timeZone:r,tzOffsetMinutes:l}={}){const i=await f(s);if(k())return pe({day:t,seed:i});const c=M({timeZone:r,tzOffsetMinutes:l}),u=P({source:a,model:n});return y({baseUrl:e,accessToken:i,slug:p.usageHourly,params:t?{day:t,...u,...c}:{...u,...c}})}async function Fe({baseUrl:e,accessToken:s,months:t,to:a,source:n,model:r,timeZone:l,tzOffsetMinutes:i}={}){const c=await f(s);if(k())return ge({months:t,to:a,seed:c});const u=M({timeZone:l,tzOffsetMinutes:i}),o=P({source:n,model:r});return y({baseUrl:e,accessToken:c,slug:p.usageMonthly,params:{...t?{months:String(t)}:{},...a?{to:a}:{},...o,...u}})}async function qe({baseUrl:e,accessToken:s,weeks:t,to:a,weekStartsOn:n,source:r,model:l,timeZone:i,tzOffsetMinutes:c}={}){const u=await f(s);if(k())return ke({weeks:t,to:a,weekStartsOn:n,seed:u});const o=M({timeZone:i,tzOffsetMinutes:c}),d=P({source:r,model:l});return y({baseUrl:e,accessToken:u,slug:p.usageHeatmap,params:{weeks:String(t),to:a,week_starts_on:n,...d,...o}})}async function Ve({baseUrl:e,accessToken:s}={}){const t=await f(s);return k()?{link_code:"mock_link_code",expires_at:new Date(Date.now()+10*6e4).toISOString()}:X({baseUrl:e,accessToken:t,slug:p.linkCodeInit,body:{}})}async function $e({baseUrl:e,accessToken:s}={}){const t=await f(s);return y({baseUrl:e,accessToken:t,slug:p.publicViewProfile})}function M({timeZone:e,tzOffsetMinutes:s}={}){const t={},a=typeof e=="string"?e.trim():"";return a&&(t.tz=a),Number.isFinite(s)&&(t.tz_offset_minutes=String(Math.trunc(s))),t}function P({source:e,model:s}={}){const t={},a=typeof e=="string"?e.trim().toLowerCase():"";a&&(t.source=a);const n=typeof s=="string"?s.trim():"";return n&&(t.model=n),t}async function y({baseUrl:e,accessToken:s,slug:t,params:a,fetchOptions:n,errorPrefix:r,retry:l,requestKind:i=h.business,skipSessionExpiry:c=!1,allowRefresh:u=!0}={}){let o=await f(s),d=E(o),v=z({baseUrl:e,accessToken:o??void 0}).getHttpClient();const C=ae(l,"GET"),b=c?h.probe:i;let A=0;const{primaryPath:j,fallbackPath:I}=Q(t);for(;;)try{const S=await G({http:v,primaryPath:j,fallbackPath:I,params:a,fetchOptions:n});return U({hadAccessToken:d,accessToken:o}),S}catch(S){const T=S;if(T?.name==="AbortError")throw S;let w=null;const B=T?.statusCode??T?.status;if(u&&se({status:B,requestKind:b,hadAccessToken:d,accessToken:o})){const g=(await te())?.accessToken??null;if(E(g)){const N=z({baseUrl:e,accessToken:g}).getHttpClient();o=g,d=!0,v=N;try{const x=await G({http:N,primaryPath:j,fallbackPath:I,params:a,fetchOptions:n});return U({hadAccessToken:!0,accessToken:g}),x}catch(x){const F=x?.statusCode??x?.status;$({status:F,hadAccessToken:!0,accessToken:g,skipSessionExpiry:b===h.probe})&&L(),w=R(x,{errorPrefix:r,hadAccessToken:!0,accessToken:g,skipSessionExpiry:!0})}}else H({hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe})&&L();w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:!0})}if(w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe}),!ne({err:w,attempt:A,retryOptions:C}))throw w;const O=re({retryOptions:C,attempt:A});await ie(O),A+=1}}async function X({baseUrl:e,accessToken:s,slug:t,body:a,fetchOptions:n,errorPrefix:r,retry:l,requestKind:i=h.business,skipSessionExpiry:c=!1,allowRefresh:u=!0}={}){let o=await f(s),d=E(o),v=z({baseUrl:e,accessToken:o??void 0}).getHttpClient();const C=ae(l,"POST"),b=c?h.probe:i;let A=0;const{primaryPath:j,fallbackPath:I}=Q(t);for(;;)try{const S=await K({http:v,primaryPath:j,fallbackPath:I,body:a,fetchOptions:n});return U({hadAccessToken:d,accessToken:o}),S}catch(S){const T=S;if(T?.name==="AbortError")throw S;let w=null;const B=T?.statusCode??T?.status;if(u&&se({status:B,requestKind:b,hadAccessToken:d,accessToken:o})){const g=(await te())?.accessToken??null;if(E(g)){const N=z({baseUrl:e,accessToken:g}).getHttpClient();o=g,d=!0,v=N;try{const x=await K({http:N,primaryPath:j,fallbackPath:I,body:a,fetchOptions:n});return U({hadAccessToken:!0,accessToken:g}),x}catch(x){const F=x?.statusCode??x?.status;$({status:F,hadAccessToken:!0,accessToken:g,skipSessionExpiry:b===h.probe})&&L(),w=R(x,{errorPrefix:r,hadAccessToken:!0,accessToken:g,skipSessionExpiry:!0})}}else H({hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe})&&L();w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:!0})}if(w??=R(T,{errorPrefix:r,hadAccessToken:d,accessToken:o,skipSessionExpiry:b===h.probe}),!ne({err:w,attempt:A,retryOptions:C}))throw w;const O=re({retryOptions:C,attempt:A});await ie(O),A+=1}}function Q(e){const s=Se(e),t=`${V(J)}/${s}`,a=`${V(be)}/${s}`;return{primaryPath:t,fallbackPath:a}}function Se(e){return(typeof e=="string"?e.trim():"").replace(/^\/+/,"")}function V(e){const s=typeof e=="string"?e.trim():"";return s.endsWith("/")?s.slice(0,-1):s}async function G({http:e,primaryPath:s,fallbackPath:t,params:a,fetchOptions:n}={}){try{return await e.get(s,{params:a,...n||{}})}catch(r){if(!Y(r,s))throw r;return await e.get(t,{params:a,...n||{}})}}async function K({http:e,primaryPath:s,fallbackPath:t,body:a,fetchOptions:n}={}){try{return await W({http:e,path:s,body:a,fetchOptions:n})}catch(r){if(!Y(r,s))throw r;return await W({http:e,path:t,body:a,fetchOptions:n})}}async function W({http:e,path:s,body:t,fetchOptions:a}={}){return await e.post(s,t,{...a||{}})}function Y(e,s){return!s||!s.startsWith(`${V(J)}/`)?!1:(e?.statusCode??e?.status)===404}function R(e,{errorPrefix:s,hadAccessToken:t,accessToken:a,skipSessionExpiry:n}={}){const r=typeof e?.message=="string"?e.message.trim():"",l=typeof e?.error=="string"?e.error.trim():"",i=r||l||String(e||"Unknown error"),c=ve(i),u=new Error(s?`${s}: ${c}`:c);u.cause=e;const o=e?.statusCode??e?.status;return $({status:o,hadAccessToken:t,accessToken:a,skipSessionExpiry:n})&&L(),typeof o=="number"&&(u.status=o,u.statusCode=o),u.retryable=Ae(o)||Me(i),c!==i&&(u.originalMessage=i),e?.nextActions&&(u.nextActions=e.nextActions),e?.error&&(u.error=e.error),u}function H({hadAccessToken:e,accessToken:s,skipSessionExpiry:t}={}){return t||!e||!E(s)?!1:Pe(s)}function $({status:e,hadAccessToken:s,accessToken:t,skipSessionExpiry:a}={}){return e!==401?!1:H({hadAccessToken:s,accessToken:t,skipSessionExpiry:a})}function _e({hadAccessToken:e,accessToken:s}={}){return H({hadAccessToken:e,accessToken:s})}function U({hadAccessToken:e,accessToken:s}={}){_e({hadAccessToken:e,accessToken:s})&&he()}function ve(e){return ee(e)?xe:String(e||"Unknown error")}function ee(e){const s=String(e||"").toLowerCase();return s?!!(s.includes("deno:")||s.includes("deno")||s.includes("econnreset")||s.includes("econnrefused")||s.includes("etimedout")||s.includes("timeout")&&s.includes("request")||s.includes("upstream")&&(s.includes("deno")||s.includes("connect"))):!1}function se({status:e,requestKind:s,hadAccessToken:t,accessToken:a}={}){return e!==401||s!==h.business?!1:H({hadAccessToken:t,accessToken:a})}async function te(){return D||(D=Te.auth.getCurrentSession().then(({data:e})=>e?.session??null).catch(()=>null).finally(()=>{D=null}),D)}function Ae(e){return e===502||e===503||e===504}function Me(e){const s=String(e||"").toLowerCase();return s?!!(ee(s)||s.includes("econnreset")||s.includes("econnrefused")||s.includes("etimedout")||s.includes("timeout")||s.includes("networkerror")||s.includes("failed to fetch")||s.includes("socket hang up")||s.includes("connection reset")):!1}function ae(e,s){const a=(s||"GET").toUpperCase()==="GET"?{maxRetries:2,baseDelayMs:300,maxDelayMs:1500,jitterRatio:.2}:{maxRetries:0,baseDelayMs:0,maxDelayMs:0,jitterRatio:0};if(e==null)return a;if(e===!1)return{maxRetries:0,baseDelayMs:0,maxDelayMs:0,jitterRatio:0};const n=q(e.maxRetries??a.maxRetries,0,10),r=q(e.baseDelayMs??a.baseDelayMs,50,6e4),l=q(e.maxDelayMs??a.maxDelayMs,r,12e4),i=typeof e.jitterRatio=="number"?Math.max(0,Math.min(.5,e.jitterRatio)):a.jitterRatio;return{maxRetries:n,baseDelayMs:r,maxDelayMs:l,jitterRatio:i}}function E(e){return!!ye(e)}function Pe(e){if(!E(e))return!1;const s=e.split(".");return s.length!==3?!1:s.every(t=>/^[A-Za-z0-9_-]+$/.test(t))}function ne({err:e,attempt:s,retryOptions:t}={}){return!t||t.maxRetries<=0||s>=t.maxRetries?!1:!!(e&&e.retryable)}function re({retryOptions:e,attempt:s}={}){if(!e||e.maxRetries<=0)return 0;const t=e.baseDelayMs*Math.pow(2,s),a=Math.min(e.maxDelayMs,t),n=a*e.jitterRatio*Math.random();return Math.round(a+n)}function q(e,s,t){const a=Number(e);return Number.isFinite(a)?Math.min(t,Math.max(s,Math.floor(a))):s}function ie(e){return!e||e<=0?Promise.resolve():new Promise(s=>setTimeout(s,e))}const _={TOP_LEFT:"┌",TOP_RIGHT:"┐",BOTTOM_LEFT:"└",BOTTOM_RIGHT:"┘",HORIZONTAL:"─",VERTICAL:"│"};function Ge({title:e,subtitle:s,children:t,className:a="",bodyClassName:n=""}){return m.jsxs("div",{className:`relative flex flex-col matrix-panel ${a}`,children:[m.jsxs("div",{className:"flex items-center leading-none",children:[m.jsx("span",{className:"shrink-0 text-matrix-dim",children:_.TOP_LEFT}),m.jsx("span",{className:"mx-3 shrink-0 text-heading uppercase text-matrix-primary px-2 py-1 bg-matrix-panelStrong border border-matrix-ghost",children:e}),s?m.jsxs("span",{className:"text-caption text-matrix-muted mr-2 uppercase",children:["[",s,"]"]}):null,m.jsx("span",{className:"flex-1 overflow-hidden whitespace-nowrap text-matrix-ghost",children:_.HORIZONTAL.repeat(100)}),m.jsx("span",{className:"shrink-0 text-matrix-dim",children:_.TOP_RIGHT})]}),m.jsxs("div",{className:"flex flex-1",children:[m.jsx("div",{className:"shrink-0 w-3 flex justify-center text-matrix-ghost",children:_.VERTICAL}),m.jsx("div",{className:`flex-1 min-w-0 py-5 px-4 relative z-10 ${n}`,children:t}),m.jsx("div",{className:"shrink-0 w-3 flex justify-center text-matrix-ghost",children:_.VERTICAL})]}),m.jsxs("div",{className:"flex items-center leading-none text-matrix-ghost",children:[m.jsx("span",{className:"shrink-0",children:_.BOTTOM_LEFT}),m.jsx("span",{className:"flex-1 overflow-hidden whitespace-nowrap",children:_.HORIZONTAL.repeat(100)}),m.jsx("span",{className:"shrink-0",children:_.BOTTOM_RIGHT})]})]})}export{Ge as A,Be as a,je as b,Oe as c,Fe as d,Ce as e,Ue as f,qe as g,Ne as h,$e as i,He as j,Ie as k,Le as l,Ee as p,Ve as r,De as s,ze as t};