tokentracker-cli 0.94.0 → 0.95.0
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 +9 -7
- package/README.ja.md +8 -6
- package/README.ko.md +8 -6
- package/README.md +23 -10
- package/README.zh-CN.md +8 -6
- package/dashboard/dist/assets/{AchievementBadge-DPqwk2zI.js → AchievementBadge-Pi3Gvbm8.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-CELHoMQt.js → AchievementsPage-C4WLT8Rl.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-DdAC0VCb.js → AchievementsSection-ilvR2ssr.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-Dd4I1SpM.js → BadgeDetailModal-CjEeToxa.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-DL2-4mnm.js → BotAnimated-DDf9pBuK.js} +1 -1
- package/dashboard/dist/assets/{Card-B_MpSRse.js → Card-DNous84-.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-BLZZ4rG6.js → ClawdAnimated-BLMIRntb.js} +2 -2
- package/dashboard/dist/assets/{CommandPalette-B-vfdIbH.js → CommandPalette-vVekhoFO.js} +1 -1
- package/dashboard/dist/assets/CommunityStatsModal-C0Kp_J8B.js +1 -0
- package/dashboard/dist/assets/{ConfirmModal-DLnRwUXC.js → ConfirmModal-DFdpcx12.js} +1 -1
- package/dashboard/dist/assets/{Controls-FZ8wEN5w.js → Controls-RNhqybmE.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-BQjQh1IQ.js +1 -0
- package/dashboard/dist/assets/{DevicePage-D2IzPc5o.js → DevicePage-DIhh-YAk.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-BaqQaUUk.js → DialogClose-ZqxYVIzl.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-DDM4aanX.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-DrbKjtuS.js → DialogTitle-BiRcejlu.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-GddKDE8i.js → FadeIn-BDBQpeGe.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-DUu-Z5mE.js → HeaderGithubStar-CztIwtKT.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-BmDkY35A.js → HoverTooltip-Cfso7LTC.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-CGJyqWk2.js → IpCheckPage-CNE7dLs3.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-Bd91ALUj.js → LandingPage-B2a3cweM.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardAvatar-BGGUwXFd.js → LeaderboardAvatar-CwmZnIji.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-BMEqHwif.js → LeaderboardPage-DkTHj3fB.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-BSweJqm2.js → LeaderboardProfileModal-CefTO3Zh.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-CRrI3RFz.js → LeaderboardProfilePage-CnOXlQ3L.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-XIRDv46K.js → LimitsPage-BIZ1-6BB.js} +2 -2
- package/dashboard/dist/assets/{LocalOnlyNotice-CCD-lGWG.js → LocalOnlyNotice-CdHQiPhy.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-lDuqSv4f.js → LoginCard-yXLA9geu.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-DStt5VXN.js → LoginModal-BF2Pfkqa.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-dmVPSL72.js → LoginPage-DuOypZap.js} +1 -1
- package/dashboard/dist/assets/{PetPage-ybcZRctF.js → PetPage-BH3xDVV9.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-Dar_UjxF.js → PopoverPopup-CewF_cGz.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-Ct9tILpz.js → ProviderIcon-Dg0K0RPn.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-B4yLh5zx.js → ResetPasswordPage-CYwt85O3.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-BOE1CEzq.js → SegmentedControl-BJkXXomQ.js} +1 -1
- package/dashboard/dist/assets/{Select-D-bSh7Zz.js → Select-B3_WH0Qe.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-DMYjXXq4.js → SelectItemText-BUby_DUu.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-CaleS-6_.js → ServiceStatusPage-BDlVZk4i.js} +1 -1
- package/dashboard/dist/assets/SessionsPage-TaC9nahK.js +2 -0
- package/dashboard/dist/assets/{SettingsPage-iJH0Yyah.js → SettingsPage-CudcQh6m.js} +2 -2
- package/dashboard/dist/assets/SkillsPage-iDLQ8lpZ.js +1 -0
- package/dashboard/dist/assets/{TokenGalaxy-CuXKoMPg.js → TokenGalaxy-DtYzUsXU.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-Dx5GB7F5.js → ToolbarRootContext-PC8Tg1Jz.js} +1 -1
- package/dashboard/dist/assets/TrendMonitor-r8n8YO_9.js +19 -0
- package/dashboard/dist/assets/{WidgetsPage-DUaIyGtu.js → WidgetsPage-vzfGccWb.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-BzqlcAUC.js → WrappedPage-DaKuIkYE.js} +1 -1
- package/dashboard/dist/assets/{__vite-browser-external-BHz2N7Ih.css → __vite-browser-external-CCMdjCX2.css} +1 -1
- package/dashboard/dist/assets/__vite-browser-external-Dnxl50k1.js +45 -0
- package/dashboard/dist/assets/{agent-logos-BdWWxza6.js → agent-logos-B7nzn3n2.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-CANSzmm-.js → arrow-up-right-CsxyvCER.js} +1 -1
- package/dashboard/dist/assets/{check-BnJpzXRZ.js → check-hYcC7MdH.js} +1 -1
- package/dashboard/dist/assets/{composite-Ccj6KQmh.js → composite-C79LNbex.js} +1 -1
- package/dashboard/dist/assets/{copy-C2Yc8Evu.js → copy-Cz4qzE62.js} +1 -1
- package/dashboard/dist/assets/{download-B52JTk6Y.js → download-CUaSNE2E.js} +1 -1
- package/dashboard/dist/assets/{external-link-DayTwZx-.js → external-link-vq7kIyKK.js} +1 -1
- package/dashboard/dist/assets/{flame-B8GEX2yT.js → flame-CB6K4eR6.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-mhkbohkb.js → format-tokens-KI-e_JQ-.js} +1 -1
- package/dashboard/dist/assets/{icons-o8bPXqRP.js → icons-3maItkrp.js} +1 -1
- package/dashboard/dist/assets/{index-MBVWUKpA.js → index-BRXoZ7Jj.js} +1 -1
- package/dashboard/dist/assets/{index-CK_CduLm.js → index-C5WrfmLB.js} +1 -1
- package/dashboard/dist/assets/{index-Bp0ZHDtz.js → index-CUbC50Zp.js} +1 -1
- package/dashboard/dist/assets/{info-D94QM_vX.js → info-r0yGihUe.js} +1 -1
- package/dashboard/dist/assets/{limits-providers-BLzMyCiy.js → limits-providers-BN_94oe9.js} +1 -1
- package/dashboard/dist/assets/{link-2-CqBmFaDI.js → link-2-J9t0VXWM.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-SaxUpDR6.js → loader-circle-DCvOsPze.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-BoXqARks.js → maximize-2-CZ9JhGjf.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-Conh_-BD.js → modifiers.esm-DJ0_WKg0.js} +1 -1
- package/dashboard/dist/assets/module-xpSFyNBK.js +3 -0
- package/dashboard/dist/assets/{monitor-smartphone-D6qLR9qd.js → monitor-smartphone-nqbWjJx_.js} +1 -1
- package/dashboard/dist/assets/{plus-D51mjIc2.js → plus-Cg7wd2jK.js} +1 -1
- package/dashboard/dist/assets/{provider-display-DpHPjd_s.js → provider-display-B9L1nRY9.js} +2 -2
- package/dashboard/dist/assets/{react-D_AcI466.js → react-D2AD6Pk2.js} +1 -1
- package/dashboard/dist/assets/{search-CwLcNdvZ.js → search-uNiWba1h.js} +1 -1
- package/dashboard/dist/assets/{skills-api-Dqi7Mjgo.js → skills-api-BBYuAhiL.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-BPDlUxPb.js → sortable.esm-CzPxc949.js} +1 -1
- package/dashboard/dist/assets/{store-ikeRIRGd.js → store-D4A7EUwE.js} +1 -1
- package/dashboard/dist/assets/{terminal-BfeX3L5T.js → terminal-Crmm_yKF.js} +1 -1
- package/dashboard/dist/assets/{trash-2-5_Qlp1k7.js → trash-2-ia9VjRnU.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-D90Fy2_j.js → use-community-stats-KaGCAxaF.js} +1 -1
- package/dashboard/dist/assets/use-latest-request-guard-Dy8gSDkk.js +1 -0
- package/dashboard/dist/assets/{use-limits-display-prefs-D4BYFaa-.js → use-limits-display-prefs-JSTYlbTD.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-DJxLNdXY.js → use-ordered-list-C4JnHdE0.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-AQE0ummK.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-CAX_GqXc.js → use-session-efficiency-pref-CgyUz5Gc.js} +1 -1
- package/dashboard/dist/assets/{use-transform-CeW6Z5R0.js → use-transform-C7-jSJ9k.js} +1 -1
- package/dashboard/dist/assets/use-usage-limits-B3YYqn-v.js +1 -0
- package/dashboard/dist/assets/{useCurrency-BarGeFyK.js → useCurrency-CK_gcb3J.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-DUJ9iT9H.js → useTokenFormat-C_a-UkCA.js} +1 -1
- package/dashboard/dist/assets/{zap--m0IWoI3.js → zap-BIJNn-Ic.js} +1 -1
- package/dashboard/dist/brand-logos/lmstudio.svg +12 -0
- package/dashboard/dist/brand-logos/unsloth.svg +1 -0
- package/dashboard/dist/index.html +16 -12
- package/dashboard/dist/ip-check.html +2 -2
- package/dashboard/dist/leaderboard.html +2 -2
- package/dashboard/dist/llms.txt +4 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +2 -2
- package/src/commands/device-login.js +5 -10
- package/src/commands/init.js +28 -1
- package/src/commands/serve.js +6 -0
- package/src/commands/status.js +24 -0
- package/src/commands/sync.js +114 -18
- package/src/lib/cloud-account.js +102 -29
- package/src/lib/fs.js +30 -0
- package/src/lib/grok-context-breakdown.js +24 -33
- package/src/lib/grok-usage.js +95 -0
- package/src/lib/local-api.js +101 -13
- package/src/lib/pricing/index.js +15 -0
- package/src/lib/pricing/matcher.js +15 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +1094 -72
- package/src/lib/session-analytics.js +100 -40
- package/src/lib/usage-limits.js +507 -55
- package/src/lib/zcode-limits.js +65 -8
- package/dashboard/dist/assets/CommunityStatsModal-aAico565.js +0 -1
- package/dashboard/dist/assets/DashboardPage-BByRBsbt.js +0 -1
- package/dashboard/dist/assets/DialogDescription-BUrh0Jod.js +0 -1
- package/dashboard/dist/assets/SessionsPage-DOaY6_E9.js +0 -2
- package/dashboard/dist/assets/SkillsPage-BkzJOBLk.js +0 -1
- package/dashboard/dist/assets/TrendMonitor-BuKmsznP.js +0 -19
- package/dashboard/dist/assets/__vite-browser-external-CVIGknXl.js +0 -45
- package/dashboard/dist/assets/chevron-right-DJm0mbG0.js +0 -1
- package/dashboard/dist/assets/module-D2D5r9gC.js +0 -3
- package/dashboard/dist/assets/use-reduced-motion-yE3T3cat.js +0 -1
- package/dashboard/dist/assets/use-usage-limits-5HP8k9a3.js +0 -1
|
@@ -31,6 +31,7 @@ const readline = require("node:readline");
|
|
|
31
31
|
const { listClaudeProjectFiles, listRolloutFilesDeep, claudeMessageDedupKey } = require("./rollout");
|
|
32
32
|
const { parseCodexRolloutFile } = require("./codex-rollout-parser");
|
|
33
33
|
const { computeRowCost } = require("./pricing");
|
|
34
|
+
const { USD_TICKS_PER_USD, normalizeGrokUsage } = require("./grok-usage");
|
|
34
35
|
const wsl = require("./wsl-probe");
|
|
35
36
|
|
|
36
37
|
// Bump the sidecar when derived metrics change so cached rows are rebuilt
|
|
@@ -54,6 +55,8 @@ const wsl = require("./wsl-probe");
|
|
|
54
55
|
// stay valid while Grok entries appear on the next full rebuild.
|
|
55
56
|
// v11 groups native/WSL copies of one logical Claude/Codex session and scans
|
|
56
57
|
// their union, deduping shared records while retaining divergent tails.
|
|
58
|
+
// v12 fixes Grok's mutually exclusive token columns, retains exact reported
|
|
59
|
+
// cost, and adds metadata-only usage diagnostics to the local session browser.
|
|
57
60
|
// v12 retains Codex parent/subagent metadata locally and derives exact child
|
|
58
61
|
// token totals from observed child rollouts instead of spawn-call estimates.
|
|
59
62
|
const SIDECAR_VERSION = 12;
|
|
@@ -240,7 +243,12 @@ function finalizeRecord(record) {
|
|
|
240
243
|
record.active_ms = Math.max(0, finite(record.active_ms));
|
|
241
244
|
record.duration_ms = record.active_ms;
|
|
242
245
|
record.total_tokens = finite(record.total_tokens || record.tokens?.total_tokens);
|
|
243
|
-
|
|
246
|
+
const providerCost = Number(record.provider_cost_usd);
|
|
247
|
+
record.cost_usd = record.cost_source === "provider_reported"
|
|
248
|
+
&& Number.isFinite(providerCost)
|
|
249
|
+
&& providerCost >= 0
|
|
250
|
+
? providerCost
|
|
251
|
+
: computeRowCost({ source: record.source, model: record.model, ...record.tokens });
|
|
244
252
|
record.productive = record.edit_turns > 0;
|
|
245
253
|
// A first-pass delivery has exactly one user turn containing an observed
|
|
246
254
|
// edit and no repeated user request. The legacy one_shot field stays as an
|
|
@@ -583,42 +591,6 @@ function grokTimestampIso(obj) {
|
|
|
583
591
|
return new Date(ms).toISOString();
|
|
584
592
|
}
|
|
585
593
|
|
|
586
|
-
// Grok reports inputTokens as the full prompt (including cache hits). Split so
|
|
587
|
-
// pricing can apply cache_read rates correctly — same authority as the usage
|
|
588
|
-
// parser and grok-context-breakdown.readUsageTotals. Prefer the reported
|
|
589
|
-
// totalTokens; do not re-sum input+cached (that double-counts cache hits).
|
|
590
|
-
function grokUsageTotals(usage) {
|
|
591
|
-
if (!usage || typeof usage !== "object") return emptyTotals();
|
|
592
|
-
const inputRaw = finite(usage.inputTokens ?? usage.input_tokens);
|
|
593
|
-
const cached_input_tokens = finite(
|
|
594
|
-
usage.cachedReadTokens ?? usage.cache_read_input_tokens ?? usage.cached_input_tokens,
|
|
595
|
-
);
|
|
596
|
-
const cache_creation_input_tokens = finite(
|
|
597
|
-
usage.cachedWriteTokens ?? usage.cache_creation_input_tokens,
|
|
598
|
-
);
|
|
599
|
-
const output_tokens = finite(usage.outputTokens ?? usage.output_tokens);
|
|
600
|
-
const reasoning_output_tokens = finite(
|
|
601
|
-
usage.reasoningTokens ?? usage.reasoning_output_tokens,
|
|
602
|
-
);
|
|
603
|
-
const input_tokens = Math.max(0, inputRaw - cached_input_tokens);
|
|
604
|
-
let total_tokens = finite(usage.totalTokens ?? usage.total_tokens);
|
|
605
|
-
if (total_tokens <= 0) {
|
|
606
|
-
total_tokens = input_tokens
|
|
607
|
-
+ cached_input_tokens
|
|
608
|
-
+ cache_creation_input_tokens
|
|
609
|
-
+ output_tokens
|
|
610
|
-
+ reasoning_output_tokens;
|
|
611
|
-
}
|
|
612
|
-
return {
|
|
613
|
-
input_tokens,
|
|
614
|
-
cached_input_tokens,
|
|
615
|
-
cache_creation_input_tokens,
|
|
616
|
-
output_tokens,
|
|
617
|
-
reasoning_output_tokens,
|
|
618
|
-
total_tokens,
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
|
|
622
594
|
function pickGrokModel(usage, fallback) {
|
|
623
595
|
const modelUsage = usage?.modelUsage;
|
|
624
596
|
if (modelUsage && typeof modelUsage === "object") {
|
|
@@ -718,6 +690,13 @@ async function scanGrokSession(filePath) {
|
|
|
718
690
|
let currentHadEdit = false;
|
|
719
691
|
let subagentCalls = 0;
|
|
720
692
|
const subagentTypes = new Map();
|
|
693
|
+
let usageEvents = 0;
|
|
694
|
+
let providerCostEvents = 0;
|
|
695
|
+
let providerCostUsd = 0;
|
|
696
|
+
let modelCalls = 0;
|
|
697
|
+
let apiDurationMs = 0;
|
|
698
|
+
let usageIsIncomplete = false;
|
|
699
|
+
let costIsPartial = false;
|
|
721
700
|
let lastPromptFingerprint = null;
|
|
722
701
|
// Grok streams user_message_chunk pieces for one prompt. Accumulate until
|
|
723
702
|
// turn_completed, then fingerprint the full prompt for retry detection.
|
|
@@ -786,7 +765,21 @@ async function scanGrokSession(filePath) {
|
|
|
786
765
|
if (sessionUpdate === "turn_completed") {
|
|
787
766
|
closeTurn();
|
|
788
767
|
const usage = update.usage;
|
|
789
|
-
|
|
768
|
+
const normalizedUsage = normalizeGrokUsage(usage);
|
|
769
|
+
if (normalizedUsage) {
|
|
770
|
+
usageEvents += 1;
|
|
771
|
+
addTotals(tokens, normalizedUsage);
|
|
772
|
+
modelCalls += finite(normalizedUsage.model_calls);
|
|
773
|
+
apiDurationMs += finite(normalizedUsage.api_duration_ms);
|
|
774
|
+
usageIsIncomplete ||= normalizedUsage.usage_is_incomplete;
|
|
775
|
+
costIsPartial ||= normalizedUsage.cost_is_partial;
|
|
776
|
+
if (normalizedUsage.total_cost_usd != null) {
|
|
777
|
+
providerCostEvents += 1;
|
|
778
|
+
providerCostUsd = Math.round(
|
|
779
|
+
(providerCostUsd + normalizedUsage.total_cost_usd) * USD_TICKS_PER_USD,
|
|
780
|
+
) / USD_TICKS_PER_USD;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
790
783
|
const candidate = pickGrokModel(usage, model);
|
|
791
784
|
if (candidate && candidate !== "unknown") model = candidate;
|
|
792
785
|
continue;
|
|
@@ -810,6 +803,11 @@ async function scanGrokSession(filePath) {
|
|
|
810
803
|
model = normalizeSessionModel(signals.primaryModelId) || model;
|
|
811
804
|
}
|
|
812
805
|
|
|
806
|
+
const hasCompleteProviderCost = usageEvents > 0
|
|
807
|
+
&& providerCostEvents === usageEvents
|
|
808
|
+
&& !usageIsIncomplete
|
|
809
|
+
&& !costIsPartial;
|
|
810
|
+
|
|
813
811
|
return finalizeRecord({
|
|
814
812
|
version: SIDECAR_VERSION,
|
|
815
813
|
session_hash: sessionHash("grok", observedSessionId || filePath),
|
|
@@ -827,7 +825,29 @@ async function scanGrokSession(filePath) {
|
|
|
827
825
|
subagent_calls: subagentCalls,
|
|
828
826
|
subagent_types: Object.fromEntries([...subagentTypes.entries()].sort()),
|
|
829
827
|
tokens,
|
|
830
|
-
|
|
828
|
+
usage_events: usageEvents,
|
|
829
|
+
usage_precision: usageIsIncomplete ? "reported_incomplete" : (usageEvents > 0 ? "reported" : "unavailable"),
|
|
830
|
+
usage_is_incomplete: usageIsIncomplete,
|
|
831
|
+
cost_is_partial: costIsPartial,
|
|
832
|
+
cost_source: hasCompleteProviderCost ? "provider_reported" : "model_pricing",
|
|
833
|
+
provider_cost_usd: hasCompleteProviderCost ? providerCostUsd : null,
|
|
834
|
+
model_calls: modelCalls,
|
|
835
|
+
api_duration_ms: apiDurationMs,
|
|
836
|
+
context_tokens_used: finite(signals.contextTokensUsed),
|
|
837
|
+
context_window_tokens: finite(signals.contextWindowTokens),
|
|
838
|
+
context_usage_percent: finite(signals.contextWindowUsage),
|
|
839
|
+
tool_calls: finite(signals.toolCallCount),
|
|
840
|
+
tool_failures: finite(signals.toolFailureCount),
|
|
841
|
+
error_count: finite(signals.errorCount),
|
|
842
|
+
compaction_count: finite(signals.compactionCount),
|
|
843
|
+
provenance: {
|
|
844
|
+
source: "local-session-log",
|
|
845
|
+
confidence: usageIsIncomplete ? "partial" : "observed",
|
|
846
|
+
retry_confidence: "inferred",
|
|
847
|
+
content_retained: false,
|
|
848
|
+
usage: usageEvents > 0 ? "turn_completed.usage" : "unavailable",
|
|
849
|
+
cost: hasCompleteProviderCost ? "provider_reported" : "model_pricing",
|
|
850
|
+
},
|
|
831
851
|
});
|
|
832
852
|
}
|
|
833
853
|
|
|
@@ -1410,6 +1430,7 @@ function resumeCommandFor(source, sessionId) {
|
|
|
1410
1430
|
}
|
|
1411
1431
|
|
|
1412
1432
|
function toSessionBrowserRow(row) {
|
|
1433
|
+
const tokens = row.tokens && typeof row.tokens === "object" ? row.tokens : {};
|
|
1413
1434
|
return {
|
|
1414
1435
|
session_hash: row.session_hash,
|
|
1415
1436
|
session_id: row.session_id || null,
|
|
@@ -1435,6 +1456,11 @@ function toSessionBrowserRow(row) {
|
|
|
1435
1456
|
edit_turns: finite(row.edit_turns),
|
|
1436
1457
|
retry_turns: finite(row.retry_turns),
|
|
1437
1458
|
subagent_calls: finite(row.subagent_calls),
|
|
1459
|
+
input_tokens: finite(tokens.input_tokens),
|
|
1460
|
+
cached_input_tokens: finite(tokens.cached_input_tokens),
|
|
1461
|
+
cache_creation_input_tokens: finite(tokens.cache_creation_input_tokens),
|
|
1462
|
+
output_tokens: finite(tokens.output_tokens),
|
|
1463
|
+
reasoning_output_tokens: finite(tokens.reasoning_output_tokens),
|
|
1438
1464
|
direct_subagent_count: finite(row.direct_subagent_count),
|
|
1439
1465
|
descendant_subagent_count: finite(row.descendant_subagent_count),
|
|
1440
1466
|
own_total_tokens: finite(row.total_tokens),
|
|
@@ -1445,6 +1471,20 @@ function toSessionBrowserRow(row) {
|
|
|
1445
1471
|
subagent_cost_usd: finite(row.subagent_cost_usd),
|
|
1446
1472
|
combined_cost_usd: finite(row.combined_cost_usd || row.cost_usd),
|
|
1447
1473
|
cost_usd: finite(row.cost_usd),
|
|
1474
|
+
cost_source: row.cost_source || null,
|
|
1475
|
+
usage_precision: row.usage_precision || null,
|
|
1476
|
+
usage_is_incomplete: Boolean(row.usage_is_incomplete),
|
|
1477
|
+
cost_is_partial: Boolean(row.cost_is_partial),
|
|
1478
|
+
usage_events: finite(row.usage_events),
|
|
1479
|
+
model_calls: finite(row.model_calls),
|
|
1480
|
+
api_duration_ms: finite(row.api_duration_ms),
|
|
1481
|
+
context_tokens_used: finite(row.context_tokens_used),
|
|
1482
|
+
context_window_tokens: finite(row.context_window_tokens),
|
|
1483
|
+
context_usage_percent: finite(row.context_usage_percent),
|
|
1484
|
+
tool_calls: finite(row.tool_calls),
|
|
1485
|
+
tool_failures: finite(row.tool_failures),
|
|
1486
|
+
error_count: finite(row.error_count),
|
|
1487
|
+
compaction_count: finite(row.compaction_count),
|
|
1448
1488
|
productive: Boolean(row.productive),
|
|
1449
1489
|
first_pass: Boolean(row.first_pass ?? row.one_shot),
|
|
1450
1490
|
resume_command: resumeCommandFor(row.source, row.session_id),
|
|
@@ -1463,15 +1503,35 @@ function mergeSessionFragments(rows) {
|
|
|
1463
1503
|
const key = row.session_hash;
|
|
1464
1504
|
const cur = byHash.get(key);
|
|
1465
1505
|
if (!cur) {
|
|
1466
|
-
byHash.set(key, {
|
|
1506
|
+
byHash.set(key, {
|
|
1507
|
+
...row,
|
|
1508
|
+
tokens: row.tokens && typeof row.tokens === "object" ? { ...row.tokens } : emptyTotals(),
|
|
1509
|
+
_repr_tokens: finite(row.total_tokens),
|
|
1510
|
+
});
|
|
1467
1511
|
continue;
|
|
1468
1512
|
}
|
|
1469
1513
|
cur.turns = finite(cur.turns) + finite(row.turns);
|
|
1470
1514
|
cur.edit_turns = finite(cur.edit_turns) + finite(row.edit_turns);
|
|
1471
1515
|
cur.retry_turns = finite(cur.retry_turns) + finite(row.retry_turns);
|
|
1472
1516
|
cur.subagent_calls = finite(cur.subagent_calls) + finite(row.subagent_calls);
|
|
1517
|
+
addTotals(cur.tokens, row.tokens);
|
|
1473
1518
|
cur.total_tokens = finite(cur.total_tokens) + finite(row.total_tokens);
|
|
1474
1519
|
cur.cost_usd = finite(cur.cost_usd) + finite(row.cost_usd);
|
|
1520
|
+
cur.provider_cost_usd = finite(cur.provider_cost_usd) + finite(row.provider_cost_usd);
|
|
1521
|
+
cur.usage_events = finite(cur.usage_events) + finite(row.usage_events);
|
|
1522
|
+
cur.model_calls = finite(cur.model_calls) + finite(row.model_calls);
|
|
1523
|
+
cur.api_duration_ms = finite(cur.api_duration_ms) + finite(row.api_duration_ms);
|
|
1524
|
+
cur.tool_calls = finite(cur.tool_calls) + finite(row.tool_calls);
|
|
1525
|
+
cur.tool_failures = finite(cur.tool_failures) + finite(row.tool_failures);
|
|
1526
|
+
cur.error_count = finite(cur.error_count) + finite(row.error_count);
|
|
1527
|
+
cur.compaction_count = finite(cur.compaction_count) + finite(row.compaction_count);
|
|
1528
|
+
cur.context_tokens_used = Math.max(finite(cur.context_tokens_used), finite(row.context_tokens_used));
|
|
1529
|
+
cur.context_window_tokens = Math.max(finite(cur.context_window_tokens), finite(row.context_window_tokens));
|
|
1530
|
+
cur.context_usage_percent = Math.max(finite(cur.context_usage_percent), finite(row.context_usage_percent));
|
|
1531
|
+
cur.usage_is_incomplete = Boolean(cur.usage_is_incomplete) || Boolean(row.usage_is_incomplete);
|
|
1532
|
+
cur.cost_is_partial = Boolean(cur.cost_is_partial) || Boolean(row.cost_is_partial);
|
|
1533
|
+
if (cur.usage_precision !== row.usage_precision) cur.usage_precision = "mixed";
|
|
1534
|
+
if (cur.cost_source !== row.cost_source) cur.cost_source = "mixed";
|
|
1475
1535
|
cur.productive = Boolean(cur.productive) || Boolean(row.productive);
|
|
1476
1536
|
cur.active_ms = finite(cur.active_ms) + finite(row.active_ms);
|
|
1477
1537
|
if (!cur.title && row.title) cur.title = row.title;
|