@mtharrison/loupe 1.1.1 → 1.3.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 +155 -41
- package/assets/screenshot1.png +0 -0
- package/assets/screenshot2.png +0 -0
- package/dist/client/app.css +365 -263
- package/dist/client/app.js +815 -658
- package/dist/index.d.ts +7 -8
- package/dist/index.js +392 -49
- 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/store.d.ts +6 -7
- package/dist/store.js +203 -45
- package/dist/types.d.ts +62 -9
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +14 -0
- package/examples/nested-tool-call.js +234 -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);
|
|
@@ -21322,34 +21395,36 @@ function App() {
|
|
|
21322
21395
|
});
|
|
21323
21396
|
const handleSseMessage = (0, import_react3.useEffectEvent)((data2) => {
|
|
21324
21397
|
const payload = parseEvent(data2);
|
|
21398
|
+
const nextTrace = payload?.span;
|
|
21399
|
+
const nextTraceId = payload?.spanId;
|
|
21325
21400
|
if (payload?.type === "ui:reload") {
|
|
21326
21401
|
window.location.reload();
|
|
21327
21402
|
return;
|
|
21328
21403
|
}
|
|
21329
|
-
if (
|
|
21330
|
-
(0, import_react3.startTransition)(() => setDetail(
|
|
21404
|
+
if (nextTrace && selectedTraceId && nextTraceId === selectedTraceId) {
|
|
21405
|
+
(0, import_react3.startTransition)(() => setDetail(nextTrace));
|
|
21331
21406
|
}
|
|
21332
21407
|
if (!queryString) {
|
|
21333
|
-
if (payload?.type === "
|
|
21334
|
-
applyIncrementalTraceUpdate(
|
|
21408
|
+
if ((payload?.type === "span:update" || payload?.type === "span:end") && nextTrace) {
|
|
21409
|
+
applyIncrementalTraceUpdate(nextTrace);
|
|
21335
21410
|
return;
|
|
21336
21411
|
}
|
|
21337
|
-
if (payload?.type === "
|
|
21338
|
-
applyIncrementalTraceAdd(
|
|
21412
|
+
if (payload?.type === "span:start" && nextTrace) {
|
|
21413
|
+
applyIncrementalTraceAdd(nextTrace);
|
|
21339
21414
|
scheduleRefresh(180);
|
|
21340
21415
|
return;
|
|
21341
21416
|
}
|
|
21342
|
-
if (payload?.type === "
|
|
21343
|
-
applyIncrementalTraceEvict(
|
|
21417
|
+
if (payload?.type === "span:evict") {
|
|
21418
|
+
applyIncrementalTraceEvict(nextTraceId);
|
|
21344
21419
|
scheduleRefresh(180);
|
|
21345
21420
|
return;
|
|
21346
21421
|
}
|
|
21347
|
-
if (payload?.type === "
|
|
21422
|
+
if (payload?.type === "span:clear") {
|
|
21348
21423
|
clearIncrementalState();
|
|
21349
21424
|
return;
|
|
21350
21425
|
}
|
|
21351
21426
|
}
|
|
21352
|
-
scheduleRefresh(payload?.type === "
|
|
21427
|
+
scheduleRefresh(payload?.type === "span:update" || payload?.type === "span:end" ? 700 : 180);
|
|
21353
21428
|
});
|
|
21354
21429
|
(0, import_react3.useEffect)(() => {
|
|
21355
21430
|
const events = new EventSource("/api/events");
|
|
@@ -21373,75 +21448,61 @@ function App() {
|
|
|
21373
21448
|
() => getMaxDurationMs(traceItems),
|
|
21374
21449
|
[traceItems]
|
|
21375
21450
|
);
|
|
21376
|
-
const traceGroups = (0, import_react3.useMemo)(
|
|
21377
|
-
() => groupTracesForNav(traceItems),
|
|
21378
|
-
[traceItems]
|
|
21379
|
-
);
|
|
21380
21451
|
const sessionNodes = (0, import_react3.useMemo)(
|
|
21381
|
-
() =>
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21385
|
-
|
|
21386
|
-
[sessionNodes]
|
|
21452
|
+
() => sortSessionNodesForNav(
|
|
21453
|
+
data.hierarchy.rootNodes.filter((node) => node.type === "session"),
|
|
21454
|
+
traceById
|
|
21455
|
+
),
|
|
21456
|
+
[data.hierarchy.rootNodes, traceById]
|
|
21387
21457
|
);
|
|
21388
21458
|
const sessionNavItems = (0, import_react3.useMemo)(
|
|
21389
21459
|
() => deriveSessionNavItems(sessionNodes, traceById),
|
|
21390
21460
|
[sessionNodes, traceById]
|
|
21391
21461
|
);
|
|
21462
|
+
const sessionNavById = (0, import_react3.useMemo)(
|
|
21463
|
+
() => new Map(sessionNavItems.map((item) => [item.id, item])),
|
|
21464
|
+
[sessionNavItems]
|
|
21465
|
+
);
|
|
21392
21466
|
const hasActiveFilters = Boolean(
|
|
21393
21467
|
filters.search || filters.status || filters.kind || filters.tags
|
|
21394
21468
|
);
|
|
21395
|
-
const filteredSessionCount =
|
|
21469
|
+
const filteredSessionCount = sessionNodes.length;
|
|
21396
21470
|
const hasRecordedSessions = allSessionCount > 0;
|
|
21397
21471
|
const showFilteredSessionEmptyState = hasActiveFilters && hasRecordedSessions && filteredSessionCount === 0;
|
|
21472
|
+
const selectedNodePath = (0, import_react3.useMemo)(
|
|
21473
|
+
() => selectedNodeId ? findSessionNodePath(sessionNodes, selectedNodeId) : [],
|
|
21474
|
+
[sessionNodes, selectedNodeId]
|
|
21475
|
+
);
|
|
21476
|
+
const selectedTracePath = (0, import_react3.useMemo)(
|
|
21477
|
+
() => selectedTraceId ? findSessionNodePath(sessionNodes, toTraceNodeId(selectedTraceId)) : [],
|
|
21478
|
+
[sessionNodes, selectedTraceId]
|
|
21479
|
+
);
|
|
21480
|
+
const selectedPathIds = (0, import_react3.useMemo)(
|
|
21481
|
+
() => new Set(selectedNodePath.map((node) => node.id)),
|
|
21482
|
+
[selectedNodePath]
|
|
21483
|
+
);
|
|
21398
21484
|
const selectedSessionNode = (0, import_react3.useMemo)(
|
|
21399
|
-
() =>
|
|
21400
|
-
[
|
|
21485
|
+
() => (selectedNodePath[0]?.type === "session" ? selectedNodePath[0] : null) ?? (selectedTracePath[0]?.type === "session" ? selectedTracePath[0] : null) ?? sessionNodes[0] ?? null,
|
|
21486
|
+
[selectedNodePath, selectedTracePath, sessionNodes]
|
|
21401
21487
|
);
|
|
21402
21488
|
const selectedTraceSummary = (0, import_react3.useMemo)(
|
|
21403
21489
|
() => selectedTraceId ? traceById.get(selectedTraceId) ?? null : null,
|
|
21404
21490
|
[selectedTraceId, traceById]
|
|
21405
21491
|
);
|
|
21406
21492
|
(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
|
-
}
|
|
21493
|
+
const nextSelection = resolveSessionTreeSelection(
|
|
21494
|
+
sessionNodes,
|
|
21495
|
+
selectedNodeId,
|
|
21496
|
+
selectedTraceId
|
|
21497
|
+
);
|
|
21498
|
+
if (nextSelection.selectedNodeId === selectedNodeId && nextSelection.selectedTraceId === selectedTraceId) {
|
|
21430
21499
|
return;
|
|
21431
21500
|
}
|
|
21432
|
-
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
}, [
|
|
21438
|
-
data.hierarchy.rootNodes,
|
|
21439
|
-
navMode,
|
|
21440
|
-
selectedNodeId,
|
|
21441
|
-
selectedSessionNode,
|
|
21442
|
-
selectedTraceId,
|
|
21443
|
-
traceItems
|
|
21444
|
-
]);
|
|
21501
|
+
(0, import_react3.startTransition)(() => {
|
|
21502
|
+
setSelectedNodeId(nextSelection.selectedNodeId);
|
|
21503
|
+
setSelectedTraceId(nextSelection.selectedTraceId);
|
|
21504
|
+
});
|
|
21505
|
+
}, [selectedNodeId, selectedTraceId, sessionNodes]);
|
|
21445
21506
|
const loadDetail = (0, import_react3.useEffectEvent)(async (traceId) => {
|
|
21446
21507
|
const requestId = detailRequestRef.current + 1;
|
|
21447
21508
|
detailRequestRef.current = requestId;
|
|
@@ -21468,43 +21529,13 @@ function App() {
|
|
|
21468
21529
|
void loadDetail(selectedTraceId);
|
|
21469
21530
|
}, [selectedTraceId]);
|
|
21470
21531
|
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
|
|
21532
|
+
() => getDefaultExpandedSessionTreeNodeIds(
|
|
21533
|
+
sessionNodes,
|
|
21534
|
+
selectedSessionNode?.id ?? null,
|
|
21535
|
+
selectedNodeId
|
|
21485
21536
|
),
|
|
21486
|
-
[
|
|
21487
|
-
selectedNodeId,
|
|
21488
|
-
selectedNodePath,
|
|
21489
|
-
selectedSessionNode,
|
|
21490
|
-
selectedTraceId,
|
|
21491
|
-
traceById
|
|
21492
|
-
]
|
|
21537
|
+
[selectedNodeId, selectedSessionNode, sessionNodes]
|
|
21493
21538
|
);
|
|
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
21539
|
const activeTabJsonMode = tabModes[detailTab] ?? "formatted";
|
|
21509
21540
|
const activeTagFilterCount = countTagFilters(filters.tags);
|
|
21510
21541
|
const onFilterChange = (key, value) => {
|
|
@@ -21543,24 +21574,13 @@ function App() {
|
|
|
21543
21574
|
}));
|
|
21544
21575
|
});
|
|
21545
21576
|
};
|
|
21546
|
-
const toggleTraceGroupCollapse = (groupId) => {
|
|
21547
|
-
(0, import_react3.startTransition)(() => {
|
|
21548
|
-
setCollapsedTraceGroups((current) => ({
|
|
21549
|
-
...current,
|
|
21550
|
-
[groupId]: !current[groupId]
|
|
21551
|
-
}));
|
|
21552
|
-
});
|
|
21553
|
-
};
|
|
21554
21577
|
const resetFilters = () => {
|
|
21555
|
-
const nextSessionNode = (sessionNavItems[0] && sessionNodeById.get(sessionNavItems[0].id)) ?? null;
|
|
21556
21578
|
(0, import_react3.startTransition)(() => {
|
|
21557
21579
|
setFilters(INITIAL_FILTERS);
|
|
21558
21580
|
setShowAdvancedFilters(false);
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
|
|
21562
|
-
navMode === "traces" ? traceItems[0]?.id ?? null : getNewestTraceId(nextSessionNode)
|
|
21563
|
-
);
|
|
21581
|
+
setSelectedNodeId(null);
|
|
21582
|
+
setSelectedTraceId(null);
|
|
21583
|
+
setDetailTab("conversation");
|
|
21564
21584
|
});
|
|
21565
21585
|
};
|
|
21566
21586
|
const clearTraces = async () => {
|
|
@@ -21594,78 +21614,21 @@ function App() {
|
|
|
21594
21614
|
() => setIsSessionsPanelCollapsed((current) => !current)
|
|
21595
21615
|
);
|
|
21596
21616
|
};
|
|
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
21617
|
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;
|
|
21618
|
+
const nextTraceId = node.type === "trace" ? node.meta.traceId ?? node.traceIds[0] ?? null : getNewestTraceIdForNode(node);
|
|
21642
21619
|
(0, import_react3.startTransition)(() => {
|
|
21643
|
-
|
|
21644
|
-
setSelectedSessionId(nextSessionId ?? null);
|
|
21645
|
-
setSelectedNodeId(nextSelectedNodeId);
|
|
21620
|
+
setSelectedNodeId(node.id);
|
|
21646
21621
|
setSelectedTraceId(nextTraceId);
|
|
21647
21622
|
setDetailTab("conversation");
|
|
21648
21623
|
});
|
|
21649
21624
|
};
|
|
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
21625
|
const navigateToHierarchyNode = (nodeId) => {
|
|
21659
|
-
const node =
|
|
21626
|
+
const node = findSessionNodeById(sessionNodes, nodeId);
|
|
21660
21627
|
if (!node) {
|
|
21661
21628
|
return;
|
|
21662
21629
|
}
|
|
21663
|
-
const
|
|
21664
|
-
const nextSessionId = nodePath[0]?.type === "session" ? nodePath[0].id : selectedSessionId;
|
|
21665
|
-
const nextTraceId = selectedTraceId && node.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceId(node);
|
|
21630
|
+
const nextTraceId = selectedTraceId && node.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceIdForNode(node);
|
|
21666
21631
|
(0, import_react3.startTransition)(() => {
|
|
21667
|
-
setNavMode("sessions");
|
|
21668
|
-
setSelectedSessionId(nextSessionId ?? null);
|
|
21669
21632
|
setSelectedNodeId(nodeId);
|
|
21670
21633
|
if (nextTraceId !== selectedTraceId) {
|
|
21671
21634
|
setSelectedTraceId(nextTraceId);
|
|
@@ -21674,17 +21637,6 @@ function App() {
|
|
|
21674
21637
|
};
|
|
21675
21638
|
const detailTabs = buildDetailTabs(detail);
|
|
21676
21639
|
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
21640
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "app-shell", children: [
|
|
21689
21641
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BackgroundGlow, {}),
|
|
21690
21642
|
/* @__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 +21765,45 @@ function App() {
|
|
|
21813
21765
|
isSessionsPanelCollapsed && "is-sidebar-collapsed"
|
|
21814
21766
|
),
|
|
21815
21767
|
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)(
|
|
21768
|
+
/* @__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)(
|
|
21769
|
+
SessionTreeNavigator,
|
|
21770
|
+
{
|
|
21771
|
+
defaultExpandedNodeIds,
|
|
21772
|
+
expandedNodeOverrides,
|
|
21773
|
+
hasActiveFilters,
|
|
21774
|
+
items: sessionNavItems,
|
|
21775
|
+
maxDurationMs: navigatorMaxDurationMs,
|
|
21776
|
+
nodes: sessionNodes,
|
|
21777
|
+
onSelect: handleHierarchySelect,
|
|
21778
|
+
onToggle: toggleNodeExpansion,
|
|
21779
|
+
selectedNodeId,
|
|
21780
|
+
selectedPathIds,
|
|
21781
|
+
selectedTraceId,
|
|
21782
|
+
sessionNavById,
|
|
21783
|
+
totalCount: allSessionCount,
|
|
21784
|
+
traceById
|
|
21785
|
+
}
|
|
21786
|
+
) : /* @__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: [
|
|
21787
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21848
21788
|
EmptyState,
|
|
21849
21789
|
{
|
|
21850
|
-
icon:
|
|
21851
|
-
title: "No sessions
|
|
21852
|
-
description: "
|
|
21790
|
+
icon: Funnel,
|
|
21791
|
+
title: "No sessions match the current filters",
|
|
21792
|
+
description: "Try adjusting the search, status, kind, or tag filters to broaden the result set."
|
|
21853
21793
|
}
|
|
21854
|
-
)
|
|
21855
|
-
|
|
21794
|
+
),
|
|
21795
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, { variant: "outline", onClick: resetFilters, children: [
|
|
21796
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { "data-icon": "inline-start" }),
|
|
21797
|
+
"Clear filters"
|
|
21798
|
+
] })
|
|
21799
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21800
|
+
EmptyState,
|
|
21801
|
+
{
|
|
21802
|
+
icon: Network,
|
|
21803
|
+
title: "No sessions yet",
|
|
21804
|
+
description: "Trigger any traced LLM call and the session tree will appear here."
|
|
21805
|
+
}
|
|
21806
|
+
) }) }) }),
|
|
21856
21807
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { className: "timeline-card content-card inspector-card", children: selectedTraceId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21857
21808
|
TraceDetailPanel,
|
|
21858
21809
|
{
|
|
@@ -21865,20 +21816,18 @@ function App() {
|
|
|
21865
21816
|
onApplyTraceFilter: applyTraceFilter,
|
|
21866
21817
|
onNavigateHierarchyNode: navigateToHierarchyNode,
|
|
21867
21818
|
onTabChange: (value) => setDetailTab(value),
|
|
21868
|
-
onSelectTimelineNode: handleTimelineSelect,
|
|
21869
21819
|
onToggleJsonMode: (tabId) => (0, import_react3.startTransition)(() => {
|
|
21870
21820
|
setTabModes((current) => ({
|
|
21871
21821
|
...current,
|
|
21872
21822
|
[tabId]: (current[tabId] ?? "formatted") === "formatted" ? "raw" : "formatted"
|
|
21873
21823
|
}));
|
|
21874
|
-
})
|
|
21875
|
-
timelineModel: null
|
|
21824
|
+
})
|
|
21876
21825
|
}
|
|
21877
21826
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, { className: "content-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21878
21827
|
EmptyState,
|
|
21879
21828
|
{
|
|
21880
21829
|
icon: ArrowUpRight,
|
|
21881
|
-
title: "Select a trace from the session
|
|
21830
|
+
title: "Select a trace from the session tree",
|
|
21882
21831
|
description: "Choose any call on the left to inspect the full request, response, context, and stream details."
|
|
21883
21832
|
}
|
|
21884
21833
|
) }) })
|
|
@@ -21931,63 +21880,51 @@ function ThemeSwitcher({
|
|
|
21931
21880
|
)
|
|
21932
21881
|
] });
|
|
21933
21882
|
}
|
|
21934
|
-
function
|
|
21883
|
+
function SessionTreeNavigator({
|
|
21884
|
+
defaultExpandedNodeIds,
|
|
21885
|
+
expandedNodeOverrides,
|
|
21935
21886
|
hasActiveFilters,
|
|
21936
21887
|
items,
|
|
21937
|
-
|
|
21938
|
-
|
|
21939
|
-
|
|
21888
|
+
maxDurationMs,
|
|
21889
|
+
nodes,
|
|
21890
|
+
onSelect,
|
|
21891
|
+
onToggle,
|
|
21892
|
+
selectedNodeId,
|
|
21893
|
+
selectedPathIds,
|
|
21894
|
+
selectedTraceId,
|
|
21895
|
+
sessionNavById,
|
|
21896
|
+
totalCount,
|
|
21897
|
+
traceById
|
|
21940
21898
|
}) {
|
|
21941
21899
|
const filteredCount = items.length;
|
|
21942
21900
|
const countLabel = hasActiveFilters && totalCount > filteredCount ? `${filteredCount} of ${totalCount} sessions` : formatCountLabel(
|
|
21943
21901
|
hasActiveFilters ? filteredCount : Math.max(filteredCount, totalCount),
|
|
21944
21902
|
"session"
|
|
21945
21903
|
);
|
|
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-
|
|
21904
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-section", children: [
|
|
21905
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-header", children: [
|
|
21906
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-title-row", children: [
|
|
21907
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-title", children: "Sessions" }),
|
|
21908
|
+
hasActiveFilters ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", className: "session-tree-filter-badge", children: "Filtered" }) : null
|
|
21951
21909
|
] }),
|
|
21952
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-
|
|
21910
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-meta", children: countLabel })
|
|
21953
21911
|
] }),
|
|
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
|
-
}) })
|
|
21912
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21913
|
+
HierarchyTree,
|
|
21914
|
+
{
|
|
21915
|
+
defaultExpandedNodeIds,
|
|
21916
|
+
expandedNodeOverrides,
|
|
21917
|
+
maxDurationMs,
|
|
21918
|
+
nodes,
|
|
21919
|
+
onSelect,
|
|
21920
|
+
onToggle,
|
|
21921
|
+
selectedNodeId,
|
|
21922
|
+
selectedPathIds,
|
|
21923
|
+
selectedTraceId,
|
|
21924
|
+
sessionNavById,
|
|
21925
|
+
traceById
|
|
21926
|
+
}
|
|
21927
|
+
) })
|
|
21991
21928
|
] });
|
|
21992
21929
|
}
|
|
21993
21930
|
function getSessionNavBadge(item) {
|
|
@@ -22009,6 +21946,374 @@ function BackgroundGlow() {
|
|
|
22009
21946
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid-noise" })
|
|
22010
21947
|
] });
|
|
22011
21948
|
}
|
|
21949
|
+
function HierarchyTree({
|
|
21950
|
+
defaultExpandedNodeIds,
|
|
21951
|
+
expandedNodeOverrides,
|
|
21952
|
+
maxDurationMs,
|
|
21953
|
+
nodes,
|
|
21954
|
+
onSelect,
|
|
21955
|
+
onToggle,
|
|
21956
|
+
selectedNodeId,
|
|
21957
|
+
selectedPathIds,
|
|
21958
|
+
selectedTraceId,
|
|
21959
|
+
sessionNavById,
|
|
21960
|
+
traceById
|
|
21961
|
+
}) {
|
|
21962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-root", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21963
|
+
HierarchyTreeNode,
|
|
21964
|
+
{
|
|
21965
|
+
defaultExpandedNodeIds,
|
|
21966
|
+
depth: 0,
|
|
21967
|
+
expandedNodeOverrides,
|
|
21968
|
+
maxDurationMs,
|
|
21969
|
+
node,
|
|
21970
|
+
onSelect,
|
|
21971
|
+
onToggle,
|
|
21972
|
+
selectedNodeId,
|
|
21973
|
+
selectedPathIds,
|
|
21974
|
+
selectedTraceId,
|
|
21975
|
+
sessionNavById,
|
|
21976
|
+
traceById
|
|
21977
|
+
},
|
|
21978
|
+
node.id
|
|
21979
|
+
)) });
|
|
21980
|
+
}
|
|
21981
|
+
function HierarchyTreeNode({
|
|
21982
|
+
defaultExpandedNodeIds,
|
|
21983
|
+
depth,
|
|
21984
|
+
expandedNodeOverrides,
|
|
21985
|
+
maxDurationMs,
|
|
21986
|
+
node,
|
|
21987
|
+
onSelect,
|
|
21988
|
+
onToggle,
|
|
21989
|
+
selectedNodeId,
|
|
21990
|
+
selectedPathIds,
|
|
21991
|
+
selectedTraceId,
|
|
21992
|
+
sessionNavById,
|
|
21993
|
+
traceById
|
|
21994
|
+
}) {
|
|
21995
|
+
const isExpandable = node.children.length > 0;
|
|
21996
|
+
const isForcedExpanded = isExpandable && selectedPathIds.has(node.id);
|
|
21997
|
+
const expandedOverride = expandedNodeOverrides[node.id];
|
|
21998
|
+
const isExpanded = isExpandable && (expandedOverride ?? (isForcedExpanded || defaultExpandedNodeIds.has(node.id)));
|
|
21999
|
+
const isInPath = selectedPathIds.has(node.id);
|
|
22000
|
+
const nodeCopy = getHierarchyNodeCopy(node, traceById);
|
|
22001
|
+
const trace = node.meta.traceId ? traceById.get(node.meta.traceId) ?? null : null;
|
|
22002
|
+
const sessionNavItem = node.type === "session" ? sessionNavById.get(node.id) ?? null : null;
|
|
22003
|
+
if (node.type === "trace" && trace) {
|
|
22004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22005
|
+
TraceHierarchyLeaf,
|
|
22006
|
+
{
|
|
22007
|
+
depth,
|
|
22008
|
+
maxDurationMs,
|
|
22009
|
+
node,
|
|
22010
|
+
nodeCopy,
|
|
22011
|
+
onSelect,
|
|
22012
|
+
inPath: isInPath,
|
|
22013
|
+
selected: selectedNodeId === node.id,
|
|
22014
|
+
selectedTrace: selectedTraceId === trace.id,
|
|
22015
|
+
trace
|
|
22016
|
+
}
|
|
22017
|
+
);
|
|
22018
|
+
}
|
|
22019
|
+
if (sessionNavItem) {
|
|
22020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22021
|
+
SessionHierarchyBranch,
|
|
22022
|
+
{
|
|
22023
|
+
depth,
|
|
22024
|
+
defaultExpandedNodeIds,
|
|
22025
|
+
expandedNodeOverrides,
|
|
22026
|
+
isExpanded,
|
|
22027
|
+
item: sessionNavItem,
|
|
22028
|
+
maxDurationMs,
|
|
22029
|
+
node,
|
|
22030
|
+
onSelect,
|
|
22031
|
+
onToggle,
|
|
22032
|
+
selected: selectedNodeId === node.id,
|
|
22033
|
+
selectedNodeId,
|
|
22034
|
+
selectedPathIds,
|
|
22035
|
+
selectedTraceId,
|
|
22036
|
+
sessionNavById,
|
|
22037
|
+
traceById
|
|
22038
|
+
}
|
|
22039
|
+
);
|
|
22040
|
+
}
|
|
22041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22042
|
+
"div",
|
|
22043
|
+
{
|
|
22044
|
+
className: "tree-node-wrap",
|
|
22045
|
+
style: { "--depth": String(depth) },
|
|
22046
|
+
children: [
|
|
22047
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22048
|
+
"div",
|
|
22049
|
+
{
|
|
22050
|
+
className: clsx_default(
|
|
22051
|
+
"tree-node-card",
|
|
22052
|
+
selectedNodeId === node.id && "is-active",
|
|
22053
|
+
isInPath && "is-in-path",
|
|
22054
|
+
node.type === "trace" && "is-trace"
|
|
22055
|
+
),
|
|
22056
|
+
children: [
|
|
22057
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22058
|
+
"button",
|
|
22059
|
+
{
|
|
22060
|
+
type: "button",
|
|
22061
|
+
className: clsx_default("tree-node-toggle", !isExpandable && "is-static"),
|
|
22062
|
+
disabled: !isExpandable,
|
|
22063
|
+
onClick: () => {
|
|
22064
|
+
if (isExpandable) {
|
|
22065
|
+
onToggle(node.id);
|
|
22066
|
+
}
|
|
22067
|
+
},
|
|
22068
|
+
"aria-label": isExpandable ? `${isExpanded ? "Collapse" : "Expand"} ${nodeCopy.label}` : void 0,
|
|
22069
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: clsx_default(isExpanded && "is-open") })
|
|
22070
|
+
}
|
|
22071
|
+
),
|
|
22072
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22073
|
+
"button",
|
|
22074
|
+
{
|
|
22075
|
+
type: "button",
|
|
22076
|
+
className: "tree-node-select",
|
|
22077
|
+
onClick: () => onSelect(node),
|
|
22078
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy", children: [
|
|
22079
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-heading", children: [
|
|
22080
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-label", children: nodeCopy.label }),
|
|
22081
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22082
|
+
Badge,
|
|
22083
|
+
{
|
|
22084
|
+
variant: "secondary",
|
|
22085
|
+
className: "tree-node-inline-badge",
|
|
22086
|
+
semantic: nodeCopy.badge,
|
|
22087
|
+
children: nodeCopy.badge
|
|
22088
|
+
}
|
|
22089
|
+
)
|
|
22090
|
+
] }),
|
|
22091
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: nodeCopy.meta })
|
|
22092
|
+
] })
|
|
22093
|
+
}
|
|
22094
|
+
)
|
|
22095
|
+
]
|
|
22096
|
+
}
|
|
22097
|
+
),
|
|
22098
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-node-children", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22099
|
+
HierarchyTreeNode,
|
|
22100
|
+
{
|
|
22101
|
+
defaultExpandedNodeIds,
|
|
22102
|
+
depth: depth + 1,
|
|
22103
|
+
expandedNodeOverrides,
|
|
22104
|
+
maxDurationMs,
|
|
22105
|
+
node: child,
|
|
22106
|
+
onSelect,
|
|
22107
|
+
onToggle,
|
|
22108
|
+
selectedNodeId,
|
|
22109
|
+
selectedPathIds,
|
|
22110
|
+
selectedTraceId,
|
|
22111
|
+
sessionNavById,
|
|
22112
|
+
traceById
|
|
22113
|
+
},
|
|
22114
|
+
child.id
|
|
22115
|
+
)) }) : null
|
|
22116
|
+
]
|
|
22117
|
+
}
|
|
22118
|
+
);
|
|
22119
|
+
}
|
|
22120
|
+
function SessionHierarchyBranch({
|
|
22121
|
+
defaultExpandedNodeIds,
|
|
22122
|
+
depth,
|
|
22123
|
+
expandedNodeOverrides,
|
|
22124
|
+
isExpanded,
|
|
22125
|
+
item,
|
|
22126
|
+
maxDurationMs,
|
|
22127
|
+
node,
|
|
22128
|
+
onSelect,
|
|
22129
|
+
onToggle,
|
|
22130
|
+
selected,
|
|
22131
|
+
selectedNodeId,
|
|
22132
|
+
selectedPathIds,
|
|
22133
|
+
selectedTraceId,
|
|
22134
|
+
sessionNavById,
|
|
22135
|
+
traceById
|
|
22136
|
+
}) {
|
|
22137
|
+
const detailLabel = formatList([
|
|
22138
|
+
formatCountLabel(item.callCount, "call"),
|
|
22139
|
+
formatUsdCost(item.costUsd)
|
|
22140
|
+
]) || formatCountLabel(item.callCount, "call");
|
|
22141
|
+
const sessionSelectedPath = selectedNodeId ? findSessionNodePath([node], selectedNodeId) : [];
|
|
22142
|
+
const sessionTimelineModel = buildHierarchyTimelineModel(
|
|
22143
|
+
node,
|
|
22144
|
+
traceById,
|
|
22145
|
+
selectedNodeId,
|
|
22146
|
+
sessionSelectedPath,
|
|
22147
|
+
selectedTraceId
|
|
22148
|
+
);
|
|
22149
|
+
const sessionTimelineRow = sessionTimelineModel?.rows[0] ?? null;
|
|
22150
|
+
const showEmbeddedTimeline = isExpanded && Boolean(sessionTimelineModel?.rows.length);
|
|
22151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22152
|
+
"div",
|
|
22153
|
+
{
|
|
22154
|
+
className: "tree-node-wrap",
|
|
22155
|
+
style: { "--depth": String(depth) },
|
|
22156
|
+
children: [
|
|
22157
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22158
|
+
"div",
|
|
22159
|
+
{
|
|
22160
|
+
className: clsx_default(
|
|
22161
|
+
"tree-node-card tree-session-card",
|
|
22162
|
+
selected && "is-active",
|
|
22163
|
+
selectedPathIds.has(node.id) && "is-in-path"
|
|
22164
|
+
),
|
|
22165
|
+
children: [
|
|
22166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22167
|
+
"button",
|
|
22168
|
+
{
|
|
22169
|
+
type: "button",
|
|
22170
|
+
className: clsx_default(
|
|
22171
|
+
"tree-node-toggle",
|
|
22172
|
+
!node.children.length && "is-static"
|
|
22173
|
+
),
|
|
22174
|
+
disabled: !node.children.length,
|
|
22175
|
+
onClick: () => {
|
|
22176
|
+
if (node.children.length) {
|
|
22177
|
+
onToggle(node.id);
|
|
22178
|
+
}
|
|
22179
|
+
},
|
|
22180
|
+
"aria-label": node.children.length ? `${isExpanded ? "Collapse" : "Expand"} ${item.primaryLabel}` : void 0,
|
|
22181
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: clsx_default(isExpanded && "is-open") })
|
|
22182
|
+
}
|
|
22183
|
+
),
|
|
22184
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22185
|
+
"button",
|
|
22186
|
+
{
|
|
22187
|
+
type: "button",
|
|
22188
|
+
className: "tree-node-select session-tree-select",
|
|
22189
|
+
onClick: () => onSelect(node),
|
|
22190
|
+
children: [
|
|
22191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy session-tree-copy", children: [
|
|
22192
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-card-header", children: [
|
|
22193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-card-title", title: item.primaryLabel, children: item.primaryLabel }),
|
|
22194
|
+
item.latestTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-card-time", children: item.latestTimestamp }) : null
|
|
22195
|
+
] }),
|
|
22196
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: detailLabel }),
|
|
22197
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-card-footer", children: [
|
|
22198
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-card-id", children: item.shortSessionId }),
|
|
22199
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-card-badges", children: [
|
|
22200
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", children: "Session" }),
|
|
22201
|
+
getSessionNavBadge(item)
|
|
22202
|
+
] })
|
|
22203
|
+
] })
|
|
22204
|
+
] }),
|
|
22205
|
+
sessionTimelineModel && sessionTimelineRow ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22206
|
+
SessionTreeTimelineBar,
|
|
22207
|
+
{
|
|
22208
|
+
model: sessionTimelineModel,
|
|
22209
|
+
row: sessionTimelineRow
|
|
22210
|
+
}
|
|
22211
|
+
) : null
|
|
22212
|
+
]
|
|
22213
|
+
}
|
|
22214
|
+
)
|
|
22215
|
+
]
|
|
22216
|
+
}
|
|
22217
|
+
),
|
|
22218
|
+
showEmbeddedTimeline && sessionTimelineModel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "session-tree-timeline-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22219
|
+
"div",
|
|
22220
|
+
{
|
|
22221
|
+
className: "session-tree-timeline-list",
|
|
22222
|
+
role: "list",
|
|
22223
|
+
"aria-label": "Session timeline",
|
|
22224
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22225
|
+
HierarchyTimelineRows,
|
|
22226
|
+
{
|
|
22227
|
+
className: "is-embedded",
|
|
22228
|
+
model: sessionTimelineModel,
|
|
22229
|
+
onSelectRow: (nodeId) => {
|
|
22230
|
+
const selectedTimelineNode = findSessionNodeById([node], nodeId);
|
|
22231
|
+
if (selectedTimelineNode) {
|
|
22232
|
+
onSelect(selectedTimelineNode);
|
|
22233
|
+
}
|
|
22234
|
+
},
|
|
22235
|
+
rows: sessionTimelineModel.rows.slice(1)
|
|
22236
|
+
}
|
|
22237
|
+
)
|
|
22238
|
+
}
|
|
22239
|
+
) }) : isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-node-children", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22240
|
+
HierarchyTreeNode,
|
|
22241
|
+
{
|
|
22242
|
+
defaultExpandedNodeIds,
|
|
22243
|
+
depth: depth + 1,
|
|
22244
|
+
expandedNodeOverrides,
|
|
22245
|
+
maxDurationMs,
|
|
22246
|
+
node: child,
|
|
22247
|
+
onSelect,
|
|
22248
|
+
onToggle,
|
|
22249
|
+
selectedNodeId,
|
|
22250
|
+
selectedPathIds,
|
|
22251
|
+
selectedTraceId,
|
|
22252
|
+
sessionNavById,
|
|
22253
|
+
traceById
|
|
22254
|
+
},
|
|
22255
|
+
child.id
|
|
22256
|
+
)) }) : null
|
|
22257
|
+
]
|
|
22258
|
+
}
|
|
22259
|
+
);
|
|
22260
|
+
}
|
|
22261
|
+
function TraceHierarchyLeaf({
|
|
22262
|
+
depth,
|
|
22263
|
+
inPath,
|
|
22264
|
+
maxDurationMs,
|
|
22265
|
+
node,
|
|
22266
|
+
nodeCopy,
|
|
22267
|
+
onSelect,
|
|
22268
|
+
selected,
|
|
22269
|
+
selectedTrace,
|
|
22270
|
+
trace
|
|
22271
|
+
}) {
|
|
22272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22273
|
+
"div",
|
|
22274
|
+
{
|
|
22275
|
+
className: "tree-node-wrap tree-trace-wrap",
|
|
22276
|
+
style: { "--depth": String(depth) },
|
|
22277
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22278
|
+
"div",
|
|
22279
|
+
{
|
|
22280
|
+
className: clsx_default(
|
|
22281
|
+
"tree-node-card is-trace",
|
|
22282
|
+
inPath && "is-in-path",
|
|
22283
|
+
selected && "is-active",
|
|
22284
|
+
selectedTrace && "is-detail-trace"
|
|
22285
|
+
),
|
|
22286
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22287
|
+
"button",
|
|
22288
|
+
{
|
|
22289
|
+
type: "button",
|
|
22290
|
+
className: "tree-node-select tree-trace-select",
|
|
22291
|
+
onClick: () => onSelect(node),
|
|
22292
|
+
children: [
|
|
22293
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy", children: [
|
|
22294
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-nav-kicker", children: getTraceActorLabel(trace) }),
|
|
22295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-label", children: nodeCopy.label }),
|
|
22296
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: formatList([
|
|
22297
|
+
formatTimelineTimestamp(trace.startedAt),
|
|
22298
|
+
nodeCopy.meta
|
|
22299
|
+
]) })
|
|
22300
|
+
] }),
|
|
22301
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22302
|
+
TraceElapsedBar,
|
|
22303
|
+
{
|
|
22304
|
+
compact: true,
|
|
22305
|
+
durationMs: trace.durationMs,
|
|
22306
|
+
maxDurationMs
|
|
22307
|
+
}
|
|
22308
|
+
)
|
|
22309
|
+
]
|
|
22310
|
+
}
|
|
22311
|
+
)
|
|
22312
|
+
}
|
|
22313
|
+
)
|
|
22314
|
+
}
|
|
22315
|
+
);
|
|
22316
|
+
}
|
|
22012
22317
|
function StatusBadge({
|
|
22013
22318
|
status,
|
|
22014
22319
|
onClick
|
|
@@ -22031,235 +22336,191 @@ function TraceMetricPill({
|
|
|
22031
22336
|
}
|
|
22032
22337
|
);
|
|
22033
22338
|
}
|
|
22034
|
-
function
|
|
22035
|
-
|
|
22036
|
-
|
|
22037
|
-
|
|
22339
|
+
function TraceElapsedBar({
|
|
22340
|
+
compact = false,
|
|
22341
|
+
durationMs,
|
|
22342
|
+
maxDurationMs
|
|
22038
22343
|
}) {
|
|
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;
|
|
22344
|
+
const durationLabel = formatElapsedLabel(durationMs);
|
|
22345
|
+
const scale = getElapsedScale(durationMs, maxDurationMs);
|
|
22346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22347
|
+
"div",
|
|
22348
|
+
{
|
|
22349
|
+
className: cn(
|
|
22350
|
+
"trace-elapsed-bar",
|
|
22351
|
+
compact && "is-compact",
|
|
22352
|
+
durationMs === null && "is-pending"
|
|
22353
|
+
),
|
|
22354
|
+
style: { "--elapsed-scale": String(scale) },
|
|
22355
|
+
children: [
|
|
22356
|
+
/* @__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" }) }),
|
|
22357
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-elapsed-label", children: durationLabel })
|
|
22358
|
+
]
|
|
22061
22359
|
}
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22360
|
+
);
|
|
22361
|
+
}
|
|
22362
|
+
function SessionTreeTimelineBar({
|
|
22363
|
+
model,
|
|
22364
|
+
row
|
|
22365
|
+
}) {
|
|
22366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22367
|
+
"span",
|
|
22368
|
+
{
|
|
22369
|
+
className: "session-tree-timeline",
|
|
22370
|
+
style: {
|
|
22371
|
+
"--session-tree-offset": model.durationMs > 0 ? String(row.offsetMs / model.durationMs) : "0",
|
|
22372
|
+
"--session-tree-span": model.durationMs > 0 ? String(row.durationMs / model.durationMs) : "1"
|
|
22373
|
+
},
|
|
22374
|
+
children: [
|
|
22375
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-timeline-meta", children: [
|
|
22376
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-timeline-start", children: formatTimelineTimestamp(row.startedAt) }),
|
|
22377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "session-tree-timeline-duration", children: formatElapsedLabel(row.durationMs) })
|
|
22378
|
+
] }),
|
|
22379
|
+
/* @__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" }) })
|
|
22380
|
+
]
|
|
22068
22381
|
}
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22382
|
+
);
|
|
22383
|
+
}
|
|
22384
|
+
function HierarchyTimelineRows({
|
|
22385
|
+
className,
|
|
22386
|
+
model,
|
|
22387
|
+
onSelectRow,
|
|
22388
|
+
rows
|
|
22389
|
+
}) {
|
|
22390
|
+
return rows.map((row) => {
|
|
22391
|
+
const isTraceRow = row.type === "trace";
|
|
22392
|
+
const rowClassName = cn(
|
|
22393
|
+
"hierarchy-timeline-row",
|
|
22394
|
+
className,
|
|
22395
|
+
isTraceRow ? "is-clickable" : "is-structure",
|
|
22396
|
+
row.depth === 0 && "is-root",
|
|
22397
|
+
row.isActive && "is-active",
|
|
22398
|
+
row.isDetailTrace && "is-detail-trace",
|
|
22399
|
+
row.isInPath && "is-in-path",
|
|
22400
|
+
`is-${row.type.replace(/[^a-z0-9-]/gi, "-")}`
|
|
22072
22401
|
);
|
|
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
|
-
}
|
|
22402
|
+
const rowStyle = {
|
|
22403
|
+
"--timeline-depth": String(row.depth),
|
|
22404
|
+
"--timeline-offset": String(
|
|
22405
|
+
model.durationMs > 0 ? row.offsetMs / model.durationMs : 0
|
|
22406
|
+
),
|
|
22407
|
+
"--timeline-span": String(
|
|
22408
|
+
model.durationMs > 0 ? row.durationMs / model.durationMs : 1
|
|
22409
|
+
)
|
|
22410
|
+
};
|
|
22411
|
+
const rowContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Fragment, { children: [
|
|
22412
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-time", children: formatTimelineTimestamp(row.startedAt) }),
|
|
22413
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-branch", children: [
|
|
22414
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-gutter", "aria-hidden": "true", children: [
|
|
22415
|
+
row.ancestorContinuations.map((continues, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22416
|
+
"span",
|
|
22417
|
+
{
|
|
22418
|
+
className: cn(
|
|
22419
|
+
"hierarchy-timeline-row-ancestor",
|
|
22420
|
+
continues && "has-line"
|
|
22220
22421
|
),
|
|
22221
|
-
|
|
22222
|
-
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
|
|
22422
|
+
style: {
|
|
22423
|
+
"--timeline-connector-index": String(index)
|
|
22424
|
+
}
|
|
22425
|
+
},
|
|
22426
|
+
`${row.id}-ancestor-${index}`
|
|
22427
|
+
)),
|
|
22428
|
+
row.depth > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22429
|
+
"span",
|
|
22430
|
+
{
|
|
22431
|
+
className: "hierarchy-timeline-row-connector",
|
|
22432
|
+
style: {
|
|
22433
|
+
"--timeline-connector-index": String(row.depth - 1)
|
|
22434
|
+
},
|
|
22435
|
+
children: [
|
|
22436
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-connector-top" }),
|
|
22437
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-connector-elbow" }),
|
|
22438
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22439
|
+
"span",
|
|
22234
22440
|
{
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
children: rowContent
|
|
22441
|
+
className: cn(
|
|
22442
|
+
"hierarchy-timeline-row-connector-bottom",
|
|
22443
|
+
(row.hasVisibleChildren || !row.isLastSibling) && "has-line"
|
|
22444
|
+
)
|
|
22240
22445
|
}
|
|
22241
22446
|
)
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22246
|
-
|
|
22247
|
-
|
|
22447
|
+
]
|
|
22448
|
+
}
|
|
22449
|
+
) : null
|
|
22450
|
+
] }),
|
|
22451
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-labels", children: [
|
|
22452
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-title", children: [
|
|
22453
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-title-text", children: row.label }),
|
|
22454
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22455
|
+
Badge,
|
|
22456
|
+
{
|
|
22457
|
+
variant: "secondary",
|
|
22458
|
+
className: "hierarchy-timeline-pill",
|
|
22459
|
+
semantic: row.badge,
|
|
22460
|
+
children: row.badge
|
|
22461
|
+
}
|
|
22462
|
+
),
|
|
22463
|
+
row.hasStructuredInput ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22464
|
+
"span",
|
|
22465
|
+
{
|
|
22466
|
+
className: "hierarchy-timeline-row-flag",
|
|
22467
|
+
title: "Structured input detected for this call",
|
|
22468
|
+
children: "Structured input"
|
|
22469
|
+
}
|
|
22470
|
+
) : null,
|
|
22471
|
+
row.hasHighlights && !row.hasStructuredInput ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22472
|
+
"span",
|
|
22473
|
+
{
|
|
22474
|
+
className: "hierarchy-timeline-row-flag is-highlight",
|
|
22475
|
+
title: "Trace insights available",
|
|
22476
|
+
children: "Insight"
|
|
22477
|
+
}
|
|
22478
|
+
) : null
|
|
22479
|
+
] }),
|
|
22480
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-meta", children: row.meta })
|
|
22481
|
+
] })
|
|
22482
|
+
] }),
|
|
22483
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "hierarchy-timeline-row-bars", children: [
|
|
22484
|
+
/* @__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" }) }),
|
|
22485
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-duration", children: formatElapsedLabel(row.durationMs) })
|
|
22486
|
+
] })
|
|
22487
|
+
] });
|
|
22488
|
+
if (isTraceRow) {
|
|
22489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22490
|
+
"div",
|
|
22491
|
+
{
|
|
22492
|
+
role: "listitem",
|
|
22493
|
+
title: buildHierarchyTimelineRowTooltip(row),
|
|
22494
|
+
"aria-current": row.isActive || row.isDetailTrace ? "true" : void 0,
|
|
22495
|
+
"data-hierarchy-row-id": row.id,
|
|
22496
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22497
|
+
"button",
|
|
22248
22498
|
{
|
|
22249
|
-
|
|
22499
|
+
type: "button",
|
|
22250
22500
|
className: rowClassName,
|
|
22251
22501
|
style: rowStyle,
|
|
22252
|
-
|
|
22253
|
-
"aria-current": row.isActive || row.isDetailTrace ? "true" : void 0,
|
|
22254
|
-
"data-hierarchy-row-id": row.id,
|
|
22502
|
+
onClick: () => onSelectRow(row.id),
|
|
22255
22503
|
children: rowContent
|
|
22256
|
-
}
|
|
22257
|
-
|
|
22258
|
-
|
|
22259
|
-
|
|
22260
|
-
|
|
22261
|
-
|
|
22262
|
-
|
|
22504
|
+
}
|
|
22505
|
+
)
|
|
22506
|
+
},
|
|
22507
|
+
row.id
|
|
22508
|
+
);
|
|
22509
|
+
}
|
|
22510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22511
|
+
"div",
|
|
22512
|
+
{
|
|
22513
|
+
role: "listitem",
|
|
22514
|
+
className: rowClassName,
|
|
22515
|
+
style: rowStyle,
|
|
22516
|
+
title: buildHierarchyTimelineRowTooltip(row),
|
|
22517
|
+
"aria-current": row.isActive || row.isDetailTrace ? "true" : void 0,
|
|
22518
|
+
"data-hierarchy-row-id": row.id,
|
|
22519
|
+
children: rowContent
|
|
22520
|
+
},
|
|
22521
|
+
row.id
|
|
22522
|
+
);
|
|
22523
|
+
});
|
|
22263
22524
|
}
|
|
22264
22525
|
function TraceDetailPanel({
|
|
22265
22526
|
activeTab,
|
|
@@ -22271,10 +22532,8 @@ function TraceDetailPanel({
|
|
|
22271
22532
|
onApplyTraceFilter,
|
|
22272
22533
|
onBack,
|
|
22273
22534
|
onNavigateHierarchyNode,
|
|
22274
|
-
onSelectTimelineNode,
|
|
22275
22535
|
onTabChange,
|
|
22276
|
-
onToggleJsonMode
|
|
22277
|
-
timelineModel
|
|
22536
|
+
onToggleJsonMode
|
|
22278
22537
|
}) {
|
|
22279
22538
|
const traceDetailPrimaryRef = (0, import_react3.useRef)(null);
|
|
22280
22539
|
const [showInlineContextRail, setShowInlineContextRail] = (0, import_react3.useState)(false);
|
|
@@ -22284,7 +22543,6 @@ function TraceDetailPanel({
|
|
|
22284
22543
|
const detailSubtitle = formatTraceProviderSummary(detail ?? fallbackTrace);
|
|
22285
22544
|
const detailCostUsd = detail ? getUsageCostUsd(detail.usage) : fallbackTrace?.costUsd ?? null;
|
|
22286
22545
|
const detailCostLabel = formatUsdCost(detailCostUsd);
|
|
22287
|
-
const hasSecondaryInspector = Boolean(detail && timelineModel);
|
|
22288
22546
|
const detailFilterSource = detail ?? fallbackTrace;
|
|
22289
22547
|
const canInlineContextRailTab = activeTab === "conversation" || activeTab === "request" || activeTab === "response";
|
|
22290
22548
|
const visibleDetailTabs = canInlineContextRailTab && showInlineContextRail ? detailTabs.filter((tab) => tab.id !== "context") : detailTabs;
|
|
@@ -22386,77 +22644,59 @@ function TraceDetailPanel({
|
|
|
22386
22644
|
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
22645
|
] }),
|
|
22388
22646
|
/* @__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
|
-
|
|
22647
|
+
/* @__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: [
|
|
22648
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "trace-detail-toolbar", children: [
|
|
22649
|
+
/* @__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)) }) }) }),
|
|
22650
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22651
|
+
Button,
|
|
22652
|
+
{
|
|
22653
|
+
variant: "outline",
|
|
22654
|
+
className: "trace-detail-json-toggle",
|
|
22655
|
+
onClick: () => onToggleJsonMode(activeTab),
|
|
22656
|
+
children: [
|
|
22657
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Boxes, { "data-icon": "inline-start" }),
|
|
22658
|
+
jsonMode === "formatted" ? "Raw JSON" : "Formatted"
|
|
22659
|
+
]
|
|
22660
|
+
}
|
|
22661
|
+
)
|
|
22662
|
+
] }),
|
|
22663
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator, {}),
|
|
22664
|
+
/* @__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: [
|
|
22665
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "detail-inline-context-main", children: renderTabContent(
|
|
22666
|
+
activeTab,
|
|
22667
|
+
detail,
|
|
22668
|
+
jsonMode,
|
|
22669
|
+
onApplyTagFilter,
|
|
22670
|
+
onApplyTraceFilter
|
|
22671
|
+
) }),
|
|
22672
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22673
|
+
"aside",
|
|
22674
|
+
{
|
|
22675
|
+
className: "conversation-context-rail",
|
|
22676
|
+
"aria-label": "Context summary",
|
|
22677
|
+
children: [
|
|
22678
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-context-rail-header", children: [
|
|
22679
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-context-rail-title", children: "Context" }),
|
|
22680
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-context-rail-copy", children: "Key trace metadata alongside the conversation." })
|
|
22681
|
+
] }),
|
|
22682
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22683
|
+
ContextInspectorView,
|
|
22402
22684
|
{
|
|
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
|
-
]
|
|
22685
|
+
detail,
|
|
22686
|
+
onApplyTagFilter
|
|
22410
22687
|
}
|
|
22411
22688
|
)
|
|
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)(
|
|
22689
|
+
]
|
|
22690
|
+
}
|
|
22691
|
+
)
|
|
22692
|
+
] }) : renderTabContent(
|
|
22693
|
+
activeTab,
|
|
22694
|
+
detail,
|
|
22695
|
+
jsonMode,
|
|
22696
|
+
onApplyTagFilter,
|
|
22697
|
+
onApplyTraceFilter
|
|
22698
|
+
) }) })
|
|
22699
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-detail-empty", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22460
22700
|
EmptyState,
|
|
22461
22701
|
{
|
|
22462
22702
|
icon: ArrowUpRight,
|
|
@@ -23528,52 +23768,6 @@ function buildDetailTabs(detail) {
|
|
|
23528
23768
|
}
|
|
23529
23769
|
return tabs;
|
|
23530
23770
|
}
|
|
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
23771
|
function getHierarchyNodeCopy(node, traceById) {
|
|
23578
23772
|
switch (node.type) {
|
|
23579
23773
|
case "session":
|
|
@@ -23710,40 +23904,6 @@ function formatTraceProviderSummary(trace) {
|
|
|
23710
23904
|
}
|
|
23711
23905
|
return formatList([trace.provider, trace.model]);
|
|
23712
23906
|
}
|
|
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
23907
|
function getTraceActorLabel(trace) {
|
|
23748
23908
|
if (trace.kind === "guardrail") {
|
|
23749
23909
|
return `${capitalize(trace.hierarchy.guardrailPhase || "guardrail")} guardrail`;
|
|
@@ -24287,9 +24447,6 @@ async function copyText(value) {
|
|
|
24287
24447
|
return false;
|
|
24288
24448
|
}
|
|
24289
24449
|
}
|
|
24290
|
-
function toSessionNodeId(sessionId) {
|
|
24291
|
-
return `session:${sessionId}`;
|
|
24292
|
-
}
|
|
24293
24450
|
function toTraceNodeId(traceId) {
|
|
24294
24451
|
return `trace:${traceId}`;
|
|
24295
24452
|
}
|
|
@@ -24784,12 +24941,6 @@ function getSemanticBadgeValue(value) {
|
|
|
24784
24941
|
return null;
|
|
24785
24942
|
}
|
|
24786
24943
|
}
|
|
24787
|
-
function formatCompactTimestamp2(value) {
|
|
24788
|
-
return new Date(value).toLocaleTimeString([], {
|
|
24789
|
-
hour: "2-digit",
|
|
24790
|
-
minute: "2-digit"
|
|
24791
|
-
});
|
|
24792
|
-
}
|
|
24793
24944
|
function formatTimelineTimestamp(value) {
|
|
24794
24945
|
return new Date(value).toLocaleTimeString([], {
|
|
24795
24946
|
hour: "2-digit",
|
|
@@ -24803,6 +24954,14 @@ function getMaxDurationMs(items) {
|
|
|
24803
24954
|
);
|
|
24804
24955
|
return durations.length ? Math.max(...durations) : 1;
|
|
24805
24956
|
}
|
|
24957
|
+
function getElapsedScale(durationMs, maxDurationMs) {
|
|
24958
|
+
if (durationMs === null || durationMs <= 0 || !Number.isFinite(durationMs)) {
|
|
24959
|
+
return 0.16;
|
|
24960
|
+
}
|
|
24961
|
+
const safeMax = Math.max(maxDurationMs, durationMs, 1);
|
|
24962
|
+
const ratio = Math.log1p(durationMs) / Math.log1p(safeMax);
|
|
24963
|
+
return Math.max(0.14, Math.min(1, ratio));
|
|
24964
|
+
}
|
|
24806
24965
|
function formatElapsedLabel(durationMs) {
|
|
24807
24966
|
if (durationMs === null || !Number.isFinite(durationMs)) {
|
|
24808
24967
|
return "Running";
|
|
@@ -24993,7 +25152,7 @@ function parseEvent(data) {
|
|
|
24993
25152
|
return null;
|
|
24994
25153
|
}
|
|
24995
25154
|
}
|
|
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,
|
|
25155
|
+
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
25156
|
var init_app = __esm({
|
|
24998
25157
|
"client/src/app.tsx"() {
|
|
24999
25158
|
init_lucide_react();
|
|
@@ -25011,8 +25170,6 @@ var init_app = __esm({
|
|
|
25011
25170
|
MESSAGE_COLLAPSE_LINE_LIMIT_SYSTEM = 5;
|
|
25012
25171
|
MESSAGE_COLLAPSE_HEIGHT_PROSE_SYSTEM = "9rem";
|
|
25013
25172
|
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
25173
|
EMPTY_TRACE_INSIGHTS = {
|
|
25017
25174
|
highlights: [],
|
|
25018
25175
|
structuredInputs: []
|