fleetlens 0.15.2 → 0.15.4

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 (222) 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 +18 -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 +1 -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.nft.json +1 -1
  17. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  18. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
  19. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  20. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  21. package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
  22. package/app/apps/web/.next/server/app/api/menubar/route/app-paths-manifest.json +3 -0
  23. package/app/apps/web/.next/server/app/api/menubar/route/build-manifest.json +9 -0
  24. package/app/apps/web/.next/server/app/api/menubar/route/server-reference-manifest.json +4 -0
  25. package/app/apps/web/.next/server/app/api/menubar/route.js +6 -0
  26. package/app/apps/web/.next/server/app/api/menubar/route.js.map +5 -0
  27. package/app/apps/web/.next/server/app/api/menubar/route.js.nft.json +1 -0
  28. package/app/apps/web/.next/server/app/api/menubar/route_client-reference-manifest.js +3 -0
  29. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js +1 -1
  30. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
  31. package/app/apps/web/.next/server/app/api/projects/open-folder/route/app-paths-manifest.json +3 -0
  32. package/app/apps/web/.next/server/app/api/projects/open-folder/route/build-manifest.json +9 -0
  33. package/app/apps/web/.next/server/app/api/projects/open-folder/route/server-reference-manifest.json +4 -0
  34. package/app/apps/web/.next/server/app/api/projects/open-folder/route.js +7 -0
  35. package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.map +5 -0
  36. package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.nft.json +1 -0
  37. package/app/apps/web/.next/server/app/api/projects/open-folder/route_client-reference-manifest.js +3 -0
  38. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  39. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  40. package/app/apps/web/.next/server/app/api/settings/credentials/route/app-paths-manifest.json +3 -0
  41. package/app/apps/web/.next/server/app/api/settings/credentials/route/build-manifest.json +9 -0
  42. package/app/apps/web/.next/server/app/api/settings/credentials/route/server-reference-manifest.json +4 -0
  43. package/app/apps/web/.next/server/app/api/settings/credentials/route.js +10 -0
  44. package/app/apps/web/.next/server/app/api/settings/credentials/route.js.map +5 -0
  45. package/app/apps/web/.next/server/app/api/settings/credentials/route.js.nft.json +1 -0
  46. package/app/apps/web/.next/server/app/api/settings/credentials/route_client-reference-manifest.js +3 -0
  47. package/app/apps/web/.next/server/app/api/settings/route.js +4 -4
  48. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  49. package/app/apps/web/.next/server/app/changelog/page.js +1 -1
  50. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
  51. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  52. package/app/apps/web/.next/server/app/day/[date]/page.js +1 -1
  53. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  54. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  55. package/app/apps/web/.next/server/app/day/page.js +1 -1
  56. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  57. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  58. package/app/apps/web/.next/server/app/digest/[date]/page.js +1 -1
  59. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  60. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  61. package/app/apps/web/.next/server/app/digest/page.js +1 -1
  62. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  63. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  64. package/app/apps/web/.next/server/app/insights/[key]/page.js +1 -1
  65. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  66. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  67. package/app/apps/web/.next/server/app/insights/page.js +1 -1
  68. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  69. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  70. package/app/apps/web/.next/server/app/page.js +1 -1
  71. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  72. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  73. package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
  74. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  75. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  76. package/app/apps/web/.next/server/app/print/[key]/page.js +1 -1
  77. package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
  78. package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
  79. package/app/apps/web/.next/server/app/projects/[slug]/page.js +2 -2
  80. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  81. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  82. package/app/apps/web/.next/server/app/projects/page.js +1 -1
  83. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  84. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  85. package/app/apps/web/.next/server/app/runs/page.js +1 -1
  86. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  87. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  88. package/app/apps/web/.next/server/app/sessions/[id]/page.js +1 -1
  89. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  90. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  91. package/app/apps/web/.next/server/app/sessions/page.js +1 -1
  92. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  93. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  94. package/app/apps/web/.next/server/app/settings/page.js +2 -2
  95. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  96. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  97. package/app/apps/web/.next/server/app/team/onboarding/page.js +1 -1
  98. package/app/apps/web/.next/server/app/team/onboarding/page.js.nft.json +1 -1
  99. package/app/apps/web/.next/server/app/team/onboarding/page_client-reference-manifest.js +1 -1
  100. package/app/apps/web/.next/server/app/team/page.js +1 -1
  101. package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
  102. package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
  103. package/app/apps/web/.next/server/app/usage/page.js +1 -1
  104. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  105. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  106. package/app/apps/web/.next/server/app-paths-manifest.json +3 -0
  107. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_projects_open-folder_route_actions_0m~419c.js +3 -0
  108. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_settings_credentials_route_actions_04an_i2.js +3 -0
  109. package/app/apps/web/.next/server/chunks/[root-of-the-server]__05z0pcw._.js +3 -0
  110. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_nle98._.js +3 -0
  111. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0b5r~-1._.js +3 -0
  112. package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0a0~7d6._.js → [root-of-the-server]__0t7i-hy._.js} +2 -2
  113. package/app/apps/web/.next/server/chunks/[root-of-the-server]__12iid50._.js +3 -0
  114. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_menubar_route_actions_0xep8_i.js +3 -0
  115. package/app/apps/web/.next/server/chunks/{node_modules_next_036my~r._.js → node_modules_next_04~_e52._.js} +5 -5
  116. package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +14 -14
  117. package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
  118. package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
  119. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0.zquoa._.js +1 -1
  120. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__03svi~4._.js +8 -0
  121. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04eq6z2._.js +1 -1
  122. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04il6m2._.js +1 -1
  123. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__08l86e-._.js +1 -1
  124. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__09rjz7_._.js +1 -1
  125. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ar_8wr._.js +1 -1
  126. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__10~b4bf._.js → [root-of-the-server]__0blm9gz._.js} +3 -3
  127. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0e.gxk3._.js +1 -1
  128. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0g-tomj._.js +3 -0
  129. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0i.q-1h._.js +1 -1
  130. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0k1x-c9._.js +1 -1
  131. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0lz4a~g._.js +1 -1
  132. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0nr2~y1._.js +3 -0
  133. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o1_g.~._.js +1 -1
  134. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0p1x6v2._.js +1 -1
  135. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +1 -1
  136. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0rvzdnx._.js +1 -1
  137. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0stu~~r._.js +1 -1
  138. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0tejjy_._.js +1 -1
  139. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0u39afl._.js +1 -1
  140. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ufi3.w._.js +1 -1
  141. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0xy1qim._.js +1 -1
  142. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +3 -3
  143. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10srpu0._.js +1 -1
  144. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js +1 -1
  145. package/app/apps/web/.next/server/chunks/ssr/_02r-a1a._.js +8 -0
  146. package/app/apps/web/.next/server/chunks/ssr/_0k62ejd._.js +8 -0
  147. package/app/apps/web/.next/server/chunks/ssr/{_0xu2pvc._.js → _0k8yioi._.js} +2 -2
  148. package/app/apps/web/.next/server/chunks/ssr/{_0wj750k._.js → _0t~mx7w._.js} +2 -2
  149. package/app/apps/web/.next/server/chunks/ssr/{_0kajk31._.js → _0whg~r-._.js} +2 -2
  150. package/app/apps/web/.next/server/chunks/ssr/_13jdm1g._.js +3 -0
  151. package/app/apps/web/.next/server/chunks/ssr/apps_web_0~aj0~u._.js +3 -0
  152. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_sessions-grid_tsx_0bri5x.._.js +1 -1
  153. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0x014hn._.js +16 -0
  154. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
  155. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
  156. package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_12vc-v-._.js +3 -0
  157. package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +1 -1
  158. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0mx_509._.js +1 -1
  159. package/app/apps/web/.next/server/functions-config-manifest.json +3 -0
  160. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  161. package/app/apps/web/.next/server/middleware-manifest.json +5 -5
  162. package/app/apps/web/.next/server/pages/500.html +1 -1
  163. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  164. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  165. package/app/apps/web/.next/static/chunks/0-z49mtd-zwgv.js +1 -0
  166. package/app/apps/web/.next/static/chunks/043slkg3juwck.js +1 -0
  167. package/app/apps/web/.next/static/chunks/{0~qdw1b2uz._5.js → 044mtrzh7d7va.js} +3 -3
  168. package/app/apps/web/.next/static/chunks/05b0dn.r00hq1.js +1 -0
  169. package/app/apps/web/.next/static/chunks/{14vx702c32kn6.js → 0_0~~ipv90vm3.js} +1 -1
  170. package/app/apps/web/.next/static/chunks/0awkd5df28gvj.js +6 -0
  171. package/app/apps/web/.next/static/chunks/{0m7dd-2zd9vl2.js → 0eoc4yy0s0gpe.js} +1 -1
  172. package/app/apps/web/.next/static/chunks/0g0hv.dt-de9g.js +14 -0
  173. package/app/apps/web/.next/static/chunks/0rsp61c8wb.sx.js +6 -0
  174. package/app/apps/web/.next/static/chunks/{03rd.3cc_t~yf.js → 0s~0-8l~_kqnf.js} +1 -1
  175. package/app/apps/web/.next/static/chunks/0t2on1dhydyb2.css +1 -0
  176. package/app/apps/web/.next/static/chunks/0y3448zrint0k.js +6 -0
  177. package/app/apps/web/app/api/menubar/route.ts +66 -0
  178. package/app/apps/web/app/api/projects/open-folder/route.ts +60 -0
  179. package/app/apps/web/app/api/settings/credentials/route.ts +45 -0
  180. package/app/apps/web/app/layout.tsx +2 -0
  181. package/app/apps/web/app/projects/[slug]/local-folders-button.tsx +406 -0
  182. package/app/apps/web/app/projects/[slug]/page.tsx +155 -20
  183. package/app/apps/web/app/projects/page.tsx +2 -2
  184. package/app/apps/web/app/sessions/[id]/page.tsx +4 -1
  185. package/app/apps/web/app/sessions/[id]/session-view/header-stats.tsx +81 -0
  186. package/app/apps/web/app/sessions/[id]/session-view.tsx +11 -0
  187. package/app/apps/web/app/sessions/sessions-grid.tsx +56 -25
  188. package/app/apps/web/app/settings/page.tsx +26 -0
  189. package/app/apps/web/app/usage/page.tsx +80 -0
  190. package/app/apps/web/components/menubar-install-banner.tsx +117 -0
  191. package/app/apps/web/components/menubar-install.tsx +107 -0
  192. package/app/apps/web/components/zai-credentials-form.tsx +116 -0
  193. package/app/apps/web/lib/changelog-data.generated.ts +1 -1
  194. package/app/apps/web/lib/entries-index.ts +4 -4
  195. package/app/apps/web/lib/menubar-data.ts +50 -0
  196. package/app/apps/web/lib/usage-data.ts +4 -0
  197. package/app/apps/web/package.json +1 -1
  198. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  199. package/dist/daemon-worker.js +640 -240
  200. package/dist/index.js +938 -283
  201. package/package.json +3 -2
  202. package/app/apps/web/.next/server/chunks/[root-of-the-server]__065lib8._.js +0 -3
  203. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0a7n44-._.js +0 -3
  204. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0c00i76._.js +0 -3
  205. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0lhwp-k._.js +0 -8
  206. package/app/apps/web/.next/server/chunks/ssr/_0s3n5mz._.js +0 -8
  207. package/app/apps/web/.next/server/chunks/ssr/_12mbgs5._.js +0 -3
  208. package/app/apps/web/.next/server/chunks/ssr/apps_web_0q2x4a~._.js +0 -3
  209. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0b-4-4j._.js +0 -8
  210. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +0 -16
  211. package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0cepfi8._.js +0 -3
  212. package/app/apps/web/.next/static/chunks/00a9oyw~h5i1p.js +0 -1
  213. package/app/apps/web/.next/static/chunks/03gy1evbn94qu.js +0 -6
  214. package/app/apps/web/.next/static/chunks/040s42ypidk7s.css +0 -1
  215. package/app/apps/web/.next/static/chunks/0d2x-wfu.m0-z.js +0 -6
  216. package/app/apps/web/.next/static/chunks/0i77er85v.rj..js +0 -1
  217. package/app/apps/web/.next/static/chunks/0nqklmbs5s3ax.js +0 -6
  218. package/app/apps/web/.next/static/chunks/0tirv_vo6q8uc.js +0 -1
  219. package/app/apps/web/.next/static/chunks/0u6gxpqhl0gc7.js +0 -14
  220. /package/app/apps/web/.next/static/{mTj8nKiazosAKJec15dLe → nmAGY0LiBgXuibWTKZ1RD}/_buildManifest.js +0 -0
  221. /package/app/apps/web/.next/static/{mTj8nKiazosAKJec15dLe → nmAGY0LiBgXuibWTKZ1RD}/_clientMiddlewareManifest.js +0 -0
  222. /package/app/apps/web/.next/static/{mTj8nKiazosAKJec15dLe → nmAGY0LiBgXuibWTKZ1RD}/_ssgManifest.js +0 -0
@@ -8,40 +8,6 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
- // src/usage/storage.ts
12
- import { appendFileSync, mkdirSync, readFileSync as readFileSync2, existsSync } from "node:fs";
13
- import { dirname } from "node:path";
14
- function appendSnapshot(filePath, snapshot) {
15
- mkdirSync(dirname(filePath), { recursive: true });
16
- appendFileSync(filePath, JSON.stringify(snapshot) + "\n", "utf8");
17
- }
18
- function readSnapshots(filePath) {
19
- if (!existsSync(filePath)) return [];
20
- const content = readFileSync2(filePath, "utf8");
21
- const snapshots = [];
22
- for (const line of content.split("\n")) {
23
- if (!line.trim()) continue;
24
- try {
25
- snapshots.push(JSON.parse(line));
26
- } catch {
27
- }
28
- }
29
- return snapshots;
30
- }
31
- function latestClaudeCodeSnapshot(filePath) {
32
- const all = readSnapshots(filePath);
33
- for (let i = all.length - 1; i >= 0; i--) {
34
- const s = all[i];
35
- if (!s.agent || s.agent === "claude-code") return s;
36
- }
37
- return null;
38
- }
39
- var init_storage = __esm({
40
- "src/usage/storage.ts"() {
41
- "use strict";
42
- }
43
- });
44
-
45
11
  // ../parser/dist/analytics.js
