fleetlens 0.15.7 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/app-path-routes-manifest.json +9 -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 +62 -0
  6. package/app/apps/web/.next/server/app/_global-error/page.js +1 -1
  7. package/app/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
  16. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/app/apps/web/.next/server/app/agent/page/app-paths-manifest.json +3 -0
  19. package/app/apps/web/.next/server/app/agent/page/build-manifest.json +17 -0
  20. package/app/apps/web/.next/server/app/agent/page/next-font-manifest.json +6 -0
  21. package/app/apps/web/.next/server/app/agent/page/react-loadable-manifest.json +1 -0
  22. package/app/apps/web/.next/server/app/agent/page/server-reference-manifest.json +4 -0
  23. package/app/apps/web/.next/server/app/agent/page.js +18 -0
  24. package/app/apps/web/.next/server/app/agent/page.js.map +5 -0
  25. package/app/apps/web/.next/server/app/agent/page.js.nft.json +1 -0
  26. package/app/apps/web/.next/server/app/agent/page_client-reference-manifest.js +3 -0
  27. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route/app-paths-manifest.json +3 -0
  28. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route/build-manifest.json +9 -0
  29. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route/server-reference-manifest.json +4 -0
  30. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route.js +7 -0
  31. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route.js.map +5 -0
  32. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route.js.nft.json +1 -0
  33. package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route_client-reference-manifest.js +3 -0
  34. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route/app-paths-manifest.json +3 -0
  35. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route/build-manifest.json +9 -0
  36. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route/server-reference-manifest.json +4 -0
  37. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route.js +9 -0
  38. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route.js.map +5 -0
  39. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route.js.nft.json +1 -0
  40. package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route_client-reference-manifest.js +3 -0
  41. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route/app-paths-manifest.json +3 -0
  42. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route/build-manifest.json +9 -0
  43. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route/server-reference-manifest.json +4 -0
  44. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route.js +7 -0
  45. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route.js.map +5 -0
  46. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route.js.nft.json +1 -0
  47. package/app/apps/web/.next/server/app/api/agent/chats/[id]/route_client-reference-manifest.js +3 -0
  48. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route/app-paths-manifest.json +3 -0
  49. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route/build-manifest.json +9 -0
  50. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route/server-reference-manifest.json +4 -0
  51. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route.js +7 -0
  52. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route.js.map +5 -0
  53. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route.js.nft.json +1 -0
  54. package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route_client-reference-manifest.js +3 -0
  55. package/app/apps/web/.next/server/app/api/agent/chats/route/app-paths-manifest.json +3 -0
  56. package/app/apps/web/.next/server/app/api/agent/chats/route/build-manifest.json +9 -0
  57. package/app/apps/web/.next/server/app/api/agent/chats/route/server-reference-manifest.json +4 -0
  58. package/app/apps/web/.next/server/app/api/agent/chats/route.js +7 -0
  59. package/app/apps/web/.next/server/app/api/agent/chats/route.js.map +5 -0
  60. package/app/apps/web/.next/server/app/api/agent/chats/route.js.nft.json +1 -0
  61. package/app/apps/web/.next/server/app/api/agent/chats/route_client-reference-manifest.js +3 -0
  62. package/app/apps/web/.next/server/app/api/agent/index/route/app-paths-manifest.json +3 -0
  63. package/app/apps/web/.next/server/app/api/agent/index/route/build-manifest.json +9 -0
  64. package/app/apps/web/.next/server/app/api/agent/index/route/server-reference-manifest.json +4 -0
  65. package/app/apps/web/.next/server/app/api/agent/index/route.js +9 -0
  66. package/app/apps/web/.next/server/app/api/agent/index/route.js.map +5 -0
  67. package/app/apps/web/.next/server/app/api/agent/index/route.js.nft.json +1 -0
  68. package/app/apps/web/.next/server/app/api/agent/index/route_client-reference-manifest.js +3 -0
  69. package/app/apps/web/.next/server/app/api/agent/mcp/route/app-paths-manifest.json +3 -0
  70. package/app/apps/web/.next/server/app/api/agent/mcp/route/build-manifest.json +9 -0
  71. package/app/apps/web/.next/server/app/api/agent/mcp/route/server-reference-manifest.json +4 -0
  72. package/app/apps/web/.next/server/app/api/agent/mcp/route.js +10 -0
  73. package/app/apps/web/.next/server/app/api/agent/mcp/route.js.map +5 -0
  74. package/app/apps/web/.next/server/app/api/agent/mcp/route.js.nft.json +1 -0
  75. package/app/apps/web/.next/server/app/api/agent/mcp/route_client-reference-manifest.js +3 -0
  76. package/app/apps/web/.next/server/app/api/agent/suggestions/route/app-paths-manifest.json +3 -0
  77. package/app/apps/web/.next/server/app/api/agent/suggestions/route/build-manifest.json +9 -0
  78. package/app/apps/web/.next/server/app/api/agent/suggestions/route/server-reference-manifest.json +4 -0
  79. package/app/apps/web/.next/server/app/api/agent/suggestions/route.js +12 -0
  80. package/app/apps/web/.next/server/app/api/agent/suggestions/route.js.map +5 -0
  81. package/app/apps/web/.next/server/app/api/agent/suggestions/route.js.nft.json +1 -0
  82. package/app/apps/web/.next/server/app/api/agent/suggestions/route_client-reference-manifest.js +3 -0
  83. package/app/apps/web/.next/server/app/api/ask/route.js +3 -4
  84. package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
  85. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +4 -4
  86. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  87. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +4 -4
  88. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
  89. package/app/apps/web/.next/server/app/api/digest/month-index/route.js +2 -2
  90. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  91. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +4 -4
  92. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  93. package/app/apps/web/.next/server/app/api/digest/week-index/route.js +2 -2
  94. package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
  95. package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
  96. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
  97. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js +3 -3
  98. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
  99. package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.nft.json +1 -1
  100. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  101. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  102. package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
  103. package/app/apps/web/.next/server/app/api/settings/credentials/route.js +5 -5
  104. package/app/apps/web/.next/server/app/api/settings/credentials/route.js.nft.json +1 -1
  105. package/app/apps/web/.next/server/app/api/settings/route.js +3 -3
  106. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  107. package/app/apps/web/.next/server/app/api/team/autostart/route.js.nft.json +1 -1
  108. package/app/apps/web/.next/server/app/api/team/onboarding/start/route.js.nft.json +1 -1
  109. package/app/apps/web/.next/server/app/api/team/sync-projects/route.js.nft.json +1 -1
  110. package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -1
  111. package/app/apps/web/.next/server/app/changelog/page.js +1 -1
  112. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
  113. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  114. package/app/apps/web/.next/server/app/day/[date]/page.js +2 -2
  115. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  116. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  117. package/app/apps/web/.next/server/app/day/page.js +1 -1
  118. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  119. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  120. package/app/apps/web/.next/server/app/digest/[date]/page.js +1 -1
  121. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  122. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  123. package/app/apps/web/.next/server/app/digest/page.js +1 -1
  124. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  125. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  126. package/app/apps/web/.next/server/app/insights/[key]/page.js +2 -2
  127. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  128. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  129. package/app/apps/web/.next/server/app/insights/page.js +2 -2
  130. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  131. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  132. package/app/apps/web/.next/server/app/page.js +2 -2
  133. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  134. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  135. package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
  136. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  137. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  138. package/app/apps/web/.next/server/app/print/[key]/page.js +2 -2
  139. package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
  140. package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
  141. package/app/apps/web/.next/server/app/projects/[slug]/page.js +1 -1
  142. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  143. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  144. package/app/apps/web/.next/server/app/projects/page.js +1 -1
  145. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  146. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  147. package/app/apps/web/.next/server/app/runs/page.js +1 -1
  148. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  149. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  150. package/app/apps/web/.next/server/app/sessions/[id]/page.js +1 -1
  151. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  152. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  153. package/app/apps/web/.next/server/app/sessions/page.js +1 -1
  154. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  155. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  156. package/app/apps/web/.next/server/app/settings/page.js +2 -2
  157. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  158. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  159. package/app/apps/web/.next/server/app/team/onboarding/page.js +1 -1
  160. package/app/apps/web/.next/server/app/team/onboarding/page.js.nft.json +1 -1
  161. package/app/apps/web/.next/server/app/team/onboarding/page_client-reference-manifest.js +1 -1
  162. package/app/apps/web/.next/server/app/team/page.js +1 -1
  163. package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
  164. package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
  165. package/app/apps/web/.next/server/app/usage/page.js +1 -1
  166. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  167. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  168. package/app/apps/web/.next/server/app-paths-manifest.json +9 -0
  169. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_agent_chats_[id]_events_route_actions_0fkgl_r.js +3 -0
  170. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_agent_chats_[id]_stop_route_actions_036fon_.js +3 -0
  171. package/app/apps/web/.next/server/chunks/09og__next-internal_server_app_api_agent_chats_[id]_messages_route_actions_0ubwh4q.js +3 -0
  172. package/app/apps/web/.next/server/chunks/[root-of-the-server]__01~cgp8._.js +3 -0
  173. package/app/apps/web/.next/server/chunks/[root-of-the-server]__02faosk._.js +30 -0
  174. package/app/apps/web/.next/server/chunks/[root-of-the-server]__02puo0u._.js +3 -0
  175. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0367vbv._.js +3 -0
  176. package/app/apps/web/.next/server/chunks/[root-of-the-server]__04g-b-m._.js +9 -0
  177. package/app/apps/web/.next/server/chunks/[root-of-the-server]__06xto5z._.js +9 -0
  178. package/app/apps/web/.next/server/chunks/[root-of-the-server]__096_llw._.js +3 -0
  179. package/app/apps/web/.next/server/chunks/[root-of-the-server]__09cgmam._.js +28 -0
  180. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_5tf-2._.js +21 -0
  181. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0gvw6dk._.js +3 -0
  182. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0mx_9mb._.js +5 -0
  183. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0pirsh0._.js +9 -0
  184. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0sbhe0s._.js +3 -0
  185. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0tk8p3d._.js +28 -0
  186. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0u6pamj._.js +28 -0
  187. package/app/apps/web/.next/server/chunks/[root-of-the-server]__123tfcb._.js +3 -0
  188. package/app/apps/web/.next/server/chunks/[root-of-the-server]__12jomao._.js +28 -0
  189. package/app/apps/web/.next/server/chunks/_132c.4p._.js +3 -0
  190. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_agent_chats_[id]_route_actions_0b95y8h.js +3 -0
  191. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_agent_chats_route_actions_07b4w1x.js +3 -0
  192. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_agent_index_route_actions_03~ylvr.js +3 -0
  193. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_agent_mcp_route_actions_0-b30h..js +3 -0
  194. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_agent_suggestions_route_actions_0r_5s~k.js +3 -0
  195. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0sr4wr_.js +13 -0
  196. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0z_xi9k.js +16 -0
  197. package/app/apps/web/.next/server/chunks/{packages_0o6.gpk._.js → packages_entries_dist_0-0s5ui._.js} +2 -2
  198. package/app/apps/web/.next/server/chunks/packages_entries_dist_0~0d7ku._.js +3 -0
  199. package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +8 -8
  200. package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
  201. package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
  202. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0e.gxk3._.js → [root-of-the-server]__0.wm54e._.js} +2 -2
  203. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__04il6m2._.js → [root-of-the-server]__04qodwp._.js} +2 -2
  204. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0k1x-c9._.js → [root-of-the-server]__07~kk2~._.js} +2 -2
  205. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__03uoeiw._.js → [root-of-the-server]__0_78i1t._.js} +2 -2
  206. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0amklf0._.js +3 -0
  207. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0nr2~y1._.js → [root-of-the-server]__0d5y90m._.js} +2 -2
  208. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__03svi~4._.js → [root-of-the-server]__0iv286q._.js} +2 -2
  209. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0j683am._.js +3 -0
  210. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0rvzdnx._.js → [root-of-the-server]__0kml6jt._.js} +2 -2
  211. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__08l86e-._.js → [root-of-the-server]__0lmftab._.js} +2 -2
  212. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ns6ydi._.js +3 -0
  213. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0vo.r~s._.js +3 -0
  214. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~8.fgs._.js +3 -0
  215. package/app/apps/web/.next/server/chunks/ssr/_0k8yioi._.js +1 -1
  216. package/app/apps/web/.next/server/chunks/ssr/{_13jdm1g._.js → _0~r5ica._.js} +2 -2
  217. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_agent_page_actions_0tuled1.js +3 -0
  218. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_day_[date]_day-view_tsx_0wjoe1u._.js +1 -1
  219. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_[id]_session-view_tsx_0-9t5~.._.js +12 -0
  220. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0x014hn._.js +1 -1
  221. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_agent-chat_tsx_0xbtx2n._.js +5 -0
  222. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
  223. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
  224. package/app/apps/web/.next/server/chunks/ssr/{node_modules_0yrkyef._.js → node_modules_next_dist_0t-hj0x._.js} +2 -2
  225. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0~g07z5.js +4 -0
  226. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0mx_509._.js +1 -1
  227. package/app/apps/web/.next/server/functions-config-manifest.json +8 -0
  228. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  229. package/app/apps/web/.next/server/middleware-manifest.json +5 -5
  230. package/app/apps/web/.next/server/pages/500.html +1 -1
  231. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  232. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  233. package/app/apps/web/.next/static/chunks/04feoajklmrl3.js +3 -0
  234. package/app/apps/web/.next/static/chunks/07bzlfv97o1ig.js +10 -0
  235. package/app/apps/web/.next/static/chunks/0d~7p_ye7v7_5.css +1 -0
  236. package/app/apps/web/.next/static/chunks/0iiqpl6d_3i5~.js +1 -0
  237. package/app/apps/web/.next/static/chunks/0mry~475v0fa3.js +14 -0
  238. package/app/apps/web/.next/static/chunks/0qwgm81o9o~um.js +1 -0
  239. package/app/apps/web/.next/static/chunks/{0y3448zrint0k.js → 0~rycwo36m~c3.js} +1 -1
  240. package/app/apps/web/.next/static/chunks/12zmbd3mlcbn_.js +1 -0
  241. package/app/apps/web/.next/static/chunks/16bapkvp5.x37.js +1 -0
  242. package/app/apps/web/app/agent/page.tsx +12 -0
  243. package/app/apps/web/app/api/agent/chats/[id]/events/route.ts +86 -0
  244. package/app/apps/web/app/api/agent/chats/[id]/messages/route.ts +47 -0
  245. package/app/apps/web/app/api/agent/chats/[id]/route.ts +19 -0
  246. package/app/apps/web/app/api/agent/chats/[id]/stop/route.ts +10 -0
  247. package/app/apps/web/app/api/agent/chats/route.ts +26 -0
  248. package/app/apps/web/app/api/agent/index/route.ts +56 -0
  249. package/app/apps/web/app/api/agent/mcp/route.ts +31 -0
  250. package/app/apps/web/app/api/agent/suggestions/route.ts +150 -0
  251. package/app/apps/web/components/agent-chat.tsx +940 -0
  252. package/app/apps/web/components/sidebar.tsx +8 -21
  253. package/app/apps/web/lib/agent/chat-model.ts +125 -0
  254. package/app/apps/web/lib/agent/chat-store.test.ts +125 -0
  255. package/app/apps/web/lib/agent/chat-store.ts +59 -0
  256. package/app/apps/web/lib/agent/extract.test.ts +141 -0
  257. package/app/apps/web/lib/agent/extract.ts +75 -0
  258. package/app/apps/web/lib/agent/index-store.ts +206 -0
  259. package/app/apps/web/lib/agent/links.test.ts +27 -0
  260. package/app/apps/web/lib/agent/links.ts +10 -0
  261. package/app/apps/web/lib/agent/mcp.test.ts +83 -0
  262. package/app/apps/web/lib/agent/mcp.ts +85 -0
  263. package/app/apps/web/lib/agent/prompt.test.ts +38 -0
  264. package/app/apps/web/lib/agent/prompt.ts +44 -0
  265. package/app/apps/web/lib/agent/run.ts +426 -0
  266. package/app/apps/web/lib/agent/search.test.ts +111 -0
  267. package/app/apps/web/lib/agent/search.ts +144 -0
  268. package/app/apps/web/lib/agent/suggestions.test.ts +156 -0
  269. package/app/apps/web/lib/agent/suggestions.ts +167 -0
  270. package/app/apps/web/lib/agent/tools.test.ts +98 -0
  271. package/app/apps/web/lib/agent/tools.ts +176 -0
  272. package/app/apps/web/lib/agent/types.ts +50 -0
  273. package/app/apps/web/lib/changelog-data.generated.ts +1 -1
  274. package/app/apps/web/package.json +1 -1
  275. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  276. package/app/apps/web/vitest.config.ts +4 -0
  277. package/dist/daemon-worker.js +9 -4
  278. package/dist/index.js +19 -12
  279. package/menubar/FleetlensMenubar.app/Contents/Info.plist +2 -2
  280. package/menubar/FleetlensMenubar.app/Contents/MacOS/FleetlensMenubar +0 -0
  281. package/package.json +1 -1
  282. package/app/apps/web/.next/server/chunks/[root-of-the-server]__03ewxxu._.js +0 -9
  283. package/app/apps/web/.next/server/chunks/[root-of-the-server]__03rmbz6._.js +0 -3
  284. package/app/apps/web/.next/server/chunks/[root-of-the-server]__05z0pcw._.js +0 -3
  285. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0acikq.._.js +0 -9
  286. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0b5r~-1._.js +0 -3
  287. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jbc7tz._.js +0 -3
  288. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ow1kn1._.js +0 -9
  289. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0t7i-hy._.js +0 -3
  290. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0~xt99s._.js +0 -3
  291. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0ck.78s.js +0 -21
  292. package/app/apps/web/.next/server/chunks/packages_09wmnv.._.js +0 -3
  293. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0g-tomj._.js +0 -3
  294. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +0 -12
  295. package/app/apps/web/.next/static/chunks/02xxpexzk3rf-.js +0 -1
  296. package/app/apps/web/.next/static/chunks/044mtrzh7d7va.js +0 -10
  297. package/app/apps/web/.next/static/chunks/05-k9oryi9wz1.js +0 -14
  298. package/app/apps/web/.next/static/chunks/05b0dn.r00hq1.js +0 -1
  299. package/app/apps/web/.next/static/chunks/0t2on1dhydyb2.css +0 -1
  300. package/app/apps/web/.next/static/chunks/0tliv91mhmrzn.js +0 -1
  301. /package/app/apps/web/.next/static/{5IC6kxw0JoPeCIPdnTpEp → bTww6lPxII4wde65VQDrF}/_buildManifest.js +0 -0
  302. /package/app/apps/web/.next/static/{5IC6kxw0JoPeCIPdnTpEp → bTww6lPxII4wde65VQDrF}/_clientMiddlewareManifest.js +0 -0
  303. /package/app/apps/web/.next/static/{5IC6kxw0JoPeCIPdnTpEp → bTww6lPxII4wde65VQDrF}/_ssgManifest.js +0 -0
