tokentracker-cli 0.7.0 → 0.8.1

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.
@@ -210,7 +210,7 @@
210
210
  ]
211
211
  }
212
212
  </script>
213
- <script type="module" crossorigin src="/assets/main-CuwxhzW4.js"></script>
213
+ <script type="module" crossorigin src="/assets/main-CBVhF0BE.js"></script>
214
214
  <link rel="stylesheet" crossorigin href="/assets/main-HLMqEvtH.css">
215
215
  </head>
216
216
  <body>
@@ -51,7 +51,7 @@
51
51
  "description": "Shareable Token Tracker dashboard snapshot."
52
52
  }
53
53
  </script>
54
- <script type="module" crossorigin src="/assets/main-CuwxhzW4.js"></script>
54
+ <script type="module" crossorigin src="/assets/main-CBVhF0BE.js"></script>
55
55
  <link rel="stylesheet" crossorigin href="/assets/main-HLMqEvtH.css">
56
56
  </head>
57
57
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tokentracker-cli",
3
- "version": "0.7.0",
4
- "description": "Token usage tracker for AI agent CLIs (Claude Code, Codex, Cursor, Gemini, Kiro, OpenCode, OpenClaw, Every Code, Hermes, GitHub Copilot, Kimi Code, CodeBuddy, oh-my-pi, Craft Agents)",
3
+ "version": "0.8.1",
4
+ "description": "Token usage tracker for AI agent CLIs (Claude Code, Codex, Cursor, Gemini, Kiro, OpenCode, OpenClaw, Every Code, Hermes, GitHub Copilot, Kimi Code, CodeBuddy, oh-my-pi, pi, Craft Agents)",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
7
7
  "tokentracker-cli": "bin/tracker.js",
@@ -44,6 +44,11 @@ const {
44
44
  probeOpenclawSessionPluginState,
45
45
  } = require("../lib/openclaw-session-plugin");
46
46
  const { resolveTrackerPaths } = require("../lib/tracker-paths");
47
+ const {
48
+ resolveOmpAgentDir,
49
+ resolvePiAgentDir,
50
+ piAgentDirCollidesWithOmp,
51
+ } = require("../lib/rollout");
47
52
  const { resolveRuntimeConfig, DEFAULT_BASE_URL } = require("../lib/runtime-config");
