fleetlens 0.11.2 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/app-path-routes-manifest.json +3 -0
  3. package/app/apps/web/.next/build-manifest.json +3 -3
  4. package/app/apps/web/.next/prerender-manifest.json +3 -3
  5. package/app/apps/web/.next/routes-manifest.json +22 -0
  6. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  7. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  8. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/app/apps/web/.next/server/app/_not-found/page.js +2 -1
  14. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/app/apps/web/.next/server/app/api/ask/route.js +1 -1
  17. package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
  18. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +2 -2
  19. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  20. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +2 -2
  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 +1 -1
  23. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  24. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +2 -2
  25. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  26. package/app/apps/web/.next/server/app/api/digest/week-index/route.js +1 -1
  27. package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/api/events/route.js +1 -1
  29. package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
  30. package/app/apps/web/.next/server/app/api/jobs/route.js +1 -1
  31. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
  32. package/app/apps/web/.next/server/app/api/pdf/[key]/route/app-paths-manifest.json +3 -0
  33. package/app/apps/web/.next/server/app/api/pdf/[key]/route/build-manifest.json +9 -0
  34. package/app/apps/web/.next/server/app/api/pdf/[key]/route/server-reference-manifest.json +4 -0
  35. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js +10 -0
  36. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.map +5 -0
  37. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -0
  38. package/app/apps/web/.next/server/app/api/pdf/[key]/route_client-reference-manifest.js +3 -0
  39. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js +1 -1
  40. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  41. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js +1 -1
  42. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  43. package/app/apps/web/.next/server/app/api/runs/route.js +1 -1
  44. package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
  45. package/app/apps/web/.next/server/app/api/settings/route.js +1 -1
  46. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  47. package/app/apps/web/.next/server/app/api/team-config/route.js +1 -1
  48. package/app/apps/web/.next/server/app/api/team-config/route.js.nft.json +1 -1
  49. package/app/apps/web/.next/server/app/api/workflow-agent/route/app-paths-manifest.json +3 -0
  50. package/app/apps/web/.next/server/app/api/workflow-agent/route/build-manifest.json +9 -0
  51. package/app/apps/web/.next/server/app/api/workflow-agent/route/server-reference-manifest.json +4 -0
  52. package/app/apps/web/.next/server/app/api/workflow-agent/route.js +7 -0
  53. package/app/apps/web/.next/server/app/api/workflow-agent/route.js.map +5 -0
  54. package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -0
  55. package/app/apps/web/.next/server/app/api/workflow-agent/route_client-reference-manifest.js +3 -0
  56. package/app/apps/web/.next/server/app/changelog/page.js +2 -1
  57. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
  58. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  59. package/app/apps/web/.next/server/app/day/[date]/page.js +2 -1
  60. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  61. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  62. package/app/apps/web/.next/server/app/day/page.js +2 -1
  63. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  64. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  65. package/app/apps/web/.next/server/app/digest/[date]/page.js +2 -1
  66. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  67. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  68. package/app/apps/web/.next/server/app/digest/page.js +2 -1
  69. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  70. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  71. package/app/apps/web/.next/server/app/insights/[key]/page.js +2 -1
  72. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  73. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  74. package/app/apps/web/.next/server/app/insights/page.js +2 -1
  75. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  76. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  77. package/app/apps/web/.next/server/app/page.js +2 -1
  78. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  79. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  80. package/app/apps/web/.next/server/app/parallelism/page.js +2 -1
  81. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  82. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  83. package/app/apps/web/.next/server/app/print/[key]/page/app-paths-manifest.json +3 -0
  84. package/app/apps/web/.next/server/app/print/[key]/page/build-manifest.json +17 -0
  85. package/app/apps/web/.next/server/app/print/[key]/page/next-font-manifest.json +6 -0
  86. package/app/apps/web/.next/server/app/print/[key]/page/react-loadable-manifest.json +1 -0
  87. package/app/apps/web/.next/server/app/print/[key]/page/server-reference-manifest.json +4 -0
  88. package/app/apps/web/.next/server/app/print/[key]/page.js +19 -0
  89. package/app/apps/web/.next/server/app/print/[key]/page.js.map +5 -0
  90. package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -0
  91. package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +3 -0
  92. package/app/apps/web/.next/server/app/projects/[slug]/page.js +2 -1
  93. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  94. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  95. package/app/apps/web/.next/server/app/projects/page.js +2 -1
  96. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  97. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  98. package/app/apps/web/.next/server/app/runs/page.js +2 -1
  99. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  100. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  101. package/app/apps/web/.next/server/app/sessions/[id]/page.js +2 -1
  102. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  103. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  104. package/app/apps/web/.next/server/app/sessions/page.js +2 -1
  105. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  106. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  107. package/app/apps/web/.next/server/app/settings/page.js +2 -1
  108. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  109. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  110. package/app/apps/web/.next/server/app/team/page.js +2 -1
  111. package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
  112. package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
  113. package/app/apps/web/.next/server/app/usage/page.js +2 -1
  114. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  115. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  116. package/app/apps/web/.next/server/app-paths-manifest.json +3 -0
  117. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0455vu3._.js +2 -2
  118. package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0_8zh-i._.js → [root-of-the-server]__04j3tng._.js} +2 -2
  119. package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0jprdks._.js → [root-of-the-server]__0cnh3k4._.js} +2 -2
  120. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0e.f-t.._.js +3 -0
  121. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0kc9e1n._.js +3 -0
  122. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0y5p73y._.js +3 -0
  123. package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0ej_p3s._.js → [root-of-the-server]__132eosx._.js} +2 -2
  124. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_pdf_[key]_route_actions_0intcw9.js +3 -0
  125. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_workflow-agent_route_actions_0gxw9tv.js +3 -0
  126. package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +1 -1
  127. package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +3 -0
  128. package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +3 -0
  129. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04eq6z2._.js +1 -1
  130. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04il6m2._.js +11 -0
  131. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0exckd4._.js +1 -1
  132. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0n-ax-5._.js +3 -0
  133. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o03ymy._.js +2 -2
  134. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0rvzdnx._.js +1 -1
  135. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0z7mg0b._.js +1 -1
  136. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +12 -0
  137. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__136-0me._.js +8 -0
  138. package/app/apps/web/.next/server/chunks/ssr/_0cgg5zi._.js +3 -0
  139. package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.js +1 -1
  140. package/app/apps/web/.next/server/chunks/ssr/_0kajk31._.js +3 -0
  141. package/app/apps/web/.next/server/chunks/ssr/_0w.cv64._.js +8 -0
  142. package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
  143. package/app/apps/web/.next/server/chunks/ssr/apps_web_0.mu7c7._.js +1 -1
  144. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_print_[key]_page_actions_0_ygul-.js +3 -0
  145. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_01d-iwx._.js +6 -0
  146. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_week-digest_tsx_0c9ha31._.js +3 -0
  147. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0k0tl52._.js +3 -0
  148. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +3 -0
  149. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +3 -0
  150. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_07orc4m.js +4 -0
  151. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_12.endt._.js +1 -1
  152. package/app/apps/web/.next/server/edge/chunks/[root-of-the-server]__0.sx~id._.js +11 -0
  153. package/app/apps/web/.next/server/edge/chunks/node_modules_next_dist_esm_build_templates_edge-wrapper_0p1t1z8.js +3 -0
  154. package/app/apps/web/.next/server/edge/chunks/turbopack-node_modules_next_dist_esm_build_templates_edge-wrapper_0mw-sqe.js +3 -0
  155. package/app/apps/web/.next/server/functions-config-manifest.json +4 -1
  156. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  157. package/app/apps/web/.next/server/middleware-manifest.json +30 -2
  158. package/app/apps/web/.next/server/pages/500.html +1 -1
  159. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  160. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  161. package/app/apps/web/.next/static/chunks/00xkqnvk4-d1-.js +10 -0
  162. package/app/apps/web/.next/static/chunks/03_7wmpodz36t.js +1 -0
  163. package/app/apps/web/.next/static/chunks/0716x58e1_2c5.js +1 -0
  164. package/app/apps/web/.next/static/chunks/0nnjldasalwdu.js +4 -0
  165. package/app/apps/web/.next/static/chunks/0okg13phslr1..js +4 -0
  166. package/app/apps/web/.next/static/chunks/0vf-3rauafbek.js +6 -0
  167. package/app/apps/web/.next/static/chunks/0vl27-vjob2_9.js +6 -0
  168. package/app/apps/web/.next/static/chunks/0yo458-7577lr.js +1 -0
  169. package/app/apps/web/.next/static/chunks/14bjditmmrn7l.js +1 -0
  170. package/app/apps/web/.next/static/rrY-ephAArv8tjJOXD622/_clientMiddlewareManifest.js +6 -0
  171. package/app/apps/web/app/api/events/route.ts +50 -2
  172. package/app/apps/web/app/api/pdf/[key]/route.ts +199 -0
  173. package/app/apps/web/app/api/workflow-agent/route.ts +27 -0
  174. package/app/apps/web/app/insights/[key]/page.tsx +4 -1
  175. package/app/apps/web/app/layout.tsx +23 -1
  176. package/app/apps/web/app/page.tsx +24 -1
  177. package/app/apps/web/app/print/[key]/page.tsx +91 -0
  178. package/app/apps/web/app/projects/[slug]/page.tsx +6 -7
  179. package/app/apps/web/app/projects/page.tsx +2 -3
  180. package/app/apps/web/app/sessions/[id]/session-view.tsx +1297 -19
  181. package/app/apps/web/app/sessions/sessions-grid.tsx +10 -1
  182. package/app/apps/web/components/dashboard-view.tsx +2 -1
  183. package/app/apps/web/components/export-pdf-button.tsx +76 -0
  184. package/app/apps/web/components/month-digest-view.tsx +10 -0
  185. package/app/apps/web/components/week-digest-view.tsx +10 -0
  186. package/app/apps/web/lib/changelog-data.generated.ts +1 -1
  187. package/app/apps/web/lib/entries-index.ts +5 -4
  188. package/app/apps/web/lib/find-chrome.ts +71 -0
  189. package/app/apps/web/middleware.ts +22 -0
  190. package/app/apps/web/package.json +1 -1
  191. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  192. package/dist/daemon-worker.js +1716 -281
  193. package/dist/index.js +1617 -195
  194. package/package.json +1 -1
  195. package/app/apps/web/.next/server/chunks/packages_parser_dist_04rh1zd._.js +0 -3
  196. package/app/apps/web/.next/server/chunks/packages_parser_dist_0ndsxe6._.js +0 -3
  197. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0_xpuh7._.js +0 -3
  198. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d~2~le._.js +0 -8
  199. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +0 -12
  200. package/app/apps/web/.next/server/chunks/ssr/_02s1n-x._.js +0 -8
  201. package/app/apps/web/.next/server/chunks/ssr/_0fjbf--._.js +0 -3
  202. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0ly1xes._.js +0 -6
  203. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0af94gl._.js +0 -3
  204. package/app/apps/web/.next/static/chunks/0.3mqbj24kwtc.js +0 -6
  205. package/app/apps/web/.next/static/chunks/0byz8fqw.exef.js +0 -1
  206. package/app/apps/web/.next/static/chunks/0l3ck.awv~4t7.js +0 -1
  207. package/app/apps/web/.next/static/chunks/0lxuac2v0_gdl.js +0 -6
  208. package/app/apps/web/.next/static/chunks/0m62vx92~0_0d.js +0 -1
  209. package/app/apps/web/.next/static/chunks/0rtba0saz74e1.js +0 -10
  210. package/app/apps/web/.next/static/chunks/0s4eyofh28l~u.js +0 -1
  211. package/app/apps/web/.next/static/chunks/0uev~g~qvbjv9.js +0 -4
  212. package/app/apps/web/.next/static/m6ibRSdAu8jD10VBA2OFH/_clientMiddlewareManifest.js +0 -1
  213. /package/app/apps/web/.next/static/{m6ibRSdAu8jD10VBA2OFH → rrY-ephAArv8tjJOXD622}/_buildManifest.js +0 -0
  214. /package/app/apps/web/.next/static/{m6ibRSdAu8jD10VBA2OFH → rrY-ephAArv8tjJOXD622}/_ssgManifest.js +0 -0
@@ -75,6 +75,16 @@ function findConductorWorkspace(projectName) {
75
75
  const canonicalEndIdx = m.index + m[0].length - workspaceName.length - 1 - trailingSlash;
76
76
  return { canonicalEndIdx, workspaceName };
77
77
  }
