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 +21 -33
- package/bin/tracker.js +1 -1
- package/dashboard/dist/assets/{AsciiBox-vyDhXYY5.js → AsciiBox-BTY8AuX7.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-CrplxZFL.js → DashboardPage-BNW-6Myn.js} +1 -1
- package/dashboard/dist/assets/{LandingExtras-DlrtqIDj.js → LandingExtras-C6oIZxN4.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-Czwkjje0.js → LeaderboardPage-CdAHOBHv.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfilePage-C4rorru6.js → LeaderboardProfilePage-CPBD0FCr.js} +1 -1
- package/dashboard/dist/assets/{MatrixRain-bGmRmuOW.js → MatrixRain-hFJ62iN5.js} +1 -1
- package/dashboard/dist/assets/{MatrixShell-BfOGBm5o.js → MatrixShell-BfXpCNQj.js} +1 -1
- package/dashboard/dist/assets/{main-BYPG1_bI.js → main-DepLUlUX.js} +4 -4
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/commands/init.js +7 -11
- package/src/commands/serve.js +12 -0
- package/src/commands/sync.js +9 -9
- package/src/lib/debug-flags.js +1 -1
- package/src/lib/insforge-client.js +2 -2
- package/src/lib/openclaw-hook.js +10 -10
- package/src/lib/openclaw-session-plugin.js +10 -10
- package/src/lib/opencode-config.js +1 -1
- package/src/lib/runtime-config.js +7 -7
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
|
[](https://opensource.org/licenses/MIT)
|
|
10
|
-
[](https://www.npmjs.com/package/tokentracker)
|
|
8
|
+
[](https://www.npmjs.com/package/tokentracker-cli)
|
|
11
9
|
[](https://nodejs.org/)
|
|
12
10
|
[](https://www.apple.com/macos/)
|
|
13
11
|
|
|
@@ -18,21 +16,17 @@
|
|
|
18
16
|
## Quick Start
|
|
19
17
|
|
|
20
18
|
```bash
|
|
21
|
-
|
|
22
|
-
npx tokentracker init
|
|
23
|
-
|
|
24
|
-
# View your dashboard
|
|
25
|
-
npx tokentracker
|
|
19
|
+
npx tokentracker-cli
|
|
26
20
|
```
|
|
27
21
|
|
|
28
|
-
|
|
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
|
|
35
|
-
- **
|
|
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
|
-
|
|
53
|
-
tokentracker
|
|
48
|
+
npm i -g tokentracker-cli
|
|
54
49
|
|
|
55
|
-
#
|
|
50
|
+
# Then use anywhere:
|
|
51
|
+
tokentracker # Open dashboard
|
|
56
52
|
tokentracker serve --port 3000
|
|
57
|
-
|
|
58
|
-
#
|
|
59
|
-
tokentracker
|
|
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
|
|
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
|
-
| `
|
|
106
|
-
| `
|
|
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/
|
|
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
|
|
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.
|
|
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};
|