@truefoundry/trueforge-ui 0.3.0-rc.0 → 0.3.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +14 -6
  3. package/dist/AgentCodeSnippets-NZOFJE57.js +74 -0
  4. package/dist/AgentCodeSnippets-NZOFJE57.js.map +1 -0
  5. package/dist/AgentMetricChart-JPU3MFQ2.js +15 -0
  6. package/dist/AgentOverview-EEBHJC32.js +167 -0
  7. package/dist/AgentOverview-EEBHJC32.js.map +1 -0
  8. package/dist/AgentSessionEventTimeline-26Z6IB3B.js +79 -0
  9. package/dist/AgentSessionEventTimeline-26Z6IB3B.js.map +1 -0
  10. package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js +504 -0
  11. package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js.map +1 -0
  12. package/dist/AgentSessions-3MPDZASK.js +275 -0
  13. package/dist/AgentSessions-3MPDZASK.js.map +1 -0
  14. package/dist/{ConnectorSettings-FXQ5B7TN.js → ConnectorSettings-MXFRWWR6.js} +8 -6
  15. package/dist/{ConnectorSettings-FXQ5B7TN.js.map → ConnectorSettings-MXFRWWR6.js.map} +1 -1
  16. package/dist/{DockLayout-LBNQJZNF.js → DockLayout-LM4AFMFY.js} +11 -10
  17. package/dist/{DockLayout-LBNQJZNF.js.map → DockLayout-LM4AFMFY.js.map} +1 -1
  18. package/dist/DrawerLayout-JR3O6RRB.js +184 -0
  19. package/dist/DrawerLayout-JR3O6RRB.js.map +1 -0
  20. package/dist/{ModelSettings-4L4LOQJA.js → ModelSettings-G7IFNC2Y.js} +8 -6
  21. package/dist/{ModelSettings-4L4LOQJA.js.map → ModelSettings-G7IFNC2Y.js.map} +1 -1
  22. package/dist/OpenUiFenceBlock-2TV5TQ6P.js +9 -0
  23. package/dist/OpenUiFenceBlock-2TV5TQ6P.js.map +1 -0
  24. package/dist/{SandboxSettings-Z4ZG6ZX4.js → SandboxSettings-NXAANMAX.js} +8 -6
  25. package/dist/{SandboxSettings-Z4ZG6ZX4.js.map → SandboxSettings-NXAANMAX.js.map} +1 -1
  26. package/dist/SchedulesPage-KKLUDO6B.js +15 -0
  27. package/dist/SchedulesPage-KKLUDO6B.js.map +1 -0
  28. package/dist/{SettingsBuilder-WF7ZWKQW.js → SettingsBuilder-L34IQ56S.js} +26 -22
  29. package/dist/SettingsBuilder-L34IQ56S.js.map +1 -0
  30. package/dist/{ShellRouteSync-T4WLY57Q.js → ShellRouteSync-CEBETGEJ.js} +95 -22
  31. package/dist/ShellRouteSync-CEBETGEJ.js.map +1 -0
  32. package/dist/SidebarLayout-A2HJPPHS.js +308 -0
  33. package/dist/SidebarLayout-A2HJPPHS.js.map +1 -0
  34. package/dist/{SkillSettings-3EPPC3IT.js → SkillSettings-FGGMSUNO.js} +8 -6
  35. package/dist/{SkillSettings-3EPPC3IT.js.map → SkillSettings-FGGMSUNO.js.map} +1 -1
  36. package/dist/{TrueForgeUIWithRouter-NZ4FGPE4.js → TrueForgeUIWithRouter-MZVJWJMB.js} +14 -10
  37. package/dist/{TrueForgeUIWithRouter-NZ4FGPE4.js.map → TrueForgeUIWithRouter-MZVJWJMB.js.map} +1 -1
  38. package/dist/{WidgetLayout-3QZ357FL.js → WidgetLayout-6QM45OQQ.js} +17 -13
  39. package/dist/WidgetLayout-6QM45OQQ.js.map +1 -0
  40. package/dist/chunk-2XPPBEYF.js +74 -0
  41. package/dist/chunk-2XPPBEYF.js.map +1 -0
  42. package/dist/chunk-6O6FWUDW.js +1376 -0
  43. package/dist/chunk-6O6FWUDW.js.map +1 -0
  44. package/dist/chunk-7Z2C2K7F.js +578 -0
  45. package/dist/chunk-7Z2C2K7F.js.map +1 -0
  46. package/dist/{chunk-WREC7D54.js → chunk-CYHJDKFB.js} +115 -32
  47. package/dist/chunk-CYHJDKFB.js.map +1 -0
  48. package/dist/chunk-DJUFS2BW.js +27 -0
  49. package/dist/chunk-DJUFS2BW.js.map +1 -0
  50. package/dist/chunk-DMMZSZTN.js +252 -0
  51. package/dist/chunk-DMMZSZTN.js.map +1 -0
  52. package/dist/chunk-FJW36PD7.js +180 -0
  53. package/dist/chunk-FJW36PD7.js.map +1 -0
  54. package/dist/chunk-M62XY4NC.js +555 -0
  55. package/dist/chunk-M62XY4NC.js.map +1 -0
  56. package/dist/{chunk-B52K63AW.js → chunk-MPNSO7E6.js} +2 -2
  57. package/dist/{chunk-CFLVPV5M.js → chunk-QC42MLAK.js} +7 -2
  58. package/dist/chunk-QC42MLAK.js.map +1 -0
  59. package/dist/chunk-RDXBMTP5.js +32 -0
  60. package/dist/chunk-RDXBMTP5.js.map +1 -0
  61. package/dist/chunk-SFZNIO6U.js +18 -0
  62. package/dist/chunk-SFZNIO6U.js.map +1 -0
  63. package/dist/chunk-U7KURWW3.js +840 -0
  64. package/dist/chunk-U7KURWW3.js.map +1 -0
  65. package/dist/chunk-WVE3F724.js +200 -0
  66. package/dist/chunk-WVE3F724.js.map +1 -0
  67. package/dist/{chunk-FJ5RSSMA.js → chunk-XAU7QFG3.js} +178 -36
  68. package/dist/chunk-XAU7QFG3.js.map +1 -0
  69. package/dist/chunk-Y6S4OVVQ.js +16 -0
  70. package/dist/chunk-Y6S4OVVQ.js.map +1 -0
  71. package/dist/chunk-ZKNUMH2M.js +119 -0
  72. package/dist/chunk-ZKNUMH2M.js.map +1 -0
  73. package/dist/chunk-ZTMKFZQ3.js +13214 -0
  74. package/dist/chunk-ZTMKFZQ3.js.map +1 -0
  75. package/dist/{createTrueFoundryServer-B72bU-J7.d.ts → createTrueFoundryServer-CmZnBh_l.d.ts} +15 -4
  76. package/dist/index.d.ts +1002 -22
  77. package/dist/index.js +689 -67
  78. package/dist/index.js.map +1 -1
  79. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +552 -8
  80. package/dist/plugins/trueforge-agent-server-adapter/index.js +503 -188
  81. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  82. package/dist/styles.css +1 -1
  83. package/package.json +8 -7
  84. package/dist/DrawerLayout-Q6UK4VMI.js +0 -159
  85. package/dist/DrawerLayout-Q6UK4VMI.js.map +0 -1
  86. package/dist/OpenUiFenceBlock-6UIIAVBX.js +0 -9
  87. package/dist/SettingsBuilder-WF7ZWKQW.js.map +0 -1
  88. package/dist/ShellRouteSync-T4WLY57Q.js.map +0 -1
  89. package/dist/SidebarLayout-3WZ3CVON.js +0 -256
  90. package/dist/SidebarLayout-3WZ3CVON.js.map +0 -1
  91. package/dist/WidgetLayout-3QZ357FL.js.map +0 -1
  92. package/dist/chunk-36KOSC2J.js +0 -567
  93. package/dist/chunk-36KOSC2J.js.map +0 -1
  94. package/dist/chunk-3S6KHO7H.js +0 -2121
  95. package/dist/chunk-3S6KHO7H.js.map +0 -1
  96. package/dist/chunk-7L63OK3O.js +0 -91
  97. package/dist/chunk-7L63OK3O.js.map +0 -1
  98. package/dist/chunk-CFLVPV5M.js.map +0 -1
  99. package/dist/chunk-FJ5RSSMA.js.map +0 -1
  100. package/dist/chunk-OSV3HI5M.js +0 -6891
  101. package/dist/chunk-OSV3HI5M.js.map +0 -1
  102. package/dist/chunk-WQULF5AT.js +0 -460
  103. package/dist/chunk-WQULF5AT.js.map +0 -1
  104. package/dist/chunk-WREC7D54.js.map +0 -1
  105. package/dist/chunk-YIWUG6MC.js +0 -101
  106. package/dist/chunk-YIWUG6MC.js.map +0 -1
  107. package/dist/chunk-ZXOADNF3.js +0 -75
  108. package/dist/chunk-ZXOADNF3.js.map +0 -1
  109. /package/dist/{OpenUiFenceBlock-6UIIAVBX.js.map → AgentMetricChart-JPU3MFQ2.js.map} +0 -0
  110. /package/dist/{chunk-B52K63AW.js.map → chunk-MPNSO7E6.js.map} +0 -0
