tokentracker-cli 0.63.0 → 0.64.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/{ActivityHeatmap-CkJIcWzw.js → ActivityHeatmap-DjMtMPit.js} +1 -1
- package/dashboard/dist/assets/{Card-yLBo3TPK.js → Card-CD9YpCAv.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-kR7KrvS7.js → DashboardPage-Djhg-yJL.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-jh6HO_Sr.js → DevicePage-DA74Sryo.js} +1 -1
- package/dashboard/dist/assets/{DialogTitle-D9Ik_gvc.js → DialogTitle-DDp9MHUJ.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-C4EDHmX4.js → FadeIn-CBspmJ4G.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-CJ1KBbIb.js → HeaderGithubStar-BDgq5Gx4.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-vMPzCKhT.js → IpCheckPage-L1GKKx8L.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-CPXGM_d3.js → LandingPage-BxI6zHR6.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardAvatar-DF8a3ppM.js → LeaderboardAvatar-DHKVlkOF.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-D4SbAwT8.js → LeaderboardPage-C8JB9MuB.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfileModal-BG9JVFBq.js → LeaderboardProfileModal-CpciUHf2.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfilePage-BMd6sNT9.js → LeaderboardProfilePage-c2Pg5hum.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-DukMAnn1.js → LimitsPage-DkqHHv2V.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-DrmW8xfr.js → LocalOnlyNotice-CVAJM9pw.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-3i9PG3UX.js → LoginPage-L9n2F1t8.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-BhGTdXgG.js → PopoverPopup-B883Co46.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-ClHd4Qcj.js → ResetPasswordPage-dcb-XQ_8.js} +1 -1
- package/dashboard/dist/assets/{Select-DFu3_H6P.js → Select-Dn_eH-Cb.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-fc4n0xEf.js → SelectItemText-BBymhOah.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-DYuS-mL2.js → SettingsPage-DpP5jrlC.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-Bq4GiK2C.js → SkillsPage-BKBEMpDa.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-DtVlysKw.js → WidgetsPage-ByTWGppP.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-BoTb94i8.js → WrappedPage-BzBYot91.js} +1 -1
- package/dashboard/dist/assets/{agent-logos-CWH1ZjEy.js → agent-logos-7x6sZdXn.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-Dz-ejaM3.js → arrow-up-right-NtrFTgFM.js} +1 -1
- package/dashboard/dist/assets/{download-BwyTu0h1.js → download-DBI1zmF1.js} +1 -1
- package/dashboard/dist/assets/{info-r1_Ohszh.js → info-WyXjj_mj.js} +1 -1
- package/dashboard/dist/assets/{main-B8THj1x9.js → main-sjN9-3PX.js} +2 -2
- package/dashboard/dist/assets/{pencil-DWftrgh9.js → pencil-zlgm1deI.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-DhH4ucKB.js → use-limits-display-prefs-D_3UqeaO.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-CE-ExJHY.js → use-native-settings-BIZTMAe_.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-BWqgtMqj.js → use-usage-limits-DyrBGYy1.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-Cg2lR7Uw.js → useCurrency-BJEllMZE.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-DVYU0_fs.js → useScrollLock-Bim1sAXp.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dashboard/dist/share.html +1 -1
- package/package.json +4 -2
- package/src/lib/opencode-go-limits.js +253 -20
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +44 -6
- package/src/lib/skills-manager.js +2 -2
- package/src/lib/sqlite-reader.js +59 -0
- package/src/lib/usage-limits.js +4 -4
package/src/lib/rollout.js
CHANGED
|
@@ -147,9 +147,26 @@ async function parseRolloutIncremental({
|
|
|
147
147
|
const key = filePath;
|
|
148
148
|
const prev = cursors.files[key] || null;
|
|
149
149
|
const inode = st.ino || 0;
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
const
|
|
150
|
+
const sameInode = prev && prev.inode === inode;
|
|
151
|
+
const prevOffset = sameInode ? prev.offset || 0 : 0;
|
|
152
|
+
const truncated = sameInode && prevOffset > st.size;
|
|
153
|
+
const startOffset = sameInode && !truncated ? prevOffset : 0;
|
|
154
|
+
const lastTotal = sameInode && !truncated ? prev.lastTotal || null : null;
|
|
155
|
+
const lastModel = sameInode && !truncated ? prev.lastModel || null : null;
|
|
156
|
+
|
|
157
|
+
if (!projectEnabled && sameInode && !truncated && startOffset >= st.size) {
|
|
158
|
+
if (cb) {
|
|
159
|
+
cb({
|
|
160
|
+
index: idx + 1,
|
|
161
|
+
total: totalFiles,
|
|
162
|
+
filePath,
|
|
163
|
+
filesProcessed,
|
|
164
|
+
eventsAggregated,
|
|
165
|
+
bucketsQueued: touchedBuckets.size,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
153
170
|
|
|
154
171
|
const projectContext = projectEnabled
|
|
155
172
|
? await resolveProjectContextForFile({
|
|
@@ -165,6 +182,7 @@ async function parseRolloutIncremental({
|
|
|
165
182
|
|
|
166
183
|
const result = await parseRolloutFile({
|
|
167
184
|
filePath,
|
|
185
|
+
fileStat: st,
|
|
168
186
|
startOffset,
|
|
169
187
|
lastTotal,
|
|
170
188
|
lastModel,
|
|
@@ -267,7 +285,24 @@ async function parseClaudeIncremental({
|
|
|
267
285
|
const key = filePath;
|
|
268
286
|
const prev = cursors.files[key] || null;
|
|
269
287
|
const inode = st.ino || 0;
|
|
270
|
-
const
|
|
288
|
+
const sameInode = prev && prev.inode === inode;
|
|
289
|
+
const prevOffset = sameInode ? prev.offset || 0 : 0;
|
|
290
|
+
const truncated = sameInode && prevOffset > st.size;
|
|
291
|
+
const startOffset = sameInode && !truncated ? prevOffset : 0;
|
|
292
|
+
|
|
293
|
+
if (!projectEnabled && sameInode && !truncated && startOffset >= st.size) {
|
|
294
|
+
if (cb) {
|
|
295
|
+
cb({
|
|
296
|
+
index: idx + 1,
|
|
297
|
+
total: totalFiles,
|
|
298
|
+
filePath,
|
|
299
|
+
filesProcessed,
|
|
300
|
+
eventsAggregated,
|
|
301
|
+
bucketsQueued: touchedBuckets.size,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
271
306
|
|
|
272
307
|
const projectContext = projectEnabled
|
|
273
308
|
? await resolveProjectContextForFile({
|
|
@@ -283,6 +318,7 @@ async function parseClaudeIncremental({
|
|
|
283
318
|
|
|
284
319
|
const result = await parseClaudeFile({
|
|
285
320
|
filePath,
|
|
321
|
+
fileStat: st,
|
|
286
322
|
startOffset,
|
|
287
323
|
hourlyState,
|
|
288
324
|
touchedBuckets,
|
|
@@ -770,6 +806,7 @@ function codexSessionIdFromPath(filePath) {
|
|
|
770
806
|
|
|
771
807
|
async function parseRolloutFile({
|
|
772
808
|
filePath,
|
|
809
|
+
fileStat,
|
|
773
810
|
startOffset,
|
|
774
811
|
lastTotal,
|
|
775
812
|
lastModel,
|
|
@@ -786,7 +823,7 @@ async function parseRolloutFile({
|
|
|
786
823
|
seenCodexEvents,
|
|
787
824
|
sessionId,
|
|
788
825
|
}) {
|
|
789
|
-
const st = await fs.stat(filePath);
|
|
826
|
+
const st = fileStat || (await fs.stat(filePath));
|
|
790
827
|
const endOffset = st.size;
|
|
791
828
|
if (startOffset >= endOffset) {
|
|
792
829
|
return { endOffset, lastTotal, lastModel, eventsAggregated: 0 };
|
|
@@ -926,6 +963,7 @@ async function parseRolloutFile({
|
|
|
926
963
|
|
|
927
964
|
async function parseClaudeFile({
|
|
928
965
|
filePath,
|
|
966
|
+
fileStat,
|
|
929
967
|
startOffset,
|
|
930
968
|
hourlyState,
|
|
931
969
|
touchedBuckets,
|
|
@@ -936,7 +974,7 @@ async function parseClaudeFile({
|
|
|
936
974
|
projectKey,
|
|
937
975
|
seenMessageHashes,
|
|
938
976
|
}) {
|
|
939
|
-
const st = await fs.stat(filePath).catch(() => null);
|
|
977
|
+
const st = fileStat || (await fs.stat(filePath).catch(() => null));
|
|
940
978
|
if (!st || !st.isFile()) return { endOffset: startOffset, eventsAggregated: 0 };
|
|
941
979
|
|
|
942
980
|
const endOffset = st.size;
|
|
@@ -577,8 +577,8 @@ function targetSkillPath(baseDir, directory) {
|
|
|
577
577
|
const targetPath = path.resolve(root, safe);
|
|
578
578
|
if (!pathStrictlyWithin(root, targetPath)) return null;
|
|
579
579
|
try {
|
|
580
|
-
const rootStat = fs.
|
|
581
|
-
if (
|
|
580
|
+
const rootStat = fs.statSync(root);
|
|
581
|
+
if (!rootStat.isDirectory()) return null;
|
|
582
582
|
} catch (e) {
|
|
583
583
|
if (e?.code !== "ENOENT") return null;
|
|
584
584
|
}
|
package/src/lib/sqlite-reader.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const cp = require("node:child_process");
|
|
2
2
|
const fssync = require("node:fs");
|
|
3
|
+
const { promisify } = require("node:util");
|
|
3
4
|
|
|
4
5
|
const warnedSqliteReadFailures = new Set();
|
|
5
6
|
|
|
@@ -116,6 +117,63 @@ function readSqliteJsonRows(dbPath, sql, options = {}) {
|
|
|
116
117
|
return [];
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
async function readSqliteRowsWithCliAsync(dbPath, sql, { execFile, timeout, maxBuffer }) {
|
|
121
|
+
const { stdout } = await execFile("sqlite3", ["-json", dbPath, sql], {
|
|
122
|
+
encoding: "utf8",
|
|
123
|
+
maxBuffer,
|
|
124
|
+
timeout,
|
|
125
|
+
});
|
|
126
|
+
if (!stdout || !stdout.trim()) return [];
|
|
127
|
+
const rows = JSON.parse(stdout);
|
|
128
|
+
return Array.isArray(rows) ? rows : [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Async twin of readSqliteJsonRows for hot paths that must not block the event
|
|
132
|
+
// loop (e.g. the usage-limits poll — see the "limits 路径 spawnSync 冻结全端点"
|
|
133
|
+
// lesson). The CLI path runs via async execFile; the node:sqlite fallback is
|
|
134
|
+
// synchronous (no async API exists), but it only runs when the sqlite3 CLI is
|
|
135
|
+
// absent — uncommon on macOS/Linux, where the async path keeps the loop free.
|
|
136
|
+
async function readSqliteJsonRowsAsync(dbPath, sql, options = {}) {
|
|
137
|
+
if (!dbPath || !sql) return [];
|
|
138
|
+
try {
|
|
139
|
+
if (!fssync.existsSync(dbPath)) return [];
|
|
140
|
+
} catch (_e) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
const execFile = options.execFile || promisify(cp.execFile);
|
|
144
|
+
const requireFn = options.requireFn || require;
|
|
145
|
+
const env = options.env || process.env;
|
|
146
|
+
const timeout = Number.isFinite(options.timeout) ? options.timeout : 30_000;
|
|
147
|
+
const maxBuffer = Number.isFinite(options.maxBuffer) ? options.maxBuffer : 50 * 1024 * 1024;
|
|
148
|
+
const label = options.label || "local";
|
|
149
|
+
|
|
150
|
+
let cliError = null;
|
|
151
|
+
try {
|
|
152
|
+
return await readSqliteRowsWithCliAsync(dbPath, sql, { execFile, timeout, maxBuffer });
|
|
153
|
+
} catch (err) {
|
|
154
|
+
cliError = err;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let nodeSqliteError = null;
|
|
158
|
+
try {
|
|
159
|
+
return readSqliteRowsWithNode(dbPath, sql, { requireFn });
|
|
160
|
+
} catch (err) {
|
|
161
|
+
nodeSqliteError = err;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (isSqliteCliUnavailable(cliError) && isNodeSqliteUnavailable(nodeSqliteError)) {
|
|
165
|
+
warnSqliteUnavailable({
|
|
166
|
+
dbPath,
|
|
167
|
+
label,
|
|
168
|
+
cliError,
|
|
169
|
+
nodeSqliteError,
|
|
170
|
+
env,
|
|
171
|
+
stderr: options.stderr,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
|
|
119
177
|
function readSqliteFirstValue(dbPath, sql, column, options = {}) {
|
|
120
178
|
const rows = readSqliteJsonRows(dbPath, sql, options);
|
|
121
179
|
const row = rows[0];
|
|
@@ -131,6 +189,7 @@ function resetSqliteReaderWarningsForTests() {
|
|
|
131
189
|
|
|
132
190
|
module.exports = {
|
|
133
191
|
readSqliteJsonRows,
|
|
192
|
+
readSqliteJsonRowsAsync,
|
|
134
193
|
readSqliteFirstValue,
|
|
135
194
|
resetSqliteReaderWarningsForTests,
|
|
136
195
|
};
|
package/src/lib/usage-limits.js
CHANGED
|
@@ -2477,10 +2477,10 @@ async function fetchUsageLimitsUncached({
|
|
|
2477
2477
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
2478
2478
|
withProviderTimeout(fetchZcodeLimits({ home, env, fetchImpl: providerFetch }), "ZCode", providerTimeoutMs)
|
|
2479
2479
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
2480
|
-
// OpenCode Go
|
|
2481
|
-
//
|
|
2482
|
-
// src/lib/opencode-go-limits.js
|
|
2483
|
-
withProviderTimeout(fetchOpencodeGoLimits({ env, fetchImpl: providerFetch }), "OpenCode Go", providerTimeoutMs)
|
|
2480
|
+
// OpenCode Go: local opencode.db cost-vs-dollar-cap estimate by default
|
|
2481
|
+
// (auth-free, zero-config), upgraded to the exact server-side scrape when an
|
|
2482
|
+
// OPENCODE_GO_AUTH_COOKIE is set. See src/lib/opencode-go-limits.js.
|
|
2483
|
+
withProviderTimeout(fetchOpencodeGoLimits({ home, env, fetchImpl: providerFetch }), "OpenCode Go", providerTimeoutMs)
|
|
2484
2484
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
2485
2485
|
]);
|
|
2486
2486
|
|