tokentracker-cli 0.80.0 → 0.80.2

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.
Files changed (72) hide show
  1. package/dashboard/dist/assets/{AchievementBadge-D9jOMhlD.js → AchievementBadge-lZzUk8UJ.js} +1 -1
  2. package/dashboard/dist/assets/{AchievementsPage-DuswZa4g.js → AchievementsPage-Ddht3Szx.js} +2 -2
  3. package/dashboard/dist/assets/{AchievementsSection-BJPeE1Uq.js → AchievementsSection-Bz9Enx-j.js} +1 -1
  4. package/dashboard/dist/assets/{BadgeDetailModal-nNPIsy6i.js → BadgeDetailModal-C7QiFDH4.js} +1 -1
  5. package/dashboard/dist/assets/{Card-VENq8eEp.js → Card-Cs_xyoXz.js} +1 -1
  6. package/dashboard/dist/assets/{ClawdAnimated-Cq7TW0vv.js → ClawdAnimated-C1Y6W_Di.js} +1 -1
  7. package/dashboard/dist/assets/{CommunityStatsModal-y2VftQuq.js → CommunityStatsModal-B1VvGpUY.js} +1 -1
  8. package/dashboard/dist/assets/{ConfirmModal-CWgnJ4hm.js → ConfirmModal-Cd-fM8lV.js} +1 -1
  9. package/dashboard/dist/assets/{Controls-BUQ_iZZq.js → Controls-D0ULfwWh.js} +1 -1
  10. package/dashboard/dist/assets/DashboardPage-DXbecrQR.js +19 -0
  11. package/dashboard/dist/assets/{DevicePage-Dh3XDtNx.js → DevicePage-BJsSXmi0.js} +1 -1
  12. package/dashboard/dist/assets/{DialogClose-KTFU_B3F.js → DialogClose-BkG6LVKN.js} +1 -1
  13. package/dashboard/dist/assets/DialogDescription-DDDcU_07.js +1 -0
  14. package/dashboard/dist/assets/{DialogTitle-bza2pIek.js → DialogTitle-Do2zDkSF.js} +1 -1
  15. package/dashboard/dist/assets/{FadeIn-Dm3FVNfr.js → FadeIn-BlxFR4Uo.js} +1 -1
  16. package/dashboard/dist/assets/{HeaderGithubStar-CbSElzLt.js → HeaderGithubStar-CsLBMMBv.js} +1 -1
  17. package/dashboard/dist/assets/{IpCheckPage-BDON7VCU.js → IpCheckPage-Bi1QPsiQ.js} +1 -1
  18. package/dashboard/dist/assets/{LandingPage-Ck3CwZrt.js → LandingPage-Ble4Qxzj.js} +1 -1
  19. package/dashboard/dist/assets/{LeaderboardAvatar-GVUy0Ynq.js → LeaderboardAvatar-D2Iqj9VP.js} +1 -1
  20. package/dashboard/dist/assets/{LeaderboardPage-C19Rkt44.js → LeaderboardPage-DImECEuN.js} +2 -2
  21. package/dashboard/dist/assets/{LeaderboardProfileModal-QcEq_o6E.js → LeaderboardProfileModal-BGkNzlpU.js} +3 -3
  22. package/dashboard/dist/assets/{LeaderboardProfilePage-pFhI6292.js → LeaderboardProfilePage-f-E74S02.js} +1 -1
  23. package/dashboard/dist/assets/{LimitsPage-ChV3Qezd.js → LimitsPage-BgTxwSrO.js} +1 -1
  24. package/dashboard/dist/assets/{LocalOnlyNotice-ALvpjznF.js → LocalOnlyNotice-D91Lp2zA.js} +1 -1
  25. package/dashboard/dist/assets/{LoginPage-CL-QrJxU.js → LoginPage-hbsmEr6V.js} +1 -1
  26. package/dashboard/dist/assets/{PetPage-DSuvdGgd.js → PetPage-CIj7VSZN.js} +1 -1
  27. package/dashboard/dist/assets/{PopoverPopup-jSDQ87Bi.js → PopoverPopup-DMgjzzjH.js} +1 -1
  28. package/dashboard/dist/assets/{ResetPasswordPage-Dk2IDAJq.js → ResetPasswordPage-Cv1mRgno.js} +1 -1
  29. package/dashboard/dist/assets/{Select-Cz6WTj7D.js → Select-DvneEQak.js} +1 -1
  30. package/dashboard/dist/assets/{SelectItemText-BZyRjWCM.js → SelectItemText-BQlJKuRz.js} +1 -1
  31. package/dashboard/dist/assets/{SettingsPage-CANz8HMM.js → SettingsPage-DpnL6Jm6.js} +1 -1
  32. package/dashboard/dist/assets/{SkillsPage-WZkQG_83.js → SkillsPage-Cz7d619N.js} +1 -1
  33. package/dashboard/dist/assets/{WidgetsPage-BEyJ62NV.js → WidgetsPage-BP1zxfmh.js} +1 -1
  34. package/dashboard/dist/assets/{WrappedPage-Ck_dOx_w.js → WrappedPage-2eIams41.js} +1 -1
  35. package/dashboard/dist/assets/{agent-logos-DpjHiAbZ.js → agent-logos-C0_7FQ0s.js} +1 -1
  36. package/dashboard/dist/assets/{arrow-up-right-C4iYPBtK.js → arrow-up-right-DBYYRxgR.js} +1 -1
  37. package/dashboard/dist/assets/check-B1MZEuWp.js +1 -0
  38. package/dashboard/dist/assets/{copy-CHJ-38K6.js → copy-BxhpNvJX.js} +1 -1
  39. package/dashboard/dist/assets/{download-BSeG8u17.js → download-DAvxmQ3t.js} +1 -1
  40. package/dashboard/dist/assets/{flame-DeHwKcE-.js → flame-DX9uRr7X.js} +1 -1
  41. package/dashboard/dist/assets/{format-tokens-B-MJYJyp.js → format-tokens-mMtru3Ww.js} +1 -1
  42. package/dashboard/dist/assets/{info-DA_0xr_o.js → info-BLfeChk0.js} +1 -1
  43. package/dashboard/dist/assets/{link-2-noUH83Lc.js → link-2-JVAqARKl.js} +1 -1
  44. package/dashboard/dist/assets/{loader-circle-wL7KZtm0.js → loader-circle--bezqxUZ.js} +1 -1
  45. package/dashboard/dist/assets/{main-BHfJDFcu.js → main-8AbVGr5W.js} +16 -16
  46. package/dashboard/dist/assets/{provider-display-DxIClOGM.js → provider-display-DUwBv-X6.js} +1 -1
  47. package/dashboard/dist/assets/{trash-2-B8TPUmxZ.js → trash-2-Z1EIC4PI.js} +1 -1
  48. package/dashboard/dist/assets/{use-community-stats-CXD3MRRE.js → use-community-stats-Dr1q98cg.js} +1 -1
  49. package/dashboard/dist/assets/{use-limits-display-prefs-C2pJVYTn.js → use-limits-display-prefs-DnacsQ0f.js} +1 -1
  50. package/dashboard/dist/assets/{use-native-settings-BeOBLEZa.js → use-native-settings-BgBQK2b0.js} +1 -1
  51. package/dashboard/dist/assets/{use-ordered-list-kAtW8pJm.js → use-ordered-list-BBs8mEfc.js} +1 -1
  52. package/dashboard/dist/assets/{use-quality-per-dollar-pref-CFZUZM3S.js → use-quality-per-dollar-pref-BSagz4Mk.js} +1 -1
  53. package/dashboard/dist/assets/{use-transform-B9YwpyKi.js → use-transform-CL6RuAA2.js} +1 -1
  54. package/dashboard/dist/assets/{use-usage-limits-DSX5iKPE.js → use-usage-limits-CzNniz6Z.js} +1 -1
  55. package/dashboard/dist/assets/{useCurrency-CKg5K4Nj.js → useCurrency-ByQkX7uG.js} +1 -1
  56. package/dashboard/dist/assets/{useScrollLock-DyyY_Vyt.js → useScrollLock-D5wf8_sp.js} +1 -1
  57. package/dashboard/dist/assets/useTokenFormat-BpdwKlbn.js +1 -0
  58. package/dashboard/dist/assets/{zap-B69x9NCT.js → zap-v3s0o4Ig.js} +1 -1
  59. package/dashboard/dist/index.html +1 -1
  60. package/dashboard/dist/share.html +1 -1
  61. package/package.json +1 -1
  62. package/src/commands/init.js +596 -6
  63. package/src/commands/sync.js +16 -1
  64. package/src/lib/codex-config.js +135 -40
  65. package/src/lib/codex-context-breakdown.js +123 -43
  66. package/src/lib/codex-rollout-parser.js +329 -32
  67. package/src/lib/pricing/seed-snapshot.json +1 -1
  68. package/src/lib/rollout.js +167 -8
  69. package/dashboard/dist/assets/DashboardPage-WkiygMmq.js +0 -19
  70. package/dashboard/dist/assets/DialogDescription-DIra288n.js +0 -1
  71. package/dashboard/dist/assets/check-BkPUxPZV.js +0 -1
  72. package/dashboard/dist/assets/useTokenFormat-FfTjEH_m.js +0 -1
