@mtharrison/loupe 1.3.0 → 1.5.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 +29 -3
- package/dist/client/app.css +237 -137
- package/dist/client/app.js +428 -361
- package/dist/index.js +75 -1
- package/dist/session-nav.d.ts +1 -1
- package/dist/session-nav.js +8 -1
- package/dist/store.d.ts +1 -0
- package/dist/store.js +84 -39
- package/dist/utils.js +3 -1
- package/examples/fully-featured.js +533 -0
- package/package.json +3 -2
package/dist/client/app.js
CHANGED
|
@@ -21048,7 +21048,7 @@ function resolveSessionTreeSelection(sessionNodes, selectedNodeId, selectedTrace
|
|
|
21048
21048
|
selectedTraceId: nextSelectedTraceId
|
|
21049
21049
|
};
|
|
21050
21050
|
}
|
|
21051
|
-
function getDefaultExpandedSessionTreeNodeIds(sessionNodes, activeSessionId, selectedNodeId) {
|
|
21051
|
+
function getDefaultExpandedSessionTreeNodeIds(sessionNodes, activeSessionId, selectedNodeId, selectedTraceId = null) {
|
|
21052
21052
|
const expanded = /* @__PURE__ */ new Set();
|
|
21053
21053
|
const activeSession = (activeSessionId ? sessionNodes.find((node) => node.id === activeSessionId) ?? null : null) ?? sessionNodes[0] ?? null;
|
|
21054
21054
|
if (!activeSession) {
|
|
@@ -21069,6 +21069,16 @@ function getDefaultExpandedSessionTreeNodeIds(sessionNodes, activeSessionId, sel
|
|
|
21069
21069
|
}
|
|
21070
21070
|
}
|
|
21071
21071
|
}
|
|
21072
|
+
if (selectedTraceId) {
|
|
21073
|
+
for (const node of findSessionNodePath(
|
|
21074
|
+
[activeSession],
|
|
21075
|
+
`trace:${selectedTraceId}`
|
|
21076
|
+
)) {
|
|
21077
|
+
if (node.children.length) {
|
|
21078
|
+
expanded.add(node.id);
|
|
21079
|
+
}
|
|
21080
|
+
}
|
|
21081
|
+
}
|
|
21072
21082
|
return expanded;
|
|
21073
21083
|
}
|
|
21074
21084
|
function deriveSessionNavItem(node, traceById) {
|
|
@@ -21459,7 +21469,7 @@ function App() {
|
|
|
21459
21469
|
() => deriveSessionNavItems(sessionNodes, traceById),
|
|
21460
21470
|
[sessionNodes, traceById]
|
|
21461
21471
|
);
|
|
21462
|
-
const
|
|
21472
|
+
const sessionNavById2 = (0, import_react3.useMemo)(
|
|
21463
21473
|
() => new Map(sessionNavItems.map((item) => [item.id, item])),
|
|
21464
21474
|
[sessionNavItems]
|
|
21465
21475
|
);
|
|
@@ -21478,8 +21488,10 @@ function App() {
|
|
|
21478
21488
|
[sessionNodes, selectedTraceId]
|
|
21479
21489
|
);
|
|
21480
21490
|
const selectedPathIds = (0, import_react3.useMemo)(
|
|
21481
|
-
() => new Set(
|
|
21482
|
-
|
|
21491
|
+
() => new Set(
|
|
21492
|
+
[...selectedNodePath, ...selectedTracePath].map((node) => node.id)
|
|
21493
|
+
),
|
|
21494
|
+
[selectedNodePath, selectedTracePath]
|
|
21483
21495
|
);
|
|
21484
21496
|
const selectedSessionNode = (0, import_react3.useMemo)(
|
|
21485
21497
|
() => (selectedNodePath[0]?.type === "session" ? selectedNodePath[0] : null) ?? (selectedTracePath[0]?.type === "session" ? selectedTracePath[0] : null) ?? sessionNodes[0] ?? null,
|
|
@@ -21532,9 +21544,10 @@ function App() {
|
|
|
21532
21544
|
() => getDefaultExpandedSessionTreeNodeIds(
|
|
21533
21545
|
sessionNodes,
|
|
21534
21546
|
selectedSessionNode?.id ?? null,
|
|
21535
|
-
selectedNodeId
|
|
21547
|
+
selectedNodeId,
|
|
21548
|
+
selectedTraceId
|
|
21536
21549
|
),
|
|
21537
|
-
[selectedNodeId, selectedSessionNode, sessionNodes]
|
|
21550
|
+
[selectedNodeId, selectedSessionNode, selectedTraceId, sessionNodes]
|
|
21538
21551
|
);
|
|
21539
21552
|
const activeTabJsonMode = tabModes[detailTab] ?? "formatted";
|
|
21540
21553
|
const activeTagFilterCount = countTagFilters(filters.tags);
|
|
@@ -21627,7 +21640,7 @@ function App() {
|
|
|
21627
21640
|
if (!node) {
|
|
21628
21641
|
return;
|
|
21629
21642
|
}
|
|
21630
|
-
const nextTraceId = selectedTraceId && node.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceIdForNode(node);
|
|
21643
|
+
const nextTraceId = node.type === "trace" ? node.meta.traceId ?? node.traceIds[0] ?? null : selectedTraceId && node.traceIds.includes(selectedTraceId) ? selectedTraceId : getNewestTraceIdForNode(node);
|
|
21631
21644
|
(0, import_react3.startTransition)(() => {
|
|
21632
21645
|
setSelectedNodeId(nodeId);
|
|
21633
21646
|
if (nextTraceId !== selectedTraceId) {
|
|
@@ -21779,7 +21792,7 @@ function App() {
|
|
|
21779
21792
|
selectedNodeId,
|
|
21780
21793
|
selectedPathIds,
|
|
21781
21794
|
selectedTraceId,
|
|
21782
|
-
sessionNavById,
|
|
21795
|
+
sessionNavById: sessionNavById2,
|
|
21783
21796
|
totalCount: allSessionCount,
|
|
21784
21797
|
traceById
|
|
21785
21798
|
}
|
|
@@ -21809,6 +21822,7 @@ function App() {
|
|
|
21809
21822
|
{
|
|
21810
21823
|
activeTab,
|
|
21811
21824
|
detail,
|
|
21825
|
+
detailPath: selectedTracePath.length ? selectedTracePath : selectedNodePath,
|
|
21812
21826
|
detailTabs,
|
|
21813
21827
|
fallbackTrace: selectedTraceSummary,
|
|
21814
21828
|
jsonMode: activeTabJsonMode,
|
|
@@ -21821,7 +21835,8 @@ function App() {
|
|
|
21821
21835
|
...current,
|
|
21822
21836
|
[tabId]: (current[tabId] ?? "formatted") === "formatted" ? "raw" : "formatted"
|
|
21823
21837
|
}));
|
|
21824
|
-
})
|
|
21838
|
+
}),
|
|
21839
|
+
traceById
|
|
21825
21840
|
}
|
|
21826
21841
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, { className: "content-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21827
21842
|
EmptyState,
|
|
@@ -21892,7 +21907,7 @@ function SessionTreeNavigator({
|
|
|
21892
21907
|
selectedNodeId,
|
|
21893
21908
|
selectedPathIds,
|
|
21894
21909
|
selectedTraceId,
|
|
21895
|
-
sessionNavById,
|
|
21910
|
+
sessionNavById: sessionNavById2,
|
|
21896
21911
|
totalCount,
|
|
21897
21912
|
traceById
|
|
21898
21913
|
}) {
|
|
@@ -21921,7 +21936,7 @@ function SessionTreeNavigator({
|
|
|
21921
21936
|
selectedNodeId,
|
|
21922
21937
|
selectedPathIds,
|
|
21923
21938
|
selectedTraceId,
|
|
21924
|
-
sessionNavById,
|
|
21939
|
+
sessionNavById: sessionNavById2,
|
|
21925
21940
|
traceById
|
|
21926
21941
|
}
|
|
21927
21942
|
) })
|
|
@@ -21934,9 +21949,6 @@ function getSessionNavBadge(item) {
|
|
|
21934
21949
|
if (item.status === "pending") {
|
|
21935
21950
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "warning", children: "Running" });
|
|
21936
21951
|
}
|
|
21937
|
-
if (item.hasHighlights) {
|
|
21938
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "secondary", semantic: "guardrail", children: "Insight" });
|
|
21939
|
-
}
|
|
21940
21952
|
return null;
|
|
21941
21953
|
}
|
|
21942
21954
|
function BackgroundGlow() {
|
|
@@ -21956,7 +21968,7 @@ function HierarchyTree({
|
|
|
21956
21968
|
selectedNodeId,
|
|
21957
21969
|
selectedPathIds,
|
|
21958
21970
|
selectedTraceId,
|
|
21959
|
-
sessionNavById,
|
|
21971
|
+
sessionNavById: sessionNavById2,
|
|
21960
21972
|
traceById
|
|
21961
21973
|
}) {
|
|
21962
21974
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-root", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -21972,7 +21984,7 @@ function HierarchyTree({
|
|
|
21972
21984
|
selectedNodeId,
|
|
21973
21985
|
selectedPathIds,
|
|
21974
21986
|
selectedTraceId,
|
|
21975
|
-
sessionNavById,
|
|
21987
|
+
sessionNavById: sessionNavById2,
|
|
21976
21988
|
traceById
|
|
21977
21989
|
},
|
|
21978
21990
|
node.id
|
|
@@ -21989,7 +22001,7 @@ function HierarchyTreeNode({
|
|
|
21989
22001
|
selectedNodeId,
|
|
21990
22002
|
selectedPathIds,
|
|
21991
22003
|
selectedTraceId,
|
|
21992
|
-
sessionNavById,
|
|
22004
|
+
sessionNavById: sessionNavById2,
|
|
21993
22005
|
traceById
|
|
21994
22006
|
}) {
|
|
21995
22007
|
const isExpandable = node.children.length > 0;
|
|
@@ -21999,20 +22011,28 @@ function HierarchyTreeNode({
|
|
|
21999
22011
|
const isInPath = selectedPathIds.has(node.id);
|
|
22000
22012
|
const nodeCopy = getHierarchyNodeCopy(node, traceById);
|
|
22001
22013
|
const trace = node.meta.traceId ? traceById.get(node.meta.traceId) ?? null : null;
|
|
22002
|
-
const sessionNavItem = node.type === "session" ?
|
|
22014
|
+
const sessionNavItem = node.type === "session" ? sessionNavById2.get(node.id) ?? null : null;
|
|
22003
22015
|
if (node.type === "trace" && trace) {
|
|
22004
22016
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22005
|
-
|
|
22017
|
+
TraceHierarchyNode,
|
|
22006
22018
|
{
|
|
22019
|
+
defaultExpandedNodeIds,
|
|
22007
22020
|
depth,
|
|
22021
|
+
expandedNodeOverrides,
|
|
22008
22022
|
maxDurationMs,
|
|
22009
22023
|
node,
|
|
22010
22024
|
nodeCopy,
|
|
22011
22025
|
onSelect,
|
|
22026
|
+
onToggle,
|
|
22012
22027
|
inPath: isInPath,
|
|
22028
|
+
isExpanded,
|
|
22013
22029
|
selected: selectedNodeId === node.id,
|
|
22030
|
+
selectedNodeId,
|
|
22031
|
+
selectedPathIds,
|
|
22014
22032
|
selectedTrace: selectedTraceId === trace.id,
|
|
22015
|
-
|
|
22033
|
+
selectedTraceId,
|
|
22034
|
+
trace,
|
|
22035
|
+
traceById
|
|
22016
22036
|
}
|
|
22017
22037
|
);
|
|
22018
22038
|
}
|
|
@@ -22033,7 +22053,7 @@ function HierarchyTreeNode({
|
|
|
22033
22053
|
selectedNodeId,
|
|
22034
22054
|
selectedPathIds,
|
|
22035
22055
|
selectedTraceId,
|
|
22036
|
-
sessionNavById,
|
|
22056
|
+
sessionNavById: sessionNavById2,
|
|
22037
22057
|
traceById
|
|
22038
22058
|
}
|
|
22039
22059
|
);
|
|
@@ -22108,7 +22128,7 @@ function HierarchyTreeNode({
|
|
|
22108
22128
|
selectedNodeId,
|
|
22109
22129
|
selectedPathIds,
|
|
22110
22130
|
selectedTraceId,
|
|
22111
|
-
sessionNavById,
|
|
22131
|
+
sessionNavById: sessionNavById2,
|
|
22112
22132
|
traceById
|
|
22113
22133
|
},
|
|
22114
22134
|
child.id
|
|
@@ -22131,7 +22151,7 @@ function SessionHierarchyBranch({
|
|
|
22131
22151
|
selectedNodeId,
|
|
22132
22152
|
selectedPathIds,
|
|
22133
22153
|
selectedTraceId,
|
|
22134
|
-
sessionNavById,
|
|
22154
|
+
sessionNavById: sessionNavById2,
|
|
22135
22155
|
traceById
|
|
22136
22156
|
}) {
|
|
22137
22157
|
const detailLabel = formatList([
|
|
@@ -22146,8 +22166,27 @@ function SessionHierarchyBranch({
|
|
|
22146
22166
|
sessionSelectedPath,
|
|
22147
22167
|
selectedTraceId
|
|
22148
22168
|
);
|
|
22169
|
+
const [showGuardrails, setShowGuardrails] = (0, import_react3.useState)(true);
|
|
22149
22170
|
const sessionTimelineRow = sessionTimelineModel?.rows[0] ?? null;
|
|
22150
|
-
const
|
|
22171
|
+
const embeddedTimelineRows = (0, import_react3.useMemo)(() => {
|
|
22172
|
+
if (!sessionTimelineModel) {
|
|
22173
|
+
return [];
|
|
22174
|
+
}
|
|
22175
|
+
const visibleRows = sessionTimelineModel.rows.slice(1);
|
|
22176
|
+
const baseDepth = visibleRows[0]?.depth ?? 0;
|
|
22177
|
+
if (baseDepth <= 0) {
|
|
22178
|
+
return visibleRows;
|
|
22179
|
+
}
|
|
22180
|
+
return visibleRows.map((row) => ({
|
|
22181
|
+
...row,
|
|
22182
|
+
depth: Math.max(0, row.depth - baseDepth),
|
|
22183
|
+
ancestorContinuations: row.ancestorContinuations.slice(baseDepth)
|
|
22184
|
+
}));
|
|
22185
|
+
}, [sessionTimelineModel]);
|
|
22186
|
+
const guardrailRowCount = embeddedTimelineRows.filter(
|
|
22187
|
+
(row) => isGuardrailTimelineRow(row)
|
|
22188
|
+
).length;
|
|
22189
|
+
const showEmbeddedTimeline = isExpanded && embeddedTimelineRows.length > 0;
|
|
22151
22190
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22152
22191
|
"div",
|
|
22153
22192
|
{
|
|
@@ -22215,28 +22254,49 @@ function SessionHierarchyBranch({
|
|
|
22215
22254
|
]
|
|
22216
22255
|
}
|
|
22217
22256
|
),
|
|
22218
|
-
showEmbeddedTimeline && sessionTimelineModel ? /* @__PURE__ */ (0, import_jsx_runtime.
|
|
22219
|
-
"div",
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22257
|
+
showEmbeddedTimeline && sessionTimelineModel ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-timeline-shell", children: [
|
|
22258
|
+
guardrailRowCount ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "session-tree-timeline-toolbar", children: [
|
|
22259
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "session-tree-timeline-toolbar-copy", children: [
|
|
22260
|
+
formatCountLabel(guardrailRowCount, "guardrail check"),
|
|
22261
|
+
" ",
|
|
22262
|
+
showGuardrails ? "compact" : "hidden"
|
|
22263
|
+
] }),
|
|
22264
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22265
|
+
BadgeButton,
|
|
22226
22266
|
{
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
}
|
|
22234
|
-
},
|
|
22235
|
-
rows: sessionTimelineModel.rows.slice(1)
|
|
22267
|
+
variant: "outline",
|
|
22268
|
+
semantic: "guardrail",
|
|
22269
|
+
onClick: () => (0, import_react3.startTransition)(
|
|
22270
|
+
() => setShowGuardrails((current) => !current)
|
|
22271
|
+
),
|
|
22272
|
+
children: showGuardrails ? "Hide guardrails" : "Show guardrails"
|
|
22236
22273
|
}
|
|
22237
22274
|
)
|
|
22238
|
-
}
|
|
22239
|
-
|
|
22275
|
+
] }) : null,
|
|
22276
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22277
|
+
"div",
|
|
22278
|
+
{
|
|
22279
|
+
className: "session-tree-timeline-list",
|
|
22280
|
+
role: "list",
|
|
22281
|
+
"aria-label": "Session timeline",
|
|
22282
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22283
|
+
HierarchyTimelineRows,
|
|
22284
|
+
{
|
|
22285
|
+
className: "is-embedded",
|
|
22286
|
+
guardrailVisibility: showGuardrails ? "compact" : "hidden",
|
|
22287
|
+
model: sessionTimelineModel,
|
|
22288
|
+
onSelectRow: (nodeId) => {
|
|
22289
|
+
const selectedTimelineNode = findSessionNodeById([node], nodeId);
|
|
22290
|
+
if (selectedTimelineNode) {
|
|
22291
|
+
onSelect(selectedTimelineNode);
|
|
22292
|
+
}
|
|
22293
|
+
},
|
|
22294
|
+
rows: embeddedTimelineRows
|
|
22295
|
+
}
|
|
22296
|
+
)
|
|
22297
|
+
}
|
|
22298
|
+
)
|
|
22299
|
+
] }) : isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-node-children", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22240
22300
|
HierarchyTreeNode,
|
|
22241
22301
|
{
|
|
22242
22302
|
defaultExpandedNodeIds,
|
|
@@ -22249,7 +22309,7 @@ function SessionHierarchyBranch({
|
|
|
22249
22309
|
selectedNodeId,
|
|
22250
22310
|
selectedPathIds,
|
|
22251
22311
|
selectedTraceId,
|
|
22252
|
-
sessionNavById,
|
|
22312
|
+
sessionNavById: sessionNavById2,
|
|
22253
22313
|
traceById
|
|
22254
22314
|
},
|
|
22255
22315
|
child.id
|
|
@@ -22258,59 +22318,105 @@ function SessionHierarchyBranch({
|
|
|
22258
22318
|
}
|
|
22259
22319
|
);
|
|
22260
22320
|
}
|
|
22261
|
-
function
|
|
22321
|
+
function TraceHierarchyNode({
|
|
22322
|
+
defaultExpandedNodeIds,
|
|
22262
22323
|
depth,
|
|
22324
|
+
expandedNodeOverrides,
|
|
22263
22325
|
inPath,
|
|
22326
|
+
isExpanded,
|
|
22264
22327
|
maxDurationMs,
|
|
22265
22328
|
node,
|
|
22266
22329
|
nodeCopy,
|
|
22267
22330
|
onSelect,
|
|
22331
|
+
onToggle,
|
|
22268
22332
|
selected,
|
|
22333
|
+
selectedNodeId,
|
|
22334
|
+
selectedPathIds,
|
|
22269
22335
|
selectedTrace,
|
|
22270
|
-
|
|
22336
|
+
selectedTraceId,
|
|
22337
|
+
trace,
|
|
22338
|
+
traceById
|
|
22271
22339
|
}) {
|
|
22272
|
-
|
|
22340
|
+
const isExpandable = node.children.length > 0;
|
|
22341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22273
22342
|
"div",
|
|
22274
22343
|
{
|
|
22275
22344
|
className: "tree-node-wrap tree-trace-wrap",
|
|
22276
22345
|
style: { "--depth": String(depth) },
|
|
22277
|
-
children:
|
|
22278
|
-
|
|
22279
|
-
|
|
22280
|
-
|
|
22281
|
-
|
|
22282
|
-
|
|
22283
|
-
|
|
22284
|
-
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
|
|
22288
|
-
|
|
22289
|
-
|
|
22290
|
-
|
|
22291
|
-
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
|
|
22298
|
-
|
|
22299
|
-
|
|
22300
|
-
|
|
22301
|
-
|
|
22302
|
-
|
|
22303
|
-
|
|
22304
|
-
|
|
22305
|
-
|
|
22306
|
-
|
|
22307
|
-
|
|
22308
|
-
|
|
22309
|
-
|
|
22310
|
-
|
|
22311
|
-
|
|
22312
|
-
|
|
22313
|
-
|
|
22346
|
+
children: [
|
|
22347
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22348
|
+
"div",
|
|
22349
|
+
{
|
|
22350
|
+
className: clsx_default(
|
|
22351
|
+
"tree-node-card is-trace",
|
|
22352
|
+
inPath && "is-in-path",
|
|
22353
|
+
selected && "is-active",
|
|
22354
|
+
selectedTrace && "is-detail-trace"
|
|
22355
|
+
),
|
|
22356
|
+
children: [
|
|
22357
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22358
|
+
"button",
|
|
22359
|
+
{
|
|
22360
|
+
type: "button",
|
|
22361
|
+
className: clsx_default("tree-node-toggle", !isExpandable && "is-static"),
|
|
22362
|
+
disabled: !isExpandable,
|
|
22363
|
+
onClick: () => {
|
|
22364
|
+
if (isExpandable) {
|
|
22365
|
+
onToggle(node.id);
|
|
22366
|
+
}
|
|
22367
|
+
},
|
|
22368
|
+
"aria-label": isExpandable ? `${isExpanded ? "Collapse" : "Expand"} ${nodeCopy.label}` : void 0,
|
|
22369
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: clsx_default(isExpanded && "is-open") })
|
|
22370
|
+
}
|
|
22371
|
+
),
|
|
22372
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22373
|
+
"button",
|
|
22374
|
+
{
|
|
22375
|
+
type: "button",
|
|
22376
|
+
className: "tree-node-select tree-trace-select",
|
|
22377
|
+
onClick: () => onSelect(node),
|
|
22378
|
+
children: [
|
|
22379
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tree-node-copy", children: [
|
|
22380
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-nav-kicker", children: getTraceActorLabel(trace) }),
|
|
22381
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-label", children: nodeCopy.label }),
|
|
22382
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tree-node-meta", children: formatList([
|
|
22383
|
+
formatTimelineTimestamp(trace.startedAt),
|
|
22384
|
+
nodeCopy.meta
|
|
22385
|
+
]) })
|
|
22386
|
+
] }),
|
|
22387
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22388
|
+
TraceElapsedBar,
|
|
22389
|
+
{
|
|
22390
|
+
compact: true,
|
|
22391
|
+
durationMs: trace.durationMs,
|
|
22392
|
+
maxDurationMs
|
|
22393
|
+
}
|
|
22394
|
+
)
|
|
22395
|
+
]
|
|
22396
|
+
}
|
|
22397
|
+
)
|
|
22398
|
+
]
|
|
22399
|
+
}
|
|
22400
|
+
),
|
|
22401
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tree-node-children", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22402
|
+
HierarchyTreeNode,
|
|
22403
|
+
{
|
|
22404
|
+
defaultExpandedNodeIds,
|
|
22405
|
+
depth: depth + 1,
|
|
22406
|
+
expandedNodeOverrides,
|
|
22407
|
+
maxDurationMs,
|
|
22408
|
+
node: child,
|
|
22409
|
+
onSelect,
|
|
22410
|
+
onToggle,
|
|
22411
|
+
selectedNodeId,
|
|
22412
|
+
selectedPathIds,
|
|
22413
|
+
selectedTraceId,
|
|
22414
|
+
sessionNavById,
|
|
22415
|
+
traceById
|
|
22416
|
+
},
|
|
22417
|
+
child.id
|
|
22418
|
+
)) }) : null
|
|
22419
|
+
]
|
|
22314
22420
|
}
|
|
22315
22421
|
);
|
|
22316
22422
|
}
|
|
@@ -22383,24 +22489,45 @@ function SessionTreeTimelineBar({
|
|
|
22383
22489
|
}
|
|
22384
22490
|
function HierarchyTimelineRows({
|
|
22385
22491
|
className,
|
|
22492
|
+
guardrailVisibility = "compact",
|
|
22386
22493
|
model,
|
|
22387
22494
|
onSelectRow,
|
|
22388
22495
|
rows
|
|
22389
22496
|
}) {
|
|
22390
|
-
|
|
22391
|
-
|
|
22497
|
+
const [expandedGuardrailGroups, setExpandedGuardrailGroups] = (0, import_react3.useState)({});
|
|
22498
|
+
const displayItems = (0, import_react3.useMemo)(
|
|
22499
|
+
() => buildHierarchyTimelineDisplayItems(
|
|
22500
|
+
rows,
|
|
22501
|
+
guardrailVisibility,
|
|
22502
|
+
expandedGuardrailGroups
|
|
22503
|
+
),
|
|
22504
|
+
[expandedGuardrailGroups, guardrailVisibility, rows]
|
|
22505
|
+
);
|
|
22506
|
+
if (!displayItems.length) {
|
|
22507
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-empty-state", children: "No visible rows. Show guardrails to inspect them." });
|
|
22508
|
+
}
|
|
22509
|
+
return displayItems.map((item) => {
|
|
22510
|
+
const row = item.row;
|
|
22511
|
+
const isEmbeddedRow = className?.includes("is-embedded") ?? false;
|
|
22512
|
+
const hasSemanticIndent = isEmbeddedRow && row.type === "trace" && row.traceKind === "child-actor";
|
|
22513
|
+
const isTraceRow = item.kind === "row" && row.type === "trace";
|
|
22392
22514
|
const rowClassName = cn(
|
|
22393
22515
|
"hierarchy-timeline-row",
|
|
22394
22516
|
className,
|
|
22395
|
-
isTraceRow
|
|
22517
|
+
(isTraceRow || item.kind === "guardrail-group") && "is-clickable",
|
|
22518
|
+
!isTraceRow && item.kind !== "guardrail-group" && "is-structure",
|
|
22396
22519
|
row.depth === 0 && "is-root",
|
|
22397
22520
|
row.isActive && "is-active",
|
|
22398
22521
|
row.isDetailTrace && "is-detail-trace",
|
|
22399
22522
|
row.isInPath && "is-in-path",
|
|
22523
|
+
hasSemanticIndent && "has-semantic-indent is-child-actor-trace",
|
|
22524
|
+
row.traceKind === "guardrail" && "is-guardrail-trace",
|
|
22525
|
+
item.kind === "guardrail-group" && "is-structure is-guardrail-group",
|
|
22526
|
+
item.kind === "row" && item.compact && "is-guardrail-compact",
|
|
22400
22527
|
`is-${row.type.replace(/[^a-z0-9-]/gi, "-")}`
|
|
22401
22528
|
);
|
|
22402
22529
|
const rowStyle = {
|
|
22403
|
-
"--timeline-depth": String(row.depth),
|
|
22530
|
+
"--timeline-depth": String(row.depth + (hasSemanticIndent ? 1 : 0)),
|
|
22404
22531
|
"--timeline-offset": String(
|
|
22405
22532
|
model.durationMs > 0 ? row.offsetMs / model.durationMs : 0
|
|
22406
22533
|
),
|
|
@@ -22456,26 +22583,11 @@ function HierarchyTimelineRows({
|
|
|
22456
22583
|
{
|
|
22457
22584
|
variant: "secondary",
|
|
22458
22585
|
className: "hierarchy-timeline-pill",
|
|
22459
|
-
semantic: row.badge,
|
|
22460
|
-
children: row.badge
|
|
22586
|
+
semantic: item.kind === "guardrail-group" || row.traceKind === "guardrail" ? "guardrail" : row.badge,
|
|
22587
|
+
children: item.kind === "guardrail-group" ? "Guardrail" : row.badge
|
|
22461
22588
|
}
|
|
22462
22589
|
),
|
|
22463
|
-
|
|
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
|
|
22590
|
+
item.kind === "guardrail-group" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hierarchy-timeline-row-toggle-label", children: item.isExpanded ? "Hide" : `Show ${item.itemCount}` }) : null
|
|
22479
22591
|
] }),
|
|
22480
22592
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-meta", children: row.meta })
|
|
22481
22593
|
] })
|
|
@@ -22485,6 +22597,35 @@ function HierarchyTimelineRows({
|
|
|
22485
22597
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "hierarchy-timeline-row-duration", children: formatElapsedLabel(row.durationMs) })
|
|
22486
22598
|
] })
|
|
22487
22599
|
] });
|
|
22600
|
+
if (item.kind === "guardrail-group") {
|
|
22601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22602
|
+
"div",
|
|
22603
|
+
{
|
|
22604
|
+
role: "listitem",
|
|
22605
|
+
title: buildHierarchyTimelineRowTooltip(row),
|
|
22606
|
+
"data-hierarchy-row-id": row.id,
|
|
22607
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22608
|
+
"button",
|
|
22609
|
+
{
|
|
22610
|
+
type: "button",
|
|
22611
|
+
className: rowClassName,
|
|
22612
|
+
style: rowStyle,
|
|
22613
|
+
onClick: () => (0, import_react3.startTransition)(
|
|
22614
|
+
() => setExpandedGuardrailGroups(
|
|
22615
|
+
(current) => current[item.id] ? Object.fromEntries(
|
|
22616
|
+
Object.entries(current).filter(
|
|
22617
|
+
([key]) => key !== item.id
|
|
22618
|
+
)
|
|
22619
|
+
) : { ...current, [item.id]: true }
|
|
22620
|
+
)
|
|
22621
|
+
),
|
|
22622
|
+
children: rowContent
|
|
22623
|
+
}
|
|
22624
|
+
)
|
|
22625
|
+
},
|
|
22626
|
+
item.id
|
|
22627
|
+
);
|
|
22628
|
+
}
|
|
22488
22629
|
if (isTraceRow) {
|
|
22489
22630
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22490
22631
|
"div",
|
|
@@ -22525,6 +22666,7 @@ function HierarchyTimelineRows({
|
|
|
22525
22666
|
function TraceDetailPanel({
|
|
22526
22667
|
activeTab,
|
|
22527
22668
|
detail,
|
|
22669
|
+
detailPath,
|
|
22528
22670
|
detailTabs,
|
|
22529
22671
|
fallbackTrace,
|
|
22530
22672
|
jsonMode,
|
|
@@ -22533,11 +22675,12 @@ function TraceDetailPanel({
|
|
|
22533
22675
|
onBack,
|
|
22534
22676
|
onNavigateHierarchyNode,
|
|
22535
22677
|
onTabChange,
|
|
22536
|
-
onToggleJsonMode
|
|
22678
|
+
onToggleJsonMode,
|
|
22679
|
+
traceById
|
|
22537
22680
|
}) {
|
|
22538
22681
|
const traceDetailPrimaryRef = (0, import_react3.useRef)(null);
|
|
22539
22682
|
const [showInlineContextRail, setShowInlineContextRail] = (0, import_react3.useState)(false);
|
|
22540
|
-
const detailCopy = detail ? getTraceDisplayCopy(detail) : fallbackTrace ? getTraceDisplayCopy(fallbackTrace) : null;
|
|
22683
|
+
const detailCopy = detailPath.length ? getHierarchyPathDisplayCopy(detailPath, traceById) : detail ? getTraceDisplayCopy(detail) : fallbackTrace ? getTraceDisplayCopy(fallbackTrace) : null;
|
|
22541
22684
|
const detailStatus = detail?.status ?? fallbackTrace?.status ?? null;
|
|
22542
22685
|
const detailDuration = detail ? formatTraceDuration(detail) : fallbackTrace ? fallbackTrace.durationMs == null ? "Running" : `${fallbackTrace.durationMs} ms` : null;
|
|
22543
22686
|
const detailSubtitle = formatTraceProviderSummary(detail ?? fallbackTrace);
|
|
@@ -22736,10 +22879,8 @@ function renderTabContent(tab, detail, jsonMode, onApplyTagFilter, onApplyTraceF
|
|
|
22736
22879
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22737
22880
|
MessagesCard,
|
|
22738
22881
|
{
|
|
22739
|
-
insights: detail.insights,
|
|
22740
22882
|
title: "Request messages",
|
|
22741
|
-
messages: requestMessages
|
|
22742
|
-
sourcePrefix: "request"
|
|
22883
|
+
messages: requestMessages
|
|
22743
22884
|
}
|
|
22744
22885
|
),
|
|
22745
22886
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(JsonCard, { title: "Request options", value: detail.request.options }),
|
|
@@ -22768,10 +22909,8 @@ function renderTabContent(tab, detail, jsonMode, onApplyTagFilter, onApplyTraceF
|
|
|
22768
22909
|
responseMessage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22769
22910
|
MessagesCard,
|
|
22770
22911
|
{
|
|
22771
|
-
insights: detail.insights,
|
|
22772
22912
|
title: "Assistant message",
|
|
22773
|
-
messages: [responseMessage]
|
|
22774
|
-
sourcePrefix: "response"
|
|
22913
|
+
messages: [responseMessage]
|
|
22775
22914
|
}
|
|
22776
22915
|
) : null,
|
|
22777
22916
|
toolCalls.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolCallsCard, { title: "Tool calls", toolCalls }) : null,
|
|
@@ -22834,10 +22973,8 @@ function renderTabContent(tab, detail, jsonMode, onApplyTagFilter, onApplyTraceF
|
|
|
22834
22973
|
detail.stream.reconstructed?.message ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22835
22974
|
MessagesCard,
|
|
22836
22975
|
{
|
|
22837
|
-
insights: detail.insights,
|
|
22838
22976
|
title: "Reconstructed output",
|
|
22839
|
-
messages: [detail.stream.reconstructed.message]
|
|
22840
|
-
sourcePrefix: "stream"
|
|
22977
|
+
messages: [detail.stream.reconstructed.message]
|
|
22841
22978
|
}
|
|
22842
22979
|
) : null,
|
|
22843
22980
|
detail.stream.reconstructed?.tool_calls?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -22848,6 +22985,24 @@ function renderTabContent(tab, detail, jsonMode, onApplyTagFilter, onApplyTraceF
|
|
|
22848
22985
|
}
|
|
22849
22986
|
) : null
|
|
22850
22987
|
] });
|
|
22988
|
+
case "otel":
|
|
22989
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22990
|
+
JsonCard,
|
|
22991
|
+
{
|
|
22992
|
+
title: "OTel span",
|
|
22993
|
+
value: {
|
|
22994
|
+
name: detail.name,
|
|
22995
|
+
spanContext: detail.spanContext,
|
|
22996
|
+
parentSpanId: detail.parentSpanId,
|
|
22997
|
+
spanKind: detail.spanKind,
|
|
22998
|
+
spanStatus: detail.spanStatus,
|
|
22999
|
+
startTime: detail.startedAt,
|
|
23000
|
+
endTime: detail.endedAt,
|
|
23001
|
+
attributes: detail.attributes,
|
|
23002
|
+
events: detail.events
|
|
23003
|
+
}
|
|
23004
|
+
}
|
|
23005
|
+
);
|
|
22851
23006
|
default:
|
|
22852
23007
|
return null;
|
|
22853
23008
|
}
|
|
@@ -22863,7 +23018,6 @@ function ConversationView({
|
|
|
22863
23018
|
);
|
|
22864
23019
|
const costUsd = getUsageCostUsd(detail.usage);
|
|
22865
23020
|
const costLabel = formatUsdCost(costUsd);
|
|
22866
|
-
const traceInsights = detail.insights ?? EMPTY_TRACE_INSIGHTS;
|
|
22867
23021
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-layout", children: [
|
|
22868
23022
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-meta", children: [
|
|
22869
23023
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-meta-primary", children: [
|
|
@@ -22922,26 +23076,21 @@ function ConversationView({
|
|
|
22922
23076
|
) : null
|
|
22923
23077
|
] })
|
|
22924
23078
|
] }),
|
|
22925
|
-
traceInsights.highlights.length || traceInsights.structuredInputs.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TraceInsightsSummary, { detail, insights: traceInsights }) : null,
|
|
22926
23079
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "conversation-thread", children: [
|
|
22927
23080
|
requestMessages.length ? requestMessages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22928
23081
|
ConversationMessage,
|
|
22929
23082
|
{
|
|
22930
|
-
|
|
22931
|
-
message,
|
|
22932
|
-
source: `request:${index}`
|
|
23083
|
+
message
|
|
22933
23084
|
},
|
|
22934
23085
|
`${message.role}-${index}`
|
|
22935
23086
|
)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "muted-copy", children: "No request messages recorded." }),
|
|
22936
23087
|
hasRenderableContent(responseMessage?.content) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22937
23088
|
ConversationMessage,
|
|
22938
23089
|
{
|
|
22939
|
-
insights: traceInsights,
|
|
22940
23090
|
message: {
|
|
22941
23091
|
role: responseMessage?.role || "assistant",
|
|
22942
23092
|
content: responseMessage?.content
|
|
22943
|
-
}
|
|
22944
|
-
source: "response:0"
|
|
23093
|
+
}
|
|
22945
23094
|
}
|
|
22946
23095
|
) : null,
|
|
22947
23096
|
responseToolCalls.map((toolCall, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -22956,59 +23105,8 @@ function ConversationView({
|
|
|
22956
23105
|
] })
|
|
22957
23106
|
] });
|
|
22958
23107
|
}
|
|
22959
|
-
function TraceInsightsSummary({
|
|
22960
|
-
detail,
|
|
22961
|
-
insights
|
|
22962
|
-
}) {
|
|
22963
|
-
const title = detail.kind === "guardrail" ? "Why this guardrail ran" : "Trace insights";
|
|
22964
|
-
const highlights = insights.highlights.filter(
|
|
22965
|
-
(item) => item.kind !== "structured-input" || !insights.structuredInputs.length
|
|
22966
|
-
);
|
|
22967
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { className: "detail-section trace-insights-card", children: [
|
|
22968
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, { children: [
|
|
22969
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: title }),
|
|
22970
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardDescription, { children: "Deterministic signals extracted from the trace payload." })
|
|
22971
|
-
] }),
|
|
22972
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, { className: "trace-insights-content", children: [
|
|
22973
|
-
highlights.map((highlight, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22974
|
-
"div",
|
|
22975
|
-
{
|
|
22976
|
-
className: "trace-insight-item",
|
|
22977
|
-
children: [
|
|
22978
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "trace-insight-item-header", children: [
|
|
22979
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { semantic: "guardrail", variant: "secondary", children: highlight.title }),
|
|
22980
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "trace-insight-item-source", children: formatInsightSource(highlight.source) })
|
|
22981
|
-
] }),
|
|
22982
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-insight-item-copy", children: highlight.description })
|
|
22983
|
-
]
|
|
22984
|
-
},
|
|
22985
|
-
`${highlight.kind}-${highlight.source}-${index}`
|
|
22986
|
-
)),
|
|
22987
|
-
insights.structuredInputs.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22988
|
-
"div",
|
|
22989
|
-
{
|
|
22990
|
-
className: "trace-insight-item is-structured",
|
|
22991
|
-
children: [
|
|
22992
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "trace-insight-item-header", children: [
|
|
22993
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge, { semantic: "guardrail", variant: "secondary", children: [
|
|
22994
|
-
"Structured ",
|
|
22995
|
-
item.role,
|
|
22996
|
-
" input"
|
|
22997
|
-
] }),
|
|
22998
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-insight-item-tags", children: item.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", children: tag }, tag)) })
|
|
22999
|
-
] }),
|
|
23000
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trace-insight-item-copy", children: item.snippet })
|
|
23001
|
-
]
|
|
23002
|
-
},
|
|
23003
|
-
`${item.role}-${item.snippet}-${index}`
|
|
23004
|
-
))
|
|
23005
|
-
] })
|
|
23006
|
-
] });
|
|
23007
|
-
}
|
|
23008
23108
|
function ConversationMessage({
|
|
23009
|
-
|
|
23010
|
-
message,
|
|
23011
|
-
source
|
|
23109
|
+
message
|
|
23012
23110
|
}) {
|
|
23013
23111
|
const toolCalls = getMessageToolCalls(message);
|
|
23014
23112
|
if (message.role === "tool") {
|
|
@@ -23022,21 +23120,8 @@ function ConversationMessage({
|
|
|
23022
23120
|
);
|
|
23023
23121
|
}
|
|
23024
23122
|
if (toolCalls.length) {
|
|
23025
|
-
const messageInsights2 = getMessageInsightMatches(
|
|
23026
|
-
insights,
|
|
23027
|
-
source,
|
|
23028
|
-
message.role,
|
|
23029
|
-
message.content
|
|
23030
|
-
);
|
|
23031
23123
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.Fragment, { children: [
|
|
23032
|
-
hasRenderableContent(message.content) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
23033
|
-
ConversationBubble,
|
|
23034
|
-
{
|
|
23035
|
-
role: message.role,
|
|
23036
|
-
content: message.content,
|
|
23037
|
-
insights: messageInsights2
|
|
23038
|
-
}
|
|
23039
|
-
) : null,
|
|
23124
|
+
hasRenderableContent(message.content) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationBubble, { role: message.role, content: message.content }) : null,
|
|
23040
23125
|
toolCalls.map((toolCall, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
23041
23126
|
ToolCallBubble,
|
|
23042
23127
|
{
|
|
@@ -23050,33 +23135,16 @@ function ConversationMessage({
|
|
|
23050
23135
|
if (!hasRenderableContent(message.content)) {
|
|
23051
23136
|
return null;
|
|
23052
23137
|
}
|
|
23053
|
-
|
|
23054
|
-
insights,
|
|
23055
|
-
source,
|
|
23056
|
-
message.role,
|
|
23057
|
-
message.content
|
|
23058
|
-
);
|
|
23059
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
23060
|
-
ConversationBubble,
|
|
23061
|
-
{
|
|
23062
|
-
content: message.content,
|
|
23063
|
-
insights: messageInsights,
|
|
23064
|
-
role: message.role
|
|
23065
|
-
}
|
|
23066
|
-
);
|
|
23138
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationBubble, { content: message.content, role: message.role });
|
|
23067
23139
|
}
|
|
23068
23140
|
function ConversationBubble({
|
|
23069
23141
|
content,
|
|
23070
|
-
insights,
|
|
23071
23142
|
role
|
|
23072
23143
|
}) {
|
|
23073
23144
|
const tone = role === "user" ? "is-user" : role === "assistant" ? "is-assistant" : "is-system";
|
|
23074
23145
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: clsx_default("conversation-row", tone), children: [
|
|
23075
23146
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-role", children: role }),
|
|
23076
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
23077
|
-
insights.structuredInputs.length || insights.highlights.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageInsightBanner, { insights }) : null,
|
|
23078
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RichMessageContent, { content, role })
|
|
23079
|
-
] })
|
|
23147
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "conversation-bubble", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RichMessageContent, { content, role }) })
|
|
23080
23148
|
] });
|
|
23081
23149
|
}
|
|
23082
23150
|
function ToolResultBubble({
|
|
@@ -23110,54 +23178,6 @@ function ToolCallBubble({ index, toolCall }) {
|
|
|
23110
23178
|
] })
|
|
23111
23179
|
] });
|
|
23112
23180
|
}
|
|
23113
|
-
function MessageInsightBanner({
|
|
23114
|
-
insights
|
|
23115
|
-
}) {
|
|
23116
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "message-insight-banner", children: [
|
|
23117
|
-
insights.structuredInputs.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
23118
|
-
"div",
|
|
23119
|
-
{
|
|
23120
|
-
className: "message-insight-card",
|
|
23121
|
-
children: [
|
|
23122
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "message-insight-card-header", children: [
|
|
23123
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { semantic: "guardrail", variant: "secondary", children: "Structured input" }),
|
|
23124
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "message-insight-card-tags", children: item.tags.slice(0, 3).map((tag) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: "outline", children: tag }, tag)) })
|
|
23125
|
-
] }),
|
|
23126
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "message-insight-card-copy", children: [
|
|
23127
|
-
"XML-like markup detected in this ",
|
|
23128
|
-
item.role,
|
|
23129
|
-
" message."
|
|
23130
|
-
] })
|
|
23131
|
-
]
|
|
23132
|
-
},
|
|
23133
|
-
`${item.role}-${item.snippet}-${index}`
|
|
23134
|
-
)),
|
|
23135
|
-
insights.highlights.map((highlight, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
23136
|
-
"div",
|
|
23137
|
-
{
|
|
23138
|
-
className: "message-insight-card is-highlight",
|
|
23139
|
-
children: [
|
|
23140
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "message-insight-card-header", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { semantic: "guardrail", variant: "secondary", children: highlight.title }) }),
|
|
23141
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "message-insight-card-copy", children: highlight.description })
|
|
23142
|
-
]
|
|
23143
|
-
},
|
|
23144
|
-
`${highlight.kind}-${highlight.source}-${index}`
|
|
23145
|
-
))
|
|
23146
|
-
] });
|
|
23147
|
-
}
|
|
23148
|
-
function getMessageInsightMatches(insights, source, role, content) {
|
|
23149
|
-
const text = extractPlainMessageText(content);
|
|
23150
|
-
const normalizedText = text ? text.replace(/\s+/g, " ") : null;
|
|
23151
|
-
const structuredInputs = insights.structuredInputs.filter(
|
|
23152
|
-
(item) => item.role === role && normalizedText !== null && normalizedText.includes(item.snippet.replace(/\.\.\.$/, ""))
|
|
23153
|
-
);
|
|
23154
|
-
return {
|
|
23155
|
-
highlights: insights.highlights.filter(
|
|
23156
|
-
(highlight) => !(highlight.kind === "structured-input" && structuredInputs.length) && (highlight.source === source || normalizedText !== null && highlight.snippet.length > 0 && normalizedText.includes(highlight.snippet.replace(/\.\.\.$/, "")))
|
|
23157
|
-
),
|
|
23158
|
-
structuredInputs
|
|
23159
|
-
};
|
|
23160
|
-
}
|
|
23161
23181
|
function RichMessageContent({
|
|
23162
23182
|
content,
|
|
23163
23183
|
role
|
|
@@ -23542,9 +23562,7 @@ function MetadataActionButton({
|
|
|
23542
23562
|
);
|
|
23543
23563
|
}
|
|
23544
23564
|
function MessagesCard({
|
|
23545
|
-
insights = EMPTY_TRACE_INSIGHTS,
|
|
23546
23565
|
messages,
|
|
23547
|
-
sourcePrefix,
|
|
23548
23566
|
title
|
|
23549
23567
|
}) {
|
|
23550
23568
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { className: "detail-section", children: [
|
|
@@ -23552,9 +23570,7 @@ function MessagesCard({
|
|
|
23552
23570
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, { className: "message-stack", children: messages.length ? messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
23553
23571
|
StructuredMessageCard,
|
|
23554
23572
|
{
|
|
23555
|
-
|
|
23556
|
-
message,
|
|
23557
|
-
source: `${sourcePrefix}:${index}`
|
|
23573
|
+
message
|
|
23558
23574
|
},
|
|
23559
23575
|
`${message.role}-${index}`
|
|
23560
23576
|
)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "muted-copy", children: "No messages recorded." }) })
|
|
@@ -23570,20 +23586,12 @@ function ToolCallsCard({
|
|
|
23570
23586
|
] });
|
|
23571
23587
|
}
|
|
23572
23588
|
function StructuredMessageCard({
|
|
23573
|
-
|
|
23574
|
-
message,
|
|
23575
|
-
source
|
|
23589
|
+
message
|
|
23576
23590
|
}) {
|
|
23577
23591
|
const toolCalls = getMessageToolCalls(message);
|
|
23578
23592
|
const hasContent = hasRenderableContent(message.content);
|
|
23579
23593
|
const isToolCallTurn = toolCalls.length > 0;
|
|
23580
23594
|
const isToolResult = message.role === "tool";
|
|
23581
|
-
const messageInsights = getMessageInsightMatches(
|
|
23582
|
-
insights,
|
|
23583
|
-
source,
|
|
23584
|
-
message.role,
|
|
23585
|
-
message.content
|
|
23586
|
-
);
|
|
23587
23595
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("message-card", `role-${message.role}`), children: [
|
|
23588
23596
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "message-card-header", children: [
|
|
23589
23597
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { semantic: message.role, variant: "secondary", children: message.role }),
|
|
@@ -23594,7 +23602,6 @@ function StructuredMessageCard({
|
|
|
23594
23602
|
] })
|
|
23595
23603
|
] }),
|
|
23596
23604
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "message-card-body", children: [
|
|
23597
|
-
messageInsights.structuredInputs.length || messageInsights.highlights.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageInsightBanner, { insights: messageInsights }) : null,
|
|
23598
23605
|
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RichMessageContent, { content: message.content, role: message.role }) : isToolCallTurn ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "message-card-hint", children: "Tool call emitted." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "message-card-hint", children: "No content recorded." }),
|
|
23599
23606
|
isToolCallTurn ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolCallStack, { toolCalls, compact: true }) : null
|
|
23600
23607
|
] })
|
|
@@ -23766,6 +23773,7 @@ function buildDetailTabs(detail) {
|
|
|
23766
23773
|
if (detail.stream) {
|
|
23767
23774
|
tabs.push({ id: "stream", label: "Stream" });
|
|
23768
23775
|
}
|
|
23776
|
+
tabs.push({ id: "otel", label: "OTel" });
|
|
23769
23777
|
return tabs;
|
|
23770
23778
|
}
|
|
23771
23779
|
function getHierarchyNodeCopy(node, traceById) {
|
|
@@ -23824,8 +23832,8 @@ function getHierarchyNodeCopy(node, traceById) {
|
|
|
23824
23832
|
trace.provider,
|
|
23825
23833
|
trace.model,
|
|
23826
23834
|
formatCostSummaryLabel(
|
|
23827
|
-
|
|
23828
|
-
|
|
23835
|
+
getHierarchyNodeCostUsd(node) ?? trace.costUsd,
|
|
23836
|
+
node.count > 1
|
|
23829
23837
|
)
|
|
23830
23838
|
]) : formatList([
|
|
23831
23839
|
formatCountLabel(node.count, "call"),
|
|
@@ -23848,55 +23856,24 @@ function getHierarchyNodeCopy(node, traceById) {
|
|
|
23848
23856
|
}
|
|
23849
23857
|
}
|
|
23850
23858
|
function getTraceDisplayCopy(trace) {
|
|
23851
|
-
const actor = trace.hierarchy.childActorId || trace.hierarchy.rootActorId;
|
|
23852
|
-
const breadcrumbs = getTraceBreadcrumbs(trace);
|
|
23853
|
-
const pathParts = breadcrumbs.map((item) => item.label);
|
|
23854
23859
|
return {
|
|
23855
|
-
breadcrumbs,
|
|
23856
|
-
path:
|
|
23857
|
-
subtitle: formatList([actor, trace.provider, trace.model]),
|
|
23860
|
+
breadcrumbs: [],
|
|
23861
|
+
path: "",
|
|
23858
23862
|
title: getTraceTitle(trace)
|
|
23859
23863
|
};
|
|
23860
23864
|
}
|
|
23861
|
-
function
|
|
23862
|
-
const
|
|
23863
|
-
|
|
23864
|
-
|
|
23865
|
-
|
|
23866
|
-
|
|
23867
|
-
|
|
23868
|
-
|
|
23869
|
-
|
|
23870
|
-
|
|
23871
|
-
|
|
23872
|
-
|
|
23873
|
-
];
|
|
23874
|
-
if (trace.kind === "guardrail") {
|
|
23875
|
-
const label = `${capitalize(trace.hierarchy.guardrailPhase || "guardrail")} guardrail`;
|
|
23876
|
-
breadcrumbs.push({
|
|
23877
|
-
label,
|
|
23878
|
-
nodeId: `guardrail:${sessionId}:${rootActorId}:${trace.hierarchy.guardrailType || label.toLowerCase()}`
|
|
23879
|
-
});
|
|
23880
|
-
} else if (trace.kind === "child-actor" && trace.hierarchy.childActorId) {
|
|
23881
|
-
breadcrumbs.push({
|
|
23882
|
-
label: `Child actor: ${trace.hierarchy.childActorId}`,
|
|
23883
|
-
nodeId: `child-actor:${sessionId}:${rootActorId}:${trace.hierarchy.childActorId}`
|
|
23884
|
-
});
|
|
23885
|
-
} else if (trace.kind === "stage") {
|
|
23886
|
-
if (trace.hierarchy.childActorId) {
|
|
23887
|
-
breadcrumbs.push({
|
|
23888
|
-
label: `Child actor: ${trace.hierarchy.childActorId}`,
|
|
23889
|
-
nodeId: `child-actor:${sessionId}:${rootActorId}:${trace.hierarchy.childActorId}`
|
|
23890
|
-
});
|
|
23891
|
-
}
|
|
23892
|
-
if (trace.hierarchy.stage) {
|
|
23893
|
-
breadcrumbs.push({
|
|
23894
|
-
label: `Stage: ${trace.hierarchy.stage}`,
|
|
23895
|
-
nodeId: `stage:${sessionId}:${rootActorId}:${trace.hierarchy.childActorId || "root"}:${trace.hierarchy.stage}`
|
|
23896
|
-
});
|
|
23897
|
-
}
|
|
23898
|
-
}
|
|
23899
|
-
return breadcrumbs;
|
|
23865
|
+
function getHierarchyPathDisplayCopy(path, traceById) {
|
|
23866
|
+
const breadcrumbs = path.map((node) => ({
|
|
23867
|
+
label: getHierarchyNodeCopy(node, traceById).label,
|
|
23868
|
+
nodeId: node.id
|
|
23869
|
+
}));
|
|
23870
|
+
const lastNode = path[path.length - 1] ?? null;
|
|
23871
|
+
const lastTrace = lastNode?.type === "trace" && lastNode.meta.traceId ? traceById.get(lastNode.meta.traceId) ?? null : null;
|
|
23872
|
+
return {
|
|
23873
|
+
breadcrumbs,
|
|
23874
|
+
path: breadcrumbs.map((item) => item.label).join(" / "),
|
|
23875
|
+
title: lastTrace ? getTraceTitle(lastTrace) : breadcrumbs.at(-1)?.label || "Trace"
|
|
23876
|
+
};
|
|
23900
23877
|
}
|
|
23901
23878
|
function formatTraceProviderSummary(trace) {
|
|
23902
23879
|
if (!trace) {
|
|
@@ -23924,7 +23901,7 @@ function getTraceTitle(trace) {
|
|
|
23924
23901
|
return trace.hierarchy.stage ? `Stage run: ${trace.hierarchy.stage}` : "Stage run";
|
|
23925
23902
|
}
|
|
23926
23903
|
if (trace.kind === "child-actor") {
|
|
23927
|
-
return `Child actor ${trace.mode}`;
|
|
23904
|
+
return trace.hierarchy.childActorId ? `Child actor ${trace.mode}: ${trace.hierarchy.childActorId}` : `Child actor ${trace.mode}`;
|
|
23928
23905
|
}
|
|
23929
23906
|
if (trace.kind === "actor") {
|
|
23930
23907
|
return trace.mode === "stream" ? "Actor response stream" : "Actor response invoke";
|
|
@@ -24047,12 +24024,12 @@ function patchHierarchyNode(node, traceId, previousSummary, nextSummary, costDel
|
|
|
24047
24024
|
let nextLabel = node.label;
|
|
24048
24025
|
if (containsTrace) {
|
|
24049
24026
|
if (node.type === "trace" && node.meta.traceId === traceId) {
|
|
24050
|
-
nextMeta.costUsd = nextSummary.costUsd;
|
|
24051
24027
|
nextMeta.model = nextSummary.model;
|
|
24052
24028
|
nextMeta.provider = nextSummary.provider;
|
|
24053
24029
|
nextMeta.status = nextSummary.status;
|
|
24054
24030
|
nextLabel = nextSummary.model ? `${nextSummary.model} ${nextSummary.mode}` : traceId;
|
|
24055
|
-
}
|
|
24031
|
+
}
|
|
24032
|
+
if (costDelta !== 0 || previousSummary?.costUsd !== null || nextSummary.costUsd !== null) {
|
|
24056
24033
|
const currentCost = typeof nextMeta.costUsd === "number" && Number.isFinite(nextMeta.costUsd) ? nextMeta.costUsd : 0;
|
|
24057
24034
|
nextMeta.costUsd = roundCostUsd2(currentCost + costDelta);
|
|
24058
24035
|
}
|
|
@@ -24110,6 +24087,7 @@ function buildHierarchyTimelineModel(rootNode, traceById, selectedNodeId, select
|
|
|
24110
24087
|
costUsd: getHierarchyNodeCostUsd(node),
|
|
24111
24088
|
depth,
|
|
24112
24089
|
durationMs: timing.durationMs,
|
|
24090
|
+
guardrailPhase: trace?.hierarchy.guardrailPhase ?? null,
|
|
24113
24091
|
hasHighlights: Boolean(trace?.flags?.hasHighlights),
|
|
24114
24092
|
hasStructuredInput: Boolean(trace?.flags?.hasStructuredInput),
|
|
24115
24093
|
hasVisibleChildren: children.length > 0,
|
|
@@ -24120,8 +24098,12 @@ function buildHierarchyTimelineModel(rootNode, traceById, selectedNodeId, select
|
|
|
24120
24098
|
isLastSibling,
|
|
24121
24099
|
label: copy.label,
|
|
24122
24100
|
meta: copy.meta,
|
|
24101
|
+
model: trace?.model ?? null,
|
|
24123
24102
|
offsetMs: Math.max(0, timing.startMs - rootTiming.startMs),
|
|
24103
|
+
provider: trace?.provider ?? null,
|
|
24124
24104
|
startedAt: timing.startedAt,
|
|
24105
|
+
traceId: node.meta?.traceId ?? null,
|
|
24106
|
+
traceKind: trace?.kind ?? null,
|
|
24125
24107
|
type: node.type
|
|
24126
24108
|
});
|
|
24127
24109
|
for (const [index, child] of children.entries()) {
|
|
@@ -24142,6 +24124,128 @@ function buildHierarchyTimelineModel(rootNode, traceById, selectedNodeId, select
|
|
|
24142
24124
|
startedAt: rootTiming.startedAt
|
|
24143
24125
|
};
|
|
24144
24126
|
}
|
|
24127
|
+
function isGuardrailTimelineRow(row) {
|
|
24128
|
+
return row.type === "trace" && row.traceKind === "guardrail";
|
|
24129
|
+
}
|
|
24130
|
+
function buildHierarchyTimelineDisplayItems(rows, guardrailVisibility, expandedGuardrailGroups) {
|
|
24131
|
+
const items = [];
|
|
24132
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
24133
|
+
const row = rows[index];
|
|
24134
|
+
if (!isGuardrailTimelineRow(row)) {
|
|
24135
|
+
items.push({ compact: false, id: row.id, kind: "row", row });
|
|
24136
|
+
continue;
|
|
24137
|
+
}
|
|
24138
|
+
let groupEnd = index + 1;
|
|
24139
|
+
while (groupEnd < rows.length && isGuardrailTimelineRow(rows[groupEnd]) && rows[groupEnd].depth === row.depth) {
|
|
24140
|
+
groupEnd += 1;
|
|
24141
|
+
}
|
|
24142
|
+
const groupRows = rows.slice(index, groupEnd);
|
|
24143
|
+
index = groupEnd - 1;
|
|
24144
|
+
if (guardrailVisibility === "hidden") {
|
|
24145
|
+
continue;
|
|
24146
|
+
}
|
|
24147
|
+
if (groupRows.length === 1) {
|
|
24148
|
+
items.push({
|
|
24149
|
+
compact: true,
|
|
24150
|
+
id: row.id,
|
|
24151
|
+
kind: "row",
|
|
24152
|
+
row
|
|
24153
|
+
});
|
|
24154
|
+
continue;
|
|
24155
|
+
}
|
|
24156
|
+
const groupId = getGuardrailGroupId(groupRows);
|
|
24157
|
+
const forceExpanded = groupRows.some(
|
|
24158
|
+
(item) => item.isActive || item.isDetailTrace || item.hasVisibleChildren
|
|
24159
|
+
);
|
|
24160
|
+
const isExpanded = forceExpanded || Boolean(expandedGuardrailGroups[groupId]);
|
|
24161
|
+
if (!isExpanded) {
|
|
24162
|
+
items.push({
|
|
24163
|
+
id: groupId,
|
|
24164
|
+
isExpanded: false,
|
|
24165
|
+
itemCount: groupRows.length,
|
|
24166
|
+
kind: "guardrail-group",
|
|
24167
|
+
row: buildGuardrailGroupRow(groupRows)
|
|
24168
|
+
});
|
|
24169
|
+
continue;
|
|
24170
|
+
}
|
|
24171
|
+
if (expandedGuardrailGroups[groupId]) {
|
|
24172
|
+
items.push({
|
|
24173
|
+
id: groupId,
|
|
24174
|
+
isExpanded: true,
|
|
24175
|
+
itemCount: groupRows.length,
|
|
24176
|
+
kind: "guardrail-group",
|
|
24177
|
+
row: buildGuardrailGroupRow(groupRows)
|
|
24178
|
+
});
|
|
24179
|
+
}
|
|
24180
|
+
items.push(
|
|
24181
|
+
...groupRows.map((item) => ({
|
|
24182
|
+
compact: false,
|
|
24183
|
+
id: item.id,
|
|
24184
|
+
kind: "row",
|
|
24185
|
+
row: item
|
|
24186
|
+
}))
|
|
24187
|
+
);
|
|
24188
|
+
}
|
|
24189
|
+
return items;
|
|
24190
|
+
}
|
|
24191
|
+
function getGuardrailGroupId(rows) {
|
|
24192
|
+
return `guardrail-group:${rows[0]?.id || "unknown"}:${rows.at(-1)?.id || "unknown"}`;
|
|
24193
|
+
}
|
|
24194
|
+
function buildGuardrailGroupRow(rows) {
|
|
24195
|
+
const firstRow = rows[0];
|
|
24196
|
+
const maxEndMs = rows.reduce(
|
|
24197
|
+
(maxValue, row) => Math.max(maxValue, row.offsetMs + row.durationMs),
|
|
24198
|
+
firstRow.offsetMs + firstRow.durationMs
|
|
24199
|
+
);
|
|
24200
|
+
const guardrailPhase = getSharedTimelineRowValue(rows, "guardrailPhase");
|
|
24201
|
+
const provider = getSharedTimelineRowValue(rows, "provider");
|
|
24202
|
+
const model = getSharedTimelineRowValue(rows, "model");
|
|
24203
|
+
return {
|
|
24204
|
+
...firstRow,
|
|
24205
|
+
badge: "Guardrail",
|
|
24206
|
+
costUsd: sumTimelineRowCosts(rows),
|
|
24207
|
+
durationMs: Math.max(1, maxEndMs - firstRow.offsetMs),
|
|
24208
|
+
guardrailPhase,
|
|
24209
|
+
hasHighlights: rows.some((row) => row.hasHighlights),
|
|
24210
|
+
hasStructuredInput: rows.some((row) => row.hasStructuredInput),
|
|
24211
|
+
hasVisibleChildren: rows.at(-1)?.hasVisibleChildren ?? false,
|
|
24212
|
+
id: getGuardrailGroupId(rows),
|
|
24213
|
+
isActive: false,
|
|
24214
|
+
isDetailTrace: false,
|
|
24215
|
+
isInPath: rows.some((row) => row.isInPath),
|
|
24216
|
+
isLastSibling: rows.at(-1)?.isLastSibling ?? firstRow.isLastSibling,
|
|
24217
|
+
label: getGuardrailGroupLabel(rows, guardrailPhase),
|
|
24218
|
+
meta: formatList([
|
|
24219
|
+
formatList([provider, model]),
|
|
24220
|
+
formatCostSummaryLabel(sumTimelineRowCosts(rows), rows.length > 1)
|
|
24221
|
+
]) || formatCountLabel(rows.length, "guardrail check"),
|
|
24222
|
+
model,
|
|
24223
|
+
provider,
|
|
24224
|
+
traceId: null,
|
|
24225
|
+
traceKind: "guardrail",
|
|
24226
|
+
type: "guardrail"
|
|
24227
|
+
};
|
|
24228
|
+
}
|
|
24229
|
+
function getGuardrailGroupLabel(rows, guardrailPhase) {
|
|
24230
|
+
if (rows.length === 1) {
|
|
24231
|
+
return rows[0].label;
|
|
24232
|
+
}
|
|
24233
|
+
if (guardrailPhase) {
|
|
24234
|
+
return formatCountLabel(rows.length, `${guardrailPhase} guardrail check`);
|
|
24235
|
+
}
|
|
24236
|
+
return formatCountLabel(rows.length, "guardrail check");
|
|
24237
|
+
}
|
|
24238
|
+
function getSharedTimelineRowValue(rows, key) {
|
|
24239
|
+
const firstValue = rows[0]?.[key] ?? null;
|
|
24240
|
+
return rows.every((row) => (row[key] ?? null) === firstValue) ? firstValue : null;
|
|
24241
|
+
}
|
|
24242
|
+
function sumTimelineRowCosts(rows) {
|
|
24243
|
+
const costRows = rows.map((row) => row.costUsd).filter((cost) => typeof cost === "number");
|
|
24244
|
+
if (!costRows.length) {
|
|
24245
|
+
return null;
|
|
24246
|
+
}
|
|
24247
|
+
return roundCostUsd2(costRows.reduce((sum, cost) => sum + cost, 0));
|
|
24248
|
+
}
|
|
24145
24249
|
function compareHierarchyNodesForTimeline(left, right, getTiming) {
|
|
24146
24250
|
const leftTiming = getTiming(left);
|
|
24147
24251
|
const rightTiming = getTiming(right);
|
|
@@ -24220,32 +24324,12 @@ function getTimelineTypeLabel(type) {
|
|
|
24220
24324
|
return startCase(type);
|
|
24221
24325
|
}
|
|
24222
24326
|
}
|
|
24223
|
-
function formatInsightSource(source) {
|
|
24224
|
-
if (source.startsWith("request:")) {
|
|
24225
|
-
return `Request ${Number(source.split(":")[1] || 0) + 1}`;
|
|
24226
|
-
}
|
|
24227
|
-
if (source.startsWith("response:")) {
|
|
24228
|
-
return "Response";
|
|
24229
|
-
}
|
|
24230
|
-
if (source.startsWith("stream:")) {
|
|
24231
|
-
return "Stream";
|
|
24232
|
-
}
|
|
24233
|
-
if (source === "trace:guardrail") {
|
|
24234
|
-
return "Guardrail context";
|
|
24235
|
-
}
|
|
24236
|
-
return source;
|
|
24237
|
-
}
|
|
24238
24327
|
function buildHierarchyTimelineRowTooltip(row) {
|
|
24239
24328
|
const parts = [
|
|
24240
24329
|
`${row.label} (${getTimelineTypeLabel(row.type)})`,
|
|
24241
24330
|
`Started ${formatTimelineTimestamp(row.startedAt)}`,
|
|
24242
24331
|
`Duration ${formatElapsedLabel(row.durationMs)}`
|
|
24243
24332
|
];
|
|
24244
|
-
if (row.hasStructuredInput) {
|
|
24245
|
-
parts.push("Structured input detected");
|
|
24246
|
-
} else if (row.hasHighlights) {
|
|
24247
|
-
parts.push("Trace insights available");
|
|
24248
|
-
}
|
|
24249
24333
|
if (row.costUsd !== null) {
|
|
24250
24334
|
parts.push(`Cost ${formatUsdCost(row.costUsd)}`);
|
|
24251
24335
|
}
|
|
@@ -24709,16 +24793,6 @@ function toMarkdownText(content) {
|
|
|
24709
24793
|
}
|
|
24710
24794
|
return null;
|
|
24711
24795
|
}
|
|
24712
|
-
function extractPlainMessageText(content) {
|
|
24713
|
-
const markdown = toMarkdownText(content);
|
|
24714
|
-
if (markdown !== null) {
|
|
24715
|
-
return markdown;
|
|
24716
|
-
}
|
|
24717
|
-
if (typeof content === "string") {
|
|
24718
|
-
return content;
|
|
24719
|
-
}
|
|
24720
|
-
return null;
|
|
24721
|
-
}
|
|
24722
24796
|
function detectStructuredMarkup(text) {
|
|
24723
24797
|
const tagRegex = /<\/?([A-Za-z][\w:-]*)\b[^>]*>/g;
|
|
24724
24798
|
const tagNames = [...text.matchAll(tagRegex)].map(
|
|
@@ -25052,9 +25126,6 @@ function CardHeader({ children }) {
|
|
|
25052
25126
|
function CardTitle({ children }) {
|
|
25053
25127
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "ui-card-title", children });
|
|
25054
25128
|
}
|
|
25055
|
-
function CardDescription({ children }) {
|
|
25056
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "ui-card-description", children });
|
|
25057
|
-
}
|
|
25058
25129
|
function CardContent({
|
|
25059
25130
|
children,
|
|
25060
25131
|
className
|
|
@@ -25152,7 +25223,7 @@ function parseEvent(data) {
|
|
|
25152
25223
|
return null;
|
|
25153
25224
|
}
|
|
25154
25225
|
}
|
|
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,
|
|
25226
|
+
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, MarkdownBlock, STATUS_OPTIONS, KIND_OPTIONS, INITIAL_FILTERS;
|
|
25156
25227
|
var init_app = __esm({
|
|
25157
25228
|
"client/src/app.tsx"() {
|
|
25158
25229
|
init_lucide_react();
|
|
@@ -25170,10 +25241,6 @@ var init_app = __esm({
|
|
|
25170
25241
|
MESSAGE_COLLAPSE_LINE_LIMIT_SYSTEM = 5;
|
|
25171
25242
|
MESSAGE_COLLAPSE_HEIGHT_PROSE_SYSTEM = "9rem";
|
|
25172
25243
|
MESSAGE_COLLAPSE_HEIGHT_STRUCTURED_SYSTEM = "9rem";
|
|
25173
|
-
EMPTY_TRACE_INSIGHTS = {
|
|
25174
|
-
highlights: [],
|
|
25175
|
-
structuredInputs: []
|
|
25176
|
-
};
|
|
25177
25244
|
MarkdownBlock = (0, import_react3.lazy)(
|
|
25178
25245
|
() => import("./markdown-block-DMQHS3E5.js").then((module) => ({
|
|
25179
25246
|
default: module.MarkdownBlock
|