@@ -12,12 +12,10 @@ import {
12
12
  PinOff,
13
13
  Search,
14
14
  Activity,
15
- Gauge,
16
15
  Lightbulb,
17
- Radio,
18
16
  Settings,
19
17
  CalendarDays,
20
- Users,
18
+ Sparkles,
21
19
  } from "lucide-react";
22
20
  import { formatRelative, prettyProjectName } from "@/lib/format";
23
21
  import { ThemeToggle } from "@/components/theme-toggle";
@@ -204,13 +202,6 @@ export function Sidebar({
204
202
  >
205
203
  Day
206
204
  </NavLink>
207
- <NavLink
208
- href="/usage"
209
- active={pathname === "/usage"}
210
- icon={<Gauge size={15} />}
211
- >
212
- Usage
213
- </NavLink>
214
205
  <NavLink
215
206
  href="/insights"
216
207
  active={pathname === "/insights"}
@@ -218,19 +209,15 @@ export function Sidebar({
218
209
  >
219
210
  Insights
220
211
  </NavLink>
212
+ {/* Usage and Team live in the sidebar widgets below (both already
213
+ link to their pages); Runs is reachable from the Agent
214
+ header. Keeping the nav to the primary destinations. */}
221
215
  <NavLink
222
- href="/runs"
223
- active={pathname === "/runs" || pathname.startsWith("/runs/")}
224
- icon={<Radio size={15} />}
225
- >
226
- Runs
227
- </NavLink>
228
- <NavLink
229
- href="/team"
230
- active={pathname === "/team" || pathname.startsWith("/team/")}
231
- icon={<Users size={15} />}
216
+ href="/agent"
217
+ active={pathname === "/agent" || pathname === "/runs" || pathname.startsWith("/runs/")}
218
+ icon={<Sparkles size={15} />}
232
219
  >
233
- Team
220
+ Agent
234
221
  </NavLink>
235
222
  </nav>
236
223
 
@@ -0,0 +1,125 @@
1
+
2
+ export type TextSegment = { kind: "text"; text: string };
3
+ export type ToolSegment = {
4
+ kind: "tool";
5
+ id: string;
6
+ name: string;
7
+ input: unknown;
8
+ brief?: string;
9
+ isError?: boolean;
10
+ done: boolean;
11
+ };
12
+ export type Segment = TextSegment | ToolSegment;
13
+
14
+ export type StoredMessage =
15
+ | { role: "user"; text: string }
16
+ | { role: "assistant"; segments: Segment[] };
17
+
18
+ export type ChatStatus = "idle" | "running" | "error";
19
+
20
+ export type Chat = {
21
+ version: 1;
22
+ id: string;
23
+ title: string;
24
+ created_at: string;
25
+ updated_at: string;
26
+ status: ChatStatus;
27
+ /** Highest run-event seq folded into this chat — SSE clients resume after it. */
28
+ lastSeq: number;
29
+ messages: StoredMessage[];
30
+ };
31
+
32
+ export type ChatListItem = {
33
+ id: string;
34
+ title: string;
35
+ updated_at: string;
36
+ status: ChatStatus;
37
+ messageCount: number;
38
+ };
39
+
40
+ /** Normalized event emitted by a run. seq is per-run, starting at 1. */
41
+ export type RunEvent =
42
+ | { seq: number; type: "delta"; text: string }
43
+ | { seq: number; type: "tool"; id: string; name: string; input: unknown }
44
+ | { seq: number; type: "tool_result"; id: string; name: string; brief: string; isError: boolean }
45
+ | { seq: number; type: "done"; totalTokens?: number }
46
+ | { seq: number; type: "error"; message: string };
47
+
48
+ /** Omit<union, K> collapses to the common keys; this distributes instead so
49
+ * emit sites can pass any variant sans seq. */
50
+ export type RunEventBody = RunEvent extends infer E ? (E extends RunEvent ? Omit<E, "seq"> : never) : never;
51
+
52
+ const TITLE_MAX = 80;
53
+
54
+ export function chatTitle(firstUserText: string): string {
55
+ return firstUserText.replace(/\s+/g, " ").trim().slice(0, TITLE_MAX);
56
+ }
57
+
58
+ export function createChat(): Chat {
59
+ const now = new Date().toISOString();
60
+ return {
61
+ version: 1,
62
+ id: crypto.randomUUID(),
63
+ title: "New conversation",
64
+ created_at: now,
65
+ updated_at: now,
66
+ status: "idle",
67
+ lastSeq: 0,
68
+ messages: [],
69
+ };
70
+ }
71
+
72
+ export function newAssistantMessage(): StoredMessage {
73
+ return { role: "assistant", segments: [] };
74
+ }
75
+
76
+ /** Fold one run event into the chat. Pure; the same reducer runs on the
77
+ * server (persistence) and could run client-side, so restore and live
78
+ * rendering can never drift apart. Events at or below lastSeq are replays
79
+ * and ignored. */
80
+ export function applyRunEvent(chat: Chat, event: RunEvent): Chat {
81
+ if (event.seq <= chat.lastSeq) return chat;
82
+ const messages = [...chat.messages];
83
+ let last = messages[messages.length - 1];
84
+ if (!last || last.role !== "assistant") {
85
+ last = newAssistantMessage();
86
+ messages.push(last);
87
+ }
88
+ const assistant = { ...last, segments: [...(last as { segments: Segment[] }).segments] } as Extract<
89
+ StoredMessage,
90
+ { role: "assistant" }
91
+ >;
92
+ messages[messages.length - 1] = assistant;
93
+
94
+ let status: ChatStatus = chat.status;
95
+ switch (event.type) {
96
+ case "delta": {
97
+ const tail = assistant.segments[assistant.segments.length - 1];
98
+ if (tail?.kind === "text") {
99
+ assistant.segments[assistant.segments.length - 1] = { kind: "text", text: tail.text + event.text };
100
+ } else {
101
+ assistant.segments.push({ kind: "text", text: event.text });
102
+ }
103
+ break;
104
+ }
105
+ case "tool":
106
+ assistant.segments.push({ kind: "tool", id: event.id, name: event.name, input: event.input, done: false });
107
+ break;
108
+ case "tool_result":
109
+ assistant.segments = assistant.segments.map((s) =>
110
+ s.kind === "tool" && s.id === event.id ? { ...s, brief: event.brief, isError: event.isError, done: true } : s,
111
+ );
112
+ break;
113
+ case "done":
114
+ status = "idle";
115
+ assistant.segments = assistant.segments.map((s) => (s.kind === "tool" && !s.done ? { ...s, done: true } : s));
116
+ break;
117
+ case "error":
118
+ status = "error";
119
+ assistant.segments = assistant.segments.map((s) => (s.kind === "tool" && !s.done ? { ...s, done: true } : s));
120
+ assistant.segments.push({ kind: "text", text: `\n\n**Error:** ${event.message}` });
121
+ break;
122
+ }
123
+
124
+ return { ...chat, messages, status, lastSeq: event.seq, updated_at: new Date().toISOString() };
125
+ }
@@ -0,0 +1,125 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from "vitest";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import {
6
+ applyRunEvent,
7
+ chatTitle,
8
+ createChat,
9
+ deleteChat,
10
+ listChats,
11
+ newAssistantMessage,
12
+ readChat,
13
+ writeChat,
14
+ type Chat,
15
+ type RunEvent,
16
+ type RunEventBody,
17
+ } from "./chat-store";
18
+
19
+ let dir: string;
20
+ let prevHome: string | undefined;
21
+
22
+ beforeAll(() => {
23
+ dir = mkdtempSync(join(tmpdir(), "cclens-chat-test-"));
24
+ prevHome = process.env.CCLENS_HOME;
25
+ process.env.CCLENS_HOME = dir;
26
+ });
27
+
28
+ afterAll(() => {
29
+ if (prevHome === undefined) delete process.env.CCLENS_HOME;
30
+ else process.env.CCLENS_HOME = prevHome;
31
+ rmSync(dir, { recursive: true, force: true });
32
+ });
33
+
34
+ function running(): Chat {
35
+ const chat = createChat();
36
+ chat.messages.push({ role: "user", text: "find my daemon work" });
37
+ chat.messages.push(newAssistantMessage());
38
+ chat.status = "running";
39
+ return chat;
40
+ }
41
+
42
+ const ev = (e: RunEventBody, seq = 1): RunEvent => ({ seq, ...e }) as RunEvent;
43
+
44
+ describe("applyRunEvent", () => {
45
+ test("delta appends to the trailing text segment, creating one if needed", () => {
46
+ let chat = running();
47
+ chat = applyRunEvent(chat, ev({ type: "delta", text: "Hello" }));
48
+ chat = applyRunEvent(chat, ev({ type: "delta", text: " world" }, 2));
49
+ const last = chat.messages[chat.messages.length - 1]!;
50
+ expect(last.role).toBe("assistant");
51
+ expect(last.role === "assistant" && last.segments).toEqual([{ kind: "text", text: "Hello world" }]);
52
+ });
53
+
54
+ test("tool events add tool segments; results resolve them by id", () => {
55
+ let chat = running();
56
+ chat = applyRunEvent(chat, ev({ type: "delta", text: "Searching. " }));
57
+ chat = applyRunEvent(chat, ev({ type: "tool", id: "t1", name: "search_sessions", input: { query: "x" } }, 2));
58
+ chat = applyRunEvent(chat, ev({ type: "tool_result", id: "t1", name: "search_sessions", brief: "3 matching sessions", isError: false }, 3));
59
+ chat = applyRunEvent(chat, ev({ type: "delta", text: "Found it." }, 4));
60
+ const last = chat.messages[chat.messages.length - 1]!;
61
+ expect(last.role === "assistant" && last.segments).toEqual([
62
+ { kind: "text", text: "Searching. " },
63
+ { kind: "tool", id: "t1", name: "search_sessions", input: { query: "x" }, brief: "3 matching sessions", isError: false, done: true },
64
+ { kind: "text", text: "Found it." },
65
+ ]);
66
+ });
67
+
68
+ test("done marks the chat idle and finalizes dangling tools", () => {
69
+ let chat = running();
70
+ chat = applyRunEvent(chat, ev({ type: "tool", id: "t1", name: "get_session", input: {} }));
71
+ chat = applyRunEvent(chat, ev({ type: "done", totalTokens: 123 }, 2));
72
+ expect(chat.status).toBe("idle");
73
+ const last = chat.messages[chat.messages.length - 1]!;
74
+ expect(last.role === "assistant" && last.segments[0]).toMatchObject({ kind: "tool", done: true });
75
+ expect(chat.lastSeq).toBe(2);
76
+ });
77
+
78
+ test("error appends an error text segment and marks the chat error", () => {
79
+ let chat = running();
80
+ chat = applyRunEvent(chat, ev({ type: "error", message: "timed out" }));
81
+ expect(chat.status).toBe("error");
82
+ const last = chat.messages[chat.messages.length - 1]!;
83
+ expect(last.role === "assistant" && last.segments.some((s) => s.kind === "text" && s.text.includes("timed out"))).toBe(true);
84
+ });
85
+
86
+ test("stale events (seq <= lastSeq) are ignored", () => {
87
+ let chat = running();
88
+ chat = applyRunEvent(chat, ev({ type: "delta", text: "a" }, 5));
89
+ chat = applyRunEvent(chat, ev({ type: "delta", text: "b" }, 5));
90
+ const last = chat.messages[chat.messages.length - 1]!;
91
+ expect(last.role === "assistant" && last.segments).toEqual([{ kind: "text", text: "a" }]);
92
+ });
93
+ });
94
+
95
+ describe("chatTitle", () => {
96
+ test("derives from the first user message, collapsed and clamped", () => {
97
+ expect(chatTitle(" find my\ndaemon work ")).toBe("find my daemon work");
98
+ expect(chatTitle("x".repeat(200)).length).toBeLessThanOrEqual(80);
99
+ });
100
+ });
101
+
102
+ describe("fs round-trip", () => {
103
+ test("create, write, read, list, delete", () => {
104
+ const a = createChat();
105
+ a.messages.push({ role: "user", text: "first chat" });
106
+ a.title = chatTitle("first chat");
107
+ writeChat(a);
108
+ const b = createChat();
109
+ b.messages.push({ role: "user", text: "second chat" });
110
+ b.title = chatTitle("second chat");
111
+ b.updated_at = new Date(Date.now() + 1000).toISOString();
112
+ writeChat(b);
113
+
114
+ expect(readChat(a.id)?.messages[0]).toEqual({ role: "user", text: "first chat" });
115
+ expect(readChat("nope")).toBeNull();
116
+
117
+ const listed = listChats();
118
+ expect(listed.map((c) => c.id)).toEqual([b.id, a.id]); // newest first
119
+ expect(listed[0]).toMatchObject({ title: "second chat", status: "idle", messageCount: 1 });
120
+
121
+ deleteChat(a.id);
122
+ expect(readChat(a.id)).toBeNull();
123
+ expect(listChats().map((c) => c.id)).toEqual([b.id]);
124
+ });
125
+ });
@@ -0,0 +1,59 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { cclensPath } from "@claude-lens/parser/fs";
4
+ import type { Chat, ChatListItem } from "./chat-model";
5
+
6
+ export * from "./chat-model";
7
+
8
+ /* ── persistence: one JSON file per conversation ───────────────────── */
9
+
10
+ function chatsDir(): string {
11
+ return cclensPath("agent-chats");
12
+ }
13
+
14
+ function chatPath(id: string): string {
15
+ return join(chatsDir(), `${id}.json`);
16
+ }
17
+
18
+ export function writeChat(chat: Chat): void {
19
+ mkdirSync(chatsDir(), { recursive: true });
20
+ const final = chatPath(chat.id);
21
+ const tmp = `${final}.tmp.${process.pid}`;
22
+ writeFileSync(tmp, JSON.stringify(chat), "utf8");
23
+ renameSync(tmp, final);
24
+ }
25
+
26
+ export function readChat(id: string): Chat | null {
27
+ // Ids come from URLs — resolve strictly inside the chats dir.
28
+ if (!/^[a-zA-Z0-9-]+$/.test(id)) return null;
29
+ try {
30
+ const chat = JSON.parse(readFileSync(chatPath(id), "utf8")) as Chat;
31
+ return chat.version === 1 ? chat : null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ export function listChats(): ChatListItem[] {
38
+ if (!existsSync(chatsDir())) return [];
39
+ const out: ChatListItem[] = [];
40
+ for (const f of readdirSync(chatsDir())) {
41
+ if (!f.endsWith(".json")) continue;
42
+ const chat = readChat(f.slice(0, -".json".length));
43
+ if (!chat) continue;
44
+ out.push({
45
+ id: chat.id,
46
+ title: chat.title,
47
+ updated_at: chat.updated_at,
48
+ status: chat.status,
49
+ messageCount: chat.messages.length,
50
+ });
51
+ }
52
+ out.sort((a, b) => b.updated_at.localeCompare(a.updated_at));
53
+ return out;
54
+ }
55
+
56
+ export function deleteChat(id: string): void {
57
+ if (!/^[a-zA-Z0-9-]+$/.test(id)) return;
58
+ rmSync(chatPath(id), { force: true });
59
+ }
@@ -0,0 +1,141 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { SessionDetail, SessionEvent } from "@claude-lens/parser";
3
+ import { extractIndexDoc } from "./extract";
4
+
5
+ function ev(partial: Partial<SessionEvent> & { role: SessionEvent["role"] }): SessionEvent {
6
+ return {
7
+ index: 0,
8
+ rawType: partial.role,
9
+ preview: "",
10
+ blocks: [],
11
+ raw: null,
12
+ ...partial,
13
+ };
14
+ }
15
+
16
+ function session(events: SessionEvent[], meta: Partial<SessionDetail> = {}): SessionDetail {
17
+ return {
18
+ id: "abc-123",
19
+ filePath: "/tmp/abc-123.jsonl",
20
+ projectName: "/Users/me/Repo/foo",
21
+ projectDir: "-Users-me-Repo-foo",
22
+ sessionId: "abc-123",
23
+ eventCount: events.length,
24
+ totalUsage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
25
+ status: "idle",
26
+ firstTimestamp: "2026-07-01T10:00:00.000Z",
27
+ lastTimestamp: "2026-07-01T11:00:00.000Z",
28
+ events,
29
+ ...meta,
30
+ } as SessionDetail;
31
+ }
32
+
33
+ const FILE = { mtimeMs: 1000, sizeBytes: 2000 };
34
+
35
+ describe("extractIndexDoc", () => {
36
+ test("extracts user and agent text blocks as chunks", () => {
37
+ const doc = extractIndexDoc(
38
+ session([
39
+ ev({ index: 0, role: "user", blocks: [{ type: "text", text: "fix the daemon crash" }] }),
40
+ ev({ index: 1, role: "agent", blocks: [{ type: "text", text: "Found the crash in pid.ts" }] }),
41
+ ev({ index: 2, role: "tool-call", blocks: [{ type: "tool_use", id: "t1", name: "Bash", input: { command: "ls secret" } }] }),
42
+ ev({ index: 3, role: "agent-thinking", blocks: [{ type: "thinking", thinking: "hmm private" }] }),
43
+ ]),
44
+ FILE,
45
+ );
46
+ expect(doc.chunks).toEqual([
47
+ { role: "user", text: "fix the daemon crash", idx: 0 },
48
+ { role: "agent", text: "Found the crash in pid.ts", idx: 1 },
49
+ ]);
50
+ });
51
+
52
+ test("fills metadata: canonical project, start day, title, agent default", () => {
53
+ const doc = extractIndexDoc(
54
+ session(
55
+ [ev({ index: 0, role: "user", blocks: [{ type: "text", text: "hello world" }] })],
56
+ { projectName: "/Users/me/Repo/foo/.worktrees/kip-1", firstUserPreview: "hello world" },
57
+ ),
58
+ FILE,
59
+ );
60
+ expect(doc.sessionId).toBe("abc-123");
61
+ expect(doc.agent).toBe("claude-code");
62
+ expect(doc.project).toBe("/Users/me/Repo/foo");
63
+ expect(doc.repoName).toBeUndefined();
64
+ expect(doc.day).toBe("2026-07-01");
65
+ expect(doc.title).toBe("hello world");
66
+ expect(doc.mtimeMs).toBe(1000);
67
+ expect(doc.sizeBytes).toBe(2000);
68
+ });
69
+
70
+ test("skips command wrappers, skill loads, and teammate deliveries", () => {
71
+ const doc = extractIndexDoc(
72
+ session([
73
+ ev({ index: 0, role: "user", blocks: [{ type: "text", text: "<command-name>/clear</command-name>" }] }),
74
+ ev({ index: 1, role: "user", blocks: [{ type: "text", text: "Base directory for this skill: /x\n# Skill" }] }),
75
+ ev({
76
+ index: 2,
77
+ role: "user",
78
+ blocks: [{ type: "text", text: "ignore me" }],
79
+ teammateMessage: { teammateId: "t", body: "ignore me", kind: "message" },
80
+ }),
81
+ ev({ index: 3, role: "user", blocks: [{ type: "text", text: "real question" }] }),
82
+ ]),
83
+ FILE,
84
+ );
85
+ expect(doc.chunks).toEqual([{ role: "user", text: "real question", idx: 3 }]);
86
+ });
87
+
88
+ test("strips system-reminder spans inside user text", () => {
89
+ const doc = extractIndexDoc(
90
+ session([
91
+ ev({
92
+ index: 0,
93
+ role: "user",
94
+ blocks: [{ type: "text", text: "before <system-reminder>injected</system-reminder> after" }],
95
+ }),
96
+ ]),
97
+ FILE,
98
+ );
99
+ expect(doc.chunks[0]!.text).toBe("before after");
100
+ });
101
+
102
+ test("caps chunk length and total text, marking truncation", () => {
103
+ const long = "x".repeat(10_000);
104
+ const events: SessionEvent[] = [];
105
+ for (let i = 0; i < 200; i++) {
106
+ events.push(ev({ index: i, role: "agent", blocks: [{ type: "text", text: long }] }));
107
+ }
108
+ const doc = extractIndexDoc(session(events), FILE);
109
+ expect(Math.max(...doc.chunks.map((c) => c.text.length))).toBeLessThanOrEqual(4000);
110
+ const total = doc.chunks.reduce((s, c) => s + c.text.length, 0);
111
+ expect(total).toBeLessThanOrEqual(300_000);
112
+ expect(doc.truncated).toBe(true);
113
+ });
114
+
115
+ test("drops empty and whitespace-only text", () => {
116
+ const doc = extractIndexDoc(
117
+ session([
118
+ ev({ index: 0, role: "user", blocks: [{ type: "text", text: " " }] }),
119
+ ev({ index: 1, role: "agent", blocks: [{ type: "text", text: "" }] }),
120
+ ]),
121
+ FILE,
122
+ );
123
+ expect(doc.chunks).toEqual([]);
124
+ });
125
+
126
+ test("carries the git repo name when the session has one", () => {
127
+ const doc = extractIndexDoc(
128
+ session([ev({ index: 0, role: "user", blocks: [{ type: "text", text: "hi" }] })], { repoName: "fleetlens" }),
129
+ FILE,
130
+ );
131
+ expect(doc.repoName).toBe("fleetlens");
132
+ });
133
+
134
+ test("title falls back to first user chunk when firstUserPreview is absent", () => {
135
+ const doc = extractIndexDoc(
136
+ session([ev({ index: 0, role: "user", blocks: [{ type: "text", text: "the actual ask" }] })]),
137
+ FILE,
138
+ );
139
+ expect(doc.title).toBe("the actual ask");
140
+ });
141
+ });
@@ -0,0 +1,75 @@
1
+ import { canonicalProjectName, toLocalDay, type SessionDetail } from "@claude-lens/parser";
2
+ import { INDEX_VERSION, type IndexChunk, type IndexDoc } from "./types";
3
+
4
+ const CHUNK_MAX = 4000;
5
+ const DOC_TEXT_MAX = 300_000;
6
+ const TITLE_MAX = 120;
7
+
8
+ /** Harness-injected user events that aren't real human input. */
9
+ const SKIP_PREFIXES = [
10
+ "<command-name>",
11
+ "<local-command",
12
+ "Base directory for this skill:",
13
+ "<task-notification>",
14
+ "[SYSTEM NOTIFICATION",
15
+ "Caveat: the messages below",
16
+ ];
17
+
18
+ function cleanText(text: string): string {
19
+ return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trimEnd();
20
+ }
21
+
22
+ /** Tool calls, tool results, and thinking are deliberately excluded —
23
+ * search should find what was said, not every file path a tool printed. */
24
+ export function extractIndexDoc(
25
+ session: SessionDetail,
26
+ file: { mtimeMs: number; sizeBytes: number },
27
+ ): IndexDoc {
28
+ const chunks: IndexChunk[] = [];
29
+ let totalChars = 0;
30
+ let truncated = false;
31
+
32
+ for (const e of session.events) {
33
+ if (e.role !== "user" && e.role !== "agent") continue;
34
+ if (e.role === "user" && e.teammateMessage) continue;
35
+ for (const b of e.blocks) {
36
+ if (b.type !== "text" || typeof b.text !== "string") continue;
37
+ if (SKIP_PREFIXES.some((p) => b.text.startsWith(p))) continue;
38
+ let text = cleanText(b.text);
39
+ if (!text.trim()) continue;
40
+ if (text.length > CHUNK_MAX) {
41
+ text = text.slice(0, CHUNK_MAX);
42
+ truncated = true;
43
+ }
44
+ if (totalChars + text.length > DOC_TEXT_MAX) {
45
+ truncated = true;
46
+ break;
47
+ }
48
+ totalChars += text.length;
49
+ chunks.push({ role: e.role, text, idx: e.index });
50
+ }
51
+ if (totalChars >= DOC_TEXT_MAX) break;
52
+ }
53
+
54
+ const firstUser = chunks.find((c) => c.role === "user");
55
+ const rawTitle = session.firstUserPreview?.trim() || firstUser?.text.trim() || "(untitled session)";
56
+ const title = rawTitle.replace(/\s+/g, " ").slice(0, TITLE_MAX);
57
+
58
+ const startMs = session.firstTimestamp ? Date.parse(session.firstTimestamp) : NaN;
59
+
60
+ return {
61
+ version: INDEX_VERSION,
62
+ sessionId: session.id,
63
+ agent: session.agent ?? "claude-code",
64
+ project: canonicalProjectName(session.projectName),
65
+ ...(session.repoName ? { repoName: session.repoName } : {}),
66
+ day: Number.isNaN(startMs) ? "" : toLocalDay(startMs),
67
+ startIso: session.firstTimestamp,
68
+ endIso: session.lastTimestamp,
69
+ title,
70
+ chunks,
71
+ ...(truncated ? { truncated } : {}),
72
+ mtimeMs: file.mtimeMs,
73
+ sizeBytes: file.sizeBytes,
74
+ };
75
+ }