fleetlens 0.13.0 → 0.13.2

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 (211) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/build-manifest.json +8 -8
  3. package/app/apps/web/.next/prerender-manifest.json +3 -3
  4. package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +5 -5
  5. package/app/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  7. package/app/apps/web/.next/server/app/_global-error.rsc +7 -7
  8. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  9. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  10. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  11. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  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/build-manifest.json +5 -5
  14. package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
  15. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  16. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
  18. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +1 -1
  19. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
  20. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +1 -1
  21. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
  22. package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
  23. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +1 -1
  24. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
  26. package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
  27. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
  29. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
  30. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
  31. package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
  32. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
  33. package/app/apps/web/.next/server/app/api/team-config/route.js.nft.json +1 -1
  34. package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -1
  35. package/app/apps/web/.next/server/app/changelog/page/build-manifest.json +5 -5
  36. package/app/apps/web/.next/server/app/changelog/page.js +1 -1
  37. package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
  38. package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  39. package/app/apps/web/.next/server/app/day/[date]/page/build-manifest.json +5 -5
  40. package/app/apps/web/.next/server/app/day/[date]/page.js +1 -1
  41. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
  42. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
  43. package/app/apps/web/.next/server/app/day/page/build-manifest.json +5 -5
  44. package/app/apps/web/.next/server/app/day/page.js +1 -1
  45. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
  46. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
  47. package/app/apps/web/.next/server/app/digest/[date]/page/build-manifest.json +5 -5
  48. package/app/apps/web/.next/server/app/digest/[date]/page.js +1 -1
  49. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
  50. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
  51. package/app/apps/web/.next/server/app/digest/page/build-manifest.json +5 -5
  52. package/app/apps/web/.next/server/app/digest/page.js +1 -1
  53. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
  54. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
  55. package/app/apps/web/.next/server/app/insights/[key]/page/build-manifest.json +5 -5
  56. package/app/apps/web/.next/server/app/insights/[key]/page.js +1 -1
  57. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  58. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  59. package/app/apps/web/.next/server/app/insights/page/build-manifest.json +5 -5
  60. package/app/apps/web/.next/server/app/insights/page.js +3 -2
  61. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  62. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  63. package/app/apps/web/.next/server/app/page/build-manifest.json +5 -5
  64. package/app/apps/web/.next/server/app/page.js +1 -1
  65. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  66. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  67. package/app/apps/web/.next/server/app/parallelism/page/build-manifest.json +5 -5
  68. package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
  69. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  70. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  71. package/app/apps/web/.next/server/app/print/[key]/page/build-manifest.json +5 -5
  72. package/app/apps/web/.next/server/app/print/[key]/page.js +1 -1
  73. package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
  74. package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
  75. package/app/apps/web/.next/server/app/projects/[slug]/page/build-manifest.json +5 -5
  76. package/app/apps/web/.next/server/app/projects/[slug]/page.js +1 -1
  77. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  78. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  79. package/app/apps/web/.next/server/app/projects/page/build-manifest.json +5 -5
  80. package/app/apps/web/.next/server/app/projects/page.js +1 -1
  81. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  82. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  83. package/app/apps/web/.next/server/app/runs/page/build-manifest.json +5 -5
  84. package/app/apps/web/.next/server/app/runs/page.js +1 -1
  85. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
  86. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
  87. package/app/apps/web/.next/server/app/sessions/[id]/page/build-manifest.json +5 -5
  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/build-manifest.json +5 -5
  92. package/app/apps/web/.next/server/app/sessions/page.js +1 -1
  93. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  94. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  95. package/app/apps/web/.next/server/app/settings/page/build-manifest.json +5 -5
  96. package/app/apps/web/.next/server/app/settings/page.js +1 -1
  97. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  98. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  99. package/app/apps/web/.next/server/app/team/page/build-manifest.json +5 -5
  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/build-manifest.json +5 -5
  104. package/app/apps/web/.next/server/app/usage/page.js +1 -1
  105. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  106. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  107. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0gril0u._.js +9 -0
  108. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0n79hpm._.js +9 -0
  109. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0~utv~v._.js +9 -0
  110. package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
  111. package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
  112. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0exckd4._.js +1 -1
  113. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0-1_njm._.js → [root-of-the-server]__0k1x-c9._.js} +2 -2
  114. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0lhwp-k._.js +8 -0
  115. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0n-ax-5._.js +1 -1
  116. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +3 -3
  117. package/app/apps/web/.next/server/chunks/ssr/_0kajk31._.js +1 -1
  118. package/app/apps/web/.next/server/chunks/ssr/_0s3n5mz._.js +8 -0
  119. package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
  120. package/app/apps/web/.next/server/chunks/ssr/{_0jw2sm7._.js → _12mbgs5._.js} +2 -2
  121. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_day_[date]_day-view_tsx_0wjoe1u._.js +1 -1
  122. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_insights_page_tsx_071kwyw._.js +3 -0
  123. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_sessions-grid_tsx_0bri5x.._.js +3 -0
  124. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0l6hsch._.js +6 -0
  125. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
  126. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
  127. package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0cepfi8._.js +3 -0
  128. package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +1 -1
  129. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0mx_509._.js +1 -1
  130. package/app/apps/web/.next/server/middleware-build-manifest.js +8 -8
  131. package/app/apps/web/.next/server/middleware-manifest.json +5 -5
  132. package/app/apps/web/.next/server/pages/500.html +1 -1
  133. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  134. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  135. package/app/apps/web/.next/static/chunks/02xxpexzk3rf-.js +1 -0
  136. package/app/apps/web/.next/static/chunks/{07lbm-sdh9c2j.js → 0389wb_f0j78j.js} +1 -1
  137. package/app/apps/web/.next/static/chunks/03gy1evbn94qu.js +6 -0
  138. package/app/apps/web/.next/static/chunks/03rd.3cc_t~yf.js +4 -0
  139. package/app/apps/web/.next/static/chunks/{0l4e3as18eexy.js → 0g223u9amib0q.js} +1 -1
  140. package/app/apps/web/.next/static/chunks/{0h3.-_s-k0mj3.js → 0i.hc~2bj0_3d.js} +1 -1
  141. package/app/apps/web/.next/static/chunks/0m7dd-2zd9vl2.js +4 -0
  142. package/app/apps/web/.next/static/chunks/0nqklmbs5s3ax.js +6 -0
  143. package/app/apps/web/.next/static/chunks/{073081qv4uyn8.js → 0p--hzrway8~3.js} +1 -1
  144. package/app/apps/web/.next/static/chunks/{0gblp_v.kiu-..js → 0qv-gw888_5nu.js} +1 -1
  145. package/app/apps/web/.next/static/chunks/{14bjditmmrn7l.js → 0tirv_vo6q8uc.js} +1 -1
  146. package/app/apps/web/.next/static/chunks/0uyctl-m8iydb.js +1 -0
  147. package/app/apps/web/.next/static/chunks/0~qdw1b2uz._5.js +10 -0
  148. package/app/apps/web/.next/static/chunks/{0n0n.0279ot6c.js → 14vx702c32kn6.js} +1 -1
  149. package/app/apps/web/.next/static/chunks/{turbopack-0lb9w090w5ezx.js → turbopack-0mxu3~9vk.brh.js} +1 -1
  150. package/app/apps/web/app/api/digest/_shared/digest-route-helpers.ts +178 -0
  151. package/app/apps/web/app/api/digest/day/[date]/route.ts +34 -128
  152. package/app/apps/web/app/api/digest/month/[yearMonth]/route.ts +36 -121
  153. package/app/apps/web/app/api/digest/week/[startDate]/route.ts +36 -123
  154. package/app/apps/web/app/insights/page.tsx +20 -5
  155. package/app/apps/web/app/parallelism/burst-detail-modal.tsx +637 -0
  156. package/app/apps/web/app/parallelism/concurrency-info-modal.tsx +228 -0
  157. package/app/apps/web/app/parallelism/gantt-chart-utils.ts +49 -0
  158. package/app/apps/web/app/parallelism/gantt-chart.tsx +24 -903
  159. package/app/apps/web/app/sessions/[id]/session-view/colors.ts +31 -0
  160. package/app/apps/web/app/sessions/[id]/session-view/debug-list.tsx +78 -0
  161. package/app/apps/web/app/sessions/[id]/session-view/drawer.tsx +414 -0
  162. package/app/apps/web/app/sessions/[id]/session-view/entry-day-strip.tsx +124 -0
  163. package/app/apps/web/app/sessions/[id]/session-view/header-stats.tsx +217 -0
  164. package/app/apps/web/app/sessions/[id]/session-view/helpers.ts +135 -0
  165. package/app/apps/web/app/sessions/[id]/session-view/minimap.tsx +1587 -0
  166. package/app/apps/web/app/sessions/[id]/session-view/subagent-drawer.tsx +339 -0
  167. package/app/apps/web/app/sessions/[id]/session-view/token-stats.tsx +111 -0
  168. package/app/apps/web/app/sessions/[id]/session-view/tooltip.tsx +63 -0
  169. package/app/apps/web/app/sessions/[id]/session-view/types.ts +46 -0
  170. package/app/apps/web/app/sessions/[id]/session-view/workflows-panel.tsx +944 -0
  171. package/app/apps/web/app/sessions/[id]/session-view/workflows-shared.tsx +104 -0
  172. package/app/apps/web/app/sessions/[id]/session-view.tsx +1513 -5018
  173. package/app/apps/web/app/sessions/[id]/team-tab/minimap-hover-card.tsx +201 -0
  174. package/app/apps/web/app/sessions/[id]/team-tab/minimap-idle-band.tsx +53 -0
  175. package/app/apps/web/app/sessions/[id]/team-tab/minimap-shared.ts +20 -0
  176. package/app/apps/web/app/sessions/[id]/team-tab/team-minimap.tsx +10 -265
  177. package/app/apps/web/app/sessions/sessions-grid.tsx +10 -10
  178. package/app/apps/web/components/digest-actions.tsx +103 -0
  179. package/app/apps/web/components/job-queue-widget.tsx +1 -1
  180. package/app/apps/web/components/month-digest-view.tsx +19 -64
  181. package/app/apps/web/components/searchable-select.tsx +215 -0
  182. package/app/apps/web/components/tail-mode.tsx +46 -9
  183. package/app/apps/web/components/week-digest-view.tsx +16 -71
  184. package/app/apps/web/lib/changelog-data.generated.ts +1 -1
  185. package/app/apps/web/lib/entries-index.ts +7 -8
  186. package/app/apps/web/lib/entries.ts +0 -9
  187. package/app/apps/web/lib/format.test.ts +221 -0
  188. package/app/apps/web/lib/format.ts +17 -0
  189. package/app/apps/web/lib/utilization-tone.test.ts +56 -0
  190. package/app/apps/web/package.json +1 -1
  191. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  192. package/dist/daemon-worker.js +35 -43
  193. package/dist/index.js +37 -49
  194. package/package.json +1 -1
  195. package/app/apps/web/.next/server/chunks/[root-of-the-server]__04j3tng._.js +0 -9
  196. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0cnh3k4._.js +0 -9
  197. package/app/apps/web/.next/server/chunks/[root-of-the-server]__132eosx._.js +0 -9
  198. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__136-0me._.js +0 -8
  199. package/app/apps/web/.next/server/chunks/ssr/_0w.cv64._.js +0 -8
  200. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_01d-iwx._.js +0 -6
  201. package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0-lmm4p._.js +0 -3
  202. package/app/apps/web/.next/static/chunks/05k84gif3ucxm.js +0 -6
  203. package/app/apps/web/.next/static/chunks/0nnjldasalwdu.js +0 -4
  204. package/app/apps/web/.next/static/chunks/0okg13phslr1..js +0 -4
  205. package/app/apps/web/.next/static/chunks/0pzt9vemtzct8.js +0 -10
  206. package/app/apps/web/.next/static/chunks/0qmh5da6gfm56.js +0 -1
  207. package/app/apps/web/.next/static/chunks/0rnay-a.-jr8-.js +0 -1
  208. package/app/apps/web/.next/static/chunks/0snv3-2ux2xvv.js +0 -6
  209. /package/app/apps/web/.next/static/{rbp9x3iPbzrz-wxS-DAU5 → bZs5UyzsYBqC6MFY5n-M_}/_buildManifest.js +0 -0
  210. /package/app/apps/web/.next/static/{rbp9x3iPbzrz-wxS-DAU5 → bZs5UyzsYBqC6MFY5n-M_}/_clientMiddlewareManifest.js +0 -0
  211. /package/app/apps/web/.next/static/{rbp9x3iPbzrz-wxS-DAU5 → bZs5UyzsYBqC6MFY5n-M_}/_ssgManifest.js +0 -0