48
53
  const {
49
54
  BOLD,
@@ -428,15 +433,22 @@ async function applyIntegrationSetup({ home, trackerDir, notifyPath, notifyOrigi
428
433
  // oh-my-pi: passive reader — no hook installation needed.
429
434
  // TokenTracker reads ~/.omp/agent/sessions/**/*.jsonl directly.
430
435
  {
431
- const ompHome = process.env.OMP_HOME ||
432
- (process.env.PI_CONFIG_DIR ? path.join(home, process.env.PI_CONFIG_DIR) : path.join(home, ".omp"));
433
- const ompAgentDir = process.env.PI_CODING_AGENT_DIR || path.join(ompHome, "agent");
434
- const ompSessions = path.join(ompAgentDir, "sessions");
436
+ const ompSessions = path.join(resolveOmpAgentDir(process.env), "sessions");
435
437
  if (fssync.existsSync(ompSessions)) {
436
438
  summary.push({ label: "oh-my-pi", status: "detected", detail: "Passive reader (no hook needed)" });
437
439
  }
438
440
  }
439
441
 
442
+ // pi (@mariozechner/pi-coding-agent): passive reader — no hook installation needed.
443
+ // TokenTracker reads ~/.pi/agent/sessions/**/*.jsonl directly. Skip when its
444
+ // agent dir collides with omp's so the summary matches what sync will scan.
445
+ if (!piAgentDirCollidesWithOmp(process.env)) {
446
+ const piSessions = path.join(resolvePiAgentDir(process.env), "sessions");
447
+ if (fssync.existsSync(piSessions)) {
448
+ summary.push({ label: "pi", status: "detected", detail: "Passive reader (no hook needed)" });
449
+ }
450
+ }
451
+
440
452
  // Craft Agents: passive reader — no hook installation needed.
441
453
  // TokenTracker reads ~/.craft-agent/workspaces/<id>/sessions/**/session.jsonl
442
454
  // (and any user-relocated workspace listed in ~/.craft-agent/config.json).
@@ -41,6 +41,9 @@ const {
41
41
  resolveCodebuddyProjectFiles,
42
42
  resolveOmpSessionFiles,
43
43
  resolveOmpAgentDir,
44
+ resolvePiSessionFiles,
45
+ resolvePiAgentDir,
46
+ piAgentDirCollidesWithOmp,
44
47
  resolveCraftSessionFiles,
45
48
  resolveCraftConfigDir,
46
49
  } = require("../lib/rollout");
@@ -185,6 +188,13 @@ async function cmdStatus(argv = []) {
185
188
  const ompInstalled = fssync.existsSync(path.join(ompAgentDir, "sessions"));
186
189
  const ompFiles = ompInstalled ? resolveOmpSessionFiles(process.env) : [];
187
190
 
191
+ // pi (@mariozechner/pi-coding-agent) — passive scan only (no hooks).
192
+ // Skip when its agent dir collides with omp's; sync would dedupe anyway.
193
+ const piCollides = piAgentDirCollidesWithOmp(process.env);
194
+ const piAgentDir = resolvePiAgentDir(process.env);
195
+ const piInstalled = !piCollides && fssync.existsSync(path.join(piAgentDir, "sessions"));
196
+ const piFiles = piInstalled ? resolvePiSessionFiles(process.env) : [];
197
+
188
198
  // Craft Agents — passive scan only (no hooks).
189
199
  const craftConfigDir = resolveCraftConfigDir(process.env);
190
200
  const craftInstalled = fssync.existsSync(craftConfigDir);
@@ -231,6 +241,9 @@ async function cmdStatus(argv = []) {
231
241
  ompInstalled
232
242
  ? `- oh-my-pi: passive reader (${ompFiles.length} session jsonl file${ompFiles.length !== 1 ? "s" : ""} found)`
233
243
  : null,
244
+ piInstalled
245
+ ? `- pi: passive reader (${piFiles.length} session jsonl file${piFiles.length !== 1 ? "s" : ""} found)`
246
+ : null,
234
247
  craftInstalled
235
248
  ? `- Craft Agents: passive reader (${craftFiles.length} session jsonl file${craftFiles.length !== 1 ? "s" : ""} found)`
236
249
  : null,
@@ -30,6 +30,9 @@ const {
30
30
  parseKimiIncremental,
31
31
  resolveOmpSessionFiles,
32
32
  parseOmpIncremental,
33
+ resolvePiSessionFiles,
34
+ parsePiIncremental,
35
+ piAgentDirCollidesWithOmp,
33
36
  resolveCraftSessionFiles,
34
37
  parseCraftIncremental,
35
38
  resolveCodebuddyProjectFiles,
@@ -477,6 +480,33 @@ async function cmdSync(argv) {
477
480
  });
478
481
  }
479
482
 
483
+ // ── pi (@mariozechner/pi-coding-agent) — passive ~/.pi/agent/sessions/**/*.jsonl reader ──
484
+ // Skip pi parse if its agent dir resolves to the same path as omp's. This
485
+ // prevents double-counting when explicit overrides (TOKENTRACKER_OMP_AGENT_DIR /
486
+ // TOKENTRACKER_PI_AGENT_DIR) bypass the install-signal disambiguator.
487
+ let piResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
488
+ const piFiles = piAgentDirCollidesWithOmp(process.env)
489
+ ? []
490
+ : resolvePiSessionFiles(process.env);
491
+ if (piFiles.length > 0) {
492
+ if (progress?.enabled) {
493
+ progress.start(`Parsing pi ${renderBar(0)} | buckets 0`);
494
+ }
495
+ piResult = await parsePiIncremental({
496
+ sessionFiles: piFiles,
497
+ cursors,
498
+ queuePath,
499
+ env: process.env,
500
+ onProgress: (p) => {
501
+ if (!progress?.enabled) return;
502
+ const pct = p.total > 0 ? p.index / p.total : 1;
503
+ progress.update(
504
+ `Parsing pi ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} files | buckets ${formatNumber(p.bucketsQueued)}`,
505
+ );
506
+ },
507
+ });
508
+ }
509
+
480
510
  // ── Craft Agents (passive ~/.craft-agent + workspaces session.jsonl reader) ──
481
511
  let craftResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
482
512
  const craftFiles = resolveCraftSessionFiles(process.env);
@@ -619,6 +649,7 @@ async function cmdSync(argv) {
619
649
  kimiResult.recordsProcessed +
620
650
  codebuddyResult.recordsProcessed +
621
651
  ompResult.recordsProcessed +
652
+ piResult.recordsProcessed +
622
653
  craftResult.recordsProcessed +
623
654
  copilotResult.recordsProcessed;
624
655
  const totalBuckets =
@@ -634,6 +665,7 @@ async function cmdSync(argv) {
634
665
  kimiResult.bucketsQueued +
635
666
  codebuddyResult.bucketsQueued +
636
667
  ompResult.bucketsQueued +
668
+ piResult.bucketsQueued +
637
669
  craftResult.bucketsQueued +
638
670
  copilotResult.bucketsQueued;
639
671
  process.stdout.write(