whoburnedmore 0.4.0 → 0.5.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.
- package/dist/index.js +281 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { spawn } from "node:child_process";
|
|
|
10
10
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
11
11
|
import { createRequire as createRequire4 } from "node:module";
|
|
12
12
|
import { platform as platform3 } from "node:os";
|
|
13
|
-
import { join as
|
|
13
|
+
import { join as join7 } from "node:path";
|
|
14
14
|
import { createInterface } from "node:readline/promises";
|
|
15
15
|
import pc2 from "picocolors";
|
|
16
16
|
|
|
@@ -286,19 +286,231 @@ function autoSyncInstalled() {
|
|
|
286
286
|
// src/collect.ts
|
|
287
287
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
288
288
|
import { createRequire as createRequire3 } from "node:module";
|
|
289
|
-
import { dirname as dirname2, join as
|
|
289
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
290
|
+
|
|
291
|
+
// src/attribution.ts
|
|
292
|
+
import { readFileSync as readFileSync2, readdirSync, statSync } from "node:fs";
|
|
293
|
+
import { homedir as homedir3 } from "node:os";
|
|
294
|
+
import { basename, join as join3 } from "node:path";
|
|
295
|
+
|
|
296
|
+
// src/pricing.ts
|
|
297
|
+
var TABLE = [
|
|
298
|
+
{ match: /opus/i, price: { in: 15, out: 75, cacheWrite: 18.75, cacheRead: 1.5 } },
|
|
299
|
+
{ match: /sonnet/i, price: { in: 3, out: 15, cacheWrite: 3.75, cacheRead: 0.3 } },
|
|
300
|
+
{ match: /haiku/i, price: { in: 0.8, out: 4, cacheWrite: 1, cacheRead: 0.08 } },
|
|
301
|
+
{ match: /fable/i, price: { in: 15, out: 75, cacheWrite: 18.75, cacheRead: 1.5 } },
|
|
302
|
+
{ match: /gpt-4o|gpt-4\.1/i, price: { in: 2.5, out: 10, cacheWrite: 2.5, cacheRead: 1.25 } },
|
|
303
|
+
{ match: /gpt-5|o3|o4|codex/i, price: { in: 1.25, out: 10, cacheWrite: 1.25, cacheRead: 0.125 } },
|
|
304
|
+
{ match: /gemini.*flash/i, price: { in: 0.15, out: 0.6, cacheWrite: 0.15, cacheRead: 0.0375 } },
|
|
305
|
+
{ match: /gemini/i, price: { in: 1.25, out: 5, cacheWrite: 1.25, cacheRead: 0.31 } }
|
|
306
|
+
];
|
|
307
|
+
function estimateCostUSD(model, t) {
|
|
308
|
+
const row = TABLE.find((r) => r.match.test(model));
|
|
309
|
+
if (!row) return 0;
|
|
310
|
+
const p = row.price;
|
|
311
|
+
const usd = (t.inputTokens * p.in + t.outputTokens * p.out + t.cacheCreationTokens * p.cacheWrite + t.cacheReadTokens * p.cacheRead) / 1e6;
|
|
312
|
+
return usd > 0 ? usd : 0;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// src/attribution.ts
|
|
316
|
+
var CLAUDE_PROJECTS = join3(homedir3(), ".claude", "projects");
|
|
317
|
+
var MAX_FILES = 5e3;
|
|
318
|
+
var MAX_FILE_BYTES = 64 * 1024 * 1024;
|
|
319
|
+
var TIME_BUDGET_MS = 3e4;
|
|
320
|
+
var MAX_STATS = 300;
|
|
321
|
+
var MAX_PROJECTS = 500;
|
|
322
|
+
function createAccumulator() {
|
|
323
|
+
return {
|
|
324
|
+
tools: /* @__PURE__ */ new Map(),
|
|
325
|
+
skills: /* @__PURE__ */ new Map(),
|
|
326
|
+
projects: /* @__PURE__ */ new Map(),
|
|
327
|
+
agent: {
|
|
328
|
+
messageCount: 0,
|
|
329
|
+
subagentMessages: 0,
|
|
330
|
+
subagentTokens: 0,
|
|
331
|
+
totalTokens: 0
|
|
332
|
+
},
|
|
333
|
+
titles: /* @__PURE__ */ new Map(),
|
|
334
|
+
sessionMessages: /* @__PURE__ */ new Map()
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function createFileContext() {
|
|
338
|
+
return { toolNames: /* @__PURE__ */ new Map() };
|
|
339
|
+
}
|
|
340
|
+
function recordTokens(usage) {
|
|
341
|
+
if (!usage || typeof usage !== "object") return 0;
|
|
342
|
+
const u = usage;
|
|
343
|
+
const n = (v) => {
|
|
344
|
+
const x = Math.round(Number(v));
|
|
345
|
+
return Number.isFinite(x) && x > 0 ? x : 0;
|
|
346
|
+
};
|
|
347
|
+
return n(u.input_tokens) + n(u.output_tokens) + n(u.cache_creation_input_tokens) + n(u.cache_read_input_tokens);
|
|
348
|
+
}
|
|
349
|
+
function processRecord(rec, acc, ctx) {
|
|
350
|
+
if (!rec || typeof rec !== "object") return;
|
|
351
|
+
const r = rec;
|
|
352
|
+
if (typeof r.attributionSkill === "string" && r.attributionSkill) {
|
|
353
|
+
const s = r.attributionSkill.slice(0, 128);
|
|
354
|
+
acc.skills.set(s, (acc.skills.get(s) ?? 0) + 1);
|
|
355
|
+
}
|
|
356
|
+
if (r.type === "ai-title" && typeof r.aiTitle === "string" && r.aiTitle && typeof r.sessionId === "string" && r.sessionId) {
|
|
357
|
+
acc.titles.set(r.sessionId, r.aiTitle.slice(0, 200));
|
|
358
|
+
}
|
|
359
|
+
const content = r.message?.content;
|
|
360
|
+
if (!Array.isArray(content)) return;
|
|
361
|
+
const isAssistant = r.type === "assistant" || r.message?.role === "assistant";
|
|
362
|
+
const isUser = r.type === "user" || r.message?.role === "user";
|
|
363
|
+
if (isAssistant) {
|
|
364
|
+
for (const block of content) {
|
|
365
|
+
if (block && typeof block === "object" && block.type === "tool_use" && typeof block.name === "string") {
|
|
366
|
+
const name = block.name.slice(0, 128);
|
|
367
|
+
if (!name) continue;
|
|
368
|
+
const t = acc.tools.get(name) ?? { count: 0, errors: 0 };
|
|
369
|
+
t.count += 1;
|
|
370
|
+
acc.tools.set(name, t);
|
|
371
|
+
const id = block.id;
|
|
372
|
+
if (typeof id === "string" && id) ctx.toolNames.set(id, name);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const tokens = recordTokens(r.message?.usage);
|
|
376
|
+
acc.agent.messageCount += 1;
|
|
377
|
+
acc.agent.totalTokens += tokens;
|
|
378
|
+
const sidechain = r.isSidechain === true;
|
|
379
|
+
if (sidechain) {
|
|
380
|
+
acc.agent.subagentMessages += 1;
|
|
381
|
+
acc.agent.subagentTokens += tokens;
|
|
382
|
+
}
|
|
383
|
+
if (typeof r.sessionId === "string" && r.sessionId) {
|
|
384
|
+
acc.sessionMessages.set(
|
|
385
|
+
r.sessionId,
|
|
386
|
+
(acc.sessionMessages.get(r.sessionId) ?? 0) + 1
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
if (typeof r.cwd === "string" && r.cwd && tokens > 0) {
|
|
390
|
+
const name = basename(r.cwd).slice(0, 128) || "unknown";
|
|
391
|
+
const model = typeof r.message?.model === "string" ? r.message.model : "unknown";
|
|
392
|
+
const u = r.message?.usage;
|
|
393
|
+
const num3 = (v) => {
|
|
394
|
+
const x = Math.round(Number(v));
|
|
395
|
+
return Number.isFinite(x) && x > 0 ? x : 0;
|
|
396
|
+
};
|
|
397
|
+
const cost = estimateCostUSD(model, {
|
|
398
|
+
inputTokens: num3(u?.input_tokens),
|
|
399
|
+
outputTokens: num3(u?.output_tokens),
|
|
400
|
+
cacheCreationTokens: num3(u?.cache_creation_input_tokens),
|
|
401
|
+
cacheReadTokens: num3(u?.cache_read_input_tokens)
|
|
402
|
+
});
|
|
403
|
+
const p = acc.projects.get(name) ?? { tokens: 0, costUSD: 0 };
|
|
404
|
+
p.tokens += tokens;
|
|
405
|
+
p.costUSD += cost;
|
|
406
|
+
acc.projects.set(name, p);
|
|
407
|
+
}
|
|
408
|
+
} else if (isUser) {
|
|
409
|
+
for (const block of content) {
|
|
410
|
+
if (block && typeof block === "object" && block.type === "tool_result" && block.is_error === true) {
|
|
411
|
+
const id = block.tool_use_id;
|
|
412
|
+
const name = typeof id === "string" ? ctx.toolNames.get(id) : void 0;
|
|
413
|
+
if (name) {
|
|
414
|
+
const t = acc.tools.get(name) ?? { count: 0, errors: 0 };
|
|
415
|
+
t.errors += 1;
|
|
416
|
+
acc.tools.set(name, t);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function toSkillStats(map) {
|
|
423
|
+
return [...map.entries()].map(([name, count]) => ({ name, count })).filter((s) => s.count > 0).sort((a, b) => b.count - a.count).slice(0, MAX_STATS);
|
|
424
|
+
}
|
|
425
|
+
function toToolStats(map) {
|
|
426
|
+
return [...map.entries()].map(([name, v]) => ({ name, count: v.count, errors: v.errors })).filter((s) => s.count > 0).sort((a, b) => b.count - a.count).slice(0, MAX_STATS).map((s) => s.errors > 0 ? s : { name: s.name, count: s.count });
|
|
427
|
+
}
|
|
428
|
+
function toProjectStats(map) {
|
|
429
|
+
return [...map.entries()].map(([name, v]) => ({
|
|
430
|
+
name,
|
|
431
|
+
tokens: v.tokens,
|
|
432
|
+
costUSD: Number(v.costUSD.toFixed(6))
|
|
433
|
+
})).filter((p) => p.tokens > 0).sort((a, b) => b.tokens - a.tokens).slice(0, MAX_PROJECTS);
|
|
434
|
+
}
|
|
435
|
+
function accumulatorToResult(acc) {
|
|
436
|
+
return {
|
|
437
|
+
tools: toToolStats(acc.tools),
|
|
438
|
+
skills: toSkillStats(acc.skills),
|
|
439
|
+
projects: toProjectStats(acc.projects),
|
|
440
|
+
agent: { ...acc.agent },
|
|
441
|
+
titles: acc.titles,
|
|
442
|
+
sessionMessages: acc.sessionMessages
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function listTranscripts(dir) {
|
|
446
|
+
const out = [];
|
|
447
|
+
const walk = (d) => {
|
|
448
|
+
if (out.length >= MAX_FILES) return;
|
|
449
|
+
let entries;
|
|
450
|
+
try {
|
|
451
|
+
entries = readdirSync(d, { withFileTypes: true });
|
|
452
|
+
} catch {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
for (const e of entries) {
|
|
456
|
+
if (out.length >= MAX_FILES) return;
|
|
457
|
+
const p = join3(d, e.name);
|
|
458
|
+
if (e.isDirectory()) walk(p);
|
|
459
|
+
else if (e.isFile() && e.name.endsWith(".jsonl")) {
|
|
460
|
+
try {
|
|
461
|
+
out.push({ path: p, mtime: statSync(p).mtimeMs });
|
|
462
|
+
} catch {
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
walk(dir);
|
|
468
|
+
return out.sort((a, b) => b.mtime - a.mtime).slice(0, MAX_FILES).map((f) => f.path);
|
|
469
|
+
}
|
|
470
|
+
function collectAttribution() {
|
|
471
|
+
const acc = createAccumulator();
|
|
472
|
+
const deadline = Date.now() + TIME_BUDGET_MS;
|
|
473
|
+
try {
|
|
474
|
+
for (const file of listTranscripts(CLAUDE_PROJECTS)) {
|
|
475
|
+
if (Date.now() > deadline) break;
|
|
476
|
+
let size = 0;
|
|
477
|
+
try {
|
|
478
|
+
size = statSync(file).size;
|
|
479
|
+
} catch {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
if (size > MAX_FILE_BYTES) continue;
|
|
483
|
+
let text;
|
|
484
|
+
try {
|
|
485
|
+
text = readFileSync2(file, "utf8");
|
|
486
|
+
} catch {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
const ctx = createFileContext();
|
|
490
|
+
for (const line of text.split("\n")) {
|
|
491
|
+
if (!line) continue;
|
|
492
|
+
try {
|
|
493
|
+
processRecord(JSON.parse(line), acc, ctx);
|
|
494
|
+
} catch {
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
return accumulatorToResult(acc);
|
|
501
|
+
}
|
|
290
502
|
|
|
291
503
|
// src/cursor.ts
|
|
292
504
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
293
505
|
import { existsSync as existsSync3 } from "node:fs";
|
|
294
506
|
import { createRequire as createRequire2 } from "node:module";
|
|
295
|
-
import { homedir as
|
|
296
|
-
import { join as
|
|
507
|
+
import { homedir as homedir4, platform as platform2 } from "node:os";
|
|
508
|
+
import { join as join5 } from "node:path";
|
|
297
509
|
|
|
298
510
|
// src/tokscale.ts
|
|
299
511
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
300
512
|
import { createRequire } from "node:module";
|
|
301
|
-
import { dirname, join as
|
|
513
|
+
import { dirname, join as join4 } from "node:path";
|
|
302
514
|
var LOOKBACK_DAYS = 30;
|
|
303
515
|
function num(n) {
|
|
304
516
|
const v = Math.round(Number(n));
|
|
@@ -342,7 +554,7 @@ function resolveTokscaleBin() {
|
|
|
342
554
|
const pkg = require3("tokscale/package.json");
|
|
343
555
|
const rel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.tokscale ?? "";
|
|
344
556
|
if (!rel) return null;
|
|
345
|
-
const binPath =
|
|
557
|
+
const binPath = join4(dirname(pkgPath), rel);
|
|
346
558
|
if (/\.(c|m)?js$/.test(binPath)) {
|
|
347
559
|
return { cmd: process.execPath, prefixArgs: [binPath] };
|
|
348
560
|
}
|
|
@@ -397,9 +609,9 @@ function collectCursorViaTokscale(lookbackDays = LOOKBACK_DAYS) {
|
|
|
397
609
|
// src/cursor.ts
|
|
398
610
|
var EVENTS_URL = "https://cursor.com/api/dashboard/get-filtered-usage-events";
|
|
399
611
|
function cursorDbPath() {
|
|
400
|
-
const home =
|
|
612
|
+
const home = homedir4();
|
|
401
613
|
const os = platform2();
|
|
402
|
-
const p = os === "darwin" ?
|
|
614
|
+
const p = os === "darwin" ? join5(home, "Library", "Application Support", "Cursor", "User", "globalStorage", "state.vscdb") : os === "win32" ? join5(process.env.APPDATA ?? join5(home, "AppData", "Roaming"), "Cursor", "User", "globalStorage", "state.vscdb") : join5(process.env.XDG_CONFIG_HOME ?? join5(home, ".config"), "Cursor", "User", "globalStorage", "state.vscdb");
|
|
403
615
|
return existsSync3(p) ? p : null;
|
|
404
616
|
}
|
|
405
617
|
function readCursorToken(db) {
|
|
@@ -672,7 +884,7 @@ function resolveCcusageBin() {
|
|
|
672
884
|
const pkgPath = require3.resolve("ccusage/package.json");
|
|
673
885
|
const pkg = require3("ccusage/package.json");
|
|
674
886
|
const rel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.ccusage ?? "ccusage";
|
|
675
|
-
const binPath =
|
|
887
|
+
const binPath = join6(dirname2(pkgPath), rel);
|
|
676
888
|
if (/\.(c|m)?js$/.test(binPath)) {
|
|
677
889
|
return { cmd: process.execPath, prefixArgs: [binPath] };
|
|
678
890
|
}
|
|
@@ -760,11 +972,25 @@ async function collectAll() {
|
|
|
760
972
|
blocks.push(...cursor.blocks);
|
|
761
973
|
toolsFound.push("cursor");
|
|
762
974
|
}
|
|
975
|
+
const { tools, skills, projects, agent, titles, sessionMessages } = collectAttribution();
|
|
976
|
+
const dedupedSessions = dedupeSessions(sessions).map((s) => {
|
|
977
|
+
const title = titles.get(s.sessionId);
|
|
978
|
+
const messageCount = sessionMessages.get(s.sessionId);
|
|
979
|
+
return {
|
|
980
|
+
...s,
|
|
981
|
+
...title ? { title } : {},
|
|
982
|
+
...messageCount ? { messageCount } : {}
|
|
983
|
+
};
|
|
984
|
+
});
|
|
763
985
|
return {
|
|
764
986
|
entries: dedupeDaily(entries),
|
|
765
|
-
sessions:
|
|
987
|
+
sessions: dedupedSessions,
|
|
766
988
|
blocks: dedupeBlocks(blocks),
|
|
767
|
-
toolsFound
|
|
989
|
+
toolsFound,
|
|
990
|
+
tools,
|
|
991
|
+
skills,
|
|
992
|
+
projects,
|
|
993
|
+
agent
|
|
768
994
|
};
|
|
769
995
|
}
|
|
770
996
|
|
|
@@ -4855,13 +5081,42 @@ var SessionEntry = external_exports.object({
|
|
|
4855
5081
|
cacheCreationTokens: tokenCount,
|
|
4856
5082
|
cacheReadTokens: tokenCount,
|
|
4857
5083
|
costUSD: external_exports.number().nonnegative(),
|
|
4858
|
-
lastActivity: Timestamp
|
|
5084
|
+
lastActivity: Timestamp,
|
|
5085
|
+
/** Human-readable AI-generated session title (from transcripts). Optional. */
|
|
5086
|
+
title: external_exports.string().max(200).optional(),
|
|
5087
|
+
/** Number of assistant messages in this session (from transcripts). Optional. */
|
|
5088
|
+
messageCount: external_exports.number().int().nonnegative().optional()
|
|
4859
5089
|
});
|
|
4860
5090
|
var BlockEntry = external_exports.object({
|
|
4861
5091
|
startTime: Timestamp,
|
|
4862
5092
|
totalTokens: tokenCount,
|
|
4863
5093
|
costUSD: external_exports.number().nonnegative()
|
|
4864
5094
|
});
|
|
5095
|
+
var ToolStat = external_exports.object({
|
|
5096
|
+
name: external_exports.string().min(1).max(128),
|
|
5097
|
+
count: external_exports.number().int().nonnegative(),
|
|
5098
|
+
/** How many of those calls returned an error/interrupt (tool reliability). Optional. */
|
|
5099
|
+
errors: external_exports.number().int().nonnegative().optional()
|
|
5100
|
+
});
|
|
5101
|
+
var ProjectStat = external_exports.object({
|
|
5102
|
+
name: external_exports.string().min(1).max(128),
|
|
5103
|
+
tokens: external_exports.number().int().nonnegative(),
|
|
5104
|
+
costUSD: external_exports.number().nonnegative()
|
|
5105
|
+
});
|
|
5106
|
+
var AgentStat = external_exports.object({
|
|
5107
|
+
/** Total assistant messages across transcripts. */
|
|
5108
|
+
messageCount: external_exports.number().int().nonnegative(),
|
|
5109
|
+
/** Assistant messages that ran inside a subagent sidechain. */
|
|
5110
|
+
subagentMessages: external_exports.number().int().nonnegative(),
|
|
5111
|
+
/** Tokens spent inside subagent sidechains. */
|
|
5112
|
+
subagentTokens: external_exports.number().int().nonnegative(),
|
|
5113
|
+
/** Total tokens observed across transcripts (denominator for the share). */
|
|
5114
|
+
totalTokens: external_exports.number().int().nonnegative()
|
|
5115
|
+
});
|
|
5116
|
+
var SkillStat = external_exports.object({
|
|
5117
|
+
name: external_exports.string().min(1).max(128),
|
|
5118
|
+
count: external_exports.number().int().nonnegative()
|
|
5119
|
+
});
|
|
4865
5120
|
var SubmitPayload = external_exports.object({
|
|
4866
5121
|
cliVersion: external_exports.string().min(1).max(32),
|
|
4867
5122
|
entries: external_exports.array(DailyUsageEntry).min(1).max(2e4),
|
|
@@ -4869,6 +5124,14 @@ var SubmitPayload = external_exports.object({
|
|
|
4869
5124
|
sessions: external_exports.array(SessionEntry).max(1e4).optional(),
|
|
4870
5125
|
/** Optional time-window rollups (ccusage blocks) for peak-hours analysis. */
|
|
4871
5126
|
blocks: external_exports.array(BlockEntry).max(1e4).optional(),
|
|
5127
|
+
/** Optional tool-call frequencies parsed from local transcripts (names + counts). */
|
|
5128
|
+
tools: external_exports.array(ToolStat).max(300).optional(),
|
|
5129
|
+
/** Optional skill-usage frequencies parsed from local transcripts. */
|
|
5130
|
+
skills: external_exports.array(SkillStat).max(300).optional(),
|
|
5131
|
+
/** Optional per-project usage totals parsed from local transcripts. */
|
|
5132
|
+
projects: external_exports.array(ProjectStat).max(500).optional(),
|
|
5133
|
+
/** Optional subagent-vs-main rollup parsed from local transcripts. */
|
|
5134
|
+
agent: AgentStat.optional(),
|
|
4872
5135
|
/** Optional friends-board code (from `--board=<code>`): auto-join this board on submit. */
|
|
4873
5136
|
board: external_exports.string().min(1).max(32).optional()
|
|
4874
5137
|
});
|
|
@@ -5154,7 +5417,7 @@ async function confirm(question) {
|
|
|
5154
5417
|
function showLocalDashboard(entries) {
|
|
5155
5418
|
const dir = defaultConfigDir();
|
|
5156
5419
|
mkdirSync3(dir, { recursive: true });
|
|
5157
|
-
const file =
|
|
5420
|
+
const file = join7(dir, "dashboard.html");
|
|
5158
5421
|
writeFileSync3(file, renderDashboardHtml(entries));
|
|
5159
5422
|
console.log();
|
|
5160
5423
|
console.log(` Local dashboard: ${pc2.cyan(`file://${file}`)}`);
|
|
@@ -5173,7 +5436,7 @@ async function run(flags) {
|
|
|
5173
5436
|
} finally {
|
|
5174
5437
|
stop();
|
|
5175
5438
|
}
|
|
5176
|
-
const { entries, sessions, blocks, toolsFound } = collected;
|
|
5439
|
+
const { entries, sessions, blocks, toolsFound, tools, skills, projects, agent } = collected;
|
|
5177
5440
|
if (entries.length === 0) {
|
|
5178
5441
|
console.log();
|
|
5179
5442
|
console.log(" Nothing to burn yet \u2014 no local usage found from any coding agent.");
|
|
@@ -5183,6 +5446,10 @@ async function run(flags) {
|
|
|
5183
5446
|
const payload = { cliVersion: VERSION, entries };
|
|
5184
5447
|
if (sessions.length > 0) payload.sessions = sessions;
|
|
5185
5448
|
if (blocks.length > 0) payload.blocks = blocks;
|
|
5449
|
+
if (tools.length > 0) payload.tools = tools;
|
|
5450
|
+
if (skills.length > 0) payload.skills = skills;
|
|
5451
|
+
if (projects.length > 0) payload.projects = projects;
|
|
5452
|
+
if (agent.messageCount > 0) payload.agent = agent;
|
|
5186
5453
|
if (flags.board) payload.board = flags.board;
|
|
5187
5454
|
if (flags.dryRun) {
|
|
5188
5455
|
console.log(pc2.dim("\n --dry-run: this exact payload would be sent, nothing else:\n"));
|