@truefoundry/trueforge-ui 0.3.0-rc.1 → 0.3.0-rc.3
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.
- package/CHANGELOG.md +70 -0
- package/README.md +22 -7
- package/dist/{AgentCodeSnippets-NZOFJE57.js → AgentCodeSnippets-N546FNNS.js} +38 -23
- package/dist/AgentCodeSnippets-N546FNNS.js.map +1 -0
- package/dist/AgentMetricChart-YWJYVYYA.js +15 -0
- package/dist/{AgentOverview-EEBHJC32.js → AgentOverview-VF74XC7I.js} +7 -7
- package/dist/{AgentSessionEventTimeline-26Z6IB3B.js → AgentSessionEventTimeline-RFR6LQMY.js} +19 -10
- package/dist/AgentSessionEventTimeline-RFR6LQMY.js.map +1 -0
- package/dist/{AgentSessionEventTimelineChart-CGCU7WBK.js → AgentSessionEventTimelineChart-27CQF6FX.js} +144 -57
- package/dist/AgentSessionEventTimelineChart-27CQF6FX.js.map +1 -0
- package/dist/{AgentSessions-3MPDZASK.js → AgentSessions-4IVX2SGD.js} +36 -12
- package/dist/AgentSessions-4IVX2SGD.js.map +1 -0
- package/dist/{ConnectorSettings-MXFRWWR6.js → ConnectorSettings-R5VEP7BO.js} +162 -126
- package/dist/ConnectorSettings-R5VEP7BO.js.map +1 -0
- package/dist/{DockLayout-LM4AFMFY.js → DockLayout-F44RWGEY.js} +10 -10
- package/dist/{DrawerLayout-JR3O6RRB.js → DrawerLayout-SQ323AVM.js} +14 -12
- package/dist/DrawerLayout-SQ323AVM.js.map +1 -0
- package/dist/{ModelSettings-G7IFNC2Y.js → ModelSettings-6QLS63HM.js} +22 -28
- package/dist/ModelSettings-6QLS63HM.js.map +1 -0
- package/dist/OpenUiFenceBlock-4ROX3G4X.js +9 -0
- package/dist/{SandboxSettings-NXAANMAX.js → SandboxSettings-OLKDXIQS.js} +17 -21
- package/dist/SandboxSettings-OLKDXIQS.js.map +1 -0
- package/dist/SchedulesPage-TMOTK6DR.js +15 -0
- package/dist/{SettingsBuilder-L34IQ56S.js → SettingsBuilder-GISAH2WU.js} +8 -8
- package/dist/{ShellRouteSync-CEBETGEJ.js → ShellRouteSync-EN33DUQ7.js} +171 -26
- package/dist/ShellRouteSync-EN33DUQ7.js.map +1 -0
- package/dist/{SidebarLayout-A2HJPPHS.js → SidebarLayout-35K4AKTC.js} +80 -58
- package/dist/SidebarLayout-35K4AKTC.js.map +1 -0
- package/dist/{SkillSettings-FGGMSUNO.js → SkillSettings-JSX2BTII.js} +24 -22
- package/dist/SkillSettings-JSX2BTII.js.map +1 -0
- package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js → TrueForgeUIWithRouter-6VCR7ES3.js} +9 -9
- package/dist/{WidgetLayout-6QM45OQQ.js → WidgetLayout-RKBSN2FZ.js} +10 -10
- package/dist/{chunk-ZTMKFZQ3.js → chunk-2O5EJ6QS.js} +4440 -3042
- package/dist/chunk-2O5EJ6QS.js.map +1 -0
- package/dist/chunk-6WCIL3H2.js +517 -0
- package/dist/chunk-6WCIL3H2.js.map +1 -0
- package/dist/{chunk-WVE3F724.js → chunk-73FQVITT.js} +21 -4
- package/dist/chunk-73FQVITT.js.map +1 -0
- package/dist/{chunk-QC42MLAK.js → chunk-7AAO4UDQ.js} +4 -3
- package/dist/chunk-7AAO4UDQ.js.map +1 -0
- package/dist/{chunk-CYHJDKFB.js → chunk-F5QVQIBH.js} +172 -46
- package/dist/chunk-F5QVQIBH.js.map +1 -0
- package/dist/{chunk-FJW36PD7.js → chunk-GIPFF6FZ.js} +28 -24
- package/dist/chunk-GIPFF6FZ.js.map +1 -0
- package/dist/{chunk-6O6FWUDW.js → chunk-GSJAYYLR.js} +233 -195
- package/dist/chunk-GSJAYYLR.js.map +1 -0
- package/dist/{chunk-MPNSO7E6.js → chunk-J5BPHEDT.js} +2 -2
- package/dist/chunk-KR7WYHVF.js +195 -0
- package/dist/chunk-KR7WYHVF.js.map +1 -0
- package/dist/{chunk-DMMZSZTN.js → chunk-LUG7E6BL.js} +60 -16
- package/dist/chunk-LUG7E6BL.js.map +1 -0
- package/dist/chunk-LXJMINS6.js +587 -0
- package/dist/chunk-LXJMINS6.js.map +1 -0
- package/dist/{chunk-U7KURWW3.js → chunk-PT4EENB3.js} +244 -52
- package/dist/chunk-PT4EENB3.js.map +1 -0
- package/dist/{chunk-XAU7QFG3.js → chunk-Q6TCT7ZJ.js} +68 -256
- package/dist/chunk-Q6TCT7ZJ.js.map +1 -0
- package/dist/{chunk-ZKNUMH2M.js → chunk-XLFOXQKZ.js} +13 -11
- package/dist/chunk-XLFOXQKZ.js.map +1 -0
- package/dist/{chunk-M62XY4NC.js → chunk-XY6LZQES.js} +235 -108
- package/dist/chunk-XY6LZQES.js.map +1 -0
- package/dist/{createTrueFoundryServer-CmZnBh_l.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +8 -5
- package/dist/index.d.ts +316 -94
- package/dist/index.js +65 -488
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +36 -13
- package/dist/plugins/trueforge-agent-server-adapter/index.js +69 -34
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -4
- package/dist/AgentCodeSnippets-NZOFJE57.js.map +0 -1
- package/dist/AgentMetricChart-JPU3MFQ2.js +0 -15
- package/dist/AgentSessionEventTimeline-26Z6IB3B.js.map +0 -1
- package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js.map +0 -1
- package/dist/AgentSessions-3MPDZASK.js.map +0 -1
- package/dist/ConnectorSettings-MXFRWWR6.js.map +0 -1
- package/dist/DrawerLayout-JR3O6RRB.js.map +0 -1
- package/dist/ModelSettings-G7IFNC2Y.js.map +0 -1
- package/dist/OpenUiFenceBlock-2TV5TQ6P.js +0 -9
- package/dist/SandboxSettings-NXAANMAX.js.map +0 -1
- package/dist/SchedulesPage-KKLUDO6B.js +0 -15
- package/dist/ShellRouteSync-CEBETGEJ.js.map +0 -1
- package/dist/SidebarLayout-A2HJPPHS.js.map +0 -1
- package/dist/SkillSettings-FGGMSUNO.js.map +0 -1
- package/dist/chunk-2XPPBEYF.js +0 -74
- package/dist/chunk-2XPPBEYF.js.map +0 -1
- package/dist/chunk-6O6FWUDW.js.map +0 -1
- package/dist/chunk-7Z2C2K7F.js +0 -578
- package/dist/chunk-7Z2C2K7F.js.map +0 -1
- package/dist/chunk-CYHJDKFB.js.map +0 -1
- package/dist/chunk-DMMZSZTN.js.map +0 -1
- package/dist/chunk-FJW36PD7.js.map +0 -1
- package/dist/chunk-M62XY4NC.js.map +0 -1
- package/dist/chunk-QC42MLAK.js.map +0 -1
- package/dist/chunk-SFZNIO6U.js +0 -18
- package/dist/chunk-SFZNIO6U.js.map +0 -1
- package/dist/chunk-U7KURWW3.js.map +0 -1
- package/dist/chunk-WVE3F724.js.map +0 -1
- package/dist/chunk-XAU7QFG3.js.map +0 -1
- package/dist/chunk-ZKNUMH2M.js.map +0 -1
- package/dist/chunk-ZTMKFZQ3.js.map +0 -1
- /package/dist/{AgentMetricChart-JPU3MFQ2.js.map → AgentMetricChart-YWJYVYYA.js.map} +0 -0
- /package/dist/{AgentOverview-EEBHJC32.js.map → AgentOverview-VF74XC7I.js.map} +0 -0
- /package/dist/{DockLayout-LM4AFMFY.js.map → DockLayout-F44RWGEY.js.map} +0 -0
- /package/dist/{OpenUiFenceBlock-2TV5TQ6P.js.map → OpenUiFenceBlock-4ROX3G4X.js.map} +0 -0
- /package/dist/{SchedulesPage-KKLUDO6B.js.map → SchedulesPage-TMOTK6DR.js.map} +0 -0
- /package/dist/{SettingsBuilder-L34IQ56S.js.map → SettingsBuilder-GISAH2WU.js.map} +0 -0
- /package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js.map → TrueForgeUIWithRouter-6VCR7ES3.js.map} +0 -0
- /package/dist/{WidgetLayout-6QM45OQQ.js.map → WidgetLayout-RKBSN2FZ.js.map} +0 -0
- /package/dist/{chunk-MPNSO7E6.js.map → chunk-J5BPHEDT.js.map} +0 -0
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
buildTimelineAxisTicks,
|
|
8
8
|
formatCostUsd,
|
|
9
9
|
formatDurationMs,
|
|
10
|
+
formatTimelineAxisDuration,
|
|
10
11
|
formatTimelineDuration,
|
|
11
12
|
formatTokenCount,
|
|
12
13
|
getActiveTimelineMs,
|
|
@@ -19,26 +20,31 @@ import {
|
|
|
19
20
|
getTimelineHoverTargetId,
|
|
20
21
|
getTimelineLayout,
|
|
21
22
|
getTimelineRange,
|
|
23
|
+
groupCoincidentTimelineMarkers,
|
|
22
24
|
groupOverlappingToolCalls,
|
|
23
|
-
|
|
25
|
+
mergeOverlappingSubAgentSegments,
|
|
26
|
+
roundDurationMsToSecond,
|
|
24
27
|
useThemeMode
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-2O5EJ6QS.js";
|
|
29
|
+
import "./chunk-KR7WYHVF.js";
|
|
30
|
+
import "./chunk-Q6TCT7ZJ.js";
|
|
31
|
+
import "./chunk-PT4EENB3.js";
|
|
29
32
|
import "./chunk-M6MHLVSO.js";
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
33
|
+
import "./chunk-J5BPHEDT.js";
|
|
34
|
+
import "./chunk-LXJMINS6.js";
|
|
32
35
|
|
|
33
36
|
// src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
|
|
34
37
|
import {
|
|
38
|
+
BarController,
|
|
35
39
|
BarElement,
|
|
36
40
|
Chart as ChartJS,
|
|
37
41
|
LinearScale,
|
|
42
|
+
PointElement,
|
|
43
|
+
ScatterController,
|
|
38
44
|
Tooltip
|
|
39
45
|
} from "chart.js";
|
|
40
46
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
41
|
-
import {
|
|
47
|
+
import { Chart } from "react-chartjs-2";
|
|
42
48
|
|
|
43
49
|
// src/atoms/agent-details/AgentSessionTimelineTooltip.tsx
|
|
44
50
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -70,6 +76,7 @@ function SessionTurnTooltip({
|
|
|
70
76
|
durationMs,
|
|
71
77
|
segments
|
|
72
78
|
}) {
|
|
79
|
+
const isDark = useThemeMode() === "dark";
|
|
73
80
|
return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-72 max-w-full overflow-auto text-xs text-text-primary", children: [
|
|
74
81
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
75
82
|
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: `Turn ${turnNumber}` }),
|
|
@@ -86,7 +93,7 @@ function SessionTurnTooltip({
|
|
|
86
93
|
"span",
|
|
87
94
|
{
|
|
88
95
|
className: "size-1.5 shrink-0 rounded-full",
|
|
89
|
-
style: { backgroundColor: getSessionEventColor(segment.type) }
|
|
96
|
+
style: { backgroundColor: getSessionEventColor(segment.type, isDark) }
|
|
90
97
|
}
|
|
91
98
|
),
|
|
92
99
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: label }),
|
|
@@ -107,6 +114,27 @@ function SessionToolCallGroupTooltip({ group }) {
|
|
|
107
114
|
] }, segment.id)) })
|
|
108
115
|
] });
|
|
109
116
|
}
|
|
117
|
+
function SessionMarkerGroupTooltip({ group }) {
|
|
118
|
+
const isDark = useThemeMode() === "dark";
|
|
119
|
+
const singleSegment = group.segments.length === 1 ? group.segments[0] : void 0;
|
|
120
|
+
if (singleSegment != null) return /* @__PURE__ */ jsx(SessionEventTooltip, { segment: singleSegment });
|
|
121
|
+
return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-80 max-w-full overflow-auto text-xs", children: [
|
|
122
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-text-secondary", children: "Events" }),
|
|
123
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border pt-1.5", children: group.segments.map((segment) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start gap-1.5 py-0.5", children: [
|
|
124
|
+
/* @__PURE__ */ jsx(
|
|
125
|
+
"span",
|
|
126
|
+
{
|
|
127
|
+
className: "mt-1 size-1.5 shrink-0 rounded-full",
|
|
128
|
+
style: { backgroundColor: getSessionEventColor(segment.type, isDark) }
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
132
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-text-secondary", children: getSessionEventTooltipHeading(segment.type) }),
|
|
133
|
+
/* @__PURE__ */ jsx("div", { className: "wrap-break-word font-medium text-text-primary", children: segment.description.trim() || segment.title })
|
|
134
|
+
] })
|
|
135
|
+
] }, segment.id)) })
|
|
136
|
+
] });
|
|
137
|
+
}
|
|
110
138
|
function SessionSubAgentGroupTooltip({ group }) {
|
|
111
139
|
return /* @__PURE__ */ jsxs("div", { className: "max-h-72 w-80 max-w-full overflow-auto text-xs", children: [
|
|
112
140
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
@@ -114,29 +142,30 @@ function SessionSubAgentGroupTooltip({ group }) {
|
|
|
114
142
|
/* @__PURE__ */ jsx("span", { className: "tabular-nums text-text-secondary", children: formatTimelineDuration(group.endMs - group.startMs) })
|
|
115
143
|
] }),
|
|
116
144
|
/* @__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) })
|
|
145
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium text-text-primary", children: group.segments.length === 1 ? segment.description || segment.title : `Sub-agent ${index + 1}: ${segment.description || segment.title}` }),
|
|
146
|
+
group.segments.length === 1 ? null : /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-text-secondary", children: formatTimelineDuration(segment.endMs - segment.startMs) })
|
|
119
147
|
] }, segment.id)) })
|
|
120
148
|
] });
|
|
121
149
|
}
|
|
122
150
|
|
|
123
151
|
// src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
|
|
124
152
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
125
|
-
ChartJS.register(
|
|
153
|
+
ChartJS.register(BarController, BarElement, LinearScale, PointElement, ScatterController, Tooltip);
|
|
126
154
|
var MARKER_PX = 4;
|
|
127
155
|
var TURN_GAP_PX = 12;
|
|
128
156
|
var END_PAD_PX = 12;
|
|
129
157
|
var BAR_RADIUS_PX = 2;
|
|
130
158
|
var ROW_GAP_PX = 8;
|
|
159
|
+
var MARKER_EVENT_GAP_PX = 2;
|
|
131
160
|
var OVERHEAD_PX = 30;
|
|
132
|
-
function rowCenters(heights,
|
|
161
|
+
function rowCenters({ heights, gaps }) {
|
|
133
162
|
const centers = [];
|
|
134
163
|
let offset = 0;
|
|
135
|
-
|
|
164
|
+
heights.forEach((height, index) => {
|
|
136
165
|
centers.push(offset + height / 2);
|
|
137
|
-
offset += height +
|
|
138
|
-
}
|
|
139
|
-
return { centers, band:
|
|
166
|
+
offset += height + (gaps[index] ?? 0);
|
|
167
|
+
});
|
|
168
|
+
return { centers, band: offset };
|
|
140
169
|
}
|
|
141
170
|
function eventOrder(type) {
|
|
142
171
|
if (type === "sub_agent") return 0;
|
|
@@ -159,8 +188,8 @@ function AgentSessionEventTimelineChart({
|
|
|
159
188
|
const isDark = mode === "dark";
|
|
160
189
|
const axis = isDark ? "#8c8c92" : "#71717a";
|
|
161
190
|
const grid = isDark ? "#27272a" : "#e4e4e7";
|
|
162
|
-
const turnFill = isDark ? "#3f3f46" : "#
|
|
163
|
-
const turnHover = isDark ? "#52525b" : "#
|
|
191
|
+
const turnFill = isDark ? "#3f3f46" : "#E0ECFD";
|
|
192
|
+
const turnHover = isDark ? "#52525b" : "#E0ECFD";
|
|
164
193
|
const wrapperRef = useRef(null);
|
|
165
194
|
const [widthPx, setWidthPx] = useState(0);
|
|
166
195
|
const [overheadPx, setOverheadPx] = useState(OVERHEAD_PX);
|
|
@@ -199,17 +228,22 @@ function AgentSessionEventTimelineChart({
|
|
|
199
228
|
window.removeEventListener("resize", refreshTooltipAnchor);
|
|
200
229
|
};
|
|
201
230
|
}, [refreshTooltipAnchor, tooltipTarget]);
|
|
202
|
-
const
|
|
231
|
+
const segmentTotalMs = Math.max(0, ...segments.map((segment) => segment.endMs));
|
|
232
|
+
const activeTotalMs = Math.max(1, roundDurationMsToSecond(segmentTotalMs));
|
|
203
233
|
const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);
|
|
204
|
-
const
|
|
234
|
+
const activeTurnStartsMs = useMemo(
|
|
235
|
+
() => turnStartsMs.filter((startMs, index) => index === 0 || startMs <= activeTotalMs),
|
|
236
|
+
[activeTotalMs, turnStartsMs]
|
|
237
|
+
);
|
|
238
|
+
const gapCount = Math.max(0, activeTurnStartsMs.length - 1);
|
|
205
239
|
const scaleWidthPx = Math.max(widthPx / 2, widthPx - TURN_GAP_PX * gapCount - END_PAD_PX);
|
|
206
240
|
const msPerPx = activeTotalMs / Math.max(1, scaleWidthPx);
|
|
207
241
|
const turnGapMs = TURN_GAP_PX * msPerPx;
|
|
208
242
|
const totalMs = activeTotalMs + gapCount * turnGapMs;
|
|
209
243
|
const timelineMaxMs = totalMs + END_PAD_PX * msPerPx;
|
|
210
244
|
const timelineGaps = useMemo(
|
|
211
|
-
() =>
|
|
212
|
-
[
|
|
245
|
+
() => activeTurnStartsMs.slice(1).map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),
|
|
246
|
+
[activeTurnStartsMs, turnGapMs]
|
|
213
247
|
);
|
|
214
248
|
const visibleSegments = useMemo(
|
|
215
249
|
() => segments.flatMap((segment) => {
|
|
@@ -219,6 +253,8 @@ function AgentSessionEventTimelineChart({
|
|
|
219
253
|
}),
|
|
220
254
|
[hiddenTypes, segments, turnGapMs, turnOrdinals]
|
|
221
255
|
);
|
|
256
|
+
const markerGroups = useMemo(() => groupCoincidentTimelineMarkers(visibleSegments), [visibleSegments]);
|
|
257
|
+
const durationSegments = useMemo(() => visibleSegments.filter((segment) => !segment.isMarker), [visibleSegments]);
|
|
222
258
|
const turnBars = useMemo(
|
|
223
259
|
() => turnRanges.length < 2 ? [] : turnRanges.map((range) => ({
|
|
224
260
|
...range,
|
|
@@ -230,24 +266,23 @@ function AgentSessionEventTimelineChart({
|
|
|
230
266
|
[msPerPx, turnGapMs, turnRanges]
|
|
231
267
|
);
|
|
232
268
|
const subAgentSegments = useMemo(
|
|
233
|
-
() =>
|
|
234
|
-
[
|
|
269
|
+
() => durationSegments.filter((segment) => segment.type === "sub_agent"),
|
|
270
|
+
[durationSegments]
|
|
235
271
|
);
|
|
236
|
-
const mainSubAgents = useMemo(() =>
|
|
272
|
+
const mainSubAgents = useMemo(() => mergeOverlappingSubAgentSegments(subAgentSegments), [subAgentSegments]);
|
|
237
273
|
const subAgentGroups = useMemo(
|
|
238
274
|
() => getSubAgentHoverGroups({ bars: mainSubAgents, subAgentSegments }),
|
|
239
275
|
[mainSubAgents, subAgentSegments]
|
|
240
276
|
);
|
|
241
277
|
const subAgentLanes = useMemo(
|
|
242
|
-
() => getSubAgentLanes({ subAgentSegments, threadSegments:
|
|
243
|
-
[msPerPx, subAgentSegments
|
|
278
|
+
() => getSubAgentLanes({ subAgentSegments, threadSegments: durationSegments, minWidthMs: MARKER_PX * msPerPx }),
|
|
279
|
+
[durationSegments, msPerPx, subAgentSegments]
|
|
244
280
|
);
|
|
245
281
|
const mainCandidates = useMemo(() => {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
(segment) => segment.threadId === MAIN_THREAD_ID || segment.type === "sub_agent" && kept.has(segment.id)
|
|
282
|
+
return [...durationSegments.filter((segment) => segment.threadId === MAIN_THREAD_ID), ...mainSubAgents].sort(
|
|
283
|
+
(left, right) => left.startMs - right.startMs || left.endMs - right.endMs
|
|
249
284
|
);
|
|
250
|
-
}, [
|
|
285
|
+
}, [durationSegments, mainSubAgents]);
|
|
251
286
|
const toolCallGroups = useMemo(
|
|
252
287
|
() => groupOverlappingToolCalls(mainCandidates.filter((segment) => segment.type === "tool_call")).filter(
|
|
253
288
|
(group) => group.segments.length > 1
|
|
@@ -264,14 +299,20 @@ function AgentSessionEventTimelineChart({
|
|
|
264
299
|
);
|
|
265
300
|
const laneCount = subAgentLanes.reduce((count, lane) => Math.max(count, lane.lane + 1), 0);
|
|
266
301
|
const hasTurnRow = turnBars.length > 0;
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
[hasTurnRow, laneCount]
|
|
271
|
-
|
|
302
|
+
const markerRow = hasTurnRow ? 1 : 0;
|
|
303
|
+
const eventRow = markerRow + 1;
|
|
304
|
+
const { centers, band } = useMemo(() => {
|
|
305
|
+
const heights = [...hasTurnRow ? [16] : [], 10, 28, ...Array.from({ length: laneCount }, () => 12)];
|
|
306
|
+
const gaps = heights.map((_, index) => {
|
|
307
|
+
if (index === heights.length - 1) return 0;
|
|
308
|
+
return index === markerRow ? MARKER_EVENT_GAP_PX : ROW_GAP_PX;
|
|
309
|
+
});
|
|
310
|
+
return rowCenters({ heights, gaps });
|
|
311
|
+
}, [hasTurnRow, laneCount, markerRow]);
|
|
272
312
|
const chartTargets = useMemo(
|
|
273
313
|
() => [
|
|
274
314
|
...turnBars.map((bar) => ({ type: TIMELINE_TYPE.turn, bar })),
|
|
315
|
+
...markerGroups.map((group) => ({ type: TIMELINE_TYPE.markerGroup, group })),
|
|
275
316
|
...subAgentLanes.flatMap(
|
|
276
317
|
(lane) => lane.segments.map((segment) => ({ type: TIMELINE_TYPE.event, segment }))
|
|
277
318
|
),
|
|
@@ -282,7 +323,7 @@ function AgentSessionEventTimelineChart({
|
|
|
282
323
|
}),
|
|
283
324
|
...toolCallGroups.map((group) => ({ type: TIMELINE_TYPE.toolCallGroup, group }))
|
|
284
325
|
],
|
|
285
|
-
[mainEventSegments, subAgentGroups, subAgentLanes, toolCallGroups, turnBars]
|
|
326
|
+
[mainEventSegments, markerGroups, subAgentGroups, subAgentLanes, toolCallGroups, turnBars]
|
|
286
327
|
);
|
|
287
328
|
const barDataset = ({
|
|
288
329
|
label,
|
|
@@ -321,14 +362,31 @@ function AgentSessionEventTimelineChart({
|
|
|
321
362
|
thickness: 16
|
|
322
363
|
})
|
|
323
364
|
),
|
|
365
|
+
...markerGroups.map((group) => {
|
|
366
|
+
const type = group.segments.length === 1 ? group.segments[0]?.type : "system";
|
|
367
|
+
const color = getSessionEventColor(type ?? "system", isDark);
|
|
368
|
+
return {
|
|
369
|
+
type: "scatter",
|
|
370
|
+
label: group.segments.map((segment) => getSessionEventLabel(segment.type)).join(", "),
|
|
371
|
+
data: [{ x: group.startMs, y: centers[markerRow] ?? 0 }],
|
|
372
|
+
pointStyle: "rectRot",
|
|
373
|
+
pointRadius: 5,
|
|
374
|
+
pointHoverRadius: 6,
|
|
375
|
+
clip: false,
|
|
376
|
+
backgroundColor: color,
|
|
377
|
+
hoverBackgroundColor: getSessionEventHoverColor(type ?? "system", isDark),
|
|
378
|
+
borderWidth: 0,
|
|
379
|
+
order: 0
|
|
380
|
+
};
|
|
381
|
+
}),
|
|
324
382
|
...subAgentLanes.flatMap(
|
|
325
383
|
(lane) => lane.segments.map(
|
|
326
384
|
(segment) => barDataset({
|
|
327
385
|
label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,
|
|
328
386
|
range: segment,
|
|
329
387
|
y: centers[eventRow + 1 + lane.lane] ?? 0,
|
|
330
|
-
color: getSessionEventColor(segment.type),
|
|
331
|
-
hover: getSessionEventHoverColor(segment.type),
|
|
388
|
+
color: getSessionEventColor(segment.type, isDark),
|
|
389
|
+
hover: getSessionEventHoverColor(segment.type, isDark),
|
|
332
390
|
thickness: 12,
|
|
333
391
|
order: eventOrder(segment.type),
|
|
334
392
|
inflateAmount: 0.5
|
|
@@ -340,8 +398,8 @@ function AgentSessionEventTimelineChart({
|
|
|
340
398
|
label: `${getSessionEventLabel(segment.type)}: ${segment.title}`,
|
|
341
399
|
range: segment,
|
|
342
400
|
y: centers[eventRow] ?? 0,
|
|
343
|
-
color: getSessionEventColor(segment.type),
|
|
344
|
-
hover: getSessionEventHoverColor(segment.type),
|
|
401
|
+
color: getSessionEventColor(segment.type, isDark),
|
|
402
|
+
hover: getSessionEventHoverColor(segment.type, isDark),
|
|
345
403
|
thickness: 28,
|
|
346
404
|
order: eventOrder(segment.type),
|
|
347
405
|
inflateAmount: 0.5
|
|
@@ -352,8 +410,8 @@ function AgentSessionEventTimelineChart({
|
|
|
352
410
|
label: "Parallel tool calls",
|
|
353
411
|
range: group,
|
|
354
412
|
y: centers[eventRow] ?? 0,
|
|
355
|
-
color: getSessionEventColor("tool_call"),
|
|
356
|
-
hover: getSessionEventHoverColor("tool_call"),
|
|
413
|
+
color: getSessionEventColor("tool_call", isDark),
|
|
414
|
+
hover: getSessionEventHoverColor("tool_call", isDark),
|
|
357
415
|
thickness: 28,
|
|
358
416
|
order: eventOrder("tool_call"),
|
|
359
417
|
inflateAmount: 0.5
|
|
@@ -361,7 +419,19 @@ function AgentSessionEventTimelineChart({
|
|
|
361
419
|
)
|
|
362
420
|
]
|
|
363
421
|
}),
|
|
364
|
-
[
|
|
422
|
+
[
|
|
423
|
+
centers,
|
|
424
|
+
eventRow,
|
|
425
|
+
isDark,
|
|
426
|
+
mainEventSegments,
|
|
427
|
+
markerGroups,
|
|
428
|
+
markerRow,
|
|
429
|
+
subAgentLanes,
|
|
430
|
+
toolCallGroups,
|
|
431
|
+
turnBars,
|
|
432
|
+
turnFill,
|
|
433
|
+
turnHover
|
|
434
|
+
]
|
|
365
435
|
);
|
|
366
436
|
const turnLabelPlugin = useMemo(
|
|
367
437
|
() => ({
|
|
@@ -436,21 +506,17 @@ function AgentSessionEventTimelineChart({
|
|
|
436
506
|
grid: { color: grid },
|
|
437
507
|
border: { color: grid },
|
|
438
508
|
afterBuildTicks: (scale) => {
|
|
439
|
-
scale.ticks = buildTimelineAxisTicks({
|
|
440
|
-
ticks: scale.ticks,
|
|
441
|
-
totalMs,
|
|
442
|
-
timelineMaxMs
|
|
443
|
-
});
|
|
509
|
+
scale.ticks = buildTimelineAxisTicks({ activeTotalMs, turnStartsMs: activeTurnStartsMs, turnGapMs });
|
|
444
510
|
},
|
|
445
511
|
ticks: {
|
|
446
512
|
color: axis,
|
|
513
|
+
align: "inner",
|
|
447
514
|
autoSkip: false,
|
|
448
|
-
includeBounds:
|
|
515
|
+
includeBounds: false,
|
|
449
516
|
maxTicksLimit: 9,
|
|
450
|
-
stepSize: timelineMaxMs / 8,
|
|
451
517
|
callback: (value) => {
|
|
452
518
|
const timelineMs = Number(value);
|
|
453
|
-
return timelineMs <= totalMs ?
|
|
519
|
+
return timelineMs <= totalMs ? formatTimelineAxisDuration(getActiveTimelineMs(timelineMs, timelineGaps)) : "";
|
|
454
520
|
}
|
|
455
521
|
}
|
|
456
522
|
},
|
|
@@ -465,7 +531,20 @@ function AgentSessionEventTimelineChart({
|
|
|
465
531
|
}
|
|
466
532
|
}
|
|
467
533
|
}),
|
|
468
|
-
[
|
|
534
|
+
[
|
|
535
|
+
activeTotalMs,
|
|
536
|
+
activeTurnStartsMs,
|
|
537
|
+
axis,
|
|
538
|
+
band,
|
|
539
|
+
chartTargets,
|
|
540
|
+
grid,
|
|
541
|
+
onSelectTurn,
|
|
542
|
+
refreshTooltipAnchor,
|
|
543
|
+
timelineGaps,
|
|
544
|
+
timelineMaxMs,
|
|
545
|
+
totalMs,
|
|
546
|
+
turnGapMs
|
|
547
|
+
]
|
|
469
548
|
);
|
|
470
549
|
const tooltipTurn = tooltipTarget?.type === TIMELINE_TYPE.turn ? turns[tooltipTarget.bar.turnIndex] : void 0;
|
|
471
550
|
const containerStyle = useMemo(() => ({ height: band + overheadPx }), [band, overheadPx]);
|
|
@@ -483,7 +562,7 @@ function AgentSessionEventTimelineChart({
|
|
|
483
562
|
segment: tooltipTarget.segment,
|
|
484
563
|
subAgentLabel: tooltipTarget.segment.type === "sub_agent" ? void 0 : subAgentLanes.find((lane) => lane.threadId === tooltipTarget.segment.threadId)?.track.description
|
|
485
564
|
}
|
|
486
|
-
) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? /* @__PURE__ */ jsx2(SessionToolCallGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? /* @__PURE__ */ jsx2(SessionSubAgentGroupTooltip, { group: tooltipTarget.group }) : null;
|
|
565
|
+
) : tooltipTarget?.type === TIMELINE_TYPE.toolCallGroup ? /* @__PURE__ */ jsx2(SessionToolCallGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.markerGroup ? /* @__PURE__ */ jsx2(SessionMarkerGroupTooltip, { group: tooltipTarget.group }) : tooltipTarget?.type === TIMELINE_TYPE.subAgentGroup ? /* @__PURE__ */ jsx2(SessionSubAgentGroupTooltip, { group: tooltipTarget.group }) : null;
|
|
487
566
|
return /* @__PURE__ */ jsx2("div", { ref: wrapperRef, className: "w-full", "data-slot": "agent-session-event-timeline-chart", children: /* @__PURE__ */ jsx2(
|
|
488
567
|
LightTooltip,
|
|
489
568
|
{
|
|
@@ -494,11 +573,19 @@ function AgentSessionEventTimelineChart({
|
|
|
494
573
|
open: tooltipTarget != null && tooltipContent != null,
|
|
495
574
|
className: "max-w-[min(25rem,calc(100vw-1rem))] whitespace-normal",
|
|
496
575
|
anchor: tooltipAnchor,
|
|
497
|
-
children: /* @__PURE__ */ jsx2("div", { className: "w-full", style: containerStyle, onMouseLeave: clearTooltip, children: /* @__PURE__ */ jsx2(
|
|
576
|
+
children: /* @__PURE__ */ jsx2("div", { className: "w-full", style: containerStyle, onMouseLeave: clearTooltip, children: /* @__PURE__ */ jsx2(
|
|
577
|
+
Chart,
|
|
578
|
+
{
|
|
579
|
+
type: "bar",
|
|
580
|
+
data: chartData,
|
|
581
|
+
options: chartOptions,
|
|
582
|
+
plugins: [turnLabelPlugin, overheadPlugin]
|
|
583
|
+
}
|
|
584
|
+
) })
|
|
498
585
|
}
|
|
499
586
|
) });
|
|
500
587
|
}
|
|
501
588
|
export {
|
|
502
589
|
AgentSessionEventTimelineChart
|
|
503
590
|
};
|
|
504
|
-
//# sourceMappingURL=AgentSessionEventTimelineChart-
|
|
591
|
+
//# sourceMappingURL=AgentSessionEventTimelineChart-27CQF6FX.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 BarController,\n BarElement,\n Chart as ChartJS,\n LinearScale,\n PointElement,\n ScatterController,\n Tooltip,\n type ChartData,\n type ChartDataset,\n type ChartOptions,\n type Plugin,\n} from 'chart.js';\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType, type CSSProperties } from 'react';\nimport { Chart } from 'react-chartjs-2';\n\nimport { useThemeMode } from '../../theme/SlotsProvider.js';\nimport { roundDurationMsToSecond } from '../../utils/sessionDisplayFormat.js';\nimport {\n getSessionEventColor,\n getSessionEventHoverColor,\n getSessionEventLabel,\n MAIN_THREAD_ID,\n type SessionEventTimelineSegment,\n} from '../../utils/sessionEventTimeline.js';\nimport {\n buildTimelineAxisTicks,\n formatTimelineAxisDuration,\n getActiveTimelineMs,\n getSubAgentHoverGroups,\n getSubAgentLanes,\n getTimelineHoverTargetId,\n getTimelineLayout,\n getTimelineRange,\n groupCoincidentTimelineMarkers,\n groupOverlappingToolCalls,\n mergeOverlappingSubAgentSegments,\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 SessionMarkerGroupTooltip,\n SessionSubAgentGroupTooltip,\n SessionToolCallGroupTooltip,\n SessionTurnTooltip,\n} from './AgentSessionTimelineTooltip.js';\nimport type { AgentSessionEventTimelineChartProps } from './types.js';\n\nChartJS.register(BarController, BarElement, LinearScale, PointElement, ScatterController, 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 MARKER_EVENT_GAP_PX = 2;\nconst OVERHEAD_PX = 30;\n\ntype BarPoint = { x: [number, number]; y: number };\ntype MarkerPoint = { x: number; y: number };\ntype TimelineChartType = 'bar' | 'scatter';\n\nfunction rowCenters({ heights, gaps }: { heights: number[]; gaps: number[] }): { centers: number[]; band: number } {\n const centers: number[] = [];\n let offset = 0;\n heights.forEach((height, index) => {\n centers.push(offset + height / 2);\n offset += height + (gaps[index] ?? 0);\n });\n return { centers, band: offset };\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' : '#E0ECFD';\n const turnHover = isDark ? '#52525b' : '#E0ECFD';\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 segmentTotalMs = Math.max(0, ...segments.map(segment => segment.endMs));\n const activeTotalMs = Math.max(1, roundDurationMsToSecond(segmentTotalMs));\n const { turnStartsMs, turnOrdinals, turnRanges } = useMemo(() => getTimelineLayout(segments), [segments]);\n const activeTurnStartsMs = useMemo(\n () => turnStartsMs.filter((startMs, index) => index === 0 || startMs <= activeTotalMs),\n [activeTotalMs, turnStartsMs],\n );\n const gapCount = Math.max(0, activeTurnStartsMs.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 activeTurnStartsMs\n .slice(1)\n .map((startMs, index) => ({ startMs: startMs + index * turnGapMs, endMs: startMs + (index + 1) * turnGapMs })),\n [activeTurnStartsMs, turnGapMs],\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 markerGroups = useMemo(() => groupCoincidentTimelineMarkers(visibleSegments), [visibleSegments]);\n const durationSegments = useMemo(() => visibleSegments.filter(segment => !segment.isMarker), [visibleSegments]);\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 () => durationSegments.filter(segment => segment.type === 'sub_agent'),\n [durationSegments],\n );\n const mainSubAgents = useMemo(() => mergeOverlappingSubAgentSegments(subAgentSegments), [subAgentSegments]);\n const subAgentGroups = useMemo(\n () => getSubAgentHoverGroups({ bars: mainSubAgents, subAgentSegments }),\n [mainSubAgents, subAgentSegments],\n );\n const subAgentLanes = useMemo(\n () => getSubAgentLanes({ subAgentSegments, threadSegments: durationSegments, minWidthMs: MARKER_PX * msPerPx }),\n [durationSegments, msPerPx, subAgentSegments],\n );\n const mainCandidates = useMemo(() => {\n return [...durationSegments.filter(segment => segment.threadId === MAIN_THREAD_ID), ...mainSubAgents].sort(\n (left, right) => left.startMs - right.startMs || left.endMs - right.endMs,\n );\n }, [durationSegments, mainSubAgents]);\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 markerRow = hasTurnRow ? 1 : 0;\n const eventRow = markerRow + 1;\n const { centers, band } = useMemo(() => {\n const heights = [...(hasTurnRow ? [16] : []), 10, 28, ...Array.from({ length: laneCount }, () => 12)];\n const gaps = heights.map((_, index) => {\n if (index === heights.length - 1) return 0;\n return index === markerRow ? MARKER_EVENT_GAP_PX : ROW_GAP_PX;\n });\n return rowCenters({ heights, gaps });\n }, [hasTurnRow, laneCount, markerRow]);\n\n const chartTargets = useMemo<Array<TimelineHoverTarget | null>>(\n () => [\n ...turnBars.map((bar): TimelineHoverTarget => ({ type: TIMELINE_TYPE.turn, bar })),\n ...markerGroups.map((group): TimelineHoverTarget => ({ type: TIMELINE_TYPE.markerGroup, group })),\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, markerGroups, 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<TimelineChartType, Array<BarPoint | MarkerPoint>, 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 ...markerGroups.map(group => {\n const type = group.segments.length === 1 ? group.segments[0]?.type : 'system';\n const color = getSessionEventColor(type ?? 'system', isDark);\n return {\n type: 'scatter' as const,\n label: group.segments.map(segment => getSessionEventLabel(segment.type)).join(', '),\n data: [{ x: group.startMs, y: centers[markerRow] ?? 0 }] satisfies MarkerPoint[],\n pointStyle: 'rectRot' as const,\n pointRadius: 5,\n pointHoverRadius: 6,\n clip: false,\n backgroundColor: color,\n hoverBackgroundColor: getSessionEventHoverColor(type ?? 'system', isDark),\n borderWidth: 0,\n order: 0,\n } satisfies ChartDataset<'scatter', MarkerPoint[]>;\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, isDark),\n hover: getSessionEventHoverColor(segment.type, isDark),\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, isDark),\n hover: getSessionEventHoverColor(segment.type, isDark),\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', isDark),\n hover: getSessionEventHoverColor('tool_call', isDark),\n thickness: 28,\n order: eventOrder('tool_call'),\n inflateAmount: 0.5,\n }),\n ),\n ],\n }),\n [\n centers,\n eventRow,\n isDark,\n mainEventSegments,\n markerGroups,\n markerRow,\n subAgentLanes,\n toolCallGroups,\n turnBars,\n turnFill,\n turnHover,\n ],\n );\n\n const turnLabelPlugin = useMemo<Plugin<TimelineChartType>>(\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<TimelineChartType>>(\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<TimelineChartType>>(\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({ activeTotalMs, turnStartsMs: activeTurnStartsMs, turnGapMs });\n },\n ticks: {\n color: axis,\n align: 'inner',\n autoSkip: false,\n includeBounds: false,\n maxTicksLimit: 9,\n callback: value => {\n const timelineMs = Number(value);\n return timelineMs <= totalMs\n ? formatTimelineAxisDuration(getActiveTimelineMs(timelineMs, timelineGaps))\n : '';\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 [\n activeTotalMs,\n activeTurnStartsMs,\n axis,\n band,\n chartTargets,\n grid,\n onSelectTurn,\n refreshTooltipAnchor,\n timelineGaps,\n timelineMaxMs,\n totalMs,\n turnGapMs,\n ],\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.markerGroup ? (\n <SessionMarkerGroupTooltip 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 <Chart<TimelineChartType, Array<BarPoint | MarkerPoint>, string>\n type=\"bar\"\n data={chartData}\n options={chartOptions}\n plugins={[turnLabelPlugin, overheadPlugin]}\n />\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 { useThemeMode } from '../../theme/SlotsProvider.js';\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 {\n TimelineMarkerGroup,\n TimelineSubAgentGroup,\n TimelineToolCallGroup,\n} 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 const isDark = useThemeMode() === 'dark';\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, isDark) }}\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 SessionMarkerGroupTooltip({ group }: { group: TimelineMarkerGroup }) {\n const isDark = useThemeMode() === 'dark';\n const singleSegment = group.segments.length === 1 ? group.segments[0] : undefined;\n if (singleSegment != null) return <SessionEventTooltip segment={singleSegment} />;\n\n return (\n <div className=\"max-h-72 w-80 max-w-full overflow-auto text-xs\">\n <span className=\"font-medium text-text-secondary\">Events</span>\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 min-w-0 items-start gap-1.5 py-0.5\">\n <span\n className=\"mt-1 size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: getSessionEventColor(segment.type, isDark) }}\n />\n <div className=\"min-w-0\">\n <div className=\"font-medium text-text-secondary\">{getSessionEventTooltipHeading(segment.type)}</div>\n <div className=\"wrap-break-word font-medium text-text-primary\">\n {segment.description.trim() || segment.title}\n </div>\n </div>\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 {group.segments.length === 1\n ? segment.description || segment.title\n : `Sub-agent ${index + 1}: ${segment.description || segment.title}`}\n </span>\n {group.segments.length === 1 ? null : (\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {formatTimelineDuration(segment.endMs - segment.startMs)}\n </span>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx"]}
|
|
@@ -1,41 +1,55 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
buildSessionResumeHref
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-73FQVITT.js";
|
|
5
5
|
import {
|
|
6
6
|
useOptionalResolvedRoutes
|
|
7
7
|
} from "./chunk-Y6S4OVVQ.js";
|
|
8
|
-
import {
|
|
9
|
-
drainListPages
|
|
10
|
-
} from "./chunk-SFZNIO6U.js";
|
|
11
8
|
import {
|
|
12
9
|
sessionIsCreateAgent
|
|
13
10
|
} from "./chunk-RDXBMTP5.js";
|
|
14
11
|
import {
|
|
15
12
|
EmptyScreen,
|
|
16
13
|
Skeleton,
|
|
14
|
+
useResourcePermissions,
|
|
17
15
|
useSessionShareSearch,
|
|
18
16
|
useSlot
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-2O5EJ6QS.js";
|
|
18
|
+
import "./chunk-KR7WYHVF.js";
|
|
21
19
|
import {
|
|
22
20
|
Icon
|
|
23
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-Q6TCT7ZJ.js";
|
|
24
22
|
import {
|
|
25
23
|
sessionTimeRangeFromCreatedAt,
|
|
26
24
|
useAgentSessionsServer,
|
|
27
25
|
useOptionalShellMode,
|
|
28
26
|
useServer
|
|
29
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-PT4EENB3.js";
|
|
30
28
|
import "./chunk-M6MHLVSO.js";
|
|
31
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-J5BPHEDT.js";
|
|
32
30
|
import {
|
|
33
31
|
cn
|
|
34
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-LXJMINS6.js";
|
|
35
33
|
|
|
36
34
|
// src/atoms/agent-details/AgentSessions.tsx
|
|
37
35
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
38
36
|
import { Group, Panel, Separator } from "react-resizable-panels";
|
|
37
|
+
|
|
38
|
+
// src/utils/drainListPages.ts
|
|
39
|
+
async function drainListPages({
|
|
40
|
+
fetchPage
|
|
41
|
+
}) {
|
|
42
|
+
const items = [];
|
|
43
|
+
let pageToken;
|
|
44
|
+
do {
|
|
45
|
+
const page = await fetchPage(pageToken);
|
|
46
|
+
items.push(...page.data);
|
|
47
|
+
pageToken = page.nextPageToken;
|
|
48
|
+
} while (pageToken != null && pageToken.length > 0);
|
|
49
|
+
return items;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/atoms/agent-details/AgentSessions.tsx
|
|
39
53
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
40
54
|
function sessionTitle(entry) {
|
|
41
55
|
const title = entry.title?.trim();
|
|
@@ -47,12 +61,20 @@ function entryIsMutable(entry) {
|
|
|
47
61
|
}
|
|
48
62
|
return entry.agentName == null;
|
|
49
63
|
}
|
|
64
|
+
function entrySourceType(entry) {
|
|
65
|
+
return "sourceType" in entry && Reflect.get(entry, "sourceType") === "schedule" ? "schedule" : void 0;
|
|
66
|
+
}
|
|
50
67
|
function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
|
|
51
68
|
const sessionsServer = useAgentSessionsServer();
|
|
52
69
|
const chatServer = useServer();
|
|
53
70
|
const shell = useOptionalShellMode();
|
|
54
71
|
const routes = useOptionalResolvedRoutes();
|
|
55
72
|
const { sessionId: selectedSessionId, updateShareSearch } = useSessionShareSearch();
|
|
73
|
+
const { allows } = useResourcePermissions({
|
|
74
|
+
resourceType: "session",
|
|
75
|
+
resourceIds: selectedSessionId == null ? [] : [selectedSessionId]
|
|
76
|
+
});
|
|
77
|
+
const canResume = allows(selectedSessionId, "MANAGE");
|
|
56
78
|
const AgentSessionListRow = useSlot("AgentSessionListRow");
|
|
57
79
|
const AgentSessionDetailHeader = useSlot("AgentSessionDetailHeader");
|
|
58
80
|
const AgentSessionTimelineContainer = useSlot("AgentSessionTimelineContainer");
|
|
@@ -165,7 +187,7 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
|
|
|
165
187
|
const resumeLabel = resumeIsCreateAgent ? "Resume Agent building" : "Resume Chat";
|
|
166
188
|
const resumeHref = selectedSessionId != null && routes != null ? buildSessionResumeHref({ sessionId: selectedSessionId, routes }) : null;
|
|
167
189
|
const handleResume = () => {
|
|
168
|
-
if (selectedSessionId == null || shell == null) return;
|
|
190
|
+
if (!canResume || selectedSessionId == null || shell == null) return;
|
|
169
191
|
const agentName = detailSession?.agentName ?? selectedEntry?.agentName;
|
|
170
192
|
shell.openHistorySession({
|
|
171
193
|
sessionId: selectedSessionId,
|
|
@@ -199,6 +221,7 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
|
|
|
199
221
|
{
|
|
200
222
|
title: sessionTitle(entry),
|
|
201
223
|
agentName: entry.agentName ?? void 0,
|
|
224
|
+
sourceType: entrySourceType(entry),
|
|
202
225
|
lastActivityAt: entry.lastActivityAt,
|
|
203
226
|
metrics: entry.metrics,
|
|
204
227
|
active: entry.id === selectedSessionId,
|
|
@@ -253,6 +276,7 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
|
|
|
253
276
|
createdAt: detailSession?.createdAt ?? selectedEntry?.createdAt,
|
|
254
277
|
view: shareView,
|
|
255
278
|
onClose: clearSelectedSession,
|
|
279
|
+
canResume,
|
|
256
280
|
...resumeProps
|
|
257
281
|
}
|
|
258
282
|
),
|
|
@@ -272,4 +296,4 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
|
|
|
272
296
|
export {
|
|
273
297
|
AgentSessions
|
|
274
298
|
};
|
|
275
|
-
//# sourceMappingURL=AgentSessions-
|
|
299
|
+
//# sourceMappingURL=AgentSessions-4IVX2SGD.js.map
|