usage-board 4.0.0 → 4.0.2

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.
Files changed (46) hide show
  1. package/dist/index.mjs +1 -1
  2. package/dist/public/_nuxt/BILXBbDI.js +21 -0
  3. package/dist/public/_nuxt/{DF2WsXH3.js → BJWBp9U3.js} +1 -1
  4. package/dist/public/_nuxt/{DXWxIyGU.js → BOTUKIyR.js} +1 -1
  5. package/dist/public/_nuxt/{De8DvPWL.js → BVD8FQXV.js} +1 -1
  6. package/dist/public/_nuxt/BXbx6JCB.js +1 -0
  7. package/dist/public/_nuxt/BfVC-jX7.js +1 -0
  8. package/dist/public/_nuxt/BhIINiyq.js +146 -0
  9. package/dist/public/_nuxt/CJECfsOP.js +1 -0
  10. package/dist/public/_nuxt/{D7qEPtpx.js → CJv0IWZB.js} +1 -1
  11. package/dist/public/_nuxt/{DKaPq50Z.js → CXOkrwUP.js} +2 -2
  12. package/dist/public/_nuxt/DFbWcbwl.js +261 -0
  13. package/dist/public/_nuxt/{C0GhHHgI.js → DaoeXHW_.js} +2 -2
  14. package/dist/public/_nuxt/DjeKkZG3.js +25 -0
  15. package/dist/public/_nuxt/builds/latest.json +1 -1
  16. package/dist/public/_nuxt/builds/meta/80f1a776-82e2-4b5c-9c07-a61063a0dd84.json +1 -0
  17. package/dist/public/_nuxt/{Jp5cgQZi.js → nv0LjcWu.js} +2 -2
  18. package/dist/public/_nuxt/{37OOe3RF.js → tDg_nW46.js} +1 -1
  19. package/dist/server/chunks/build/client.precomputed.mjs +1 -1
  20. package/dist/server/chunks/nitro/nitro.mjs +561 -333
  21. package/dist/server/chunks/routes/api/analysis/agent/session.json.mjs +16 -2
  22. package/dist/server/chunks/routes/api/analysis/agent/token.json.mjs +2 -2
  23. package/dist/server/chunks/routes/api/analysis/cache.json.mjs +1 -1
  24. package/dist/server/chunks/routes/api/analysis/hot-project.json.mjs +4 -3
  25. package/dist/server/chunks/routes/api/analysis/model.json.mjs +1 -1
  26. package/dist/server/chunks/routes/api/analysis/overview-cards.json.mjs +1 -1
  27. package/dist/server/chunks/routes/api/analysis/session.json.mjs +1 -1
  28. package/dist/server/chunks/routes/api/analysis/token/daily.json.mjs +13 -2
  29. package/dist/server/chunks/routes/api/analysis/token/today-hourly.json.mjs +1 -1
  30. package/dist/server/chunks/routes/api/analysis/token.json.mjs +1 -1
  31. package/dist/server/chunks/routes/api/payload.json.mjs +1 -1
  32. package/dist/server/chunks/routes/api/projects/_project/modules.get.mjs +1 -1
  33. package/dist/server/chunks/routes/api/projects/catalog.get.mjs +1 -1
  34. package/dist/server/chunks/routes/renderer.mjs +1 -1
  35. package/dist/server/chunks/routes/ws.mjs +13 -1
  36. package/dist/server/index.mjs +1 -1
  37. package/dist/server/package.json +1 -1
  38. package/package.json +1 -1
  39. package/dist/public/_nuxt/65Ayv2XK.js +0 -146
  40. package/dist/public/_nuxt/BOWwkrCY.js +0 -25
  41. package/dist/public/_nuxt/D9-Yw1TR.js +0 -1
  42. package/dist/public/_nuxt/DgMMKsPE.js +0 -258
  43. package/dist/public/_nuxt/DxvuOJRP.js +0 -1
  44. package/dist/public/_nuxt/builds/meta/7ce9c611-6071-4cbd-8926-1e53d9ef21bd.json +0 -1
  45. package/dist/public/_nuxt/qXgLTL_3.js +0 -21
  46. package/dist/public/_nuxt/y6mAKUDU.js +0 -1
@@ -2,7 +2,7 @@ import process from 'node:process';globalThis._importMeta_=globalThis._importMet
2
2
  import https from 'node:https';
3
3
  import { EventEmitter } from 'node:events';
4
4
  import { Buffer as Buffer$1 } from 'node:buffer';
5
- import { promises, existsSync, mkdirSync, readFileSync, statSync, readdirSync, accessSync, constants } from 'node:fs';
5
+ import { promises, existsSync, rmSync, mkdirSync, readFileSync, statSync, readdirSync, accessSync, constants } from 'node:fs';
6
6
  import { resolve as resolve$1, dirname as dirname$1, join, sep, basename as basename$1 } from 'node:path';
7
7
  import { createHash } from 'node:crypto';
8
8
  import { DatabaseSync } from 'node:sqlite';