78
+ function findSupersetWorkspace(projectName) {
79
+ const idx = projectName.indexOf(SUPERSET_MARKER);
80
+ if (idx < 0)
81
+ return null;
82
+ const segs = projectName.slice(idx + SUPERSET_MARKER.length).split("/").filter(Boolean);
83
+ if (segs.length === 0)
84
+ return null;
85
+ const workspaceName = UUID_SEG_RE.test(segs[0]) ? segs[1] ?? segs[0] : segs[0];
86
+ return { canonical: projectName.slice(0, idx) + SUPERSET_MARKER + workspaceName, workspaceName };
87
+ }
78
88
  function canonicalProjectName(projectName) {
79
89
  const normalized = projectName.replace(/\/{2,}/g, "/");
80
90
  const wt = findWorktreeMarker(normalized);
@@ -83,6 +93,9 @@ function canonicalProjectName(projectName) {
83
93
  const cd = findConductorWorkspace(normalized);
84
94
  if (cd)
85
95
  return normalized.slice(0, cd.canonicalEndIdx);
96
+ const ss = findSupersetWorkspace(normalized);
97
+ if (ss)
98
+ return ss.canonical;
86
99
  return normalized;
87
100
  }
88
101
  function worktreeName(projectName) {
@@ -96,8 +109,16 @@ function worktreeName(projectName) {
96
109
  const cd = findConductorWorkspace(normalized);
97
110
  if (cd)
98
111
  return cd.workspaceName;
112
+ const ss = findSupersetWorkspace(normalized);
113
+ if (ss)
114
+ return ss.workspaceName;
99
115
  return null;
100
116
  }
117
+ function projectRepoName(projectName) {
118
+ const canonical = canonicalProjectName(projectName);
119
+ const segs = canonical.replace(/\/+$/, "").split("/").filter(Boolean);
120
+ return segs[segs.length - 1] || canonical;
121
+ }
101
122
  function makeDay(date) {
102
123
  return {
103
124
  date,
@@ -138,7 +159,19 @@ function dailyActivity(sessions) {
138
159
  };
139
160
  for (const s of sessions) {
140
161
  const startDay = sessionDay(s);
141
- if (startDay) {
162
+ if (s.dailyBreakdown && s.dailyBreakdown.length > 0) {
163
+ for (const d of s.dailyBreakdown) {
164
+ const bucket = touchBucket(d.day);
165
+ bucket.toolCalls += d.toolCalls;
166
+ bucket.turns += d.turns;
167
+ bucket.tokens.input += d.tokens.input;
168
+ bucket.tokens.output += d.tokens.output;
169
+ bucket.tokens.cacheRead += d.tokens.cacheRead;
170
+ bucket.tokens.cacheWrite += d.tokens.cacheWrite;
171
+ }
172
+ if (startDay)
173
+ touchBucket(startDay).durationMs += s.durationMs ?? 0;
174
+ } else if (startDay) {
142
175
  const bucket = touchBucket(startDay);
143
176
  bucket.toolCalls += s.toolCallCount ?? 0;
144
177
  bucket.turns += s.turnCount ?? 0;
@@ -148,31 +181,30 @@ function dailyActivity(sessions) {
148
181
  bucket.tokens.cacheWrite += s.totalUsage.cacheWrite;
149
182
  bucket.durationMs += s.durationMs ?? 0;
150
183
  }
184
+ const presenceDays = /* @__PURE__ */ new Set();
151
185
  const segments = s.activeSegments;
152
186
  if (segments && segments.length > 0) {
153
- const touchedDays = /* @__PURE__ */ new Set();
154
187
  for (const seg of segments) {
155
188
  let cur = seg.startMs;
156
189
  while (cur < seg.endMs) {
157
190
  const day = toLocalDay(cur);
158
- touchedDays.add(day);
191
+ presenceDays.add(day);
159
192
  const d = new Date(cur);
160
193
  d.setHours(24, 0, 0, 0);
161
194
  const dayEndMs = Math.min(d.getTime(), seg.endMs);
162
- const bucket = touchBucket(day);
163
- bucket.airTimeMs += dayEndMs - cur;
195
+ touchBucket(day).airTimeMs += dayEndMs - cur;
164
196
  cur = dayEndMs;
165
197
  }
166
198
  }
167
- for (const day of touchedDays) {
168
- const bucket = touchBucket(day);
169
- bucket.sessions++;
170
- }
171
199
  } else if (startDay) {
172
- const bucket = touchBucket(startDay);
173
- bucket.sessions++;
174
- bucket.airTimeMs += s.airTimeMs ?? 0;
200
+ presenceDays.add(startDay);
201
+ touchBucket(startDay).airTimeMs += s.airTimeMs ?? 0;
175
202
  }
203
+ if (s.dailyBreakdown)
204
+ for (const d of s.dailyBreakdown)
205
+ presenceDays.add(d.day);
206
+ for (const day of presenceDays)
207
+ touchBucket(day).sessions++;
176
208
  }
177
209
  const range = minDay && maxDay ? daysBetween(minDay, maxDay) : [];
178
210
  const out = [];
@@ -517,13 +549,13 @@ function summarizeBursts(bursts) {
517
549
  function groupByProject(sessions) {
518
550
  const map = /* @__PURE__ */ new Map();
519
551
  for (const s of sessions) {
520
- const canonical = canonicalProjectName(s.projectName);
521
- const key = canonical;
552
+ const repo = projectRepoName(s.projectName);
553
+ const key = repo;
522
554
  let cur = map.get(key);
523
555
  if (!cur) {
524
556
  cur = {
525
- projectDir: canonical,
526
- projectName: canonical,
557
+ projectDir: repo,
558
+ projectName: repo,
527
559
  sessions: [],
528
560
  rawProjectDirs: [],
529
561
  worktreeCount: 0,
@@ -565,7 +597,7 @@ function groupByProject(sessions) {
565
597
  }
566
598
  return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
567
599
  }
568
- var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
600
+ var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
569
601
  var init_analytics = __esm({
570
602
  "../parser/dist/analytics.js"() {
571
603
  "use strict";
@@ -576,6 +608,8 @@ var init_analytics = __esm({
576
608
  "/claude/worktrees/"
577
609
  ];
578
610
  CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
611
+ SUPERSET_MARKER = "/.superset/worktrees/";
612
+ UUID_SEG_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
579
613
  PR_CREATE_RE = /gh\s+pr\s+create\b/i;
580
614
  PR_NUMBER_RE = /#(\d+)/;
581
615
  TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
@@ -589,7 +623,7 @@ function getAgentMetadata(kind) {
589
623
  function isAgentKind(s) {
590
624
  return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
591
625
  }
592
- var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
626
+ var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
593
627
  var init_agent_metadata = __esm({
594
628
  "../parser/dist/agent-metadata.js"() {
595
629
  "use strict";
@@ -614,10 +648,26 @@ var init_agent_metadata = __esm({
614
648
  accentColor: "rgb(124, 92, 246)",
615
649
  iconChar: "\u273A"
616
650
  };
651
+ ANTIGRAVITY_METADATA = {
652
+ kind: "antigravity",
653
+ displayName: "Antigravity",
654
+ shortLabel: "Agy",
655
+ accentColor: "rgb(236, 72, 153)",
656
+ iconChar: "\u23C3"
657
+ };
658
+ COWORK_METADATA = {
659
+ kind: "cowork",
660
+ displayName: "Cowork",
661
+ shortLabel: "Cowork",
662
+ accentColor: "rgb(217, 119, 87)",
663
+ iconChar: "\u2318"
664
+ };
617
665
  agentMetadata = [
618
666
  CLAUDE_CODE_METADATA,
619
667
  CODEX_METADATA,
620
- GEMINI_METADATA
668
+ GEMINI_METADATA,
669
+ ANTIGRAVITY_METADATA,
670
+ COWORK_METADATA
621
671
  ];
622
672
  KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
623
673
  }
@@ -1199,9 +1249,31 @@ function parseTranscript(rawLines) {
1199
1249
  let linesAdded = 0;
1200
1250
  let linesRemoved = 0;
1201
1251
  const filesEdited = /* @__PURE__ */ new Set();
1252
+ const perDay = /* @__PURE__ */ new Map();
1253
+ const fallbackDay = startMs !== void 0 ? toLocalDay(startMs) : void 0;
1254
+ const dayBucket = (ts) => {
1255
+ let day;
1256
+ if (ts) {
1257
+ const ms = Date.parse(ts);
1258
+ if (!Number.isNaN(ms))
1259
+ day = toLocalDay(ms);
1260
+ }
1261
+ day = day ?? fallbackDay;
1262
+ if (!day)
1263
+ return void 0;
1264
+ let b = perDay.get(day);
1265
+ if (!b) {
1266
+ b = { toolCalls: 0, turns: 0, tokens: { ...BLANK_USAGE2 } };
1267
+ perDay.set(day, b);
1268
+ }
1269
+ return b;
1270
+ };
1202
1271
  for (const e of events) {
1203
1272
  if (e.role === "tool-call") {
1204
1273
  toolCallCount++;
1274
+ const tcDay = dayBucket(e.timestamp);
1275
+ if (tcDay)
1276
+ tcDay.toolCalls++;
1205
1277
  const toolBlock = e.blocks.find((b) => b && b.type === "tool_use");
1206
1278
  if (toolBlock) {
1207
1279
  const input = toolBlock.input ?? {};
@@ -1238,6 +1310,9 @@ function parseTranscript(rawLines) {
1238
1310
  firstUserPreview = e.teammateMessage ? e.teammateMessage.body : e.preview;
1239
1311
  }
1240
1312
  turnCount++;
1313
+ const turnDay = dayBucket(e.timestamp);
1314
+ if (turnDay)
1315
+ turnDay.turns++;
1241
1316
  lastUserPreview = e.preview;
1242
1317
  }
1243
1318
  }
@@ -1279,6 +1354,14 @@ function parseTranscript(rawLines) {
1279
1354
  totalUsage.output += u.output;
1280
1355
  totalUsage.cacheRead += u.cacheRead;
1281
1356
  totalUsage.cacheWrite += u.cacheWrite;
1357
+ const ts = typeof o.timestamp === "string" ? o.timestamp : void 0;
1358
+ const b = dayBucket(ts);
1359
+ if (b) {
1360
+ b.tokens.input += u.input;
1361
+ b.tokens.output += u.output;
1362
+ b.tokens.cacheRead += u.cacheRead;
1363
+ b.tokens.cacheWrite += u.cacheWrite;
1364
+ }
1282
1365
  }
1283
1366
  }
1284
1367
  }
@@ -1302,6 +1385,7 @@ function parseTranscript(rawLines) {
1302
1385
  lastAgentPreview,
1303
1386
  toolCallCount,
1304
1387
  turnCount,
1388
+ dailyBreakdown: Array.from(perDay.entries()).map(([day, v]) => ({ day, toolCalls: v.toolCalls, turns: v.turns, tokens: v.tokens })).sort((a, b) => a.day.localeCompare(b.day)),
1305
1389
  airTimeMs,
1306
1390
  activeSegments,
1307
1391
  linesAdded,
@@ -1320,6 +1404,7 @@ var init_parser = __esm({
1320
1404
  "../parser/dist/parser.js"() {
1321
1405
  "use strict";
1322
1406
  init_user_input();
1407
+ init_analytics();
1323
1408
  BLANK_USAGE2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
1324
1409
  TEAMMATE_MSG_RE = /^\s*<teammate-message\s+teammate_id="([^"]+)"[^>]*>([\s\S]*?)<\/teammate-message>/;
1325
1410
  }
@@ -1593,7 +1678,7 @@ async function loadCalibrationEvents(root = DEFAULT_ROOT) {
1593
1678
  out.sort((a, b) => a.ts.localeCompare(b.ts));
1594
1679
  return out;
1595
1680
  }
1596
- function aggregateUsageFromLines(lines, seenKeys, usage) {
1681
+ function aggregateUsageFromLines(lines, seenKeys, usage, perDay, fallbackDay) {
1597
1682
  for (const raw of lines) {
1598
1683
  if (!raw || typeof raw !== "object")
1599
1684
  continue;
@@ -1613,35 +1698,131 @@ function aggregateUsageFromLines(lines, seenKeys, usage) {
1613
1698
  const u = m.usage;
1614
1699
  if (u) {
1615
1700
  const toNum = (v) => typeof v === "number" ? v : 0;
1616
- usage.input += toNum(u.input_tokens);
1617
- usage.output += toNum(u.output_tokens);
1618
- usage.cacheRead += toNum(u.cache_read_input_tokens);
1619
- usage.cacheWrite += toNum(u.cache_creation_input_tokens);
1701
+ const inp = toNum(u.input_tokens);
1702
+ const out = toNum(u.output_tokens);
1703
+ const cr = toNum(u.cache_read_input_tokens);
1704
+ const cw = toNum(u.cache_creation_input_tokens);
1705
+ usage.input += inp;
1706
+ usage.output += out;
1707
+ usage.cacheRead += cr;
1708
+ usage.cacheWrite += cw;
1709
+ if (perDay) {
1710
+ let day;
1711
+ const ts = typeof r.timestamp === "string" ? r.timestamp : void 0;
1712
+ if (ts) {
1713
+ const ms = Date.parse(ts);
1714
+ if (!Number.isNaN(ms))
1715
+ day = toLocalDay(ms);
1716
+ }
1717
+ day = day ?? fallbackDay;
1718
+ if (day) {
1719
+ let d = perDay.get(day);
1720
+ if (!d) {
1721
+ d = { ...BLANK_USAGE3 };
1722
+ perDay.set(day, d);
1723
+ }
1724
+ d.input += inp;
1725
+ d.output += out;
1726
+ d.cacheRead += cr;
1727
+ d.cacheWrite += cw;
1728
+ }
1729
+ }
1620
1730
  }
1621
1731
  }
1622
1732
  }
1623
- async function computeSessionUsageWithSubagents(parentLines, projectDirPath, sessionId) {
1733
+ async function computeSessionUsageWithSubagents(parentLines, projectDirPath, sessionId, fallbackDay) {
1624
1734
  const usage = { ...BLANK_USAGE3 };
1625
1735
  const seenKeys = /* @__PURE__ */ new Set();
1626
- aggregateUsageFromLines(parentLines, seenKeys, usage);
1736
+ const perDay = /* @__PURE__ */ new Map();
1737
+ aggregateUsageFromLines(parentLines, seenKeys, usage, perDay, fallbackDay);
1627
1738
  const subagentsDir = path.join(projectDirPath, sessionId, "subagents");
1628
1739
  let entries;
1629
1740
  try {
1630
1741
  entries = await fs.readdir(subagentsDir);
1631
1742
  } catch {
1632
- return usage;
1743
+ return { usage, perDay };
1633
1744
  }
1634
1745
  const jsonlFiles = entries.filter((f) => f.endsWith(".jsonl"));
1635
1746
  if (jsonlFiles.length === 0)
1636
- return usage;
1747
+ return { usage, perDay };
1637
1748
  await Promise.all(jsonlFiles.map(async (f) => {
1638
1749
  try {
1639
1750
  const lines = await readJsonlFile(path.join(subagentsDir, f));
1640
- aggregateUsageFromLines(lines, seenKeys, usage);
1751
+ aggregateUsageFromLines(lines, seenKeys, usage, perDay, fallbackDay);
1752
+ } catch {
1753
+ }
1754
+ }));
1755
+ return { usage, perDay };
1756
+ }
1757
+ function mergeDailyTokens(base, perDayTokens, totalUsage) {
1758
+ const counts = new Map((base ?? []).map((d) => [d.day, d]));
1759
+ const days = /* @__PURE__ */ new Set([...counts.keys(), ...perDayTokens.keys()]);
1760
+ const out = [...days].sort((a, b) => a.localeCompare(b)).map((day) => ({
1761
+ day,
1762
+ toolCalls: counts.get(day)?.toolCalls ?? 0,
1763
+ turns: counts.get(day)?.turns ?? 0,
1764
+ tokens: { ...perDayTokens.get(day) ?? BLANK_USAGE3 }
1765
+ }));
1766
+ if (out.length > 0) {
1767
+ const summed = out.reduce((a, r) => ({
1768
+ input: a.input + r.tokens.input,
1769
+ output: a.output + r.tokens.output,
1770
+ cacheRead: a.cacheRead + r.tokens.cacheRead,
1771
+ cacheWrite: a.cacheWrite + r.tokens.cacheWrite
1772
+ }), { ...BLANK_USAGE3 });
1773
+ const first = out[0].tokens;
1774
+ first.input += totalUsage.input - summed.input;
1775
+ first.output += totalUsage.output - summed.output;
1776
+ first.cacheRead += totalUsage.cacheRead - summed.cacheRead;
1777
+ first.cacheWrite += totalUsage.cacheWrite - summed.cacheWrite;
1778
+ }
1779
+ return out;
1780
+ }
1781
+ async function scanWorkflowAggregate(projectDirPath, sessionId) {
1782
+ const dir = path.join(projectDirPath, sessionId, "workflows");
1783
+ let entries;
1784
+ try {
1785
+ entries = await fs.readdir(dir);
1786
+ } catch {
1787
+ return { workflowCount: 0, spawnedAgentCount: 0, spans: [] };
1788
+ }
1789
+ const jsonFiles = entries.filter((f) => f.startsWith("wf_") && f.endsWith(".json"));
1790
+ if (jsonFiles.length === 0)
1791
+ return { workflowCount: 0, spawnedAgentCount: 0, spans: [] };
1792
+ let spawnedAgentCount = 0;
1793
+ const spans = [];
1794
+ const parsed = await Promise.all(jsonFiles.map(async (f) => {
1795
+ try {
1796
+ const j = JSON.parse(await fs.readFile(path.join(dir, f), "utf8"));
1797
+ if (typeof j.agentCount === "number")
1798
+ spawnedAgentCount += j.agentCount;
1799
+ if (typeof j.startTime === "number" && typeof j.durationMs === "number" && j.durationMs > 0) {
1800
+ spans.push({ startMs: j.startTime, endMs: j.startTime + j.durationMs });
1801
+ }
1802
+ return true;
1641
1803
  } catch {
1804
+ return false;
1642
1805
  }
1643
1806
  }));
1644
- return usage;
1807
+ return { workflowCount: parsed.filter(Boolean).length, spawnedAgentCount, spans };
1808
+ }
1809
+ function foldWorkflowAgentTime(activeSegments, spans) {
1810
+ if (spans.length === 0)
1811
+ return {};
1812
+ const all = [...activeSegments ?? [], ...spans].filter((s) => s.endMs > s.startMs).sort((a, b) => a.startMs - b.startMs);
1813
+ if (all.length === 0)
1814
+ return {};
1815
+ const merged = [{ ...all[0] }];
1816
+ for (let i = 1; i < all.length; i++) {
1817
+ const cur = all[i];
1818
+ const last = merged[merged.length - 1];
1819
+ if (cur.startMs <= last.endMs)
1820
+ last.endMs = Math.max(last.endMs, cur.endMs);
1821
+ else
1822
+ merged.push({ ...cur });
1823
+ }
1824
+ const airTimeMs = merged.reduce((n, s) => n + (s.endMs - s.startMs), 0);
1825
+ return { activeSegments: merged, airTimeMs };
1645
1826
  }
1646
1827
  async function getCachedMeta(f) {
1647
1828
  const cached = metaCache.get(f.fullPath);
@@ -1653,13 +1834,19 @@ async function getCachedMeta(f) {
1653
1834
  const { meta } = parseTranscript(rawLines);
1654
1835
  const sessionId = sessionIdFromFileName(f.fileName);
1655
1836
  const projectDirPath = path.dirname(f.fullPath);
1656
- meta.totalUsage = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId);
1837
+ const fallbackDay = meta.firstTimestamp ? toLocalDay(Date.parse(meta.firstTimestamp)) : void 0;
1838
+ const { usage, perDay: perDayTokens } = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId, fallbackDay);
1839
+ meta.totalUsage = usage;
1840
+ meta.dailyBreakdown = mergeDailyTokens(meta.dailyBreakdown, perDayTokens, usage);
1841
+ const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
1657
1842
  const full = {
1658
1843
  ...meta,
1659
1844
  id: sessionId,
1660
1845
  filePath: f.fullPath,
1661
1846
  projectDir: f.projectDir,
1662
- projectName: meta.cwd ?? decodeProjectName(f.projectDir)
1847
+ projectName: meta.cwd ?? decodeProjectName(f.projectDir),
1848
+ ...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
1849
+ ...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
1663
1850
  };
1664
1851
  metaCache.set(f.fullPath, { meta: full, mtimeMs: f.mtimeMs, sizeBytes: f.sizeBytes });
1665
1852
  return full;
@@ -1675,13 +1862,17 @@ async function getCachedDetail(f) {
1675
1862
  try {
1676
1863
  const rawLines = await readJsonlFile(f.fullPath);
1677
1864
  const { meta, events } = parseTranscript(rawLines);
1865
+ const sessionId = sessionIdFromFileName(f.fileName);
1866
+ const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
1678
1867
  const detail = {
1679
1868
  ...meta,
1680
- id: sessionIdFromFileName(f.fileName),
1869
+ id: sessionId,
1681
1870
  filePath: f.fullPath,
1682
1871
  projectDir: f.projectDir,
1683
1872
  projectName: meta.cwd ?? decodeProjectName(f.projectDir),
1684
- events
1873
+ events,
1874
+ ...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
1875
+ ...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
1685
1876
  };
1686
1877
  detailCache.set(f.fullPath, { detail, mtimeMs: f.mtimeMs, sizeBytes: f.sizeBytes });
1687
1878
  const metaOnly = { ...detail };
@@ -1713,8 +1904,18 @@ async function getSession(id, opts = {}) {
1713
1904
  return detail;
1714
1905
  const sessionStartMs = detail.firstTimestamp ? Date.parse(detail.firstTimestamp) : void 0;
1715
1906
  const subagentsDir = path.join(path.dirname(hit.fullPath), sessionIdFromFileName(hit.fileName), "subagents");
1716
- const subagents = await loadSubagents(subagentsDir, sessionStartMs, detail.events);
1717
- return { ...detail, subagents };
1907
+ const workflowsDir = path.join(path.dirname(hit.fullPath), sessionIdFromFileName(hit.fileName), "workflows");
1908
+ const [subagents, workflows] = await Promise.all([
1909
+ loadSubagents(subagentsDir, sessionStartMs, detail.events),
1910
+ loadWorkflows(workflowsDir, sessionStartMs, detail.events)
1911
+ ]);
1912
+ const spawnedAgentCount = workflows.reduce((n, w) => n + w.agentCount, 0);
1913
+ return {
1914
+ ...detail,
1915
+ subagents,
1916
+ workflows,
1917
+ ...workflows.length > 0 ? { workflowCount: workflows.length, spawnedAgentCount } : {}
1918
+ };
1718
1919
  }
1719
1920
  function summarizeSubagentLines(lines) {
1720
1921
  let startMs;
@@ -1904,6 +2105,248 @@ async function loadSubagents(dir, sessionStartMs, parentEvents) {
1904
2105
  }));
1905
2106
  return runs.filter((r) => r !== null).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
1906
2107
  }
2108
+ async function loadWorkflows(dir, sessionStartMs, parentEvents) {
2109
+ let entries;
2110
+ try {
2111
+ entries = await fs.readdir(dir);
2112
+ } catch {
2113
+ return [];
2114
+ }
2115
+ const jsonFiles = entries.filter((f) => f.startsWith("wf_") && f.endsWith(".json"));
2116
+ if (jsonFiles.length === 0)
2117
+ return [];
2118
+ const dispatches = [];
2119
+ for (const e of parentEvents) {
2120
+ if (e.role !== "tool-call" || e.toolName !== "Workflow")
2121
+ continue;
2122
+ const tsMs = e.timestamp ? Date.parse(e.timestamp) : NaN;
2123
+ if (Number.isNaN(tsMs))
2124
+ continue;
2125
+ for (const b of e.blocks) {
2126
+ if (b?.type !== "tool_use" || b.name !== "Workflow")
2127
+ continue;
2128
+ dispatches.push({ toolUseId: b.id, parentUuid: e.uuid ?? "", tsMs });
2129
+ }
2130
+ }
2131
+ dispatches.sort((a, b) => a.tsMs - b.tsMs);
2132
+ const matchDispatch = (startMs) => {
2133
+ if (startMs === void 0 || dispatches.length === 0)
2134
+ return void 0;
2135
+ const TOLERANCE_MS = 6e4;
2136
+ let before;
2137
+ let beforeDelta = Infinity;
2138
+ let nearest;
2139
+ let nearestDelta = Infinity;
2140
+ for (const d of dispatches) {
2141
+ const delta = Math.abs(startMs - d.tsMs);
2142
+ if (delta > TOLERANCE_MS)
2143
+ continue;
2144
+ if (delta < nearestDelta) {
2145
+ nearest = d;
2146
+ nearestDelta = delta;
2147
+ }
2148
+ if (d.tsMs <= startMs && delta < beforeDelta) {
2149
+ before = d;
2150
+ beforeDelta = delta;
2151
+ }
2152
+ }
2153
+ return before ?? nearest;
2154
+ };
2155
+ const num2 = (v) => typeof v === "number" ? v : void 0;
2156
+ const str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
2157
+ const runs = await Promise.all(jsonFiles.map(async (f) => {
2158
+ let j;
2159
+ try {
2160
+ j = JSON.parse(await fs.readFile(path.join(dir, f), "utf8"));
2161
+ } catch {
2162
+ return null;
2163
+ }
2164
+ const runId = str(j.runId) ?? f.replace(/\.json$/, "");
2165
+ const startMs = num2(j.startTime);
2166
+ const durationMs = num2(j.durationMs);
2167
+ const endMs = startMs !== void 0 && durationMs !== void 0 ? startMs + durationMs : void 0;
2168
+ const startTOffsetMs = sessionStartMs !== void 0 && startMs !== void 0 ? Math.max(0, startMs - sessionStartMs) : void 0;
2169
+ const endTOffsetMs = sessionStartMs !== void 0 && endMs !== void 0 ? Math.max(0, endMs - sessionStartMs) : void 0;
2170
+ const phases = Array.isArray(j.phases) ? j.phases.filter((p) => !!p && typeof p === "object" && typeof p.title === "string").map((p) => ({ title: p.title, detail: str(p.detail) })) : [];
2171
+ const logs = Array.isArray(j.logs) ? j.logs.filter((l) => typeof l === "string") : [];
2172
+ const cap = (v, n) => {
2173
+ const s = str(v);
2174
+ return s === void 0 ? void 0 : s.length > n ? s.slice(0, n) + "\u2026" : s;
2175
+ };
2176
+ const progress = Array.isArray(j.workflowProgress) ? j.workflowProgress : [];
2177
+ const agents = progress.filter((e) => !!e && typeof e === "object" && e.type === "workflow_agent").map((e) => ({
2178
+ index: num2(e.index) ?? 0,
2179
+ label: str(e.label) ?? "(agent)",
2180
+ phaseIndex: num2(e.phaseIndex),
2181
+ phaseTitle: str(e.phaseTitle),
2182
+ agentId: str(e.agentId),
2183
+ model: str(e.model),
2184
+ state: str(e.state),
2185
+ startedAt: num2(e.startedAt),
2186
+ durationMs: num2(e.durationMs),
2187
+ tokens: num2(e.tokens),
2188
+ toolCalls: num2(e.toolCalls),
2189
+ lastToolSummary: cap(e.lastToolSummary, 200),
2190
+ promptPreview: cap(e.promptPreview, 600),
2191
+ resultPreview: cap(e.resultPreview, 600)
2192
+ })).sort((a, b) => a.index - b.index);
2193
+ const parent = matchDispatch(startMs);
2194
+ return {
2195
+ runId,
2196
+ name: str(j.workflowName) ?? runId,
2197
+ description: str(j.summary),
2198
+ status: str(j.status) ?? "unknown",
2199
+ agentCount: num2(j.agentCount) ?? 0,
2200
+ toolCallCount: num2(j.totalToolCalls) ?? 0,
2201
+ totalTokens: num2(j.totalTokens) ?? 0,
2202
+ durationMs,
2203
+ startMs,
2204
+ endMs,
2205
+ startTOffsetMs,
2206
+ endTOffsetMs,
2207
+ model: str(j.defaultModel),
2208
+ phases,
2209
+ logs,
2210
+ agents,
2211
+ parentToolUseId: parent?.toolUseId,
2212
+ parentUuid: parent?.parentUuid
2213
+ };
2214
+ }));
2215
+ return runs.filter((r) => r !== null).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
2216
+ }
2217
+ function salientToolInput(input) {
2218
+ if (!input || typeof input !== "object")
2219
+ return "";
2220
+ const o = input;
2221
+ const pick = (k) => typeof o[k] === "string" ? o[k] : void 0;
2222
+ return pick("command") ?? pick("file_path") ?? pick("path") ?? pick("pattern") ?? pick("url") ?? pick("description") ?? pick("query") ?? pick("prompt") ?? pick("old_string") ?? JSON.stringify(o);
2223
+ }
2224
+ async function loadWorkflowAgentDetail(sessionId, runId, agentId, opts = {}) {
2225
+ const { root = DEFAULT_ROOT } = opts;
2226
+ if (!/^[\w.-]+$/.test(runId) || !/^[\w.-]+$/.test(agentId))
2227
+ return null;
2228
+ const files = await walkJsonlFiles(root);
2229
+ const hit = files.find((f) => sessionIdFromFileName(f.fileName) === sessionId);
2230
+ if (!hit)
2231
+ return null;
2232
+ const file = path.join(path.dirname(hit.fullPath), sessionId, "subagents", "workflows", runId, `agent-${agentId}.jsonl`);
2233
+ let lines;
2234
+ try {
2235
+ lines = await readJsonlFile(file);
2236
+ } catch {
2237
+ return null;
2238
+ }
2239
+ const errored = /* @__PURE__ */ new Set();
2240
+ for (const raw of lines) {
2241
+ if (!raw || typeof raw !== "object")
2242
+ continue;
2243
+ const content = raw.message?.content;
2244
+ if (!Array.isArray(content))
2245
+ continue;
2246
+ for (const b of content) {
2247
+ if (b && typeof b === "object" && b.type === "tool_result" && b.is_error === true && typeof b.tool_use_id === "string") {
2248
+ errored.add(b.tool_use_id);
2249
+ }
2250
+ }
2251
+ }
2252
+ const steps = [];
2253
+ const toolCounts = /* @__PURE__ */ new Map();
2254
+ const totalUsage = { ...BLANK_USAGE3 };
2255
+ const seen = /* @__PURE__ */ new Set();
2256
+ let prompt;
2257
+ let finalText;
2258
+ let model;
2259
+ let assistantMessageCount = 0;
2260
+ let eventCount = 0;
2261
+ let startMs;
2262
+ let endMs;
2263
+ for (const raw of lines) {
2264
+ if (!raw || typeof raw !== "object")
2265
+ continue;
2266
+ const r = raw;
2267
+ eventCount++;
2268
+ const ts = typeof r.timestamp === "string" ? Date.parse(r.timestamp) : NaN;
2269
+ if (!Number.isNaN(ts)) {
2270
+ if (startMs === void 0 || ts < startMs)
2271
+ startMs = ts;
2272
+ if (endMs === void 0 || ts > endMs)
2273
+ endMs = ts;
2274
+ }
2275
+ if (prompt === void 0 && r.type === "user" && (r.parentUuid === null || r.parentUuid === void 0)) {
2276
+ const c = r.message?.content;
2277
+ if (typeof c === "string")
2278
+ prompt = c;
2279
+ else if (Array.isArray(c)) {
2280
+ const t = c.find((b) => b && typeof b === "object" && b.type === "text");
2281
+ if (t?.text)
2282
+ prompt = t.text;
2283
+ }
2284
+ }
2285
+ if (r.type !== "assistant")
2286
+ continue;
2287
+ const m = r.message;
2288
+ if (!m)
2289
+ continue;
2290
+ if (!model && typeof m.model === "string")
2291
+ model = m.model;
2292
+ const mid = typeof m.id === "string" ? m.id : void 0;
2293
+ const rid = typeof r.requestId === "string" ? r.requestId : void 0;
2294
+ const key = mid != null && rid != null ? `${mid}:${rid}` : void 0;
2295
+ const fresh = key ? !seen.has(key) : true;
2296
+ if (key && fresh)
2297
+ seen.add(key);
2298
+ if (fresh) {
2299
+ assistantMessageCount++;
2300
+ const u = m.usage;
2301
+ if (u) {
2302
+ const n = (v) => typeof v === "number" ? v : 0;
2303
+ totalUsage.input += n(u.input_tokens);
2304
+ totalUsage.output += n(u.output_tokens);
2305
+ totalUsage.cacheRead += n(u.cache_read_input_tokens);
2306
+ totalUsage.cacheWrite += n(u.cache_creation_input_tokens);
2307
+ }
2308
+ }
2309
+ const content = m.content;
2310
+ if (!Array.isArray(content))
2311
+ continue;
2312
+ for (const b of content) {
2313
+ if (!b || typeof b !== "object")
2314
+ continue;
2315
+ if (b.type === "text" && typeof b.text === "string") {
2316
+ finalText = b.text;
2317
+ } else if (b.type === "tool_use" && typeof b.name === "string") {
2318
+ toolCounts.set(b.name, (toolCounts.get(b.name) ?? 0) + 1);
2319
+ if (steps.length < 2e3) {
2320
+ const salient = salientToolInput(b.input);
2321
+ const preview = salient.replace(/\s+/g, " ").trim().slice(0, 160);
2322
+ const full = salient.length > 4e3 ? salient.slice(0, 4e3) + "\u2026" : salient;
2323
+ steps.push({
2324
+ index: steps.length + 1,
2325
+ tool: b.name,
2326
+ preview,
2327
+ // Only carry `full` when it adds something over the one-line preview.
2328
+ full: full.length > preview.length || full.includes("\n") ? full : void 0,
2329
+ isError: typeof b.id === "string" && errored.has(b.id)
2330
+ });
2331
+ }
2332
+ }
2333
+ }
2334
+ }
2335
+ const toolCalls = Array.from(toolCounts.entries()).map(([name, count]) => ({ name, count })).sort((a, b) => b.count - a.count);
2336
+ return {
2337
+ agentId,
2338
+ prompt,
2339
+ finalText,
2340
+ steps,
2341
+ toolCalls,
2342
+ toolCallCount: steps.length,
2343
+ assistantMessageCount,
2344
+ eventCount,
2345
+ totalUsage,
2346
+ model,
2347
+ durationMs: startMs !== void 0 && endMs !== void 0 ? endMs - startMs : void 0
2348
+ };
2349
+ }
1907
2350
  async function listProjects(root = DEFAULT_ROOT) {
1908
2351
  const files = await walkJsonlFiles(root);
1909
2352
  const byRawDir = /* @__PURE__ */ new Map();
@@ -1925,10 +2368,10 @@ async function listProjects(root = DEFAULT_ROOT) {
1925
2368
  const canonicalMap = /* @__PURE__ */ new Map();
1926
2369
  for (const [rawDir, { count, lastActiveMs }] of byRawDir) {
1927
2370
  const cwdOrDecoded = cwdForProject(rawDir) ?? decodeProjectName(rawDir);
1928
- const canonical = canonicalProjectName(cwdOrDecoded);
2371
+ const repo = projectRepoName(cwdOrDecoded);
1929
2372
  const wt = worktreeName(cwdOrDecoded);
1930
- const agg = canonicalMap.get(canonical) ?? {
1931
- canonicalName: canonical,
2373
+ const agg = canonicalMap.get(repo) ?? {
2374
+ canonicalName: repo,
1932
2375
  count: 0,
1933
2376
  lastActiveMs: 0,
1934
2377
  worktreeBranches: /* @__PURE__ */ new Set()
@@ -1938,7 +2381,7 @@ async function listProjects(root = DEFAULT_ROOT) {
1938
2381
  agg.lastActiveMs = lastActiveMs;
1939
2382
  if (wt)
1940
2383
  agg.worktreeBranches.add(wt);
1941
- canonicalMap.set(canonical, agg);
2384
+ canonicalMap.set(repo, agg);
1942
2385
  }
1943
2386
  return Array.from(canonicalMap.values()).map((a) => ({
1944
2387
  projectDir: a.canonicalName,
@@ -2838,76 +3281,705 @@ async function parseSession(file) {
2838
3281
  prevMs = ms;
2839
3282
  }
2840
3283
  }
2841
- const activeSegments = computeActiveSegments3(tsMs);
2842
- const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
2843
- const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
2844
- const sessionId = metaRec.sessionId ?? file.filenameId;
2845
- const projectName = cwd ? canonicalProjectName(cwd) : file.slug;
2846
- const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
3284
+ const activeSegments = computeActiveSegments3(tsMs);
3285
+ const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
3286
+ const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
3287
+ const sessionId = metaRec.sessionId ?? file.filenameId;
3288
+ const projectName = cwd ? canonicalProjectName(cwd) : file.slug;
3289
+ const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
3290
+ const meta = {
3291
+ agent: "gemini",
3292
+ id: sessionId,
3293
+ filePath: file.filePath,
3294
+ projectName,
3295
+ projectDir,
3296
+ sessionId,
3297
+ firstTimestamp,
3298
+ lastTimestamp,
3299
+ durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
3300
+ eventCount: events.length,
3301
+ model,
3302
+ cwd,
3303
+ totalUsage,
3304
+ status: "idle",
3305
+ firstUserPreview,
3306
+ lastUserPreview,
3307
+ lastAgentPreview,
3308
+ toolCallCount,
3309
+ turnCount,
3310
+ airTimeMs,
3311
+ activeSegments
3312
+ };
3313
+ return { meta, events };
3314
+ }
3315
+ function computeActiveSegments3(tsMs) {
3316
+ if (tsMs.length === 0)
3317
+ return [];
3318
+ const sorted = [...tsMs].sort((a, b) => a - b);
3319
+ const out = [];
3320
+ let segStart = sorted[0];
3321
+ let segEnd = sorted[0];
3322
+ for (let i = 1; i < sorted.length; i++) {
3323
+ if (sorted[i] - segEnd > IDLE_GAP_MS2) {
3324
+ out.push({ startMs: segStart, endMs: segEnd });
3325
+ segStart = sorted[i];
3326
+ }
3327
+ segEnd = sorted[i];
3328
+ }
3329
+ out.push({ startMs: segStart, endMs: segEnd });
3330
+ return out;
3331
+ }
3332
+ function clearGeminiCaches() {
3333
+ metaCache3.clear();
3334
+ detailCache3.clear();
3335
+ projectsCache = null;
3336
+ }
3337
+ async function listGeminiSessions(opts = {}) {
3338
+ const root = opts.root ?? DEFAULT_GEMINI_ROOT;
3339
+ const files = await listSessionFiles(root);
3340
+ const out = [];
3341
+ for (const file of files) {
3342
+ const cached = metaCache3.get(file.filePath);
3343
+ if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
3344
+ out.push(cached.meta);
3345
+ continue;
3346
+ }
3347
+ try {
3348
+ const { meta } = await parseSession(file);
3349
+ metaCache3.set(file.filePath, {
3350
+ meta,
3351
+ mtimeMs: file.mtimeMs,
3352
+ sizeBytes: file.sizeBytes
3353
+ });
3354
+ out.push(meta);
3355
+ } catch {
3356
+ }
3357
+ }
3358
+ out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
3359
+ if (opts.limit !== void 0)
3360
+ return out.slice(0, opts.limit);
3361
+ return out;
3362
+ }
3363
+ async function getGeminiSession(id, opts = {}) {
3364
+ const root = opts.root ?? DEFAULT_GEMINI_ROOT;
3365
+ const files = await listSessionFiles(root);
3366
+ let chosen;
3367
+ for (const file of files) {
3368
+ if (file.filenameId === id || id.startsWith(file.filenameId)) {
3369
+ chosen = file;
3370
+ break;
3371
+ }
3372
+ }
3373
+ if (!chosen) {
3374
+ for (const file of files) {
3375
+ const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
3376
+ if (meta2.id === id) {
3377
+ chosen = file;
3378
+ break;
3379
+ }
3380
+ }
3381
+ }
3382
+ if (!chosen)
3383
+ return null;
3384
+ const cached = detailCache3.get(chosen.filePath);
3385
+ if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
3386
+ return cached.detail;
3387
+ }
3388
+ const { meta, events } = await parseSession(chosen);
3389
+ const detail = { ...meta, events };
3390
+ detailCache3.set(chosen.filePath, {
3391
+ detail,
3392
+ mtimeMs: chosen.mtimeMs,
3393
+ sizeBytes: chosen.sizeBytes
3394
+ });
3395
+ return detail;
3396
+ }
3397
+ function geminiSessionLocalDay(meta) {
3398
+ if (!meta.firstTimestamp)
3399
+ return void 0;
3400
+ const ms = Date.parse(meta.firstTimestamp);
3401
+ return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
3402
+ }
3403
+ var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
3404
+ var init_gemini = __esm({
3405
+ "../parser/dist/gemini.js"() {
3406
+ "use strict";
3407
+ init_analytics();
3408
+ init_user_input();
3409
+ DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
3410
+ GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
3411
+ SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
3412
+ IDLE_GAP_MS2 = 3 * 60 * 1e3;
3413
+ projectsCache = null;
3414
+ metaCache3 = /* @__PURE__ */ new Map();
3415
+ detailCache3 = /* @__PURE__ */ new Map();
3416
+ }
3417
+ });
3418
+
3419
+ // ../parser/dist/antigravity.js
3420
+ import { promises as fs4 } from "node:fs";
3421
+ import os4 from "node:os";
3422
+ import path4 from "node:path";
3423
+ async function safeReaddir3(p) {
3424
+ return fs4.readdir(p).catch(() => []);
3425
+ }
3426
+ async function loadSlugToCwd2(root) {
3427
+ const historyFile = path4.join(root, "history.jsonl");
3428
+ const stat = await fs4.stat(historyFile).catch(() => null);
3429
+ if (!stat)
3430
+ return /* @__PURE__ */ new Map();
3431
+ if (historyCache && historyCache.mtimeMs === stat.mtimeMs) {
3432
+ return historyCache.slugToCwd;
3433
+ }
3434
+ const raw = await fs4.readFile(historyFile, "utf8").catch(() => "");
3435
+ const slugToCwd = /* @__PURE__ */ new Map();
3436
+ for (const line of raw.split("\n")) {
3437
+ const trimmed = line.trim();
3438
+ if (!trimmed)
3439
+ continue;
3440
+ try {
3441
+ const parsed = JSON.parse(trimmed);
3442
+ if (parsed.conversationId && parsed.workspace) {
3443
+ slugToCwd.set(parsed.conversationId, parsed.workspace);
3444
+ }
3445
+ } catch {
3446
+ }
3447
+ }
3448
+ historyCache = { mtimeMs: stat.mtimeMs, slugToCwd };
3449
+ return slugToCwd;
3450
+ }
3451
+ async function listSessionFiles2(root) {
3452
+ const slugToCwd = await loadSlugToCwd2(root);
3453
+ const out = [];
3454
+ const brainDir = path4.join(root, "brain");
3455
+ const entries = await safeReaddir3(brainDir);
3456
+ for (const entry of entries) {
3457
+ const transcriptPath = path4.join(brainDir, entry, ".system_generated", "logs", "transcript.jsonl");
3458
+ const stat = await fs4.stat(transcriptPath).catch(() => null);
3459
+ if (stat && stat.isFile()) {
3460
+ out.push({
3461
+ filePath: transcriptPath,
3462
+ conversationId: entry,
3463
+ cwd: slugToCwd.get(entry),
3464
+ mtimeMs: stat.mtimeMs,
3465
+ sizeBytes: stat.size
3466
+ });
3467
+ }
3468
+ }
3469
+ return out;
3470
+ }
3471
+ function emptyUsage3() {
3472
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
3473
+ }
3474
+ function previewOf3(text) {
3475
+ return text.replace(/\s+/g, " ").trim().slice(0, 200);
3476
+ }
3477
+ function truncate4(s, n) {
3478
+ return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
3479
+ }
3480
+ async function parseSession2(file) {
3481
+ const raw = await fs4.readFile(file.filePath, "utf8");
3482
+ const events = [];
3483
+ const totalUsage = emptyUsage3();
3484
+ let firstTimestamp;
3485
+ let lastTimestamp;
3486
+ let model;
3487
+ let toolCallCount = 0;
3488
+ let turnCount = 0;
3489
+ let firstUserPreview;
3490
+ let lastUserPreview;
3491
+ let lastAgentPreview;
3492
+ const tsMs = [];
3493
+ let idx = 0;
3494
+ function pushEvent(e) {
3495
+ events.push(e);
3496
+ if (e.timestamp && e.role !== "meta") {
3497
+ if (!firstTimestamp)
3498
+ firstTimestamp = e.timestamp;
3499
+ lastTimestamp = e.timestamp;
3500
+ const ms = Date.parse(e.timestamp);
3501
+ if (Number.isFinite(ms))
3502
+ tsMs.push(ms);
3503
+ }
3504
+ }
3505
+ const pendingToolCalls = [];
3506
+ const parsedObjects = [];
3507
+ const indexMap = /* @__PURE__ */ new Map();
3508
+ for (const line of raw.split("\n")) {
3509
+ const trimmed = line.trim();
3510
+ if (!trimmed)
3511
+ continue;
3512
+ try {
3513
+ const obj = JSON.parse(trimmed);
3514
+ const stepIdx = obj.step_index;
3515
+ if (typeof stepIdx === "number") {
3516
+ if (indexMap.has(stepIdx)) {
3517
+ parsedObjects[indexMap.get(stepIdx)] = obj;
3518
+ } else {
3519
+ indexMap.set(stepIdx, parsedObjects.length);
3520
+ parsedObjects.push(obj);
3521
+ }
3522
+ } else {
3523
+ parsedObjects.push(obj);
3524
+ }
3525
+ } catch {
3526
+ }
3527
+ }
3528
+ for (const eventObj of parsedObjects) {
3529
+ const ts = eventObj.created_at || eventObj.timestamp;
3530
+ if (eventObj.type === "USER_INPUT") {
3531
+ if (typeof eventObj.content === "string") {
3532
+ const matchNoNeed = eventObj.content.match(/Model Selection` from .*? to (.*?)\.\s*No need to/);
3533
+ if (matchNoNeed) {
3534
+ let rawModel = matchNoNeed[1].trim();
3535
+ rawModel = rawModel.replace(/\s*\(.*?\)\s*$/, "").trim();
3536
+ model = rawModel;
3537
+ } else {
3538
+ const matchDot = eventObj.content.match(/Model Selection` from .*? to ([^\n]+)/);
3539
+ if (matchDot) {
3540
+ let rawModel = matchDot[1].trim();
3541
+ if (rawModel.endsWith(".")) {
3542
+ rawModel = rawModel.slice(0, -1).trim();
3543
+ }
3544
+ rawModel = rawModel.replace(/\s*\(.*?\)\s*$/, "").trim();
3545
+ model = rawModel;
3546
+ }
3547
+ }
3548
+ }
3549
+ let text2 = eventObj.content || "";
3550
+ const requestMatch = text2.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
3551
+ if (requestMatch) {
3552
+ text2 = requestMatch[1].trim();
3553
+ }
3554
+ const preview = previewOf3(text2);
3555
+ const isHidden = isFrameworkInjectedUserInput(text2);
3556
+ if (text2 && !isHidden) {
3557
+ if (!firstUserPreview)
3558
+ firstUserPreview = preview;
3559
+ lastUserPreview = preview;
3560
+ turnCount += 1;
3561
+ }
3562
+ pushEvent({
3563
+ index: idx++,
3564
+ timestamp: ts,
3565
+ role: "user",
3566
+ rawType: "antigravity/user",
3567
+ preview,
3568
+ blocks: text2 ? [{ type: "text", text: text2 }] : [],
3569
+ messageId: eventObj.step_index?.toString(),
3570
+ raw: eventObj
3571
+ });
3572
+ continue;
3573
+ }
3574
+ if (eventObj.type === "PLANNER_RESPONSE") {
3575
+ const thinking = eventObj.thinking;
3576
+ const content = eventObj.content;
3577
+ if (thinking) {
3578
+ pushEvent({
3579
+ index: idx++,
3580
+ timestamp: ts,
3581
+ role: "agent-thinking",
3582
+ rawType: "antigravity/thought",
3583
+ preview: previewOf3(thinking),
3584
+ blocks: [{ type: "thinking", thinking }],
3585
+ model,
3586
+ raw: eventObj
3587
+ });
3588
+ }
3589
+ if (content) {
3590
+ const preview = previewOf3(content);
3591
+ lastAgentPreview = preview;
3592
+ pushEvent({
3593
+ index: idx++,
3594
+ timestamp: ts,
3595
+ role: "agent",
3596
+ rawType: "antigravity/agent",
3597
+ preview,
3598
+ blocks: [{ type: "text", text: content }],
3599
+ messageId: eventObj.step_index?.toString(),
3600
+ model,
3601
+ raw: eventObj
3602
+ });
3603
+ }
3604
+ const toolCalls = eventObj.tool_calls || [];
3605
+ for (let cIdx = 0; cIdx < toolCalls.length; cIdx++) {
3606
+ const tc = toolCalls[cIdx];
3607
+ toolCallCount += 1;
3608
+ const toolUseId = `tool-${eventObj.step_index}-${cIdx}`;
3609
+ const argsStr = tc.args ? JSON.stringify(tc.args) : "";
3610
+ pendingToolCalls.push({ id: toolUseId, name: tc.name });
3611
+ pushEvent({
3612
+ index: idx++,
3613
+ timestamp: ts,
3614
+ role: "tool-call",
3615
+ rawType: "antigravity/tool_call",
3616
+ preview: `${tc.name}(${truncate4(argsStr, 80)})`,
3617
+ blocks: [{ type: "tool_use", id: toolUseId, name: tc.name, input: tc.args || {} }],
3618
+ toolName: tc.name,
3619
+ toolUseId,
3620
+ model,
3621
+ raw: tc
3622
+ });
3623
+ }
3624
+ continue;
3625
+ }
3626
+ if (eventObj.source === "MODEL" && eventObj.type !== "PLANNER_RESPONSE" && eventObj.type !== "ERROR_MESSAGE" && pendingToolCalls.length > 0) {
3627
+ const matchedCall = pendingToolCalls.shift();
3628
+ const toolUseId = matchedCall ? matchedCall.id : `tool-${eventObj.step_index}-unknown`;
3629
+ const contentStr = typeof eventObj.content === "string" ? eventObj.content : JSON.stringify(eventObj.content || "");
3630
+ const isError = eventObj.status === "ERROR" || eventObj.status === "FAILED" || eventObj.status === "CANCELED" || !!eventObj.error;
3631
+ pushEvent({
3632
+ index: idx++,
3633
+ timestamp: ts,
3634
+ role: "tool-result",
3635
+ rawType: "antigravity/tool_result",
3636
+ preview: previewOf3(contentStr),
3637
+ blocks: [{
3638
+ type: "tool_result",
3639
+ tool_use_id: toolUseId,
3640
+ content: contentStr,
3641
+ is_error: isError
3642
+ }],
3643
+ toolUseId,
3644
+ toolResult: contentStr,
3645
+ raw: eventObj
3646
+ });
3647
+ continue;
3648
+ }
3649
+ const text = eventObj.content || eventObj.error || "";
3650
+ pushEvent({
3651
+ index: idx++,
3652
+ timestamp: ts,
3653
+ role: "meta",
3654
+ rawType: `antigravity/${eventObj.type?.toLowerCase() || "unknown"}`,
3655
+ preview: previewOf3(text),
3656
+ blocks: text ? [{ type: "text", text }] : [],
3657
+ raw: eventObj
3658
+ });
3659
+ }
3660
+ const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
3661
+ if (startMs !== void 0 && Number.isFinite(startMs)) {
3662
+ let prevMs;
3663
+ for (const ev of events) {
3664
+ if (!ev.timestamp)
3665
+ continue;
3666
+ const ms = Date.parse(ev.timestamp);
3667
+ if (!Number.isFinite(ms))
3668
+ continue;
3669
+ ev.tOffsetMs = Math.max(0, ms - startMs);
3670
+ if (prevMs !== void 0)
3671
+ ev.gapMs = Math.max(0, ms - prevMs);
3672
+ prevMs = ms;
3673
+ }
3674
+ }
3675
+ const activeSegments = computeActiveSegments4(tsMs);
3676
+ const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
3677
+ const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
3678
+ const sessionId = file.conversationId;
3679
+ const cwd = file.cwd;
3680
+ const projectName = cwd ? canonicalProjectName(cwd) : file.conversationId;
3681
+ const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.conversationId;
3682
+ const meta = {
3683
+ agent: "antigravity",
3684
+ id: sessionId,
3685
+ filePath: file.filePath,
3686
+ projectName,
3687
+ projectDir,
3688
+ sessionId,
3689
+ firstTimestamp,
3690
+ lastTimestamp,
3691
+ durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
3692
+ eventCount: events.length,
3693
+ model,
3694
+ cwd,
3695
+ totalUsage,
3696
+ status: "idle",
3697
+ firstUserPreview,
3698
+ lastUserPreview,
3699
+ lastAgentPreview,
3700
+ toolCallCount,
3701
+ turnCount,
3702
+ airTimeMs,
3703
+ activeSegments
3704
+ };
3705
+ return { meta, events };
3706
+ }
3707
+ function computeActiveSegments4(tsMs) {
3708
+ if (tsMs.length === 0)
3709
+ return [];
3710
+ const sorted = [...tsMs].sort((a, b) => a - b);
3711
+ const out = [];
3712
+ let segStart = sorted[0];
3713
+ let segEnd = sorted[0];
3714
+ for (let i = 1; i < sorted.length; i++) {
3715
+ if (sorted[i] - segEnd > IDLE_GAP_MS3) {
3716
+ out.push({ startMs: segStart, endMs: segEnd });
3717
+ segStart = sorted[i];
3718
+ }
3719
+ segEnd = sorted[i];
3720
+ }
3721
+ out.push({ startMs: segStart, endMs: segEnd });
3722
+ return out;
3723
+ }
3724
+ function clearAntigravityCaches() {
3725
+ metaCache4.clear();
3726
+ detailCache4.clear();
3727
+ historyCache = null;
3728
+ }
3729
+ async function listAntigravitySessions(opts = {}) {
3730
+ const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
3731
+ const files = await listSessionFiles2(root);
3732
+ const out = [];
3733
+ for (const file of files) {
3734
+ const cached = metaCache4.get(file.filePath);
3735
+ if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes && cached.cwd === file.cwd) {
3736
+ out.push(cached.meta);
3737
+ continue;
3738
+ }
3739
+ try {
3740
+ const { meta } = await parseSession2(file);
3741
+ metaCache4.set(file.filePath, {
3742
+ meta,
3743
+ mtimeMs: file.mtimeMs,
3744
+ sizeBytes: file.sizeBytes,
3745
+ cwd: file.cwd
3746
+ });
3747
+ out.push(meta);
3748
+ } catch {
3749
+ }
3750
+ }
3751
+ out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
3752
+ if (opts.limit !== void 0)
3753
+ return out.slice(0, opts.limit);
3754
+ return out;
3755
+ }
3756
+ async function getAntigravitySession(id, opts = {}) {
3757
+ const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
3758
+ const files = await listSessionFiles2(root);
3759
+ let chosen;
3760
+ for (const file of files) {
3761
+ if (file.conversationId === id) {
3762
+ chosen = file;
3763
+ break;
3764
+ }
3765
+ }
3766
+ if (!chosen)
3767
+ return null;
3768
+ const cached = detailCache4.get(chosen.filePath);
3769
+ if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes && cached.cwd === chosen.cwd) {
3770
+ return cached.detail;
3771
+ }
3772
+ const { meta, events } = await parseSession2(chosen);
3773
+ const detail = { ...meta, events };
3774
+ detailCache4.set(chosen.filePath, {
3775
+ detail,
3776
+ mtimeMs: chosen.mtimeMs,
3777
+ sizeBytes: chosen.sizeBytes,
3778
+ cwd: chosen.cwd
3779
+ });
3780
+ return detail;
3781
+ }
3782
+ function antigravitySessionLocalDay(meta) {
3783
+ if (!meta.firstTimestamp)
3784
+ return void 0;
3785
+ const ms = Date.parse(meta.firstTimestamp);
3786
+ return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
3787
+ }
3788
+ var DEFAULT_ANTIGRAVITY_ROOT, IDLE_GAP_MS3, historyCache, metaCache4, detailCache4;
3789
+ var init_antigravity = __esm({
3790
+ "../parser/dist/antigravity.js"() {
3791
+ "use strict";
3792
+ init_analytics();
3793
+ init_user_input();
3794
+ DEFAULT_ANTIGRAVITY_ROOT = path4.join(os4.homedir(), ".gemini", "antigravity-cli");
3795
+ IDLE_GAP_MS3 = 3 * 60 * 1e3;
3796
+ historyCache = null;
3797
+ metaCache4 = /* @__PURE__ */ new Map();
3798
+ detailCache4 = /* @__PURE__ */ new Map();
3799
+ }
3800
+ });
3801
+
3802
+ // ../parser/dist/cowork.js
3803
+ import { promises as fs5 } from "node:fs";
3804
+ import os5 from "node:os";
3805
+ import path5 from "node:path";
3806
+ function defaultCoworkRoot() {
3807
+ const home = os5.homedir();
3808
+ if (process.platform === "darwin") {
3809
+ return path5.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions");
3810
+ }
3811
+ if (process.platform === "win32") {
3812
+ const appData = process.env.APPDATA ?? path5.join(home, "AppData", "Roaming");
3813
+ return path5.join(appData, "Claude", "local-agent-mode-sessions");
3814
+ }
3815
+ return path5.join(home, ".config", "Claude", "local-agent-mode-sessions");
3816
+ }
3817
+ async function safeReaddir4(p) {
3818
+ return fs5.readdir(p).catch(() => []);
3819
+ }
3820
+ async function statMs(p) {
3821
+ const s = await fs5.stat(p).catch(() => null);
3822
+ return s ? s.mtimeMs : 0;
3823
+ }
3824
+ async function listSessionFiles3(root) {
3825
+ const out = [];
3826
+ const accounts = await safeReaddir4(root);
3827
+ for (const accountId of accounts) {
3828
+ const accountDir = path5.join(root, accountId);
3829
+ const workspaces = await safeReaddir4(accountDir);
3830
+ for (const workspaceId of workspaces) {
3831
+ const workspaceDir = path5.join(accountDir, workspaceId);
3832
+ const spacesMtimeMs = await statMs(path5.join(workspaceDir, "spaces.json"));
3833
+ const entries = await safeReaddir4(workspaceDir);
3834
+ for (const entry of entries) {
3835
+ if (!SESSION_ID_RE.test(entry))
3836
+ continue;
3837
+ const auditPath = path5.join(workspaceDir, entry, "audit.jsonl");
3838
+ const auditStat = await fs5.stat(auditPath).catch(() => null);
3839
+ if (!auditStat || !auditStat.isFile() || auditStat.size === 0)
3840
+ continue;
3841
+ const metaPath = path5.join(workspaceDir, `${entry}.json`);
3842
+ const metaMtimeMs = await statMs(metaPath);
3843
+ out.push({
3844
+ sessionId: entry,
3845
+ auditPath,
3846
+ metaPath,
3847
+ workspaceDir,
3848
+ auditMtimeMs: auditStat.mtimeMs,
3849
+ auditSize: auditStat.size,
3850
+ metaMtimeMs,
3851
+ spacesMtimeMs
3852
+ });
3853
+ }
3854
+ }
3855
+ }
3856
+ return out;
3857
+ }
3858
+ async function loadSpacesForWorkspace(workspaceDir) {
3859
+ const spacesPath = path5.join(workspaceDir, "spaces.json");
3860
+ const stat = await fs5.stat(spacesPath).catch(() => null);
3861
+ if (!stat)
3862
+ return /* @__PURE__ */ new Map();
3863
+ const cached = spacesCache.get(workspaceDir);
3864
+ if (cached && cached.mtimeMs === stat.mtimeMs)
3865
+ return cached.spaceIdToPath;
3866
+ const raw = await fs5.readFile(spacesPath, "utf8").catch(() => "");
3867
+ const out = /* @__PURE__ */ new Map();
3868
+ try {
3869
+ const parsed = JSON.parse(raw);
3870
+ for (const space of parsed.spaces ?? []) {
3871
+ const id = typeof space.id === "string" ? space.id : void 0;
3872
+ const folders = Array.isArray(space.folders) ? space.folders : [];
3873
+ const first = folders[0];
3874
+ const folderPath = typeof first?.path === "string" ? first.path : void 0;
3875
+ if (id && folderPath)
3876
+ out.set(id, folderPath);
3877
+ }
3878
+ } catch {
3879
+ }
3880
+ spacesCache.set(workspaceDir, { mtimeMs: stat.mtimeMs, spaceIdToPath: out });
3881
+ return out;
3882
+ }
3883
+ async function readCoworkMeta(metaPath) {
3884
+ const raw = await fs5.readFile(metaPath, "utf8").catch(() => "");
3885
+ if (!raw)
3886
+ return {};
3887
+ try {
3888
+ const j = JSON.parse(raw);
3889
+ return {
3890
+ spaceId: typeof j.spaceId === "string" ? j.spaceId : void 0,
3891
+ userSelectedFolders: Array.isArray(j.userSelectedFolders) ? j.userSelectedFolders.filter((s) => typeof s === "string") : void 0,
3892
+ cwd: typeof j.cwd === "string" ? j.cwd : void 0,
3893
+ model: typeof j.model === "string" ? j.model : void 0,
3894
+ title: typeof j.title === "string" ? j.title : void 0,
3895
+ createdAt: typeof j.createdAt === "number" ? j.createdAt : void 0,
3896
+ lastActivityAt: typeof j.lastActivityAt === "number" ? j.lastActivityAt : void 0
3897
+ };
3898
+ } catch {
3899
+ return {};
3900
+ }
3901
+ }
3902
+ function resolveProject(meta, spaceIdToPath) {
3903
+ let projectPath;
3904
+ if (meta.spaceId)
3905
+ projectPath = spaceIdToPath.get(meta.spaceId);
3906
+ if (!projectPath && meta.userSelectedFolders && meta.userSelectedFolders.length > 0) {
3907
+ projectPath = meta.userSelectedFolders[0];
3908
+ }
3909
+ if (!projectPath) {
3910
+ return { projectName: "cowork:unspaced", projectDir: "cowork-unspaced" };
3911
+ }
3912
+ return {
3913
+ projectName: canonicalProjectName(projectPath),
3914
+ projectDir: projectPath.replace(/^\//, "-").replace(/\//g, "-"),
3915
+ cwd: projectPath
3916
+ };
3917
+ }
3918
+ async function readJsonl2(filePath) {
3919
+ const raw = await fs5.readFile(filePath, "utf8");
3920
+ const out = [];
3921
+ for (const line of raw.split("\n")) {
3922
+ const trimmed = line.trim();
3923
+ if (!trimmed)
3924
+ continue;
3925
+ try {
3926
+ out.push(JSON.parse(trimmed));
3927
+ } catch {
3928
+ }
3929
+ }
3930
+ return out;
3931
+ }
3932
+ async function parseCoworkSession(file) {
3933
+ const [lines, coworkMeta, spaceIdToPath] = await Promise.all([
3934
+ readJsonl2(file.auditPath),
3935
+ readCoworkMeta(file.metaPath),
3936
+ loadSpacesForWorkspace(file.workspaceDir)
3937
+ ]);
3938
+ const { meta: baseMeta, events } = parseTranscript(lines);
3939
+ const { projectName, projectDir, cwd } = resolveProject(coworkMeta, spaceIdToPath);
2847
3940
  const meta = {
2848
- agent: "gemini",
2849
- id: sessionId,
2850
- filePath: file.filePath,
3941
+ ...baseMeta,
3942
+ agent: "cowork",
3943
+ id: file.sessionId,
3944
+ sessionId: file.sessionId,
3945
+ filePath: file.auditPath,
2851
3946
  projectName,
2852
3947
  projectDir,
2853
- sessionId,
2854
- firstTimestamp,
2855
- lastTimestamp,
2856
- durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
2857
- eventCount: events.length,
2858
- model,
2859
- cwd,
2860
- totalUsage,
2861
- status: "idle",
2862
- firstUserPreview,
2863
- lastUserPreview,
2864
- lastAgentPreview,
2865
- toolCallCount,
2866
- turnCount,
2867
- airTimeMs,
2868
- activeSegments
3948
+ cwd: cwd ?? baseMeta.cwd,
3949
+ model: baseMeta.model ?? coworkMeta.model
2869
3950
  };
2870
3951
  return { meta, events };
2871
3952
  }
2872
- function computeActiveSegments3(tsMs) {
2873
- if (tsMs.length === 0)
2874
- return [];
2875
- const sorted = [...tsMs].sort((a, b) => a - b);
2876
- const out = [];
2877
- let segStart = sorted[0];
2878
- let segEnd = sorted[0];
2879
- for (let i = 1; i < sorted.length; i++) {
2880
- if (sorted[i] - segEnd > IDLE_GAP_MS2) {
2881
- out.push({ startMs: segStart, endMs: segEnd });
2882
- segStart = sorted[i];
2883
- }
2884
- segEnd = sorted[i];
2885
- }
2886
- out.push({ startMs: segStart, endMs: segEnd });
2887
- return out;
3953
+ function cacheKeyFor(file) {
3954
+ return {
3955
+ auditMtimeMs: file.auditMtimeMs,
3956
+ auditSize: file.auditSize,
3957
+ metaMtimeMs: file.metaMtimeMs,
3958
+ spacesMtimeMs: file.spacesMtimeMs
3959
+ };
2888
3960
  }
2889
- function clearGeminiCaches() {
2890
- metaCache3.clear();
2891
- detailCache3.clear();
2892
- projectsCache = null;
3961
+ function cacheKeyMatches(a, b) {
3962
+ return a.auditMtimeMs === b.auditMtimeMs && a.auditSize === b.auditSize && a.metaMtimeMs === b.metaMtimeMs && a.spacesMtimeMs === b.spacesMtimeMs;
2893
3963
  }
2894
- async function listGeminiSessions(opts = {}) {
2895
- const root = opts.root ?? DEFAULT_GEMINI_ROOT;
2896
- const files = await listSessionFiles(root);
3964
+ function clearCoworkCaches() {
3965
+ metaCache5.clear();
3966
+ detailCache5.clear();
3967
+ spacesCache.clear();
3968
+ }
3969
+ async function listCoworkSessions(opts = {}) {
3970
+ const root = opts.root ?? DEFAULT_COWORK_ROOT;
3971
+ const files = await listSessionFiles3(root);
2897
3972
  const out = [];
2898
3973
  for (const file of files) {
2899
- const cached = metaCache3.get(file.filePath);
2900
- if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
3974
+ const key = cacheKeyFor(file);
3975
+ const cached = metaCache5.get(file.auditPath);
3976
+ if (cached && cacheKeyMatches(cached.key, key)) {
2901
3977
  out.push(cached.meta);
2902
3978
  continue;
2903
3979
  }
2904
3980
  try {
2905
- const { meta } = await parseSession(file);
2906
- metaCache3.set(file.filePath, {
2907
- meta,
2908
- mtimeMs: file.mtimeMs,
2909
- sizeBytes: file.sizeBytes
2910
- });
3981
+ const { meta } = await parseCoworkSession(file);
3982
+ metaCache5.set(file.auditPath, { meta, key });
2911
3983
  out.push(meta);
2912
3984
  } catch {
2913
3985
  }
@@ -2917,59 +3989,38 @@ async function listGeminiSessions(opts = {}) {
2917
3989
  return out.slice(0, opts.limit);
2918
3990
  return out;
2919
3991
  }
2920
- async function getGeminiSession(id, opts = {}) {
2921
- const root = opts.root ?? DEFAULT_GEMINI_ROOT;
2922
- const files = await listSessionFiles(root);
2923
- let chosen;
2924
- for (const file of files) {
2925
- if (file.filenameId === id || id.startsWith(file.filenameId)) {
2926
- chosen = file;
2927
- break;
2928
- }
2929
- }
2930
- if (!chosen) {
2931
- for (const file of files) {
2932
- const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
2933
- if (meta2.id === id) {
2934
- chosen = file;
2935
- break;
2936
- }
2937
- }
2938
- }
2939
- if (!chosen)
3992
+ async function getCoworkSession(id, opts = {}) {
3993
+ const root = opts.root ?? DEFAULT_COWORK_ROOT;
3994
+ const files = await listSessionFiles3(root);
3995
+ const file = files.find((f) => f.sessionId === id);
3996
+ if (!file)
2940
3997
  return null;
2941
- const cached = detailCache3.get(chosen.filePath);
2942
- if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
3998
+ const key = cacheKeyFor(file);
3999
+ const cached = detailCache5.get(file.auditPath);
4000
+ if (cached && cacheKeyMatches(cached.key, key))
2943
4001
  return cached.detail;
2944
- }
2945
- const { meta, events } = await parseSession(chosen);
4002
+ const { meta, events } = await parseCoworkSession(file);
2946
4003
  const detail = { ...meta, events };
2947
- detailCache3.set(chosen.filePath, {
2948
- detail,
2949
- mtimeMs: chosen.mtimeMs,
2950
- sizeBytes: chosen.sizeBytes
2951
- });
4004
+ detailCache5.set(file.auditPath, { detail, key });
2952
4005
  return detail;
2953
4006
  }
2954
- function geminiSessionLocalDay(meta) {
4007
+ function coworkSessionLocalDay(meta) {
2955
4008
  if (!meta.firstTimestamp)
2956
4009
  return void 0;
2957
4010
  const ms = Date.parse(meta.firstTimestamp);
2958
4011
  return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
2959
4012
  }
2960
- var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
2961
- var init_gemini = __esm({
2962
- "../parser/dist/gemini.js"() {
4013
+ var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache5, detailCache5;
4014
+ var init_cowork = __esm({
4015
+ "../parser/dist/cowork.js"() {
2963
4016
  "use strict";
2964
4017
  init_analytics();
2965
- init_user_input();
2966
- DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
2967
- GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
2968
- SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
2969
- IDLE_GAP_MS2 = 3 * 60 * 1e3;
2970
- projectsCache = null;
2971
- metaCache3 = /* @__PURE__ */ new Map();
2972
- detailCache3 = /* @__PURE__ */ new Map();
4018
+ init_parser();
4019
+ DEFAULT_COWORK_ROOT = defaultCoworkRoot();
4020
+ SESSION_ID_RE = /^local_[0-9a-f-]+$/;
4021
+ spacesCache = /* @__PURE__ */ new Map();
4022
+ metaCache5 = /* @__PURE__ */ new Map();
4023
+ detailCache5 = /* @__PURE__ */ new Map();
2973
4024
  }
2974
4025
  });
2975
4026
 
@@ -3017,11 +4068,14 @@ var init_team_wire = __esm({
3017
4068
  // ../parser/dist/fs.js
3018
4069
  var fs_exports = {};
3019
4070
  __export(fs_exports, {
4071
+ DEFAULT_ANTIGRAVITY_ROOT: () => DEFAULT_ANTIGRAVITY_ROOT,
3020
4072
  DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
4073
+ DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
3021
4074
  DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
3022
4075
  DEFAULT_ROOT: () => DEFAULT_ROOT,
3023
4076
  RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
3024
4077
  agentSources: () => agentSources,
4078
+ antigravitySessionLocalDay: () => antigravitySessionLocalDay,
3025
4079
  buildCalibrationCurve: () => buildCalibrationCurve,
3026
4080
  cacheStats: () => cacheStats,
3027
4081
  cclensHome: () => cclensHome,
@@ -3029,19 +4083,24 @@ __export(fs_exports, {
3029
4083
  clearCaches: () => clearCaches,
3030
4084
  clearTeamConfig: () => clearTeamConfig,
3031
4085
  codexSessionLocalDay: () => codexSessionLocalDay,
4086
+ coworkSessionLocalDay: () => coworkSessionLocalDay,
3032
4087
  decodeProjectName: () => decodeProjectName,
3033
4088
  findTeamLead: () => findTeamLead,
3034
4089
  geminiSessionLocalDay: () => geminiSessionLocalDay,
3035
4090
  getAgentSource: () => getAgentSource,
4091
+ getAntigravitySession: () => getAntigravitySession,
3036
4092
  getAnySession: () => getAnySession,
3037
4093
  getCodexSession: () => getCodexSession,
4094
+ getCoworkSession: () => getCoworkSession,
3038
4095
  getGeminiSession: () => getGeminiSession,
3039
4096
  getLatestCodexUsage: () => getLatestCodexUsage,
3040
4097
  getSession: () => getSession,
3041
4098
  invalidateFile: () => invalidateFile,
3042
4099
  isFleetlensRuntimeDir: () => isFleetlensRuntimeDir,
3043
4100
  listAllSessions: () => listAllSessions,
4101
+ listAntigravitySessions: () => listAntigravitySessions,
3044
4102
  listCodexSessions: () => listCodexSessions,
4103
+ listCoworkSessions: () => listCoworkSessions,
3045
4104
  listGeminiSessions: () => listGeminiSessions,
3046
4105
  listProjects: () => listProjects,
3047
4106
  listSessions: () => listSessions,
@@ -3050,20 +4109,21 @@ __export(fs_exports, {
3050
4109
  loadCalibrationSnapshots: () => loadCalibrationSnapshots,
3051
4110
  loadTeamForSession: () => loadTeamForSession,
3052
4111
  loadUsageByDay: () => loadUsageByDay,
4112
+ loadWorkflowAgentDetail: () => loadWorkflowAgentDetail,
3053
4113
  readJsonlFile: () => readJsonlFile,
3054
4114
  readTeamConfig: () => readTeamConfig,
3055
4115
  sessionIdFromFileName: () => sessionIdFromFileName,
3056
4116
  walkJsonlFiles: () => walkJsonlFiles,
3057
4117
  writeTeamConfig: () => writeTeamConfig
3058
4118
  });
3059
- import { promises as fs4 } from "node:fs";
3060
- import os4 from "node:os";
3061
- import path4 from "node:path";
4119
+ import { promises as fs6 } from "node:fs";
4120
+ import os6 from "node:os";
4121
+ import path6 from "node:path";
3062
4122
  function cclensHome() {
3063
- return process.env.CCLENS_HOME || path4.join(os4.homedir(), ".cclens");
4123
+ return process.env.CCLENS_HOME || path6.join(os6.homedir(), ".cclens");
3064
4124
  }
3065
4125
  function cclensPath(...parts) {
3066
- return path4.join(cclensHome(), ...parts);
4126
+ return path6.join(cclensHome(), ...parts);
3067
4127
  }
3068
4128
  function cacheStats() {
3069
4129
  return claudeCodeCacheStats();
@@ -3072,6 +4132,8 @@ function clearCaches() {
3072
4132
  clearClaudeCodeCaches();
3073
4133
  clearCodexCaches();
3074
4134
  clearGeminiCaches();
4135
+ clearAntigravityCaches();
4136
+ clearCoworkCaches();
3075
4137
  }
3076
4138
  function invalidateFile(fullPath) {
3077
4139
  invalidateClaudeCodeFile(fullPath);
@@ -3103,7 +4165,7 @@ function usageLogPath() {
3103
4165
  async function loadUsageByDay(start, end) {
3104
4166
  let raw;
3105
4167
  try {
3106
- raw = await fs4.readFile(usageLogPath(), "utf8");
4168
+ raw = await fs6.readFile(usageLogPath(), "utf8");
3107
4169
  } catch {
3108
4170
  return { by_day: [] };
3109
4171
  }
@@ -3148,7 +4210,7 @@ async function loadUsageByDay(start, end) {
3148
4210
  async function loadCalibrationSnapshots() {
3149
4211
  let raw;
3150
4212
  try {
3151
- raw = await fs4.readFile(usageLogPath(), "utf8");
4213
+ raw = await fs6.readFile(usageLogPath(), "utf8");
3152
4214
  } catch {
3153
4215
  return [];
3154
4216
  }
@@ -3306,7 +4368,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
3306
4368
  ]);
3307
4369
  return buildCalibrationCurve(events, snapshots, tier, granularityMin);
3308
4370
  }
3309
- var codexSource, geminiSource, agentSources;
4371
+ var codexSource, geminiSource, antigravitySource, coworkSource, agentSources;
3310
4372
  var init_fs = __esm({
3311
4373
  "../parser/dist/fs.js"() {
3312
4374
  "use strict";
@@ -3316,9 +4378,13 @@ var init_fs = __esm({
3316
4378
  init_claude_code();
3317
4379
  init_codex();
3318
4380
  init_gemini();
4381
+ init_antigravity();
4382
+ init_cowork();
3319
4383
  init_claude_code();
3320
4384
  init_codex();
3321
4385
  init_gemini();
4386
+ init_antigravity();
4387
+ init_cowork();
3322
4388
  init_team_config();
3323
4389
  init_team_wire();
3324
4390
  codexSource = {
@@ -3352,7 +4418,33 @@ var init_fs = __esm({
3352
4418
  return getGeminiSession(id);
3353
4419
  }
3354
4420
  };
3355
- agentSources = [claudeCodeSource, codexSource, geminiSource];
4421
+ antigravitySource = {
4422
+ ...ANTIGRAVITY_METADATA,
4423
+ defaultRoot: DEFAULT_ANTIGRAVITY_ROOT,
4424
+ async listSessions(opts) {
4425
+ return listAntigravitySessions(opts);
4426
+ },
4427
+ async getSession(id) {
4428
+ return getAntigravitySession(id);
4429
+ }
4430
+ };
4431
+ coworkSource = {
4432
+ ...COWORK_METADATA,
4433
+ defaultRoot: DEFAULT_COWORK_ROOT,
4434
+ async listSessions(opts) {
4435
+ return listCoworkSessions(opts);
4436
+ },
4437
+ async getSession(id) {
4438
+ return getCoworkSession(id);
4439
+ }
4440
+ };
4441
+ agentSources = [
4442
+ claudeCodeSource,
4443
+ codexSource,
4444
+ geminiSource,
4445
+ antigravitySource,
4446
+ coworkSource
4447
+ ];
3356
4448
  }
3357
4449
  });
3358
4450
 
@@ -3764,8 +4856,10 @@ var init_aggregate = __esm({
3764
4856
  // ../parser/dist/index.js
3765
4857
  var dist_exports = {};
3766
4858
  __export(dist_exports, {
4859
+ ANTIGRAVITY_METADATA: () => ANTIGRAVITY_METADATA,
3767
4860
  CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
3768
4861
  CODEX_METADATA: () => CODEX_METADATA,
4862
+ COWORK_METADATA: () => COWORK_METADATA,
3769
4863
  GEMINI_METADATA: () => GEMINI_METADATA,
3770
4864
  PRICES: () => PRICES,
3771
4865
  RATE_PER_PCT: () => RATE_PER_PCT,
@@ -3806,6 +4900,7 @@ __export(dist_exports, {
3806
4900
  predictUtilization: () => predictUtilization,
3807
4901
  priorCalendarMonth: () => priorCalendarMonth,
3808
4902
  priorCalendarWeek: () => priorCalendarWeek,
4903
+ projectRepoName: () => projectRepoName,
3809
4904
  rowPrimaryIndex: () => rowPrimaryIndex,
3810
4905
  sessionAirTimeMs: () => sessionAirTimeMs,
3811
4906
  sessionDay: () => sessionDay,
@@ -3830,10 +4925,198 @@ var init_dist = __esm({
3830
4925
  }
3831
4926
  });
3832
4927
 
4928
+ // src/perception/file-probe.ts
4929
+ var file_probe_exports = {};
4930
+ __export(file_probe_exports, {
4931
+ pathHash: () => pathHash,
4932
+ probeArtifactSignals: () => probeArtifactSignals
4933
+ });
4934
+ import { createHash } from "node:crypto";
4935
+ import { existsSync as existsSync6, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
4936
+ import { homedir as homedir2 } from "node:os";
4937
+ import { join as join7, relative, resolve as resolve2, sep } from "node:path";
4938
+ import { execFileSync as execFileSync2 } from "node:child_process";
4939
+ function pathHash(relPath) {
4940
+ return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
4941
+ }
4942
+ function defaultScanRoots(extraRoots = []) {
4943
+ const roots = [];
4944
+ const home = join7(homedir2(), ".claude");
4945
+ if (existsSync6(home)) roots.push({ root: home, label: "user" });
4946
+ for (const e of extraRoots) {
4947
+ const r = resolve2(e, ".claude");
4948
+ if (existsSync6(r) && r !== home) roots.push({ root: r, label: "project" });
4949
+ }
4950
+ return roots;
4951
+ }
4952
+ function listMarkdownFiles(dir) {
4953
+ if (!existsSync6(dir)) return [];
4954
+ const out = [];
4955
+ let entries;
4956
+ try {
4957
+ entries = readdirSync3(dir);
4958
+ } catch {
4959
+ return [];
4960
+ }
4961
+ for (const name of entries) {
4962
+ if (name.startsWith(".")) continue;
4963
+ const full = join7(dir, name);
4964
+ let stat;
4965
+ try {
4966
+ stat = statSync3(full);
4967
+ } catch {
4968
+ continue;
4969
+ }
4970
+ if (stat.isDirectory()) {
4971
+ out.push(...listMarkdownFiles(full));
4972
+ } else if (stat.isFile() && name.endsWith(".md")) {
4973
+ out.push(full);
4974
+ }
4975
+ }
4976
+ return out;
4977
+ }
4978
+ function firstSeenDateOf(file) {
4979
+ try {
4980
+ const out = execFileSync2(
4981
+ "git",
4982
+ ["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
4983
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname6(file) }
4984
+ ).trim().split("\n").filter(Boolean);
4985
+ if (out.length > 0) return out[out.length - 1];
4986
+ } catch {
4987
+ }
4988
+ try {
4989
+ const s = statSync3(file);
4990
+ return new Date((s.birthtime || s.mtime).getTime()).toISOString().slice(0, 10);
4991
+ } catch {
4992
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4993
+ }
4994
+ }
4995
+ function dirname6(p) {
4996
+ const i = p.lastIndexOf(sep);
4997
+ return i < 0 ? "." : p.slice(0, i);
4998
+ }
4999
+ function detectGitEmail(cwd) {
5000
+ try {
5001
+ return execFileSync2("git", ["config", "user.email"], {
5002
+ encoding: "utf8",
5003
+ stdio: ["ignore", "pipe", "ignore"],
5004
+ cwd
5005
+ }).trim() || null;
5006
+ } catch {
5007
+ return null;
5008
+ }
5009
+ }
5010
+ function todayLocal() {
5011
+ const d = /* @__PURE__ */ new Date();
5012
+ const y = d.getFullYear();
5013
+ const m = String(d.getMonth() + 1).padStart(2, "0");
5014
+ const day = String(d.getDate()).padStart(2, "0");
5015
+ return `${y}-${m}-${day}`;
5016
+ }
5017
+ function scanAuthored(roots, subdir, day) {
5018
+ const out = [];
5019
+ for (const r of roots) {
5020
+ const dir = join7(r.root, subdir);
5021
+ if (!existsSync6(dir)) continue;
5022
+ for (const f of listMarkdownFiles(dir)) {
5023
+ const firstSeen = firstSeenDateOf(f);
5024
+ if (firstSeen !== day) continue;
5025
+ const rel = relative(dir, f);
5026
+ out.push({ pathHash: pathHash(`${r.label}:${subdir}:${rel}`), firstSeenDate: firstSeen });
5027
+ }
5028
+ }
5029
+ return out;
5030
+ }
5031
+ function scanEdited(roots, day) {
5032
+ const out = [];
5033
+ for (const r of roots) {
5034
+ const dir = join7(r.root, "skills");
5035
+ if (!existsSync6(dir)) continue;
5036
+ for (const f of listMarkdownFiles(dir)) {
5037
+ const firstSeen = firstSeenDateOf(f);
5038
+ if (firstSeen === day) continue;
5039
+ let stat;
5040
+ try {
5041
+ stat = statSync3(f);
5042
+ } catch {
5043
+ continue;
5044
+ }
5045
+ const mtimeDay = new Date(stat.mtime.getTime()).toISOString().slice(0, 10);
5046
+ if (mtimeDay !== day) continue;
5047
+ const rel = relative(dir, f);
5048
+ out.push({ pathHash: pathHash(`${r.label}:skills:${rel}`), lineDelta: 0 });
5049
+ }
5050
+ }
5051
+ return out;
5052
+ }
5053
+ function claudemdLineDelta(extraRoots, authorEmail, day) {
5054
+ let delta = 0;
5055
+ const candidates = [];
5056
+ for (const e of extraRoots) {
5057
+ const f = resolve2(e, "CLAUDE.md");
5058
+ if (existsSync6(f)) candidates.push(f);
5059
+ }
5060
+ const homeClaudeMd = join7(homedir2(), "CLAUDE.md");
5061
+ if (existsSync6(homeClaudeMd)) candidates.push(homeClaudeMd);
5062
+ for (const file of candidates) {
5063
+ try {
5064
+ const out = execFileSync2(
5065
+ "git",
5066
+ ["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
5067
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname6(file) }
5068
+ );
5069
+ let currentDate = "";
5070
+ let currentEmail = "";
5071
+ for (const line of out.split("\n")) {
5072
+ if (line.startsWith("COMMIT ")) {
5073
+ const parts = line.slice("COMMIT ".length).trim().split(/\s+/);
5074
+ currentDate = parts[0] ?? "";
5075
+ currentEmail = parts.slice(1).join(" ");
5076
+ } else if (currentDate === day && line.trim().length > 0) {
5077
+ if (authorEmail && currentEmail !== authorEmail) continue;
5078
+ const parts = line.split(/\s+/);
5079
+ const added = Number(parts[0]);
5080
+ const removed = Number(parts[1]);
5081
+ if (Number.isFinite(added) && Number.isFinite(removed)) {
5082
+ delta += added - removed;
5083
+ }
5084
+ }
5085
+ }
5086
+ } catch {
5087
+ }
5088
+ }
5089
+ return delta;
5090
+ }
5091
+ function probeArtifactSignals(opts = {}) {
5092
+ const day = opts.day ?? todayLocal();
5093
+ const roots = defaultScanRoots(opts.extraRoots);
5094
+ const skillsAuthored = scanAuthored(roots, "skills", day);
5095
+ const subagentsAuthored = scanAuthored(roots, "agents", day);
5096
+ const slashCommandsAuthored = scanAuthored(roots, "commands", day);
5097
+ const skillsEdited = scanEdited(roots, day);
5098
+ const authorEmail = opts.authorEmail ?? detectGitEmail(opts.extraRoots?.[0] ?? process.cwd()) ?? void 0;
5099
+ const claudemd = claudemdLineDelta(opts.extraRoots ?? [], authorEmail, day);
5100
+ const empty = skillsAuthored.length === 0 && subagentsAuthored.length === 0 && slashCommandsAuthored.length === 0 && skillsEdited.length === 0 && claudemd === 0;
5101
+ if (empty) return null;
5102
+ return {
5103
+ skillsAuthored,
5104
+ skillsEdited,
5105
+ subagentsAuthored,
5106
+ slashCommandsAuthored,
5107
+ claudemdLineDelta: claudemd
5108
+ };
5109
+ }
5110
+ var init_file_probe = __esm({
5111
+ "src/perception/file-probe.ts"() {
5112
+ "use strict";
5113
+ }
5114
+ });
5115
+
3833
5116
  // src/daemon-worker.ts
3834
5117
  import { spawn as spawn2 } from "node:child_process";
3835
- import { appendFileSync as appendFileSync5, closeSync, existsSync as existsSync11, mkdirSync as mkdirSync13, openSync, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "node:fs";
3836
- import { dirname as dirname8, join as join9 } from "node:path";
5118
+ import { appendFileSync as appendFileSync5, closeSync, existsSync as existsSync13, mkdirSync as mkdirSync13, openSync, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
5119
+ import { dirname as dirname10, join as join11 } from "node:path";
3837
5120
  import { fileURLToPath } from "node:url";
3838
5121
 
3839
5122
  // src/usage/token.ts
@@ -3864,9 +5147,9 @@ function readFromCredentialsFile() {
3864
5147
  join(homedir(), ".claude", ".credentials.json"),
3865
5148
  join(homedir(), ".config", "claude", "credentials.json")
3866
5149
  ];
3867
- for (const path5 of candidates) {
5150
+ for (const path7 of candidates) {
3868
5151
  try {
3869
- const blob = readFileSync(path5, "utf8");
5152
+ const blob = readFileSync(path7, "utf8");
3870
5153
  const creds = extractCredentials(blob);
3871
5154
  if (creds) return creds;
3872
5155
  } catch {
@@ -4287,16 +5570,12 @@ function bucketToRollup(b) {
4287
5570
  };
4288
5571
  }
4289
5572
  function buildRollupsForRange(sessions, sinceDay) {
4290
- const buckets = dailyActivity(sessions);
4291
5573
  const startCounts = /* @__PURE__ */ new Map();
4292
5574
  for (const s of sessions) {
4293
5575
  const d = sessionDay(s);
4294
5576
  if (d) startCounts.set(d, (startCounts.get(d) ?? 0) + 1);
4295
5577
  }
4296
- return buckets.filter((b) => !sinceDay || b.date >= sinceDay).map((b) => ({
4297
- ...bucketToRollup(b),
4298
- sessions: startCounts.get(b.date) ?? 0
4299
- }));
5578
+ return dailyActivity(sessions).filter((b) => !sinceDay || b.date >= sinceDay).map((b) => ({ ...bucketToRollup(b), uniqueSessions: startCounts.get(b.date) ?? 0 }));
4300
5579
  }
4301
5580
  function dayBoundsMs(day) {
4302
5581
  const [y, m, d] = day.split("-").map(Number);
@@ -4322,7 +5601,7 @@ function sessionTouchesDay(s, day) {
4322
5601
  }
4323
5602
  return sessionDay(s) === day;
4324
5603
  }
4325
- function buildRichRollupBlocks(day, daySessions, entries, privateProjects) {
5604
+ function buildRichRollupBlocks(day, daySessions, entries, privateProjects, resolveRepo) {
4326
5605
  const bounds = dayBoundsMs(day);
4327
5606
  const clippedSessions = [];
4328
5607
  for (const s of daySessions) {
@@ -4332,16 +5611,40 @@ function buildRichRollupBlocks(day, daySessions, entries, privateProjects) {
4332
5611
  }
4333
5612
  const bursts = computeBurstsFromSessions(clippedSessions);
4334
5613
  const stats = summarizeBursts(bursts);
5614
+ const repoForEntry = (e) => {
5615
+ if (resolveRepo) {
5616
+ const own = resolveRepo(e.project);
5617
+ if (own) return own;
5618
+ const counts = /* @__PURE__ */ new Map();
5619
+ for (const d of e.edited_dirs ?? []) {
5620
+ const r = resolveRepo(d);
5621
+ if (r) counts.set(r, (counts.get(r) ?? 0) + 1);
5622
+ }
5623
+ const dominant = [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
5624
+ if (dominant) return dominant;
5625
+ }
5626
+ return e.github_repos?.length === 1 ? e.github_repos[0] : null;
5627
+ };
5628
+ const sessionRepo = /* @__PURE__ */ new Map();
5629
+ for (const e of entries) {
5630
+ if (privateProjects.has(projectRepoName(e.project)) || privateProjects.has(e.project)) continue;
5631
+ const r = repoForEntry(e);
5632
+ if (r) sessionRepo.set(e.session_id, r);
5633
+ }
4335
5634
  const projects = /* @__PURE__ */ new Map();
4336
5635
  for (const s of clippedSessions) {
4337
- const name = canonicalProjectName(s.projectName);
4338
- if (privateProjects.has(name)) continue;
5636
+ const canonical = canonicalProjectName(s.projectName);
5637
+ const name = projectRepoName(s.projectName);
5638
+ if (privateProjects.has(name) || privateProjects.has(canonical)) continue;
5639
+ const repo = resolveRepo?.(canonical) ?? sessionRepo.get(s.id);
5640
+ const key = repo ?? name;
4339
5641
  const ms = s.activeSegments.reduce((sum, seg) => sum + (seg.endMs - seg.startMs), 0);
4340
- const cur = projects.get(name) ?? { agentTimeMs: 0, sessions: 0 };
5642
+ const cur = projects.get(key) ?? { project: name, agentTimeMs: 0, sessions: 0, ...repo ? { resolved: repo } : {} };
4341
5643
  cur.agentTimeMs += ms;
4342
5644
  cur.sessions += 1;
4343
- projects.set(name, cur);
5645
+ projects.set(key, cur);
4344
5646
  }
5647
+ const projectRepos = /* @__PURE__ */ new Map();
4345
5648
  const workingShapes = /* @__PURE__ */ new Map();
4346
5649
  const skills = /* @__PURE__ */ new Map();
4347
5650
  const subagents = /* @__PURE__ */ new Map();
@@ -4355,12 +5658,12 @@ function buildRichRollupBlocks(day, daySessions, entries, privateProjects) {
4355
5658
  let longTotalMin = 0;
4356
5659
  let longMaxSingleMin = 0;
4357
5660
  for (const e of entries) {
4358
- if (privateProjects.has(e.project)) continue;
5661
+ if (privateProjects.has(projectRepoName(e.project)) || privateProjects.has(e.project)) continue;
4359
5662
  const shape = e.signals?.working_shape ?? null;
4360
5663
  if (shape) {
4361
5664
  const cur = workingShapes.get(shape) ?? { sessions: 0, agentTimeMs: 0 };
4362
5665
  cur.sessions += 1;
4363
- cur.agentTimeMs += e.numbers.active_min * 6e4;
5666
+ cur.agentTimeMs += Math.round(e.numbers.active_min * 6e4);
4364
5667
  workingShapes.set(shape, cur);
4365
5668
  }
4366
5669
  for (const [name, count] of Object.entries(e.skills)) {
@@ -4375,6 +5678,12 @@ function buildRichRollupBlocks(day, daySessions, entries, privateProjects) {
4375
5678
  prs += e.numbers.prs;
4376
5679
  commits += e.numbers.commits;
4377
5680
  pushes += e.numbers.pushes;
5681
+ if (e.github_repos?.length) {
5682
+ const key = sessionRepo.get(e.session_id) ?? projectRepoName(e.project);
5683
+ const set = projectRepos.get(key) ?? /* @__PURE__ */ new Set();
5684
+ for (const r of e.github_repos) set.add(r);
5685
+ projectRepos.set(key, set);
5686
+ }
4378
5687
  if (e.flags.includes("long_autonomous")) {
4379
5688
  longCount += 1;
4380
5689
  longTotalMin += e.numbers.active_min;
@@ -4382,11 +5691,21 @@ function buildRichRollupBlocks(day, daySessions, entries, privateProjects) {
4382
5691
  }
4383
5692
  }
4384
5693
  return {
4385
- projects: Array.from(projects.entries()).map(([project, v]) => ({ project, ...v })).sort((a, b) => b.agentTimeMs - a.agentTimeMs),
5694
+ projects: Array.from(projects.entries()).map(([key, v]) => {
5695
+ const extras = [...projectRepos.get(key) ?? []].filter((r) => r !== v.resolved);
5696
+ const repos = v.resolved ? [v.resolved, ...extras] : extras;
5697
+ return {
5698
+ project: v.project,
5699
+ agentTimeMs: v.agentTimeMs,
5700
+ sessions: v.sessions,
5701
+ ...repos.length ? { githubRepos: repos.slice(0, 5) } : {}
5702
+ };
5703
+ }).sort((a, b) => b.agentTimeMs - a.agentTimeMs),
4386
5704
  workingShapes: Array.from(workingShapes.entries()).map(([shape, v]) => ({ shape, ...v })).sort((a, b) => b.sessions - a.sessions),
4387
5705
  concurrencyPeak: stats.peakConcurrent,
4388
5706
  parallelMinutes: Math.round(stats.totalParallelMs / 6e4),
4389
- longAutonomous: { count: longCount, totalMin: longTotalMin, maxSingleMin: longMaxSingleMin },
5707
+ // Wire schema requires integer minutes (active_min is a float).
5708
+ longAutonomous: { count: longCount, totalMin: Math.round(longTotalMin), maxSingleMin: Math.round(longMaxSingleMin) },
4390
5709
  toolErrors,
4391
5710
  skillsLoaded: Array.from(skills.entries()).map(([name, sessions]) => ({ name, sessions })).sort((a, b) => b.sessions - a.sessions),
4392
5711
  subagentsDispatched: Array.from(subagents.entries()).map(([type, count]) => ({ type, count })).sort((a, b) => b.count - a.count),
@@ -4415,10 +5734,10 @@ function buildEnrichedExtras(entries) {
4415
5734
  }
4416
5735
  return { outcomeMix, helpfulnessMix, goalMix };
4417
5736
  }
4418
- function buildRichBlocksForDay(day, daySessions, privateProjects, enrichmentOptIn) {
5737
+ function buildRichBlocksForDay(day, daySessions, privateProjects, enrichmentOptIn, resolveRepo) {
4419
5738
  const entries = listEntriesForDay(day);
4420
5739
  if (entries.length === 0) return void 0;
4421
- const rich = buildRichRollupBlocks(day, daySessions, entries, privateProjects);
5740
+ const rich = buildRichRollupBlocks(day, daySessions, entries, privateProjects, resolveRepo);
4422
5741
  const enriched = enrichmentOptIn ? buildEnrichedExtras(entries) : void 0;
4423
5742
  return enriched ? { rich, enriched } : { rich };
4424
5743
  }
@@ -4427,10 +5746,11 @@ function buildIngestPayload(inputs) {
4427
5746
  return {
4428
5747
  ingestId: randomUUID(),
4429
5748
  observedAt: (/* @__PURE__ */ new Date()).toISOString(),
4430
- ...richRollup || inputs.enrichedExtras ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
5749
+ ...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
4431
5750
  ...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
4432
5751
  ...richRollup ? { richRollup } : {},
4433
5752
  ...inputs.enrichedExtras ? { enrichedExtras: inputs.enrichedExtras } : {},
5753
+ ...inputs.artifactSignals ? { artifactSignals: inputs.artifactSignals } : {},
4434
5754
  ...inputs.usageSnapshot ? { usageSnapshot: inputs.usageSnapshot } : {},
4435
5755
  ...inputs.planTier ? { planTier: inputs.planTier } : {},
4436
5756
  ...inputs.cyclePeaks ? { cyclePeaks: inputs.cyclePeaks } : {}
@@ -4450,19 +5770,81 @@ async function pushToTeamServer(config, payload) {
4450
5770
  return { ok: res.ok, status: res.status, body };
4451
5771
  }
4452
5772
 
5773
+ // src/team/git-remote.ts
5774
+ import { existsSync as existsSync4, readFileSync as readFileSync6, statSync } from "node:fs";
5775
+ import { dirname as dirname3, isAbsolute, join as join5, resolve } from "node:path";
5776
+ var GITHUB_URL_RE = /github\.com[:/]([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/;
5777
+ function parseGithubRemote(url) {
5778
+ const m = url.trim().match(GITHUB_URL_RE);
5779
+ return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
5780
+ }
5781
+ function originUrl(configText) {
5782
+ let inOrigin = false;
5783
+ for (const line of configText.split("\n")) {
5784
+ const t = line.trim();
5785
+ if (t.startsWith("[")) {
5786
+ inOrigin = /^\[remote\s+"origin"\]/.test(t);
5787
+ continue;
5788
+ }
5789
+ if (!inOrigin) continue;
5790
+ const m = t.match(/^url\s*=\s*(.+)$/);
5791
+ if (m) return m[1].trim();
5792
+ }
5793
+ return null;
5794
+ }
5795
+ function gitConfigPathFor(dir) {
5796
+ const dotGit = join5(dir, ".git");
5797
+ const st = statSync(dotGit, { throwIfNoEntry: false });
5798
+ if (!st) return null;
5799
+ if (st.isDirectory()) return join5(dotGit, "config");
5800
+ const m = readFileSync6(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
5801
+ if (!m) return null;
5802
+ const gd = isAbsolute(m[1]) ? m[1] : resolve(dir, m[1]);
5803
+ const commondirFile = join5(gd, "commondir");
5804
+ if (existsSync4(commondirFile)) {
5805
+ const common = readFileSync6(commondirFile, "utf8").trim();
5806
+ return join5(isAbsolute(common) ? common : resolve(gd, common), "config");
5807
+ }
5808
+ return join5(gd, "config");
5809
+ }
5810
+ function createRepoResolver() {
5811
+ const cache = /* @__PURE__ */ new Map();
5812
+ return (dir) => {
5813
+ if (!dir || !isAbsolute(dir)) return null;
5814
+ const hit = cache.get(dir);
5815
+ if (hit !== void 0) return hit;
5816
+ let repo = null;
5817
+ try {
5818
+ for (let d = dir; ; d = dirname3(d)) {
5819
+ const config = gitConfigPathFor(d);
5820
+ if (config && existsSync4(config)) {
5821
+ const url = originUrl(readFileSync6(config, "utf8"));
5822
+ repo = url ? parseGithubRemote(url) : null;
5823
+ break;
5824
+ }
5825
+ if (d === dirname3(d)) break;
5826
+ }
5827
+ } catch {
5828
+ repo = null;
5829
+ }
5830
+ cache.set(dir, repo);
5831
+ return repo;
5832
+ };
5833
+ }
5834
+
4453
5835
  // src/team/queue.ts
4454
5836
  init_fs();
4455
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, appendFileSync as appendFileSync2, statSync, mkdirSync as mkdirSync5 } from "node:fs";
4456
- import { dirname as dirname3 } from "node:path";
5837
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, appendFileSync as appendFileSync2, statSync as statSync2, mkdirSync as mkdirSync5 } from "node:fs";
5838
+ import { dirname as dirname4 } from "node:path";
4457
5839
  var QUEUE_PATH = cclensPath("ingest-queue.jsonl");
4458
5840
  var MAX_SIZE_BYTES = 10 * 1024 * 1024;
4459
5841
  var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
4460
5842
  function enqueuePayload(payload, queuePath = QUEUE_PATH) {
4461
- mkdirSync5(dirname3(queuePath), { recursive: true });
5843
+ mkdirSync5(dirname4(queuePath), { recursive: true });
4462
5844
  const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
4463
5845
  appendFileSync2(queuePath, JSON.stringify(entry) + "\n", "utf8");
4464
5846
  try {
4465
- const { size } = statSync(queuePath);
5847
+ const { size } = statSync2(queuePath);
4466
5848
  if (size > MAX_SIZE_BYTES) {
4467
5849
  pruneOldest(queuePath);
4468
5850
  }
@@ -4472,7 +5854,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
4472
5854
  function dequeuePayloads(queuePath = QUEUE_PATH) {
4473
5855
  let lines;
4474
5856
  try {
4475
- lines = readFileSync6(queuePath, "utf8").trim().split("\n").filter(Boolean);
5857
+ lines = readFileSync7(queuePath, "utf8").trim().split("\n").filter(Boolean);
4476
5858
  } catch {
4477
5859
  return [];
4478
5860
  }
@@ -4493,7 +5875,7 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
4493
5875
  function pruneOldest(queuePath) {
4494
5876
  let lines;
4495
5877
  try {
4496
- lines = readFileSync6(queuePath, "utf8").trim().split("\n").filter(Boolean);
5878
+ lines = readFileSync7(queuePath, "utf8").trim().split("\n").filter(Boolean);
4497
5879
  } catch {
4498
5880
  return;
4499
5881
  }
@@ -4506,8 +5888,8 @@ init_storage();
4506
5888
  import { randomUUID as randomUUID2 } from "node:crypto";
4507
5889
 
4508
5890
  // src/usage/profile.ts
4509
- import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
4510
- import { dirname as dirname4 } from "node:path";
5891
+ import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
5892
+ import { dirname as dirname5 } from "node:path";
4511
5893
  var PROFILE_ENDPOINT = "https://api.anthropic.com/api/oauth/profile";
4512
5894
  var BETA_HEADER2 = "oauth-2025-04-20";
4513
5895
  var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -4550,9 +5932,9 @@ async function fetchProfile(nowMs = Date.now()) {
4550
5932
  };
4551
5933
  }
4552
5934
  function readCachedProfile(cachePath) {
4553
- if (!existsSync4(cachePath)) return null;
5935
+ if (!existsSync5(cachePath)) return null;
4554
5936
  try {
4555
- const raw = JSON.parse(readFileSync7(cachePath, "utf8"));
5937
+ const raw = JSON.parse(readFileSync8(cachePath, "utf8"));
4556
5938
  if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
4557
5939
  return raw;
4558
5940
  } catch {
@@ -4560,7 +5942,7 @@ function readCachedProfile(cachePath) {
4560
5942
  }
4561
5943
  }
4562
5944
  function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
4563
- mkdirSync6(dirname4(cachePath), { recursive: true });
5945
+ mkdirSync6(dirname5(cachePath), { recursive: true });
4564
5946
  writeFileSync5(
4565
5947
  cachePath,
4566
5948
  JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
@@ -4722,12 +6104,12 @@ async function runTeamBackfill(log3 = noopLog, filePath = USAGE_LOG, configOverr
4722
6104
  // src/team/last-push.ts
4723
6105
  init_fs();
4724
6106
  import { writeFileSync as writeFileSync6, unlinkSync as unlinkSync2, mkdirSync as mkdirSync7 } from "node:fs";
4725
- import { join as join5 } from "node:path";
6107
+ import { join as join6 } from "node:path";
4726
6108
  var LAST_PUSH_FILE = "team-last-push.json";
4727
6109
  function write(record, dir) {
4728
6110
  const d = dir ?? cclensHome();
4729
6111
  mkdirSync7(d, { recursive: true });
4730
- writeFileSync6(join5(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
6112
+ writeFileSync6(join6(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
4731
6113
  }
4732
6114
  function writeLastPushSuccess(payload, dir) {
4733
6115
  write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
@@ -4753,6 +6135,7 @@ async function dispatchCommand(command, config, log3) {
4753
6135
  async function runActivityBackfill(command, config, log3) {
4754
6136
  const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
4755
6137
  const { toLocalDay: toLocalDay3 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
6138
+ const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
4756
6139
  const days = command.params.days;
4757
6140
  const todayMs = Date.now();
4758
6141
  const targetDayMs = todayMs - (days - 1) * 24 * 60 * 60 * 1e3;
@@ -4778,9 +6161,24 @@ async function runActivityBackfill(command, config, log3) {
4778
6161
  summary: { pushed: 0, fromDay: targetDay }
4779
6162
  };
4780
6163
  }
6164
+ const privateProjects = new Set(config.privateProjects ?? []);
6165
+ const enrichmentOptIn = !!config.enrichmentOptIn;
6166
+ const resolveRepo = createRepoResolver();
4781
6167
  let pushed = 0;
4782
6168
  for (const rollup of rollups) {
4783
- const payload = buildIngestPayload({ rollup });
6169
+ const daySessions = sessions.filter((s) => sessionTouchesDay(s, rollup.day));
6170
+ const richBlocks = buildRichBlocksForDay(rollup.day, daySessions, privateProjects, enrichmentOptIn, resolveRepo);
6171
+ let artifactSignals = null;
6172
+ try {
6173
+ artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: [process.cwd()] });
6174
+ } catch {
6175
+ }
6176
+ const payload = buildIngestPayload({
6177
+ rollup,
6178
+ richExtras: richBlocks?.rich,
6179
+ enrichedExtras: richBlocks?.enriched,
6180
+ artifactSignals: artifactSignals ?? void 0
6181
+ });
4784
6182
  const result = await pushToTeamServer(config, payload);
4785
6183
  if (!result.ok) {
4786
6184
  return {
@@ -4906,6 +6304,8 @@ async function runTeamSync(log3 = noopLog2, configOverride, options = {}) {
4906
6304
  let lastPushedDay;
4907
6305
  const privateProjects = new Set(config.privateProjects ?? []);
4908
6306
  const enrichmentOptIn = !!config.enrichmentOptIn;
6307
+ const resolveRepo = createRepoResolver();
6308
+ const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
4909
6309
  for (let i = 0; i < rollups.length; i++) {
4910
6310
  const rollup = rollups[i];
4911
6311
  const isLatest = i === rollups.length - 1;
@@ -4914,12 +6314,22 @@ async function runTeamSync(log3 = noopLog2, configOverride, options = {}) {
4914
6314
  rollup.day,
4915
6315
  daySessions,
4916
6316
  privateProjects,
4917
- enrichmentOptIn
6317
+ enrichmentOptIn,
6318
+ resolveRepo
4918
6319
  );
6320
+ let artifactSignals = null;
6321
+ try {
6322
+ artifactSignals = probeArtifactSignals2({
6323
+ day: rollup.day,
6324
+ extraRoots: [process.cwd()]
6325
+ });
6326
+ } catch {
6327
+ }
4919
6328
  const payload = buildIngestPayload({
4920
6329
  rollup,
4921
6330
  richExtras: richBlocks?.rich,
4922
6331
  enrichedExtras: richBlocks?.enriched,
6332
+ artifactSignals: artifactSignals ?? void 0,
4923
6333
  usageSnapshot: isLatest ? usageSnapshot : void 0,
4924
6334
  planTier,
4925
6335
  // Same rationale as usageSnapshot — current cycle data only on the
@@ -5038,8 +6448,8 @@ async function buildCyclePeaksForPush(planTier, loadCurve) {
5038
6448
  // src/perception/worker.ts
5039
6449
  init_dist();
5040
6450
  init_fs();
5041
- import { statSync as statSync2, readFileSync as readFileSync9 } from "node:fs";
5042
- import { basename, dirname as dirname6 } from "node:path";
6451
+ import { statSync as statSync4, readFileSync as readFileSync10 } from "node:fs";
6452
+ import { basename, dirname as dirname8 } from "node:path";
5043
6453
 
5044
6454
  // ../entries/dist/signals.js
5045
6455
  init_dist();
@@ -5271,7 +6681,7 @@ function viewEvent(ev) {
5271
6681
  cwd: rawCwd
5272
6682
  };
5273
6683
  }
5274
- var IDLE_GAP_MS3 = 3 * 60 * 1e3;
6684
+ var IDLE_GAP_MS4 = 3 * 60 * 1e3;
5275
6685
  var INTERRUPT_RE2 = /\[request interrupted|interrupted by user/i;
5276
6686
  var PR_TITLE_RE = /--title\s+["']([^"']+)["']/;
5277
6687
  var BASH_CHAIN_SPLIT_RE = /\|\||&&|;|\|/;
@@ -5383,7 +6793,7 @@ function closeTurn(t, closed, cwd) {
5383
6793
  let active = 0;
5384
6794
  for (let i = 1; i < ts.length; i++) {
5385
6795
  const dt = ts[i] - ts[i - 1];
5386
- if (dt < IDLE_GAP_MS3)
6796
+ if (dt < IDLE_GAP_MS4)
5387
6797
  active += dt;
5388
6798
  }
5389
6799
  closed.push({
@@ -5410,6 +6820,9 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
5410
6820
  const prTitles = [];
5411
6821
  let commits = 0;
5412
6822
  let pushes = 0;
6823
+ const gitToolUseIds = /* @__PURE__ */ new Set();
6824
+ const githubRepos = /* @__PURE__ */ new Set();
6825
+ const editedDirCounts = /* @__PURE__ */ new Map();
5413
6826
  const modelTurns = /* @__PURE__ */ new Map();
5414
6827
  let totalToolErrors = 0;
5415
6828
  let totalInterrupts = 0;
@@ -5451,11 +6864,23 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
5451
6864
  } else {
5452
6865
  if (Array.isArray(content)) {
5453
6866
  for (const c of content) {
5454
- if (c && typeof c === "object" && c.type === "tool_result" && c.is_error) {
6867
+ if (!c || typeof c !== "object" || c.type !== "tool_result")
6868
+ continue;
6869
+ if (c.is_error) {
5455
6870
  totalToolErrors++;
5456
6871
  if (cur)
5457
6872
  cur.toolErrors++;
5458
6873
  }
6874
+ const tuId = c.tool_use_id;
6875
+ if (tuId && gitToolUseIds.has(tuId)) {
6876
+ const rc = c.content;
6877
+ const text = typeof rc === "string" ? rc : Array.isArray(rc) ? rc.map((b) => b && typeof b === "object" && typeof b.text === "string" ? b.text : "").join("\n") : "";
6878
+ for (const m of text.matchAll(/(?<![.\w])github\.com[:/]([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git\b|[/\s"'),]|$)/g)) {
6879
+ if (m[1].toLowerCase() === "user-attachments")
6880
+ continue;
6881
+ githubRepos.add(`${m[1]}/${m[2]}`.toLowerCase());
6882
+ }
6883
+ }
5459
6884
  }
5460
6885
  }
5461
6886
  if (cur && tsMs !== void 0) {
@@ -5511,10 +6936,6 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
5511
6936
  if (name === "Skill") {
5512
6937
  const sk = String(ct.input?.skill ?? "unknown");
5513
6938
  cur.skills.set(sk, (cur.skills.get(sk) ?? 0) + 1);
5514
- } else if (name === "ToolSearch") {
5515
- const q = String(ct.input?.query ?? "");
5516
- const key = `(ToolSearch: ${trunc(q, 60)})`;
5517
- cur.skills.set(key, (cur.skills.get(key) ?? 0) + 1);
5518
6939
  }
5519
6940
  if (name === "Agent") {
5520
6941
  const inp = ct.input ?? {};
@@ -5544,10 +6965,20 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
5544
6965
  commits++;
5545
6966
  if (/\bgit\s+push\b/.test(cmd))
5546
6967
  pushes++;
6968
+ if (ct.id && /\bgit\s+push\b|\bgh\s+pr\s+/.test(cmd))
6969
+ gitToolUseIds.add(ct.id);
5547
6970
  }
5548
6971
  if (eventCwd && (name === "Bash" || name === "Edit" || name === "Write" || name === "Read")) {
5549
6972
  cwdCounts.set(eventCwd, (cwdCounts.get(eventCwd) ?? 0) + 1);
5550
6973
  }
6974
+ if (name === "Edit" || name === "Write" || name === "MultiEdit" || name === "NotebookEdit") {
6975
+ const fp = String(ct.input?.file_path ?? ct.input?.notebook_path ?? "");
6976
+ const slash = fp.lastIndexOf("/");
6977
+ if (slash > 0) {
6978
+ const dir = fp.slice(0, slash);
6979
+ editedDirCounts.set(dir, (editedDirCounts.get(dir) ?? 0) + 1);
6980
+ }
6981
+ }
5551
6982
  }
5552
6983
  }
5553
6984
  }
@@ -5559,7 +6990,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
5559
6990
  let activeMs2 = 0;
5560
6991
  for (let i = 1; i < tsSorted.length; i++) {
5561
6992
  const dt = tsSorted[i] - tsSorted[i - 1];
5562
- if (dt < IDLE_GAP_MS3)
6993
+ if (dt < IDLE_GAP_MS4)
5563
6994
  activeMs2 += dt;
5564
6995
  }
5565
6996
  const tsSortedStrings = dayEvents.map((e) => e.timestamp).filter((t) => !!t).sort();
@@ -5572,6 +7003,8 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
5572
7003
  prTitles,
5573
7004
  commits,
5574
7005
  pushes,
7006
+ githubRepos: [...githubRepos].slice(0, 5),
7007
+ editedDirs: [...editedDirCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 8).map(([dir]) => dir),
5575
7008
  modelTurns,
5576
7009
  totalToolErrors,
5577
7010
  totalInterrupts,
@@ -5725,6 +7158,8 @@ function buildEntries(sessionDetail) {
5725
7158
  first_user,
5726
7159
  final_agent,
5727
7160
  pr_titles: agg.prTitles,
7161
+ ...agg.githubRepos.length ? { github_repos: agg.githubRepos } : {},
7162
+ ...agg.editedDirs.length ? { edited_dirs: agg.editedDirs } : {},
5728
7163
  top_tools,
5729
7164
  skills,
5730
7165
  subagents,
@@ -5744,8 +7179,8 @@ function buildEntries(sessionDetail) {
5744
7179
 
5745
7180
  // src/perception/state.ts
5746
7181
  init_fs();
5747
- import { existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, renameSync as renameSync3 } from "node:fs";
5748
- import { dirname as dirname5 } from "node:path";
7182
+ import { existsSync as existsSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, renameSync as renameSync3 } from "node:fs";
7183
+ import { dirname as dirname7 } from "node:path";
5749
7184
  var STALE_MS = 15 * 60 * 1e3;
5750
7185
  var pathCached = null;
5751
7186
  function statePath() {
@@ -5755,7 +7190,7 @@ function statePath() {
5755
7190
  }
5756
7191
  function readState() {
5757
7192
  const p = statePath();
5758
- if (!existsSync5(p)) {
7193
+ if (!existsSync7(p)) {
5759
7194
  return {
5760
7195
  sweep_in_progress: false,
5761
7196
  last_sweep_started_at: null,
@@ -5763,12 +7198,12 @@ function readState() {
5763
7198
  file_checkpoints: {}
5764
7199
  };
5765
7200
  }
5766
- const raw = readFileSync8(p, "utf8");
7201
+ const raw = readFileSync9(p, "utf8");
5767
7202
  return JSON.parse(raw);
5768
7203
  }
5769
7204
  function writeState(s) {
5770
7205
  const p = statePath();
5771
- mkdirSync8(dirname5(p), { recursive: true });
7206
+ mkdirSync8(dirname7(p), { recursive: true });
5772
7207
  const tmp = `${p}.tmp`;
5773
7208
  writeFileSync7(tmp, JSON.stringify(s, null, 2), "utf8");
5774
7209
  renameSync3(tmp, p);
@@ -5799,18 +7234,18 @@ function updateCheckpoint(jsonlPath, cp) {
5799
7234
  }
5800
7235
 
5801
7236
  // src/perception/scan.ts
5802
- import { readdirSync as readdirSync3 } from "node:fs";
5803
- import { join as join6 } from "node:path";
5804
- import { homedir as homedir2 } from "node:os";
7237
+ import { readdirSync as readdirSync4 } from "node:fs";
7238
+ import { join as join8 } from "node:path";
7239
+ import { homedir as homedir3 } from "node:os";
5805
7240
  async function listAllSessionJsonls(root) {
5806
- const projectsRoot = root ?? join6(homedir2(), ".claude", "projects");
7241
+ const projectsRoot = root ?? join8(homedir3(), ".claude", "projects");
5807
7242
  const out = [];
5808
7243
  try {
5809
- for (const project of readdirSync3(projectsRoot)) {
5810
- const dir = join6(projectsRoot, project);
7244
+ for (const project of readdirSync4(projectsRoot)) {
7245
+ const dir = join8(projectsRoot, project);
5811
7246
  try {
5812
- for (const f of readdirSync3(dir)) {
5813
- if (f.endsWith(".jsonl")) out.push(join6(dir, f));
7247
+ for (const f of readdirSync4(dir)) {
7248
+ if (f.endsWith(".jsonl")) out.push(join8(dir, f));
5814
7249
  }
5815
7250
  } catch {
5816
7251
  }
@@ -5843,10 +7278,10 @@ async function runPerceptionSweep(opts = {}) {
5843
7278
  const files = await listAllSessionJsonls(opts.projectsRoot);
5844
7279
  for (const f of files) {
5845
7280
  try {
5846
- const stat = statSync2(f);
7281
+ const stat = statSync4(f);
5847
7282
  const prev = state.file_checkpoints[f];
5848
7283
  if (prev && prev.byte_offset >= stat.size) continue;
5849
- const raw = readFileSync9(f, "utf8");
7284
+ const raw = readFileSync10(f, "utf8");
5850
7285
  const rawLines = raw.split("\n").filter(Boolean).map((l) => {
5851
7286
  try {
5852
7287
  return JSON.parse(l);
@@ -5857,7 +7292,7 @@ async function runPerceptionSweep(opts = {}) {
5857
7292
  if (rawLines.length === 0) continue;
5858
7293
  const { meta, events } = parseTranscript(rawLines);
5859
7294
  const fileName = basename(f);
5860
- const projectDir = basename(dirname6(f));
7295
+ const projectDir = basename(dirname8(f));
5861
7296
  const sessionId = fileName.replace(/\.jsonl$/, "");
5862
7297
  const sd = {
5863
7298
  ...meta,
@@ -5896,7 +7331,7 @@ async function runPerceptionSweep(opts = {}) {
5896
7331
  const built = buildEntries(detail);
5897
7332
  for (const e of built) {
5898
7333
  try {
5899
- const stat = statSync2(meta.filePath);
7334
+ const stat = statSync4(meta.filePath);
5900
7335
  e.source_checkpoint.byte_offset = stat.size;
5901
7336
  } catch {
5902
7337
  }
@@ -6398,8 +7833,8 @@ function getErrorMap() {
6398
7833
 
6399
7834
  // ../../node_modules/zod/v3/helpers/parseUtil.js
6400
7835
  var makeIssue = (params) => {
6401
- const { data, path: path5, errorMaps, issueData } = params;
6402
- const fullPath = [...path5, ...issueData.path || []];
7836
+ const { data, path: path7, errorMaps, issueData } = params;
7837
+ const fullPath = [...path7, ...issueData.path || []];
6403
7838
  const fullIssue = {
6404
7839
  ...issueData,
6405
7840
  path: fullPath
@@ -6515,11 +7950,11 @@ var errorUtil;
6515
7950
 
6516
7951
  // ../../node_modules/zod/v3/types.js
6517
7952
  var ParseInputLazyPath = class {
6518
- constructor(parent, value, path5, key) {
7953
+ constructor(parent, value, path7, key) {
6519
7954
  this._cachedPath = [];
6520
7955
  this.parent = parent;
6521
7956
  this.data = value;
6522
- this._path = path5;
7957
+ this._path = path7;
6523
7958
  this._key = key;
6524
7959
  }
6525
7960
  get path() {
@@ -10053,14 +11488,14 @@ var ENRICHMENT_SYSTEM_PROMPT = SYSTEM_PROMPT;
10053
11488
  // ../entries/dist/llm-runner.js
10054
11489
  init_fs();
10055
11490
  import { spawn } from "node:child_process";
10056
- import { mkdirSync as mkdirSync10, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as existsSync7 } from "node:fs";
10057
- import { join as join8 } from "node:path";
11491
+ import { mkdirSync as mkdirSync10, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "node:fs";
11492
+ import { join as join10 } from "node:path";
10058
11493
  import { randomUUID as randomUUID4 } from "node:crypto";
10059
11494
 
10060
11495
  // ../entries/dist/tmux-runner.js
10061
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync8, existsSync as existsSync6, readdirSync as readdirSync4, realpathSync, readFileSync as readFileSync10, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
10062
- import { join as join7 } from "node:path";
10063
- import { homedir as homedir3 } from "node:os";
11496
+ import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync8, existsSync as existsSync8, readdirSync as readdirSync5, realpathSync, readFileSync as readFileSync11, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
11497
+ import { join as join9 } from "node:path";
11498
+ import { homedir as homedir4 } from "node:os";
10064
11499
  import { spawnSync } from "node:child_process";
10065
11500
  var TmuxUnavailableError = class extends Error {
10066
11501
  constructor(message) {
@@ -10088,16 +11523,16 @@ function tmuxRunnerAvailable() {
10088
11523
  return { ok: true };
10089
11524
  }
10090
11525
  function runtimeCwd() {
10091
- const dir = join7(homedir3(), ".cclens", "runtime");
10092
- if (!existsSync6(dir))
11526
+ const dir = join9(homedir4(), ".cclens", "runtime");
11527
+ if (!existsSync8(dir))
10093
11528
  mkdirSync9(dir, { recursive: true });
10094
11529
  return realpathSync(dir);
10095
11530
  }
10096
11531
  function ensureRuntimeCwdTrusted(cwd) {
10097
- const cfgPath = join7(homedir3(), ".claude.json");
11532
+ const cfgPath = join9(homedir4(), ".claude.json");
10098
11533
  let cfg;
10099
11534
  try {
10100
- cfg = JSON.parse(readFileSync10(cfgPath, "utf8"));
11535
+ cfg = JSON.parse(readFileSync11(cfgPath, "utf8"));
10101
11536
  } catch {
10102
11537
  return;
10103
11538
  }
@@ -10140,9 +11575,9 @@ async function runClaudeUnderTmuxImpl(args) {
10140
11575
  ensureRuntimeCwdTrusted(cwd);
10141
11576
  const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
10142
11577
  const sessionName = `cclens-${runId}`;
10143
- const systemFile = join7(cwd, `system-${runId}.txt`);
10144
- const userFile = join7(cwd, `user-${runId}.txt`);
10145
- const wrapper = join7(cwd, `run-${runId}.sh`);
11578
+ const systemFile = join9(cwd, `system-${runId}.txt`);
11579
+ const userFile = join9(cwd, `user-${runId}.txt`);
11580
+ const wrapper = join9(cwd, `run-${runId}.sh`);
10146
11581
  writeFileSync8(systemFile, args.systemPrompt);
10147
11582
  writeFileSync8(userFile, args.reminder ? `${args.userPrompt}
10148
11583
 
@@ -10221,35 +11656,35 @@ function num(v) {
10221
11656
  function sleep(ms) {
10222
11657
  return new Promise((r) => setTimeout(r, ms));
10223
11658
  }
10224
- var PROJECTS_ROOT = () => join7(homedir3(), ".claude", "projects");
11659
+ var PROJECTS_ROOT = () => join9(homedir4(), ".claude", "projects");
10225
11660
  function snapshotAllTranscripts() {
10226
11661
  const out = /* @__PURE__ */ new Set();
10227
11662
  const root = PROJECTS_ROOT();
10228
11663
  let subs;
10229
11664
  try {
10230
- subs = readdirSync4(root);
11665
+ subs = readdirSync5(root);
10231
11666
  } catch {
10232
11667
  return out;
10233
11668
  }
10234
11669
  for (const sub of subs) {
10235
- const dir = join7(root, sub);
11670
+ const dir = join9(root, sub);
10236
11671
  let files;
10237
11672
  try {
10238
- files = readdirSync4(dir);
11673
+ files = readdirSync5(dir);
10239
11674
  } catch {
10240
11675
  continue;
10241
11676
  }
10242
11677
  for (const f of files) {
10243
11678
  if (f.endsWith(".jsonl"))
10244
- out.add(join7(dir, f));
11679
+ out.add(join9(dir, f));
10245
11680
  }
10246
11681
  }
10247
11682
  return out;
10248
11683
  }
10249
- function readJsonlCwd(path5, maxLines = 8) {
11684
+ function readJsonlCwd(path7, maxLines = 8) {
10250
11685
  let raw;
10251
11686
  try {
10252
- raw = readFileSync10(path5, "utf8");
11687
+ raw = readFileSync11(path7, "utf8");
10253
11688
  } catch {
10254
11689
  return void 0;
10255
11690
  }
@@ -10277,22 +11712,22 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
10277
11712
  const root = PROJECTS_ROOT();
10278
11713
  let subs;
10279
11714
  try {
10280
- subs = readdirSync4(root);
11715
+ subs = readdirSync5(root);
10281
11716
  } catch {
10282
11717
  subs = [];
10283
11718
  }
10284
11719
  for (const sub of subs) {
10285
- const dir = join7(root, sub);
11720
+ const dir = join9(root, sub);
10286
11721
  let files;
10287
11722
  try {
10288
- files = readdirSync4(dir);
11723
+ files = readdirSync5(dir);
10289
11724
  } catch {
10290
11725
  continue;
10291
11726
  }
10292
11727
  for (const f of files) {
10293
11728
  if (!f.endsWith(".jsonl"))
10294
11729
  continue;
10295
- const full = join7(dir, f);
11730
+ const full = join9(dir, f);
10296
11731
  if (existingBefore.has(full))
10297
11732
  continue;
10298
11733
  if (readJsonlCwd(full) === targetCwd)
@@ -10303,10 +11738,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
10303
11738
  }
10304
11739
  throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
10305
11740
  }
10306
- function parseTranscript2(path5, defaultModel) {
11741
+ function parseTranscript2(path7, defaultModel) {
10307
11742
  let raw;
10308
11743
  try {
10309
- raw = readFileSync10(path5, "utf8");
11744
+ raw = readFileSync11(path7, "utf8");
10310
11745
  } catch {
10311
11746
  return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
10312
11747
  }
@@ -10366,7 +11801,7 @@ function cleanup(cwd, runId, tmuxBin, sessionName, transcriptPath) {
10366
11801
  }
10367
11802
  for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
10368
11803
  try {
10369
- unlinkSync3(join7(cwd, f));
11804
+ unlinkSync3(join9(cwd, f));
10370
11805
  } catch {
10371
11806
  }
10372
11807
  }
@@ -10381,7 +11816,7 @@ function shellEscape(s) {
10381
11816
  // ../entries/dist/llm-runner.js
10382
11817
  var RUNS_DIR = cclensPath("llm-runs");
10383
11818
  function ensureRunsDir() {
10384
- if (!existsSync7(RUNS_DIR)) {
11819
+ if (!existsSync9(RUNS_DIR)) {
10385
11820
  try {
10386
11821
  mkdirSync10(RUNS_DIR, { recursive: true });
10387
11822
  } catch {
@@ -10410,17 +11845,17 @@ function newRunId(kind) {
10410
11845
  return `${ts}_${kind}_${short}`;
10411
11846
  }
10412
11847
  function tracePath(runId) {
10413
- return join8(RUNS_DIR, `${runId}.jsonl`);
11848
+ return join10(RUNS_DIR, `${runId}.jsonl`);
10414
11849
  }
10415
- function safeAppend(path5, line) {
11850
+ function safeAppend(path7, line) {
10416
11851
  try {
10417
- appendFileSync3(path5, line);
11852
+ appendFileSync3(path7, line);
10418
11853
  } catch {
10419
11854
  }
10420
11855
  }
10421
- function safeWrite(path5, line) {
11856
+ function safeWrite(path7, line) {
10422
11857
  try {
10423
- writeFileSync9(path5, line);
11858
+ writeFileSync9(path7, line);
10424
11859
  } catch {
10425
11860
  }
10426
11861
  }
@@ -10498,7 +11933,7 @@ async function runClaudeSubprocess(args) {
10498
11933
  return runClaudePrintMode(args);
10499
11934
  }
10500
11935
  function runClaudePrintMode(args) {
10501
- return new Promise((resolve, reject) => {
11936
+ return new Promise((resolve3, reject) => {
10502
11937
  ensureRunsDir();
10503
11938
  const kind = detectKindFromSystemPrompt(args.systemPrompt);
10504
11939
  const runId = newRunId(kind);
@@ -10629,7 +12064,7 @@ ${args.reminder}` : args.userPrompt;
10629
12064
  reject(new Error(`claude exited ${code}: ${stderr.trim().slice(0, 300)}`));
10630
12065
  return;
10631
12066
  }
10632
- resolve({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
12067
+ resolve3({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
10633
12068
  });
10634
12069
  proc.on("error", (err) => {
10635
12070
  safeAppend(trace, JSON.stringify({ _meta: { type: "spawn_error", run_id: runId, ts: (/* @__PURE__ */ new Date()).toISOString(), error: err.message } }) + "\n");
@@ -10809,8 +12244,8 @@ function applyEnrichmentError(entry, errorMessage, model, costUsd, generatedAt,
10809
12244
 
10810
12245
  // ../entries/dist/budget.js
10811
12246
  init_fs();
10812
- import { appendFileSync as appendFileSync4, readFileSync as readFileSync11, existsSync as existsSync8, mkdirSync as mkdirSync11 } from "node:fs";
10813
- import { dirname as dirname7 } from "node:path";
12247
+ import { appendFileSync as appendFileSync4, readFileSync as readFileSync12, existsSync as existsSync10, mkdirSync as mkdirSync11 } from "node:fs";
12248
+ import { dirname as dirname9 } from "node:path";
10814
12249
  var spendPathCached = null;
10815
12250
  function spendPath() {
10816
12251
  if (spendPathCached)
@@ -10820,17 +12255,17 @@ function spendPath() {
10820
12255
  }
10821
12256
  function appendSpend(record) {
10822
12257
  const p = spendPath();
10823
- mkdirSync11(dirname7(p), { recursive: true });
12258
+ mkdirSync11(dirname9(p), { recursive: true });
10824
12259
  appendFileSync4(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
10825
12260
  }
10826
12261
  function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
10827
12262
  const p = spendPath();
10828
- if (!existsSync8(p))
12263
+ if (!existsSync10(p))
10829
12264
  return 0;
10830
12265
  const year = now.getUTCFullYear();
10831
12266
  const month = now.getUTCMonth();
10832
12267
  let total = 0;
10833
- const raw = readFileSync11(p, "utf8");
12268
+ const raw = readFileSync12(p, "utf8");
10834
12269
  for (const line of raw.split("\n")) {
10835
12270
  if (!line)
10836
12271
  continue;
@@ -10852,7 +12287,7 @@ function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
10852
12287
 
10853
12288
  // ../entries/dist/pipeline-lock.js
10854
12289
  init_fs();
10855
- import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as existsSync9, readFileSync as readFileSync12, statSync as statSync3 } from "node:fs";
12290
+ import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as existsSync11, readFileSync as readFileSync13, statSync as statSync5 } from "node:fs";
10856
12291
  var STALE_MS2 = 60 * 1e3;
10857
12292
  var HEARTBEAT_MS = 30 * 1e3;
10858
12293
  var lockPathCached = null;
@@ -10898,13 +12333,13 @@ function pidAlive(pid) {
10898
12333
  }
10899
12334
  function interactiveLockFresh(nowMs) {
10900
12335
  const p = lockPath();
10901
- if (!existsSync9(p))
12336
+ if (!existsSync11(p))
10902
12337
  return false;
10903
12338
  try {
10904
- const mtime = statSync3(p).mtimeMs;
12339
+ const mtime = statSync5(p).mtimeMs;
10905
12340
  if (nowMs - mtime > STALE_MS2)
10906
12341
  return false;
10907
- const pid = Number(readFileSync12(p, "utf8").trim());
12342
+ const pid = Number(readFileSync13(p, "utf8").trim());
10908
12343
  if (!Number.isFinite(pid) || pid <= 0)
10909
12344
  return false;
10910
12345
  if (!pidAlive(pid))
@@ -10919,7 +12354,7 @@ function interactiveLockFresh(nowMs) {
10919
12354
  var THIRTY_MIN_MS = 30 * 60 * 1e3;
10920
12355
 
10921
12356
  // ../entries/dist/settings.js
10922
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync12, existsSync as existsSync10 } from "node:fs";
12357
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync12, existsSync as existsSync12 } from "node:fs";
10923
12358
  init_fs();
10924
12359
  var DEFAULT_SETTINGS = {
10925
12360
  ai_features: {
@@ -10951,10 +12386,10 @@ function fromDisk(d) {
10951
12386
  }
10952
12387
  function readSettings() {
10953
12388
  const p = settingsPath();
10954
- if (!existsSync10(p))
12389
+ if (!existsSync12(p))
10955
12390
  return DEFAULT_SETTINGS;
10956
12391
  try {
10957
- const raw = readFileSync13(p, "utf8");
12392
+ const raw = readFileSync14(p, "utf8");
10958
12393
  return fromDisk(JSON.parse(raw));
10959
12394
  } catch {
10960
12395
  return DEFAULT_SETTINGS;
@@ -11127,7 +12562,7 @@ function rollupOutcomeDay(entries) {
11127
12562
  return "exploratory";
11128
12563
  return "trivial";
11129
12564
  }
11130
- function truncate4(s, max) {
12565
+ function truncate5(s, max) {
11131
12566
  if (s.length <= max)
11132
12567
  return s;
11133
12568
  return s.slice(0, max - 1).trimEnd() + "\u2026";
@@ -11183,7 +12618,7 @@ function computeDaySignals(entries) {
11183
12618
  type,
11184
12619
  count: v.count,
11185
12620
  sample_description: v.sample_description,
11186
- sample_prompt_preview: truncate4(v.sample_prompt_preview, 200)
12621
+ sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
11187
12622
  }));
11188
12623
  const frameCounts = /* @__PURE__ */ new Map();
11189
12624
  for (const s of signalsList) {
@@ -11202,7 +12637,7 @@ function computeDaySignals(entries) {
11202
12637
  if ((e.first_user ?? "").length > 0)
11203
12638
  verbosity_distribution[s.verbosity] += 1;
11204
12639
  for (const ref of s.external_refs) {
11205
- external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate4(ref.preview, 200) });
12640
+ external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate5(ref.preview, 200) });
11206
12641
  }
11207
12642
  const ints = e.numbers.interrupts ?? 0;
11208
12643
  interrupts += ints;
@@ -12045,7 +13480,7 @@ function computeInteractionModes(entries) {
12045
13480
  date: entry.local_day,
12046
13481
  project_display: prettyProject3(entry.project),
12047
13482
  type: sa.type,
12048
- prompt_preview: truncate5(sa.prompt_preview, 200)
13483
+ prompt_preview: truncate6(sa.prompt_preview, 200)
12049
13484
  });
12050
13485
  }
12051
13486
  const skillExamples = [];
@@ -12062,7 +13497,7 @@ function computeInteractionModes(entries) {
12062
13497
  skillExamples.push({
12063
13498
  date: e.local_day,
12064
13499
  skill,
12065
- first_user_preview: truncate5(e.first_user, 200)
13500
+ first_user_preview: truncate6(e.first_user, 200)
12066
13501
  });
12067
13502
  }
12068
13503
  }
@@ -12079,7 +13514,7 @@ function computeInteractionModes(entries) {
12079
13514
  project_display: prettyProject3(longestTurnEntry.project),
12080
13515
  active_min: longestTurnEntry.numbers.active_min,
12081
13516
  top_tools: longestTurnEntry.top_tools.slice(0, 5),
12082
- first_user_preview: truncate5(longestTurnEntry.first_user, 200)
13517
+ first_user_preview: truncate6(longestTurnEntry.first_user, 200)
12083
13518
  } : null;
12084
13519
  const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
12085
13520
  const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
@@ -12110,7 +13545,7 @@ function computeInteractionModes(entries) {
12110
13545
  }
12111
13546
  };
12112
13547
  }
12113
- function truncate5(s, max) {
13548
+ function truncate6(s, max) {
12114
13549
  if (s.length <= max)
12115
13550
  return s;
12116
13551
  return s.slice(0, max - 1).trimEnd() + "\u2026";
@@ -12167,7 +13602,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
12167
13602
  evidence_subagent = {
12168
13603
  type: sa.type,
12169
13604
  description: sa.description,
12170
- prompt_preview: truncate5(sa.prompt_preview, 200)
13605
+ prompt_preview: truncate6(sa.prompt_preview, 200)
12171
13606
  };
12172
13607
  }
12173
13608
  const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
@@ -12178,7 +13613,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
12178
13613
  outcome: dayOutcome.get(dd.key) ?? null,
12179
13614
  helpfulness: dayHelp.get(dd.key) ?? null,
12180
13615
  evidence_subagent,
12181
- evidence_first_user: repEntry?.first_user ? truncate5(repEntry.first_user, 200) : null,
13616
+ evidence_first_user: repEntry?.first_user ? truncate6(repEntry.first_user, 200) : null,
12182
13617
  day_signature: dd.day_signature ?? null
12183
13618
  };
12184
13619
  });
@@ -12253,7 +13688,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
12253
13688
  date: day,
12254
13689
  session_id: ref.session_id,
12255
13690
  ref_kind: ref.kind,
12256
- preview: truncate5(ref.preview, 200)
13691
+ preview: truncate6(ref.preview, 200)
12257
13692
  });
12258
13693
  }
12259
13694
  total_interrupts += signals.comm_style.steering.interrupts;
@@ -12325,7 +13760,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
12325
13760
  count: v.count,
12326
13761
  days: [...v.days].sort(),
12327
13762
  sample_description: v.sample_description,
12328
- sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
13763
+ sample_prompt_preview: truncate6(v.sample_prompt_preview, 200)
12329
13764
  })),
12330
13765
  threads,
12331
13766
  communication_style: {
@@ -12625,7 +14060,7 @@ var MonthDigestResponseSchema = external_exports.object({
12625
14060
  }).passthrough();
12626
14061
 
12627
14062
  // ../entries/dist/top-sessions.js
12628
- var IDLE_GAP_MS4 = 3 * 60 * 1e3;
14063
+ var IDLE_GAP_MS5 = 3 * 60 * 1e3;
12629
14064
  var LONG_AUTONOMOUS_MIN = 20;
12630
14065
  var N_USER = 150;
12631
14066
  var N_FIRST_AGENT = 150;
@@ -12656,7 +14091,7 @@ function activeMs(timestamps) {
12656
14091
  let active = 0;
12657
14092
  for (let i = 1; i < ts.length; i++) {
12658
14093
  const dt = ts[i] - ts[i - 1];
12659
- if (dt < IDLE_GAP_MS4)
14094
+ if (dt < IDLE_GAP_MS5)
12660
14095
  active += dt;
12661
14096
  }
12662
14097
  return active;
@@ -12830,7 +14265,7 @@ function buildSessionSlice(entry, events, daySignature) {
12830
14265
  let intEnd = sortedTs[0];
12831
14266
  for (let i = 1; i < sortedTs.length; i++) {
12832
14267
  const dt = sortedTs[i] - intEnd;
12833
- if (dt >= IDLE_GAP_MS4) {
14268
+ if (dt >= IDLE_GAP_MS5) {
12834
14269
  intervals.push({
12835
14270
  start_min: fmtMin(intStart - sliceStartMs),
12836
14271
  end_min: fmtMin(intEnd - sliceStartMs)
@@ -13711,14 +15146,14 @@ async function getUpdateAvailability() {
13711
15146
  if (isDevMode()) return null;
13712
15147
  const latest = await fetchLatestVersion();
13713
15148
  if (latest === null) return {
13714
- current: "0.11.2",
15149
+ current: "0.12.1",
13715
15150
  latest: null,
13716
15151
  updateAvailable: false
13717
15152
  };
13718
15153
  return {
13719
- current: "0.11.2",
15154
+ current: "0.12.1",
13720
15155
  latest,
13721
- updateAvailable: shouldUpdate("0.11.2", latest)
15156
+ updateAvailable: shouldUpdate("0.12.1", latest)
13722
15157
  };
13723
15158
  }
13724
15159
 
@@ -13728,7 +15163,7 @@ var DAEMON_LOG = cclensPath("daemon.log");
13728
15163
  var UPDATE_STATE = cclensPath("daemon-update.json");
13729
15164
  var WATCHDOG_INTERVAL_MS = 5 * 1e3;
13730
15165
  var AUTO_UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1e3;
13731
- mkdirSync13(dirname8(USAGE_LOG3), { recursive: true });
15166
+ mkdirSync13(dirname10(USAGE_LOG3), { recursive: true });
13732
15167
  function log2(level, message) {
13733
15168
  const line = `${(/* @__PURE__ */ new Date()).toISOString()} ${level.toUpperCase()} ${message}
13734
15169
  `;
@@ -13770,7 +15205,7 @@ var perceptionHandle = setInterval(async () => {
13770
15205
  }, PERCEPTION_INTERVAL_MS);
13771
15206
  function readUpdateState() {
13772
15207
  try {
13773
- return JSON.parse(readFileSync14(UPDATE_STATE, "utf8"));
15208
+ return JSON.parse(readFileSync15(UPDATE_STATE, "utf8"));
13774
15209
  } catch {
13775
15210
  return null;
13776
15211
  }
@@ -13790,7 +15225,7 @@ function nextUpdateCheckFromState(nowMs) {
13790
15225
  }
13791
15226
  var nextUpdateCheckAtMs = nextUpdateCheckFromState(Date.now());
13792
15227
  function cliEntryPath() {
13793
- return join9(dirname8(fileURLToPath(import.meta.url)), "index.js");
15228
+ return join11(dirname10(fileURLToPath(import.meta.url)), "index.js");
13794
15229
  }
13795
15230
  async function runDaemonUpdateCheck() {
13796
15231
  if (process.env.FLEETLENS_DAEMON_AUTO_UPDATE === "0") {
@@ -13819,7 +15254,7 @@ async function runDaemonUpdateCheck() {
13819
15254
  return;
13820
15255
  }
13821
15256
  const entry = cliEntryPath();
13822
- if (!existsSync11(entry)) {
15257
+ if (!existsSync13(entry)) {
13823
15258
  log2("warn", `update check found ${availability.latest}, but CLI entry is missing at ${entry}`);
13824
15259
  return;
13825
15260
  }
@@ -13911,7 +15346,7 @@ function scheduleAfter(now, outcome) {
13911
15346
  nextPollAtMs = now + currentIntervalMs;
13912
15347
  }
13913
15348
  function sleep2(ms) {
13914
- return new Promise((resolve) => setTimeout(resolve, ms));
15349
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
13915
15350
  }
13916
15351
  async function runLoop() {
13917
15352
  while (true) {