cchubber 0.3.7 → 0.3.9
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/package.json +1 -1
- package/src/cli/index.js +9 -2
- package/src/renderers/html-report.js +3 -3
- package/src/telemetry.js +15 -0
package/package.json
CHANGED
package/src/cli/index.js
CHANGED
|
@@ -4,6 +4,13 @@ import { resolve, join } from 'path';
|
|
|
4
4
|
import { existsSync, writeFileSync } from 'fs';
|
|
5
5
|
import { homedir, platform } from 'os';
|
|
6
6
|
import { exec } from 'child_process';
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname } from 'path';
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const PKG = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
13
|
+
const VERSION = PKG.version;
|
|
7
14
|
|
|
8
15
|
import { readAllJSONL, aggregateDaily, aggregateByModel, aggregateByProject } from '../readers/jsonl-reader.js';
|
|
9
16
|
import { readStatsCache } from '../readers/stats-cache.js';
|
|
@@ -41,7 +48,7 @@ const flags = {
|
|
|
41
48
|
if (flags.help) {
|
|
42
49
|
console.log(`
|
|
43
50
|
╔═══════════════════════════════════════════════╗
|
|
44
|
-
║ CC Hubber
|
|
51
|
+
║ CC Hubber v${VERSION} ║
|
|
45
52
|
║ What you spent. Why you spent it. Is that ║
|
|
46
53
|
║ normal. ║
|
|
47
54
|
╚═══════════════════════════════════════════════╝
|
|
@@ -78,7 +85,7 @@ async function main() {
|
|
|
78
85
|
|
|
79
86
|
console.log(`
|
|
80
87
|
/\\ _ /\\
|
|
81
|
-
/ \\(_)/ \\ CC Hubber
|
|
88
|
+
/ \\(_)/ \\ CC Hubber v${VERSION}
|
|
82
89
|
\\ / ◉ \\ / What you spent. Why. Is that normal.
|
|
83
90
|
\\/ ~ \\/
|
|
84
91
|
`);
|
|
@@ -15,7 +15,7 @@ export function renderHTML(report) {
|
|
|
15
15
|
date: d.date, cost: d.cost, cacheOutputRatio: d.cacheOutputRatio || 0, isAnomaly: anomalyDates.has(d.date),
|
|
16
16
|
})));
|
|
17
17
|
|
|
18
|
-
const projectsJSON = JSON.stringify((projectBreakdown || []).
|
|
18
|
+
const projectsJSON = JSON.stringify((projectBreakdown || []).map(p => ({
|
|
19
19
|
name: p.name, path: p.path, messages: p.messageCount, sessions: p.sessionCount,
|
|
20
20
|
input: p.inputTokens, output: p.outputTokens, cacheRead: p.cacheReadTokens, cacheWrite: p.cacheCreationTokens,
|
|
21
21
|
})));
|
|
@@ -409,7 +409,7 @@ ${inflection && inflection.multiplier >= 1.5 ? `
|
|
|
409
409
|
<div>
|
|
410
410
|
<span class="text-[10px] uppercase tracking-[0.05em] text-[#908fa0] block mb-4">Top Tools Usage</span>
|
|
411
411
|
<div class="space-y-3">
|
|
412
|
-
${sessionIntel.topTools.slice(0,
|
|
412
|
+
${sessionIntel.topTools.slice(0, 10).map((t, i) => `
|
|
413
413
|
<div class="space-y-1">
|
|
414
414
|
<div class="flex justify-between text-[11px] font-mono">
|
|
415
415
|
<span class="text-[#c7c4d7]">${t.name}</span>
|
|
@@ -672,7 +672,7 @@ ${cacheHealth.totalCacheBreaks > 0 ? `
|
|
|
672
672
|
if(ptb&&P.length>0){
|
|
673
673
|
P.sort(function(a,b){return(b.output/1e6*OUT+b.cacheRead/1e6*CACHE_R)-(a.output/1e6*OUT+a.cacheRead/1e6*CACHE_R)});
|
|
674
674
|
var h='';
|
|
675
|
-
for(var i=0;i<
|
|
675
|
+
for(var i=0;i<P.length;i++){
|
|
676
676
|
var p=P[i];
|
|
677
677
|
h+='<tr class="tbl-row">';
|
|
678
678
|
h+='<td class="px-8 py-4 text-sm font-semibold text-[#e3e2e3]">'+p.name;
|
package/src/telemetry.js
CHANGED
|
@@ -19,9 +19,23 @@ export function shouldSendTelemetry(flags) {
|
|
|
19
19
|
if (flags.noTelemetry) return false;
|
|
20
20
|
if (process.env.CC_HUBBER_TELEMETRY === '0') return false;
|
|
21
21
|
if (process.env.DO_NOT_TRACK === '1') return false;
|
|
22
|
+
|
|
23
|
+
// Throttle: once per 24 hours per machine
|
|
24
|
+
const stampFile = join(homedir(), '.cchubber-last-telemetry');
|
|
25
|
+
try {
|
|
26
|
+
if (existsSync(stampFile)) {
|
|
27
|
+
const last = parseInt(readFileSync(stampFile, 'utf-8').trim());
|
|
28
|
+
if (Date.now() - last < 86400000) return false; // <24h since last send
|
|
29
|
+
}
|
|
30
|
+
} catch {}
|
|
31
|
+
|
|
22
32
|
return true;
|
|
23
33
|
}
|
|
24
34
|
|
|
35
|
+
function markTelemetrySent() {
|
|
36
|
+
try { writeFileSync(join(homedir(), '.cchubber-last-telemetry'), String(Date.now())); } catch {}
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
export function sendTelemetry(report) {
|
|
26
40
|
const payload = {
|
|
27
41
|
v: '0.3.3',
|
|
@@ -136,6 +150,7 @@ export function sendTelemetry(report) {
|
|
|
136
150
|
req.setTimeout(3000, () => req.destroy());
|
|
137
151
|
req.write(data);
|
|
138
152
|
req.end();
|
|
153
|
+
markTelemetrySent();
|
|
139
154
|
} catch {
|
|
140
155
|
// never crash on telemetry
|
|
141
156
|
}
|