tokentracker-cli 0.79.9 → 0.80.1
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-B1WOPlu0.js → AchievementBadge-D617bvS9.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-9kHEQicS.js → AchievementsPage-mzE76Ah9.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-Dw05PYPr.js → AchievementsSection-8CYGBoPJ.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-DaWgiijJ.js → BadgeDetailModal-DM3veVmW.js} +1 -1
- package/dashboard/dist/assets/{Card-DYhrLLM4.js → Card-DWONuizy.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-BLy2LUKz.js → ClawdAnimated-CGQXyWuH.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-CWYqfht3.js → CommunityStatsModal-B5yDmJ0o.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-DcE2C24Y.js → ConfirmModal-d4wpsMPW.js} +1 -1
- package/dashboard/dist/assets/{Controls-CI7qw0-b.js → Controls-CMSqknaB.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-CAlgaBa7.js → DashboardPage-Cw6lmVSg.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-DinOyaeN.js → DevicePage-CsPSjSLH.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-CjfSDrLo.js → DialogClose-Cbs-z783.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-B0fmBJxQ.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-f7gNmCca.js → DialogTitle-C4mJiIQW.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-D_5w0Qh0.js → FadeIn-xOJwCmZ8.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-DTZyNKyL.js → HeaderGithubStar-oRz4rfC8.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-D8CViF98.js → IpCheckPage-CTwL-Zmz.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-CqN5KEjV.js → LandingPage-CqYJ3sZh.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardAvatar-CwUVO4wn.js → LeaderboardAvatar-CuF6Kzkj.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-B12HJ9LA.js → LeaderboardPage-BvOPIj-b.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-DFzPpsnV.js → LeaderboardProfileModal-DVXuKkRN.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-Z0ZYpNFd.js → LeaderboardProfilePage-RE1CPqzM.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-BpwioIa-.js → LimitsPage-BovkRgac.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-Covi6zdt.js → LocalOnlyNotice-CTFFU_ip.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-CRqbhwCx.js → LoginPage-mguBCTBZ.js} +1 -1
- package/dashboard/dist/assets/{PetPage-BY_yObVj.js → PetPage-C5KLH6Fm.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-B2dE3Ary.js → PopoverPopup-CLDh5yIk.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-C8IEJbVc.js → ResetPasswordPage-DnhgHQrV.js} +1 -1
- package/dashboard/dist/assets/{Select-BmRLYSqA.js → Select-DPSaPIlz.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-FC46bk8b.js → SelectItemText-jIBbXpqi.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-DipzOQVg.js → SettingsPage-BK0IqSjg.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-CziypUTf.js → SkillsPage-BQNoMpL2.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-CJegJhVR.js → WidgetsPage-308d8icu.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-DcMiKvzf.js → WrappedPage-T720sQ9S.js} +1 -1
- package/dashboard/dist/assets/{agent-logos-S7bF1LwW.js → agent-logos-Blo5C96d.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-D0yeL56y.js → arrow-up-right-DKz2Ua6U.js} +1 -1
- package/dashboard/dist/assets/check-fF6lQGN-.js +1 -0
- package/dashboard/dist/assets/{copy-D-z9ZtIu.js → copy-DcUFG0PD.js} +1 -1
- package/dashboard/dist/assets/{download-Dwxnd3QG.js → download-CNK1wtxV.js} +1 -1
- package/dashboard/dist/assets/{flame-Bdqk9A75.js → flame-BEhJZRaZ.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-DNVcCRwm.js → format-tokens-Bsfbd8nj.js} +1 -1
- package/dashboard/dist/assets/{info-CMLT6oUI.js → info-DRJLv-aV.js} +1 -1
- package/dashboard/dist/assets/{link-2-BmiHu726.js → link-2-C0GdaANY.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-CXVUQtzm.js → loader-circle-F9ymYeor.js} +1 -1
- package/dashboard/dist/assets/{main-B9m79io-.js → main-CThKxvKx.js} +3 -3
- package/dashboard/dist/assets/{provider-display-BoAesdke.js → provider-display-D4NdFjHN.js} +1 -1
- package/dashboard/dist/assets/{trash-2-C9Rh2DAL.js → trash-2-D9vulGMW.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-aZwYxrXR.js → use-community-stats-BU4dXEOM.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-tJKR83RT.js → use-limits-display-prefs-Bx2VJhwl.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-PjfJPK5v.js → use-native-settings-BSXaxaTC.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-D1QFmZUY.js → use-ordered-list-OA0HwwEL.js} +1 -1
- package/dashboard/dist/assets/{use-quality-per-dollar-pref-4N3Su4wC.js → use-quality-per-dollar-pref-Bqooc4FA.js} +1 -1
- package/dashboard/dist/assets/{use-transform-D9nurInL.js → use-transform-CZ9FdRGw.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-DapTpi_6.js → use-usage-limits-Ct_A4wTr.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-B0DH9ZZA.js → useCurrency-D4bvdaFB.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-DijV6DYS.js → useScrollLock-ZsWO-GoL.js} +1 -1
- package/dashboard/dist/assets/useTokenFormat-B3huMEws.js +1 -0
- package/dashboard/dist/assets/{zap-BVfhR3Ck.js → zap-C9Mp-GNU.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +1 -1
- package/src/commands/init.js +607 -6
- package/src/commands/sync.js +176 -7
- package/src/lib/codex-config.js +135 -40
- package/src/lib/codex-context-breakdown.js +123 -43
- package/src/lib/codex-rollout-parser.js +329 -32
- package/src/lib/local-api.js +11 -5
- package/src/lib/openclaw-session-plugin.js +13 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +230 -10
- package/src/lib/usage-limits.js +9 -5
- package/dashboard/dist/assets/DialogDescription-DWs-KIUA.js +0 -1
- package/dashboard/dist/assets/check-Dn9BLYEf.js +0 -1
- package/dashboard/dist/assets/useTokenFormat-nxdG6gi9.js +0 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
"use strict";
|
|
12
12
|
|
|
13
|
-
const
|
|
13
|
+
const crypto = require("node:crypto");
|
|
14
14
|
const os = require("node:os");
|
|
15
15
|
const path = require("node:path");
|
|
16
16
|
|
|
@@ -25,8 +25,8 @@ const {
|
|
|
25
25
|
|
|
26
26
|
const {
|
|
27
27
|
parseCodexRolloutFile,
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
discoverCodexSessionFiles,
|
|
29
|
+
rolloutSessionIdFromPath,
|
|
30
30
|
finalizeToolRows,
|
|
31
31
|
finalizeSkillRows,
|
|
32
32
|
finalizeExecRows,
|
|
@@ -120,25 +120,55 @@ function buildDateRange({ period, date }) {
|
|
|
120
120
|
// ---------------------------------------------------------------------------
|
|
121
121
|
|
|
122
122
|
const CACHE = new Map();
|
|
123
|
+
const PARSED_GROUP_CACHE = new Map();
|
|
123
124
|
const CACHE_TTL_MS = 60_000;
|
|
124
|
-
const CACHE_SCHEMA_VERSION = "codex-context-
|
|
125
|
-
|
|
126
|
-
function maxMtimeMs(files) {
|
|
127
|
-
let max = 0;
|
|
128
|
-
for (const filePath of files) {
|
|
129
|
-
try {
|
|
130
|
-
const st = fs.statSync(filePath);
|
|
131
|
-
if (st.mtimeMs > max) max = st.mtimeMs;
|
|
132
|
-
} catch {}
|
|
133
|
-
}
|
|
134
|
-
return max;
|
|
135
|
-
}
|
|
125
|
+
const CACHE_SCHEMA_VERSION = "codex-context-v4";
|
|
126
|
+
const MAX_PARSED_GROUP_CACHE_ENTRIES = 4096;
|
|
136
127
|
|
|
137
128
|
function cacheTimeZoneKey(timeZoneContext) {
|
|
138
129
|
if (!timeZoneContext) return "";
|
|
139
130
|
return `${timeZoneContext.timeZone || ""}|${Number.isFinite(timeZoneContext.offsetMinutes) ? timeZoneContext.offsetMinutes : ""}`;
|
|
140
131
|
}
|
|
141
132
|
|
|
133
|
+
function statIdentity(filePath, stat) {
|
|
134
|
+
return JSON.stringify([filePath, stat.size, stat.mtimeMs, stat.ctimeMs, stat.ino]);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function inventorySignature(entries) {
|
|
138
|
+
const hash = crypto.createHash("sha256");
|
|
139
|
+
for (const { filePath, stat, candidate } of entries) {
|
|
140
|
+
hash.update(statIdentity(filePath, stat));
|
|
141
|
+
hash.update(candidate ? "1" : "0");
|
|
142
|
+
hash.update("\0");
|
|
143
|
+
}
|
|
144
|
+
return hash.digest("hex");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function parsedGroupCacheKey(entries, { from, to, timeZoneContext }) {
|
|
148
|
+
const hash = crypto.createHash("sha256");
|
|
149
|
+
hash.update(CACHE_SCHEMA_VERSION);
|
|
150
|
+
hash.update(from || "");
|
|
151
|
+
hash.update("\0");
|
|
152
|
+
hash.update(to || "");
|
|
153
|
+
hash.update("\0");
|
|
154
|
+
hash.update(cacheTimeZoneKey(timeZoneContext));
|
|
155
|
+
for (const { filePath, stat } of entries) {
|
|
156
|
+
hash.update(statIdentity(filePath, stat));
|
|
157
|
+
hash.update("\0");
|
|
158
|
+
}
|
|
159
|
+
return hash.digest("hex");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function rememberParsedGroup(key, value) {
|
|
163
|
+
PARSED_GROUP_CACHE.delete(key);
|
|
164
|
+
PARSED_GROUP_CACHE.set(key, value);
|
|
165
|
+
while (PARSED_GROUP_CACHE.size > MAX_PARSED_GROUP_CACHE_ENTRIES) {
|
|
166
|
+
const oldest = PARSED_GROUP_CACHE.keys().next().value;
|
|
167
|
+
if (!oldest) break;
|
|
168
|
+
PARSED_GROUP_CACHE.delete(oldest);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
142
172
|
// ---------------------------------------------------------------------------
|
|
143
173
|
// Main entry
|
|
144
174
|
// ---------------------------------------------------------------------------
|
|
@@ -151,6 +181,9 @@ async function computeCodexContextBreakdown({
|
|
|
151
181
|
codexDir = null,
|
|
152
182
|
top = 20,
|
|
153
183
|
timeZoneContext = null,
|
|
184
|
+
exhaustive = false,
|
|
185
|
+
nowMs = Date.now(),
|
|
186
|
+
includeDiagnostics = false,
|
|
154
187
|
} = {}) {
|
|
155
188
|
let fromKey = from;
|
|
156
189
|
let toKey = to;
|
|
@@ -160,10 +193,33 @@ async function computeCodexContextBreakdown({
|
|
|
160
193
|
toKey = range?.to || null;
|
|
161
194
|
}
|
|
162
195
|
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
196
|
+
const codexHome = process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
|
|
197
|
+
const roots = codexDir
|
|
198
|
+
? [codexDir]
|
|
199
|
+
: [path.join(codexHome, "sessions"), path.join(codexHome, "archived_sessions")];
|
|
200
|
+
const baseDir = roots.join(path.delimiter);
|
|
201
|
+
const diagnostics = {
|
|
202
|
+
cache_hit: false,
|
|
203
|
+
full_metadata_audit: false,
|
|
204
|
+
discovered_files: 0,
|
|
205
|
+
candidate_files: 0,
|
|
206
|
+
stat_calls: 0,
|
|
207
|
+
metadata_cache_hits: 0,
|
|
208
|
+
opened_files: 0,
|
|
209
|
+
parsed_files: 0,
|
|
210
|
+
parse_cache_hits: 0,
|
|
211
|
+
json_parse_calls: 0,
|
|
212
|
+
};
|
|
213
|
+
const discovered = discoverCodexSessionFiles(roots, {
|
|
214
|
+
from: fromKey,
|
|
215
|
+
to: toKey,
|
|
216
|
+
timeZoneContext,
|
|
217
|
+
exhaustive,
|
|
218
|
+
nowMs,
|
|
219
|
+
diagnostics,
|
|
220
|
+
});
|
|
221
|
+
const candidates = discovered.filter((entry) => entry.candidate);
|
|
222
|
+
const fileSignature = inventorySignature(discovered);
|
|
167
223
|
const cacheKey = [
|
|
168
224
|
CACHE_SCHEMA_VERSION,
|
|
169
225
|
baseDir,
|
|
@@ -171,24 +227,48 @@ async function computeCodexContextBreakdown({
|
|
|
171
227
|
toKey || "",
|
|
172
228
|
cacheTimeZoneKey(timeZoneContext),
|
|
173
229
|
Number.isFinite(top) ? top : 20,
|
|
174
|
-
|
|
175
|
-
|
|
230
|
+
exhaustive ? "exhaustive" : "bounded",
|
|
231
|
+
fileSignature,
|
|
176
232
|
].join("|");
|
|
177
233
|
const cached = CACHE.get(cacheKey);
|
|
178
234
|
if (cached && Date.now() - cached.at < CACHE_TTL_MS) {
|
|
179
|
-
|
|
235
|
+
diagnostics.cache_hit = true;
|
|
236
|
+
return includeDiagnostics ? { ...cached.value, diagnostics } : cached.value;
|
|
180
237
|
}
|
|
181
238
|
|
|
182
239
|
const sessions = [];
|
|
240
|
+
const seenTokenEvents = new Set();
|
|
241
|
+
|
|
242
|
+
const candidateGroups = new Map();
|
|
243
|
+
for (const entry of candidates) {
|
|
244
|
+
const sessionKey = rolloutSessionIdFromPath(entry.filePath) || entry.filePath;
|
|
245
|
+
if (!candidateGroups.has(sessionKey)) candidateGroups.set(sessionKey, []);
|
|
246
|
+
candidateGroups.get(sessionKey).push(entry);
|
|
247
|
+
}
|
|
183
248
|
|
|
184
|
-
for (const
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
from: fromKey,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
249
|
+
for (const entries of candidateGroups.values()) {
|
|
250
|
+
const filePaths = entries.map((entry) => entry.filePath);
|
|
251
|
+
const cacheable = Boolean(rolloutSessionIdFromPath(filePaths[0]));
|
|
252
|
+
const parsedCacheKey = cacheable
|
|
253
|
+
? parsedGroupCacheKey(entries, { from: fromKey, to: toKey, timeZoneContext })
|
|
254
|
+
: null;
|
|
255
|
+
let parsed = parsedCacheKey ? PARSED_GROUP_CACHE.get(parsedCacheKey) : null;
|
|
256
|
+
if (parsed) {
|
|
257
|
+
// Cacheable groups are partitioned by rollout UUID, so their token event
|
|
258
|
+
// keys cannot overlap and cache hits need not backfill seenTokenEvents.
|
|
259
|
+
diagnostics.parse_cache_hits += 1;
|
|
260
|
+
PARSED_GROUP_CACHE.delete(parsedCacheKey);
|
|
261
|
+
PARSED_GROUP_CACHE.set(parsedCacheKey, parsed);
|
|
262
|
+
} else {
|
|
263
|
+
parsed = await parseCodexRolloutFile(filePaths.length === 1 ? filePaths[0] : filePaths, {
|
|
264
|
+
from: fromKey,
|
|
265
|
+
to: toKey,
|
|
266
|
+
timeZoneContext,
|
|
267
|
+
diagnostics,
|
|
268
|
+
seenTokenEvents,
|
|
269
|
+
});
|
|
270
|
+
if (parsedCacheKey) rememberParsedGroup(parsedCacheKey, parsed);
|
|
271
|
+
}
|
|
192
272
|
if (!parsed || !parsed.totals || !parsed.totals.total_tokens) continue;
|
|
193
273
|
sessions.push(parsed);
|
|
194
274
|
}
|
|
@@ -261,26 +341,25 @@ async function computeCodexContextBreakdown({
|
|
|
261
341
|
}))
|
|
262
342
|
.sort((a, b) => (b.totals?.total_tokens || 0) - (a.totals?.total_tokens || 0));
|
|
263
343
|
|
|
264
|
-
const nonTextToolTotal = toolRows.reduce((sum, row) => {
|
|
265
|
-
if ((row.raw_name || row.name) === "text_response") return sum;
|
|
266
|
-
return sum + Number(row.totals?.total_tokens || 0);
|
|
267
|
-
}, 0);
|
|
268
|
-
const displayedMessageTotal = Math.max(
|
|
269
|
-
0,
|
|
270
|
-
Number(grand.total_tokens || 0) - Number(grand.reasoning_output_tokens || 0) - nonTextToolTotal,
|
|
271
|
-
);
|
|
272
344
|
const textResponse = toolRows.find((row) => (row.raw_name || row.name) === "text_response");
|
|
273
345
|
const textResponseTotals = textResponse?.totals || emptyTotals();
|
|
274
346
|
const textResponseHistoryWeight = Math.max(
|
|
275
347
|
0,
|
|
276
348
|
Number(textResponseTotals.cached_input_tokens || 0) + Number(textResponseTotals.cache_creation_input_tokens || 0),
|
|
277
349
|
);
|
|
350
|
+
const textResponseInputWeight = Math.max(0, Number(textResponseTotals.input_tokens || 0));
|
|
351
|
+
const textResponseOutputWeight = Math.max(
|
|
352
|
+
0,
|
|
353
|
+
Number(textResponseTotals.output_tokens || 0) - Number(textResponseTotals.reasoning_output_tokens || 0),
|
|
354
|
+
);
|
|
355
|
+
const displayedMessageTotal =
|
|
356
|
+
textResponseInputWeight + textResponseHistoryWeight + textResponseOutputWeight;
|
|
278
357
|
const messageAlloc = allocateByLargestRemainder(
|
|
279
358
|
displayedMessageTotal,
|
|
280
359
|
{
|
|
281
|
-
user_input:
|
|
360
|
+
user_input: textResponseInputWeight,
|
|
282
361
|
conversation_history: textResponseHistoryWeight,
|
|
283
|
-
assistant_response:
|
|
362
|
+
assistant_response: textResponseOutputWeight,
|
|
284
363
|
},
|
|
285
364
|
["user_input", "conversation_history", "assistant_response"],
|
|
286
365
|
);
|
|
@@ -350,7 +429,7 @@ async function computeCodexContextBreakdown({
|
|
|
350
429
|
scope: "supported",
|
|
351
430
|
breakdown_status: "ok",
|
|
352
431
|
totals: grand,
|
|
353
|
-
session_count: sessions.
|
|
432
|
+
session_count: new Set(sessions.map((session) => session.sessionId || session.filePath)).size,
|
|
354
433
|
message_count: sessions.reduce((a, s) => a + (s.turnCount || 0), 0),
|
|
355
434
|
message_breakdown: {
|
|
356
435
|
categories: messageBreakdown,
|
|
@@ -387,12 +466,13 @@ async function computeCodexContextBreakdown({
|
|
|
387
466
|
},
|
|
388
467
|
};
|
|
389
468
|
|
|
390
|
-
|
|
469
|
+
const cacheValue = { ...result };
|
|
470
|
+
CACHE.set(cacheKey, { at: Date.now(), value: cacheValue });
|
|
391
471
|
while (CACHE.size > 32) {
|
|
392
472
|
const oldest = [...CACHE.entries()].sort((a, b) => a[1].at - b[1].at)[0];
|
|
393
473
|
if (oldest) CACHE.delete(oldest[0]);
|
|
394
474
|
}
|
|
395
|
-
return result;
|
|
475
|
+
return includeDiagnostics ? { ...result, diagnostics } : result;
|
|
396
476
|
}
|
|
397
477
|
|
|
398
478
|
module.exports = {
|