@ipv9/tokentracker-cli 0.39.44 → 0.39.46
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/dashboard/dist/assets/{Card-C_H8B1rI.js → Card-Bk5BMQ2P.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-DPP44kwE.js +60 -0
- package/dashboard/dist/assets/{FadeIn-BE8I9B4-.js → FadeIn-CWvnEI0O.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-DQ9gR343.js → IpCheckPage-BmSn2zKd.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-Balfhw3-.js → LimitsPage-CDCccsH_.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-hxi161Wl.js → LocalOnlyNotice-D19MhLRF.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-B4zbh-jA.js → PopoverPopup-D78fYtAs.js} +1 -1
- package/dashboard/dist/assets/{Select-DLYT4NCO.js → Select-CKV1Rvl0.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-DUyZrDnS.js → SelectItemText-5eDkx616.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-BySJoulk.js → SettingsPage-DIwe50pL.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-DpiMLTPo.js → SkillsPage-zUzRrWak.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-C6je8upG.js → WidgetsPage-3yOTNqKD.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-ByarX-vY.js → WrappedPage-DPAnbLdi.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-C-WAJGZ8.js → arrow-up-right-BGg2lx0L.js} +1 -1
- package/dashboard/dist/assets/{download-BhOg_qb4.js → download-BU4HPPvG.js} +1 -1
- package/dashboard/dist/assets/{format-Co2okzG-.js → format-vw28c71d.js} +1 -1
- package/dashboard/dist/assets/limitDisplay-CY5Qlw5s.js +1 -0
- package/dashboard/dist/assets/{main-q9UoIq7C.js → main-D9Jo7Pt-.js} +7 -3
- package/dashboard/dist/assets/{mock-data-0XiGBeUV.js → mock-data-B0oPPFnn.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-DmEIJPtg.js → use-limits-display-prefs-BAGMxrq7.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-QLM3Sd2C.js → use-native-settings-C4lSH6qA.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-Dtize6Tx.js → useCurrency-Dvz0184_.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/commands/doctor.js +6 -0
- package/src/lib/doctor.js +164 -10
- package/src/lib/local-api.js +79 -20
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/process-list.js +91 -0
- package/src/lib/rollout.js +19 -9
- package/src/lib/single-flight.js +59 -0
- package/src/lib/transcript-suppression.js +133 -0
- package/src/lib/usage-limits.js +79 -19
- package/dashboard/dist/assets/DashboardPage-DOa3N76u.js +0 -60
- package/dashboard/dist/assets/limitDisplay-CPMQA7lm.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as A}from"./format-Co2okzG-.js";function ht(){if(typeof Intl>"u"||!Intl.DateTimeFormat)return null;try{return Intl.DateTimeFormat().resolvedOptions().timeZone||null}catch{return null}}function kt(t=new Date){const e=t instanceof Date?t:new Date(t);if(!Number.isFinite(e.getTime()))return 0;const n=e.getTimezoneOffset();return Number.isFinite(n)?-n:0}function V(t){if(!Number.isFinite(t)||t===0)return"UTC";const e=t>=0?"+":"-",n=Math.abs(t),o=String(Math.floor(n/60)).padStart(2,"0"),a=String(n%60).padStart(2,"0");return`UTC${e}${o}:${a}`}function bt({timeZone:t,offsetMinutes:e}={}){const n=V(e);return t&&t!=="UTC"?`${t} (${n})`:n}function wt({timeZone:t,offsetMinutes:e}={}){return Number.isFinite(e)?V(e):t||"UTC"}function Dt({timeZone:t,offsetMinutes:e,date:n=new Date}={}){const o=n instanceof Date?n:new Date(n);if(!Number.isFinite(o.getTime()))return"";if(t&&typeof Intl<"u"&&Intl.DateTimeFormat)try{const s=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(o).reduce((m,c)=>(c.type&&c.value&&(m[c.type]=c.value),m),{}),i=s.year,u=s.month,_=s.day;if(i&&u&&_)return`${i}-${u}-${_}`}catch{}if(typeof e=="number"&&Number.isFinite(e)){const a=new Date(o.getTime()+e*6e4);return J(a)}return G(o)}function Z({timeZone:t,offsetMinutes:e,date:n=new Date}={}){const o=n instanceof Date?n:new Date(n);if(!Number.isFinite(o.getTime()))return null;if(t&&typeof Intl<"u"&&Intl.DateTimeFormat)try{const s=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(o).reduce((m,c)=>(c.type&&c.value&&(m[c.type]=c.value),m),{}),i=Number(s.year),u=Number(s.month),_=Number(s.day);if(Number.isFinite(i)&&Number.isFinite(u)&&Number.isFinite(_))return{year:i,month:u,day:_}}catch{}if(typeof e=="number"&&Number.isFinite(e)){const a=new Date(o.getTime()+e*6e4);return{year:a.getUTCFullYear(),month:a.getUTCMonth()+1,day:a.getUTCDate()}}return{year:o.getFullYear(),month:o.getMonth()+1,day:o.getDate()}}function yt({timeZone:t,offsetMinutes:e}={}){return t?`tz:${t}`:typeof e=="number"&&Number.isFinite(e)?`offset:${Math.trunc(e)}`:"utc"}function J(t){const e=t.getUTCFullYear(),n=String(t.getUTCMonth()+1).padStart(2,"0"),o=String(t.getUTCDate()).padStart(2,"0");return`${e}-${n}-${o}`}function G(t){const e=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),o=String(t.getDate()).padStart(2,"0");return`${e}-${n}-${o}`}function f(t){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate())).toISOString().slice(0,10)}function F(t){const e=t instanceof Date?t:new Date(t);if(!Number.isFinite(e.getTime()))return"";const n=e.getFullYear(),o=String(e.getMonth()+1).padStart(2,"0"),a=String(e.getDate()).padStart(2,"0");return`${n}-${o}-${a}`}function Q(t){if(!t)return null;const e=String(t).trim(),n=e.split("-");if(n.length!==3)return null;const o=Number(n[0]),a=Number(n[1])-1,r=Number(n[2]);if(!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(r))return null;const s=new Date(Date.UTC(o,a,r));return Number.isFinite(s.getTime())&&f(s)===e?s:null}function X(t){if(!t)return"";const e=t.year,n=String(t.month).padStart(2,"0"),o=String(t.day).padStart(2,"0");return!e||!n||!o?"":`${e}-${n}-${o}`}function tt(t,{timeZone:e,offsetMinutes:n,now:o}={}){const a=o instanceof Date&&Number.isFinite(o.getTime())?o:new Date,r=Z({timeZone:e,offsetMinutes:n,date:a});if(!r){const u=F(new Date);return{from:u,to:u}}const s=X(r),i=Q(s);if(!i)return{from:s,to:s};if(t==="day")return{from:s,to:s};if(t==="24h"){const u=new Date(i);return u.setUTCDate(u.getUTCDate()-1),{from:f(u),to:s}}if(t==="week"){const u=new Date(i);return u.setUTCDate(u.getUTCDate()-6),{from:f(u),to:s}}if(t==="month"){const u=new Date(i);return u.setUTCDate(u.getUTCDate()-29),{from:f(u),to:s}}if(t==="total"){const u=new Date(Date.UTC(i.getUTCFullYear(),i.getUTCMonth()-23,1));return{from:f(u),to:s}}return tt("week")}function P(t){if(typeof t!="string")return null;const e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t.trim());if(!e)return null;const n=Number(e[1]),o=Number(e[2])-1,a=Number(e[3]),r=new Date(Date.UTC(n,o,a));return Number.isFinite(r.getTime())&&f(r)===t.trim()?r:null}function v(t,e){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()+e))}function et(t,e){const n=Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())-Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate());return Math.floor(n/864e5)}function R(t,e){if(!Array.isArray(t)||t.length===0)return 0;const n=t.length,o=(n-1)*e,a=Math.floor(o),r=o-a,s=t[a]??t[n-1],i=t[Math.min(n-1,a+1)]??t[n-1];return Math.round(s+(i-s)*r)}function nt(t){return t<=0?0:t>=4?4:t}function q({weeks:t=52,now:e,weekStartsOn:n="sun"}={}){const o=e instanceof Date&&Number.isFinite(e.getTime())?e:new Date,a=F(o),r=P(a)||new Date(Date.UTC(o.getFullYear(),o.getMonth(),o.getDate())),s=n==="mon"?1:0,i=r.getUTCDay(),u=v(r,-((i-s+7)%7)),_=v(u,-7*(Math.max(1,t)-1));return{from:f(_),to:a}}function ot({dailyRows:t,weeks:e=52,to:n,weekStartsOn:o="sun"}={}){const a=P(n)||new Date(Date.UTC(new Date().getFullYear(),new Date().getMonth(),new Date().getDate())),{from:r}=q({weeks:e,now:a,weekStartsOn:o}),s=P(r)||v(a,-(e*7-1)),i=(()=>{const h=(s.getUTCDay()-(o==="mon"?1:0)+7)%7;return v(s,-h)})(),u=new Map;for(const l of Array.isArray(t)?t:[]){const d=typeof l?.day=="string"?l.day:null;if(!d)continue;const h=A(l?.conversation_count)??0,y=A(l?.billable_total_tokens??l?.total_tokens)??0;u.set(d,{value:Math.max(0,h),tokens:Math.max(0,y),models:l?.models||null})}const _=et(i,a)+1,m=Math.ceil(_/7),c=[];for(let l=0;l<_;l++){const d=v(i,l),h=f(d),y=u.get(h),b=y?y.value:0;b>0&&c.push(b)}c.sort((l,d)=>l-d);const p=R(c,.5),C=R(c,.75),D=R(c,.9);function S(l){return!l||l<=0?0:l<=p?1:l<=C?2:l<=D?3:4}const g=[];for(let l=0;l<m;l++){const d=[];for(let h=0;h<7;h++){const y=l*7+h,b=v(i,y);if(b.getTime()>a.getTime()){d.push(null);continue}const M=f(b),w=u.get(M),T=w?w.value:0,N=w?w.tokens:0,x=w?w.models:null;d.push({day:M,value:T,total_tokens:N,level:nt(S(T)),models:x})}g.push(d)}const k=g.length>e?g.slice(g.length-e):g;return{from:r,to:f(a),weeks:k,thresholds:{t1:p,t2:C,t3:D}}}function at({dailyRows:t,to:e}={}){const n=P(e)||new Date(Date.UTC(new Date().getFullYear(),new Date().getMonth(),new Date().getDate())),o=new Map;for(const r of Array.isArray(t)?t:[]){const s=typeof r?.day=="string"?r.day:null;if(!s)continue;const i=A(r?.conversation_count??r?.billable_total_tokens??r?.total_tokens)??0;o.set(s,Math.max(0,i))}let a=0;for(let r=0;r<370;r++){const s=f(v(n,-r));if((o.get(s)??0)>0){a+=1;continue}break}return a}const Y={},H="tokentracker",st=["tokentracker/tokentracker","spacedriveapp/spacedrive","acme/alpha","acme/beta","neo/nebula","signal/flux","matrix/terminal","orbit/atlas","lumen/core","delta/horizon"];function rt(){if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock")||"").toLowerCase();if(e==="0"||e==="false"||e==="off"||e==="no")return!1;if(e==="1"||e==="true"||e==="on"||e==="yes")return!0}if(typeof import.meta<"u"&&Y){const t="".toLowerCase();if(t==="1"||t==="true")return!0}return!1}function it(){if(typeof import.meta<"u"&&Y){const t="".trim();if(t)return t;const e="".trim();if(e)return e}if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock_now")||"").trim();if(e)return e;const n=String(t.get("mock_today")||"").trim();if(n)return n}return""}function ut(t){if(!t)return null;const e=String(t).trim();if(!e)return null;if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[o,a,r]=e.split("-").map(Number);if(!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(r))return null;const s=new Date(o,a-1,r,12,0,0);return Number.isFinite(s.getTime())?s:null}const n=new Date(e);return Number.isFinite(n.getTime())?n:null}function Tt(){return rt()?ut(it()):null}function ct(){if(typeof import.meta<"u"&&Y){const t="".trim();if(t)return t}if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock_seed")||"").trim();if(e)return e}return H}function lt(){if(typeof import.meta<"u"&&Y){const t="".trim(),e=Number(t);if(Number.isFinite(e)&&e>0)return Math.floor(e)}if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock_missing")||"").trim(),n=Number(e);if(Number.isFinite(n)&&n>0)return Math.floor(n)}return 0}function I(t){return(t==null?ct():String(t)).trim()||H}function L(t){let e=2166136261;for(let n=0;n<t.length;n+=1)e^=t.charCodeAt(n),e=Math.imul(e,16777619);return e>>>0}function U(t){if(typeof t!="string")return null;const e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t.trim());if(!e)return null;const n=Number(e[1]),o=Number(e[2])-1,a=Number(e[3]),r=new Date(Date.UTC(n,o,a));return Number.isFinite(r.getTime())&&f(r)===t.trim()?r:null}function K(t,e){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()+e))}function W(t,e){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth()+e,1))}function _t(t){return`${t.getUTCFullYear()}-${String(t.getUTCMonth()+1).padStart(2,"0")}`}function $({from:t,to:e,seed:n}){const o=U(F(new Date))||new Date,a=U(t)||o,r=U(e)||a,s=[],i=I(n),u=Math.floor((Date.UTC(r.getUTCFullYear(),r.getUTCMonth(),r.getUTCDate())-Date.UTC(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate()))/864e5)+1;for(let _=0;_<u;_+=1){const m=K(a,_),c=f(m),p=L(`${i}:${c}`),C=p%1e3/1e3,D=.6+.4*Math.sin(_/6*Math.PI*.5),S=m.getUTCDay()===0||m.getUTCDay()===6?.65:1,g=18e3+Math.round(12e3*C),k=Math.max(0,Math.round(g*D*S)),l=Math.round(k*.46),d=Math.round(k*.34),h=Math.round(k*.14),y=Math.max(0,k-l-d-h),b={};if(k>0){const M=["gpt-4o","claude-3.5-sonnet","gemini-1.5-pro","deepseek-coder"],w=1+p%3;let T=k;for(let N=0;N<w;N++){const x=M[(p+N)%M.length];if(N===w-1)b[x]=T;else{const O=Math.round(T*(.3+.4*((p+N*17)%10)/10));b[x]=O,T-=O}}}s.push({day:c,total_tokens:k,billable_total_tokens:k,input_tokens:l,output_tokens:d,cached_input_tokens:h,reasoning_output_tokens:y,conversation_count:1+p%5,models:b})}return s}function mt({day:t,seed:e}){const n=U(t)||U(F(new Date))||new Date,o=f(n),a=I(e),r=Array.from({length:48},(i,u)=>{const _=Math.floor(u/2),m=u%2===0?0:30,c=L(`${a}:${o}:${_}:${m}`),p=c%1e3/1e3,C=(_+m/60)/24,D=.4+.6*Math.sin(C*Math.PI*2),S=900+Math.round(700*p),g=Math.max(0,Math.round(S*D)),k=Math.round(g*.46),l=Math.round(g*.34),d=Math.round(g*.14),h=Math.max(0,g-k-l-d),y={};if(g>0){const b=["gpt-4o","claude-3.5-sonnet","gemini-1.5-pro","deepseek-coder"],M=1+c%2;let w=g;for(let T=0;T<M;T++){const N=b[(c+T)%b.length];if(T===M-1)y[N]=w;else{const x=Math.round(w*(.3+.4*((c+T*17)%10)/10));y[N]=x,w-=x}}}return{hour:`${o}T${String(_).padStart(2,"0")}:${String(m).padStart(2,"0")}:00`,total_tokens:g,billable_total_tokens:g,input_tokens:k,output_tokens:l,cached_input_tokens:d,reasoning_output_tokens:h,models:y}}),s=Math.max(0,Math.min(48,lt()));if(s>0){const i=Date.now(),u=r.map((c,p)=>{const C=Date.parse(c.hour);return Number.isFinite(C)&&C<=i?{index:p,ts:C}:null}).filter(Boolean),_=Math.max(0,u.length-s),m=u.slice(_);for(const c of m){const p=r[c.index];p&&(r[c.index]={...p,missing:!0})}}return r}function dt({months:t=24,to:e,seed:n}){const o=U(e)||U(F(new Date))||new Date,a=new Date(Date.UTC(o.getUTCFullYear(),o.getUTCMonth(),1)),r=I(n),s=[];for(let i=t-1;i>=0;i-=1){const u=W(a,-i),_=_t(u),m=L(`${r}:${_}`),c=m%1e3/1e3,p=.7+.3*Math.sin(s.length/6*Math.PI*.5),C=36e4+Math.round(2e5*c),D=Math.max(0,Math.round(C*p)),S=Math.round(D*.46),g=Math.round(D*.34),k=Math.round(D*.14),l=Math.max(0,D-S-g-k),d={};if(D>0){const h=["gpt-4o","claude-3.5-sonnet","gemini-1.5-pro","deepseek-coder"],y=1+m%3;let b=D;for(let M=0;M<y;M++){const w=h[(m+M)%h.length];if(M===y-1)d[w]=b;else{const T=Math.round(b*(.3+.4*((m+M*17)%10)/10));d[w]=T,b-=T}}}s.push({month:_,total_tokens:D,billable_total_tokens:D,input_tokens:S,output_tokens:g,cached_input_tokens:k,reasoning_output_tokens:l,models:d})}return s}function B(t){return t.reduce((e,n)=>(e.total_tokens+=Number(n.total_tokens||0),e.billable_total_tokens+=Number(n.billable_total_tokens||n.total_tokens||0),e.input_tokens+=Number(n.input_tokens||0),e.output_tokens+=Number(n.output_tokens||0),e.cached_input_tokens+=Number(n.cached_input_tokens||0),e.reasoning_output_tokens+=Number(n.reasoning_output_tokens||0),e.conversation_count+=Number(n.conversation_count||0),e),{total_tokens:0,billable_total_tokens:0,input_tokens:0,output_tokens:0,cached_input_tokens:0,reasoning_output_tokens:0,conversation_count:0})}function ft(t,e=1.75){const n=Number(t||0);return!Number.isFinite(n)||n<=0?"0.000000":(n*e/1e6).toFixed(6)}function j(t,e){const n=Number.isFinite(e)?e:0;return{total_tokens:Math.max(0,Math.round(t.total_tokens*n)),billable_total_tokens:Math.max(0,Math.round((t.billable_total_tokens??t.total_tokens)*n)),input_tokens:Math.max(0,Math.round(t.input_tokens*n)),output_tokens:Math.max(0,Math.round(t.output_tokens*n)),cached_input_tokens:Math.max(0,Math.round(t.cached_input_tokens*n)),reasoning_output_tokens:Math.max(0,Math.round(t.reasoning_output_tokens*n))}}function z(t){return{...t,total_cost_usd:ft(t.total_tokens)}}function Mt({from:t,to:e,seed:n}={}){const o=$({from:t,to:e,seed:n});return{from:t,to:e,data:o}}function Ut({day:t,seed:e}={}){const n=U(t)||new Date,o=f(n),a=mt({day:o,seed:e});return{day:o,data:a}}function Ct({months:t=24,to:e,seed:n}={}){const o=U(e)||U(F(new Date))||new Date,a=f(o),r=dt({months:t,to:a,seed:n}),s=W(new Date(Date.UTC(o.getUTCFullYear(),o.getUTCMonth(),1)),-(t-1));return{from:f(s),to:a,months:t,data:r}}function Nt({from:t,to:e,seed:n,rolling:o=!0}={}){const a=$({from:t,to:e,seed:n}),r=B(a),s=z(r),i=o?gt({to:e,seed:n}):null;return{from:t,to:e,days:a.length,totals:s,...i?{rolling:i}:{}}}function gt({to:t,seed:e}={}){const n=U(t)||U(F(new Date))||new Date,o=f(n),a=f(K(n,-6)),r=f(K(n,-29)),s=$({from:a,to:o,seed:e}),i=$({from:r,to:o,seed:e});return{last_7d:E({rows:s,from:a,to:o}),last_30d:E({rows:i,from:r,to:o})}}function E({rows:t,from:e,to:n}={}){const o=B(t||[]),a=(t||[]).filter(s=>Number(s.billable_total_tokens??s.total_tokens)>0).length,r=a>0?Math.floor(o.billable_total_tokens/a):0;return{from:e,to:n,totals:{billable_total_tokens:o.billable_total_tokens,conversation_count:o.conversation_count},active_days:a,avg_per_active_day:r}}function Ft({seed:t,limit:e=3}={}){const n=I(t),o=st.map((a,r)=>{const i=12e4+L(`${n}:${a}`)%9e5,u=r%4*4200,_=Math.max(0,i+u),m=Math.max(0,Math.round(_*.96));return{project_key:a,project_ref:`https://github.com/${a}`,total_tokens:String(_),billable_total_tokens:String(m)}}).sort((a,r)=>Number(r.billable_total_tokens)-Number(a.billable_total_tokens)).slice(0,Math.max(1,Math.min(10,Math.floor(Number(e)||3))));return{generated_at:new Date().toISOString(),entries:o}}function St({weeks:t=52,to:e,weekStartsOn:n="sun",seed:o}={}){const a=q({weeks:t,now:U(e)||U(F(new Date))||new Date,weekStartsOn:n}),r=$({from:a.from,to:a.to,seed:o});return{...ot({dailyRows:r,weeks:t,to:a.to,weekStartsOn:n}),week_starts_on:n,active_days:r.filter(i=>Number(i.billable_total_tokens??i.total_tokens)>0).length,streak_days:at({dailyRows:r,to:a.to})}}function xt({from:t,to:e,seed:n}={}){const o=$({from:t,to:e,seed:n}),a=B(o),s=[{source:"codex",weight:.7,models:[{model:"gpt-5.2-codex",model_id:"gpt-5.2-codex",weight:.2},{model:"unknown",model_id:"unknown",weight:.8}]},{source:"claude",weight:.2,models:[{model:"claude-3.5",model_id:"claude-3.5",weight:.3},{model:"unknown",model_id:"unknown",weight:.7}]},{source:"every-code",weight:.1,models:[{model:"unknown",model_id:"unknown",weight:1}]}].map(i=>{const u=j(a,i.weight),_=i.models.map(m=>{const c=j(u,m.weight);return{model:m.model,model_id:m.model_id||m.model,totals:z(c)}});return{source:i.source,totals:z(u),models:_}});return{from:t,to:e,days:o.length,sources:s,pricing:{model:"mock",pricing_mode:"add",source:"mock",effective_from:F(new Date),rates_per_million_usd:{input:"1.750000",cached_input:"0.175000",output:"14.000000",reasoning_output:"14.000000"}}}}function vt(){return{fetched_at:"2025-12-31T12:00:00Z",claude:{configured:!0,plan_label:"Max",five_hour:{utilization:92},seven_day:{utilization:68}},codex:{configured:!0,plan_label:"Pro",primary_window:{used_percent:34},secondary_window:{used_percent:78}},cursor:{configured:!1},gemini:{configured:!1},kimi:{configured:!1},zai:{configured:!1},kiro:{configured:!1},copilot:{configured:!0,error:null,plan_name:"Pro",primary_window:{used_percent:52.7,used:158,limit:300,reset_at:"2026-08-01T00:00:00.000Z"},secondary_window:{used_percent:12,used:6,limit:50,reset_at:"2026-08-01T00:00:00.000Z"},otel_enabled:!1,otel_exporter_type:null,otel_path:null,otel_default_dir:"~/.copilot/otel",otel_has_files:!1},antigravity:{configured:!1}}}function $t({from:t,to:e,source:n="claude"}={}){if(n==="codex")return{from:t,to:e,source:"codex",scope:"supported",totals:{input_tokens:142e4,cached_input_tokens:588e4,cache_creation_input_tokens:92e4,output_tokens:256e4,reasoning_output_tokens:61e4,total_tokens:1078e4},session_count:188,message_count:5436,tool_calls_breakdown:{categories:[{name:"Execution",calls:742,totals:{input_tokens:32e4,cached_input_tokens:104e4,cache_creation_input_tokens:11e4,output_tokens:46e4,reasoning_output_tokens:12e4,total_tokens:193e4},tools:[{name:"exec_command",calls:510,totals:{input_tokens:25e4,cached_input_tokens:82e4,cache_creation_input_tokens:8e4,output_tokens:37e4,reasoning_output_tokens:9e4,total_tokens:152e4}},{name:"write_stdin",calls:232,totals:{input_tokens:7e4,cached_input_tokens:22e4,cache_creation_input_tokens:3e4,output_tokens:9e4,reasoning_output_tokens:3e4,total_tokens:41e4}}]},{name:"Browser",calls:406,totals:{input_tokens:21e4,cached_input_tokens:88e4,cache_creation_input_tokens:9e4,output_tokens:42e4,reasoning_output_tokens:1e5,total_tokens:17e5},tools:[{name:"take_snapshot",calls:180,totals:{input_tokens:1e5,cached_input_tokens:4e5,cache_creation_input_tokens:4e4,output_tokens:18e4,reasoning_output_tokens:4e4,total_tokens:76e4}},{name:"click",calls:126,totals:{input_tokens:6e4,cached_input_tokens:25e4,cache_creation_input_tokens:3e4,output_tokens:12e4,reasoning_output_tokens:35e3,total_tokens:495e3}},{name:"evaluate_script",calls:100,totals:{input_tokens:5e4,cached_input_tokens:23e4,cache_creation_input_tokens:2e4,output_tokens:12e4,reasoning_output_tokens:25e3,total_tokens:445e3}}]}],tools_total:363e4,privacy:{includes_inputs:!1,note:"Aggregated tool names only; no tool arguments or outputs are included."}},exec_command_breakdown:{by_type:[{name:"test",calls:168,failures:14,duration_ms:482e3,max_duration_ms:18400,output_chars:45e4,output_lines:8600,totals:{input_tokens:9e4,cached_input_tokens:32e4,output_tokens:16e4,reasoning_output_tokens:42e3,total_tokens:612e3}},{name:"build",calls:116,failures:9,duration_ms:392e3,max_duration_ms:22100,output_chars:31e4,output_lines:5200,totals:{input_tokens:7e4,cached_input_tokens:24e4,output_tokens:13e4,reasoning_output_tokens:3e4,total_tokens:47e4}}],by_exit:[{name:"completed:0",calls:438,failures:0,duration_ms:104e4,max_duration_ms:22100,output_chars:83e4,output_lines:13100,totals:{input_tokens:22e4,cached_input_tokens:78e4,output_tokens:35e4,reasoning_output_tokens:82e3,total_tokens:1432e3}},{name:"completed:1",calls:72,failures:72,duration_ms:155e3,max_duration_ms:11800,output_chars:12e4,output_lines:2300,totals:{input_tokens:3e4,cached_input_tokens:11e4,output_tokens:55e3,reasoning_output_tokens:8e3,total_tokens:195e3}}]}};if(n!=="claude")return{from:t,to:e,source:n,scope:"unsupported",totals:{input_tokens:0,cached_input_tokens:0,cache_creation_input_tokens:0,output_tokens:0,reasoning_output_tokens:0,total_tokens:0},categories:["system_prefix","conversation_history","user_input","tool_calls","subagents","reasoning","assistant_response"].map(s=>({key:s,totals:{input_tokens:0,cached_input_tokens:0,cache_creation_input_tokens:0,output_tokens:0,reasoning_output_tokens:0,total_tokens:0},percent:0})),session_count:0,message_count:0};const o=[{key:"system_prefix",total:12896539},{key:"conversation_history",total:320207200},{key:"user_input",total:998025},{key:"tool_calls",total:4808739},{key:"subagents",total:1022828},{key:"reasoning",total:11073118},{key:"assistant_response",total:1289174}],a=o.reduce((s,i)=>s+i.total,0),r=o.map(({key:s,total:i})=>({key:s,totals:{input_tokens:s==="user_input"?i:0,cached_input_tokens:s==="conversation_history"?Math.round(i*.95):0,cache_creation_input_tokens:s==="system_prefix"?i:s==="conversation_history"?Math.round(i*.05):0,output_tokens:["tool_calls","subagents","reasoning","assistant_response"].includes(s)?i:0,reasoning_output_tokens:s==="reasoning"?i:0,total_tokens:i},percent:Number((i/a*100).toFixed(2))}));return{from:t,to:e,source:"claude",scope:"supported",totals:{input_tokens:998025,cached_input_tokens:Math.round(320207200*.95),cache_creation_input_tokens:12896539+Math.round(320207200*.05),output_tokens:18193859,reasoning_output_tokens:11073118,total_tokens:a},categories:r,session_count:312,message_count:12046}}export{yt as a,ot as b,at as c,Dt as d,kt as e,f,q as g,ht as h,rt as i,Tt as j,tt as k,bt as l,wt as m,Mt as n,Nt as o,xt as p,Ut as q,Ft as r,Ct as s,St as t,vt as u,$t as v};
|
|
1
|
+
import{t as A}from"./format-vw28c71d.js";function ht(){if(typeof Intl>"u"||!Intl.DateTimeFormat)return null;try{return Intl.DateTimeFormat().resolvedOptions().timeZone||null}catch{return null}}function kt(t=new Date){const e=t instanceof Date?t:new Date(t);if(!Number.isFinite(e.getTime()))return 0;const n=e.getTimezoneOffset();return Number.isFinite(n)?-n:0}function V(t){if(!Number.isFinite(t)||t===0)return"UTC";const e=t>=0?"+":"-",n=Math.abs(t),o=String(Math.floor(n/60)).padStart(2,"0"),a=String(n%60).padStart(2,"0");return`UTC${e}${o}:${a}`}function bt({timeZone:t,offsetMinutes:e}={}){const n=V(e);return t&&t!=="UTC"?`${t} (${n})`:n}function wt({timeZone:t,offsetMinutes:e}={}){return Number.isFinite(e)?V(e):t||"UTC"}function Dt({timeZone:t,offsetMinutes:e,date:n=new Date}={}){const o=n instanceof Date?n:new Date(n);if(!Number.isFinite(o.getTime()))return"";if(t&&typeof Intl<"u"&&Intl.DateTimeFormat)try{const s=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(o).reduce((m,c)=>(c.type&&c.value&&(m[c.type]=c.value),m),{}),i=s.year,u=s.month,_=s.day;if(i&&u&&_)return`${i}-${u}-${_}`}catch{}if(typeof e=="number"&&Number.isFinite(e)){const a=new Date(o.getTime()+e*6e4);return J(a)}return G(o)}function Z({timeZone:t,offsetMinutes:e,date:n=new Date}={}){const o=n instanceof Date?n:new Date(n);if(!Number.isFinite(o.getTime()))return null;if(t&&typeof Intl<"u"&&Intl.DateTimeFormat)try{const s=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).formatToParts(o).reduce((m,c)=>(c.type&&c.value&&(m[c.type]=c.value),m),{}),i=Number(s.year),u=Number(s.month),_=Number(s.day);if(Number.isFinite(i)&&Number.isFinite(u)&&Number.isFinite(_))return{year:i,month:u,day:_}}catch{}if(typeof e=="number"&&Number.isFinite(e)){const a=new Date(o.getTime()+e*6e4);return{year:a.getUTCFullYear(),month:a.getUTCMonth()+1,day:a.getUTCDate()}}return{year:o.getFullYear(),month:o.getMonth()+1,day:o.getDate()}}function yt({timeZone:t,offsetMinutes:e}={}){return t?`tz:${t}`:typeof e=="number"&&Number.isFinite(e)?`offset:${Math.trunc(e)}`:"utc"}function J(t){const e=t.getUTCFullYear(),n=String(t.getUTCMonth()+1).padStart(2,"0"),o=String(t.getUTCDate()).padStart(2,"0");return`${e}-${n}-${o}`}function G(t){const e=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),o=String(t.getDate()).padStart(2,"0");return`${e}-${n}-${o}`}function f(t){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate())).toISOString().slice(0,10)}function F(t){const e=t instanceof Date?t:new Date(t);if(!Number.isFinite(e.getTime()))return"";const n=e.getFullYear(),o=String(e.getMonth()+1).padStart(2,"0"),a=String(e.getDate()).padStart(2,"0");return`${n}-${o}-${a}`}function Q(t){if(!t)return null;const e=String(t).trim(),n=e.split("-");if(n.length!==3)return null;const o=Number(n[0]),a=Number(n[1])-1,r=Number(n[2]);if(!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(r))return null;const s=new Date(Date.UTC(o,a,r));return Number.isFinite(s.getTime())&&f(s)===e?s:null}function X(t){if(!t)return"";const e=t.year,n=String(t.month).padStart(2,"0"),o=String(t.day).padStart(2,"0");return!e||!n||!o?"":`${e}-${n}-${o}`}function tt(t,{timeZone:e,offsetMinutes:n,now:o}={}){const a=o instanceof Date&&Number.isFinite(o.getTime())?o:new Date,r=Z({timeZone:e,offsetMinutes:n,date:a});if(!r){const u=F(new Date);return{from:u,to:u}}const s=X(r),i=Q(s);if(!i)return{from:s,to:s};if(t==="day")return{from:s,to:s};if(t==="24h"){const u=new Date(i);return u.setUTCDate(u.getUTCDate()-1),{from:f(u),to:s}}if(t==="week"){const u=new Date(i);return u.setUTCDate(u.getUTCDate()-6),{from:f(u),to:s}}if(t==="month"){const u=new Date(i);return u.setUTCDate(u.getUTCDate()-29),{from:f(u),to:s}}if(t==="total"){const u=new Date(Date.UTC(i.getUTCFullYear(),i.getUTCMonth()-23,1));return{from:f(u),to:s}}return tt("week")}function P(t){if(typeof t!="string")return null;const e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t.trim());if(!e)return null;const n=Number(e[1]),o=Number(e[2])-1,a=Number(e[3]),r=new Date(Date.UTC(n,o,a));return Number.isFinite(r.getTime())&&f(r)===t.trim()?r:null}function v(t,e){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()+e))}function et(t,e){const n=Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())-Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate());return Math.floor(n/864e5)}function R(t,e){if(!Array.isArray(t)||t.length===0)return 0;const n=t.length,o=(n-1)*e,a=Math.floor(o),r=o-a,s=t[a]??t[n-1],i=t[Math.min(n-1,a+1)]??t[n-1];return Math.round(s+(i-s)*r)}function nt(t){return t<=0?0:t>=4?4:t}function q({weeks:t=52,now:e,weekStartsOn:n="sun"}={}){const o=e instanceof Date&&Number.isFinite(e.getTime())?e:new Date,a=F(o),r=P(a)||new Date(Date.UTC(o.getFullYear(),o.getMonth(),o.getDate())),s=n==="mon"?1:0,i=r.getUTCDay(),u=v(r,-((i-s+7)%7)),_=v(u,-7*(Math.max(1,t)-1));return{from:f(_),to:a}}function ot({dailyRows:t,weeks:e=52,to:n,weekStartsOn:o="sun"}={}){const a=P(n)||new Date(Date.UTC(new Date().getFullYear(),new Date().getMonth(),new Date().getDate())),{from:r}=q({weeks:e,now:a,weekStartsOn:o}),s=P(r)||v(a,-(e*7-1)),i=(()=>{const h=(s.getUTCDay()-(o==="mon"?1:0)+7)%7;return v(s,-h)})(),u=new Map;for(const l of Array.isArray(t)?t:[]){const d=typeof l?.day=="string"?l.day:null;if(!d)continue;const h=A(l?.conversation_count)??0,y=A(l?.billable_total_tokens??l?.total_tokens)??0;u.set(d,{value:Math.max(0,h),tokens:Math.max(0,y),models:l?.models||null})}const _=et(i,a)+1,m=Math.ceil(_/7),c=[];for(let l=0;l<_;l++){const d=v(i,l),h=f(d),y=u.get(h),b=y?y.value:0;b>0&&c.push(b)}c.sort((l,d)=>l-d);const p=R(c,.5),C=R(c,.75),D=R(c,.9);function S(l){return!l||l<=0?0:l<=p?1:l<=C?2:l<=D?3:4}const g=[];for(let l=0;l<m;l++){const d=[];for(let h=0;h<7;h++){const y=l*7+h,b=v(i,y);if(b.getTime()>a.getTime()){d.push(null);continue}const M=f(b),w=u.get(M),T=w?w.value:0,N=w?w.tokens:0,x=w?w.models:null;d.push({day:M,value:T,total_tokens:N,level:nt(S(T)),models:x})}g.push(d)}const k=g.length>e?g.slice(g.length-e):g;return{from:r,to:f(a),weeks:k,thresholds:{t1:p,t2:C,t3:D}}}function at({dailyRows:t,to:e}={}){const n=P(e)||new Date(Date.UTC(new Date().getFullYear(),new Date().getMonth(),new Date().getDate())),o=new Map;for(const r of Array.isArray(t)?t:[]){const s=typeof r?.day=="string"?r.day:null;if(!s)continue;const i=A(r?.conversation_count??r?.billable_total_tokens??r?.total_tokens)??0;o.set(s,Math.max(0,i))}let a=0;for(let r=0;r<370;r++){const s=f(v(n,-r));if((o.get(s)??0)>0){a+=1;continue}break}return a}const Y={},H="tokentracker",st=["tokentracker/tokentracker","spacedriveapp/spacedrive","acme/alpha","acme/beta","neo/nebula","signal/flux","matrix/terminal","orbit/atlas","lumen/core","delta/horizon"];function rt(){if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock")||"").toLowerCase();if(e==="0"||e==="false"||e==="off"||e==="no")return!1;if(e==="1"||e==="true"||e==="on"||e==="yes")return!0}if(typeof import.meta<"u"&&Y){const t="".toLowerCase();if(t==="1"||t==="true")return!0}return!1}function it(){if(typeof import.meta<"u"&&Y){const t="".trim();if(t)return t;const e="".trim();if(e)return e}if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock_now")||"").trim();if(e)return e;const n=String(t.get("mock_today")||"").trim();if(n)return n}return""}function ut(t){if(!t)return null;const e=String(t).trim();if(!e)return null;if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[o,a,r]=e.split("-").map(Number);if(!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(r))return null;const s=new Date(o,a-1,r,12,0,0);return Number.isFinite(s.getTime())?s:null}const n=new Date(e);return Number.isFinite(n.getTime())?n:null}function Tt(){return rt()?ut(it()):null}function ct(){if(typeof import.meta<"u"&&Y){const t="".trim();if(t)return t}if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock_seed")||"").trim();if(e)return e}return H}function lt(){if(typeof import.meta<"u"&&Y){const t="".trim(),e=Number(t);if(Number.isFinite(e)&&e>0)return Math.floor(e)}if(typeof window<"u"){const t=new URLSearchParams(window.location.search),e=String(t.get("mock_missing")||"").trim(),n=Number(e);if(Number.isFinite(n)&&n>0)return Math.floor(n)}return 0}function I(t){return(t==null?ct():String(t)).trim()||H}function L(t){let e=2166136261;for(let n=0;n<t.length;n+=1)e^=t.charCodeAt(n),e=Math.imul(e,16777619);return e>>>0}function U(t){if(typeof t!="string")return null;const e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t.trim());if(!e)return null;const n=Number(e[1]),o=Number(e[2])-1,a=Number(e[3]),r=new Date(Date.UTC(n,o,a));return Number.isFinite(r.getTime())&&f(r)===t.trim()?r:null}function K(t,e){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()+e))}function W(t,e){return new Date(Date.UTC(t.getUTCFullYear(),t.getUTCMonth()+e,1))}function _t(t){return`${t.getUTCFullYear()}-${String(t.getUTCMonth()+1).padStart(2,"0")}`}function $({from:t,to:e,seed:n}){const o=U(F(new Date))||new Date,a=U(t)||o,r=U(e)||a,s=[],i=I(n),u=Math.floor((Date.UTC(r.getUTCFullYear(),r.getUTCMonth(),r.getUTCDate())-Date.UTC(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate()))/864e5)+1;for(let _=0;_<u;_+=1){const m=K(a,_),c=f(m),p=L(`${i}:${c}`),C=p%1e3/1e3,D=.6+.4*Math.sin(_/6*Math.PI*.5),S=m.getUTCDay()===0||m.getUTCDay()===6?.65:1,g=18e3+Math.round(12e3*C),k=Math.max(0,Math.round(g*D*S)),l=Math.round(k*.46),d=Math.round(k*.34),h=Math.round(k*.14),y=Math.max(0,k-l-d-h),b={};if(k>0){const M=["gpt-4o","claude-3.5-sonnet","gemini-1.5-pro","deepseek-coder"],w=1+p%3;let T=k;for(let N=0;N<w;N++){const x=M[(p+N)%M.length];if(N===w-1)b[x]=T;else{const O=Math.round(T*(.3+.4*((p+N*17)%10)/10));b[x]=O,T-=O}}}s.push({day:c,total_tokens:k,billable_total_tokens:k,input_tokens:l,output_tokens:d,cached_input_tokens:h,reasoning_output_tokens:y,conversation_count:1+p%5,models:b})}return s}function mt({day:t,seed:e}){const n=U(t)||U(F(new Date))||new Date,o=f(n),a=I(e),r=Array.from({length:48},(i,u)=>{const _=Math.floor(u/2),m=u%2===0?0:30,c=L(`${a}:${o}:${_}:${m}`),p=c%1e3/1e3,C=(_+m/60)/24,D=.4+.6*Math.sin(C*Math.PI*2),S=900+Math.round(700*p),g=Math.max(0,Math.round(S*D)),k=Math.round(g*.46),l=Math.round(g*.34),d=Math.round(g*.14),h=Math.max(0,g-k-l-d),y={};if(g>0){const b=["gpt-4o","claude-3.5-sonnet","gemini-1.5-pro","deepseek-coder"],M=1+c%2;let w=g;for(let T=0;T<M;T++){const N=b[(c+T)%b.length];if(T===M-1)y[N]=w;else{const x=Math.round(w*(.3+.4*((c+T*17)%10)/10));y[N]=x,w-=x}}}return{hour:`${o}T${String(_).padStart(2,"0")}:${String(m).padStart(2,"0")}:00`,total_tokens:g,billable_total_tokens:g,input_tokens:k,output_tokens:l,cached_input_tokens:d,reasoning_output_tokens:h,models:y}}),s=Math.max(0,Math.min(48,lt()));if(s>0){const i=Date.now(),u=r.map((c,p)=>{const C=Date.parse(c.hour);return Number.isFinite(C)&&C<=i?{index:p,ts:C}:null}).filter(Boolean),_=Math.max(0,u.length-s),m=u.slice(_);for(const c of m){const p=r[c.index];p&&(r[c.index]={...p,missing:!0})}}return r}function dt({months:t=24,to:e,seed:n}){const o=U(e)||U(F(new Date))||new Date,a=new Date(Date.UTC(o.getUTCFullYear(),o.getUTCMonth(),1)),r=I(n),s=[];for(let i=t-1;i>=0;i-=1){const u=W(a,-i),_=_t(u),m=L(`${r}:${_}`),c=m%1e3/1e3,p=.7+.3*Math.sin(s.length/6*Math.PI*.5),C=36e4+Math.round(2e5*c),D=Math.max(0,Math.round(C*p)),S=Math.round(D*.46),g=Math.round(D*.34),k=Math.round(D*.14),l=Math.max(0,D-S-g-k),d={};if(D>0){const h=["gpt-4o","claude-3.5-sonnet","gemini-1.5-pro","deepseek-coder"],y=1+m%3;let b=D;for(let M=0;M<y;M++){const w=h[(m+M)%h.length];if(M===y-1)d[w]=b;else{const T=Math.round(b*(.3+.4*((m+M*17)%10)/10));d[w]=T,b-=T}}}s.push({month:_,total_tokens:D,billable_total_tokens:D,input_tokens:S,output_tokens:g,cached_input_tokens:k,reasoning_output_tokens:l,models:d})}return s}function B(t){return t.reduce((e,n)=>(e.total_tokens+=Number(n.total_tokens||0),e.billable_total_tokens+=Number(n.billable_total_tokens||n.total_tokens||0),e.input_tokens+=Number(n.input_tokens||0),e.output_tokens+=Number(n.output_tokens||0),e.cached_input_tokens+=Number(n.cached_input_tokens||0),e.reasoning_output_tokens+=Number(n.reasoning_output_tokens||0),e.conversation_count+=Number(n.conversation_count||0),e),{total_tokens:0,billable_total_tokens:0,input_tokens:0,output_tokens:0,cached_input_tokens:0,reasoning_output_tokens:0,conversation_count:0})}function ft(t,e=1.75){const n=Number(t||0);return!Number.isFinite(n)||n<=0?"0.000000":(n*e/1e6).toFixed(6)}function j(t,e){const n=Number.isFinite(e)?e:0;return{total_tokens:Math.max(0,Math.round(t.total_tokens*n)),billable_total_tokens:Math.max(0,Math.round((t.billable_total_tokens??t.total_tokens)*n)),input_tokens:Math.max(0,Math.round(t.input_tokens*n)),output_tokens:Math.max(0,Math.round(t.output_tokens*n)),cached_input_tokens:Math.max(0,Math.round(t.cached_input_tokens*n)),reasoning_output_tokens:Math.max(0,Math.round(t.reasoning_output_tokens*n))}}function z(t){return{...t,total_cost_usd:ft(t.total_tokens)}}function Mt({from:t,to:e,seed:n}={}){const o=$({from:t,to:e,seed:n});return{from:t,to:e,data:o}}function Ut({day:t,seed:e}={}){const n=U(t)||new Date,o=f(n),a=mt({day:o,seed:e});return{day:o,data:a}}function Ct({months:t=24,to:e,seed:n}={}){const o=U(e)||U(F(new Date))||new Date,a=f(o),r=dt({months:t,to:a,seed:n}),s=W(new Date(Date.UTC(o.getUTCFullYear(),o.getUTCMonth(),1)),-(t-1));return{from:f(s),to:a,months:t,data:r}}function Nt({from:t,to:e,seed:n,rolling:o=!0}={}){const a=$({from:t,to:e,seed:n}),r=B(a),s=z(r),i=o?gt({to:e,seed:n}):null;return{from:t,to:e,days:a.length,totals:s,...i?{rolling:i}:{}}}function gt({to:t,seed:e}={}){const n=U(t)||U(F(new Date))||new Date,o=f(n),a=f(K(n,-6)),r=f(K(n,-29)),s=$({from:a,to:o,seed:e}),i=$({from:r,to:o,seed:e});return{last_7d:E({rows:s,from:a,to:o}),last_30d:E({rows:i,from:r,to:o})}}function E({rows:t,from:e,to:n}={}){const o=B(t||[]),a=(t||[]).filter(s=>Number(s.billable_total_tokens??s.total_tokens)>0).length,r=a>0?Math.floor(o.billable_total_tokens/a):0;return{from:e,to:n,totals:{billable_total_tokens:o.billable_total_tokens,conversation_count:o.conversation_count},active_days:a,avg_per_active_day:r}}function Ft({seed:t,limit:e=3}={}){const n=I(t),o=st.map((a,r)=>{const i=12e4+L(`${n}:${a}`)%9e5,u=r%4*4200,_=Math.max(0,i+u),m=Math.max(0,Math.round(_*.96));return{project_key:a,project_ref:`https://github.com/${a}`,total_tokens:String(_),billable_total_tokens:String(m)}}).sort((a,r)=>Number(r.billable_total_tokens)-Number(a.billable_total_tokens)).slice(0,Math.max(1,Math.min(10,Math.floor(Number(e)||3))));return{generated_at:new Date().toISOString(),entries:o}}function St({weeks:t=52,to:e,weekStartsOn:n="sun",seed:o}={}){const a=q({weeks:t,now:U(e)||U(F(new Date))||new Date,weekStartsOn:n}),r=$({from:a.from,to:a.to,seed:o});return{...ot({dailyRows:r,weeks:t,to:a.to,weekStartsOn:n}),week_starts_on:n,active_days:r.filter(i=>Number(i.billable_total_tokens??i.total_tokens)>0).length,streak_days:at({dailyRows:r,to:a.to})}}function xt({from:t,to:e,seed:n}={}){const o=$({from:t,to:e,seed:n}),a=B(o),s=[{source:"codex",weight:.7,models:[{model:"gpt-5.2-codex",model_id:"gpt-5.2-codex",weight:.2},{model:"unknown",model_id:"unknown",weight:.8}]},{source:"claude",weight:.2,models:[{model:"claude-3.5",model_id:"claude-3.5",weight:.3},{model:"unknown",model_id:"unknown",weight:.7}]},{source:"every-code",weight:.1,models:[{model:"unknown",model_id:"unknown",weight:1}]}].map(i=>{const u=j(a,i.weight),_=i.models.map(m=>{const c=j(u,m.weight);return{model:m.model,model_id:m.model_id||m.model,totals:z(c)}});return{source:i.source,totals:z(u),models:_}});return{from:t,to:e,days:o.length,sources:s,pricing:{model:"mock",pricing_mode:"add",source:"mock",effective_from:F(new Date),rates_per_million_usd:{input:"1.750000",cached_input:"0.175000",output:"14.000000",reasoning_output:"14.000000"}}}}function vt(){return{fetched_at:"2025-12-31T12:00:00Z",claude:{configured:!0,plan_label:"Max",five_hour:{utilization:92},seven_day:{utilization:68}},codex:{configured:!0,plan_label:"Pro",primary_window:{used_percent:34},secondary_window:{used_percent:78}},cursor:{configured:!1},gemini:{configured:!1},kimi:{configured:!1},zai:{configured:!1},kiro:{configured:!1},copilot:{configured:!0,error:null,plan_name:"Pro",primary_window:{used_percent:52.7,used:158,limit:300,reset_at:"2026-08-01T00:00:00.000Z"},secondary_window:{used_percent:12,used:6,limit:50,reset_at:"2026-08-01T00:00:00.000Z"},otel_enabled:!1,otel_exporter_type:null,otel_path:null,otel_default_dir:"~/.copilot/otel",otel_has_files:!1},antigravity:{configured:!1}}}function $t({from:t,to:e,source:n="claude"}={}){if(n==="codex")return{from:t,to:e,source:"codex",scope:"supported",totals:{input_tokens:142e4,cached_input_tokens:588e4,cache_creation_input_tokens:92e4,output_tokens:256e4,reasoning_output_tokens:61e4,total_tokens:1078e4},session_count:188,message_count:5436,tool_calls_breakdown:{categories:[{name:"Execution",calls:742,totals:{input_tokens:32e4,cached_input_tokens:104e4,cache_creation_input_tokens:11e4,output_tokens:46e4,reasoning_output_tokens:12e4,total_tokens:193e4},tools:[{name:"exec_command",calls:510,totals:{input_tokens:25e4,cached_input_tokens:82e4,cache_creation_input_tokens:8e4,output_tokens:37e4,reasoning_output_tokens:9e4,total_tokens:152e4}},{name:"write_stdin",calls:232,totals:{input_tokens:7e4,cached_input_tokens:22e4,cache_creation_input_tokens:3e4,output_tokens:9e4,reasoning_output_tokens:3e4,total_tokens:41e4}}]},{name:"Browser",calls:406,totals:{input_tokens:21e4,cached_input_tokens:88e4,cache_creation_input_tokens:9e4,output_tokens:42e4,reasoning_output_tokens:1e5,total_tokens:17e5},tools:[{name:"take_snapshot",calls:180,totals:{input_tokens:1e5,cached_input_tokens:4e5,cache_creation_input_tokens:4e4,output_tokens:18e4,reasoning_output_tokens:4e4,total_tokens:76e4}},{name:"click",calls:126,totals:{input_tokens:6e4,cached_input_tokens:25e4,cache_creation_input_tokens:3e4,output_tokens:12e4,reasoning_output_tokens:35e3,total_tokens:495e3}},{name:"evaluate_script",calls:100,totals:{input_tokens:5e4,cached_input_tokens:23e4,cache_creation_input_tokens:2e4,output_tokens:12e4,reasoning_output_tokens:25e3,total_tokens:445e3}}]}],tools_total:363e4,privacy:{includes_inputs:!1,note:"Aggregated tool names only; no tool arguments or outputs are included."}},exec_command_breakdown:{by_type:[{name:"test",calls:168,failures:14,duration_ms:482e3,max_duration_ms:18400,output_chars:45e4,output_lines:8600,totals:{input_tokens:9e4,cached_input_tokens:32e4,output_tokens:16e4,reasoning_output_tokens:42e3,total_tokens:612e3}},{name:"build",calls:116,failures:9,duration_ms:392e3,max_duration_ms:22100,output_chars:31e4,output_lines:5200,totals:{input_tokens:7e4,cached_input_tokens:24e4,output_tokens:13e4,reasoning_output_tokens:3e4,total_tokens:47e4}}],by_exit:[{name:"completed:0",calls:438,failures:0,duration_ms:104e4,max_duration_ms:22100,output_chars:83e4,output_lines:13100,totals:{input_tokens:22e4,cached_input_tokens:78e4,output_tokens:35e4,reasoning_output_tokens:82e3,total_tokens:1432e3}},{name:"completed:1",calls:72,failures:72,duration_ms:155e3,max_duration_ms:11800,output_chars:12e4,output_lines:2300,totals:{input_tokens:3e4,cached_input_tokens:11e4,output_tokens:55e3,reasoning_output_tokens:8e3,total_tokens:195e3}}]}};if(n!=="claude")return{from:t,to:e,source:n,scope:"unsupported",totals:{input_tokens:0,cached_input_tokens:0,cache_creation_input_tokens:0,output_tokens:0,reasoning_output_tokens:0,total_tokens:0},categories:["system_prefix","conversation_history","user_input","tool_calls","subagents","reasoning","assistant_response"].map(s=>({key:s,totals:{input_tokens:0,cached_input_tokens:0,cache_creation_input_tokens:0,output_tokens:0,reasoning_output_tokens:0,total_tokens:0},percent:0})),session_count:0,message_count:0};const o=[{key:"system_prefix",total:12896539},{key:"conversation_history",total:320207200},{key:"user_input",total:998025},{key:"tool_calls",total:4808739},{key:"subagents",total:1022828},{key:"reasoning",total:11073118},{key:"assistant_response",total:1289174}],a=o.reduce((s,i)=>s+i.total,0),r=o.map(({key:s,total:i})=>({key:s,totals:{input_tokens:s==="user_input"?i:0,cached_input_tokens:s==="conversation_history"?Math.round(i*.95):0,cache_creation_input_tokens:s==="system_prefix"?i:s==="conversation_history"?Math.round(i*.05):0,output_tokens:["tool_calls","subagents","reasoning","assistant_response"].includes(s)?i:0,reasoning_output_tokens:s==="reasoning"?i:0,total_tokens:i},percent:Number((i/a*100).toFixed(2))}));return{from:t,to:e,source:"claude",scope:"supported",totals:{input_tokens:998025,cached_input_tokens:Math.round(320207200*.95),cache_creation_input_tokens:12896539+Math.round(320207200*.05),output_tokens:18193859,reasoning_output_tokens:11073118,total_tokens:a},categories:r,session_count:312,message_count:12046}}export{yt as a,ot as b,at as c,Dt as d,kt as e,f,q as g,ht as h,rt as i,Tt as j,tt as k,bt as l,wt as m,Mt as n,Nt as o,xt as p,Ut as q,Ft as r,Ct as s,St as t,vt as u,$t as v};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as o,$ as I,a0 as h,a1 as C,a2 as R}from"./main-
|
|
1
|
+
import{r as o,$ as I,a0 as h,a1 as C,a2 as R}from"./main-D9Jo7Pt-.js";const d=["claude","codex","cursor","gemini","kimi","zai","kiro","copilot","antigravity"],Y={claude:"Claude",codex:"Codex",cursor:"Cursor",gemini:"Gemini",kimi:"Kimi",zai:"Z.AI",kiro:"Kiro",copilot:"GitHub Copilot",antigravity:"Antigravity"},P={claude:"/brand-logos/claude-code.svg",codex:"/brand-logos/codex.svg",cursor:"/brand-logos/cursor.svg",gemini:"/brand-logos/gemini.svg",kimi:"/brand-logos/kimi.svg",zai:null,kiro:"/brand-logos/kiro.svg",copilot:"/brand-logos/copilot.svg",antigravity:"/brand-logos/antigravity.svg"},w="tt.limits.providerOrder",m="tt.limits.providerVisibility",S="tt.limits.displayMode",p="limitsDisplayMode",f=Object.freeze({USED:"used",REMAINING:"remaining"}),E=new Set(Object.values(f));function O(){if(typeof window>"u")return[...d];try{const n=window.localStorage.getItem(w);if(!n)return[...d];const a=JSON.parse(n);if(!Array.isArray(a))return[...d];const r=a.filter(c=>d.includes(c));for(const c of d)r.includes(c)||r.push(c);return r}catch{return[...d]}}function D(){const n=Object.fromEntries(d.map(a=>[a,!0]));if(typeof window>"u")return n;try{const a=window.localStorage.getItem(m);if(!a)return n;const r=JSON.parse(a);if(!r||typeof r!="object")return n;const c={...n};for(const u of d)typeof r[u]=="boolean"&&(c[u]=r[u]);return c}catch{return n}}function v(){if(typeof window>"u")return f.USED;try{const n=window.localStorage.getItem(S);return E.has(n)?n:f.USED}catch{return f.USED}}function T(){const[n,a]=o.useState(O),[r,c]=o.useState(D),[u,l]=o.useState(v),g=o.useCallback(t=>{E.has(t)&&(l(t),I()&&h(p,t))},[]);o.useEffect(()=>{if(!(typeof window>"u"))try{window.localStorage.setItem(w,JSON.stringify(n))}catch{}},[n]),o.useEffect(()=>{if(!(typeof window>"u"))try{window.localStorage.setItem(m,JSON.stringify(r))}catch{}},[r]),o.useEffect(()=>{if(!(typeof window>"u"))try{window.localStorage.setItem(S,u)}catch{}},[u]),o.useEffect(()=>{if(!I())return;const t=C(e=>{const i=e?.[p];E.has(i)&&l(i)});return R(),t},[]),o.useEffect(()=>{if(typeof window>"u")return;const t=e=>{e.key===w&&a(O()),e.key===m&&c(D()),e.key===S&&l(v())};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)},[]);const k=o.useCallback(t=>{c(e=>({...e,[t]:!e[t]}))},[]),x=o.useCallback(t=>{a(e=>{const i=e.indexOf(t);if(i<=0)return e;const s=[...e];return[s[i-1],s[i]]=[s[i],s[i-1]],s})},[]),M=o.useCallback(t=>{a(e=>{const i=e.indexOf(t);if(i<0||i>=e.length-1)return e;const s=[...e];return[s[i],s[i+1]]=[s[i+1],s[i]],s})},[]),_=o.useCallback((t,e)=>{t!==e&&a(i=>{const s=i.indexOf(t),b=i.indexOf(e);if(s<0||b<0)return i;const y=[...i],[N]=y.splice(s,1);return y.splice(b,0,N),y})},[]),L=o.useCallback(()=>{a([...d]),c(Object.fromEntries(d.map(t=>[t,!0]))),g(f.USED)},[g]),A=o.useMemo(()=>n.filter(t=>r[t]!==!1),[n,r]);return{order:n,visibility:r,displayMode:u,setDisplayMode:g,visibleOrdered:A,toggle:k,moveUp:x,moveDown:M,moveToward:_,reset:L}}export{f as L,P as a,Y as b,T as u};
|
package/dashboard/dist/assets/{use-native-settings-QLM3Sd2C.js → use-native-settings-C4lSH6qA.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as a,x,r as n,b0 as g,b1 as m,a1 as b,a2 as u,a0 as f,a$ as h}from"./main-
|
|
1
|
+
import{j as a,x,r as n,b0 as g,b1 as m,a1 as b,a2 as u,a0 as f,a$ as h}from"./main-D9Jo7Pt-.js";import{C as y}from"./Card-Bk5BMQ2P.js";function k({checked:s,onChange:t,disabled:e,ariaLabel:i}){return a.jsx("button",{type:"button",role:"switch","aria-checked":s,"aria-label":i,onClick:t,disabled:e,className:x("relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-oai-brand-500 disabled:opacity-50 disabled:cursor-not-allowed",s?"bg-oai-brand-500":"bg-oai-gray-300 dark:bg-oai-gray-700"),children:a.jsx("span",{className:x("inline-block h-3.5 w-3.5 rounded-full bg-white transition-transform",s?"translate-x-[18px]":"translate-x-[3px]")})})}function p({label:s,hint:t,control:e}){return a.jsxs("div",{className:"flex items-center justify-between gap-4 py-3",children:[a.jsxs("div",{className:"min-w-0 flex-1",children:[a.jsx("div",{className:"text-sm text-oai-gray-900 dark:text-oai-gray-200",children:s}),t?a.jsx("div",{className:"mt-0.5 text-xs text-oai-gray-500 dark:text-oai-gray-400",children:t}):null]}),a.jsx("div",{className:"shrink-0",children:e})]})}function N({title:s,subtitle:t,action:e,children:i}){return a.jsxs(y,{children:[a.jsxs("div",{className:"mb-3 flex items-start justify-between gap-4",children:[a.jsxs("div",{className:"min-w-0 flex-1",children:[a.jsx("h2",{className:"text-sm font-medium text-oai-gray-500 dark:text-oai-gray-300 uppercase tracking-wide",children:s}),t?a.jsx("p",{className:"mt-1 truncate text-xs text-oai-gray-500 dark:text-oai-gray-400",children:t}):null]}),e?a.jsx("div",{className:"shrink-0",children:e}):null]}),a.jsx("div",{className:"-mb-3 divide-y divide-oai-gray-200/60 dark:divide-oai-gray-800/60",children:i})]})}function w({options:s,value:t,onChange:e}){return a.jsx("div",{className:"inline-flex items-center rounded-lg border border-oai-gray-200 bg-oai-gray-50 p-0.5 dark:border-oai-gray-800 dark:bg-oai-gray-900",children:s.map(({value:i,label:d,Icon:l})=>{const r=t===i;return a.jsxs("button",{type:"button",onClick:()=>e(i),"aria-pressed":r,className:x("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors",r?"bg-white text-oai-black shadow-sm dark:bg-oai-gray-800 dark:text-white":"text-oai-gray-500 hover:text-oai-black dark:text-oai-gray-400 dark:hover:text-white"),children:[l?a.jsx(l,{className:"h-3.5 w-3.5","aria-hidden":!0}):null,a.jsx("span",{children:d})]},i)})})}function S(){const[s,t]=n.useState(null),e=g()&&m();n.useEffect(()=>{if(!e)return;const r=b(o=>t(o));return u(),r},[e]);const i=n.useCallback((r,o)=>{e&&(t(c=>c&&{...c,[r]:o}),f(r,o))},[e]),d=n.useCallback(r=>{e&&h(r)},[e]),l=n.useCallback(()=>{e&&u()},[e]);return{available:e,settings:s,setSetting:i,runAction:d,refresh:l}}export{N as S,k as T,p as a,w as b,S as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e,r as t,aZ as c,a_ as r,C as a}from"./main-
|
|
1
|
+
import{c as e,r as t,aZ as c,a_ as r,C as a}from"./main-D9Jo7Pt-.js";const o=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]],C=e("info",o),n=Object.freeze({currency:a,rate:1,symbol:"$",rates:{...r},rateSource:"default",rateFetchedAt:null,setCurrency:()=>{}});function y(){return t.useContext(c)??n}export{C as I,y as u};
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
]
|
|
226
226
|
}
|
|
227
227
|
</script>
|
|
228
|
-
<script type="module" crossorigin src="/assets/main-
|
|
228
|
+
<script type="module" crossorigin src="/assets/main-D9Jo7Pt-.js"></script>
|
|
229
229
|
<link rel="stylesheet" crossorigin href="/assets/main-t7dbBL4x.css">
|
|
230
230
|
</head>
|
|
231
231
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ipv9/tokentracker-cli",
|
|
3
|
-
"version": "0.39.
|
|
3
|
+
"version": "0.39.46",
|
|
4
4
|
"description": "Local-first token and cost dashboard for 22 AI coding tools, including Claude Code, Codex, Cursor, Gemini, Kiro, OpenCode, OpenClaw, Copilot, Antigravity, Zed, and Goose.",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"bin": {
|
package/src/commands/doctor.js
CHANGED
|
@@ -6,6 +6,7 @@ const { resolveTrackerPaths } = require("../lib/tracker-paths");
|
|
|
6
6
|
const { collectTrackerDiagnostics } = require("../lib/diagnostics");
|
|
7
7
|
const { resolveRuntimeConfig } = require("../lib/runtime-config");
|
|
8
8
|
const { buildDoctorReport } = require("../lib/doctor");
|
|
9
|
+
const { detectTranscriptSuppression } = require("../lib/transcript-suppression");
|
|
9
10
|
|
|
10
11
|
async function cmdDoctor(argv = []) {
|
|
11
12
|
const opts = parseArgs(argv);
|
|
@@ -39,6 +40,11 @@ async function cmdDoctor(argv = []) {
|
|
|
39
40
|
cliPath,
|
|
40
41
|
queuePath,
|
|
41
42
|
},
|
|
43
|
+
ingest: {
|
|
44
|
+
// A one-shot read of the process list. `doctor` is not long-lived, so the
|
|
45
|
+
// module's TTL cache is bypassed here to keep the answer current.
|
|
46
|
+
transcriptSuppression: detectTranscriptSuppression({ useCache: false }),
|
|
47
|
+
},
|
|
42
48
|
});
|
|
43
49
|
|
|
44
50
|
const jsonOutput = opts.json || Boolean(opts.out);
|
package/src/lib/doctor.js
CHANGED
|
@@ -5,6 +5,11 @@ const path = require("node:path");
|
|
|
5
5
|
|
|
6
6
|
const { readJsonStrict } = require("./fs");
|
|
7
7
|
|
|
8
|
+
// Stands in for a check whose `id` is missing or not a usable string, so that such
|
|
9
|
+
// a check can still be counted rather than silently dropped. See rule 2 in
|
|
10
|
+
// `listDegradedChecks`.
|
|
11
|
+
const UNNAMED_CHECK_ID = "(unnamed)";
|
|
12
|
+
|
|
8
13
|
async function buildDoctorReport({
|
|
9
14
|
runtime = {},
|
|
10
15
|
diagnostics = null,
|
|
@@ -12,6 +17,7 @@ async function buildDoctorReport({
|
|
|
12
17
|
now = () => new Date(),
|
|
13
18
|
paths = {},
|
|
14
19
|
system = null,
|
|
20
|
+
ingest = null,
|
|
15
21
|
} = {}) {
|
|
16
22
|
const checks = [];
|
|
17
23
|
|
|
@@ -36,22 +42,133 @@ async function buildDoctorReport({
|
|
|
36
42
|
// No cloud reachability check: TokenTracker is local-only, so there is no
|
|
37
43
|
// remote endpoint whose availability could affect anything here.
|
|
38
44
|
|
|
45
|
+
if (ingest) {
|
|
46
|
+
const suppression = buildTranscriptSuppressionCheck(ingest.transcriptSuppression);
|
|
47
|
+
if (suppression) checks.push(suppression);
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
if (diagnostics) {
|
|
40
51
|
checks.push(...buildDiagnosticsChecks(diagnostics));
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
const summary = summarizeChecks(checks);
|
|
55
|
+
const degradedChecks = listDegradedChecks(checks);
|
|
44
56
|
|
|
45
57
|
return {
|
|
46
58
|
version: 1,
|
|
47
59
|
generated_at: now().toISOString(),
|
|
48
60
|
ok: summary.critical === 0,
|
|
61
|
+
// `ok` answers "should this exit non-zero", and only `critical` moves it.
|
|
62
|
+
// A warning therefore leaves an entirely green-looking report, which is
|
|
63
|
+
// exactly how a source going unrecorded stayed invisible. `degraded` is the
|
|
64
|
+
// machine-readable half of that distinction: automation can alert on it
|
|
65
|
+
// without any existing caller's exit code changing.
|
|
66
|
+
//
|
|
67
|
+
// It counts every warn and fail except a warn whose check marked itself
|
|
68
|
+
// `advisory`. A first version counted every warn, which made it useless on the
|
|
69
|
+
// one machine it was written for: that box carries a standing
|
|
70
|
+
// `queue.row_invariant` warn about two parseable invariant violations, so
|
|
71
|
+
// `degraded` read true
|
|
72
|
+
// on a perfectly healthy day and an alert wired to it could never clear. An
|
|
73
|
+
// always-on alert and an alert that never fires fail the same way.
|
|
74
|
+
// `listDegradedChecks` holds the exact rule including its two fail-closed
|
|
75
|
+
// clauses. Advisory is assigned at the individual warning return site: a
|
|
76
|
+
// standing condition can opt out without muting an actionable warning from
|
|
77
|
+
// the same check id.
|
|
78
|
+
degraded: degradedChecks.length > 0,
|
|
79
|
+
// Which checks put it there. Without this, `degraded: true` is unactionable —
|
|
80
|
+
// a consumer has to re-derive the reason by walking `checks` itself, and a
|
|
81
|
+
// human reading the JSON cannot tell a new problem from the standing one.
|
|
82
|
+
degraded_checks: degradedChecks,
|
|
49
83
|
summary,
|
|
50
84
|
checks,
|
|
51
85
|
diagnostics,
|
|
52
86
|
};
|
|
53
87
|
}
|
|
54
88
|
|
|
89
|
+
// A check is advisory when its warn describes a standing condition the operator
|
|
90
|
+
// cannot act on in the moment. Such a check still reports `warn` and still appears
|
|
91
|
+
// in `summary.warn`: the report does not become quieter, only the alert signal
|
|
92
|
+
// becomes specific. Anything that does not opt in counts, so a new check is
|
|
93
|
+
// alert-worthy by default and has to argue its way out.
|
|
94
|
+
//
|
|
95
|
+
// Two rules here are deliberately fail-CLOSED, because the failure this field
|
|
96
|
+
// exists to prevent is a real problem reading as silence, and both were live
|
|
97
|
+
// holes in the first version of this function:
|
|
98
|
+
//
|
|
99
|
+
// 1. `advisory` suppresses a `warn` and NOTHING ELSE. The rationale for the
|
|
100
|
+
// flag is about standing warnings; nothing argues for muting a `fail` on the
|
|
101
|
+
// same id, so a `fail` degrades the report whatever the flag says.
|
|
102
|
+
// 2. A check with a missing or malformed `id` is still counted, under
|
|
103
|
+
// UNNAMED_CHECK_ID. The earlier version mapped to `check.id` and then
|
|
104
|
+
// dropped non-strings, so an id typo silently removed a genuine warn from
|
|
105
|
+
// `degraded` altogether — it rendered as `[WARN] unknown` to a human and as
|
|
106
|
+
// nothing at all to automation. A placeholder keeps `degraded` and
|
|
107
|
+
// `degraded_checks` honest and in agreement.
|
|
108
|
+
function listDegradedChecks(checks = []) {
|
|
109
|
+
return checks
|
|
110
|
+
.filter((check) => check && (check.status === "warn" || check.status === "fail"))
|
|
111
|
+
// A malformed id overrides advisory suppression. Advisory is an explicit
|
|
112
|
+
// classification made at a known warning call site; if that identity is
|
|
113
|
+
// lost, fail closed under the placeholder rather than silently dropping it.
|
|
114
|
+
.filter((check) => !(
|
|
115
|
+
check.status === "warn"
|
|
116
|
+
&& check.advisory === true
|
|
117
|
+
&& typeof check.id === "string"
|
|
118
|
+
&& check.id.trim().length > 0
|
|
119
|
+
))
|
|
120
|
+
.map((check) =>
|
|
121
|
+
typeof check.id === "string" && check.id.trim().length > 0 ? check.id : UNNAMED_CHECK_ID,
|
|
122
|
+
)
|
|
123
|
+
.sort();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Reports Claude CLI processes that were started with `--no-session-persistence`.
|
|
127
|
+
// Those sessions write no transcript, and transcripts are the only thing the
|
|
128
|
+
// Claude parser can read, so their tokens are unobservable to TokenTracker.
|
|
129
|
+
//
|
|
130
|
+
// Returns null when the platform cannot answer the question at all. A check that
|
|
131
|
+
// was never run must not be printed as `[OK]` — absence is honest, a green line
|
|
132
|
+
// would not be.
|
|
133
|
+
function buildTranscriptSuppressionCheck(detection) {
|
|
134
|
+
if (!detection || detection.supported === false) return null;
|
|
135
|
+
|
|
136
|
+
const id = "ingest.transcript_suppressed";
|
|
137
|
+
|
|
138
|
+
if (!detection.checked) {
|
|
139
|
+
return {
|
|
140
|
+
id,
|
|
141
|
+
status: "warn",
|
|
142
|
+
detail: "Could not read the process list, so transcript-suppressed sessions were not checked",
|
|
143
|
+
critical: false,
|
|
144
|
+
meta: { checked: false, reason: detection.reason || "process_list_failed" },
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const count = Number(detection.count) || 0;
|
|
149
|
+
if (count === 0) {
|
|
150
|
+
return {
|
|
151
|
+
id,
|
|
152
|
+
status: "ok",
|
|
153
|
+
detail: "No Claude CLI process is running with --no-session-persistence",
|
|
154
|
+
critical: false,
|
|
155
|
+
meta: { checked: true, count: 0, models: [] },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const models = Array.isArray(detection.models) ? detection.models : [];
|
|
160
|
+
const modelSuffix = models.length ? ` (${models.join(", ")})` : "";
|
|
161
|
+
return {
|
|
162
|
+
id,
|
|
163
|
+
status: "warn",
|
|
164
|
+
detail:
|
|
165
|
+
`${count} Claude CLI process${count === 1 ? "" : "es"} running with --no-session-persistence${modelSuffix}`
|
|
166
|
+
+ " - these sessions write no transcript, so their token usage cannot be recorded",
|
|
167
|
+
critical: false,
|
|
168
|
+
meta: { checked: true, count, models },
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
55
172
|
async function buildSystemChecks({
|
|
56
173
|
nodeVersion = process.version,
|
|
57
174
|
platform = process.platform,
|
|
@@ -82,11 +199,14 @@ function buildNodeVersionCheck(nodeVersion) {
|
|
|
82
199
|
async function buildBrowserOpenerCheck({ platform = process.platform, env = process.env, commandExists }) {
|
|
83
200
|
const headless = isHeadlessEnvironment({ platform, env });
|
|
84
201
|
if (headless) {
|
|
202
|
+
// Standing environment property: neither --no-open nor opening the printed
|
|
203
|
+
// URL manually can make a headless session acquire a browser opener.
|
|
85
204
|
return {
|
|
86
205
|
id: "browser.opener",
|
|
87
206
|
status: "warn",
|
|
88
207
|
detail: "headless/session environment detected; use --no-open or open the printed URL manually",
|
|
89
208
|
critical: false,
|
|
209
|
+
advisory: true,
|
|
90
210
|
meta: { platform, command: null, headless: true },
|
|
91
211
|
};
|
|
92
212
|
}
|
|
@@ -332,14 +452,21 @@ function buildDiagnosticsChecks(diagnostics) {
|
|
|
332
452
|
notify.claude_hook_configured ||
|
|
333
453
|
notify.gemini_hook_configured ||
|
|
334
454
|
notify.opencode_plugin_configured ||
|
|
335
|
-
notify.openclaw_hook_configured
|
|
455
|
+
notify.openclaw_hook_configured ||
|
|
456
|
+
notify.openclaw_session_plugin_configured ||
|
|
457
|
+
notify.grok_hook_configured,
|
|
336
458
|
);
|
|
337
459
|
|
|
460
|
+
// This aggregate describes an optional integration preference, not whether
|
|
461
|
+
// passive log ingestion works. `init` also skips hooks for providers whose
|
|
462
|
+
// config is absent, so "none configured" can be a stable, intentional state.
|
|
463
|
+
// Keep only that warn advisory; this check currently has no fail path.
|
|
338
464
|
checks.push({
|
|
339
465
|
id: "notify.configured",
|
|
340
466
|
status: notifyConfigured ? "ok" : "warn",
|
|
341
467
|
detail: notifyConfigured ? "notify configured" : "notify not configured",
|
|
342
468
|
critical: false,
|
|
469
|
+
...(notifyConfigured ? {} : { advisory: true }),
|
|
343
470
|
meta: { configured: notifyConfigured },
|
|
344
471
|
});
|
|
345
472
|
|
|
@@ -378,8 +505,23 @@ function summarizeChecks(checks = []) {
|
|
|
378
505
|
// and how many.
|
|
379
506
|
const QUEUE_VIOLATIONS_SHOWN = 5;
|
|
380
507
|
|
|
381
|
-
|
|
382
|
-
|
|
508
|
+
// `advisory: true` keeps a warn out of `degraded` and `degraded_checks` while
|
|
509
|
+
// leaving it a full `warn` in `checks` and in `summary.warn`. The flag is decided
|
|
510
|
+
// PER CALL SITE, not once for this check id, because the two warns this check can
|
|
511
|
+
// emit are not the same kind of thing:
|
|
512
|
+
//
|
|
513
|
+
// - a parseable row-invariant violation IS advisory: the row is already written
|
|
514
|
+
// and rendered, so there is nothing the operator can do at report time.
|
|
515
|
+
// - an unparseable line or unreadable queue is NOT. Those conditions omit usage
|
|
516
|
+
// or can stop ingestion and are actionable (corruption, permissions, disk).
|
|
517
|
+
//
|
|
518
|
+
// An earlier version of this function stamped `advisory: true` on everything it
|
|
519
|
+
// returned, which silenced the unreadable case: `warn` in `checks`,
|
|
520
|
+
// `degraded: false` on the wire. Default is NOT advisory, so a new call site has
|
|
521
|
+
// to argue its way out rather than inherit silence.
|
|
522
|
+
function queueCheck(status, detail, meta, { advisory = false } = {}) {
|
|
523
|
+
const check = { id: "queue.row_invariant", status, detail, critical: false, meta };
|
|
524
|
+
return advisory ? { ...check, advisory: true } : check;
|
|
383
525
|
}
|
|
384
526
|
|
|
385
527
|
async function readQueueRowsForDoctor(queuePath) {
|
|
@@ -420,17 +562,29 @@ async function checkQueueRows(queuePath) {
|
|
|
420
562
|
const parts = [];
|
|
421
563
|
if (violations.length > 0) parts.push(`${violations.length} row problem(s)`);
|
|
422
564
|
if (malformed > 0) parts.push(`${malformed} unparseable line(s)`);
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
565
|
+
// Parseable invariant violations are already on disk and already aggregated
|
|
566
|
+
// into what the dashboard renders, so they are advisory. Malformed lines are
|
|
567
|
+
// skipped by local-api readers and their usage is absent; corruption or a
|
|
568
|
+
// partial write is actionable and must degrade the report.
|
|
569
|
+
return queueCheck(
|
|
570
|
+
"warn",
|
|
571
|
+
`${parts.join(", ")} in ${rows.length + malformed} line(s)`,
|
|
572
|
+
{
|
|
573
|
+
path: queuePath,
|
|
574
|
+
rows: rows.length,
|
|
575
|
+
malformed,
|
|
576
|
+
violations: violations.length,
|
|
577
|
+
examples: violations.slice(0, QUEUE_VIOLATIONS_SHOWN),
|
|
578
|
+
},
|
|
579
|
+
{ advisory: malformed === 0 },
|
|
580
|
+
);
|
|
430
581
|
}
|
|
431
582
|
|
|
432
583
|
module.exports = {
|
|
433
584
|
buildDoctorReport,
|
|
585
|
+
buildTranscriptSuppressionCheck,
|
|
586
|
+
listDegradedChecks,
|
|
587
|
+
UNNAMED_CHECK_ID,
|
|
434
588
|
checkQueueRows,
|
|
435
589
|
buildBrowserOpenerCheck,
|
|
436
590
|
buildNodeVersionCheck,
|
package/src/lib/local-api.js
CHANGED
|
@@ -743,6 +743,40 @@ function json(res, data, status) {
|
|
|
743
743
|
const IP_CHECK_PROXY_PREFIX = "/proxy/ipcheck";
|
|
744
744
|
const IP_CHECK_TARGET = "https://ip.net.coffee";
|
|
745
745
|
|
|
746
|
+
const LOCAL_API_METHODS = new Map([
|
|
747
|
+
["/api/local-auth", ["GET"]],
|
|
748
|
+
["/proxy/ipcheck", ["GET", "HEAD"]],
|
|
749
|
+
["/api/avatar-proxy", ["GET", "HEAD"]],
|
|
750
|
+
["/functions/tokentracker-local-sync", ["POST"]],
|
|
751
|
+
["/functions/tokentracker-wrapped", ["GET"]],
|
|
752
|
+
["/functions/tokentracker-usage-summary", ["GET"]],
|
|
753
|
+
["/functions/tokentracker-usage-daily", ["GET"]],
|
|
754
|
+
["/functions/tokentracker-usage-heatmap", ["GET"]],
|
|
755
|
+
["/functions/tokentracker-usage-model-breakdown", ["GET"]],
|
|
756
|
+
["/functions/tokentracker-usage-category-breakdown", ["GET"]],
|
|
757
|
+
["/functions/tokentracker-project-usage-summary", ["GET"]],
|
|
758
|
+
["/functions/tokentracker-user-status", ["GET"]],
|
|
759
|
+
["/functions/tokentracker-usage-hourly", ["GET"]],
|
|
760
|
+
["/functions/tokentracker-usage-monthly", ["GET"]],
|
|
761
|
+
["/functions/tokentracker-skills", ["GET", "POST"]],
|
|
762
|
+
["/functions/tokentracker-usage-limits", ["GET"]],
|
|
763
|
+
["/functions/tokentracker-ingest-health", ["GET"]],
|
|
764
|
+
]);
|
|
765
|
+
|
|
766
|
+
// Preserve the established JSON shape for the two mutation-capable endpoints
|
|
767
|
+
// that already returned `{ ok: false, error }` for unsupported methods.
|
|
768
|
+
const LOCAL_API_OK_FALSE_METHOD_ERRORS = new Set([
|
|
769
|
+
"/functions/tokentracker-local-sync",
|
|
770
|
+
"/functions/tokentracker-skills",
|
|
771
|
+
]);
|
|
772
|
+
|
|
773
|
+
function allowedMethodsForLocalApiPath(pathname) {
|
|
774
|
+
return LOCAL_API_METHODS.get(pathname)
|
|
775
|
+
|| (pathname.startsWith(`${IP_CHECK_PROXY_PREFIX}/`)
|
|
776
|
+
? LOCAL_API_METHODS.get(IP_CHECK_PROXY_PREFIX)
|
|
777
|
+
: null);
|
|
778
|
+
}
|
|
779
|
+
|
|
746
780
|
// HTTP hop-by-hop headers (RFC 7230 §6.1) plus headers undici/fetch manages
|
|
747
781
|
// internally. Forwarding any of these to `fetch(...)` either silently breaks
|
|
748
782
|
// the request (host being wrong) or, on stricter undici versions like the
|
|
@@ -961,12 +995,21 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
961
995
|
|
|
962
996
|
return async function handleLocalApi(req, res, url) {
|
|
963
997
|
const p = url.pathname;
|
|
998
|
+
const allowedMethods = allowedMethodsForLocalApiPath(p);
|
|
999
|
+
const method = String(req.method || "GET").toUpperCase();
|
|
1000
|
+
if (allowedMethods && !allowedMethods.includes(method)) {
|
|
1001
|
+
const error = "Method Not Allowed";
|
|
1002
|
+
res.writeHead(405, {
|
|
1003
|
+
"Content-Type": "application/json",
|
|
1004
|
+
Allow: allowedMethods.join(", "),
|
|
1005
|
+
});
|
|
1006
|
+
res.end(JSON.stringify(
|
|
1007
|
+
LOCAL_API_OK_FALSE_METHOD_ERRORS.has(p) ? { ok: false, error } : { error },
|
|
1008
|
+
));
|
|
1009
|
+
return true;
|
|
1010
|
+
}
|
|
964
1011
|
|
|
965
1012
|
if (p === "/api/local-auth") {
|
|
966
|
-
if (String(req.method || "GET").toUpperCase() !== "GET") {
|
|
967
|
-
json(res, { error: "Method Not Allowed" }, 405);
|
|
968
|
-
return true;
|
|
969
|
-
}
|
|
970
1013
|
res.writeHead(200, {
|
|
971
1014
|
"Content-Type": "application/json",
|
|
972
1015
|
"Cache-Control": "no-store",
|
|
@@ -982,10 +1025,6 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
982
1025
|
// (exfiltrate dashboard cookies, anonymously POST through user IP).
|
|
983
1026
|
if (p.startsWith(`${IP_CHECK_PROXY_PREFIX}/`) || p === IP_CHECK_PROXY_PREFIX) {
|
|
984
1027
|
const method = String(req.method || "GET").toUpperCase();
|
|
985
|
-
if (method !== "GET" && method !== "HEAD") {
|
|
986
|
-
json(res, { error: "Method Not Allowed" }, 405);
|
|
987
|
-
return true;
|
|
988
|
-
}
|
|
989
1028
|
const targetPath = p === IP_CHECK_PROXY_PREFIX
|
|
990
1029
|
? "/"
|
|
991
1030
|
: p.slice(IP_CHECK_PROXY_PREFIX.length) || "/";
|
|
@@ -1057,10 +1096,6 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
1057
1096
|
// proxy); strip cookies/auth; small in-memory cache.
|
|
1058
1097
|
if (p === "/api/avatar-proxy") {
|
|
1059
1098
|
const method = String(req.method || "GET").toUpperCase();
|
|
1060
|
-
if (method !== "GET" && method !== "HEAD") {
|
|
1061
|
-
json(res, { error: "Method Not Allowed" }, 405);
|
|
1062
|
-
return true;
|
|
1063
|
-
}
|
|
1064
1099
|
const target = url.searchParams.get("url");
|
|
1065
1100
|
if (!target) {
|
|
1066
1101
|
json(res, { error: "Missing url" }, 400);
|
|
@@ -1164,10 +1199,6 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
1164
1199
|
|
|
1165
1200
|
// --- local-sync (POST) ---
|
|
1166
1201
|
if (p === "/functions/tokentracker-local-sync") {
|
|
1167
|
-
if (String(req.method || "GET").toUpperCase() !== "POST") {
|
|
1168
|
-
json(res, { ok: false, error: "Method Not Allowed" }, 405);
|
|
1169
|
-
return true;
|
|
1170
|
-
}
|
|
1171
1202
|
if (!isAuthorizedLocalMutation(req)) {
|
|
1172
1203
|
json(res, { ok: false, error: "Unauthorized" }, 401);
|
|
1173
1204
|
return true;
|
|
@@ -1706,7 +1737,6 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
1706
1737
|
return true;
|
|
1707
1738
|
}
|
|
1708
1739
|
|
|
1709
|
-
json(res, { ok: false, error: "Method Not Allowed" }, 405);
|
|
1710
1740
|
} catch (e) {
|
|
1711
1741
|
json(res, { ok: false, error: e?.message || "Unknown skills error" }, 500);
|
|
1712
1742
|
}
|
|
@@ -1715,10 +1745,9 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
1715
1745
|
|
|
1716
1746
|
// --- usage-limits ---
|
|
1717
1747
|
if (p === "/functions/tokentracker-usage-limits") {
|
|
1718
|
-
const { getUsageLimits, resetUsageLimitsCache } = require("./usage-limits");
|
|
1748
|
+
const { getUsageLimits, isForcedRefresh, resetUsageLimitsCache } = require("./usage-limits");
|
|
1719
1749
|
try {
|
|
1720
|
-
|
|
1721
|
-
if (forceRefresh === "1" || forceRefresh === "true") {
|
|
1750
|
+
if (isForcedRefresh(url.searchParams.get("refresh"))) {
|
|
1722
1751
|
resetUsageLimitsCache();
|
|
1723
1752
|
}
|
|
1724
1753
|
const data = await getUsageLimits({
|
|
@@ -1733,6 +1762,36 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
1733
1762
|
return true;
|
|
1734
1763
|
}
|
|
1735
1764
|
|
|
1765
|
+
// --- ingest-health ---
|
|
1766
|
+
// Reports collection problems that make a source under-report without any
|
|
1767
|
+
// error: right now, Claude CLI sessions started with
|
|
1768
|
+
// `--no-session-persistence`, which write no transcript for the parser to
|
|
1769
|
+
// read. Served from the module's short TTL cache so that a dashboard poll
|
|
1770
|
+
// cannot turn into a process spawn per request.
|
|
1771
|
+
//
|
|
1772
|
+
// The payload is deliberately narrow — a count, model ids, and a coarse
|
|
1773
|
+
// reason. No pid, argv, or environment value is returned, because this
|
|
1774
|
+
// endpoint answers unauthenticated loopback GETs.
|
|
1775
|
+
if (p === "/functions/tokentracker-ingest-health") {
|
|
1776
|
+
const { detectTranscriptSuppression } = require("./transcript-suppression");
|
|
1777
|
+
try {
|
|
1778
|
+
const suppression = detectTranscriptSuppression({ platform: process.platform });
|
|
1779
|
+
json(res, {
|
|
1780
|
+
transcript_suppressed: {
|
|
1781
|
+
supported: suppression.supported,
|
|
1782
|
+
checked: suppression.checked,
|
|
1783
|
+
count: suppression.count,
|
|
1784
|
+
models: suppression.models,
|
|
1785
|
+
reason: suppression.reason,
|
|
1786
|
+
},
|
|
1787
|
+
checked_at: suppression.checked_at,
|
|
1788
|
+
});
|
|
1789
|
+
} catch (e) {
|
|
1790
|
+
json(res, { error: e?.message || "Unknown error" }, 500);
|
|
1791
|
+
}
|
|
1792
|
+
return true;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1736
1795
|
return false;
|
|
1737
1796
|
};
|
|
1738
1797
|
}
|