omp-usage-analyzer 0.1.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/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # OMP Usage Analyzer CLI
2
+
3
+ Run directly with `bunx`:
4
+
5
+ ```sh
6
+ bunx omp-usage-analyzer
7
+ ```
8
+
9
+ Or run locally:
10
+
11
+ ```sh
12
+ bun run report -- --no-open
13
+ ```
14
+
15
+ CLI flags:
16
+
17
+ - `-o, --out <dir>`: output directory (defaults to temporary directory)
18
+ - `--no-open`: do not open the report in the browser
19
+ - `--sync`: synchronize sessions across all Oh My Pi projects first
20
+ - `--start <YYYY-MM-DD>`: first included day
21
+ - `--end <YYYY-MM-DD>`: last included day
22
+ - `-h, --help`: show help message
23
+
24
+ See root [README.md](../README.md) for full documentation.
package/dist/cli.js ADDED
@@ -0,0 +1,868 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/cli.ts
5
+ import { parseArgs } from "util";
6
+ import * as fs2 from "fs";
7
+ import * as os from "os";
8
+ import * as path2 from "path";
9
+
10
+ // src/open.ts
11
+ import * as fs from "fs";
12
+ import * as path from "path";
13
+ function windowsOpenerCommand(target) {
14
+ const systemRoot = process.env.SystemRoot || "C:\\Windows";
15
+ const absolute = path.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
16
+ const powershell = fs.existsSync(absolute) ? absolute : "powershell.exe";
17
+ const script = `$ErrorActionPreference='Stop';Start-Process '${target.replaceAll("'", "''")}'`;
18
+ return [
19
+ powershell,
20
+ "-NoProfile",
21
+ "-NonInteractive",
22
+ "-EncodedCommand",
23
+ Buffer.from(script, "utf16le").toString("base64")
24
+ ];
25
+ }
26
+ function openInBrowser(urlOrPath) {
27
+ let cmd;
28
+ switch (process.platform) {
29
+ case "darwin":
30
+ cmd = ["open", urlOrPath];
31
+ break;
32
+ case "win32":
33
+ cmd = windowsOpenerCommand(urlOrPath);
34
+ break;
35
+ default:
36
+ cmd = ["xdg-open", urlOrPath];
37
+ break;
38
+ }
39
+ try {
40
+ Bun.spawn(cmd, {
41
+ stdin: "ignore",
42
+ stdout: "ignore",
43
+ stderr: "ignore",
44
+ windowsHide: process.platform === "win32"
45
+ });
46
+ } catch (err) {
47
+ console.warn("Failed to automatically open browser:", err);
48
+ }
49
+ }
50
+
51
+ // src/db.ts
52
+ import { Database } from "bun:sqlite";
53
+ import { getStatsDbPath } from "@oh-my-pi/pi-utils";
54
+ import { syncAllSessions } from "@oh-my-pi/omp-stats";
55
+
56
+ // ../shared/src/index.ts
57
+ var ADVICE_SEVERITIES = ["warning", "concern", "critical", "error", "blocker"];
58
+
59
+ // src/advisor-advice.ts
60
+ var MATERIAL_SEVERITY_ALIASES = {
61
+ warn: "warning",
62
+ warning: "warning",
63
+ concern: "concern",
64
+ critical: "critical",
65
+ fatal: "critical",
66
+ error: "error",
67
+ blocker: "blocker",
68
+ blocked: "blocker"
69
+ };
70
+ var ADVISORY_TAG_PATTERN = /<advisory\b([^>]*?)(?:\/>|>([\s\S]*?)<\/advisory\s*>)/gi;
71
+ var MARKER_PATTERN = /(?:^|\n)\s*\[?(warning|warn|concern|critical|error|fatal|blocker|blocked)\]?\s*:/gi;
72
+ function createEmptyAdviceCounts() {
73
+ return { warning: 0, concern: 0, critical: 0, error: 0, blocker: 0 };
74
+ }
75
+ function countAdvicePieces(counts) {
76
+ return ADVICE_SEVERITIES.reduce((total, severity) => total + counts[severity], 0);
77
+ }
78
+ function addAdviceCounts(target, source) {
79
+ for (const severity of ADVICE_SEVERITIES)
80
+ target[severity] += source[severity];
81
+ return target;
82
+ }
83
+ function extractAdvisorAdviceByEntry(sessionJsonl) {
84
+ const byEntry = new Map;
85
+ const pendingCalls = new Map;
86
+ const completedCalls = new Set;
87
+ for (const line of sessionJsonl.split(/\r?\n/)) {
88
+ if (!line.trim())
89
+ continue;
90
+ let entry;
91
+ try {
92
+ entry = JSON.parse(line);
93
+ } catch {
94
+ continue;
95
+ }
96
+ if (entry.type !== "message" || typeof entry.id !== "string")
97
+ continue;
98
+ const message = entry.message;
99
+ if (!message || !Array.isArray(message.content))
100
+ continue;
101
+ if (message.role === "assistant") {
102
+ const counts = createEmptyAdviceCounts();
103
+ for (const value of message.content) {
104
+ if (!value || typeof value !== "object")
105
+ continue;
106
+ const block = value;
107
+ if (block.type === "text" && typeof block.text === "string") {
108
+ addAdviceCounts(counts, extractTextAdvice(block.text));
109
+ continue;
110
+ }
111
+ if (block.type !== "toolCall" || block.name !== "advise" || typeof block.id !== "string") {
112
+ continue;
113
+ }
114
+ const severity2 = normalizeMaterialSeverity(block.arguments?.severity);
115
+ pendingCalls.set(block.id, { entryId: entry.id, severity: severity2 });
116
+ }
117
+ mergeEntryCounts(byEntry, entry.id, counts);
118
+ continue;
119
+ }
120
+ if (message.role !== "toolResult" || message.toolName !== "advise")
121
+ continue;
122
+ const parentId = typeof entry.parentId === "string" ? entry.parentId : undefined;
123
+ const callId = typeof message.toolCallId === "string" ? message.toolCallId : undefined;
124
+ const pending = callId ? pendingCalls.get(callId) : undefined;
125
+ const severity = normalizeMaterialSeverity(message.details?.severity);
126
+ const entryId = parentId ?? pending?.entryId;
127
+ if (callId)
128
+ completedCalls.add(callId);
129
+ if (entryId && severity)
130
+ increment(byEntry, entryId, severity);
131
+ }
132
+ for (const [callId, call] of pendingCalls) {
133
+ if (!completedCalls.has(callId) && call.severity)
134
+ increment(byEntry, call.entryId, call.severity);
135
+ }
136
+ return byEntry;
137
+ }
138
+ function extractTextAdvice(text) {
139
+ const counts = createEmptyAdviceCounts();
140
+ const textOutsideTags = text.replace(ADVISORY_TAG_PATTERN, (_match, attributes, body) => {
141
+ const severityMatch = String(attributes).match(/\bseverity\s*=\s*["']([^"']+)["']/i);
142
+ const severity = normalizeMaterialSeverity(severityMatch?.[1]);
143
+ if (severity) {
144
+ counts[severity] += 1;
145
+ } else if (!severityMatch && (/\bguidance\s*=/i.test(attributes) || String(body ?? "").trim())) {
146
+ counts.warning += 1;
147
+ }
148
+ return "";
149
+ });
150
+ for (const match of textOutsideTags.matchAll(MARKER_PATTERN)) {
151
+ const severity = normalizeMaterialSeverity(match[1]);
152
+ if (severity)
153
+ counts[severity] += 1;
154
+ }
155
+ return counts;
156
+ }
157
+ function normalizeMaterialSeverity(value) {
158
+ return typeof value === "string" ? MATERIAL_SEVERITY_ALIASES[value.trim().toLowerCase()] : undefined;
159
+ }
160
+ function increment(byEntry, entryId, severity) {
161
+ const counts = byEntry.get(entryId) ?? createEmptyAdviceCounts();
162
+ counts[severity] += 1;
163
+ byEntry.set(entryId, counts);
164
+ }
165
+ function mergeEntryCounts(byEntry, entryId, counts) {
166
+ if (!countAdvicePieces(counts))
167
+ return;
168
+ const existing = byEntry.get(entryId);
169
+ if (existing) {
170
+ addAdviceCounts(existing, counts);
171
+ } else {
172
+ byEntry.set(entryId, counts);
173
+ }
174
+ }
175
+
176
+ // src/db.ts
177
+ async function loadRawUsageRecords(options = {}) {
178
+ const dbPath = options.dbPath || getStatsDbPath();
179
+ if (options.sync) {
180
+ try {
181
+ await syncAllSessions({ workers: 2 });
182
+ } catch (err) {
183
+ console.warn("Warning: stats sync was skipped or failed:", err);
184
+ }
185
+ }
186
+ const db = new Database(dbPath, { readonly: true });
187
+ try {
188
+ let query = `
189
+ SELECT
190
+ id,
191
+ session_file,
192
+ entry_id,
193
+ folder,
194
+ model,
195
+ provider,
196
+ api,
197
+ timestamp,
198
+ date(timestamp / 1000, 'unixepoch', 'localtime') as day,
199
+ duration,
200
+ ttft,
201
+ input_tokens,
202
+ output_tokens,
203
+ cache_read_tokens,
204
+ cache_write_tokens,
205
+ total_tokens,
206
+ agent_type,
207
+ cost_total
208
+ FROM messages
209
+ WHERE 1=1
210
+ `;
211
+ const params = [];
212
+ if (options.range?.startDay) {
213
+ query += ` AND date(timestamp / 1000, 'unixepoch', 'localtime') >= ?`;
214
+ params.push(options.range.startDay);
215
+ }
216
+ if (options.range?.endDay) {
217
+ query += ` AND date(timestamp / 1000, 'unixepoch', 'localtime') <= ?`;
218
+ params.push(options.range.endDay);
219
+ }
220
+ query += ` ORDER BY timestamp ASC`;
221
+ const stmt = db.prepare(query);
222
+ const rows = stmt.all(...params);
223
+ const adviceByFile = new Map;
224
+ const advisorSessionFiles = [
225
+ ...new Set(rows.filter((row) => row.agent_type === "advisor").map((row) => row.session_file))
226
+ ];
227
+ for (const sessionFile of advisorSessionFiles) {
228
+ const file = Bun.file(sessionFile);
229
+ if (!await file.exists())
230
+ continue;
231
+ adviceByFile.set(sessionFile, extractAdvisorAdviceByEntry(await file.text()));
232
+ }
233
+ return rows.map((row) => {
234
+ let role = "unknown";
235
+ if (row.agent_type === "advisor")
236
+ role = "advisor";
237
+ else if (row.agent_type === "subagent")
238
+ role = "subagent";
239
+ else if (row.agent_type === "main")
240
+ role = "main";
241
+ return {
242
+ id: row.id,
243
+ sessionFile: row.session_file,
244
+ entryId: row.entry_id,
245
+ folder: row.folder || "global",
246
+ model: row.model,
247
+ provider: row.provider,
248
+ api: row.api,
249
+ timestamp: row.timestamp,
250
+ day: row.day,
251
+ inputTokens: row.input_tokens || 0,
252
+ duration: row.duration,
253
+ ttft: row.ttft,
254
+ outputTokens: row.output_tokens || 0,
255
+ cacheReadTokens: row.cache_read_tokens || 0,
256
+ cacheWriteTokens: row.cache_write_tokens || 0,
257
+ totalTokens: row.total_tokens || 0,
258
+ agentType: role,
259
+ dbCostTotal: row.cost_total || 0,
260
+ adviceBySeverity: adviceByFile.get(row.session_file)?.get(row.entry_id)
261
+ };
262
+ });
263
+ } finally {
264
+ db.close();
265
+ }
266
+ }
267
+
268
+ // src/pricing.ts
269
+ import { getBundledModel } from "@oh-my-pi/pi-catalog";
270
+ var KNOWN_MODEL_PRICING = {
271
+ "gpt-5.6-sol": { input: 5, output: 15, cacheRead: 1.25, cacheWrite: 5 },
272
+ "gpt-5.6-luna": { input: 3, output: 10, cacheRead: 0.75, cacheWrite: 3 },
273
+ "gpt-5.6-terra": { input: 0.5, output: 2, cacheRead: 0.125, cacheWrite: 0.5 },
274
+ "gpt-5.5": { input: 2.5, output: 10, cacheRead: 0.625, cacheWrite: 2.5 },
275
+ "gpt-5.3-codex-spark": { input: 0.25, output: 1, cacheRead: 0.0625, cacheWrite: 0.25 },
276
+ "gpt-5": { input: 5, output: 15, cacheRead: 1.25, cacheWrite: 5 },
277
+ "gpt-4o": { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 2.5 },
278
+ "gpt-4o-mini": { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0.15 },
279
+ o1: { input: 15, output: 60, cacheRead: 7.5, cacheWrite: 15 },
280
+ "o1-mini": { input: 3, output: 12, cacheRead: 1.5, cacheWrite: 3 },
281
+ "o3-mini": { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 1.1 },
282
+ "grok-4.6": { input: 2, output: 10, cacheRead: 0.5, cacheWrite: 2 },
283
+ "grok-2-1212": { input: 2, output: 10, cacheRead: 0.5, cacheWrite: 2 },
284
+ "grok-beta": { input: 5, output: 15, cacheRead: 1.25, cacheWrite: 5 },
285
+ "deepseek/deepseek-v4-flash-0731": {
286
+ input: 0.14,
287
+ output: 0.28,
288
+ cacheRead: 0.014,
289
+ cacheWrite: 0.14
290
+ },
291
+ "deepseek/deepseek-v4-flash-0731:small": {
292
+ input: 0.1,
293
+ output: 0.2,
294
+ cacheRead: 0.01,
295
+ cacheWrite: 0.1
296
+ },
297
+ "deepseek/deepseek-chat": { input: 0.14, output: 0.28, cacheRead: 0.014, cacheWrite: 0.14 },
298
+ "deepseek/deepseek-coder": { input: 0.14, output: 0.28, cacheRead: 0.014, cacheWrite: 0.14 },
299
+ "deepseek/deepseek-r1": { input: 0.55, output: 2.19, cacheRead: 0.14, cacheWrite: 0.55 },
300
+ "stealth/ox-alpha": { input: 0.5, output: 1.5, cacheRead: 0.125, cacheWrite: 0.5 },
301
+ "openrouter/free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
302
+ "gemini-3.7-flash": { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0.075 },
303
+ "gemini-3.7-flash-tiered": { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0.075 },
304
+ "gemini-2.0-flash": { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0.1 },
305
+ "gemini-1.5-pro": { input: 1.25, output: 5, cacheRead: 0.3125, cacheWrite: 1.25 },
306
+ "gemini-1.5-flash": { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0.075 },
307
+ "cursor-grok-4.5-medium-fast": { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 2 },
308
+ "cursor-grok-4.6-low": { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 1 },
309
+ "composer-2.5-fast": { input: 1.5, output: 6, cacheRead: 0.375, cacheWrite: 1.5 },
310
+ "claude-3-5-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
311
+ "claude-3-5-haiku": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
312
+ "claude-fable-5": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
313
+ "claude-3-opus": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }
314
+ };
315
+ function getHistoricalFallbackRates(modelId) {
316
+ const lower = modelId.toLowerCase();
317
+ if (lower.includes("flash") || lower.includes("mini") || lower.includes("haiku") || lower.includes("terra") || lower.includes("spark") || lower.includes("small") || lower.includes("low") || lower.includes("free")) {
318
+ return {
319
+ input: 0.25,
320
+ output: 1,
321
+ cacheRead: 0.0625,
322
+ cacheWrite: 0.25
323
+ };
324
+ }
325
+ if (lower.includes("opus") || lower.includes("sol") || lower.includes("o1") || lower.includes("r1") || lower.includes("high")) {
326
+ return {
327
+ input: 5,
328
+ output: 15,
329
+ cacheRead: 1.25,
330
+ cacheWrite: 5
331
+ };
332
+ }
333
+ return {
334
+ input: 2,
335
+ output: 8,
336
+ cacheRead: 0.5,
337
+ cacheWrite: 2
338
+ };
339
+ }
340
+ function getModelPricingRates(modelId, provider) {
341
+ if (KNOWN_MODEL_PRICING[modelId]) {
342
+ return { rates: KNOWN_MODEL_PRICING[modelId], isFallback: false };
343
+ }
344
+ if (provider) {
345
+ try {
346
+ const catModel = getBundledModel(provider, modelId);
347
+ if (catModel?.cost) {
348
+ return {
349
+ rates: {
350
+ input: catModel.cost.input,
351
+ output: catModel.cost.output,
352
+ cacheRead: catModel.cost.cacheRead,
353
+ cacheWrite: catModel.cost.cacheWrite
354
+ },
355
+ isFallback: false
356
+ };
357
+ }
358
+ } catch {}
359
+ }
360
+ return { rates: getHistoricalFallbackRates(modelId), isFallback: true };
361
+ }
362
+ function createEmptyTokens() {
363
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
364
+ }
365
+ function createEmptyCost() {
366
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
367
+ }
368
+ function calculateCostFromRates(rates, tokens) {
369
+ const inputCost = tokens.input / 1e6 * rates.input;
370
+ const outputCost = tokens.output / 1e6 * rates.output;
371
+ const cacheReadCost = tokens.cacheRead / 1e6 * rates.cacheRead;
372
+ const cacheWriteCost = tokens.cacheWrite / 1e6 * rates.cacheWrite;
373
+ const total = inputCost + outputCost + cacheReadCost + cacheWriteCost;
374
+ return {
375
+ input: inputCost,
376
+ output: outputCost,
377
+ cacheRead: cacheReadCost,
378
+ cacheWrite: cacheWriteCost,
379
+ total
380
+ };
381
+ }
382
+ function addTokens(a, b) {
383
+ return {
384
+ input: a.input + b.input,
385
+ output: a.output + b.output,
386
+ cacheRead: a.cacheRead + b.cacheRead,
387
+ cacheWrite: a.cacheWrite + b.cacheWrite,
388
+ total: a.total + b.total
389
+ };
390
+ }
391
+ function addCost(a, b) {
392
+ return {
393
+ input: a.input + b.input,
394
+ output: a.output + b.output,
395
+ cacheRead: a.cacheRead + b.cacheRead,
396
+ cacheWrite: a.cacheWrite + b.cacheWrite,
397
+ total: a.total + b.total
398
+ };
399
+ }
400
+ function getProjectNameFromFolder(folder) {
401
+ if (!folder || folder === "/" || folder === ".")
402
+ return "global";
403
+ let clean = folder.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
404
+ clean = clean.replace(/^[A-Za-z]:\/?/, "");
405
+ const wtMatch = clean.match(/worktrees-([a-zA-Z0-9_-]+?)-([a-zA-Z0-9_-]+?)-\1/i);
406
+ if (wtMatch) {
407
+ return `${wtMatch[1]} (${wtMatch[2]})`;
408
+ }
409
+ const segments = clean.split("/").filter(Boolean);
410
+ const lastSeg = segments[segments.length - 1] || clean;
411
+ const simplified = lastSeg.replace(/^Projects?-/i, "").replace(/^(oss|proj|test)-/i, "").replace(/--+$/, "").replace(/^--+/, "");
412
+ return simplified || lastSeg;
413
+ }
414
+
415
+ // src/aggregator.ts
416
+ function aggregateModelSpeeds(records) {
417
+ const byModel = new Map;
418
+ for (const record of records) {
419
+ const model = record.model || "unknown-model";
420
+ const provider = record.provider || "unknown-provider";
421
+ const key = `${provider}\x00${model}`;
422
+ let stats = byModel.get(key);
423
+ if (!stats) {
424
+ stats = {
425
+ model,
426
+ provider,
427
+ lastUsed: record.timestamp,
428
+ requestCount: 0,
429
+ speeds: [],
430
+ ttftTotal: 0,
431
+ ttftCount: 0,
432
+ durationTotal: 0,
433
+ durationCount: 0,
434
+ totalOutputTokens: 0
435
+ };
436
+ byModel.set(key, stats);
437
+ }
438
+ stats.lastUsed = Math.max(stats.lastUsed, record.timestamp);
439
+ stats.requestCount += 1;
440
+ stats.totalOutputTokens += record.outputTokens;
441
+ const duration = record.duration;
442
+ if (duration != null && Number.isFinite(duration) && duration > 0) {
443
+ stats.durationTotal += duration;
444
+ stats.durationCount += 1;
445
+ if (record.outputTokens > 0) {
446
+ stats.speeds.push(record.outputTokens / (duration / 1000));
447
+ }
448
+ }
449
+ const ttft = record.ttft;
450
+ if (ttft != null && Number.isFinite(ttft) && ttft >= 0) {
451
+ stats.ttftTotal += ttft;
452
+ stats.ttftCount += 1;
453
+ }
454
+ }
455
+ const result = [];
456
+ for (const stats of byModel.values()) {
457
+ stats.speeds.sort((a, b) => a - b);
458
+ const midpoint = Math.floor(stats.speeds.length / 2);
459
+ const median = stats.speeds.length === 0 ? null : stats.speeds.length % 2 === 0 ? (stats.speeds[midpoint - 1] + stats.speeds[midpoint]) / 2 : stats.speeds[midpoint];
460
+ result.push({
461
+ model: stats.model,
462
+ provider: stats.provider,
463
+ lastUsed: stats.lastUsed,
464
+ requestCount: stats.requestCount,
465
+ timedRequestCount: stats.durationCount,
466
+ avgTokensPerSec: stats.speeds.length ? stats.speeds.reduce((total, speed) => total + speed, 0) / stats.speeds.length : null,
467
+ medianTokensPerSec: median,
468
+ avgTtftMs: stats.ttftCount ? stats.ttftTotal / stats.ttftCount : null,
469
+ avgDurationMs: stats.durationCount ? stats.durationTotal / stats.durationCount : null,
470
+ totalOutputTokens: stats.totalOutputTokens
471
+ });
472
+ }
473
+ return result.sort((a, b) => b.lastUsed - a.lastUsed);
474
+ }
475
+ function aggregateUsageRecords(records) {
476
+ const pricingRatesMap = {};
477
+ const fallbackModelSet = new Set;
478
+ const daysMap = {};
479
+ const projectsMap = {};
480
+ const modelsMap = {};
481
+ const advisorByDay = {};
482
+ const advisorByModel = {};
483
+ let overallTokens = createEmptyTokens();
484
+ let overallCost = createEmptyCost();
485
+ let overallRequests = 0;
486
+ let advisorTotalTokens = createEmptyTokens();
487
+ let advisorTotalCost = createEmptyCost();
488
+ let advisorTotalPieces = 0;
489
+ const advisorAdviceBySeverity = createEmptyAdviceCounts();
490
+ let mainTokens = 0;
491
+ let subagentTokens = 0;
492
+ let advisorTokens = 0;
493
+ let mainCost = 0;
494
+ let subagentCost = 0;
495
+ let advisorCost = 0;
496
+ let minDay = "";
497
+ let maxDay = "";
498
+ for (const record of records) {
499
+ const day = record.day;
500
+ if (!minDay || day < minDay)
501
+ minDay = day;
502
+ if (!maxDay || day > maxDay)
503
+ maxDay = day;
504
+ const modelName = record.model || "unknown-model";
505
+ const provider = record.provider || "unknown-provider";
506
+ let rates = pricingRatesMap[modelName];
507
+ if (!rates) {
508
+ const resolved = getModelPricingRates(modelName, provider);
509
+ rates = resolved.rates;
510
+ pricingRatesMap[modelName] = rates;
511
+ if (resolved.isFallback) {
512
+ fallbackModelSet.add(modelName);
513
+ }
514
+ }
515
+ const currentTokens = {
516
+ input: record.inputTokens,
517
+ output: record.outputTokens,
518
+ cacheRead: record.cacheReadTokens,
519
+ cacheWrite: record.cacheWriteTokens,
520
+ total: record.totalTokens
521
+ };
522
+ const currentCost = calculateCostFromRates(rates, currentTokens);
523
+ overallTokens = addTokens(overallTokens, currentTokens);
524
+ overallCost = addCost(overallCost, currentCost);
525
+ overallRequests += 1;
526
+ if (record.agentType === "advisor") {
527
+ advisorTokens += currentTokens.total;
528
+ advisorCost += currentCost.total;
529
+ } else if (record.agentType === "subagent") {
530
+ subagentTokens += currentTokens.total;
531
+ subagentCost += currentCost.total;
532
+ } else {
533
+ mainTokens += currentTokens.total;
534
+ mainCost += currentCost.total;
535
+ }
536
+ if (!daysMap[day]) {
537
+ daysMap[day] = {
538
+ day,
539
+ tokens: createEmptyTokens(),
540
+ cost: createEmptyCost(),
541
+ requests: 0,
542
+ activeProjects: 0,
543
+ activeModels: 0,
544
+ advisorTokens: 0,
545
+ advisorCost: 0,
546
+ advisorAdvicePieces: 0
547
+ };
548
+ }
549
+ const daySummary = daysMap[day];
550
+ daySummary.tokens = addTokens(daySummary.tokens, currentTokens);
551
+ daySummary.cost = addCost(daySummary.cost, currentCost);
552
+ daySummary.requests += 1;
553
+ const folder = record.folder || "global";
554
+ if (!projectsMap[folder]) {
555
+ projectsMap[folder] = {
556
+ folder,
557
+ projectName: getProjectNameFromFolder(folder),
558
+ tokens: createEmptyTokens(),
559
+ cost: createEmptyCost(),
560
+ requests: 0,
561
+ byDay: {},
562
+ byModel: {}
563
+ };
564
+ }
565
+ const projectSummary = projectsMap[folder];
566
+ projectSummary.tokens = addTokens(projectSummary.tokens, currentTokens);
567
+ projectSummary.cost = addCost(projectSummary.cost, currentCost);
568
+ projectSummary.requests += 1;
569
+ if (!projectSummary.byDay[day]) {
570
+ projectSummary.byDay[day] = {
571
+ day,
572
+ tokens: createEmptyTokens(),
573
+ cost: createEmptyCost(),
574
+ requests: 0,
575
+ byModel: {}
576
+ };
577
+ }
578
+ const projDay = projectSummary.byDay[day];
579
+ projDay.tokens = addTokens(projDay.tokens, currentTokens);
580
+ projDay.cost = addCost(projDay.cost, currentCost);
581
+ projDay.requests += 1;
582
+ if (!projDay.byModel[modelName]) {
583
+ projDay.byModel[modelName] = {
584
+ tokens: createEmptyTokens(),
585
+ cost: createEmptyCost(),
586
+ requests: 0
587
+ };
588
+ }
589
+ projDay.byModel[modelName].tokens = addTokens(projDay.byModel[modelName].tokens, currentTokens);
590
+ projDay.byModel[modelName].cost = addCost(projDay.byModel[modelName].cost, currentCost);
591
+ projDay.byModel[modelName].requests += 1;
592
+ if (!projectSummary.byModel[modelName]) {
593
+ projectSummary.byModel[modelName] = {
594
+ tokens: createEmptyTokens(),
595
+ cost: createEmptyCost(),
596
+ requests: 0
597
+ };
598
+ }
599
+ projectSummary.byModel[modelName].tokens = addTokens(projectSummary.byModel[modelName].tokens, currentTokens);
600
+ projectSummary.byModel[modelName].cost = addCost(projectSummary.byModel[modelName].cost, currentCost);
601
+ projectSummary.byModel[modelName].requests += 1;
602
+ if (!modelsMap[modelName]) {
603
+ modelsMap[modelName] = {
604
+ model: modelName,
605
+ provider,
606
+ rates,
607
+ isFallbackRates: fallbackModelSet.has(modelName),
608
+ tokens: createEmptyTokens(),
609
+ cost: createEmptyCost(),
610
+ requests: 0,
611
+ byDay: {}
612
+ };
613
+ }
614
+ const modelSummary = modelsMap[modelName];
615
+ modelSummary.tokens = addTokens(modelSummary.tokens, currentTokens);
616
+ modelSummary.cost = addCost(modelSummary.cost, currentCost);
617
+ modelSummary.requests += 1;
618
+ if (!modelSummary.byDay[day]) {
619
+ modelSummary.byDay[day] = {
620
+ tokens: createEmptyTokens(),
621
+ cost: createEmptyCost(),
622
+ requests: 0
623
+ };
624
+ }
625
+ modelSummary.byDay[day].tokens = addTokens(modelSummary.byDay[day].tokens, currentTokens);
626
+ modelSummary.byDay[day].cost = addCost(modelSummary.byDay[day].cost, currentCost);
627
+ modelSummary.byDay[day].requests += 1;
628
+ if (record.agentType === "advisor") {
629
+ const advicePieces = record.adviceBySeverity ? countAdvicePieces(record.adviceBySeverity) : 0;
630
+ advisorTotalPieces += advicePieces;
631
+ if (record.adviceBySeverity) {
632
+ addAdviceCounts(advisorAdviceBySeverity, record.adviceBySeverity);
633
+ }
634
+ advisorTotalTokens = addTokens(advisorTotalTokens, currentTokens);
635
+ advisorTotalCost = addCost(advisorTotalCost, currentCost);
636
+ daySummary.advisorTokens += currentTokens.total;
637
+ daySummary.advisorCost += currentCost.total;
638
+ daySummary.advisorAdvicePieces += advicePieces;
639
+ if (!advisorByDay[day]) {
640
+ advisorByDay[day] = {
641
+ day,
642
+ tokens: createEmptyTokens(),
643
+ cost: createEmptyCost(),
644
+ advicePieces: 0,
645
+ adviceBySeverity: createEmptyAdviceCounts(),
646
+ costPerAdvice: 0,
647
+ tokensPerAdvice: 0
648
+ };
649
+ }
650
+ const advDay = advisorByDay[day];
651
+ advDay.tokens = addTokens(advDay.tokens, currentTokens);
652
+ advDay.cost = addCost(advDay.cost, currentCost);
653
+ advDay.advicePieces += advicePieces;
654
+ if (record.adviceBySeverity) {
655
+ addAdviceCounts(advDay.adviceBySeverity, record.adviceBySeverity);
656
+ }
657
+ advDay.costPerAdvice = advDay.advicePieces ? advDay.cost.total / advDay.advicePieces : 0;
658
+ advDay.tokensPerAdvice = advDay.advicePieces ? Math.round(advDay.tokens.total / advDay.advicePieces) : 0;
659
+ if (!advisorByModel[modelName]) {
660
+ advisorByModel[modelName] = {
661
+ model: modelName,
662
+ provider: record.provider,
663
+ advicePieces: 0,
664
+ adviceBySeverity: createEmptyAdviceCounts(),
665
+ tokens: createEmptyTokens(),
666
+ cost: createEmptyCost(),
667
+ costPerAdvice: 0
668
+ };
669
+ }
670
+ const advMod = advisorByModel[modelName];
671
+ advMod.tokens = addTokens(advMod.tokens, currentTokens);
672
+ advMod.cost = addCost(advMod.cost, currentCost);
673
+ advMod.advicePieces += advicePieces;
674
+ if (record.adviceBySeverity) {
675
+ addAdviceCounts(advMod.adviceBySeverity, record.adviceBySeverity);
676
+ }
677
+ advMod.costPerAdvice = advMod.advicePieces ? advMod.cost.total / advMod.advicePieces : 0;
678
+ }
679
+ }
680
+ for (const day of Object.keys(daysMap)) {
681
+ let activeProjs = 0;
682
+ for (const proj of Object.values(projectsMap)) {
683
+ if (proj.byDay[day])
684
+ activeProjs++;
685
+ }
686
+ let activeMods = 0;
687
+ for (const mod of Object.values(modelsMap)) {
688
+ if (mod.byDay[day])
689
+ activeMods++;
690
+ }
691
+ daysMap[day].activeProjects = activeProjs;
692
+ daysMap[day].activeModels = activeMods;
693
+ }
694
+ const totalAdvicePieces = advisorTotalPieces;
695
+ const costPerAdvice = totalAdvicePieces > 0 ? advisorTotalCost.total / totalAdvicePieces : 0;
696
+ const tokensPerAdvice = totalAdvicePieces > 0 ? Math.round(advisorTotalTokens.total / totalAdvicePieces) : 0;
697
+ const advisorSummary = {
698
+ tokens: advisorTotalTokens,
699
+ cost: advisorTotalCost,
700
+ totalAdvicePieces,
701
+ costPerAdvice,
702
+ tokensPerAdvice,
703
+ adviceBySeverity: advisorAdviceBySeverity,
704
+ byDay: advisorByDay,
705
+ byModel: advisorByModel
706
+ };
707
+ const totalDays = Object.keys(daysMap).length;
708
+ return {
709
+ generatedAt: new Date().toISOString(),
710
+ dateRangeAvailable: {
711
+ minDay: minDay || "1970-01-01",
712
+ maxDay: maxDay || "1970-01-01",
713
+ totalDays
714
+ },
715
+ pricingRates: pricingRatesMap,
716
+ fallbackModels: Array.from(fallbackModelSet),
717
+ days: daysMap,
718
+ projects: projectsMap,
719
+ models: modelsMap,
720
+ recentModelSpeeds: aggregateModelSpeeds(records),
721
+ advisor: advisorSummary,
722
+ overall: {
723
+ tokens: overallTokens,
724
+ cost: overallCost,
725
+ requests: overallRequests,
726
+ mainTokens,
727
+ subagentTokens,
728
+ advisorTokens,
729
+ mainCost,
730
+ subagentCost,
731
+ advisorCost
732
+ }
733
+ };
734
+ }
735
+
736
+ // src/report-html.ts
737
+ import { readFileSync } from "fs";
738
+ import { fileURLToPath } from "url";
739
+ var DATASET_PLACEHOLDER_PATTERN = /\{\s*"__omp_dataset_placeholder__"\s*:\s*true\s*\}/g;
740
+ var CANDIDATE_TEMPLATE_PATHS = [
741
+ fileURLToPath(new URL("./dist-template/index.html", import.meta.url)),
742
+ fileURLToPath(new URL("../dist-template/index.html", import.meta.url)),
743
+ fileURLToPath(new URL("../../web/dist-template/index.html", import.meta.url))
744
+ ];
745
+ function loadTemplateHtml() {
746
+ for (const candidate of CANDIDATE_TEMPLATE_PATHS) {
747
+ try {
748
+ return readFileSync(candidate, "utf8");
749
+ } catch {}
750
+ }
751
+ throw new Error(`Report template not found. Searched:
752
+ ${CANDIDATE_TEMPLATE_PATHS.map((p) => ` - ${p}`).join(`
753
+ `)}
754
+ Run "bun run build" first.`);
755
+ }
756
+ function generateReportHtml(dataset) {
757
+ const template = loadTemplateHtml();
758
+ DATASET_PLACEHOLDER_PATTERN.lastIndex = 0;
759
+ const firstMarker = DATASET_PLACEHOLDER_PATTERN.exec(template);
760
+ if (!firstMarker) {
761
+ throw new Error(`Report template is missing its dataset placeholder. Run "bun run build" first.`);
762
+ }
763
+ if (DATASET_PLACEHOLDER_PATTERN.exec(template)) {
764
+ throw new Error("Report template contains more than one dataset placeholder.");
765
+ }
766
+ const serializedData = JSON.stringify(dataset).replaceAll("<", "\\u003c");
767
+ return `${template.slice(0, firstMarker.index)}${serializedData}${template.slice(firstMarker.index + firstMarker[0].length)}`;
768
+ }
769
+
770
+ // src/cli.ts
771
+ function parseCliArgs(argv) {
772
+ const { values } = parseArgs({
773
+ args: argv,
774
+ options: {
775
+ out: { type: "string", short: "o" },
776
+ open: { type: "boolean", default: true },
777
+ "no-open": { type: "boolean" },
778
+ sync: { type: "boolean", default: false },
779
+ start: { type: "string" },
780
+ end: { type: "string" },
781
+ help: { type: "boolean", short: "h" }
782
+ },
783
+ allowPositionals: true
784
+ });
785
+ const open = values["no-open"] ? false : values.open ?? true;
786
+ return {
787
+ outDir: values.out,
788
+ open,
789
+ sync: values.sync ?? false,
790
+ start: values.start,
791
+ end: values.end,
792
+ help: values.help
793
+ };
794
+ }
795
+ async function runCli(argv = process.argv.slice(2)) {
796
+ const opts = parseCliArgs(argv);
797
+ if (opts.help) {
798
+ console.log(`
799
+ Oh My Pi Usage & API Cost Analyzer
800
+
801
+ USAGE:
802
+ omp-usage-analyzer [flags]
803
+ bunx omp-usage-analyzer [flags]
804
+ FLAGS:
805
+ -o, --out <dir> Output folder for the generated report
806
+ (Default: generates into OS temp directory)
807
+ --no-open Do not open the report in the browser
808
+ --sync Run SDK sync across all sessions before report generation
809
+ --start <date> Optional filter start date (YYYY-MM-DD)
810
+ --end <date> Optional filter end date (YYYY-MM-DD)
811
+ -h, --help Display this help message
812
+ `);
813
+ return "";
814
+ }
815
+ console.log("Loading Oh My Pi usage data from local stats storage...");
816
+ const records = await loadRawUsageRecords({
817
+ dbPath: Bun.env.OMP_STATS_DB_PATH || undefined,
818
+ sync: opts.sync,
819
+ range: {
820
+ startDay: opts.start,
821
+ endDay: opts.end
822
+ }
823
+ });
824
+ console.log(`Loaded ${records.length.toLocaleString()} usage records.`);
825
+ if (records.length === 0) {
826
+ console.warn("Notice: No usage records found matching criteria.");
827
+ }
828
+ console.log("Aggregating usage per project, day, model, and advisor economics...");
829
+ const dataset = aggregateUsageRecords(records);
830
+ console.log("Generating interactive SolidJS + Tailwind report...");
831
+ const html = generateReportHtml(dataset);
832
+ let targetDir = opts.outDir;
833
+ let isTemp = false;
834
+ if (!targetDir) {
835
+ targetDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "omp-usage-report-"));
836
+ isTemp = true;
837
+ } else {
838
+ fs2.mkdirSync(targetDir, { recursive: true });
839
+ }
840
+ const outputPath = path2.resolve(targetDir, "index.html");
841
+ fs2.writeFileSync(outputPath, html, "utf-8");
842
+ console.log(`
843
+ Report generated successfully!`);
844
+ console.log(`Path: ${outputPath}`);
845
+ if (isTemp) {
846
+ console.log(`(Generated in temporary folder)`);
847
+ }
848
+ console.log(`
849
+ Summary:`);
850
+ console.log(` Total Tokens: ${dataset.overall.tokens.total.toLocaleString()}`);
851
+ console.log(` Est. API Cost: $${dataset.overall.cost.total.toFixed(2)}`);
852
+ console.log(` Advisor Spend: $${dataset.advisor.cost.total.toFixed(2)} (${dataset.advisor.totalAdvicePieces} advice pieces)`);
853
+ console.log(` Cost / Advice: $${dataset.advisor.costPerAdvice.toFixed(3)}`);
854
+ if (opts.open) {
855
+ openInBrowser(outputPath);
856
+ }
857
+ return outputPath;
858
+ }
859
+ if (import.meta.main) {
860
+ runCli().catch((err) => {
861
+ console.error("Fatal error:", err);
862
+ process.exit(1);
863
+ });
864
+ }
865
+ export {
866
+ parseCliArgs,
867
+ runCli
868
+ };
@@ -0,0 +1,19 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="dark" />
7
+ <title>Oh My Pi · Usage Ledger</title>
8
+ <script type="module" crossorigin>(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={context:void 0,registry:void 0,effects:void 0,done:!1,getContextId(){return t(this.context.count)},getNextContextId(){return t(this.context.count++)}};function t(t){let n=String(t),r=n.length-1;return e.context.id+(r?String.fromCharCode(96+r):``)+n}var n=(e,t)=>e===t,r=Symbol(`solid-track`),i={equals:n},a=null,o=D,s=1,c=2,l={owned:null,cleanups:null,context:null,owner:null},u=null,d=null,f=null,p=null,m=null,h=0;function g(e,t){let n=f,r=u,i=e.length===0,a=t===void 0?r:t,o=i?l:{owned:null,cleanups:null,context:a?a.context:null,owner:a},s=i?e:()=>e(()=>b(()=>A(o)));u=o,f=null;try{return E(s,!0)}finally{f=n,u=r}}function _(e,t){t=t?Object.assign({},i,t):i;let n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0};return[re.bind(n),e=>(typeof e==`function`&&(e=d&&d.running&&d.sources.has(n)?e(n.tValue):e(n.value)),x(n,e))]}function v(e,t,n){S(w(e,t,!1,s))}function y(e,t,n){n=n?Object.assign({},i,n):i;let r=w(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,S(r),re.bind(r)}function b(e){if(f===null)return e();let t=f;f=null;try{return e()}finally{f=t}}function ee(e){return u===null||(u.cleanups===null?u.cleanups=[e]:u.cleanups.push(e)),e}var[te,ne]=_(!1);function re(){let e=d&&d.running;if(this.sources&&(e?this.tState:this.state)){if((e?this.tState:this.state)===s)S(this);else{let e=p;p=null,E(()=>O(this),!1),p=e}}if(f){let e=this.observers;if(!e||e[e.length-1]!==f){let t=e?e.length:0;f.sources?(f.sources.push(this),f.sourceSlots.push(t)):(f.sources=[this],f.sourceSlots=[t]),e?(e.push(f),this.observerSlots.push(f.sources.length-1)):(this.observers=[f],this.observerSlots=[f.sources.length-1])}}return e&&d.sources.has(this)?this.tValue:this.value}function x(e,t,n){let r=d&&d.running&&d.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(d){let r=d.running;(r||!n&&d.sources.has(e))&&(d.sources.add(e),e.tValue=t),r||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&E(()=>{for(let t=0;t<e.observers.length;t+=1){let n=e.observers[t],r=d&&d.running;r&&d.disposed.has(n)||((r?!n.tState:!n.state)&&(n.pure?p.push(n):m.push(n),n.observers&&k(n)),r?n.tState=s:n.state=s)}if(p.length>1e6)throw p=[],Error()},!1)}return t}function S(e){if(!e.fn)return;A(e);let t=h;C(e,d&&d.running&&d.sources.has(e)?e.tValue:e.value,t),d&&!d.running&&d.sources.has(e)&&queueMicrotask(()=>{E(()=>{d&&(d.running=!0),f=u=e,C(e,e.tValue,t),f=u=null},!1)})}function C(e,t,n){let r,i=u,a=f;f=u=e;try{r=e.fn(t)}catch(t){return e.pure&&(d&&d.running?(e.tState=s,e.tOwned&&e.tOwned.forEach(A),e.tOwned=void 0):(e.state=s,e.owned&&e.owned.forEach(A),e.owned=null)),e.updatedAt=n+1,se(t)}finally{f=a,u=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?x(e,r,!0):d&&d.running&&e.pure?(d.sources.has(e)||(e.value=r),d.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function w(e,t,n,r=s,i){let a={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:u,context:u?u.context:null,pure:n};return d&&d.running&&(a.state=0,a.tState=r),u===null||u!==l&&(d&&d.running&&u.pure?u.tOwned?u.tOwned.push(a):u.tOwned=[a]:u.owned?u.owned.push(a):u.owned=[a]),a}function T(e){let t=d&&d.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===c)return O(e);if(e.suspense&&b(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<h);){if(t&&d.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let t=e,i=n[r+1];for(;(t=t.owner)&&t!==i;)if(d.disposed.has(t))return}if((t?e.tState:e.state)===s)S(e);else if((t?e.tState:e.state)===c){let t=p;p=null,E(()=>O(e,n[0]),!1),p=t}}}function E(e,t){if(p)return e();let n=!1;t||(p=[]),m?n=!0:m=[],h++;try{let t=e();return ie(n),t}catch(e){n||(m=null),p=null,se(e)}}function ie(e){if(p&&=(D(p),null),e)return;let t;if(d){if(!d.promises.size&&!d.queue.size){let e=d.sources,n=d.disposed;m.push.apply(m,d.effects),t=d.resolve;for(let e of m)`tState`in e&&(e.state=e.tState),delete e.tState;d=null,E(()=>{for(let e of n)A(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)A(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}ne(!1)},!1)}else if(d.running){d.running=!1,d.effects.push.apply(d.effects,m),m=null,ne(!0);return}}let n=m;m=null,n.length&&E(()=>o(n),!1),t&&t()}function D(e){for(let t=0;t<e.length;t++)T(e[t])}function O(e,t){let n=d&&d.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let i=e.sources[r];if(i.sources){let e=n?i.tState:i.state;e===s?i!==t&&(!i.updatedAt||i.updatedAt<h)&&T(i):e===c&&O(i,t)}}}function k(e){let t=d&&d.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=c:r.state=c,r.pure?p.push(r):m.push(r),r.observers&&k(r))}}function A(e){let t;if(e.sources)for(;e.sources.length;){let t=e.sources.pop(),n=e.sourceSlots.pop(),r=t.observers;if(r&&r.length){let e=r.pop(),i=t.observerSlots.pop();n<r.length&&(e.sourceSlots[i]=n,r[n]=e,t.observerSlots[n]=i)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)A(e.tOwned[t]);delete e.tOwned}if(d&&d.running&&e.pure)j(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)A(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}d&&d.running?e.tState=0:e.state=0}function j(e,t){if(t||(e.tState=0,d.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)j(e.owned[t])}function ae(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function oe(e,t,n){try{for(let n of t)n(e)}catch(e){se(e,n&&n.owner||null)}}function se(e,t=u){let n=a&&t&&t.context&&t.context[a],r=ae(e);if(!n)throw r;m?m.push({fn(){oe(r,n,t)},state:s}):oe(r,n,t)}var ce=Symbol(`fallback`);function le(e){for(let t=0;t<e.length;t++)e[t]()}function ue(e,t,n={}){let i=[],a=[],o=[],s=0,c=t.length>1?[]:null;return ee(()=>le(o)),()=>{let l=e()||[],u=l.length,d,f;return l[r],b(()=>{let e,t,r,m,h,_,v,y,b;if(u===0)s!==0&&(le(o),o=[],i=[],a=[],s=0,c&&=[]),n.fallback&&(i=[ce],a[0]=g(e=>(o[0]=e,n.fallback())),s=1);else if(s===0){for(a=Array(u),f=0;f<u;f++)i[f]=l[f],a[f]=g(p);s=u}else{for(r=Array(u),m=Array(u),c&&(h=Array(u)),_=0,v=Math.min(s,u);_<v&&i[_]===l[_];_++);for(v=s-1,y=u-1;v>=_&&y>=_&&i[v]===l[y];v--,y--)r[y]=a[v],m[y]=o[v],c&&(h[y]=c[v]);for(e=new Map,t=Array(y+1),f=y;f>=_;f--)b=l[f],d=e.get(b),t[f]=d===void 0?-1:d,e.set(b,f);for(d=_;d<=v;d++)b=i[d],f=e.get(b),f!==void 0&&f!==-1?(r[f]=a[d],m[f]=o[d],c&&(h[f]=c[d]),f=t[f],e.set(b,f)):o[d]();for(f=_;f<u;f++)f in r?(a[f]=r[f],o[f]=m[f],c&&(c[f]=h[f],c[f](f))):a[f]=g(p);a=a.slice(0,s=u),i=l.slice(0)}return a});function p(e){if(o[f]=e,c){let[e,n]=_(f);return c[f]=n,t(l[f],e)}return t(l[f])}}}function M(e,t){return b(()=>e(t||{}))}var de=e=>`Stale read from <${e}>.`;function N(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return y(ue(()=>e.each,e.children,t||void 0))}function P(e){let t=e.keyed,n=y(()=>e.when,void 0,void 0),r=t?n:y(n,void 0,{equals:(e,t)=>!e==!t});return y(()=>{let i=r();if(i){let a=e.children;return typeof a==`function`&&a.length>0?b(()=>a(t?i:()=>{if(!b(r))throw de(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var F=e=>y(()=>e());function fe(e,t,n){let r=n.length,i=t.length,a=r,o=0,s=0,c=t[i-1].nextSibling,l=null;for(;o<i||s<a;){if(t[o]===n[s]){o++,s++;continue}for(;t[i-1]===n[a-1];)i--,a--;if(i===o){let t=a<r?s?n[s-1].nextSibling:n[a-s]:c;for(;s<a;)e.insertBefore(n[s++],t)}else if(a===s)for(;o<i;)(!l||!l.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[a-1]&&n[s]===t[i-1]){let r=t[--i].nextSibling;e.insertBefore(n[s++],t[o++].nextSibling),e.insertBefore(n[--a],r),t[i]=n[a]}else{if(!l){l=new Map;let e=s;for(;e<a;)l.set(n[e],e++)}let r=l.get(t[o]);if(r!=null){if(s<r&&r<a){let c=o,u=1,d;for(;++c<i&&c<a&&(d=l.get(t[c]))!=null&&d===r+u;)u++;if(u>r-s){let i=t[o];for(;s<r;)e.insertBefore(n[s++],i)}else e.replaceChild(n[s++],t[o++])}else o++}else t[o++].remove()}}}var pe=`_$DX_DELEGATE`;function me(e,t,n,r={}){let i;return g(r=>{i=r,t===document?e():B(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function I(e,t,n,r){let i,a=()=>{let t=r?document.createElementNS(`http://www.w3.org/1998/Math/MathML`,`template`):document.createElement(`template`);return t.innerHTML=e,n?t.content.firstChild.firstChild:r?t.firstChild:t.content.firstChild},o=t?()=>b(()=>document.importNode(i||=a(),!0)):()=>(i||=a()).cloneNode(!0);return o.cloneNode=o,o}function he(e,t=window.document){let n=t[pe]||(t[pe]=new Set);for(let r=0,i=e.length;r<i;r++){let i=e[r];n.has(i)||(n.add(i),t.addEventListener(i,_e))}}function L(e,t,n){ge(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function R(e,t){ge(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function z(e,t,n){n==null?e.style.removeProperty(t):e.style.setProperty(t,n)}function B(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return V(e,t,r,n);v(r=>V(e,t(),r,n),r)}function ge(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function _e(t){if(e.registry&&e.events&&e.events.find(([e,n])=>n===t))return;let n=t.target,r=`$$${t.type}`,i=t.target,a=t.currentTarget,o=e=>Object.defineProperty(t,"target",{configurable:!0,value:e}),s=()=>{let e=n[r];if(e&&!n.disabled){let i=n[`${r}Data`];if(i===void 0?e.call(n,t):e.call(n,i,t),t.cancelBubble)return}return n.host&&typeof n.host!=`string`&&!n.host._$host&&n.contains(t.target)&&o(n.host),!0},c=()=>{for(;s()&&(n=n._$host||n.parentNode||n.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return n||document}}),e.registry&&!e.done&&(e.done=_$HY.done=!0),t.composedPath){let e=t.composedPath();o(e[0]);for(let t=0;t<e.length-2&&(n=e[t],s());t++){if(n._$host){n=n._$host,c();break}if(n.parentNode===a)break}}else c();o(i)}function V(e,t,n,r,i){let a=ge(e);if(a){!n&&(n=[...e.childNodes]);let t=[];for(let e=0;e<n.length;e++){let r=n[e];r.nodeType===8&&r.data.slice(0,2)===`!$`?r.remove():t.push(r)}n=t}for(;typeof n==`function`;)n=n();if(t===n)return n;let o=typeof t,s=r!==void 0;if(e=s&&n[0]&&n[0].parentNode||e,o===`string`||o===`number`){if(a||o===`number`&&(t=t.toString(),t===n))return n;if(s){let i=n[0];i&&i.nodeType===3?i.data!==t&&(i.data=t):i=document.createTextNode(t),n=H(e,n,r,i)}else n=n!==``&&typeof n==`string`?e.firstChild.data=t:e.textContent=t}else if(t==null||o===`boolean`){if(a)return n;n=H(e,n,r)}else if(o===`function`)return v(()=>{let i=t();for(;typeof i==`function`;)i=i();n=V(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(ve(o,t,n,i))return v(()=>n=V(e,o,n,r,!0)),()=>n;if(a){if(!o.length)return n;if(r===void 0)return n=[...e.childNodes];let t=o[0];if(t.parentNode!==e)return n;let i=[t];for(;(t=t.nextSibling)!==r;)i.push(t);return n=i}if(o.length===0){if(n=H(e,n,r),s)return n}else c?n.length===0?ye(e,o,r):fe(e,n,o):(n&&H(e),ye(e,o));n=o}else if(t.nodeType){if(a&&t.parentNode)return n=s?[t]:t;if(Array.isArray(n)){if(s)return n=H(e,n,r,t);H(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function ve(e,t,n,r){let i=!1;for(let a=0,o=t.length;a<o;a++){let o=t[a],s=n&&n[e.length],c;if(o!=null&&o!==!0&&o!==!1){if((c=typeof o)==`object`&&o.nodeType)e.push(o);else if(Array.isArray(o))i=ve(e,o,s)||i;else if(c===`function`){if(r){for(;typeof o==`function`;)o=o();i=ve(e,Array.isArray(o)?o:[o],Array.isArray(s)?s:[s])||i}else e.push(o),i=!0}else{let t=String(o);s&&s.nodeType===3&&s.data===t?e.push(s):e.push(document.createTextNode(t))}}}return i}function ye(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function H(e,t,n,r){if(n===void 0)return e.textContent=``;let i=r||document.createTextNode(``);if(t.length){let r=!1;for(let a=t.length-1;a>=0;a--){let o=t[a];if(i!==o){let t=o.parentNode===e;!r&&!a?t?e.replaceChild(i,o):e.insertBefore(i,n):t&&o.remove()}else r=!0}}else e.insertBefore(i,n);return[i]}var be=[`warning`,`concern`,`critical`,`error`,`blocker`],xe=365.2425,Se=6e4,Ce=525600,we=43200,Te=1440,Ee=86400;Ee*7,Ee*xe/12*3;var De=Symbol.for(`constructDateFrom`);function Oe(e,t){return typeof e==`function`?e(t):e&&typeof e==`object`&&De in e?e[De](t):e instanceof Date?new e.constructor(t):new Date(t)}function ke(e,t){return Oe(t||e,e)}var Ae={};function je(){return Ae}function Me(e){let t=ke(e),n=new Date(Date.UTC(t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds()));return n.setUTCFullYear(t.getFullYear()),+e-n}function Ne(e,...t){let n=Oe.bind(null,e||t.find(e=>typeof e==`object`));return t.map(n)}function Pe(e,t){let n=+ke(e)-ke(t);return n<0?-1:n>0?1:n}function Fe(e){return Oe(e,Date.now())}function Ie(e){return t=>{let n=(e?Math[e]:Math.trunc)(t);return n===0?0:n}}var Le={lessThanXSeconds:{one:`less than a second`,other:`less than {{count}} seconds`},xSeconds:{one:`1 second`,other:`{{count}} seconds`},halfAMinute:`half a minute`,lessThanXMinutes:{one:`less than a minute`,other:`less than {{count}} minutes`},xMinutes:{one:`1 minute`,other:`{{count}} minutes`},aboutXHours:{one:`about 1 hour`,other:`about {{count}} hours`},xHours:{one:`1 hour`,other:`{{count}} hours`},xDays:{one:`1 day`,other:`{{count}} days`},aboutXWeeks:{one:`about 1 week`,other:`about {{count}} weeks`},xWeeks:{one:`1 week`,other:`{{count}} weeks`},aboutXMonths:{one:`about 1 month`,other:`about {{count}} months`},xMonths:{one:`1 month`,other:`{{count}} months`},aboutXYears:{one:`about 1 year`,other:`about {{count}} years`},xYears:{one:`1 year`,other:`{{count}} years`},overXYears:{one:`over 1 year`,other:`over {{count}} years`},almostXYears:{one:`almost 1 year`,other:`almost {{count}} years`}},Re=(e,t,n)=>{let r,i=Le[e];return r=typeof i==`string`?i:t===1?i.one:i.other.replace(`{{count}}`,t.toString()),n?.addSuffix?n.comparison&&n.comparison>0?`in `+r:r+` ago`:r};function ze(e){return(t={})=>{let n=t.width?String(t.width):e.defaultWidth;return e.formats[n]||e.formats[e.defaultWidth]}}var Be={date:ze({formats:{full:`EEEE, MMMM do, y`,long:`MMMM do, y`,medium:`MMM d, y`,short:`MM/dd/yyyy`},defaultWidth:`full`}),time:ze({formats:{full:`h:mm:ss a zzzz`,long:`h:mm:ss a z`,medium:`h:mm:ss a`,short:`h:mm a`},defaultWidth:`full`}),dateTime:ze({formats:{full:`{{date}} 'at' {{time}}`,long:`{{date}} 'at' {{time}}`,medium:`{{date}}, {{time}}`,short:`{{date}}, {{time}}`},defaultWidth:`full`})},Ve={lastWeek:`'last' eeee 'at' p`,yesterday:`'yesterday at' p`,today:`'today at' p`,tomorrow:`'tomorrow at' p`,nextWeek:`eeee 'at' p`,other:`P`},He=(e,t,n,r)=>Ve[e];function U(e){return(t,n)=>{let r=n?.context?String(n.context):`standalone`,i;if(r===`formatting`&&e.formattingValues){let t=e.defaultFormattingWidth||e.defaultWidth,r=n?.width?String(n.width):t;i=e.formattingValues[r]||e.formattingValues[t]}else{let t=e.defaultWidth,r=n?.width?String(n.width):e.defaultWidth;i=e.values[r]||e.values[t]}let a=e.argumentCallback?e.argumentCallback(t):t;return i[a]}}var Ue={ordinalNumber:(e,t)=>{let n=Number(e),r=n%100;if(r>20||r<10)switch(r%10){case 1:return n+`st`;case 2:return n+`nd`;case 3:return n+`rd`}return n+`th`},era:U({values:{narrow:[`B`,`A`],abbreviated:[`BC`,`AD`],wide:[`Before Christ`,`Anno Domini`]},defaultWidth:`wide`}),quarter:U({values:{narrow:[`1`,`2`,`3`,`4`],abbreviated:[`Q1`,`Q2`,`Q3`,`Q4`],wide:[`1st quarter`,`2nd quarter`,`3rd quarter`,`4th quarter`]},defaultWidth:`wide`,argumentCallback:e=>e-1}),month:U({values:{narrow:[`J`,`F`,`M`,`A`,`M`,`J`,`J`,`A`,`S`,`O`,`N`,`D`],abbreviated:[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],wide:[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`]},defaultWidth:`wide`}),day:U({values:{narrow:[`S`,`M`,`T`,`W`,`T`,`F`,`S`],short:[`Su`,`Mo`,`Tu`,`We`,`Th`,`Fr`,`Sa`],abbreviated:[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`],wide:[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`]},defaultWidth:`wide`}),dayPeriod:U({values:{narrow:{am:`a`,pm:`p`,midnight:`mi`,noon:`n`,morning:`morning`,afternoon:`afternoon`,evening:`evening`,night:`night`},abbreviated:{am:`AM`,pm:`PM`,midnight:`midnight`,noon:`noon`,morning:`morning`,afternoon:`afternoon`,evening:`evening`,night:`night`},wide:{am:`a.m.`,pm:`p.m.`,midnight:`midnight`,noon:`noon`,morning:`morning`,afternoon:`afternoon`,evening:`evening`,night:`night`}},defaultWidth:`wide`,formattingValues:{narrow:{am:`a`,pm:`p`,midnight:`mi`,noon:`n`,morning:`in the morning`,afternoon:`in the afternoon`,evening:`in the evening`,night:`at night`},abbreviated:{am:`AM`,pm:`PM`,midnight:`midnight`,noon:`noon`,morning:`in the morning`,afternoon:`in the afternoon`,evening:`in the evening`,night:`at night`},wide:{am:`a.m.`,pm:`p.m.`,midnight:`midnight`,noon:`noon`,morning:`in the morning`,afternoon:`in the afternoon`,evening:`in the evening`,night:`at night`}},defaultFormattingWidth:`wide`})};function W(e){return(t,n={})=>{let r=n.width,i=r&&e.matchPatterns[r]||e.matchPatterns[e.defaultMatchWidth],a=t.match(i);if(!a)return null;let o=a[0],s=r&&e.parsePatterns[r]||e.parsePatterns[e.defaultParseWidth],c=Array.isArray(s)?Ge(s,e=>e.test(o)):We(s,e=>e.test(o)),l;l=e.valueCallback?e.valueCallback(c):c,l=n.valueCallback?n.valueCallback(l):l;let u=t.slice(o.length);return{value:l,rest:u}}}function We(e,t){for(let n in e)if(Object.prototype.hasOwnProperty.call(e,n)&&t(e[n]))return n}function Ge(e,t){for(let n=0;n<e.length;n++)if(t(e[n]))return n}function Ke(e){return(t,n={})=>{let r=t.match(e.matchPattern);if(!r)return null;let i=r[0],a=t.match(e.parsePattern);if(!a)return null;let o=e.valueCallback?e.valueCallback(a[0]):a[0];o=n.valueCallback?n.valueCallback(o):o;let s=t.slice(i.length);return{value:o,rest:s}}}var qe={code:`en-US`,formatDistance:Re,formatLong:Be,formatRelative:He,localize:Ue,match:{ordinalNumber:Ke({matchPattern:/^(\d+)(th|st|nd|rd)?/i,parsePattern:/\d+/i,valueCallback:e=>parseInt(e,10)}),era:W({matchPatterns:{narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},defaultMatchWidth:`wide`,parsePatterns:{any:[/^b/i,/^(a|c)/i]},defaultParseWidth:`any`}),quarter:W({matchPatterns:{narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},defaultMatchWidth:`wide`,parsePatterns:{any:[/1/i,/2/i,/3/i,/4/i]},defaultParseWidth:`any`,valueCallback:e=>e+1}),month:W({matchPatterns:{narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},defaultMatchWidth:`wide`,parsePatterns:{narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},defaultParseWidth:`any`}),day:W({matchPatterns:{narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},defaultMatchWidth:`wide`,parsePatterns:{narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},defaultParseWidth:`any`}),dayPeriod:W({matchPatterns:{narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},defaultMatchWidth:`any`,parsePatterns:{any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},defaultParseWidth:`any`})},options:{weekStartsOn:0,firstWeekContainsDate:1}};function Je(e,t,n){let r=je(),i=n?.locale??r.locale??qe,a=Pe(e,t);if(isNaN(a))throw RangeError(`Invalid time value`);let o=Object.assign({},n,{addSuffix:n?.addSuffix,comparison:a}),[s,c]=Ne(n?.in,...a>0?[t,e]:[e,t]),l=Ie(n?.roundingMethod??`round`),u=c.getTime()-s.getTime(),d=u/Se,f=(u-(Me(c)-Me(s)))/Se,p=n?.unit,m;if(m=p||(d<1?`second`:d<60?`minute`:d<1440?`hour`:f<43200?`day`:f<525600?`month`:`year`),m===`second`){let e=l(u/1e3);return i.formatDistance(`xSeconds`,e,o)}if(m===`minute`){let e=l(d);return i.formatDistance(`xMinutes`,e,o)}if(m===`hour`){let e=l(d/60);return i.formatDistance(`xHours`,e,o)}if(m===`day`){let e=l(f/Te);return i.formatDistance(`xDays`,e,o)}if(m===`month`){let e=l(f/we);return e===12&&p!==`month`?i.formatDistance(`xYears`,1,o):i.formatDistance(`xMonths`,e,o)}{let e=l(f/Ce);return i.formatDistance(`xYears`,e,o)}}function Ye(e,t){return Je(e,Fe(e),t)}var Xe=I(`<div class=vector-chart><div class=chart-key aria-hidden=true><span><i></i></span><span><i class=chart-key-line></i></span></div><div class=chart-stage><svg role=img><polyline class=chart-line>`),Ze=I(`<svg><g class=chart-grid aria-hidden=true><line x1=58 x2=880></line><text x=48 text-anchor=end></text><text class=secondary-axis x=899 text-anchor=end></svg>`,!1,!0,!1),Qe=I(`<svg><text class=chart-axis-label text-anchor=middle></svg>`,!1,!0,!1),$e=I(`<svg><g><rect class=chart-bar rx=4></svg>`,!1,!0,!1),et=I(`<svg><circle class=chart-dot></svg>`,!1,!0,!1),tt=I(`<svg><rect class=chart-hit y=16 tabIndex=0></svg>`,!1,!0,!1),nt=I(`<div><strong></strong><span><b></b></span><span><b>`),rt=I(`<div class=distribution-stage><svg viewBox="0 0 100 18"preserveAspectRatio=none role=img aria-label="Project token distribution">`),it=I(`<div class=distribution-legend>`),at=I(`<div class=distribution-chart>`),ot=I(`<div class="empty compact">No project activity in this window.`),st=I(`<svg><rect class=distribution-segment y=0 height=18 tabIndex=0></svg>`,!1,!0,!1),ct=I(`<div class=distribution-tooltip><strong></strong><span> · <!>%`),lt=I(`<button class=distribution-legend-item type=button><i></i><span><strong></strong><small></small></span><b>%`),G=900,ut=270,dt=58,K=16,ft=34,pt=822,mt=[`#00d8ff`,`#6366f1`,`#10b981`,`#f59e0b`,`#a78bfa`,`#38bdf8`,`#fb7185`,`#71717a`];function ht(e){let[t,n]=_(),r=()=>e.height??ut,i=()=>r()-K-ft,a=y(()=>{let t=0,n=0;for(let r of e.points)t=Math.max(t,r.primary),n=Math.max(n,r.secondary);let r=e.wholeNumberPrimary?Math.max(4,Math.ceil(t/4)*4):Math.max(t,2**-52);n=Math.max(n,2**-52);let a=i(),o=pt/Math.max(e.points.length,1),s=Math.max(3,Math.min(34,o*.58)),c=e.points.map((e,t)=>{let i=dt+o*t+o/2,s=e.primary/r*a,c=K+a-e.secondary/n*a;return{...e,x:i,primaryHeight:s,secondaryY:c}});return{points:c,barWidth:s,line:c.map(e=>`${e.x},${e.secondaryY}`).join(` `),labelStep:Math.max(1,Math.ceil(c.length/7)),primaryMax:r,secondaryMax:n}}),o=y(()=>a().points.find(e=>e.key===t()));return(()=>{var s=Xe(),c=s.firstChild,l=c.firstChild,u=l.firstChild,d=l.nextSibling,f=d.firstChild,p=c.nextSibling,m=p.firstChild,h=m.firstChild;return B(l,()=>e.primaryLabel,null),B(d,()=>e.secondaryLabel,null),B(m,M(N,{each:[0,.25,.5,.75,1],children:t=>{let n=K+i()*(1-t);return(()=>{var r=Ze(),i=r.firstChild,o=i.nextSibling,s=o.nextSibling;return L(i,`y1`,n),L(i,`y2`,n),L(o,`y`,n+4),B(o,()=>e.formatPrimary(a().primaryMax*t)),L(s,`y`,n+4),B(s,()=>e.formatSecondary(a().secondaryMax*t)),v(()=>L(s,`fill`,e.secondaryColor)),r})()}}),h),B(m,M(N,{get each(){return a().points},children:(n,o)=>(()=>{var s=$e(),c=s.firstChild;return B(s,M(P,{get when(){return o()%a().labelStep===0||o()===a().points.length-1},get children(){var e=Qe();return B(e,()=>n.label),v(t=>{var i=n.x,a=r()-8;return i!==t.e&&L(e,`x`,t.e=i),a!==t.t&&L(e,`y`,t.t=a),t},{e:void 0,t:void 0}),e}}),null),v(r=>{var o=n.x-a().barWidth/2,s=K+i()-n.primaryHeight,l=a().barWidth,u=n.primaryHeight,d=e.primaryColor,f=t()&&t()!==n.key?.24:.72;return o!==r.e&&L(c,`x`,r.e=o),s!==r.t&&L(c,`y`,r.t=s),l!==r.a&&L(c,`width`,r.a=l),u!==r.o&&L(c,`height`,r.o=u),d!==r.i&&L(c,`fill`,r.i=d),f!==r.n&&L(c,`opacity`,r.n=f),r},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),s})()}),h),B(m,M(N,{get each(){return a().points},children:r=>[(()=>{var n=et();return v(i=>{var a=r.x,o=r.secondaryY,s=t()===r.key?5:3,c=e.secondaryColor;return a!==i.e&&L(n,`cx`,i.e=a),o!==i.t&&L(n,`cy`,i.t=o),s!==i.a&&L(n,`r`,i.a=s),c!==i.o&&L(n,`fill`,i.o=c),i},{e:void 0,t:void 0,a:void 0,o:void 0}),n})(),(()=>{var t=tt();return t.addEventListener(`pointerleave`,()=>n()),t.addEventListener(`pointerenter`,()=>n(r.key)),t.addEventListener(`blur`,()=>n()),t.addEventListener(`focus`,()=>n(r.key)),v(n=>{var o=`${e.id}-point-${r.key}`,s=`${e.testId}-point-${r.key}`,c=r.x-Math.max(a().barWidth,18)/2,l=Math.max(a().barWidth,18),u=i(),d=`${r.label}: ${e.formatPrimary(r.primary)}, ${e.formatSecondary(r.secondary)}`;return o!==n.e&&L(t,`id`,n.e=o),s!==n.t&&L(t,`data-testid`,n.t=s),c!==n.a&&L(t,`x`,n.a=c),l!==n.o&&L(t,`width`,n.o=l),u!==n.i&&L(t,`height`,n.i=u),d!==n.n&&L(t,`aria-label`,n.n=d),n},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),t})()]}),null),B(p,M(P,{get when(){return o()},children:t=>(()=>{var n=nt(),r=n.firstChild,i=r.nextSibling,a=i.firstChild,o=i.nextSibling,s=o.firstChild;return B(r,()=>t().label),B(i,()=>e.primaryLabel,a),B(a,()=>e.formatPrimary(t().primary)),B(o,()=>e.secondaryLabel,s),B(s,()=>e.formatSecondary(t().secondary)),v(e=>{var r=`chart-tooltip ${t().x/G>.72?`align-right`:t().x/G<.28?`align-left`:``}`,i=`${t().x/G*100}%`;return r!==e.e&&R(n,e.e=r),i!==e.t&&z(n,`left`,e.t=i),e},{e:void 0,t:void 0}),n})()}),null),v(t=>{var n=e.id,i=e.testId,o=e.primaryColor,c=e.secondaryColor,l=`0 0 ${G} ${r()}`,d=`${e.primaryLabel} and ${e.secondaryLabel} by day`,p=a().line,g=e.secondaryColor;return n!==t.e&&L(s,`id`,t.e=n),i!==t.t&&L(s,`data-testid`,t.t=i),o!==t.a&&z(u,`background-color`,t.a=o),c!==t.o&&z(f,`background-color`,t.o=c),l!==t.i&&L(m,`viewBox`,t.i=l),d!==t.n&&L(m,`aria-label`,t.n=d),p!==t.s&&L(h,`points`,t.s=p),g!==t.h&&L(h,`stroke`,t.h=g),t},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0,h:void 0}),s})()}function gt(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return(t>>>0).toString(16)}function _t(e){let[t,n]=_(),r=y(()=>{let t=[...e.points].filter(e=>e.value>0).sort((e,t)=>t.value-e.value),n=t.slice(0,7),r=t.slice(7);r.length&&n.push({key:`other-projects`,label:`${r.length} other projects`,value:r.reduce((e,t)=>e+t.value,0),detail:`Combined remainder`});let i=n.reduce((e,t)=>e+t.value,0),a=0;return n.map((e,t)=>{let n=i?e.value/i*100:0,r={...e,width:n,offset:a,color:mt[t]};return a+=n,r})}),i=y(()=>r().find(e=>e.key===t()));return(()=>{var a=at();return B(a,M(P,{get when(){return r().length},get fallback(){return ot()},get children(){return[(()=>{var a=rt(),o=a.firstChild;return B(o,M(N,{get each(){return r()},children:r=>(()=>{var i=st();return i.addEventListener(`pointerleave`,()=>n()),i.addEventListener(`pointerenter`,()=>n(r.key)),i.addEventListener(`blur`,()=>n()),i.addEventListener(`focus`,()=>n(r.key)),v(n=>{var a=`${e.id}-segment-${gt(r.key)}`,o=`${e.testId}-segment-${gt(r.key)}`,s=r.offset,c=r.width,l=r.color,u=t()&&t()!==r.key?.25:.9,d=`${r.label}: ${e.formatValue(r.value)}`;return a!==n.e&&L(i,`id`,n.e=a),o!==n.t&&L(i,`data-testid`,n.t=o),s!==n.a&&L(i,`x`,n.a=s),c!==n.o&&L(i,`width`,n.o=c),l!==n.i&&L(i,`fill`,n.i=l),u!==n.n&&L(i,`opacity`,n.n=u),d!==n.s&&L(i,`aria-label`,n.s=d),n},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),i})()})),B(a,M(P,{get when(){return i()},children:t=>(()=>{var n=ct(),r=n.firstChild,i=r.nextSibling,a=i.firstChild,o=a.nextSibling;return o.nextSibling,B(r,()=>t().label),B(i,()=>e.formatValue(t().value),a),B(i,()=>t().width.toFixed(1),o),n})()}),null),a})(),(()=>{var t=it();return B(t,M(N,{get each(){return r()},children:t=>(()=>{var r=lt(),i=r.firstChild,a=i.nextSibling,o=a.firstChild,s=o.nextSibling,c=a.nextSibling,l=c.firstChild;return r.addEventListener(`pointerleave`,()=>n()),r.addEventListener(`pointerenter`,()=>n(t.key)),r.addEventListener(`blur`,()=>n()),r.addEventListener(`focus`,()=>n(t.key)),B(o,()=>t.label),B(s,()=>t.detail),B(c,()=>t.width.toFixed(1),l),v(n=>{var a=`${e.id}-legend-${gt(t.key)}`,o=`${e.testId}-legend-${gt(t.key)}`,s=t.color;return a!==n.e&&L(r,`id`,n.e=a),o!==n.t&&L(r,`data-testid`,n.t=o),s!==n.a&&z(i,`background-color`,n.a=s),n},{e:void 0,t:void 0,a:void 0}),r})()})),t})()]}})),v(t=>{var n=e.id,r=e.testId;return n!==t.e&&L(a,`id`,t.e=n),r!==t.t&&L(a,`data-testid`,t.t=r),t},{e:void 0,t:void 0}),a})()}var q=(e,t,n,r)=>({input:e,output:t,cacheRead:n,cacheWrite:r,total:e+t+n+r}),J=e=>({input:e*.28,output:e*.51,cacheRead:e*.08,cacheWrite:e*.13,total:e}),Y=[`2026-08-28`,`2026-08-29`,`2026-08-30`,`2026-08-31`,`2026-09-01`,`2026-09-02`,`2026-09-03`],vt=[{warning:1,concern:2,critical:0,error:0,blocker:1},{warning:1,concern:3,critical:0,error:0,blocker:1},{warning:1,concern:3,critical:0,error:0,blocker:2},{warning:1,concern:4,critical:0,error:0,blocker:2},{warning:1,concern:2,critical:0,error:0,blocker:1},{warning:1,concern:2,critical:0,error:0,blocker:2},{warning:1,concern:2,critical:0,error:0,blocker:1}],yt=vt.map(e=>Object.values(e).reduce((e,t)=>e+t,0)),bt={generatedAt:`2026-09-03T14:30:00.000Z`,dateRangeAvailable:{minDay:Y[0],maxDay:Y.at(-1),totalDays:Y.length},pricingRates:{"claude-sonnet-4":{input:3,output:15,cacheRead:.3,cacheWrite:3.75},"gpt-5.2-codex":{input:1.75,output:14,cacheRead:.175,cacheWrite:0}},fallbackModels:[`gpt-5.2-codex`],days:Object.fromEntries(Y.map((e,t)=>[e,{day:e,tokens:q(92e3+t*22e3,26e3+t*6500,155e3+t*27e3,8e3+t*1200),cost:J(2.8+t*.72),requests:28+t*6,activeProjects:2+t%3,activeModels:2,advisorTokens:19e3+t*2500,advisorCost:.56+t*.08,advisorAdvicePieces:yt[t]}])),projects:{"C:/Projects/api-gateway":{folder:`C:/Projects/api-gateway`,projectName:`api-gateway`,tokens:q(59e4,164e3,98e4,49e3),cost:J(19.84),requests:192,byDay:Object.fromEntries(Y.map((e,t)=>[e,{day:e,tokens:q(65e3+t*7e3,17e3+t*2200,11e4+t*9e3,6e3),cost:J(2+t*.2),requests:22+t,byModel:{}}])),byModel:{"claude-sonnet-4":{tokens:q(41e4,111e3,72e4,39e3),cost:J(14.1),requests:132},"gpt-5.2-codex":{tokens:q(18e4,53e3,26e4,1e4),cost:J(5.74),requests:60}}},"C:/Projects/web-dashboard":{folder:`C:/Projects/web-dashboard`,projectName:`web-dashboard`,tokens:q(245e3,77e3,38e4,21e3),cost:J(8.22),requests:83,byDay:Object.fromEntries(Y.map((e,t)=>[e,{day:e,tokens:q(24e3+t*3e3,8e3+t*900,39e3+t*4e3,2300),cost:J(.7+t*.1),requests:8+t,byModel:{}}])),byModel:{"claude-sonnet-4":{tokens:q(245e3,77e3,38e4,21e3),cost:J(8.22),requests:83}}}},models:{"claude-sonnet-4":{model:`claude-sonnet-4`,provider:`anthropic`,rates:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},isFallbackRates:!1,tokens:q(655e3,188e3,11e5,6e4),cost:J(22.32),requests:215,byDay:{}},"gpt-5.2-codex":{model:`gpt-5.2-codex`,provider:`openai`,rates:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},isFallbackRates:!0,tokens:q(18e4,53e3,26e4,1e4),cost:J(5.74),requests:60,byDay:{}}},recentModelSpeeds:[{model:`gpt-5.6-sol`,provider:`openai-codex`,lastUsed:178844532e4,requestCount:60,timedRequestCount:58,avgTokensPerSec:92.4,medianTokensPerSec:88.7,avgTtftMs:418,avgDurationMs:12760,totalOutputTokens:53e3},{model:`claude-sonnet-4`,provider:`anthropic`,lastUsed:17884371e5,requestCount:215,timedRequestCount:210,avgTokensPerSec:71.8,medianTokensPerSec:69.3,avgTtftMs:331,avgDurationMs:15420,totalOutputTokens:188e3},{model:`gemini-3.1-pro`,provider:`google`,lastUsed:17883888e5,requestCount:38,timedRequestCount:38,avgTokensPerSec:118.6,medianTokensPerSec:111.2,avgTtftMs:612,avgDurationMs:9840,totalOutputTokens:41e3},{model:`stealth/ox-alpha`,provider:`openrouter`,lastUsed:17881677e5,requestCount:12,timedRequestCount:0,avgTokensPerSec:null,medianTokensPerSec:null,avgTtftMs:890,avgDurationMs:null,totalOutputTokens:8400}],advisor:{tokens:q(97e3,36e3,142e3,8e3),cost:J(4.89),totalAdvicePieces:35,costPerAdvice:.1397,tokensPerAdvice:8086,adviceBySeverity:{warning:7,concern:18,critical:0,error:0,blocker:10},byDay:Object.fromEntries(Y.map((e,t)=>[e,{day:e,tokens:q(9e3+t*1200,3500+t*500,14e3+t*1600,800),cost:J(.56+t*.08),advicePieces:yt[t],adviceBySeverity:vt[t],costPerAdvice:.14,tokensPerAdvice:7600+t*130}])),byModel:{"claude-sonnet-4":{model:`claude-sonnet-4`,provider:`anthropic`,advicePieces:23,adviceBySeverity:{warning:4,concern:12,critical:0,error:0,blocker:7},tokens:q(69e3,25e3,97e3,5e3),cost:J(3.42),costPerAdvice:3.42/23},"gpt-5.2-codex":{model:`gpt-5.2-codex`,provider:`openai`,advicePieces:12,adviceBySeverity:{warning:3,concern:6,critical:0,error:0,blocker:3},tokens:q(28e3,11e3,45e3,3e3),cost:J(1.47),costPerAdvice:1.47/12}}},overall:{tokens:q(835e3,241e3,136e4,7e4),cost:J(28.06),requests:275,mainTokens:171e4,subagentTokens:503e3,advisorTokens:283e3,mainCost:19.8,subagentCost:3.37,advisorCost:4.89}},xt=I(`<section class=metrics aria-label="Summary metrics">`),St=I(`<div class="panel-grid overview-charts">`),Ct=I(`<section class=project-section aria-labelledby=project-section-title><div class=section-heading><div><span class=section-kicker>Project breakdown</span><h2 id=project-section-title>Where the work happened</h2><p> projects in the selected window</p></div><input id=project-search data-testid=project-search class=search-input type=search placeholder="Filter projects…"></div><div class=card-list>`),wt=I(`<section id=model-speeds-panel class=speed-section aria-labelledby=model-speeds-title><div class="tab-intro speed-intro"><span class=section-kicker>Observed performance</span><h2 id=model-speeds-title>Response stream telemetry</h2><p>Token generation speed and latency measured from real model responses.</p></div><div class=speed-summary aria-label="Model speed summary"></div><div class="section-heading speed-heading"><div><span class=section-kicker>Recent model ledger</span><h2>Measured responses</h2><p> models, ordered by last use</p></div><input id=model-speed-search data-testid=model-speed-search class=search-input type=search aria-label="Filter model speeds"placeholder="Filter models or providers…"></div><div class=speed-list>`),Tt=I(`<section class=tab-intro><span class=section-kicker>Advisor intelligence</span><h2>Economics of every second opinion</h2><p>Trace advisor volume, unit cost, and model mix.`),Et=I(`<div class=advisor-grid>`),Dt=I(`<div class=severity-summary><span class=metric-label>Severity mix`),Ot=I(`<p class="severity-note text-xs text-zinc-500 mt-2">Material advice only: concerns, blockers, errors, and warnings. Passive reviews and non-material nits are excluded from the advice piece count.`),kt=I(`<section class=breakdown-section aria-labelledby=advisor-models-title><div class="section-heading compact-heading"><div><span class=section-kicker>Advisor models breakdown</span><h2 id=advisor-models-title>Models behind the advice</h2><p>All-time model totals recorded for advisor messages.</p></div></div><div class=advisor-model-grid>`),At=I(`<section class=tab-intro><span class=section-kicker>Models & rates</span><h2>Rate directory</h2><p>Observed spend and effective catalog rates per million tokens.`),jt=I(`<div class=rate-card-grid>`),Mt=I(`<main class=app-shell><header class=topbar><div class=brand-lockup><span class=brand-mark aria-hidden=true>OMP</span><div><div class=brand-kicker>Local intelligence / usage telemetry</div><h1 class=brand-title>Usage analyzer</h1></div></div><div class=generated><span>Snapshot</span><time></time></div></header><section class=command-bar aria-label="Report controls"><nav class=tabs aria-label="Report sections"></nav><div class=range-controls><div class=preset-row aria-label="Date presets"></div><label class=date-field><span>From</span><input id=range-start data-testid=range-start class=control-input type=date></label><label class=date-field><span>Through</span><input id=range-end data-testid=range-end class=control-input type=date>`),Nt=I(`<button role=tab>`),Pt=I(`<button>`),Ft=I(`<div class=empty>No projects match this window.`),It=I(`<article class=project-card><div class=project-head><div class=project-identity><div class=project-name></div><div class=project-path></div></div><div class=project-total><span> · <!> req</span></div></div><div class=model-rows>`),Lt=I(`<div class=model-row><span class="mono model-name"></span><span><small>Tokens</small><b></b></span><span><small>Requests</small><b></b></span><span><small>Spend</small><b>`),Rt=I(`<div class=empty>No model performance matches this filter.`),zt=I(`<article class=speed-card><header class=speed-card-header><div class=speed-model-title><h3></h3><span class=provider-pill></span></div><div class=last-used><span>Last used</span><time></time></div></header><div class=speed-stats><div class=speed-primary><small>Observed speed</small><strong></strong><div class=speed-track aria-hidden=true><i>`),Bt=I(`<div class=empty>No advisor model usage recorded.`),Vt=I(`<article class=advisor-model-card><header><div><h3></h3><span class=provider-pill></span></div><strong></strong></header><div class=advisor-model-stats><span><small>Advice pieces</small><b></b></span><span><small>Input</small><b></b></span><span><small>Output</small><b></b></span><span><small>Total tokens</small><b></b></span><span><small>Cost / piece</small><b>`),Ht=I(`<div class=empty>No model usage recorded.`),Ut=I(`<article class=rate-card><header><div class=rate-model-title><h3></h3><span class=provider-pill></span></div><div class=observed-cost><small>Observed spend</small><strong></strong></div></header><div class=rate-values><span><small>Input</small><b></b></span><span><small>Output</small><b></b></span><span><small>Cache read</small><b></b></span><span><small>Cache write</small><b>`),Wt=I(`<span class=badge>Past-model fallback`),Gt=I(`<div><div class=metric-label></div><div class=metric-value></div><div class=metric-detail>`),Kt=I(`<div><div class=metric-label></div><strong>`),qt=I(`<div><div class=metric-label></div><strong></strong><span>`),Jt=I(`<div class=speed-value><small></small><b>`),Yt=I(`<div aria-label="Advice by severity">`),Xt=I(`<span><small></small><b>`),Zt=I(`<section class=panel><div class=panel-heading><div><span class=section-kicker></span><h2 class=panel-title></h2></div><span class=panel-note>`),Qt=()=>({input:0,output:0,cacheRead:0,cacheWrite:0,total:0}),$t=()=>({input:0,output:0,cacheRead:0,cacheWrite:0,total:0});function en(e,t){e.input+=t.input,e.output+=t.output,e.cacheRead+=t.cacheRead,e.cacheWrite+=t.cacheWrite,e.total+=t.total}function tn(e,t){e.input+=t.input,e.output+=t.output,e.cacheRead+=t.cacheRead,e.cacheWrite+=t.cacheWrite,e.total+=t.total}function X(e){return e>=1e9?`${(e/1e9).toFixed(2)}B`:e>=1e6?`${(e/1e6).toFixed(2)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}var Z=(e,t=2)=>`$${e.toFixed(t)}`,nn=(e,t,n)=>e>=t&&e<=n,rn=[...be].reverse(),an=e=>e.toLocaleString(void 0,{minimumFractionDigits:1,maximumFractionDigits:1});function on(e){return Number.isFinite(e)?Ye(new Date(e),{addSuffix:!0}):`Unknown`}function sn(){let e=document.getElementById(`omp-dataset`);if(!e?.textContent)return bt;try{let t=JSON.parse(e.textContent);return t.__omp_dataset_placeholder__?bt:t}catch{return bt}}function cn(e,t){let n=new Date(`${e}T00:00:00Z`);return n.setUTCDate(n.getUTCDate()+t),n.toISOString().slice(0,10)}function ln(){let e=sn(),t=e.dateRangeAvailable.minDay,n=e.dateRangeAvailable.maxDay,[r,i]=_(`overview`),[a,o]=_(`all`),[s,c]=_(t),[l,u]=_(n),[d,f]=_(``),[p,m]=_(``),h=e=>{if(o(e),e===`custom`||e===`all`){e===`all`&&(c(t),u(n));return}let r=cn(n,-(Number.parseInt(e,10)-1));c(r<t?t:r),u(n)},g=y(()=>Object.values(e.days).filter(e=>nn(e.day,s(),l())).sort((e,t)=>e.day.localeCompare(t.day))),b=y(()=>{let t=Qt(),n=$t(),r=0,i=0,a=0,o=0,c={warning:0,concern:0,critical:0,error:0,blocker:0};for(let e of g())en(t,e.tokens),tn(n,e.cost),r+=e.requests,i+=e.advisorAdvicePieces,a+=e.advisorCost,o+=e.advisorTokens;for(let t of Object.values(e.advisor.byDay))if(nn(t.day,s(),l()))for(let e of be)c[e]+=t.adviceBySeverity?.[e]??0;return{tokens:t,cost:n,requests:r,advicePieces:i,adviceBySeverity:c,advisorCost:a,costPerAdvice:i?a/i:0,tokensPerAdvice:i?Math.round(o/i):0}}),ee=y(()=>Object.values(e.projects).map(e=>{let t=Qt(),n=$t(),r=0,i=new Map;for(let a of Object.values(e.byDay))if(nn(a.day,s(),l())){en(t,a.tokens),tn(n,a.cost),r+=a.requests;for(let[e,t]of Object.entries(a.byModel)){let n=i.get(e)??{tokens:Qt(),cost:$t(),requests:0};en(n.tokens,t.tokens),tn(n.cost,t.cost),n.requests+=t.requests,i.set(e,n)}}let o=i.size||a()!==`all`?[...i.entries()]:Object.entries(e.byModel);return{...e,tokens:t,cost:n,requests:r,models:o}}).filter(e=>e.projectName.toLowerCase().includes(d().trim().toLowerCase())).sort((e,t)=>t.cost.total-e.cost.total)),te=y(()=>Object.values(e.advisor.byDay).filter(e=>nn(e.day,s(),l())).sort((e,t)=>e.day.localeCompare(t.day))),ne=y(()=>g().map(e=>({key:e.day,label:e.day.slice(5),primary:e.tokens.total,secondary:e.cost.total}))),re=y(()=>te().map(e=>({key:e.day,label:e.day.slice(5),primary:e.advicePieces,secondary:e.costPerAdvice}))),x=y(()=>ee().map(e=>({key:e.folder,label:e.projectName,value:e.tokens.total,detail:Z(e.cost.total)}))),S=y(()=>Object.values(e.advisor.byModel).sort((e,t)=>t.cost.total-e.cost.total)),C=y(()=>{let t=p().trim().toLowerCase();return e.recentModelSpeeds.filter(e=>!t||e.model.toLowerCase().includes(t)||e.provider.toLowerCase().includes(t))}),w=y(()=>C().reduce((e,t)=>t.avgTokensPerSec!=null&&(e?.avgTokensPerSec==null||t.avgTokensPerSec>e.avgTokensPerSec)?t:e,void 0)),T=y(()=>C().reduce((e,t)=>t.avgTtftMs!=null&&(e?.avgTtftMs==null||t.avgTtftMs<e.avgTtftMs)?t:e,void 0)),E=y(()=>C().reduce((e,t)=>!e||t.requestCount>e.requestCount||t.requestCount===e.requestCount&&t.lastUsed>e.lastUsed?t:e,void 0)),ie=y(()=>{let e={},t=[...x()].sort((e,t)=>t.value-e.value);for(let n=0;n<t.length;n+=1)e[t[n].key]=mt[Math.min(n,mt.length-1)];return e});return(()=>{var _=Mt(),y=_.firstChild,te=y.firstChild.nextSibling.firstChild.nextSibling,D=y.nextSibling.firstChild,O=D.nextSibling.firstChild,k=O.nextSibling,A=k.firstChild.nextSibling,j=k.nextSibling.firstChild.nextSibling;return B(te,()=>new Date(e.generatedAt).toLocaleString()),B(D,M(N,{each:[{id:`overview`,label:`Overview & Projects`},{id:`speeds`,label:`Model Speeds`},{id:`advisor`,label:`Advisor Intelligence`},{id:`models`,label:`Models & Rates`}],children:e=>(()=>{var t=Nt();return t.$$click=()=>i(e.id),B(t,()=>e.label),v(n=>{var i=`tab-${e.id}`,a=`tab-${e.id}`,o=`tab-button ${r()===e.id?`active`:``}`,s=r()===e.id;return i!==n.e&&L(t,`id`,n.e=i),a!==n.t&&L(t,`data-testid`,n.t=a),o!==n.a&&R(t,n.a=o),s!==n.o&&L(t,`aria-selected`,n.o=s),n},{e:void 0,t:void 0,a:void 0,o:void 0}),t})()})),B(O,M(N,{each:[`1d`,`7d`,`30d`,`90d`,`all`],children:e=>(()=>{var t=Pt();return t.$$click=()=>h(e),L(t,`id`,`range-${e}`),L(t,`data-testid`,`range-${e}`),B(t,e===`all`?`All`:e),v(()=>R(t,`control-button ${a()===e?`active`:``}`)),t})()})),A.$$input=e=>{o(`custom`),c(e.currentTarget.value)},L(A,`min`,t),j.$$input=e=>{o(`custom`),u(e.currentTarget.value)},L(j,`max`,n),B(_,M(P,{get when(){return r()===`overview`},get children(){return[(()=>{var e=xt();return B(e,M(Q,{label:`Total tokens`,get value(){return X(b().tokens.total)},get detail(){return`${X(b().tokens.input)} in · ${X(b().tokens.output)} out`},tone:`cyan`}),null),B(e,M(Q,{label:`Est. API cost`,get value(){return Z(b().cost.total)},get detail(){return`${Z(b().cost.input)} input`},tone:`amber`}),null),B(e,M(Q,{label:`Requests`,get value(){return b().requests.toLocaleString()},get detail(){return`${g().length} active days`}}),null),B(e,M(Q,{label:`Advisor pieces`,get value(){return b().advicePieces.toLocaleString()},get detail(){return`${X(b().tokensPerAdvice)} tokens / piece`},tone:`indigo`}),null),B(e,M(Q,{label:`Advisor cost`,get value(){return Z(b().advisorCost)},get detail(){return`${b().cost.total?(b().advisorCost/b().cost.total*100).toFixed(1):`0.0`}% of spend`},tone:`emerald`}),null),B(e,M(Q,{label:`Cost / advice`,get value(){return Z(b().costPerAdvice,3)},detail:`estimated API value`}),null),e})(),(()=>{var e=St();return B(e,M(pn,{title:`Daily activity`,note:`Token volume with cost trace`,eyebrow:`Usage trace`,get children(){return M(ht,{id:`activity-chart`,testId:`activity-chart`,get points(){return ne()},primaryLabel:`Tokens`,secondaryLabel:`Cost`,primaryColor:`#00d8ff`,secondaryColor:`#f59e0b`,height:460,formatPrimary:X,formatSecondary:Z})}}),null),B(e,M(pn,{title:`Project distribution`,note:`Share of selected tokens`,eyebrow:`Workspaces`,get children(){return M(_t,{id:`project-chart`,testId:`project-chart`,get points(){return x()},formatValue:X})}}),null),e})(),(()=>{var e=Ct(),t=e.firstChild,n=t.firstChild,r=n.firstChild.nextSibling.nextSibling,i=r.firstChild,a=n.nextSibling,o=t.nextSibling;return B(r,()=>ee().length,i),a.$$input=e=>f(e.currentTarget.value),B(o,M(N,{get each(){return ee()},get fallback(){return Ft()},children:e=>(()=>{var t=It(),n=t.firstChild,r=n.firstChild,i=r.firstChild,a=i.nextSibling,o=r.nextSibling,s=o.firstChild,c=s.firstChild,l=c.nextSibling;l.nextSibling;var u=n.nextSibling;return B(i,()=>e.projectName),B(a,()=>e.folder),B(o,()=>Z(e.cost.total),s),B(s,()=>X(e.tokens.total),c),B(s,()=>e.requests,l),B(u,M(N,{get each(){return e.models},children:([e,t])=>(()=>{var n=Lt(),r=n.firstChild,i=r.nextSibling,a=i.firstChild.nextSibling,o=i.nextSibling,s=o.firstChild.nextSibling,c=o.nextSibling.firstChild.nextSibling;return B(r,e),B(a,()=>X(t.tokens.total)),B(s,()=>t.requests),B(c,()=>Z(t.cost.total)),n})()})),v(n=>z(t,`border-left-color`,ie()[e.folder])),t})()})),v(()=>a.value=d()),e})()]}}),null),B(_,M(P,{get when(){return r()===`speeds`},get children(){var e=wt(),t=e.firstChild.nextSibling,n=t.nextSibling,r=n.firstChild,i=r.firstChild.nextSibling.nextSibling,a=i.firstChild,o=r.nextSibling,s=n.nextSibling;return B(t,M(dn,{label:`Fastest model`,get value(){return F(()=>w()?.avgTokensPerSec==null)()?`—`:`${an(w().avgTokensPerSec)} tok/s`},get detail(){return w()?.model??`No measured responses`},tone:`cyan`}),null),B(t,M(dn,{label:`Lowest TTFT`,get value(){return F(()=>T()?.avgTtftMs==null)()?`—`:`${Math.round(T().avgTtftMs)} ms`},get detail(){return T()?.model??`No latency samples`},tone:`emerald`}),null),B(t,M(dn,{label:`Most active`,get value(){return E()?.requestCount.toLocaleString()??`—`},get detail(){return E()?.model??`No recent requests`},tone:`indigo`}),null),B(i,()=>C().length,a),o.$$input=e=>m(e.currentTarget.value),B(s,M(N,{get each(){return C()},get fallback(){return Rt()},children:e=>{let t=()=>{let t=w()?.avgTokensPerSec;return e.avgTokensPerSec!=null&&t?Math.max(3,e.avgTokensPerSec/t*100):0};return(()=>{var n=zt(),r=n.firstChild,i=r.firstChild,a=i.firstChild,o=a.nextSibling,s=i.nextSibling.firstChild.nextSibling,c=r.nextSibling,l=c.firstChild.firstChild.nextSibling,u=l.nextSibling.firstChild;return B(a,()=>e.model),B(o,()=>e.provider),B(s,()=>on(e.lastUsed)),B(l,(()=>{var t=F(()=>e.avgTokensPerSec==null);return()=>t()?`No sample`:`${an(e.avgTokensPerSec)} tok/s`})()),B(c,M($,{label:`TTFT`,get value(){return F(()=>e.avgTtftMs==null)()?`—`:`${Math.round(e.avgTtftMs)} ms`}}),null),B(c,M($,{label:`Avg. duration`,get value(){return F(()=>e.avgDurationMs==null)()?`—`:`${an(e.avgDurationMs/1e3)} s`}}),null),B(c,M($,{label:`Samples`,get value(){return`${e.timedRequestCount.toLocaleString()} timed / ${e.requestCount.toLocaleString()} total`}}),null),B(c,M($,{label:`Output tokens`,get value(){return X(e.totalOutputTokens)}}),null),v(n=>{var r=new Date(e.lastUsed).toISOString(),i=`${t()}%`;return r!==n.e&&L(s,`datetime`,n.e=r),i!==n.t&&z(u,`width`,n.t=i),n},{e:void 0,t:void 0}),n})()}})),v(()=>o.value=p()),e}}),null),B(_,M(P,{get when(){return r()===`advisor`},get children(){return[Tt(),(()=>{var e=Et();return B(e,M(un,{label:`Advice pieces`,get value(){return b().advicePieces.toLocaleString()},tone:`cyan`}),null),B(e,M(un,{label:`Tokens / piece`,get value(){return X(b().tokensPerAdvice)},tone:`indigo`}),null),B(e,M(un,{label:`Cost / piece`,get value(){return Z(b().costPerAdvice,3)},tone:`amber`}),null),e})(),(()=>{var e=Dt();return e.firstChild,B(e,M(fn,{get counts(){return b().adviceBySeverity}}),null),e})(),Ot(),M(pn,{title:`Advisor daily activity`,note:`Advice volume with unit-cost trace`,eyebrow:`Daily signal`,get children(){return M(ht,{id:`advisor-chart`,testId:`advisor-chart`,get points(){return re()},primaryLabel:`Advice pieces`,secondaryLabel:`Cost / piece`,primaryColor:`#6366f1`,wholeNumberPrimary:!0,secondaryColor:`#f59e0b`,formatPrimary:e=>Math.round(e).toLocaleString(),formatSecondary:e=>Z(e,3)})}}),(()=>{var e=kt(),t=e.firstChild.nextSibling;return B(t,M(N,{get each(){return S()},get fallback(){return Bt()},children:e=>(()=>{var t=Vt(),n=t.firstChild,r=n.firstChild,i=r.firstChild,a=i.nextSibling,o=r.nextSibling,s=n.nextSibling.firstChild,c=s.firstChild.nextSibling,l=s.nextSibling,u=l.firstChild.nextSibling,d=l.nextSibling,f=d.firstChild.nextSibling,p=d.nextSibling,m=p.firstChild.nextSibling,h=p.nextSibling.firstChild.nextSibling;return B(i,()=>e.model),B(a,()=>e.provider),B(o,()=>Z(e.cost.total)),B(c,()=>e.advicePieces.toLocaleString()),B(u,()=>X(e.tokens.input)),B(f,()=>X(e.tokens.output)),B(m,()=>X(e.tokens.total)),B(h,()=>Z(e.costPerAdvice,3)),B(t,M(fn,{get counts(){return e.adviceBySeverity},compact:!0}),null),t})()})),e})()]}}),null),B(_,M(P,{get when(){return r()===`models`},get children(){return[At(),(()=>{var t=jt();return B(t,M(N,{get each(){return Object.values(e.models).sort((e,t)=>t.cost.total-e.cost.total)},get fallback(){return Ht()},children:e=>(()=>{var t=Ut(),n=t.firstChild,r=n.firstChild,i=r.firstChild,a=i.nextSibling,o=r.nextSibling.firstChild.nextSibling,s=n.nextSibling.firstChild,c=s.firstChild.nextSibling,l=s.nextSibling,u=l.firstChild.nextSibling,d=l.nextSibling,f=d.firstChild.nextSibling,p=d.nextSibling.firstChild.nextSibling;return B(i,()=>e.model),B(a,()=>e.provider),B(r,(()=>{var t=F(()=>!!e.isFallbackRates);return()=>t()&&Wt()})(),null),B(o,()=>Z(e.cost.total)),B(c,()=>Z(e.rates.input)),B(u,()=>Z(e.rates.output)),B(f,()=>Z(e.rates.cacheRead)),B(p,()=>Z(e.rates.cacheWrite)),t})()})),t})()]}}),null),v(e=>{var t=l(),n=s();return t!==e.e&&L(A,`max`,e.e=t),n!==e.t&&L(j,`min`,e.t=n),e},{e:void 0,t:void 0}),v(()=>A.value=s()),v(()=>j.value=l()),_})()}function Q(e){return(()=>{var t=Gt(),n=t.firstChild,r=n.nextSibling,i=r.nextSibling;return B(n,()=>e.label),B(r,()=>e.value),B(i,()=>e.detail),v(()=>R(t,`metric ${e.tone?`tone-${e.tone}`:``}`)),t})()}function un(e){return(()=>{var t=Kt(),n=t.firstChild,r=n.nextSibling;return B(n,()=>e.label),B(r,()=>e.value),v(()=>R(t,`advisor-stat tone-${e.tone}`)),t})()}function dn(e){return(()=>{var t=qt(),n=t.firstChild,r=n.nextSibling,i=r.nextSibling;return B(n,()=>e.label),B(r,()=>e.value),B(i,()=>e.detail),v(()=>R(t,`speed-summary-item tone-${e.tone}`)),t})()}function $(e){return(()=>{var t=Jt(),n=t.firstChild,r=n.nextSibling;return B(n,()=>e.label),B(r,()=>e.value),t})()}function fn(e){return(()=>{var t=Yt();return B(t,M(N,{each:rn,children:t=>(()=>{var n=Xt(),r=n.firstChild,i=r.nextSibling;return R(n,`severity-pill severity-${t}`),B(r,t),B(i,()=>e.counts[t].toLocaleString()),n})()})),v(()=>R(t,`severity-breakdown ${e.compact?`compact`:``}`)),t})()}function pn(e){return(()=>{var t=Zt(),n=t.firstChild.firstChild,r=n.firstChild,i=r.nextSibling,a=n.nextSibling;return B(r,()=>e.eyebrow),B(i,()=>e.title),B(a,()=>e.note),B(t,()=>e.children,null),t})()}he([`input`,`click`]);var mn=document.getElementById(`root`);if(!mn)throw Error(`Dashboard root element is missing`);me(()=>M(ln,{}),mn);</script>
9
+ <style rel="stylesheet" crossorigin>/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
10
+ @layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-zinc-500:#71717b;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}@supports (color:lab(0% 0 0)){:root,:host{--color-zinc-500:lab(47.8878% 1.65477 -5.77283)}}}@layer base{*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.mt-2{margin-top:calc(var(--spacing) * 2)}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-zinc-500{color:var(--color-zinc-500)}}:root{color:#f4f4f5;font-synthesis:none;--canvas:#0d0e12;--surface-1:#13141b;--surface-2:#1a1b23;--surface-inset:#101116;--border-soft:#ffffff0e;--border:#ffffff14;--border-strong:#282a36;--text-primary:#f4f4f5;--text-secondary:#a1a1aa;--text-tertiary:#85858f;--text-muted:#52525b;--cyan:#00d8ff;--cyan-soft:#00d8ff1c;--indigo:#6366f1;--indigo-soft:#6366f11f;--amber:#f59e0b;--amber-soft:#f59e0b1a;--emerald:#10b981;--emerald-soft:#10b9811a;--warning:#f59e0b;--warning-soft:#f59e0b1a;--concern:#fb923c;--concern-soft:#fb923c1a;--critical:#fb7185;--critical-soft:#fb71851a;--error:#ef4444;--error-soft:#ef44441a;--blocker:#d946ef;--blocker-soft:#d946ef1a;background:#0d0e12;font-family:Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}html{background:var(--canvas)}body{background:radial-gradient(circle at 22% -20%, #6366f114, transparent 34rem), var(--canvas);min-width:320px;min-height:100vh;margin:0;overflow-x:hidden}button,input{font:inherit}button,[role=tab],.chart-hit,.distribution-segment{cursor:pointer}input{cursor:text}::selection{color:var(--text-primary);background:#6366f161}.app-shell{width:min(1500px,100%);min-width:0;margin:0 auto;padding:24px 32px 64px}.topbar{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;gap:24px;min-width:0;padding:8px 0 24px;display:flex}.brand-lockup{align-items:center;gap:14px;min-width:0;display:flex}.brand-mark{-webkit-user-select:none;user-select:none;width:42px;height:42px;color:var(--canvas);background:var(--text-primary);letter-spacing:-.03em;border-radius:3px;place-items:center;font:750 11px/1 ui-monospace,SFMono-Regular,Consolas,monospace;display:grid}.brand-kicker,.section-kicker,.metric-label,.date-field>span{-webkit-user-select:none;user-select:none;color:var(--text-tertiary);letter-spacing:.12em;text-transform:uppercase;font-size:10px;font-weight:650}.brand-title{color:var(--text-primary);letter-spacing:-.035em;margin:3px 0 0;font-size:clamp(22px,3vw,31px);font-weight:600;line-height:1.05}.generated{min-width:0;color:var(--text-secondary);font-variant-numeric:tabular-nums;justify-items:end;gap:3px;font:12px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace;display:grid}.generated span{-webkit-user-select:none;user-select:none;color:var(--text-muted);letter-spacing:.14em;text-transform:uppercase;font:650 9px/1 ui-sans-serif,system-ui,sans-serif}.command-bar{border-bottom:1px solid var(--border);justify-content:space-between;align-items:center;gap:20px;min-width:0;padding:14px 0;display:flex}.tabs,.range-controls,.preset-row{align-items:center;gap:6px;min-width:0;display:flex}.tab-button,.control-button{-webkit-user-select:none;user-select:none;color:var(--text-secondary);white-space:nowrap;background:0 0;border:1px solid #0000;border-radius:3px;padding:7px 10px;font-size:12px;transition:color .14s,background .14s,border-color .14s}.tab-button:hover,.control-button:hover{color:var(--text-primary);background:#ffffff09}.tab-button.active,.control-button.active{color:#f4f4f5;background:#27272a;border-color:#3f3f46}.tab-button.active{box-shadow:inset 0 -1px 0 var(--cyan)}.control-button{min-width:34px;color:var(--text-tertiary);padding-inline:8px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.tab-button:focus-visible,.control-button:focus-visible,.control-input:focus-visible,.search-input:focus-visible,.chart-hit:focus-visible,.distribution-segment:focus-visible,.distribution-legend-item:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}.range-controls{flex-wrap:wrap;justify-content:flex-end}.date-field{align-items:center;gap:7px;display:flex}.control-input,.search-input{min-width:0;color:var(--text-primary);background:var(--surface-inset);border:1px solid var(--border-strong);--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;border-radius:3px;padding:7px 9px;font:12px/1.25 ui-monospace,SFMono-Regular,Consolas,monospace;transition:border-color .14s,background .14s}.control-input:hover,.search-input:hover{border-color:#3f3f46}.metrics{background:var(--surface-1);border:1px solid var(--border);border-radius:4px;grid-template-columns:repeat(6,minmax(0,1fr));min-width:0;margin:22px 0 12px;display:grid}.metric{border-right:1px solid var(--border);min-width:0;padding:18px;position:relative;overflow:hidden}.metric:after,.advisor-stat:after,.speed-summary-item:after{content:"";opacity:.8;background:var(--text-muted);height:1px;position:absolute;inset:auto 18px 0}.metric:last-child{border-right:0}.metric-value{color:var(--text-primary);font-variant-numeric:tabular-nums;letter-spacing:-.045em;margin-top:10px;font:600 clamp(18px,2vw,27px)/1 ui-monospace,SFMono-Regular,Consolas,monospace}.metric-detail{color:var(--text-tertiary);overflow-wrap:anywhere;margin-top:7px;font-size:11px}.tone-cyan:after{background:var(--cyan)}.tone-indigo:after{background:var(--indigo)}.tone-amber:after{background:var(--amber)}.tone-emerald:after{background:var(--emerald)}.panel-grid{grid-template-columns:minmax(0,1.55fr) minmax(320px,.8fr);gap:12px;min-width:0;display:grid}.panel{background:var(--surface-1);border:1px solid var(--border);border-radius:4px;min-width:0;padding:18px}.overview-charts .panel:first-child{flex-direction:column;display:flex}.overview-charts .panel:first-child .vector-chart,.overview-charts .panel:first-child .chart-stage{flex-direction:column;flex:1;min-height:0;display:flex}.overview-charts .panel:first-child .vector-chart svg{width:100%;height:auto}.panel-heading{justify-content:space-between;align-items:flex-start;gap:16px;min-width:0;margin-bottom:18px;display:flex}.panel-title,.section-heading h2,.tab-intro h2{color:var(--text-primary);letter-spacing:-.02em;margin:4px 0 0;font-size:16px;font-weight:580}.panel-note,.section-heading p,.tab-intro p{color:var(--text-tertiary);margin:0;font-size:11px}.vector-chart,.distribution-chart,.chart-stage,.distribution-stage{min-width:0;position:relative}.chart-key{-webkit-user-select:none;user-select:none;color:var(--text-secondary);gap:16px;margin:-2px 0 6px 58px;font-size:11px;display:flex}.chart-key span{align-items:center;gap:6px;display:flex}.chart-key i{border-radius:2px;width:8px;height:8px}.chart-key i.chart-key-line{border-radius:2px;width:12px;height:2px}.vector-chart svg{width:100%;height:auto;min-height:220px;display:block;overflow:visible}.chart-grid line{stroke:var(--border);stroke-width:1px;vector-effect:non-scaling-stroke}.chart-grid text,.chart-axis-label{-webkit-user-select:none;user-select:none;fill:var(--text-tertiary);font:12px ui-monospace,SFMono-Regular,Consolas,monospace}.chart-grid .secondary-axis{fill:var(--amber);opacity:.9}.chart-bar,.chart-dot,.distribution-segment{transition:opacity .14s,r .14s}.chart-line{fill:none;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}.chart-dot{stroke:var(--surface-1);stroke-width:2px;vector-effect:non-scaling-stroke}.chart-hit{fill:#0000}.chart-tooltip,.distribution-tooltip{pointer-events:none;z-index:3;min-width:150px;color:var(--text-secondary);border:1px solid var(--border-strong);background:#1a1b23f7;border-radius:3px;gap:6px;padding:10px 11px;font-size:10px;display:grid;position:absolute;box-shadow:0 12px 28px #00000052}.chart-tooltip{top:4px;transform:translate(-50%)}.chart-tooltip.align-right{transform:translate(calc(-100% - 12px))}.chart-tooltip.align-left{transform:translate(12px)}.chart-tooltip strong,.distribution-tooltip strong{color:var(--text-primary);font:600 11px ui-monospace,SFMono-Regular,Consolas,monospace}.chart-tooltip span{justify-content:space-between;gap:14px;display:flex}.chart-tooltip b{color:var(--text-primary);font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.distribution-stage{padding-top:7px}.distribution-stage svg{border-radius:3px;width:100%;height:22px;display:block;overflow:hidden}.distribution-tooltip{top:38px;left:0}.distribution-legend{gap:3px;margin-top:22px;display:grid}.distribution-legend-item{width:100%;min-width:0;color:var(--text-secondary);text-align:left;background:0 0;border:1px solid #0000;border-radius:3px;grid-template-columns:8px minmax(0,1fr) auto;align-items:center;gap:10px;padding:8px;transition:background .14s,border-color .14s;display:grid}.distribution-legend-item:hover,.distribution-legend-item:focus-visible{background:var(--surface-2);border-color:var(--border)}.distribution-legend-item i{border-radius:2px;width:7px;height:20px}.distribution-legend-item span{gap:2px;min-width:0;display:grid}.distribution-legend-item strong,.distribution-legend-item small{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.distribution-legend-item strong{color:var(--text-secondary);font-size:11px;font-weight:520}.distribution-legend-item small{color:var(--text-muted);font-size:10px}.distribution-legend-item b{color:var(--text-primary);font:550 11px ui-monospace,SFMono-Regular,Consolas,monospace}.project-section,.breakdown-section{border-top:1px solid var(--border);min-width:0;margin-top:30px;padding-top:26px}.section-heading{justify-content:space-between;align-items:end;gap:20px;min-width:0;margin-bottom:14px;display:flex}.section-heading p,.tab-intro p{margin-top:5px}.search-input{width:min(360px,100%);padding:9px 11px}.card-list,.advisor-model-grid,.rate-card-grid{gap:8px;min-width:0;display:grid}.project-card,.advisor-model-card,.rate-card{background:var(--surface-1);border:1px solid var(--border);border-radius:4px;min-width:0;overflow:hidden}.project-card{border-left-width:2px;padding:13px}.project-head,.advisor-model-card header,.rate-card header{justify-content:space-between;align-items:flex-start;gap:18px;min-width:0;display:flex}.project-identity,.rate-model-title,.advisor-model-card header>div{min-width:0}.project-name,.advisor-model-card h3,.rate-card h3{color:var(--text-primary);overflow-wrap:anywhere;margin:0;font-size:13px;font-weight:560}.project-path{color:var(--text-muted);overflow-wrap:anywhere;margin-top:4px;font:10px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace}.project-total,.observed-cost{color:var(--amber);text-align:right;font-variant-numeric:tabular-nums;flex:none;font:600 14px/1.2 ui-monospace,SFMono-Regular,Consolas,monospace}.project-total span,.observed-cost small{color:var(--text-tertiary);margin-top:5px;font-size:10px;font-weight:450;display:block}.model-rows{border-top:1px solid var(--border-soft);margin-top:11px;display:grid}.model-row{border-bottom:1px solid var(--border-soft);grid-template-columns:minmax(180px,1.6fr) repeat(3,minmax(86px,.55fr));align-items:center;gap:14px;min-width:0;padding:8px 2px;font-size:11px;display:grid}.model-row:last-child{border-bottom:0}.model-row>span:not(.model-name),.advisor-model-stats span,.rate-values span{gap:4px;min-width:0;display:grid}.model-row small,.advisor-model-stats small,.rate-values small{-webkit-user-select:none;user-select:none;color:var(--text-muted);letter-spacing:.08em;text-transform:uppercase;font-size:9px;font-weight:600}.model-row b,.advisor-model-stats b,.rate-values b{color:var(--text-secondary);overflow-wrap:anywhere;font:520 11px ui-monospace,SFMono-Regular,Consolas,monospace}.mono{min-width:0;color:var(--text-secondary);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.tab-intro{padding:34px 0 18px}.tab-intro h2{letter-spacing:-.035em;font-size:23px}.speed-section{min-width:0}.speed-summary{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;min-width:0;display:grid}.speed-summary-item{background:var(--surface-1);border:1px solid var(--border);border-radius:4px;min-width:0;padding:16px;position:relative;overflow:hidden}.speed-summary-item strong{color:var(--text-primary);font-variant-numeric:tabular-nums;margin-top:9px;font:600 clamp(18px,2vw,24px)/1 ui-monospace,SFMono-Regular,Consolas,monospace;display:block}.speed-summary-item>span{min-width:0;color:var(--text-tertiary);overflow-wrap:anywhere;margin-top:7px;font:11px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace;display:block}.speed-heading{border-top:1px solid var(--border);align-items:end;margin-top:30px;padding-top:26px}.speed-list{gap:8px;min-width:0;display:grid}.speed-card{background:var(--surface-1);border:1px solid var(--border);border-radius:4px;min-width:0;padding:15px;overflow:hidden}.speed-card-header{justify-content:space-between;align-items:flex-start;gap:18px;min-width:0;display:flex}.speed-model-title{min-width:0}.speed-model-title h3{color:var(--text-primary);overflow-wrap:anywhere;margin:0;font:560 13px/1.35 ui-monospace,SFMono-Regular,Consolas,monospace}.last-used{min-width:0;color:var(--text-secondary);font-variant-numeric:tabular-nums;flex:none;justify-items:end;gap:4px;font:11px/1.3 ui-monospace,SFMono-Regular,Consolas,monospace;display:grid}.last-used span,.speed-primary small,.speed-value small{-webkit-user-select:none;user-select:none;color:var(--text-muted);letter-spacing:.08em;text-transform:uppercase;font:600 9px/1 ui-sans-serif,system-ui,sans-serif}.speed-stats{background:var(--border-soft);border-top:1px solid var(--border-soft);grid-template-columns:minmax(190px,1.45fr) repeat(4,minmax(90px,.65fr));align-items:stretch;gap:1px;min-width:0;margin-top:14px;display:grid}.speed-primary,.speed-value{background:var(--surface-inset);align-content:center;gap:7px;min-width:0;padding:13px 12px;display:grid}.speed-primary strong{color:var(--cyan);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;font:600 18px/1 ui-monospace,SFMono-Regular,Consolas,monospace}.speed-track{background:var(--surface-2);border-radius:2px;width:100%;height:3px;overflow:hidden}.speed-track i{background:var(--cyan);border-radius:2px;height:100%;display:block}.speed-value b{color:var(--text-secondary);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;font:560 12px/1.25 ui-monospace,SFMono-Regular,Consolas,monospace}.advisor-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;min-width:0;margin-bottom:12px;display:grid}.advisor-stat{background:var(--surface-1);border:1px solid var(--border);border-radius:4px;min-width:0;padding:18px;position:relative;overflow:hidden}.advisor-stat strong{color:var(--text-primary);margin-top:9px;font:600 24px/1 ui-monospace,SFMono-Regular,Consolas,monospace;display:block}.severity-summary{background:var(--surface-inset);border:1px solid var(--border-soft);border-radius:4px;align-items:center;gap:16px;min-width:0;margin-bottom:12px;padding:11px 14px;display:flex}.severity-summary .severity-breakdown{margin-top:0}.severity-note{color:var(--text-muted);margin:0 0 14px;font-size:11px;line-height:1.5}.severity-breakdown{flex-wrap:wrap;gap:6px;margin-top:14px;display:flex}.severity-breakdown.compact{border-top:1px solid var(--border-soft);padding-top:14px}.severity-pill{background:var(--surface-inset);border:1px solid var(--border);font-variant-numeric:tabular-nums;border-radius:3px;align-items:center;gap:5px;padding:4px 7px;font:550 10px/1.1 ui-monospace,SFMono-Regular,Consolas,monospace;display:inline-flex}.severity-pill small{-webkit-user-select:none;user-select:none;color:var(--text-tertiary);font:inherit;text-transform:uppercase;letter-spacing:.045em}.severity-pill b{color:var(--text-primary);font:inherit}.severity-warning{background:var(--warning-soft);border-color:var(--warning)}@supports (color:color-mix(in lab, red, red)){.severity-warning{border-color:color-mix(in srgb, var(--warning) 24%, transparent)}}.severity-concern{background:var(--concern-soft);border-color:var(--concern)}@supports (color:color-mix(in lab, red, red)){.severity-concern{border-color:color-mix(in srgb, var(--concern) 24%, transparent)}}.severity-critical{background:var(--critical-soft);border-color:var(--critical)}@supports (color:color-mix(in lab, red, red)){.severity-critical{border-color:color-mix(in srgb, var(--critical) 24%, transparent)}}.severity-error{background:var(--error-soft);border-color:var(--error)}@supports (color:color-mix(in lab, red, red)){.severity-error{border-color:color-mix(in srgb, var(--error) 24%, transparent)}}.severity-blocker{background:var(--blocker-soft);border-color:var(--blocker)}@supports (color:color-mix(in lab, red, red)){.severity-blocker{border-color:color-mix(in srgb, var(--blocker) 24%, transparent)}}.severity-warning small{color:var(--warning)}.severity-concern small{color:var(--concern)}.severity-critical small{color:var(--critical)}.severity-error small{color:var(--error)}.severity-blocker small{color:var(--blocker)}.compact-heading{align-items:flex-start}.advisor-model-grid,.rate-card-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.advisor-model-card,.rate-card{padding:16px}.advisor-model-card header strong{color:var(--amber);flex:none;font:600 14px ui-monospace,SFMono-Regular,Consolas,monospace}.provider-pill,.badge{-webkit-user-select:none;user-select:none;max-width:100%;color:var(--text-secondary);overflow-wrap:anywhere;background:#27272a;border:1px solid #3f3f46;border-radius:3px;margin-top:7px;padding:3px 6px;font:550 9px/1 ui-monospace,SFMono-Regular,Consolas,monospace;display:inline-flex}.badge{color:#fbbf24;background:var(--amber-soft);border-color:#f59e0b3d;margin-left:6px}.advisor-model-stats,.rate-values{border-top:1px solid var(--border-soft);grid-template-columns:repeat(5,minmax(0,1fr));gap:10px;min-width:0;margin-top:16px;padding-top:14px;display:grid}.rate-card-grid{padding-bottom:10px}.rate-card header{min-width:0}.rate-values{grid-template-columns:repeat(4,minmax(0,1fr))}.empty{color:var(--text-tertiary);background:var(--surface-1);border:1px solid var(--border);text-align:center;border-radius:4px;grid-column:1/-1;padding:48px 16px}.empty.compact{padding:34px 12px}@media (max-width:1080px){.command-bar{flex-direction:column;align-items:flex-start}.range-controls{justify-content:flex-start}.metrics{grid-template-columns:repeat(3,minmax(0,1fr))}.metric:nth-child(3){border-right:0}.metric:nth-child(-n+3){border-bottom:1px solid var(--border)}.panel-grid{grid-template-columns:1fr}.speed-stats{grid-template-columns:repeat(4,minmax(0,1fr))}.speed-primary{grid-column:span 2}}@media (max-width:760px){.app-shell{padding:16px 16px 44px}.topbar{align-items:flex-start}.generated{display:none}.tabs{scrollbar-width:thin;width:100%;padding-bottom:3px;overflow-x:auto}.range-controls{align-items:flex-start;width:100%}.date-field{flex:150px}.control-input{width:100%}.metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.metric:nth-child(3){border-right:1px solid var(--border)}.metric:nth-child(2n){border-right:0}.metric:nth-child(-n+4){border-bottom:1px solid var(--border)}.section-heading,.project-head,.advisor-model-card header,.rate-card header,.speed-card-header{flex-direction:column;align-items:stretch}.search-input{width:100%}.project-total,.observed-cost{text-align:left}.model-row{grid-template-columns:repeat(3,minmax(0,1fr))}.model-name{grid-column:1/-1}.advisor-model-grid,.rate-card-grid,.speed-summary{grid-template-columns:1fr}.speed-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.last-used{justify-items:start}.advisor-model-stats{grid-template-columns:repeat(3,minmax(0,1fr))}.metric-detail,.panel-note,.section-heading p,.tab-intro p{font-size:12px}.date-field>span{font-size:11px}.chart-grid text,.chart-axis-label{font-size:24px}}@media (max-width:480px){.brand-mark{width:36px;height:36px}.brand-kicker{display:none}.tabs{gap:4px}.tab-button{padding-inline:8px}.range-controls,.preset-row{gap:4px}.date-field{flex-basis:calc(50% - 4px);display:grid}.metric,.panel{padding:14px}.panel-heading{flex-direction:column;align-items:flex-start}.chart-key{margin-left:4px}.vector-chart svg{min-height:190px}.advisor-grid{grid-template-columns:1fr}.severity-summary{flex-direction:column;align-items:flex-start;gap:8px}.advisor-model-stats,.rate-values{grid-template-columns:repeat(2,minmax(0,1fr))}}
11
+ /*$vite$:1*/</style>
12
+ </head>
13
+ <body>
14
+ <script id="omp-dataset" type="application/json">
15
+ { "__omp_dataset_placeholder__": true }
16
+ </script>
17
+ <div id="root"></div>
18
+ </body>
19
+ </html>
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "omp-usage-analyzer",
3
+ "version": "0.1.0",
4
+ "description": "Interactive telemetry, token volume, and API cost analyzer for Oh My Pi coding agent",
5
+ "keywords": [
6
+ "analyzer",
7
+ "bun",
8
+ "cli",
9
+ "cost",
10
+ "oh-my-pi",
11
+ "telemetry",
12
+ "tokens",
13
+ "usage"
14
+ ],
15
+ "homepage": "https://github.com/jkelin/omp-usage-analyzer#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/jkelin/omp-usage-analyzer/issues"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Jan Kelin",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/jkelin/omp-usage-analyzer.git"
24
+ },
25
+ "bin": {
26
+ "omp-usage-analyzer": "dist/cli.js"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "dist-template",
31
+ "README.md"
32
+ ],
33
+ "type": "module",
34
+ "scripts": {
35
+ "build": "bun run --cwd ../web build && bun run ./build.ts",
36
+ "bundle": "bun run ./build.ts",
37
+ "format": "oxfmt src tests package.json tsconfig.json",
38
+ "lint": "oxlint src tests",
39
+ "prepublishOnly": "bun run build",
40
+ "pretest": "bun run build",
41
+ "report": "bun run src/cli.ts",
42
+ "test": "bun test"
43
+ },
44
+ "dependencies": {
45
+ "@oh-my-pi/omp-stats": "^18.1.5",
46
+ "@oh-my-pi/pi-catalog": "^18.1.5",
47
+ "@oh-my-pi/pi-utils": "^18.1.5"
48
+ },
49
+ "devDependencies": {
50
+ "@omp/shared": "0.1.0",
51
+ "@types/bun": "^1.4.0",
52
+ "typescript": "^7.0.2"
53
+ }
54
+ }