fleetlens 0.7.0 → 0.9.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.
Files changed (143) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/app-path-routes-manifest.json +1 -0
  3. package/app/apps/web/.next/build-manifest.json +5 -5
  4. package/app/apps/web/.next/prerender-manifest.json +3 -3
  5. package/app/apps/web/.next/routes-manifest.json +6 -0
  6. package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +2 -2
  7. package/app/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/app/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  12. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  14. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  15. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/app/apps/web/.next/server/app/_not-found/page/build-manifest.json +2 -2
  17. package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
  18. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  21. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
  22. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  23. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  24. package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
  26. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  27. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  29. package/app/apps/web/.next/server/app/changelog/page/app-paths-manifest.json +3 -0
  30. package/app/apps/web/.next/server/app/changelog/page/build-manifest.json +17 -0
  31. package/app/apps/web/.next/server/app/changelog/page/next-font-manifest.json +6 -0
  32. package/app/apps/web/.next/server/app/changelog/page/react-loadable-manifest.json +1 -0
  33. package/app/apps/web/.next/server/app/changelog/page/server-reference-manifest.json +4 -0
  34. package/app/apps/web/.next/server/app/changelog/page.js +17 -0
  35. package/app/apps/web/.next/server/app/changelog/page.js.map +5 -0
  36. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -0
  37. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +3 -0
  38. package/app/apps/web/.next/server/app/day/[date]/page/build-manifest.json +2 -2
  39. package/app/apps/web/.next/server/app/day/[date]/page.js +1 -1
  40. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  41. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  42. package/app/apps/web/.next/server/app/day/page/build-manifest.json +2 -2
  43. package/app/apps/web/.next/server/app/day/page.js +1 -1
  44. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  45. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  46. package/app/apps/web/.next/server/app/digest/[date]/page/build-manifest.json +2 -2
  47. package/app/apps/web/.next/server/app/digest/[date]/page.js +1 -1
  48. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  49. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  50. package/app/apps/web/.next/server/app/digest/page/build-manifest.json +2 -2
  51. package/app/apps/web/.next/server/app/digest/page.js +1 -1
  52. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  53. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  54. package/app/apps/web/.next/server/app/insights/[key]/page/build-manifest.json +2 -2
  55. package/app/apps/web/.next/server/app/insights/[key]/page.js +1 -1
  56. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  57. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  58. package/app/apps/web/.next/server/app/insights/page/build-manifest.json +2 -2
  59. package/app/apps/web/.next/server/app/insights/page.js +1 -1
  60. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  61. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  62. package/app/apps/web/.next/server/app/page/build-manifest.json +2 -2
  63. package/app/apps/web/.next/server/app/page.js +1 -1
  64. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  65. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  66. package/app/apps/web/.next/server/app/parallelism/page/build-manifest.json +2 -2
  67. package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
  68. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  69. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  70. package/app/apps/web/.next/server/app/projects/[slug]/page/build-manifest.json +2 -2
  71. package/app/apps/web/.next/server/app/projects/[slug]/page.js +1 -1
  72. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  73. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  74. package/app/apps/web/.next/server/app/projects/page/build-manifest.json +2 -2
  75. package/app/apps/web/.next/server/app/projects/page.js +1 -1
  76. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  77. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  78. package/app/apps/web/.next/server/app/runs/page/build-manifest.json +2 -2
  79. package/app/apps/web/.next/server/app/runs/page.js +1 -1
  80. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  81. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  82. package/app/apps/web/.next/server/app/sessions/[id]/page/build-manifest.json +2 -2
  83. package/app/apps/web/.next/server/app/sessions/[id]/page.js +1 -1
  84. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  85. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  86. package/app/apps/web/.next/server/app/sessions/page/build-manifest.json +2 -2
  87. package/app/apps/web/.next/server/app/sessions/page.js +1 -1
  88. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  89. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  90. package/app/apps/web/.next/server/app/settings/page/build-manifest.json +2 -2
  91. package/app/apps/web/.next/server/app/settings/page.js +1 -1
  92. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  93. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  94. package/app/apps/web/.next/server/app/usage/page/build-manifest.json +2 -2
  95. package/app/apps/web/.next/server/app/usage/page.js +1 -1
  96. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  97. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  98. package/app/apps/web/.next/server/app-paths-manifest.json +1 -0
  99. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.z48ue._.js +1 -1
  100. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0dctov1._.js +2 -2
  101. package/app/apps/web/.next/server/chunks/packages_09hmrqx._.js +1 -1
  102. package/app/apps/web/.next/server/chunks/packages_118y1lp._.js +1 -1
  103. package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_122oe0-.js +1 -1
  104. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0vvlth5._.js → [root-of-the-server]__02~v50d._.js} +2 -2
  105. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__09rjz7_._.js +3 -0
  106. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +1 -1
  107. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ytdqxt._.js +3 -0
  108. package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
  109. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_changelog_page_actions_12_04gy.js +3 -0
  110. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +1 -1
  111. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_changelog-mark-read_tsx_0hm41sv._.js +3 -0
  112. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0m67-xi._.js +3 -0
  113. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0uwo3v3.js +4 -0
  114. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_10_oegc._.js +1 -1
  115. package/app/apps/web/.next/server/middleware-build-manifest.js +5 -5
  116. package/app/apps/web/.next/server/pages/500.html +1 -1
  117. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  118. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  119. package/app/apps/web/.next/static/chunks/05b689hq3x49w.js +1 -0
  120. package/app/apps/web/.next/static/chunks/0cxyt4-24..b7.js +14 -0
  121. package/app/apps/web/.next/static/chunks/{0mykrrv810ra-.js → 0kjot8367asxe.js} +1 -1
  122. package/app/apps/web/.next/static/chunks/{turbopack-0_p36yduv.waj.js → turbopack-00w.w1u3c~d-6.js} +1 -1
  123. package/app/apps/web/app/changelog/page.tsx +238 -0
  124. package/app/apps/web/app/layout.tsx +2 -0
  125. package/app/apps/web/components/changelog-icon.tsx +62 -0
  126. package/app/apps/web/components/changelog-mark-read.tsx +12 -0
  127. package/app/apps/web/components/sidebar.tsx +7 -0
  128. package/app/apps/web/lib/calibration-data.ts +4 -64
  129. package/app/apps/web/lib/changelog-data.generated.ts +3 -0
  130. package/app/apps/web/lib/changelog.ts +67 -0
  131. package/app/apps/web/lib/cycle-peaks.test.ts +185 -0
  132. package/app/apps/web/lib/cycle-peaks.ts +104 -0
  133. package/app/apps/web/package.json +1 -1
  134. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  135. package/dist/daemon-worker.js +574 -38
  136. package/dist/index.js +601 -65
  137. package/package.json +1 -1
  138. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0v.6dx0._.js +0 -3
  139. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_usage-data_ts_0xtv99n._.js +0 -3
  140. package/app/apps/web/.next/static/chunks/09gdxttgu~.aj.js +0 -14
  141. /package/app/apps/web/.next/static/{qYW0u_NOmV0v7lf7xZc6x → u6-8f8u1tspYCacGAz53R}/_buildManifest.js +0 -0
  142. /package/app/apps/web/.next/static/{qYW0u_NOmV0v7lf7xZc6x → u6-8f8u1tspYCacGAz53R}/_clientMiddlewareManifest.js +0 -0
  143. /package/app/apps/web/.next/static/{qYW0u_NOmV0v7lf7xZc6x → u6-8f8u1tspYCacGAz53R}/_ssgManifest.js +0 -0
