vibestats 1.0.6 → 1.0.8
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/dist/index.js +69 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -315,37 +315,48 @@ function parseCodexJsonl() {
|
|
|
315
315
|
const entries = [];
|
|
316
316
|
const codexDir = getCodexDir();
|
|
317
317
|
const sessionsDir = join(codexDir, "sessions");
|
|
318
|
-
|
|
319
|
-
const jsonlFiles =
|
|
318
|
+
const archivedDir = join(codexDir, "archived_sessions");
|
|
319
|
+
const jsonlFiles = [
|
|
320
|
+
...findJsonlFiles(sessionsDir),
|
|
321
|
+
...findJsonlFiles(archivedDir)
|
|
322
|
+
];
|
|
323
|
+
if (jsonlFiles.length === 0) return entries;
|
|
320
324
|
for (const filePath of jsonlFiles) {
|
|
321
325
|
try {
|
|
322
326
|
const content = readFileSync(filePath, "utf-8");
|
|
323
327
|
const lines = content.split("\n");
|
|
328
|
+
let currentModel = "gpt-5";
|
|
324
329
|
for (const line of lines) {
|
|
325
330
|
if (!line.trim()) continue;
|
|
326
331
|
try {
|
|
327
332
|
const entry = JSON.parse(line);
|
|
328
|
-
if (entry.type
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
outputTokens
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
333
|
+
if (entry.type === "turn_context" && entry.payload?.model) {
|
|
334
|
+
currentModel = entry.payload.model;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (entry.type === "event_msg" && entry.payload?.type === "token_count") {
|
|
338
|
+
const info = entry.payload.info;
|
|
339
|
+
if (!info?.last_token_usage) continue;
|
|
340
|
+
const usage = info.last_token_usage;
|
|
341
|
+
const timestamp = entry.timestamp;
|
|
342
|
+
if (!timestamp) continue;
|
|
343
|
+
const date = timestamp.split("T")[0];
|
|
344
|
+
const pricing = getCodexModelPricing(currentModel);
|
|
345
|
+
const inputTokens = usage.input_tokens || 0;
|
|
346
|
+
const outputTokens = usage.output_tokens || 0;
|
|
347
|
+
const cachedInputTokens = usage.cached_input_tokens || 0;
|
|
348
|
+
const cost = (inputTokens - cachedInputTokens) * pricing.input / 1e6 + outputTokens * pricing.output / 1e6 + cachedInputTokens * pricing.cachedInput / 1e6;
|
|
349
|
+
entries.push({
|
|
350
|
+
date,
|
|
351
|
+
model: getCodexModelDisplayName(currentModel),
|
|
352
|
+
inputTokens,
|
|
353
|
+
outputTokens,
|
|
354
|
+
cacheWriteTokens: 0,
|
|
355
|
+
cacheReadTokens: cachedInputTokens,
|
|
356
|
+
cost,
|
|
357
|
+
source: "codex"
|
|
358
|
+
});
|
|
359
|
+
}
|
|
349
360
|
} catch {
|
|
350
361
|
}
|
|
351
362
|
}
|
|
@@ -1436,21 +1447,49 @@ function getModelAbbrevFromDisplayName(displayName) {
|
|
|
1436
1447
|
};
|
|
1437
1448
|
return map[displayName] || displayName.slice(0, 5).toLowerCase();
|
|
1438
1449
|
}
|
|
1450
|
+
function aggregateRowsToMonthly(rows) {
|
|
1451
|
+
const monthMap = /* @__PURE__ */ new Map();
|
|
1452
|
+
for (const row of rows) {
|
|
1453
|
+
const month = row.key.slice(0, 7);
|
|
1454
|
+
const existing = monthMap.get(month);
|
|
1455
|
+
if (existing) {
|
|
1456
|
+
existing.inputTokens += row.inputTokens;
|
|
1457
|
+
existing.outputTokens += row.outputTokens;
|
|
1458
|
+
existing.cacheWriteTokens += row.cacheWriteTokens;
|
|
1459
|
+
existing.cacheReadTokens += row.cacheReadTokens;
|
|
1460
|
+
existing.totalTokens += row.totalTokens;
|
|
1461
|
+
existing.cost += row.cost;
|
|
1462
|
+
} else {
|
|
1463
|
+
monthMap.set(month, { ...row, key: month });
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return Array.from(monthMap.values()).sort((a, b) => a.key.localeCompare(b.key));
|
|
1467
|
+
}
|
|
1439
1468
|
function encodeUsageToUrl(stats, baseUrl = "https://vibestats.wolfai.dev") {
|
|
1440
1469
|
const params = new URLSearchParams();
|
|
1441
|
-
const aggMap = { daily: "d", monthly: "m", model: "mo", total: "t" };
|
|
1442
|
-
params.set("agg", aggMap[stats.aggregation] || "d");
|
|
1443
1470
|
if (stats.source !== "claude") {
|
|
1444
1471
|
params.set("src", stats.source);
|
|
1445
1472
|
}
|
|
1446
1473
|
const formatDateCompact = (d) => d.replace(/-/g, "");
|
|
1447
|
-
const
|
|
1448
|
-
const
|
|
1449
|
-
const
|
|
1474
|
+
const startMs = new Date(stats.dateRange.start).getTime();
|
|
1475
|
+
const endMs = new Date(stats.dateRange.end).getTime();
|
|
1476
|
+
const daySpan = Math.ceil((endMs - startMs) / (1e3 * 60 * 60 * 24));
|
|
1477
|
+
const useMonthly = stats.aggregation === "daily" && daySpan > 31;
|
|
1478
|
+
const aggMap = { daily: "d", monthly: "m", model: "mo", total: "t" };
|
|
1479
|
+
const effectiveAgg = useMonthly ? "monthly" : stats.aggregation;
|
|
1480
|
+
params.set("agg", aggMap[effectiveAgg] || "d");
|
|
1481
|
+
let rowsToEncode;
|
|
1482
|
+
if (useMonthly) {
|
|
1483
|
+
rowsToEncode = aggregateRowsToMonthly(stats.rows);
|
|
1484
|
+
} else {
|
|
1485
|
+
rowsToEncode = stats.rows.slice(-31);
|
|
1486
|
+
}
|
|
1487
|
+
const startDate = useMonthly ? stats.dateRange.start : rowsToEncode[0]?.key || stats.dateRange.start;
|
|
1488
|
+
const endDate = useMonthly ? stats.dateRange.end : rowsToEncode[rowsToEncode.length - 1]?.key || stats.dateRange.end;
|
|
1450
1489
|
params.set("dr", `${formatDateCompact(startDate)}-${formatDateCompact(endDate)}`);
|
|
1451
|
-
const rows =
|
|
1490
|
+
const rows = rowsToEncode.map((row) => {
|
|
1452
1491
|
let key = row.key;
|
|
1453
|
-
if (
|
|
1492
|
+
if (effectiveAgg === "daily" && row.key.length === 10) {
|
|
1454
1493
|
key = row.key.slice(5).replace("-", "");
|
|
1455
1494
|
}
|
|
1456
1495
|
return [
|