@mtharrison/loupe 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -12
- package/assets/screenshot1.png +0 -0
- package/assets/screenshot2.png +0 -0
- package/dist/client/app.css +365 -263
- package/dist/client/app.js +803 -648
- package/dist/index.d.ts +3 -2
- package/dist/index.js +330 -2
- package/dist/server.d.ts +1 -0
- package/dist/server.js +42 -11
- package/dist/session-nav.d.ts +10 -0
- package/dist/session-nav.js +91 -0
- package/dist/types.d.ts +18 -0
- package/examples/openai-multiturn-tools.js +399 -0
- package/package.json +3 -1
package/dist/client/app.js
CHANGED
|
@@ -20995,6 +20995,82 @@ var init_theme = __esm({
|
|
|
20995
20995
|
function deriveSessionNavItems(sessionNodes, traceById) {
|
|
20996
20996
|
return sessionNodes.map((node) => deriveSessionNavItem(node, traceById)).sort(compareSessionNavItems);
|
|
20997
20997
|
}
|
|
20998
|
+
function sortSessionNodesForNav(sessionNodes, traceById) {
|
|
20999
|
+
const itemById = new Map(
|
|
21000
|
+
sessionNodes.map((node) => [node.id, deriveSessionNavItem(node, traceById)])
|
|
21001
|
+
);
|
|
21002
|
+
return sessionNodes.slice().sort(
|
|
21003
|
+
(left, right) => compareSessionNavItems(
|
|
21004
|
+
itemById.get(left.id),
|
|
21005
|
+
itemById.get(right.id)
|
|
21006
|
+
)
|
|
21007
|
+
);
|
|
21008
|
+
}
|
|
21009
|
+
function findSessionNodePath(nodes, id, trail = []) {
|
|
21010
|
+
for (const node of nodes) {
|
|
21011
|
+
const nextTrail = [...trail, node];
|
|
21012
|
+
if (node.id === id) {
|
|
21013
|
+
return nextTrail;
|
|
21014
|
+
}
|
|
21015
|
+
const childTrail = findSessionNodePath(node.children, id, nextTrail);
|
|
21016
|
+
if (childTrail.length) {
|
|
21017
|
+
return childTrail;
|
|
21018
|
+
}
|
|
21019
|
+
}
|
|
21020
|
+
return [];
|
|
21021
|
+
}
|
|
21022
|
+
function findSessionNodeById(nodes, id) {
|
|
21023
|
+
return findSessionNodePath(nodes, id).at(-1) ?? null;
|
|
21024
|
+
}
|
|
21025
|
+
function getNewestTraceIdForNode(node) {
|
|
21026
|
+
if (!node?.traceIds.length) {
|
|
21027
|
+
return null;
|
|
21028
|
+
}
|
|
21029
|
+
if (typeof node.meta?.traceId === "string" && node.meta.traceId) {
|
|
21030
|
+
return node.meta.traceId;
|
|
21031
|
+
}
|
|
21032
|
+
return node.traceIds[0] || null;
|
|
21033
|
+
}
|
|
21034
|
+
function resolveSessionTreeSelection(sessionNodes, selectedNodeId, selectedTraceId) {
|
|
21035
|
+
const selectedNode = selectedNodeId ? findSessionNodeById(sessionNodes, selectedNodeId) : null;
|
|
21036
|
+
const selectedTraceNode = selectedTraceId ? findSessionNodeById(sessionNodes, `trace:${selectedTraceId}`) : null;
|
|
21037
|
+
const fallbackNode = selectedNode ?? selectedTraceNode ?? sessionNodes[0] ?? null;
|
|
21038
|
+
if (!fallbackNode) {
|
|
21039
|
+
return {
|
|
21040
|
+
selectedNodeId: null,
|
|
21041
|
+
selectedTraceId: null
|
|
21042
|
+
};
|
|
21043
|
+
}
|
|
21044
|
+
const nextSelectedNodeId = selectedNode?.id ?? fallbackNode.id;
|
|
21045
|
+
const nextSelectedTraceId = selectedTraceId && fallbackNode.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceIdForNode(fallbackNode);
|
|
21046
|
+
return {
|
|
21047
|
+
selectedNodeId: nextSelectedNodeId,
|
|
21048
|
+
selectedTraceId: nextSelectedTraceId
|
|
21049
|
+
};
|
|
21050
|
+
}
|
|
21051
|
+
function getDefaultExpandedSessionTreeNodeIds(sessionNodes, activeSessionId, selectedNodeId) {
|
|
21052
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
21053
|
+
const activeSession = (activeSessionId ? sessionNodes.find((node) => node.id === activeSessionId) ?? null : null) ?? sessionNodes[0] ?? null;
|
|
21054
|
+
if (!activeSession) {
|
|
21055
|
+
return expanded;
|
|
21056
|
+
}
|
|
21057
|
+
if (activeSession.children.length) {
|
|
21058
|
+
expanded.add(activeSession.id);
|
|
21059
|
+
}
|
|
21060
|
+
visitSessionTree(activeSession.children, (node) => {
|
|
21061
|
+
if (node.children.length && node.type === "actor") {
|
|
21062
|
+
expanded.add(node.id);
|
|
21063
|
+
}
|
|
21064
|
+
});
|
|
21065
|
+
if (selectedNodeId) {
|
|
21066
|
+
for (const node of findSessionNodePath([activeSession], selectedNodeId)) {
|
|
21067
|
+
if (node.children.length) {
|
|
21068
|
+
expanded.add(node.id);
|
|
21069
|
+
}
|
|
21070
|
+
}
|
|
21071
|
+
}
|
|
21072
|
+
return expanded;
|
|
21073
|
+
}
|
|
20998
21074
|
function deriveSessionNavItem(node, traceById) {
|
|
20999
21075
|
const traces = node.traceIds.map((traceId) => traceById.get(traceId)).filter((trace) => Boolean(trace));
|
|
21000
21076
|
const latestTrace = getLatestTrace(traces);
|
|
@@ -21110,6 +21186,12 @@ function formatCompactTimestamp(value) {
|
|
|
21110
21186
|
minute: "2-digit"
|
|
21111
21187
|
});
|
|
21112
21188
|
}
|
|
21189
|
+
function visitSessionTree(nodes, visitor) {
|
|
21190
|
+
for (const node of nodes) {
|
|
21191
|
+
visitor(node);
|
|
21192
|
+
visitSessionTree(node.children, visitor);
|
|
21193
|
+
}
|
|
21194
|
+
}
|
|
21113
21195
|
var init_session_nav = __esm({
|
|
21114
21196
|
"src/session-nav.ts"() {
|
|
21115
21197
|
}
|
|
@@ -21122,14 +21204,9 @@ function App() {
|
|
|
21122
21204
|
hierarchy: { filtered: 0, rootNodes: [], total: 0 },
|
|
21123
21205
|
traces: { filtered: 0, items: [], total: 0 }
|
|
21124
21206
|
});
|
|
21125
|
-
const [navMode, setNavMode] = (0, import_react3.useState)("sessions");
|
|
21126
21207
|
const [theme, setTheme] = (0, import_react3.useState)(() => resolvePreferredTheme());
|
|
21127
21208
|
const [eventsConnected, setEventsConnected] = (0, import_react3.useState)(false);
|
|
21128
21209
|
const [expandedNodeOverrides, setExpandedNodeOverrides] = (0, import_react3.useState)({});
|
|
21129
|
-
const [collapsedTraceGroups, setCollapsedTraceGroups] = (0, import_react3.useState)({});
|
|
21130
|
-
const [selectedSessionId, setSelectedSessionId] = (0, import_react3.useState)(
|
|
21131
|
-
null
|
|
21132
|
-
);
|
|
21133
21210
|
const [selectedNodeId, setSelectedNodeId] = (0, import_react3.useState)(null);
|
|
21134
21211
|
const [selectedTraceId, setSelectedTraceId] = (0, import_react3.useState)(null);
|
|
21135
21212
|
const [detail, setDetail] = (0, import_react3.useState)(null);
|
|
@@ -21194,9 +21271,6 @@ function App() {
|
|
|
21194
21271
|
(0, import_react3.startTransition)(() => {
|
|
21195
21272
|
setData({ traces, hierarchy });
|
|
21196
21273
|
setAllSessionCount(nextAllSessionCount);
|
|
21197
|
-
setSelectedSessionId(
|
|
21198
|
-
(current) => current ?? hierarchy.rootNodes[0]?.id ?? null
|
|
21199
|
-
);
|
|
21200
21274
|
});
|
|
21201
21275
|
} finally {
|
|
21202
21276
|
refreshInFlightRef.current = false;
|
|
@@ -21314,7 +21388,6 @@ function App() {
|
|
|
21314
21388
|
traces: { filtered: 0, items: [], total: 0 }
|
|
21315
21389
|
});
|
|
21316
21390
|
setAllSessionCount(0);
|
|
21317
|
-
setSelectedSessionId(null);
|
|
21318
21391
|
setSelectedNodeId(null);
|
|
21319
21392
|
setSelectedTraceId(null);
|
|
21320
21393
|
setDetail(null);
|
|
@@ -21373,75 +21446,61 @@ function App() {
|
|
|
21373
21446
|
() => getMaxDurationMs(traceItems),
|
|
21374
21447
|
[traceItems]
|
|
21375
21448
|
);
|
|
21376
|
-
const traceGroups = (0, import_react3.useMemo)(
|
|
21377
|
-
() => groupTracesForNav(traceItems),
|
|
21378
|
-
[traceItems]
|
|
21379
|
-
);
|
|
21380
21449
|
const sessionNodes = (0, import_react3.useMemo)(
|
|
21381
|
-
() =>
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21385
|
-
|
|
21386
|
-
[sessionNodes]
|
|
21450
|
+
() => sortSessionNodesForNav(
|
|
21451
|
+
data.hierarchy.rootNodes.filter((node) => node.type === "session"),
|
|
21452
|
+
traceById
|
|
21453
|
+
),
|
|
21454
|
+
[data.hierarchy.rootNodes, traceById]
|
|
21387
21455
|
);
|
|
21388
21456
|
const sessionNavItems = (0, import_react3.useMemo)(
|
|
21389
21457
|
() => deriveSessionNavItems(sessionNodes, traceById),
|
|
21390
21458
|
[sessionNodes, traceById]
|
|
21391
21459
|
);
|
|
21460
|
+
const sessionNavById = (0, import_react3.useMemo)(
|
|
21461
|
+
() => new Map(sessionNavItems.map((item) => [item.id, item])),
|
|
21462
|
+
[sessionNavItems]
|
|
21463
|
+
);
|
|
21392
21464
|
const hasActiveFilters = Boolean(
|
|
21393
21465
|
filters.search || filters.status || filters.kind || filters.tags
|
|
21394
21466
|
);
|
|
21395
|
-
const filteredSessionCount =
|
|
21467
|
+
const filteredSessionCount = sessionNodes.length;
|
|
21396
21468
|
const hasRecordedSessions = allSessionCount > 0;
|
|
21397
21469
|
const showFilteredSessionEmptyState = hasActiveFilters && hasRecordedSessions && filteredSessionCount === 0;
|
|
21470
|
+
const selectedNodePath = (0, import_react3.useMemo)(
|
|
21471
|
+
() => selectedNodeId ? findSessionNodePath(sessionNodes, selectedNodeId) : [],
|
|
21472
|
+
[sessionNodes, selectedNodeId]
|
|
21473
|
+
);
|
|
21474
|
+
const selectedTracePath = (0, import_react3.useMemo)(
|
|
21475
|
+
() => selectedTraceId ? findSessionNodePath(sessionNodes, toTraceNodeId(selectedTraceId)) : [],
|
|
21476
|
+
[sessionNodes, selectedTraceId]
|
|
21477
|
+
);
|
|
21478
|
+
const selectedPathIds = (0, import_react3.useMemo)(
|
|
21479
|
+
() => new Set(selectedNodePath.map((node) => node.id)),
|
|
21480
|
+
[selectedNodePath]
|
|
21481
|
+
);
|
|
21398
21482
|
const selectedSessionNode = (0, import_react3.useMemo)(
|
|
21399
|
-
() =>
|
|
21400
|
-
[
|
|
21483
|
+
() => (selectedNodePath[0]?.type === "session" ? selectedNodePath[0] : null) ?? (selectedTracePath[0]?.type === "session" ? selectedTracePath[0] : null) ?? sessionNodes[0] ?? null,
|
|
21484
|
+
[selectedNodePath, selectedTracePath, sessionNodes]
|
|
21401
21485
|
);
|
|
21402
21486
|
const selectedTraceSummary = (0, import_react3.useMemo)(
|
|
21403
21487
|
() => selectedTraceId ? traceById.get(selectedTraceId) ?? null : null,
|
|
21404
21488
|
[selectedTraceId, traceById]
|
|
21405
21489
|
);
|
|
21406
21490
|
(0, import_react3.useEffect)(() => {
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21410
|
-
|
|
21411
|
-
|
|
21412
|
-
|
|
21413
|
-
(0, import_react3.useEffect)(() => {
|
|
21414
|
-
if (navMode !== "sessions") {
|
|
21415
|
-
return;
|
|
21416
|
-
}
|
|
21417
|
-
const currentSelectedNode = selectedNodeId && selectedSessionNode ? findNodeById([selectedSessionNode], selectedNodeId) : null;
|
|
21418
|
-
const fallbackTraceId = getNewestTraceId(selectedSessionNode);
|
|
21419
|
-
const fallbackNodeId = currentSelectedNode?.id ?? (fallbackTraceId ? toTraceNodeId(fallbackTraceId) : selectedSessionNode?.id ?? null);
|
|
21420
|
-
if (fallbackNodeId !== selectedNodeId) {
|
|
21421
|
-
(0, import_react3.startTransition)(() => setSelectedNodeId(fallbackNodeId));
|
|
21422
|
-
}
|
|
21423
|
-
}, [navMode, selectedNodeId, selectedSessionNode]);
|
|
21424
|
-
(0, import_react3.useEffect)(() => {
|
|
21425
|
-
const hasSelectedTrace = selectedTraceId ? traceItems.some((trace) => trace.id === selectedTraceId) : false;
|
|
21426
|
-
if (navMode === "traces") {
|
|
21427
|
-
if (!hasSelectedTrace) {
|
|
21428
|
-
(0, import_react3.startTransition)(() => setSelectedTraceId(traceItems[0]?.id ?? null));
|
|
21429
|
-
}
|
|
21491
|
+
const nextSelection = resolveSessionTreeSelection(
|
|
21492
|
+
sessionNodes,
|
|
21493
|
+
selectedNodeId,
|
|
21494
|
+
selectedTraceId
|
|
21495
|
+
);
|
|
21496
|
+
if (nextSelection.selectedNodeId === selectedNodeId && nextSelection.selectedTraceId === selectedTraceId) {
|
|
21430
21497
|
return;
|
|
21431
21498
|
}
|
|
21432
|
-
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
}, [
|
|
21438
|
-
data.hierarchy.rootNodes,
|
|
21439
|
-
navMode,
|
|
21440
|
-
selectedNodeId,
|
|
21441
|
-
selectedSessionNode,
|
|
21442
|
-
selectedTraceId,
|
|
21443
|
-
traceItems
|
|
21444
|
-
]);
|
|
21499
|
+
(0, import_react3.startTransition)(() => {
|
|
21500
|
+
setSelectedNodeId(nextSelection.selectedNodeId);
|
|
21501
|
+
setSelectedTraceId(nextSelection.selectedTraceId);
|
|
21502
|
+
});
|
|
21503
|
+
}, [selectedNodeId, selectedTraceId, sessionNodes]);
|
|
21445
21504
|
const loadDetail = (0, import_react3.useEffectEvent)(async (traceId) => {
|
|
21446
21505
|
const requestId = detailRequestRef.current + 1;
|
|
21447
21506
|
detailRequestRef.current = requestId;
|
|
@@ -21468,43 +21527,13 @@ function App() {
|
|
|
21468
21527
|
void loadDetail(selectedTraceId);
|
|
21469
21528
|
}, [selectedTraceId]);
|
|
21470
21529
|
const defaultExpandedNodeIds = (0, import_react3.useMemo)(
|
|
21471
|
-
() =>
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
() => selectedNodeId ? findNodePath(data.hierarchy.rootNodes, selectedNodeId) : [],
|
|
21476
|
-
[data.hierarchy.rootNodes, selectedNodeId]
|
|
21477
|
-
);
|
|
21478
|
-
const selectedTimelineModel = (0, import_react3.useMemo)(
|
|
21479
|
-
() => buildHierarchyTimelineModel(
|
|
21480
|
-
selectedSessionNode,
|
|
21481
|
-
traceById,
|
|
21482
|
-
selectedNodeId,
|
|
21483
|
-
selectedNodePath,
|
|
21484
|
-
selectedTraceId
|
|
21530
|
+
() => getDefaultExpandedSessionTreeNodeIds(
|
|
21531
|
+
sessionNodes,
|
|
21532
|
+
selectedSessionNode?.id ?? null,
|
|
21533
|
+
selectedNodeId
|
|
21485
21534
|
),
|
|
21486
|
-
[
|
|
21487
|
-
selectedNodeId,
|
|
21488
|
-
selectedNodePath,
|
|
21489
|
-
selectedSessionNode,
|
|
21490
|
-
selectedTraceId,
|
|
21491
|
-
traceById
|
|
21492
|
-
]
|
|
21535
|
+
[selectedNodeId, selectedSessionNode, sessionNodes]
|
|
21493
21536
|
);
|
|
21494
|
-
(0, import_react3.useEffect)(() => {
|
|
21495
|
-
if (!selectedNodePath.length) {
|
|
21496
|
-
return;
|
|
21497
|
-
}
|
|
21498
|
-
(0, import_react3.startTransition)(() => {
|
|
21499
|
-
setExpandedNodeOverrides((current) => {
|
|
21500
|
-
const next = { ...current };
|
|
21501
|
-
for (const node of selectedNodePath.slice(0, -1)) {
|
|
21502
|
-
next[node.id] = true;
|
|
21503
|
-
}
|
|
21504
|
-
return next;
|
|
21505
|
-
});
|
|
21506
|
-
});
|
|
21507
|
-
}, [selectedNodePath]);
|
|
21508
21537
|
const activeTabJsonMode = tabModes[detailTab] ?? "formatted";
|
|
21509
21538
|
const activeTagFilterCount = countTagFilters(filters.tags);
|
|
21510
21539
|
const onFilterChange = (key, value) => {
|
|
@@ -21543,24 +21572,13 @@ function App() {
|
|
|
21543
21572
|
}));
|
|
21544
21573
|
});
|
|
21545
21574
|
};
|
|
21546
|
-
const toggleTraceGroupCollapse = (groupId) => {
|
|
21547
|
-
(0, import_react3.startTransition)(() => {
|
|
21548
|
-
setCollapsedTraceGroups((current) => ({
|
|
21549
|
-
...current,
|
|
21550
|
-
[groupId]: !current[groupId]
|
|
21551
|
-
}));
|
|
21552
|
-
});
|
|
21553
|
-
};
|
|
21554
21575
|
const resetFilters = () => {
|
|
21555
|
-
const nextSessionNode = (sessionNavItems[0] && sessionNodeById.get(sessionNavItems[0].id)) ?? null;
|
|
21556
21576
|
(0, import_react3.startTransition)(() => {
|
|
21557
21577
|
setFilters(INITIAL_FILTERS);
|
|
21558
21578
|
setShowAdvancedFilters(false);
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
|
|
21562
|
-
navMode === "traces" ? traceItems[0]?.id ?? null : getNewestTraceId(nextSessionNode)
|
|
21563
|
-
);
|
|
21579
|
+
setSelectedNodeId(null);
|
|
21580
|
+
setSelectedTraceId(null);
|
|
21581
|
+
setDetailTab("conversation");
|
|
21564
21582
|
});
|
|
21565
21583
|
};
|
|
21566
21584
|
const clearTraces = async () => {
|
|
@@ -21594,78 +21612,21 @@ function App() {
|
|
|
21594
21612
|
() => setIsSessionsPanelCollapsed((current) => !current)
|
|
21595
21613
|
);
|
|
21596
21614
|
};
|
|
21597
|
-
const showSessionsMode = () => {
|
|
21598
|
-
const tracePath = selectedTraceId ? findNodePath(data.hierarchy.rootNodes, `trace:${selectedTraceId}`) : [];
|
|
21599
|
-
const fallbackSessionNode = tracePath[0] ?? selectedSessionNode ?? ((sessionNavItems[0] && sessionNodeById.get(sessionNavItems[0].id)) ?? null);
|
|
21600
|
-
const fallbackNodeId = tracePath[tracePath.length - 1]?.id ?? selectedNodeId ?? fallbackSessionNode?.id ?? null;
|
|
21601
|
-
const nextTraceId = selectedTraceId && traceById.has(selectedTraceId) ? selectedTraceId : getNewestTraceId(fallbackSessionNode);
|
|
21602
|
-
(0, import_react3.startTransition)(() => {
|
|
21603
|
-
setNavMode("sessions");
|
|
21604
|
-
setSelectedSessionId(fallbackSessionNode?.id ?? null);
|
|
21605
|
-
setSelectedNodeId(fallbackNodeId);
|
|
21606
|
-
setSelectedTraceId(nextTraceId);
|
|
21607
|
-
setDetailTab("conversation");
|
|
21608
|
-
});
|
|
21609
|
-
};
|
|
21610
|
-
const showTracesMode = () => {
|
|
21611
|
-
(0, import_react3.startTransition)(() => {
|
|
21612
|
-
const nextTraceId = selectedTraceId && traceItems.some((trace) => trace.id === selectedTraceId) ? selectedTraceId : traceItems[0]?.id ?? null;
|
|
21613
|
-
setNavMode("traces");
|
|
21614
|
-
setSelectedTraceId(nextTraceId);
|
|
21615
|
-
setSelectedNodeId(nextTraceId ? `trace:${nextTraceId}` : selectedNodeId);
|
|
21616
|
-
setDetailTab("conversation");
|
|
21617
|
-
if (nextTraceId) {
|
|
21618
|
-
const nextTrace = traceById.get(nextTraceId);
|
|
21619
|
-
if (nextTrace?.hierarchy.sessionId) {
|
|
21620
|
-
setSelectedSessionId(toSessionNodeId(nextTrace.hierarchy.sessionId));
|
|
21621
|
-
}
|
|
21622
|
-
}
|
|
21623
|
-
});
|
|
21624
|
-
};
|
|
21625
|
-
const selectTraceFromList = (traceId) => {
|
|
21626
|
-
const trace = traceById.get(traceId);
|
|
21627
|
-
(0, import_react3.startTransition)(() => {
|
|
21628
|
-
setNavMode("traces");
|
|
21629
|
-
setSelectedTraceId(traceId);
|
|
21630
|
-
setSelectedNodeId(`trace:${traceId}`);
|
|
21631
|
-
setDetailTab("conversation");
|
|
21632
|
-
if (trace?.hierarchy.sessionId) {
|
|
21633
|
-
setSelectedSessionId(toSessionNodeId(trace.hierarchy.sessionId));
|
|
21634
|
-
}
|
|
21635
|
-
});
|
|
21636
|
-
};
|
|
21637
21615
|
const handleHierarchySelect = (node) => {
|
|
21638
|
-
const
|
|
21639
|
-
const nextTraceId = node.type === "trace" ? node.meta.traceId ?? node.traceIds[0] ?? null : getNewestTraceId(node);
|
|
21640
|
-
const nextSessionId = nodePath[0]?.type === "session" ? nodePath[0].id : selectedSessionId;
|
|
21641
|
-
const nextSelectedNodeId = node.type === "trace" ? node.id : nextTraceId ? toTraceNodeId(nextTraceId) : node.id;
|
|
21616
|
+
const nextTraceId = node.type === "trace" ? node.meta.traceId ?? node.traceIds[0] ?? null : getNewestTraceIdForNode(node);
|
|
21642
21617
|
(0, import_react3.startTransition)(() => {
|
|
21643
|
-
|
|
21644
|
-
setSelectedSessionId(nextSessionId ?? null);
|
|
21645
|
-
setSelectedNodeId(nextSelectedNodeId);
|
|
21618
|
+
setSelectedNodeId(node.id);
|
|
21646
21619
|
setSelectedTraceId(nextTraceId);
|
|
21647
21620
|
setDetailTab("conversation");
|
|
21648
21621
|
});
|
|
21649
21622
|
};
|
|
21650
|
-
const handleTimelineSelect = (nodeId) => {
|
|
21651
|
-
const scopeNodes = selectedSessionNode ? [selectedSessionNode] : data.hierarchy.rootNodes;
|
|
21652
|
-
const node = findNodeById(scopeNodes, nodeId) ?? findNodeById(data.hierarchy.rootNodes, nodeId);
|
|
21653
|
-
if (!node) {
|
|
21654
|
-
return;
|
|
21655
|
-
}
|
|
21656
|
-
handleHierarchySelect(node);
|
|
21657
|
-
};
|
|
21658
21623
|
const navigateToHierarchyNode = (nodeId) => {
|
|
21659
|
-
const node =
|
|
21624
|
+
const node = findSessionNodeById(sessionNodes, nodeId);
|
|
21660
21625
|
if (!node) {
|
|
21661
21626
|
return;
|
|
21662
21627
|
}
|
|
21663
|
-
const
|
|
21664
|
-
const nextSessionId = nodePath[0]?.type === "session" ? nodePath[0].id : selectedSessionId;
|
|
21665
|
-
const nextTraceId = selectedTraceId && node.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceId(node);
|
|
21628
|
+
const nextTraceId = selectedTraceId && node.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceIdForNode(node);
|
|
21666
21629
|
(0, import_react3.startTransition)(() => {
|
|
21667
|
-
setNavMode("sessions");
|
|
21668
|
-
setSelectedSessionId(nextSessionId ?? null);
|
|
21669
21630
|
setSelectedNodeId(nodeId);
|
|
21670
21631
|
if (nextTraceId !== selectedTraceId) {
|
|
21671
21632
|
setSelectedTraceId(nextTraceId);
|
|
@@ -21674,17 +21635,6 @@ function App() {
|
|
|
21674
21635
|
};
|
|
21675
21636
|
const detailTabs = buildDetailTabs(detail);
|
|
21676
21637
|
const activeTab = detailTabs.some((tab) => tab.id === detailTab) ? detailTab : detailTabs[0]?.id ?? "conversation";
|
|
21677
|
-
const handleSessionChange = (sessionId) => {
|
|
21678
|
-
const sessionNode = sessionNodeById.get(sessionId) ?? null;
|
|
21679
|
-
const nextTraceId = getNewestTraceId(sessionNode);
|
|
21680
|
-
(0, import_react3.startTransition)(() => {
|
|
21681
|
-
setNavMode("sessions");
|
|
21682
|
-
setSelectedSessionId(sessionId);
|
|
21683
|
-
setSelectedNodeId(nextTraceId ? toTraceNodeId(nextTraceId) : sessionId);
|
|
21684
|
-
setSelectedTraceId(nextTraceId);
|
|
21685
|
-
setDetailTab("conversation");
|
|
21686
|
-
});
|
|
21687
|
-
};
|
|
21688
21638
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "app-shell", children: [
|
|
21689
21639
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BackgroundGlow, {}),
|
|
21690
21640
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "app-frame", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "board-shell inspector-shell", children: [
|
|
@@ -21813,46 +21763,45 @@ function App() {
|
|
|
21813
21763
|
isSessionsPanelCollapsed && "is-sidebar-collapsed"
|
|
21814
21764
|
),
|
|
21815
21765
|
children: [
|
|
21816
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { className: "sidebar-card session-sidebar-card inspector-card", children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
21817
|
-
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
21821
|
-
|
|
21822
|
-
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
21829
|
-
|
|
21830
|
-
|
|
21831
|
-
|
|
21832
|
-
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
EmptyState,
|
|
21837
|
-
{
|
|
21838
|
-
icon: Funnel,
|
|
21839
|
-
title: "No sessions match the current filters",
|
|
21840
|
-
description: "Try adjusting the search, status, kind, or tag filters to broaden the result set."
|
|
21841
|
-
}
|
|
21842
|
-
),
|
|
21843
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { variant: "outline", onClick: resetFilters, children: [
|
|
21844
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { "data-icon": "inline-start" }),
|
|
21845
|
-
"Clear filters"
|
|
21846
|
-
] })
|
|
21847
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21766
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { className: "sidebar-card session-sidebar-card inspector-card", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-sidebar-shell", children: sessionNodes.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21767
|
+
SessionTreeNavigator,
|
|
21768
|
+
{
|
|
21769
|
+
defaultExpandedNodeIds,
|
|
21770
|
+
expandedNodeOverrides,
|
|
21771
|
+
hasActiveFilters,
|
|
21772
|
+
items: sessionNavItems,
|
|
21773
|
+
maxDurationMs: navigatorMaxDurationMs,
|
|
21774
|
+
nodes: sessionNodes,
|
|
21775
|
+
onSelect: handleHierarchySelect,
|
|
21776
|
+
onToggle: toggleNodeExpansion,
|
|
21777
|
+
selectedNodeId,
|
|
21778
|
+
selectedPathIds,
|
|
21779
|
+
selectedTraceId,
|
|
21780
|
+
sessionNavById,
|
|
21781
|
+
totalCount: allSessionCount,
|
|
21782
|
+
traceById
|
|
21783
|
+
}
|
|
21784
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-sidebar-empty", children: showFilteredSessionEmptyState ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-sidebar-empty-state", children: [
|
|
21785
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21848
21786
|
EmptyState,
|
|
21849
21787
|
{
|
|
21850
|
-
icon:
|
|
21851
|
-
title: "No sessions
|
|
21852
|
-
description: "
|
|
21788
|
+
icon: Funnel,
|
|
21789
|
+
title: "No sessions match the current filters",
|
|
21790
|
+
description: "Try adjusting the search, status, kind, or tag filters to broaden the result set."
|
|
21853
21791
|
}
|
|
21854
|
-
)
|
|
21855
|
-
|
|
21792
|
+
),
|
|
21793
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { variant: "outline", onClick: resetFilters, children: [
|
|
21794
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { "data-icon": "inline-start" }),
|
|
21795
|
+
"Clear filters"
|
|
21796
|
+
] })
|
|
21797
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21798
|
+
EmptyState,
|
|
21799
|
+
{
|
|
21800
|
+
icon: Network,
|
|
21801
|
+
title: "No sessions yet",
|
|
21802
|
+
description: "Trigger any traced LLM call and the session tree will appear here."
|
|
21803
|
+
}
|
|
21804
|
+
) }) }) }),
|
|
21856
21805
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { className: "timeline-card content-card inspector-card", children: selectedTraceId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21857
21806
|
TraceDetailPanel,
|
|
21858
21807
|
{
|
|
@@ -21865,20 +21814,18 @@ function App() {
|
|
|
21865
21814
|
onApplyTraceFilter: applyTraceFilter,
|
|
21866
21815
|
onNavigateHierarchyNode: navigateToHierarchyNode,
|
|
21867
21816
|
onTabChange: (value) => setDetailTab(value),
|
|
21868
|
-
onSelectTimelineNode: handleTimelineSelect,
|
|
21869
21817
|
onToggleJsonMode: (tabId) => (0, import_react3.startTransition)(() => {
|
|
21870
21818
|
setTabModes((current) => ({
|
|
21871
21819
|
...current,
|
|
21872
21820
|
[tabId]: (current[tabId] ?? "formatted") === "formatted" ? "raw" : "formatted"
|
|
21873
21821
|
}));
|
|
21874
|
-
})
|
|
21875
|
-
timelineModel: null
|
|
21822
|
+
})
|
|
21876
21823
|
}
|
|
21877
21824
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, { className: "content-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21878
21825
|
EmptyState,
|
|
21879
21826
|
{
|
|
21880
21827
|
icon: ArrowUpRight,
|
|
21881
|
-
title: "Select a trace from the session
|
|
21828
|
+
title: "Select a trace from the session tree",
|
|
21882
21829
|
description: "Choose any call on the left to inspect the full request, response, context, and stream details."
|
|
21883
21830
|
}
|
|
21884
21831
|
) }) })
|
|
@@ -21931,63 +21878,51 @@ function ThemeSwitcher({
|
|
|
21931
21878
|
)
|
|
21932
21879
|
] });
|
|
21933
21880
|
}
|
|
21934
|
-
function
|
|
21881
|
+
function SessionTreeNavigator({
|
|
21882
|
+
defaultExpandedNodeIds,
|
|
21883
|
+
expandedNodeOverrides,
|
|
21935
21884
|
hasActiveFilters,
|
|
21936
21885
|
items,
|
|
21937
|
-
|
|
21938
|
-
|
|
21939
|
-
|
|
21886
|
+
maxDurationMs,
|
|
21887
|
+
nodes,
|
|
21888
|
+
onSelect,
|
|
21889
|
+
onToggle,
|
|
21890
|
+
selectedNodeId,
|
|
21891
|
+
selectedPathIds,
|
|
21892
|
+
selectedTraceId,
|
|
21893
|
+
sessionNavById,
|
|
21894
|
+
totalCount,
|
|
21895
|
+
traceById
|
|
21940
21896
|
}) {
|
|
21941
21897
|
const filteredCount = items.length;
|
|
21942
21898
|
const countLabel = hasActiveFilters && totalCount > filteredCount ? `${filteredCount} of ${totalCount} sessions` : formatCountLabel(
|
|
21943
21899
|
hasActiveFilters ? filteredCount : Math.max(filteredCount, totalCount),
|
|
21944
21900
|
"session"
|
|
21945
21901
|
);
|
|
21946
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-
|
|
21947
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-
|
|
21948
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-
|
|
21949
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-
|
|
21950
|
-
hasActiveFilters ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", className: "session-
|
|
21902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-section", children: [
|
|
21903
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-header", children: [
|
|
21904
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-title-row", children: [
|
|
21905
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-title", children: "Sessions" }),
|
|
21906
|
+
hasActiveFilters ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", className: "session-tree-filter-badge", children: "Filtered" }) : null
|
|
21951
21907
|
] }),
|
|
21952
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-
|
|
21908
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-meta", children: countLabel })
|
|
21953
21909
|
] }),
|
|
21954
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-
|
|
21955
|
-
|
|
21956
|
-
|
|
21957
|
-
|
|
21958
|
-
|
|
21959
|
-
|
|
21960
|
-
|
|
21961
|
-
|
|
21962
|
-
|
|
21963
|
-
|
|
21964
|
-
|
|
21965
|
-
|
|
21966
|
-
|
|
21967
|
-
|
|
21968
|
-
|
|
21969
|
-
|
|
21970
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-nav-card-header", children: [
|
|
21971
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21972
|
-
"div",
|
|
21973
|
-
{
|
|
21974
|
-
className: "session-nav-card-title",
|
|
21975
|
-
title: item.primaryLabel,
|
|
21976
|
-
children: item.primaryLabel
|
|
21977
|
-
}
|
|
21978
|
-
),
|
|
21979
|
-
item.latestTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-nav-card-time", children: item.latestTimestamp }) : null
|
|
21980
|
-
] }),
|
|
21981
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-nav-card-meta", children: detailLabel }),
|
|
21982
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-nav-card-footer", children: [
|
|
21983
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-nav-card-id", children: item.shortSessionId }),
|
|
21984
|
-
badge
|
|
21985
|
-
] })
|
|
21986
|
-
]
|
|
21987
|
-
},
|
|
21988
|
-
item.id
|
|
21989
|
-
);
|
|
21990
|
-
}) })
|
|
21910
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21911
|
+
HierarchyTree,
|
|
21912
|
+
{
|
|
21913
|
+
defaultExpandedNodeIds,
|
|
21914
|
+
expandedNodeOverrides,
|
|
21915
|
+
maxDurationMs,
|
|
21916
|
+
nodes,
|
|
21917
|
+
onSelect,
|
|
21918
|
+
onToggle,
|
|
21919
|
+
selectedNodeId,
|
|
21920
|
+
selectedPathIds,
|
|
21921
|
+
selectedTraceId,
|
|
21922
|
+
sessionNavById,
|
|
21923
|
+
traceById
|
|
21924
|
+
}
|
|
21925
|
+
) })
|
|
21991
21926
|
] });
|
|
21992
21927
|
}
|
|
21993
21928
|
function getSessionNavBadge(item) {
|
|
@@ -22009,6 +21944,374 @@ function BackgroundGlow() {
|
|
|
22009
21944
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid-noise" })
|
|
22010
21945
|
] });
|
|
22011
21946
|
}
|
|
21947
|
+
function HierarchyTree({
|
|
21948
|
+
defaultExpandedNodeIds,
|
|
21949
|
+
expandedNodeOverrides,
|
|
21950
|
+
maxDurationMs,
|
|
21951
|
+
nodes,
|
|
21952
|
+
onSelect,
|
|
21953
|
+
onToggle,
|
|
21954
|
+
selectedNodeId,
|
|
21955
|
+
selectedPathIds,
|
|
21956
|
+
selectedTraceId,
|
|
21957
|
+
sessionNavById,
|
|
21958
|
+
traceById
|
|
21959
|
+
}) {
|
|
21960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-root", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21961
|
+
HierarchyTreeNode,
|
|
21962
|
+
{
|
|
21963
|
+
defaultExpandedNodeIds,
|
|
21964
|
+
depth: 0,
|
|
21965
|
+
expandedNodeOverrides,
|
|
21966
|
+
maxDurationMs,
|
|
21967
|
+
node,
|
|
21968
|
+
onSelect,
|
|
21969
|
+
onToggle,
|
|
21970
|
+
selectedNodeId,
|
|
21971
|
+
selectedPathIds,
|
|
21972
|
+
selectedTraceId,
|
|
21973
|
+
sessionNavById,
|
|
21974
|
+
traceById
|
|
21975
|
+
},
|
|
21976
|
+
node.id
|
|
21977
|
+
)) });
|
|
21978
|
+
}
|
|
21979
|
+
function HierarchyTreeNode({
|
|
21980
|
+
defaultExpandedNodeIds,
|
|
21981
|
+
depth,
|
|
21982
|
+
expandedNodeOverrides,
|
|
21983
|
+
maxDurationMs,
|
|
21984
|
+
node,
|
|
21985
|
+
onSelect,
|
|
21986
|
+
onToggle,
|
|
21987
|
+
selectedNodeId,
|
|
21988
|
+
selectedPathIds,
|
|
21989
|
+
selectedTraceId,
|
|
21990
|
+
sessionNavById,
|
|
21991
|
+
traceById
|
|
21992
|
+
}) {
|
|
21993
|
+
const isExpandable = node.children.length > 0;
|
|
21994
|
+
const isForcedExpanded = isExpandable && selectedPathIds.has(node.id);
|
|
21995
|
+
const expandedOverride = expandedNodeOverrides[node.id];
|
|
21996
|
+
const isExpanded = isExpandable && (expandedOverride ?? (isForcedExpanded || defaultExpandedNodeIds.has(node.id)));
|
|
21997
|
+
const isInPath = selectedPathIds.has(node.id);
|
|
21998
|
+
const nodeCopy = getHierarchyNodeCopy(node, traceById);
|
|
21999
|
+
const trace = node.meta.traceId ? traceById.get(node.meta.traceId) ?? null : null;
|
|
22000
|
+
const sessionNavItem = node.type === "session" ? sessionNavById.get(node.id) ?? null : null;
|
|
22001
|
+
if (node.type === "trace" && trace) {
|
|
22002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22003
|
+
TraceHierarchyLeaf,
|
|
22004
|
+
{
|
|
22005
|
+
depth,
|
|
22006
|
+
maxDurationMs,
|
|
22007
|
+
node,
|
|
22008
|
+
nodeCopy,
|
|
22009
|
+
onSelect,
|
|
22010
|
+
inPath: isInPath,
|
|
22011
|
+
selected: selectedNodeId === node.id,
|
|
22012
|
+
selectedTrace: selectedTraceId === trace.id,
|
|
22013
|
+
trace
|
|
22014
|
+
}
|
|
22015
|
+
);
|
|
22016
|
+
}
|
|
22017
|
+
if (sessionNavItem) {
|
|
22018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22019
|
+
SessionHierarchyBranch,
|
|
22020
|
+
{
|
|
22021
|
+
depth,
|
|
22022
|
+
defaultExpandedNodeIds,
|
|
22023
|
+
expandedNodeOverrides,
|
|
22024
|
+
isExpanded,
|
|
22025
|
+
item: sessionNavItem,
|
|
22026
|
+
maxDurationMs,
|
|
22027
|
+
node,
|
|
22028
|
+
onSelect,
|
|
22029
|
+
onToggle,
|
|
22030
|
+
selected: selectedNodeId === node.id,
|
|
22031
|
+
selectedNodeId,
|
|
22032
|
+
selectedPathIds,
|
|
22033
|
+
selectedTraceId,
|
|
22034
|
+
sessionNavById,
|
|
22035
|
+
traceById
|
|
22036
|
+
}
|
|
22037
|
+
);
|
|
22038
|
+
}
|
|
22039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22040
|
+
"div",
|
|
22041
|
+
{
|
|
22042
|
+
className: "tree-node-wrap",
|
|
22043
|
+
style: { "--depth": String(depth) },
|
|
22044
|
+
children: [
|
|
22045
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22046
|
+
"div",
|
|
22047
|
+
{
|
|
22048
|
+
className: clsx_default(
|
|
22049
|
+
"tree-node-card",
|
|
22050
|
+
selectedNodeId === node.id && "is-active",
|
|
22051
|
+
isInPath && "is-in-path",
|
|
22052
|
+
node.type === "trace" && "is-trace"
|
|
22053
|
+
),
|
|
22054
|
+
children: [
|
|
22055
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22056
|
+
"button",
|
|
22057
|
+
{
|
|
22058
|
+
type: "button",
|
|
22059
|
+
className: clsx_default("tree-node-toggle", !isExpandable && "is-static"),
|
|
22060
|
+
disabled: !isExpandable,
|
|
22061
|
+
onClick: () => {
|
|
22062
|
+
if (isExpandable) {
|
|
22063
|
+
onToggle(node.id);
|
|
22064
|
+
}
|
|
22065
|
+
},
|
|
22066
|
+
"aria-label": isExpandable ? `${isExpanded ? "Collapse" : "Expand"} ${nodeCopy.label}` : void 0,
|
|
22067
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: clsx_default(isExpanded && "is-open") })
|
|
22068
|
+
}
|
|
22069
|
+
),
|
|
22070
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22071
|
+
"button",
|
|
22072
|
+
{
|
|
22073
|
+
type: "button",
|
|
22074
|
+
className: "tree-node-select",
|
|
22075
|
+
onClick: () => onSelect(node),
|
|
22076
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy", children: [
|
|
22077
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-heading", children: [
|
|
22078
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-label", children: nodeCopy.label }),
|
|
22079
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22080
|
+
Badge,
|
|
22081
|
+
{
|
|
22082
|
+
variant: "secondary",
|
|
22083
|
+
className: "tree-node-inline-badge",
|
|
22084
|
+
semantic: nodeCopy.badge,
|
|
22085
|
+
children: nodeCopy.badge
|
|
22086
|
+
}
|
|
22087
|
+
)
|
|
22088
|
+
] }),
|
|
22089
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: nodeCopy.meta })
|
|
22090
|
+
] })
|
|
22091
|
+
}
|
|
22092
|
+
)
|
|
22093
|
+
]
|
|
22094
|
+
}
|
|
22095
|
+
),
|
|
22096
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-node-children", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22097
|
+
HierarchyTreeNode,
|
|
22098
|
+
{
|
|
22099
|
+
defaultExpandedNodeIds,
|
|
22100
|
+
depth: depth + 1,
|
|
22101
|
+
expandedNodeOverrides,
|
|
22102
|
+
maxDurationMs,
|
|
22103
|
+
node: child,
|
|
22104
|
+
onSelect,
|
|
22105
|
+
onToggle,
|
|
22106
|
+
selectedNodeId,
|
|
22107
|
+
selectedPathIds,
|
|
22108
|
+
selectedTraceId,
|
|
22109
|
+
sessionNavById,
|
|
22110
|
+
traceById
|
|
22111
|
+
},
|
|
22112
|
+
child.id
|
|
22113
|
+
)) }) : null
|
|
22114
|
+
]
|
|
22115
|
+
}
|
|
22116
|
+
);
|
|
22117
|
+
}
|
|
22118
|
+
function SessionHierarchyBranch({
|
|
22119
|
+
defaultExpandedNodeIds,
|
|
22120
|
+
depth,
|
|
22121
|
+
expandedNodeOverrides,
|
|
22122
|
+
isExpanded,
|
|
22123
|
+
item,
|
|
22124
|
+
maxDurationMs,
|
|
22125
|
+
node,
|
|
22126
|
+
onSelect,
|
|
22127
|
+
onToggle,
|
|
22128
|
+
selected,
|
|
22129
|
+
selectedNodeId,
|
|
22130
|
+
selectedPathIds,
|
|
22131
|
+
selectedTraceId,
|
|
22132
|
+
sessionNavById,
|
|
22133
|
+
traceById
|
|
22134
|
+
}) {
|
|
22135
|
+
const detailLabel = formatList([
|
|
22136
|
+
formatCountLabel(item.callCount, "call"),
|
|
22137
|
+
formatUsdCost(item.costUsd)
|
|
22138
|
+
]) || formatCountLabel(item.callCount, "call");
|
|
22139
|
+
const sessionSelectedPath = selectedNodeId ? findSessionNodePath([node], selectedNodeId) : [];
|
|
22140
|
+
const sessionTimelineModel = buildHierarchyTimelineModel(
|
|
22141
|
+
node,
|
|
22142
|
+
traceById,
|
|
22143
|
+
selectedNodeId,
|
|
22144
|
+
sessionSelectedPath,
|
|
22145
|
+
selectedTraceId
|
|
22146
|
+
);
|
|
22147
|
+
const sessionTimelineRow = sessionTimelineModel?.rows[0] ?? null;
|
|
22148
|
+
const showEmbeddedTimeline = isExpanded && Boolean(sessionTimelineModel?.rows.length);
|
|
22149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22150
|
+
"div",
|
|
22151
|
+
{
|
|
22152
|
+
className: "tree-node-wrap",
|
|
22153
|
+
style: { "--depth": String(depth) },
|
|
22154
|
+
children: [
|
|
22155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22156
|
+
"div",
|
|
22157
|
+
{
|
|
22158
|
+
className: clsx_default(
|
|
22159
|
+
"tree-node-card tree-session-card",
|
|
22160
|
+
selected && "is-active",
|
|
22161
|
+
selectedPathIds.has(node.id) && "is-in-path"
|
|
22162
|
+
),
|
|
22163
|
+
children: [
|
|
22164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22165
|
+
"button",
|
|
22166
|
+
{
|
|
22167
|
+
type: "button",
|
|
22168
|
+
className: clsx_default(
|
|
22169
|
+
"tree-node-toggle",
|
|
22170
|
+
!node.children.length && "is-static"
|
|
22171
|
+
),
|
|
22172
|
+
disabled: !node.children.length,
|
|
22173
|
+
onClick: () => {
|
|
22174
|
+
if (node.children.length) {
|
|
22175
|
+
onToggle(node.id);
|
|
22176
|
+
}
|
|
22177
|
+
},
|
|
22178
|
+
"aria-label": node.children.length ? `${isExpanded ? "Collapse" : "Expand"} ${item.primaryLabel}` : void 0,
|
|
22179
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: clsx_default(isExpanded && "is-open") })
|
|
22180
|
+
}
|
|
22181
|
+
),
|
|
22182
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22183
|
+
"button",
|
|
22184
|
+
{
|
|
22185
|
+
type: "button",
|
|
22186
|
+
className: "tree-node-select session-tree-select",
|
|
22187
|
+
onClick: () => onSelect(node),
|
|
22188
|
+
children: [
|
|
22189
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy session-tree-copy", children: [
|
|
22190
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-card-header", children: [
|
|
22191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-card-title", title: item.primaryLabel, children: item.primaryLabel }),
|
|
22192
|
+
item.latestTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-card-time", children: item.latestTimestamp }) : null
|
|
22193
|
+
] }),
|
|
22194
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: detailLabel }),
|
|
22195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-card-footer", children: [
|
|
22196
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-card-id", children: item.shortSessionId }),
|
|
22197
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-card-badges", children: [
|
|
22198
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", children: "Session" }),
|
|
22199
|
+
getSessionNavBadge(item)
|
|
22200
|
+
] })
|
|
22201
|
+
] })
|
|
22202
|
+
] }),
|
|
22203
|
+
sessionTimelineModel && sessionTimelineRow ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22204
|
+
SessionTreeTimelineBar,
|
|
22205
|
+
{
|
|
22206
|
+
model: sessionTimelineModel,
|
|
22207
|
+
row: sessionTimelineRow
|
|
22208
|
+
}
|
|
22209
|
+
) : null
|
|
22210
|
+
]
|
|
22211
|
+
}
|
|
22212
|
+
)
|
|
22213
|
+
]
|
|
22214
|
+
}
|
|
22215
|
+
),
|
|
22216
|
+
showEmbeddedTimeline && sessionTimelineModel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-timeline-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22217
|
+
"div",
|
|
22218
|
+
{
|
|
22219
|
+
className: "session-tree-timeline-list",
|
|
22220
|
+
role: "list",
|
|
22221
|
+
"aria-label": "Session timeline",
|
|
22222
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22223
|
+
HierarchyTimelineRows,
|
|
22224
|
+
{
|
|
22225
|
+
className: "is-embedded",
|
|
22226
|
+
model: sessionTimelineModel,
|
|
22227
|
+
onSelectRow: (nodeId) => {
|
|
22228
|
+
const selectedTimelineNode = findSessionNodeById([node], nodeId);
|
|
22229
|
+
if (selectedTimelineNode) {
|
|
22230
|
+
onSelect(selectedTimelineNode);
|
|
22231
|
+
}
|
|
22232
|
+
},
|
|
22233
|
+
rows: sessionTimelineModel.rows.slice(1)
|
|
22234
|
+
}
|
|
22235
|
+
)
|
|
22236
|
+
}
|
|
22237
|
+
) }) : isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-node-children", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22238
|
+
HierarchyTreeNode,
|
|
22239
|
+
{
|
|
22240
|
+
defaultExpandedNodeIds,
|
|
22241
|
+
depth: depth + 1,
|
|
22242
|
+
expandedNodeOverrides,
|
|
22243
|
+
maxDurationMs,
|
|
22244
|
+
node: child,
|
|
22245
|
+
onSelect,
|
|
22246
|
+
onToggle,
|
|
22247
|
+
selectedNodeId,
|
|
22248
|
+
selectedPathIds,
|
|
22249
|
+
selectedTraceId,
|
|
22250
|
+
sessionNavById,
|
|
22251
|
+
traceById
|
|
22252
|
+
},
|
|
22253
|
+
child.id
|
|
22254
|
+
)) }) : null
|
|
22255
|
+
]
|
|
22256
|
+
}
|
|
22257
|
+
);
|
|
22258
|
+
}
|
|
22259
|
+
function TraceHierarchyLeaf({
|
|
22260
|
+
depth,
|
|
22261
|
+
inPath,
|
|
22262
|
+
maxDurationMs,
|
|
22263
|
+
node,
|
|
22264
|
+
nodeCopy,
|
|
22265
|
+
onSelect,
|
|
22266
|
+
selected,
|
|
22267
|
+
selectedTrace,
|
|
22268
|
+
trace
|
|
22269
|
+
}) {
|
|
22270
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22271
|
+
"div",
|
|
22272
|
+
{
|
|
22273
|
+
className: "tree-node-wrap tree-trace-wrap",
|
|
22274
|
+
style: { "--depth": String(depth) },
|
|
22275
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22276
|
+
"div",
|
|
22277
|
+
{
|
|
22278
|
+
className: clsx_default(
|
|
22279
|
+
"tree-node-card is-trace",
|
|
22280
|
+
inPath && "is-in-path",
|
|
22281
|
+
selected && "is-active",
|
|
22282
|
+
selectedTrace && "is-detail-trace"
|
|
22283
|
+
),
|
|
22284
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22285
|
+
"button",
|
|
22286
|
+
{
|
|
22287
|
+
type: "button",
|
|
22288
|
+
className: "tree-node-select tree-trace-select",
|
|
22289
|
+
onClick: () => onSelect(node),
|
|
22290
|
+
children: [
|
|
22291
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy", children: [
|
|
22292
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-nav-kicker", children: getTraceActorLabel(trace) }),
|
|
22293
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-label", children: nodeCopy.label }),
|
|
22294
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: formatList([
|
|
22295
|
+
formatTimelineTimestamp(trace.startedAt),
|
|
22296
|
+
nodeCopy.meta
|
|
22297
|
+
]) })
|
|
22298
|
+
] }),
|
|
22299
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22300
|
+
TraceElapsedBar,
|
|
22301
|
+
{
|
|
22302
|
+
compact: true,
|
|
22303
|
+
durationMs: trace.durationMs,
|
|
22304
|
+
maxDurationMs
|
|
22305
|
+
}
|
|
22306
|
+
)
|
|
22307
|
+
]
|
|
22308
|
+
}
|
|
22309
|
+
)
|
|
22310
|
+
}
|
|
22311
|
+
)
|
|
22312
|
+
}
|
|
22313
|
+
);
|
|
22314
|
+
}
|
|
22012
22315
|
function StatusBadge({
|
|
22013
22316
|
status,
|
|
22014
22317
|
onClick
|
|
@@ -22031,235 +22334,191 @@ function TraceMetricPill({
|
|
|
22031
22334
|
}
|
|
22032
22335
|
);
|
|
22033
22336
|
}
|
|
22034
|
-
function
|
|
22035
|
-
|
|
22036
|
-
|
|
22037
|
-
|
|
22337
|
+
function TraceElapsedBar({
|
|
22338
|
+
compact = false,
|
|
22339
|
+
durationMs,
|
|
22340
|
+
maxDurationMs
|
|
22038
22341
|
}) {
|
|
22039
|
-
const
|
|
22040
|
-
const
|
|
22041
|
-
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22045
|
-
|
|
22046
|
-
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
}
|
|
22055
|
-
const list = listRef.current;
|
|
22056
|
-
const target = [...list.querySelectorAll(
|
|
22057
|
-
"[data-hierarchy-row-id]"
|
|
22058
|
-
)].find((element) => element.dataset.hierarchyRowId === activeRowId);
|
|
22059
|
-
if (!target) {
|
|
22060
|
-
return;
|
|
22342
|
+
const durationLabel = formatElapsedLabel(durationMs);
|
|
22343
|
+
const scale = getElapsedScale(durationMs, maxDurationMs);
|
|
22344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22345
|
+
"div",
|
|
22346
|
+
{
|
|
22347
|
+
className: cn(
|
|
22348
|
+
"trace-elapsed-bar",
|
|
22349
|
+
compact && "is-compact",
|
|
22350
|
+
durationMs === null && "is-pending"
|
|
22351
|
+
),
|
|
22352
|
+
style: { "--elapsed-scale": String(scale) },
|
|
22353
|
+
children: [
|
|
22354
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-elapsed-track", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-elapsed-span" }) }),
|
|
22355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-elapsed-label", children: durationLabel })
|
|
22356
|
+
]
|
|
22061
22357
|
}
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22358
|
+
);
|
|
22359
|
+
}
|
|
22360
|
+
function SessionTreeTimelineBar({
|
|
22361
|
+
model,
|
|
22362
|
+
row
|
|
22363
|
+
}) {
|
|
22364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22365
|
+
"span",
|
|
22366
|
+
{
|
|
22367
|
+
className: "session-tree-timeline",
|
|
22368
|
+
style: {
|
|
22369
|
+
"--session-tree-offset": model.durationMs > 0 ? String(row.offsetMs / model.durationMs) : "0",
|
|
22370
|
+
"--session-tree-span": model.durationMs > 0 ? String(row.durationMs / model.durationMs) : "1"
|
|
22371
|
+
},
|
|
22372
|
+
children: [
|
|
22373
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-timeline-meta", children: [
|
|
22374
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-timeline-start", children: formatTimelineTimestamp(row.startedAt) }),
|
|
22375
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-timeline-duration", children: formatElapsedLabel(row.durationMs) })
|
|
22376
|
+
] }),
|
|
22377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-timeline-track", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-timeline-bar" }) })
|
|
22378
|
+
]
|
|
22068
22379
|
}
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22380
|
+
);
|
|
22381
|
+
}
|
|
22382
|
+
function HierarchyTimelineRows({
|
|
22383
|
+
className,
|
|
22384
|
+
model,
|
|
22385
|
+
onSelectRow,
|
|
22386
|
+
rows
|
|
22387
|
+
}) {
|
|
22388
|
+
return rows.map((row) => {
|
|
22389
|
+
const isTraceRow = row.type === "trace";
|
|
22390
|
+
const rowClassName = cn(
|
|
22391
|
+
"hierarchy-timeline-row",
|
|
22392
|
+
className,
|
|
22393
|
+
isTraceRow ? "is-clickable" : "is-structure",
|
|
22394
|
+
row.depth === 0 && "is-root",
|
|
22395
|
+
row.isActive && "is-active",
|
|
22396
|
+
row.isDetailTrace && "is-detail-trace",
|
|
22397
|
+
row.isInPath && "is-in-path",
|
|
22398
|
+
`is-${row.type.replace(/[^a-z0-9-]/gi, "-")}`
|
|
22072
22399
|
);
|
|
22073
|
-
const
|
|
22074
|
-
|
|
22075
|
-
|
|
22076
|
-
|
|
22077
|
-
|
|
22078
|
-
|
|
22079
|
-
|
|
22080
|
-
|
|
22081
|
-
|
|
22082
|
-
|
|
22083
|
-
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
|
|
22090
|
-
|
|
22091
|
-
|
|
22092
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {}),
|
|
22093
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {}),
|
|
22094
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-axis-track", children: axisStops.map((stop) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22095
|
-
"span",
|
|
22096
|
-
{
|
|
22097
|
-
className: "hierarchy-timeline-axis-tick",
|
|
22098
|
-
style: { "--timeline-axis-offset": String(stop) },
|
|
22099
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-axis-label", children: formatElapsedLabel(model.durationMs * stop) })
|
|
22100
|
-
},
|
|
22101
|
-
stop
|
|
22102
|
-
)) })
|
|
22103
|
-
] }),
|
|
22104
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22105
|
-
"div",
|
|
22106
|
-
{
|
|
22107
|
-
ref: listRef,
|
|
22108
|
-
className: "hierarchy-timeline-list",
|
|
22109
|
-
role: "list",
|
|
22110
|
-
"aria-label": "Nested session timeline",
|
|
22111
|
-
children: model.rows.map((row) => {
|
|
22112
|
-
const isTraceRow = row.type === "trace";
|
|
22113
|
-
const rowClassName = cn(
|
|
22114
|
-
"hierarchy-timeline-row",
|
|
22115
|
-
isTraceRow ? "is-clickable" : "is-structure",
|
|
22116
|
-
row.depth === 0 && "is-root",
|
|
22117
|
-
row.isActive && "is-active",
|
|
22118
|
-
row.isDetailTrace && "is-detail-trace",
|
|
22119
|
-
row.isInPath && "is-in-path",
|
|
22120
|
-
`is-${row.type.replace(/[^a-z0-9-]/gi, "-")}`
|
|
22121
|
-
);
|
|
22122
|
-
const rowStyle = {
|
|
22123
|
-
"--timeline-depth": String(row.depth),
|
|
22124
|
-
"--timeline-offset": String(
|
|
22125
|
-
model.durationMs > 0 ? row.offsetMs / model.durationMs : 0
|
|
22126
|
-
),
|
|
22127
|
-
"--timeline-span": String(
|
|
22128
|
-
model.durationMs > 0 ? row.durationMs / model.durationMs : 1
|
|
22129
|
-
)
|
|
22130
|
-
};
|
|
22131
|
-
const rowContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Fragment, { children: [
|
|
22132
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-time", children: formatTimelineTimestamp(row.startedAt) }),
|
|
22133
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-branch", children: [
|
|
22134
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22135
|
-
"div",
|
|
22136
|
-
{
|
|
22137
|
-
className: "hierarchy-timeline-row-gutter",
|
|
22138
|
-
"aria-hidden": "true",
|
|
22139
|
-
children: [
|
|
22140
|
-
row.ancestorContinuations.map((continues, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22141
|
-
"span",
|
|
22142
|
-
{
|
|
22143
|
-
className: cn(
|
|
22144
|
-
"hierarchy-timeline-row-ancestor",
|
|
22145
|
-
continues && "has-line"
|
|
22146
|
-
),
|
|
22147
|
-
style: {
|
|
22148
|
-
"--timeline-connector-index": String(index)
|
|
22149
|
-
}
|
|
22150
|
-
},
|
|
22151
|
-
`${row.id}-ancestor-${index}`
|
|
22152
|
-
)),
|
|
22153
|
-
row.depth > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22154
|
-
"span",
|
|
22155
|
-
{
|
|
22156
|
-
className: "hierarchy-timeline-row-connector",
|
|
22157
|
-
style: {
|
|
22158
|
-
"--timeline-connector-index": String(
|
|
22159
|
-
row.depth - 1
|
|
22160
|
-
)
|
|
22161
|
-
},
|
|
22162
|
-
children: [
|
|
22163
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-connector-top" }),
|
|
22164
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-connector-elbow" }),
|
|
22165
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22166
|
-
"span",
|
|
22167
|
-
{
|
|
22168
|
-
className: cn(
|
|
22169
|
-
"hierarchy-timeline-row-connector-bottom",
|
|
22170
|
-
(row.hasVisibleChildren || !row.isLastSibling) && "has-line"
|
|
22171
|
-
)
|
|
22172
|
-
}
|
|
22173
|
-
)
|
|
22174
|
-
]
|
|
22175
|
-
}
|
|
22176
|
-
) : null
|
|
22177
|
-
]
|
|
22178
|
-
}
|
|
22179
|
-
),
|
|
22180
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-labels", children: [
|
|
22181
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-title", children: [
|
|
22182
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-title-text", children: row.label }),
|
|
22183
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22184
|
-
Badge,
|
|
22185
|
-
{
|
|
22186
|
-
variant: "secondary",
|
|
22187
|
-
className: "hierarchy-timeline-pill",
|
|
22188
|
-
semantic: row.badge,
|
|
22189
|
-
children: row.badge
|
|
22190
|
-
}
|
|
22191
|
-
),
|
|
22192
|
-
row.hasStructuredInput ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22193
|
-
"span",
|
|
22194
|
-
{
|
|
22195
|
-
className: "hierarchy-timeline-row-flag",
|
|
22196
|
-
title: "Structured input detected for this call",
|
|
22197
|
-
children: "Structured input"
|
|
22198
|
-
}
|
|
22199
|
-
) : null,
|
|
22200
|
-
row.hasHighlights && !row.hasStructuredInput ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22201
|
-
"span",
|
|
22202
|
-
{
|
|
22203
|
-
className: "hierarchy-timeline-row-flag is-highlight",
|
|
22204
|
-
title: "Trace insights available",
|
|
22205
|
-
children: "Insight"
|
|
22206
|
-
}
|
|
22207
|
-
) : null
|
|
22208
|
-
] }),
|
|
22209
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-meta", children: row.meta })
|
|
22210
|
-
] })
|
|
22211
|
-
] }),
|
|
22212
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-bars", children: [
|
|
22213
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22214
|
-
"div",
|
|
22215
|
-
{
|
|
22216
|
-
className: "hierarchy-timeline-row-track",
|
|
22217
|
-
"aria-hidden": "true",
|
|
22218
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-bar" })
|
|
22219
|
-
}
|
|
22400
|
+
const rowStyle = {
|
|
22401
|
+
"--timeline-depth": String(row.depth),
|
|
22402
|
+
"--timeline-offset": String(
|
|
22403
|
+
model.durationMs > 0 ? row.offsetMs / model.durationMs : 0
|
|
22404
|
+
),
|
|
22405
|
+
"--timeline-span": String(
|
|
22406
|
+
model.durationMs > 0 ? row.durationMs / model.durationMs : 1
|
|
22407
|
+
)
|
|
22408
|
+
};
|
|
22409
|
+
const rowContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Fragment, { children: [
|
|
22410
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-time", children: formatTimelineTimestamp(row.startedAt) }),
|
|
22411
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-branch", children: [
|
|
22412
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-gutter", "aria-hidden": "true", children: [
|
|
22413
|
+
row.ancestorContinuations.map((continues, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22414
|
+
"span",
|
|
22415
|
+
{
|
|
22416
|
+
className: cn(
|
|
22417
|
+
"hierarchy-timeline-row-ancestor",
|
|
22418
|
+
continues && "has-line"
|
|
22220
22419
|
),
|
|
22221
|
-
|
|
22222
|
-
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
|
|
22420
|
+
style: {
|
|
22421
|
+
"--timeline-connector-index": String(index)
|
|
22422
|
+
}
|
|
22423
|
+
},
|
|
22424
|
+
`${row.id}-ancestor-${index}`
|
|
22425
|
+
)),
|
|
22426
|
+
row.depth > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22427
|
+
"span",
|
|
22428
|
+
{
|
|
22429
|
+
className: "hierarchy-timeline-row-connector",
|
|
22430
|
+
style: {
|
|
22431
|
+
"--timeline-connector-index": String(row.depth - 1)
|
|
22432
|
+
},
|
|
22433
|
+
children: [
|
|
22434
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-connector-top" }),
|
|
22435
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-connector-elbow" }),
|
|
22436
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22437
|
+
"span",
|
|
22234
22438
|
{
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
children: rowContent
|
|
22439
|
+
className: cn(
|
|
22440
|
+
"hierarchy-timeline-row-connector-bottom",
|
|
22441
|
+
(row.hasVisibleChildren || !row.isLastSibling) && "has-line"
|
|
22442
|
+
)
|
|
22240
22443
|
}
|
|
22241
22444
|
)
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22246
|
-
|
|
22247
|
-
|
|
22445
|
+
]
|
|
22446
|
+
}
|
|
22447
|
+
) : null
|
|
22448
|
+
] }),
|
|
22449
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-labels", children: [
|
|
22450
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-title", children: [
|
|
22451
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-title-text", children: row.label }),
|
|
22452
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22453
|
+
Badge,
|
|
22454
|
+
{
|
|
22455
|
+
variant: "secondary",
|
|
22456
|
+
className: "hierarchy-timeline-pill",
|
|
22457
|
+
semantic: row.badge,
|
|
22458
|
+
children: row.badge
|
|
22459
|
+
}
|
|
22460
|
+
),
|
|
22461
|
+
row.hasStructuredInput ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22462
|
+
"span",
|
|
22463
|
+
{
|
|
22464
|
+
className: "hierarchy-timeline-row-flag",
|
|
22465
|
+
title: "Structured input detected for this call",
|
|
22466
|
+
children: "Structured input"
|
|
22467
|
+
}
|
|
22468
|
+
) : null,
|
|
22469
|
+
row.hasHighlights && !row.hasStructuredInput ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22470
|
+
"span",
|
|
22471
|
+
{
|
|
22472
|
+
className: "hierarchy-timeline-row-flag is-highlight",
|
|
22473
|
+
title: "Trace insights available",
|
|
22474
|
+
children: "Insight"
|
|
22475
|
+
}
|
|
22476
|
+
) : null
|
|
22477
|
+
] }),
|
|
22478
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-meta", children: row.meta })
|
|
22479
|
+
] })
|
|
22480
|
+
] }),
|
|
22481
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-bars", children: [
|
|
22482
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-track", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-bar" }) }),
|
|
22483
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-duration", children: formatElapsedLabel(row.durationMs) })
|
|
22484
|
+
] })
|
|
22485
|
+
] });
|
|
22486
|
+
if (isTraceRow) {
|
|
22487
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22488
|
+
"div",
|
|
22489
|
+
{
|
|
22490
|
+
role: "listitem",
|
|
22491
|
+
title: buildHierarchyTimelineRowTooltip(row),
|
|
22492
|
+
"aria-current": row.isActive || row.isDetailTrace ? "true" : void 0,
|
|
22493
|
+
"data-hierarchy-row-id": row.id,
|
|
22494
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22495
|
+
"button",
|
|
22248
22496
|
{
|
|
22249
|
-
|
|
22497
|
+
type: "button",
|
|
22250
22498
|
className: rowClassName,
|
|
22251
22499
|
style: rowStyle,
|
|
22252
|
-
|
|
22253
|
-
"aria-current": row.isActive || row.isDetailTrace ? "true" : void 0,
|
|
22254
|
-
"data-hierarchy-row-id": row.id,
|
|
22500
|
+
onClick: () => onSelectRow(row.id),
|
|
22255
22501
|
children: rowContent
|
|
22256
|
-
}
|
|
22257
|
-
|
|
22258
|
-
|
|
22259
|
-
|
|
22260
|
-
|
|
22261
|
-
|
|
22262
|
-
|
|
22502
|
+
}
|
|
22503
|
+
)
|
|
22504
|
+
},
|
|
22505
|
+
row.id
|
|
22506
|
+
);
|
|
22507
|
+
}
|
|
22508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22509
|
+
"div",
|
|
22510
|
+
{
|
|
22511
|
+
role: "listitem",
|
|
22512
|
+
className: rowClassName,
|
|
22513
|
+
style: rowStyle,
|
|
22514
|
+
title: buildHierarchyTimelineRowTooltip(row),
|
|
22515
|
+
"aria-current": row.isActive || row.isDetailTrace ? "true" : void 0,
|
|
22516
|
+
"data-hierarchy-row-id": row.id,
|
|
22517
|
+
children: rowContent
|
|
22518
|
+
},
|
|
22519
|
+
row.id
|
|
22520
|
+
);
|
|
22521
|
+
});
|
|
22263
22522
|
}
|
|
22264
22523
|
function TraceDetailPanel({
|
|
22265
22524
|
activeTab,
|
|
@@ -22271,10 +22530,8 @@ function TraceDetailPanel({
|
|
|
22271
22530
|
onApplyTraceFilter,
|
|
22272
22531
|
onBack,
|
|
22273
22532
|
onNavigateHierarchyNode,
|
|
22274
|
-
onSelectTimelineNode,
|
|
22275
22533
|
onTabChange,
|
|
22276
|
-
onToggleJsonMode
|
|
22277
|
-
timelineModel
|
|
22534
|
+
onToggleJsonMode
|
|
22278
22535
|
}) {
|
|
22279
22536
|
const traceDetailPrimaryRef = (0, import_react3.useRef)(null);
|
|
22280
22537
|
const [showInlineContextRail, setShowInlineContextRail] = (0, import_react3.useState)(false);
|
|
@@ -22284,7 +22541,6 @@ function TraceDetailPanel({
|
|
|
22284
22541
|
const detailSubtitle = formatTraceProviderSummary(detail ?? fallbackTrace);
|
|
22285
22542
|
const detailCostUsd = detail ? getUsageCostUsd(detail.usage) : fallbackTrace?.costUsd ?? null;
|
|
22286
22543
|
const detailCostLabel = formatUsdCost(detailCostUsd);
|
|
22287
|
-
const hasSecondaryInspector = Boolean(detail && timelineModel);
|
|
22288
22544
|
const detailFilterSource = detail ?? fallbackTrace;
|
|
22289
22545
|
const canInlineContextRailTab = activeTab === "conversation" || activeTab === "request" || activeTab === "response";
|
|
22290
22546
|
const visibleDetailTabs = canInlineContextRailTab && showInlineContextRail ? detailTabs.filter((tab) => tab.id !== "context") : detailTabs;
|
|
@@ -22386,77 +22642,59 @@ function TraceDetailPanel({
|
|
|
22386
22642
|
onBack ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { variant: "outline", onClick: onBack, children: "Show hierarchy" }) }) : null
|
|
22387
22643
|
] }),
|
|
22388
22644
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator, {}),
|
|
22389
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-body", children: detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22390
|
-
"div",
|
|
22391
|
-
|
|
22392
|
-
|
|
22393
|
-
|
|
22394
|
-
|
|
22395
|
-
|
|
22396
|
-
|
|
22397
|
-
|
|
22398
|
-
|
|
22399
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22400
|
-
|
|
22401
|
-
|
|
22645
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-body", children: detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-main", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "trace-detail-primary", ref: traceDetailPrimaryRef, children: [
|
|
22646
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "trace-detail-toolbar", children: [
|
|
22647
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-tabs-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tabs, { value: activeTab, onChange: onTabChange, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsList, { className: "detail-tabs", children: visibleDetailTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsTrigger, { value: tab.id, children: tab.label }, tab.id)) }) }) }),
|
|
22648
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22649
|
+
Button,
|
|
22650
|
+
{
|
|
22651
|
+
variant: "outline",
|
|
22652
|
+
className: "trace-detail-json-toggle",
|
|
22653
|
+
onClick: () => onToggleJsonMode(activeTab),
|
|
22654
|
+
children: [
|
|
22655
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Boxes, { "data-icon": "inline-start" }),
|
|
22656
|
+
jsonMode === "formatted" ? "Raw JSON" : "Formatted"
|
|
22657
|
+
]
|
|
22658
|
+
}
|
|
22659
|
+
)
|
|
22660
|
+
] }),
|
|
22661
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator, {}),
|
|
22662
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-pane", children: showContextRailInPrimary ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "detail-inline-context-layout", children: [
|
|
22663
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "detail-inline-context-main", children: renderTabContent(
|
|
22664
|
+
activeTab,
|
|
22665
|
+
detail,
|
|
22666
|
+
jsonMode,
|
|
22667
|
+
onApplyTagFilter,
|
|
22668
|
+
onApplyTraceFilter
|
|
22669
|
+
) }),
|
|
22670
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22671
|
+
"aside",
|
|
22672
|
+
{
|
|
22673
|
+
className: "conversation-context-rail",
|
|
22674
|
+
"aria-label": "Context summary",
|
|
22675
|
+
children: [
|
|
22676
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-context-rail-header", children: [
|
|
22677
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-context-rail-title", children: "Context" }),
|
|
22678
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-context-rail-copy", children: "Key trace metadata alongside the conversation." })
|
|
22679
|
+
] }),
|
|
22680
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22681
|
+
ContextInspectorView,
|
|
22402
22682
|
{
|
|
22403
|
-
|
|
22404
|
-
|
|
22405
|
-
onClick: () => onToggleJsonMode(activeTab),
|
|
22406
|
-
children: [
|
|
22407
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Boxes, { "data-icon": "inline-start" }),
|
|
22408
|
-
jsonMode === "formatted" ? "Raw JSON" : "Formatted"
|
|
22409
|
-
]
|
|
22683
|
+
detail,
|
|
22684
|
+
onApplyTagFilter
|
|
22410
22685
|
}
|
|
22411
22686
|
)
|
|
22412
|
-
]
|
|
22413
|
-
|
|
22414
|
-
|
|
22415
|
-
|
|
22416
|
-
|
|
22417
|
-
|
|
22418
|
-
|
|
22419
|
-
|
|
22420
|
-
|
|
22421
|
-
|
|
22422
|
-
|
|
22423
|
-
"aside",
|
|
22424
|
-
{
|
|
22425
|
-
className: "conversation-context-rail",
|
|
22426
|
-
"aria-label": "Context summary",
|
|
22427
|
-
children: [
|
|
22428
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-context-rail-header", children: [
|
|
22429
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-context-rail-title", children: "Context" }),
|
|
22430
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-context-rail-copy", children: "Key trace metadata alongside the conversation." })
|
|
22431
|
-
] }),
|
|
22432
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22433
|
-
ContextInspectorView,
|
|
22434
|
-
{
|
|
22435
|
-
detail,
|
|
22436
|
-
onApplyTagFilter
|
|
22437
|
-
}
|
|
22438
|
-
)
|
|
22439
|
-
]
|
|
22440
|
-
}
|
|
22441
|
-
)
|
|
22442
|
-
] }) : renderTabContent(
|
|
22443
|
-
activeTab,
|
|
22444
|
-
detail,
|
|
22445
|
-
jsonMode,
|
|
22446
|
-
onApplyTagFilter,
|
|
22447
|
-
onApplyTraceFilter
|
|
22448
|
-
) }) })
|
|
22449
|
-
] }),
|
|
22450
|
-
timelineModel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("aside", { className: "trace-detail-secondary", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22451
|
-
HierarchyTimelineOverview,
|
|
22452
|
-
{
|
|
22453
|
-
model: timelineModel,
|
|
22454
|
-
onSelectRow: onSelectTimelineNode
|
|
22455
|
-
}
|
|
22456
|
-
) }) : null
|
|
22457
|
-
]
|
|
22458
|
-
}
|
|
22459
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-empty", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22687
|
+
]
|
|
22688
|
+
}
|
|
22689
|
+
)
|
|
22690
|
+
] }) : renderTabContent(
|
|
22691
|
+
activeTab,
|
|
22692
|
+
detail,
|
|
22693
|
+
jsonMode,
|
|
22694
|
+
onApplyTagFilter,
|
|
22695
|
+
onApplyTraceFilter
|
|
22696
|
+
) }) })
|
|
22697
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-empty", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22460
22698
|
EmptyState,
|
|
22461
22699
|
{
|
|
22462
22700
|
icon: ArrowUpRight,
|
|
@@ -23528,52 +23766,6 @@ function buildDetailTabs(detail) {
|
|
|
23528
23766
|
}
|
|
23529
23767
|
return tabs;
|
|
23530
23768
|
}
|
|
23531
|
-
function findNodeById(nodes, id) {
|
|
23532
|
-
for (const node of nodes) {
|
|
23533
|
-
if (node.id === id) {
|
|
23534
|
-
return node;
|
|
23535
|
-
}
|
|
23536
|
-
const child = findNodeById(node.children, id);
|
|
23537
|
-
if (child) {
|
|
23538
|
-
return child;
|
|
23539
|
-
}
|
|
23540
|
-
}
|
|
23541
|
-
return null;
|
|
23542
|
-
}
|
|
23543
|
-
function findNodePath(nodes, id, trail = []) {
|
|
23544
|
-
for (const node of nodes) {
|
|
23545
|
-
const nextTrail = [...trail, node];
|
|
23546
|
-
if (node.id === id) {
|
|
23547
|
-
return nextTrail;
|
|
23548
|
-
}
|
|
23549
|
-
const childTrail = findNodePath(node.children, id, nextTrail);
|
|
23550
|
-
if (childTrail.length) {
|
|
23551
|
-
return childTrail;
|
|
23552
|
-
}
|
|
23553
|
-
}
|
|
23554
|
-
return [];
|
|
23555
|
-
}
|
|
23556
|
-
function getNewestTraceId(node) {
|
|
23557
|
-
if (!node?.traceIds.length) {
|
|
23558
|
-
return null;
|
|
23559
|
-
}
|
|
23560
|
-
return node.traceIds[0] || null;
|
|
23561
|
-
}
|
|
23562
|
-
function getDefaultExpandedNodeIds(nodes) {
|
|
23563
|
-
const expanded = /* @__PURE__ */ new Set();
|
|
23564
|
-
const visit = (node) => {
|
|
23565
|
-
if (node.children.length && (node.type === "session" || node.type === "actor")) {
|
|
23566
|
-
expanded.add(node.id);
|
|
23567
|
-
}
|
|
23568
|
-
for (const child of node.children) {
|
|
23569
|
-
visit(child);
|
|
23570
|
-
}
|
|
23571
|
-
};
|
|
23572
|
-
for (const node of nodes) {
|
|
23573
|
-
visit(node);
|
|
23574
|
-
}
|
|
23575
|
-
return expanded;
|
|
23576
|
-
}
|
|
23577
23769
|
function getHierarchyNodeCopy(node, traceById) {
|
|
23578
23770
|
switch (node.type) {
|
|
23579
23771
|
case "session":
|
|
@@ -23710,40 +23902,6 @@ function formatTraceProviderSummary(trace) {
|
|
|
23710
23902
|
}
|
|
23711
23903
|
return formatList([trace.provider, trace.model]);
|
|
23712
23904
|
}
|
|
23713
|
-
function groupTracesForNav(items) {
|
|
23714
|
-
const groups = /* @__PURE__ */ new Map();
|
|
23715
|
-
const uniqueSessions = new Set(items.map((item) => item.hierarchy.sessionId));
|
|
23716
|
-
const groupMode = uniqueSessions.size > 1 ? "session" : "kind";
|
|
23717
|
-
for (const item of items) {
|
|
23718
|
-
const key = groupMode === "session" ? `session:${item.hierarchy.sessionId || "unknown-session"}` : `kind:${item.kind}:${item.hierarchy.guardrailPhase || item.hierarchy.stage || item.mode}`;
|
|
23719
|
-
const group = groups.get(key) ?? [];
|
|
23720
|
-
group.push(item);
|
|
23721
|
-
groups.set(key, group);
|
|
23722
|
-
}
|
|
23723
|
-
return [...groups.entries()].map(([groupKey, traces]) => {
|
|
23724
|
-
const latestStartedAt = traces[0]?.startedAt ?? null;
|
|
23725
|
-
return {
|
|
23726
|
-
costUsd: sumTraceCosts(traces),
|
|
23727
|
-
id: `trace-group:${groupKey}`,
|
|
23728
|
-
isAggregateCost: traces.length > 1,
|
|
23729
|
-
items: traces,
|
|
23730
|
-
label: groupMode === "session" ? `Session ${shortId2(traces[0]?.hierarchy.sessionId || "unknown")}` : getTraceActorLabel(traces[0]),
|
|
23731
|
-
meta: formatList([
|
|
23732
|
-
latestStartedAt ? formatCompactTimestamp2(latestStartedAt) : null,
|
|
23733
|
-
formatCountLabel(traces.length, "trace")
|
|
23734
|
-
]) || "No metadata"
|
|
23735
|
-
};
|
|
23736
|
-
});
|
|
23737
|
-
}
|
|
23738
|
-
function sumTraceCosts(items) {
|
|
23739
|
-
const costs = items.map((item) => item.costUsd).filter(
|
|
23740
|
-
(value) => value !== null && Number.isFinite(value)
|
|
23741
|
-
);
|
|
23742
|
-
if (!costs.length) {
|
|
23743
|
-
return null;
|
|
23744
|
-
}
|
|
23745
|
-
return roundCostUsd2(costs.reduce((sum, value) => sum + value, 0));
|
|
23746
|
-
}
|
|
23747
23905
|
function getTraceActorLabel(trace) {
|
|
23748
23906
|
if (trace.kind === "guardrail") {
|
|
23749
23907
|
return `${capitalize(trace.hierarchy.guardrailPhase || "guardrail")} guardrail`;
|
|
@@ -24287,9 +24445,6 @@ async function copyText(value) {
|
|
|
24287
24445
|
return false;
|
|
24288
24446
|
}
|
|
24289
24447
|
}
|
|
24290
|
-
function toSessionNodeId(sessionId) {
|
|
24291
|
-
return `session:${sessionId}`;
|
|
24292
|
-
}
|
|
24293
24448
|
function toTraceNodeId(traceId) {
|
|
24294
24449
|
return `trace:${traceId}`;
|
|
24295
24450
|
}
|
|
@@ -24784,12 +24939,6 @@ function getSemanticBadgeValue(value) {
|
|
|
24784
24939
|
return null;
|
|
24785
24940
|
}
|
|
24786
24941
|
}
|
|
24787
|
-
function formatCompactTimestamp2(value) {
|
|
24788
|
-
return new Date(value).toLocaleTimeString([], {
|
|
24789
|
-
hour: "2-digit",
|
|
24790
|
-
minute: "2-digit"
|
|
24791
|
-
});
|
|
24792
|
-
}
|
|
24793
24942
|
function formatTimelineTimestamp(value) {
|
|
24794
24943
|
return new Date(value).toLocaleTimeString([], {
|
|
24795
24944
|
hour: "2-digit",
|
|
@@ -24803,6 +24952,14 @@ function getMaxDurationMs(items) {
|
|
|
24803
24952
|
);
|
|
24804
24953
|
return durations.length ? Math.max(...durations) : 1;
|
|
24805
24954
|
}
|
|
24955
|
+
function getElapsedScale(durationMs, maxDurationMs) {
|
|
24956
|
+
if (durationMs === null || durationMs <= 0 || !Number.isFinite(durationMs)) {
|
|
24957
|
+
return 0.16;
|
|
24958
|
+
}
|
|
24959
|
+
const safeMax = Math.max(maxDurationMs, durationMs, 1);
|
|
24960
|
+
const ratio = Math.log1p(durationMs) / Math.log1p(safeMax);
|
|
24961
|
+
return Math.max(0.14, Math.min(1, ratio));
|
|
24962
|
+
}
|
|
24806
24963
|
function formatElapsedLabel(durationMs) {
|
|
24807
24964
|
if (durationMs === null || !Number.isFinite(durationMs)) {
|
|
24808
24965
|
return "Running";
|
|
@@ -24993,7 +25150,7 @@ function parseEvent(data) {
|
|
|
24993
25150
|
return null;
|
|
24994
25151
|
}
|
|
24995
25152
|
}
|
|
24996
|
-
var import_react3, import_jsx_runtime, MESSAGE_COLLAPSE_CHAR_LIMIT, MESSAGE_COLLAPSE_LINE_LIMIT, MESSAGE_COLLAPSE_HEIGHT_PROSE, MESSAGE_COLLAPSE_HEIGHT_STRUCTURED, MESSAGE_COLLAPSE_CHAR_LIMIT_SYSTEM, MESSAGE_COLLAPSE_LINE_LIMIT_SYSTEM, MESSAGE_COLLAPSE_HEIGHT_PROSE_SYSTEM, MESSAGE_COLLAPSE_HEIGHT_STRUCTURED_SYSTEM,
|
|
25153
|
+
var import_react3, import_jsx_runtime, MESSAGE_COLLAPSE_CHAR_LIMIT, MESSAGE_COLLAPSE_LINE_LIMIT, MESSAGE_COLLAPSE_HEIGHT_PROSE, MESSAGE_COLLAPSE_HEIGHT_STRUCTURED, MESSAGE_COLLAPSE_CHAR_LIMIT_SYSTEM, MESSAGE_COLLAPSE_LINE_LIMIT_SYSTEM, MESSAGE_COLLAPSE_HEIGHT_PROSE_SYSTEM, MESSAGE_COLLAPSE_HEIGHT_STRUCTURED_SYSTEM, EMPTY_TRACE_INSIGHTS, MarkdownBlock, STATUS_OPTIONS, KIND_OPTIONS, INITIAL_FILTERS;
|
|
24997
25154
|
var init_app = __esm({
|
|
24998
25155
|
"client/src/app.tsx"() {
|
|
24999
25156
|
init_lucide_react();
|
|
@@ -25011,8 +25168,6 @@ var init_app = __esm({
|
|
|
25011
25168
|
MESSAGE_COLLAPSE_LINE_LIMIT_SYSTEM = 5;
|
|
25012
25169
|
MESSAGE_COLLAPSE_HEIGHT_PROSE_SYSTEM = "9rem";
|
|
25013
25170
|
MESSAGE_COLLAPSE_HEIGHT_STRUCTURED_SYSTEM = "9rem";
|
|
25014
|
-
TIMELINE_AXIS_STOPS = [0, 0.25, 0.5, 0.75, 1];
|
|
25015
|
-
COMPACT_TIMELINE_AXIS_STOPS = [0, 0.5, 1];
|
|
25016
25171
|
EMPTY_TRACE_INSIGHTS = {
|
|
25017
25172
|
highlights: [],
|
|
25018
25173
|
structuredInputs: []
|