tokentracker-cli 0.81.2 → 0.81.3
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/dashboard/dist/assets/AchievementBadge-DiSoAalB.js +1 -0
- package/dashboard/dist/assets/AchievementsPage-DI_cvzqy.js +2 -0
- package/dashboard/dist/assets/AchievementsSection-ClWZZNvc.js +1 -0
- package/dashboard/dist/assets/BadgeDetailModal-DpQeG_6H.js +1 -0
- package/dashboard/dist/assets/Card-B0hyofoy.js +1 -0
- package/dashboard/dist/assets/ClawdAnimated-DZJGQ3-9.js +1 -0
- package/dashboard/dist/assets/CommunityStatsModal-Dcikt0kT.js +1 -0
- package/dashboard/dist/assets/ConfirmModal-DCfRP4oI.js +1 -0
- package/dashboard/dist/assets/DashboardPage-DBajsWEp.js +1 -0
- package/dashboard/dist/assets/DevicePage-De6KuFaJ.js +1 -0
- package/dashboard/dist/assets/DialogDescription-uQ4gVIv9.js +1 -0
- package/dashboard/dist/assets/DialogTitle-BvElfi0r.js +1 -0
- package/dashboard/dist/assets/FadeIn-DZoN7vbQ.js +1 -0
- package/dashboard/dist/assets/HeaderGithubStar-C9HQnEsI.js +1 -0
- package/dashboard/dist/assets/{IpCheckPage-CMf9CHFr.js → IpCheckPage-82zniXwO.js} +3 -3
- package/dashboard/dist/assets/{LandingPage-BT61_TqT.js → LandingPage-Df9fdR0n.js} +168 -168
- package/dashboard/dist/assets/LeaderboardAvatar-CjfEgoR8.js +1 -0
- package/dashboard/dist/assets/LeaderboardPage-BdbE6Nhj.js +2 -0
- package/dashboard/dist/assets/{LeaderboardProfileModal-C_kxqOMn.js → LeaderboardProfileModal-CDTK21dp.js} +4 -4
- package/dashboard/dist/assets/{LeaderboardProfilePage-zgNsE0EQ.js → LeaderboardProfilePage-B6QWnwB1.js} +3 -3
- package/dashboard/dist/assets/{LimitsPage-BiQpqxj8.js → LimitsPage-f0L0d15j.js} +4 -4
- package/dashboard/dist/assets/LocalOnlyNotice-DOcSDrOy.js +1 -0
- package/dashboard/dist/assets/LoginPage-WY_sRA7I.js +1 -0
- package/dashboard/dist/assets/PetPage-CNbgNE6f.js +1 -0
- package/dashboard/dist/assets/PopoverPopup-Cv525-dF.js +1 -0
- package/dashboard/dist/assets/ResetPasswordPage-vrcj6bBP.js +1 -0
- package/dashboard/dist/assets/Select-3HkgkO8y.js +1 -0
- package/dashboard/dist/assets/SelectItemText-Bz8FAKEv.js +1 -0
- package/dashboard/dist/assets/SettingsPage-CVldAt69.js +1 -0
- package/dashboard/dist/assets/SkillsPage-Dnz3eGcE.js +1 -0
- package/dashboard/dist/assets/TrendMonitor-OopQ06B8.js +19 -0
- package/dashboard/dist/assets/WidgetsPage-4dWjZkc9.js +1 -0
- package/dashboard/dist/assets/WrappedPage-Dbd-8EKD.js +1 -0
- package/dashboard/dist/assets/__vite-browser-external-CQxW1DuO.css +1 -0
- package/dashboard/dist/assets/__vite-browser-external-CxN2E6q5.js +1312 -0
- package/dashboard/dist/assets/agent-logos-CT9fumzx.js +1 -0
- package/dashboard/dist/assets/arrow-up-right-CGnVz9Km.js +1 -0
- package/dashboard/dist/assets/check-CkI3WNti.js +1 -0
- package/dashboard/dist/assets/copy-Bh3g2_O-.js +1 -0
- package/dashboard/dist/assets/download-BITw7nKX.js +1 -0
- package/dashboard/dist/assets/flame-ByAsnNar.js +1 -0
- package/dashboard/dist/assets/format-tokens-Cu8JtuN4.js +1 -0
- package/dashboard/dist/assets/icons-D9OB0N43.js +1 -0
- package/dashboard/dist/assets/index-lKnLA6Pd.js +1 -0
- package/dashboard/dist/assets/info-Mu2CLf-A.js +1 -0
- package/dashboard/dist/assets/link-2-CSlVaUw9.js +1 -0
- package/dashboard/dist/assets/loader-circle-CYck0YaS.js +1 -0
- package/dashboard/dist/assets/provider-display-BB925tPa.js +42 -0
- package/dashboard/dist/assets/terminal-4YysOnTe.js +1 -0
- package/dashboard/dist/assets/trash-2-C8-ZfrZG.js +1 -0
- package/dashboard/dist/assets/use-community-stats-Cxt-otko.js +1 -0
- package/dashboard/dist/assets/use-limits-display-prefs-BUFZh6fe.js +1 -0
- package/dashboard/dist/assets/use-native-settings-DbdPXxGf.js +1 -0
- package/dashboard/dist/assets/{use-ordered-list-DPbiKnPc.js → use-ordered-list-BZMM-iIj.js} +2 -2
- package/dashboard/dist/assets/use-quality-per-dollar-pref-DXoW5A0_.js +1 -0
- package/dashboard/dist/assets/use-transform-CuAoUb8H.js +1 -0
- package/dashboard/dist/assets/use-usage-limits-BEc3QMzR.js +1 -0
- package/dashboard/dist/assets/useCurrency-CpDnFC0N.js +1 -0
- package/dashboard/dist/assets/useScrollLock-Vyaif-7C.js +1 -0
- package/dashboard/dist/assets/useTokenFormat-B8FrUarf.js +1 -0
- package/dashboard/dist/assets/zap-CdeKJ6HL.js +1 -0
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +1 -1
- package/src/commands/serve.js +8 -6
- package/src/commands/status.js +2 -1
- package/src/commands/sync.js +164 -36
- package/src/lib/codex-context-breakdown.js +330 -13
- package/src/lib/codex-rollout-parser.js +323 -42
- package/src/lib/cursor-store.js +1289 -0
- package/src/lib/diagnostics.js +8 -5
- package/src/lib/fs.js +254 -16
- package/src/lib/local-api.js +106 -17
- package/src/lib/pricing/index.js +8 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +101 -9
- package/dashboard/dist/assets/AchievementBadge-DXWHZrAL.js +0 -1
- package/dashboard/dist/assets/AchievementsPage-BhrQXniL.js +0 -2
- package/dashboard/dist/assets/AchievementsSection-gzP3m1Ml.js +0 -1
- package/dashboard/dist/assets/BadgeDetailModal-DGKPuvDU.js +0 -1
- package/dashboard/dist/assets/Card-BRtYQ-Ot.js +0 -1
- package/dashboard/dist/assets/ClawdAnimated-UsNG-qDv.js +0 -1
- package/dashboard/dist/assets/CommunityStatsModal-CJQw-P4t.js +0 -1
- package/dashboard/dist/assets/ConfirmModal-ByY4GDsy.js +0 -1
- package/dashboard/dist/assets/DashboardPage-CuLVnW98.js +0 -19
- package/dashboard/dist/assets/DevicePage-D67CxpmR.js +0 -1
- package/dashboard/dist/assets/DialogClose-Ci8hkTw5.js +0 -1
- package/dashboard/dist/assets/DialogDescription-C9vXUZU0.js +0 -1
- package/dashboard/dist/assets/DialogTitle-sLJxKWjv.js +0 -1
- package/dashboard/dist/assets/FadeIn-xVds37w6.js +0 -1
- package/dashboard/dist/assets/HeaderGithubStar-kK3omgmB.js +0 -1
- package/dashboard/dist/assets/LeaderboardAvatar-DyKz6NdT.js +0 -1
- package/dashboard/dist/assets/LeaderboardPage-DJ4zihJJ.js +0 -2
- package/dashboard/dist/assets/LocalOnlyNotice-DTrrUVbZ.js +0 -1
- package/dashboard/dist/assets/LoginPage-BOM9Q2sI.js +0 -1
- package/dashboard/dist/assets/PetPage-BURk7RG-.js +0 -1
- package/dashboard/dist/assets/PopoverPopup-BV_aoNBd.js +0 -1
- package/dashboard/dist/assets/ResetPasswordPage-SBL2LvXC.js +0 -1
- package/dashboard/dist/assets/Select-BsRdHde3.js +0 -1
- package/dashboard/dist/assets/SelectItemText-DgkrZxIq.js +0 -1
- package/dashboard/dist/assets/SettingsPage-DqxVsfnB.js +0 -1
- package/dashboard/dist/assets/SkillsPage-B0VfWkOh.js +0 -1
- package/dashboard/dist/assets/WidgetsPage-4QQ8wI_g.js +0 -1
- package/dashboard/dist/assets/WrappedPage-BK53khVY.js +0 -1
- package/dashboard/dist/assets/agent-logos-DXpW_Wmz.js +0 -1
- package/dashboard/dist/assets/arrow-up-right-DCc--V5G.js +0 -1
- package/dashboard/dist/assets/check-DqxuosV2.js +0 -1
- package/dashboard/dist/assets/copy-qChAT7MY.js +0 -1
- package/dashboard/dist/assets/download-W9R3sBph.js +0 -1
- package/dashboard/dist/assets/flame-0eyhMnfU.js +0 -1
- package/dashboard/dist/assets/format-tokens-CkfBUcoa.js +0 -1
- package/dashboard/dist/assets/info-DY1O85-U.js +0 -1
- package/dashboard/dist/assets/link-2-B_Z66hFT.js +0 -1
- package/dashboard/dist/assets/loader-circle-xH40lon2.js +0 -1
- package/dashboard/dist/assets/main-CeaB5N36.js +0 -1259
- package/dashboard/dist/assets/main-DAc77vwF.css +0 -1
- package/dashboard/dist/assets/provider-display-C_XKZQcF.js +0 -42
- package/dashboard/dist/assets/trash-2-DVhNJ74r.js +0 -1
- package/dashboard/dist/assets/use-community-stats-CO-nr2Vf.js +0 -1
- package/dashboard/dist/assets/use-limits-display-prefs-RRqmyoxt.js +0 -1
- package/dashboard/dist/assets/use-native-settings-79piPeET.js +0 -1
- package/dashboard/dist/assets/use-quality-per-dollar-pref-DyF49QRF.js +0 -1
- package/dashboard/dist/assets/use-transform-BvXyGAtb.js +0 -1
- package/dashboard/dist/assets/use-usage-limits-BiZ_I-KE.js +0 -1
- package/dashboard/dist/assets/useCurrency-D-C1e7eE.js +0 -1
- package/dashboard/dist/assets/useScrollLock-BfU2EMvG.js +0 -1
- package/dashboard/dist/assets/useTokenFormat-Cm4EvrQp.js +0 -1
- package/dashboard/dist/assets/zap-DlAOTwFs.js +0 -1
package/src/commands/sync.js
CHANGED
|
@@ -106,6 +106,11 @@ const {
|
|
|
106
106
|
parseCursorCsv,
|
|
107
107
|
} = require("../lib/cursor-config");
|
|
108
108
|
const { purgeProjectUsage } = require("../lib/project-usage-purge");
|
|
109
|
+
const {
|
|
110
|
+
isCodexSessionCursorPath,
|
|
111
|
+
isCursorStoreRetry,
|
|
112
|
+
openCursorStore,
|
|
113
|
+
} = require("../lib/cursor-store");
|
|
109
114
|
const { resolveTrackerPaths } = require("../lib/tracker-paths");
|
|
110
115
|
const { resolveRuntimeConfig } = require("../lib/runtime-config");
|
|
111
116
|
|
|
@@ -186,6 +191,8 @@ const CODEX_RESCAN_DEDUP_REPAIR_KEY = "codexRescanDedupRepair_2026_06";
|
|
|
186
191
|
const CODEX_FORK_REPLAY_REPAIR_KEY = "codexForkReplayRepair_2026_07";
|
|
187
192
|
const DROID_DUP_SESSION_REPAIR_KEY = "droidDupSessionInflationRepair_2026_06";
|
|
188
193
|
const CODEX_COLD_SCAN_AUDIT_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
194
|
+
const NOTIFY_LOCK_WAIT_MS = 130_000;
|
|
195
|
+
const NOTIFY_LOCK_POLL_MS = 5_000;
|
|
189
196
|
const CODEX_COLD_SCAN_AUDIT_MAX_SYNCS = 288;
|
|
190
197
|
// 0.57.0 mis-attributed mimocode's mirrored Claude/claude-mem history to
|
|
191
198
|
// source=mimo (read the whole DB instead of only providerID=mimo rows). This
|
|
@@ -285,9 +292,51 @@ function mergeCopilotAppDbStates(primary = {}, alias = {}) {
|
|
|
285
292
|
return { ...primary, ...newer, sessionTotals };
|
|
286
293
|
}
|
|
287
294
|
|
|
295
|
+
function sleep(ms) {
|
|
296
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function acquireSyncLock(
|
|
300
|
+
lockPath,
|
|
301
|
+
opts,
|
|
302
|
+
{
|
|
303
|
+
notifyWaitMs = NOTIFY_LOCK_WAIT_MS,
|
|
304
|
+
notifyPollMs = NOTIFY_LOCK_POLL_MS,
|
|
305
|
+
} = {},
|
|
306
|
+
) {
|
|
307
|
+
let lock = await openLock(lockPath, { quietIfLocked: opts.auto });
|
|
308
|
+
if (lock || !opts.fromNotify || notifyWaitMs <= 0) return lock;
|
|
309
|
+
|
|
310
|
+
// One low-frequency waiter coalesces every notify that lands behind an
|
|
311
|
+
// active native/background sync. This avoids both losing the final Codex
|
|
312
|
+
// turn and spawning a fleet of idle retry processes during a long scan.
|
|
313
|
+
const waiter = await openLock(`${lockPath}.notify-wait`, {
|
|
314
|
+
quietIfLocked: true,
|
|
315
|
+
});
|
|
316
|
+
if (!waiter) return null;
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const deadline = Date.now() + notifyWaitMs;
|
|
320
|
+
while (!lock && Date.now() < deadline) {
|
|
321
|
+
const remaining = deadline - Date.now();
|
|
322
|
+
await sleep(Math.min(Math.max(1, notifyPollMs), remaining));
|
|
323
|
+
lock = await openLock(lockPath, { quietIfLocked: true });
|
|
324
|
+
}
|
|
325
|
+
return lock;
|
|
326
|
+
} finally {
|
|
327
|
+
await waiter.release();
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
288
331
|
async function cmdSync(argv, context = {}) {
|
|
289
332
|
const opts = parseArgs(argv);
|
|
290
333
|
const diagnostics = context && typeof context === "object" ? context.diagnostics : null;
|
|
334
|
+
const cursorStoreOptions = context && typeof context === "object"
|
|
335
|
+
? context.cursorStoreOptions
|
|
336
|
+
: null;
|
|
337
|
+
const lockWaitOptions = context && typeof context === "object"
|
|
338
|
+
? context.lockWaitOptions
|
|
339
|
+
: undefined;
|
|
291
340
|
const syncDiagnostics = diagnostics && typeof diagnostics === "object" ? diagnostics : null;
|
|
292
341
|
const home = os.homedir();
|
|
293
342
|
const { trackerDir } = await resolveTrackerPaths({ home });
|
|
@@ -298,7 +347,7 @@ async function cmdSync(argv, context = {}) {
|
|
|
298
347
|
}
|
|
299
348
|
|
|
300
349
|
const lockPath = path.join(trackerDir, "sync.lock");
|
|
301
|
-
const lock = await
|
|
350
|
+
const lock = await acquireSyncLock(lockPath, opts, lockWaitOptions);
|
|
302
351
|
if (!lock) return;
|
|
303
352
|
|
|
304
353
|
let progress = null;
|
|
@@ -314,8 +363,24 @@ async function cmdSync(argv, context = {}) {
|
|
|
314
363
|
const grokSignalPath = path.join(trackerDir, "grok-last-session.json");
|
|
315
364
|
const legacyGrokSignalPath = path.join(trackerDir, "tracker", "grok-last-session.json");
|
|
316
365
|
|
|
366
|
+
// Native publication owns backlog and failure-backoff retries on its next
|
|
367
|
+
// five-minute tick. Remove any legacy detached retry marker immediately so
|
|
368
|
+
// an already-sleeping retry process observes the missing marker and exits.
|
|
369
|
+
if (opts.publishAccount) {
|
|
370
|
+
await clearAutoRetry(trackerDir);
|
|
371
|
+
}
|
|
372
|
+
|
|
317
373
|
const config = await readJson(configPath);
|
|
318
|
-
const
|
|
374
|
+
const codexCursorRoots = [process.env.CODEX_HOME || path.join(home, ".codex")];
|
|
375
|
+
const cursorStore = await openCursorStore({
|
|
376
|
+
trackerDir,
|
|
377
|
+
cursorsPath,
|
|
378
|
+
codexRoots: codexCursorRoots,
|
|
379
|
+
...(cursorStoreOptions && typeof cursorStoreOptions === "object"
|
|
380
|
+
? cursorStoreOptions
|
|
381
|
+
: {}),
|
|
382
|
+
});
|
|
383
|
+
const cursors = cursorStore.cursors;
|
|
319
384
|
const uploadThrottle = normalizeUploadState(await readJson(uploadThrottlePath));
|
|
320
385
|
let uploadThrottleState = uploadThrottle;
|
|
321
386
|
let grokHookSignal = null;
|
|
@@ -418,6 +483,7 @@ async function cmdSync(argv, context = {}) {
|
|
|
418
483
|
}
|
|
419
484
|
|
|
420
485
|
if (isFullSourceScan) {
|
|
486
|
+
await cursorStore.materializeAllCodexState(cursors);
|
|
421
487
|
await migrateRolloutCumulativeDeltaBuckets({ cursors, queuePath, rolloutFiles });
|
|
422
488
|
const codexRescanRepairRan = await repairCodexRescanInflation({
|
|
423
489
|
cursors,
|
|
@@ -446,20 +512,29 @@ async function cmdSync(argv, context = {}) {
|
|
|
446
512
|
});
|
|
447
513
|
}
|
|
448
514
|
|
|
449
|
-
const codexColdSkipEnabled = opts.auto &&
|
|
515
|
+
const codexColdSkipEnabled = opts.auto && sourceAllowed("codex");
|
|
450
516
|
const codexColdAuditDue = codexColdSkipEnabled
|
|
451
517
|
? isCodexColdScanAuditDue(cursors)
|
|
452
518
|
: false;
|
|
453
|
-
|
|
519
|
+
let codexColdFilter = codexColdSkipEnabled
|
|
454
520
|
? await filterColdCodexRolloutFiles({
|
|
455
521
|
rolloutFiles,
|
|
456
522
|
cursors,
|
|
523
|
+
codexCursorStore: cursorStore,
|
|
457
524
|
projectEnabled: true,
|
|
458
525
|
auditDue: codexColdAuditDue,
|
|
459
526
|
diagnostics: syncDiagnostics,
|
|
460
527
|
})
|
|
461
528
|
: { rolloutFiles, skipped: 0 };
|
|
462
529
|
const rolloutFilesForParse = codexColdFilter.rolloutFiles;
|
|
530
|
+
let codexCursorLoadRestarted = false;
|
|
531
|
+
if (!codexColdSkipEnabled && sourceAllowed("codex")) {
|
|
532
|
+
const loadResult = await cursorStore.loadCodexFilesForPaths(
|
|
533
|
+
rolloutFilesForParse,
|
|
534
|
+
cursors,
|
|
535
|
+
);
|
|
536
|
+
codexCursorLoadRestarted = Boolean(loadResult?.restarted);
|
|
537
|
+
}
|
|
463
538
|
|
|
464
539
|
const openclawFiles = openclawSignal?.sessionFile
|
|
465
540
|
? [{ path: openclawSignal.sessionFile, source: "openclaw" }]
|
|
@@ -473,30 +548,58 @@ async function cmdSync(argv, context = {}) {
|
|
|
473
548
|
|
|
474
549
|
let parseResult = { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
475
550
|
let codexParseSucceeded = false;
|
|
551
|
+
let codexFallbackRetryRan = Boolean(
|
|
552
|
+
codexColdFilter.restarted || codexCursorLoadRestarted,
|
|
553
|
+
);
|
|
554
|
+
const runCodexParse = (files) => parseRolloutIncremental({
|
|
555
|
+
rolloutFiles: files,
|
|
556
|
+
cursors,
|
|
557
|
+
codexEventStore: Array.isArray(cursors.codexHashes)
|
|
558
|
+
? null
|
|
559
|
+
: cursorStore.codexEventStore,
|
|
560
|
+
queuePath,
|
|
561
|
+
projectQueuePath,
|
|
562
|
+
diagnostics: syncDiagnostics,
|
|
563
|
+
onProgress: (p) => {
|
|
564
|
+
if (!progress?.enabled) return;
|
|
565
|
+
const pct = p.total > 0 ? p.index / p.total : 1;
|
|
566
|
+
progress.update(
|
|
567
|
+
`Parsing ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} files | buckets ${formatNumber(
|
|
568
|
+
p.bucketsQueued,
|
|
569
|
+
)}`,
|
|
570
|
+
);
|
|
571
|
+
},
|
|
572
|
+
});
|
|
476
573
|
try {
|
|
477
|
-
parseResult = await
|
|
478
|
-
rolloutFiles: rolloutFilesForParse,
|
|
479
|
-
cursors,
|
|
480
|
-
queuePath,
|
|
481
|
-
projectQueuePath,
|
|
482
|
-
diagnostics: syncDiagnostics,
|
|
483
|
-
onProgress: (p) => {
|
|
484
|
-
if (!progress?.enabled) return;
|
|
485
|
-
const pct = p.total > 0 ? p.index / p.total : 1;
|
|
486
|
-
progress.update(
|
|
487
|
-
`Parsing ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} files | buckets ${formatNumber(
|
|
488
|
-
p.bucketsQueued,
|
|
489
|
-
)}`,
|
|
490
|
-
);
|
|
491
|
-
},
|
|
492
|
-
});
|
|
574
|
+
parseResult = await runCodexParse(rolloutFilesForParse);
|
|
493
575
|
codexParseSucceeded = true;
|
|
494
576
|
} catch (err) {
|
|
495
|
-
|
|
577
|
+
if (isCursorStoreRetry(err)) {
|
|
578
|
+
await cursorStore.loadCodexFilesForPaths(rolloutFiles, cursors);
|
|
579
|
+
codexColdFilter = { rolloutFiles, skipped: 0, restarted: true };
|
|
580
|
+
codexFallbackRetryRan = true;
|
|
581
|
+
if (syncDiagnostics) {
|
|
582
|
+
syncDiagnostics.cold_skipped = 0;
|
|
583
|
+
syncDiagnostics.parse_candidates = rolloutFiles.reduce(
|
|
584
|
+
(count, entry) => count + (
|
|
585
|
+
typeof entry === "string" || !entry?.source || entry.source === "codex"
|
|
586
|
+
? 1
|
|
587
|
+
: 0
|
|
588
|
+
),
|
|
589
|
+
0,
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
parseResult = await runCodexParse(rolloutFiles);
|
|
593
|
+
codexParseSucceeded = true;
|
|
594
|
+
} else if (err?.code === "TOKENTRACKER_CURSOR_STORE_CORRUPT") {
|
|
595
|
+
throw err;
|
|
596
|
+
} else {
|
|
597
|
+
warnProviderParseFailure("Codex", err, opts);
|
|
598
|
+
}
|
|
496
599
|
}
|
|
497
600
|
if (codexColdSkipEnabled && codexParseSucceeded) {
|
|
498
601
|
recordCodexColdScanAudit(cursors, {
|
|
499
|
-
fullAudit: codexColdAuditDue,
|
|
602
|
+
fullAudit: codexColdAuditDue || codexFallbackRetryRan,
|
|
500
603
|
skipped: codexColdFilter.skipped,
|
|
501
604
|
});
|
|
502
605
|
}
|
|
@@ -1851,12 +1954,12 @@ async function cmdSync(argv, context = {}) {
|
|
|
1851
1954
|
}
|
|
1852
1955
|
|
|
1853
1956
|
cursors.updatedAt = new Date().toISOString();
|
|
1854
|
-
await
|
|
1957
|
+
await cursorStore.commit(cursors);
|
|
1855
1958
|
if (syncDiagnostics) {
|
|
1856
|
-
const cursorStat = await fs.stat(
|
|
1959
|
+
const cursorStat = await fs.stat(cursorStore.currentCorePath);
|
|
1857
1960
|
syncDiagnostics.cursor_commits = Number(syncDiagnostics.cursor_commits || 0) + 1;
|
|
1858
1961
|
syncDiagnostics.cursor_bytes = Number(syncDiagnostics.cursor_bytes || 0) + cursorStat.size;
|
|
1859
|
-
syncDiagnostics.cursor_path =
|
|
1962
|
+
syncDiagnostics.cursor_path = cursorStore.currentCorePath;
|
|
1860
1963
|
}
|
|
1861
1964
|
if (grokHookSignalConsumed && grokHookSignalPath) {
|
|
1862
1965
|
await fs.unlink(grokHookSignalPath).catch(() => {});
|
|
@@ -1868,8 +1971,37 @@ async function cmdSync(argv, context = {}) {
|
|
|
1868
1971
|
|
|
1869
1972
|
let uploadResult = { inserted: 0, skipped: 0 };
|
|
1870
1973
|
let uploadAttempted = false;
|
|
1974
|
+
let backgroundUploadDecision = null;
|
|
1975
|
+
|
|
1976
|
+
if (opts.publishAccount) {
|
|
1977
|
+
const uploadStateBefore = (await readJson(queueStatePath)) || { offset: 0 };
|
|
1978
|
+
const queueSizeBefore = await safeStatSize(queuePath);
|
|
1979
|
+
const pendingBytesBefore = Math.max(
|
|
1980
|
+
0,
|
|
1981
|
+
queueSizeBefore - Number(uploadStateBefore.offset || 0),
|
|
1982
|
+
);
|
|
1983
|
+
// The native five-minute loop is already the success cadence. Reuse the
|
|
1984
|
+
// shared decision helper for pending/backoff handling, but intentionally
|
|
1985
|
+
// ignore the legacy 30-minute success throttle so account publication
|
|
1986
|
+
// does not become stale again. Failure backoff remains authoritative.
|
|
1987
|
+
backgroundUploadDecision = decideAutoUpload({
|
|
1988
|
+
nowMs: Date.now(),
|
|
1989
|
+
pendingBytes: pendingBytesBefore,
|
|
1990
|
+
state: {
|
|
1991
|
+
...uploadThrottleState,
|
|
1992
|
+
nextAllowedAtMs: Number(uploadThrottleState.backoffUntilMs || 0),
|
|
1993
|
+
},
|
|
1994
|
+
config: {
|
|
1995
|
+
batchSize: 200,
|
|
1996
|
+
maxBatchesSmall: 5,
|
|
1997
|
+
maxBatchesLarge: 5,
|
|
1998
|
+
},
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
1871
2001
|
|
|
1872
|
-
if (runtime.deviceToken && runtime.baseUrl &&
|
|
2002
|
+
if (runtime.deviceToken && runtime.baseUrl &&
|
|
2003
|
+
(!isBackgroundLightweightSync || opts.publishAccount) &&
|
|
2004
|
+
(!backgroundUploadDecision || backgroundUploadDecision.allowed)) {
|
|
1873
2005
|
uploadAttempted = true;
|
|
1874
2006
|
// Mirror the machine identity into the purge-surviving seed file so a
|
|
1875
2007
|
// future `uninstall --purge` + reinstall recovers the same cloud device
|
|
@@ -1886,8 +2018,8 @@ async function cmdSync(argv, context = {}) {
|
|
|
1886
2018
|
deviceToken: runtime.deviceToken,
|
|
1887
2019
|
queuePath,
|
|
1888
2020
|
queueStatePath,
|
|
1889
|
-
maxBatches: opts.drain ? 100 : 5,
|
|
1890
|
-
batchSize: 200,
|
|
2021
|
+
maxBatches: opts.drain ? 100 : (backgroundUploadDecision?.maxBatches || 5),
|
|
2022
|
+
batchSize: backgroundUploadDecision?.batchSize || 200,
|
|
1891
2023
|
});
|
|
1892
2024
|
// Record success so the exponential backoff step resets — otherwise
|
|
1893
2025
|
// a single past failure keeps us pessimistically throttled forever.
|
|
@@ -1926,7 +2058,7 @@ async function cmdSync(argv, context = {}) {
|
|
|
1926
2058
|
|
|
1927
2059
|
if (pendingBytes <= 0) {
|
|
1928
2060
|
await clearAutoRetry(trackerDir);
|
|
1929
|
-
} else if (opts.auto && uploadAttempted) {
|
|
2061
|
+
} else if (opts.auto && uploadAttempted && !opts.publishAccount) {
|
|
1930
2062
|
const retryAtMs = Number(uploadThrottleState?.nextAllowedAtMs || 0);
|
|
1931
2063
|
if (retryAtMs > Date.now()) {
|
|
1932
2064
|
await scheduleAutoRetry({
|
|
@@ -2027,7 +2159,6 @@ async function cmdSync(argv, context = {}) {
|
|
|
2027
2159
|
} finally {
|
|
2028
2160
|
progress?.stop();
|
|
2029
2161
|
await lock.release();
|
|
2030
|
-
await fs.unlink(lockPath).catch(() => {});
|
|
2031
2162
|
}
|
|
2032
2163
|
}
|
|
2033
2164
|
|
|
@@ -2040,6 +2171,7 @@ function parseArgs(argv) {
|
|
|
2040
2171
|
source: null,
|
|
2041
2172
|
drain: false,
|
|
2042
2173
|
background: false,
|
|
2174
|
+
publishAccount: false,
|
|
2043
2175
|
allLocalSources: false,
|
|
2044
2176
|
repairGrok: false,
|
|
2045
2177
|
};
|
|
@@ -2056,6 +2188,7 @@ function parseArgs(argv) {
|
|
|
2056
2188
|
else if (a.startsWith("--source=")) out.source = normalizeSyncSource(a.slice("--source=".length));
|
|
2057
2189
|
else if (a === "--drain") out.drain = true;
|
|
2058
2190
|
else if (a === "--background" || a === "--lightweight") out.background = true;
|
|
2191
|
+
else if (a === "--publish-account") out.publishAccount = true;
|
|
2059
2192
|
else if (a === "--all-local-sources") out.allLocalSources = true;
|
|
2060
2193
|
else if (a === "--repair-grok") out.repairGrok = true;
|
|
2061
2194
|
else throw new Error(`Unknown option: ${a}`);
|
|
@@ -2129,6 +2262,7 @@ function recordCodexColdScanAudit(cursors, { fullAudit = false, skipped = 0 } =
|
|
|
2129
2262
|
|
|
2130
2263
|
module.exports = {
|
|
2131
2264
|
cmdSync,
|
|
2265
|
+
acquireSyncLock,
|
|
2132
2266
|
migrateCursorUnknownBuckets,
|
|
2133
2267
|
migrateRolloutCumulativeDeltaBuckets,
|
|
2134
2268
|
repairCodexRescanInflation,
|
|
@@ -3655,12 +3789,6 @@ async function scanForForkedCodexRollout(rolloutFiles) {
|
|
|
3655
3789
|
return { forked: false, indeterminate };
|
|
3656
3790
|
}
|
|
3657
3791
|
|
|
3658
|
-
function isCodexSessionCursorPath(filePath) {
|
|
3659
|
-
if (typeof filePath !== "string") return false;
|
|
3660
|
-
const normalized = filePath.replace(/\\/g, "/");
|
|
3661
|
-
return /\/\.codex\/(?:archived_)?sessions\//.test(normalized);
|
|
3662
|
-
}
|
|
3663
|
-
|
|
3664
3792
|
async function projectUsageKeysFromQueuePath(queuePath, source) {
|
|
3665
3793
|
if (typeof queuePath !== "string" || !queuePath) return [];
|
|
3666
3794
|
let raw = "";
|