tokentracker-cli 0.5.99 → 0.5.100

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.
@@ -135,7 +135,7 @@
135
135
  ]
136
136
  }
137
137
  </script>
138
- <script type="module" crossorigin src="/assets/main-BhjD_pKB.js"></script>
138
+ <script type="module" crossorigin src="/assets/main-BYMjcXxR.js"></script>
139
139
  <link rel="stylesheet" crossorigin href="/assets/main-HLMqEvtH.css">
140
140
  </head>
141
141
  <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-BhjD_pKB.js"></script>
54
+ <script type="module" crossorigin src="/assets/main-BYMjcXxR.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.5.99",
4
- "description": "Token usage tracker for AI agent CLIs (Claude Code, Codex, Cursor, Kiro, Gemini, OpenCode, OpenClaw, Hermes, GitHub Copilot)",
3
+ "version": "0.5.100",
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)",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
7
7
  "tokentracker-cli": "bin/tracker.js",
@@ -425,6 +425,18 @@ async function applyIntegrationSetup({ home, trackerDir, notifyPath, notifyOrigi
425
425
  }
426
426
  }
427
427
 
428
+ // oh-my-pi: passive reader — no hook installation needed.
429
+ // TokenTracker reads ~/.omp/agent/sessions/**/*.jsonl directly.
430
+ {
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");
435
+ if (fssync.existsSync(ompSessions)) {
436
+ summary.push({ label: "oh-my-pi", status: "detected", detail: "Passive reader (no hook needed)" });
437
+ }
438
+ }
439
+
428
440
  // CodeBuddy: Claude-Code fork. Install the SessionEnd hook so finished
429
441
  // sessions trigger notify.cjs → tracker sync; passive scan still runs as a
430
442
  // safety net for sessions that don't fire SessionEnd cleanly.
@@ -16,19 +16,31 @@ const {
16
16
  isGeminiHookConfigured,
17
17
  buildGeminiHookCommand,
18
18
  } = require("../lib/gemini-config");
19
- const { resolveOpencodeConfigDir, isOpencodePluginInstalled } = require("../lib/opencode-config");
19
+ const {
20
+ resolveOpencodeConfigDir,
21
+ isOpencodePluginInstalled,
22
+ } = require("../lib/opencode-config");
20
23
  const { collectLocalSubscriptions } = require("../lib/subscriptions");
21
- const { describeCopilotOtelStatus, readCopilotOauthToken } = require("../lib/usage-limits");
22
- const { normalizeState: normalizeUploadState } = require("../lib/upload-throttle");
24
+ const {
25
+ describeCopilotOtelStatus,
26
+ readCopilotOauthToken,
27
+ } = require("../lib/usage-limits");
28
+ const {
29
+ normalizeState: normalizeUploadState,
30
+ } = require("../lib/upload-throttle");
23
31
  const { collectTrackerDiagnostics } = require("../lib/diagnostics");
24
32
  const { probeOpenclawHookState } = require("../lib/openclaw-hook");
25
- const { probeOpenclawSessionPluginState } = require("../lib/openclaw-session-plugin");
33
+ const {
34
+ probeOpenclawSessionPluginState,
35
+ } = require("../lib/openclaw-session-plugin");
26
36
  const { resolveTrackerPaths } = require("../lib/tracker-paths");
27
37
  const {
28
38
  resolveKimiWireFiles,
29
39
  resolveKiroCliDbPath,
30
40
  resolveCodebuddyHome,
31
41
  resolveCodebuddyProjectFiles,
42
+ resolveOmpSessionFiles,
43
+ resolveOmpAgentDir,
32
44
  } = require("../lib/rollout");
33
45
 