@@ -0,0 +1,504 @@
1
+ "use client";
2
+ import {
3
+ LightTooltip,
4
+ MAIN_THREAD_ID,
5
+ SESSION_EVENT_TOOLTIP_HIDE_DURATION,
6
+ TIMELINE_TYPE,
7
+ buildTimelineAxisTicks,
8
+ formatCostUsd,
9
+ formatDurationMs,
10
+ formatTimelineDuration,
11
+ formatTokenCount,
12
+ getActiveTimelineMs,
13
+ getSessionEventColor,
14
+ getSessionEventHoverColor,
15
+ getSessionEventLabel,
16
+ getSessionEventTooltipHeading,
17
+ getSubAgentHoverGroups,
18
+ getSubAgentLanes,
19
+ getTimelineHoverTargetId,
20
+ getTimelineLayout,
21
+ getTimelineRange,
22
+ groupOverlappingToolCalls,
23
+ pickLongestNonOverlappingSegments,
24
+ useThemeMode
25
+ } from "./chunk-ZTMKFZQ3.js";
26
+ import "./chunk-2XPPBEYF.js";
27
+ import "./chunk-XAU7QFG3.js";
28
+ import "./chunk-U7KURWW3.js";
29
+ import "./chunk-M6MHLVSO.js";
30
+ import "./chunk-MPNSO7E6.js";
31
+ import "./chunk-7Z2C2K7F.js";
32
+
33
+ // src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
34
+ import {
35
+ BarElement,
36
+ Chart as ChartJS,
37
+ LinearScale,
38
+ Tooltip
39
+ } from "chart.js";
40
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
41
+ import { Bar } from "react-chartjs-2";
42
+
43
+ // src/atoms/agent-details/AgentSessionTimelineTooltip.tsx
44
+ import { jsx, jsxs } from "react/jsx-runtime";
45
+ function hasSessionEventTooltip(segment) {
46
+ return segment.type !== "system" || segment.description.trim().length > 0;
47
+ }
48
+ function SessionEventTooltip({
49
+ segment,
50
+ subAgentLabel
51
+ }) {
52
+ const showDuration = !segment.isMarker && !SESSION_EVENT_TOOLTIP_HIDE_DURATION.has(segment.type);
53
+ const content = segment.description.trim();
54
+ if (segment.type === "system") {
55
+ if (content.length === 0) return null;
56
+ return /* @__PURE__ */ jsx("p", { className: "max-w-[25rem] whitespace-normal break-words text-xs font-medium text-text-primary", children: content });
57
+ }
58
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-72 max-w-[25rem] overflow-auto whitespace-normal break-words text-xs", children: [
59
+ subAgentLabel != null ? /* @__PURE__ */ jsx("div", { className: "border-b border-border py-1.5 text-text-secondary", children: `Sub-Agent: ${subAgentLabel}` }) : null,
60
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 pt-1", children: [
61
+ /* @__PURE__ */ jsx("span", { className: segment.type === "error" ? "font-medium text-failure-bg" : "font-medium text-text-secondary", children: getSessionEventTooltipHeading(segment.type) }),
62
+ showDuration ? /* @__PURE__ */ jsx("span", { className: "tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) }) : null
63
+ ] }),
64
+ content.length > 0 ? /* @__PURE__ */ jsx("p", { className: "mt-1.5 line-clamp-6 font-medium text-text-primary", children: content }) : null
65
+ ] });
66
+ }
67
+ function SessionTurnTooltip({
68
+ turn,
69
+ turnNumber,
70
+ durationMs,
71
+ segments
72
+ }) {
73
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-72 max-w-full overflow-auto text-xs text-text-primary", children: [
74
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
75
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: `Turn ${turnNumber}` }),
76
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums text-text-secondary", children: formatDurationMs(durationMs) })
77
+ ] }),
78
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-col text-text-secondary", children: [
79
+ turn.totalCostInUsd != null ? /* @__PURE__ */ jsx("span", { children: `Cost: ${formatCostUsd(turn.totalCostInUsd)}` }) : null,
80
+ turn.totalTokens != null ? /* @__PURE__ */ jsx("span", { children: `Tokens: ${formatTokenCount(turn.totalTokens)}` }) : null
81
+ ] }),
82
+ /* @__PURE__ */ jsx("div", { className: "mt-2 border-t border-border pt-2", children: segments.map((segment) => {
83
+ const label = segment.type === "tool_call" || segment.type === "sub_agent" ? segment.description : segment.title;
84
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
85
+ /* @__PURE__ */ jsx(
86
+ "span",
87
+ {
88
+ className: "size-1.5 shrink-0 rounded-full",
89
+ style: { backgroundColor: getSessionEventColor(segment.type) }
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: label }),
93
+ segment.isMarker ? null : /* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) })
94
+ ] }, segment.id);
95
+ }) })
96
+ ] });
97
+ }
98
+ function SessionToolCallGroupTooltip({ group }) {
99
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-80 max-w-full overflow-auto text-xs", children: [
100
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
101
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-secondary", children: "Tool calls" }),
102
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums text-text-secondary", children: formatTimelineDuration(group.endMs - group.startMs) })
103
+ ] }),
104
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border pt-1.5", children: group.segments.map((segment) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
105
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium text-text-primary", children: segment.description || segment.title }),
106
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) })
107
+ ] }, segment.id)) })
108
+ ] });
109
+ }
110
+ function SessionSubAgentGroupTooltip({ group }) {
111
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-80 max-w-full overflow-auto text-xs", children: [
112
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
113
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-text-secondary", children: "Sub-agents" }),
114
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums text-text-secondary", children: formatTimelineDuration(group.endMs - group.startMs) })
115
+ ] }),
116
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border pt-1.5", children: group.segments.map((segment, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 py-0.5", children: [
117
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium text-text-primary", children: `Sub-agent ${index + 1}: ${segment.description || segment.title}` }),
118
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) })
119
+ ] }, segment.id)) })
120
+ ] });
121
+ }
122
+
123
+ // src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
124
+ import { jsx as jsx2 } from "react/jsx-runtime";
125
+ ChartJS.register(LinearScale, BarElement, Tooltip);
126
+ var MARKER_PX = 4;
127
+ var TURN_GAP_PX = 12;
128
+ var END_PAD_PX = 12;
129
+ var BAR_RADIUS_PX = 2;
130
+ var ROW_GAP_PX = 8;
131
+ var OVERHEAD_PX = 30;
132
+ function rowCenters(heights, gap) {
133
+ const centers = [];
134
+ let offset = 0;
135
+ for (const height of heights) {
136
+ centers.push(offset + height / 2);
137
+ offset += height + gap;
138
+ }
139
+ return { centers, band: Math.max(0, offset - gap) };
140
+ }
141
+ function eventOrder(type) {
142
+ if (type === "sub_agent") return 0;
143
+ if (type === "model") return 2;
144
+ return 1;
145
+ }
146
+ function turnBarLabelPoint(element) {
147
+ if (!("x" in element) || !("y" in element) || !("base" in element)) return null;
148
+ const { x, y, base } = element;
149
+ if (typeof x !== "number" || typeof y !== "number" || typeof base !== "number") return null;
150
+ return { x: (x + base) / 2, y };
151
+ }
152
+ function AgentSessionEventTimelineChart({
153
+ turns,
154
+ segments,
155
+ hiddenTypes,
156
+ onSelectTurn
157
+ }) {
158
+ const mode = useThemeMode();
159
+ const isDark = mode === "dark";
160
+ const axis = isDark ? "#8c8c92" : "#71717a";
161
+ const grid = isDark ? "#27272a" : "#e4e4e7";
162
+ const turnFill = isDark ? "#3f3f46" : "#e4e4e7";
163
+ const turnHover = isDark ? "#52525b" : "#d4d4d8";
164
+ const wrapperRef = useRef(null);
165
+ const [widthPx, setWidthPx] = useState(0);
166
+ const [overheadPx, setOverheadPx] = useState(OVERHEAD_PX);
167
+ const [tooltipTarget, setTooltipTarget] = useState(null);
168
+ const [tooltipAnchor, setTooltipAnchor] = useState(null);
169
+ const tooltipIdRef = useRef("");
170
+ const tooltipCursorXRef = useRef(null);
171
+ useEffect(() => {
172
+ const wrapper = wrapperRef.current;
173
+ if (wrapper == null) return void 0;
174
+ const update = () => setWidthPx(wrapper.clientWidth);
175
+ update();
176
+ const observer = new ResizeObserver(update);
177
+ observer.observe(wrapper);
178
+ return () => observer.disconnect();
179
+ }, []);
180
+ const refreshTooltipAnchor = useCallback(() => {
181
+ const wrapper = wrapperRef.current;
182
+ const left = tooltipCursorXRef.current;
183
+ if (wrapper == null || left == null) return;
184
+ setTooltipAnchor({ left, top: wrapper.getBoundingClientRect().bottom });
185
+ }, []);
186
+ const clearTooltip = useCallback(() => {
187
+ tooltipIdRef.current = "";
188
+ tooltipCursorXRef.current = null;
189
+ setTooltipTarget(null);
190
+ setTooltipAnchor(null);
191
+ }, []);
192
+ useEffect(() => {
193
+ if (tooltipTarget == null) return void 0;
194
+ refreshTooltipAnchor();
195
+ window.addEventListener("scroll", refreshTooltipAnchor, true);
196
+ window.addEventListener("resize", refreshTooltipAnchor);
197
+ return () => {
198
+ window.removeEventListener("scroll", refreshTooltipAnchor, true);
199
+ window.removeEventListener("resize", refreshTooltipAnchor);
200
+ };
201
+ }, [refreshTooltipAnchor, tooltipTarget]);
202
+ const activeTotalMs = Math.max(1, ...segments.map((segment) => segment.endMs));
203
+ const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);
204
+ const gapCount = Math.max(0, turnStartsMs.length - 1);
205
+ const scaleWidthPx = Math.max(widthPx / 2, widthPx - TURN_GAP_PX * gapCount - END_PAD_PX);
206
+ const msPerPx = activeTotalMs / Math.max(1, scaleWidthPx);
207
+ const turnGapMs = TURN_GAP_PX * msPerPx;
208
+ const totalMs = activeTotalMs + gapCount * turnGapMs;
209
+ const timelineMaxMs = totalMs + END_PAD_PX * msPerPx;
210
+ const timelineGaps = useMemo(
211
+ () => turnStartsMs.slice(1).map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),
212
+ [turnGapMs, turnStartsMs]
213
+ );
214
+ const visibleSegments = useMemo(
215
+ () => segments.flatMap((segment) => {
216
+ if (hiddenTypes.has(segment.type)) return [];
217
+ const shiftMs = (turnOrdinals.get(segment.turnIndex) ?? 0) * turnGapMs;
218
+ return [{ ...segment, startMs: segment.startMs + shiftMs, endMs: segment.endMs + shiftMs }];
219
+ }),
220
+ [hiddenTypes, segments, turnGapMs, turnOrdinals]
221
+ );
222
+ const turnBars = useMemo(
223
+ () => turnRanges.length < 2 ? [] : turnRanges.map((range) => ({
224
+ ...range,
225
+ id: `turn-${range.turnIndex}`,
226
+ durationMs: range.endMs - range.startMs,
227
+ startMs: range.startMs + range.ordinal * turnGapMs,
228
+ endMs: range.endMs + range.ordinal * turnGapMs + MARKER_PX * msPerPx
229
+ })),
230
+ [msPerPx, turnGapMs, turnRanges]
231
+ );
232
+ const subAgentSegments = useMemo(
233
+ () => visibleSegments.filter((segment) => segment.type === "sub_agent"),
234
+ [visibleSegments]
235
+ );
236
+ const mainSubAgents = useMemo(() => pickLongestNonOverlappingSegments(subAgentSegments), [subAgentSegments]);
237
+ const subAgentGroups = useMemo(
238
+ () => getSubAgentHoverGroups({ bars: mainSubAgents, subAgentSegments }),
239
+ [mainSubAgents, subAgentSegments]
240
+ );
241
+ const subAgentLanes = useMemo(
242
+ () => getSubAgentLanes({ subAgentSegments, threadSegments: visibleSegments, minWidthMs: MARKER_PX * msPerPx }),
243
+ [msPerPx, subAgentSegments, visibleSegments]
244
+ );
245
+ const mainCandidates = useMemo(() => {
246
+ const kept = new Set(mainSubAgents.map((segment) => segment.id));
247
+ return visibleSegments.filter(
248
+ (segment) => segment.threadId === MAIN_THREAD_ID || segment.type === "sub_agent" && kept.has(segment.id)
249
+ );
250
+ }, [mainSubAgents, visibleSegments]);
251
+ const toolCallGroups = useMemo(
252
+ () => groupOverlappingToolCalls(mainCandidates.filter((segment) => segment.type === "tool_call")).filter(
253
+ (group) => group.segments.length > 1
254
+ ),
255
+ [mainCandidates]
256
+ );
257
+ const groupedIds = useMemo(
258
+ () => new Set(toolCallGroups.flatMap((group) => group.segments.map((segment) => segment.id))),
259
+ [toolCallGroups]
260
+ );
261
+ const mainEventSegments = useMemo(
262
+ () => mainCandidates.filter((segment) => !groupedIds.has(segment.id)),
263
+ [groupedIds, mainCandidates]
264
+ );
265
+ const laneCount = subAgentLanes.reduce((count, lane) => Math.max(count, lane.lane + 1), 0);
266
+ const hasTurnRow = turnBars.length > 0;
267
+ const eventRow = hasTurnRow ? 1 : 0;
268
+ const { centers, band } = useMemo(
269
+ () => rowCenters([...hasTurnRow ? [16] : [], 28, ...Array.from({ length: laneCount }, () => 12)], ROW_GAP_PX),
270
+ [hasTurnRow, laneCount]
271
+ );
272
+ const chartTargets = useMemo(
273
+ () => [
274
+ ...turnBars.map((bar) => ({ type: TIMELINE_TYPE.turn, bar })),
275
+ ...subAgentLanes.flatMap(
276
+ (lane) => lane.segments.map((segment) => ({ type: TIMELINE_TYPE.event, segment }))
277
+ ),
278
+ ...mainEventSegments.map((segment) => {
279
+ if (segment.type !== "sub_agent") return { type: TIMELINE_TYPE.event, segment };
280
+ const group = subAgentGroups.find((candidate) => candidate.barId === segment.id);
281
+ return group == null ? { type: TIMELINE_TYPE.event, segment } : { type: TIMELINE_TYPE.subAgentGroup, group };
282
+ }),
283
+ ...toolCallGroups.map((group) => ({ type: TIMELINE_TYPE.toolCallGroup, group }))
284
+ ],
285
+ [mainEventSegments, subAgentGroups, subAgentLanes, toolCallGroups, turnBars]
286
+ );
287
+ const barDataset = ({
288
+ label,
289
+ range,
290
+ y,
291
+ color,
292
+ hover,
293
+ thickness,
294
+ order = 1,
295
+ inflateAmount
296
+ }) => ({
297
+ label,
298
+ data: [{ x: getTimelineRange(range), y }],
299
+ backgroundColor: color,
300
+ hoverBackgroundColor: hover,
301
+ hoverBorderColor: hover,
302
+ borderWidth: 0,
303
+ borderSkipped: false,
304
+ borderRadius: BAR_RADIUS_PX,
305
+ minBarLength: MARKER_PX,
306
+ barThickness: thickness,
307
+ grouped: false,
308
+ order,
309
+ ...inflateAmount == null ? {} : { inflateAmount }
310
+ });
311
+ const chartData = useMemo(
312
+ () => ({
313
+ datasets: [
314
+ ...turnBars.map(
315
+ (bar) => barDataset({
316
+ label: `Turn ${bar.ordinal + 1}`,
317
+ range: bar,
318
+ y: centers[0] ?? 0,
319
+ color: turnFill,
320
+ hover: turnHover,
321
+ thickness: 16
322
+ })
323
+ ),
324
+ ...subAgentLanes.flatMap(
325
+ (lane) => lane.segments.map(
326
+ (segment) => barDataset({
327
+ label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,
328
+ range: segment,
329
+ y: centers[eventRow + 1 + lane.lane] ?? 0,
330
+ color: getSessionEventColor(segment.type),
331
+ hover: getSessionEventHoverColor(segment.type),
332
+ thickness: 12,
333
+ order: eventOrder(segment.type),
334
+ inflateAmount: 0.5
335
+ })
336
+ )
337
+ ),
338
+ ...mainEventSegments.map(
339
+ (segment) => barDataset({
340
+ label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,
341
+ range: segment,
342
+ y: centers[eventRow] ?? 0,
343
+ color: getSessionEventColor(segment.type),
344
+ hover: getSessionEventHoverColor(segment.type),
345
+ thickness: 28,
346
+ order: eventOrder(segment.type),
347
+ inflateAmount: 0.5
348
+ })
349
+ ),
350
+ ...toolCallGroups.map(
351
+ (group) => barDataset({
352
+ label: "Parallel tool calls",
353
+ range: group,
354
+ y: centers[eventRow] ?? 0,
355
+ color: getSessionEventColor("tool_call"),
356
+ hover: getSessionEventHoverColor("tool_call"),
357
+ thickness: 28,
358
+ order: eventOrder("tool_call"),
359
+ inflateAmount: 0.5
360
+ })
361
+ )
362
+ ]
363
+ }),
364
+ [centers, eventRow, mainEventSegments, subAgentLanes, toolCallGroups, turnBars, turnFill, turnHover]
365
+ );
366
+ const turnLabelPlugin = useMemo(
367
+ () => ({
368
+ id: "turnLabels",
369
+ afterDatasetsDraw(chart) {
370
+ const { ctx } = chart;
371
+ ctx.save();
372
+ ctx.fillStyle = axis;
373
+ ctx.font = "500 10px sans-serif";
374
+ ctx.textAlign = "center";
375
+ ctx.textBaseline = "middle";
376
+ turnBars.forEach((bar, index) => {
377
+ const element = chart.getDatasetMeta(index).data[0];
378
+ if (element == null) return;
379
+ const point = turnBarLabelPoint(element);
380
+ if (point) ctx.fillText(`T${bar.ordinal + 1}`, point.x, point.y);
381
+ });
382
+ ctx.restore();
383
+ }
384
+ }),
385
+ [axis, turnBars]
386
+ );
387
+ const overheadPlugin = useMemo(
388
+ () => ({
389
+ id: "timelineOverhead",
390
+ afterLayout(chart) {
391
+ const next = Math.round(chart.height - chart.chartArea.height);
392
+ setOverheadPx((previous) => previous === next ? previous : next);
393
+ }
394
+ }),
395
+ []
396
+ );
397
+ const chartOptions = useMemo(
398
+ () => ({
399
+ indexAxis: "y",
400
+ animation: false,
401
+ responsive: true,
402
+ maintainAspectRatio: false,
403
+ onClick: (_event, elements) => {
404
+ const target = chartTargets[elements[0]?.datasetIndex ?? -1];
405
+ if (target?.type === TIMELINE_TYPE.turn) onSelectTurn?.(target.bar.turnIndex);
406
+ },
407
+ onHover: (event, elements) => {
408
+ const hoveredDatasetIndex = elements[0]?.datasetIndex;
409
+ const next = hoveredDatasetIndex == null ? null : chartTargets[hoveredDatasetIndex] ?? null;
410
+ const native = event.native;
411
+ if (native?.target instanceof HTMLElement) {
412
+ native.target.style.cursor = next?.type === TIMELINE_TYPE.turn ? "pointer" : "default";
413
+ }
414
+ if (native instanceof MouseEvent) {
415
+ tooltipCursorXRef.current = native.clientX;
416
+ refreshTooltipAnchor();
417
+ }
418
+ if (hoveredDatasetIndex == null) return;
419
+ const nextId = getTimelineHoverTargetId(next);
420
+ if (tooltipIdRef.current === nextId) return;
421
+ tooltipIdRef.current = nextId;
422
+ setTooltipTarget(next);
423
+ if (next == null) {
424
+ setTooltipAnchor(null);
425
+ return;
426
+ }
427
+ refreshTooltipAnchor();
428
+ },
429
+ plugins: { legend: { display: false }, tooltip: { enabled: false } },
430
+ scales: {
431
+ x: {
432
+ type: "linear",
433
+ position: "top",
434
+ min: 0,
435
+ max: timelineMaxMs,
436
+ grid: { color: grid },
437
+ border: { color: grid },
438
+ afterBuildTicks: (scale) => {
439
+ scale.ticks = buildTimelineAxisTicks({
440
+ ticks: scale.ticks,
441
+ totalMs,
442
+ timelineMaxMs
443
+ });
444
+ },
445
+ ticks: {
446
+ color: axis,
447
+ autoSkip: false,
448
+ includeBounds: true,
449
+ maxTicksLimit: 9,
450
+ stepSize: timelineMaxMs / 8,
451
+ callback: (value) => {
452
+ const timelineMs = Number(value);
453
+ return timelineMs <= totalMs ? formatTimelineDuration(getActiveTimelineMs(timelineMs, timelineGaps)) : "";
454
+ }
455
+ }
456
+ },
457
+ y: {
458
+ type: "linear",
459
+ display: false,
460
+ reverse: true,
461
+ offset: false,
462
+ min: 0,
463
+ max: band,
464
+ grid: { display: false }
465
+ }
466
+ }
467
+ }),
468
+ [axis, band, chartTargets, grid, onSelectTurn, refreshTooltipAnchor, timelineGaps, timelineMaxMs, totalMs]
469
+ );
470
+ const tooltipTurn = tooltipTarget?.type === TIMELINE_TYPE.turn ? turns[tooltipTarget.bar.turnIndex] : void 0;
471
+ const containerStyle = useMemo(() => ({ height: band + overheadPx }), [band, overheadPx]);
472
+ const tooltipContent = tooltipTarget?.type === TIMELINE_TYPE.turn && tooltipTurn != null ? /* @__PURE__ */ jsx2(
473
+ SessionTurnTooltip,
474
+ {
475
+ turn: tooltipTurn,
476
+ turnNumber: tooltipTarget.bar.ordinal + 1,
477
+ durationMs: tooltipTarget.bar.durationMs,
478
+ segments: segments.filter((segment) => segment.turnIndex === tooltipTarget.bar.turnIndex)
479
+ }
480
+ ) : tooltipTarget?.type === TIMELINE_TYPE.event && hasSessionEventTooltip(tooltipTarget.segment) ? /* @__PURE__ */ jsx2(
481
+ SessionEventTooltip,
482
+ {
483
+ segment: tooltipTarget.segment,
484
+ subAgentLabel: tooltipTarget.segment.type === "sub_agent" ? void 0 : subAgentLanes.find((lane) => lane.threadId === tooltipTarget.segment.threadId)?.track.description
485
+ }
486
+ ) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? /* @__PURE__ */ jsx2(SessionToolCallGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? /* @__PURE__ */ jsx2(SessionSubAgentGroupTooltip, { group: tooltipTarget.group }) : null;
487
+ return /* @__PURE__ */ jsx2("div", { ref: wrapperRef, className: "w-full", "data-slot": "agent-session-event-timeline-chart", children: /* @__PURE__ */ jsx2(
488
+ LightTooltip,
489
+ {
490
+ title: tooltipContent,
491
+ side: "bottom",
492
+ triggerClassName: "block w-full",
493
+ followCursor: true,
494
+ open: tooltipTarget != null && tooltipContent != null,
495
+ className: "max-w-[min(25rem,calc(100vw-1rem))] whitespace-normal",
496
+ anchor: tooltipAnchor,
497
+ children: /* @__PURE__ */ jsx2("div", { className: "w-full", style: containerStyle, onMouseLeave: clearTooltip, children: /* @__PURE__ */ jsx2(Bar, { data: chartData, options: chartOptions, plugins: [turnLabelPlugin, overheadPlugin] }) })
498
+ }
499
+ ) });
500
+ }
501
+ export {
502
+ AgentSessionEventTimelineChart
503
+ };
504
+ //# sourceMappingURL=AgentSessionEventTimelineChart-CGCU7WBK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/atoms/agent-details/AgentSessionEventTimelineChart.tsx","../src/atoms/agent-details/AgentSessionTimelineTooltip.tsx"],"sourcesContent":["'use client';\n\nimport {\n BarElement,\n Chart as ChartJS,\n LinearScale,\n Tooltip,\n type ChartData,\n type ChartOptions,\n type Plugin,\n} from 'chart.js';\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType, type CSSProperties } from 'react';\nimport { Bar } from 'react-chartjs-2';\n\nimport { useThemeMode } from '../../theme/SlotsProvider.js';\nimport {\n formatTimelineDuration,\n getSessionEventColor,\n getSessionEventHoverColor,\n getSessionEventLabel,\n MAIN_THREAD_ID,\n type SessionEventTimelineSegment,\n} from '../../utils/sessionEventTimeline.js';\nimport {\n buildTimelineAxisTicks,\n getActiveTimelineMs,\n getSubAgentHoverGroups,\n getSubAgentLanes,\n getTimelineHoverTargetId,\n getTimelineLayout,\n getTimelineRange,\n groupOverlappingToolCalls,\n pickLongestNonOverlappingSegments,\n TIMELINE_TYPE,\n type TimelineGap,\n type TimelineHoverTarget,\n type TimelineTurnBar,\n} from '../../utils/sessionEventTimelineChart.js';\nimport { LightTooltip } from '../primitives/Tooltip.js';\nimport {\n hasSessionEventTooltip,\n SessionEventTooltip,\n SessionSubAgentGroupTooltip,\n SessionToolCallGroupTooltip,\n SessionTurnTooltip,\n} from './AgentSessionTimelineTooltip.js';\nimport type { AgentSessionEventTimelineChartProps } from './types.js';\n\nChartJS.register(LinearScale, BarElement, Tooltip);\n\nconst MARKER_PX = 4;\nconst TURN_GAP_PX = 12;\nconst END_PAD_PX = 12;\nconst BAR_RADIUS_PX = 2;\nconst ROW_GAP_PX = 8;\nconst OVERHEAD_PX = 30;\n\ntype BarPoint = { x: [number, number]; y: number };\n\nfunction rowCenters(heights: number[], gap: number): { centers: number[]; band: number } {\n const centers: number[] = [];\n let offset = 0;\n for (const height of heights) {\n centers.push(offset + height / 2);\n offset += height + gap;\n }\n return { centers, band: Math.max(0, offset - gap) };\n}\n\nfunction eventOrder(type: SessionEventTimelineSegment['type']): number {\n if (type === 'sub_agent') return 0;\n if (type === 'model') return 2;\n return 1;\n}\n\nfunction turnBarLabelPoint(element: object): { x: number; y: number } | null {\n if (!('x' in element) || !('y' in element) || !('base' in element)) return null;\n const { x, y, base } = element;\n if (typeof x !== 'number' || typeof y !== 'number' || typeof base !== 'number') return null;\n return { x: (x + base) / 2, y };\n}\n\nexport function AgentSessionEventTimelineChart({\n turns,\n segments,\n hiddenTypes,\n onSelectTurn,\n}: AgentSessionEventTimelineChartProps) {\n const mode = useThemeMode();\n const isDark = mode === 'dark';\n const axis = isDark ? '#8c8c92' : '#71717a';\n const grid = isDark ? '#27272a' : '#e4e4e7';\n const turnFill = isDark ? '#3f3f46' : '#e4e4e7';\n const turnHover = isDark ? '#52525b' : '#d4d4d8';\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [widthPx, setWidthPx] = useState(0);\n const [overheadPx, setOverheadPx] = useState(OVERHEAD_PX);\n const [tooltipTarget, setTooltipTarget] = useState<TimelineHoverTarget | null>(null);\n const [tooltipAnchor, setTooltipAnchor] = useState<{ left: number; top: number } | null>(null);\n const tooltipIdRef = useRef('');\n const tooltipCursorXRef = useRef<number | null>(null);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (wrapper == null) return undefined;\n const update = () => setWidthPx(wrapper.clientWidth);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(wrapper);\n return () => observer.disconnect();\n }, []);\n\n const refreshTooltipAnchor = useCallback(() => {\n const wrapper = wrapperRef.current;\n const left = tooltipCursorXRef.current;\n if (wrapper == null || left == null) return;\n setTooltipAnchor({ left, top: wrapper.getBoundingClientRect().bottom });\n }, []);\n\n const clearTooltip = useCallback(() => {\n tooltipIdRef.current = '';\n tooltipCursorXRef.current = null;\n setTooltipTarget(null);\n setTooltipAnchor(null);\n }, []);\n\n useEffect(() => {\n if (tooltipTarget == null) return undefined;\n // Anchors use viewport coordinates, so remeasure the chart whenever any\n // scroll ancestor or the viewport moves it.\n refreshTooltipAnchor();\n window.addEventListener('scroll', refreshTooltipAnchor, true);\n window.addEventListener('resize', refreshTooltipAnchor);\n return () => {\n window.removeEventListener('scroll', refreshTooltipAnchor, true);\n window.removeEventListener('resize', refreshTooltipAnchor);\n };\n }, [refreshTooltipAnchor, tooltipTarget]);\n\n const activeTotalMs = Math.max(1, ...segments.map(segment => segment.endMs));\n const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);\n const gapCount = Math.max(0, turnStartsMs.length - 1);\n const scaleWidthPx = Math.max(widthPx / 2, widthPx - TURN_GAP_PX * gapCount - END_PAD_PX);\n const msPerPx = activeTotalMs / Math.max(1, scaleWidthPx);\n const turnGapMs = TURN_GAP_PX * msPerPx;\n const totalMs = activeTotalMs + gapCount * turnGapMs;\n const timelineMaxMs = totalMs + END_PAD_PX * msPerPx;\n const timelineGaps = useMemo<TimelineGap[]>(\n () =>\n turnStartsMs\n .slice(1)\n .map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),\n [turnGapMs, turnStartsMs],\n );\n\n const visibleSegments = useMemo(\n () =>\n segments.flatMap(segment => {\n if (hiddenTypes.has(segment.type)) return [];\n const shiftMs = (turnOrdinals.get(segment.turnIndex) ?? 0) * turnGapMs;\n return [{ ...segment, startMs: segment.startMs + shiftMs, endMs: segment.endMs + shiftMs }];\n }),\n [hiddenTypes, segments, turnGapMs, turnOrdinals],\n );\n const turnBars = useMemo<TimelineTurnBar[]>(\n () =>\n turnRanges.length < 2\n ? []\n : turnRanges.map(range => ({\n ...range,\n id: `turn-${range.turnIndex}`,\n durationMs: range.endMs - range.startMs,\n startMs: range.startMs + range.ordinal * turnGapMs,\n endMs: range.endMs + range.ordinal * turnGapMs + MARKER_PX * msPerPx,\n })),\n [msPerPx, turnGapMs, turnRanges],\n );\n const subAgentSegments = useMemo(\n () => visibleSegments.filter(segment => segment.type === 'sub_agent'),\n [visibleSegments],\n );\n const mainSubAgents = useMemo(() => pickLongestNonOverlappingSegments(subAgentSegments), [subAgentSegments]);\n const subAgentGroups = useMemo(\n () => getSubAgentHoverGroups({ bars: mainSubAgents, subAgentSegments }),\n [mainSubAgents, subAgentSegments],\n );\n const subAgentLanes = useMemo(\n () => getSubAgentLanes({ subAgentSegments, threadSegments: visibleSegments, minWidthMs: MARKER_PX * msPerPx }),\n [msPerPx, subAgentSegments, visibleSegments],\n );\n const mainCandidates = useMemo(() => {\n const kept = new Set(mainSubAgents.map(segment => segment.id));\n return visibleSegments.filter(\n segment => segment.threadId === MAIN_THREAD_ID || (segment.type === 'sub_agent' && kept.has(segment.id)),\n );\n }, [mainSubAgents, visibleSegments]);\n const toolCallGroups = useMemo(\n () =>\n groupOverlappingToolCalls(mainCandidates.filter(segment => segment.type === 'tool_call')).filter(\n group => group.segments.length > 1,\n ),\n [mainCandidates],\n );\n const groupedIds = useMemo(\n () => new Set(toolCallGroups.flatMap(group => group.segments.map(segment => segment.id))),\n [toolCallGroups],\n );\n const mainEventSegments = useMemo(\n () => mainCandidates.filter(segment => !groupedIds.has(segment.id)),\n [groupedIds, mainCandidates],\n );\n const laneCount = subAgentLanes.reduce((count, lane) => Math.max(count, lane.lane + 1), 0);\n const hasTurnRow = turnBars.length > 0;\n const eventRow = hasTurnRow ? 1 : 0;\n const { centers, band } = useMemo(\n () => rowCenters([...(hasTurnRow ? [16] : []), 28, ...Array.from({ length: laneCount }, () => 12)], ROW_GAP_PX),\n [hasTurnRow, laneCount],\n );\n\n const chartTargets = useMemo<Array<TimelineHoverTarget | null>>(\n () => [\n ...turnBars.map((bar): TimelineHoverTarget => ({ type: TIMELINE_TYPE.turn, bar })),\n ...subAgentLanes.flatMap(lane =>\n lane.segments.map((segment): TimelineHoverTarget => ({ type: TIMELINE_TYPE.event, segment })),\n ),\n ...mainEventSegments.map((segment): TimelineHoverTarget | null => {\n if (segment.type !== 'sub_agent') return { type: TIMELINE_TYPE.event, segment };\n const group = subAgentGroups.find(candidate => candidate.barId === segment.id);\n return group == null ? { type: TIMELINE_TYPE.event, segment } : { type: TIMELINE_TYPE.subAgentGroup, group };\n }),\n ...toolCallGroups.map((group): TimelineHoverTarget => ({ type: TIMELINE_TYPE.toolCallGroup, group })),\n ],\n [mainEventSegments, subAgentGroups, subAgentLanes, toolCallGroups, turnBars],\n );\n\n const barDataset = ({\n label,\n range,\n y,\n color,\n hover,\n thickness,\n order = 1,\n inflateAmount,\n }: {\n label: string;\n range: TimelineGap;\n y: number;\n color: string;\n hover: string;\n thickness: number;\n order?: number;\n inflateAmount?: number;\n }) => ({\n label,\n data: [{ x: getTimelineRange(range), y }] satisfies BarPoint[],\n backgroundColor: color,\n hoverBackgroundColor: hover,\n hoverBorderColor: hover,\n borderWidth: 0,\n borderSkipped: false,\n borderRadius: BAR_RADIUS_PX,\n minBarLength: MARKER_PX,\n barThickness: thickness,\n grouped: false,\n order,\n ...(inflateAmount == null ? {} : { inflateAmount }),\n });\n\n const chartData = useMemo<ChartData<'bar', BarPoint[], string>>(\n () => ({\n datasets: [\n ...turnBars.map(bar =>\n barDataset({\n label: `Turn ${bar.ordinal + 1}`,\n range: bar,\n y: centers[0] ?? 0,\n color: turnFill,\n hover: turnHover,\n thickness: 16,\n }),\n ),\n ...subAgentLanes.flatMap(lane =>\n lane.segments.map(segment =>\n barDataset({\n label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,\n range: segment,\n y: centers[eventRow + 1 + lane.lane] ?? 0,\n color: getSessionEventColor(segment.type),\n hover: getSessionEventHoverColor(segment.type),\n thickness: 12,\n order: eventOrder(segment.type),\n inflateAmount: 0.5,\n }),\n ),\n ),\n ...mainEventSegments.map(segment =>\n barDataset({\n label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,\n range: segment,\n y: centers[eventRow] ?? 0,\n color: getSessionEventColor(segment.type),\n hover: getSessionEventHoverColor(segment.type),\n thickness: 28,\n order: eventOrder(segment.type),\n inflateAmount: 0.5,\n }),\n ),\n ...toolCallGroups.map(group =>\n barDataset({\n label: 'Parallel tool calls',\n range: group,\n y: centers[eventRow] ?? 0,\n color: getSessionEventColor('tool_call'),\n hover: getSessionEventHoverColor('tool_call'),\n thickness: 28,\n order: eventOrder('tool_call'),\n inflateAmount: 0.5,\n }),\n ),\n ],\n }),\n [centers, eventRow, mainEventSegments, subAgentLanes, toolCallGroups, turnBars, turnFill, turnHover],\n );\n\n const turnLabelPlugin = useMemo<Plugin<'bar'>>(\n () => ({\n id: 'turnLabels',\n afterDatasetsDraw(chart) {\n const { ctx } = chart;\n ctx.save();\n ctx.fillStyle = axis;\n ctx.font = '500 10px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n turnBars.forEach((bar, index) => {\n const element = chart.getDatasetMeta(index).data[0];\n if (element == null) return;\n const point = turnBarLabelPoint(element);\n if (point) ctx.fillText(`T${bar.ordinal + 1}`, point.x, point.y);\n });\n ctx.restore();\n },\n }),\n [axis, turnBars],\n );\n const overheadPlugin = useMemo<Plugin<'bar'>>(\n () => ({\n id: 'timelineOverhead',\n afterLayout(chart) {\n const next = Math.round(chart.height - chart.chartArea.height);\n setOverheadPx(previous => (previous === next ? previous : next));\n },\n }),\n [],\n );\n\n const chartOptions = useMemo<ChartOptions<'bar'>>(\n () => ({\n indexAxis: 'y',\n animation: false,\n responsive: true,\n maintainAspectRatio: false,\n onClick: (_event, elements) => {\n const target = chartTargets[elements[0]?.datasetIndex ?? -1];\n if (target?.type === TIMELINE_TYPE.turn) onSelectTurn?.(target.bar.turnIndex);\n },\n onHover: (event, elements) => {\n const hoveredDatasetIndex = elements[0]?.datasetIndex;\n const next = hoveredDatasetIndex == null ? null : (chartTargets[hoveredDatasetIndex] ?? null);\n const native = event.native;\n if (native?.target instanceof HTMLElement) {\n native.target.style.cursor = next?.type === TIMELINE_TYPE.turn ? 'pointer' : 'default';\n }\n if (native instanceof MouseEvent) {\n tooltipCursorXRef.current = native.clientX;\n refreshTooltipAnchor();\n }\n // Pointer between bars keeps the current tooltip; a bar without a tooltip dismisses it.\n if (hoveredDatasetIndex == null) return;\n const nextId = getTimelineHoverTargetId(next);\n if (tooltipIdRef.current === nextId) return;\n tooltipIdRef.current = nextId;\n setTooltipTarget(next);\n if (next == null) {\n setTooltipAnchor(null);\n return;\n }\n refreshTooltipAnchor();\n },\n plugins: { legend: { display: false }, tooltip: { enabled: false } },\n scales: {\n x: {\n type: 'linear',\n position: 'top',\n min: 0,\n max: timelineMaxMs,\n grid: { color: grid },\n border: { color: grid },\n afterBuildTicks: scale => {\n scale.ticks = buildTimelineAxisTicks({\n ticks: scale.ticks,\n totalMs,\n timelineMaxMs,\n });\n },\n ticks: {\n color: axis,\n autoSkip: false,\n includeBounds: true,\n maxTicksLimit: 9,\n stepSize: timelineMaxMs / 8,\n callback: value => {\n const timelineMs = Number(value);\n return timelineMs <= totalMs ? formatTimelineDuration(getActiveTimelineMs(timelineMs, timelineGaps)) : '';\n },\n },\n },\n y: {\n type: 'linear',\n display: false,\n reverse: true,\n offset: false,\n min: 0,\n max: band,\n grid: { display: false },\n },\n },\n }),\n [axis, band, chartTargets, grid, onSelectTurn, refreshTooltipAnchor, timelineGaps, timelineMaxMs, totalMs],\n );\n\n const tooltipTurn = tooltipTarget?.type === TIMELINE_TYPE.turn ? turns[tooltipTarget.bar.turnIndex] : undefined;\n const containerStyle = useMemo<CSSProperties>(() => ({ height: band + overheadPx }), [band, overheadPx]);\n const tooltipContent =\n tooltipTarget?.type === TIMELINE_TYPE.turn && tooltipTurn != null ? (\n <SessionTurnTooltip\n turn={tooltipTurn}\n turnNumber={tooltipTarget.bar.ordinal + 1}\n durationMs={tooltipTarget.bar.durationMs}\n segments={segments.filter(segment => segment.turnIndex === tooltipTarget.bar.turnIndex)}\n />\n ) : tooltipTarget?.type === TIMELINE_TYPE.event && hasSessionEventTooltip(tooltipTarget.segment) ? (\n <SessionEventTooltip\n segment={tooltipTarget.segment}\n subAgentLabel={\n tooltipTarget.segment.type === 'sub_agent'\n ? undefined\n : subAgentLanes.find(lane => lane.threadId === tooltipTarget.segment.threadId)?.track.description\n }\n />\n ) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? (\n <SessionToolCallGroupTooltip group={tooltipTarget.group} />\n ) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? (\n <SessionSubAgentGroupTooltip group={tooltipTarget.group} />\n ) : null;\n\n return (\n <div ref={wrapperRef} className=\"w-full\" data-slot=\"agent-session-event-timeline-chart\">\n <LightTooltip\n title={tooltipContent}\n side=\"bottom\"\n triggerClassName=\"block w-full\"\n followCursor\n open={tooltipTarget != null && tooltipContent != null}\n className=\"max-w-[min(25rem,calc(100vw-1rem))] whitespace-normal\"\n anchor={tooltipAnchor}\n >\n <div className=\"w-full\" style={containerStyle} onMouseLeave={clearTooltip}>\n <Bar data={chartData} options={chartOptions} plugins={[turnLabelPlugin, overheadPlugin]} />\n </div>\n </LightTooltip>\n </div>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentSessionEventTimelineChart: ComponentType<AgentSessionEventTimelineChartProps>;\n }\n}\n","'use client';\n\nimport { formatCostUsd, formatDurationMs, formatTokenCount } from '../../utils/sessionDisplayFormat.js';\nimport {\n formatTimelineDuration,\n getSessionEventColor,\n getSessionEventTooltipHeading,\n SESSION_EVENT_TOOLTIP_HIDE_DURATION,\n type SessionEventTimelineSegment,\n} from '../../utils/sessionEventTimeline.js';\nimport type { TimelineSubAgentGroup, TimelineToolCallGroup } from '../../utils/sessionEventTimelineChart.js';\nimport type { SessionTurnView } from '../../utils/sessionTurnViews.js';\n\nexport function hasSessionEventTooltip(segment: SessionEventTimelineSegment): boolean {\n return segment.type !== 'system' || segment.description.trim().length > 0;\n}\n\nexport function SessionEventTooltip({\n segment,\n subAgentLabel,\n}: {\n segment: SessionEventTimelineSegment;\n subAgentLabel?: string;\n}) {\n const showDuration = !segment.isMarker && !SESSION_EVENT_TOOLTIP_HIDE_DURATION.has(segment.type);\n const content = segment.description.trim();\n if (segment.type === 'system') {\n if (content.length === 0) return null;\n return (\n <p className=\"max-w-[25rem] whitespace-normal break-words text-xs font-medium text-text-primary\">{content}</p>\n );\n }\n\n return (\n <div className=\"max-h-72 max-w-[25rem] overflow-auto whitespace-normal break-words text-xs\">\n {subAgentLabel != null ? (\n <div className=\"border-b border-border py-1.5 text-text-secondary\">{`Sub-Agent: ${subAgentLabel}`}</div>\n ) : null}\n <div className=\"flex items-center justify-between gap-3 pt-1\">\n <span className={segment.type === 'error' ? 'font-medium text-failure-bg' : 'font-medium text-text-secondary'}>\n {getSessionEventTooltipHeading(segment.type)}\n </span>\n {showDuration ? (\n <span className=\"tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n ) : null}\n </div>\n {content.length > 0 ? <p className=\"mt-1.5 line-clamp-6 font-medium text-text-primary\">{content}</p> : null}\n </div>\n );\n}\n\nexport function SessionTurnTooltip({\n turn,\n turnNumber,\n durationMs,\n segments,\n}: {\n turn: SessionTurnView;\n turnNumber: number;\n durationMs: number;\n segments: SessionEventTimelineSegment[];\n}) {\n return (\n <div className=\"max-h-72 w-72 max-w-full overflow-auto text-xs text-text-primary\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-semibold\">{`Turn ${turnNumber}`}</span>\n <span className=\"tabular-nums text-text-secondary\">{formatDurationMs(durationMs)}</span>\n </div>\n <div className=\"mt-1 flex flex-col text-text-secondary\">\n {turn.totalCostInUsd != null ? <span>{`Cost: ${formatCostUsd(turn.totalCostInUsd)}`}</span> : null}\n {turn.totalTokens != null ? <span>{`Tokens: ${formatTokenCount(turn.totalTokens)}`}</span> : null}\n </div>\n <div className=\"mt-2 border-t border-border pt-2\">\n {segments.map(segment => {\n const label =\n segment.type === 'tool_call' || segment.type === 'sub_agent' ? segment.description : segment.title;\n return (\n <div key={segment.id} className=\"flex min-w-0 items-center gap-1.5\">\n <span\n className=\"size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: getSessionEventColor(segment.type) }}\n />\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n {segment.isMarker ? null : (\n <span className=\"ml-auto shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport function SessionToolCallGroupTooltip({ group }: { group: TimelineToolCallGroup }) {\n return (\n <div className=\"max-h-72 w-80 max-w-full overflow-auto text-xs\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-medium text-text-secondary\">Tool calls</span>\n <span className=\"tabular-nums text-text-secondary\">{formatTimelineDuration(group.endMs - group.startMs)}</span>\n </div>\n <div className=\"mt-1.5 border-t border-border pt-1.5\">\n {group.segments.map(segment => (\n <div key={segment.id} className=\"flex items-center justify-between gap-2 py-0.5\">\n <span className=\"min-w-0 truncate font-medium text-text-primary\">\n {segment.description || segment.title}\n </span>\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport function SessionSubAgentGroupTooltip({ group }: { group: TimelineSubAgentGroup }) {\n return (\n <div className=\"max-h-72 w-80 max-w-full overflow-auto text-xs\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"font-medium text-text-secondary\">Sub-agents</span>\n <span className=\"tabular-nums text-text-secondary\">{formatTimelineDuration(group.endMs - group.startMs)}</span>\n </div>\n <div className=\"mt-1.5 border-t border-border pt-1.5\">\n {group.segments.map((segment, index) => (\n <div key={segment.id} className=\"flex items-center justify-between gap-2 py-0.5\">\n <span className=\"min-w-0 truncate font-medium text-text-primary\">\n {`Sub-agent ${index + 1}: ${segment.description || segment.title}`}\n </span>\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx"]}