@@ -172,6 +172,7 @@ async function parseRolloutIncremental({
172
172
  onProgress,
173
173
  source,
174
174
  publicRepoResolver,
175
+ diagnostics,
175
176
  }) {
176
177
  await ensureDir(path.dirname(queuePath));
177
178
  let filesProcessed = 0;
@@ -189,6 +190,7 @@ async function parseRolloutIncremental({
189
190
  const projectFreshnessNowMs = Date.now();
190
191
  const touchedBuckets = new Set();
191
192
  const defaultSource = normalizeSourceInput(source) || DEFAULT_SOURCE;
193
+ const syncDiagnostics = diagnostics && typeof diagnostics === "object" ? diagnostics : null;
192
194
 
193
195
  if (!cursors.files || typeof cursors.files !== "object") {
194
196
  cursors.files = {};
@@ -199,7 +201,108 @@ async function parseRolloutIncremental({
199
201
  // external rewrite of a session file (Codex-Manager's atomic provider-patch on
200
202
  // account switch, issue #187) cannot re-count already-counted events.
201
203
  const prevCodexHashes = Array.isArray(cursors?.codexHashes) ? cursors.codexHashes : [];
202
- const seenCodexEvents = new Set(prevCodexHashes);
204
+ if (!Array.isArray(cursors.codexHashes)) cursors.codexHashes = prevCodexHashes;
205
+ let seenCodexEvents = null;
206
+ let newCodexEventKeys = null;
207
+ let newCodexEventKeySet = null;
208
+ let appendOnlyCodexEvents = null;
209
+ let historicalCodexEvents = null;
210
+ let cursorSessionPaths = null;
211
+ if (syncDiagnostics) {
212
+ const codexParseCandidates = (Array.isArray(rolloutFiles) ? rolloutFiles : []).reduce((count, entry) => {
213
+ const entrySource = typeof entry === "string"
214
+ ? defaultSource
215
+ : normalizeSourceInput(entry?.source) || defaultSource;
216
+ return count + (entrySource === DEFAULT_SOURCE ? 1 : 0);
217
+ }, 0);
218
+ const discoveredRollouts = Number(syncDiagnostics.discovered_rollouts);
219
+ const cursorKeys = Number(syncDiagnostics.cursor_keys);
220
+ const coldSkipped = Number(syncDiagnostics.cold_skipped);
221
+ const parseCandidates = Number(syncDiagnostics.parse_candidates);
222
+ Object.assign(syncDiagnostics, {
223
+ discovered_rollouts: Number.isFinite(discoveredRollouts) ? discoveredRollouts : codexParseCandidates,
224
+ cursor_keys: Number.isFinite(cursorKeys) ? cursorKeys : Object.keys(cursors.files).length,
225
+ parse_candidates: Number.isFinite(parseCandidates) ? parseCandidates : codexParseCandidates,
226
+ stat_candidates: 0,
227
+ cold_skipped: Number.isFinite(coldSkipped) ? coldSkipped : 0,
228
+ content_files_read: 0,
229
+ hash_set_constructions: 0,
230
+ hash_array_materializations: 0,
231
+ hash_array_materialized_items: 0,
232
+ codex_hash_count: prevCodexHashes.length,
233
+ });
234
+ }
235
+ const ensureNewCodexEventKeys = () => {
236
+ if (!newCodexEventKeys) newCodexEventKeys = [];
237
+ if (!newCodexEventKeySet) newCodexEventKeySet = new Set();
238
+ };
239
+ const recordNewCodexEvent = (key) => {
240
+ ensureNewCodexEventKeys();
241
+ if (newCodexEventKeySet.has(key)) return;
242
+ newCodexEventKeySet.add(key);
243
+ newCodexEventKeys.push(key);
244
+ if (seenCodexEvents) seenCodexEvents.add(key);
245
+ };
246
+ const getAppendOnlyCodexEvents = () => {
247
+ if (!appendOnlyCodexEvents) {
248
+ appendOnlyCodexEvents = {
249
+ has(key) {
250
+ return Boolean(
251
+ newCodexEventKeySet?.has(key) ||
252
+ seenCodexEvents?.has(key)
253
+ );
254
+ },
255
+ add: recordNewCodexEvent,
256
+ };
257
+ }
258
+ return appendOnlyCodexEvents;
259
+ };
260
+ const getHistoricalCodexEvents = () => {
261
+ if (!seenCodexEvents) {
262
+ seenCodexEvents = new Set(prevCodexHashes);
263
+ for (const key of newCodexEventKeys || []) seenCodexEvents.add(key);
264
+ if (syncDiagnostics) syncDiagnostics.hash_set_constructions += 1;
265
+ }
266
+ if (!historicalCodexEvents) {
267
+ historicalCodexEvents = {
268
+ has: (key) => seenCodexEvents.has(key),
269
+ add: recordNewCodexEvent,
270
+ };
271
+ }
272
+ return historicalCodexEvents;
273
+ };
274
+ const getCursorSessionPaths = () => {
275
+ if (cursorSessionPaths) return cursorSessionPaths;
276
+ cursorSessionPaths = new Map();
277
+ for (const existingPath of Object.keys(cursors.files)) {
278
+ const sessionId = codexSessionIdFromPath(existingPath);
279
+ if (!sessionId) continue;
280
+ if (!cursorSessionPaths.has(sessionId)) cursorSessionPaths.set(sessionId, new Set());
281
+ cursorSessionPaths.get(sessionId).add(existingPath);
282
+ }
283
+ return cursorSessionPaths;
284
+ };
285
+ const needsHistoricalCodexDedup = ({
286
+ filePath,
287
+ prev,
288
+ sameInode,
289
+ truncated,
290
+ startOffset,
291
+ rebuildingBaseline,
292
+ }) => {
293
+ if (rebuildingBaseline) return true;
294
+ if (prev && (!sameInode || truncated)) return true;
295
+ if (sameInode && !truncated && startOffset > 0) return false;
296
+ if (prev?.lastTotal) return true;
297
+ const sessionId = codexSessionIdFromPath(filePath);
298
+ if (!sessionId) return true;
299
+ const knownPaths = getCursorSessionPaths().get(sessionId);
300
+ if (!knownPaths) return false;
301
+ for (const knownPath of knownPaths) {
302
+ if (knownPath !== filePath) return true;
303
+ }
304
+ return false;
305
+ };
203
306
 
204
307
  for (let idx = 0; idx < rolloutFiles.length; idx++) {
205
308
  const entry = rolloutFiles[idx];
@@ -209,6 +312,7 @@ async function parseRolloutIncremental({
209
312
  typeof entry === "string"
210
313
  ? defaultSource
211
314
  : normalizeSourceInput(entry?.source) || defaultSource;
315
+ if (syncDiagnostics && fileSource === DEFAULT_SOURCE) syncDiagnostics.stat_candidates += 1;
212
316
  const st = await fs.stat(filePath).catch(() => null);
213
317
  if (!st || !st.isFile()) continue;
214
318
 
@@ -218,8 +322,18 @@ async function parseRolloutIncremental({
218
322
  const sameInode = prev && prev.inode === inode;
219
323
  const prevOffset = sameInode ? prev.offset || 0 : 0;
220
324
  const truncated = sameInode && prevOffset > st.size;
221
- const startOffset = sameInode && !truncated ? prevOffset : 0;
222
- const lastTotal = sameInode && !truncated ? prev.lastTotal || null : null;
325
+ const rebuildingCodexBaseline = Boolean(
326
+ fileSource === DEFAULT_SOURCE &&
327
+ sameInode &&
328
+ !truncated &&
329
+ prevOffset > 0 &&
330
+ prevOffset < st.size &&
331
+ (!prev.lastTotal || typeof prev.lastTotal !== "object")
332
+ );
333
+ const startOffset = sameInode && !truncated && !rebuildingCodexBaseline ? prevOffset : 0;
334
+ const lastTotal = sameInode && !truncated && !rebuildingCodexBaseline
335
+ ? prev.lastTotal || null
336
+ : null;
223
337
  const lastModel = sameInode && !truncated ? prev.lastModel || null : null;
224
338
 
225
339
  const codexProjectFastPath = projectEnabled && fileSource === DEFAULT_SOURCE;
@@ -270,6 +384,21 @@ async function parseRolloutIncremental({
270
384
  const projectRef = projectContext?.projectRef || null;
271
385
  const projectKey = projectContext?.projectKey || null;
272
386
 
387
+ if (syncDiagnostics && !projectContextOnlyScan && fileSource === DEFAULT_SOURCE) {
388
+ syncDiagnostics.content_files_read += 1;
389
+ }
390
+ const codexEventTracker = fileSource === DEFAULT_SOURCE
391
+ ? (needsHistoricalCodexDedup({
392
+ filePath,
393
+ prev,
394
+ sameInode,
395
+ truncated,
396
+ startOffset,
397
+ rebuildingBaseline: rebuildingCodexBaseline,
398
+ })
399
+ ? getHistoricalCodexEvents
400
+ : getAppendOnlyCodexEvents)
401
+ : null;
273
402
  const result = projectContextOnlyScan
274
403
  ? await scanRolloutProjectFileContexts({
275
404
  filePath,
@@ -299,7 +428,7 @@ async function parseRolloutIncremental({
299
428
  publicRepoCache,
300
429
  publicRepoResolver,
301
430
  projectContext,
302
- seenCodexEvents,
431
+ seenCodexEvents: codexEventTracker,
303
432
  sessionId: codexSessionIdFromPath(filePath),
304
433
  });
305
434
 
@@ -341,7 +470,12 @@ async function parseRolloutIncremental({
341
470
  const projectBucketsQueued = projectEnabled
342
471
  ? await enqueueTouchedProjectBuckets({ projectQueuePath, projectState, projectTouchedBuckets })
343
472
  : 0;
344
- cursors.codexHashes = Array.from(seenCodexEvents);
473
+ for (const key of newCodexEventKeys || []) prevCodexHashes.push(key);
474
+ if (syncDiagnostics) {
475
+ syncDiagnostics.codex_hash_count = Array.isArray(cursors.codexHashes)
476
+ ? cursors.codexHashes.length
477
+ : prevCodexHashes.length;
478
+ }
345
479
  hourlyState.updatedAt = new Date().toISOString();
346
480
  cursors.hourly = hourlyState;
347
481
  if (projectState) {
@@ -359,8 +493,23 @@ async function filterColdCodexRolloutFiles({
359
493
  auditDue = false,
360
494
  nowMs = Date.now(),
361
495
  recentDays = DEFAULT_CODEX_COLD_SKIP_RECENT_DAYS,
496
+ diagnostics = null,
362
497
  } = {}) {
363
498
  const files = Array.isArray(rolloutFiles) ? rolloutFiles : [];
499
+ const syncDiagnostics = diagnostics && typeof diagnostics === "object" ? diagnostics : null;
500
+ const isCodexEntry = (entry) => (
501
+ typeof entry === "string" || (normalizeSourceInput(entry?.source) || DEFAULT_SOURCE) === DEFAULT_SOURCE
502
+ );
503
+ if (syncDiagnostics) {
504
+ const discoveredRollouts = files.reduce(
505
+ (count, entry) => count + (isCodexEntry(entry) ? 1 : 0),
506
+ 0,
507
+ );
508
+ syncDiagnostics.discovered_rollouts = discoveredRollouts;
509
+ syncDiagnostics.cursor_keys = Object.keys(cursors?.files || {}).length;
510
+ syncDiagnostics.cold_skipped = 0;
511
+ syncDiagnostics.parse_candidates = discoveredRollouts;
512
+ }
364
513
  if (auditDue || !cursors?.files || typeof cursors.files !== "object") {
365
514
  return { rolloutFiles: files, skipped: 0 };
366
515
  }
@@ -414,6 +563,13 @@ async function filterColdCodexRolloutFiles({
414
563
  skipped += 1;
415
564
  }
416
565
 
566
+ if (syncDiagnostics) {
567
+ syncDiagnostics.cold_skipped = skipped;
568
+ syncDiagnostics.parse_candidates = out.reduce(
569
+ (count, entry) => count + (isCodexEntry(entry) ? 1 : 0),
570
+ 0,
571
+ );
572
+ }
417
573
  return { rolloutFiles: out, skipped };
418
574
  }
419
575
 
@@ -1665,10 +1821,13 @@ async function parseRolloutFile({
1665
1821
  // rewrite) manages Codex. Other rollout-format sources (e.g. every-code) have
1666
1822
  // their own model re-alignment that legitimately re-reads prior events, which
1667
1823
  // this dedup would otherwise suppress.
1668
- if (seenCodexEvents && source === "codex") {
1824
+ const codexEvents = typeof seenCodexEvents === "function"
1825
+ ? seenCodexEvents()
1826
+ : seenCodexEvents;
1827
+ if (codexEvents && source === "codex") {
1669
1828
  const dedupKey = `${sessionId || filePath}:${tokenTimestamp}`;
1670
- if (seenCodexEvents.has(dedupKey)) continue;
1671
- seenCodexEvents.add(dedupKey);
1829
+ if (codexEvents.has(dedupKey)) continue;
1830
+ codexEvents.add(dedupKey);
1672
1831
  }
1673
1832
 
1674
1833
  const bucket = getHourlyBucket(hourlyState, source, model, bucketStart);