fleetlens 0.7.1 → 0.10.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 (130) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/build-manifest.json +3 -3
  3. package/app/apps/web/.next/prerender-manifest.json +3 -3
  4. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  5. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  6. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  12. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/app/apps/web/.next/server/app/api/ask/route.js +1 -1
  14. package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
  15. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +3 -3
  16. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  17. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +3 -3
  18. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
  19. package/app/apps/web/.next/server/app/api/digest/month-index/route.js +2 -2
  20. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  21. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +3 -3
  22. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  23. package/app/apps/web/.next/server/app/api/digest/week-index/route.js +2 -2
  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/events/route.js +1 -1
  26. package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
  27. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  29. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  30. package/app/apps/web/.next/server/app/api/settings/route.js +4 -4
  31. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  32. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
  33. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  34. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  35. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  36. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  37. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  38. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  39. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  40. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  41. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  42. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  43. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  44. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  45. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  46. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  47. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  48. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  49. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  50. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  51. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  52. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  53. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  54. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  55. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  56. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  57. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  58. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  59. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  60. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  61. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  62. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  63. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  64. package/app/apps/web/.next/server/chunks/[root-of-the-server]__07qxzx4._.js +9 -0
  65. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0fu2xfy._.js +5 -0
  66. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0gfd42k._.js +9 -0
  67. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0i.m8y0._.js +3 -0
  68. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0iy5aqy._.js +9 -0
  69. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nh7-nf._.js +3 -0
  70. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nvdffv._.js +3 -0
  71. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0s2~c3g._.js +3 -0
  72. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0ck.78s.js +3 -3
  73. package/app/apps/web/.next/server/chunks/packages_09wmnv.._.js +3 -0
  74. package/app/apps/web/.next/server/chunks/packages_0o6.gpk._.js +3 -0
  75. package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +13 -13
  76. package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_122oe0-.js +1 -1
  77. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d~2~le._.js +1 -1
  78. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +1 -1
  79. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0s4dg1y._.js +3 -0
  80. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0tejjy_._.js +1 -1
  81. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +3 -3
  82. package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.js +1 -1
  83. package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
  84. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0ly1xes._.js +1 -1
  85. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +1 -1
  86. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_usage-charts-dashboard_tsx_0bgr_uv._.js +1 -1
  87. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0m67-xi._.js +1 -1
  88. package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +1 -1
  89. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_10_oegc._.js +1 -1
  90. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  91. package/app/apps/web/.next/server/pages/500.html +1 -1
  92. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  93. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  94. package/app/apps/web/.next/static/chunks/04a36uhu~p_z-.css +1 -0
  95. package/app/apps/web/.next/static/chunks/{0q2vd~aj.1hpz.js → 09--oejbzw3q-.js} +3 -3
  96. package/app/apps/web/.next/static/chunks/0l3ck.awv~4t7.js +1 -0
  97. package/app/apps/web/.next/static/chunks/{171za22fv684..js → 0lxuac2v0_gdl.js} +2 -2
  98. package/app/apps/web/.next/static/chunks/0n0n.0279ot6c.js +1 -0
  99. package/app/apps/web/.next/static/chunks/0qcu452dr~edz.js +14 -0
  100. package/app/apps/web/.next/static/chunks/0uev~g~qvbjv9.js +4 -0
  101. package/app/apps/web/components/previous-cycles-trend.tsx +26 -11
  102. package/app/apps/web/components/usage-chart.tsx +35 -37
  103. package/app/apps/web/components/usage-gauges.tsx +18 -12
  104. package/app/apps/web/components/usage-sidebar.tsx +23 -12
  105. package/app/apps/web/lib/changelog-data.generated.ts +1 -1
  106. package/app/apps/web/lib/utilization-tone.ts +74 -0
  107. package/app/apps/web/package.json +1 -1
  108. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  109. package/dist/daemon-worker.js +694 -67
  110. package/dist/index.js +1449 -823
  111. package/package.json +1 -1
  112. package/app/apps/web/.next/server/chunks/[externals]__0fpbr8-._.js +0 -3
  113. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0-vgrh1._.js +0 -3
  114. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.z48ue._.js +0 -3
  115. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_8zh-i._.js +0 -9
  116. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0dctov1._.js +0 -5
  117. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0e8n_x4._.js +0 -3
  118. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ej_p3s._.js +0 -9
  119. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jprdks._.js +0 -9
  120. package/app/apps/web/.next/server/chunks/packages_09hmrqx._.js +0 -3
  121. package/app/apps/web/.next/server/chunks/packages_118y1lp._.js +0 -3
  122. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ytdqxt._.js +0 -3
  123. package/app/apps/web/.next/static/chunks/05m.oz3kmf1p7.js +0 -1
  124. package/app/apps/web/.next/static/chunks/07-fq4im3pmjp.js +0 -4
  125. package/app/apps/web/.next/static/chunks/0o9ayt8sknubd.js +0 -1
  126. package/app/apps/web/.next/static/chunks/0wfbj5zr~az.z.css +0 -1
  127. package/app/apps/web/.next/static/chunks/179_t_igg8ghh.js +0 -14
  128. /package/app/apps/web/.next/static/{tiK9aMHXkgnKLNmxj9J1P → L0Dy1hOQrZjV9l0TNulvk}/_buildManifest.js +0 -0
  129. /package/app/apps/web/.next/static/{tiK9aMHXkgnKLNmxj9J1P → L0Dy1hOQrZjV9l0TNulvk}/_clientMiddlewareManifest.js +0 -0
  130. /package/app/apps/web/.next/static/{tiK9aMHXkgnKLNmxj9J1P → L0Dy1hOQrZjV9l0TNulvk}/_ssgManifest.js +0 -0
@@ -32,21 +32,37 @@ function findWorktreeMarker(projectName) {
32
32
  }
33
33
  return null;
34
34
  }
35
+ function findConductorWorkspace(projectName) {
36
+ const m = CONDUCTOR_RE.exec(projectName);
37
+ if (!m)
38
+ return null;
39
+ const workspaceName = m[1];
40
+ const trailingSlash = m[0].endsWith("/") ? 1 : 0;
41
+ const canonicalEndIdx = m.index + m[0].length - workspaceName.length - 1 - trailingSlash;
42
+ return { canonicalEndIdx, workspaceName };
43
+ }
35
44
  function canonicalProjectName(projectName) {
36
45
  const normalized = projectName.replace(/\/{2,}/g, "/");
37
- const hit = findWorktreeMarker(normalized);
38
- if (hit)
39
- return normalized.slice(0, hit.idx);
46
+ const wt = findWorktreeMarker(normalized);
47
+ if (wt)
48
+ return normalized.slice(0, wt.idx);
49
+ const cd = findConductorWorkspace(normalized);
50
+ if (cd)
51
+ return normalized.slice(0, cd.canonicalEndIdx);
40
52
  return normalized;
41
53
  }
42
54
  function worktreeName(projectName) {
43
55
  const normalized = projectName.replace(/\/{2,}/g, "/");
44
- const hit = findWorktreeMarker(normalized);
45
- if (!hit)
46
- return null;
47
- const tail = normalized.slice(hit.idx + hit.marker.length);
48
- const slash = tail.indexOf("/");
49
- return slash >= 0 ? tail.slice(0, slash) : tail;
56
+ const wt = findWorktreeMarker(normalized);
57
+ if (wt) {
58
+ const tail = normalized.slice(wt.idx + wt.marker.length);
59
+ const slash = tail.indexOf("/");
60
+ return slash >= 0 ? tail.slice(0, slash) : tail;
61
+ }
62
+ const cd = findConductorWorkspace(normalized);
63
+ if (cd)
64
+ return cd.workspaceName;
65
+ return null;
50
66
  }