package/dist/index.js CHANGED
@@ -454,9 +454,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
454
454
  console.warn(
455
455
  ` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
456
456
  );
457
- } else if (verify.installedVersion !== "0.7.0") {
457
+ } else if (verify.installedVersion !== "0.9.0") {
458
458
  console.log(
459
- ` \u2192 This process is still running ${"0.7.0"}. Next invocation will use ${verify.installedVersion}.`
459
+ ` \u2192 This process is still running ${"0.9.0"}. Next invocation will use ${verify.installedVersion}.`
460
460
  );
461
461
  }
462
462
  }
@@ -492,7 +492,7 @@ async function checkForUpdate() {
492
492
  if (process.env.__FLEETLENS_UPDATED === "1" || process.env.__CCLENS_UPDATED === "1") return;
493
493
  const latest = await fetchLatestVersion();
494
494
  if (latest === null) return;
495
- const current = "0.7.0";
495
+ const current = "0.9.0";
496
496
  if (!shouldUpdate(current, latest)) return;
497
497
  console.log(`Updating ${PACKAGE_NAME} ${current} \u2192 ${latest}...`);
498
498
  await stopRunningServices();
@@ -574,7 +574,7 @@ async function restartServices(state) {
574
574
  }
575
575
  async function forceUpdate() {
576
576
  const latest = await fetchLatestVersion();
577
- const current = "0.7.0";
577
+ const current = "0.9.0";
578
578
  if (latest === null) {
579
579
  console.error("Could not reach npm registry. Check your network.");
580
580
  process.exit(1);
@@ -747,10 +747,10 @@ async function web(args2) {
747
747
  const noOpen = args2.includes("--no-open");
748
748
  const positional = args2.filter((a) => !a.startsWith("--"));
749
749
  const rawPath = positional[0] ?? "";
750
- const path4 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
750
+ const path5 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
751
751
  const status2 = getServerStatus();
752
752
  if (status2.running) {
753
- const url = `http://localhost:${status2.port}${path4}`;
753
+ const url = `http://localhost:${status2.port}${path5}`;
754
754
  console.log(noOpen ? `Server running at ${url}` : `Opening ${url}`);
755
755
  if (!noOpen) openBrowser(url);
756
756
  return;
@@ -758,7 +758,7 @@ async function web(args2) {
758
758
  console.log("fleetlens is not running. Starting server...");
759
759
  try {
760
760
  const result = await startServer({});
761
- const url = `http://localhost:${result.port}${path4}`;
761
+ const url = `http://localhost:${result.port}${path5}`;
762
762
  console.log(`fleetlens running on ${url} (PID ${result.pid})`);
763
763
  if (!noOpen) openBrowser(url);
764
764
  } catch (err) {
@@ -816,9 +816,9 @@ function readFromCredentialsFile() {
816
816
  join4(homedir3(), ".claude", ".credentials.json"),
817
817
  join4(homedir3(), ".config", "claude", "credentials.json")
818
818
  ];
819
- for (const path4 of candidates) {
819
+ for (const path5 of candidates) {
820
820
  try {
821
- const blob = readFileSync5(path4, "utf8");
821
+ const blob = readFileSync5(path5, "utf8");
822
822
  const creds = extractCredentials(blob);
823
823
  if (creds) return creds;
824
824
  } catch {
@@ -1556,7 +1556,7 @@ function getAgentMetadata(kind) {
1556
1556
  function isAgentKind(s) {
1557
1557
  return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
1558
1558
  }
1559
- var CLAUDE_CODE_METADATA, CODEX_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
1559
+ var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
1560
1560
  var init_agent_metadata = __esm({
1561
1561
  "../parser/dist/agent-metadata.js"() {
1562
1562
  "use strict";
@@ -1574,9 +1574,17 @@ var init_agent_metadata = __esm({
1574
1574
  accentColor: "rgb(16, 163, 127)",
1575
1575
  iconChar: "\u25C6"
1576
1576
  };
1577
+ GEMINI_METADATA = {
1578
+ kind: "gemini",
1579
+ displayName: "Gemini CLI",
1580
+ shortLabel: "Gemini",
1581
+ accentColor: "rgb(124, 92, 246)",
1582
+ iconChar: "\u273A"
1583
+ };
1577
1584
  agentMetadata = [
1578
1585
  CLAUDE_CODE_METADATA,
1579
- CODEX_METADATA
1586
+ CODEX_METADATA,
1587
+ GEMINI_METADATA
1580
1588
  ];
1581
1589
  KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
1582
1590
  }
@@ -3360,10 +3368,510 @@ var init_codex = __esm({
3360
3368
  }
3361
3369
  });
3362
3370
 
3371
+ // ../parser/dist/gemini.js
3372
+ import { promises as fs3 } from "node:fs";
3373
+ import os3 from "node:os";
3374
+ import path3 from "node:path";
3375
+ async function safeReaddir2(p) {
3376
+ return fs3.readdir(p).catch(() => []);
3377
+ }
3378
+ async function listSessionFiles(root) {
3379
+ const out = [];
3380
+ const slugs = await safeReaddir2(root);
3381
+ for (const slug of slugs) {
3382
+ const chatsDir = path3.join(root, slug, "chats");
3383
+ const entries2 = await safeReaddir2(chatsDir);
3384
+ for (const entry of entries2) {
3385
+ if (!SESSION_FILE_RE.test(entry))
3386
+ continue;
3387
+ const full = path3.join(chatsDir, entry);
3388
+ const stat = await fs3.stat(full).catch(() => null);
3389
+ if (!stat || !stat.isFile())
3390
+ continue;
3391
+ const filenameId = entry.replace(/\.(jsonl|json)$/, "").split("-").pop() ?? entry;
3392
+ out.push({
3393
+ filePath: full,
3394
+ slug,
3395
+ filenameId,
3396
+ format: entry.endsWith(".jsonl") ? "jsonl" : "legacy-json",
3397
+ mtimeMs: stat.mtimeMs,
3398
+ sizeBytes: stat.size
3399
+ });
3400
+ }
3401
+ }
3402
+ return out;
3403
+ }
3404
+ async function loadSlugToCwd() {
3405
+ const stat = await fs3.stat(GEMINI_PROJECTS_FILE).catch(() => null);
3406
+ if (!stat)
3407
+ return /* @__PURE__ */ new Map();
3408
+ if (projectsCache && projectsCache.mtimeMs === stat.mtimeMs) {
3409
+ return projectsCache.slugToCwd;
3410
+ }
3411
+ const raw = await fs3.readFile(GEMINI_PROJECTS_FILE, "utf8").catch(() => "");
3412
+ let parsed;
3413
+ try {
3414
+ parsed = JSON.parse(raw);
3415
+ } catch {
3416
+ parsed = {};
3417
+ }
3418
+ const slugToCwd = /* @__PURE__ */ new Map();
3419
+ for (const [cwd, slug] of Object.entries(parsed.projects ?? {})) {
3420
+ if (typeof slug === "string")
3421
+ slugToCwd.set(slug, cwd);
3422
+ }
3423
+ projectsCache = { mtimeMs: stat.mtimeMs, slugToCwd };
3424
+ return slugToCwd;
3425
+ }
3426
+ function isRewindMarker(o) {
3427
+ return !!o && typeof o === "object" && "$rewindTo" in o;
3428
+ }
3429
+ function isSetMarker(o) {
3430
+ return !!o && typeof o === "object" && "$set" in o;
3431
+ }
3432
+ function isMessageRecord(o) {
3433
+ return !!o && typeof o === "object" && typeof o.id === "string" && typeof o.type === "string";
3434
+ }
3435
+ async function readAndReplay(file) {
3436
+ const raw = await fs3.readFile(file.filePath, "utf8");
3437
+ if (file.format === "legacy-json") {
3438
+ let blob;
3439
+ try {
3440
+ blob = JSON.parse(raw);
3441
+ } catch {
3442
+ return { meta: {}, messages: [] };
3443
+ }
3444
+ const meta2 = {
3445
+ sessionId: typeof blob.sessionId === "string" ? blob.sessionId : void 0,
3446
+ projectHash: typeof blob.projectHash === "string" ? blob.projectHash : void 0,
3447
+ startTime: typeof blob.startTime === "string" ? blob.startTime : void 0,
3448
+ lastUpdated: typeof blob.lastUpdated === "string" ? blob.lastUpdated : void 0,
3449
+ summary: typeof blob.summary === "string" ? blob.summary : void 0
3450
+ };
3451
+ const msgs = Array.isArray(blob.messages) ? blob.messages : [];
3452
+ const messages2 = msgs.filter(isMessageRecord);
3453
+ return { meta: meta2, messages: messages2 };
3454
+ }
3455
+ const meta = {};
3456
+ const byId = /* @__PURE__ */ new Map();
3457
+ const order = [];
3458
+ for (const line of raw.split("\n")) {
3459
+ const trimmed = line.trim();
3460
+ if (!trimmed)
3461
+ continue;
3462
+ let obj;
3463
+ try {
3464
+ obj = JSON.parse(trimmed);
3465
+ } catch {
3466
+ continue;
3467
+ }
3468
+ if (isRewindMarker(obj)) {
3469
+ const target = obj.$rewindTo;
3470
+ const idx = order.indexOf(target);
3471
+ if (idx >= 0) {
3472
+ for (const id of order.slice(idx))
3473
+ byId.delete(id);
3474
+ order.length = idx;
3475
+ }
3476
+ continue;
3477
+ }
3478
+ if (isSetMarker(obj)) {
3479
+ Object.assign(meta, obj.$set);
3480
+ continue;
3481
+ }
3482
+ if (isMessageRecord(obj)) {
3483
+ if (!byId.has(obj.id))
3484
+ order.push(obj.id);
3485
+ byId.set(obj.id, obj);
3486
+ continue;
3487
+ }
3488
+ if (typeof obj === "object" && obj !== null) {
3489
+ const m = obj;
3490
+ if (typeof m.sessionId === "string" && !meta.sessionId) {
3491
+ meta.sessionId = m.sessionId;
3492
+ if (typeof m.projectHash === "string")
3493
+ meta.projectHash = m.projectHash;
3494
+ if (typeof m.startTime === "string")
3495
+ meta.startTime = m.startTime;
3496
+ if (typeof m.lastUpdated === "string")
3497
+ meta.lastUpdated = m.lastUpdated;
3498
+ if (typeof m.summary === "string")
3499
+ meta.summary = m.summary;
3500
+ }
3501
+ }
3502
+ }
3503
+ const messages = [];
3504
+ for (const id of order) {
3505
+ const m = byId.get(id);
3506
+ if (m)
3507
+ messages.push(m);
3508
+ }
3509
+ return { meta, messages };
3510
+ }
3511
+ function emptyUsage2() {
3512
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
3513
+ }
3514
+ function previewOf2(text) {
3515
+ return text.replace(/\s+/g, " ").trim().slice(0, 200);
3516
+ }
3517
+ function flattenContent(c) {
3518
+ if (!c)
3519
+ return "";
3520
+ if (typeof c === "string")
3521
+ return c;
3522
+ const parts = Array.isArray(c) ? c : [c];
3523
+ const out = [];
3524
+ for (const p of parts) {
3525
+ if (!p || typeof p !== "object")
3526
+ continue;
3527
+ const part = p;
3528
+ if (typeof part.text === "string") {
3529
+ out.push(part.text);
3530
+ continue;
3531
+ }
3532
+ const fr = part.functionResponse;
3533
+ if (fr) {
3534
+ const resp = fr.response;
3535
+ if (typeof resp === "string") {
3536
+ out.push(resp);
3537
+ } else if (resp && typeof resp === "object") {
3538
+ const r = resp;
3539
+ if (typeof r.output === "string")
3540
+ out.push(r.output);
3541
+ else if (typeof r.error === "string")
3542
+ out.push(`error: ${r.error}`);
3543
+ else
3544
+ out.push(JSON.stringify(r));
3545
+ }
3546
+ }
3547
+ }
3548
+ return out.join("\n");
3549
+ }
3550
+ function truncate3(s, n) {
3551
+ return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
3552
+ }
3553
+ async function parseSession(file) {
3554
+ const { meta: metaRec, messages } = await readAndReplay(file);
3555
+ const slugToCwd = await loadSlugToCwd();
3556
+ const cwd = slugToCwd.get(file.slug);
3557
+ const events = [];
3558
+ const totalUsage = emptyUsage2();
3559
+ let firstTimestamp;
3560
+ let lastTimestamp;
3561
+ let model;
3562
+ let toolCallCount = 0;
3563
+ let turnCount = 0;
3564
+ let firstUserPreview;
3565
+ let lastUserPreview;
3566
+ let lastAgentPreview;
3567
+ const tsMs = [];
3568
+ let idx = 0;
3569
+ function pushEvent(e) {
3570
+ events.push(e);
3571
+ if (e.timestamp && e.role !== "meta") {
3572
+ if (!firstTimestamp)
3573
+ firstTimestamp = e.timestamp;
3574
+ lastTimestamp = e.timestamp;
3575
+ const ms = Date.parse(e.timestamp);
3576
+ if (Number.isFinite(ms))
3577
+ tsMs.push(ms);
3578
+ }
3579
+ }
3580
+ for (const msg of messages) {
3581
+ const ts = msg.timestamp;
3582
+ if (msg.type === "user") {
3583
+ const text = flattenContent(msg.displayContent ?? msg.content);
3584
+ const preview = previewOf2(text);
3585
+ if (text) {
3586
+ if (!firstUserPreview)
3587
+ firstUserPreview = preview;
3588
+ lastUserPreview = preview;
3589
+ turnCount += 1;
3590
+ }
3591
+ pushEvent({
3592
+ index: idx++,
3593
+ timestamp: ts,
3594
+ role: "user",
3595
+ rawType: "gemini/user",
3596
+ preview,
3597
+ blocks: text ? [{ type: "text", text }] : [],
3598
+ messageId: msg.id,
3599
+ raw: msg
3600
+ });
3601
+ continue;
3602
+ }
3603
+ if (msg.type === "gemini") {
3604
+ if (typeof msg.model === "string")
3605
+ model = msg.model;
3606
+ const text = flattenContent(msg.content);
3607
+ const preview = previewOf2(text);
3608
+ if (text)
3609
+ lastAgentPreview = preview;
3610
+ let usage2;
3611
+ if (msg.tokens) {
3612
+ const t = msg.tokens;
3613
+ const u = {
3614
+ input: t.input ?? 0,
3615
+ output: t.output ?? 0,
3616
+ cacheRead: t.cached ?? 0,
3617
+ cacheWrite: 0
3618
+ };
3619
+ usage2 = u;
3620
+ totalUsage.input += u.input;
3621
+ totalUsage.output += u.output;
3622
+ totalUsage.cacheRead += u.cacheRead;
3623
+ }
3624
+ for (const th of msg.thoughts ?? []) {
3625
+ const thText = [th.subject, th.description].filter(Boolean).join(": ");
3626
+ if (!thText)
3627
+ continue;
3628
+ pushEvent({
3629
+ index: idx++,
3630
+ timestamp: th.timestamp ?? ts,
3631
+ role: "agent-thinking",
3632
+ rawType: "gemini/thought",
3633
+ preview: previewOf2(thText),
3634
+ blocks: [{ type: "thinking", thinking: thText }],
3635
+ model,
3636
+ raw: th
3637
+ });
3638
+ }
3639
+ if (text) {
3640
+ pushEvent({
3641
+ index: idx++,
3642
+ timestamp: ts,
3643
+ role: "agent",
3644
+ rawType: "gemini/agent",
3645
+ preview,
3646
+ blocks: [{ type: "text", text }],
3647
+ messageId: msg.id,
3648
+ model,
3649
+ usage: usage2,
3650
+ raw: msg
3651
+ });
3652
+ } else if (usage2) {
3653
+ pushEvent({
3654
+ index: idx++,
3655
+ timestamp: ts,
3656
+ role: "agent",
3657
+ rawType: "gemini/agent",
3658
+ preview: "",
3659
+ blocks: [],
3660
+ messageId: msg.id,
3661
+ model,
3662
+ usage: usage2,
3663
+ raw: msg
3664
+ });
3665
+ }
3666
+ for (const tc of msg.toolCalls ?? []) {
3667
+ toolCallCount += 1;
3668
+ const argsStr = tc.args ? JSON.stringify(tc.args) : "";
3669
+ pushEvent({
3670
+ index: idx++,
3671
+ timestamp: tc.timestamp ?? ts,
3672
+ role: "tool-call",
3673
+ rawType: "gemini/tool_call",
3674
+ preview: `${tc.name}(${truncate3(argsStr, 80)})`,
3675
+ blocks: [{ type: "tool_use", id: tc.id, name: tc.name, input: tc.args ?? {} }],
3676
+ toolName: tc.name,
3677
+ toolUseId: tc.id,
3678
+ model,
3679
+ raw: tc
3680
+ });
3681
+ const status2 = (tc.status ?? "").toLowerCase();
3682
+ const isTerminal = status2 === "success" || status2 === "error" || status2 === "cancelled";
3683
+ if (isTerminal) {
3684
+ const resultText = flattenContent(tc.result);
3685
+ pushEvent({
3686
+ index: idx++,
3687
+ timestamp: tc.timestamp ?? ts,
3688
+ role: "tool-result",
3689
+ rawType: "gemini/tool_result",
3690
+ preview: previewOf2(resultText),
3691
+ blocks: [
3692
+ {
3693
+ type: "tool_result",
3694
+ tool_use_id: tc.id,
3695
+ content: resultText,
3696
+ is_error: status2 === "error" || status2 === "cancelled"
3697
+ }
3698
+ ],
3699
+ toolUseId: tc.id,
3700
+ toolResult: resultText,
3701
+ raw: tc
3702
+ });
3703
+ }
3704
+ }
3705
+ continue;
3706
+ }
3707
+ if (msg.type === "info" || msg.type === "warning" || msg.type === "error") {
3708
+ const text = flattenContent(msg.content);
3709
+ pushEvent({
3710
+ index: idx++,
3711
+ timestamp: ts,
3712
+ role: "meta",
3713
+ rawType: `gemini/${msg.type}`,
3714
+ preview: previewOf2(text),
3715
+ blocks: text ? [{ type: "text", text }] : [],
3716
+ raw: msg
3717
+ });
3718
+ continue;
3719
+ }
3720
+ }
3721
+ const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
3722
+ if (startMs !== void 0 && Number.isFinite(startMs)) {
3723
+ let prevMs;
3724
+ for (const ev of events) {
3725
+ if (!ev.timestamp)
3726
+ continue;
3727
+ const ms = Date.parse(ev.timestamp);
3728
+ if (!Number.isFinite(ms))
3729
+ continue;
3730
+ ev.tOffsetMs = Math.max(0, ms - startMs);
3731
+ if (prevMs !== void 0)
3732
+ ev.gapMs = Math.max(0, ms - prevMs);
3733
+ prevMs = ms;
3734
+ }
3735
+ }
3736
+ const activeSegments = computeActiveSegments3(tsMs);
3737
+ const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
3738
+ const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
3739
+ const sessionId = metaRec.sessionId ?? file.filenameId;
3740
+ const projectName = cwd ? canonicalProjectName(cwd) : file.slug;
3741
+ const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
3742
+ const meta = {
3743
+ agent: "gemini",
3744
+ id: sessionId,
3745
+ filePath: file.filePath,
3746
+ projectName,
3747
+ projectDir,
3748
+ sessionId,
3749
+ firstTimestamp,
3750
+ lastTimestamp,
3751
+ durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
3752
+ eventCount: events.length,
3753
+ model,
3754
+ cwd,
3755
+ totalUsage,
3756
+ status: "idle",
3757
+ firstUserPreview,
3758
+ lastUserPreview,
3759
+ lastAgentPreview,
3760
+ toolCallCount,
3761
+ turnCount,
3762
+ airTimeMs,
3763
+ activeSegments
3764
+ };
3765
+ return { meta, events };
3766
+ }
3767
+ function computeActiveSegments3(tsMs) {
3768
+ if (tsMs.length === 0)
3769
+ return [];
3770
+ const sorted = [...tsMs].sort((a, b) => a - b);
3771
+ const out = [];
3772
+ let segStart = sorted[0];
3773
+ let segEnd = sorted[0];
3774
+ for (let i = 1; i < sorted.length; i++) {
3775
+ if (sorted[i] - segEnd > IDLE_GAP_MS2) {
3776
+ out.push({ startMs: segStart, endMs: segEnd });
3777
+ segStart = sorted[i];
3778
+ }
3779
+ segEnd = sorted[i];
3780
+ }
3781
+ out.push({ startMs: segStart, endMs: segEnd });
3782
+ return out;
3783
+ }
3784
+ function clearGeminiCaches() {
3785
+ metaCache3.clear();
3786
+ detailCache3.clear();
3787
+ projectsCache = null;
3788
+ }
3789
+ async function listGeminiSessions(opts = {}) {
3790
+ const root = opts.root ?? DEFAULT_GEMINI_ROOT;
3791
+ const files = await listSessionFiles(root);
3792
+ const out = [];
3793
+ for (const file of files) {
3794
+ const cached = metaCache3.get(file.filePath);
3795
+ if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
3796
+ out.push(cached.meta);
3797
+ continue;
3798
+ }
3799
+ try {
3800
+ const { meta } = await parseSession(file);
3801
+ metaCache3.set(file.filePath, {
3802
+ meta,
3803
+ mtimeMs: file.mtimeMs,
3804
+ sizeBytes: file.sizeBytes
3805
+ });
3806
+ out.push(meta);
3807
+ } catch {
3808
+ }
3809
+ }
3810
+ out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
3811
+ if (opts.limit !== void 0)
3812
+ return out.slice(0, opts.limit);
3813
+ return out;
3814
+ }
3815
+ async function getGeminiSession(id, opts = {}) {
3816
+ const root = opts.root ?? DEFAULT_GEMINI_ROOT;
3817
+ const files = await listSessionFiles(root);
3818
+ let chosen;
3819
+ for (const file of files) {
3820
+ if (file.filenameId === id || id.startsWith(file.filenameId)) {
3821
+ chosen = file;
3822
+ break;
3823
+ }
3824
+ }
3825
+ if (!chosen) {
3826
+ for (const file of files) {
3827
+ const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
3828
+ if (meta2.id === id) {
3829
+ chosen = file;
3830
+ break;
3831
+ }
3832
+ }
3833
+ }
3834
+ if (!chosen)
3835
+ return null;
3836
+ const cached = detailCache3.get(chosen.filePath);
3837
+ if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
3838
+ return cached.detail;
3839
+ }
3840
+ const { meta, events } = await parseSession(chosen);
3841
+ const detail = { ...meta, events };
3842
+ detailCache3.set(chosen.filePath, {
3843
+ detail,
3844
+ mtimeMs: chosen.mtimeMs,
3845
+ sizeBytes: chosen.sizeBytes
3846
+ });
3847
+ return detail;
3848
+ }
3849
+ function geminiSessionLocalDay(meta) {
3850
+ if (!meta.firstTimestamp)
3851
+ return void 0;
3852
+ const ms = Date.parse(meta.firstTimestamp);
3853
+ return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
3854
+ }
3855
+ var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
3856
+ var init_gemini = __esm({
3857
+ "../parser/dist/gemini.js"() {
3858
+ "use strict";
3859
+ init_analytics();
3860
+ DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
3861
+ GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
3862
+ SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
3863
+ IDLE_GAP_MS2 = 3 * 60 * 1e3;
3864
+ projectsCache = null;
3865
+ metaCache3 = /* @__PURE__ */ new Map();
3866
+ detailCache3 = /* @__PURE__ */ new Map();
3867
+ }
3868
+ });
3869
+
3363
3870
  // ../parser/dist/fs.js
3364
3871
  var fs_exports = {};
3365
3872
  __export(fs_exports, {
3366
3873
  DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
3874
+ DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
3367
3875
  DEFAULT_ROOT: () => DEFAULT_ROOT,
3368
3876
  agentSources: () => agentSources,
3369
3877
  buildCalibrationCurve: () => buildCalibrationCurve,
@@ -3372,14 +3880,17 @@ __export(fs_exports, {
3372
3880
  codexSessionLocalDay: () => codexSessionLocalDay,
3373
3881
  decodeProjectName: () => decodeProjectName,
3374
3882
  findTeamLead: () => findTeamLead,
3883
+ geminiSessionLocalDay: () => geminiSessionLocalDay,
3375
3884
  getAgentSource: () => getAgentSource,
3376
3885
  getAnySession: () => getAnySession,
3377
3886
  getCodexSession: () => getCodexSession,
3887
+ getGeminiSession: () => getGeminiSession,
3378
3888
  getLatestCodexUsage: () => getLatestCodexUsage,
3379
3889
  getSession: () => getSession,
3380
3890
  invalidateFile: () => invalidateFile,
3381
3891
  listAllSessions: () => listAllSessions,
3382
3892
  listCodexSessions: () => listCodexSessions,
3893
+ listGeminiSessions: () => listGeminiSessions,
3383
3894
  listProjects: () => listProjects,
3384
3895
  listSessions: () => listSessions,
3385
3896
  loadCalibrationCurve: () => loadCalibrationCurve,
@@ -3391,15 +3902,16 @@ __export(fs_exports, {
3391
3902
  sessionIdFromFileName: () => sessionIdFromFileName,
3392
3903
  walkJsonlFiles: () => walkJsonlFiles
3393
3904
  });
3394
- import { promises as fs3 } from "node:fs";
3395
- import os3 from "node:os";
3396
- import path3 from "node:path";
3905
+ import { promises as fs4 } from "node:fs";
3906
+ import os4 from "node:os";
3907
+ import path4 from "node:path";
3397
3908
  function cacheStats() {
3398
3909
  return claudeCodeCacheStats();
3399
3910
  }
3400
3911
  function clearCaches() {
3401
3912
  clearClaudeCodeCaches();
3402
3913
  clearCodexCaches();
3914
+ clearGeminiCaches();
3403
3915
  }
3404
3916
  function invalidateFile(fullPath) {
3405
3917
  invalidateClaudeCodeFile(fullPath);
@@ -3428,7 +3940,7 @@ async function getAnySession(id) {
3428
3940
  async function loadUsageByDay(start2, end) {
3429
3941
  let raw;
3430
3942
  try {
3431
- raw = await fs3.readFile(USAGE_LOG2, "utf8");
3943
+ raw = await fs4.readFile(USAGE_LOG2, "utf8");
3432
3944
  } catch {
3433
3945
  return { by_day: [] };
3434
3946
  }
@@ -3473,7 +3985,7 @@ async function loadUsageByDay(start2, end) {
3473
3985
  async function loadCalibrationSnapshots() {
3474
3986
  let raw;
3475
3987
  try {
3476
- raw = await fs3.readFile(USAGE_LOG2, "utf8");
3988
+ raw = await fs4.readFile(USAGE_LOG2, "utf8");
3477
3989
  } catch {
3478
3990
  return [];
3479
3991
  }
@@ -3631,7 +4143,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
3631
4143
  ]);
3632
4144
  return buildCalibrationCurve(events, snapshots, tier, granularityMin);
3633
4145
  }
3634
- var codexSource, agentSources, USAGE_LOG2;
4146
+ var codexSource, geminiSource, agentSources, USAGE_LOG2;
3635
4147
  var init_fs = __esm({
3636
4148
  "../parser/dist/fs.js"() {
3637
4149
  "use strict";
@@ -3640,8 +4152,10 @@ var init_fs = __esm({
3640
4152
  init_calibration();
3641
4153
  init_claude_code();
3642
4154
  init_codex();
4155
+ init_gemini();
3643
4156
  init_claude_code();
3644
4157
  init_codex();
4158
+ init_gemini();
3645
4159
  codexSource = {
3646
4160
  ...CODEX_METADATA,
3647
4161
  defaultRoot: DEFAULT_CODEX_ROOT,
@@ -3663,8 +4177,18 @@ var init_fs = __esm({
3663
4177
  };
3664
4178
  }
3665
4179
  };
3666
- agentSources = [claudeCodeSource, codexSource];
3667
- USAGE_LOG2 = path3.join(os3.homedir(), ".cclens", "usage.jsonl");
4180
+ geminiSource = {
4181
+ ...GEMINI_METADATA,
4182
+ defaultRoot: DEFAULT_GEMINI_ROOT,
4183
+ async listSessions(opts) {
4184
+ return listGeminiSessions(opts);
4185
+ },
4186
+ async getSession(id) {
4187
+ return getGeminiSession(id);
4188
+ }
4189
+ };
4190
+ agentSources = [claudeCodeSource, codexSource, geminiSource];
4191
+ USAGE_LOG2 = path4.join(os4.homedir(), ".cclens", "usage.jsonl");
3668
4192
  }
3669
4193
  });
3670
4194
 
@@ -4161,7 +4685,7 @@ var init_trivial = __esm({
4161
4685
  });
4162
4686
 
4163
4687
  // ../entries/dist/build.js
4164
- var IDLE_GAP_MS2;
4688
+ var IDLE_GAP_MS3;
4165
4689
  var init_build = __esm({
4166
4690
  "../entries/dist/build.js"() {
4167
4691
  "use strict";
@@ -4169,7 +4693,7 @@ var init_build = __esm({
4169
4693
  init_types();
4170
4694
  init_signals();
4171
4695
  init_trivial();
4172
- IDLE_GAP_MS2 = 3 * 60 * 1e3;
4696
+ IDLE_GAP_MS3 = 3 * 60 * 1e3;
4173
4697
  }
4174
4698
  });
4175
4699
 
@@ -4203,11 +4727,11 @@ function digestsDir() {
4203
4727
  digestsDirCached = envOverride ?? join6(homedir5(), ".cclens", "digests");
4204
4728
  return digestsDirCached;
4205
4729
  }
4206
- function __setDigestsDirForTest(path4) {
4207
- digestsDirCached = path4;
4208
- mkdirSync3(join6(path4, "day"), { recursive: true });
4209
- mkdirSync3(join6(path4, "week"), { recursive: true });
4210
- mkdirSync3(join6(path4, "month"), { recursive: true });
4730
+ function __setDigestsDirForTest(path5) {
4731
+ digestsDirCached = path5;
4732
+ mkdirSync3(join6(path5, "day"), { recursive: true });
4733
+ mkdirSync3(join6(path5, "week"), { recursive: true });
4734
+ mkdirSync3(join6(path5, "month"), { recursive: true });
4211
4735
  }
4212
4736
  function dayDigestPath(date) {
4213
4737
  return join6(digestsDir(), "day", `${date}.json`);
@@ -4394,9 +4918,9 @@ function entriesDir() {
4394
4918
  entriesDirCached = envOverride ?? join7(homedir6(), ".cclens", "entries");
4395
4919
  return entriesDirCached;
4396
4920
  }
4397
- function __setEntriesDirForTest(path4) {
4398
- entriesDirCached = path4;
4399
- mkdirSync4(path4, { recursive: true });
4921
+ function __setEntriesDirForTest(path5) {
4922
+ entriesDirCached = path5;
4923
+ mkdirSync4(path5, { recursive: true });
4400
4924
  }
4401
4925
  function pathFor(sessionId, localDay) {
4402
4926
  return join7(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
@@ -4931,8 +5455,8 @@ var init_parseUtil = __esm({
4931
5455
  init_errors();
4932
5456
  init_en();
4933
5457
  makeIssue = (params) => {
4934
- const { data, path: path4, errorMaps, issueData } = params;
4935
- const fullPath = [...path4, ...issueData.path || []];
5458
+ const { data, path: path5, errorMaps, issueData } = params;
5459
+ const fullPath = [...path5, ...issueData.path || []];
4936
5460
  const fullIssue = {
4937
5461
  ...issueData,
4938
5462
  path: fullPath
@@ -5240,11 +5764,11 @@ var init_types2 = __esm({
5240
5764
  init_parseUtil();
5241
5765
  init_util();
5242
5766
  ParseInputLazyPath = class {
5243
- constructor(parent, value, path4, key) {
5767
+ constructor(parent, value, path5, key) {
5244
5768
  this._cachedPath = [];
5245
5769
  this.parent = parent;
5246
5770
  this.data = value;
5247
- this._path = path4;
5771
+ this._path = path5;
5248
5772
  this._key = key;
5249
5773
  }
5250
5774
  get path() {
@@ -8765,15 +9289,15 @@ function newRunId(kind) {
8765
9289
  function tracePath(runId) {
8766
9290
  return join8(RUNS_DIR, `${runId}.jsonl`);
8767
9291
  }
8768
- function safeAppend(path4, line) {
9292
+ function safeAppend(path5, line) {
8769
9293
  try {
8770
- appendFileSync2(path4, line);
9294
+ appendFileSync2(path5, line);
8771
9295
  } catch {
8772
9296
  }
8773
9297
  }
8774
- function safeWrite(path4, line) {
9298
+ function safeWrite(path5, line) {
8775
9299
  try {
8776
- writeFileSync4(path4, line);
9300
+ writeFileSync4(path5, line);
8777
9301
  } catch {
8778
9302
  }
8779
9303
  }
@@ -9113,8 +9637,8 @@ function spendPath() {
9113
9637
  spendPathCached = join9(homedir8(), ".cclens", "llm-spend.jsonl");
9114
9638
  return spendPathCached;
9115
9639
  }
9116
- function __setSpendPathForTest(path4) {
9117
- spendPathCached = path4;
9640
+ function __setSpendPathForTest(path5) {
9641
+ spendPathCached = path5;
9118
9642
  }
9119
9643
  function appendSpend(record) {
9120
9644
  const p = spendPath();
@@ -9165,8 +9689,8 @@ function lockPath() {
9165
9689
  lockPathCached = join10(homedir9(), ".cclens", "llm-interactive.lock");
9166
9690
  return lockPathCached;
9167
9691
  }
9168
- function __setInteractiveLockPathForTest(path4) {
9169
- lockPathCached = path4;
9692
+ function __setInteractiveLockPathForTest(path5) {
9693
+ lockPathCached = path5;
9170
9694
  }
9171
9695
  function touchLock() {
9172
9696
  writeFileSync5(lockPath(), String(process.pid), "utf8");
@@ -9323,8 +9847,8 @@ function settingsPath() {
9323
9847
  settingsPathCached = join11(homedir10(), ".cclens", "settings.json");
9324
9848
  return settingsPathCached;
9325
9849
  }
9326
- function __setSettingsPathForTest(path4) {
9327
- settingsPathCached = path4;
9850
+ function __setSettingsPathForTest(path5) {
9851
+ settingsPathCached = path5;
9328
9852
  }
9329
9853
  function toDisk(s) {
9330
9854
  return {
@@ -9788,6 +10312,7 @@ var dist_exports = {};
9788
10312
  __export(dist_exports, {
9789
10313
  CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
9790
10314
  CODEX_METADATA: () => CODEX_METADATA,
10315
+ GEMINI_METADATA: () => GEMINI_METADATA,
9791
10316
  PRICES: () => PRICES,
9792
10317
  RATE_PER_PCT: () => RATE_PER_PCT,
9793
10318
  RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
@@ -10021,7 +10546,7 @@ function rollupOutcomeDay(entries2) {
10021
10546
  return "exploratory";
10022
10547
  return "trivial";
10023
10548
  }
10024
- function truncate3(s, max) {
10549
+ function truncate4(s, max) {
10025
10550
  if (s.length <= max)
10026
10551
  return s;
10027
10552
  return s.slice(0, max - 1).trimEnd() + "\u2026";
@@ -10077,7 +10602,7 @@ function computeDaySignals(entries2) {
10077
10602
  type,
10078
10603
  count: v.count,
10079
10604
  sample_description: v.sample_description,
10080
- sample_prompt_preview: truncate3(v.sample_prompt_preview, 200)
10605
+ sample_prompt_preview: truncate4(v.sample_prompt_preview, 200)
10081
10606
  }));
10082
10607
  const frameCounts = /* @__PURE__ */ new Map();
10083
10608
  for (const s of signalsList) {
@@ -10096,7 +10621,7 @@ function computeDaySignals(entries2) {
10096
10621
  if ((e.first_user ?? "").length > 0)
10097
10622
  verbosity_distribution[s.verbosity] += 1;
10098
10623
  for (const ref of s.external_refs) {
10099
- external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate3(ref.preview, 200) });
10624
+ external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate4(ref.preview, 200) });
10100
10625
  }
10101
10626
  const ints = e.numbers.interrupts ?? 0;
10102
10627
  interrupts += ints;
@@ -10969,7 +11494,7 @@ function computeInteractionModes(entries2) {
10969
11494
  date: entry.local_day,
10970
11495
  project_display: prettyProject3(entry.project),
10971
11496
  type: sa.type,
10972
- prompt_preview: truncate4(sa.prompt_preview, 200)
11497
+ prompt_preview: truncate5(sa.prompt_preview, 200)
10973
11498
  });
10974
11499
  }
10975
11500
  const skillExamples = [];
@@ -10986,7 +11511,7 @@ function computeInteractionModes(entries2) {
10986
11511
  skillExamples.push({
10987
11512
  date: e.local_day,
10988
11513
  skill,
10989
- first_user_preview: truncate4(e.first_user, 200)
11514
+ first_user_preview: truncate5(e.first_user, 200)
10990
11515
  });
10991
11516
  }
10992
11517
  }
@@ -11003,7 +11528,7 @@ function computeInteractionModes(entries2) {
11003
11528
  project_display: prettyProject3(longestTurnEntry.project),
11004
11529
  active_min: longestTurnEntry.numbers.active_min,
11005
11530
  top_tools: longestTurnEntry.top_tools.slice(0, 5),
11006
- first_user_preview: truncate4(longestTurnEntry.first_user, 200)
11531
+ first_user_preview: truncate5(longestTurnEntry.first_user, 200)
11007
11532
  } : null;
11008
11533
  const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
11009
11534
  const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
@@ -11034,7 +11559,7 @@ function computeInteractionModes(entries2) {
11034
11559
  }
11035
11560
  };
11036
11561
  }
11037
- function truncate4(s, max) {
11562
+ function truncate5(s, max) {
11038
11563
  if (s.length <= max)
11039
11564
  return s;
11040
11565
  return s.slice(0, max - 1).trimEnd() + "\u2026";
@@ -11081,7 +11606,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
11081
11606
  evidence_subagent = {
11082
11607
  type: sa.type,
11083
11608
  description: sa.description,
11084
- prompt_preview: truncate4(sa.prompt_preview, 200)
11609
+ prompt_preview: truncate5(sa.prompt_preview, 200)
11085
11610
  };
11086
11611
  }
11087
11612
  const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
@@ -11092,7 +11617,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
11092
11617
  outcome: dayOutcome.get(dd.key) ?? null,
11093
11618
  helpfulness: dayHelp.get(dd.key) ?? null,
11094
11619
  evidence_subagent,
11095
- evidence_first_user: repEntry?.first_user ? truncate4(repEntry.first_user, 200) : null,
11620
+ evidence_first_user: repEntry?.first_user ? truncate5(repEntry.first_user, 200) : null,
11096
11621
  day_signature: dd.day_signature ?? null
11097
11622
  };
11098
11623
  });
@@ -11167,7 +11692,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
11167
11692
  date: day2,
11168
11693
  session_id: ref.session_id,
11169
11694
  ref_kind: ref.kind,
11170
- preview: truncate4(ref.preview, 200)
11695
+ preview: truncate5(ref.preview, 200)
11171
11696
  });
11172
11697
  }
11173
11698
  total_interrupts += signals.comm_style.steering.interrupts;
@@ -11239,7 +11764,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
11239
11764
  count: v.count,
11240
11765
  days: [...v.days].sort(),
11241
11766
  sample_description: v.sample_description,
11242
- sample_prompt_preview: truncate4(v.sample_prompt_preview, 200)
11767
+ sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
11243
11768
  })),
11244
11769
  threads,
11245
11770
  communication_style: {
@@ -11887,7 +12412,7 @@ function activeMs(timestamps) {
11887
12412
  let active = 0;
11888
12413
  for (let i = 1; i < ts.length; i++) {
11889
12414
  const dt = ts[i] - ts[i - 1];
11890
- if (dt < IDLE_GAP_MS3)
12415
+ if (dt < IDLE_GAP_MS4)
11891
12416
  active += dt;
11892
12417
  }
11893
12418
  return active;
@@ -12058,7 +12583,7 @@ function buildSessionSlice(entry, events, daySignature) {
12058
12583
  let intEnd = sortedTs[0];
12059
12584
  for (let i = 1; i < sortedTs.length; i++) {
12060
12585
  const dt = sortedTs[i] - intEnd;
12061
- if (dt >= IDLE_GAP_MS3) {
12586
+ if (dt >= IDLE_GAP_MS4) {
12062
12587
  intervals.push({
12063
12588
  start_min: fmtMin(intStart - sliceStartMs),
12064
12589
  end_min: fmtMin(intEnd - sliceStartMs)
@@ -12455,14 +12980,14 @@ async function generateTopSession(slice, opts = {}) {
12455
12980
  void lastModel;
12456
12981
  }
12457
12982
  }
12458
- var IDLE_GAP_MS3, LONG_AUTONOMOUS_MIN, N_USER, N_FIRST_AGENT, N_LAST_AGENT, N_USER_TURN1, N_SUBAGENT, SHELL_NOISE, INTERRUPT_RE2, PR_TITLE_RE, PinResponseSchema, TopSessionResponseSchema, SYSTEM_PROMPT5, TOP_SESSION_SYSTEM_PROMPT, DEFAULT_MODEL5, defaultCallLLMTopSession, validateTopSession;
12983
+ var IDLE_GAP_MS4, LONG_AUTONOMOUS_MIN, N_USER, N_FIRST_AGENT, N_LAST_AGENT, N_USER_TURN1, N_SUBAGENT, SHELL_NOISE, INTERRUPT_RE2, PR_TITLE_RE, PinResponseSchema, TopSessionResponseSchema, SYSTEM_PROMPT5, TOP_SESSION_SYSTEM_PROMPT, DEFAULT_MODEL5, defaultCallLLMTopSession, validateTopSession;
12459
12984
  var init_top_sessions = __esm({
12460
12985
  "../entries/dist/top-sessions.js"() {
12461
12986
  "use strict";
12462
12987
  init_zod();
12463
12988
  init_signals();
12464
12989
  init_llm_runner();
12465
- IDLE_GAP_MS3 = 3 * 60 * 1e3;
12990
+ IDLE_GAP_MS4 = 3 * 60 * 1e3;
12466
12991
  LONG_AUTONOMOUS_MIN = 20;
12467
12992
  N_USER = 150;
12468
12993
  N_FIRST_AGENT = 150;
@@ -14018,6 +14543,7 @@ async function buildCyclePeaksForPush(planTier, loadCurve) {
14018
14543
  const HOUR = 36e5;
14019
14544
  const nowMs = Date.now();
14020
14545
  const peaksFor = (cycleKey, realKey, predKey, maxCycles) => {
14546
+ const TOLERANCE_MS = cycleKey === "cycle_end_7d" ? 12 * HOUR : 0;
14021
14547
  const byCycle = /* @__PURE__ */ new Map();
14022
14548
  for (const p of dump.curve) {
14023
14549
  const k = p[cycleKey];
@@ -14029,8 +14555,18 @@ async function buildCyclePeaksForPush(planTier, loadCurve) {
14029
14555
  arr.push(p);
14030
14556
  byCycle.set(bucket, arr);
14031
14557
  }
14032
- const out = [];
14558
+ const merged = [];
14033
14559
  for (const [endMs, points] of Array.from(byCycle.entries()).sort((a, b) => a[0] - b[0])) {
14560
+ const last = merged[merged.length - 1];
14561
+ if (last && endMs - last.endMs <= TOLERANCE_MS) {
14562
+ last.endMs = endMs;
14563
+ last.points.push(...points);
14564
+ } else {
14565
+ merged.push({ endMs, points: [...points] });
14566
+ }
14567
+ }
14568
+ const out = [];
14569
+ for (const { endMs, points } of merged) {
14034
14570
  let peak = 0;
14035
14571
  let source = "predicted";
14036
14572
  for (const p of points) {
@@ -14526,9 +15062,9 @@ function listTraceFiles() {
14526
15062
  if (!existsSync12(RUNS_DIR2)) return [];
14527
15063
  const entries2 = readdirSync3(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
14528
15064
  return entries2.map((f) => {
14529
- const path4 = join17(RUNS_DIR2, f);
14530
- const st = statSync4(path4);
14531
- return { runId: f.replace(/\.jsonl$/, ""), path: path4, mtimeMs: st.mtimeMs };
15065
+ const path5 = join17(RUNS_DIR2, f);
15066
+ const st = statSync4(path5);
15067
+ return { runId: f.replace(/\.jsonl$/, ""), path: path5, mtimeMs: st.mtimeMs };
14532
15068
  }).sort((a, b) => b.mtimeMs - a.mtimeMs);
14533
15069
  }
14534
15070
  function resolveRunId(arg) {
@@ -14550,8 +15086,8 @@ function resolveRunId(arg) {
14550
15086
  }
14551
15087
  return null;
14552
15088
  }
14553
- function readTrace(path4) {
14554
- return readFileSync15(path4, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
15089
+ function readTrace(path5) {
15090
+ return readFileSync15(path5, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
14555
15091
  try {
14556
15092
  return JSON.parse(l);
14557
15093
  } catch {
@@ -14732,7 +15268,7 @@ async function main() {
14732
15268
  case "version":
14733
15269
  case "--version":
14734
15270
  case "-v":
14735
- console.log(`fleetlens ${"0.7.0"}`);
15271
+ console.log(`fleetlens ${"0.9.0"}`);
14736
15272
  break;
14737
15273
  case "help":
14738
15274
  case "--help":