tokentracker-cli 1.5.16 → 1.5.17
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-CnnJGct8.js → AchievementBadge-BiEoQE7Z.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-CFkUJVxy.js → AchievementsPage-4g0Q8O0U.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-CoLQX04M.js → AchievementsSection-D5dyOWFj.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-s8rObEHY.js → BadgeDetailModal-Bz067XUw.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-BmBnL-i8.js → BotAnimated-CFiGrlrg.js} +1 -1
- package/dashboard/dist/assets/{Card-BIqie5mN.js → Card-CkYKahsn.js} +1 -1
- package/dashboard/dist/assets/{CloudCheckoutPage-B_c8Q58A.js → CloudCheckoutPage-BCzIRPkW.js} +1 -1
- package/dashboard/dist/assets/{CloudPage-CfW_pDf2.js → CloudPage-C0MZTK-9.js} +2 -2
- package/dashboard/dist/assets/{CommandPalette-BRryGPVJ.js → CommandPalette-DwSGE7c-.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-Cyh1Q9Fw.js → CommunityStatsModal-B80ps9B5.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-DWBYqpLJ.js → ConfirmModal-xthCJoY5.js} +1 -1
- package/dashboard/dist/assets/{Controls-CPSiCzVW.js → Controls-DZ9vKkCI.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-JcS1xwUm.js → DashboardPage-C4SwA5lD.js} +1 -1
- package/dashboard/dist/assets/{DateRangePopover-DjuS6888.js → DateRangePopover-D8ihZ5SK.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-DZ3qiDbT.js → DevicePage-OVnpUpAc.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-CfORRnoT.js → DialogClose-DpueWMdH.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-CNb40Z5w.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-DZO6-sTI.js → DialogTitle-Be_-fYZA.js} +1 -1
- package/dashboard/dist/assets/{ElectricLogo-BzR7mRin.js → ElectricLogo-BJek75ac.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-BxHaUvz_.js → FadeIn-HIpnpyJ-.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-KGzKAmuQ.js → HeaderGithubStar-Dj0guZ3R.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-C6pASVDN.js → HoverTooltip-B3p_QB2m.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-BJ8TROZC.js → IpCheckPage-DrxLV2uL.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-B15GRFpI.js → LandingPage-C3RPJvXW.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardPage-C3hJ2Gh3.js → LeaderboardPage-CkVKRCA7.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProBadge-CRfBTxpt.js → LeaderboardProBadge-C39qylf0.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfileModal-DTGmcjWF.js → LeaderboardProfileModal-D1DEHNRN.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-BD04D7ML.js → LeaderboardProfilePage-CoBBl1-f.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-LsDCIUKd.js → LimitsPage-BnjPGpcE.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-B3XQKD8k.js → LocalOnlyNotice-CqCRY_ls.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-DF1XcskU.js → LoginCard-BeA3kcgy.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-DuyVT0Tt.js → LoginModal-D9S7DnuH.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-kge4kJKa.js → LoginPage-CXRATGB_.js} +1 -1
- package/dashboard/dist/assets/{PetPage-DuYtsKza.js → PetPage-0_l-kTr4.js} +2 -2
- package/dashboard/dist/assets/{PopoverPopup-BkNNS3VG.js → PopoverPopup-CfPgHc44.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-z2TKXPlS.js → ProviderIcon-DtjD5jVb.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-CXM9E6d1.js → ResetPasswordPage-Bt8QpFOe.js} +1 -1
- package/dashboard/dist/assets/{Select-CeoAayzi.js → Select-BgQXA6kK.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-CRxvAgUV.js → SelectItemText-C7hWQpTf.js} +1 -1
- package/dashboard/dist/assets/{SelfHostPage-Cavstn-d.js → SelfHostPage-CUK_eL6K.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-CdIeM_DX.js → ServiceStatusPage-CF0nAsAf.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-DPihAS26.js → SessionsPage-CE2cz-4_.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-zxOsLeE5.js → SettingsPage-su2wAKfz.js} +3 -3
- package/dashboard/dist/assets/{SkillsPage-BRGonzsC.js → SkillsPage-Bp0PnSf_.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-D9-huQJ_.js → TokenGalaxy-CjY25cur.js} +1 -1
- package/dashboard/dist/assets/{TooltipPopup-BS99Tf44.js → TooltipPopup-DDztBp5x.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-DlNT4ObY.js → TrendMonitor-CDaOhv8o.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-DTFnmTwq.js → WidgetsPage-CjaQe3QN.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-DwMdnusQ.js → WrappedPage-P4LVouC8.js} +1 -1
- package/dashboard/dist/assets/{__vite-browser-external-DR_a-OTS.js → __vite-browser-external-CzHn8J8J.js} +2 -2
- package/dashboard/dist/assets/{agent-logos-D6kTooyz.js → agent-logos-CS9Iaf0t.js} +1 -1
- package/dashboard/dist/assets/{arrow-left-jpuJhYL4.js → arrow-left-nH7mwAsq.js} +1 -1
- package/dashboard/dist/assets/{arrow-right-n1hLkwiK.js → arrow-right-BoRjpMCP.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-fZmEfh7R.js → arrow-up-right-Cg0soM7i.js} +1 -1
- package/dashboard/dist/assets/{calendar-days-B0LdECvD.js → calendar-days-6BSY0SCe.js} +1 -1
- package/dashboard/dist/assets/{check-CcnNd8bi.js → check-Ldxu9X3c.js} +1 -1
- package/dashboard/dist/assets/{chevron-down-DhbHBjVC.js → chevron-down-Cl1UIsFC.js} +1 -1
- package/dashboard/dist/assets/{cloud-checkout-9XOoux-p.js → cloud-checkout-CgoKsrLa.js} +1 -1
- package/dashboard/dist/assets/{composite-DIDAkYhy.js → composite-CqtsbFSD.js} +1 -1
- package/dashboard/dist/assets/{copy-BNDBunFG.js → copy-CHDv4TDb.js} +1 -1
- package/dashboard/dist/assets/{download-wlqdqJmq.js → download-bExf6Ccu.js} +1 -1
- package/dashboard/dist/assets/{external-link-BvssZ_45.js → external-link-DPe3LHcW.js} +1 -1
- package/dashboard/dist/assets/{flame-DP8IUT3E.js → flame-CYUEYQbn.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-DMsx_fWk.js → format-tokens-CJ73U0H5.js} +1 -1
- package/dashboard/dist/assets/{gift-zF4D6O4a.js → gift-BCmo7fKV.js} +1 -1
- package/dashboard/dist/assets/{icons-Batw5aOg.js → icons-BtAa7a8Q.js} +1 -1
- package/dashboard/dist/assets/{index-Dc8PQ8ZR.js → index--VJpPvce.js} +1 -1
- package/dashboard/dist/assets/{index-3qKpTOzz.js → index-CKwNx_s1.js} +1 -1
- package/dashboard/dist/assets/{index-dCfimErX.js → index-CSFt_XvV.js} +1 -1
- package/dashboard/dist/assets/{index-Cqla2Zq5.js → index-CyhRNpQp.js} +1 -1
- package/dashboard/dist/assets/{info-DcUyOPKG.js → info-Cc5_kre6.js} +1 -1
- package/dashboard/dist/assets/{link-2-CS-cWLmx.js → link-2-_RZOZ7kJ.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-DKc-gwgL.js → loader-circle-7GinPf0v.js} +1 -1
- package/dashboard/dist/assets/{local-usage-transfer-bHATORmq.js → local-usage-transfer-Cx5WBzma.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-B4QifJzx.js → modifiers.esm-CO1bm3IT.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-D8vpN9Jv.js → monitor-smartphone-CjBB2EQT.js} +1 -1
- package/dashboard/dist/assets/{play-D70P7DVT.js → play-B9AHJ0ir.js} +1 -1
- package/dashboard/dist/assets/{plus-YomnSdqY.js → plus-BYHC32xe.js} +1 -1
- package/dashboard/dist/assets/{provider-display-VXu7Hzwq.js → provider-display-N2l_YZhb.js} +1 -1
- package/dashboard/dist/assets/{react-CUO9Gs2G.js → react-DSS6zSQ7.js} +1 -1
- package/dashboard/dist/assets/{safePolygon-CbVKM3Lv.js → safePolygon-BdbLh1jE.js} +1 -1
- package/dashboard/dist/assets/{search-BUi1hAmV.js → search-D89mjm04.js} +1 -1
- package/dashboard/dist/assets/{server-B-agbJYI.js → server-PR9yTCiu.js} +1 -1
- package/dashboard/dist/assets/{shield-check-yHx3fQDo.js → shield-check-BYLC3hFn.js} +1 -1
- package/dashboard/dist/assets/{skills-api-DojEO2dS.js → skills-api-CM8yP8ZQ.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-r4Lz4ugj.js → sortable.esm-4l8igdkd.js} +1 -1
- package/dashboard/dist/assets/{store-GzQbKyT-.js → store-uku0hfBl.js} +1 -1
- package/dashboard/dist/assets/{terminal-BLCZgZTm.js → terminal-CQsyMIKh.js} +1 -1
- package/dashboard/dist/assets/{trash-BFGtCBJS.js → trash-Du6DwmPp.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-DGdLAa8L.js → use-community-stats-BI2Vkwhm.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-l39bM4s0.js → use-latest-request-guard-AGXK-7W_.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-JcWgMNA0.js → use-limits-display-prefs-XaEErSEN.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-0sXFw6mq.js → use-native-settings-BzNwI3lk.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-mRdyZ18r.js → use-ordered-list-BUkFot2m.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-Dl-5CnUW.js +1 -0
- package/dashboard/dist/assets/{use-transform-CbJqMa_Y.js → use-transform-CRTGmr0C.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-qQKS4sHR.js → use-usage-limits-DMHAKEU7.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-BJyZCVtd.js → useCurrency-D7bYEIAY.js} +1 -1
- package/dashboard/dist/assets/{usePositioner-zsiJqVGU.js → usePositioner-PRBIy_6t.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-DxEKSp5H.js → useTokenFormat-CGacmoDz.js} +1 -1
- package/dashboard/dist/assets/{zap-D40-8VPk.js → zap-B8svUQzd.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/dsh-session.js +81 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/session-analytics.js +4 -1
- package/src/lib/session-performance.js +15 -0
- package/dashboard/dist/assets/DialogDescription-ChihKLnm.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-D2g3iGbi.js +0 -1
package/src/lib/dsh-session.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
const fs = require("node:fs");
|
|
9
9
|
const path = require("node:path");
|
|
10
10
|
const crypto = require("node:crypto");
|
|
11
|
+
const { createDshPerformanceCollector, normalizePerformance } = require("./session-performance");
|
|
11
12
|
const {
|
|
12
13
|
isDshSessionLogName,
|
|
13
14
|
parseDshVersion,
|
|
@@ -101,6 +102,48 @@ function eventTimestampMs(entry) {
|
|
|
101
102
|
return Number.isFinite(time) && time >= MIN_DSH_TIMESTAMP_MS ? time : null;
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
function firstStreamTokenTime(stream) {
|
|
106
|
+
// DSH v4 stores raw chunks and packed delta runs together. Only non-empty
|
|
107
|
+
// deltas (or a name-bearing tool delta) mark a token; block-start does not.
|
|
108
|
+
for (const record of stream) {
|
|
109
|
+
if (record?.type === "chunk") {
|
|
110
|
+
const chunk = record.chunk;
|
|
111
|
+
const token = ["text-delta", "reasoning-delta"].includes(chunk?.type)
|
|
112
|
+
? typeof chunk.text === "string" && chunk.text.length > 0
|
|
113
|
+
: chunk?.type === "tool-call-delta" && (
|
|
114
|
+
(typeof chunk.argumentsDelta === "string" && chunk.argumentsDelta.length > 0)
|
|
115
|
+
|| (typeof chunk.name === "string" && chunk.name.length > 0));
|
|
116
|
+
const time = eventTimestampMs(record);
|
|
117
|
+
if (token && time !== null) return time;
|
|
118
|
+
} else if (["text-chunks", "reasoning-chunks", "tool-call-chunks"].includes(record?.type)) {
|
|
119
|
+
const tool = record.type === "tool-call-chunks";
|
|
120
|
+
const fragments = tool ? record.args : record.texts;
|
|
121
|
+
let time = eventTimestampMs({ time: record.time0 });
|
|
122
|
+
if (time === null || !Array.isArray(fragments)) continue;
|
|
123
|
+
for (let index = 0; index < fragments.length; index += 1) {
|
|
124
|
+
if (index > 0) {
|
|
125
|
+
const gap = record.dt?.[index - 1];
|
|
126
|
+
if (typeof gap !== "number" || !Number.isFinite(gap)) break;
|
|
127
|
+
time += gap;
|
|
128
|
+
}
|
|
129
|
+
if ((typeof fragments[index] === "string" && fragments[index].length > 0)
|
|
130
|
+
|| (tool && typeof record.name === "string" && record.name.length > 0)) return time;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function messageTiming(data, step, end) {
|
|
138
|
+
if (!step || step.failed || data?.interrupted || step.turn !== data?.turn || step.step !== data?.step) return null;
|
|
139
|
+
const stream = Array.isArray(data?.stream) ? data.stream : null;
|
|
140
|
+
if (stream) {
|
|
141
|
+
const finish = stream.findLast((record) => record?.type === "chunk" && record.chunk?.type === "finish");
|
|
142
|
+
if (!finish || !finish.chunk.reason?.kind || ["error", "aborted"].includes(finish.chunk.reason.kind)) return null;
|
|
143
|
+
}
|
|
144
|
+
return { start: step.ts, end, firstToken: stream ? firstStreamTokenTime(stream) : null };
|
|
145
|
+
}
|
|
146
|
+
|
|
104
147
|
function directoryEntryIs(entry, fullPath, kind) {
|
|
105
148
|
const check = kind === "dir" ? entry.isDirectory() : entry.isFile();
|
|
106
149
|
if (check) return true;
|
|
@@ -279,6 +322,7 @@ async function parseDshTranscript(filePath) {
|
|
|
279
322
|
events: [],
|
|
280
323
|
};
|
|
281
324
|
const lines = text.split("\n");
|
|
325
|
+
let openStep = null;
|
|
282
326
|
for (let index = 0; index < lines.length; index += 1) {
|
|
283
327
|
const line = lines[index];
|
|
284
328
|
if (!line) continue;
|
|
@@ -292,6 +336,33 @@ async function parseDshTranscript(filePath) {
|
|
|
292
336
|
const data = entry.data && typeof entry.data === "object" ? entry.data : null;
|
|
293
337
|
const seq = Number.isFinite(entry.seq) ? entry.seq : index;
|
|
294
338
|
switch (entry.type) {
|
|
339
|
+
case "step/start": {
|
|
340
|
+
openStep = Number.isInteger(data?.turn) && Number.isInteger(data?.step)
|
|
341
|
+
? { turn: data.turn, step: data.step, ts: eventTimestampMs(entry), failed: false } : null;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case "assistant/attempt":
|
|
345
|
+
case "assistant/chunk": {
|
|
346
|
+
// A retry's step time includes failed work/backoff, so it cannot be a
|
|
347
|
+
// clean request sample even if the eventual message reports usage.
|
|
348
|
+
// v4 records the failed try as assistant/attempt. v1 has no attempt
|
|
349
|
+
// event: the failed try ends as a top-level assistant/chunk whose
|
|
350
|
+
// chunk is a finish with an error or aborted reason.
|
|
351
|
+
const chunk = data?.chunk;
|
|
352
|
+
const failedFinish = entry.type === "assistant/chunk"
|
|
353
|
+
&& chunk?.type === "finish"
|
|
354
|
+
&& ["error", "aborted"].includes(chunk.reason?.kind);
|
|
355
|
+
if ((entry.type === "assistant/attempt" || failedFinish)
|
|
356
|
+
&& openStep && openStep.turn === data?.turn && openStep.step === data?.step) {
|
|
357
|
+
openStep.failed = true;
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
case "step/end":
|
|
362
|
+
case "turn/start":
|
|
363
|
+
case "turn/end":
|
|
364
|
+
openStep = null;
|
|
365
|
+
break;
|
|
295
366
|
case "session": {
|
|
296
367
|
transcript.header = entry;
|
|
297
368
|
break;
|
|
@@ -329,6 +400,8 @@ async function parseDshTranscript(filePath) {
|
|
|
329
400
|
const ts = eventTimestampMs(entry);
|
|
330
401
|
const model = modelName(message?.source?.model) || transcript.fallbackModel || "unknown";
|
|
331
402
|
const delta = dshUsageDelta(data?.usage);
|
|
403
|
+
const timing = messageTiming(data, openStep, ts);
|
|
404
|
+
openStep = null;
|
|
332
405
|
if (delta) {
|
|
333
406
|
transcript.events.push({
|
|
334
407
|
kind: "usage",
|
|
@@ -336,6 +409,7 @@ async function parseDshTranscript(filePath) {
|
|
|
336
409
|
ts,
|
|
337
410
|
model,
|
|
338
411
|
delta,
|
|
412
|
+
timing,
|
|
339
413
|
});
|
|
340
414
|
}
|
|
341
415
|
break;
|
|
@@ -405,6 +479,7 @@ function buildRow(transcript, owners) {
|
|
|
405
479
|
const times = new Set();
|
|
406
480
|
const agentTypes = new Map();
|
|
407
481
|
const modelsForEdits = new Map();
|
|
482
|
+
const performanceCollector = createDshPerformanceCollector();
|
|
408
483
|
let turns = 0;
|
|
409
484
|
let edits = 0;
|
|
410
485
|
let retries = 0;
|
|
@@ -451,6 +526,9 @@ function buildRow(transcript, owners) {
|
|
|
451
526
|
addUsage(modelRow, delta);
|
|
452
527
|
modelRow.usage_events += 1;
|
|
453
528
|
modelUsage.set(model, modelRow);
|
|
529
|
+
if (event.timing) performanceCollector.consumeUsage({
|
|
530
|
+
model, outputTokens: delta.output_tokens + delta.reasoning_output_tokens, ...event.timing,
|
|
531
|
+
});
|
|
454
532
|
if (event.ts != null) {
|
|
455
533
|
const bucketTime = new Date(Math.floor(event.ts / 60000) * 60000).toISOString();
|
|
456
534
|
const key = `${model}\u0000${bucketTime}`;
|
|
@@ -478,9 +556,11 @@ function buildRow(transcript, owners) {
|
|
|
478
556
|
const gap = orderedTimes[index] - orderedTimes[index - 1];
|
|
479
557
|
if (gap > 0 && gap <= DSH_ACTIVE_GAP_MS) activeMs += gap;
|
|
480
558
|
}
|
|
559
|
+
const performance = performanceCollector.finish();
|
|
481
560
|
const models = [...modelUsage.values()].map((row) => ({
|
|
482
561
|
...row,
|
|
483
562
|
edit_turns: modelsForEdits.get(row.model) || 0,
|
|
563
|
+
performance: performance.byModel.get(row.model) || normalizePerformance(),
|
|
484
564
|
}));
|
|
485
565
|
// A session that only handshook (no user turn, no usage) has nothing to say.
|
|
486
566
|
if (!tokens.total_tokens && !turns) return null;
|
|
@@ -507,6 +587,7 @@ function buildRow(transcript, owners) {
|
|
|
507
587
|
started_at: orderedTimes.length ? new Date(orderedTimes[0]).toISOString() : null,
|
|
508
588
|
ended_at: orderedTimes.length ? new Date(orderedTimes.at(-1)).toISOString() : null,
|
|
509
589
|
active_ms: activeMs,
|
|
590
|
+
performance: performance.performance,
|
|
510
591
|
provenance: {
|
|
511
592
|
source: "local-session-log",
|
|
512
593
|
confidence: "observed",
|