34
46
  async function cmdStatus(argv = []) {
@@ -60,8 +72,13 @@ async function cmdStatus(argv = []) {
60
72
  "settings.json",
61
73
  );
62
74
  const geminiConfigDir = resolveGeminiConfigDir({ home, env: process.env });
63
- const geminiSettingsPath = resolveGeminiSettingsPath({ configDir: geminiConfigDir });
64
- const opencodeConfigDir = resolveOpencodeConfigDir({ home, env: process.env });
75
+ const geminiSettingsPath = resolveGeminiSettingsPath({
76
+ configDir: geminiConfigDir,
77
+ });
78
+ const opencodeConfigDir = resolveOpencodeConfigDir({
79
+ home,
80
+ env: process.env,
81
+ });
65
82
  const notifyPath = path.join(binDir, "notify.cjs");
66
83
  const claudeHookCommand = buildClaudeHookCommand(notifyPath);
67
84
  const codebuddyHookCommand = buildHookCommand(notifyPath, "codebuddy");
@@ -70,20 +87,26 @@ async function cmdStatus(argv = []) {
70
87
  const config = await readJson(configPath);
71
88
  const cursors = await readJson(cursorsPath);
72
89
  const queueState = (await readJson(queueStatePath)) || { offset: 0 };
73
- const uploadThrottle = normalizeUploadState(await readJson(uploadThrottlePath));
90
+ const uploadThrottle = normalizeUploadState(
91
+ await readJson(uploadThrottlePath),
92
+ );
74
93
  const autoRetry = await readJson(autoRetryPath);
75
94
 
76
95
  const queueSize = await safeStatSize(queuePath);
77
96
  const pendingBytes = Math.max(0, queueSize - (queueState.offset || 0));
78
97
 
79
98
  const lastNotify = (await safeReadText(notifySignalPath))?.trim() || null;
80
- const lastOpenclawSync = (await safeReadText(openclawSignalPath))?.trim() || null;
81
- const lastNotifySpawn = parseEpochMsToIso((await safeReadText(throttlePath))?.trim() || null);
99
+ const lastOpenclawSync =
100
+ (await safeReadText(openclawSignalPath))?.trim() || null;
101
+ const lastNotifySpawn = parseEpochMsToIso(
102
+ (await safeReadText(throttlePath))?.trim() || null,
103
+ );
82
104
 
83
105
  const codexNotify = await readCodexNotify(codexConfigPath);
84
106
  const notifyConfigured = Array.isArray(codexNotify) && codexNotify.length > 0;
85
107
  const everyCodeNotify = await readEveryCodeNotify(codeConfigPath);
86
- const everyCodeConfigured = Array.isArray(everyCodeNotify) && everyCodeNotify.length > 0;
108
+ const everyCodeConfigured =
109
+ Array.isArray(everyCodeNotify) && everyCodeNotify.length > 0;
87
110
  const claudeHookConfigured = await isClaudeHookConfigured({
88
111
  settingsPath: claudeSettingsPath,
89
112
  hookCommand: claudeHookCommand,
@@ -104,7 +127,11 @@ async function cmdStatus(argv = []) {
104
127
  trackerDir,
105
128
  env: process.env,
106
129
  });
107
- const openclawHookState = await probeOpenclawHookState({ home, trackerDir, env: process.env });
130
+ const openclawHookState = await probeOpenclawHookState({
131
+ home,
132
+ trackerDir,
133
+ env: process.env,
134
+ });
108
135
 
109
136
  const lastUpload = uploadThrottle.lastSuccessMs
110
137
  ? parseEpochMsToIso(uploadThrottle.lastSuccessMs)
@@ -151,9 +178,17 @@ async function cmdStatus(argv = []) {
151
178
  ? resolveCodebuddyProjectFiles(process.env)
152
179
  : [];
153
180
 
181
+ // oh-my-pi — passive scan only (no hooks).
182
+ const ompAgentDir = resolveOmpAgentDir(process.env);
183
+ const ompInstalled = fssync.existsSync(path.join(ompAgentDir, "sessions"));
184
+ const ompFiles = ompInstalled ? resolveOmpSessionFiles(process.env) : [];
185
+
154
186
  const copilotToken = readCopilotOauthToken({ home });
155
187
  const copilotOtel = describeCopilotOtelStatus({ home, env: process.env });
156
- const copilotLines = formatCopilotLines({ token: copilotToken, otel: copilotOtel });
188
+ const copilotLines = formatCopilotLines({
189
+ token: copilotToken,
190
+ otel: copilotOtel,
191
+ });
157
192
 
158
193
  process.stdout.write(
159
194
  [
@@ -186,6 +221,9 @@ async function cmdStatus(argv = []) {
186
221
  codebuddyInstalled
187
222
  ? `- CodeBuddy hooks: ${codebuddyHookConfigured ? "set" : "unset"} (${codebuddyFiles.length} session jsonl file${codebuddyFiles.length !== 1 ? "s" : ""} found)`
188
223
  : null,
224
+ ompInstalled
225
+ ? `- oh-my-pi: passive reader (${ompFiles.length} session jsonl file${ompFiles.length !== 1 ? "s" : ""} found)`
226
+ : null,
189
227
  ...copilotLines,
190
228
  ...subscriptionLines,
191
229
  "",
@@ -197,7 +235,9 @@ async function cmdStatus(argv = []) {
197
235
 
198
236
  function formatCopilotLines({ token, otel }) {
199
237
  if (!token && !otel.otel_has_files) return [];
200
- const limitsState = token ? "set (via GitHub OAuth)" : "unset (no Copilot OAuth token found)";
238
+ const limitsState = token
239
+ ? "set (via GitHub OAuth)"
240
+ : "unset (no Copilot OAuth token found)";
201
241
  const usageState = otel.otel_has_files
202
242
  ? `set (${otel.otel_path || otel.otel_default_dir})`
203
243
  : otel.otel_enabled
@@ -235,7 +275,11 @@ function formatSubscriptionLine(entry = {}) {
235
275
 
236
276
  if (!planType) return null;
237
277
 
238
- if (tool === "claude" && provider === "anthropic" && product === "subscription") {
278
+ if (
279
+ tool === "claude" &&
280
+ provider === "anthropic" &&
281
+ product === "subscription"
282
+ ) {
239
283
  const suffix = rateLimitTier ? ` (rate limit tier: ${rateLimitTier})` : "";
240
284
  return `- ${toolLabel} subscription: ${planType}${suffix}`;
241
285
  }
@@ -249,7 +293,11 @@ function formatSubscriptionLine(entry = {}) {
249
293
  }
250
294
 
251
295
  function parseArgs(argv) {
252
- const out = { diagnostics: false, probeKeychain: false, probeKeychainDetails: false };
296
+ const out = {
297
+ diagnostics: false,
298
+ probeKeychain: false,
299
+ probeKeychainDetails: false,
300
+ };
253
301
 
254
302
  for (let i = 0; i < argv.length; i++) {
255
303
  const a = argv[i];
@@ -27,6 +27,8 @@ const {
27
27
  parseCopilotIncremental,
28
28
  resolveKimiWireFiles,
29
29
  parseKimiIncremental,
30
+ resolveOmpSessionFiles,
31
+ parseOmpIncremental,
30
32
  resolveCodebuddyProjectFiles,
31
33
  parseCodebuddyIncremental,
32
34
  resolveKiroCliSessionFiles,
@@ -447,6 +449,28 @@ async function cmdSync(argv) {
447
449
  });
448
450
  }
449
451
 
452
+ // ── oh-my-pi (passive ~/.omp/agent/sessions/**/*.jsonl reader) ──
453
+ let ompResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
454
+ const ompFiles = resolveOmpSessionFiles(process.env);
455
+ if (ompFiles.length > 0) {
456
+ if (progress?.enabled) {
457
+ progress.start(`Parsing oh-my-pi ${renderBar(0)} | buckets 0`);
458
+ }
459
+ ompResult = await parseOmpIncremental({
460
+ sessionFiles: ompFiles,
461
+ cursors,
462
+ queuePath,
463
+ env: process.env,
464
+ onProgress: (p) => {
465
+ if (!progress?.enabled) return;
466
+ const pct = p.total > 0 ? p.index / p.total : 1;
467
+ progress.update(
468
+ `Parsing oh-my-pi ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} files | buckets ${formatNumber(p.bucketsQueued)}`,
469
+ );
470
+ },
471
+ });
472
+ }
473
+
450
474
  // ── GitHub Copilot CLI (OTEL JSONL files) ──
451
475
  let copilotResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
452
476
  const copilotPaths = resolveCopilotOtelPaths(process.env);
@@ -566,6 +590,7 @@ async function cmdSync(argv) {
566
590
  hermesResult.recordsProcessed +
567
591
  kimiResult.recordsProcessed +
568
592
  codebuddyResult.recordsProcessed +
593
+ ompResult.recordsProcessed +
569
594
  copilotResult.recordsProcessed;
570
595
  const totalBuckets =
571
596
  parseResult.bucketsQueued +
@@ -579,6 +604,7 @@ async function cmdSync(argv) {
579
604
  hermesResult.bucketsQueued +
580
605
  kimiResult.bucketsQueued +
581
606
  codebuddyResult.bucketsQueued +
607
+ ompResult.bucketsQueued +
582
608
  copilotResult.bucketsQueued;
583
609
  process.stdout.write(
584
610
  [