51
67
  function makeDay(date) {
52
68
  return {
@@ -515,7 +531,7 @@ function groupByProject(sessions) {
515
531
  }
516
532
  return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
517
533
  }
518
- var BLANK_USAGE, WORKTREE_MARKERS, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
534
+ var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
519
535
  var init_analytics = __esm({
520
536
  "../parser/dist/analytics.js"() {
521
537
  "use strict";
@@ -525,6 +541,7 @@ var init_analytics = __esm({
525
541
  "/.worktrees/",
526
542
  "/claude/worktrees/"
527
543
  ];
544
+ CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
528
545
  PR_CREATE_RE = /gh\s+pr\s+create\b/i;
529
546
  PR_NUMBER_RE = /#(\d+)/;
530
547
  TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
@@ -538,7 +555,7 @@ function getAgentMetadata(kind) {
538
555
  function isAgentKind(s) {
539
556
  return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
540
557
  }
541
- var CLAUDE_CODE_METADATA, CODEX_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
558
+ var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
542
559
  var init_agent_metadata = __esm({
543
560
  "../parser/dist/agent-metadata.js"() {
544
561
  "use strict";
@@ -556,9 +573,17 @@ var init_agent_metadata = __esm({
556
573
  accentColor: "rgb(16, 163, 127)",
557
574
  iconChar: "\u25C6"
558
575
  };
576
+ GEMINI_METADATA = {
577
+ kind: "gemini",
578
+ displayName: "Gemini CLI",
579
+ shortLabel: "Gemini",
580
+ accentColor: "rgb(124, 92, 246)",
581
+ iconChar: "\u273A"
582
+ };
559
583
  agentMetadata = [
560
584
  CLAUDE_CODE_METADATA,
561
- CODEX_METADATA
585
+ CODEX_METADATA,
586
+ GEMINI_METADATA
562
587
  ];
563
588
  KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
564
589
  }
@@ -749,10 +774,64 @@ var init_calibration = __esm({
749
774
  }
750
775
  });
751
776
 
777
+ // ../parser/dist/user-input.js
778
+ function stripFrameworkBoilerplate(rawText) {
779
+ if (!rawText)
780
+ return rawText;
781
+ let out = rawText;
782
+ for (const re of STRIPPABLE_WRAPPERS) {
783
+ out = out.replace(re, "");
784
+ }
785
+ return out.trim();
786
+ }
787
+ function isFrameworkInjectedUserInput(rawText) {
788
+ if (!rawText)
789
+ return false;
790
+ const stripped = stripFrameworkBoilerplate(rawText);
791
+ if (!stripped)
792
+ return true;
793
+ for (const prefix of ENTIRELY_INJECTED_PREFIXES) {
794
+ if (stripped.startsWith(prefix))
795
+ return true;
796
+ }
797
+ return false;
798
+ }
799
+ var STRIPPABLE_WRAPPERS, ENTIRELY_INJECTED_PREFIXES;
800
+ var init_user_input = __esm({
801
+ "../parser/dist/user-input.js"() {
802
+ "use strict";
803
+ STRIPPABLE_WRAPPERS = [
804
+ /<system_instruction\b[^>]*>[\s\S]*?<\/system_instruction>\s*/gi
805
+ ];
806
+ ENTIRELY_INJECTED_PREFIXES = [
807
+ "<command-name>",
808
+ "<local-command-stdout>",
809
+ "<local-command-caveat>",
810
+ "<task-notification>",
811
+ "Base directory for this skill:"
812
+ ];
813
+ }
814
+ });
815
+
752
816
  // ../parser/dist/parser.js
753
817
  function cleanText(s) {
754
818
  return s.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
755
819
  }
820
+ function extractRawUserText(rawMsg) {
821
+ const c = rawMsg?.content;
822
+ if (typeof c === "string")
823
+ return c;
824
+ if (Array.isArray(c)) {
825
+ for (const block of c) {
826
+ if (block && typeof block === "object") {
827
+ const b = block;
828
+ if (b.type === "text" && typeof b.text === "string")
829
+ return b.text;
830
+ }
831
+ }
832
+ }
833
+ return "";
834
+ }
756
835
  function truncate(s, n = 200) {
757
836
  const one = cleanText(s);
758
837
  return one.length > n ? one.slice(0, n - 1) + "\u2026" : one;
@@ -851,7 +930,8 @@ function toEvent(raw, index) {
851
930
  const msg = r.message ?? {};
852
931
  const c = msg.content;
853
932
  if (typeof c === "string") {
854
- const tm = classifyTeammateMessage(c);
933
+ const cleaned = stripFrameworkBoilerplate(c);
934
+ const tm = classifyTeammateMessage(cleaned);
855
935
  return {
856
936
  index,
857
937
  uuid,
@@ -859,8 +939,8 @@ function toEvent(raw, index) {
859
939
  timestamp,
860
940
  role: "user",
861
941
  rawType,
862
- preview: truncate(c, 200),
863
- blocks: [{ type: "text", text: c }],
942
+ preview: truncate(cleaned, 200),
943
+ blocks: cleaned ? [{ type: "text", text: cleaned }] : [],
864
944
  raw,
865
945
  teammateMessage: tm
866
946
  };
@@ -884,7 +964,9 @@ function toEvent(raw, index) {
884
964
  };
885
965
  }
886
966
  const textBlock = c.find((b) => b?.type === "text");
887
- const tm = textBlock ? classifyTeammateMessage(textBlock.text) : void 0;
967
+ const cleanedText = textBlock ? stripFrameworkBoilerplate(textBlock.text) : "";
968
+ const cleanedBlocks = textBlock ? c.map((b) => b === textBlock ? { type: "text", text: cleanedText } : b) : c;
969
+ const tm = cleanedText ? classifyTeammateMessage(cleanedText) : void 0;
888
970
  return {
889
971
  index,
890
972
  uuid,
@@ -892,8 +974,8 @@ function toEvent(raw, index) {
892
974
  timestamp,
893
975
  role: "user",
894
976
  rawType,
895
- preview: textBlock ? truncate(textBlock.text, 200) : truncate(JSON.stringify(c), 200),
896
- blocks: c,
977
+ preview: cleanedText ? truncate(cleanedText, 200) : truncate(JSON.stringify(c), 200),
978
+ blocks: cleanedBlocks,
897
979
  raw,
898
980
  teammateMessage: tm
899
981
  };
@@ -1113,8 +1195,8 @@ function parseTranscript(rawLines) {
1113
1195
  }
1114
1196
  if (e.role === "user") {
1115
1197
  const rawMsg = e.raw?.message;
1116
- const rawContent = typeof rawMsg?.content === "string" ? rawMsg.content : "";
1117
- const isHidden = rawContent.startsWith("<command-name>") || rawContent.startsWith("<local-command-caveat>") || rawContent.startsWith("Base directory for this skill:") || rawContent.startsWith("<task-notification>");
1198
+ const rawContent = extractRawUserText(rawMsg);
1199
+ const isHidden = isFrameworkInjectedUserInput(rawContent);
1118
1200
  const isTeamNoise = e.teammateMessage !== void 0 && !agentName;
1119
1201
  if (!isHidden && !isTeamNoise) {
1120
1202
  if (!firstUserPreview) {
@@ -1199,6 +1281,7 @@ var BLANK_USAGE2, TEAMMATE_MSG_RE;
1199
1281
  var init_parser = __esm({
1200
1282
  "../parser/dist/parser.js"() {
1201
1283
  "use strict";
1284
+ init_user_input();
1202
1285
  BLANK_USAGE2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
1203
1286
  TEAMMATE_MSG_RE = /^\s*<teammate-message\s+teammate_id="([^"]+)"[^>]*>([\s\S]*?)<\/teammate-message>/;
1204
1287
  }
@@ -2017,7 +2100,8 @@ function parseRollout(file, lines) {
2017
2100
  if (type === "event_msg" && subtype === "user_message") {
2018
2101
  const text = typeof payload.message === "string" ? payload.message : "";
2019
2102
  const preview = previewOf(text);
2020
- if (text) {
2103
+ const isHidden = isFrameworkInjectedUserInput(text);
2104
+ if (text && !isHidden) {
2021
2105
  if (!firstUserPreview)
2022
2106
  firstUserPreview = preview;
2023
2107
  lastUserPreview = preview;
@@ -2334,6 +2418,7 @@ var init_codex = __esm({
2334
2418
  "../parser/dist/codex.js"() {
2335
2419
  "use strict";
2336
2420
  init_analytics();
2421
+ init_user_input();
2337
2422
  DEFAULT_CODEX_ROOT = path2.join(os2.homedir(), ".codex", "sessions");
2338
2423
  ROLLOUT_RE = /^rollout-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})-([0-9a-f-]+)\.jsonl$/;
2339
2424
  IDLE_GAP_MS = 3 * 60 * 1e3;
@@ -2342,10 +2427,512 @@ var init_codex = __esm({
2342
2427
  }
2343
2428
  });
2344
2429
 
2430
+ // ../parser/dist/gemini.js
2431
+ import { promises as fs3 } from "node:fs";
2432
+ import os3 from "node:os";
2433
+ import path3 from "node:path";
2434
+ async function safeReaddir2(p) {
2435
+ return fs3.readdir(p).catch(() => []);
2436
+ }
2437
+ async function listSessionFiles(root) {
2438
+ const out = [];
2439
+ const slugs = await safeReaddir2(root);
2440
+ for (const slug of slugs) {
2441
+ const chatsDir = path3.join(root, slug, "chats");
2442
+ const entries = await safeReaddir2(chatsDir);
2443
+ for (const entry of entries) {
2444
+ if (!SESSION_FILE_RE.test(entry))
2445
+ continue;
2446
+ const full = path3.join(chatsDir, entry);
2447
+ const stat = await fs3.stat(full).catch(() => null);
2448
+ if (!stat || !stat.isFile())
2449
+ continue;
2450
+ const filenameId = entry.replace(/\.(jsonl|json)$/, "").split("-").pop() ?? entry;
2451
+ out.push({
2452
+ filePath: full,
2453
+ slug,
2454
+ filenameId,
2455
+ format: entry.endsWith(".jsonl") ? "jsonl" : "legacy-json",
2456
+ mtimeMs: stat.mtimeMs,
2457
+ sizeBytes: stat.size
2458
+ });
2459
+ }
2460
+ }
2461
+ return out;
2462
+ }
2463
+ async function loadSlugToCwd() {
2464
+ const stat = await fs3.stat(GEMINI_PROJECTS_FILE).catch(() => null);
2465
+ if (!stat)
2466
+ return /* @__PURE__ */ new Map();
2467
+ if (projectsCache && projectsCache.mtimeMs === stat.mtimeMs) {
2468
+ return projectsCache.slugToCwd;
2469
+ }
2470
+ const raw = await fs3.readFile(GEMINI_PROJECTS_FILE, "utf8").catch(() => "");
2471
+ let parsed;
2472
+ try {
2473
+ parsed = JSON.parse(raw);
2474
+ } catch {
2475
+ parsed = {};
2476
+ }
2477
+ const slugToCwd = /* @__PURE__ */ new Map();
2478
+ for (const [cwd, slug] of Object.entries(parsed.projects ?? {})) {
2479
+ if (typeof slug === "string")
2480
+ slugToCwd.set(slug, cwd);
2481
+ }
2482
+ projectsCache = { mtimeMs: stat.mtimeMs, slugToCwd };
2483
+ return slugToCwd;
2484
+ }
2485
+ function isRewindMarker(o) {
2486
+ return !!o && typeof o === "object" && "$rewindTo" in o;
2487
+ }
2488
+ function isSetMarker(o) {
2489
+ return !!o && typeof o === "object" && "$set" in o;
2490
+ }
2491
+ function isMessageRecord(o) {
2492
+ return !!o && typeof o === "object" && typeof o.id === "string" && typeof o.type === "string";
2493
+ }
2494
+ async function readAndReplay(file) {
2495
+ const raw = await fs3.readFile(file.filePath, "utf8");
2496
+ if (file.format === "legacy-json") {
2497
+ let blob;
2498
+ try {
2499
+ blob = JSON.parse(raw);
2500
+ } catch {
2501
+ return { meta: {}, messages: [] };
2502
+ }
2503
+ const meta2 = {
2504
+ sessionId: typeof blob.sessionId === "string" ? blob.sessionId : void 0,
2505
+ projectHash: typeof blob.projectHash === "string" ? blob.projectHash : void 0,
2506
+ startTime: typeof blob.startTime === "string" ? blob.startTime : void 0,
2507
+ lastUpdated: typeof blob.lastUpdated === "string" ? blob.lastUpdated : void 0,
2508
+ summary: typeof blob.summary === "string" ? blob.summary : void 0
2509
+ };
2510
+ const msgs = Array.isArray(blob.messages) ? blob.messages : [];
2511
+ const messages2 = msgs.filter(isMessageRecord);
2512
+ return { meta: meta2, messages: messages2 };
2513
+ }
2514
+ const meta = {};
2515
+ const byId = /* @__PURE__ */ new Map();
2516
+ const order = [];
2517
+ for (const line of raw.split("\n")) {
2518
+ const trimmed = line.trim();
2519
+ if (!trimmed)
2520
+ continue;
2521
+ let obj;
2522
+ try {
2523
+ obj = JSON.parse(trimmed);
2524
+ } catch {
2525
+ continue;
2526
+ }
2527
+ if (isRewindMarker(obj)) {
2528
+ const target = obj.$rewindTo;
2529
+ const idx = order.indexOf(target);
2530
+ if (idx >= 0) {
2531
+ for (const id of order.slice(idx))
2532
+ byId.delete(id);
2533
+ order.length = idx;
2534
+ }
2535
+ continue;
2536
+ }
2537
+ if (isSetMarker(obj)) {
2538
+ Object.assign(meta, obj.$set);
2539
+ continue;
2540
+ }
2541
+ if (isMessageRecord(obj)) {
2542
+ if (!byId.has(obj.id))
2543
+ order.push(obj.id);
2544
+ byId.set(obj.id, obj);
2545
+ continue;
2546
+ }
2547
+ if (typeof obj === "object" && obj !== null) {
2548
+ const m = obj;
2549
+ if (typeof m.sessionId === "string" && !meta.sessionId) {
2550
+ meta.sessionId = m.sessionId;
2551
+ if (typeof m.projectHash === "string")
2552
+ meta.projectHash = m.projectHash;
2553
+ if (typeof m.startTime === "string")
2554
+ meta.startTime = m.startTime;
2555
+ if (typeof m.lastUpdated === "string")
2556
+ meta.lastUpdated = m.lastUpdated;
2557
+ if (typeof m.summary === "string")
2558
+ meta.summary = m.summary;
2559
+ }
2560
+ }
2561
+ }
2562
+ const messages = [];
2563
+ for (const id of order) {
2564
+ const m = byId.get(id);
2565
+ if (m)
2566
+ messages.push(m);
2567
+ }
2568
+ return { meta, messages };
2569
+ }
2570
+ function emptyUsage2() {
2571
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
2572
+ }
2573
+ function previewOf2(text) {
2574
+ return text.replace(/\s+/g, " ").trim().slice(0, 200);
2575
+ }
2576
+ function flattenContent(c) {
2577
+ if (!c)
2578
+ return "";
2579
+ if (typeof c === "string")
2580
+ return c;
2581
+ const parts = Array.isArray(c) ? c : [c];
2582
+ const out = [];
2583
+ for (const p of parts) {
2584
+ if (!p || typeof p !== "object")
2585
+ continue;
2586
+ const part = p;
2587
+ if (typeof part.text === "string") {
2588
+ out.push(part.text);
2589
+ continue;
2590
+ }
2591
+ const fr = part.functionResponse;
2592
+ if (fr) {
2593
+ const resp = fr.response;
2594
+ if (typeof resp === "string") {
2595
+ out.push(resp);
2596
+ } else if (resp && typeof resp === "object") {
2597
+ const r = resp;
2598
+ if (typeof r.output === "string")
2599
+ out.push(r.output);
2600
+ else if (typeof r.error === "string")
2601
+ out.push(`error: ${r.error}`);
2602
+ else
2603
+ out.push(JSON.stringify(r));
2604
+ }
2605
+ }
2606
+ }
2607
+ return out.join("\n");
2608
+ }
2609
+ function truncate3(s, n) {
2610
+ return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
2611
+ }
2612
+ async function parseSession(file) {
2613
+ const { meta: metaRec, messages } = await readAndReplay(file);
2614
+ const slugToCwd = await loadSlugToCwd();
2615
+ const cwd = slugToCwd.get(file.slug);
2616
+ const events = [];
2617
+ const totalUsage = emptyUsage2();
2618
+ let firstTimestamp;
2619
+ let lastTimestamp;
2620
+ let model;
2621
+ let toolCallCount = 0;
2622
+ let turnCount = 0;
2623
+ let firstUserPreview;
2624
+ let lastUserPreview;
2625
+ let lastAgentPreview;
2626
+ const tsMs = [];
2627
+ let idx = 0;
2628
+ function pushEvent(e) {
2629
+ events.push(e);
2630
+ if (e.timestamp && e.role !== "meta") {
2631
+ if (!firstTimestamp)
2632
+ firstTimestamp = e.timestamp;
2633
+ lastTimestamp = e.timestamp;
2634
+ const ms = Date.parse(e.timestamp);
2635
+ if (Number.isFinite(ms))
2636
+ tsMs.push(ms);
2637
+ }
2638
+ }
2639
+ for (const msg of messages) {
2640
+ const ts = msg.timestamp;
2641
+ if (msg.type === "user") {
2642
+ const text = flattenContent(msg.displayContent ?? msg.content);
2643
+ const preview = previewOf2(text);
2644
+ const isHidden = isFrameworkInjectedUserInput(text);
2645
+ if (text && !isHidden) {
2646
+ if (!firstUserPreview)
2647
+ firstUserPreview = preview;
2648
+ lastUserPreview = preview;
2649
+ turnCount += 1;
2650
+ }
2651
+ pushEvent({
2652
+ index: idx++,
2653
+ timestamp: ts,
2654
+ role: "user",
2655
+ rawType: "gemini/user",
2656
+ preview,
2657
+ blocks: text ? [{ type: "text", text }] : [],
2658
+ messageId: msg.id,
2659
+ raw: msg
2660
+ });
2661
+ continue;
2662
+ }
2663
+ if (msg.type === "gemini") {
2664
+ if (typeof msg.model === "string")
2665
+ model = msg.model;
2666
+ const text = flattenContent(msg.content);
2667
+ const preview = previewOf2(text);
2668
+ if (text)
2669
+ lastAgentPreview = preview;
2670
+ let usage;
2671
+ if (msg.tokens) {
2672
+ const t = msg.tokens;
2673
+ const u = {
2674
+ input: t.input ?? 0,
2675
+ output: t.output ?? 0,
2676
+ cacheRead: t.cached ?? 0,
2677
+ cacheWrite: 0
2678
+ };
2679
+ usage = u;
2680
+ totalUsage.input += u.input;
2681
+ totalUsage.output += u.output;
2682
+ totalUsage.cacheRead += u.cacheRead;
2683
+ }
2684
+ for (const th of msg.thoughts ?? []) {
2685
+ const thText = [th.subject, th.description].filter(Boolean).join(": ");
2686
+ if (!thText)
2687
+ continue;
2688
+ pushEvent({
2689
+ index: idx++,
2690
+ timestamp: th.timestamp ?? ts,
2691
+ role: "agent-thinking",
2692
+ rawType: "gemini/thought",
2693
+ preview: previewOf2(thText),
2694
+ blocks: [{ type: "thinking", thinking: thText }],
2695
+ model,
2696
+ raw: th
2697
+ });
2698
+ }
2699
+ if (text) {
2700
+ pushEvent({
2701
+ index: idx++,
2702
+ timestamp: ts,
2703
+ role: "agent",
2704
+ rawType: "gemini/agent",
2705
+ preview,
2706
+ blocks: [{ type: "text", text }],
2707
+ messageId: msg.id,
2708
+ model,
2709
+ usage,
2710
+ raw: msg
2711
+ });
2712
+ } else if (usage) {
2713
+ pushEvent({
2714
+ index: idx++,
2715
+ timestamp: ts,
2716
+ role: "agent",
2717
+ rawType: "gemini/agent",
2718
+ preview: "",
2719
+ blocks: [],
2720
+ messageId: msg.id,
2721
+ model,
2722
+ usage,
2723
+ raw: msg
2724
+ });
2725
+ }
2726
+ for (const tc of msg.toolCalls ?? []) {
2727
+ toolCallCount += 1;
2728
+ const argsStr = tc.args ? JSON.stringify(tc.args) : "";
2729
+ pushEvent({
2730
+ index: idx++,
2731
+ timestamp: tc.timestamp ?? ts,
2732
+ role: "tool-call",
2733
+ rawType: "gemini/tool_call",
2734
+ preview: `${tc.name}(${truncate3(argsStr, 80)})`,
2735
+ blocks: [{ type: "tool_use", id: tc.id, name: tc.name, input: tc.args ?? {} }],
2736
+ toolName: tc.name,
2737
+ toolUseId: tc.id,
2738
+ model,
2739
+ raw: tc
2740
+ });
2741
+ const status = (tc.status ?? "").toLowerCase();
2742
+ const isTerminal = status === "success" || status === "error" || status === "cancelled";
2743
+ if (isTerminal) {
2744
+ const resultText = flattenContent(tc.result);
2745
+ pushEvent({
2746
+ index: idx++,
2747
+ timestamp: tc.timestamp ?? ts,
2748
+ role: "tool-result",
2749
+ rawType: "gemini/tool_result",
2750
+ preview: previewOf2(resultText),
2751
+ blocks: [
2752
+ {
2753
+ type: "tool_result",
2754
+ tool_use_id: tc.id,
2755
+ content: resultText,
2756
+ is_error: status === "error" || status === "cancelled"
2757
+ }
2758
+ ],
2759
+ toolUseId: tc.id,
2760
+ toolResult: resultText,
2761
+ raw: tc
2762
+ });
2763
+ }
2764
+ }
2765
+ continue;
2766
+ }
2767
+ if (msg.type === "info" || msg.type === "warning" || msg.type === "error") {
2768
+ const text = flattenContent(msg.content);
2769
+ pushEvent({
2770
+ index: idx++,
2771
+ timestamp: ts,
2772
+ role: "meta",
2773
+ rawType: `gemini/${msg.type}`,
2774
+ preview: previewOf2(text),
2775
+ blocks: text ? [{ type: "text", text }] : [],
2776
+ raw: msg
2777
+ });
2778
+ continue;
2779
+ }
2780
+ }
2781
+ const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
2782
+ if (startMs !== void 0 && Number.isFinite(startMs)) {
2783
+ let prevMs;
2784
+ for (const ev of events) {
2785
+ if (!ev.timestamp)
2786
+ continue;
2787
+ const ms = Date.parse(ev.timestamp);
2788
+ if (!Number.isFinite(ms))
2789
+ continue;
2790
+ ev.tOffsetMs = Math.max(0, ms - startMs);
2791
+ if (prevMs !== void 0)
2792
+ ev.gapMs = Math.max(0, ms - prevMs);
2793
+ prevMs = ms;
2794
+ }
2795
+ }
2796
+ const activeSegments = computeActiveSegments3(tsMs);
2797
+ const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
2798
+ const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
2799
+ const sessionId = metaRec.sessionId ?? file.filenameId;
2800
+ const projectName = cwd ? canonicalProjectName(cwd) : file.slug;
2801
+ const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
2802
+ const meta = {
2803
+ agent: "gemini",
2804
+ id: sessionId,
2805
+ filePath: file.filePath,
2806
+ projectName,
2807
+ projectDir,
2808
+ sessionId,
2809
+ firstTimestamp,
2810
+ lastTimestamp,
2811
+ durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
2812
+ eventCount: events.length,
2813
+ model,
2814
+ cwd,
2815
+ totalUsage,
2816
+ status: "idle",
2817
+ firstUserPreview,
2818
+ lastUserPreview,
2819
+ lastAgentPreview,
2820
+ toolCallCount,
2821
+ turnCount,
2822
+ airTimeMs,
2823
+ activeSegments
2824
+ };
2825
+ return { meta, events };
2826
+ }
2827
+ function computeActiveSegments3(tsMs) {
2828
+ if (tsMs.length === 0)
2829
+ return [];
2830
+ const sorted = [...tsMs].sort((a, b) => a - b);
2831
+ const out = [];
2832
+ let segStart = sorted[0];
2833
+ let segEnd = sorted[0];
2834
+ for (let i = 1; i < sorted.length; i++) {
2835
+ if (sorted[i] - segEnd > IDLE_GAP_MS2) {
2836
+ out.push({ startMs: segStart, endMs: segEnd });
2837
+ segStart = sorted[i];
2838
+ }
2839
+ segEnd = sorted[i];
2840
+ }
2841
+ out.push({ startMs: segStart, endMs: segEnd });
2842
+ return out;
2843
+ }
2844
+ function clearGeminiCaches() {
2845
+ metaCache3.clear();
2846
+ detailCache3.clear();
2847
+ projectsCache = null;
2848
+ }
2849
+ async function listGeminiSessions(opts = {}) {
2850
+ const root = opts.root ?? DEFAULT_GEMINI_ROOT;
2851
+ const files = await listSessionFiles(root);
2852
+ const out = [];
2853
+ for (const file of files) {
2854
+ const cached = metaCache3.get(file.filePath);
2855
+ if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
2856
+ out.push(cached.meta);
2857
+ continue;
2858
+ }
2859
+ try {
2860
+ const { meta } = await parseSession(file);
2861
+ metaCache3.set(file.filePath, {
2862
+ meta,
2863
+ mtimeMs: file.mtimeMs,
2864
+ sizeBytes: file.sizeBytes
2865
+ });
2866
+ out.push(meta);
2867
+ } catch {
2868
+ }
2869
+ }
2870
+ out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
2871
+ if (opts.limit !== void 0)
2872
+ return out.slice(0, opts.limit);
2873
+ return out;
2874
+ }
2875
+ async function getGeminiSession(id, opts = {}) {
2876
+ const root = opts.root ?? DEFAULT_GEMINI_ROOT;
2877
+ const files = await listSessionFiles(root);
2878
+ let chosen;
2879
+ for (const file of files) {
2880
+ if (file.filenameId === id || id.startsWith(file.filenameId)) {
2881
+ chosen = file;
2882
+ break;
2883
+ }
2884
+ }
2885
+ if (!chosen) {
2886
+ for (const file of files) {
2887
+ const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
2888
+ if (meta2.id === id) {
2889
+ chosen = file;
2890
+ break;
2891
+ }
2892
+ }
2893
+ }
2894
+ if (!chosen)
2895
+ return null;
2896
+ const cached = detailCache3.get(chosen.filePath);
2897
+ if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
2898
+ return cached.detail;
2899
+ }
2900
+ const { meta, events } = await parseSession(chosen);
2901
+ const detail = { ...meta, events };
2902
+ detailCache3.set(chosen.filePath, {
2903
+ detail,
2904
+ mtimeMs: chosen.mtimeMs,
2905
+ sizeBytes: chosen.sizeBytes
2906
+ });
2907
+ return detail;
2908
+ }
2909
+ function geminiSessionLocalDay(meta) {
2910
+ if (!meta.firstTimestamp)
2911
+ return void 0;
2912
+ const ms = Date.parse(meta.firstTimestamp);
2913
+ return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
2914
+ }
2915
+ var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
2916
+ var init_gemini = __esm({
2917
+ "../parser/dist/gemini.js"() {
2918
+ "use strict";
2919
+ init_analytics();
2920
+ init_user_input();
2921
+ DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
2922
+ GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
2923
+ SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
2924
+ IDLE_GAP_MS2 = 3 * 60 * 1e3;
2925
+ projectsCache = null;
2926
+ metaCache3 = /* @__PURE__ */ new Map();
2927
+ detailCache3 = /* @__PURE__ */ new Map();
2928
+ }
2929
+ });
2930
+
2345
2931
  // ../parser/dist/fs.js
2346
2932
  var fs_exports = {};
2347
2933
  __export(fs_exports, {
2348
2934
  DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
2935
+ DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
2349
2936
  DEFAULT_ROOT: () => DEFAULT_ROOT,
2350
2937
  agentSources: () => agentSources,
2351
2938
  buildCalibrationCurve: () => buildCalibrationCurve,
@@ -2354,14 +2941,17 @@ __export(fs_exports, {
2354
2941
  codexSessionLocalDay: () => codexSessionLocalDay,
2355
2942
  decodeProjectName: () => decodeProjectName,
2356
2943
  findTeamLead: () => findTeamLead,
2944
+ geminiSessionLocalDay: () => geminiSessionLocalDay,
2357
2945
  getAgentSource: () => getAgentSource,
2358
2946
  getAnySession: () => getAnySession,
2359
2947
  getCodexSession: () => getCodexSession,
2948
+ getGeminiSession: () => getGeminiSession,
2360
2949
  getLatestCodexUsage: () => getLatestCodexUsage,
2361
2950
  getSession: () => getSession,
2362
2951
  invalidateFile: () => invalidateFile,
2363
2952
  listAllSessions: () => listAllSessions,
2364
2953
  listCodexSessions: () => listCodexSessions,
2954
+ listGeminiSessions: () => listGeminiSessions,
2365
2955
  listProjects: () => listProjects,
2366
2956
  listSessions: () => listSessions,
2367
2957
  loadCalibrationCurve: () => loadCalibrationCurve,
@@ -2373,15 +2963,16 @@ __export(fs_exports, {
2373
2963
  sessionIdFromFileName: () => sessionIdFromFileName,
2374
2964
  walkJsonlFiles: () => walkJsonlFiles
2375
2965
  });
2376
- import { promises as fs3 } from "node:fs";
2377
- import os3 from "node:os";
2378
- import path3 from "node:path";
2966
+ import { promises as fs4 } from "node:fs";
2967
+ import os4 from "node:os";
2968
+ import path4 from "node:path";
2379
2969
  function cacheStats() {
2380
2970
  return claudeCodeCacheStats();
2381
2971
  }
2382
2972
  function clearCaches() {
2383
2973
  clearClaudeCodeCaches();
2384
2974
  clearCodexCaches();
2975
+ clearGeminiCaches();
2385
2976
  }
2386
2977
  function invalidateFile(fullPath) {
2387
2978
  invalidateClaudeCodeFile(fullPath);
@@ -2410,7 +3001,7 @@ async function getAnySession(id) {
2410
3001
  async function loadUsageByDay(start, end) {
2411
3002
  let raw;
2412
3003
  try {
2413
- raw = await fs3.readFile(USAGE_LOG, "utf8");
3004
+ raw = await fs4.readFile(USAGE_LOG, "utf8");
2414
3005
  } catch {
2415
3006
  return { by_day: [] };
2416
3007
  }
@@ -2455,7 +3046,7 @@ async function loadUsageByDay(start, end) {
2455
3046
  async function loadCalibrationSnapshots() {
2456
3047
  let raw;
2457
3048
  try {
2458
- raw = await fs3.readFile(USAGE_LOG, "utf8");
3049
+ raw = await fs4.readFile(USAGE_LOG, "utf8");
2459
3050
  } catch {
2460
3051
  return [];
2461
3052
  }
@@ -2613,7 +3204,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
2613
3204
  ]);
2614
3205
  return buildCalibrationCurve(events, snapshots, tier, granularityMin);
2615
3206
  }
2616
- var codexSource, agentSources, USAGE_LOG;
3207
+ var codexSource, geminiSource, agentSources, USAGE_LOG;
2617
3208
  var init_fs = __esm({
2618
3209
  "../parser/dist/fs.js"() {
2619
3210
  "use strict";
@@ -2622,8 +3213,10 @@ var init_fs = __esm({
2622
3213
  init_calibration();
2623
3214
  init_claude_code();
2624
3215
  init_codex();
3216
+ init_gemini();
2625
3217
  init_claude_code();
2626
3218
  init_codex();
3219
+ init_gemini();
2627
3220
  codexSource = {
2628
3221
  ...CODEX_METADATA,
2629
3222
  defaultRoot: DEFAULT_CODEX_ROOT,
@@ -2645,8 +3238,18 @@ var init_fs = __esm({
2645
3238
  };
2646
3239
  }
2647
3240
  };
2648
- agentSources = [claudeCodeSource, codexSource];
2649
- USAGE_LOG = path3.join(os3.homedir(), ".cclens", "usage.jsonl");
3241
+ geminiSource = {
3242
+ ...GEMINI_METADATA,
3243
+ defaultRoot: DEFAULT_GEMINI_ROOT,
3244
+ async listSessions(opts) {
3245
+ return listGeminiSessions(opts);
3246
+ },
3247
+ async getSession(id) {
3248
+ return getGeminiSession(id);
3249
+ }
3250
+ };
3251
+ agentSources = [claudeCodeSource, codexSource, geminiSource];
3252
+ USAGE_LOG = path4.join(os4.homedir(), ".cclens", "usage.jsonl");
2650
3253
  }
2651
3254
  });
2652
3255
 
@@ -2815,7 +3418,13 @@ function buildPresentation(events) {
2815
3418
  return false;
2816
3419
  if (e.role === "user") {
2817
3420
  const txt = firstTextOfBlocks(e.blocks) ?? "";
2818
- if (SKILL_CONTENT_RE.test(txt))
3421
+ if (e.blocks.length === 0 || !txt.trim())
3422
+ return false;
3423
+ if (SLASH_COMMAND_RE.test(txt))
3424
+ return true;
3425
+ if (TASK_NOTIFICATION_RE.test(txt))
3426
+ return true;
3427
+ if (isFrameworkInjectedUserInput(txt))
2819
3428
  return false;
2820
3429
  }
2821
3430
  return true;
@@ -2943,13 +3552,13 @@ function buildPresentation(events) {
2943
3552
  }
2944
3553
  return rows;
2945
3554
  }
2946
- var INTERRUPT_RE, RATE_LIMIT_RE, SKILL_CONTENT_RE, SLASH_COMMAND_RE, TASK_NOTIFICATION_RE;
3555
+ var INTERRUPT_RE, RATE_LIMIT_RE, SLASH_COMMAND_RE, TASK_NOTIFICATION_RE;
2947
3556
  var init_presentation = __esm({
2948
3557
  "../parser/dist/presentation.js"() {
2949
3558
  "use strict";
3559
+ init_user_input();
2950
3560
  INTERRUPT_RE = /\[request interrupted|interrupted by user/i;
2951
3561
  RATE_LIMIT_RE = /rate.?limit|overloaded_error|api error|Error sending message/i;
2952
- SKILL_CONTENT_RE = /^Base directory for this skill:/;
2953
3562
  SLASH_COMMAND_RE = /<command-name>(\/[^<\s]+)<\/command-name>(?:[\s\S]*?<command-args>([\s\S]*?)<\/command-args>)?/;
2954
3563
  TASK_NOTIFICATION_RE = /<task-notification>/;
2955
3564
  }
@@ -3051,6 +3660,7 @@ var dist_exports = {};
3051
3660
  __export(dist_exports, {
3052
3661
  CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
3053
3662
  CODEX_METADATA: () => CODEX_METADATA,
3663
+ GEMINI_METADATA: () => GEMINI_METADATA,
3054
3664
  PRICES: () => PRICES,
3055
3665
  RATE_PER_PCT: () => RATE_PER_PCT,
3056
3666
  RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
@@ -3082,6 +3692,7 @@ __export(dist_exports, {
3082
3692
  groupSnapsByCycle: () => groupSnapsByCycle,
3083
3693
  highLevelMetrics: () => highLevelMetrics,
3084
3694
  isAgentKind: () => isAgentKind,
3695
+ isFrameworkInjectedUserInput: () => isFrameworkInjectedUserInput,
3085
3696
  last4CompletedWeeks: () => last4CompletedWeeks,
3086
3697
  modelFamily: () => modelFamily,
3087
3698
  parseTranscript: () => parseTranscript,
@@ -3092,6 +3703,7 @@ __export(dist_exports, {
3092
3703
  rowPrimaryIndex: () => rowPrimaryIndex,
3093
3704
  sessionAirTimeMs: () => sessionAirTimeMs,
3094
3705
  sessionDay: () => sessionDay,
3706
+ stripFrameworkBoilerplate: () => stripFrameworkBoilerplate,
3095
3707
  summarizeBursts: () => summarizeBursts,
3096
3708
  toLocalDay: () => toLocalDay,
3097
3709
  userSoloRate: () => userSoloRate,
@@ -3102,6 +3714,7 @@ var init_dist = __esm({
3102
3714
  "use strict";
3103
3715
  init_types();
3104
3716
  init_parser();
3717
+ init_user_input();
3105
3718
  init_presentation();
3106
3719
  init_analytics();
3107
3720
  init_aggregate();
@@ -3144,9 +3757,9 @@ function readFromCredentialsFile() {
3144
3757
  join(homedir(), ".claude", ".credentials.json"),
3145
3758
  join(homedir(), ".config", "claude", "credentials.json")
3146
3759
  ];
3147
- for (const path4 of candidates) {
3760
+ for (const path5 of candidates) {
3148
3761
  try {
3149
- const blob = readFileSync(path4, "utf8");
3762
+ const blob = readFileSync(path5, "utf8");
3150
3763
  const creds = extractCredentials(blob);
3151
3764
  if (creds) return creds;
3152
3765
  } catch {
@@ -3274,9 +3887,13 @@ function readSnapshots(filePath) {
3274
3887
  }
3275
3888
  return snapshots;
3276
3889
  }
3277
- function latestSnapshot(filePath) {
3890
+ function latestClaudeCodeSnapshot(filePath) {
3278
3891
  const all = readSnapshots(filePath);
3279
- return all.length > 0 ? all[all.length - 1] : null;
3892
+ for (let i = all.length - 1; i >= 0; i--) {
3893
+ const s = all[i];
3894
+ if (!s.agent || s.agent === "claude-code") return s;
3895
+ }
3896
+ return null;
3280
3897
  }
3281
3898
 
3282
3899
  // src/daemon-worker.ts
@@ -3318,7 +3935,7 @@ init_dist();
3318
3935
  import { randomUUID } from "node:crypto";
3319
3936
  var SNAPSHOT_FRESHNESS_MS = 10 * 60 * 1e3;
3320
3937
  function readLatestUsageSnapshotForWire(filePath, nowMs = Date.now()) {
3321
- const raw = latestSnapshot(filePath);
3938
+ const raw = latestClaudeCodeSnapshot(filePath);
3322
3939
  if (!raw) return null;
3323
3940
  const capturedMs = Date.parse(raw.captured_at);
3324
3941
  if (Number.isNaN(capturedMs)) return null;
@@ -3739,17 +4356,21 @@ var PROMPT_FRAME_ORIGIN = {
3739
4356
  };
3740
4357
 
3741
4358
  // ../entries/dist/signals.js
4359
+ init_dist();
3742
4360
  var TEAMMATE_RE = /^<teammate-message\b/;
3743
4361
  var SKILL_LOAD_RE = /^Base directory for this skill:/;
3744
4362
  var SLASH_COMMAND_RE2 = /^<command-name>|^<local-command-stdout>/;
3745
4363
  function classifyUserInputSource(text) {
3746
4364
  if (!text)
3747
4365
  return "human";
3748
- if (TEAMMATE_RE.test(text))
4366
+ const stripped = stripFrameworkBoilerplate(text);
4367
+ if (!stripped)
4368
+ return "system_instruction";
4369
+ if (TEAMMATE_RE.test(stripped))
3749
4370
  return "teammate";
3750
- if (SKILL_LOAD_RE.test(text))
4371
+ if (SKILL_LOAD_RE.test(stripped))
3751
4372
  return "skill_load";
3752
- if (SLASH_COMMAND_RE2.test(text))
4373
+ if (SLASH_COMMAND_RE2.test(stripped))
3753
4374
  return "slash_command";
3754
4375
  return "human";
3755
4376
  }
@@ -3964,7 +4585,7 @@ function viewEvent(ev) {
3964
4585
  cwd: rawCwd
3965
4586
  };
3966
4587
  }
3967
- var IDLE_GAP_MS2 = 3 * 60 * 1e3;
4588
+ var IDLE_GAP_MS3 = 3 * 60 * 1e3;
3968
4589
  var INTERRUPT_RE2 = /\[request interrupted|interrupted by user/i;
3969
4590
  var PR_TITLE_RE = /--title\s+["']([^"']+)["']/;
3970
4591
  var BASH_CHAIN_SPLIT_RE = /\|\||&&|;|\|/;
@@ -4076,7 +4697,7 @@ function closeTurn(t, closed, cwd) {
4076
4697
  let active = 0;
4077
4698
  for (let i = 1; i < ts.length; i++) {
4078
4699
  const dt = ts[i] - ts[i - 1];
4079
- if (dt < IDLE_GAP_MS2)
4700
+ if (dt < IDLE_GAP_MS3)
4080
4701
  active += dt;
4081
4702
  }
4082
4703
  closed.push({
@@ -4138,7 +4759,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
4138
4759
  closeTurn(cur, closed, eventCwd);
4139
4760
  }
4140
4761
  cur = newTurn(tsMs, text);
4141
- if (!firstUser && text && !text.startsWith("<command-name>")) {
4762
+ if (!firstUser && text && classifyUserInputSource(text) === "human") {
4142
4763
  firstUser = text;
4143
4764
  }
4144
4765
  } else {
@@ -4252,7 +4873,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
4252
4873
  let activeMs2 = 0;
4253
4874
  for (let i = 1; i < tsSorted.length; i++) {
4254
4875
  const dt = tsSorted[i] - tsSorted[i - 1];
4255
- if (dt < IDLE_GAP_MS2)
4876
+ if (dt < IDLE_GAP_MS3)
4256
4877
  activeMs2 += dt;
4257
4878
  }
4258
4879
  const tsSortedStrings = dayEvents.map((e) => e.timestamp).filter((t) => !!t).sort();
@@ -4382,7 +5003,13 @@ function buildEntries(sessionDetail) {
4382
5003
  return classifyUserInputSource(text) === "human";
4383
5004
  }).map((ev) => blockText(ev.blocks) || ev.preview || "").join("\n");
4384
5005
  const satisfaction_signals = countSatisfactionSignals(humanText);
4385
- const user_input_sources = { human: 0, teammate: 0, skill_load: 0, slash_command: 0 };
5006
+ const user_input_sources = {
5007
+ human: 0,
5008
+ teammate: 0,
5009
+ skill_load: 0,
5010
+ slash_command: 0,
5011
+ system_instruction: 0
5012
+ };
4386
5013
  for (const ev of dayEvents) {
4387
5014
  const v = viewEvent(ev);
4388
5015
  if (v.rawType !== "user")
@@ -5267,8 +5894,8 @@ function getErrorMap() {
5267
5894
 
5268
5895
  // ../../node_modules/zod/v3/helpers/parseUtil.js
5269
5896
  var makeIssue = (params) => {
5270
- const { data, path: path4, errorMaps, issueData } = params;
5271
- const fullPath = [...path4, ...issueData.path || []];
5897
+ const { data, path: path5, errorMaps, issueData } = params;
5898
+ const fullPath = [...path5, ...issueData.path || []];
5272
5899
  const fullIssue = {
5273
5900
  ...issueData,
5274
5901
  path: fullPath
@@ -5384,11 +6011,11 @@ var errorUtil;
5384
6011
 
5385
6012
  // ../../node_modules/zod/v3/types.js
5386
6013
  var ParseInputLazyPath = class {
5387
- constructor(parent, value, path4, key) {
6014
+ constructor(parent, value, path5, key) {
5388
6015
  this._cachedPath = [];
5389
6016
  this.parent = parent;
5390
6017
  this.data = value;
5391
- this._path = path4;
6018
+ this._path = path5;
5392
6019
  this._key = key;
5393
6020
  }
5394
6021
  get path() {
@@ -8958,15 +9585,15 @@ function newRunId(kind) {
8958
9585
  function tracePath(runId) {
8959
9586
  return join9(RUNS_DIR, `${runId}.jsonl`);
8960
9587
  }
8961
- function safeAppend(path4, line) {
9588
+ function safeAppend(path5, line) {
8962
9589
  try {
8963
- appendFileSync3(path4, line);
9590
+ appendFileSync3(path5, line);
8964
9591
  } catch {
8965
9592
  }
8966
9593
  }
8967
- function safeWrite(path4, line) {
9594
+ function safeWrite(path5, line) {
8968
9595
  try {
8969
- writeFileSync7(path4, line);
9596
+ writeFileSync7(path5, line);
8970
9597
  } catch {
8971
9598
  }
8972
9599
  }
@@ -9602,7 +10229,7 @@ function rollupOutcomeDay(entries) {
9602
10229
  return "exploratory";
9603
10230
  return "trivial";
9604
10231
  }
9605
- function truncate3(s, max) {
10232
+ function truncate4(s, max) {
9606
10233
  if (s.length <= max)
9607
10234
  return s;
9608
10235
  return s.slice(0, max - 1).trimEnd() + "\u2026";
@@ -9658,7 +10285,7 @@ function computeDaySignals(entries) {
9658
10285
  type,
9659
10286
  count: v.count,
9660
10287
  sample_description: v.sample_description,
9661
- sample_prompt_preview: truncate3(v.sample_prompt_preview, 200)
10288
+ sample_prompt_preview: truncate4(v.sample_prompt_preview, 200)
9662
10289
  }));
9663
10290
  const frameCounts = /* @__PURE__ */ new Map();
9664
10291
  for (const s of signalsList) {
@@ -9677,7 +10304,7 @@ function computeDaySignals(entries) {
9677
10304
  if ((e.first_user ?? "").length > 0)
9678
10305
  verbosity_distribution[s.verbosity] += 1;
9679
10306
  for (const ref of s.external_refs) {
9680
- external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate3(ref.preview, 200) });
10307
+ external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate4(ref.preview, 200) });
9681
10308
  }
9682
10309
  const ints = e.numbers.interrupts ?? 0;
9683
10310
  interrupts += ints;
@@ -10520,7 +11147,7 @@ function computeInteractionModes(entries) {
10520
11147
  date: entry.local_day,
10521
11148
  project_display: prettyProject3(entry.project),
10522
11149
  type: sa.type,
10523
- prompt_preview: truncate4(sa.prompt_preview, 200)
11150
+ prompt_preview: truncate5(sa.prompt_preview, 200)
10524
11151
  });
10525
11152
  }
10526
11153
  const skillExamples = [];
@@ -10537,7 +11164,7 @@ function computeInteractionModes(entries) {
10537
11164
  skillExamples.push({
10538
11165
  date: e.local_day,
10539
11166
  skill,
10540
- first_user_preview: truncate4(e.first_user, 200)
11167
+ first_user_preview: truncate5(e.first_user, 200)
10541
11168
  });
10542
11169
  }
10543
11170
  }
@@ -10554,7 +11181,7 @@ function computeInteractionModes(entries) {
10554
11181
  project_display: prettyProject3(longestTurnEntry.project),
10555
11182
  active_min: longestTurnEntry.numbers.active_min,
10556
11183
  top_tools: longestTurnEntry.top_tools.slice(0, 5),
10557
- first_user_preview: truncate4(longestTurnEntry.first_user, 200)
11184
+ first_user_preview: truncate5(longestTurnEntry.first_user, 200)
10558
11185
  } : null;
10559
11186
  const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
10560
11187
  const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
@@ -10585,7 +11212,7 @@ function computeInteractionModes(entries) {
10585
11212
  }
10586
11213
  };
10587
11214
  }
10588
- function truncate4(s, max) {
11215
+ function truncate5(s, max) {
10589
11216
  if (s.length <= max)
10590
11217
  return s;
10591
11218
  return s.slice(0, max - 1).trimEnd() + "\u2026";
@@ -10642,7 +11269,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
10642
11269
  evidence_subagent = {
10643
11270
  type: sa.type,
10644
11271
  description: sa.description,
10645
- prompt_preview: truncate4(sa.prompt_preview, 200)
11272
+ prompt_preview: truncate5(sa.prompt_preview, 200)
10646
11273
  };
10647
11274
  }
10648
11275
  const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
@@ -10653,7 +11280,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
10653
11280
  outcome: dayOutcome.get(dd.key) ?? null,
10654
11281
  helpfulness: dayHelp.get(dd.key) ?? null,
10655
11282
  evidence_subagent,
10656
- evidence_first_user: repEntry?.first_user ? truncate4(repEntry.first_user, 200) : null,
11283
+ evidence_first_user: repEntry?.first_user ? truncate5(repEntry.first_user, 200) : null,
10657
11284
  day_signature: dd.day_signature ?? null
10658
11285
  };
10659
11286
  });
@@ -10728,7 +11355,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
10728
11355
  date: day,
10729
11356
  session_id: ref.session_id,
10730
11357
  ref_kind: ref.kind,
10731
- preview: truncate4(ref.preview, 200)
11358
+ preview: truncate5(ref.preview, 200)
10732
11359
  });
10733
11360
  }
10734
11361
  total_interrupts += signals.comm_style.steering.interrupts;
@@ -10800,7 +11427,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
10800
11427
  count: v.count,
10801
11428
  days: [...v.days].sort(),
10802
11429
  sample_description: v.sample_description,
10803
- sample_prompt_preview: truncate4(v.sample_prompt_preview, 200)
11430
+ sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
10804
11431
  })),
10805
11432
  threads,
10806
11433
  communication_style: {
@@ -11100,7 +11727,7 @@ var MonthDigestResponseSchema = external_exports.object({
11100
11727
  }).passthrough();
11101
11728
 
11102
11729
  // ../entries/dist/top-sessions.js
11103
- var IDLE_GAP_MS3 = 3 * 60 * 1e3;
11730
+ var IDLE_GAP_MS4 = 3 * 60 * 1e3;
11104
11731
  var LONG_AUTONOMOUS_MIN = 20;
11105
11732
  var N_USER = 150;
11106
11733
  var N_FIRST_AGENT = 150;
@@ -11131,7 +11758,7 @@ function activeMs(timestamps) {
11131
11758
  let active = 0;
11132
11759
  for (let i = 1; i < ts.length; i++) {
11133
11760
  const dt = ts[i] - ts[i - 1];
11134
- if (dt < IDLE_GAP_MS3)
11761
+ if (dt < IDLE_GAP_MS4)
11135
11762
  active += dt;
11136
11763
  }
11137
11764
  return active;
@@ -11305,7 +11932,7 @@ function buildSessionSlice(entry, events, daySignature) {
11305
11932
  let intEnd = sortedTs[0];
11306
11933
  for (let i = 1; i < sortedTs.length; i++) {
11307
11934
  const dt = sortedTs[i] - intEnd;
11308
- if (dt >= IDLE_GAP_MS3) {
11935
+ if (dt >= IDLE_GAP_MS4) {
11309
11936
  intervals.push({
11310
11937
  start_min: fmtMin(intStart - sliceStartMs),
11311
11938
  end_min: fmtMin(intEnd - sliceStartMs)