@kaitranntt/ccs 5.12.1 → 5.13.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +23 -0
  2. package/VERSION +1 -1
  3. package/dist/cliproxy/account-manager.d.ts +20 -1
  4. package/dist/cliproxy/account-manager.d.ts.map +1 -1
  5. package/dist/cliproxy/account-manager.js +58 -3
  6. package/dist/cliproxy/account-manager.js.map +1 -1
  7. package/dist/cliproxy/auth-handler.d.ts +2 -0
  8. package/dist/cliproxy/auth-handler.d.ts.map +1 -1
  9. package/dist/cliproxy/auth-handler.js +68 -10
  10. package/dist/cliproxy/auth-handler.js.map +1 -1
  11. package/dist/cliproxy/cliproxy-executor.d.ts.map +1 -1
  12. package/dist/cliproxy/cliproxy-executor.js +57 -2
  13. package/dist/cliproxy/cliproxy-executor.js.map +1 -1
  14. package/dist/commands/cliproxy-command.d.ts.map +1 -1
  15. package/dist/commands/cliproxy-command.js +121 -5
  16. package/dist/commands/cliproxy-command.js.map +1 -1
  17. package/dist/commands/help-command.d.ts.map +1 -1
  18. package/dist/commands/help-command.js +3 -0
  19. package/dist/commands/help-command.js.map +1 -1
  20. package/dist/management/doctor.d.ts +10 -0
  21. package/dist/management/doctor.d.ts.map +1 -1
  22. package/dist/management/doctor.js +104 -4
  23. package/dist/management/doctor.js.map +1 -1
  24. package/dist/management/environment-diagnostics.d.ts +69 -0
  25. package/dist/management/environment-diagnostics.d.ts.map +1 -0
  26. package/dist/management/environment-diagnostics.js +229 -0
  27. package/dist/management/environment-diagnostics.js.map +1 -0
  28. package/dist/management/oauth-port-diagnostics.d.ts +85 -0
  29. package/dist/management/oauth-port-diagnostics.d.ts.map +1 -0
  30. package/dist/management/oauth-port-diagnostics.js +189 -0
  31. package/dist/management/oauth-port-diagnostics.js.map +1 -0
  32. package/dist/ui/assets/{accounts-B9xp2MbI.js → accounts-BqgbKJ_T.js} +1 -1
  33. package/dist/ui/assets/analytics-kvupQ2oO.js +64 -0
  34. package/dist/ui/assets/{api-DYr0Tx6Z.js → api-BDi9b5BG.js} +1 -1
  35. package/dist/ui/assets/cliproxy-jQ6copQ7.js +1 -0
  36. package/dist/ui/assets/{dropdown-menu-iwA6PgQW.js → dropdown-menu-DpmTYmUM.js} +1 -1
  37. package/dist/ui/assets/form-utils-DKkU3nz7.js +20 -0
  38. package/dist/ui/assets/{health-ChYme1jV.js → health-CWKKFk6T.js} +1 -1
  39. package/dist/ui/assets/icons-Pr4HmEFP.js +1 -0
  40. package/dist/ui/assets/index-BnrVxA3p.css +1 -0
  41. package/dist/ui/assets/index-JNyH4mtq.js +10 -0
  42. package/dist/ui/assets/{settings-B2OdR7RO.js → settings-D7tDThbI.js} +1 -1
  43. package/dist/ui/assets/{shared-ZSfv4HA6.js → shared-BsRfvJUd.js} +1 -1
  44. package/dist/ui/assets/{table-OTpVLgy9.js → table-DHr1Oba_.js} +1 -1
  45. package/dist/ui/index.html +4 -4
  46. package/dist/web-server/data-aggregator.d.ts +45 -0
  47. package/dist/web-server/data-aggregator.d.ts.map +1 -0
  48. package/dist/web-server/data-aggregator.js +305 -0
  49. package/dist/web-server/data-aggregator.js.map +1 -0
  50. package/dist/web-server/health-service.d.ts +1 -1
  51. package/dist/web-server/health-service.d.ts.map +1 -1
  52. package/dist/web-server/health-service.js +68 -5
  53. package/dist/web-server/health-service.js.map +1 -1
  54. package/dist/web-server/jsonl-parser.d.ts +68 -0
  55. package/dist/web-server/jsonl-parser.d.ts.map +1 -0
  56. package/dist/web-server/jsonl-parser.js +212 -0
  57. package/dist/web-server/jsonl-parser.js.map +1 -0
  58. package/dist/web-server/model-pricing.d.ts +42 -0
  59. package/dist/web-server/model-pricing.d.ts.map +1 -0
  60. package/dist/web-server/model-pricing.js +642 -0
  61. package/dist/web-server/model-pricing.js.map +1 -0
  62. package/dist/web-server/usage-disk-cache.d.ts +1 -2
  63. package/dist/web-server/usage-disk-cache.d.ts.map +1 -1
  64. package/dist/web-server/usage-disk-cache.js +2 -1
  65. package/dist/web-server/usage-disk-cache.js.map +1 -1
  66. package/dist/web-server/usage-routes.d.ts +1 -1
  67. package/dist/web-server/usage-routes.d.ts.map +1 -1
  68. package/dist/web-server/usage-routes.js +194 -11
  69. package/dist/web-server/usage-routes.js.map +1 -1
  70. package/dist/web-server/usage-types.d.ts +57 -0
  71. package/dist/web-server/usage-types.d.ts.map +1 -0
  72. package/dist/web-server/usage-types.js +9 -0
  73. package/dist/web-server/usage-types.js.map +1 -0
  74. package/package.json +3 -3
  75. package/dist/ui/assets/analytics-BfjSH3d-.js +0 -64
  76. package/dist/ui/assets/cliproxy-BuB-MuAt.js +0 -1
  77. package/dist/ui/assets/form-utils-CSa50xnO.js +0 -20
  78. package/dist/ui/assets/icons-ByUiVGTN.js +0 -1
  79. package/dist/ui/assets/index-ChihF1Y9.css +0 -1
  80. package/dist/ui/assets/index-P2CKOdyd.js +0 -10
