codex-devtools 0.2.0 → 0.2.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/dist-electron/main/chunks/{CodexServiceContext-BYe2UXME.cjs → CodexServiceContext-DaxLI918.cjs} +53 -52
- package/dist-electron/main/index.cjs +1 -1
- package/dist-electron/main/standalone.cjs +1 -1
- package/out/renderer/assets/{index-C-iGxog-.js → index-5ydAmpDO.js} +278 -34
- package/out/renderer/assets/{index-D3FYKy1U.css → index-Cgat1ue6.css} +157 -0
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
|
@@ -369,16 +369,32 @@ function diffTokenUsage(previous, current) {
|
|
|
369
369
|
reasoning_output_tokens: current.reasoning_output_tokens - previous.reasoning_output_tokens,
|
|
370
370
|
total_tokens: current.total_tokens - previous.total_tokens
|
|
371
371
|
};
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
372
|
+
const normalized = {
|
|
373
|
+
input_tokens: Math.max(delta.input_tokens, 0),
|
|
374
|
+
cached_input_tokens: Math.max(delta.cached_input_tokens, 0),
|
|
375
|
+
output_tokens: Math.max(delta.output_tokens, 0),
|
|
376
|
+
reasoning_output_tokens: Math.max(delta.reasoning_output_tokens, 0),
|
|
377
|
+
total_tokens: Math.max(delta.total_tokens, 0)
|
|
378
|
+
};
|
|
379
|
+
const hasAnyPositive = normalized.input_tokens > 0 || normalized.cached_input_tokens > 0 || normalized.output_tokens > 0 || normalized.reasoning_output_tokens > 0 || normalized.total_tokens > 0;
|
|
380
|
+
return hasAnyPositive ? normalized : null;
|
|
378
381
|
}
|
|
379
382
|
function isSameTokenUsage(left, right) {
|
|
380
383
|
return left.input_tokens === right.input_tokens && left.cached_input_tokens === right.cached_input_tokens && left.output_tokens === right.output_tokens && left.reasoning_output_tokens === right.reasoning_output_tokens && left.total_tokens === right.total_tokens;
|
|
381
384
|
}
|
|
385
|
+
function resolveTokenUsage(previousTotalUsage, currentTotalUsage, fallbackUsage) {
|
|
386
|
+
if (!previousTotalUsage) {
|
|
387
|
+
return fallbackUsage;
|
|
388
|
+
}
|
|
389
|
+
const delta = diffTokenUsage(previousTotalUsage, currentTotalUsage);
|
|
390
|
+
if (delta) {
|
|
391
|
+
return delta;
|
|
392
|
+
}
|
|
393
|
+
if (isSameTokenUsage(previousTotalUsage, currentTotalUsage)) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
return fallbackUsage;
|
|
397
|
+
}
|
|
382
398
|
const AGENTS_HEADING_PATTERN = /^#?\s*AGENTS\.md instructions\b/i;
|
|
383
399
|
const AGENTS_INSTRUCTIONS_BLOCK_PATTERN = /<INSTRUCTIONS>[\s\S]*<\/INSTRUCTIONS>/i;
|
|
384
400
|
const ENVIRONMENT_CONTEXT_WRAPPER_PATTERN = /^<environment_context>[\s\S]*<\/environment_context>$/i;
|
|
@@ -1022,6 +1038,7 @@ class CodexChunkBuilder {
|
|
|
1022
1038
|
let pendingUser = null;
|
|
1023
1039
|
let lastSeenModelUsage = null;
|
|
1024
1040
|
let lastSeenCollaborationMode = "";
|
|
1041
|
+
let previousTotalUsage = null;
|
|
1025
1042
|
const flushAIChunk = () => {
|
|
1026
1043
|
if (!currentAI) {
|
|
1027
1044
|
return;
|
|
@@ -1276,30 +1293,33 @@ class CodexChunkBuilder {
|
|
|
1276
1293
|
addReasoningSection(ai, "event", [entry.payload.text]);
|
|
1277
1294
|
continue;
|
|
1278
1295
|
}
|
|
1279
|
-
if (isEventMsgEntry(entry) && isTokenCountPayload(entry.payload)) {
|
|
1280
|
-
|
|
1281
|
-
|
|
1296
|
+
if (isEventMsgEntry(entry) && isTokenCountPayload(entry.payload) && entry.payload.info) {
|
|
1297
|
+
const currentTotalUsage = entry.payload.info.total_token_usage;
|
|
1298
|
+
const usage = resolveTokenUsage(
|
|
1299
|
+
previousTotalUsage,
|
|
1300
|
+
currentTotalUsage,
|
|
1301
|
+
entry.payload.info.last_token_usage
|
|
1302
|
+
);
|
|
1303
|
+
previousTotalUsage = currentTotalUsage;
|
|
1304
|
+
if (!usage) {
|
|
1305
|
+
continue;
|
|
1306
|
+
}
|
|
1307
|
+
this.accumulateMetricsFromTokenUsage(ai.metrics, usage);
|
|
1308
|
+
this.assignTokenUsageToPendingTool(ai, usage);
|
|
1282
1309
|
}
|
|
1283
1310
|
}
|
|
1284
1311
|
flushPendingEventUser();
|
|
1285
1312
|
flushAIChunk();
|
|
1286
1313
|
return chunks;
|
|
1287
1314
|
}
|
|
1288
|
-
|
|
1289
|
-
if (!isTokenCountPayload(entry.payload) || !entry.payload.info) {
|
|
1290
|
-
return;
|
|
1291
|
-
}
|
|
1292
|
-
const usage = entry.payload.info.last_token_usage;
|
|
1315
|
+
accumulateMetricsFromTokenUsage(target, usage) {
|
|
1293
1316
|
target.inputTokens = (target.inputTokens ?? 0) + usage.input_tokens;
|
|
1294
1317
|
target.cachedTokens = (target.cachedTokens ?? 0) + usage.cached_input_tokens;
|
|
1295
1318
|
target.outputTokens = (target.outputTokens ?? 0) + usage.output_tokens;
|
|
1296
1319
|
target.reasoningTokens = (target.reasoningTokens ?? 0) + usage.reasoning_output_tokens;
|
|
1297
1320
|
target.totalTokens = (target.totalTokens ?? 0) + usage.total_tokens;
|
|
1298
1321
|
}
|
|
1299
|
-
assignTokenUsageToPendingTool(ai,
|
|
1300
|
-
if (!isTokenCountPayload(entry.payload) || !entry.payload.info) {
|
|
1301
|
-
return;
|
|
1302
|
-
}
|
|
1322
|
+
assignTokenUsageToPendingTool(ai, usage) {
|
|
1303
1323
|
if (ai.pendingUsageToolIndex === null) {
|
|
1304
1324
|
return;
|
|
1305
1325
|
}
|
|
@@ -1308,13 +1328,14 @@ class CodexChunkBuilder {
|
|
|
1308
1328
|
ai.pendingUsageToolIndex = null;
|
|
1309
1329
|
return;
|
|
1310
1330
|
}
|
|
1311
|
-
const usage = entry.payload.info.last_token_usage;
|
|
1312
1331
|
if (tool.tokenUsage) {
|
|
1313
1332
|
tool.tokenUsage.inputTokens += usage.input_tokens;
|
|
1333
|
+
tool.tokenUsage.cachedInputTokens += usage.cached_input_tokens;
|
|
1314
1334
|
tool.tokenUsage.outputTokens += usage.output_tokens;
|
|
1315
1335
|
} else {
|
|
1316
1336
|
tool.tokenUsage = {
|
|
1317
1337
|
inputTokens: usage.input_tokens,
|
|
1338
|
+
cachedInputTokens: usage.cached_input_tokens,
|
|
1318
1339
|
outputTokens: usage.output_tokens
|
|
1319
1340
|
};
|
|
1320
1341
|
}
|
|
@@ -1478,21 +1499,11 @@ function buildSessionStatsRecord(parsed, revision, nowIso) {
|
|
|
1478
1499
|
}
|
|
1479
1500
|
const timestamp = parseTimestamp(entry.timestamp);
|
|
1480
1501
|
const currentTotal = entry.payload.info.total_token_usage;
|
|
1481
|
-
|
|
1482
|
-
if (previousTotalUsage) {
|
|
1483
|
-
const delta = diffTokenUsage(previousTotalUsage, currentTotal);
|
|
1484
|
-
if (delta) {
|
|
1485
|
-
usage = delta;
|
|
1486
|
-
} else if (isSameTokenUsage(previousTotalUsage, currentTotal)) {
|
|
1487
|
-
previousTotalUsage = currentTotal;
|
|
1488
|
-
continue;
|
|
1489
|
-
} else {
|
|
1490
|
-
usage = entry.payload.info.last_token_usage;
|
|
1491
|
-
}
|
|
1492
|
-
} else {
|
|
1493
|
-
usage = currentTotal;
|
|
1494
|
-
}
|
|
1502
|
+
const usage = resolveTokenUsage(previousTotalUsage, currentTotal, entry.payload.info.last_token_usage);
|
|
1495
1503
|
previousTotalUsage = currentTotal;
|
|
1504
|
+
if (!usage) {
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1496
1507
|
const usageTotals = tokenUsageToTotals(usage);
|
|
1497
1508
|
addTokenTotals(tokens, usageTotals);
|
|
1498
1509
|
const modelTotals = ensureModelBucket(modelBuckets, currentModel, currentReasoningEffort);
|
|
@@ -1518,7 +1529,7 @@ function buildSessionStatsRecord(parsed, revision, nowIso) {
|
|
|
1518
1529
|
}
|
|
1519
1530
|
const lastActivity = parsed.entries[parsed.entries.length - 1]?.timestamp ?? parsed.session.startTime;
|
|
1520
1531
|
return {
|
|
1521
|
-
tokenComputationVersion:
|
|
1532
|
+
tokenComputationVersion: 4,
|
|
1522
1533
|
sessionId: parsed.session.id,
|
|
1523
1534
|
filePath: parsed.session.filePath,
|
|
1524
1535
|
revision,
|
|
@@ -2030,21 +2041,11 @@ class CodexSessionParser {
|
|
|
2030
2041
|
eventMessages.push(entry);
|
|
2031
2042
|
if (isTokenCountPayload(entry.payload) && entry.payload.info) {
|
|
2032
2043
|
const currentTotal = entry.payload.info.total_token_usage;
|
|
2033
|
-
|
|
2034
|
-
if (previousTotalUsage) {
|
|
2035
|
-
const delta = diffTokenUsage(previousTotalUsage, currentTotal);
|
|
2036
|
-
if (delta) {
|
|
2037
|
-
usage = delta;
|
|
2038
|
-
} else if (isSameTokenUsage(previousTotalUsage, currentTotal)) {
|
|
2039
|
-
previousTotalUsage = currentTotal;
|
|
2040
|
-
continue;
|
|
2041
|
-
} else {
|
|
2042
|
-
usage = entry.payload.info.last_token_usage;
|
|
2043
|
-
}
|
|
2044
|
-
} else {
|
|
2045
|
-
usage = currentTotal;
|
|
2046
|
-
}
|
|
2044
|
+
const usage = resolveTokenUsage(previousTotalUsage, currentTotal, entry.payload.info.last_token_usage);
|
|
2047
2045
|
previousTotalUsage = currentTotal;
|
|
2046
|
+
if (!usage) {
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2048
2049
|
metrics.inputTokens += usage.input_tokens;
|
|
2049
2050
|
metrics.cachedTokens += usage.cached_input_tokens;
|
|
2050
2051
|
metrics.outputTokens += usage.output_tokens;
|
|
@@ -2383,12 +2384,12 @@ class StatsSnapshotStore {
|
|
|
2383
2384
|
}
|
|
2384
2385
|
}
|
|
2385
2386
|
}
|
|
2386
|
-
const DETAIL_CACHE_PREFIX = "detail-
|
|
2387
|
-
const CHUNKS_CACHE_PREFIX = "chunks-
|
|
2387
|
+
const DETAIL_CACHE_PREFIX = "detail-v3";
|
|
2388
|
+
const CHUNKS_CACHE_PREFIX = "chunks-v4";
|
|
2388
2389
|
const SESSIONS_CACHE_PREFIX = "sessions";
|
|
2389
|
-
const STATS_CACHE_PREFIX = "stats-
|
|
2390
|
+
const STATS_CACHE_PREFIX = "stats-v3";
|
|
2390
2391
|
const UNKNOWN_REVISION = "unknown-revision";
|
|
2391
|
-
const TOKEN_COMPUTATION_VERSION =
|
|
2392
|
+
const TOKEN_COMPUTATION_VERSION = 4;
|
|
2392
2393
|
function hasCompactionSignals(entries) {
|
|
2393
2394
|
return entries.some(
|
|
2394
2395
|
(entry) => isCompactedEntry(entry) || isCompactionEntry(entry) || isEventMsgEntry(entry) && isContextCompactedPayload(entry.payload)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const electron = require("electron");
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const path = require("node:path");
|
|
5
|
-
const CodexServiceContext = require("./chunks/CodexServiceContext-
|
|
5
|
+
const CodexServiceContext = require("./chunks/CodexServiceContext-DaxLI918.cjs");
|
|
6
6
|
require("node:events");
|
|
7
7
|
require("node:os");
|
|
8
8
|
require("node:crypto");
|
|
@@ -5,7 +5,7 @@ const fastifyStatic = require("@fastify/static");
|
|
|
5
5
|
const Fastify = require("fastify");
|
|
6
6
|
const path = require("node:path");
|
|
7
7
|
const node_url = require("node:url");
|
|
8
|
-
const CodexServiceContext = require("./chunks/CodexServiceContext-
|
|
8
|
+
const CodexServiceContext = require("./chunks/CodexServiceContext-DaxLI918.cjs");
|
|
9
9
|
const fs = require("node:fs");
|
|
10
10
|
require("node:events");
|
|
11
11
|
require("node:os");
|
|
@@ -9423,27 +9423,124 @@ const DashboardView = () => {
|
|
|
9423
9423
|
] })
|
|
9424
9424
|
] });
|
|
9425
9425
|
};
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
}
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
return `${minutes}m`;
|
|
9435
|
-
}
|
|
9436
|
-
if (minutes === 0) {
|
|
9437
|
-
return `${hours}h`;
|
|
9438
|
-
}
|
|
9439
|
-
return `${hours}h ${minutes}m`;
|
|
9440
|
-
}
|
|
9426
|
+
const CONTRIBUTION_WEEKDAY_LABELS = ["", "Mon", "", "Wed", "", "Fri", ""];
|
|
9427
|
+
const CALENDAR_METRIC_OPTIONS = [
|
|
9428
|
+
{ value: "totalTokens", label: "Total tokens", tooltipLabel: "total tokens" },
|
|
9429
|
+
{ value: "inputTokens", label: "Input tokens", tooltipLabel: "input tokens" },
|
|
9430
|
+
{ value: "outputTokens", label: "Output tokens", tooltipLabel: "output tokens" },
|
|
9431
|
+
{ value: "eventCount", label: "Events", tooltipLabel: "events" },
|
|
9432
|
+
{ value: "sessionCount", label: "Sessions", tooltipLabel: "sessions" }
|
|
9433
|
+
];
|
|
9441
9434
|
function normalizeScope(scope) {
|
|
9442
9435
|
if (scope.type === "project" && scope.cwd.trim().length > 0) {
|
|
9443
9436
|
return { type: "project", cwd: scope.cwd.trim() };
|
|
9444
9437
|
}
|
|
9445
9438
|
return { type: "all" };
|
|
9446
9439
|
}
|
|
9440
|
+
function parseDateKey(value) {
|
|
9441
|
+
return /* @__PURE__ */ new Date(`${value}T00:00:00`);
|
|
9442
|
+
}
|
|
9443
|
+
function formatDateKey(date) {
|
|
9444
|
+
const year = date.getFullYear();
|
|
9445
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
9446
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
9447
|
+
return `${year}-${month}-${day}`;
|
|
9448
|
+
}
|
|
9449
|
+
function getContributionLevel(outputTokens, maxOutputTokens) {
|
|
9450
|
+
if (!Number.isFinite(outputTokens) || outputTokens <= 0 || maxOutputTokens <= 0) {
|
|
9451
|
+
return 0;
|
|
9452
|
+
}
|
|
9453
|
+
const normalized = Math.log(outputTokens + 1) / Math.log(maxOutputTokens + 1);
|
|
9454
|
+
if (normalized < 0.25) {
|
|
9455
|
+
return 1;
|
|
9456
|
+
}
|
|
9457
|
+
if (normalized < 0.5) {
|
|
9458
|
+
return 2;
|
|
9459
|
+
}
|
|
9460
|
+
if (normalized < 0.75) {
|
|
9461
|
+
return 3;
|
|
9462
|
+
}
|
|
9463
|
+
return 4;
|
|
9464
|
+
}
|
|
9465
|
+
function getDailyMetricValue(point, metric) {
|
|
9466
|
+
if (!point) {
|
|
9467
|
+
return 0;
|
|
9468
|
+
}
|
|
9469
|
+
switch (metric) {
|
|
9470
|
+
case "totalTokens":
|
|
9471
|
+
return point.totalTokens;
|
|
9472
|
+
case "inputTokens":
|
|
9473
|
+
return point.inputTokens;
|
|
9474
|
+
case "outputTokens":
|
|
9475
|
+
return point.outputTokens;
|
|
9476
|
+
case "eventCount":
|
|
9477
|
+
return point.eventCount;
|
|
9478
|
+
case "sessionCount":
|
|
9479
|
+
return point.sessionCount;
|
|
9480
|
+
default:
|
|
9481
|
+
return 0;
|
|
9482
|
+
}
|
|
9483
|
+
}
|
|
9484
|
+
function buildDailyContributionGrid(daily, metric) {
|
|
9485
|
+
if (daily.length === 0) {
|
|
9486
|
+
return {
|
|
9487
|
+
weeks: [],
|
|
9488
|
+
months: []
|
|
9489
|
+
};
|
|
9490
|
+
}
|
|
9491
|
+
const sorted = [...daily].sort((left, right) => left.date.localeCompare(right.date));
|
|
9492
|
+
const valuesByDate = new Map(sorted.map((point) => [point.date, point]));
|
|
9493
|
+
const maxMetricValue = Math.max(...sorted.map((point) => getDailyMetricValue(point, metric)), 0);
|
|
9494
|
+
const firstDate = parseDateKey(sorted[0].date);
|
|
9495
|
+
const lastDate = parseDateKey(sorted[sorted.length - 1].date);
|
|
9496
|
+
const paddedStart = new Date(firstDate);
|
|
9497
|
+
paddedStart.setDate(paddedStart.getDate() - paddedStart.getDay());
|
|
9498
|
+
const paddedEnd = new Date(lastDate);
|
|
9499
|
+
paddedEnd.setDate(paddedEnd.getDate() + (6 - paddedEnd.getDay()));
|
|
9500
|
+
const weeks = [];
|
|
9501
|
+
const cursor = new Date(paddedStart);
|
|
9502
|
+
while (cursor <= paddedEnd) {
|
|
9503
|
+
const week = [];
|
|
9504
|
+
for (let offset = 0; offset < 7; offset += 1) {
|
|
9505
|
+
const date = formatDateKey(cursor);
|
|
9506
|
+
const point = valuesByDate.get(date);
|
|
9507
|
+
const inRange = cursor >= firstDate && cursor <= lastDate;
|
|
9508
|
+
const metricValue = getDailyMetricValue(point, metric);
|
|
9509
|
+
week.push({
|
|
9510
|
+
date,
|
|
9511
|
+
metricValue,
|
|
9512
|
+
level: getContributionLevel(metricValue, maxMetricValue),
|
|
9513
|
+
inRange
|
|
9514
|
+
});
|
|
9515
|
+
cursor.setDate(cursor.getDate() + 1);
|
|
9516
|
+
}
|
|
9517
|
+
weeks.push(week);
|
|
9518
|
+
}
|
|
9519
|
+
const months = [];
|
|
9520
|
+
let previousMonthKey = "";
|
|
9521
|
+
weeks.forEach((week, weekIndex) => {
|
|
9522
|
+
const monthStartCell = week.find((cell) => cell.inRange && cell.date.endsWith("-01"));
|
|
9523
|
+
const anchor = monthStartCell != null ? monthStartCell : week.find((cell) => cell.inRange);
|
|
9524
|
+
if (!anchor) {
|
|
9525
|
+
return;
|
|
9526
|
+
}
|
|
9527
|
+
const monthDate = parseDateKey(anchor.date);
|
|
9528
|
+
const monthKey = `${monthDate.getFullYear()}-${String(monthDate.getMonth() + 1).padStart(2, "0")}`;
|
|
9529
|
+
if (monthKey === previousMonthKey) {
|
|
9530
|
+
return;
|
|
9531
|
+
}
|
|
9532
|
+
months.push({
|
|
9533
|
+
key: monthKey,
|
|
9534
|
+
label: monthDate.toLocaleString(void 0, { month: "short" }),
|
|
9535
|
+
weekIndex
|
|
9536
|
+
});
|
|
9537
|
+
previousMonthKey = monthKey;
|
|
9538
|
+
});
|
|
9539
|
+
return {
|
|
9540
|
+
weeks,
|
|
9541
|
+
months
|
|
9542
|
+
};
|
|
9543
|
+
}
|
|
9447
9544
|
const StatsView = () => {
|
|
9448
9545
|
const {
|
|
9449
9546
|
projects,
|
|
@@ -9462,6 +9559,8 @@ const StatsView = () => {
|
|
|
9462
9559
|
fetchStats: state.fetchStats,
|
|
9463
9560
|
setStatsScope: state.setStatsScope
|
|
9464
9561
|
}));
|
|
9562
|
+
const [calendarMetric, setCalendarMetric] = reactExports.useState("outputTokens");
|
|
9563
|
+
const [contributionTooltip, setContributionTooltip] = reactExports.useState(null);
|
|
9465
9564
|
reactExports.useEffect(() => {
|
|
9466
9565
|
if (!statsData && !statsLoading) {
|
|
9467
9566
|
void fetchStats(statsScope);
|
|
@@ -9470,7 +9569,7 @@ const StatsView = () => {
|
|
|
9470
9569
|
const dailyMaxOutput = reactExports.useMemo(
|
|
9471
9570
|
() => {
|
|
9472
9571
|
var _a;
|
|
9473
|
-
return Math.max(...(_a = statsData == null ? void 0 : statsData.daily.map((point) => point.outputTokens)) != null ? _a : [
|
|
9572
|
+
return Math.max(...(_a = statsData == null ? void 0 : statsData.daily.map((point) => point.outputTokens)) != null ? _a : [0]);
|
|
9474
9573
|
},
|
|
9475
9574
|
[statsData]
|
|
9476
9575
|
);
|
|
@@ -9481,6 +9580,30 @@ const StatsView = () => {
|
|
|
9481
9580
|
},
|
|
9482
9581
|
[statsData]
|
|
9483
9582
|
);
|
|
9583
|
+
const dailyContributionGrid = reactExports.useMemo(
|
|
9584
|
+
() => {
|
|
9585
|
+
var _a;
|
|
9586
|
+
return buildDailyContributionGrid((_a = statsData == null ? void 0 : statsData.daily) != null ? _a : [], calendarMetric);
|
|
9587
|
+
},
|
|
9588
|
+
[statsData, calendarMetric]
|
|
9589
|
+
);
|
|
9590
|
+
const selectedCalendarMetricOption = reactExports.useMemo(
|
|
9591
|
+
() => {
|
|
9592
|
+
var _a;
|
|
9593
|
+
return (_a = CALENDAR_METRIC_OPTIONS.find((option) => option.value === calendarMetric)) != null ? _a : CALENDAR_METRIC_OPTIONS[2];
|
|
9594
|
+
},
|
|
9595
|
+
[calendarMetric]
|
|
9596
|
+
);
|
|
9597
|
+
reactExports.useEffect(() => {
|
|
9598
|
+
setContributionTooltip(null);
|
|
9599
|
+
}, [calendarMetric, statsData]);
|
|
9600
|
+
const uncachedInputTokens = reactExports.useMemo(
|
|
9601
|
+
() => {
|
|
9602
|
+
var _a, _b;
|
|
9603
|
+
return Math.max(((_a = statsData == null ? void 0 : statsData.totals.inputTokens) != null ? _a : 0) - ((_b = statsData == null ? void 0 : statsData.totals.cachedTokens) != null ? _b : 0), 0);
|
|
9604
|
+
},
|
|
9605
|
+
[statsData]
|
|
9606
|
+
);
|
|
9484
9607
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "stats-shell", children: [
|
|
9485
9608
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "stats-header", children: [
|
|
9486
9609
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Stats" }),
|
|
@@ -9550,20 +9673,20 @@ const StatsView = () => {
|
|
|
9550
9673
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stat-label", children: "Total tokens" }),
|
|
9551
9674
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "stat-value", children: statsData.totals.totalTokens.toLocaleString() })
|
|
9552
9675
|
] }),
|
|
9676
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
9677
|
+
"article",
|
|
9678
|
+
{
|
|
9679
|
+
className: "stat-card",
|
|
9680
|
+
title: `Cached: ${statsData.totals.cachedTokens.toLocaleString()} | Uncached: ${uncachedInputTokens.toLocaleString()}`,
|
|
9681
|
+
children: [
|
|
9682
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stat-label", children: "In" }),
|
|
9683
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "stat-value", children: statsData.totals.inputTokens.toLocaleString() })
|
|
9684
|
+
]
|
|
9685
|
+
}
|
|
9686
|
+
),
|
|
9553
9687
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("article", { className: "stat-card", children: [
|
|
9554
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stat-label", children: "
|
|
9688
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stat-label", children: "Out" }),
|
|
9555
9689
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "stat-value", children: statsData.totals.outputTokens.toLocaleString() })
|
|
9556
|
-
] }),
|
|
9557
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("article", { className: "stat-card", children: [
|
|
9558
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stat-label", children: "Active time" }),
|
|
9559
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "stat-value", children: formatDuration$1(statsData.totals.durationMs) })
|
|
9560
|
-
] }),
|
|
9561
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("article", { className: "stat-card", children: [
|
|
9562
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stat-label", children: "Sessions" }),
|
|
9563
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("strong", { className: "stat-value", children: [
|
|
9564
|
-
statsData.totals.sessions.toLocaleString(),
|
|
9565
|
-
statsData.totals.archivedSessions > 0 ? ` (${statsData.totals.archivedSessions.toLocaleString()} archived)` : ""
|
|
9566
|
-
] })
|
|
9567
9690
|
] })
|
|
9568
9691
|
] }),
|
|
9569
9692
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "stats-section", children: [
|
|
@@ -9572,7 +9695,8 @@ const StatsView = () => {
|
|
|
9572
9695
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stats-section-subtle", children: "Output tokens" })
|
|
9573
9696
|
] }),
|
|
9574
9697
|
statsData.daily.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "empty-copy", children: "No daily token data yet." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "stats-day-list", children: statsData.daily.map((point) => {
|
|
9575
|
-
const
|
|
9698
|
+
const rawWidthPercent = dailyMaxOutput > 0 ? point.outputTokens / dailyMaxOutput * 100 : 0;
|
|
9699
|
+
const widthPercent = Number.isFinite(rawWidthPercent) ? Math.max(0, Math.min(100, rawWidthPercent)) : 0;
|
|
9576
9700
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "stats-day-row", children: [
|
|
9577
9701
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "stats-day-label", children: point.date }),
|
|
9578
9702
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "stats-day-bar-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "stats-day-bar", style: { width: `${widthPercent}%` } }) }),
|
|
@@ -9580,6 +9704,117 @@ const StatsView = () => {
|
|
|
9580
9704
|
] }, point.date);
|
|
9581
9705
|
}) })
|
|
9582
9706
|
] }),
|
|
9707
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "stats-section", children: [
|
|
9708
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "stats-section-header", children: [
|
|
9709
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: "Output calendar" }),
|
|
9710
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "stats-section-header-actions", children: [
|
|
9711
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "sidebar-label", htmlFor: "stats-calendar-metric", children: "Type" }),
|
|
9712
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9713
|
+
"select",
|
|
9714
|
+
{
|
|
9715
|
+
id: "stats-calendar-metric",
|
|
9716
|
+
className: "app-select stats-contrib-select",
|
|
9717
|
+
value: calendarMetric,
|
|
9718
|
+
onChange: (event) => {
|
|
9719
|
+
setCalendarMetric(event.target.value);
|
|
9720
|
+
},
|
|
9721
|
+
children: CALENDAR_METRIC_OPTIONS.map((option) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value))
|
|
9722
|
+
}
|
|
9723
|
+
)
|
|
9724
|
+
] })
|
|
9725
|
+
] }),
|
|
9726
|
+
dailyContributionGrid.weeks.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "empty-copy", children: "No daily token data yet." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "stats-contrib-frame", children: [
|
|
9727
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "stats-contrib-weekdays", children: CONTRIBUTION_WEEKDAY_LABELS.map((label, index) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: label }, `contrib-weekday-${index}`)) }),
|
|
9728
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "stats-contrib-scroll", children: [
|
|
9729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9730
|
+
"div",
|
|
9731
|
+
{
|
|
9732
|
+
className: "stats-contrib-months",
|
|
9733
|
+
style: { gridTemplateColumns: `repeat(${dailyContributionGrid.weeks.length}, 12px)` },
|
|
9734
|
+
children: dailyContributionGrid.months.map((month) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9735
|
+
"span",
|
|
9736
|
+
{
|
|
9737
|
+
className: "stats-contrib-month",
|
|
9738
|
+
style: { gridColumn: String(month.weekIndex + 1) },
|
|
9739
|
+
children: month.label
|
|
9740
|
+
},
|
|
9741
|
+
month.key
|
|
9742
|
+
))
|
|
9743
|
+
}
|
|
9744
|
+
),
|
|
9745
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9746
|
+
"div",
|
|
9747
|
+
{
|
|
9748
|
+
className: "stats-contrib-weeks",
|
|
9749
|
+
role: "img",
|
|
9750
|
+
"aria-label": "Daily output tokens calendar heatmap",
|
|
9751
|
+
children: dailyContributionGrid.weeks.map((week, weekIndex) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "stats-contrib-week", children: week.map((cell) => {
|
|
9752
|
+
const tooltipText = `${cell.date} • ${cell.metricValue.toLocaleString()} ${selectedCalendarMetricOption.tooltipLabel}`;
|
|
9753
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9754
|
+
"div",
|
|
9755
|
+
{
|
|
9756
|
+
className: `stats-contrib-cell level-${cell.level}${!cell.inRange ? " is-padding" : ""}${cell.inRange && cell.level === 0 ? " is-empty" : ""}`,
|
|
9757
|
+
title: cell.inRange ? tooltipText : void 0,
|
|
9758
|
+
"aria-label": cell.inRange ? tooltipText : void 0,
|
|
9759
|
+
tabIndex: cell.inRange ? 0 : -1,
|
|
9760
|
+
onMouseEnter: (event) => {
|
|
9761
|
+
if (!cell.inRange) {
|
|
9762
|
+
return;
|
|
9763
|
+
}
|
|
9764
|
+
setContributionTooltip({
|
|
9765
|
+
text: tooltipText,
|
|
9766
|
+
x: event.clientX,
|
|
9767
|
+
y: event.clientY
|
|
9768
|
+
});
|
|
9769
|
+
},
|
|
9770
|
+
onMouseMove: (event) => {
|
|
9771
|
+
if (!cell.inRange) {
|
|
9772
|
+
return;
|
|
9773
|
+
}
|
|
9774
|
+
setContributionTooltip({
|
|
9775
|
+
text: tooltipText,
|
|
9776
|
+
x: event.clientX,
|
|
9777
|
+
y: event.clientY
|
|
9778
|
+
});
|
|
9779
|
+
},
|
|
9780
|
+
onMouseLeave: () => {
|
|
9781
|
+
setContributionTooltip(null);
|
|
9782
|
+
},
|
|
9783
|
+
onFocus: (event) => {
|
|
9784
|
+
if (!cell.inRange) {
|
|
9785
|
+
return;
|
|
9786
|
+
}
|
|
9787
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
9788
|
+
setContributionTooltip({
|
|
9789
|
+
text: tooltipText,
|
|
9790
|
+
x: rect.left + rect.width / 2,
|
|
9791
|
+
y: rect.bottom + 4
|
|
9792
|
+
});
|
|
9793
|
+
},
|
|
9794
|
+
onBlur: () => {
|
|
9795
|
+
setContributionTooltip(null);
|
|
9796
|
+
}
|
|
9797
|
+
},
|
|
9798
|
+
cell.date
|
|
9799
|
+
);
|
|
9800
|
+
}) }, `week-${weekIndex}`))
|
|
9801
|
+
}
|
|
9802
|
+
)
|
|
9803
|
+
] })
|
|
9804
|
+
] }),
|
|
9805
|
+
contributionTooltip ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
9806
|
+
"div",
|
|
9807
|
+
{
|
|
9808
|
+
className: "stats-contrib-tooltip",
|
|
9809
|
+
role: "tooltip",
|
|
9810
|
+
style: {
|
|
9811
|
+
left: `${contributionTooltip.x + 12}px`,
|
|
9812
|
+
top: `${contributionTooltip.y + 12}px`
|
|
9813
|
+
},
|
|
9814
|
+
children: contributionTooltip.text
|
|
9815
|
+
}
|
|
9816
|
+
) : null
|
|
9817
|
+
] }),
|
|
9583
9818
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "stats-grid-2", children: [
|
|
9584
9819
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("article", { className: "stats-section", children: [
|
|
9585
9820
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "stats-section-header", children: [
|
|
@@ -11149,12 +11384,15 @@ function parseCommandPreview(execution) {
|
|
|
11149
11384
|
return null;
|
|
11150
11385
|
}
|
|
11151
11386
|
const ExecutionTrace = ({ execution }) => {
|
|
11152
|
-
var _a, _b, _c;
|
|
11387
|
+
var _a, _b, _c, _d, _e;
|
|
11153
11388
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
11154
11389
|
const output = (_b = (_a = execution.functionOutput) == null ? void 0 : _a.output) != null ? _b : "";
|
|
11155
11390
|
const commandPreview = reactExports.useMemo(() => parseCommandPreview(execution), [execution]);
|
|
11156
11391
|
const isTerminalCommand = reactExports.useMemo(() => isTerminalCommandExecution(execution), [execution]);
|
|
11157
|
-
const tokenUsageLabel = execution.tokenUsage ? `${execution.tokenUsage.inputTokens.toLocaleString()} in
|
|
11392
|
+
const tokenUsageLabel = execution.tokenUsage ? `${execution.tokenUsage.inputTokens.toLocaleString()} in (${((_c = execution.tokenUsage.cachedInputTokens) != null ? _c : 0).toLocaleString()} cached + ${Math.max(
|
|
11393
|
+
execution.tokenUsage.inputTokens - ((_d = execution.tokenUsage.cachedInputTokens) != null ? _d : 0),
|
|
11394
|
+
0
|
|
11395
|
+
).toLocaleString()} uncached) • ${execution.tokenUsage.outputTokens.toLocaleString()} out` : null;
|
|
11158
11396
|
const formattedArguments = reactExports.useMemo(
|
|
11159
11397
|
() => prettyPrintJson(execution.functionCall.arguments),
|
|
11160
11398
|
[execution.functionCall.arguments]
|
|
@@ -11163,7 +11401,7 @@ const ExecutionTrace = ({ execution }) => {
|
|
|
11163
11401
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11164
11402
|
"section",
|
|
11165
11403
|
{
|
|
11166
|
-
className: `trace-card ${((
|
|
11404
|
+
className: `trace-card ${((_e = execution.functionOutput) == null ? void 0 : _e.isError) ? "error" : ""} ${isTerminalCommand ? "terminal" : ""}`,
|
|
11167
11405
|
children: [
|
|
11168
11406
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11169
11407
|
"button",
|
|
@@ -11211,7 +11449,9 @@ const ExecutionTraceGroup = ({
|
|
|
11211
11449
|
}) => {
|
|
11212
11450
|
const [expanded, setExpanded] = reactExports.useState(false);
|
|
11213
11451
|
const tokenTotals = reactExports.useMemo(() => {
|
|
11452
|
+
var _a;
|
|
11214
11453
|
let inputTokens = 0;
|
|
11454
|
+
let cachedInputTokens = 0;
|
|
11215
11455
|
let outputTokens = 0;
|
|
11216
11456
|
let hasTokenUsage = false;
|
|
11217
11457
|
for (const execution of executions) {
|
|
@@ -11220,15 +11460,19 @@ const ExecutionTraceGroup = ({
|
|
|
11220
11460
|
}
|
|
11221
11461
|
hasTokenUsage = true;
|
|
11222
11462
|
inputTokens += execution.tokenUsage.inputTokens;
|
|
11463
|
+
cachedInputTokens += (_a = execution.tokenUsage.cachedInputTokens) != null ? _a : 0;
|
|
11223
11464
|
outputTokens += execution.tokenUsage.outputTokens;
|
|
11224
11465
|
}
|
|
11225
|
-
return { hasTokenUsage, inputTokens, outputTokens };
|
|
11466
|
+
return { hasTokenUsage, inputTokens, cachedInputTokens, outputTokens };
|
|
11226
11467
|
}, [executions]);
|
|
11227
11468
|
if (executions.length === 0) {
|
|
11228
11469
|
return null;
|
|
11229
11470
|
}
|
|
11230
11471
|
const countLabel = `${executions.length} command${executions.length === 1 ? "" : "s"}`;
|
|
11231
|
-
const tokenUsageLabel = tokenTotals.hasTokenUsage ? `${tokenTotals.inputTokens.toLocaleString()} in
|
|
11472
|
+
const tokenUsageLabel = tokenTotals.hasTokenUsage ? `${tokenTotals.inputTokens.toLocaleString()} in (${tokenTotals.cachedInputTokens.toLocaleString()} cached + ${Math.max(
|
|
11473
|
+
tokenTotals.inputTokens - tokenTotals.cachedInputTokens,
|
|
11474
|
+
0
|
|
11475
|
+
).toLocaleString()} uncached) • ${tokenTotals.outputTokens.toLocaleString()} out` : null;
|
|
11232
11476
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "trace-group-card", children: [
|
|
11233
11477
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11234
11478
|
"button",
|
|
@@ -1021,6 +1021,25 @@ select {
|
|
|
1021
1021
|
letter-spacing: 0.06em;
|
|
1022
1022
|
}
|
|
1023
1023
|
|
|
1024
|
+
.stats-section-header-actions {
|
|
1025
|
+
margin-left: auto;
|
|
1026
|
+
display: inline-flex;
|
|
1027
|
+
align-items: center;
|
|
1028
|
+
gap: 8px;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.stats-section-header-actions .sidebar-label,
|
|
1032
|
+
.stats-section-header-actions .stats-section-subtle {
|
|
1033
|
+
white-space: nowrap;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.stats-contrib-select {
|
|
1037
|
+
width: auto;
|
|
1038
|
+
min-width: 156px;
|
|
1039
|
+
padding: 6px 9px;
|
|
1040
|
+
font-size: 0.78rem;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1024
1043
|
.stats-day-list {
|
|
1025
1044
|
list-style: none;
|
|
1026
1045
|
margin: 0;
|
|
@@ -1061,6 +1080,120 @@ select {
|
|
|
1061
1080
|
background: linear-gradient(90deg, rgba(59, 130, 246, 0.8), rgba(56, 189, 248, 0.85));
|
|
1062
1081
|
}
|
|
1063
1082
|
|
|
1083
|
+
.stats-contrib-frame {
|
|
1084
|
+
display: grid;
|
|
1085
|
+
grid-template-columns: 30px minmax(0, 1fr);
|
|
1086
|
+
gap: 8px;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.stats-contrib-weekdays {
|
|
1090
|
+
display: grid;
|
|
1091
|
+
grid-template-rows: repeat(7, 12px);
|
|
1092
|
+
gap: 3px;
|
|
1093
|
+
padding-top: 18px;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.stats-contrib-weekdays span {
|
|
1097
|
+
font-size: 0.63rem;
|
|
1098
|
+
line-height: 12px;
|
|
1099
|
+
color: var(--text-muted);
|
|
1100
|
+
text-align: right;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.stats-contrib-scroll {
|
|
1104
|
+
min-width: 0;
|
|
1105
|
+
overflow-x: auto;
|
|
1106
|
+
overflow-y: hidden;
|
|
1107
|
+
padding-bottom: 2px;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.stats-contrib-months {
|
|
1111
|
+
display: grid;
|
|
1112
|
+
gap: 3px;
|
|
1113
|
+
margin-bottom: 4px;
|
|
1114
|
+
min-width: -moz-max-content;
|
|
1115
|
+
min-width: max-content;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
.stats-contrib-month {
|
|
1119
|
+
font-size: 0.66rem;
|
|
1120
|
+
color: var(--text-muted);
|
|
1121
|
+
font-family: var(--font-mono);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
.stats-contrib-weeks {
|
|
1125
|
+
display: flex;
|
|
1126
|
+
gap: 3px;
|
|
1127
|
+
min-width: -moz-max-content;
|
|
1128
|
+
min-width: max-content;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
.stats-contrib-week {
|
|
1132
|
+
display: grid;
|
|
1133
|
+
grid-template-rows: repeat(7, 12px);
|
|
1134
|
+
gap: 3px;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
.stats-contrib-cell {
|
|
1138
|
+
width: 12px;
|
|
1139
|
+
height: 12px;
|
|
1140
|
+
border-radius: 3px;
|
|
1141
|
+
border: 1px solid rgba(59, 130, 246, 0.25);
|
|
1142
|
+
background: rgba(59, 130, 246, 0.08);
|
|
1143
|
+
cursor: pointer;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
.stats-contrib-cell.level-0 {
|
|
1147
|
+
background: rgba(59, 130, 246, 0.08);
|
|
1148
|
+
border-color: rgba(59, 130, 246, 0.2);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
.stats-contrib-cell.level-1 {
|
|
1152
|
+
background: rgba(59, 130, 246, 0.28);
|
|
1153
|
+
border-color: rgba(59, 130, 246, 0.3);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
.stats-contrib-cell.level-2 {
|
|
1157
|
+
background: rgba(59, 130, 246, 0.46);
|
|
1158
|
+
border-color: rgba(59, 130, 246, 0.45);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
.stats-contrib-cell.level-3 {
|
|
1162
|
+
background: rgba(59, 130, 246, 0.64);
|
|
1163
|
+
border-color: rgba(59, 130, 246, 0.6);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
.stats-contrib-cell.level-4 {
|
|
1167
|
+
background: rgba(59, 130, 246, 0.82);
|
|
1168
|
+
border-color: rgba(59, 130, 246, 0.78);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
.stats-contrib-cell.is-empty {
|
|
1172
|
+
background: rgba(59, 130, 246, 0.05);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
.stats-contrib-cell.is-padding {
|
|
1176
|
+
background: transparent;
|
|
1177
|
+
border-color: transparent;
|
|
1178
|
+
cursor: default;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
.stats-contrib-tooltip {
|
|
1182
|
+
position: fixed;
|
|
1183
|
+
z-index: 30;
|
|
1184
|
+
max-width: min(320px, calc(100vw - 24px));
|
|
1185
|
+
border: 1px solid var(--border-strong);
|
|
1186
|
+
border-radius: 8px;
|
|
1187
|
+
background: var(--bg-panel-raised);
|
|
1188
|
+
color: var(--text-primary);
|
|
1189
|
+
padding: 6px 8px;
|
|
1190
|
+
font-size: 0.72rem;
|
|
1191
|
+
font-family: var(--font-mono);
|
|
1192
|
+
line-height: 1.3;
|
|
1193
|
+
pointer-events: none;
|
|
1194
|
+
white-space: nowrap;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1064
1197
|
.stats-grid-2 {
|
|
1065
1198
|
display: grid;
|
|
1066
1199
|
gap: 12px;
|
|
@@ -1387,6 +1520,30 @@ select {
|
|
|
1387
1520
|
gap: 8px;
|
|
1388
1521
|
}
|
|
1389
1522
|
|
|
1523
|
+
.stats-section-header-actions {
|
|
1524
|
+
width: 100%;
|
|
1525
|
+
margin-left: 0;
|
|
1526
|
+
justify-content: space-between;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
.stats-contrib-select {
|
|
1530
|
+
flex: 1;
|
|
1531
|
+
min-width: 0;
|
|
1532
|
+
max-width: 180px;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
.stats-contrib-frame {
|
|
1536
|
+
grid-template-columns: 1fr;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
.stats-contrib-weekdays {
|
|
1540
|
+
display: none;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
.stats-contrib-month {
|
|
1544
|
+
font-size: 0.6rem;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1390
1547
|
.chat-session-token-strip {
|
|
1391
1548
|
flex-wrap: wrap;
|
|
1392
1549
|
gap: 8px;
|
package/out/renderer/index.html
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<link rel="icon" type="image/png" sizes="32x32" href="./assets/32x32-DQgygEFU.png" />
|
|
8
8
|
<link rel="icon" type="image/png" sizes="16x16" href="./assets/16x16-B2_QkmoB.png" />
|
|
9
9
|
<title>codex-devtools</title>
|
|
10
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-5ydAmpDO.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="./assets/index-Cgat1ue6.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="root">
|