tokentracker-cli 0.88.2 → 0.88.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-BcCrg832.js → AchievementBadge-B6CZtEaS.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-C95dF_C-.js → AchievementsPage-YJJREeYN.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-B-VD8CfN.js → AchievementsSection-Bz8kzUKE.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-CDTJ3tR6.js → BadgeDetailModal-B18owwHf.js} +1 -1
- package/dashboard/dist/assets/{Card-a0RpvhLn.js → Card-D_HcMRXq.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-CaLKUbmC.js → ClawdAnimated-BR4Vm-wp.js} +1 -1
- package/dashboard/dist/assets/{CommandPalette-CQpkX7dK.js → CommandPalette-DD0iOGEP.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-Cj53g1ky.js → CommunityStatsModal-CfJn-_nP.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-FHZmD91i.js → ConfirmModal-8zQyesYk.js} +1 -1
- package/dashboard/dist/assets/{Controls-BSk2Eph4.js → Controls-Dd_7ctXC.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-Ci1jVw-F.js → DashboardPage-CyIp3wde.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-BnCWVmOI.js → DevicePage-BjNEbSgO.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-BUhPBSeF.js → DialogClose-BPRpp4Wp.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-FmibVDMx.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-CbNKnmTY.js → DialogTitle-Cq4jatmU.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-D87p8xfM.js → FadeIn-DoK6rAcp.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-kE4I1PyE.js → HeaderGithubStar-B3konO6W.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-miw72aLh.js → HoverTooltip-BaDkj8r8.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-D-JoHTz-.js → IpCheckPage-BkrAKRYK.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-Dx_MOVjJ.js → LandingPage-av_mctyf.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardAvatar-arnp_cWI.js → LeaderboardAvatar-CgdMLdWa.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-zsoFUX5G.js → LeaderboardPage-Vb3i4Qpc.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-CrmSTl9n.js → LeaderboardProfileModal-CVxiTLDv.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-BSE0fPco.js → LeaderboardProfilePage-BWIwKo1y.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-BrU9e8AV.js → LimitsPage-CA1Ve4x5.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-BWDZKn00.js → LocalOnlyNotice-Rm3uyEk3.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-DS8mxxs_.js → LoginCard-DL0l2lLw.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-DhINfVDV.js → LoginModal-C5Fk3Jms.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-BKmuhR74.js → LoginPage-Cu7DAOnx.js} +1 -1
- package/dashboard/dist/assets/{PetPage-QQk_B1SJ.js → PetPage-BgqjLomc.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-DS6ml7IE.js → PopoverPopup-CEHZ6QXJ.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-DkHp1Hrl.js → ProviderIcon-BC3XWoZ3.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-CvJiufPF.js → ResetPasswordPage-BrongFEU.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-DbYmpdj3.js → SegmentedControl-D8EHNgNi.js} +1 -1
- package/dashboard/dist/assets/{Select-DJcVfYm7.js → Select-D9k3JTvC.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-DUQLkHGQ.js → SelectItemText-BZ-2piB5.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-DqPQUM1f.js → ServiceStatusPage-Cv_KU00i.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-CPOSombb.js → SessionsPage-DIPKSBas.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-nIfi1h7D.js → SettingsPage-ClKxRKyx.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-BnngQwIu.js → SkillsPage-DvuwO5Yv.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-CAVmlIYW.js → TokenGalaxy-DIM8f80U.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-CyG7xQo2.js → ToolbarRootContext-BprUPTPI.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-DyuKVbzV.js → TrendMonitor-DWFiGJ35.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-72n9-HCD.js → WidgetsPage-DL-MG-Q7.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-Dp1aUOyA.js → WrappedPage-CGIDKH61.js} +1 -1
- package/dashboard/dist/assets/{__vite-browser-external-8kU62_i_.js → __vite-browser-external-BKzvjCbJ.js} +2 -2
- package/dashboard/dist/assets/{agent-logos-ChfjzWPV.js → agent-logos-CbNruoos.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-CiTMPVa_.js → arrow-up-right-eLrRdfJt.js} +1 -1
- package/dashboard/dist/assets/{check-OQW1qgf_.js → check-DZD0Jp7h.js} +1 -1
- package/dashboard/dist/assets/{chevron-right-BitImfyV.js → chevron-right-B500Y_Nj.js} +1 -1
- package/dashboard/dist/assets/{copy-BM76c1Ob.js → copy-uJNaZG-w.js} +1 -1
- package/dashboard/dist/assets/{download-DaKmqoH2.js → download-DzvthQjK.js} +1 -1
- package/dashboard/dist/assets/{external-link-AL639M-l.js → external-link-CbRIdeZk.js} +1 -1
- package/dashboard/dist/assets/{flame-BeYD0c6y.js → flame-BGvWQF3z.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-DK1Fdxfq.js → format-tokens-BmLj1DrP.js} +1 -1
- package/dashboard/dist/assets/{icons-BtLj_BDi.js → icons-oryPazn7.js} +1 -1
- package/dashboard/dist/assets/{index-BK2Bm5Vp.js → index-BC_awyRs.js} +1 -1
- package/dashboard/dist/assets/{index-BHBegQjp.js → index-RZ9PpvhZ.js} +1 -1
- package/dashboard/dist/assets/{index-D4kdhgAz.js → index-lCPHhuCN.js} +1 -1
- package/dashboard/dist/assets/{info-CIwDFvrE.js → info-DmArnish.js} +1 -1
- package/dashboard/dist/assets/{limits-providers-BFkGzLM4.js → limits-providers-DmO_jdt4.js} +1 -1
- package/dashboard/dist/assets/{link-2-xFS-GP5p.js → link-2-Cp4yrCYD.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-83n_EWic.js → loader-circle-DGUMo8NS.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-CevrJZKM.js → maximize-2-BLObxnY1.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-a1oXNZlE.js → modifiers.esm-B_-ZYAOP.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-CSP2FeVP.js → monitor-smartphone-CFtFQCf_.js} +1 -1
- package/dashboard/dist/assets/{provider-display-CamXa0pj.js → provider-display-zfwJ-zfN.js} +1 -1
- package/dashboard/dist/assets/{react-DV1nb3lW.js → react-C9v6bUwR.js} +1 -1
- package/dashboard/dist/assets/{search-wj8Kxgr5.js → search-DcdG91Gl.js} +1 -1
- package/dashboard/dist/assets/{skills-api-BNpGEfgh.js → skills-api-Cbj6O4EO.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-Xh3nfzFR.js → sortable.esm-CvVo8fVR.js} +1 -1
- package/dashboard/dist/assets/{store-lBXh9-l6.js → store-BCViEsFt.js} +1 -1
- package/dashboard/dist/assets/{terminal-uNBlGBuA.js → terminal-BBtxMCI7.js} +1 -1
- package/dashboard/dist/assets/{trash-2-08YOSvJh.js → trash-2-Dn_E9JQO.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-CMyCuzcM.js → use-community-stats-DPAzvqWl.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-BkqvWQ4X.js → use-limits-display-prefs-DC9B7mbP.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-CJ9F2mdG.js → use-ordered-list-BUUwYoO2.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-Bs24cR01.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-Hf4gvuAl.js → use-session-efficiency-pref-OJfrVVxb.js} +1 -1
- package/dashboard/dist/assets/{use-transform-BBP_cds4.js → use-transform-CVLI5mjY.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-DsLD0OEm.js → use-usage-limits-BXgn5HJr.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-CXngtOdH.js → useCurrency-RNt_kRXK.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-Q65zPe5d.js → useScrollLock-CGjecig7.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-CE5zbI_h.js → useTokenFormat-CPg1vv3V.js} +1 -1
- package/dashboard/dist/assets/{zap-CHYAc2Be.js → zap-CamjYQ0R.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/ip-check.html +1 -1
- package/dashboard/dist/leaderboard.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/lib/codex-rollout-parser.js +15 -2
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/session-analytics.js +128 -96
- package/dashboard/dist/assets/DialogDescription-Dp7bBdfJ.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-CD_DKLbl.js +0 -1
|
@@ -250,8 +250,23 @@ function finalizeRecord(record) {
|
|
|
250
250
|
return record;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
function readableSessionPaths(filePath) {
|
|
254
|
+
const candidates = (Array.isArray(filePath) ? filePath : [filePath]).filter(Boolean);
|
|
255
|
+
const readable = candidates.filter((value) => sessionFileStatKey(value));
|
|
256
|
+
if (!readable.length) {
|
|
257
|
+
throw new Error("session files vanished before they could be scanned");
|
|
258
|
+
}
|
|
259
|
+
return readable;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function isRecoverableSessionReadError(error) {
|
|
263
|
+
return ["ENOENT", "EACCES", "EPERM", "EISDIR", "EIO", "ESTALE"].includes(error?.code);
|
|
264
|
+
}
|
|
265
|
+
|
|
253
266
|
async function scanClaudeSession(filePath) {
|
|
254
|
-
|
|
267
|
+
// Native and WSL mounts can disappear independently after discovery. Keep
|
|
268
|
+
// the surviving mirror instead of dropping the whole logical session.
|
|
269
|
+
const filePaths = readableSessionPaths(filePath);
|
|
255
270
|
const primaryFilePath = filePaths[0] || String(filePath || "");
|
|
256
271
|
const tokens = emptyTotals();
|
|
257
272
|
// One logical cross-root group is cached and scanned as a unit, so widening
|
|
@@ -289,68 +304,76 @@ async function scanClaudeSession(filePath) {
|
|
|
289
304
|
// already present in an earlier root. Hashes stay in-memory only, preserving
|
|
290
305
|
// the metadata-only persistence contract.
|
|
291
306
|
const priorRecordHashes = new Set();
|
|
307
|
+
let scannedFiles = 0;
|
|
292
308
|
for (const currentFilePath of filePaths) {
|
|
293
309
|
const currentRecordHashes = new Set();
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
310
|
+
try {
|
|
311
|
+
const input = fs.createReadStream(currentFilePath, { encoding: "utf8" });
|
|
312
|
+
const lines = readline.createInterface({ input, crlfDelay: Infinity });
|
|
313
|
+
for await (const line of lines) {
|
|
314
|
+
if (filePaths.length > 1) {
|
|
315
|
+
const recordHash = crypto.createHash("sha256").update(line).digest("base64url");
|
|
316
|
+
if (priorRecordHashes.has(recordHash)) continue;
|
|
317
|
+
currentRecordHashes.add(recordHash);
|
|
318
|
+
}
|
|
319
|
+
let obj;
|
|
320
|
+
try { obj = JSON.parse(line); } catch { continue; }
|
|
321
|
+
updateBounds(bounds, obj.timestamp || obj.message?.timestamp);
|
|
322
|
+
if (typeof obj.sessionId === "string" && obj.sessionId) {
|
|
323
|
+
rawSessionId = obj.sessionId;
|
|
324
|
+
observedSessionId = obj.sessionId;
|
|
325
|
+
}
|
|
326
|
+
if (typeof obj.cwd === "string" && obj.cwd) cwd = obj.cwd;
|
|
327
|
+
// Claude writes its own generated one-line summary as an "ai-title" record.
|
|
328
|
+
// It is agent-authored metadata (not the raw prompt body); keep the latest.
|
|
329
|
+
if (obj.type === "ai-title" && typeof obj.aiTitle === "string") {
|
|
330
|
+
const cleaned = cleanSessionTitle(obj.aiTitle);
|
|
331
|
+
if (cleaned) aiTitle = cleaned;
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (obj.type === "user") {
|
|
335
|
+
const prompt = extractClaudePrompt(obj);
|
|
336
|
+
if (!prompt) continue;
|
|
337
|
+
const fingerprint = promptFingerprint(prompt);
|
|
338
|
+
if (lastPromptFingerprint && fingerprint === lastPromptFingerprint) retryTurns += 1;
|
|
339
|
+
lastPromptFingerprint = fingerprint;
|
|
340
|
+
closeTurn();
|
|
341
|
+
turns += 1;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (obj.type !== "assistant" || !obj.message) continue;
|
|
345
|
+
const dedupKey = claudeMessageDedupKey(obj);
|
|
346
|
+
if (dedupKey && seenMessages.has(dedupKey)) continue;
|
|
347
|
+
if (dedupKey) seenMessages.add(dedupKey);
|
|
348
|
+
// Claude writes internal summary/observer messages with model
|
|
349
|
+
// "<synthetic>". They are not a billable model and can appear after the
|
|
350
|
+
// real assistant messages in the same session. Keep the latest real
|
|
351
|
+
// model instead of letting that marker overwrite it.
|
|
352
|
+
const candidateModel = normalizeSessionModel(obj.message.model);
|
|
353
|
+
if (candidateModel) model = candidateModel;
|
|
354
|
+
addTotals(tokens, tokenTotals(obj.message.usage));
|
|
355
|
+
const content = Array.isArray(obj.message.content) ? obj.message.content : [];
|
|
356
|
+
for (const block of content) {
|
|
357
|
+
if (!block || block.type !== "tool_use") continue;
|
|
358
|
+
const name = String(block.name || "").toLowerCase();
|
|
359
|
+
if (EDIT_TOOLS.has(name)) currentHadEdit = true;
|
|
360
|
+
if (name === "agent" || name === "task") {
|
|
361
|
+
subagentCalls += 1;
|
|
362
|
+
const subtype = typeof block.input?.subagent_type === "string"
|
|
363
|
+
? block.input.subagent_type.trim().slice(0, 64)
|
|
364
|
+
: "unspecified";
|
|
365
|
+
subagentTypes.set(subtype || "unspecified", (subagentTypes.get(subtype || "unspecified") || 0) + 1);
|
|
366
|
+
}
|
|
349
367
|
}
|
|
350
368
|
}
|
|
369
|
+
scannedFiles += 1;
|
|
370
|
+
} catch (error) {
|
|
371
|
+
if (!isRecoverableSessionReadError(error)) throw error;
|
|
372
|
+
} finally {
|
|
373
|
+
for (const recordHash of currentRecordHashes) priorRecordHashes.add(recordHash);
|
|
351
374
|
}
|
|
352
|
-
for (const recordHash of currentRecordHashes) priorRecordHashes.add(recordHash);
|
|
353
375
|
}
|
|
376
|
+
if (!scannedFiles) throw new Error("all grouped Claude session files failed during read");
|
|
354
377
|
closeTurn();
|
|
355
378
|
return finalizeRecord({
|
|
356
379
|
version: SIDECAR_VERSION,
|
|
@@ -377,7 +400,7 @@ async function scanClaudeSession(filePath) {
|
|
|
377
400
|
}
|
|
378
401
|
|
|
379
402
|
async function scanCodexDeliverySignals(filePath) {
|
|
380
|
-
const filePaths = (
|
|
403
|
+
const filePaths = readableSessionPaths(filePath);
|
|
381
404
|
const bounds = emptyBounds();
|
|
382
405
|
let turns = 0;
|
|
383
406
|
let editTurns = 0;
|
|
@@ -404,46 +427,54 @@ async function scanCodexDeliverySignals(filePath) {
|
|
|
404
427
|
}
|
|
405
428
|
|
|
406
429
|
const priorRecordHashes = new Set();
|
|
430
|
+
let scannedFiles = 0;
|
|
407
431
|
for (const currentFilePath of filePaths) {
|
|
408
432
|
const currentRecordHashes = new Set();
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
433
|
+
try {
|
|
434
|
+
const input = fs.createReadStream(currentFilePath, { encoding: "utf8" });
|
|
435
|
+
const lines = readline.createInterface({ input, crlfDelay: Infinity });
|
|
436
|
+
for await (const line of lines) {
|
|
437
|
+
if (filePaths.length > 1) {
|
|
438
|
+
const recordHash = crypto.createHash("sha256").update(line).digest("base64url");
|
|
439
|
+
if (priorRecordHashes.has(recordHash)) continue;
|
|
440
|
+
currentRecordHashes.add(recordHash);
|
|
441
|
+
}
|
|
442
|
+
let obj;
|
|
443
|
+
try { obj = JSON.parse(line); } catch { continue; }
|
|
444
|
+
updateBounds(bounds, obj.timestamp);
|
|
445
|
+
if (obj.type === "turn_context") {
|
|
446
|
+
hasTurnContext = true;
|
|
447
|
+
beginTurn(String(obj.payload?.turn_id || obj.timestamp || turns + 1));
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
const prompt = extractCodexPrompt(obj);
|
|
451
|
+
if (prompt) {
|
|
452
|
+
const fingerprint = promptFingerprint(prompt);
|
|
453
|
+
if (lastPromptFingerprint && fingerprint === lastPromptFingerprint) retryTurns += 1;
|
|
454
|
+
lastPromptFingerprint = fingerprint;
|
|
455
|
+
if (!hasTurnContext) beginTurn(String(obj.timestamp || turns + 1));
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
if (obj.type !== "response_item") continue;
|
|
459
|
+
const toolNames = extractCodexSignalTools(obj.payload);
|
|
460
|
+
if (!toolNames.length) continue;
|
|
461
|
+
if (!currentTurnOpen) beginTurn(String(obj.timestamp || turns + 1));
|
|
462
|
+
if (toolNames.some((name) => EDIT_TOOLS.has(name))) currentHadEdit = true;
|
|
463
|
+
for (const name of toolNames) {
|
|
464
|
+
if (!CODEX_SUBAGENT_TOOLS.has(name)) continue;
|
|
465
|
+
subagentCalls += 1;
|
|
466
|
+
const displayName = name === "multi_agent_v1__spawn_agent" ? "spawn_agent" : name;
|
|
467
|
+
subagentTypes.set(displayName, (subagentTypes.get(displayName) || 0) + 1);
|
|
468
|
+
}
|
|
443
469
|
}
|
|
470
|
+
scannedFiles += 1;
|
|
471
|
+
} catch (error) {
|
|
472
|
+
if (!isRecoverableSessionReadError(error)) throw error;
|
|
473
|
+
} finally {
|
|
474
|
+
for (const recordHash of currentRecordHashes) priorRecordHashes.add(recordHash);
|
|
444
475
|
}
|
|
445
|
-
for (const recordHash of currentRecordHashes) priorRecordHashes.add(recordHash);
|
|
446
476
|
}
|
|
477
|
+
if (!scannedFiles) throw new Error("all grouped Codex signal files failed during read");
|
|
447
478
|
closeTurn();
|
|
448
479
|
return {
|
|
449
480
|
bounds,
|
|
@@ -456,7 +487,7 @@ async function scanCodexDeliverySignals(filePath) {
|
|
|
456
487
|
}
|
|
457
488
|
|
|
458
489
|
async function scanCodexSession(filePath) {
|
|
459
|
-
const filePaths = (
|
|
490
|
+
const filePaths = readableSessionPaths(filePath);
|
|
460
491
|
const primaryFilePath = filePaths[0] || String(filePath || "");
|
|
461
492
|
const [parsed, signals] = await Promise.all([
|
|
462
493
|
parseCodexRolloutFile(filePaths, { seenTokenEvents: new Set() }),
|
|
@@ -1034,8 +1065,8 @@ function loadCodexTitleIndex(filePath) {
|
|
|
1034
1065
|
// touching updates.jsonl on some partial flushes).
|
|
1035
1066
|
function analyticsEntryStatKey(source, filePath) {
|
|
1036
1067
|
const filePaths = (Array.isArray(filePath) ? filePath : [filePath]).filter(Boolean);
|
|
1037
|
-
const sessionStats = filePaths.map((value) => sessionFileStatKey(value));
|
|
1038
|
-
if (sessionStats.
|
|
1068
|
+
const sessionStats = filePaths.map((value) => sessionFileStatKey(value) || "missing");
|
|
1069
|
+
if (sessionStats.every((value) => value === "missing")) return null;
|
|
1039
1070
|
const sessionStat = sessionStats.join("|");
|
|
1040
1071
|
if (source === "codex") {
|
|
1041
1072
|
const titleStats = filePaths.map((value) => (
|
|
@@ -1446,4 +1477,5 @@ module.exports = {
|
|
|
1446
1477
|
sessionsToCsv,
|
|
1447
1478
|
providerRoots,
|
|
1448
1479
|
dedupeClaudeFilesAcrossRoots,
|
|
1480
|
+
analyticsEntryStatKey,
|
|
1449
1481
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,z as a}from"./__vite-browser-external-8kU62_i_.js";import{u as p}from"./DialogTitle-CbNKnmTY.js";import{u as c}from"./useScrollLock-Q65zPe5d.js";const x=n.forwardRef(function(e,r){const{render:l,className:u,style:m,id:s,...t}=e,{store:i}=p(),o=c(s);return i.useSyncedValueWithCleanup("descriptionElementId",o),a("p",e,{ref:r,props:[{id:o},t]})});export{x as D};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as o}from"./__vite-browser-external-8kU62_i_.js";import{h as r,i as t,p as s}from"./react-DV1nb3lW.js";function i(){!r.current&&t();const[e]=o.useState(s.current);return e}export{i as u};
|