46
12
  function toLocalDay(ms) {
47
13
  const d = new Date(ms);
@@ -114,11 +80,22 @@ function worktreeName(projectName) {
114
80
  return ss.workspaceName;
115
81
  return null;
116
82
  }
117
- function projectRepoName(projectName) {
83
+ function projectKey(projectName) {
118
84
  const canonical = canonicalProjectName(projectName);
119
85
  const segs = canonical.replace(/\/+$/, "").split("/").filter(Boolean);
120
86
  return segs[segs.length - 1] || canonical;
121
87
  }
88
+ function sessionProjectKey(s) {
89
+ return s.repoName ?? projectKey(s.projectName);
90
+ }
91
+ function buildProjectKeyResolver(sessions) {
92
+ const alias = /* @__PURE__ */ new Map();
93
+ for (const s of sessions) {
94
+ if (s.repoName)
95
+ alias.set(projectKey(s.projectName), s.repoName);
96
+ }
97
+ return (s) => s.repoName ?? alias.get(projectKey(s.projectName)) ?? projectKey(s.projectName);
98
+ }
122
99
  function makeDay(date) {
123
100
  return {
124
101
  date,
@@ -553,8 +530,9 @@ function summarizeBursts(bursts) {
553
530
  }
554
531
  function groupByProject(sessions) {
555
532
  const map = /* @__PURE__ */ new Map();
533
+ const keyOf = buildProjectKeyResolver(sessions);
556
534
  for (const s of sessions) {
557
- const repo = projectRepoName(s.projectName);
535
+ const repo = keyOf(s);
558
536
  const key = repo;
559
537
  let cur = map.get(key);
560
538
  if (!cur) {
@@ -583,7 +561,7 @@ function groupByProject(sessions) {
583
561
  p.metrics = highLevelMetrics(p.sessions);
584
562
  const wtNames = /* @__PURE__ */ new Set();
585
563
  for (const s of p.sessions) {
586
- const wt = worktreeName(s.projectName);
564
+ const wt = s.worktreeName ?? worktreeName(s.projectName) ?? (s.cwd ? worktreeName(s.cwd) : null);
587
565
  if (wt)
588
566
  wtNames.add(wt);
589
567
  }
@@ -602,7 +580,7 @@ function groupByProject(sessions) {
602
580
  }
603
581
  return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
604
582
  }
605
- var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
583
+ var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, projectRepoName, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
606
584
  var init_analytics = __esm({
607
585
  "../parser/dist/analytics.js"() {
608
586
  "use strict";
@@ -615,6 +593,7 @@ var init_analytics = __esm({
615
593
  CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
616
594
  SUPERSET_MARKER = "/.superset/worktrees/";
617
595
  UUID_SEG_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
596
+ projectRepoName = projectKey;
618
597
  PR_CREATE_RE = /gh\s+pr\s+create\b/i;
619
598
  PR_NUMBER_RE = /#(\d+)/;
620
599
  TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
@@ -628,7 +607,7 @@ function getAgentMetadata(kind) {
628
607
  function isAgentKind(s) {
629
608
  return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
630
609
  }
631
- var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
610
+ var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
632
611
  var init_agent_metadata = __esm({
633
612
  "../parser/dist/agent-metadata.js"() {
634
613
  "use strict";
@@ -667,12 +646,20 @@ var init_agent_metadata = __esm({
667
646
  accentColor: "rgb(217, 119, 87)",
668
647
  iconChar: "\u2318"
669
648
  };
649
+ ZAI_METADATA = {
650
+ kind: "zai",
651
+ displayName: "Z.ai",
652
+ shortLabel: "Z.ai",
653
+ accentColor: "rgb(59, 130, 246)",
654
+ iconChar: "Z"
655
+ };
670
656
  agentMetadata = [
671
657
  CLAUDE_CODE_METADATA,
672
658
  CODEX_METADATA,
673
659
  GEMINI_METADATA,
674
660
  ANTIGRAVITY_METADATA,
675
- COWORK_METADATA
661
+ COWORK_METADATA,
662
+ ZAI_METADATA
676
663
  ];
677
664
  KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
678
665
  }
@@ -1413,6 +1400,187 @@ var init_parser = __esm({
1413
1400
  }
1414
1401
  });
1415
1402
 
1403
+ // ../parser/dist/git-project.js
1404
+ import { existsSync, readFileSync as readFileSync2, realpathSync, statSync } from "node:fs";
1405
+ import { homedir as homedir2 } from "node:os";
1406
+ import { basename, dirname, isAbsolute, join as join2, resolve } from "node:path";
1407
+ function resolveGitDir(root, dotGitText) {
1408
+ const m = dotGitText.match(/^gitdir:\s*(.+)\s*$/m);
1409
+ if (!m)
1410
+ return void 0;
1411
+ const gitDir = m[1].trim();
1412
+ return isAbsolute(gitDir) ? gitDir : resolve(root, gitDir);
1413
+ }
1414
+ function resolveCommonDir(gitDir) {
1415
+ const file = join2(gitDir, "commondir");
1416
+ if (!existsSync(file))
1417
+ return void 0;
1418
+ const common = readFileSync2(file, "utf8").trim();
1419
+ if (!common)
1420
+ return void 0;
1421
+ return isAbsolute(common) ? common : resolve(gitDir, common);
1422
+ }
1423
+ function dotGitInfoFor(root) {
1424
+ const dotGit = join2(root, ".git");
1425
+ const st = statSync(dotGit, { throwIfNoEntry: false });
1426
+ if (!st)
1427
+ return null;
1428
+ if (st.isDirectory())
1429
+ return { root, gitDir: dotGit, commonDir: dotGit };
1430
+ const gitDir = resolveGitDir(root, readFileSync2(dotGit, "utf8"));
1431
+ if (!gitDir)
1432
+ return { root };
1433
+ return { root, gitDir, commonDir: resolveCommonDir(gitDir) };
1434
+ }
1435
+ function walkBoundary(start) {
1436
+ const home = realpathOrSelf(homedir2());
1437
+ return start === home || start.startsWith(`${home}/`) ? home : void 0;
1438
+ }
1439
+ function nearestDotGit(start) {
1440
+ if (!start || !isAbsolute(start))
1441
+ return null;
1442
+ const boundary = walkBoundary(start);
1443
+ for (let dir = start.replace(/\/+$/, "") || start; ; dir = dirname(dir)) {
1444
+ if (dir === boundary)
1445
+ return null;
1446
+ const info = dotGitInfoFor(dir);
1447
+ if (info)
1448
+ return info;
1449
+ const parent = dirname(dir);
1450
+ if (parent === dir)
1451
+ return null;
1452
+ }
1453
+ }
1454
+ function originUrl(configText) {
1455
+ let inOrigin = false;
1456
+ for (const line of configText.split("\n")) {
1457
+ const t = line.trim();
1458
+ if (t.startsWith("[")) {
1459
+ inOrigin = /^\[remote\s+"origin"\]/.test(t);
1460
+ continue;
1461
+ }
1462
+ if (!inOrigin)
1463
+ continue;
1464
+ const m = t.match(/^url\s*=\s*(.+)$/);
1465
+ if (m)
1466
+ return m[1].trim();
1467
+ }
1468
+ return void 0;
1469
+ }
1470
+ function parseRemote(url) {
1471
+ const m = url.match(REMOTE_URL_RE);
1472
+ if (!m)
1473
+ return void 0;
1474
+ const host = m[1];
1475
+ const segs = m[2].split("/").filter(Boolean);
1476
+ if (segs.length < 2)
1477
+ return void 0;
1478
+ const name = segs[segs.length - 1];
1479
+ const owner = segs.slice(0, -1).join("/");
1480
+ return { host, owner, name, url, webUrl: `https://${host}/${owner}/${name}` };
1481
+ }
1482
+ function remoteFor(git) {
1483
+ const dir = git.commonDir ?? git.gitDir;
1484
+ if (!dir)
1485
+ return void 0;
1486
+ const config = join2(dir, "config");
1487
+ if (!existsSync(config))
1488
+ return void 0;
1489
+ const url = originUrl(readFileSync2(config, "utf8"));
1490
+ return url ? parseRemote(url) : void 0;
1491
+ }
1492
+ function headBranch(gitDir) {
1493
+ if (!gitDir)
1494
+ return void 0;
1495
+ const head = join2(gitDir, "HEAD");
1496
+ if (!existsSync(head))
1497
+ return void 0;
1498
+ const t = readFileSync2(head, "utf8").trim();
1499
+ const m = t.match(/^ref:\s*refs\/heads\/(.+)$/);
1500
+ return m ? m[1] : `detached @ ${t.slice(0, 7)}`;
1501
+ }
1502
+ function defaultBranch(commonDir) {
1503
+ if (!commonDir)
1504
+ return void 0;
1505
+ const head = join2(commonDir, "refs", "remotes", "origin", "HEAD");
1506
+ if (existsSync(head)) {
1507
+ const m = readFileSync2(head, "utf8").trim().match(/refs\/remotes\/origin\/(.+)$/);
1508
+ if (m)
1509
+ return m[1];
1510
+ }
1511
+ const packed = join2(commonDir, "packed-refs");
1512
+ if (existsSync(packed)) {
1513
+ const m = readFileSync2(packed, "utf8").match(/refs\/remotes\/origin\/(\S+)/);
1514
+ if (m && m[1] !== "HEAD")
1515
+ return m[1];
1516
+ }
1517
+ return void 0;
1518
+ }
1519
+ function readGitFolder(path7) {
1520
+ if (!existsSync(path7))
1521
+ return { exists: false, isWorktree: false };
1522
+ try {
1523
+ const git = nearestDotGit(realpathOrSelf(path7));
1524
+ if (!git)
1525
+ return { exists: true, isWorktree: false };
1526
+ const projectRoot = projectRootFromCommonDir(git.commonDir);
1527
+ const isWorktree = !!projectRoot && realpathOrSelf(projectRoot) !== realpathOrSelf(git.root);
1528
+ return {
1529
+ exists: true,
1530
+ isWorktree,
1531
+ branch: headBranch(git.gitDir),
1532
+ defaultBranch: defaultBranch(git.commonDir),
1533
+ remote: remoteFor(git)
1534
+ };
1535
+ } catch {
1536
+ return { exists: true, isWorktree: false };
1537
+ }
1538
+ }
1539
+ function projectRootFromCommonDir(commonDir) {
1540
+ if (!commonDir)
1541
+ return void 0;
1542
+ return basename(commonDir) === ".git" ? dirname(commonDir) : void 0;
1543
+ }
1544
+ function realpathOrSelf(p) {
1545
+ try {
1546
+ return realpathSync(p);
1547
+ } catch {
1548
+ return p;
1549
+ }
1550
+ }
1551
+ function resolveProjectIdentity(cwd) {
1552
+ const normalized = realpathOrSelf(cwd.replace(/\/{2,}/g, "/"));
1553
+ try {
1554
+ const git = nearestDotGit(normalized);
1555
+ if (git) {
1556
+ const projectRoot = realpathOrSelf(projectRootFromCommonDir(git.commonDir) ?? git.root);
1557
+ const gitRoot = realpathOrSelf(git.root);
1558
+ const wt2 = projectRoot !== gitRoot ? worktreeName(normalized) ?? basename(git.root) : void 0;
1559
+ const identity = { projectName: projectRoot };
1560
+ if (wt2)
1561
+ identity.worktreeName = wt2;
1562
+ const remote = remoteFor(git);
1563
+ if (remote) {
1564
+ identity.remote = remote;
1565
+ identity.repoName = remote.name;
1566
+ }
1567
+ return identity;
1568
+ }
1569
+ } catch {
1570
+ }
1571
+ const projectName = canonicalProjectName(normalized);
1572
+ const wt = worktreeName(normalized) ?? void 0;
1573
+ return wt ? { projectName, worktreeName: wt } : { projectName };
1574
+ }
1575
+ var REMOTE_URL_RE;
1576
+ var init_git_project = __esm({
1577
+ "../parser/dist/git-project.js"() {
1578
+ "use strict";
1579
+ init_analytics();
1580
+ REMOTE_URL_RE = /^(?:(?:https?|ssh|git):\/\/)?(?:[^@/]+@)?([^/:]+)[:/](.+?)(?:\.git)?\/?$/;
1581
+ }
1582
+ });
1583
+
1416
1584
  // ../parser/dist/team.js
1417
1585
  function groupByTeam(sessions, details) {
1418
1586
  const byTeam = /* @__PURE__ */ new Map();
@@ -1881,12 +2049,16 @@ async function getCachedMeta(f) {
1881
2049
  const sessionId = sessionIdFromFileName(f.fileName);
1882
2050
  const projectDirPath = path.dirname(f.fullPath);
1883
2051
  const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
2052
+ const cwd = meta.cwd ?? decodeProjectName(f.projectDir);
2053
+ const project = resolveProjectIdentity(cwd);
1884
2054
  const full = {
1885
2055
  ...meta,
1886
2056
  id: sessionId,
1887
2057
  filePath: f.fullPath,
1888
2058
  projectDir: f.projectDir,
1889
- projectName: meta.cwd ?? decodeProjectName(f.projectDir),
2059
+ projectName: project.projectName,
2060
+ worktreeName: project.worktreeName,
2061
+ repoName: project.repoName,
1890
2062
  ...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
1891
2063
  ...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
1892
2064
  };
@@ -1907,12 +2079,16 @@ async function getCachedDetail(f) {
1907
2079
  const sessionId = sessionIdFromFileName(f.fileName);
1908
2080
  await applySubagentUsage(meta, rawLines, f);
1909
2081
  const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
2082
+ const cwd = meta.cwd ?? decodeProjectName(f.projectDir);
2083
+ const project = resolveProjectIdentity(cwd);
1910
2084
  const detail = {
1911
2085
  ...meta,
1912
2086
  id: sessionId,
1913
2087
  filePath: f.fullPath,
1914
2088
  projectDir: f.projectDir,
1915
- projectName: meta.cwd ?? decodeProjectName(f.projectDir),
2089
+ projectName: project.projectName,
2090
+ worktreeName: project.worktreeName,
2091
+ repoName: project.repoName,
1916
2092
  events,
1917
2093
  ...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
1918
2094
  ...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
@@ -2404,19 +2580,25 @@ async function listProjects(root = DEFAULT_ROOT) {
2404
2580
  cur.lastActiveMs = f.mtimeMs;
2405
2581
  byRawDir.set(f.projectDir, cur);
2406
2582
  }
2407
- const cwdForProject = (dir) => {
2583
+ const cachedIdentityForProject = (dir) => {
2408
2584
  for (const [, entry] of metaCache.entries()) {
2409
- if (entry.meta.projectDir === dir && entry.meta.cwd) {
2410
- return entry.meta.cwd;
2585
+ if (entry.meta.projectDir === dir) {
2586
+ return {
2587
+ cwd: entry.meta.cwd,
2588
+ projectName: entry.meta.projectName,
2589
+ worktreeName: entry.meta.worktreeName
2590
+ };
2411
2591
  }
2412
2592
  }
2413
2593
  return void 0;
2414
2594
  };
2415
2595
  const canonicalMap = /* @__PURE__ */ new Map();
2416
2596
  for (const [rawDir, { count, lastActiveMs }] of byRawDir) {
2417
- const cwdOrDecoded = cwdForProject(rawDir) ?? decodeProjectName(rawDir);
2418
- const repo = projectRepoName(cwdOrDecoded);
2419
- const wt = worktreeName(cwdOrDecoded);
2597
+ const cached = cachedIdentityForProject(rawDir);
2598
+ const cwdOrDecoded = cached?.cwd ?? decodeProjectName(rawDir);
2599
+ const projectName = cached?.projectName ?? canonicalProjectName(cwdOrDecoded);
2600
+ const wt = cached?.worktreeName ?? worktreeName(cwdOrDecoded) ?? void 0;
2601
+ const repo = projectKey(projectName);
2420
2602
  const agg = canonicalMap.get(repo) ?? {
2421
2603
  canonicalName: repo,
2422
2604
  count: 0,
@@ -2482,6 +2664,7 @@ var init_claude_code = __esm({
2482
2664
  "use strict";
2483
2665
  init_parser();
2484
2666
  init_analytics();
2667
+ init_git_project();
2485
2668
  init_team();
2486
2669
  init_agent_metadata();
2487
2670
  init_calibration();
@@ -2788,13 +2971,16 @@ function parseRollout(file, lines) {
2788
2971
  const activeSegments = computeActiveSegments2(tsMs);
2789
2972
  const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
2790
2973
  const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
2791
- const projectName = cwd ? canonicalProjectName(cwd) : "(unknown)";
2974
+ const project = cwd ? resolveProjectIdentity(cwd) : void 0;
2975
+ const projectName = project?.projectName ?? "(unknown)";
2792
2976
  const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : "(unknown)";
2793
2977
  const meta = {
2794
2978
  agent: "codex",
2795
2979
  id: file.sessionId,
2796
2980
  filePath: file.filePath,
2797
2981
  projectName,
2982
+ worktreeName: project?.worktreeName,
2983
+ repoName: project?.repoName,
2798
2984
  projectDir,
2799
2985
  sessionId: file.sessionId,
2800
2986
  firstTimestamp,
@@ -2926,13 +3112,16 @@ async function getLatestCodexUsage(opts = {}) {
2926
3112
  const fiveResetUnix = numberOf(primary?.resets_at);
2927
3113
  const sevenResetUnix = numberOf(secondary?.resets_at);
2928
3114
  const planType = typeof rl.plan_type === "string" ? rl.plan_type : null;
3115
+ const nowMs = Date.now();
3116
+ const fiveExpired = fiveResetUnix !== void 0 && nowMs > fiveResetUnix * 1e3;
3117
+ const sevenExpired = sevenResetUnix !== void 0 && nowMs > sevenResetUnix * 1e3;
2929
3118
  return {
2930
3119
  five_hour: {
2931
- utilization: fivePct ?? null,
3120
+ utilization: fiveExpired ? 0 : fivePct ?? null,
2932
3121
  resets_at: fiveResetUnix !== void 0 ? new Date(fiveResetUnix * 1e3).toISOString() : null
2933
3122
  },
2934
3123
  seven_day: {
2935
- utilization: sevenPct ?? null,
3124
+ utilization: sevenExpired ? 0 : sevenPct ?? null,
2936
3125
  resets_at: sevenResetUnix !== void 0 ? new Date(sevenResetUnix * 1e3).toISOString() : null
2937
3126
  },
2938
3127
  plan_type: planType,
@@ -2953,6 +3142,7 @@ var init_codex = __esm({
2953
3142
  "../parser/dist/codex.js"() {
2954
3143
  "use strict";
2955
3144
  init_analytics();
3145
+ init_git_project();
2956
3146
  init_user_input();
2957
3147
  DEFAULT_CODEX_ROOT = path2.join(os2.homedir(), ".codex", "sessions");
2958
3148
  ROLLOUT_RE = /^rollout-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})-([0-9a-f-]+)\.jsonl$/;
@@ -3332,13 +3522,16 @@ async function parseSession(file) {
3332
3522
  const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
3333
3523
  const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
3334
3524
  const sessionId = metaRec.sessionId ?? file.filenameId;
3335
- const projectName = cwd ? canonicalProjectName(cwd) : file.slug;
3525
+ const project = cwd ? resolveProjectIdentity(cwd) : void 0;
3526
+ const projectName = project?.projectName ?? file.slug;
3336
3527
  const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
3337
3528
  const meta = {
3338
3529
  agent: "gemini",
3339
3530
  id: sessionId,
3340
3531
  filePath: file.filePath,
3341
3532
  projectName,
3533
+ worktreeName: project?.worktreeName,
3534
+ repoName: project?.repoName,
3342
3535
  projectDir,
3343
3536
  sessionId,
3344
3537
  firstTimestamp,
@@ -3452,6 +3645,7 @@ var init_gemini = __esm({
3452
3645
  "../parser/dist/gemini.js"() {
3453
3646
  "use strict";
3454
3647
  init_analytics();
3648
+ init_git_project();
3455
3649
  init_user_input();
3456
3650
  DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
3457
3651
  GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
@@ -3725,13 +3919,16 @@ async function parseSession2(file) {
3725
3919
  const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
3726
3920
  const sessionId = file.conversationId;
3727
3921
  const cwd = file.cwd;
3728
- const projectName = cwd ? canonicalProjectName(cwd) : file.conversationId;
3922
+ const project = cwd ? resolveProjectIdentity(cwd) : void 0;
3923
+ const projectName = project?.projectName ?? file.conversationId;
3729
3924
  const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.conversationId;
3730
3925
  const meta = {
3731
3926
  agent: "antigravity",
3732
3927
  id: sessionId,
3733
3928
  filePath: file.filePath,
3734
3929
  projectName,
3930
+ worktreeName: project?.worktreeName,
3931
+ repoName: project?.repoName,
3735
3932
  projectDir,
3736
3933
  sessionId,
3737
3934
  firstTimestamp,
@@ -3838,6 +4035,7 @@ var init_antigravity = __esm({
3838
4035
  "../parser/dist/antigravity.js"() {
3839
4036
  "use strict";
3840
4037
  init_analytics();
4038
+ init_git_project();
3841
4039
  init_user_input();
3842
4040
  DEFAULT_ANTIGRAVITY_ROOT = path4.join(os4.homedir(), ".gemini", "antigravity-cli");
3843
4041
  IDLE_GAP_MS3 = 3 * 60 * 1e3;
@@ -3957,8 +4155,10 @@ function resolveProject(meta, spaceIdToPath) {
3957
4155
  if (!projectPath) {
3958
4156
  return { projectName: "cowork:unspaced", projectDir: "cowork-unspaced" };
3959
4157
  }
4158
+ const project = resolveProjectIdentity(projectPath);
3960
4159
  return {
3961
- projectName: canonicalProjectName(projectPath),
4160
+ projectName: project.projectName,
4161
+ worktreeName: project.worktreeName,
3962
4162
  projectDir: projectPath.replace(/^\//, "-").replace(/\//g, "-"),
3963
4163
  cwd: projectPath
3964
4164
  };
@@ -4185,8 +4385,8 @@ var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache5, detailCache5;
4185
4385
  var init_cowork = __esm({
4186
4386
  "../parser/dist/cowork.js"() {
4187
4387
  "use strict";
4188
- init_analytics();
4189
4388
  init_claude_code();
4389
+ init_git_project();
4190
4390
  init_parser();
4191
4391
  DEFAULT_COWORK_ROOT = defaultCoworkRoot();
4192
4392
  SESSION_ID_RE = /^local_[0-9a-f-]+$/;
@@ -4197,36 +4397,36 @@ var init_cowork = __esm({
4197
4397
  });
4198
4398
 
4199
4399
  // ../parser/dist/team-config.js
4200
- import { readFileSync as readFileSync3, writeFileSync, unlinkSync, mkdirSync as mkdirSync2, renameSync } from "node:fs";
4201
- import { join as join2 } from "node:path";
4202
- function shouldSyncProject(repoName, sp) {
4400
+ import { readFileSync as readFileSync3, writeFileSync, unlinkSync, mkdirSync, renameSync } from "node:fs";
4401
+ import { join as join3 } from "node:path";
4402
+ function shouldSyncProject(projectKey2, sp) {
4203
4403
  if (!sp)
4204
4404
  return true;
4205
- if (sp.excluded.includes(repoName))
4405
+ if (sp.excluded.includes(projectKey2))
4206
4406
  return false;
4207
- if (sp.included.includes(repoName))
4407
+ if (sp.included.includes(projectKey2))
4208
4408
  return true;
4209
4409
  return sp.autoIncludeNew;
4210
4410
  }
4211
4411
  function readTeamConfig(dir) {
4212
4412
  const d = dir ?? cclensHome();
4213
4413
  try {
4214
- return JSON.parse(readFileSync3(join2(d, CONFIG_FILE), "utf8"));
4414
+ return JSON.parse(readFileSync3(join3(d, CONFIG_FILE), "utf8"));
4215
4415
  } catch {
4216
4416
  return null;
4217
4417
  }
4218
4418
  }
4219
4419
  function writeTeamConfig(config, dir) {
4220
4420
  const d = dir ?? cclensHome();
4221
- mkdirSync2(d, { recursive: true });
4222
- const tmp = join2(d, `${CONFIG_FILE}.${process.pid}.tmp`);
4421
+ mkdirSync(d, { recursive: true });
4422
+ const tmp = join3(d, `${CONFIG_FILE}.${process.pid}.tmp`);
4223
4423
  writeFileSync(tmp, JSON.stringify(config, null, 2), { mode: 384 });
4224
- renameSync(tmp, join2(d, CONFIG_FILE));
4424
+ renameSync(tmp, join3(d, CONFIG_FILE));
4225
4425
  }
4226
4426
  function clearTeamConfig(dir) {
4227
4427
  const d = dir ?? cclensHome();
4228
4428
  try {
4229
- unlinkSync(join2(d, CONFIG_FILE));
4429
+ unlinkSync(join3(d, CONFIG_FILE));
4230
4430
  } catch {
4231
4431
  }
4232
4432
  }
@@ -4259,6 +4459,7 @@ __export(fs_exports, {
4259
4459
  RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
4260
4460
  agentSources: () => agentSources,
4261
4461
  antigravitySessionLocalDay: () => antigravitySessionLocalDay,
4462
+ appendUsageSnapshot: () => appendUsageSnapshot,
4262
4463
  buildCalibrationCurve: () => buildCalibrationCurve,
4263
4464
  cacheStats: () => cacheStats,
4264
4465
  cclensHome: () => cclensHome,
@@ -4292,14 +4493,17 @@ __export(fs_exports, {
4292
4493
  loadTeamForSession: () => loadTeamForSession,
4293
4494
  loadUsageByDay: () => loadUsageByDay,
4294
4495
  loadWorkflowAgentDetail: () => loadWorkflowAgentDetail,
4496
+ pruneUsageAgent: () => pruneUsageAgent,
4497
+ readGitFolder: () => readGitFolder,
4295
4498
  readJsonlFile: () => readJsonlFile,
4296
4499
  readTeamConfig: () => readTeamConfig,
4500
+ resolveProjectIdentity: () => resolveProjectIdentity,
4297
4501
  sessionIdFromFileName: () => sessionIdFromFileName,
4298
4502
  shouldSyncProject: () => shouldSyncProject,
4299
4503
  walkJsonlFiles: () => walkJsonlFiles,
4300
4504
  writeTeamConfig: () => writeTeamConfig
4301
4505
  });
4302
- import { promises as fs6 } from "node:fs";
4506
+ import { promises as fs6, existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2, appendFileSync, mkdirSync as mkdirSync2 } from "node:fs";
4303
4507
  import os6 from "node:os";
4304
4508
  import path6 from "node:path";
4305
4509
  function cclensHome() {
@@ -4345,6 +4549,27 @@ async function getAnySession(id) {
4345
4549
  function usageLogPath() {
4346
4550
  return cclensPath("usage.jsonl");
4347
4551
  }
4552
+ function appendUsageSnapshot(snapshot) {
4553
+ const p = usageLogPath();
4554
+ mkdirSync2(path6.dirname(p), { recursive: true });
4555
+ appendFileSync(p, JSON.stringify(snapshot) + "\n", "utf8");
4556
+ }
4557
+ function pruneUsageAgent(agent) {
4558
+ const p = usageLogPath();
4559
+ if (!existsSync2(p))
4560
+ return;
4561
+ const kept = readFileSync4(p, "utf8").split("\n").filter((line) => {
4562
+ if (!line.trim())
4563
+ return false;
4564
+ try {
4565
+ return JSON.parse(line).agent !== agent;
4566
+ } catch {
4567
+ return true;
4568
+ }
4569
+ });
4570
+ mkdirSync2(path6.dirname(p), { recursive: true });
4571
+ writeFileSync2(p, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
4572
+ }
4348
4573
  async function loadUsageByDay(start, end) {
4349
4574
  let raw;
4350
4575
  try {
@@ -4569,6 +4794,7 @@ var init_fs = __esm({
4569
4794
  init_antigravity();
4570
4795
  init_cowork();
4571
4796
  init_claude_code();
4797
+ init_git_project();
4572
4798
  init_codex();
4573
4799
  init_gemini();
4574
4800
  init_antigravity();
@@ -4636,6 +4862,53 @@ var init_fs = __esm({
4636
4862
  }
4637
4863
  });
4638
4864
 
4865
+ // src/usage/storage.ts
4866
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync4 } from "node:fs";
4867
+ import { dirname as dirname2 } from "node:path";
4868
+ function appendSnapshot(filePath, snapshot) {
4869
+ mkdirSync3(dirname2(filePath), { recursive: true });
4870
+ appendFileSync2(filePath, JSON.stringify(snapshot) + "\n", "utf8");
4871
+ }
4872
+ function readSnapshots(filePath) {
4873
+ if (!existsSync4(filePath)) return [];
4874
+ const content = readFileSync6(filePath, "utf8");
4875
+ const snapshots = [];
4876
+ for (const line of content.split("\n")) {
4877
+ if (!line.trim()) continue;
4878
+ try {
4879
+ snapshots.push(JSON.parse(line));
4880
+ } catch {
4881
+ }
4882
+ }
4883
+ return snapshots;
4884
+ }
4885
+ function pruneAgent(filePath, agent) {
4886
+ if (!existsSync4(filePath)) return;
4887
+ const kept = readFileSync6(filePath, "utf8").split("\n").filter((line) => {
4888
+ if (!line.trim()) return false;
4889
+ try {
4890
+ return JSON.parse(line).agent !== agent;
4891
+ } catch {
4892
+ return true;
4893
+ }
4894
+ });
4895
+ mkdirSync3(dirname2(filePath), { recursive: true });
4896
+ writeFileSync3(filePath, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
4897
+ }
4898
+ function latestClaudeCodeSnapshot(filePath) {
4899
+ const all = readSnapshots(filePath);
4900
+ for (let i = all.length - 1; i >= 0; i--) {
4901
+ const s = all[i];
4902
+ if (!s.agent || s.agent === "claude-code") return s;
4903
+ }
4904
+ return null;
4905
+ }
4906
+ var init_storage = __esm({
4907
+ "src/usage/storage.ts"() {
4908
+ "use strict";
4909
+ }
4910
+ });
4911
+
4639
4912
  // ../parser/dist/types.js
4640
4913
  var init_types = __esm({
4641
4914
  "../parser/dist/types.js"() {
@@ -5053,11 +5326,13 @@ __export(dist_exports, {
5053
5326
  RATE_PER_PCT: () => RATE_PER_PCT,
5054
5327
  RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
5055
5328
  RATE_PER_PCT_7D: () => RATE_PER_PCT_7D,
5329
+ ZAI_METADATA: () => ZAI_METADATA,
5056
5330
  agentMetadata: () => agentMetadata,
5057
5331
  aggregateConcurrency: () => aggregateConcurrency,
5058
5332
  buildGanttDay: () => buildGanttDay,
5059
5333
  buildMegaRows: () => buildMegaRows,
5060
5334
  buildPresentation: () => buildPresentation,
5335
+ buildProjectKeyResolver: () => buildProjectKeyResolver,
5061
5336
  buildSpendIndex: () => buildSpendIndex,
5062
5337
  calendarMonth: () => calendarMonth,
5063
5338
  calendarWeek: () => calendarWeek,
@@ -5086,10 +5361,12 @@ __export(dist_exports, {
5086
5361
  predictAnchored: () => predictAnchored,
5087
5362
  priorCalendarMonth: () => priorCalendarMonth,
5088
5363
  priorCalendarWeek: () => priorCalendarWeek,
5364
+ projectKey: () => projectKey,
5089
5365
  projectRepoName: () => projectRepoName,
5090
5366
  rowPrimaryIndex: () => rowPrimaryIndex,
5091
5367
  sessionAirTimeMs: () => sessionAirTimeMs,
5092
5368
  sessionDay: () => sessionDay,
5369
+ sessionProjectKey: () => sessionProjectKey,
5093
5370
  stripFrameworkBoilerplate: () => stripFrameworkBoilerplate,
5094
5371
  summarizeBursts: () => summarizeBursts,
5095
5372
  toLocalDay: () => toLocalDay,
@@ -5118,25 +5395,25 @@ __export(file_probe_exports, {
5118
5395
  probeArtifactSignals: () => probeArtifactSignals
5119
5396
  });
5120
5397
  import { createHash } from "node:crypto";
5121
- import { existsSync as existsSync6, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
5122
- import { homedir as homedir2 } from "node:os";
5123
- import { join as join7, relative, resolve as resolve2, sep } from "node:path";
5398
+ import { existsSync as existsSync9, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
5399
+ import { homedir as homedir3 } from "node:os";
5400
+ import { join as join8, relative, resolve as resolve3, sep } from "node:path";
5124
5401
  import { execFileSync as execFileSync2 } from "node:child_process";
5125
5402
  function pathHash(relPath) {
5126
5403
  return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
5127
5404
  }
5128
5405
  function defaultScanRoots(extraRoots = []) {
5129
5406
  const roots = [];
5130
- const home = join7(homedir2(), ".claude");
5131
- if (existsSync6(home)) roots.push({ root: home, label: "user" });
5407
+ const home = join8(homedir3(), ".claude");
5408
+ if (existsSync9(home)) roots.push({ root: home, label: "user" });
5132
5409
  for (const e of extraRoots) {
5133
- const r = resolve2(e, ".claude");
5134
- if (existsSync6(r) && r !== home) roots.push({ root: r, label: "project" });
5410
+ const r = resolve3(e, ".claude");
5411
+ if (existsSync9(r) && r !== home) roots.push({ root: r, label: "project" });
5135
5412
  }
5136
5413
  return roots;
5137
5414
  }
5138
5415
  function listMarkdownFiles(dir) {
5139
- if (!existsSync6(dir)) return [];
5416
+ if (!existsSync9(dir)) return [];
5140
5417
  const out = [];
5141
5418
  let entries;
5142
5419
  try {
@@ -5146,10 +5423,10 @@ function listMarkdownFiles(dir) {
5146
5423
  }
5147
5424
  for (const name of entries) {
5148
5425
  if (name.startsWith(".")) continue;
5149
- const full = join7(dir, name);
5426
+ const full = join8(dir, name);
5150
5427
  let stat;
5151
5428
  try {
5152
- stat = statSync4(full);
5429
+ stat = statSync5(full);
5153
5430
  } catch {
5154
5431
  continue;
5155
5432
  }
@@ -5166,19 +5443,19 @@ function firstSeenDateOf(file) {
5166
5443
  const out = execFileSync2(
5167
5444
  "git",
5168
5445
  ["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
5169
- { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname7(file) }
5446
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname8(file) }
5170
5447
  ).trim().split("\n").filter(Boolean);
5171
5448
  if (out.length > 0) return out[out.length - 1];
5172
5449
  } catch {
5173
5450
  }
5174
5451
  try {
5175
- const s = statSync4(file);
5452
+ const s = statSync5(file);
5176
5453
  return localDay(s.birthtime || s.mtime);
5177
5454
  } catch {
5178
5455
  return todayLocal();
5179
5456
  }
5180
5457
  }
5181
- function dirname7(p) {
5458
+ function dirname8(p) {
5182
5459
  const i = p.lastIndexOf(sep);
5183
5460
  return i < 0 ? "." : p.slice(0, i);
5184
5461
  }
@@ -5205,8 +5482,8 @@ function todayLocal() {
5205
5482
  function scanAuthored(roots, subdir, day) {
5206
5483
  const out = [];
5207
5484
  for (const r of roots) {
5208
- const dir = join7(r.root, subdir);
5209
- if (!existsSync6(dir)) continue;
5485
+ const dir = join8(r.root, subdir);
5486
+ if (!existsSync9(dir)) continue;
5210
5487
  for (const f of listMarkdownFiles(dir)) {
5211
5488
  const firstSeen = firstSeenDateOf(f);
5212
5489
  if (firstSeen !== day) continue;
@@ -5219,14 +5496,14 @@ function scanAuthored(roots, subdir, day) {
5219
5496
  function scanEdited(roots, day) {
5220
5497
  const out = [];
5221
5498
  for (const r of roots) {
5222
- const dir = join7(r.root, "skills");
5223
- if (!existsSync6(dir)) continue;
5499
+ const dir = join8(r.root, "skills");
5500
+ if (!existsSync9(dir)) continue;
5224
5501
  for (const f of listMarkdownFiles(dir)) {
5225
5502
  const firstSeen = firstSeenDateOf(f);
5226
5503
  if (firstSeen === day) continue;
5227
5504
  let stat;
5228
5505
  try {
5229
- stat = statSync4(f);
5506
+ stat = statSync5(f);
5230
5507
  } catch {
5231
5508
  continue;
5232
5509
  }
@@ -5242,17 +5519,17 @@ function claudemdLineDelta(extraRoots, authorEmail, day) {
5242
5519
  let delta = 0;
5243
5520
  const candidates = [];
5244
5521
  for (const e of extraRoots) {
5245
- const f = resolve2(e, "CLAUDE.md");
5246
- if (existsSync6(f)) candidates.push(f);
5522
+ const f = resolve3(e, "CLAUDE.md");
5523
+ if (existsSync9(f)) candidates.push(f);
5247
5524
  }
5248
- const homeClaudeMd = join7(homedir2(), "CLAUDE.md");
5249
- if (existsSync6(homeClaudeMd)) candidates.push(homeClaudeMd);
5525
+ const homeClaudeMd = join8(homedir3(), "CLAUDE.md");
5526
+ if (existsSync9(homeClaudeMd)) candidates.push(homeClaudeMd);
5250
5527
  for (const file of candidates) {
5251
5528
  try {
5252
5529
  const out = execFileSync2(
5253
5530
  "git",
5254
5531
  ["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
5255
- { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname7(file) }
5532
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname8(file) }
5256
5533
  );
5257
5534
  let currentDate = "";
5258
5535
  let currentEmail = "";
@@ -5303,8 +5580,8 @@ var init_file_probe = __esm({
5303
5580
 
5304
5581
  // src/daemon-worker.ts
5305
5582
  import { spawn as spawn2 } from "node:child_process";
5306
- import { closeSync, existsSync as existsSync13, mkdirSync as mkdirSync13, openSync, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "node:fs";
5307
- import { dirname as dirname10, join as join11 } from "node:path";
5583
+ import { closeSync, existsSync as existsSync16, mkdirSync as mkdirSync14, openSync, readFileSync as readFileSync19, writeFileSync as writeFileSync14 } from "node:fs";
5584
+ import { dirname as dirname11, join as join12 } from "node:path";
5308
5585
  import { fileURLToPath } from "node:url";
5309
5586
 
5310
5587
  // src/usage/token.ts
@@ -5445,16 +5722,120 @@ function normalizeExtra(raw) {
5445
5722
  };
5446
5723
  }
5447
5724
 
5725
+ // src/usage/zai.ts
5726
+ init_fs();
5727
+ import { existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
5728
+ var ZAI_QUOTA_ENDPOINT = "https://api.z.ai/api/monitor/usage/quota/limit";
5729
+ var ZAI_SUBSCRIPTION_ENDPOINT = "https://api.z.ai/api/biz/subscription/list";
5730
+ var ZaiApiError = class extends Error {
5731
+ constructor(message, code) {
5732
+ super(message);
5733
+ this.code = code;
5734
+ }
5735
+ };
5736
+ function resolveApiKey() {
5737
+ try {
5738
+ const p = cclensPath("credentials.json");
5739
+ if (existsSync3(p)) {
5740
+ const store = JSON.parse(readFileSync5(p, "utf8"));
5741
+ return store.zai?.apiKey ?? null;
5742
+ }
5743
+ } catch {
5744
+ }
5745
+ return null;
5746
+ }
5747
+ function epochMsToIso(ms) {
5748
+ if (typeof ms !== "number" || Number.isNaN(ms)) return null;
5749
+ return new Date(ms).toISOString();
5750
+ }
5751
+ function windowFromLimit(limit) {
5752
+ return {
5753
+ utilization: typeof limit.percentage === "number" ? limit.percentage : null,
5754
+ resets_at: epochMsToIso(limit.nextResetTime)
5755
+ };
5756
+ }
5757
+ function zaiHeaders(key) {
5758
+ return { Authorization: key, "Accept-Language": "en-US,en" };
5759
+ }
5760
+ async function fetchZaiUsage() {
5761
+ const key = resolveApiKey();
5762
+ if (!key) {
5763
+ throw new ZaiApiError(
5764
+ "No Z.ai API key found. Set ZAI_API_KEY (or GLM_API_KEY), or write ~/.config/zai/key.json.",
5765
+ "no_key"
5766
+ );
5767
+ }
5768
+ let res;
5769
+ try {
5770
+ res = await fetch(ZAI_QUOTA_ENDPOINT, { headers: zaiHeaders(key) });
5771
+ } catch (err) {
5772
+ throw new ZaiApiError(`Network error reaching Z.ai: ${err.message}`, "network");
5773
+ }
5774
+ if (!res.ok) {
5775
+ throw new ZaiApiError(`Z.ai quota endpoint returned ${res.status} ${res.statusText}`, "http");
5776
+ }
5777
+ let body;
5778
+ try {
5779
+ body = await res.json();
5780
+ } catch (err) {
5781
+ throw new ZaiApiError(`Failed to parse Z.ai quota response: ${err.message}`, "parse");
5782
+ }
5783
+ const b = body;
5784
+ const limits = b.data?.limits ?? [];
5785
+ let fiveHour = null;
5786
+ let sevenDay = null;
5787
+ let webSearch = null;
5788
+ for (const limit of limits) {
5789
+ if (limit.type === "TIME_LIMIT") {
5790
+ const percentage = typeof limit.percentage === "number" ? limit.percentage : null;
5791
+ webSearch = {
5792
+ used: percentage,
5793
+ limit: percentage !== null ? 100 : null
5794
+ };
5795
+ continue;
5796
+ }
5797
+ const window = windowFromLimit(limit);
5798
+ if (limit.unit === 6) {
5799
+ sevenDay = sevenDay ?? window;
5800
+ } else {
5801
+ fiveHour = fiveHour ?? window;
5802
+ }
5803
+ }
5804
+ let planType = null;
5805
+ try {
5806
+ const subRes = await fetch(ZAI_SUBSCRIPTION_ENDPOINT, { headers: zaiHeaders(key) });
5807
+ if (subRes.ok) {
5808
+ const sub = await subRes.json();
5809
+ const entry = sub.data?.[0];
5810
+ planType = entry?.productName || entry?.planName || entry?.name || null;
5811
+ }
5812
+ } catch {
5813
+ }
5814
+ return {
5815
+ captured_at: (/* @__PURE__ */ new Date()).toISOString(),
5816
+ agent: "zai",
5817
+ five_hour: fiveHour ?? { utilization: null, resets_at: null },
5818
+ seven_day: sevenDay ?? { utilization: null, resets_at: null },
5819
+ seven_day_opus: null,
5820
+ seven_day_sonnet: null,
5821
+ seven_day_oauth_apps: null,
5822
+ seven_day_cowork: null,
5823
+ extra_usage: null,
5824
+ plan_type: planType,
5825
+ web_search_quota: webSearch ?? null
5826
+ };
5827
+ }
5828
+
5448
5829
  // src/daemon-worker.ts
5449
5830
  init_storage();
5450
5831
  init_fs();
5451
5832
 
5452
5833
  // src/daemon-log.ts
5453
5834
  init_fs();
5454
- import { appendFileSync as appendFileSync2 } from "node:fs";
5835
+ import { appendFileSync as appendFileSync3 } from "node:fs";
5455
5836
  function appendDaemonLogLine(level, msg) {
5456
5837
  try {
5457
- appendFileSync2(
5838
+ appendFileSync3(
5458
5839
  cclensPath("daemon.log"),
5459
5840
  `${(/* @__PURE__ */ new Date()).toISOString()} ${level.toUpperCase()} ${msg}
5460
5841
  `,
@@ -5486,9 +5867,9 @@ import { randomUUID } from "node:crypto";
5486
5867
 
5487
5868
  // ../entries/dist/fs.js
5488
5869
  init_fs();
5489
- import { readFileSync as readFileSync5, readdirSync as readdirSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, renameSync as renameSync3, existsSync as existsSync3 } from "node:fs";
5870
+ import { readFileSync as readFileSync8, readdirSync as readdirSync2, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, renameSync as renameSync3, existsSync as existsSync6 } from "node:fs";
5490
5871
  import { randomBytes } from "node:crypto";
5491
- import { join as join4 } from "node:path";
5872
+ import { join as join5 } from "node:path";
5492
5873
 
5493
5874
  // ../entries/dist/types.js
5494
5875
  var CURRENT_ENTRY_SCHEMA_VERSION = 2;
@@ -5561,12 +5942,12 @@ var PROMPT_FRAME_ORIGIN = {
5561
5942
 
5562
5943
  // ../entries/dist/digest-fs.js
5563
5944
  init_fs();
5564
- import { readFileSync as readFileSync4, readdirSync, writeFileSync as writeFileSync2, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync3, existsSync as existsSync2 } from "node:fs";
5565
- import { dirname as dirname2, join as join3 } from "node:path";
5945
+ import { readFileSync as readFileSync7, readdirSync, writeFileSync as writeFileSync4, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "node:fs";
5946
+ import { dirname as dirname3, join as join4 } from "node:path";
5566
5947
  var digestsDirCached = null;
5567
5948
  function parseDigestFile(path7, expectedVersion) {
5568
5949
  try {
5569
- const parsed = JSON.parse(readFileSync4(path7, "utf8"));
5950
+ const parsed = JSON.parse(readFileSync7(path7, "utf8"));
5570
5951
  if (!parsed || typeof parsed !== "object")
5571
5952
  return null;
5572
5953
  if (parsed.version !== expectedVersion)
@@ -5586,16 +5967,16 @@ function digestsDir() {
5586
5967
  return digestsDirCached;
5587
5968
  }
5588
5969
  function dayDigestPath(date) {
5589
- return join3(digestsDir(), "day", `${date}.json`);
5970
+ return join4(digestsDir(), "day", `${date}.json`);
5590
5971
  }
5591
5972
  function weekDigestPath(monday) {
5592
- return join3(digestsDir(), "week", `${monday}.json`);
5973
+ return join4(digestsDir(), "week", `${monday}.json`);
5593
5974
  }
5594
5975
  function writeDayDigest(digest) {
5595
5976
  const final = dayDigestPath(digest.key);
5596
- mkdirSync3(dirname2(final), { recursive: true });
5977
+ mkdirSync4(dirname3(final), { recursive: true });
5597
5978
  const tmp = `${final}.tmp`;
5598
- writeFileSync2(tmp, JSON.stringify(digest, null, 2), "utf8");
5979
+ writeFileSync4(tmp, JSON.stringify(digest, null, 2), "utf8");
5599
5980
  if (process.platform !== "win32") {
5600
5981
  try {
5601
5982
  chmodSync(tmp, 384);
@@ -5606,7 +5987,7 @@ function writeDayDigest(digest) {
5606
5987
  }
5607
5988
  function readDayDigest(date) {
5608
5989
  const p = dayDigestPath(date);
5609
- if (!existsSync2(p))
5990
+ if (!existsSync5(p))
5610
5991
  return null;
5611
5992
  return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
5612
5993
  }
@@ -5626,9 +6007,9 @@ function setTodayDigestInCache(date, digest, nowMs) {
5626
6007
  }
5627
6008
  function writeWeekDigest(digest) {
5628
6009
  const final = weekDigestPath(digest.key);
5629
- mkdirSync3(dirname2(final), { recursive: true });
6010
+ mkdirSync4(dirname3(final), { recursive: true });
5630
6011
  const tmp = `${final}.tmp`;
5631
- writeFileSync2(tmp, JSON.stringify(digest, null, 2), "utf8");
6012
+ writeFileSync4(tmp, JSON.stringify(digest, null, 2), "utf8");
5632
6013
  if (process.platform !== "win32") {
5633
6014
  try {
5634
6015
  chmodSync(tmp, 384);
@@ -5639,7 +6020,7 @@ function writeWeekDigest(digest) {
5639
6020
  }
5640
6021
  function readWeekDigest(monday) {
5641
6022
  const p = weekDigestPath(monday);
5642
- if (!existsSync2(p))
6023
+ if (!existsSync5(p))
5643
6024
  return null;
5644
6025
  return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
5645
6026
  }
@@ -5669,18 +6050,18 @@ function entriesDir() {
5669
6050
  return entriesDirCached;
5670
6051
  }
5671
6052
  function pathFor(sessionId, localDay2) {
5672
- return join4(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
6053
+ return join5(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
5673
6054
  }
5674
6055
  function tmpPathFor(final) {
5675
6056
  return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
5676
6057
  }
5677
6058
  function writeEntry(entry) {
5678
6059
  const dir = entriesDir();
5679
- mkdirSync4(dir, { recursive: true });
6060
+ mkdirSync5(dir, { recursive: true });
5680
6061
  const final = pathFor(entry.session_id, entry.local_day);
5681
6062
  const tmp = tmpPathFor(final);
5682
6063
  const json = JSON.stringify(entry, null, 2);
5683
- writeFileSync3(tmp, json, { encoding: "utf8" });
6064
+ writeFileSync5(tmp, json, { encoding: "utf8" });
5684
6065
  renameSync3(tmp, final);
5685
6066
  }
5686
6067
  var PRESERVABLE_STATUSES = /* @__PURE__ */ new Set([
@@ -5704,7 +6085,7 @@ function enrichmentInputHash(e) {
5704
6085
  }
5705
6086
  function writeEntryPreservingEnrichment(fresh) {
5706
6087
  const dir = entriesDir();
5707
- mkdirSync4(dir, { recursive: true });
6088
+ mkdirSync5(dir, { recursive: true });
5708
6089
  const final = pathFor(fresh.session_id, fresh.local_day);
5709
6090
  const existing = readEntry(fresh.session_id, fresh.local_day);
5710
6091
  let toWrite = fresh;
@@ -5712,22 +6093,22 @@ function writeEntryPreservingEnrichment(fresh) {
5712
6093
  toWrite = { ...fresh, enrichment: existing.enrichment };
5713
6094
  }
5714
6095
  const tmp = tmpPathFor(final);
5715
- writeFileSync3(tmp, JSON.stringify(toWrite, null, 2), { encoding: "utf8" });
6096
+ writeFileSync5(tmp, JSON.stringify(toWrite, null, 2), { encoding: "utf8" });
5716
6097
  renameSync3(tmp, final);
5717
6098
  }
5718
6099
  function readEntry(sessionId, localDay2) {
5719
6100
  const p = pathFor(sessionId, localDay2);
5720
- if (!existsSync3(p))
6101
+ if (!existsSync6(p))
5721
6102
  return null;
5722
- const raw = readFileSync5(p, "utf8");
6103
+ const raw = readFileSync8(p, "utf8");
5723
6104
  return JSON.parse(raw);
5724
6105
  }
5725
6106
  function entryExists(sessionId, localDay2) {
5726
- return existsSync3(pathFor(sessionId, localDay2));
6107
+ return existsSync6(pathFor(sessionId, localDay2));
5727
6108
  }
5728
6109
  function listEntryKeys() {
5729
6110
  const dir = entriesDir();
5730
- if (!existsSync3(dir))
6111
+ if (!existsSync6(dir))
5731
6112
  return [];
5732
6113
  return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
5733
6114
  }
@@ -5746,8 +6127,8 @@ function listEntriesForDay(localDay2) {
5746
6127
 
5747
6128
  // src/perception/build-entries.ts
5748
6129
  init_dist();
5749
- import { statSync, readFileSync as readFileSync6 } from "node:fs";
5750
- import { basename, dirname as dirname3 } from "node:path";
6130
+ import { statSync as statSync2, readFileSync as readFileSync9 } from "node:fs";
6131
+ import { basename as basename2, dirname as dirname4 } from "node:path";
5751
6132
 
5752
6133
  // ../entries/dist/signals.js
5753
6134
  init_dist();
@@ -6338,6 +6719,7 @@ function buildEntries(sessionDetail) {
6338
6719
  const entries = [];
6339
6720
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
6340
6721
  const sessionFallbackProject = canonicalProjectName(sessionDetail.projectName ?? "");
6722
+ const trustSessionProject = !!sessionDetail.worktreeName;
6341
6723
  for (const [local_day, dayEvents] of byDay) {
6342
6724
  if (dayEvents.length === 0)
6343
6725
  continue;
@@ -6402,7 +6784,7 @@ function buildEntries(sessionDetail) {
6402
6784
  const finalAgentRaw = agg.finalAgent ?? "";
6403
6785
  const final_agent = trunc(minimizeImages(finalAgentRaw), 400);
6404
6786
  let project = sessionFallbackProject;
6405
- if (agg.cwdCounts.size > 0) {
6787
+ if (!trustSessionProject && agg.cwdCounts.size > 0) {
6406
6788
  const best = [...agg.cwdCounts.entries()].sort((a, b) => b[1] - a[1])[0];
6407
6789
  project = canonicalProjectName(best[0]);
6408
6790
  }
@@ -6484,8 +6866,8 @@ function decodeProjectDirName(projectDir) {
6484
6866
  return projectDir.replace(/-/g, "/");
6485
6867
  }
6486
6868
  function buildEntriesForFile(filePath) {
6487
- const stat = statSync(filePath);
6488
- const raw = readFileSync6(filePath, "utf8");
6869
+ const stat = statSync2(filePath);
6870
+ const raw = readFileSync9(filePath, "utf8");
6489
6871
  const rawLines = raw.split("\n").filter(Boolean).map((l) => {
6490
6872
  try {
6491
6873
  return JSON.parse(l);
@@ -6495,8 +6877,8 @@ function buildEntriesForFile(filePath) {
6495
6877
  }).filter((x) => x !== null);
6496
6878
  if (rawLines.length === 0) return null;
6497
6879
  const { meta, events } = parseTranscript(rawLines);
6498
- const fileName = basename(filePath);
6499
- const projectDir = basename(dirname3(filePath));
6880
+ const fileName = basename2(filePath);
6881
+ const projectDir = basename2(dirname4(filePath));
6500
6882
  const sessionId = fileName.replace(/\.jsonl$/, "");
6501
6883
  const sd = {
6502
6884
  ...meta,
@@ -6577,7 +6959,7 @@ function clipSegmentsToDay(segments, bounds) {
6577
6959
  }
6578
6960
  function filterSyncedSessions(sessions, syncProjects) {
6579
6961
  if (!syncProjects) return sessions;
6580
- return sessions.filter((s) => shouldSyncProject(projectRepoName(s.projectName), syncProjects));
6962
+ return sessions.filter((s) => shouldSyncProject(projectKey(s.projectName), syncProjects));
6581
6963
  }
6582
6964
  function sessionTouchesDay(s, day) {
6583
6965
  const bounds = dayBoundsMs(day);
@@ -6618,7 +7000,7 @@ function buildRichRollupBlocks(day, daySessions, entries, resolveRepo) {
6618
7000
  const projects = /* @__PURE__ */ new Map();
6619
7001
  for (const s of clippedSessions) {
6620
7002
  const canonical = canonicalProjectName(s.projectName);
6621
- const name = projectRepoName(s.projectName);
7003
+ const name = projectKey(s.projectName);
6622
7004
  const repo = resolveRepo?.(canonical) ?? sessionRepo.get(s.id);
6623
7005
  const key = repo ?? name;
6624
7006
  const ms = s.activeSegments.reduce((sum, seg) => sum + (seg.endMs - seg.startMs), 0);
@@ -6661,7 +7043,7 @@ function buildRichRollupBlocks(day, daySessions, entries, resolveRepo) {
6661
7043
  commits += e.numbers.commits;
6662
7044
  pushes += e.numbers.pushes;
6663
7045
  if (e.github_repos?.length) {
6664
- const key = sessionRepo.get(e.session_id) ?? projectRepoName(e.project);
7046
+ const key = sessionRepo.get(e.session_id) ?? projectKey(e.project);
6665
7047
  const set = projectRepos.get(key) ?? /* @__PURE__ */ new Set();
6666
7048
  for (const r of e.github_repos) set.add(r);
6667
7049
  projectRepos.set(key, set);
@@ -6746,7 +7128,7 @@ function buildIngestPayload(inputs) {
6746
7128
  return {
6747
7129
  ingestId: randomUUID(),
6748
7130
  observedAt: (/* @__PURE__ */ new Date()).toISOString(),
6749
- cliVersion: "0.15.2",
7131
+ cliVersion: "0.15.4",
6750
7132
  ...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
6751
7133
  ...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
6752
7134
  ...richRollup ? { richRollup } : {},
@@ -6773,14 +7155,14 @@ async function pushToTeamServer(config, payload) {
6773
7155
  }
6774
7156
 
6775
7157
  // src/team/git-remote.ts
6776
- import { existsSync as existsSync4, readFileSync as readFileSync7, statSync as statSync2 } from "node:fs";
6777
- import { dirname as dirname4, isAbsolute, join as join5, resolve } from "node:path";
7158
+ import { existsSync as existsSync7, readFileSync as readFileSync10, statSync as statSync3 } from "node:fs";
7159
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join6, resolve as resolve2 } from "node:path";
6778
7160
  var GITHUB_URL_RE = /github\.com[:/]([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/;
6779
7161
  function parseGithubRemote(url) {
6780
7162
  const m = url.trim().match(GITHUB_URL_RE);
6781
7163
  return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
6782
7164
  }
6783
- function originUrl(configText) {
7165
+ function originUrl2(configText) {
6784
7166
  let inOrigin = false;
6785
7167
  for (const line of configText.split("\n")) {
6786
7168
  const t = line.trim();
@@ -6795,36 +7177,36 @@ function originUrl(configText) {
6795
7177
  return null;
6796
7178
  }
6797
7179
  function gitConfigPathFor(dir) {
6798
- const dotGit = join5(dir, ".git");
6799
- const st = statSync2(dotGit, { throwIfNoEntry: false });
7180
+ const dotGit = join6(dir, ".git");
7181
+ const st = statSync3(dotGit, { throwIfNoEntry: false });
6800
7182
  if (!st) return null;
6801
- if (st.isDirectory()) return join5(dotGit, "config");
6802
- const m = readFileSync7(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
7183
+ if (st.isDirectory()) return join6(dotGit, "config");
7184
+ const m = readFileSync10(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
6803
7185
  if (!m) return null;
6804
- const gd = isAbsolute(m[1]) ? m[1] : resolve(dir, m[1]);
6805
- const commondirFile = join5(gd, "commondir");
6806
- if (existsSync4(commondirFile)) {
6807
- const common = readFileSync7(commondirFile, "utf8").trim();
6808
- return join5(isAbsolute(common) ? common : resolve(gd, common), "config");
7186
+ const gd = isAbsolute2(m[1]) ? m[1] : resolve2(dir, m[1]);
7187
+ const commondirFile = join6(gd, "commondir");
7188
+ if (existsSync7(commondirFile)) {
7189
+ const common = readFileSync10(commondirFile, "utf8").trim();
7190
+ return join6(isAbsolute2(common) ? common : resolve2(gd, common), "config");
6809
7191
  }
6810
- return join5(gd, "config");
7192
+ return join6(gd, "config");
6811
7193
  }
6812
7194
  function createRepoResolver() {
6813
7195
  const cache = /* @__PURE__ */ new Map();
6814
7196
  return (dir) => {
6815
- if (!dir || !isAbsolute(dir)) return null;
7197
+ if (!dir || !isAbsolute2(dir)) return null;
6816
7198
  const hit = cache.get(dir);
6817
7199
  if (hit !== void 0) return hit;
6818
7200
  let repo = null;
6819
7201
  try {
6820
- for (let d = dir; ; d = dirname4(d)) {
7202
+ for (let d = dir; ; d = dirname5(d)) {
6821
7203
  const config = gitConfigPathFor(d);
6822
- if (config && existsSync4(config)) {
6823
- const url = originUrl(readFileSync7(config, "utf8"));
7204
+ if (config && existsSync7(config)) {
7205
+ const url = originUrl2(readFileSync10(config, "utf8"));
6824
7206
  repo = url ? parseGithubRemote(url) : null;
6825
7207
  break;
6826
7208
  }
6827
- if (d === dirname4(d)) break;
7209
+ if (d === dirname5(d)) break;
6828
7210
  }
6829
7211
  } catch {
6830
7212
  repo = null;
@@ -6836,17 +7218,17 @@ function createRepoResolver() {
6836
7218
 
6837
7219
  // src/team/queue.ts
6838
7220
  init_fs();
6839
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync4, appendFileSync as appendFileSync3, statSync as statSync3, mkdirSync as mkdirSync5 } from "node:fs";
6840
- import { dirname as dirname5 } from "node:path";
7221
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, appendFileSync as appendFileSync4, statSync as statSync4, mkdirSync as mkdirSync6 } from "node:fs";
7222
+ import { dirname as dirname6 } from "node:path";
6841
7223
  var QUEUE_PATH = cclensPath("ingest-queue.jsonl");
6842
7224
  var MAX_SIZE_BYTES = 10 * 1024 * 1024;
6843
7225
  var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
6844
7226
  function enqueuePayload(payload, queuePath = QUEUE_PATH) {
6845
- mkdirSync5(dirname5(queuePath), { recursive: true });
7227
+ mkdirSync6(dirname6(queuePath), { recursive: true });
6846
7228
  const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
6847
- appendFileSync3(queuePath, JSON.stringify(entry) + "\n", "utf8");
7229
+ appendFileSync4(queuePath, JSON.stringify(entry) + "\n", "utf8");
6848
7230
  try {
6849
- const { size } = statSync3(queuePath);
7231
+ const { size } = statSync4(queuePath);
6850
7232
  if (size > MAX_SIZE_BYTES) {
6851
7233
  pruneOldest(queuePath);
6852
7234
  }
@@ -6856,7 +7238,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
6856
7238
  function dequeuePayloads(queuePath = QUEUE_PATH) {
6857
7239
  let lines;
6858
7240
  try {
6859
- lines = readFileSync8(queuePath, "utf8").trim().split("\n").filter(Boolean);
7241
+ lines = readFileSync11(queuePath, "utf8").trim().split("\n").filter(Boolean);
6860
7242
  } catch {
6861
7243
  return [];
6862
7244
  }
@@ -6871,18 +7253,18 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
6871
7253
  } catch {
6872
7254
  }
6873
7255
  }
6874
- writeFileSync4(queuePath, "", "utf8");
7256
+ writeFileSync6(queuePath, "", "utf8");
6875
7257
  return valid.map((e) => e.payload);
6876
7258
  }
6877
7259
  function pruneOldest(queuePath) {
6878
7260
  let lines;
6879
7261
  try {
6880
- lines = readFileSync8(queuePath, "utf8").trim().split("\n").filter(Boolean);
7262
+ lines = readFileSync11(queuePath, "utf8").trim().split("\n").filter(Boolean);
6881
7263
  } catch {
6882
7264
  return;
6883
7265
  }
6884
7266
  const keep = lines.slice(Math.floor(lines.length / 2));
6885
- writeFileSync4(queuePath, keep.join("\n") + "\n", "utf8");
7267
+ writeFileSync6(queuePath, keep.join("\n") + "\n", "utf8");
6886
7268
  }
6887
7269
 
6888
7270
  // src/team/backfill.ts
@@ -6890,8 +7272,8 @@ init_storage();
6890
7272
  import { randomUUID as randomUUID2 } from "node:crypto";
6891
7273
 
6892
7274
  // src/usage/profile.ts
6893
- import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "node:fs";
6894
- import { dirname as dirname6 } from "node:path";
7275
+ import { existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
7276
+ import { dirname as dirname7 } from "node:path";
6895
7277
  var PROFILE_ENDPOINT = "https://api.anthropic.com/api/oauth/profile";
6896
7278
  var BETA_HEADER2 = "oauth-2025-04-20";
6897
7279
  var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -6934,9 +7316,9 @@ async function fetchProfile(nowMs = Date.now()) {
6934
7316
  };
6935
7317
  }
6936
7318
  function readCachedProfile(cachePath) {
6937
- if (!existsSync5(cachePath)) return null;
7319
+ if (!existsSync8(cachePath)) return null;
6938
7320
  try {
6939
- const raw = JSON.parse(readFileSync9(cachePath, "utf8"));
7321
+ const raw = JSON.parse(readFileSync12(cachePath, "utf8"));
6940
7322
  if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
6941
7323
  return raw;
6942
7324
  } catch {
@@ -6944,8 +7326,8 @@ function readCachedProfile(cachePath) {
6944
7326
  }
6945
7327
  }
6946
7328
  function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
6947
- mkdirSync6(dirname6(cachePath), { recursive: true });
6948
- writeFileSync5(
7329
+ mkdirSync7(dirname7(cachePath), { recursive: true });
7330
+ writeFileSync7(
6949
7331
  cachePath,
6950
7332
  JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
6951
7333
  { mode: 384 }
@@ -7105,13 +7487,13 @@ async function runTeamBackfill(log3 = noopLog, filePath = USAGE_LOG, configOverr
7105
7487
 
7106
7488
  // src/team/sync-log.ts
7107
7489
  init_fs();
7108
- import { readFileSync as readFileSync10 } from "node:fs";
7490
+ import { readFileSync as readFileSync13 } from "node:fs";
7109
7491
  var MAX_LINES = 300;
7110
7492
  var MAX_MSG_CHARS = 1900;
7111
7493
  function readPendingSyncLog(watermark) {
7112
7494
  let raw;
7113
7495
  try {
7114
- raw = readFileSync10(cclensPath("daemon.log"), "utf8");
7496
+ raw = readFileSync13(cclensPath("daemon.log"), "utf8");
7115
7497
  } catch {
7116
7498
  return { lines: [] };
7117
7499
  }
@@ -7131,13 +7513,13 @@ function readPendingSyncLog(watermark) {
7131
7513
 
7132
7514
  // src/team/last-push.ts
7133
7515
  init_fs();
7134
- import { writeFileSync as writeFileSync6, unlinkSync as unlinkSync2, mkdirSync as mkdirSync7 } from "node:fs";
7135
- import { join as join6 } from "node:path";
7516
+ import { writeFileSync as writeFileSync8, unlinkSync as unlinkSync2, mkdirSync as mkdirSync8 } from "node:fs";
7517
+ import { join as join7 } from "node:path";
7136
7518
  var LAST_PUSH_FILE = "team-last-push.json";
7137
7519
  function write(record, dir) {
7138
7520
  const d = dir ?? cclensHome();
7139
- mkdirSync7(d, { recursive: true });
7140
- writeFileSync6(join6(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
7521
+ mkdirSync8(d, { recursive: true });
7522
+ writeFileSync8(join7(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
7141
7523
  }
7142
7524
  function writeLastPushSuccess(payload, dir) {
7143
7525
  write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
@@ -7161,8 +7543,8 @@ async function dispatchCommand(command, config, log3) {
7161
7543
  }
7162
7544
  }
7163
7545
  async function runActivityBackfill(command, config, log3) {
7164
- const { listSessions: listSessions2, shouldSyncProject: shouldSyncProject2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
7165
- const { toLocalDay: toLocalDay3, projectRepoName: projectRepoName2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
7546
+ const { listSessions: listSessions2, resolveProjectIdentity: resolveProjectIdentity2, shouldSyncProject: shouldSyncProject2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
7547
+ const { toLocalDay: toLocalDay3, projectKey: projectKey2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
7166
7548
  const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
7167
7549
  const days = command.params.days;
7168
7550
  const todayMs = Date.now();
@@ -7196,7 +7578,7 @@ async function runActivityBackfill(command, config, log3) {
7196
7578
  const richBlocks = buildRichBlocksForDay(rollup.day, daySessions, resolveRepo);
7197
7579
  let artifactSignals = null;
7198
7580
  try {
7199
- const cwdAllowed = shouldSyncProject2(projectRepoName2(process.cwd()), config.syncProjects);
7581
+ const cwdAllowed = shouldSyncProject2(projectKey2(resolveProjectIdentity2(process.cwd()).projectName), config.syncProjects);
7200
7582
  artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: cwdAllowed ? [process.cwd()] : [] });
7201
7583
  } catch {
7202
7584
  }
@@ -7227,6 +7609,7 @@ async function runActivityBackfill(command, config, log3) {
7227
7609
  }
7228
7610
 
7229
7611
  // src/team/sync.ts
7612
+ init_dist();
7230
7613
  init_fs();
7231
7614
  var inFlightCommands = /* @__PURE__ */ new Set();
7232
7615
  var USAGE_LOG2 = cclensPath("usage.jsonl");
@@ -7341,7 +7724,7 @@ async function runTeamSync(log3 = noopLog2, configOverride, options = {}) {
7341
7724
  try {
7342
7725
  resetEnsuredSessions();
7343
7726
  const { listSessions: listSessions2, loadCalibrationCurve: loadCalibrationCurve2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
7344
- const { toLocalDay: toLocalDay3, projectRepoName: projectRepoName2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
7727
+ const { toLocalDay: toLocalDay3 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
7345
7728
  const today = toLocalDay3(Date.now());
7346
7729
  let patches = {};
7347
7730
  const persistConfig = (patch) => {
@@ -7528,7 +7911,7 @@ async function runTeamSync(log3 = noopLog2, configOverride, options = {}) {
7528
7911
  } : void 0;
7529
7912
  let artifactSignals = null;
7530
7913
  try {
7531
- const cwdAllowed = shouldSyncProject(projectRepoName2(process.cwd()), config.syncProjects);
7914
+ const cwdAllowed = shouldSyncProject(projectKey(resolveProjectIdentity(process.cwd()).projectName), config.syncProjects);
7532
7915
  artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: cwdAllowed ? [process.cwd()] : [] });
7533
7916
  } catch {
7534
7917
  }
@@ -7715,13 +8098,13 @@ async function buildCyclePeaksForPush(planTier, loadCurve) {
7715
8098
  }
7716
8099
 
7717
8100
  // src/perception/worker.ts
7718
- import { statSync as statSync5 } from "node:fs";
8101
+ import { statSync as statSync6 } from "node:fs";
7719
8102
  init_fs();
7720
8103
 
7721
8104
  // src/perception/state.ts
7722
8105
  init_fs();
7723
- import { existsSync as existsSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, renameSync as renameSync4 } from "node:fs";
7724
- import { dirname as dirname8 } from "node:path";
8106
+ import { existsSync as existsSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, renameSync as renameSync4 } from "node:fs";
8107
+ import { dirname as dirname9 } from "node:path";
7725
8108
  var STALE_MS = 15 * 60 * 1e3;
7726
8109
  var pathCached = null;
7727
8110
  function statePath() {
@@ -7731,7 +8114,7 @@ function statePath() {
7731
8114
  }
7732
8115
  function readState() {
7733
8116
  const p = statePath();
7734
- if (!existsSync7(p)) {
8117
+ if (!existsSync10(p)) {
7735
8118
  return {
7736
8119
  sweep_in_progress: false,
7737
8120
  last_sweep_started_at: null,
@@ -7739,14 +8122,14 @@ function readState() {
7739
8122
  file_checkpoints: {}
7740
8123
  };
7741
8124
  }
7742
- const raw = readFileSync11(p, "utf8");
8125
+ const raw = readFileSync14(p, "utf8");
7743
8126
  return JSON.parse(raw);
7744
8127
  }
7745
8128
  function writeState(s) {
7746
8129
  const p = statePath();
7747
- mkdirSync8(dirname8(p), { recursive: true });
8130
+ mkdirSync9(dirname9(p), { recursive: true });
7748
8131
  const tmp = `${p}.tmp`;
7749
- writeFileSync7(tmp, JSON.stringify(s, null, 2), "utf8");
8132
+ writeFileSync9(tmp, JSON.stringify(s, null, 2), "utf8");
7750
8133
  renameSync4(tmp, p);
7751
8134
  }
7752
8135
  function markSweepStart() {
@@ -7776,17 +8159,17 @@ function updateCheckpoint(jsonlPath, cp) {
7776
8159
 
7777
8160
  // src/perception/scan.ts
7778
8161
  import { readdirSync as readdirSync4 } from "node:fs";
7779
- import { join as join8 } from "node:path";
7780
- import { homedir as homedir3 } from "node:os";
8162
+ import { join as join9 } from "node:path";
8163
+ import { homedir as homedir4 } from "node:os";
7781
8164
  async function listAllSessionJsonls(root) {
7782
- const projectsRoot = root ?? join8(homedir3(), ".claude", "projects");
8165
+ const projectsRoot = root ?? join9(homedir4(), ".claude", "projects");
7783
8166
  const out = [];
7784
8167
  try {
7785
8168
  for (const project of readdirSync4(projectsRoot)) {
7786
- const dir = join8(projectsRoot, project);
8169
+ const dir = join9(projectsRoot, project);
7787
8170
  try {
7788
8171
  for (const f of readdirSync4(dir)) {
7789
- if (f.endsWith(".jsonl")) out.push(join8(dir, f));
8172
+ if (f.endsWith(".jsonl")) out.push(join9(dir, f));
7790
8173
  }
7791
8174
  } catch {
7792
8175
  }
@@ -7813,7 +8196,7 @@ async function runPerceptionSweep(opts = {}) {
7813
8196
  const files = await listAllSessionJsonls(opts.projectsRoot);
7814
8197
  for (const f of files) {
7815
8198
  try {
7816
- const stat = statSync5(f);
8199
+ const stat = statSync6(f);
7817
8200
  const prev = state.file_checkpoints[f];
7818
8201
  if (prev && prev.byte_offset >= stat.size) continue;
7819
8202
  const built = buildEntriesForFile(f);
@@ -7845,7 +8228,7 @@ async function runPerceptionSweep(opts = {}) {
7845
8228
  const built = buildEntries(detail);
7846
8229
  for (const e of built) {
7847
8230
  try {
7848
- const stat = statSync5(meta.filePath);
8231
+ const stat = statSync6(meta.filePath);
7849
8232
  e.source_checkpoint.byte_offset = stat.size;
7850
8233
  } catch {
7851
8234
  }
@@ -12002,14 +12385,14 @@ var ENRICHMENT_SYSTEM_PROMPT = SYSTEM_PROMPT;
12002
12385
  // ../entries/dist/llm-runner.js
12003
12386
  init_fs();
12004
12387
  import { spawn } from "node:child_process";
12005
- import { mkdirSync as mkdirSync10, appendFileSync as appendFileSync4, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "node:fs";
12006
- import { join as join10 } from "node:path";
12388
+ import { mkdirSync as mkdirSync11, appendFileSync as appendFileSync5, writeFileSync as writeFileSync11, existsSync as existsSync12 } from "node:fs";
12389
+ import { join as join11 } from "node:path";
12007
12390
  import { randomUUID as randomUUID4 } from "node:crypto";
12008
12391
 
12009
12392
  // ../entries/dist/tmux-runner.js
12010
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync8, existsSync as existsSync8, readdirSync as readdirSync5, realpathSync, readFileSync as readFileSync12, unlinkSync as unlinkSync3, renameSync as renameSync5 } from "node:fs";
12011
- import { join as join9 } from "node:path";
12012
- import { homedir as homedir4 } from "node:os";
12393
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10, existsSync as existsSync11, readdirSync as readdirSync5, realpathSync as realpathSync2, readFileSync as readFileSync15, unlinkSync as unlinkSync3, renameSync as renameSync5 } from "node:fs";
12394
+ import { join as join10 } from "node:path";
12395
+ import { homedir as homedir5 } from "node:os";
12013
12396
  import { spawnSync } from "node:child_process";
12014
12397
  var TmuxUnavailableError = class extends Error {
12015
12398
  constructor(message) {
@@ -12037,16 +12420,16 @@ function tmuxRunnerAvailable() {
12037
12420
  return { ok: true };
12038
12421
  }
12039
12422
  function runtimeCwd() {
12040
- const dir = join9(homedir4(), ".cclens", "runtime");
12041
- if (!existsSync8(dir))
12042
- mkdirSync9(dir, { recursive: true });
12043
- return realpathSync(dir);
12423
+ const dir = join10(homedir5(), ".cclens", "runtime");
12424
+ if (!existsSync11(dir))
12425
+ mkdirSync10(dir, { recursive: true });
12426
+ return realpathSync2(dir);
12044
12427
  }
12045
12428
  function ensureRuntimeCwdTrusted(cwd) {
12046
- const cfgPath = join9(homedir4(), ".claude.json");
12429
+ const cfgPath = join10(homedir5(), ".claude.json");
12047
12430
  let cfg;
12048
12431
  try {
12049
- cfg = JSON.parse(readFileSync12(cfgPath, "utf8"));
12432
+ cfg = JSON.parse(readFileSync15(cfgPath, "utf8"));
12050
12433
  } catch {
12051
12434
  return;
12052
12435
  }
@@ -12061,7 +12444,7 @@ function ensureRuntimeCwdTrusted(cwd) {
12061
12444
  cfg.projects = projects;
12062
12445
  const tmp = `${cfgPath}.cclens-tmp-${process.pid}`;
12063
12446
  try {
12064
- writeFileSync8(tmp, JSON.stringify(cfg, null, 2));
12447
+ writeFileSync10(tmp, JSON.stringify(cfg, null, 2));
12065
12448
  renameSync5(tmp, cfgPath);
12066
12449
  } catch {
12067
12450
  try {
@@ -12089,16 +12472,16 @@ async function runClaudeUnderTmuxImpl(args) {
12089
12472
  ensureRuntimeCwdTrusted(cwd);
12090
12473
  const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
12091
12474
  const sessionName = `cclens-${runId}`;
12092
- const systemFile = join9(cwd, `system-${runId}.txt`);
12093
- const userFile = join9(cwd, `user-${runId}.txt`);
12094
- const wrapper = join9(cwd, `run-${runId}.sh`);
12095
- writeFileSync8(systemFile, args.systemPrompt);
12096
- writeFileSync8(userFile, args.reminder ? `${args.userPrompt}
12475
+ const systemFile = join10(cwd, `system-${runId}.txt`);
12476
+ const userFile = join10(cwd, `user-${runId}.txt`);
12477
+ const wrapper = join10(cwd, `run-${runId}.sh`);
12478
+ writeFileSync10(systemFile, args.systemPrompt);
12479
+ writeFileSync10(userFile, args.reminder ? `${args.userPrompt}
12097
12480
 
12098
12481
  ---
12099
12482
 
12100
12483
  ${args.reminder}` : args.userPrompt);
12101
- writeFileSync8(wrapper, `#!/bin/bash
12484
+ writeFileSync10(wrapper, `#!/bin/bash
12102
12485
  SYS="$(cat ${shellEscape(systemFile)})"
12103
12486
  USR="$(cat ${shellEscape(userFile)})"
12104
12487
  exec ${shellEscape(claudeBin)} \\
@@ -12170,7 +12553,7 @@ function num(v) {
12170
12553
  function sleep(ms) {
12171
12554
  return new Promise((r) => setTimeout(r, ms));
12172
12555
  }
12173
- var PROJECTS_ROOT = () => join9(homedir4(), ".claude", "projects");
12556
+ var PROJECTS_ROOT = () => join10(homedir5(), ".claude", "projects");
12174
12557
  function snapshotAllTranscripts() {
12175
12558
  const out = /* @__PURE__ */ new Set();
12176
12559
  const root = PROJECTS_ROOT();
@@ -12181,7 +12564,7 @@ function snapshotAllTranscripts() {
12181
12564
  return out;
12182
12565
  }
12183
12566
  for (const sub of subs) {
12184
- const dir = join9(root, sub);
12567
+ const dir = join10(root, sub);
12185
12568
  let files;
12186
12569
  try {
12187
12570
  files = readdirSync5(dir);
@@ -12190,7 +12573,7 @@ function snapshotAllTranscripts() {
12190
12573
  }
12191
12574
  for (const f of files) {
12192
12575
  if (f.endsWith(".jsonl"))
12193
- out.add(join9(dir, f));
12576
+ out.add(join10(dir, f));
12194
12577
  }
12195
12578
  }
12196
12579
  return out;
@@ -12198,7 +12581,7 @@ function snapshotAllTranscripts() {
12198
12581
  function readJsonlCwd(path7, maxLines = 8) {
12199
12582
  let raw;
12200
12583
  try {
12201
- raw = readFileSync12(path7, "utf8");
12584
+ raw = readFileSync15(path7, "utf8");
12202
12585
  } catch {
12203
12586
  return void 0;
12204
12587
  }
@@ -12231,7 +12614,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
12231
12614
  subs = [];
12232
12615
  }
12233
12616
  for (const sub of subs) {
12234
- const dir = join9(root, sub);
12617
+ const dir = join10(root, sub);
12235
12618
  let files;
12236
12619
  try {
12237
12620
  files = readdirSync5(dir);
@@ -12241,7 +12624,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
12241
12624
  for (const f of files) {
12242
12625
  if (!f.endsWith(".jsonl"))
12243
12626
  continue;
12244
- const full = join9(dir, f);
12627
+ const full = join10(dir, f);
12245
12628
  if (existingBefore.has(full))
12246
12629
  continue;
12247
12630
  if (readJsonlCwd(full) === targetCwd)
@@ -12255,7 +12638,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
12255
12638
  function parseTranscript2(path7, defaultModel) {
12256
12639
  let raw;
12257
12640
  try {
12258
- raw = readFileSync12(path7, "utf8");
12641
+ raw = readFileSync15(path7, "utf8");
12259
12642
  } catch {
12260
12643
  return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
12261
12644
  }
@@ -12315,7 +12698,7 @@ function cleanup(cwd, runId, tmuxBin, sessionName, transcriptPath) {
12315
12698
  }
12316
12699
  for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
12317
12700
  try {
12318
- unlinkSync3(join9(cwd, f));
12701
+ unlinkSync3(join10(cwd, f));
12319
12702
  } catch {
12320
12703
  }
12321
12704
  }
@@ -12330,9 +12713,9 @@ function shellEscape(s) {
12330
12713
  // ../entries/dist/llm-runner.js
12331
12714
  var RUNS_DIR = cclensPath("llm-runs");
12332
12715
  function ensureRunsDir() {
12333
- if (!existsSync9(RUNS_DIR)) {
12716
+ if (!existsSync12(RUNS_DIR)) {
12334
12717
  try {
12335
- mkdirSync10(RUNS_DIR, { recursive: true });
12718
+ mkdirSync11(RUNS_DIR, { recursive: true });
12336
12719
  } catch {
12337
12720
  }
12338
12721
  }
@@ -12359,17 +12742,17 @@ function newRunId(kind) {
12359
12742
  return `${ts}_${kind}_${short}`;
12360
12743
  }
12361
12744
  function tracePath(runId) {
12362
- return join10(RUNS_DIR, `${runId}.jsonl`);
12745
+ return join11(RUNS_DIR, `${runId}.jsonl`);
12363
12746
  }
12364
12747
  function safeAppend(path7, line) {
12365
12748
  try {
12366
- appendFileSync4(path7, line);
12749
+ appendFileSync5(path7, line);
12367
12750
  } catch {
12368
12751
  }
12369
12752
  }
12370
12753
  function safeWrite(path7, line) {
12371
12754
  try {
12372
- writeFileSync9(path7, line);
12755
+ writeFileSync11(path7, line);
12373
12756
  } catch {
12374
12757
  }
12375
12758
  }
@@ -12447,7 +12830,7 @@ async function runClaudeSubprocess(args) {
12447
12830
  return runClaudePrintMode(args);
12448
12831
  }
12449
12832
  function runClaudePrintMode(args) {
12450
- return new Promise((resolve3, reject) => {
12833
+ return new Promise((resolve4, reject) => {
12451
12834
  ensureRunsDir();
12452
12835
  const kind = detectKindFromSystemPrompt(args.systemPrompt);
12453
12836
  const runId = newRunId(kind);
@@ -12578,7 +12961,7 @@ ${args.reminder}` : args.userPrompt;
12578
12961
  reject(new Error(`claude exited ${code}: ${stderr.trim().slice(0, 300)}`));
12579
12962
  return;
12580
12963
  }
12581
- resolve3({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
12964
+ resolve4({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
12582
12965
  });
12583
12966
  proc.on("error", (err) => {
12584
12967
  safeAppend(trace, JSON.stringify({ _meta: { type: "spawn_error", run_id: runId, ts: (/* @__PURE__ */ new Date()).toISOString(), error: err.message } }) + "\n");
@@ -12758,8 +13141,8 @@ function applyEnrichmentError(entry, errorMessage, model, costUsd, generatedAt,
12758
13141
 
12759
13142
  // ../entries/dist/budget.js
12760
13143
  init_fs();
12761
- import { appendFileSync as appendFileSync5, readFileSync as readFileSync13, existsSync as existsSync10, mkdirSync as mkdirSync11 } from "node:fs";
12762
- import { dirname as dirname9 } from "node:path";
13144
+ import { appendFileSync as appendFileSync6, readFileSync as readFileSync16, existsSync as existsSync13, mkdirSync as mkdirSync12 } from "node:fs";
13145
+ import { dirname as dirname10 } from "node:path";
12763
13146
  var spendPathCached = null;
12764
13147
  function spendPath() {
12765
13148
  if (spendPathCached)
@@ -12769,17 +13152,17 @@ function spendPath() {
12769
13152
  }
12770
13153
  function appendSpend(record) {
12771
13154
  const p = spendPath();
12772
- mkdirSync11(dirname9(p), { recursive: true });
12773
- appendFileSync5(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
13155
+ mkdirSync12(dirname10(p), { recursive: true });
13156
+ appendFileSync6(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
12774
13157
  }
12775
13158
  function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
12776
13159
  const p = spendPath();
12777
- if (!existsSync10(p))
13160
+ if (!existsSync13(p))
12778
13161
  return 0;
12779
13162
  const year = now.getUTCFullYear();
12780
13163
  const month = now.getUTCMonth();
12781
13164
  let total = 0;
12782
- const raw = readFileSync13(p, "utf8");
13165
+ const raw = readFileSync16(p, "utf8");
12783
13166
  for (const line of raw.split("\n")) {
12784
13167
  if (!line)
12785
13168
  continue;
@@ -12801,7 +13184,7 @@ function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
12801
13184
 
12802
13185
  // ../entries/dist/pipeline-lock.js
12803
13186
  init_fs();
12804
- import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as existsSync11, readFileSync as readFileSync14, statSync as statSync6 } from "node:fs";
13187
+ import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync4, existsSync as existsSync14, readFileSync as readFileSync17, statSync as statSync7 } from "node:fs";
12805
13188
  var STALE_MS2 = 60 * 1e3;
12806
13189
  var HEARTBEAT_MS = 30 * 1e3;
12807
13190
  var lockPathCached = null;
@@ -12813,7 +13196,7 @@ function lockPath() {
12813
13196
  return lockPathCached;
12814
13197
  }
12815
13198
  function touchLock() {
12816
- writeFileSync10(lockPath(), String(process.pid), "utf8");
13199
+ writeFileSync12(lockPath(), String(process.pid), "utf8");
12817
13200
  }
12818
13201
  function writeInteractiveLock() {
12819
13202
  touchLock();
@@ -12847,13 +13230,13 @@ function pidAlive(pid) {
12847
13230
  }
12848
13231
  function interactiveLockFresh(nowMs) {
12849
13232
  const p = lockPath();
12850
- if (!existsSync11(p))
13233
+ if (!existsSync14(p))
12851
13234
  return false;
12852
13235
  try {
12853
- const mtime = statSync6(p).mtimeMs;
13236
+ const mtime = statSync7(p).mtimeMs;
12854
13237
  if (nowMs - mtime > STALE_MS2)
12855
13238
  return false;
12856
- const pid = Number(readFileSync14(p, "utf8").trim());
13239
+ const pid = Number(readFileSync17(p, "utf8").trim());
12857
13240
  if (!Number.isFinite(pid) || pid <= 0)
12858
13241
  return false;
12859
13242
  if (!pidAlive(pid))
@@ -12868,7 +13251,7 @@ function interactiveLockFresh(nowMs) {
12868
13251
  var THIRTY_MIN_MS = 30 * 60 * 1e3;
12869
13252
 
12870
13253
  // ../entries/dist/settings.js
12871
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync11, renameSync as renameSync6, chmodSync as chmodSync2, mkdirSync as mkdirSync12, existsSync as existsSync12 } from "node:fs";
13254
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync13, renameSync as renameSync6, chmodSync as chmodSync2, mkdirSync as mkdirSync13, existsSync as existsSync15 } from "node:fs";
12872
13255
  init_fs();
12873
13256
  var DEFAULT_SETTINGS = {
12874
13257
  ai_features: {
@@ -12900,10 +13283,10 @@ function fromDisk(d) {
12900
13283
  }
12901
13284
  function readSettings() {
12902
13285
  const p = settingsPath();
12903
- if (!existsSync12(p))
13286
+ if (!existsSync15(p))
12904
13287
  return DEFAULT_SETTINGS;
12905
13288
  try {
12906
- const raw = readFileSync15(p, "utf8");
13289
+ const raw = readFileSync18(p, "utf8");
12907
13290
  return fromDisk(JSON.parse(raw));
12908
13291
  } catch {
12909
13292
  return DEFAULT_SETTINGS;
@@ -15512,6 +15895,9 @@ async function* runWeekDigestPipeline(monday, opts) {
15512
15895
  }
15513
15896
  }
15514
15897
 
15898
+ // ../entries/dist/credentials.js
15899
+ init_fs();
15900
+
15515
15901
  // src/perception/backfill.ts
15516
15902
  function toLocalDay2(ms) {
15517
15903
  const d = new Date(ms);
@@ -15660,14 +16046,14 @@ async function getUpdateAvailability() {
15660
16046
  if (isDevMode()) return null;
15661
16047
  const latest = await fetchLatestVersion();
15662
16048
  if (latest === null) return {
15663
- current: "0.15.2",
16049
+ current: "0.15.4",
15664
16050
  latest: null,
15665
16051
  updateAvailable: false
15666
16052
  };
15667
16053
  return {
15668
- current: "0.15.2",
16054
+ current: "0.15.4",
15669
16055
  latest,
15670
- updateAvailable: shouldUpdate("0.15.2", latest)
16056
+ updateAvailable: shouldUpdate("0.15.4", latest)
15671
16057
  };
15672
16058
  }
15673
16059
 
@@ -15677,7 +16063,7 @@ var DAEMON_LOG = cclensPath("daemon.log");
15677
16063
  var UPDATE_STATE = cclensPath("daemon-update.json");
15678
16064
  var WATCHDOG_INTERVAL_MS = 5 * 1e3;
15679
16065
  var AUTO_UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1e3;
15680
- mkdirSync13(dirname10(USAGE_LOG3), { recursive: true });
16066
+ mkdirSync14(dirname11(USAGE_LOG3), { recursive: true });
15681
16067
  function log2(level, message) {
15682
16068
  appendDaemonLogLine(level, message);
15683
16069
  }
@@ -15715,14 +16101,14 @@ var perceptionHandle = setInterval(async () => {
15715
16101
  }, PERCEPTION_INTERVAL_MS);
15716
16102
  function readUpdateState() {
15717
16103
  try {
15718
- return JSON.parse(readFileSync16(UPDATE_STATE, "utf8"));
16104
+ return JSON.parse(readFileSync19(UPDATE_STATE, "utf8"));
15719
16105
  } catch {
15720
16106
  return null;
15721
16107
  }
15722
16108
  }
15723
16109
  function writeUpdateState(state) {
15724
16110
  try {
15725
- writeFileSync12(UPDATE_STATE, JSON.stringify(state, null, 2), { mode: 384 });
16111
+ writeFileSync14(UPDATE_STATE, JSON.stringify(state, null, 2), { mode: 384 });
15726
16112
  } catch {
15727
16113
  }
15728
16114
  }
@@ -15735,7 +16121,7 @@ function nextUpdateCheckFromState(nowMs) {
15735
16121
  }
15736
16122
  var nextUpdateCheckAtMs = nextUpdateCheckFromState(Date.now());
15737
16123
  function cliEntryPath() {
15738
- return join11(dirname10(fileURLToPath(import.meta.url)), "index.js");
16124
+ return join12(dirname11(fileURLToPath(import.meta.url)), "index.js");
15739
16125
  }
15740
16126
  async function runDaemonUpdateCheck() {
15741
16127
  if (process.env.FLEETLENS_DAEMON_AUTO_UPDATE === "0") {
@@ -15767,7 +16153,7 @@ async function runDaemonUpdateCheck() {
15767
16153
  return;
15768
16154
  }
15769
16155
  const entry = cliEntryPath();
15770
- if (!existsSync13(entry)) {
16156
+ if (!existsSync16(entry)) {
15771
16157
  log2("warn", `update check found ${availability.latest}, but CLI entry is missing at ${entry}`);
15772
16158
  return;
15773
16159
  }
@@ -15830,6 +16216,20 @@ async function tick() {
15830
16216
  log2("warn", `${source.kind} poll failed: ${err.message}`);
15831
16217
  }
15832
16218
  }
16219
+ try {
16220
+ const zaiSnapshot = await fetchZaiUsage();
16221
+ appendSnapshot(USAGE_LOG3, zaiSnapshot);
16222
+ log2(
16223
+ "info",
16224
+ `zai snapshot 5h=${zaiSnapshot.five_hour.utilization}% 7d=${zaiSnapshot.seven_day.utilization}%`
16225
+ );
16226
+ } catch (err) {
16227
+ if (err instanceof ZaiApiError && err.code === "no_key") {
16228
+ pruneAgent(USAGE_LOG3, "zai");
16229
+ } else {
16230
+ log2("warn", `zai poll failed: ${err.message}`);
16231
+ }
16232
+ }
15833
16233
  try {
15834
16234
  const snapshot = await fetchUsage();
15835
16235
  appendSnapshot(USAGE_LOG3, snapshot);
@@ -15859,7 +16259,7 @@ function scheduleAfter(now, outcome) {
15859
16259
  nextPollAtMs = now + currentIntervalMs;
15860
16260
  }
15861
16261
  function sleep2(ms) {
15862
- return new Promise((resolve3) => setTimeout(resolve3, ms));
16262
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
15863
16263
  }
15864
16264
  async function runLoop() {
15865
16265
  while (true) {