@kaitranntt/ccs 7.51.0-dev.4 → 7.51.0-dev.6

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 (44) hide show
  1. package/README.md +1 -1
  2. package/dist/cliproxy/stats-fetcher.d.ts +41 -0
  3. package/dist/cliproxy/stats-fetcher.d.ts.map +1 -1
  4. package/dist/cliproxy/stats-fetcher.js +32 -1
  5. package/dist/cliproxy/stats-fetcher.js.map +1 -1
  6. package/dist/ui/assets/{accounts-Cs_Uohn7.js → accounts-CbGqm04Q.js} +1 -1
  7. package/dist/ui/assets/{alert-dialog-cRwDSggu.js → alert-dialog-zpinTbtF.js} +1 -1
  8. package/dist/ui/assets/{api-C73W2Hb1.js → api-CalCxo_A.js} +1 -1
  9. package/dist/ui/assets/{auth-section-DgF431PH.js → auth-section-BjuUeaLO.js} +1 -1
  10. package/dist/ui/assets/{backups-section-9V2yDu_e.js → backups-section-DNkq5ZUy.js} +1 -1
  11. package/dist/ui/assets/{checkbox-BeoeEcEZ.js → checkbox-Df7G7a1w.js} +1 -1
  12. package/dist/ui/assets/{cliproxy-DAlyh7zw.js → cliproxy-DLwo08Aq.js} +1 -1
  13. package/dist/ui/assets/{cliproxy-control-panel-CE4y4VDk.js → cliproxy-control-panel--SMhq8Fs.js} +1 -1
  14. package/dist/ui/assets/{confirm-dialog-COTT5ztZ.js → confirm-dialog-Dl3qe-0j.js} +1 -1
  15. package/dist/ui/assets/{copilot-Cm5PT0v6.js → copilot-CdJG-Shj.js} +1 -1
  16. package/dist/ui/assets/{cursor-DYhCaKbC.js → cursor-DMH09Hqq.js} +1 -1
  17. package/dist/ui/assets/{droid-eTM2_tVh.js → droid-ufxKKFsV.js} +1 -1
  18. package/dist/ui/assets/{globalenv-section-Dzt_ECFK.js → globalenv-section-CZMJi0Tl.js} +1 -1
  19. package/dist/ui/assets/{health-Bk8Cj2vi.js → health-CU3rjKc6.js} +1 -1
  20. package/dist/ui/assets/{index-BXDW5hxG.js → index-CFOuEr7f.js} +1 -1
  21. package/dist/ui/assets/{index-CKnNRLzv.js → index-CxzNRZhe.js} +1 -1
  22. package/dist/ui/assets/{index-jqDLGaO4.js → index-KBHcxzj5.js} +1 -1
  23. package/dist/ui/assets/index-UzqXH0bn.js +47 -0
  24. package/dist/ui/assets/{index-D1Gx_G_A.js → index-v5UgttWm.js} +1 -1
  25. package/dist/ui/assets/{proxy-status-widget-D-PfDCn1.js → proxy-status-widget-FJrBfPdV.js} +1 -1
  26. package/dist/ui/assets/{separator-CjXUYlSy.js → separator-B8bpSt_-.js} +1 -1
  27. package/dist/ui/assets/{shared-C9EvhZ8u.js → shared-BK-E4ojq.js} +1 -1
  28. package/dist/ui/assets/{switch-DFLN6xA0.js → switch-kyFX8Qe1.js} +1 -1
  29. package/dist/ui/assets/{updates-FcpGeTFg.js → updates-DBinmc39.js} +1 -1
  30. package/dist/ui/index.html +1 -1
  31. package/dist/web-server/usage/aggregator.d.ts +4 -0
  32. package/dist/web-server/usage/aggregator.d.ts.map +1 -1
  33. package/dist/web-server/usage/aggregator.js +24 -1
  34. package/dist/web-server/usage/aggregator.js.map +1 -1
  35. package/dist/web-server/usage/cliproxy-usage-syncer.d.ts +34 -0
  36. package/dist/web-server/usage/cliproxy-usage-syncer.d.ts.map +1 -0
  37. package/dist/web-server/usage/cliproxy-usage-syncer.js +152 -0
  38. package/dist/web-server/usage/cliproxy-usage-syncer.js.map +1 -0
  39. package/dist/web-server/usage/cliproxy-usage-transformer.d.ts +26 -0
  40. package/dist/web-server/usage/cliproxy-usage-transformer.d.ts.map +1 -0
  41. package/dist/web-server/usage/cliproxy-usage-transformer.js +141 -0
  42. package/dist/web-server/usage/cliproxy-usage-transformer.js.map +1 -0
  43. package/package.json +1 -1
  44. package/dist/ui/assets/index-hlYFfpDN.js +0 -47
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ /**
3
+ * CLIProxy Usage Syncer
4
+ *
5
+ * Periodically fetches CLIProxy usage data, transforms it, and persists
6
+ * snapshots locally so analytics data survives CLIProxy restarts.
7
+ *
8
+ * Snapshot location: ~/.ccs/cache/cliproxy-usage/latest.json
9
+ * Sync interval: 5 minutes
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.stopCliproxySync = exports.startCliproxySync = exports.syncCliproxyUsage = exports.loadCachedCliproxyData = void 0;
36
+ const fs = __importStar(require("fs"));
37
+ const path = __importStar(require("path"));
38
+ const stats_fetcher_1 = require("../../cliproxy/stats-fetcher");
39
+ const cliproxy_usage_transformer_1 = require("./cliproxy-usage-transformer");
40
+ const config_manager_1 = require("../../utils/config-manager");
41
+ const ui_1 = require("../../utils/ui");
42
+ const SNAPSHOT_VERSION = 1;
43
+ // Module-level interval ID
44
+ let syncIntervalId = null;
45
+ // ---------------------------------------------------------------------------
46
+ // Cache directory helpers
47
+ // ---------------------------------------------------------------------------
48
+ function getCliproxyCacheDir() {
49
+ return path.join((0, config_manager_1.getCcsDir)(), 'cache', 'cliproxy-usage');
50
+ }
51
+ function getLatestSnapshotPath() {
52
+ return path.join(getCliproxyCacheDir(), 'latest.json');
53
+ }
54
+ function ensureCliproxyCacheDir() {
55
+ const dir = getCliproxyCacheDir();
56
+ if (!fs.existsSync(dir)) {
57
+ fs.mkdirSync(dir, { recursive: true });
58
+ }
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Load cached data
62
+ // ---------------------------------------------------------------------------
63
+ /**
64
+ * Read the latest CLIProxy usage snapshot from disk.
65
+ * Returns empty arrays on failure (file not found, parse error, version mismatch).
66
+ */
67
+ async function loadCachedCliproxyData() {
68
+ const empty = { daily: [], hourly: [], monthly: [] };
69
+ try {
70
+ const snapshotPath = getLatestSnapshotPath();
71
+ if (!fs.existsSync(snapshotPath)) {
72
+ return empty;
73
+ }
74
+ const raw = fs.readFileSync(snapshotPath, 'utf-8');
75
+ const snapshot = JSON.parse(raw);
76
+ if (snapshot.version !== SNAPSHOT_VERSION) {
77
+ console.log((0, ui_1.info)('CLIProxy snapshot version mismatch, will refresh on next sync'));
78
+ return empty;
79
+ }
80
+ return { daily: snapshot.daily, hourly: snapshot.hourly, monthly: snapshot.monthly };
81
+ }
82
+ catch (err) {
83
+ console.log((0, ui_1.warn)('Failed to read CLIProxy snapshot:') + ` ${err.message}`);
84
+ return empty;
85
+ }
86
+ }
87
+ exports.loadCachedCliproxyData = loadCachedCliproxyData;
88
+ // ---------------------------------------------------------------------------
89
+ // Sync
90
+ // ---------------------------------------------------------------------------
91
+ /**
92
+ * Fetch latest CLIProxy usage data and persist a snapshot to disk.
93
+ * Non-fatal: logs warning and returns early if CLIProxy is unavailable.
94
+ */
95
+ async function syncCliproxyUsage() {
96
+ const raw = await (0, stats_fetcher_1.fetchCliproxyUsageRaw)();
97
+ if (raw === null) {
98
+ console.log((0, ui_1.warn)('CLIProxy usage sync skipped: proxy unavailable'));
99
+ return;
100
+ }
101
+ try {
102
+ ensureCliproxyCacheDir();
103
+ const daily = (0, cliproxy_usage_transformer_1.transformCliproxyToDailyUsage)(raw);
104
+ const hourly = (0, cliproxy_usage_transformer_1.transformCliproxyToHourlyUsage)(raw);
105
+ const monthly = (0, cliproxy_usage_transformer_1.transformCliproxyToMonthlyUsage)(raw);
106
+ const snapshot = {
107
+ version: SNAPSHOT_VERSION,
108
+ timestamp: Date.now(),
109
+ daily,
110
+ hourly,
111
+ monthly,
112
+ };
113
+ // Atomic write: temp file + rename
114
+ const snapshotPath = getLatestSnapshotPath();
115
+ const tempFile = snapshotPath + '.tmp';
116
+ fs.writeFileSync(tempFile, JSON.stringify(snapshot), 'utf-8');
117
+ fs.renameSync(tempFile, snapshotPath);
118
+ console.log((0, ui_1.ok)('CLIProxy usage snapshot updated'));
119
+ }
120
+ catch (err) {
121
+ // Non-fatal - stale snapshot will continue to be served
122
+ console.log((0, ui_1.warn)('Failed to write CLIProxy snapshot:') + ` ${err.message}`);
123
+ }
124
+ }
125
+ exports.syncCliproxyUsage = syncCliproxyUsage;
126
+ // ---------------------------------------------------------------------------
127
+ // Interval management
128
+ // ---------------------------------------------------------------------------
129
+ /**
130
+ * Start periodic CLIProxy usage sync (every 5 minutes).
131
+ * Performs an immediate sync on startup.
132
+ */
133
+ function startCliproxySync() {
134
+ console.log((0, ui_1.info)('Starting CLIProxy usage sync (interval: 5 min)'));
135
+ // Fire-and-forget initial sync
136
+ void syncCliproxyUsage();
137
+ syncIntervalId = setInterval(() => {
138
+ void syncCliproxyUsage();
139
+ }, 5 * 60 * 1000);
140
+ }
141
+ exports.startCliproxySync = startCliproxySync;
142
+ /**
143
+ * Stop periodic CLIProxy usage sync.
144
+ */
145
+ function stopCliproxySync() {
146
+ if (syncIntervalId !== null) {
147
+ clearInterval(syncIntervalId);
148
+ syncIntervalId = null;
149
+ }
150
+ }
151
+ exports.stopCliproxySync = stopCliproxySync;
152
+ //# sourceMappingURL=cliproxy-usage-syncer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliproxy-usage-syncer.js","sourceRoot":"","sources":["../../../src/web-server/usage/cliproxy-usage-syncer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * CLIProxy Usage Transformer
3
+ *
4
+ * Transforms CLIProxy's usage API response into DailyUsage/HourlyUsage/MonthlyUsage
5
+ * types compatible with the CCS analytics dashboard.
6
+ */
7
+ import type { CliproxyUsageApiResponse, CliproxyRequestDetail } from '../../cliproxy/stats-fetcher';
8
+ import type { DailyUsage, HourlyUsage, MonthlyUsage } from './types';
9
+ /** Flat entry pairing a model name with its request detail */
10
+ interface FlatDetail {
11
+ model: string;
12
+ detail: CliproxyRequestDetail;
13
+ }
14
+ /**
15
+ * Flatten the nested response.usage.apis[provider].models[model].details[]
16
+ * structure into a flat array. Failed requests are skipped.
17
+ */
18
+ export declare function flattenCliproxyDetails(response: CliproxyUsageApiResponse): FlatDetail[];
19
+ /** Transform CLIProxy usage response into DailyUsage array (sorted descending by date) */
20
+ export declare function transformCliproxyToDailyUsage(response: CliproxyUsageApiResponse): DailyUsage[];
21
+ /** Transform CLIProxy usage response into HourlyUsage array (sorted descending by hour) */
22
+ export declare function transformCliproxyToHourlyUsage(response: CliproxyUsageApiResponse): HourlyUsage[];
23
+ /** Transform CLIProxy usage response into MonthlyUsage array (sorted descending by month) */
24
+ export declare function transformCliproxyToMonthlyUsage(response: CliproxyUsageApiResponse): MonthlyUsage[];
25
+ export {};
26
+ //# sourceMappingURL=cliproxy-usage-transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliproxy-usage-transformer.d.ts","sourceRoot":"","sources":["../../../src/web-server/usage/cliproxy-usage-transformer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEpG,OAAO,KAAK,EAAkB,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAMrF,8DAA8D;AAC9D,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAuBD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,UAAU,EAAE,CAkBvF;AAiDD,0FAA0F;AAC1F,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,wBAAwB,GAAG,UAAU,EAAE,CAsB9F;AAED,2FAA2F;AAC3F,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,wBAAwB,GAAG,WAAW,EAAE,CA0BhG;AAED,6FAA6F;AAC7F,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,wBAAwB,GACjC,YAAY,EAAE,CAkBhB"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ /**
3
+ * CLIProxy Usage Transformer
4
+ *
5
+ * Transforms CLIProxy's usage API response into DailyUsage/HourlyUsage/MonthlyUsage
6
+ * types compatible with the CCS analytics dashboard.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.transformCliproxyToMonthlyUsage = exports.transformCliproxyToHourlyUsage = exports.transformCliproxyToDailyUsage = exports.flattenCliproxyDetails = void 0;
10
+ const model_pricing_1 = require("../model-pricing");
11
+ /** Build ModelBreakdown from accumulated token counts */
12
+ function buildModelBreakdown(modelName, acc) {
13
+ const { inputTokens, outputTokens, cacheReadTokens } = acc;
14
+ const cost = (0, model_pricing_1.calculateCost)({ inputTokens, outputTokens, cacheCreationTokens: 0, cacheReadTokens }, modelName);
15
+ return { modelName, inputTokens, outputTokens, cacheCreationTokens: 0, cacheReadTokens, cost };
16
+ }
17
+ // ============================================================================
18
+ // FLATTEN
19
+ // ============================================================================
20
+ /**
21
+ * Flatten the nested response.usage.apis[provider].models[model].details[]
22
+ * structure into a flat array. Failed requests are skipped.
23
+ */
24
+ function flattenCliproxyDetails(response) {
25
+ const apis = response?.usage?.apis;
26
+ if (!apis)
27
+ return [];
28
+ const results = [];
29
+ for (const providerData of Object.values(apis)) {
30
+ const models = providerData?.models;
31
+ if (!models)
32
+ continue;
33
+ for (const [model, modelData] of Object.entries(models)) {
34
+ const details = modelData?.details;
35
+ if (!details)
36
+ continue;
37
+ for (const detail of details) {
38
+ if (detail.failed)
39
+ continue;
40
+ results.push({ model, detail });
41
+ }
42
+ }
43
+ }
44
+ return results;
45
+ }
46
+ exports.flattenCliproxyDetails = flattenCliproxyDetails;
47
+ // ============================================================================
48
+ // GENERIC AGGREGATOR
49
+ // ============================================================================
50
+ /** Group flat details by a time key extractor, return sorted DailyUsage-like records */
51
+ function aggregateByKey(flat, keyFn, buildRecord, sortFn) {
52
+ // bucket: timeKey -> modelName -> accumulator
53
+ const buckets = new Map();
54
+ for (const { model, detail } of flat) {
55
+ const key = keyFn(detail.timestamp);
56
+ if (!buckets.has(key))
57
+ buckets.set(key, new Map());
58
+ const modelMap = buckets.get(key);
59
+ if (!modelMap.has(model)) {
60
+ modelMap.set(model, { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0 });
61
+ }
62
+ const acc = modelMap.get(model);
63
+ acc.inputTokens += detail.tokens?.input_tokens ?? 0;
64
+ acc.outputTokens += detail.tokens?.output_tokens ?? 0;
65
+ acc.cacheReadTokens += detail.tokens?.cached_tokens ?? 0;
66
+ }
67
+ const records = [];
68
+ Array.from(buckets.entries()).forEach(([key, modelMap]) => {
69
+ const breakdowns = Array.from(modelMap.entries()).map(([name, acc]) => buildModelBreakdown(name, acc));
70
+ records.push(buildRecord(key, breakdowns));
71
+ });
72
+ return records.sort(sortFn);
73
+ }
74
+ /** Sum token field across all breakdowns */
75
+ function sumField(breakdowns, field) {
76
+ return breakdowns.reduce((acc, b) => acc + b[field], 0);
77
+ }
78
+ // ============================================================================
79
+ // TRANSFORMS
80
+ // ============================================================================
81
+ /** Transform CLIProxy usage response into DailyUsage array (sorted descending by date) */
82
+ function transformCliproxyToDailyUsage(response) {
83
+ const flat = flattenCliproxyDetails(response);
84
+ return aggregateByKey(flat, (ts) => ts.slice(0, 10), (date, breakdowns) => {
85
+ const totalCost = sumField(breakdowns, 'cost');
86
+ return {
87
+ date,
88
+ source: 'cliproxy',
89
+ inputTokens: sumField(breakdowns, 'inputTokens'),
90
+ outputTokens: sumField(breakdowns, 'outputTokens'),
91
+ cacheCreationTokens: 0,
92
+ cacheReadTokens: sumField(breakdowns, 'cacheReadTokens'),
93
+ cost: totalCost,
94
+ totalCost,
95
+ modelsUsed: breakdowns.map((b) => b.modelName),
96
+ modelBreakdowns: breakdowns,
97
+ };
98
+ }, (a, b) => b.date.localeCompare(a.date));
99
+ }
100
+ exports.transformCliproxyToDailyUsage = transformCliproxyToDailyUsage;
101
+ /** Transform CLIProxy usage response into HourlyUsage array (sorted descending by hour) */
102
+ function transformCliproxyToHourlyUsage(response) {
103
+ const flat = flattenCliproxyDetails(response);
104
+ return aggregateByKey(flat, (ts) => {
105
+ const date = ts.slice(0, 10);
106
+ const hour = ts.slice(11, 13) || '00';
107
+ return `${date} ${hour}:00`;
108
+ }, (hour, breakdowns) => {
109
+ const totalCost = sumField(breakdowns, 'cost');
110
+ return {
111
+ hour,
112
+ source: 'cliproxy',
113
+ inputTokens: sumField(breakdowns, 'inputTokens'),
114
+ outputTokens: sumField(breakdowns, 'outputTokens'),
115
+ cacheCreationTokens: 0,
116
+ cacheReadTokens: sumField(breakdowns, 'cacheReadTokens'),
117
+ cost: totalCost,
118
+ totalCost,
119
+ modelsUsed: breakdowns.map((b) => b.modelName),
120
+ modelBreakdowns: breakdowns,
121
+ };
122
+ }, (a, b) => b.hour.localeCompare(a.hour));
123
+ }
124
+ exports.transformCliproxyToHourlyUsage = transformCliproxyToHourlyUsage;
125
+ /** Transform CLIProxy usage response into MonthlyUsage array (sorted descending by month) */
126
+ function transformCliproxyToMonthlyUsage(response) {
127
+ const flat = flattenCliproxyDetails(response);
128
+ return aggregateByKey(flat, (ts) => ts.slice(0, 7), (month, breakdowns) => ({
129
+ month,
130
+ source: 'cliproxy',
131
+ inputTokens: sumField(breakdowns, 'inputTokens'),
132
+ outputTokens: sumField(breakdowns, 'outputTokens'),
133
+ cacheCreationTokens: 0,
134
+ cacheReadTokens: sumField(breakdowns, 'cacheReadTokens'),
135
+ totalCost: sumField(breakdowns, 'cost'),
136
+ modelsUsed: breakdowns.map((b) => b.modelName),
137
+ modelBreakdowns: breakdowns,
138
+ }), (a, b) => b.month.localeCompare(a.month));
139
+ }
140
+ exports.transformCliproxyToMonthlyUsage = transformCliproxyToMonthlyUsage;
141
+ //# sourceMappingURL=cliproxy-usage-transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cliproxy-usage-transformer.js","sourceRoot":"","sources":["../../../src/web-server/usage/cliproxy-usage-transformer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaitranntt/ccs",
3
- "version": "7.51.0-dev.4",
3
+ "version": "7.51.0-dev.6",
4
4
  "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
5
5
  "keywords": [
6
6
  "cli",