@@ -1 +1 @@
1
- import{j as e}from"./radix-ui-DAH8Vq_G.js";import{C as s,h as t,i as r,a as i,B as a}from"./index-P2CKOdyd.js";import{J as l,m as o}from"./icons-ByUiVGTN.js";import{L as n}from"./react-vendor-CjrBBxxX.js";import"./tanstack-DAI1tKxf.js";import"./form-utils-CSa50xnO.js";function j(){return e.jsxs("div",{className:"p-6 max-w-6xl mx-auto space-y-8",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Settings"}),e.jsxs(s,{className:"border-yellow-500/50 bg-yellow-500/5",children:[e.jsx(t,{children:e.jsxs(r,{className:"flex items-center gap-2 text-yellow-600",children:[e.jsx(l,{className:"w-5 h-5"}),"Page Relocated"]})}),e.jsxs(i,{className:"space-y-4",children:[e.jsxs("p",{className:"text-muted-foreground",children:["The settings editor has been integrated into the ",e.jsx("strong",{children:"API Profiles"})," page for a better user experience."]}),e.jsx("p",{className:"text-muted-foreground",children:"To edit environment variables for a profile:"}),e.jsxs("ol",{className:"list-decimal list-inside text-muted-foreground space-y-1 ml-2",children:[e.jsx("li",{children:"Go to API Profiles page"}),e.jsx("li",{children:"Click the actions menu (...) on any profile"}),e.jsx("li",{children:'Select "Edit Settings"'})]}),e.jsx("div",{className:"pt-2",children:e.jsx(a,{asChild:!0,children:e.jsxs(n,{to:"/api",children:["Go to API Profiles",e.jsx(o,{className:"w-4 h-4 ml-2"})]})})})]})]})]})}export{j as SettingsPage};
1
+ import{j as e}from"./radix-ui-DAH8Vq_G.js";import{C as s,d as t,e as r,a as i,B as a}from"./index-JNyH4mtq.js";import{I as l,m as o}from"./icons-Pr4HmEFP.js";import{L as n}from"./react-vendor-CjrBBxxX.js";import"./tanstack-DAI1tKxf.js";import"./form-utils-DKkU3nz7.js";function j(){return e.jsxs("div",{className:"p-6 max-w-6xl mx-auto space-y-8",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Settings"}),e.jsxs(s,{className:"border-yellow-500/50 bg-yellow-500/5",children:[e.jsx(t,{children:e.jsxs(r,{className:"flex items-center gap-2 text-yellow-600",children:[e.jsx(l,{className:"w-5 h-5"}),"Page Relocated"]})}),e.jsxs(i,{className:"space-y-4",children:[e.jsxs("p",{className:"text-muted-foreground",children:["The settings editor has been integrated into the ",e.jsx("strong",{children:"API Profiles"})," page for a better user experience."]}),e.jsx("p",{className:"text-muted-foreground",children:"To edit environment variables for a profile:"}),e.jsxs("ol",{className:"list-decimal list-inside text-muted-foreground space-y-1 ml-2",children:[e.jsx("li",{children:"Go to API Profiles page"}),e.jsx("li",{children:"Click the actions menu (...) on any profile"}),e.jsx("li",{children:'Select "Edit Settings"'})]}),e.jsx("div",{className:"pt-2",children:e.jsx(a,{asChild:!0,children:e.jsxs(n,{to:"/api",children:["Go to API Profiles",e.jsx(o,{className:"w-4 h-4 ml-2"})]})})})]})]})]})}export{j as SettingsPage};
@@ -1 +1 @@
1
- import{j as s}from"./radix-ui-DAH8Vq_G.js";import{r as l}from"./react-vendor-CjrBBxxX.js";import{G as o,H as m,J as c,K as x,M as u,B as h,C as p,a as g}from"./index-P2CKOdyd.js";import{o as j,V as f,Y as N,j as b}from"./icons-ByUiVGTN.js";import"./tanstack-DAI1tKxf.js";import"./form-utils-CSa50xnO.js";function w(){const[t,i]=l.useState("commands"),{data:e}=o(),{data:n,isLoading:r}=m(t),d=[{id:"commands",label:"Commands",icon:j,count:e?.commands??0},{id:"skills",label:"Skills",icon:f,count:e?.skills??0},{id:"agents",label:"Agents",icon:N,count:e?.agents??0}];return s.jsxs("div",{className:"p-6 max-w-6xl mx-auto space-y-8",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"text-2xl font-bold",children:"Shared Data"}),s.jsx("p",{className:"text-muted-foreground",children:"Commands, skills, and agents shared across Claude instances"})]}),e&&!e.symlinkStatus.valid&&s.jsxs(c,{variant:"warning",children:[s.jsx(b,{className:"h-4 w-4"}),s.jsx(x,{children:"Configuration Required"}),s.jsxs(u,{children:[e.symlinkStatus.message,". Run `ccs sync` to configure."]})]}),s.jsx("div",{className:"flex gap-2 border-b pb-2",children:d.map(a=>s.jsxs(h,{variant:t===a.id?"default":"ghost",size:"sm",onClick:()=>i(a.id),className:"flex items-center gap-2",children:[s.jsx(a.icon,{className:"w-4 h-4"}),a.label," (",a.count,")"]},a.id))}),s.jsx("div",{className:"mt-4",children:r?s.jsx("div",{className:"text-muted-foreground",children:"Loading..."}):n?.items.length===0?s.jsxs("div",{className:"text-muted-foreground",children:["No ",t," found"]}):s.jsx("div",{className:"grid gap-3",children:n?.items.map(a=>s.jsx(p,{children:s.jsxs(g,{children:[s.jsx("div",{className:"font-medium",children:a.name}),s.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:a.description}),s.jsx("p",{className:"text-xs text-muted-foreground mt-2 font-mono truncate",children:a.path})]})},a.name))})})]})}export{w as SharedPage};
1
+ import{j as s}from"./radix-ui-DAH8Vq_G.js";import{r as l}from"./react-vendor-CjrBBxxX.js";import{y as o,z as m,A as c,E as x,F as u,B as h,C as p,a as g}from"./index-JNyH4mtq.js";import{o as j,x as f,Q as N,j as b}from"./icons-Pr4HmEFP.js";import"./tanstack-DAI1tKxf.js";import"./form-utils-DKkU3nz7.js";function w(){const[t,i]=l.useState("commands"),{data:e}=o(),{data:n,isLoading:r}=m(t),d=[{id:"commands",label:"Commands",icon:j,count:e?.commands??0},{id:"skills",label:"Skills",icon:f,count:e?.skills??0},{id:"agents",label:"Agents",icon:N,count:e?.agents??0}];return s.jsxs("div",{className:"p-6 max-w-6xl mx-auto space-y-8",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"text-2xl font-bold",children:"Shared Data"}),s.jsx("p",{className:"text-muted-foreground",children:"Commands, skills, and agents shared across Claude instances"})]}),e&&!e.symlinkStatus.valid&&s.jsxs(c,{variant:"warning",children:[s.jsx(b,{className:"h-4 w-4"}),s.jsx(x,{children:"Configuration Required"}),s.jsxs(u,{children:[e.symlinkStatus.message,". Run `ccs sync` to configure."]})]}),s.jsx("div",{className:"flex gap-2 border-b pb-2",children:d.map(a=>s.jsxs(h,{variant:t===a.id?"default":"ghost",size:"sm",onClick:()=>i(a.id),className:"flex items-center gap-2",children:[s.jsx(a.icon,{className:"w-4 h-4"}),a.label," (",a.count,")"]},a.id))}),s.jsx("div",{className:"mt-4",children:r?s.jsx("div",{className:"text-muted-foreground",children:"Loading..."}):n?.items.length===0?s.jsxs("div",{className:"text-muted-foreground",children:["No ",t," found"]}):s.jsx("div",{className:"grid gap-3",children:n?.items.map(a=>s.jsx(p,{children:s.jsxs(g,{children:[s.jsx("div",{className:"font-medium",children:a.name}),s.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:a.description}),s.jsx("p",{className:"text-xs text-muted-foreground mt-2 font-mono truncate",children:a.path})]})},a.name))})})]})}export{w as SharedPage};
@@ -1 +1 @@
1
- import{j as t}from"./radix-ui-DAH8Vq_G.js";import"./react-vendor-CjrBBxxX.js";import{c as l}from"./index-P2CKOdyd.js";function n({className:a,...e}){return t.jsx("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:t.jsx("table",{"data-slot":"table",className:l("w-full caption-bottom text-sm",a),...e})})}function c({className:a,...e}){return t.jsx("thead",{"data-slot":"table-header",className:l("[&_tr]:border-b",a),...e})}function d({className:a,...e}){return t.jsx("tbody",{"data-slot":"table-body",className:l("[&_tr:last-child]:border-0",a),...e})}function b({className:a,...e}){return t.jsx("tr",{"data-slot":"table-row",className:l("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",a),...e})}function i({className:a,...e}){return t.jsx("th",{"data-slot":"table-head",className:l("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",a),...e})}function m({className:a,...e}){return t.jsx("td",{"data-slot":"table-cell",className:l("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",a),...e})}export{n as T,c as a,b,i as c,d,m as e};
1
+ import{j as t}from"./radix-ui-DAH8Vq_G.js";import"./react-vendor-CjrBBxxX.js";import{c as l}from"./index-JNyH4mtq.js";function n({className:a,...e}){return t.jsx("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:t.jsx("table",{"data-slot":"table",className:l("w-full caption-bottom text-sm",a),...e})})}function c({className:a,...e}){return t.jsx("thead",{"data-slot":"table-header",className:l("[&_tr]:border-b",a),...e})}function d({className:a,...e}){return t.jsx("tbody",{"data-slot":"table-body",className:l("[&_tr:last-child]:border-0",a),...e})}function b({className:a,...e}){return t.jsx("tr",{"data-slot":"table-row",className:l("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",a),...e})}function i({className:a,...e}){return t.jsx("th",{"data-slot":"table-head",className:l("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",a),...e})}function m({className:a,...e}){return t.jsx("td",{"data-slot":"table-cell",className:l("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",a),...e})}export{n as T,c as a,b,i as c,d,m as e};
@@ -24,13 +24,13 @@
24
24
  href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap"
25
25
  rel="stylesheet"
26
26
  />
27
- <script type="module" crossorigin src="/assets/index-P2CKOdyd.js"></script>
27
+ <script type="module" crossorigin src="/assets/index-JNyH4mtq.js"></script>
28
28
  <link rel="modulepreload" crossorigin href="/assets/react-vendor-CjrBBxxX.js">
29
29
  <link rel="modulepreload" crossorigin href="/assets/radix-ui-DAH8Vq_G.js">
30
30
  <link rel="modulepreload" crossorigin href="/assets/tanstack-DAI1tKxf.js">
31
- <link rel="modulepreload" crossorigin href="/assets/icons-ByUiVGTN.js">
32
- <link rel="modulepreload" crossorigin href="/assets/form-utils-CSa50xnO.js">
33
- <link rel="stylesheet" crossorigin href="/assets/index-ChihF1Y9.css">
31
+ <link rel="modulepreload" crossorigin href="/assets/icons-Pr4HmEFP.js">
32
+ <link rel="modulepreload" crossorigin href="/assets/form-utils-DKkU3nz7.js">
33
+ <link rel="stylesheet" crossorigin href="/assets/index-BnrVxA3p.css">
34
34
  </head>
35
35
  <body>
36
36
  <div id="root"></div>
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Data Aggregator for Claude Code Usage Analytics
3
+ *
4
+ * Aggregates raw JSONL entries into daily, monthly, and session summaries.
5
+ * Uses model-pricing.ts for cost calculations.
6
+ */
7
+ import { type RawUsageEntry } from './jsonl-parser';
8
+ import { type DailyUsage, type MonthlyUsage, type SessionUsage } from './usage-types';
9
+ /**
10
+ * Aggregate raw entries into daily usage summaries
11
+ * Groups by date (YYYY-MM-DD), calculates costs per model
12
+ */
13
+ export declare function aggregateDailyUsage(entries: RawUsageEntry[], source?: string): DailyUsage[];
14
+ /**
15
+ * Aggregate raw entries into monthly usage summaries
16
+ * Groups by month (YYYY-MM), calculates costs per model
17
+ */
18
+ export declare function aggregateMonthlyUsage(entries: RawUsageEntry[], source?: string): MonthlyUsage[];
19
+ /**
20
+ * Aggregate raw entries into session usage summaries
21
+ * Groups by sessionId, tracks last activity and versions
22
+ */
23
+ export declare function aggregateSessionUsage(entries: RawUsageEntry[], source?: string): SessionUsage[];
24
+ import { type ParserOptions } from './jsonl-parser';
25
+ /**
26
+ * Load daily usage data (replaces better-ccusage loadDailyUsageData)
27
+ */
28
+ export declare function loadDailyUsageData(options?: ParserOptions): Promise<DailyUsage[]>;
29
+ /**
30
+ * Load monthly usage data (replaces better-ccusage loadMonthlyUsageData)
31
+ */
32
+ export declare function loadMonthlyUsageData(options?: ParserOptions): Promise<MonthlyUsage[]>;
33
+ /**
34
+ * Load session data (replaces better-ccusage loadSessionData)
35
+ */
36
+ export declare function loadSessionData(options?: ParserOptions): Promise<SessionUsage[]>;
37
+ /**
38
+ * Load all usage data in a single pass (more efficient)
39
+ */
40
+ export declare function loadAllUsageData(options?: ParserOptions): Promise<{
41
+ daily: DailyUsage[];
42
+ monthly: MonthlyUsage[];
43
+ session: SessionUsage[];
44
+ }>;
45
+ //# sourceMappingURL=data-aggregator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-aggregator.d.ts","sourceRoot":"","sources":["../../src/web-server/data-aggregator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAmDvB;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,SAAkB,GACvB,UAAU,EAAE,CAgFd;AAMD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,SAAkB,GACvB,YAAY,EAAE,CA+EhB;AAMD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,SAAkB,GACvB,YAAY,EAAE,CAqGhB;AAMD,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE3E;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGvF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAG3F;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAGtF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC;IACvE,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC,CAOD"}
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ /**
3
+ * Data Aggregator for Claude Code Usage Analytics
4
+ *
5
+ * Aggregates raw JSONL entries into daily, monthly, and session summaries.
6
+ * Uses model-pricing.ts for cost calculations.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.loadAllUsageData = exports.loadSessionData = exports.loadMonthlyUsageData = exports.loadDailyUsageData = exports.aggregateSessionUsage = exports.aggregateMonthlyUsage = exports.aggregateDailyUsage = void 0;
10
+ const model_pricing_1 = require("./model-pricing");
11
+ // ============================================================================
12
+ // HELPER FUNCTIONS
13
+ // ============================================================================
14
+ /** Extract YYYY-MM-DD from ISO timestamp */
15
+ function extractDate(timestamp) {
16
+ return timestamp.slice(0, 10);
17
+ }
18
+ /** Extract YYYY-MM from ISO timestamp */
19
+ function extractMonth(timestamp) {
20
+ return timestamp.slice(0, 7);
21
+ }
22
+ /** Create model breakdown from accumulated data */
23
+ function createModelBreakdown(modelName, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens) {
24
+ const cost = (0, model_pricing_1.calculateCost)({ inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens }, modelName);
25
+ return {
26
+ modelName,
27
+ inputTokens,
28
+ outputTokens,
29
+ cacheCreationTokens,
30
+ cacheReadTokens,
31
+ cost,
32
+ };
33
+ }
34
+ // ============================================================================
35
+ // DAILY AGGREGATION
36
+ // ============================================================================
37
+ /**
38
+ * Aggregate raw entries into daily usage summaries
39
+ * Groups by date (YYYY-MM-DD), calculates costs per model
40
+ */
41
+ function aggregateDailyUsage(entries, source = 'custom-parser') {
42
+ // Group entries by date
43
+ const byDate = new Map();
44
+ for (const entry of entries) {
45
+ const date = extractDate(entry.timestamp);
46
+ const existing = byDate.get(date) || [];
47
+ existing.push(entry);
48
+ byDate.set(date, existing);
49
+ }
50
+ // Build daily summaries
51
+ const dailyUsage = [];
52
+ for (const [date, dateEntries] of byDate) {
53
+ // Aggregate by model
54
+ const modelMap = new Map();
55
+ let totalInput = 0;
56
+ let totalOutput = 0;
57
+ let totalCacheCreation = 0;
58
+ let totalCacheRead = 0;
59
+ for (const entry of dateEntries) {
60
+ const model = entry.model;
61
+ const acc = modelMap.get(model) || {
62
+ inputTokens: 0,
63
+ outputTokens: 0,
64
+ cacheCreationTokens: 0,
65
+ cacheReadTokens: 0,
66
+ };
67
+ acc.inputTokens += entry.inputTokens;
68
+ acc.outputTokens += entry.outputTokens;
69
+ acc.cacheCreationTokens += entry.cacheCreationTokens;
70
+ acc.cacheReadTokens += entry.cacheReadTokens;
71
+ modelMap.set(model, acc);
72
+ totalInput += entry.inputTokens;
73
+ totalOutput += entry.outputTokens;
74
+ totalCacheCreation += entry.cacheCreationTokens;
75
+ totalCacheRead += entry.cacheReadTokens;
76
+ }
77
+ // Build model breakdowns
78
+ const modelBreakdowns = [];
79
+ let totalCost = 0;
80
+ for (const [modelName, acc] of modelMap) {
81
+ const breakdown = createModelBreakdown(modelName, acc.inputTokens, acc.outputTokens, acc.cacheCreationTokens, acc.cacheReadTokens);
82
+ modelBreakdowns.push(breakdown);
83
+ totalCost += breakdown.cost;
84
+ }
85
+ // Sort breakdowns by cost descending
86
+ modelBreakdowns.sort((a, b) => b.cost - a.cost);
87
+ dailyUsage.push({
88
+ date,
89
+ source,
90
+ inputTokens: totalInput,
91
+ outputTokens: totalOutput,
92
+ cacheCreationTokens: totalCacheCreation,
93
+ cacheReadTokens: totalCacheRead,
94
+ cost: totalCost,
95
+ totalCost,
96
+ modelsUsed: Array.from(modelMap.keys()),
97
+ modelBreakdowns,
98
+ });
99
+ }
100
+ // Sort by date descending (most recent first)
101
+ dailyUsage.sort((a, b) => b.date.localeCompare(a.date));
102
+ return dailyUsage;
103
+ }
104
+ exports.aggregateDailyUsage = aggregateDailyUsage;
105
+ // ============================================================================
106
+ // MONTHLY AGGREGATION
107
+ // ============================================================================
108
+ /**
109
+ * Aggregate raw entries into monthly usage summaries
110
+ * Groups by month (YYYY-MM), calculates costs per model
111
+ */
112
+ function aggregateMonthlyUsage(entries, source = 'custom-parser') {
113
+ // Group entries by month
114
+ const byMonth = new Map();
115
+ for (const entry of entries) {
116
+ const month = extractMonth(entry.timestamp);
117
+ const existing = byMonth.get(month) || [];
118
+ existing.push(entry);
119
+ byMonth.set(month, existing);
120
+ }
121
+ // Build monthly summaries
122
+ const monthlyUsage = [];
123
+ for (const [month, monthEntries] of byMonth) {
124
+ // Aggregate by model
125
+ const modelMap = new Map();
126
+ let totalInput = 0;
127
+ let totalOutput = 0;
128
+ let totalCacheCreation = 0;
129
+ let totalCacheRead = 0;
130
+ for (const entry of monthEntries) {
131
+ const model = entry.model;
132
+ const acc = modelMap.get(model) || {
133
+ inputTokens: 0,
134
+ outputTokens: 0,
135
+ cacheCreationTokens: 0,
136
+ cacheReadTokens: 0,
137
+ };
138
+ acc.inputTokens += entry.inputTokens;
139
+ acc.outputTokens += entry.outputTokens;
140
+ acc.cacheCreationTokens += entry.cacheCreationTokens;
141
+ acc.cacheReadTokens += entry.cacheReadTokens;
142
+ modelMap.set(model, acc);
143
+ totalInput += entry.inputTokens;
144
+ totalOutput += entry.outputTokens;
145
+ totalCacheCreation += entry.cacheCreationTokens;
146
+ totalCacheRead += entry.cacheReadTokens;
147
+ }
148
+ // Build model breakdowns
149
+ const modelBreakdowns = [];
150
+ let totalCost = 0;
151
+ for (const [modelName, acc] of modelMap) {
152
+ const breakdown = createModelBreakdown(modelName, acc.inputTokens, acc.outputTokens, acc.cacheCreationTokens, acc.cacheReadTokens);
153
+ modelBreakdowns.push(breakdown);
154
+ totalCost += breakdown.cost;
155
+ }
156
+ // Sort breakdowns by cost descending
157
+ modelBreakdowns.sort((a, b) => b.cost - a.cost);
158
+ monthlyUsage.push({
159
+ month,
160
+ source,
161
+ inputTokens: totalInput,
162
+ outputTokens: totalOutput,
163
+ cacheCreationTokens: totalCacheCreation,
164
+ cacheReadTokens: totalCacheRead,
165
+ totalCost,
166
+ modelsUsed: Array.from(modelMap.keys()),
167
+ modelBreakdowns,
168
+ });
169
+ }
170
+ // Sort by month descending (most recent first)
171
+ monthlyUsage.sort((a, b) => b.month.localeCompare(a.month));
172
+ return monthlyUsage;
173
+ }
174
+ exports.aggregateMonthlyUsage = aggregateMonthlyUsage;
175
+ // ============================================================================
176
+ // SESSION AGGREGATION
177
+ // ============================================================================
178
+ /**
179
+ * Aggregate raw entries into session usage summaries
180
+ * Groups by sessionId, tracks last activity and versions
181
+ */
182
+ function aggregateSessionUsage(entries, source = 'custom-parser') {
183
+ // Group entries by sessionId
184
+ const bySession = new Map();
185
+ for (const entry of entries) {
186
+ if (!entry.sessionId)
187
+ continue;
188
+ const existing = bySession.get(entry.sessionId) || [];
189
+ existing.push(entry);
190
+ bySession.set(entry.sessionId, existing);
191
+ }
192
+ // Build session summaries
193
+ const sessionUsage = [];
194
+ for (const [sessionId, sessionEntries] of bySession) {
195
+ // Aggregate by model
196
+ const modelMap = new Map();
197
+ const versions = new Set();
198
+ let totalInput = 0;
199
+ let totalOutput = 0;
200
+ let totalCacheCreation = 0;
201
+ let totalCacheRead = 0;
202
+ let lastActivity = '';
203
+ let projectPath = '';
204
+ for (const entry of sessionEntries) {
205
+ const model = entry.model;
206
+ const acc = modelMap.get(model) || {
207
+ inputTokens: 0,
208
+ outputTokens: 0,
209
+ cacheCreationTokens: 0,
210
+ cacheReadTokens: 0,
211
+ };
212
+ acc.inputTokens += entry.inputTokens;
213
+ acc.outputTokens += entry.outputTokens;
214
+ acc.cacheCreationTokens += entry.cacheCreationTokens;
215
+ acc.cacheReadTokens += entry.cacheReadTokens;
216
+ modelMap.set(model, acc);
217
+ totalInput += entry.inputTokens;
218
+ totalOutput += entry.outputTokens;
219
+ totalCacheCreation += entry.cacheCreationTokens;
220
+ totalCacheRead += entry.cacheReadTokens;
221
+ // Track latest timestamp
222
+ if (entry.timestamp > lastActivity) {
223
+ lastActivity = entry.timestamp;
224
+ }
225
+ // Track versions
226
+ if (entry.version) {
227
+ versions.add(entry.version);
228
+ }
229
+ // Use project path from entry
230
+ if (entry.projectPath) {
231
+ projectPath = entry.projectPath;
232
+ }
233
+ }
234
+ // Build model breakdowns
235
+ const modelBreakdowns = [];
236
+ let totalCost = 0;
237
+ for (const [modelName, acc] of modelMap) {
238
+ const breakdown = createModelBreakdown(modelName, acc.inputTokens, acc.outputTokens, acc.cacheCreationTokens, acc.cacheReadTokens);
239
+ modelBreakdowns.push(breakdown);
240
+ totalCost += breakdown.cost;
241
+ }
242
+ // Sort breakdowns by cost descending
243
+ modelBreakdowns.sort((a, b) => b.cost - a.cost);
244
+ sessionUsage.push({
245
+ sessionId,
246
+ projectPath,
247
+ inputTokens: totalInput,
248
+ outputTokens: totalOutput,
249
+ cacheCreationTokens: totalCacheCreation,
250
+ cacheReadTokens: totalCacheRead,
251
+ cost: totalCost,
252
+ totalCost,
253
+ lastActivity,
254
+ versions: Array.from(versions),
255
+ modelsUsed: Array.from(modelMap.keys()),
256
+ modelBreakdowns,
257
+ source,
258
+ });
259
+ }
260
+ // Sort by last activity descending (most recent first)
261
+ sessionUsage.sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
262
+ return sessionUsage;
263
+ }
264
+ exports.aggregateSessionUsage = aggregateSessionUsage;
265
+ // ============================================================================
266
+ // MAIN DATA LOADER (drop-in replacement for better-ccusage)
267
+ // ============================================================================
268
+ const jsonl_parser_1 = require("./jsonl-parser");
269
+ /**
270
+ * Load daily usage data (replaces better-ccusage loadDailyUsageData)
271
+ */
272
+ async function loadDailyUsageData(options) {
273
+ const entries = await (0, jsonl_parser_1.scanProjectsDirectory)(options);
274
+ return aggregateDailyUsage(entries);
275
+ }
276
+ exports.loadDailyUsageData = loadDailyUsageData;
277
+ /**
278
+ * Load monthly usage data (replaces better-ccusage loadMonthlyUsageData)
279
+ */
280
+ async function loadMonthlyUsageData(options) {
281
+ const entries = await (0, jsonl_parser_1.scanProjectsDirectory)(options);
282
+ return aggregateMonthlyUsage(entries);
283
+ }
284
+ exports.loadMonthlyUsageData = loadMonthlyUsageData;
285
+ /**
286
+ * Load session data (replaces better-ccusage loadSessionData)
287
+ */
288
+ async function loadSessionData(options) {
289
+ const entries = await (0, jsonl_parser_1.scanProjectsDirectory)(options);
290
+ return aggregateSessionUsage(entries);
291
+ }
292
+ exports.loadSessionData = loadSessionData;
293
+ /**
294
+ * Load all usage data in a single pass (more efficient)
295
+ */
296
+ async function loadAllUsageData(options) {
297
+ const entries = await (0, jsonl_parser_1.scanProjectsDirectory)(options);
298
+ return {
299
+ daily: aggregateDailyUsage(entries),
300
+ monthly: aggregateMonthlyUsage(entries),
301
+ session: aggregateSessionUsage(entries),
302
+ };
303
+ }
304
+ exports.loadAllUsageData = loadAllUsageData;
305
+ //# sourceMappingURL=data-aggregator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-aggregator.js","sourceRoot":"","sources":["../../src/web-server/data-aggregator.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * Health Check Service (Phase 06)
3
3
  *
4
4
  * Runs comprehensive health checks for CCS dashboard matching `ccs doctor` output.
5
- * Groups: System, Configuration, Profiles & Delegation, System Health, CLIProxy
5
+ * Groups: System, Environment, Configuration, Profiles & Delegation, System Health, CLIProxy, OAuth Readiness
6
6
  */
7
7
  export interface HealthCheck {
8
8
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"health-service.d.ts","sourceRoot":"","sources":["../../src/web-server/health-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAkF7D;AAimBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAyBrF"}
1
+ {"version":3,"file":"health-service.d.ts","sourceRoot":"","sources":["../../src/web-server/health-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAiG7D;AAqpBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAyBrF"}
@@ -3,7 +3,7 @@
3
3
  * Health Check Service (Phase 06)
4
4
  *
5
5
  * Runs comprehensive health checks for CCS dashboard matching `ccs doctor` output.
6
- * Groups: System, Configuration, Profiles & Delegation, System Health, CLIProxy
6
+ * Groups: System, Environment, Configuration, Profiles & Delegation, System Health, CLIProxy, OAuth Readiness
7
7
  */
8
8
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
9
  if (k2 === undefined) k2 = k;
@@ -42,6 +42,8 @@ const cliproxy_1 = require("../cliproxy");
42
42
  const claude_detector_1 = require("../utils/claude-detector");
43
43
  const port_utils_1 = require("../utils/port-utils");
44
44
  const package_json_1 = __importDefault(require("../../package.json"));
45
+ const environment_diagnostics_1 = require("../management/environment-diagnostics");
46
+ const oauth_port_diagnostics_1 = require("../management/oauth-port-diagnostics");
45
47
  /**
46
48
  * Run all health checks and return report
47
49
  */
@@ -56,7 +58,11 @@ async function runHealthChecks() {
56
58
  systemChecks.push(await checkClaudeCli());
57
59
  systemChecks.push(checkCcsDirectory(ccsDir));
58
60
  groups.push({ id: 'system', name: 'System', icon: 'Monitor', checks: systemChecks });
59
- // Group 2: Configuration
61
+ // Group 2: Environment (OAuth readiness diagnostics)
62
+ const envChecks = [];
63
+ envChecks.push(checkEnvironment());
64
+ groups.push({ id: 'environment', name: 'Environment', icon: 'Laptop', checks: envChecks });
65
+ // Group 3: Configuration
60
66
  const configChecks = [];
61
67
  configChecks.push(checkConfigFile());
62
68
  configChecks.push(...checkSettingsFiles(ccsDir));
@@ -67,7 +73,7 @@ async function runHealthChecks() {
67
73
  icon: 'Settings',
68
74
  checks: configChecks,
69
75
  });
70
- // Group 3: Profiles & Delegation
76
+ // Group 4: Profiles & Delegation
71
77
  const profileChecks = [];
72
78
  profileChecks.push(checkProfiles(ccsDir));
73
79
  profileChecks.push(checkInstances(ccsDir));
@@ -78,7 +84,7 @@ async function runHealthChecks() {
78
84
  icon: 'Users',
79
85
  checks: profileChecks,
80
86
  });
81
- // Group 4: System Health
87
+ // Group 5: System Health
82
88
  const healthChecks = [];
83
89
  healthChecks.push(checkPermissions(ccsDir));
84
90
  healthChecks.push(checkCcsSymlinks());
@@ -89,7 +95,7 @@ async function runHealthChecks() {
89
95
  icon: 'Shield',
90
96
  checks: healthChecks,
91
97
  });
92
- // Group 5: CLIProxy
98
+ // Group 6: CLIProxy
93
99
  const cliproxyChecks = [];
94
100
  cliproxyChecks.push(checkCliproxyBinary());
95
101
  cliproxyChecks.push(checkCliproxyConfig());
@@ -101,6 +107,15 @@ async function runHealthChecks() {
101
107
  icon: 'Zap',
102
108
  checks: cliproxyChecks,
103
109
  });
110
+ // Group 7: OAuth Readiness (port availability)
111
+ const oauthReadinessChecks = [];
112
+ oauthReadinessChecks.push(...(await checkOAuthPortsForDashboard()));
113
+ groups.push({
114
+ id: 'oauth-readiness',
115
+ name: 'OAuth Readiness',
116
+ icon: 'Key',
117
+ checks: oauthReadinessChecks,
118
+ });
104
119
  // Flatten all checks for backward compatibility
105
120
  const allChecks = groups.flatMap((g) => g.checks);
106
121
  // Calculate summary
@@ -673,6 +688,54 @@ async function checkCliproxyPort() {
673
688
  fix: `Kill process: kill ${portProcess.pid}`,
674
689
  };
675
690
  }
691
+ // Check 16: Environment (platform, SSH, TTY, browser capability)
692
+ function checkEnvironment() {
693
+ const diag = (0, environment_diagnostics_1.getEnvironmentDiagnostics)();
694
+ let status = 'ok';
695
+ let message = 'Browser available';
696
+ if (diag.detectedHeadless) {
697
+ if (diag.platform === 'win32' && diag.ttyStatus === 'undefined') {
698
+ status = 'warning';
699
+ message = 'Possible headless false positive (Windows)';
700
+ }
701
+ else if (diag.sshSession) {
702
+ status = 'info';
703
+ message = 'SSH session (headless mode)';
704
+ }
705
+ else {
706
+ status = 'info';
707
+ message = 'Headless environment';
708
+ }
709
+ }
710
+ return {
711
+ id: 'environment',
712
+ name: 'Environment',
713
+ status,
714
+ message,
715
+ details: `${diag.platformName} | SSH: ${diag.sshSession ? 'Yes' : 'No'} | Browser: ${diag.browserReason}`,
716
+ };
717
+ }
718
+ // Check 17: OAuth Ports (port availability for Gemini, Codex, Agy)
719
+ async function checkOAuthPortsForDashboard() {
720
+ const portDiagnostics = await (0, oauth_port_diagnostics_1.checkAuthCodePorts)();
721
+ return portDiagnostics.map((diag) => {
722
+ const providerName = diag.provider.charAt(0).toUpperCase() + diag.provider.slice(1);
723
+ const portStr = diag.port ? ` (${diag.port})` : '';
724
+ let status = 'ok';
725
+ if (diag.status === 'occupied')
726
+ status = 'warning';
727
+ if (diag.status === 'not_applicable')
728
+ status = 'info';
729
+ return {
730
+ id: `oauth-port-${diag.provider}`,
731
+ name: `${providerName}${portStr}`,
732
+ status,
733
+ message: diag.message,
734
+ details: diag.process ? `PID ${diag.process.pid}` : undefined,
735
+ fix: diag.recommendation || undefined,
736
+ };
737
+ });
738
+ }
676
739
  /**
677
740
  * Fix a health issue by its check ID
678
741
  */