@@ -0,0 +1,339 @@
1
+ "use client";
2
+
3
+ /**
4
+ * SubagentDrawer — right-side panel opened when the user clicks a
5
+ * sub-agent lane bar on the mini-map. Renders the full run profile:
6
+ * type pill, background badge, timing range, duration, model, parent
7
+ * tool-use id, activity stats (events / messages / tool calls), token
8
+ * breakdown, tools-used pills, the prompt the parent dispatched, and
9
+ * the final agent text. A "Jump to parent" button scrolls the
10
+ * transcript to the Agent tool_use row that kicked the subagent off.
11
+ */
12
+ import React from "react";
13
+ import { X } from "lucide-react";
14
+ import ReactMarkdown from "react-markdown";
15
+ import remarkGfm from "remark-gfm";
16
+ import type { SubagentRun } from "@claude-lens/parser";
17
+ import { formatGap, formatOffset } from "@/lib/format";
18
+ import { subagentColor } from "./colors";
19
+ import { StatCell, TokenLine } from "./workflows-shared";
20
+ import { shortenToolName } from "../turn-steps";
21
+
22
+ export function SubagentDrawer({
23
+ subagent,
24
+ onClose,
25
+ onJumpToParent,
26
+ }: {
27
+ subagent: SubagentRun;
28
+ onClose: () => void;
29
+ onJumpToParent: () => void;
30
+ }) {
31
+ const s = subagent;
32
+ const fill = subagentColor(s.agentType, s.runInBackground);
33
+ const startOff = formatOffset(s.startTOffsetMs);
34
+ const endOff = formatOffset(s.endTOffsetMs);
35
+ const dur = s.durationMs !== undefined ? formatGap(s.durationMs) : "—";
36
+ const totalIn = s.totalUsage.input + s.totalUsage.cacheRead + s.totalUsage.cacheWrite;
37
+ const pctRead = totalIn > 0 ? Math.round((s.totalUsage.cacheRead / totalIn) * 100) : 0;
38
+
39
+ return (
40
+ <div>
41
+ {/* Sticky title bar */}
42
+ <div
43
+ style={{
44
+ padding: "14px 20px",
45
+ borderBottom: "1px solid var(--af-border-subtle)",
46
+ display: "flex",
47
+ alignItems: "center",
48
+ gap: 10,
49
+ background: "var(--af-surface)",
50
+ position: "sticky",
51
+ top: 0,
52
+ zIndex: 1,
53
+ flexWrap: "wrap",
54
+ }}
55
+ >
56
+ <span
57
+ style={{
58
+ fontSize: 11,
59
+ fontWeight: 600,
60
+ padding: "3px 10px",
61
+ borderRadius: 4,
62
+ background: fill,
63
+ color: "#fff",
64
+ }}
65
+ >
66
+ {s.agentType}
67
+ </span>
68
+ {s.runInBackground && (
69
+ <span
70
+ style={{
71
+ fontSize: 9,
72
+ fontWeight: 600,
73
+ padding: "2px 8px",
74
+ borderRadius: 4,
75
+ background: "var(--af-warning-subtle)",
76
+ color: "var(--af-warning)",
77
+ textTransform: "uppercase",
78
+ letterSpacing: "0.04em",
79
+ }}
80
+ >
81
+ background
82
+ </span>
83
+ )}
84
+ <span
85
+ style={{
86
+ fontSize: 14,
87
+ fontWeight: 600,
88
+ color: "var(--af-text)",
89
+ flex: 1,
90
+ minWidth: 0,
91
+ overflow: "hidden",
92
+ textOverflow: "ellipsis",
93
+ whiteSpace: "nowrap",
94
+ }}
95
+ title={s.description}
96
+ >
97
+ {s.description}
98
+ </span>
99
+ <button
100
+ onClick={onClose}
101
+ style={{
102
+ background: "transparent",
103
+ border: "none",
104
+ cursor: "pointer",
105
+ color: "var(--af-text-tertiary)",
106
+ padding: 4,
107
+ borderRadius: 4,
108
+ }}
109
+ aria-label="Close"
110
+ >
111
+ <X size={16} />
112
+ </button>
113
+ </div>
114
+
115
+ {/* Meta strip */}
116
+ <div
117
+ style={{
118
+ padding: "10px 20px",
119
+ fontFamily: "var(--font-mono)",
120
+ fontSize: 11,
121
+ color: "var(--af-text-tertiary)",
122
+ borderBottom: "1px solid var(--af-border-subtle)",
123
+ display: "grid",
124
+ gridTemplateColumns: "auto 1fr",
125
+ columnGap: 10,
126
+ rowGap: 3,
127
+ }}
128
+ >
129
+ <span style={{ opacity: 0.7 }}>range</span>
130
+ <span style={{ color: "var(--af-text-secondary)" }}>
131
+ {startOff} → {endOff}
132
+ </span>
133
+ <span style={{ opacity: 0.7 }}>duration</span>
134
+ <span style={{ color: "var(--af-text-secondary)" }}>{dur}</span>
135
+ {s.model && (
136
+ <>
137
+ <span style={{ opacity: 0.7 }}>model</span>
138
+ <span style={{ color: "var(--af-text-secondary)" }}>{s.model}</span>
139
+ </>
140
+ )}
141
+ {s.parentToolUseId && (
142
+ <>
143
+ <span style={{ opacity: 0.7 }}>parent</span>
144
+ <span style={{ color: "var(--af-text-secondary)" }}>
145
+ {s.parentToolUseId.slice(0, 24)}…
146
+ </span>
147
+ </>
148
+ )}
149
+ </div>
150
+
151
+ {/* Activity stats */}
152
+ <div
153
+ style={{
154
+ padding: "14px 20px",
155
+ borderBottom: "1px solid var(--af-border-subtle)",
156
+ display: "grid",
157
+ gridTemplateColumns: "1fr 1fr 1fr",
158
+ gap: 10,
159
+ }}
160
+ >
161
+ <StatCell label="Events" value={String(s.eventCount)} />
162
+ <StatCell label="Messages" value={String(s.assistantMessageCount ?? 0)} />
163
+ <StatCell label="Tool calls" value={String(s.toolCallCount ?? 0)} />
164
+ </div>
165
+
166
+ {/* Token breakdown */}
167
+ <div
168
+ style={{
169
+ padding: "12px 20px",
170
+ borderBottom: "1px solid var(--af-border-subtle)",
171
+ fontSize: 11,
172
+ fontFamily: "var(--font-mono)",
173
+ color: "var(--af-text-secondary)",
174
+ display: "flex",
175
+ flexDirection: "column",
176
+ gap: 3,
177
+ }}
178
+ >
179
+ <TokenLine label="Input (fresh)" value={s.totalUsage.input} />
180
+ <TokenLine label="Output" value={s.totalUsage.output} />
181
+ <TokenLine
182
+ label="Cache read"
183
+ value={s.totalUsage.cacheRead}
184
+ suffix={` (${pctRead}%)`}
185
+ />
186
+ <TokenLine label="Cache write" value={s.totalUsage.cacheWrite} />
187
+ </div>
188
+
189
+ {/* Tool breakdown */}
190
+ {s.toolCalls && s.toolCalls.length > 0 && (
191
+ <div
192
+ style={{
193
+ padding: "14px 20px",
194
+ borderBottom: "1px solid var(--af-border-subtle)",
195
+ }}
196
+ >
197
+ <div
198
+ style={{
199
+ fontSize: 10,
200
+ fontWeight: 600,
201
+ textTransform: "uppercase",
202
+ letterSpacing: "0.04em",
203
+ color: "var(--af-text-tertiary)",
204
+ marginBottom: 8,
205
+ }}
206
+ >
207
+ Tools used
208
+ </div>
209
+ <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
210
+ {s.toolCalls.map((t) => (
211
+ <span
212
+ key={t.name}
213
+ style={{
214
+ display: "inline-flex",
215
+ alignItems: "center",
216
+ gap: 4,
217
+ fontSize: 11,
218
+ padding: "2px 8px",
219
+ borderRadius: 4,
220
+ background: "var(--af-border-subtle)",
221
+ color: "var(--af-text)",
222
+ fontFamily: "var(--font-mono)",
223
+ }}
224
+ >
225
+ <b style={{ fontWeight: 600 }}>{shortenToolName(t.name)}</b>
226
+ <span style={{ color: "var(--af-text-tertiary)" }}>×{t.count}</span>
227
+ </span>
228
+ ))}
229
+ </div>
230
+ </div>
231
+ )}
232
+
233
+ {/* Parent prompt (what the parent asked the subagent to do) */}
234
+ {s.prompt && (
235
+ <div
236
+ style={{
237
+ padding: "14px 20px",
238
+ borderBottom: "1px solid var(--af-border-subtle)",
239
+ }}
240
+ >
241
+ <div
242
+ style={{
243
+ display: "flex",
244
+ alignItems: "center",
245
+ justifyContent: "space-between",
246
+ marginBottom: 8,
247
+ }}
248
+ >
249
+ <div
250
+ style={{
251
+ fontSize: 10,
252
+ fontWeight: 600,
253
+ textTransform: "uppercase",
254
+ letterSpacing: "0.04em",
255
+ color: "var(--af-text-tertiary)",
256
+ }}
257
+ >
258
+ Prompt
259
+ </div>
260
+ {s.parentToolUseId && (
261
+ <button
262
+ type="button"
263
+ onClick={onJumpToParent}
264
+ style={{
265
+ fontSize: 10,
266
+ color: "var(--af-accent)",
267
+ background: "transparent",
268
+ border: "none",
269
+ cursor: "pointer",
270
+ padding: 0,
271
+ }}
272
+ >
273
+ Jump to parent →
274
+ </button>
275
+ )}
276
+ </div>
277
+ <div className="sl-prose" style={{ fontSize: 12.5 }}>
278
+ <ReactMarkdown
279
+ remarkPlugins={[remarkGfm]}
280
+ components={{
281
+ a: (props) => (
282
+ <a
283
+ {...props}
284
+ target="_blank"
285
+ rel="noopener noreferrer"
286
+ style={{
287
+ color: "var(--af-accent)",
288
+ textDecoration: "underline",
289
+ }}
290
+ />
291
+ ),
292
+ }}
293
+ >
294
+ {s.prompt}
295
+ </ReactMarkdown>
296
+ </div>
297
+ </div>
298
+ )}
299
+
300
+ {/* Final text */}
301
+ {s.finalText && (
302
+ <div style={{ padding: "14px 20px" }}>
303
+ <div
304
+ style={{
305
+ fontSize: 10,
306
+ fontWeight: 600,
307
+ textTransform: "uppercase",
308
+ letterSpacing: "0.04em",
309
+ color: "var(--af-text-tertiary)",
310
+ marginBottom: 8,
311
+ }}
312
+ >
313
+ Final result
314
+ </div>
315
+ <div className="sl-prose" style={{ fontSize: 13 }}>
316
+ <ReactMarkdown
317
+ remarkPlugins={[remarkGfm]}
318
+ components={{
319
+ a: (props) => (
320
+ <a
321
+ {...props}
322
+ target="_blank"
323
+ rel="noopener noreferrer"
324
+ style={{
325
+ color: "var(--af-accent)",
326
+ textDecoration: "underline",
327
+ }}
328
+ />
329
+ ),
330
+ }}
331
+ >
332
+ {s.finalText}
333
+ </ReactMarkdown>
334
+ </div>
335
+ </div>
336
+ )}
337
+ </div>
338
+ );
339
+ }
@@ -0,0 +1,111 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Token display chips.
5
+ *
6
+ * - `TokenChip` — per-event token chip showing `{cache-inflated input} /
7
+ * output`. Used in event rows.
8
+ * - `TurnTokenChip` — per-turn aggregate. Primary display is fresh
9
+ * input / output (not the cache-inflated sum), consistent with the
10
+ * session header. Tooltip shows the full breakdown plus a footnote
11
+ * reminding that cache reads are cumulative across all requests in
12
+ * the turn.
13
+ */
14
+ import React, { useState } from "react";
15
+ import type { SessionEvent } from "@claude-lens/parser";
16
+ import { formatTokens } from "@/lib/format";
17
+ import { Tooltip, TooltipRow } from "./tooltip";
18
+
19
+ export function TokenChip({
20
+ usage,
21
+ }: {
22
+ usage: NonNullable<SessionEvent["usage"]>;
23
+ }) {
24
+ const [hover, setHover] = useState(false);
25
+ const totalIn = usage.input + usage.cacheRead + usage.cacheWrite;
26
+ const pctRead = totalIn > 0 ? Math.round((usage.cacheRead / totalIn) * 100) : 0;
27
+ return (
28
+ <span
29
+ style={{
30
+ position: "relative",
31
+ fontFamily: "var(--font-mono)",
32
+ fontSize: 11,
33
+ color: "var(--af-text-secondary)",
34
+ display: "inline-flex",
35
+ alignItems: "center",
36
+ gap: 4,
37
+ whiteSpace: "nowrap",
38
+ }}
39
+ onMouseEnter={() => setHover(true)}
40
+ onMouseLeave={() => setHover(false)}
41
+ >
42
+ <span style={{ opacity: 0.6 }}>▤</span>
43
+ {formatTokens(totalIn)} / {formatTokens(usage.output)}
44
+ {hover && (
45
+ <Tooltip style={{ right: 0, top: "calc(100% + 6px)", minWidth: 180 }}>
46
+ <TooltipRow label="Input" value={usage.input.toLocaleString()} />
47
+ <TooltipRow
48
+ label="Cache read"
49
+ value={`${usage.cacheRead.toLocaleString()} (${pctRead}%)`}
50
+ />
51
+ <TooltipRow label="Cache write" value={usage.cacheWrite.toLocaleString()} />
52
+ <TooltipRow label="Output" value={usage.output.toLocaleString()} />
53
+ </Tooltip>
54
+ )}
55
+ </span>
56
+ );
57
+ }
58
+
59
+ export function TurnTokenChip({
60
+ usage,
61
+ }: {
62
+ usage: { input: number; output: number; cacheRead: number; cacheWrite: number };
63
+ }) {
64
+ const [hover, setHover] = useState(false);
65
+ const totalIn = usage.input + usage.cacheRead + usage.cacheWrite;
66
+ const pctRead = totalIn > 0 ? Math.round((usage.cacheRead / totalIn) * 100) : 0;
67
+ return (
68
+ <span
69
+ style={{
70
+ position: "relative",
71
+ fontFamily: "var(--font-mono)",
72
+ fontSize: 11,
73
+ color: "var(--af-text-tertiary)",
74
+ display: "inline-flex",
75
+ alignItems: "center",
76
+ gap: 4,
77
+ whiteSpace: "nowrap",
78
+ cursor: "default",
79
+ }}
80
+ onMouseEnter={() => setHover(true)}
81
+ onMouseLeave={() => setHover(false)}
82
+ >
83
+ <span style={{ opacity: 0.6 }}>▤</span>
84
+ {formatTokens(usage.input)} / {formatTokens(usage.output)}
85
+ {hover && (
86
+ <Tooltip style={{ right: 0, top: "calc(100% + 6px)", minWidth: 220 }}>
87
+ <TooltipRow label="Input (fresh)" value={usage.input.toLocaleString()} />
88
+ <TooltipRow label="Output" value={usage.output.toLocaleString()} />
89
+ <TooltipRow
90
+ label="Cache read"
91
+ value={`${usage.cacheRead.toLocaleString()} (${pctRead}%)`}
92
+ />
93
+ <TooltipRow label="Cache write" value={usage.cacheWrite.toLocaleString()} />
94
+ <div
95
+ style={{
96
+ marginTop: 6,
97
+ paddingTop: 6,
98
+ borderTop: "1px solid rgba(241,245,249,0.12)",
99
+ opacity: 0.65,
100
+ fontSize: 10,
101
+ whiteSpace: "normal",
102
+ lineHeight: 1.4,
103
+ }}
104
+ >
105
+ Cumulative across all requests in this turn.
106
+ </div>
107
+ </Tooltip>
108
+ )}
109
+ </span>
110
+ );
111
+ }
@@ -0,0 +1,63 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Tooltip + TooltipRow — generic absolutely-positioned tooltip used by
5
+ * inline header stats, token chips, hover cards, etc. The parent owns
6
+ * positioning via the `style` prop; this component only handles the
7
+ * shell (background, border-radius, pointer-events: none).
8
+ *
9
+ * TooltipRow is a small key/value row helper for the common
10
+ * label-on-left / value-on-right pattern inside a Tooltip.
11
+ */
12
+ import React, { type CSSProperties } from "react";
13
+
14
+ export function Tooltip({
15
+ children,
16
+ style,
17
+ }: {
18
+ children: React.ReactNode;
19
+ style?: CSSProperties;
20
+ }) {
21
+ return (
22
+ <div
23
+ style={{
24
+ position: "absolute",
25
+ zIndex: 100,
26
+ background: "#1A1A1A",
27
+ color: "#F5F1EC",
28
+ borderRadius: 8,
29
+ padding: "10px 12px",
30
+ fontSize: 11,
31
+ fontFamily: "var(--font-mono)",
32
+ lineHeight: 1.5,
33
+ boxShadow: "0 4px 20px rgba(0,0,0,0.18)",
34
+ pointerEvents: "none",
35
+ whiteSpace: "nowrap",
36
+ ...style,
37
+ }}
38
+ >
39
+ {children}
40
+ </div>
41
+ );
42
+ }
43
+
44
+ export function TooltipRow({
45
+ label,
46
+ value,
47
+ }: {
48
+ label: string;
49
+ value: string;
50
+ }) {
51
+ return (
52
+ <div
53
+ style={{
54
+ display: "flex",
55
+ justifyContent: "space-between",
56
+ gap: 12,
57
+ }}
58
+ >
59
+ <span style={{ opacity: 0.7 }}>{label}</span>
60
+ <span>{value}</span>
61
+ </div>
62
+ );
63
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shared types for the session-view module split.
3
+ *
4
+ * - DisplayRow: a flat list item rendered by TranscriptList. Either a
5
+ * presentation row, a collapsed turn summary, or an expanded-turn
6
+ * header/footer with its inner rows interleaved between them.
7
+ * - MinimapSeg: one segment in the minimap (a row, a whole turn, or an
8
+ * idle stripe).
9
+ *
10
+ * Also re-exports `rowPrimaryIndex` from the parser so consumers can
11
+ * import it from one place alongside the types.
12
+ */
13
+ import {
14
+ rowPrimaryIndex as rowPrimaryIndexFromLib,
15
+ type MegaRow,
16
+ type PresentationRow,
17
+ type TurnMegaRow,
18
+ } from "@claude-lens/parser";
19
+
20
+ export const rowPrimaryIndex = rowPrimaryIndexFromLib;
21
+
22
+ export type DisplayRow =
23
+ | { kind: "presentation"; row: PresentationRow; indented?: boolean }
24
+ | { kind: "turn-collapsed"; turn: TurnMegaRow }
25
+ | { kind: "turn-expanded-header"; turn: TurnMegaRow }
26
+ | { kind: "turn-expanded-footer"; turn: TurnMegaRow };
27
+
28
+ export type MinimapSeg =
29
+ | {
30
+ kind: "row";
31
+ row: PresentationRow;
32
+ primaryIndex: number;
33
+ start: number;
34
+ end: number;
35
+ }
36
+ | {
37
+ kind: "turn";
38
+ turn: TurnMegaRow;
39
+ primaryIndex: number;
40
+ start: number;
41
+ end: number;
42
+ }
43
+ | { kind: "idle"; start: number; end: number; durationMs: number };
44
+
45
+ // Re-export underlying types so consumers needing them can import here.
46
+ export type { MegaRow, PresentationRow, TurnMegaRow };