codebuddy-stats 1.0.0

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.
@@ -0,0 +1,205 @@
1
+ import fs from 'node:fs/promises';
2
+ import fsSync from 'node:fs';
3
+ import path from 'node:path';
4
+ import { createInterface } from 'node:readline';
5
+ import { getProjectsDir, getSettingsPath } from './paths.js';
6
+ import { DEFAULT_MODEL_ID, getPricingForModel, tokensToCost } from './pricing.js';
7
+ export const BASE_DIR = getProjectsDir();
8
+ async function loadModelFromSettings() {
9
+ try {
10
+ const settingsPath = getSettingsPath();
11
+ const settingsRaw = await fs.readFile(settingsPath, 'utf8');
12
+ const settings = JSON.parse(settingsRaw);
13
+ return typeof settings?.model === 'string' ? settings.model : DEFAULT_MODEL_ID;
14
+ }
15
+ catch {
16
+ return DEFAULT_MODEL_ID;
17
+ }
18
+ }
19
+ async function findJsonlFiles(dir) {
20
+ try {
21
+ const dirents = await fs.readdir(dir, { withFileTypes: true });
22
+ const files = await Promise.all(dirents.map(async (dirent) => {
23
+ const res = path.resolve(dir, dirent.name);
24
+ if (dirent.isDirectory()) {
25
+ return findJsonlFiles(res);
26
+ }
27
+ return res.endsWith('.jsonl') ? [res] : [];
28
+ }));
29
+ return files.flat();
30
+ }
31
+ catch (error) {
32
+ if (typeof error === 'object' && error && 'code' in error && error.code === 'ENOENT') {
33
+ return [];
34
+ }
35
+ throw error;
36
+ }
37
+ }
38
+ function getProjectName(filePath) {
39
+ const parts = filePath.split(path.sep);
40
+ const projectsIndex = parts.lastIndexOf('projects');
41
+ if (projectsIndex !== -1 && projectsIndex < parts.length - 1) {
42
+ return parts[projectsIndex + 1] ?? 'unknown-project';
43
+ }
44
+ return 'unknown-project';
45
+ }
46
+ function extractUsageStats(usage) {
47
+ const promptTokens = usage.prompt_tokens ?? 0;
48
+ const completionTokens = usage.completion_tokens ?? 0;
49
+ const totalTokens = usage.total_tokens ?? promptTokens + completionTokens;
50
+ const cacheHitTokens = usage.prompt_cache_hit_tokens ?? 0;
51
+ const cacheMissTokens = usage.prompt_cache_miss_tokens ?? (cacheHitTokens > 0 ? Math.max(promptTokens - cacheHitTokens, 0) : 0);
52
+ const cacheWriteTokens = usage.cache_creation_input_tokens ?? 0;
53
+ return {
54
+ promptTokens,
55
+ completionTokens,
56
+ totalTokens,
57
+ cacheHitTokens,
58
+ cacheMissTokens,
59
+ cacheWriteTokens,
60
+ };
61
+ }
62
+ function computeUsageCost(usage, modelId) {
63
+ const stats = extractUsageStats(usage);
64
+ const pricing = getPricingForModel(modelId);
65
+ let inputCost = 0;
66
+ if (stats.cacheHitTokens || stats.cacheMissTokens || stats.cacheWriteTokens) {
67
+ inputCost += tokensToCost(stats.cacheHitTokens, pricing.cacheRead);
68
+ inputCost += tokensToCost(stats.cacheMissTokens, pricing.prompt);
69
+ inputCost += tokensToCost(stats.cacheWriteTokens, pricing.cacheWrite);
70
+ }
71
+ else {
72
+ inputCost += tokensToCost(stats.promptTokens, pricing.prompt);
73
+ }
74
+ const outputCost = tokensToCost(stats.completionTokens, pricing.completion);
75
+ return { cost: inputCost + outputCost, stats, modelId: modelId || DEFAULT_MODEL_ID };
76
+ }
77
+ /**
78
+ * 加载所有用量数据
79
+ */
80
+ export async function loadUsageData(options = {}) {
81
+ const defaultModelId = await loadModelFromSettings();
82
+ const jsonlFiles = await findJsonlFiles(BASE_DIR);
83
+ // 计算日期过滤范围
84
+ let minDate = null;
85
+ if (options.days) {
86
+ const d = new Date();
87
+ d.setDate(d.getDate() - options.days + 1);
88
+ d.setHours(0, 0, 0, 0);
89
+ minDate = d.toISOString().split('T')[0] ?? null;
90
+ }
91
+ // 按日期 -> 项目 -> 模型 组织的数据
92
+ const dailyData = {};
93
+ // 按模型汇总
94
+ const modelTotals = {};
95
+ // 按项目汇总
96
+ const projectTotals = {};
97
+ // 总计
98
+ const grandTotal = {
99
+ cost: 0,
100
+ tokens: 0,
101
+ requests: 0,
102
+ cacheHitTokens: 0,
103
+ cacheMissTokens: 0,
104
+ };
105
+ for (const filePath of jsonlFiles) {
106
+ const fileStat = await fs.stat(filePath);
107
+ if (fileStat.size === 0)
108
+ continue;
109
+ const fileStream = fsSync.createReadStream(filePath);
110
+ const rl = createInterface({
111
+ input: fileStream,
112
+ crlfDelay: Number.POSITIVE_INFINITY,
113
+ });
114
+ const projectName = getProjectName(filePath);
115
+ for await (const line of rl) {
116
+ try {
117
+ const record = JSON.parse(line);
118
+ const usage = record?.providerData?.rawUsage;
119
+ const timestamp = record?.timestamp;
120
+ if (!usage || timestamp == null)
121
+ continue;
122
+ const dateObj = new Date(timestamp);
123
+ if (Number.isNaN(dateObj.getTime()))
124
+ continue;
125
+ const date = dateObj.toISOString().split('T')[0];
126
+ if (!date)
127
+ continue;
128
+ // 日期过滤
129
+ if (minDate && date < minDate)
130
+ continue;
131
+ const recordModelId = record?.providerData?.model;
132
+ const modelId = typeof recordModelId === 'string' ? recordModelId : null;
133
+ const { cost, stats: usageStats, modelId: usedModelId } = computeUsageCost(usage, modelId);
134
+ dailyData[date] ??= {};
135
+ dailyData[date][projectName] ??= {};
136
+ dailyData[date][projectName][usedModelId] ??= {
137
+ cost: 0,
138
+ promptTokens: 0,
139
+ completionTokens: 0,
140
+ totalTokens: 0,
141
+ cacheHitTokens: 0,
142
+ cacheMissTokens: 0,
143
+ cacheWriteTokens: 0,
144
+ requests: 0,
145
+ };
146
+ const dayStats = dailyData[date][projectName][usedModelId];
147
+ dayStats.cost += cost;
148
+ dayStats.promptTokens += usageStats.promptTokens;
149
+ dayStats.completionTokens += usageStats.completionTokens;
150
+ dayStats.totalTokens += usageStats.totalTokens;
151
+ dayStats.cacheHitTokens += usageStats.cacheHitTokens;
152
+ dayStats.cacheMissTokens += usageStats.cacheMissTokens;
153
+ dayStats.cacheWriteTokens += usageStats.cacheWriteTokens;
154
+ dayStats.requests += 1;
155
+ modelTotals[usedModelId] ??= { cost: 0, tokens: 0, requests: 0 };
156
+ modelTotals[usedModelId].cost += cost;
157
+ modelTotals[usedModelId].tokens += usageStats.totalTokens;
158
+ modelTotals[usedModelId].requests += 1;
159
+ projectTotals[projectName] ??= { cost: 0, tokens: 0, requests: 0 };
160
+ projectTotals[projectName].cost += cost;
161
+ projectTotals[projectName].tokens += usageStats.totalTokens;
162
+ projectTotals[projectName].requests += 1;
163
+ grandTotal.cost += cost;
164
+ grandTotal.tokens += usageStats.totalTokens;
165
+ grandTotal.requests += 1;
166
+ grandTotal.cacheHitTokens += usageStats.cacheHitTokens;
167
+ grandTotal.cacheMissTokens += usageStats.cacheMissTokens;
168
+ }
169
+ catch {
170
+ // 忽略无法解析的行
171
+ }
172
+ }
173
+ }
174
+ // 计算每日汇总
175
+ const dailySummary = {};
176
+ for (const date of Object.keys(dailyData)) {
177
+ dailySummary[date] = { cost: 0, tokens: 0, requests: 0 };
178
+ for (const project of Object.values(dailyData[date] ?? {})) {
179
+ for (const model of Object.values(project ?? {})) {
180
+ dailySummary[date].cost += model.cost;
181
+ dailySummary[date].tokens += model.totalTokens;
182
+ dailySummary[date].requests += model.requests;
183
+ }
184
+ }
185
+ }
186
+ const topModelEntry = Object.entries(modelTotals).sort((a, b) => b[1].cost - a[1].cost)[0];
187
+ const topProjectEntry = Object.entries(projectTotals).sort((a, b) => b[1].cost - a[1].cost)[0];
188
+ // 计算缓存命中率
189
+ const cacheHitRate = grandTotal.cacheHitTokens + grandTotal.cacheMissTokens > 0
190
+ ? grandTotal.cacheHitTokens / (grandTotal.cacheHitTokens + grandTotal.cacheMissTokens)
191
+ : 0;
192
+ return {
193
+ defaultModelId,
194
+ dailyData,
195
+ dailySummary,
196
+ modelTotals,
197
+ projectTotals,
198
+ grandTotal,
199
+ topModel: topModelEntry ? { id: topModelEntry[0], ...topModelEntry[1] } : null,
200
+ topProject: topProjectEntry ? { name: topProjectEntry[0], ...topProjectEntry[1] } : null,
201
+ cacheHitRate,
202
+ activeDays: Object.keys(dailyData).length,
203
+ };
204
+ }
205
+ //# sourceMappingURL=data-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-loader.js","sourceRoot":"","sources":["../../src/lib/data-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import os from 'node:os';
2
+ import path from 'node:path';
3
+ /**
4
+ * 获取 CodeBuddy 配置目录
5
+ * - Windows: %APPDATA%/CodeBuddy
6
+ * - macOS: ~/.codebuddy
7
+ * - Linux: $XDG_CONFIG_HOME/codebuddy 或 ~/.codebuddy
8
+ */
9
+ export function getConfigDir() {
10
+ if (process.platform === 'win32') {
11
+ const appData = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
12
+ return path.join(appData, 'CodeBuddy');
13
+ }
14
+ if (process.platform === 'linux') {
15
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME;
16
+ if (xdgConfigHome) {
17
+ return path.join(xdgConfigHome, 'codebuddy');
18
+ }
19
+ }
20
+ // macOS 和 Linux 默认
21
+ return path.join(os.homedir(), '.codebuddy');
22
+ }
23
+ /**
24
+ * 获取项目数据目录
25
+ */
26
+ export function getProjectsDir() {
27
+ return path.join(getConfigDir(), 'projects');
28
+ }
29
+ /**
30
+ * 获取设置文件路径
31
+ */
32
+ export function getSettingsPath() {
33
+ return path.join(getConfigDir(), 'settings.json');
34
+ }
35
+ /**
36
+ * 简化项目路径显示
37
+ * 保持原始名称不变
38
+ */
39
+ export function shortenProjectName(name) {
40
+ return name;
41
+ }
42
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;QACpF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAA;QACjD,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IACD,mBAAmB;IACnB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAA;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,CAAC,CAAA;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,eAAe,CAAC,CAAA;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,105 @@
1
+ // 模型价格 (USD / 1M tokens)
2
+ function createPricing(inputPrice, cachedInputPrice, outputPrice, cacheWritePrice) {
3
+ return {
4
+ prompt: [{ limit: Number.POSITIVE_INFINITY, pricePerMTok: inputPrice }],
5
+ completion: [{ limit: Number.POSITIVE_INFINITY, pricePerMTok: outputPrice }],
6
+ cacheRead: [{ limit: Number.POSITIVE_INFINITY, pricePerMTok: cachedInputPrice }],
7
+ cacheWrite: [
8
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: cacheWritePrice ?? inputPrice },
9
+ ],
10
+ };
11
+ }
12
+ export const MODEL_PRICING = {
13
+ 'gpt-5.2': createPricing(1.75, 0.175, 14.0),
14
+ 'gpt-5.1': createPricing(1.25, 0.125, 10.0),
15
+ 'gpt-5': createPricing(1.25, 0.125, 10.0),
16
+ 'gpt-5-mini': createPricing(0.25, 0.025, 2.0),
17
+ 'gpt-5-nano': createPricing(0.05, 0.005, 0.4),
18
+ 'gpt-5.1-chat-latest': createPricing(1.25, 0.125, 10.0),
19
+ 'gpt-5-chat-latest': createPricing(1.25, 0.125, 10.0),
20
+ 'gpt-5.1-codex': createPricing(1.25, 0.125, 10.0),
21
+ 'gpt-5-codex': createPricing(1.25, 0.125, 10.0),
22
+ 'claude-opus-4.5': createPricing(5.0, 0.5, 25.0, 10.0),
23
+ 'claude-4.5': {
24
+ prompt: [
25
+ { limit: 200_000, pricePerMTok: 3.0 },
26
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 6.0 },
27
+ ],
28
+ completion: [
29
+ { limit: 200_000, pricePerMTok: 15.0 },
30
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 22.5 },
31
+ ],
32
+ cacheRead: [
33
+ { limit: 200_000, pricePerMTok: 0.3 },
34
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.6 },
35
+ ],
36
+ cacheWrite: [
37
+ { limit: 200_000, pricePerMTok: 6.0 },
38
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 12.0 },
39
+ ],
40
+ },
41
+ 'gemini-3-pro': {
42
+ prompt: [
43
+ { limit: 200_000, pricePerMTok: 2.0 },
44
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 4.0 },
45
+ ],
46
+ completion: [
47
+ { limit: 200_000, pricePerMTok: 12.0 },
48
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 18.0 },
49
+ ],
50
+ cacheRead: [
51
+ { limit: 200_000, pricePerMTok: 0.2 },
52
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.4 },
53
+ ],
54
+ cacheWrite: [
55
+ { limit: 200_000, pricePerMTok: 0.2 },
56
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.4 },
57
+ ],
58
+ },
59
+ 'gemini-2.5-pro': {
60
+ prompt: [
61
+ { limit: 200_000, pricePerMTok: 1.25 },
62
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 2.5 },
63
+ ],
64
+ completion: [
65
+ { limit: 200_000, pricePerMTok: 10.0 },
66
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 15.0 },
67
+ ],
68
+ cacheRead: [
69
+ { limit: 200_000, pricePerMTok: 0.125 },
70
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.25 },
71
+ ],
72
+ cacheWrite: [
73
+ { limit: 200_000, pricePerMTok: 0.125 },
74
+ { limit: Number.POSITIVE_INFINITY, pricePerMTok: 0.25 },
75
+ ],
76
+ },
77
+ };
78
+ export const DEFAULT_MODEL_ID = 'gpt-5.1';
79
+ export function selectTierPrice(tokens, tiers) {
80
+ if (tokens <= 0)
81
+ return tiers[0]?.pricePerMTok ?? 0;
82
+ for (const tier of tiers) {
83
+ if (tokens <= tier.limit) {
84
+ return tier.pricePerMTok;
85
+ }
86
+ }
87
+ return tiers[tiers.length - 1]?.pricePerMTok ?? 0;
88
+ }
89
+ export function tokensToCost(tokens, tiers) {
90
+ if (!tokens)
91
+ return 0;
92
+ const price = selectTierPrice(tokens, tiers);
93
+ return (tokens / 1_000_000) * price;
94
+ }
95
+ export function getPricingForModel(modelId) {
96
+ if (modelId && MODEL_PRICING[modelId]) {
97
+ return MODEL_PRICING[modelId];
98
+ }
99
+ const fallback = MODEL_PRICING[DEFAULT_MODEL_ID];
100
+ if (!fallback) {
101
+ throw new Error(`Missing pricing for default model: ${DEFAULT_MODEL_ID}`);
102
+ }
103
+ return fallback;
104
+ }
105
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/lib/pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * 格式化数字,添加千分位分隔符
3
+ */
4
+ export function formatNumber(num) {
5
+ const n = typeof num === 'number' ? num : Number(num ?? 0);
6
+ if (!Number.isFinite(n))
7
+ return '0';
8
+ return n.toLocaleString('en-US');
9
+ }
10
+ /**
11
+ * 格式化金额
12
+ */
13
+ export function formatCost(cost) {
14
+ const n = Number.isFinite(cost) ? cost : 0;
15
+ return `$${n.toFixed(2)}`;
16
+ }
17
+ /**
18
+ * 格式化 tokens 数量 (K/M/B)
19
+ */
20
+ export function formatTokens(tokens) {
21
+ if (tokens >= 1_000_000_000) {
22
+ return `${(tokens / 1_000_000_000).toFixed(1)}B`;
23
+ }
24
+ if (tokens >= 1_000_000) {
25
+ return `${(tokens / 1_000_000).toFixed(1)}M`;
26
+ }
27
+ if (tokens >= 1_000) {
28
+ return `${(tokens / 1_000).toFixed(1)}K`;
29
+ }
30
+ return String(tokens);
31
+ }
32
+ /**
33
+ * 格式化百分比
34
+ */
35
+ export function formatPercent(ratio) {
36
+ return `${(ratio * 100).toFixed(1)}%`;
37
+ }
38
+ /**
39
+ * 截断字符串
40
+ */
41
+ export function truncate(str, maxLen) {
42
+ if (str.length <= maxLen)
43
+ return str;
44
+ return str.slice(0, maxLen - 3) + '...';
45
+ }
46
+ /**
47
+ * 右对齐字符串
48
+ */
49
+ export function padLeft(str, len) {
50
+ return str.padStart(len);
51
+ }
52
+ /**
53
+ * 左对齐字符串
54
+ */
55
+ export function padRight(str, len) {
56
+ return str.padEnd(len);
57
+ }
58
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,GAAuC;IAClE,MAAM,CAAC,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;IAC1D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAA;IACnC,OAAO,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1C,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,MAAM,IAAI,aAAa,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;IAClD,CAAC;IACD,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;IAC9C,CAAC;IACD,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QACpB,OAAO,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,MAAc;IAClD,IAAI,GAAG,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,GAAG,CAAA;IACpC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAA;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,GAAW;IAC9C,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,GAAW;IAC/C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC"}
package/index.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ESM wrapper entrypoint (kept for backward compatibility)
4
+ // If you run this file directly, it will execute the compiled CLI in ./dist.
5
+
6
+ try {
7
+ await import('./dist/index.js')
8
+ } catch (err) {
9
+ console.error('Build output not found. Please run:')
10
+ console.error(' npm run build')
11
+ console.error('or just:')
12
+ console.error(' npm start')
13
+ console.error('\nOriginal error:')
14
+ console.error(err)
15
+ process.exit(1)
16
+ }
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "codebuddy-stats",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/AnotiaWang/codebuddy-stats"
9
+ },
10
+ "bin": {
11
+ "codebuddy-stats": "./dist/index.js",
12
+ "cbs": "./dist/index.js"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "dev": "tsx --watch src/index.ts",
17
+ "prestart": "npm run build",
18
+ "start": "node dist/index.js",
19
+ "pretext": "npm run build",
20
+ "text": "node dist/index.js --no-tui"
21
+ },
22
+ "keywords": [],
23
+ "author": "",
24
+ "license": "ISC",
25
+ "description": "CodeBuddy AI cost analyzer with TUI",
26
+ "dependencies": {
27
+ "blessed": "^0.1.81"
28
+ },
29
+ "devDependencies": {
30
+ "@types/blessed": "^0.1.27",
31
+ "@types/node": "^25.0.3",
32
+ "tsx": "^4.21.0",
33
+ "typescript": "^5.9.3"
34
+ }
35
+ }