@@ -4271,7 +4271,7 @@ function _expandFromEnv(value) {
4271
4271
  const _inlineRuntimeConfig = {
4272
4272
  "app": {
4273
4273
  "baseURL": "/",
4274
- "buildId": "7ce9c611-6071-4cbd-8926-1e53d9ef21bd",
4274
+ "buildId": "80f1a776-82e2-4b5c-9c07-a61063a0dd84",
4275
4275
  "buildAssetsDir": "/_nuxt/",
4276
4276
  "cdnURL": ""
4277
4277
  },
@@ -4299,7 +4299,7 @@ const _inlineRuntimeConfig = {
4299
4299
  }
4300
4300
  },
4301
4301
  "public": {
4302
- "appVersion": "4.0.0",
4302
+ "appVersion": "4.0.2",
4303
4303
  "home": "/Users/tangchenghui"
4304
4304
  },
4305
4305
  "icon": {
@@ -4826,6 +4826,9 @@ function normalizeNumber(value) {
4826
4826
  function roundCurrency(value) {
4827
4827
  return Math.round(value * 1e6) / 1e6;
4828
4828
  }
4829
+ function sumCurrency(total, amount) {
4830
+ return Math.round((total + amount) * 1e12) / 1e12;
4831
+ }
4829
4832
  function uniqueItems(items) {
4830
4833
  return Array.from(new Set(items));
4831
4834
  }
@@ -4936,7 +4939,7 @@ function buildProjectUsage(sessionUsage) {
4936
4939
  sessions: 0,
4937
4940
  tokenTotal: 0
4938
4941
  };
4939
- project.costUSD += session.costUSD;
4942
+ project.costUSD = sumCurrency(project.costUSD, session.costUSD);
4940
4943
  project.sessions += 1;
4941
4944
  project.tokenTotal += session.tokenTotal;
4942
4945
  projects.set(session.project, project);
@@ -4971,7 +4974,7 @@ function mergeDailyTokenUsage(items) {
4971
4974
  totalTokens: 0
4972
4975
  };
4973
4976
  group.cachedInputTokens += item.cachedInputTokens;
4974
- group.costUSD += item.costUSD;
4977
+ group.costUSD = sumCurrency(group.costUSD, item.costUSD);
4975
4978
  group.inputTokens += item.inputTokens;
4976
4979
  group.outputTokens += item.outputTokens;
4977
4980
  group.reasoningOutputTokens += item.reasoningOutputTokens;
@@ -4979,7 +4982,7 @@ function mergeDailyTokenUsage(items) {
4979
4982
  for (const [modelName, usage] of Object.entries(item.models)) {
4980
4983
  const model = (_b = group.models.get(modelName)) != null ? _b : createEmptyModelUsage();
4981
4984
  model.cachedInputTokens += usage.cachedInputTokens;
4982
- model.costUSD += usage.costUSD;
4985
+ model.costUSD = sumCurrency(model.costUSD, usage.costUSD);
4983
4986
  model.inputTokens += usage.inputTokens;
4984
4987
  model.isFallback = model.isFallback || usage.isFallback;
4985
4988
  model.outputTokens += usage.outputTokens;
@@ -4990,7 +4993,7 @@ function mergeDailyTokenUsage(items) {
4990
4993
  for (const [platform, platformUsage] of Object.entries((_c = item.platforms) != null ? _c : {})) {
4991
4994
  const currentPlatformUsage = (_d = group.platforms.get(platform)) != null ? _d : createEmptyDailyPlatformTokenUsage();
4992
4995
  currentPlatformUsage.cachedInputTokens += platformUsage.cachedInputTokens;
4993
- currentPlatformUsage.costUSD += platformUsage.costUSD;
4996
+ currentPlatformUsage.costUSD = sumCurrency(currentPlatformUsage.costUSD, platformUsage.costUSD);
4994
4997
  currentPlatformUsage.inputTokens += platformUsage.inputTokens;
4995
4998
  currentPlatformUsage.outputTokens += platformUsage.outputTokens;
4996
4999
  currentPlatformUsage.reasoningOutputTokens += platformUsage.reasoningOutputTokens;
@@ -4998,7 +5001,7 @@ function mergeDailyTokenUsage(items) {
4998
5001
  for (const [modelName, usage] of Object.entries(platformUsage.models)) {
4999
5002
  const model = (_e = currentPlatformUsage.models[modelName]) != null ? _e : createEmptyModelUsage();
5000
5003
  model.cachedInputTokens += usage.cachedInputTokens;
5001
- model.costUSD += usage.costUSD;
5004
+ model.costUSD = sumCurrency(model.costUSD, usage.costUSD);
5002
5005
  model.inputTokens += usage.inputTokens;
5003
5006
  model.isFallback = model.isFallback || usage.isFallback;
5004
5007
  model.outputTokens += usage.outputTokens;
@@ -5082,8 +5085,8 @@ function createEmptyDailyPlatformTokenUsage() {
5082
5085
 
5083
5086
  var __defProp$1 = Object.defineProperty;
5084
5087
  var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5085
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, key + "" , value);
5086
- const CACHE_SCHEMA_VERSION = 9;
5088
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
5089
+ const CACHE_SCHEMA_VERSION = 10;
5087
5090
  const ROW_KEY_SEPARATOR = "";
5088
5091
  const CACHE_SCHEMA_SQL = `
5089
5092
  CREATE TABLE IF NOT EXISTS cache_schema_meta (
@@ -5382,6 +5385,8 @@ const CACHE_SCHEMA_SQL = `
5382
5385
  content TEXT NOT NULL,
5383
5386
  cost_usd REAL NOT NULL,
5384
5387
  dedupe_key TEXT,
5388
+ fallback_dedupe_key TEXT,
5389
+ is_sidechain INTEGER,
5385
5390
  model TEXT,
5386
5391
  role TEXT NOT NULL,
5387
5392
  timestamp TEXT,
@@ -5404,9 +5409,10 @@ const CACHE_SCHEMA_SQL = `
5404
5409
  class UsageCacheRepository {
5405
5410
  constructor(databasePath) {
5406
5411
  __publicField$1(this, "database");
5412
+ __publicField$1(this, "databasePath");
5407
5413
  mkdirParentDirectory(databasePath);
5408
- this.database = openSqliteDatabase(databasePath);
5409
- this.database.exec("PRAGMA foreign_keys = ON");
5414
+ this.databasePath = databasePath;
5415
+ this.database = this.openDatabase();
5410
5416
  this.initializeSchema();
5411
5417
  }
5412
5418
  loadBootstrap() {
@@ -5415,7 +5421,9 @@ class UsageCacheRepository {
5415
5421
  if (!meta) {
5416
5422
  return null;
5417
5423
  }
5418
- const scopes = this.loadHydratedUsageScopes("bootstrap", false);
5424
+ const scopes = this.loadHydratedUsageScopes("bootstrap", {
5425
+ includeInteractions: false
5426
+ });
5419
5427
  const payload = Object.fromEntries(
5420
5428
  PROJECT_USAGE_PLATFORMS.map((platform) => {
5421
5429
  var _a2;
@@ -5516,45 +5524,39 @@ class UsageCacheRepository {
5516
5524
  this.persistProjectCatalog(payload);
5517
5525
  }
5518
5526
  loadProjectDetails() {
5519
- var _a;
5520
5527
  const projects = this.database.prepare(`
5521
5528
  SELECT label, create_time, session_count
5522
5529
  FROM projects
5523
5530
  ORDER BY label ASC
5524
5531
  `).all();
5525
- if (projects.length === 0) {
5526
- return /* @__PURE__ */ new Map();
5527
- }
5528
5532
  const projectModels = groupProjectModels(this.database.prepare(`
5529
5533
  SELECT project_label, model, model_order
5530
5534
  FROM project_models
5531
5535
  ORDER BY project_label ASC, model_order ASC
5532
5536
  `).all());
5533
5537
  const scopes = this.loadHydratedUsageScopes("project");
5534
- const details = /* @__PURE__ */ new Map();
5535
- for (const project of projects) {
5536
- const analyzing = Object.fromEntries(
5537
- PROJECT_USAGE_PLATFORMS.map((platform) => {
5538
- const scopeKey = createUsageScopeKey("project", platform, project.label);
5539
- const usage = scopes.get(scopeKey);
5540
- return [
5541
- platform,
5542
- usage ? {
5543
- ...usage,
5544
- sessions: usage.sessionUsage
5545
- } : createEmptyProjectPlatformUsage()
5546
- ];
5547
- })
5548
- );
5549
- details.set(project.label, normalizeProjectUsageDetail({
5550
- analyzing,
5551
- createTime: project.create_time,
5552
- label: project.label,
5553
- models: (_a = projectModels.get(project.label)) != null ? _a : [],
5554
- sessionCound: project.session_count
5555
- }));
5538
+ return buildProjectUsageDetails(projects, projectModels, scopes);
5539
+ }
5540
+ loadProjectDetail(label) {
5541
+ var _a;
5542
+ const project = this.database.prepare(`
5543
+ SELECT label, create_time, session_count
5544
+ FROM projects
5545
+ WHERE label = ?
5546
+ `).get(label);
5547
+ if (!project) {
5548
+ return null;
5556
5549
  }
5557
- return details;
5550
+ const projectModels = groupProjectModels(this.database.prepare(`
5551
+ SELECT project_label, model, model_order
5552
+ FROM project_models
5553
+ WHERE project_label = ?
5554
+ ORDER BY model_order ASC
5555
+ `).all(label));
5556
+ const scopes = this.loadHydratedUsageScopes("project", {
5557
+ projectLabel: label
5558
+ });
5559
+ return (_a = buildProjectUsageDetails([project], projectModels, scopes).get(label)) != null ? _a : null;
5558
5560
  }
5559
5561
  loadIndexedSourceFiles() {
5560
5562
  var _a, _b, _c;
@@ -5594,6 +5596,8 @@ class UsageCacheRepository {
5594
5596
  content,
5595
5597
  cost_usd,
5596
5598
  dedupe_key,
5599
+ fallback_dedupe_key,
5600
+ is_sidechain,
5597
5601
  model,
5598
5602
  role,
5599
5603
  timestamp,
@@ -5643,21 +5647,21 @@ class UsageCacheRepository {
5643
5647
  });
5644
5648
  }
5645
5649
  upsertIndexedSourceFiles(files) {
5646
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
5650
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
5647
5651
  if (files.length === 0) {
5648
5652
  return;
5649
5653
  }
5650
5654
  const deleteFileStatement = this.database.prepare("DELETE FROM indexed_files WHERE path = ?");
5651
5655
  const insertFileStatement = this.database.prepare(`
5652
- INSERT INTO indexed_files (path, platform, cache_signature, size, mtime_ms, updated_at)
5656
+ INSERT OR REPLACE INTO indexed_files (path, platform, cache_signature, size, mtime_ms, updated_at)
5653
5657
  VALUES (?, ?, ?, ?, ?, ?)
5654
5658
  `);
5655
5659
  const insertProjectStatement = this.database.prepare(`
5656
- INSERT INTO indexed_file_projects (path, project_name, project_order)
5660
+ INSERT OR REPLACE INTO indexed_file_projects (path, project_name, project_order)
5657
5661
  VALUES (?, ?, ?)
5658
5662
  `);
5659
5663
  const insertFragmentStatement = this.database.prepare(`
5660
- INSERT INTO indexed_file_fragments (
5664
+ INSERT OR REPLACE INTO indexed_file_fragments (
5661
5665
  path,
5662
5666
  fragment_order,
5663
5667
  fragment_key,
@@ -5671,13 +5675,15 @@ class UsageCacheRepository {
5671
5675
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
5672
5676
  `);
5673
5677
  const insertInteractionStatement = this.database.prepare(`
5674
- INSERT INTO indexed_fragment_interactions (
5678
+ INSERT OR REPLACE INTO indexed_fragment_interactions (
5675
5679
  fragment_id,
5676
5680
  interaction_order,
5677
5681
  interaction_index,
5678
5682
  content,
5679
5683
  cost_usd,
5680
5684
  dedupe_key,
5685
+ fallback_dedupe_key,
5686
+ is_sidechain,
5681
5687
  model,
5682
5688
  role,
5683
5689
  timestamp,
@@ -5694,7 +5700,7 @@ class UsageCacheRepository {
5694
5700
  tool_tokens,
5695
5701
  is_fallback_model
5696
5702
  )
5697
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
5703
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
5698
5704
  `);
5699
5705
  this.database.exec("BEGIN");
5700
5706
  try {
@@ -5725,21 +5731,23 @@ class UsageCacheRepository {
5725
5731
  interaction.content,
5726
5732
  interaction.costUSD,
5727
5733
  (_a = interaction.dedupeKey) != null ? _a : null,
5734
+ (_b = interaction.fallbackDedupeKey) != null ? _b : null,
5735
+ interaction.isSidechain ? 1 : 0,
5728
5736
  interaction.model,
5729
5737
  interaction.role,
5730
5738
  interaction.timestamp,
5731
5739
  interaction.type,
5732
- (_c = (_b = interaction.usage) == null ? void 0 : _b.inputTokens) != null ? _c : null,
5733
- (_e = (_d = interaction.usage) == null ? void 0 : _d.cachedInputTokens) != null ? _e : null,
5734
- (_g = (_f = interaction.usage) == null ? void 0 : _f.outputTokens) != null ? _g : null,
5735
- (_i = (_h = interaction.usage) == null ? void 0 : _h.reasoningOutputTokens) != null ? _i : null,
5736
- (_k = (_j = interaction.usage) == null ? void 0 : _j.extraTotalTokens) != null ? _k : null,
5737
- (_m = (_l = interaction.usage) == null ? void 0 : _l.totalTokens) != null ? _m : null,
5738
- (_o = (_n = interaction.usage) == null ? void 0 : _n.costUSD) != null ? _o : null,
5739
- (_q = (_p = interaction.usage) == null ? void 0 : _p.cacheCreationTokens) != null ? _q : null,
5740
- (_s = (_r = interaction.usage) == null ? void 0 : _r.cacheReadTokens) != null ? _s : null,
5741
- (_u = (_t = interaction.usage) == null ? void 0 : _t.toolTokens) != null ? _u : null,
5742
- ((_v = interaction.usage) == null ? void 0 : _v.isFallbackModel) ? 1 : 0
5740
+ (_d = (_c = interaction.usage) == null ? void 0 : _c.inputTokens) != null ? _d : null,
5741
+ (_f = (_e = interaction.usage) == null ? void 0 : _e.cachedInputTokens) != null ? _f : null,
5742
+ (_h = (_g = interaction.usage) == null ? void 0 : _g.outputTokens) != null ? _h : null,
5743
+ (_j = (_i = interaction.usage) == null ? void 0 : _i.reasoningOutputTokens) != null ? _j : null,
5744
+ (_l = (_k = interaction.usage) == null ? void 0 : _k.extraTotalTokens) != null ? _l : null,
5745
+ (_n = (_m = interaction.usage) == null ? void 0 : _m.totalTokens) != null ? _n : null,
5746
+ (_p = (_o = interaction.usage) == null ? void 0 : _o.costUSD) != null ? _p : null,
5747
+ (_r = (_q = interaction.usage) == null ? void 0 : _q.cacheCreationTokens) != null ? _r : null,
5748
+ (_t = (_s = interaction.usage) == null ? void 0 : _s.cacheReadTokens) != null ? _t : null,
5749
+ (_v = (_u = interaction.usage) == null ? void 0 : _u.toolTokens) != null ? _v : null,
5750
+ ((_w = interaction.usage) == null ? void 0 : _w.isFallbackModel) ? 1 : 0
5743
5751
  );
5744
5752
  }
5745
5753
  }
@@ -5768,11 +5776,11 @@ class UsageCacheRepository {
5768
5776
  }
5769
5777
  replaceProjectDetails(details) {
5770
5778
  const insertProjectStatement = this.database.prepare(`
5771
- INSERT INTO projects (label, create_time, session_count, updated_at)
5779
+ INSERT OR REPLACE INTO projects (label, create_time, session_count, updated_at)
5772
5780
  VALUES (?, ?, ?, ?)
5773
5781
  `);
5774
5782
  const insertProjectModelStatement = this.database.prepare(`
5775
- INSERT INTO project_models (project_label, model, model_order)
5783
+ INSERT OR REPLACE INTO project_models (project_label, model, model_order)
5776
5784
  VALUES (?, ?, ?)
5777
5785
  `);
5778
5786
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -5811,16 +5819,11 @@ class UsageCacheRepository {
5811
5819
  }
5812
5820
  initializeSchema() {
5813
5821
  this.database.exec(CACHE_SCHEMA_SQL);
5814
- this.ensureIndexedFilesCacheSignatureColumn();
5815
- this.ensureDailyUsageModelCostColumn();
5816
- this.ensureOverviewCardSubvalueColumn();
5817
- this.ensureProjectCatalogColumns();
5818
- this.ensureInteractionExtraTotalTokenColumns();
5819
5822
  const currentSchemaVersion = this.getCurrentSchemaVersion();
5820
- if (currentSchemaVersion >= CACHE_SCHEMA_VERSION) {
5821
- return;
5823
+ if (this.shouldResetCache(currentSchemaVersion)) {
5824
+ this.resetCacheDatabase();
5825
+ this.database.exec(CACHE_SCHEMA_SQL);
5822
5826
  }
5823
- this.migrateLegacyDataIfNeeded();
5824
5827
  this.setSchemaVersion(CACHE_SCHEMA_VERSION);
5825
5828
  }
5826
5829
  getCurrentSchemaVersion() {
@@ -5831,6 +5834,49 @@ class UsageCacheRepository {
5831
5834
  WHERE id = 1
5832
5835
  `).get()) == null ? void 0 : _a.schema_version) != null ? _b : 0;
5833
5836
  }
5837
+ openDatabase() {
5838
+ const database = openSqliteDatabase(this.databasePath);
5839
+ database.exec("PRAGMA foreign_keys = ON");
5840
+ return database;
5841
+ }
5842
+ shouldResetCache(currentSchemaVersion) {
5843
+ if (this.hasLegacyData() || !this.hasCompatibleNormalizedSchema()) {
5844
+ return true;
5845
+ }
5846
+ if (currentSchemaVersion === CACHE_SCHEMA_VERSION) {
5847
+ return false;
5848
+ }
5849
+ return currentSchemaVersion !== 0 || this.hasCachedData();
5850
+ }
5851
+ hasCompatibleNormalizedSchema() {
5852
+ return this.hasTableColumns("indexed_files", ["cache_signature"]) && this.hasTableColumns("project_catalog_entries", ["platforms_json", "total_tokens"]) && !this.hasTableColumns("project_catalog_entries", ["type"]) && this.hasTableColumns("usage_scope_daily_usage_models", ["cost_usd"]) && this.hasTableColumns("usage_scope_overview_cards", ["subvalue_json"]) && this.hasTableColumns("usage_scope_interactions", ["extra_total_tokens"]) && this.hasTableColumns("indexed_fragment_interactions", ["extra_total_tokens", "fallback_dedupe_key", "is_sidechain"]);
5853
+ }
5854
+ hasTableColumns(tableName, columnNames) {
5855
+ if (!this.hasTable(tableName)) {
5856
+ return false;
5857
+ }
5858
+ const columns = this.database.prepare(`PRAGMA table_info(${tableName})`).all();
5859
+ return columnNames.every((columnName) => columns.some((column) => column.name === columnName));
5860
+ }
5861
+ hasCachedData() {
5862
+ return ["cache_state", "indexed_files", "project_catalog_entries", "projects", "usage_scopes"].some((tableName) => {
5863
+ var _a, _b;
5864
+ if (!this.hasTable(tableName)) {
5865
+ return false;
5866
+ }
5867
+ return ((_b = (_a = this.database.prepare(`SELECT COUNT(*) AS total FROM ${tableName}`).get()) == null ? void 0 : _a.total) != null ? _b : 0) > 0;
5868
+ });
5869
+ }
5870
+ resetCacheDatabase() {
5871
+ this.database.close();
5872
+ for (const path of [this.databasePath, `${this.databasePath}-shm`, `${this.databasePath}-wal`]) {
5873
+ rmSync(path, {
5874
+ force: true,
5875
+ recursive: false
5876
+ });
5877
+ }
5878
+ this.database = this.openDatabase();
5879
+ }
5834
5880
  setSchemaVersion(version) {
5835
5881
  this.database.prepare(`
5836
5882
  INSERT INTO cache_schema_meta (id, schema_version)
@@ -5945,6 +5991,12 @@ class UsageCacheRepository {
5945
5991
  if (!indexedInteractionColumns.some((column) => column.name === "extra_total_tokens")) {
5946
5992
  this.database.exec("ALTER TABLE indexed_fragment_interactions ADD COLUMN extra_total_tokens INTEGER");
5947
5993
  }
5994
+ if (!indexedInteractionColumns.some((column) => column.name === "fallback_dedupe_key")) {
5995
+ this.database.exec("ALTER TABLE indexed_fragment_interactions ADD COLUMN fallback_dedupe_key TEXT");
5996
+ }
5997
+ if (!indexedInteractionColumns.some((column) => column.name === "is_sidechain")) {
5998
+ this.database.exec("ALTER TABLE indexed_fragment_interactions ADD COLUMN is_sidechain INTEGER");
5999
+ }
5948
6000
  }
5949
6001
  }
5950
6002
  clearNormalizedTables() {
@@ -6012,7 +6064,7 @@ class UsageCacheRepository {
6012
6064
  const payloadHash = (_b = options.payloadHash) != null ? _b : createPayloadHash(JSON.stringify(payload));
6013
6065
  const deleteStatement = this.database.prepare("DELETE FROM project_catalog_entries");
6014
6066
  const insertStatement = this.database.prepare(`
6015
- INSERT INTO project_catalog_entries (label, platforms_json, total_tokens, updated_at)
6067
+ INSERT OR REPLACE INTO project_catalog_entries (label, platforms_json, total_tokens, updated_at)
6016
6068
  VALUES (?, ?, ?, ?)
6017
6069
  `);
6018
6070
  this.database.exec("BEGIN");
@@ -6043,7 +6095,7 @@ class UsageCacheRepository {
6043
6095
  const scopeKey = createUsageScopeKey(options.kind, options.platform, options.projectLabel);
6044
6096
  const payloadHash = createPayloadHash(JSON.stringify(options.usage));
6045
6097
  const insertScopeStatement = this.database.prepare(`
6046
- INSERT INTO usage_scopes (
6098
+ INSERT OR REPLACE INTO usage_scopes (
6047
6099
  scope_key,
6048
6100
  scope_kind,
6049
6101
  project_label,
@@ -6060,7 +6112,7 @@ class UsageCacheRepository {
6060
6112
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6061
6113
  `);
6062
6114
  const insertOverviewCardStatement = this.database.prepare(`
6063
- INSERT INTO usage_scope_overview_cards (
6115
+ INSERT OR REPLACE INTO usage_scope_overview_cards (
6064
6116
  scope_key,
6065
6117
  position,
6066
6118
  icon,
@@ -6074,7 +6126,7 @@ class UsageCacheRepository {
6074
6126
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
6075
6127
  `);
6076
6128
  const insertTokenRowStatement = this.database.prepare(`
6077
- INSERT INTO usage_scope_token_rows (
6129
+ INSERT OR REPLACE INTO usage_scope_token_rows (
6078
6130
  scope_key,
6079
6131
  bucket,
6080
6132
  row_order,
@@ -6092,7 +6144,7 @@ class UsageCacheRepository {
6092
6144
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6093
6145
  `);
6094
6146
  const insertTokenRowModelStatement = this.database.prepare(`
6095
- INSERT INTO usage_scope_token_row_models (
6147
+ INSERT OR REPLACE INTO usage_scope_token_row_models (
6096
6148
  scope_key,
6097
6149
  bucket,
6098
6150
  row_id,
@@ -6102,7 +6154,7 @@ class UsageCacheRepository {
6102
6154
  VALUES (?, ?, ?, ?, ?)
6103
6155
  `);
6104
6156
  const insertTokenRowProjectStatement = this.database.prepare(`
6105
- INSERT INTO usage_scope_token_row_projects (
6157
+ INSERT OR REPLACE INTO usage_scope_token_row_projects (
6106
6158
  scope_key,
6107
6159
  bucket,
6108
6160
  row_id,
@@ -6112,7 +6164,7 @@ class UsageCacheRepository {
6112
6164
  VALUES (?, ?, ?, ?, ?)
6113
6165
  `);
6114
6166
  const insertDailyUsageStatement = this.database.prepare(`
6115
- INSERT INTO usage_scope_daily_usage (
6167
+ INSERT OR REPLACE INTO usage_scope_daily_usage (
6116
6168
  scope_key,
6117
6169
  row_order,
6118
6170
  date,
@@ -6126,7 +6178,7 @@ class UsageCacheRepository {
6126
6178
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
6127
6179
  `);
6128
6180
  const insertDailyUsageModelStatement = this.database.prepare(`
6129
- INSERT INTO usage_scope_daily_usage_models (
6181
+ INSERT OR REPLACE INTO usage_scope_daily_usage_models (
6130
6182
  scope_key,
6131
6183
  date,
6132
6184
  model,
@@ -6142,7 +6194,7 @@ class UsageCacheRepository {
6142
6194
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6143
6195
  `);
6144
6196
  const insertMonthlyModelStatement = this.database.prepare(`
6145
- INSERT INTO usage_scope_monthly_model_usage (
6197
+ INSERT OR REPLACE INTO usage_scope_monthly_model_usage (
6146
6198
  scope_key,
6147
6199
  row_order,
6148
6200
  month,
@@ -6152,7 +6204,7 @@ class UsageCacheRepository {
6152
6204
  VALUES (?, ?, ?, ?, ?)
6153
6205
  `);
6154
6206
  const insertProjectUsageStatement = this.database.prepare(`
6155
- INSERT INTO usage_scope_project_usage (
6207
+ INSERT OR REPLACE INTO usage_scope_project_usage (
6156
6208
  scope_key,
6157
6209
  row_order,
6158
6210
  label,
@@ -6168,7 +6220,7 @@ class UsageCacheRepository {
6168
6220
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6169
6221
  `);
6170
6222
  const insertSessionStatement = this.database.prepare(`
6171
- INSERT INTO usage_scope_sessions (
6223
+ INSERT OR REPLACE INTO usage_scope_sessions (
6172
6224
  scope_key,
6173
6225
  session_key,
6174
6226
  session_order,
@@ -6195,7 +6247,7 @@ class UsageCacheRepository {
6195
6247
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6196
6248
  `);
6197
6249
  const insertSessionModelStatement = this.database.prepare(`
6198
- INSERT INTO usage_scope_session_models (
6250
+ INSERT OR REPLACE INTO usage_scope_session_models (
6199
6251
  scope_key,
6200
6252
  session_key,
6201
6253
  model,
@@ -6204,7 +6256,7 @@ class UsageCacheRepository {
6204
6256
  VALUES (?, ?, ?, ?)
6205
6257
  `);
6206
6258
  const insertInteractionStatement = this.database.prepare(`
6207
- INSERT INTO usage_scope_interactions (
6259
+ INSERT OR REPLACE INTO usage_scope_interactions (
6208
6260
  scope_key,
6209
6261
  session_key,
6210
6262
  interaction_order,
@@ -6389,8 +6441,12 @@ class UsageCacheRepository {
6389
6441
  }
6390
6442
  }
6391
6443
  }
6392
- loadHydratedUsageScopes(kind, includeInteractions = true) {
6393
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
6444
+ loadHydratedUsageScopes(kind, options = {}) {
6445
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
6446
+ const includeInteractions = (_a = options.includeInteractions) != null ? _a : true;
6447
+ const baseScopeWhere = options.projectLabel === void 0 ? "scope_kind = ?" : "scope_kind = ? AND project_label = ?";
6448
+ const joinedScopeWhere = options.projectLabel === void 0 ? "scope.scope_kind = ?" : "scope.scope_kind = ? AND scope.project_label = ?";
6449
+ const scopeParameters = options.projectLabel === void 0 ? [kind] : [kind, options.projectLabel];
6394
6450
  const scopes = this.database.prepare(`
6395
6451
  SELECT
6396
6452
  scope_key,
@@ -6406,9 +6462,9 @@ class UsageCacheRepository {
6406
6462
  today_top_project,
6407
6463
  today_top_project_session_count
6408
6464
  FROM usage_scopes
6409
- WHERE scope_kind = ?
6465
+ WHERE ${baseScopeWhere}
6410
6466
  ORDER BY project_label ASC, platform ASC
6411
- `).all(kind);
6467
+ `).all(...scopeParameters);
6412
6468
  if (scopes.length === 0) {
6413
6469
  return /* @__PURE__ */ new Map();
6414
6470
  }
@@ -6417,9 +6473,9 @@ class UsageCacheRepository {
6417
6473
  SELECT card.scope_key, card.position, card.icon, card.name, card.value, card.detail, card.subvalue_json, card.trend, card.trend_tone
6418
6474
  FROM usage_scope_overview_cards AS card
6419
6475
  JOIN usage_scopes AS scope ON scope.scope_key = card.scope_key
6420
- WHERE scope.scope_kind = ?
6476
+ WHERE ${joinedScopeWhere}
6421
6477
  ORDER BY card.scope_key ASC, card.position ASC
6422
- `).all(kind));
6478
+ `).all(...scopeParameters));
6423
6479
  const tokenRows = groupTokenRows(
6424
6480
  this.database.prepare(`
6425
6481
  SELECT
@@ -6438,23 +6494,23 @@ class UsageCacheRepository {
6438
6494
  row.cost_usd
6439
6495
  FROM usage_scope_token_rows AS row
6440
6496
  JOIN usage_scopes AS scope ON scope.scope_key = row.scope_key
6441
- WHERE scope.scope_kind = ?
6497
+ WHERE ${joinedScopeWhere}
6442
6498
  ORDER BY row.scope_key ASC, row.bucket ASC, row.row_order ASC
6443
- `).all(kind),
6499
+ `).all(...scopeParameters),
6444
6500
  this.database.prepare(`
6445
6501
  SELECT model.scope_key, model.bucket, model.row_id, model.model, model.model_order
6446
6502
  FROM usage_scope_token_row_models AS model
6447
6503
  JOIN usage_scopes AS scope ON scope.scope_key = model.scope_key
6448
- WHERE scope.scope_kind = ?
6504
+ WHERE ${joinedScopeWhere}
6449
6505
  ORDER BY model.scope_key ASC, model.bucket ASC, model.row_id ASC, model.model_order ASC
6450
- `).all(kind),
6506
+ `).all(...scopeParameters),
6451
6507
  this.database.prepare(`
6452
6508
  SELECT project.scope_key, project.bucket, project.row_id, project.project, project.project_order
6453
6509
  FROM usage_scope_token_row_projects AS project
6454
6510
  JOIN usage_scopes AS scope ON scope.scope_key = project.scope_key
6455
- WHERE scope.scope_kind = ?
6511
+ WHERE ${joinedScopeWhere}
6456
6512
  ORDER BY project.scope_key ASC, project.bucket ASC, project.row_id ASC, project.project_order ASC
6457
- `).all(kind)
6513
+ `).all(...scopeParameters)
6458
6514
  );
6459
6515
  const dailyUsage = groupDailyUsage(
6460
6516
  this.database.prepare(`
@@ -6470,9 +6526,9 @@ class UsageCacheRepository {
6470
6526
  daily.cost_usd
6471
6527
  FROM usage_scope_daily_usage AS daily
6472
6528
  JOIN usage_scopes AS scope ON scope.scope_key = daily.scope_key
6473
- WHERE scope.scope_kind = ?
6529
+ WHERE ${joinedScopeWhere}
6474
6530
  ORDER BY daily.scope_key ASC, daily.row_order ASC
6475
- `).all(kind),
6531
+ `).all(...scopeParameters),
6476
6532
  this.database.prepare(`
6477
6533
  SELECT
6478
6534
  model.scope_key,
@@ -6488,17 +6544,17 @@ class UsageCacheRepository {
6488
6544
  model.is_fallback
6489
6545
  FROM usage_scope_daily_usage_models AS model
6490
6546
  JOIN usage_scopes AS scope ON scope.scope_key = model.scope_key
6491
- WHERE scope.scope_kind = ?
6547
+ WHERE ${joinedScopeWhere}
6492
6548
  ORDER BY model.scope_key ASC, model.date ASC, model.model_order ASC
6493
- `).all(kind)
6549
+ `).all(...scopeParameters)
6494
6550
  );
6495
6551
  const monthlyUsage = groupMonthlyModelUsage(this.database.prepare(`
6496
6552
  SELECT monthly.scope_key, monthly.row_order, monthly.month, monthly.model, monthly.token_total
6497
6553
  FROM usage_scope_monthly_model_usage AS monthly
6498
6554
  JOIN usage_scopes AS scope ON scope.scope_key = monthly.scope_key
6499
- WHERE scope.scope_kind = ?
6555
+ WHERE ${joinedScopeWhere}
6500
6556
  ORDER BY monthly.scope_key ASC, monthly.row_order ASC
6501
- `).all(kind));
6557
+ `).all(...scopeParameters));
6502
6558
  const projectUsage = groupProjectUsage(this.database.prepare(`
6503
6559
  SELECT
6504
6560
  usage.scope_key,
@@ -6514,9 +6570,9 @@ class UsageCacheRepository {
6514
6570
  usage.cost_usd
6515
6571
  FROM usage_scope_project_usage AS usage
6516
6572
  JOIN usage_scopes AS scope ON scope.scope_key = usage.scope_key
6517
- WHERE scope.scope_kind = ?
6573
+ WHERE ${joinedScopeWhere}
6518
6574
  ORDER BY usage.scope_key ASC, usage.row_order ASC
6519
- `).all(kind));
6575
+ `).all(...scopeParameters));
6520
6576
  const sessions = groupSessions(
6521
6577
  this.database.prepare(`
6522
6578
  SELECT
@@ -6544,16 +6600,16 @@ class UsageCacheRepository {
6544
6600
  session.top_model
6545
6601
  FROM usage_scope_sessions AS session
6546
6602
  JOIN usage_scopes AS scope ON scope.scope_key = session.scope_key
6547
- WHERE scope.scope_kind = ?
6603
+ WHERE ${joinedScopeWhere}
6548
6604
  ORDER BY session.scope_key ASC, session.session_order ASC
6549
- `).all(kind),
6605
+ `).all(...scopeParameters),
6550
6606
  this.database.prepare(`
6551
6607
  SELECT model.scope_key, model.session_key, model.model, model.model_order
6552
6608
  FROM usage_scope_session_models AS model
6553
6609
  JOIN usage_scopes AS scope ON scope.scope_key = model.scope_key
6554
- WHERE scope.scope_kind = ?
6610
+ WHERE ${joinedScopeWhere}
6555
6611
  ORDER BY model.scope_key ASC, model.session_key ASC, model.model_order ASC
6556
- `).all(kind),
6612
+ `).all(...scopeParameters),
6557
6613
  includeInteractions ? this.database.prepare(`
6558
6614
  SELECT
6559
6615
  interaction.scope_key,
@@ -6579,9 +6635,9 @@ class UsageCacheRepository {
6579
6635
  interaction.is_fallback_model
6580
6636
  FROM usage_scope_interactions AS interaction
6581
6637
  JOIN usage_scopes AS scope ON scope.scope_key = interaction.scope_key
6582
- WHERE scope.scope_kind = ?
6638
+ WHERE ${joinedScopeWhere}
6583
6639
  ORDER BY interaction.scope_key ASC, interaction.session_key ASC, interaction.interaction_order ASC
6584
- `).all(kind) : []
6640
+ `).all(...scopeParameters) : []
6585
6641
  );
6586
6642
  const hydrated = /* @__PURE__ */ new Map();
6587
6643
  for (const scope of scopes) {
@@ -6589,27 +6645,27 @@ class UsageCacheRepository {
6589
6645
  continue;
6590
6646
  }
6591
6647
  const scopeTokenRows = tokenRows.get(scope.scope_key);
6592
- const sessionUsage = (_a = sessions.get(scope.scope_key)) != null ? _a : [];
6648
+ const sessionUsage = (_b = sessions.get(scope.scope_key)) != null ? _b : [];
6593
6649
  hydrated.set(scope.scope_key, {
6594
- dailyRows: (_b = scopeTokenRows == null ? void 0 : scopeTokenRows.daily) != null ? _b : [],
6595
- dailyTokenUsage: (_c = dailyUsage.get(scope.scope_key)) != null ? _c : [],
6596
- monthlyModelUsage: (_d = monthlyUsage.get(scope.scope_key)) != null ? _d : [],
6597
- monthlyRows: (_e = scopeTokenRows == null ? void 0 : scopeTokenRows.monthly) != null ? _e : [],
6598
- overviewCards: (_f = overviewCards.get(scope.scope_key)) != null ? _f : [],
6599
- projectUsage: (_g = projectUsage.get(scope.scope_key)) != null ? _g : [],
6600
- sessionRows: (_h = scopeTokenRows == null ? void 0 : scopeTokenRows.session) != null ? _h : [],
6650
+ dailyRows: (_c = scopeTokenRows == null ? void 0 : scopeTokenRows.daily) != null ? _c : [],
6651
+ dailyTokenUsage: (_d = dailyUsage.get(scope.scope_key)) != null ? _d : [],
6652
+ monthlyModelUsage: (_e = monthlyUsage.get(scope.scope_key)) != null ? _e : [],
6653
+ monthlyRows: (_f = scopeTokenRows == null ? void 0 : scopeTokenRows.monthly) != null ? _f : [],
6654
+ overviewCards: (_g = overviewCards.get(scope.scope_key)) != null ? _g : [],
6655
+ projectUsage: (_h = projectUsage.get(scope.scope_key)) != null ? _h : [],
6656
+ sessionRows: (_i = scopeTokenRows == null ? void 0 : scopeTokenRows.session) != null ? _i : [],
6601
6657
  sessionUsage,
6602
6658
  todayTopModel: scope.today_top_model ? {
6603
6659
  model: scope.today_top_model,
6604
- totalTokens: (_i = scope.today_top_model_total_tokens) != null ? _i : 0
6660
+ totalTokens: (_j = scope.today_top_model_total_tokens) != null ? _j : 0
6605
6661
  } : null,
6606
6662
  todayTopProject: scope.today_top_project ? {
6607
6663
  project: scope.today_top_project,
6608
- sessionCount: (_j = scope.today_top_project_session_count) != null ? _j : 0
6664
+ sessionCount: (_k = scope.today_top_project_session_count) != null ? _k : 0
6609
6665
  } : null,
6610
6666
  todayTotalCost: scope.today_total_cost,
6611
6667
  todayTotalTokens: scope.today_total_tokens,
6612
- weeklyRows: (_k = scopeTokenRows == null ? void 0 : scopeTokenRows.weekly) != null ? _k : []
6668
+ weeklyRows: (_l = scopeTokenRows == null ? void 0 : scopeTokenRows.weekly) != null ? _l : []
6613
6669
  });
6614
6670
  }
6615
6671
  return hydrated;
@@ -6744,6 +6800,33 @@ function groupProjectModels(rows) {
6744
6800
  }
6745
6801
  return grouped;
6746
6802
  }
6803
+ function buildProjectUsageDetails(projects, projectModels, scopes) {
6804
+ var _a;
6805
+ const details = /* @__PURE__ */ new Map();
6806
+ for (const project of projects) {
6807
+ const analyzing = Object.fromEntries(
6808
+ PROJECT_USAGE_PLATFORMS.map((platform) => {
6809
+ const scopeKey = createUsageScopeKey("project", platform, project.label);
6810
+ const usage = scopes.get(scopeKey);
6811
+ return [
6812
+ platform,
6813
+ usage ? {
6814
+ ...usage,
6815
+ sessions: usage.sessionUsage
6816
+ } : createEmptyProjectPlatformUsage()
6817
+ ];
6818
+ })
6819
+ );
6820
+ details.set(project.label, normalizeProjectUsageDetail({
6821
+ analyzing,
6822
+ createTime: project.create_time,
6823
+ label: project.label,
6824
+ models: (_a = projectModels.get(project.label)) != null ? _a : [],
6825
+ sessionCound: project.session_count
6826
+ }));
6827
+ }
6828
+ return details;
6829
+ }
6747
6830
  function groupIndexedFileProjects(rows) {
6748
6831
  var _a;
6749
6832
  const grouped = /* @__PURE__ */ new Map();
@@ -6763,7 +6846,9 @@ function groupIndexedInteractions(rows) {
6763
6846
  content: row.content,
6764
6847
  costUSD: row.cost_usd,
6765
6848
  dedupeKey: row.dedupe_key,
6849
+ fallbackDedupeKey: row.fallback_dedupe_key,
6766
6850
  index: row.interaction_index,
6851
+ isSidechain: row.is_sidechain === 1,
6767
6852
  model: row.model,
6768
6853
  role: row.role,
6769
6854
  timestamp: row.timestamp,
@@ -7527,7 +7612,7 @@ function buildDailyUsageGroups(events, options = {}) {
7527
7612
  isFallback: false
7528
7613
  };
7529
7614
  addUsage(modelUsage, event);
7530
- modelUsage.costUSD += getEventCostUSD(event, options);
7615
+ modelUsage.costUSD = sumCurrency(modelUsage.costUSD, getEventCostUSD(event, options));
7531
7616
  if (event.isFallbackModel) {
7532
7617
  modelUsage.isFallback = true;
7533
7618
  }
@@ -7652,7 +7737,7 @@ function toUsageSessionUsageItem(session, options = {}) {
7652
7737
  cachedInputTokens: getCachedInputTokens(session, options),
7653
7738
  costUSD: session.costUSD,
7654
7739
  date: formatDateLabelFromDateKey(getDateKey(startedAtDate)),
7655
- duration: formatDuration(session.durationMinutes),
7740
+ duration: formatDuration$1(session.durationMinutes),
7656
7741
  durationMinutes: session.durationMinutes,
7657
7742
  id: (_a = session.id) != null ? _a : session.sessionId,
7658
7743
  inputTokens: session.inputTokens,
@@ -7883,7 +7968,7 @@ function formatMonthLabel(monthKey) {
7883
7968
  year: "numeric"
7884
7969
  }).format(date);
7885
7970
  }
7886
- function formatDuration(minutes) {
7971
+ function formatDuration$1(minutes) {
7887
7972
  const hours = Math.floor(minutes / 60);
7888
7973
  const remainingMinutes = minutes % 60;
7889
7974
  if (hours === 0) {
@@ -8091,7 +8176,7 @@ function addEventToAggregateGroup(group, event, options) {
8091
8176
  group.outputTokens += event.outputTokens;
8092
8177
  group.reasoningOutputTokens += event.reasoningOutputTokens;
8093
8178
  group.totalTokens += event.totalTokens;
8094
- group.costUSD += getEventCostUSD(event, options);
8179
+ group.costUSD = sumCurrency(group.costUSD, getEventCostUSD(event, options));
8095
8180
  group.models = shouldIncludeModel(event, options) ? uniqueItems([...group.models, event.model]) : group.models;
8096
8181
  group.projects = uniqueItems([...group.projects, event.project]);
8097
8182
  }
@@ -8459,7 +8544,7 @@ const GEMINI_FALLBACK_PRICING_TABLE = {
8459
8544
  }
8460
8545
  };
8461
8546
 
8462
- const CLAUDE_CODE_CACHE_SIGNATURE = "claude-code-dedupe:message-id-v1";
8547
+ const CLAUDE_CODE_CACHE_SIGNATURE = "claude-code-dedupe:daily-agent-progress-v2";
8463
8548
  const claudeCodeUsageAdapter = {
8464
8549
  async createPricingResolver() {
8465
8550
  return createLiteLLMPricingResolver({
@@ -8488,20 +8573,20 @@ const claudeCodeUsageAdapter = {
8488
8573
  const lines = parseJsonlFile(filePath);
8489
8574
  const fragments = /* @__PURE__ */ new Map();
8490
8575
  for (let index = 0; index < lines.length; index += 1) {
8491
- const line = lines[index];
8492
- if (!isSupportedClaudeUsageLine(line)) {
8576
+ const line = getClaudeUsageLine(lines[index]);
8577
+ if (!line) {
8493
8578
  continue;
8494
8579
  }
8495
- const sessionId = normalizeStringValue(line.sessionId) || fallbackSessionId;
8496
- const cwd = (_a = normalizeStringValue(line.cwd)) != null ? _a : "";
8580
+ const sessionId = line.sessionId || fallbackSessionId;
8581
+ const cwd = (_a = line.cwd) != null ? _a : "";
8497
8582
  const project = getProjectName(cwd, "") || decodeClaudeProjectPath(projectPath);
8498
- const timestamp = (_b = toIsoString(line.timestamp)) != null ? _b : null;
8499
- const message = normalizeUnknownRecord(line.message);
8500
- const usageRecord = normalizeUnknownRecord(message == null ? void 0 : message.usage);
8583
+ const timestamp = line.timestamp;
8584
+ const message = line.message;
8585
+ const usageRecord = line.usage;
8501
8586
  const model = getClaudeDisplayModel(line);
8502
- const usage = usageRecord ? getClaudeInteractionUsage(usageRecord, model, resolvePricing, line) : null;
8587
+ const usage = usageRecord ? getClaudeInteractionUsage(usageRecord, model, resolvePricing, line.costUSD) : null;
8503
8588
  const key = `${project}:${sessionId}`;
8504
- const fragment = (_c = fragments.get(key)) != null ? _c : createSessionFragment({
8589
+ const fragment = (_b = fragments.get(key)) != null ? _b : createSessionFragment({
8505
8590
  project,
8506
8591
  repository: `local/${project}`,
8507
8592
  sessionId,
@@ -8510,13 +8595,15 @@ const claudeCodeUsageAdapter = {
8510
8595
  });
8511
8596
  addFragmentInteraction(fragment, {
8512
8597
  content: extractClaudeMessageText(message == null ? void 0 : message.content),
8513
- costUSD: (_d = usage == null ? void 0 : usage.costUSD) != null ? _d : 0,
8598
+ costUSD: (_c = usage == null ? void 0 : usage.costUSD) != null ? _c : 0,
8514
8599
  dedupeKey: getClaudeUniqueHash(line),
8600
+ fallbackDedupeKey: normalizeStringValue(message == null ? void 0 : message.id),
8515
8601
  index,
8602
+ isSidechain: line.isSidechain === true,
8516
8603
  model: model != null ? model : null,
8517
- role: getInteractionRole(line, message),
8604
+ role: getInteractionRole(line.type, message),
8518
8605
  timestamp,
8519
- type: normalizeStringValue(line.type) || normalizeStringValue(message == null ? void 0 : message.type) || "message",
8606
+ type: (_d = line.type) != null ? _d : normalizeStringValue(message == null ? void 0 : message.type) || "message",
8520
8607
  usage
8521
8608
  });
8522
8609
  fragments.set(key, fragment);
@@ -8527,13 +8614,12 @@ const claudeCodeUsageAdapter = {
8527
8614
  return config.claudeCodePaths.map((path) => join(path, "projects", "**", "*.jsonl"));
8528
8615
  }
8529
8616
  };
8530
- function getClaudeInteractionUsage(usage, model, resolvePricing, line) {
8531
- var _a;
8617
+ function getClaudeInteractionUsage(usage, model, resolvePricing, costUSD) {
8532
8618
  const cacheCreationTokens = normalizeNumber(usage.cache_creation_input_tokens);
8533
8619
  const cacheReadTokens = normalizeNumber(usage.cache_read_input_tokens);
8534
8620
  const inputTokens = normalizeNumber(usage.input_tokens);
8535
8621
  const outputTokens = normalizeNumber(usage.output_tokens);
8536
- const costUSD = (_a = normalizeFiniteNumberOrNull(line.costUSD)) != null ? _a : model ? calculateUsageCostUSD({
8622
+ const resolvedCostUSD = costUSD != null ? costUSD : model ? calculateUsageCostUSD({
8537
8623
  cacheCreationTokens,
8538
8624
  cachedInputTokens: cacheReadTokens,
8539
8625
  inputTokens,
@@ -8545,7 +8631,7 @@ function getClaudeInteractionUsage(usage, model, resolvePricing, line) {
8545
8631
  cacheCreationTokens,
8546
8632
  cacheReadTokens,
8547
8633
  cachedInputTokens: cacheCreationTokens + cacheReadTokens,
8548
- costUSD,
8634
+ costUSD: resolvedCostUSD,
8549
8635
  inputTokens,
8550
8636
  outputTokens,
8551
8637
  reasoningOutputTokens: 0,
@@ -8553,18 +8639,15 @@ function getClaudeInteractionUsage(usage, model, resolvePricing, line) {
8553
8639
  };
8554
8640
  }
8555
8641
  function getClaudeDisplayModel(line) {
8556
- const message = normalizeUnknownRecord(line.message);
8557
- const model = normalizeStringValue(message == null ? void 0 : message.model);
8558
- const usage = normalizeUnknownRecord(message == null ? void 0 : message.usage);
8642
+ const model = normalizeStringValue(line.message.model);
8559
8643
  if (!model) {
8560
8644
  return void 0;
8561
8645
  }
8562
- return (usage == null ? void 0 : usage.speed) === "fast" ? `${model}-fast` : model;
8646
+ return line.usage.speed === "fast" ? `${model}-fast` : model;
8563
8647
  }
8564
8648
  function getClaudeUniqueHash(line) {
8565
- const message = normalizeUnknownRecord(line.message);
8566
- const messageId = normalizeStringValue(message == null ? void 0 : message.id);
8567
- const requestId = normalizeStringValue(line.requestId);
8649
+ const messageId = normalizeStringValue(line.message.id);
8650
+ const requestId = line.requestId;
8568
8651
  return messageId ? `${messageId}:${requestId != null ? requestId : ""}` : null;
8569
8652
  }
8570
8653
  function extractClaudeMessageText(content) {
@@ -8579,35 +8662,65 @@ function extractClaudeMessageText(content) {
8579
8662
  return typeof item === "object" && item ? (_a = normalizeStringValue(item.text)) != null ? _a : "" : "";
8580
8663
  }).filter(Boolean).join("\n");
8581
8664
  }
8582
- function getInteractionRole(line, message) {
8583
- const role = normalizeStringValue(line.type) || normalizeStringValue(message == null ? void 0 : message.role) || normalizeStringValue(message == null ? void 0 : message.type) || "";
8665
+ function getInteractionRole(type, message) {
8666
+ const role = normalizeStringValue(message.role) || type || normalizeStringValue(message.type) || "";
8584
8667
  return normalizeRole(role);
8585
8668
  }
8586
- function isSupportedClaudeUsageLine(line) {
8587
- const message = normalizeUnknownRecord(line.message);
8669
+ function getClaudeUsageLine(line) {
8670
+ var _a, _b, _c, _d, _e, _f, _g;
8671
+ const progressData = normalizeUnknownRecord(line.data);
8672
+ const progressMessage = normalizeUnknownRecord(progressData == null ? void 0 : progressData.message);
8673
+ const message = (_a = normalizeUnknownRecord(progressMessage == null ? void 0 : progressMessage.message)) != null ? _a : normalizeUnknownRecord(line.message);
8588
8674
  const usage = normalizeUnknownRecord(message == null ? void 0 : message.usage);
8589
- if (hasUnsupportedClaudeNullField(line, message, usage)) {
8590
- return false;
8675
+ if (!message || !usage || hasUnsupportedClaudeNullField(line, progressMessage, message, usage)) {
8676
+ return null;
8591
8677
  }
8592
8678
  const version = normalizeStringValue(line.version);
8593
8679
  if (version && !/^\d+\.\d+\.\d+/u.test(version)) {
8594
- return false;
8680
+ return null;
8595
8681
  }
8596
- return !hasEmptyClaudeField(line, message);
8682
+ const sessionId = normalizeStringValue(line.sessionId);
8683
+ const requestId = (_b = normalizeStringValue(progressMessage == null ? void 0 : progressMessage.requestId)) != null ? _b : normalizeStringValue(line.requestId);
8684
+ if (hasEmptyClaudeField({
8685
+ message,
8686
+ requestId,
8687
+ sessionId,
8688
+ version
8689
+ })) {
8690
+ return null;
8691
+ }
8692
+ return {
8693
+ costUSD: (_c = normalizeFiniteNumberOrNull(progressMessage == null ? void 0 : progressMessage.costUSD)) != null ? _c : normalizeFiniteNumberOrNull(line.costUSD),
8694
+ cwd: normalizeStringValue(line.cwd),
8695
+ isSidechain: normalizeBooleanValue((_d = progressMessage == null ? void 0 : progressMessage.isSidechain) != null ? _d : line.isSidechain),
8696
+ message,
8697
+ requestId,
8698
+ sessionId,
8699
+ timestamp: (_f = toIsoString((_e = progressMessage == null ? void 0 : progressMessage.timestamp) != null ? _e : line.timestamp)) != null ? _f : null,
8700
+ type: (_g = normalizeStringValue(progressMessage == null ? void 0 : progressMessage.type)) != null ? _g : normalizeStringValue(line.type),
8701
+ usage
8702
+ };
8597
8703
  }
8598
- function hasUnsupportedClaudeNullField(line, message, usage) {
8599
- return line.cwd === null || line.costUSD === null || line.version === null || line.sessionId === null || line.requestId === null || line.isApiErrorMessage === null || (message == null ? void 0 : message.id) === null || (message == null ? void 0 : message.model) === null || (usage == null ? void 0 : usage.speed) === null || (usage == null ? void 0 : usage.cache_read_input_tokens) === null || (usage == null ? void 0 : usage.cache_creation_input_tokens) === null;
8704
+ function hasUnsupportedClaudeNullField(line, progressMessage, message, usage) {
8705
+ var _a, _b;
8706
+ return line.cwd === null || ((_a = progressMessage == null ? void 0 : progressMessage.costUSD) != null ? _a : line.costUSD) === null || line.version === null || line.sessionId === null || ((_b = progressMessage == null ? void 0 : progressMessage.requestId) != null ? _b : line.requestId) === null || line.isApiErrorMessage === null || message.id === null || message.model === null || usage.speed === null || usage.cache_read_input_tokens === null || usage.cache_creation_input_tokens === null;
8600
8707
  }
8601
- function hasEmptyClaudeField(line, message) {
8708
+ function hasEmptyClaudeField(options) {
8602
8709
  const candidates = [
8603
- line.sessionId,
8604
- line.requestId,
8605
- line.version,
8606
- message == null ? void 0 : message.id,
8607
- message == null ? void 0 : message.model
8710
+ options.sessionId,
8711
+ options.requestId,
8712
+ options.version,
8713
+ options.message.id,
8714
+ options.message.model
8608
8715
  ];
8609
8716
  return candidates.some((value) => typeof value === "string" && value.trim() === "");
8610
8717
  }
8718
+ function normalizeBooleanValue(value) {
8719
+ if (value === true || value === false) {
8720
+ return value;
8721
+ }
8722
+ return void 0;
8723
+ }
8611
8724
 
8612
8725
  const CODEBUFF_DEFAULT_MODEL = "codebuff-unknown";
8613
8726
  const codebuffUsageAdapter = {
@@ -8958,7 +9071,7 @@ const codexUsageAdapter = {
8958
9071
  addFragmentInteraction(fragment, {
8959
9072
  content: extractCodexContent(line),
8960
9073
  costUSD: (_h = usage == null ? void 0 : usage.costUSD) != null ? _h : 0,
8961
- dedupeKey: usage && timestamp ? getCodexDedupeKey(timestamp, model != null ? model : CODEX_FALLBACK_MODEL, usage) : null,
9074
+ dedupeKey: usage && timestamp ? getCodexDedupeKey(sessionId, timestamp, model != null ? model : CODEX_FALLBACK_MODEL, usage) : null,
8962
9075
  index,
8963
9076
  model: model != null ? model : null,
8964
9077
  role: getCodexRole(line, rawUsage !== null),
@@ -8982,7 +9095,8 @@ function getCodexRawUsage(line, previousTotals) {
8982
9095
  const info = normalizeUnknownRecord(payload == null ? void 0 : payload.info);
8983
9096
  const lastUsage = normalizeRawUsage(info == null ? void 0 : info.last_token_usage);
8984
9097
  const totalUsage = normalizeRawUsage(info == null ? void 0 : info.total_token_usage);
8985
- return lastUsage != null ? lastUsage : totalUsage ? subtractRawUsage(totalUsage, previousTotals) : null;
9098
+ const sessionUsage = lastUsage != null ? lastUsage : totalUsage ? subtractRawUsage(totalUsage, previousTotals) : null;
9099
+ return sessionUsage && sessionUsage.input_tokens === 0 && sessionUsage.cached_input_tokens === 0 && sessionUsage.output_tokens === 0 && sessionUsage.reasoning_output_tokens === 0 ? null : sessionUsage;
8986
9100
  }
8987
9101
  return getHeadlessCodexRawUsage(line);
8988
9102
  }
@@ -9170,10 +9284,11 @@ function getCodexTimestamp(line) {
9170
9284
  const payload = normalizeUnknownRecord(line.payload);
9171
9285
  return toIsoString(line.timestamp) || toIsoString(line.created_at) || toIsoString(line.createdAt) || toIsoString(payload == null ? void 0 : payload.timestamp) || toIsoString(data == null ? void 0 : data.timestamp) || toIsoString(data == null ? void 0 : data.created_at) || toIsoString(data == null ? void 0 : data.createdAt) || toIsoString(result == null ? void 0 : result.timestamp) || toIsoString(result == null ? void 0 : result.created_at) || toIsoString(result == null ? void 0 : result.createdAt) || toIsoString(response == null ? void 0 : response.timestamp) || toIsoString(response == null ? void 0 : response.created_at) || toIsoString(response == null ? void 0 : response.createdAt);
9172
9286
  }
9173
- function getCodexDedupeKey(timestamp, model, usage) {
9287
+ function getCodexDedupeKey(sessionId, timestamp, model, usage) {
9174
9288
  const rawInputTokens = usage.inputTokens + usage.cachedInputTokens;
9175
9289
  return [
9176
9290
  "codex",
9291
+ sessionId,
9177
9292
  timestamp,
9178
9293
  model,
9179
9294
  String(rawInputTokens),
@@ -9654,7 +9769,7 @@ const geminiUsageAdapter = {
9654
9769
  const files = Array.from(new Set(fileGroups.flat())).sort((a, b) => a.localeCompare(b));
9655
9770
  return files.flatMap((filePath) => toDiscoveredUsageFile(filePath, "gemini"));
9656
9771
  },
9657
- parseFile(filePath, resolvePricing) {
9772
+ parseFile(filePath) {
9658
9773
  var _a, _b, _c, _d, _e, _f, _g, _h;
9659
9774
  const data = parseJsonFile(filePath);
9660
9775
  if (!isGeminiSessionFile(data)) {
@@ -9678,7 +9793,7 @@ const geminiUsageAdapter = {
9678
9793
  const message = data.messages[index];
9679
9794
  const timestamp = toIsoString(message.timestamp);
9680
9795
  const model = ((_f = message.model) == null ? void 0 : _f.trim()) || (message.tokens ? GEMINI_FALLBACK_MODEL : null);
9681
- const usage = message.tokens && model ? getGeminiInteractionUsage(message.tokens, model, resolvePricing) : null;
9796
+ const usage = message.tokens && model ? getGeminiInteractionUsage(message.tokens) : null;
9682
9797
  addFragmentInteraction(fragment, {
9683
9798
  content: extractGeminiMessageText(message.content),
9684
9799
  costUSD: (_g = usage == null ? void 0 : usage.costUSD) != null ? _g : 0,
@@ -9699,7 +9814,7 @@ const geminiUsageAdapter = {
9699
9814
  ];
9700
9815
  }
9701
9816
  };
9702
- function getGeminiInteractionUsage(tokens, model, resolvePricing) {
9817
+ function getGeminiInteractionUsage(tokens) {
9703
9818
  const baseUsage = convertGeminiTokenUsage(tokens);
9704
9819
  const extraTotalTokens = normalizeNumber(tokens.thoughts);
9705
9820
  const usage = {
@@ -9710,14 +9825,9 @@ function getGeminiInteractionUsage(tokens, model, resolvePricing) {
9710
9825
  if (isZeroUsage(usage)) {
9711
9826
  return null;
9712
9827
  }
9713
- const costUSD = calculateUsageCostUSD({
9714
- cachedInputTokens: usage.cachedInputTokens,
9715
- inputTokens: usage.inputTokens,
9716
- outputTokens: usage.outputTokens
9717
- }, resolvePricing(model));
9718
9828
  return {
9719
9829
  ...usage,
9720
- costUSD,
9830
+ costUSD: 0,
9721
9831
  extraTotalTokens
9722
9832
  };
9723
9833
  }
@@ -10869,36 +10979,58 @@ function buildPlatformSessionsFromFiles(indexedFiles, platform) {
10869
10979
  return Array.from(details.values()).map(finalizeSessionDetail).filter(hasBillableSessionDetail).map(toProjectSessionUsageItem).sort((a, b) => Date.parse(b.startedAt) - Date.parse(a.startedAt));
10870
10980
  }
10871
10981
  function selectDedupedInteractions(indexedFiles, platform) {
10982
+ var _a;
10872
10983
  const interactionsWithoutDedupeKey = [];
10873
10984
  const interactionsByDedupeKey = /* @__PURE__ */ new Map();
10985
+ const interactionsByFallbackDedupeKey = /* @__PURE__ */ new Map();
10874
10986
  for (const file of indexedFiles) {
10875
10987
  if (file.platform !== platform) {
10876
10988
  continue;
10877
10989
  }
10878
10990
  for (const fragment of file.payload) {
10879
10991
  for (const interaction of fragment.interactions) {
10880
- if (!interaction.dedupeKey) {
10992
+ if (!interaction.dedupeKey && !interaction.fallbackDedupeKey) {
10881
10993
  interactionsWithoutDedupeKey.push({ fragment, interaction });
10882
10994
  continue;
10883
10995
  }
10884
- const existing = interactionsByDedupeKey.get(interaction.dedupeKey);
10996
+ const existing = (_a = interaction.dedupeKey ? interactionsByDedupeKey.get(interaction.dedupeKey) : void 0) != null ? _a : interaction.fallbackDedupeKey ? interactionsByFallbackDedupeKey.get(interaction.fallbackDedupeKey) : void 0;
10885
10997
  if (!existing) {
10886
- interactionsByDedupeKey.set(interaction.dedupeKey, { fragment, interaction });
10998
+ if (interaction.dedupeKey) {
10999
+ interactionsByDedupeKey.set(interaction.dedupeKey, { fragment, interaction });
11000
+ }
11001
+ if (interaction.fallbackDedupeKey) {
11002
+ interactionsByFallbackDedupeKey.set(interaction.fallbackDedupeKey, { fragment, interaction });
11003
+ }
10887
11004
  } else if (shouldReplaceDedupedInteraction(interaction, existing.interaction)) {
10888
- interactionsByDedupeKey.set(interaction.dedupeKey, { fragment: existing.fragment, interaction });
11005
+ const next = { fragment: existing.fragment, interaction };
11006
+ if (existing.interaction.dedupeKey) {
11007
+ interactionsByDedupeKey.set(existing.interaction.dedupeKey, next);
11008
+ }
11009
+ if (existing.interaction.fallbackDedupeKey) {
11010
+ interactionsByFallbackDedupeKey.set(existing.interaction.fallbackDedupeKey, next);
11011
+ }
11012
+ if (interaction.dedupeKey) {
11013
+ interactionsByDedupeKey.set(interaction.dedupeKey, next);
11014
+ }
11015
+ if (interaction.fallbackDedupeKey) {
11016
+ interactionsByFallbackDedupeKey.set(interaction.fallbackDedupeKey, next);
11017
+ }
10889
11018
  }
10890
11019
  }
10891
11020
  }
10892
11021
  }
10893
11022
  return [
10894
11023
  ...interactionsWithoutDedupeKey,
10895
- ...interactionsByDedupeKey.values()
11024
+ ...new Set(interactionsByDedupeKey.values())
10896
11025
  ];
10897
11026
  }
10898
11027
  function shouldReplaceDedupedInteraction(candidate, existing) {
10899
- var _a, _b, _c, _d;
10900
- const candidateTotal = (_b = (_a = candidate.usage) == null ? void 0 : _a.totalTokens) != null ? _b : 0;
10901
- const existingTotal = (_d = (_c = existing.usage) == null ? void 0 : _c.totalTokens) != null ? _d : 0;
11028
+ var _a, _b, _c, _d, _e, _f;
11029
+ if (((_a = candidate.isSidechain) != null ? _a : false) !== ((_b = existing.isSidechain) != null ? _b : false)) {
11030
+ return existing.isSidechain === true;
11031
+ }
11032
+ const candidateTotal = (_d = (_c = candidate.usage) == null ? void 0 : _c.totalTokens) != null ? _d : 0;
11033
+ const existingTotal = (_f = (_e = existing.usage) == null ? void 0 : _e.totalTokens) != null ? _f : 0;
10902
11034
  if (candidateTotal !== existingTotal) {
10903
11035
  return candidateTotal > existingTotal;
10904
11036
  }
@@ -10956,7 +11088,7 @@ function addInteraction(detail, interaction) {
10956
11088
  detail.outputTokens += interaction.usage.outputTokens;
10957
11089
  detail.reasoningOutputTokens += interaction.usage.reasoningOutputTokens;
10958
11090
  detail.tokenTotal += interaction.usage.totalTokens;
10959
- detail.costUSD += interaction.usage.costUSD;
11091
+ detail.costUSD = sumCurrency(detail.costUSD, interaction.usage.costUSD);
10960
11092
  if (interaction.model) {
10961
11093
  detail.models = Array.from(/* @__PURE__ */ new Set([...detail.models, interaction.model]));
10962
11094
  detail.modelTotals.set(
@@ -10993,11 +11125,11 @@ function toProjectSessionUsageItem(detail) {
10993
11125
  cachedInputTokens: detail.cachedInputTokens,
10994
11126
  costUSD: detail.costUSD,
10995
11127
  date: dateKey ? formatDateLabelFromDateKey(dateKey) : "",
10996
- duration: formatDuration(detail.durationMinutes),
11128
+ duration: formatDuration$1(detail.durationMinutes),
10997
11129
  durationMinutes: detail.durationMinutes,
10998
11130
  id: detail.key,
10999
11131
  inputTokens: detail.inputTokens,
11000
- interactions: detail.interactions.map(({ dedupeKey: _dedupeKey, ...interaction }) => ({
11132
+ interactions: detail.interactions.map(({ dedupeKey: _dedupeKey, fallbackDedupeKey: _fallbackDedupeKey, isSidechain: _isSidechain, ...interaction }) => ({
11001
11133
  ...interaction,
11002
11134
  raw: null
11003
11135
  })),
@@ -11025,6 +11157,39 @@ const PROJECT_USAGE_DATA_MODULES = [
11025
11157
  "token_usage"
11026
11158
  ];
11027
11159
 
11160
+ const DEFAULT_PAGE_SIZE = 10;
11161
+ const MAX_PAGE_SIZE = 10;
11162
+
11163
+ function normalizePagination(input = {}) {
11164
+ return {
11165
+ page: normalizePositiveInteger(input.page, 1),
11166
+ pageSize: Math.min(normalizePositiveInteger(input.pageSize, DEFAULT_PAGE_SIZE), MAX_PAGE_SIZE)
11167
+ };
11168
+ }
11169
+ function paginateItems(items, input = {}) {
11170
+ const { page, pageSize } = normalizePagination(input);
11171
+ const total = items.length;
11172
+ const pageCount = Math.max(1, Math.ceil(total / pageSize));
11173
+ const safePage = Math.min(page, pageCount);
11174
+ const start = (safePage - 1) * pageSize;
11175
+ return {
11176
+ items: items.slice(start, start + pageSize),
11177
+ pagination: {
11178
+ page: safePage,
11179
+ pageCount,
11180
+ pageSize,
11181
+ total
11182
+ }
11183
+ };
11184
+ }
11185
+ function normalizePositiveInteger(value, fallback) {
11186
+ if (!Number.isFinite(value)) {
11187
+ return fallback;
11188
+ }
11189
+ const normalized = Math.trunc(value);
11190
+ return normalized > 0 ? normalized : fallback;
11191
+ }
11192
+
11028
11193
  const DEFAULT_PROJECT_USAGE_DATA_MODULE = "session_list";
11029
11194
  function buildProjectUsageDataModuleFromDetail(detail, options) {
11030
11195
  var _a, _b, _c;
@@ -11038,7 +11203,7 @@ function buildProjectUsageDataModuleFromDetail(detail, options) {
11038
11203
  }
11039
11204
  if (modules.length === 1) {
11040
11205
  const module = modules[0];
11041
- const data = buildProjectPlatformModule(normalizedDetail, module, (_c = options.platform) != null ? _c : "all");
11206
+ const data = buildProjectPlatformModule(normalizedDetail, module, (_c = options.platform) != null ? _c : "all", options);
11042
11207
  return {
11043
11208
  data,
11044
11209
  label: normalizedDetail.label,
@@ -11051,7 +11216,7 @@ function buildProjectUsageDataModuleFromDetail(detail, options) {
11051
11216
  var _a2;
11052
11217
  return [
11053
11218
  module,
11054
- buildProjectPlatformModule(normalizedDetail, module, (_a2 = options.platform) != null ? _a2 : "all")
11219
+ buildProjectPlatformModule(normalizedDetail, module, (_a2 = options.platform) != null ? _a2 : "all", options)
11055
11220
  ];
11056
11221
  }))
11057
11222
  };
@@ -11084,34 +11249,34 @@ function buildProjectUsageCatalogItemsFromDetails(details) {
11084
11249
  };
11085
11250
  }).sort((a, b) => a.label.localeCompare(b.label));
11086
11251
  }
11087
- function buildProjectPlatformModule(detail, module, platform) {
11252
+ function buildProjectPlatformModule(detail, module, platform, pagination) {
11088
11253
  var _a;
11089
11254
  if (platform !== "all") {
11090
- return buildPlatformModulePayload((_a = detail.analyzing[platform]) != null ? _a : createEmptyProjectPlatformUsage(), module);
11255
+ return buildPlatformModulePayload((_a = detail.analyzing[platform]) != null ? _a : createEmptyProjectPlatformUsage(), module, pagination);
11091
11256
  }
11092
11257
  if (module === "session_list") {
11093
11258
  const sessions = getProjectDetailSessions(detail);
11094
11259
  const allUsage2 = buildProjectLoadUsageResult(sessions);
11095
- const platformPayloads2 = buildProjectPlatformPayloadMap(detail, module);
11260
+ const platformPayloads2 = buildProjectPlatformPayloadMap(detail, module, pagination);
11096
11261
  return {
11097
- all: buildSessionListModulePayload(allUsage2.sessionRows, sessions),
11262
+ all: buildSessionListModulePayload(allUsage2.sessionRows, sessions, pagination),
11098
11263
  ...platformPayloads2
11099
11264
  };
11100
11265
  }
11101
11266
  const allUsage = buildProjectLoadUsageResult(getProjectDetailSessions(detail));
11102
- const platformPayloads = buildProjectPlatformPayloadMap(detail, module);
11267
+ const platformPayloads = buildProjectPlatformPayloadMap(detail, module, pagination);
11103
11268
  return {
11104
- all: buildLoadUsageModulePayload(allUsage, module),
11269
+ all: buildLoadUsageModulePayload(allUsage, module, pagination),
11105
11270
  ...platformPayloads
11106
11271
  };
11107
11272
  }
11108
- function buildPlatformModulePayload(usage, module) {
11273
+ function buildPlatformModulePayload(usage, module, pagination) {
11109
11274
  if (module === "session_list") {
11110
- return buildSessionListModulePayload(usage.sessionRows, usage.sessions);
11275
+ return buildSessionListModulePayload(usage.sessionRows, usage.sessions, pagination);
11111
11276
  }
11112
- return buildLoadUsageModulePayload(usage, module);
11277
+ return buildLoadUsageModulePayload(usage, module, pagination);
11113
11278
  }
11114
- function buildLoadUsageModulePayload(usage, module) {
11279
+ function buildLoadUsageModulePayload(usage, module, pagination) {
11115
11280
  const modulePayloadBuilders = {
11116
11281
  daily_trend: () => ({
11117
11282
  dailyRows: usage.dailyRows,
@@ -11122,10 +11287,10 @@ function buildLoadUsageModulePayload(usage, module) {
11122
11287
  monthlyModelUsage: usage.monthlyModelUsage
11123
11288
  }),
11124
11289
  token_usage: () => ({
11125
- dailyRows: usage.dailyRows,
11126
- monthlyRows: usage.monthlyRows,
11127
- sessionRows: usage.sessionRows,
11128
- weeklyRows: usage.weeklyRows
11290
+ dailyRows: paginateItems(usage.dailyRows, pagination),
11291
+ monthlyRows: paginateItems(usage.monthlyRows, pagination),
11292
+ sessionRows: paginateItems(usage.sessionRows, pagination),
11293
+ weeklyRows: paginateItems(usage.weeklyRows, pagination)
11129
11294
  })
11130
11295
  };
11131
11296
  return modulePayloadBuilders[module]();
@@ -11159,21 +11324,21 @@ function getProjectDetailPlatforms(detail) {
11159
11324
  function getProjectDetailTotalTokens(detail) {
11160
11325
  return getProjectDetailSessions(detail).reduce((sum, session) => sum + session.tokenTotal, 0);
11161
11326
  }
11162
- function buildSessionListModulePayload(sessionRows, sessions) {
11327
+ function buildSessionListModulePayload(sessionRows, sessions, pagination) {
11163
11328
  const sessionList = sessions.map(({ interactions: _interactions, ...session }) => session);
11164
11329
  return {
11165
- sessionRows,
11166
- sessionUsage: sessionList,
11330
+ sessionRows: paginateItems(sessionRows, pagination),
11331
+ sessionUsage: paginateItems(sessionList, pagination),
11167
11332
  sessions: sessionList
11168
11333
  };
11169
11334
  }
11170
- function buildProjectPlatformPayloadMap(detail, module) {
11335
+ function buildProjectPlatformPayloadMap(detail, module, pagination) {
11171
11336
  return Object.fromEntries(
11172
11337
  PROJECT_USAGE_PLATFORMS.map((platform) => {
11173
11338
  var _a;
11174
11339
  return [
11175
11340
  platform,
11176
- buildPlatformModulePayload((_a = detail.analyzing[platform]) != null ? _a : createEmptyProjectPlatformUsage(), module)
11341
+ buildPlatformModulePayload((_a = detail.analyzing[platform]) != null ? _a : createEmptyProjectPlatformUsage(), module, pagination)
11177
11342
  ];
11178
11343
  })
11179
11344
  );
@@ -11219,6 +11384,7 @@ function getEarliestStartedAt(sessions) {
11219
11384
  return (_a = sessions.map((session) => session.startedAt).filter((timestamp) => Number.isFinite(Date.parse(timestamp))).sort((a, b) => Date.parse(a) - Date.parse(b))[0]) != null ? _a : null;
11220
11385
  }
11221
11386
 
11387
+ const TOP_PROJECT_LIMIT = 10;
11222
11388
  function buildHomeDashboardModules(dashboardsByPlatform, todayInsights = void 0) {
11223
11389
  const sessionUsage = buildSessionUsage(dashboardsByPlatform);
11224
11390
  const dailyTokenUsage = mergeDailyTokenUsage(
@@ -11245,7 +11411,8 @@ function buildHomeDashboardModules(dashboardsByPlatform, todayInsights = void 0)
11245
11411
  PROJECT_USAGE_PLATFORMS.flatMap((platform) => dashboardsByPlatform[platform].monthlyModelUsage)
11246
11412
  );
11247
11413
  const projectUsage = buildProjectUsage(sessionUsage);
11248
- const totalCost = dailyTokenUsage.reduce((sum, item) => sum + item.costUSD, 0);
11414
+ const sessionAnalysisItems = buildHomeSessionAnalysisItems(sessionUsage);
11415
+ const totalCost = getSessionUsageCostTotal(sessionUsage);
11249
11416
  const totalTokens = dailyTokenUsage.reduce((sum, item) => sum + item.totalTokens, 0);
11250
11417
  const inputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.inputTokens, 0);
11251
11418
  const cachedInputTokens = dailyTokenUsage.reduce((sum, item) => sum + item.cachedInputTokens, 0);
@@ -11284,12 +11451,46 @@ function buildHomeDashboardModules(dashboardsByPlatform, todayInsights = void 0)
11284
11451
  totalTokens
11285
11452
  }),
11286
11453
  sessionAnalysis: {
11287
- items: sessionUsage,
11454
+ items: sessionAnalysisItems,
11288
11455
  totalSessions
11289
11456
  },
11290
11457
  todayHourlyUsage: homeTodayInsights.todayHourlyUsage
11291
11458
  };
11292
11459
  }
11460
+ function buildHomeSessionAnalysisItems(sessionUsage) {
11461
+ var _a;
11462
+ const durationMinutesByProject = /* @__PURE__ */ new Map();
11463
+ for (const session of sessionUsage) {
11464
+ durationMinutesByProject.set(
11465
+ session.project,
11466
+ ((_a = durationMinutesByProject.get(session.project)) != null ? _a : 0) + session.durationMinutes
11467
+ );
11468
+ }
11469
+ return buildProjectUsage(sessionUsage).slice(0, TOP_PROJECT_LIMIT).map((project) => {
11470
+ var _a2, _b;
11471
+ return {
11472
+ costUSD: project.costUSD,
11473
+ duration: formatDuration((_a2 = durationMinutesByProject.get(project.label)) != null ? _a2 : 0),
11474
+ durationMinutes: (_b = durationMinutesByProject.get(project.label)) != null ? _b : 0,
11475
+ id: project.repository,
11476
+ model: "-",
11477
+ project: project.label,
11478
+ repository: project.repository,
11479
+ tokenTotal: project.tokenTotal
11480
+ };
11481
+ });
11482
+ }
11483
+ function formatDuration(minutes) {
11484
+ const hours = Math.floor(minutes / 60);
11485
+ const remainingMinutes = minutes % 60;
11486
+ if (hours === 0) {
11487
+ return `${remainingMinutes}m`;
11488
+ }
11489
+ if (remainingMinutes === 0) {
11490
+ return `${hours}h`;
11491
+ }
11492
+ return `${hours}h ${remainingMinutes}m`;
11493
+ }
11293
11494
  function buildSessionUsage(dashboardsByPlatform) {
11294
11495
  return PROJECT_USAGE_PLATFORMS.flatMap((platform) => dashboardsByPlatform[platform].sessionUsage.map((session) => ({
11295
11496
  ...session,
@@ -11297,6 +11498,19 @@ function buildSessionUsage(dashboardsByPlatform) {
11297
11498
  sessionId: `${platform}:${session.sessionId}`
11298
11499
  }))).sort((a, b) => Date.parse(b.startedAt) - Date.parse(a.startedAt));
11299
11500
  }
11501
+ function getSessionUsageCostTotal(sessions) {
11502
+ return roundCurrency(
11503
+ sessions.reduce((sessionTotal, session) => {
11504
+ if (!session.interactions) {
11505
+ return sessionTotal + session.costUSD;
11506
+ }
11507
+ return sessionTotal + session.interactions.reduce((interactionTotal, interaction) => {
11508
+ var _a, _b;
11509
+ return interactionTotal + ((_b = (_a = interaction.usage) == null ? void 0 : _a.costUSD) != null ? _b : 0);
11510
+ }, 0);
11511
+ }, 0)
11512
+ );
11513
+ }
11300
11514
  function buildHomeOverviewCards(options) {
11301
11515
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
11302
11516
  const tokenTrend = buildGrowthTrend(
@@ -11495,7 +11709,6 @@ function buildEfficiencyMetrics(options) {
11495
11709
  var __defProp = Object.defineProperty;
11496
11710
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11497
11711
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
11498
- const RUNTIME_STALE_AFTER_MS = 1e3 * 60;
11499
11712
  const WATCHER_DEBOUNCE_MS = 350;
11500
11713
  class UsageDataRuntime {
11501
11714
  constructor(config) {
@@ -11503,6 +11716,7 @@ class UsageDataRuntime {
11503
11716
  __publicField(this, "repository");
11504
11717
  __publicField(this, "state", {
11505
11718
  bootstrap: null,
11719
+ hasIndexedCurrentProcess: false,
11506
11720
  hydratedAt: 0,
11507
11721
  projectCatalog: [],
11508
11722
  projectDetails: null,
@@ -11528,8 +11742,8 @@ class UsageDataRuntime {
11528
11742
  await this.initialize();
11529
11743
  if (!this.state.bootstrap) {
11530
11744
  await this.refreshNow();
11531
- } else {
11532
- this.scheduleRefreshIfStale();
11745
+ } else if (!this.state.hasIndexedCurrentProcess) {
11746
+ void this.refreshInBackground();
11533
11747
  }
11534
11748
  return this.state.bootstrap;
11535
11749
  }
@@ -11537,8 +11751,8 @@ class UsageDataRuntime {
11537
11751
  await this.initialize();
11538
11752
  if (this.state.projectCatalog.length === 0) {
11539
11753
  await this.refreshNow();
11540
- } else {
11541
- this.scheduleRefreshIfStale();
11754
+ } else if (!this.state.hasIndexedCurrentProcess) {
11755
+ void this.refreshInBackground();
11542
11756
  }
11543
11757
  return this.state.projectCatalog;
11544
11758
  }
@@ -11551,27 +11765,33 @@ class UsageDataRuntime {
11551
11765
  return buildHomeDashboardModules(await this.getBootstrap(), this.repository.loadHomeDashboardTodayInsights());
11552
11766
  }
11553
11767
  async getProjectDataModules(request) {
11768
+ var _a, _b, _c;
11554
11769
  await this.initialize();
11555
11770
  const projectLabel = (request.project || "").trim();
11556
11771
  if (!projectLabel) {
11557
11772
  throw new Error("Missing project name for project data request.");
11558
11773
  }
11559
- if (this.state.projectDetails === null) {
11560
- this.state.projectDetails = this.repository.loadProjectDetails();
11561
- }
11562
- const detail = this.state.projectDetails.get(projectLabel);
11563
- if (!detail) {
11564
- await this.refreshNow();
11565
- } else {
11566
- this.scheduleRefreshIfStale();
11774
+ const projectDetails = (_a = this.state.projectDetails) != null ? _a : /* @__PURE__ */ new Map();
11775
+ if (!projectDetails.has(projectLabel)) {
11776
+ const storedDetail = this.repository.loadProjectDetail(projectLabel);
11777
+ if (storedDetail) {
11778
+ projectDetails.set(projectLabel, storedDetail);
11779
+ this.state.projectDetails = projectDetails;
11780
+ } else {
11781
+ await this.refreshNow();
11782
+ }
11783
+ } else if (!this.state.hasIndexedCurrentProcess) {
11784
+ void this.refreshInBackground();
11567
11785
  }
11568
- const hydratedDetail = this.state.projectDetails.get(projectLabel);
11786
+ const hydratedDetail = (_c = (_b = this.state.projectDetails) == null ? void 0 : _b.get(projectLabel)) != null ? _c : null;
11569
11787
  if (!hydratedDetail) {
11570
11788
  return null;
11571
11789
  }
11572
11790
  return buildProjectUsageDataModuleFromDetail(hydratedDetail, {
11573
11791
  module: request.module,
11574
11792
  modules: request.modules,
11793
+ page: request.page,
11794
+ pageSize: request.pageSize,
11575
11795
  platform: request.platform
11576
11796
  });
11577
11797
  }
@@ -11603,15 +11823,6 @@ class UsageDataRuntime {
11603
11823
  console.error("[usage-runtime] background refresh failed", error);
11604
11824
  });
11605
11825
  }
11606
- scheduleRefreshIfStale() {
11607
- if (Date.now() - this.state.hydratedAt < RUNTIME_STALE_AFTER_MS) {
11608
- return;
11609
- }
11610
- if (this.refreshPromise || Date.now() - this.state.refreshStartedAt < 1e3) {
11611
- return;
11612
- }
11613
- void this.refreshInBackground();
11614
- }
11615
11826
  async refresh() {
11616
11827
  this.state.refreshStartedAt = Date.now();
11617
11828
  const indexed = await buildIncrementalUsageIndex(this.config, this.repository);
@@ -11632,6 +11843,7 @@ class UsageDataRuntime {
11632
11843
  this.repository.replaceProjectDetails(projectDetails);
11633
11844
  this.state.bootstrap = bootstrap;
11634
11845
  this.state.projectCatalog = projectCatalog;
11846
+ this.state.hasIndexedCurrentProcess = true;
11635
11847
  if (this.state.projectDetails) {
11636
11848
  this.state.projectDetails = projectDetails;
11637
11849
  }
@@ -11751,9 +11963,9 @@ const DEFAULT_CLAUDE_CODE_PATH = ".claude";
11751
11963
  const DEFAULT_CLAUDE_CONFIG_PATH = join(((_a = process.env.XDG_CONFIG_HOME) == null ? void 0 : _a.trim()) || join(USER_HOME_DIR, ".config"), "claude");
11752
11964
  const DEFAULT_DROID_SESSIONS_DIR = join(USER_HOME_DIR, ".factory", "sessions");
11753
11965
  const DEFAULT_GOOSE_DB_CANDIDATES = [
11754
- join(USER_HOME_DIR, ".local", "share", "goose", "sessions", "goose.db"),
11755
- join(USER_HOME_DIR, "Library", "Application Support", "goose", "sessions", "goose.db"),
11756
- join(USER_HOME_DIR, ".local", "share", "Block", "goose", "sessions", "goose.db")
11966
+ join(USER_HOME_DIR, ".local", "share", "goose", "sessions", "sessions.db"),
11967
+ join(USER_HOME_DIR, "Library", "Application Support", "goose", "sessions", "sessions.db"),
11968
+ join(USER_HOME_DIR, ".local", "share", "Block", "goose", "sessions", "sessions.db")
11757
11969
  ];
11758
11970
  const DEFAULT_KILO_DIR = join(USER_HOME_DIR, ".local", "share", "kilo");
11759
11971
  const DEFAULT_KIMI_DIR = join(USER_HOME_DIR, ".kimi");
@@ -11848,7 +12060,7 @@ function getGoosePaths() {
11848
12060
  var _a2;
11849
12061
  const root = (_a2 = process.env.GOOSE_PATH_ROOT) == null ? void 0 : _a2.trim();
11850
12062
  if (root) {
11851
- const dbPath = resolve$1(root, "data", "sessions", "goose.db");
12063
+ const dbPath = resolve$1(root, "data", "sessions", "sessions.db");
11852
12064
  return isFileSync(dbPath) ? [dbPath] : [];
11853
12065
  }
11854
12066
  return DEFAULT_GOOSE_DB_CANDIDATES.map((path) => resolve$1(path)).filter(isFileSync);
@@ -11935,163 +12147,163 @@ const assets = {
11935
12147
  "/logo.svg": {
11936
12148
  "type": "image/svg+xml",
11937
12149
  "etag": "\"1550-fwYFdULdJ83Qp0FjnnX31iQz9oI\"",
11938
- "mtime": "2026-05-26T08:31:48.218Z",
12150
+ "mtime": "2026-05-27T09:07:32.522Z",
11939
12151
  "size": 5456,
11940
12152
  "path": "../public/logo.svg"
11941
12153
  },
11942
12154
  "/robots.txt": {
11943
12155
  "type": "text/plain; charset=utf-8",
11944
12156
  "etag": "\"18-j8OIsL9qGDmNZ+lHhp2tyH4XtaE\"",
11945
- "mtime": "2026-05-26T08:31:48.218Z",
12157
+ "mtime": "2026-05-27T09:07:32.522Z",
11946
12158
  "size": 24,
11947
12159
  "path": "../public/robots.txt"
11948
12160
  },
11949
- "/_nuxt/37OOe3RF.js": {
11950
- "type": "text/javascript; charset=utf-8",
11951
- "etag": "\"433-9g1fS7jC4SfhMOz/zYtzEkjj3l4\"",
11952
- "mtime": "2026-05-26T08:31:48.215Z",
11953
- "size": 1075,
11954
- "path": "../public/_nuxt/37OOe3RF.js"
11955
- },
11956
12161
  "/favicon.ico": {
11957
12162
  "type": "image/vnd.microsoft.icon",
11958
12163
  "etag": "\"1083e-LfyFZ+1JmdianDqe/sQN2Ou0IzQ\"",
11959
- "mtime": "2026-05-26T08:31:48.218Z",
12164
+ "mtime": "2026-05-27T09:07:32.522Z",
11960
12165
  "size": 67646,
11961
12166
  "path": "../public/favicon.ico"
11962
12167
  },
11963
- "/_nuxt/65Ayv2XK.js": {
12168
+ "/_nuxt/BJWBp9U3.js": {
11964
12169
  "type": "text/javascript; charset=utf-8",
11965
- "etag": "\"bb0d-ldbgmGlpc1qx4bYEx4cXkSFSCg8\"",
11966
- "mtime": "2026-05-26T08:31:48.215Z",
11967
- "size": 47885,
11968
- "path": "../public/_nuxt/65Ayv2XK.js"
12170
+ "etag": "\"101-Tesq+JGkSKIQcq2HziGnebJViCo\"",
12171
+ "mtime": "2026-05-27T09:07:32.517Z",
12172
+ "size": 257,
12173
+ "path": "../public/_nuxt/BJWBp9U3.js"
11969
12174
  },
11970
- "/_nuxt/BOWwkrCY.js": {
12175
+ "/_nuxt/BILXBbDI.js": {
11971
12176
  "type": "text/javascript; charset=utf-8",
11972
- "etag": "\"540a-Q/6WhDpXkujbyVqTxKp+MDIjyN8\"",
11973
- "mtime": "2026-05-26T08:31:48.215Z",
11974
- "size": 21514,
11975
- "path": "../public/_nuxt/BOWwkrCY.js"
12177
+ "etag": "\"95f9-A307WCqdxkMpOB/cNby3x2RHyYI\"",
12178
+ "mtime": "2026-05-27T09:07:32.517Z",
12179
+ "size": 38393,
12180
+ "path": "../public/_nuxt/BILXBbDI.js"
11976
12181
  },
11977
- "/_nuxt/D7qEPtpx.js": {
12182
+ "/_nuxt/BOTUKIyR.js": {
11978
12183
  "type": "text/javascript; charset=utf-8",
11979
- "etag": "\"eb4-cYfHtGVwvBnjUla1c7r6p8WQ+fU\"",
11980
- "mtime": "2026-05-26T08:31:48.215Z",
11981
- "size": 3764,
11982
- "path": "../public/_nuxt/D7qEPtpx.js"
12184
+ "etag": "\"d7b-pIo6ACRB5DaxCZRtTo8O5AXlVps\"",
12185
+ "mtime": "2026-05-27T09:07:32.517Z",
12186
+ "size": 3451,
12187
+ "path": "../public/_nuxt/BOTUKIyR.js"
11983
12188
  },
11984
- "/_nuxt/D9-Yw1TR.js": {
12189
+ "/_nuxt/BVD8FQXV.js": {
11985
12190
  "type": "text/javascript; charset=utf-8",
11986
- "etag": "\"42dc-z2VCBVgr0YDv874MuLF5LmD+w6g\"",
11987
- "mtime": "2026-05-26T08:31:48.215Z",
11988
- "size": 17116,
11989
- "path": "../public/_nuxt/D9-Yw1TR.js"
12191
+ "etag": "\"14f9-+vYSj+n6BntsoR1zbfugGwHBnvk\"",
12192
+ "mtime": "2026-05-27T09:07:32.517Z",
12193
+ "size": 5369,
12194
+ "path": "../public/_nuxt/BVD8FQXV.js"
11990
12195
  },
11991
- "/_nuxt/DF2WsXH3.js": {
12196
+ "/_nuxt/BXbx6JCB.js": {
11992
12197
  "type": "text/javascript; charset=utf-8",
11993
- "etag": "\"101-2rfNy5z/IaUQM5ONN45oT3dPyOw\"",
11994
- "mtime": "2026-05-26T08:31:48.215Z",
11995
- "size": 257,
11996
- "path": "../public/_nuxt/DF2WsXH3.js"
12198
+ "etag": "\"3f1a-v9YyNclwf3OlQwg5JLfj58x1tX8\"",
12199
+ "mtime": "2026-05-27T09:07:32.517Z",
12200
+ "size": 16154,
12201
+ "path": "../public/_nuxt/BXbx6JCB.js"
11997
12202
  },
11998
- "/_nuxt/C0GhHHgI.js": {
12203
+ "/_nuxt/BfVC-jX7.js": {
11999
12204
  "type": "text/javascript; charset=utf-8",
12000
- "etag": "\"cf91-HNazofOinHCfSBf403LLacaEnfc\"",
12001
- "mtime": "2026-05-26T08:31:48.215Z",
12002
- "size": 53137,
12003
- "path": "../public/_nuxt/C0GhHHgI.js"
12205
+ "etag": "\"2f1c-GvjXf2XwhvLaVcsVeJJ2W+Agzrs\"",
12206
+ "mtime": "2026-05-27T09:07:32.517Z",
12207
+ "size": 12060,
12208
+ "path": "../public/_nuxt/BfVC-jX7.js"
12004
12209
  },
12005
- "/_nuxt/DXWxIyGU.js": {
12210
+ "/_nuxt/BhIINiyq.js": {
12006
12211
  "type": "text/javascript; charset=utf-8",
12007
- "etag": "\"d7b-TUo4s2vJwQ7SvlmJq8Lc5JpszPo\"",
12008
- "mtime": "2026-05-26T08:31:48.216Z",
12009
- "size": 3451,
12010
- "path": "../public/_nuxt/DXWxIyGU.js"
12212
+ "etag": "\"ba8b-RgGonB5HVwajWLPO1MR7So0GI8M\"",
12213
+ "mtime": "2026-05-27T09:07:32.517Z",
12214
+ "size": 47755,
12215
+ "path": "../public/_nuxt/BhIINiyq.js"
12011
12216
  },
12012
- "/_nuxt/De8DvPWL.js": {
12217
+ "/_nuxt/CJv0IWZB.js": {
12013
12218
  "type": "text/javascript; charset=utf-8",
12014
- "etag": "\"14f9-ru/D4lCOWqCP3lvQM3EWGPMYRaw\"",
12015
- "mtime": "2026-05-26T08:31:48.215Z",
12016
- "size": 5369,
12017
- "path": "../public/_nuxt/De8DvPWL.js"
12219
+ "etag": "\"eb4-YLQQCkYdS3obs1V1advLn4aleSo\"",
12220
+ "mtime": "2026-05-27T09:07:32.517Z",
12221
+ "size": 3764,
12222
+ "path": "../public/_nuxt/CJv0IWZB.js"
12018
12223
  },
12019
- "/_nuxt/DKaPq50Z.js": {
12224
+ "/_nuxt/CJECfsOP.js": {
12020
12225
  "type": "text/javascript; charset=utf-8",
12021
- "etag": "\"f34c-URgC7Dz0Xf+JUUuL4yo1mSHnYmQ\"",
12022
- "mtime": "2026-05-26T08:31:48.216Z",
12023
- "size": 62284,
12024
- "path": "../public/_nuxt/DKaPq50Z.js"
12226
+ "etag": "\"10895-xt53mmAEjkgXulYjG9jCZNvAYT4\"",
12227
+ "mtime": "2026-05-27T09:07:32.517Z",
12228
+ "size": 67733,
12229
+ "path": "../public/_nuxt/CJECfsOP.js"
12025
12230
  },
12026
- "/_nuxt/DxvuOJRP.js": {
12231
+ "/_nuxt/CXOkrwUP.js": {
12027
12232
  "type": "text/javascript; charset=utf-8",
12028
- "etag": "\"10890-8PgC64ZUxoVro0//XJbLva3lqK0\"",
12029
- "mtime": "2026-05-26T08:31:48.216Z",
12030
- "size": 67728,
12031
- "path": "../public/_nuxt/DxvuOJRP.js"
12233
+ "etag": "\"f34c-u8PO6JNUQEdj83dhxa3RQdGy7YY\"",
12234
+ "mtime": "2026-05-27T09:07:32.517Z",
12235
+ "size": 62284,
12236
+ "path": "../public/_nuxt/CXOkrwUP.js"
12032
12237
  },
12033
- "/_nuxt/DgMMKsPE.js": {
12238
+ "/_nuxt/DjeKkZG3.js": {
12034
12239
  "type": "text/javascript; charset=utf-8",
12035
- "etag": "\"35763-ZIXCcb7yuHkNvDqXH2EEhwlcyV4\"",
12036
- "mtime": "2026-05-26T08:31:48.216Z",
12037
- "size": 218979,
12038
- "path": "../public/_nuxt/DgMMKsPE.js"
12240
+ "etag": "\"52b3-dLXnB5T7WTtenuKQlgkAo3hYDJM\"",
12241
+ "mtime": "2026-05-27T09:07:32.517Z",
12242
+ "size": 21171,
12243
+ "path": "../public/_nuxt/DjeKkZG3.js"
12039
12244
  },
12040
- "/_nuxt/Jp5cgQZi.js": {
12245
+ "/_nuxt/DaoeXHW_.js": {
12041
12246
  "type": "text/javascript; charset=utf-8",
12042
- "etag": "\"3c6da-89AEgPN5OI/3SCYBdFqSxRLSihE\"",
12043
- "mtime": "2026-05-26T08:31:48.216Z",
12044
- "size": 247514,
12045
- "path": "../public/_nuxt/Jp5cgQZi.js"
12247
+ "etag": "\"cf91-Hh4o3VXnbAZmCUpIdzWAFBvAqOw\"",
12248
+ "mtime": "2026-05-27T09:07:32.517Z",
12249
+ "size": 53137,
12250
+ "path": "../public/_nuxt/DaoeXHW_.js"
12046
12251
  },
12047
12252
  "/_nuxt/error-404.CFBEg71j.css": {
12048
12253
  "type": "text/css; charset=utf-8",
12049
12254
  "etag": "\"97e-GvhaEAryQvrSXyDcP4RiHXzYb5o\"",
12050
- "mtime": "2026-05-26T08:31:48.216Z",
12255
+ "mtime": "2026-05-27T09:07:32.518Z",
12051
12256
  "size": 2430,
12052
12257
  "path": "../public/_nuxt/error-404.CFBEg71j.css"
12053
12258
  },
12054
12259
  "/_nuxt/error-500.BqCnH31G.css": {
12055
12260
  "type": "text/css; charset=utf-8",
12056
12261
  "etag": "\"773-Tpf6lA6A2FEDtjLyWUXKolBZ3hM\"",
12057
- "mtime": "2026-05-26T08:31:48.216Z",
12262
+ "mtime": "2026-05-27T09:07:32.518Z",
12058
12263
  "size": 1907,
12059
12264
  "path": "../public/_nuxt/error-500.BqCnH31G.css"
12060
12265
  },
12061
- "/_nuxt/qXgLTL_3.js": {
12062
- "type": "text/javascript; charset=utf-8",
12063
- "etag": "\"993e-F6dGXZ77Rf6Afn6RLLvwifZFe5Q\"",
12064
- "mtime": "2026-05-26T08:31:48.216Z",
12065
- "size": 39230,
12066
- "path": "../public/_nuxt/qXgLTL_3.js"
12067
- },
12068
- "/_nuxt/y6mAKUDU.js": {
12069
- "type": "text/javascript; charset=utf-8",
12070
- "etag": "\"2c57-7lVqV+qTY/Dqb4M0PdxYAItocQw\"",
12071
- "mtime": "2026-05-26T08:31:48.216Z",
12072
- "size": 11351,
12073
- "path": "../public/_nuxt/y6mAKUDU.js"
12266
+ "/_nuxt/entry.DnkKc-6G.css": {
12267
+ "type": "text/css; charset=utf-8",
12268
+ "etag": "\"1d8a6-KK9a3JMzAwbSGw5SnlSiODNKxHg\"",
12269
+ "mtime": "2026-05-27T09:07:32.519Z",
12270
+ "size": 120998,
12271
+ "path": "../public/_nuxt/entry.DnkKc-6G.css"
12074
12272
  },
12075
12273
  "/_nuxt/builds/latest.json": {
12076
12274
  "type": "application/json",
12077
- "etag": "\"47-yneWhd0H1nYqEdMbDKqzhQJ6sxE\"",
12078
- "mtime": "2026-05-26T08:31:48.213Z",
12275
+ "etag": "\"47-kU/OMmwcdIBz/AUhQg0OeDC5kr4\"",
12276
+ "mtime": "2026-05-27T09:07:32.514Z",
12079
12277
  "size": 71,
12080
12278
  "path": "../public/_nuxt/builds/latest.json"
12081
12279
  },
12082
- "/_nuxt/builds/meta/7ce9c611-6071-4cbd-8926-1e53d9ef21bd.json": {
12280
+ "/_nuxt/tDg_nW46.js": {
12281
+ "type": "text/javascript; charset=utf-8",
12282
+ "etag": "\"433-NxH8uIPUk8I7j2aOP254GwjaJE4\"",
12283
+ "mtime": "2026-05-27T09:07:32.519Z",
12284
+ "size": 1075,
12285
+ "path": "../public/_nuxt/tDg_nW46.js"
12286
+ },
12287
+ "/_nuxt/builds/meta/80f1a776-82e2-4b5c-9c07-a61063a0dd84.json": {
12083
12288
  "type": "application/json",
12084
- "etag": "\"58-ozcqeghbP4BbYZVRtP6bwTCHhN8\"",
12085
- "mtime": "2026-05-26T08:31:48.211Z",
12289
+ "etag": "\"58-VYPe+Xe4MCP0G7G1GhAtJsOcgBg\"",
12290
+ "mtime": "2026-05-27T09:07:32.512Z",
12086
12291
  "size": 88,
12087
- "path": "../public/_nuxt/builds/meta/7ce9c611-6071-4cbd-8926-1e53d9ef21bd.json"
12292
+ "path": "../public/_nuxt/builds/meta/80f1a776-82e2-4b5c-9c07-a61063a0dd84.json"
12088
12293
  },
12089
- "/_nuxt/entry.DnkKc-6G.css": {
12090
- "type": "text/css; charset=utf-8",
12091
- "etag": "\"1d8a6-KK9a3JMzAwbSGw5SnlSiODNKxHg\"",
12092
- "mtime": "2026-05-26T08:31:48.216Z",
12093
- "size": 120998,
12094
- "path": "../public/_nuxt/entry.DnkKc-6G.css"
12294
+ "/_nuxt/DFbWcbwl.js": {
12295
+ "type": "text/javascript; charset=utf-8",
12296
+ "etag": "\"4237d-9L6bpd3yWeRFYelGQOUv+wIyrbk\"",
12297
+ "mtime": "2026-05-27T09:07:32.519Z",
12298
+ "size": 271229,
12299
+ "path": "../public/_nuxt/DFbWcbwl.js"
12300
+ },
12301
+ "/_nuxt/nv0LjcWu.js": {
12302
+ "type": "text/javascript; charset=utf-8",
12303
+ "etag": "\"3c6da-Zvl+qbXm2/IZ/Qc0CiSR/vyEqdw\"",
12304
+ "mtime": "2026-05-27T09:07:32.519Z",
12305
+ "size": 247514,
12306
+ "path": "../public/_nuxt/nv0LjcWu.js"
12095
12307
  }
12096
12308
  };
12097
12309
 
@@ -12782,7 +12994,7 @@ function getRequiredAnalysisAgentTokenType(event) {
12782
12994
  }
12783
12995
  function defineHomeAnalysisHandler(select) {
12784
12996
  return defineEventHandler(async (event) => {
12785
- return select(await getHomeAnalysisModules(event));
12997
+ return select(await getHomeAnalysisModules(event), event);
12786
12998
  });
12787
12999
  }
12788
13000
  function defineScopedAnalysisHandler(options) {
@@ -12814,6 +13026,22 @@ function normalizeQueryString(value) {
12814
13026
  return value === void 0 || value === null ? void 0 : String(value).trim();
12815
13027
  }
12816
13028
 
13029
+ function getPaginationQuery(event) {
13030
+ const query = getQuery(event);
13031
+ return normalizePagination({
13032
+ page: normalizeQueryNumber(query.page),
13033
+ pageSize: normalizeQueryNumber(query.pageSize)
13034
+ });
13035
+ }
13036
+ function normalizeQueryNumber(value) {
13037
+ const rawValue = Array.isArray(value) ? value[0] : value;
13038
+ if (rawValue === void 0 || rawValue === null || rawValue === "") {
13039
+ return void 0;
13040
+ }
13041
+ const numberValue = Number(rawValue);
13042
+ return Number.isFinite(numberValue) ? numberValue : void 0;
13043
+ }
13044
+
12817
13045
  const collections = {
12818
13046
  };
12819
13047
 
@@ -13053,4 +13281,4 @@ const websocket = nitroApp.h3App.websocket ;
13053
13281
  const handler = listener;
13054
13282
  trapUnhandledNodeErrors();
13055
13283
 
13056
- export { ANALYSIS_AGENT_TOKEN_ROW_KEYS as A, websocket as B, defineHomeAnalysisHandler as a, defineScopedAnalysisHandler as b, buildOverviewCardsWithTodayTokenBreakdown as c, defineRequiredAgentAnalysisHandler as d, defineEventHandler as e, getUsageDataRuntime as f, getRequiredAnalysisAgentTokenType as g, getRouterParam as h, getQuery as i, normalizeStringList as j, defineWebSocketHandler as k, buildAssetsURL as l, getResponseStatusText as m, normalizeStringValue as n, getResponseStatus as o, defineRenderHandler as p, publicAssetsURL as q, resolveConfig as r, createError$1 as s, destr as t, useRuntimeConfig as u, getRouteRules as v, joinURL as w, useNitroApp as x, handler as y, listener as z };
13284
+ export { ANALYSIS_AGENT_TOKEN_ROW_KEYS as A, handler as B, listener as C, websocket as D, getRequiredAnalysisAgentTokenType as a, defineHomeAnalysisHandler as b, defineScopedAnalysisHandler as c, defineRequiredAgentAnalysisHandler as d, buildOverviewCardsWithTodayTokenBreakdown as e, defineEventHandler as f, getPaginationQuery as g, getUsageDataRuntime as h, getRouterParam as i, getQuery as j, normalizeStringList as k, defineWebSocketHandler as l, buildAssetsURL as m, normalizeStringValue as n, getResponseStatusText as o, paginateItems as p, getResponseStatus as q, resolveConfig as r, defineRenderHandler as s, publicAssetsURL as t, useRuntimeConfig as u, createError$1 as v, destr as w, getRouteRules as x, joinURL as y, useNitroApp as z };