tokentracker-cli 0.77.0 → 0.77.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.
- package/README.de.md +3 -3
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dashboard/dist/assets/{ActivityHeatmap-B7z62JlL.js → ActivityHeatmap-CH6m_ZJM.js} +1 -1
- package/dashboard/dist/assets/{Card-__rwvnP4.js → Card-D_aKGDr7.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-DaCAutqr.js → ClawdAnimated-vRiBiNhb.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-CWm0mzAf.js → CommunityStatsModal-CjetJZ-5.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-B7N0Zppz.js → ConfirmModal-C6bZw6FZ.js} +1 -1
- package/dashboard/dist/assets/{Controls-BTDwRDvm.js → Controls-Cj22oGL3.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-D1_icfKi.js → DashboardPage-DPxiQkQw.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-gtfDUhRQ.js → DevicePage-YAo4ert4.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-qIxDdczo.js → DialogClose-hhTDeRp1.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-gxEpcUbJ.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-CSDMrQhN.js → DialogTitle-CA5znwms.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-NsSXdhWN.js → FadeIn--ff4ZbC-.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-bKcBtWVl.js → HeaderGithubStar-CTZvanhz.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-CE76US_W.js → IpCheckPage-Bg47gNVu.js} +1 -1
- package/dashboard/dist/assets/LandingPage-DZ8Mz38n.js +4314 -0
- package/dashboard/dist/assets/{LeaderboardAvatar-Cy3g-HWp.js → LeaderboardAvatar-3T57GKKK.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-1WBDWMat.js → LeaderboardPage-wP_yCU9I.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-D2QG43nj.js → LeaderboardProfileModal-CfVMENby.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfilePage-v4ko4GNe.js → LeaderboardProfilePage-C4bGXJCE.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-DTZULDvf.js → LimitsPage-BAQ10X55.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-C-ee2yBe.js → LocalOnlyNotice-gtHCn7Mx.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-CDEH8cRz.js → LoginPage-TXvIBzoW.js} +1 -1
- package/dashboard/dist/assets/{PetPage-DvfRgRhO.js → PetPage-Dj1jrxYe.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-BLppStGT.js → PopoverPopup-CQxxgUXk.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-BiyFeB4S.js → ResetPasswordPage-tN0tmSfP.js} +1 -1
- package/dashboard/dist/assets/{Select-CuIsuAVQ.js → Select-DnbHYPS4.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-BD39TQ1S.js → SelectItemText-2LjzGvo5.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-DQSVBBG9.js → SettingsPage-DosKS_L6.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-DaIdd4xK.js → SkillsPage-DaCJ25vT.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-3UhcR9QZ.js → WidgetsPage-CCGemQVD.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-DCVq4Xff.js → WrappedPage-YxshTScX.js} +1 -1
- package/dashboard/dist/assets/{agent-logos-R2tmPdL9.js → agent-logos-SeuxwQsp.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-BHRB6j-Z.js → arrow-up-right-Bm3t-iA0.js} +1 -1
- package/dashboard/dist/assets/check-D8Owfjyw.js +1 -0
- package/dashboard/dist/assets/{copy-DqnHEyjG.js → copy-DUNz-xWm.js} +1 -1
- package/dashboard/dist/assets/{download-BENVX8oP.js → download-COSLX73O.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-UEB1iTo5.js → format-tokens-CR28AiQO.js} +1 -1
- package/dashboard/dist/assets/{info-BJz0ItGV.js → info-Cm7V_KDO.js} +1 -1
- package/dashboard/dist/assets/{link-2-DTkXHGCX.js → link-2-CYqDGrkv.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-CD8DppwM.js → loader-circle-6XAdy2ec.js} +1 -1
- package/dashboard/dist/assets/{main-D0segwJ8.js → main-BCstrDYE.js} +3 -3
- package/dashboard/dist/assets/main-BYdJ5vWR.css +1 -0
- package/dashboard/dist/assets/{trash-2-BkzmWJMI.js → trash-2-DKLewOQb.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-Bye7a_kk.js → use-community-stats-AdPaun74.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-Cd7QCxBh.js → use-limits-display-prefs-Bau4ykMw.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-BfB5GsUB.js → use-native-settings-CidwlprT.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-CRDF6ju7.js → use-ordered-list-BVaEJaWa.js} +1 -1
- package/dashboard/dist/assets/{use-quality-per-dollar-pref-D_UMPxxS.js → use-quality-per-dollar-pref-Htlc-uFe.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-D6h39bCy.js → use-usage-limits-BnzWTJQS.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-CtAxkO0_.js → useCurrency-bd6TLRsc.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-DFY_kQZc.js → useScrollLock-ajoWrfku.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/pets/byte/spritesheet.webp +0 -0
- package/dashboard/dist/pets/ember/spritesheet.webp +0 -0
- package/dashboard/dist/pets/sprout/spritesheet.webp +0 -0
- package/dashboard/dist/share.html +2 -2
- package/package.json +1 -1
- package/src/commands/status.js +174 -18
- package/src/commands/sync.js +336 -21
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +1311 -38
- package/dashboard/dist/assets/DialogDescription-DbGIQcnQ.js +0 -1
- package/dashboard/dist/assets/LandingPage-D41_7gBb.js +0 -4312
- package/dashboard/dist/assets/check-BbbG2Gcp.js +0 -1
- package/dashboard/dist/assets/main-B8lT0e78.css +0 -1
package/src/commands/sync.js
CHANGED
|
@@ -24,6 +24,11 @@ const {
|
|
|
24
24
|
resolveKiroJsonlPath,
|
|
25
25
|
resolveHermesPath,
|
|
26
26
|
resolveCopilotOtelPaths,
|
|
27
|
+
normalizeCopilotDbPath,
|
|
28
|
+
uniqueCopilotDbPaths,
|
|
29
|
+
coalesceCopilotDbStatesByIdentity,
|
|
30
|
+
resolveCopilotSessionStorePaths,
|
|
31
|
+
getCopilotSqliteFingerprint,
|
|
27
32
|
resolveCopilotAppDbPaths,
|
|
28
33
|
parseRolloutIncremental,
|
|
29
34
|
parseClaudeIncremental,
|
|
@@ -37,7 +42,10 @@ const {
|
|
|
37
42
|
gooseInstallOwnsCursor,
|
|
38
43
|
zedInstallOwnsCursor,
|
|
39
44
|
hermesInstallOwnsCursor,
|
|
45
|
+
copilotOtelCursorHasLegacyCliUsage,
|
|
46
|
+
pruneCopilotUsageClaims,
|
|
40
47
|
parseCopilotIncremental,
|
|
48
|
+
parseCopilotSessionStoreIncremental,
|
|
41
49
|
parseCopilotAppDbIncremental,
|
|
42
50
|
resolveKimiWireFiles,
|
|
43
51
|
parseKimiIncremental,
|
|
@@ -218,6 +226,50 @@ function warnProviderParseFailure(label, err, opts) {
|
|
|
218
226
|
process.stderr.write(`${label} sync: ${err && err.message ? err.message : err}\n`);
|
|
219
227
|
}
|
|
220
228
|
|
|
229
|
+
function mergeParseResult(total, next) {
|
|
230
|
+
return {
|
|
231
|
+
recordsProcessed: total.recordsProcessed + next.recordsProcessed,
|
|
232
|
+
eventsAggregated: total.eventsAggregated + next.eventsAggregated,
|
|
233
|
+
bucketsQueued: total.bucketsQueued + next.bucketsQueued,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function copilotAppBaselineTotal(baseline) {
|
|
238
|
+
return (
|
|
239
|
+
Math.max(0, Number(baseline?.input) || 0) +
|
|
240
|
+
Math.max(0, Number(baseline?.output) || 0) +
|
|
241
|
+
Math.max(0, Number(baseline?.cached) || 0) +
|
|
242
|
+
Math.max(0, Number(baseline?.reasoning) || 0)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function mergeCopilotAppDbStates(primary = {}, alias = {}) {
|
|
247
|
+
const primaryUpdatedAt = Date.parse(primary?.updatedAt || "") || 0;
|
|
248
|
+
const aliasUpdatedAt = Date.parse(alias?.updatedAt || "") || 0;
|
|
249
|
+
const newer = aliasUpdatedAt > primaryUpdatedAt ? alias : primary;
|
|
250
|
+
const sessionTotals = {};
|
|
251
|
+
for (const state of [primary, alias]) {
|
|
252
|
+
for (const [sessionId, baseline] of Object.entries(
|
|
253
|
+
state?.sessionTotals || {},
|
|
254
|
+
)) {
|
|
255
|
+
const current = sessionTotals[sessionId];
|
|
256
|
+
const baselineTotal = copilotAppBaselineTotal(baseline);
|
|
257
|
+
const currentTotal = copilotAppBaselineTotal(current);
|
|
258
|
+
const baselineUpdatedAt = Date.parse(baseline?.updatedAt || "") || 0;
|
|
259
|
+
const currentUpdatedAt = Date.parse(current?.updatedAt || "") || 0;
|
|
260
|
+
if (
|
|
261
|
+
!current ||
|
|
262
|
+
baselineTotal > currentTotal ||
|
|
263
|
+
(baselineTotal === currentTotal &&
|
|
264
|
+
baselineUpdatedAt > currentUpdatedAt)
|
|
265
|
+
) {
|
|
266
|
+
sessionTotals[sessionId] = baseline;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return { ...primary, ...newer, sessionTotals };
|
|
271
|
+
}
|
|
272
|
+
|
|
221
273
|
async function cmdSync(argv) {
|
|
222
274
|
const opts = parseArgs(argv);
|
|
223
275
|
const home = os.homedir();
|
|
@@ -1326,19 +1378,135 @@ async function cmdSync(argv) {
|
|
|
1326
1378
|
await repairGrokQueueFromSessionSnapshots({ cursors, queuePath, queueStatePath });
|
|
1327
1379
|
}
|
|
1328
1380
|
|
|
1329
|
-
// ── GitHub Copilot
|
|
1381
|
+
// ── GitHub Copilot App / CLI unified local runtime ──
|
|
1382
|
+
//
|
|
1383
|
+
// First adoption deliberately runs legacy OTEL + App DB once before the
|
|
1384
|
+
// session-store parser records its max-id barrier. Subsequent scans use
|
|
1385
|
+
// session-store as canonical for CLI/App requests: OTEL keeps only Chat
|
|
1386
|
+
// extension LogRecords, while App DB remains an observe-only baseline.
|
|
1330
1387
|
let copilotResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
1331
|
-
const
|
|
1388
|
+
const copilotSourceAllowed = sourceAllowed("copilot");
|
|
1389
|
+
const adoptedCopilotStorePaths = new Set(
|
|
1390
|
+
Object.entries(cursors?.copilotStore?.dbs || {})
|
|
1391
|
+
.filter(([, state]) => state?.adoptedAt)
|
|
1392
|
+
.map(([dbPath]) => dbPath),
|
|
1393
|
+
);
|
|
1394
|
+
const copilotStorePaths = copilotSourceAllowed
|
|
1395
|
+
? Array.from(
|
|
1396
|
+
new Set([
|
|
1397
|
+
...resolveCopilotSessionStorePaths(process.env),
|
|
1398
|
+
...adoptedCopilotStorePaths,
|
|
1399
|
+
]),
|
|
1400
|
+
).filter((dbPath) => {
|
|
1401
|
+
if (adoptedCopilotStorePaths.has(dbPath)) return true;
|
|
1402
|
+
try { return fssync.existsSync(dbPath); } catch (_e) { return false; }
|
|
1403
|
+
})
|
|
1404
|
+
: [];
|
|
1405
|
+
const copilotStoreWasActive = cursors?.copilotStore?.active === true;
|
|
1406
|
+
const copilotStoreAdoptionFingerprints = {};
|
|
1407
|
+
if (!copilotStoreWasActive) {
|
|
1408
|
+
for (const dbPath of copilotStorePaths) {
|
|
1409
|
+
try {
|
|
1410
|
+
copilotStoreAdoptionFingerprints[dbPath] =
|
|
1411
|
+
getCopilotSqliteFingerprint(dbPath);
|
|
1412
|
+
} catch (_e) {}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
let copilotHadLegacyCliOtelHistory = false;
|
|
1416
|
+
if (!copilotStoreWasActive) {
|
|
1417
|
+
copilotHadLegacyCliOtelHistory =
|
|
1418
|
+
await copilotOtelCursorHasLegacyCliUsage(cursors);
|
|
1419
|
+
if (cursors?.copilot && typeof cursors.copilot === "object") {
|
|
1420
|
+
if (copilotHadLegacyCliOtelHistory) {
|
|
1421
|
+
cursors.copilot.legacyCliHistory = true;
|
|
1422
|
+
} else {
|
|
1423
|
+
cursors.copilot.usageClaimsComplete = true;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
let copilotLegacyHealthy = true;
|
|
1428
|
+
let copilotOtelUsageClaims =
|
|
1429
|
+
cursors?.copilot?.recentUsageEvents || [];
|
|
1430
|
+
let copilotStoreResult = {
|
|
1431
|
+
active: copilotStoreWasActive,
|
|
1432
|
+
healthy: false,
|
|
1433
|
+
adoptedThisRun: false,
|
|
1434
|
+
canonicalDbPaths: [],
|
|
1435
|
+
recordsProcessed: 0,
|
|
1436
|
+
eventsAggregated: 0,
|
|
1437
|
+
bucketsQueued: 0,
|
|
1438
|
+
usageClaims: cursors?.copilotStore?.recentEvents || [],
|
|
1439
|
+
};
|
|
1440
|
+
if (copilotSourceAllowed && copilotStoreWasActive) {
|
|
1441
|
+
if (progress?.enabled) {
|
|
1442
|
+
progress.start(`Parsing Copilot App/CLI ${renderBar(0)} | buckets 0`);
|
|
1443
|
+
}
|
|
1444
|
+
try {
|
|
1445
|
+
copilotStoreResult = await parseCopilotSessionStoreIncremental({
|
|
1446
|
+
dbPaths: copilotStorePaths,
|
|
1447
|
+
cursors,
|
|
1448
|
+
queuePath,
|
|
1449
|
+
env: process.env,
|
|
1450
|
+
otelUsageEvents: cursors?.copilot?.recentUsageEvents,
|
|
1451
|
+
onProgress: (p) => {
|
|
1452
|
+
if (!progress?.enabled) return;
|
|
1453
|
+
const pct = p.total > 0 ? p.index / p.total : 1;
|
|
1454
|
+
progress.update(
|
|
1455
|
+
`Parsing Copilot App/CLI ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} events | buckets ${formatNumber(p.bucketsQueued)}`,
|
|
1456
|
+
);
|
|
1457
|
+
},
|
|
1458
|
+
});
|
|
1459
|
+
copilotResult = mergeParseResult(copilotResult, copilotStoreResult);
|
|
1460
|
+
} catch (err) {
|
|
1461
|
+
warnProviderParseFailure("Copilot App/CLI session store", err, opts);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
const copilotPathKey = (dbPath) => {
|
|
1465
|
+
const normalized = path.normalize(dbPath);
|
|
1466
|
+
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
1467
|
+
};
|
|
1468
|
+
const canonicalCopilotStorePaths = new Set(
|
|
1469
|
+
(copilotStoreResult.canonicalDbPaths || []).map(copilotPathKey),
|
|
1470
|
+
);
|
|
1471
|
+
const adoptedCopilotStorePathKeys = new Set(
|
|
1472
|
+
Object.entries(cursors?.copilotStore?.dbs || {})
|
|
1473
|
+
.filter(([, state]) => state?.adoptedAt)
|
|
1474
|
+
.map(([dbPath]) => copilotPathKey(dbPath)),
|
|
1475
|
+
);
|
|
1476
|
+
const explicitCopilotStorePath =
|
|
1477
|
+
typeof process.env.TOKENTRACKER_COPILOT_SESSION_STORE_DB === "string" &&
|
|
1478
|
+
process.env.TOKENTRACKER_COPILOT_SESSION_STORE_DB.trim()
|
|
1479
|
+
? copilotPathKey(
|
|
1480
|
+
normalizeCopilotDbPath(
|
|
1481
|
+
process.env.TOKENTRACKER_COPILOT_SESSION_STORE_DB,
|
|
1482
|
+
process.env,
|
|
1483
|
+
),
|
|
1484
|
+
)
|
|
1485
|
+
: null;
|
|
1486
|
+
const explicitStoreIsCanonical =
|
|
1487
|
+
explicitCopilotStorePath !== null &&
|
|
1488
|
+
canonicalCopilotStorePaths.has(explicitCopilotStorePath);
|
|
1489
|
+
const explicitStoreIsAdopted =
|
|
1490
|
+
explicitCopilotStorePath !== null &&
|
|
1491
|
+
adoptedCopilotStorePathKeys.has(explicitCopilotStorePath);
|
|
1492
|
+
|
|
1493
|
+
// ── GitHub Copilot CLI / Chat extension (OTEL JSONL files) ──
|
|
1494
|
+
const copilotPaths = copilotSourceAllowed ? resolveCopilotOtelPaths(process.env) : [];
|
|
1332
1495
|
if (copilotPaths.length > 0) {
|
|
1333
1496
|
if (progress?.enabled) {
|
|
1334
1497
|
progress.start(`Parsing Copilot ${renderBar(0)} | buckets 0`);
|
|
1335
1498
|
}
|
|
1336
1499
|
try {
|
|
1337
|
-
|
|
1500
|
+
const copilotOtelResult = await parseCopilotIncremental({
|
|
1338
1501
|
otelPaths: copilotPaths,
|
|
1339
1502
|
cursors,
|
|
1340
1503
|
queuePath,
|
|
1341
1504
|
env: process.env,
|
|
1505
|
+
storeUsageEvents:
|
|
1506
|
+
copilotStoreResult.usageClaims ||
|
|
1507
|
+
cursors?.copilotStore?.recentEvents ||
|
|
1508
|
+
[],
|
|
1509
|
+
skipCliSpans: copilotStoreWasActive,
|
|
1342
1510
|
onProgress: (p) => {
|
|
1343
1511
|
if (!progress?.enabled) return;
|
|
1344
1512
|
const pct = p.total > 0 ? p.index / p.total : 1;
|
|
@@ -1347,42 +1515,189 @@ async function cmdSync(argv) {
|
|
|
1347
1515
|
);
|
|
1348
1516
|
},
|
|
1349
1517
|
});
|
|
1518
|
+
copilotOtelUsageClaims =
|
|
1519
|
+
copilotOtelResult.usageClaims ||
|
|
1520
|
+
cursors?.copilot?.recentUsageEvents ||
|
|
1521
|
+
[];
|
|
1522
|
+
copilotResult = mergeParseResult(copilotResult, copilotOtelResult);
|
|
1350
1523
|
} catch (err) {
|
|
1524
|
+
copilotLegacyHealthy = false;
|
|
1351
1525
|
warnProviderParseFailure("Copilot", err, opts);
|
|
1352
1526
|
}
|
|
1353
1527
|
}
|
|
1354
1528
|
|
|
1355
1529
|
// ── GitHub Copilot App (passive data.db session summaries) ──
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
|
|
1530
|
+
const copilotAppDbStates =
|
|
1531
|
+
cursors?.copilotApp?.dbs && typeof cursors.copilotApp.dbs === "object"
|
|
1532
|
+
? cursors.copilotApp.dbs
|
|
1533
|
+
: null;
|
|
1534
|
+
const initialTrackedCopilotAppDbPaths = new Set(
|
|
1535
|
+
Object.keys(copilotAppDbStates || {}),
|
|
1536
|
+
);
|
|
1537
|
+
const copilotAppDbCandidates = uniqueCopilotDbPaths(
|
|
1538
|
+
[
|
|
1539
|
+
...resolveCopilotAppDbPaths(process.env),
|
|
1540
|
+
...initialTrackedCopilotAppDbPaths,
|
|
1541
|
+
],
|
|
1542
|
+
process.env,
|
|
1543
|
+
Array.from(initialTrackedCopilotAppDbPaths),
|
|
1544
|
+
);
|
|
1545
|
+
coalesceCopilotDbStatesByIdentity(
|
|
1546
|
+
copilotAppDbStates,
|
|
1547
|
+
copilotAppDbCandidates,
|
|
1548
|
+
mergeCopilotAppDbStates,
|
|
1549
|
+
);
|
|
1550
|
+
const explicitStoreOwnsSingleApp =
|
|
1551
|
+
copilotAppDbCandidates.length === 1 &&
|
|
1552
|
+
explicitStoreIsAdopted;
|
|
1553
|
+
if (copilotAppDbStates && (copilotStoreWasActive || copilotStorePaths.length > 0)) {
|
|
1554
|
+
for (const dbPath of Object.keys(copilotAppDbStates)) {
|
|
1555
|
+
try {
|
|
1556
|
+
fssync.statSync(dbPath);
|
|
1557
|
+
} catch (err) {
|
|
1558
|
+
const matchingStorePath = copilotPathKey(
|
|
1559
|
+
path.join(path.dirname(dbPath), "session-store.db"),
|
|
1560
|
+
);
|
|
1561
|
+
if (err?.code === "ENOENT") {
|
|
1562
|
+
if (
|
|
1563
|
+
canonicalCopilotStorePaths.has(matchingStorePath) ||
|
|
1564
|
+
(explicitStoreOwnsSingleApp && explicitStoreIsCanonical)
|
|
1565
|
+
) {
|
|
1566
|
+
delete copilotAppDbStates[dbPath];
|
|
1567
|
+
}
|
|
1568
|
+
} else {
|
|
1569
|
+
if (!copilotStoreWasActive) copilotLegacyHealthy = false;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
const trackedCopilotAppDbPaths = new Set(
|
|
1575
|
+
Object.keys(cursors?.copilotApp?.dbs || {}),
|
|
1576
|
+
);
|
|
1577
|
+
const rawCopilotAppDbPaths = copilotSourceAllowed
|
|
1578
|
+
? Array.from(new Set([
|
|
1579
|
+
...copilotAppDbCandidates,
|
|
1580
|
+
...trackedCopilotAppDbPaths,
|
|
1581
|
+
])).filter((dbPath) => {
|
|
1582
|
+
if (trackedCopilotAppDbPaths.has(dbPath)) return true;
|
|
1583
|
+
try { return fssync.existsSync(dbPath); } catch (_e) { return false; }
|
|
1359
1584
|
})
|
|
1360
1585
|
: [];
|
|
1586
|
+
const copilotAppDbPaths = uniqueCopilotDbPaths(
|
|
1587
|
+
rawCopilotAppDbPaths,
|
|
1588
|
+
process.env,
|
|
1589
|
+
Array.from(trackedCopilotAppDbPaths),
|
|
1590
|
+
);
|
|
1361
1591
|
if (copilotAppDbPaths.length > 0) {
|
|
1362
1592
|
if (progress?.enabled) {
|
|
1363
1593
|
progress.start(`Parsing Copilot App ${renderBar(0)} | buckets 0`);
|
|
1364
1594
|
}
|
|
1595
|
+
for (const appDbPath of copilotAppDbPaths) {
|
|
1596
|
+
const storePathKey = copilotPathKey(
|
|
1597
|
+
path.join(path.dirname(appDbPath), "session-store.db"),
|
|
1598
|
+
);
|
|
1599
|
+
const observeOnly =
|
|
1600
|
+
copilotStoreWasActive ||
|
|
1601
|
+
adoptedCopilotStorePathKeys.has(storePathKey) ||
|
|
1602
|
+
(copilotAppDbPaths.length === 1 && explicitStoreIsAdopted);
|
|
1603
|
+
const catchupRelevant =
|
|
1604
|
+
!observeOnly &&
|
|
1605
|
+
!copilotStoreWasActive &&
|
|
1606
|
+
copilotStorePaths.length > 0;
|
|
1607
|
+
try {
|
|
1608
|
+
const copilotAppResult = await parseCopilotAppDbIncremental({
|
|
1609
|
+
dbPaths: [appDbPath],
|
|
1610
|
+
cursors,
|
|
1611
|
+
queuePath,
|
|
1612
|
+
env: process.env,
|
|
1613
|
+
observeOnly,
|
|
1614
|
+
onProgress: (p) => {
|
|
1615
|
+
if (!progress?.enabled) return;
|
|
1616
|
+
const pct = p.total > 0 ? p.index / p.total : 1;
|
|
1617
|
+
progress.update(
|
|
1618
|
+
`Parsing Copilot App ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(p.total)} sessions | buckets ${formatNumber(p.bucketsQueued)}`,
|
|
1619
|
+
);
|
|
1620
|
+
},
|
|
1621
|
+
});
|
|
1622
|
+
copilotResult = mergeParseResult(copilotResult, copilotAppResult);
|
|
1623
|
+
if (catchupRelevant && copilotAppResult.dbErrors > 0) {
|
|
1624
|
+
copilotLegacyHealthy = false;
|
|
1625
|
+
}
|
|
1626
|
+
} catch (err) {
|
|
1627
|
+
if (catchupRelevant) copilotLegacyHealthy = false;
|
|
1628
|
+
warnProviderParseFailure("Copilot App", err, opts);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
if (
|
|
1634
|
+
copilotSourceAllowed &&
|
|
1635
|
+
!copilotStoreWasActive &&
|
|
1636
|
+
copilotStorePaths.length > 0 &&
|
|
1637
|
+
copilotLegacyHealthy
|
|
1638
|
+
) {
|
|
1639
|
+
if (progress?.enabled) {
|
|
1640
|
+
progress.start(`Adopting Copilot App/CLI store ${renderBar(0)} | buckets 0`);
|
|
1641
|
+
}
|
|
1365
1642
|
try {
|
|
1366
|
-
const
|
|
1367
|
-
|
|
1643
|
+
const copilotHasOtelCursorHistory =
|
|
1644
|
+
(Array.isArray(cursors?.copilot?.seenIds) &&
|
|
1645
|
+
cursors.copilot.seenIds.length > 0) ||
|
|
1646
|
+
(cursors?.copilot?.fileOffsets &&
|
|
1647
|
+
Object.keys(cursors.copilot.fileOffsets).length > 0);
|
|
1648
|
+
const copilotOtelClaimsIncomplete =
|
|
1649
|
+
copilotHadLegacyCliOtelHistory ||
|
|
1650
|
+
(copilotHasOtelCursorHistory &&
|
|
1651
|
+
cursors?.copilot?.usageClaimsComplete !== true);
|
|
1652
|
+
const appSessionIds = [];
|
|
1653
|
+
const appSessionTotals = {};
|
|
1654
|
+
for (const dbState of Object.values(cursors?.copilotApp?.dbs || {})) {
|
|
1655
|
+
for (const [sessionId, totals] of Object.entries(
|
|
1656
|
+
dbState?.sessionTotals || {},
|
|
1657
|
+
)) {
|
|
1658
|
+
const total =
|
|
1659
|
+
Number(totals?.input || 0) +
|
|
1660
|
+
Number(totals?.output || 0) +
|
|
1661
|
+
Number(totals?.cached || 0) +
|
|
1662
|
+
Number(totals?.reasoning || 0);
|
|
1663
|
+
if (total <= 0) continue;
|
|
1664
|
+
appSessionIds.push(sessionId);
|
|
1665
|
+
const prior = appSessionTotals[sessionId];
|
|
1666
|
+
const priorTotal =
|
|
1667
|
+
Number(prior?.input || 0) +
|
|
1668
|
+
Number(prior?.output || 0) +
|
|
1669
|
+
Number(prior?.cached || 0) +
|
|
1670
|
+
Number(prior?.reasoning || 0);
|
|
1671
|
+
if (total > priorTotal) appSessionTotals[sessionId] = totals;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
copilotStoreResult = await parseCopilotSessionStoreIncremental({
|
|
1675
|
+
dbPaths: copilotStorePaths,
|
|
1368
1676
|
cursors,
|
|
1369
1677
|
queuePath,
|
|
1370
1678
|
env: process.env,
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
);
|
|
1377
|
-
},
|
|
1679
|
+
backfillOnFirstRun: !copilotOtelClaimsIncomplete,
|
|
1680
|
+
excludeSessionIdsOnFirstRun: appSessionIds,
|
|
1681
|
+
excludeSessionTotalsOnFirstRun: appSessionTotals,
|
|
1682
|
+
expectedFingerprints: copilotStoreAdoptionFingerprints,
|
|
1683
|
+
otelUsageEvents: copilotOtelUsageClaims,
|
|
1378
1684
|
});
|
|
1379
|
-
copilotResult =
|
|
1380
|
-
recordsProcessed: copilotResult.recordsProcessed + copilotAppResult.recordsProcessed,
|
|
1381
|
-
eventsAggregated: copilotResult.eventsAggregated + copilotAppResult.eventsAggregated,
|
|
1382
|
-
bucketsQueued: copilotResult.bucketsQueued + copilotAppResult.bucketsQueued,
|
|
1383
|
-
};
|
|
1685
|
+
copilotResult = mergeParseResult(copilotResult, copilotStoreResult);
|
|
1384
1686
|
} catch (err) {
|
|
1385
|
-
warnProviderParseFailure("Copilot App", err, opts);
|
|
1687
|
+
warnProviderParseFailure("Copilot App/CLI session store", err, opts);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
if (copilotSourceAllowed) {
|
|
1692
|
+
if (Array.isArray(cursors?.copilot?.recentUsageEvents)) {
|
|
1693
|
+
cursors.copilot.recentUsageEvents = pruneCopilotUsageClaims(
|
|
1694
|
+
cursors.copilot.recentUsageEvents,
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
if (Array.isArray(cursors?.copilotStore?.recentEvents)) {
|
|
1698
|
+
cursors.copilotStore.recentEvents = pruneCopilotUsageClaims(
|
|
1699
|
+
cursors.copilotStore.recentEvents,
|
|
1700
|
+
);
|
|
1386
1701
|
}
|
|
1387
1702
|
}
|
|
1388
1703
|
|