tokentracker-cli 0.10.1 → 0.11.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/dashboard/dist/assets/main-CeKzyCR5.css +1 -0
- package/dashboard/dist/assets/{main-Cw4csGy9.js → main-DuLJEZRP.js} +240 -198
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +1 -1
- package/src/commands/sync.js +110 -7
- package/src/lib/categorizer-utils.js +232 -0
- package/src/lib/claude-categorizer.js +541 -84
- package/src/lib/codex-context-breakdown.js +400 -0
- package/src/lib/codex-rollout-parser.js +623 -0
- package/src/lib/local-api.js +137 -14
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/dashboard/dist/assets/main-Bst6S3yM.css +0 -1
package/src/lib/local-api.js
CHANGED
|
@@ -33,6 +33,8 @@ const {
|
|
|
33
33
|
unsupportedSourcePayload: unsupportedCategoryPayload,
|
|
34
34
|
} = require("./claude-categorizer");
|
|
35
35
|
|
|
36
|
+
const { computeCodexContextBreakdown } = require("./codex-context-breakdown");
|
|
37
|
+
|
|
36
38
|
// ---------------------------------------------------------------------------
|
|
37
39
|
// Queue data helpers
|
|
38
40
|
// ---------------------------------------------------------------------------
|
|
@@ -177,6 +179,101 @@ function aggregateByDay(rows, timeZoneContext = null) {
|
|
|
177
179
|
return Array.from(byDay.values()).sort((a, b) => a.day.localeCompare(b.day));
|
|
178
180
|
}
|
|
179
181
|
|
|
182
|
+
function buildCodexCategoryFallbackFromQueue(queueRows, { from, to, timeZoneContext }) {
|
|
183
|
+
const totals = {
|
|
184
|
+
input_tokens: 0,
|
|
185
|
+
cached_input_tokens: 0,
|
|
186
|
+
cache_creation_input_tokens: 0,
|
|
187
|
+
output_tokens: 0,
|
|
188
|
+
reasoning_output_tokens: 0,
|
|
189
|
+
total_tokens: 0,
|
|
190
|
+
};
|
|
191
|
+
let conversationCount = 0;
|
|
192
|
+
|
|
193
|
+
for (const row of queueRows || []) {
|
|
194
|
+
if ((row?.source || "") !== "codex") continue;
|
|
195
|
+
if (!row.hour_start) continue;
|
|
196
|
+
const day = rowDayKey(row, timeZoneContext);
|
|
197
|
+
if (from && day < from) continue;
|
|
198
|
+
if (to && day > to) continue;
|
|
199
|
+
totals.input_tokens += Number(row.input_tokens || 0);
|
|
200
|
+
totals.cached_input_tokens += Number(row.cached_input_tokens || 0);
|
|
201
|
+
totals.cache_creation_input_tokens += Number(row.cache_creation_input_tokens || 0);
|
|
202
|
+
totals.output_tokens += Number(row.output_tokens || 0);
|
|
203
|
+
totals.reasoning_output_tokens += Number(row.reasoning_output_tokens || 0);
|
|
204
|
+
totals.total_tokens += Number(row.total_tokens || 0);
|
|
205
|
+
conversationCount += Number(row.conversation_count || 0);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
source: "codex",
|
|
210
|
+
scope: "supported",
|
|
211
|
+
breakdown_status: "queue_fallback",
|
|
212
|
+
totals,
|
|
213
|
+
session_count: 0,
|
|
214
|
+
message_count: conversationCount,
|
|
215
|
+
fallback: "queue_totals",
|
|
216
|
+
message_breakdown: {
|
|
217
|
+
categories: [
|
|
218
|
+
{
|
|
219
|
+
key: "user_input",
|
|
220
|
+
name: "User input",
|
|
221
|
+
totals: {
|
|
222
|
+
input_tokens: totals.input_tokens,
|
|
223
|
+
cached_input_tokens: 0,
|
|
224
|
+
cache_creation_input_tokens: 0,
|
|
225
|
+
output_tokens: 0,
|
|
226
|
+
reasoning_output_tokens: 0,
|
|
227
|
+
total_tokens: totals.input_tokens,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
key: "conversation_history",
|
|
232
|
+
name: "Conversation history",
|
|
233
|
+
totals: {
|
|
234
|
+
input_tokens: 0,
|
|
235
|
+
cached_input_tokens: totals.cached_input_tokens,
|
|
236
|
+
cache_creation_input_tokens: totals.cache_creation_input_tokens,
|
|
237
|
+
output_tokens: 0,
|
|
238
|
+
reasoning_output_tokens: 0,
|
|
239
|
+
total_tokens: totals.cached_input_tokens + totals.cache_creation_input_tokens,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
key: "assistant_response",
|
|
244
|
+
name: "Assistant response",
|
|
245
|
+
totals: {
|
|
246
|
+
input_tokens: 0,
|
|
247
|
+
cached_input_tokens: 0,
|
|
248
|
+
cache_creation_input_tokens: 0,
|
|
249
|
+
output_tokens: Math.max(0, totals.output_tokens - totals.reasoning_output_tokens),
|
|
250
|
+
reasoning_output_tokens: 0,
|
|
251
|
+
total_tokens: Math.max(0, totals.output_tokens - totals.reasoning_output_tokens),
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
].sort((a, b) => Number(b.totals.total_tokens || 0) - Number(a.totals.total_tokens || 0)),
|
|
255
|
+
privacy: {
|
|
256
|
+
includes_content: false,
|
|
257
|
+
note: "Queue fallback includes aggregated token categories only; message text is never returned.",
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
tool_calls_breakdown: {
|
|
261
|
+
total_calls: 0,
|
|
262
|
+
tools: [],
|
|
263
|
+
categories: [],
|
|
264
|
+
tools_total: 0,
|
|
265
|
+
privacy: {
|
|
266
|
+
includes_inputs: false,
|
|
267
|
+
note: "Codex rollout sessions were unavailable; totals come from TokenTracker queue rows.",
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
exec_command_breakdown: {
|
|
271
|
+
by_type: [],
|
|
272
|
+
by_exit: [],
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
180
277
|
function getRequestedUsageScope(url) {
|
|
181
278
|
if (url.searchParams.get("include_account_level") === "1") return "all";
|
|
182
279
|
return normalizeUsageScope(url.searchParams.get("scope"));
|
|
@@ -1002,27 +1099,53 @@ function createLocalApiHandler({ queuePath }) {
|
|
|
1002
1099
|
return true;
|
|
1003
1100
|
}
|
|
1004
1101
|
|
|
1005
|
-
// --- usage-category-breakdown (Claude
|
|
1006
|
-
//
|
|
1007
|
-
//
|
|
1008
|
-
//
|
|
1009
|
-
//
|
|
1010
|
-
// per-message role data this requires, so they return scope:unsupported.
|
|
1102
|
+
// --- usage-category-breakdown (Claude + Codex) ---
|
|
1103
|
+
// Claude: splits historical Claude usage into seven semantic categories
|
|
1104
|
+
// mirroring Claude Code's /context view (approx).
|
|
1105
|
+
// Codex: provides a tool-oriented breakdown, attributing per-turn token
|
|
1106
|
+
// deltas to observed tool calls (heuristic).
|
|
1011
1107
|
if (p === "/functions/tokentracker-usage-category-breakdown") {
|
|
1012
1108
|
const from = url.searchParams.get("from") || "";
|
|
1013
1109
|
const to = url.searchParams.get("to") || "";
|
|
1014
1110
|
const requestedSource = (url.searchParams.get("source") || "claude").trim().toLowerCase();
|
|
1015
|
-
if (requestedSource
|
|
1016
|
-
|
|
1111
|
+
if (requestedSource === "claude") {
|
|
1112
|
+
try {
|
|
1113
|
+
const result = await computeClaudeCategoryBreakdown({ from, to, projectDir: process.cwd() });
|
|
1114
|
+
json(res, { from, to, ...result });
|
|
1115
|
+
} catch (e) {
|
|
1116
|
+
console.error("[LocalAPI] usage-category-breakdown:", e?.message || e);
|
|
1117
|
+
json(res, { from, to, ...unsupportedCategoryPayload("claude"), error: "compute_failed" }, 500);
|
|
1118
|
+
}
|
|
1017
1119
|
return true;
|
|
1018
1120
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1121
|
+
|
|
1122
|
+
if (requestedSource === "codex") {
|
|
1123
|
+
try {
|
|
1124
|
+
const timeZoneContext = getTimeZoneContext(url);
|
|
1125
|
+
const result = await computeCodexContextBreakdown({
|
|
1126
|
+
from,
|
|
1127
|
+
to,
|
|
1128
|
+
top: 50,
|
|
1129
|
+
timeZoneContext,
|
|
1130
|
+
});
|
|
1131
|
+
if (!Number(result?.totals?.total_tokens || 0)) {
|
|
1132
|
+
const fallback = buildCodexCategoryFallbackFromQueue(readQueueData(qp), {
|
|
1133
|
+
from,
|
|
1134
|
+
to,
|
|
1135
|
+
timeZoneContext,
|
|
1136
|
+
});
|
|
1137
|
+
json(res, { from, to, ...fallback });
|
|
1138
|
+
return true;
|
|
1139
|
+
}
|
|
1140
|
+
json(res, { from, to, ...result });
|
|
1141
|
+
} catch (e) {
|
|
1142
|
+
console.error("[LocalAPI] usage-category-breakdown(codex):", e?.message || e);
|
|
1143
|
+
json(res, { from, to, ...unsupportedCategoryPayload("codex"), error: "compute_failed" }, 500);
|
|
1144
|
+
}
|
|
1145
|
+
return true;
|
|
1025
1146
|
}
|
|
1147
|
+
|
|
1148
|
+
json(res, { from, to, ...unsupportedCategoryPayload(requestedSource) });
|
|
1026
1149
|
return true;
|
|
1027
1150
|
}
|
|
1028
1151
|
|