tokentracker-cli 0.84.5 → 0.84.7
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 +10 -8
- package/README.ja.md +9 -7
- package/README.ko.md +9 -7
- package/README.md +12 -10
- package/README.zh-CN.md +9 -7
- package/dashboard/dist/assets/{AchievementBadge-DJvRfvu1.js → AchievementBadge-DAPsTMsx.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-Cr8WToxS.js → AchievementsPage-B9oXfXvm.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-BCPYB46e.js → AchievementsSection-DI_LTZb3.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-D-12Ek-H.js → BadgeDetailModal--WCrJWVa.js} +1 -1
- package/dashboard/dist/assets/Card-BzbSN3EC.js +1 -0
- package/dashboard/dist/assets/{ClawdAnimated-DoGgAppT.js → ClawdAnimated-Dgxae1At.js} +1 -1
- package/dashboard/dist/assets/{CommandPalette-DIKocEAD.js → CommandPalette-BiZBYV5A.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-BNuMbEWy.js → CommunityStatsModal-C6jZx10_.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-F2gPIIS9.js → ConfirmModal-lD-mHMvO.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-YvoCEGG9.js → DashboardPage-DCPNoiRG.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-CbC_J22s.js → DevicePage-DiF2IOjJ.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-VEynQCYg.js → DialogClose-Crx2EFnI.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-CHsHo924.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-BbAVHI_v.js → DialogTitle-amHXttsp.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-CZVqSnis.js → FadeIn-CIhF_9PP.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-Cs_h332Y.js → HeaderGithubStar-D6Ph2GuY.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-DvvHTphK.js → HoverTooltip-BS8eO6tj.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-DPVmqSS_.js → IpCheckPage-Cz1Je6WS.js} +1 -1
- package/dashboard/dist/assets/LandingPage-DqeXJfwn.js +2 -0
- package/dashboard/dist/assets/{LeaderboardAvatar-BAPZ2ROX.js → LeaderboardAvatar-D09yLoVA.js} +1 -1
- package/dashboard/dist/assets/LeaderboardPage-BetpFetS.js +2 -0
- package/dashboard/dist/assets/{LeaderboardProfileModal-r03akfe2.js → LeaderboardProfileModal-UW3KnANZ.js} +4 -4
- package/dashboard/dist/assets/{LeaderboardProfilePage-CU63YW2M.js → LeaderboardProfilePage-Chd_2AVY.js} +1 -1
- package/dashboard/dist/assets/LimitsPage-uhpNteXJ.js +4 -0
- package/dashboard/dist/assets/{LocalOnlyNotice-BHlcPCZk.js → LocalOnlyNotice-CpFFX8ro.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-C-dqUumR.js → LoginCard-DkZpGnVu.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-BFzRg4Iy.js → LoginModal-CALv6jkD.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-QtlnGF1S.js → LoginPage-BZuXHYAT.js} +1 -1
- package/dashboard/dist/assets/PetPage-C1LuDyYr.js +1 -0
- package/dashboard/dist/assets/{PopoverPopup-CltmqcrT.js → PopoverPopup-CluVhrMr.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-BqOI9EiD.js → ProviderIcon-D3YKjVKb.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-BsfCBUZD.js → ResetPasswordPage-CzN50nX5.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-D4biXw_Q.js → SegmentedControl-DFOAcEKU.js} +1 -1
- package/dashboard/dist/assets/{Select-DTw-14iE.js → Select-B3W_ihs_.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-3tUrnu3f.js → SelectItemText-FXRtXnFV.js} +1 -1
- package/dashboard/dist/assets/ServiceStatusPage-BItZqH7q.js +1 -0
- package/dashboard/dist/assets/{SessionsPage-DYYlNqHg.js → SessionsPage-DVQU-hTH.js} +2 -2
- package/dashboard/dist/assets/SettingsPage-ByvrwOi6.js +1 -0
- package/dashboard/dist/assets/SkillsPage-DrGr5Qij.js +1 -0
- package/dashboard/dist/assets/{TokenGalaxy-DU77e8sM.js → TokenGalaxy-ClF_n9od.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-DV3KGf-a.js → ToolbarRootContext-B82hGhAf.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-D6QYKmbl.js → TrendMonitor-DkWm7_1z.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-DSP4jCsH.js → WidgetsPage-DCY4pyR2.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-B0x6O_DU.js → WrappedPage-yGQ4DLqj.js} +1 -1
- package/dashboard/dist/assets/__vite-browser-external-BdRrPLk6.js +1483 -0
- package/dashboard/dist/assets/__vite-browser-external-hXV_ZYTG.css +1 -0
- package/dashboard/dist/assets/{agent-logos-B2S_cdOL.js → agent-logos-D5SHGOxB.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-DNUVuhx2.js → arrow-up-right-CbMcAcss.js} +1 -1
- package/dashboard/dist/assets/{check-C3ARiiE_.js → check-Dyzh7lTz.js} +1 -1
- package/dashboard/dist/assets/{chevron-right-3bY7H8jO.js → chevron-right-DT06ZIKC.js} +1 -1
- package/dashboard/dist/assets/{copy-C-UIMKoO.js → copy-B3Kt3Wrf.js} +1 -1
- package/dashboard/dist/assets/{download-DtRzJfcr.js → download-B3rOytqI.js} +1 -1
- package/dashboard/dist/assets/external-link-BamTP0Ks.js +1 -0
- package/dashboard/dist/assets/{flame-Bas3ry-g.js → flame-msy2h1ms.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-DFtRUIH8.js → format-tokens-8b1OUM_8.js} +1 -1
- package/dashboard/dist/assets/{icons-CHBt4Tmo.js → icons-C2NR2_Tf.js} +1 -1
- package/dashboard/dist/assets/{index-CZRlrK7w.js → index-C8sDJzUY.js} +1 -1
- package/dashboard/dist/assets/{index-C1ADnvzm.js → index-CvTfpiCF.js} +1 -1
- package/dashboard/dist/assets/{index-4unZlm2w.js → index-x3vFJQFt.js} +1 -1
- package/dashboard/dist/assets/{info-BkrO-fg3.js → info-C9j23aGq.js} +1 -1
- package/dashboard/dist/assets/limits-providers-ySB9Ci5l.js +1 -0
- package/dashboard/dist/assets/{link-2-DTLFz8uG.js → link-2-rrcyTT6S.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-BqQW_Ipq.js → loader-circle-x9x9I8Hv.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-YdpeE4dq.js → maximize-2-7TWFb2k7.js} +1 -1
- package/dashboard/dist/assets/{provider-display-CgBOpjq0.js → provider-display-JbSwpvxU.js} +1 -1
- package/dashboard/dist/assets/{react-DD9jpv--.js → react-DK5clHtY.js} +1 -1
- package/dashboard/dist/assets/{search--TvX-fig.js → search-DukXRvEV.js} +1 -1
- package/dashboard/dist/assets/{skills-api-C5C8a1at.js → skills-api-BUFJuwiR.js} +1 -1
- package/dashboard/dist/assets/{store-CRA8gPnP.js → store-BTh7bv09.js} +1 -1
- package/dashboard/dist/assets/{terminal-BXZyl2ek.js → terminal-CcUqLtn1.js} +1 -1
- package/dashboard/dist/assets/{trash-2-IFdBQ65v.js → trash-2-Bq7hnvNq.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-LyJ5aMpX.js → use-community-stats-qTpx6ugG.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-CKvFS1Nn.js → use-limits-display-prefs-Di_J4eVv.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-Cg-4j_0z.js → use-native-settings-CIqpv9Z3.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-2pX5PXZO.js → use-ordered-list-OwogSXT7.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-5QGGPoom.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-DilJOODA.js → use-session-efficiency-pref-CjAvMh7u.js} +1 -1
- package/dashboard/dist/assets/{use-transform-DiyYTLpI.js → use-transform-KZLdt-NZ.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-DkUmp_nW.js → use-usage-limits-Tbifa037.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-lm7KjGoD.js → useCurrency-D2td-bkn.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-DVSyJ-GE.js → useScrollLock-Cvyfyezc.js} +1 -1
- package/dashboard/dist/assets/useTokenFormat-DYIUS6IH.js +1 -0
- package/dashboard/dist/assets/{zap-CKZt1_i5.js → zap-B19mEed5.js} +1 -1
- package/dashboard/dist/brand-logos/qoder.svg +5 -0
- package/dashboard/dist/index.html +18 -15
- package/dashboard/dist/ip-check.html +2 -2
- package/dashboard/dist/leaderboard.html +2 -2
- package/dashboard/dist/llms.txt +3 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +2 -2
- package/src/commands/init.js +1 -0
- package/src/commands/status.js +34 -7
- package/src/commands/sync.js +353 -5
- package/src/lib/codex-rollout-parser.js +17 -39
- package/src/lib/codex-token-usage.js +195 -0
- package/src/lib/local-api.js +4 -1
- package/src/lib/pet-packages.js +44 -2
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/provider-status.js +104 -0
- package/src/lib/qoder-limits.js +985 -0
- package/src/lib/rollout.js +744 -91
- package/src/lib/usage-limits.js +243 -43
- package/dashboard/dist/assets/Card-Ha3x9zIj.js +0 -1
- package/dashboard/dist/assets/DialogDescription-B9bb9Ar0.js +0 -1
- package/dashboard/dist/assets/LandingPage-BCvNh3zE.js +0 -2
- package/dashboard/dist/assets/LeaderboardPage-DZSxazHP.js +0 -2
- package/dashboard/dist/assets/LimitsPage-JWZDa5_Y.js +0 -4
- package/dashboard/dist/assets/PetPage-C6UMY2qD.js +0 -1
- package/dashboard/dist/assets/SettingsPage-CYlEboSl.js +0 -1
- package/dashboard/dist/assets/SkillsPage-Bzq8V5Pd.js +0 -1
- package/dashboard/dist/assets/__vite-browser-external-D3llGq6p.js +0 -1465
- package/dashboard/dist/assets/__vite-browser-external-WKilYZnq.css +0 -1
- package/dashboard/dist/assets/limits-providers-BtwYmYHA.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-BCR01kRg.js +0 -1
- package/dashboard/dist/assets/useTokenFormat-Li8BANKO.js +0 -1
package/src/lib/usage-limits.js
CHANGED
|
@@ -27,6 +27,8 @@ const {
|
|
|
27
27
|
const { fetchGrokLimits } = require("./grok-limits");
|
|
28
28
|
const { fetchZcodeLimits } = require("./zcode-limits");
|
|
29
29
|
const { fetchOpencodeGoLimits } = require("./opencode-go-limits");
|
|
30
|
+
const { fetchQoderLimits } = require("./qoder-limits");
|
|
31
|
+
const { fetchProviderServiceStatus } = require("./provider-status");
|
|
30
32
|
const { readSqliteJsonRows, readSqliteJsonRowsAsync } = require("./sqlite-reader");
|
|
31
33
|
|
|
32
34
|
const execFileAsync = promisify(cp.execFile);
|
|
@@ -1222,11 +1224,24 @@ function runCommand(commandRunner, command, args, options = {}) {
|
|
|
1222
1224
|
return Promise.resolve(commandRunner(command, args, merged));
|
|
1223
1225
|
}
|
|
1224
1226
|
|
|
1225
|
-
const {
|
|
1227
|
+
const {
|
|
1228
|
+
timeout,
|
|
1229
|
+
maxBuffer,
|
|
1230
|
+
completeWhen,
|
|
1231
|
+
completionGraceMs = 250,
|
|
1232
|
+
killProcessGroup = false,
|
|
1233
|
+
...spawnOptions
|
|
1234
|
+
} = merged;
|
|
1226
1235
|
return new Promise((resolve) => {
|
|
1227
1236
|
let child;
|
|
1237
|
+
const useProcessGroup =
|
|
1238
|
+
killProcessGroup && process.platform !== "win32";
|
|
1228
1239
|
try {
|
|
1229
|
-
child = cp.spawn(command, args, {
|
|
1240
|
+
child = cp.spawn(command, args, {
|
|
1241
|
+
...spawnOptions,
|
|
1242
|
+
detached: useProcessGroup || spawnOptions.detached,
|
|
1243
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1244
|
+
});
|
|
1230
1245
|
} catch (error) {
|
|
1231
1246
|
resolve({ status: null, stdout: "", stderr: "", error });
|
|
1232
1247
|
return;
|
|
@@ -1238,12 +1253,14 @@ function runCommand(commandRunner, command, args, options = {}) {
|
|
|
1238
1253
|
let timedOut = false;
|
|
1239
1254
|
let timer = null;
|
|
1240
1255
|
let hardTimer = null;
|
|
1256
|
+
let completionTimer = null;
|
|
1241
1257
|
|
|
1242
1258
|
const settle = ({ status = null, error = null } = {}) => {
|
|
1243
1259
|
if (settled) return;
|
|
1244
1260
|
settled = true;
|
|
1245
1261
|
if (timer) clearTimeout(timer);
|
|
1246
1262
|
if (hardTimer) clearTimeout(hardTimer);
|
|
1263
|
+
if (completionTimer) clearTimeout(completionTimer);
|
|
1247
1264
|
let finalError = error;
|
|
1248
1265
|
if (!finalError && timedOut) {
|
|
1249
1266
|
finalError = new Error(`spawn ${command} ETIMEDOUT`);
|
|
@@ -1254,19 +1271,49 @@ function runCommand(commandRunner, command, args, options = {}) {
|
|
|
1254
1271
|
resolve(result);
|
|
1255
1272
|
};
|
|
1256
1273
|
|
|
1274
|
+
const signalChild = (signal) => {
|
|
1275
|
+
try {
|
|
1276
|
+
if (useProcessGroup && Number.isInteger(child.pid)) {
|
|
1277
|
+
process.kill(-child.pid, signal);
|
|
1278
|
+
} else {
|
|
1279
|
+
child.kill(signal);
|
|
1280
|
+
}
|
|
1281
|
+
} catch (_error) {}
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
const stopChild = ({ timeoutExpired = false } = {}) => {
|
|
1285
|
+
if (settled) return;
|
|
1286
|
+
if (timeoutExpired) timedOut = true;
|
|
1287
|
+
signalChild("SIGTERM");
|
|
1288
|
+
// Guarantee settlement even if the process group ignores SIGTERM or
|
|
1289
|
+
// keeps inherited stdio open.
|
|
1290
|
+
hardTimer = setTimeout(() => {
|
|
1291
|
+
signalChild("SIGKILL");
|
|
1292
|
+
settle({ status: null });
|
|
1293
|
+
}, 1000);
|
|
1294
|
+
if (typeof hardTimer.unref === "function") hardTimer.unref();
|
|
1295
|
+
};
|
|
1296
|
+
|
|
1257
1297
|
if (Number.isFinite(timeout) && timeout > 0) {
|
|
1258
1298
|
timer = setTimeout(() => {
|
|
1259
|
-
|
|
1260
|
-
try { child.kill("SIGTERM"); } catch (_error) {}
|
|
1261
|
-
// Guarantee settlement even if the child ignores SIGTERM or keeps stdio open.
|
|
1262
|
-
hardTimer = setTimeout(() => {
|
|
1263
|
-
try { child.kill("SIGKILL"); } catch (_error) {}
|
|
1264
|
-
settle({ status: null });
|
|
1265
|
-
}, 1000);
|
|
1266
|
-
if (typeof hardTimer.unref === "function") hardTimer.unref();
|
|
1299
|
+
stopChild({ timeoutExpired: true });
|
|
1267
1300
|
}, timeout);
|
|
1268
1301
|
}
|
|
1269
1302
|
|
|
1303
|
+
const scheduleCompletion = () => {
|
|
1304
|
+
if (typeof completeWhen !== "function" || settled) return;
|
|
1305
|
+
let complete = false;
|
|
1306
|
+
try {
|
|
1307
|
+
complete = Boolean(completeWhen(stdout, stderr));
|
|
1308
|
+
} catch (_error) {}
|
|
1309
|
+
if (!complete) return;
|
|
1310
|
+
if (completionTimer) clearTimeout(completionTimer);
|
|
1311
|
+
completionTimer = setTimeout(
|
|
1312
|
+
() => stopChild(),
|
|
1313
|
+
Math.max(0, Number(completionGraceMs) || 0),
|
|
1314
|
+
);
|
|
1315
|
+
};
|
|
1316
|
+
|
|
1270
1317
|
const collect = (stream, append) => {
|
|
1271
1318
|
if (!stream) return;
|
|
1272
1319
|
stream.setEncoding("utf8");
|
|
@@ -1275,9 +1322,11 @@ function runCommand(commandRunner, command, args, options = {}) {
|
|
|
1275
1322
|
if (stdout.length + stderr.length > maxBuffer) {
|
|
1276
1323
|
const error = new Error(`spawn ${command} maxBuffer length exceeded`);
|
|
1277
1324
|
error.code = "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
1278
|
-
|
|
1325
|
+
signalChild("SIGKILL");
|
|
1279
1326
|
settle({ status: null, error });
|
|
1327
|
+
return;
|
|
1280
1328
|
}
|
|
1329
|
+
scheduleCompletion();
|
|
1281
1330
|
});
|
|
1282
1331
|
};
|
|
1283
1332
|
collect(child.stdout, (chunk) => { stdout += chunk; });
|
|
@@ -1324,14 +1373,94 @@ function parseMonthDayResetDate(dateStr, now = new Date()) {
|
|
|
1324
1373
|
return candidate.toISOString();
|
|
1325
1374
|
}
|
|
1326
1375
|
|
|
1376
|
+
function parseKiroResetDate(dateStr, now = new Date()) {
|
|
1377
|
+
if (typeof dateStr !== "string") return null;
|
|
1378
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
|
1379
|
+
const candidate = new Date(`${dateStr}T00:00:00.000Z`);
|
|
1380
|
+
if (
|
|
1381
|
+
Number.isFinite(candidate.getTime()) &&
|
|
1382
|
+
candidate.toISOString().slice(0, 10) === dateStr
|
|
1383
|
+
) {
|
|
1384
|
+
return candidate.toISOString();
|
|
1385
|
+
}
|
|
1386
|
+
return null;
|
|
1387
|
+
}
|
|
1388
|
+
return parseMonthDayResetDate(dateStr, now);
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1327
1391
|
function isKiroUsageOutputComplete(output) {
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1392
|
+
try {
|
|
1393
|
+
parseKiroUsageOutput(output);
|
|
1394
|
+
return true;
|
|
1395
|
+
} catch (_error) {
|
|
1396
|
+
return false;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
function parseKiroCliVersion(output) {
|
|
1401
|
+
const match = String(output || "").match(
|
|
1402
|
+
/(?:kiro-cli\s+)?(\d+)\.(\d+)\.(\d+)/i,
|
|
1403
|
+
);
|
|
1404
|
+
if (!match) return null;
|
|
1405
|
+
return {
|
|
1406
|
+
major: Number(match[1]),
|
|
1407
|
+
minor: Number(match[2]),
|
|
1408
|
+
patch: Number(match[3]),
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
function kiroCliRequiresPty(version) {
|
|
1413
|
+
if (!version) return false;
|
|
1414
|
+
if (version.major !== 2) return version.major > 2;
|
|
1415
|
+
return version.minor >= 13;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
function quotePosixShellArg(value) {
|
|
1419
|
+
return `'${String(value).replace(/'/g, `'"'"'`)}'`;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
function kiroPtyInvocation(binaryPath, args, platform = process.platform) {
|
|
1423
|
+
if (platform === "darwin") {
|
|
1424
|
+
return {
|
|
1425
|
+
command: "/usr/bin/script",
|
|
1426
|
+
args: ["-q", "/dev/null", binaryPath, ...args],
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
if (platform === "linux") {
|
|
1430
|
+
const commandLine = [binaryPath, ...args]
|
|
1431
|
+
.map(quotePosixShellArg)
|
|
1432
|
+
.join(" ");
|
|
1433
|
+
return {
|
|
1434
|
+
command: "script",
|
|
1435
|
+
args: ["-q", "-c", commandLine, "/dev/null"],
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
return null;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
function combineKiroCommandOutput(result) {
|
|
1442
|
+
const stdout =
|
|
1443
|
+
typeof result?.stdout === "string" ? result.stdout.trim() : "";
|
|
1444
|
+
const stderr =
|
|
1445
|
+
typeof result?.stderr === "string" ? result.stderr.trim() : "";
|
|
1446
|
+
return [stdout, stderr].filter(Boolean).join("\n");
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
function parseKiroCommandResult(result, { now = new Date() } = {}) {
|
|
1450
|
+
const output = combineKiroCommandOutput(result);
|
|
1451
|
+
if (
|
|
1452
|
+
result?.error?.code === "ETIMEDOUT" &&
|
|
1453
|
+
!isKiroUsageOutputComplete(output)
|
|
1454
|
+
) {
|
|
1455
|
+
throw new Error("Kiro CLI timed out.");
|
|
1456
|
+
}
|
|
1457
|
+
if (!output && result?.status !== 0) {
|
|
1458
|
+
const detail = result?.error?.message
|
|
1459
|
+
? `: ${result.error.message}`
|
|
1460
|
+
: ".";
|
|
1461
|
+
throw new Error(`Kiro CLI failed with status ${result?.status ?? "unknown"}${detail}`);
|
|
1462
|
+
}
|
|
1463
|
+
return parseKiroUsageOutput(output, { now });
|
|
1335
1464
|
}
|
|
1336
1465
|
|
|
1337
1466
|
function parseKiroUsageOutput(output, { now = new Date() } = {}) {
|
|
@@ -1364,8 +1493,12 @@ function parseKiroUsageOutput(output, { now = new Date() } = {}) {
|
|
|
1364
1493
|
planName = modernPlan[1].split("\n")[0].trim() || planName;
|
|
1365
1494
|
}
|
|
1366
1495
|
|
|
1367
|
-
const resetMatch = stripped.match(
|
|
1368
|
-
|
|
1496
|
+
const resetMatch = stripped.match(
|
|
1497
|
+
/resets on (\d{4}-\d{2}-\d{2}|\d{2}\/\d{2})/i,
|
|
1498
|
+
);
|
|
1499
|
+
const primaryReset = resetMatch
|
|
1500
|
+
? parseKiroResetDate(resetMatch[1], now)
|
|
1501
|
+
: null;
|
|
1369
1502
|
|
|
1370
1503
|
let creditsPercent = null;
|
|
1371
1504
|
const percentMatch = stripped.match(/█+\s*(\d+)%/);
|
|
@@ -1845,38 +1978,76 @@ async function fetchCopilotLimits({
|
|
|
1845
1978
|
}
|
|
1846
1979
|
}
|
|
1847
1980
|
|
|
1848
|
-
async function fetchKiroLimits({
|
|
1849
|
-
|
|
1981
|
+
async function fetchKiroLimits({
|
|
1982
|
+
commandRunner,
|
|
1983
|
+
now = new Date(),
|
|
1984
|
+
platform = process.platform,
|
|
1985
|
+
} = {}) {
|
|
1986
|
+
const binaryPath = await whichBinary("kiro-cli", { commandRunner });
|
|
1987
|
+
if (!binaryPath) {
|
|
1850
1988
|
return { configured: false };
|
|
1851
1989
|
}
|
|
1852
1990
|
|
|
1853
|
-
const
|
|
1991
|
+
const versionResult = await runCommand(
|
|
1854
1992
|
commandRunner,
|
|
1855
|
-
|
|
1856
|
-
["
|
|
1993
|
+
binaryPath,
|
|
1994
|
+
["--version"],
|
|
1857
1995
|
{
|
|
1858
|
-
timeout:
|
|
1996
|
+
timeout: 2_000,
|
|
1859
1997
|
env: { ...process.env, TERM: "xterm-256color" },
|
|
1860
1998
|
},
|
|
1861
1999
|
);
|
|
2000
|
+
const version = parseKiroCliVersion(
|
|
2001
|
+
combineKiroCommandOutput(versionResult),
|
|
2002
|
+
);
|
|
2003
|
+
const args = ["chat", "--no-interactive", "/usage"];
|
|
2004
|
+
const pty = kiroPtyInvocation(binaryPath, args, platform);
|
|
2005
|
+
|
|
2006
|
+
// Kiro CLI 2.13 changed pipe behavior: /usage is treated as a normal model
|
|
2007
|
+
// prompt without a terminal. Go straight to a PTY so a refresh does not
|
|
2008
|
+
// accidentally spend credits on an assistant response. Older/unknown builds
|
|
2009
|
+
// retain the existing pipe-first behavior, with a bounded PTY fallback if
|
|
2010
|
+
// the output is not a recognizable usage panel.
|
|
2011
|
+
const attempts = [];
|
|
2012
|
+
if (kiroCliRequiresPty(version)) {
|
|
2013
|
+
if (pty) attempts.push(pty);
|
|
2014
|
+
} else {
|
|
2015
|
+
attempts.push({ command: binaryPath, args });
|
|
2016
|
+
if (pty) attempts.push(pty);
|
|
2017
|
+
}
|
|
1862
2018
|
|
|
1863
|
-
|
|
1864
|
-
const stderr = typeof result?.stderr === "string" ? result.stderr : "";
|
|
1865
|
-
const output = stderr.trim() || stdout.trim();
|
|
1866
|
-
|
|
2019
|
+
let lastError = null;
|
|
1867
2020
|
try {
|
|
1868
|
-
if (
|
|
1869
|
-
throw new Error(
|
|
2021
|
+
if (attempts.length === 0) {
|
|
2022
|
+
throw new Error(
|
|
2023
|
+
`Kiro CLI ${version ? `${version.major}.${version.minor}.${version.patch}` : ""} requires a pseudo-terminal on ${platform}.`,
|
|
2024
|
+
);
|
|
1870
2025
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
2026
|
+
for (const attempt of attempts) {
|
|
2027
|
+
const result = await runCommand(
|
|
2028
|
+
commandRunner,
|
|
2029
|
+
attempt.command,
|
|
2030
|
+
attempt.args,
|
|
2031
|
+
{
|
|
2032
|
+
timeout: 20_000,
|
|
2033
|
+
env: { ...process.env, TERM: "xterm-256color" },
|
|
2034
|
+
completeWhen: (stdout, stderr) =>
|
|
2035
|
+
isKiroUsageOutputComplete(`${stdout}\n${stderr}`),
|
|
2036
|
+
completionGraceMs: 750,
|
|
2037
|
+
killProcessGroup: Boolean(pty),
|
|
2038
|
+
},
|
|
2039
|
+
);
|
|
2040
|
+
try {
|
|
2041
|
+
return {
|
|
2042
|
+
configured: true,
|
|
2043
|
+
error: null,
|
|
2044
|
+
...parseKiroCommandResult(result, { now }),
|
|
2045
|
+
};
|
|
2046
|
+
} catch (error) {
|
|
2047
|
+
lastError = error;
|
|
2048
|
+
}
|
|
1873
2049
|
}
|
|
1874
|
-
|
|
1875
|
-
return {
|
|
1876
|
-
configured: true,
|
|
1877
|
-
error: null,
|
|
1878
|
-
...parseKiroUsageOutput(output, { now }),
|
|
1879
|
-
};
|
|
2050
|
+
throw lastError || new Error("Failed to read Kiro usage.");
|
|
1880
2051
|
} catch (error) {
|
|
1881
2052
|
return {
|
|
1882
2053
|
configured: true,
|
|
@@ -2740,7 +2911,7 @@ function toTitleCase(s) {
|
|
|
2740
2911
|
// leading brand word and Title Case the rest.
|
|
2741
2912
|
function normalizePlanLabel(raw, brand) {
|
|
2742
2913
|
if (raw == null) return null;
|
|
2743
|
-
let s = String(raw).trim();
|
|
2914
|
+
let s = String(raw).replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
2744
2915
|
if (!s) return null;
|
|
2745
2916
|
const lower = s.toLowerCase();
|
|
2746
2917
|
if (["free", "none", "unknown"].includes(lower)) return null;
|
|
@@ -2883,7 +3054,7 @@ async function fetchUsageLimitsUncached({
|
|
|
2883
3054
|
: null;
|
|
2884
3055
|
|
|
2885
3056
|
const providerFetch = withFetchTimeout(fetchImpl, providerTimeoutMs);
|
|
2886
|
-
const [claudeResult, codexResult, cursor, kimi, gemini, kiro, antigravity, copilot, grok, zcode, opencodeGo] = await Promise.all([
|
|
3057
|
+
const [claudeResult, codexResult, cursor, kimi, gemini, kiro, antigravity, copilot, grok, zcode, opencodeGo, qoder, claudeServiceStatus] = await Promise.all([
|
|
2887
3058
|
claudeToken && !freshClaudeCache && !claudeRetryAtMs
|
|
2888
3059
|
? withProviderTimeout(fetchClaudeUsageLimits(claudeToken, { fetchImpl: providerFetch, maxAttempts: 1 }), "Claude", providerTimeoutMs).then(
|
|
2889
3060
|
(value) => ({ status: "fulfilled", value }),
|
|
@@ -2906,7 +3077,7 @@ async function fetchUsageLimitsUncached({
|
|
|
2906
3077
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
2907
3078
|
withProviderTimeout(fetchGeminiLimits({ home, env, fetchImpl: providerFetch, commandRunner }), "Gemini", providerTimeoutMs)
|
|
2908
3079
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
2909
|
-
fetchKiroLimits({ commandRunner, now }),
|
|
3080
|
+
fetchKiroLimits({ commandRunner, now, platform }),
|
|
2910
3081
|
fetchAntigravityLimits({ home, commandRunner, requestFn, fetchImpl: providerFetch, nowMs }),
|
|
2911
3082
|
withProviderTimeout(fetchCopilotLimits({ home, env, fetchImpl: providerFetch, platform, securityRunner }), "GitHub Copilot", providerTimeoutMs)
|
|
2912
3083
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
@@ -2919,6 +3090,23 @@ async function fetchUsageLimitsUncached({
|
|
|
2919
3090
|
// OPENCODE_GO_AUTH_COOKIE is set. See src/lib/opencode-go-limits.js.
|
|
2920
3091
|
withProviderTimeout(fetchOpencodeGoLimits({ home, env, fetchImpl: providerFetch }), "OpenCode Go", providerTimeoutMs)
|
|
2921
3092
|
.catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
3093
|
+
withProviderTimeout(
|
|
3094
|
+
fetchQoderLimits({
|
|
3095
|
+
home,
|
|
3096
|
+
env,
|
|
3097
|
+
platform,
|
|
3098
|
+
securityRunner,
|
|
3099
|
+
fetchImpl: providerFetch,
|
|
3100
|
+
}),
|
|
3101
|
+
"Qoder",
|
|
3102
|
+
providerTimeoutMs,
|
|
3103
|
+
).catch((reason) => ({ configured: true, error: reason?.message || "Unknown error" })),
|
|
3104
|
+
// Public status-page probe (fail-soft, own 5-min cache in provider-status.js).
|
|
3105
|
+
// Only probed for configured accounts — without a token the Claude section
|
|
3106
|
+
// never renders, so the reading would have nowhere to go.
|
|
3107
|
+
claudeToken
|
|
3108
|
+
? fetchProviderServiceStatus("claude", { fetchImpl, nowMs })
|
|
3109
|
+
: Promise.resolve(null),
|
|
2922
3110
|
]);
|
|
2923
3111
|
|
|
2924
3112
|
let claude;
|
|
@@ -2985,6 +3173,15 @@ async function fetchUsageLimitsUncached({
|
|
|
2985
3173
|
}
|
|
2986
3174
|
}
|
|
2987
3175
|
|
|
3176
|
+
// Attach the service-status reading AFTER assembly so it rides on every path
|
|
3177
|
+
// (live, fresh-cache, stale-cache, error) but never gets persisted by
|
|
3178
|
+
// writeClaudeLimitsCache above — a disk cache must not resurrect an incident
|
|
3179
|
+
// banner hours later. Only active incidents ship; "none" is omitted so the
|
|
3180
|
+
// client renders nothing in the happy path.
|
|
3181
|
+
if (claude.configured && claudeServiceStatus && claudeServiceStatus.indicator !== "none") {
|
|
3182
|
+
claude.service_status = claudeServiceStatus;
|
|
3183
|
+
}
|
|
3184
|
+
|
|
2988
3185
|
let codex;
|
|
2989
3186
|
if (!codexToken) {
|
|
2990
3187
|
codex = { configured: false };
|
|
@@ -3043,6 +3240,7 @@ async function fetchUsageLimitsUncached({
|
|
|
3043
3240
|
grok: withPlanLabel(grok, null, "Grok"),
|
|
3044
3241
|
zcode: withPlanLabel(zcode, zcode.plan_label, "ZCode"),
|
|
3045
3242
|
opencodeGo: withPlanLabel(opencodeGo, opencodeGo?.plan_label, "OpenCode Go"),
|
|
3243
|
+
qoder: withPlanLabel(qoder, qoder?.plan_label, "Qoder"),
|
|
3046
3244
|
};
|
|
3047
3245
|
|
|
3048
3246
|
for (const [providerName, provider] of Object.entries(data)) {
|
|
@@ -3086,6 +3284,7 @@ module.exports = {
|
|
|
3086
3284
|
normalizeGeminiQuotaResponse,
|
|
3087
3285
|
normalizeKimiUsageResponse,
|
|
3088
3286
|
parseKiroUsageOutput,
|
|
3287
|
+
fetchKiroLimits,
|
|
3089
3288
|
normalizeAntigravityResponse,
|
|
3090
3289
|
parseListeningPorts,
|
|
3091
3290
|
detectAntigravityProcess,
|
|
@@ -3100,4 +3299,5 @@ module.exports = {
|
|
|
3100
3299
|
fetchGrokLimits,
|
|
3101
3300
|
fetchZcodeLimits,
|
|
3102
3301
|
fetchOpencodeGoLimits,
|
|
3302
|
+
fetchQoderLimits,
|
|
3103
3303
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as r,d as e}from"./__vite-browser-external-D3llGq6p.js";function n({children:i,title:a,subtitle:o,className:s="",bodyClassName:d=""}){return r.jsxs("div",{className:e("rounded-xl border border-oai-gray-200 dark:border-oai-gray-800 bg-white dark:bg-oai-gray-900 transition-colors duration-200",s),children:[(a||o)&&r.jsxs("div",{className:"px-5 py-4 border-b border-oai-gray-200 dark:border-oai-gray-800 transition-colors duration-200",children:[a&&r.jsx("h3",{className:"text-sm font-medium text-oai-gray-500 dark:text-oai-gray-300 uppercase tracking-wide transition-colors duration-200",children:a}),o&&r.jsx("p",{className:"text-sm text-oai-gray-500 dark:text-oai-gray-300 mt-1 transition-colors duration-200",children:o})]}),r.jsx("div",{className:`p-5 ${d}`,children:i})]})}export{n as C};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,z as a}from"./__vite-browser-external-D3llGq6p.js";import{u as p}from"./DialogTitle-BbAVHI_v.js";import{u as c}from"./useScrollLock-DVSyJ-GE.js";const x=n.forwardRef(function(e,r){const{render:l,className:u,style:m,id:s,...t}=e,{store:i}=p(),o=c(s);return i.useSyncedValueWithCleanup("descriptionElementId",o),a("p",e,{ref:r,props:[{id:o},t]})});export{x as D};
|