@mastra/playground-ui 53.0.0-alpha.2 → 53.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/components/LogsDataList.cjs.js +1 -0
  2. package/dist/components/LogsDataList.cjs.js.map +1 -1
  3. package/dist/components/LogsDataList.es.js +1 -0
  4. package/dist/components/LogsDataList.es.js.map +1 -1
  5. package/dist/domains/traces/components/span-data-panel-view.cjs.js +4 -3
  6. package/dist/domains/traces/components/span-data-panel-view.cjs.js.map +1 -1
  7. package/dist/domains/traces/components/span-data-panel-view.es.js +4 -3
  8. package/dist/domains/traces/components/span-data-panel-view.es.js.map +1 -1
  9. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +113 -83
  10. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  11. package/dist/domains/traces/components/trace-data-panel-view.es.js +113 -83
  12. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  13. package/dist/domains/traces/components/trace-timeline.cjs.js +14 -16
  14. package/dist/domains/traces/components/trace-timeline.cjs.js.map +1 -1
  15. package/dist/domains/traces/components/trace-timeline.es.js +14 -16
  16. package/dist/domains/traces/components/trace-timeline.es.js.map +1 -1
  17. package/dist/domains/traces/components/traces-layout.cjs.js +44 -30
  18. package/dist/domains/traces/components/traces-layout.cjs.js.map +1 -1
  19. package/dist/domains/traces/components/traces-layout.es.js +45 -31
  20. package/dist/domains/traces/components/traces-layout.es.js.map +1 -1
  21. package/dist/domains/traces/hooks/use-trace-spans.cjs.js +32 -15
  22. package/dist/domains/traces/hooks/use-trace-spans.cjs.js.map +1 -1
  23. package/dist/domains/traces/hooks/use-trace-spans.es.js +32 -17
  24. package/dist/domains/traces/hooks/use-trace-spans.es.js.map +1 -1
  25. package/dist/domains/traces/hooks/use-trace-url-state.cjs.js +31 -0
  26. package/dist/domains/traces/hooks/use-trace-url-state.cjs.js.map +1 -1
  27. package/dist/domains/traces/hooks/use-trace-url-state.es.js +31 -0
  28. package/dist/domains/traces/hooks/use-trace-url-state.es.js.map +1 -1
  29. package/dist/ee/signals/components/entity-index-list.cjs.js +1 -0
  30. package/dist/ee/signals/components/entity-index-list.cjs.js.map +1 -1
  31. package/dist/ee/signals/components/entity-index-list.es.js +1 -0
  32. package/dist/ee/signals/components/entity-index-list.es.js.map +1 -1
  33. package/dist/src/domains/traces/components/trace-data-panel-view.d.ts +11 -8
  34. package/dist/src/domains/traces/components/trace-timeline.d.ts +1 -1
  35. package/dist/src/domains/traces/components/traces-layout.d.ts +19 -9
  36. package/dist/src/domains/traces/hooks/use-trace-spans.d.ts +204 -0
  37. package/dist/src/domains/traces/hooks/use-trace-url-state.d.ts +4 -0
  38. package/dist/style.css +29 -0
  39. package/package.json +7 -7
@@ -50,22 +50,20 @@ function TraceTimeline({
50
50
  ]
51
51
  }
52
52
  ) : /* @__PURE__ */ jsxs(Fragment, { children: [
53
- (usedSpanTypes.length > 0 || leadingSlot) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-3 px-2 py-1.5", children: [
54
- leadingSlot && /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: leadingSlot }),
55
- usedSpanTypes.map((type) => {
56
- const spanUI = getSpanTypeUi(type);
57
- return /* @__PURE__ */ jsxs("div", { className: "text-ui-sm text-neutral3 flex shrink-0 items-center gap-1", children: [
58
- /* @__PURE__ */ jsx(
59
- "span",
60
- {
61
- className: "inline-block size-1.5 shrink-0 rounded-full",
62
- style: { backgroundColor: spanUI?.color }
63
- }
64
- ),
65
- spanUI?.label || type
66
- ] }, type);
67
- })
68
- ] }),
53
+ leadingSlot && /* @__PURE__ */ jsx("div", { className: "px-2 pt-1.5", children: leadingSlot }),
54
+ usedSpanTypes.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center justify-end gap-3 px-2 py-1.5", children: usedSpanTypes.map((type) => {
55
+ const spanUI = getSpanTypeUi(type);
56
+ return /* @__PURE__ */ jsxs("div", { className: "text-ui-sm text-neutral3 flex shrink-0 items-center gap-1", children: [
57
+ /* @__PURE__ */ jsx(
58
+ "span",
59
+ {
60
+ className: "inline-block size-1.5 shrink-0 rounded-full",
61
+ style: { backgroundColor: spanUI?.color }
62
+ }
63
+ ),
64
+ spanUI?.label || type
65
+ ] }, type);
66
+ }) }),
69
67
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-[minmax(0,1fr)_auto_auto] content-start items-start gap-y-px overflow-hidden py-1", children: hierarchicalSpans?.map((span) => /* @__PURE__ */ jsx(
70
68
  TraceTimelineSpan,
71
69
  {
@@ -1 +1 @@
1
- {"version":3,"file":"trace-timeline.es.js","sources":["../../../../src/domains/traces/components/trace-timeline.tsx"],"sourcesContent":["import type { Dispatch, ReactNode, SetStateAction } from 'react';\nimport { useMemo } from 'react';\nimport type { UISpan } from '../types';\nimport { spanTypePrefixes, getSpanTypeUi } from './shared';\nimport { TraceTimelineSpan } from './trace-timeline-span';\nimport { Spinner } from '@/ds/components/Spinner';\nimport { cn } from '@/lib/utils';\n\ntype TraceTimelineProps = {\n hierarchicalSpans: UISpan[];\n onSpanClick: (id: string) => void;\n selectedSpanId?: string;\n isLoading?: boolean;\n fadedTypes?: string[];\n expandedSpanIds?: string[];\n setExpandedSpanIds?: Dispatch<SetStateAction<string[]>>;\n featuredSpanIds?: string[];\n chartWidth?: 'wide' | 'default';\n /** Rendered on the left of the span type legend row. */\n leadingSlot?: ReactNode;\n};\n\nexport function TraceTimeline({\n hierarchicalSpans = [],\n onSpanClick,\n selectedSpanId,\n isLoading,\n fadedTypes,\n expandedSpanIds,\n setExpandedSpanIds,\n featuredSpanIds,\n chartWidth = 'default',\n leadingSlot,\n}: TraceTimelineProps) {\n const overallLatency = hierarchicalSpans?.[0]?.latency || 0;\n const overallStartTime = hierarchicalSpans?.[0]?.startTime || '';\n\n const usedSpanTypes = useMemo(() => {\n const collectTypes = (spans: UISpan[]): Set<string> => {\n const types = new Set<string>();\n for (const span of spans) {\n const prefix = span.type?.toLowerCase().split('_')[0];\n if (prefix) types.add(prefix);\n if (span.spans) {\n for (const t of collectTypes(span.spans)) types.add(t);\n }\n }\n return types;\n };\n const types = collectTypes(hierarchicalSpans);\n const hasOther = [...types].some(t => !spanTypePrefixes.includes(t));\n const known = spanTypePrefixes.filter(p => p !== 'other' && types.has(p));\n if (hasOther) known.push('other');\n return known;\n }, [hierarchicalSpans]);\n\n return (\n <>\n {isLoading ? (\n <div\n className={cn(\n 'flex items-center justify-center gap-3 rounded-md bg-surface3/50 p-3 text-ui-sm text-neutral3',\n '[&_svg]:size-[1.25em] [&_svg]:opacity-50',\n )}\n >\n <Spinner /> Loading Trace Timeline ...\n </div>\n ) : (\n <>\n {(usedSpanTypes.length > 0 || leadingSlot) && (\n <div className=\"flex flex-wrap items-center justify-end gap-3 px-2 py-1.5\">\n {/* The slot takes the leftover width and is the only thing allowed to\n shrink, so the legend never compresses or wraps. `min-w-0` lets it\n shrink past its content width instead of pushing the legend down. */}\n {leadingSlot && <div className=\"min-w-0 flex-1\">{leadingSlot}</div>}\n {usedSpanTypes.map(type => {\n const spanUI = getSpanTypeUi(type);\n return (\n <div key={type} className=\"text-ui-sm text-neutral3 flex shrink-0 items-center gap-1\">\n <span\n className=\"inline-block size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: spanUI?.color }}\n />\n {spanUI?.label || type}\n </div>\n );\n })}\n </div>\n )}\n <div className=\"grid grid-cols-[minmax(0,1fr)_auto_auto] content-start items-start gap-y-px overflow-hidden py-1\">\n {hierarchicalSpans?.map(span => (\n <TraceTimelineSpan\n key={span.id}\n span={span}\n siblings={hierarchicalSpans}\n onSpanClick={onSpanClick}\n selectedSpanId={selectedSpanId}\n overallLatency={overallLatency}\n overallStartTime={overallStartTime}\n fadedTypes={fadedTypes}\n featuredSpanIds={featuredSpanIds}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n chartWidth={chartWidth}\n />\n ))}\n </div>\n </>\n )}\n </>\n );\n}\n"],"names":["types"],"mappings":"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"}
1
+ {"version":3,"file":"trace-timeline.es.js","sources":["../../../../src/domains/traces/components/trace-timeline.tsx"],"sourcesContent":["import type { Dispatch, ReactNode, SetStateAction } from 'react';\nimport { useMemo } from 'react';\nimport type { UISpan } from '../types';\nimport { spanTypePrefixes, getSpanTypeUi } from './shared';\nimport { TraceTimelineSpan } from './trace-timeline-span';\nimport { Spinner } from '@/ds/components/Spinner';\nimport { cn } from '@/lib/utils';\n\ntype TraceTimelineProps = {\n hierarchicalSpans: UISpan[];\n onSpanClick: (id: string) => void;\n selectedSpanId?: string;\n isLoading?: boolean;\n fadedTypes?: string[];\n expandedSpanIds?: string[];\n setExpandedSpanIds?: Dispatch<SetStateAction<string[]>>;\n featuredSpanIds?: string[];\n chartWidth?: 'wide' | 'default';\n /** Rendered full-width above the span type legend row. */\n leadingSlot?: ReactNode;\n};\n\nexport function TraceTimeline({\n hierarchicalSpans = [],\n onSpanClick,\n selectedSpanId,\n isLoading,\n fadedTypes,\n expandedSpanIds,\n setExpandedSpanIds,\n featuredSpanIds,\n chartWidth = 'default',\n leadingSlot,\n}: TraceTimelineProps) {\n const overallLatency = hierarchicalSpans?.[0]?.latency || 0;\n const overallStartTime = hierarchicalSpans?.[0]?.startTime || '';\n\n const usedSpanTypes = useMemo(() => {\n const collectTypes = (spans: UISpan[]): Set<string> => {\n const types = new Set<string>();\n for (const span of spans) {\n const prefix = span.type?.toLowerCase().split('_')[0];\n if (prefix) types.add(prefix);\n if (span.spans) {\n for (const t of collectTypes(span.spans)) types.add(t);\n }\n }\n return types;\n };\n const types = collectTypes(hierarchicalSpans);\n const hasOther = [...types].some(t => !spanTypePrefixes.includes(t));\n const known = spanTypePrefixes.filter(p => p !== 'other' && types.has(p));\n if (hasOther) known.push('other');\n return known;\n }, [hierarchicalSpans]);\n\n return (\n <>\n {isLoading ? (\n <div\n className={cn(\n 'flex items-center justify-center gap-3 rounded-md bg-surface3/50 p-3 text-ui-sm text-neutral3',\n '[&_svg]:size-[1.25em] [&_svg]:opacity-50',\n )}\n >\n <Spinner /> Loading Trace Timeline ...\n </div>\n ) : (\n <>\n {leadingSlot && <div className=\"px-2 pt-1.5\">{leadingSlot}</div>}\n {usedSpanTypes.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-end gap-3 px-2 py-1.5\">\n {usedSpanTypes.map(type => {\n const spanUI = getSpanTypeUi(type);\n return (\n <div key={type} className=\"text-ui-sm text-neutral3 flex shrink-0 items-center gap-1\">\n <span\n className=\"inline-block size-1.5 shrink-0 rounded-full\"\n style={{ backgroundColor: spanUI?.color }}\n />\n {spanUI?.label || type}\n </div>\n );\n })}\n </div>\n )}\n <div className=\"grid grid-cols-[minmax(0,1fr)_auto_auto] content-start items-start gap-y-px overflow-hidden py-1\">\n {hierarchicalSpans?.map(span => (\n <TraceTimelineSpan\n key={span.id}\n span={span}\n siblings={hierarchicalSpans}\n onSpanClick={onSpanClick}\n selectedSpanId={selectedSpanId}\n overallLatency={overallLatency}\n overallStartTime={overallStartTime}\n fadedTypes={fadedTypes}\n featuredSpanIds={featuredSpanIds}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n chartWidth={chartWidth}\n />\n ))}\n </div>\n </>\n )}\n </>\n );\n}\n"],"names":["types"],"mappings":"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"}
@@ -5,44 +5,58 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5
5
  const jsxRuntime = require('react/jsx-runtime');
6
6
  const utils_cn = require('../../../cn-DCPcv4xv.cjs');
7
7
 
8
+ const SIDE_PANEL_WIDTH_CLASS = {
9
+ half: "w-1/2",
10
+ wide: "w-4/5",
11
+ full: "w-full"
12
+ };
8
13
  function TracesLayout({
9
14
  listSlot,
10
15
  tracePanelSlot,
11
16
  spanPanelSlot,
12
17
  scorePanelSlot,
13
18
  traceCollapsed,
14
- sidePanelWide
19
+ sidePanelWidth = "half"
15
20
  }) {
16
21
  const hasSidePanel = !!tracePanelSlot;
17
- return /* @__PURE__ */ jsxRuntime.jsxs(
18
- "div",
19
- {
20
- className: utils_cn.cn(
21
- "grid max-h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out",
22
- hasSidePanel ? sidePanelWide ? "grid-cols-[1fr_4fr]" : "grid-cols-[1fr_1fr]" : "grid-cols-[1fr]"
23
- ),
24
- children: [
25
- listSlot,
26
- hasSidePanel && /* @__PURE__ */ jsxRuntime.jsxs(
27
- "div",
28
- {
29
- className: utils_cn.cn(
30
- "grid max-h-full gap-4 overflow-auto",
31
- // Fill the page height so the trace panel reaches the bottom; when collapsed
32
- // the column shrinks to content (items-start on the outer grid).
33
- !traceCollapsed && "h-full",
34
- scorePanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr_3fr]" : "grid-rows-[2fr_3fr_3fr]" : spanPanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr]" : "grid-rows-[2fr_3fr]" : traceCollapsed ? "grid-rows-[auto]" : "grid-rows-[1fr]"
35
- ),
36
- children: [
37
- tracePanelSlot,
38
- spanPanelSlot,
39
- scorePanelSlot
40
- ]
41
- }
42
- )
43
- ]
44
- }
45
- );
22
+ const isHalf = sidePanelWidth === "half";
23
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
24
+ /* @__PURE__ */ jsxRuntime.jsxs(
25
+ "div",
26
+ {
27
+ className: utils_cn.cn(
28
+ "grid h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out",
29
+ hasSidePanel ? isHalf ? "grid-cols-[1fr_1fr]" : "grid-cols-[1fr_4fr]" : "grid-cols-[1fr]"
30
+ ),
31
+ children: [
32
+ listSlot,
33
+ hasSidePanel && /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true })
34
+ ]
35
+ }
36
+ ),
37
+ hasSidePanel && /* @__PURE__ */ jsxRuntime.jsxs(
38
+ "div",
39
+ {
40
+ role: "dialog",
41
+ "aria-label": "Trace details",
42
+ "data-trace-side-panel": true,
43
+ className: utils_cn.cn(
44
+ // z-50 matches the route Header (a z-50 grid sibling in the app frame) so the panel,
45
+ // rendered later in the DOM, paints above it while body-level portals stay on top.
46
+ "absolute inset-y-0 right-0 z-50 min-w-0 p-3",
47
+ "transition-[width] duration-300 ease-in-out",
48
+ SIDE_PANEL_WIDTH_CLASS[sidePanelWidth],
49
+ "grid gap-4 overflow-auto [&>*]:rounded-lg [&>*]:bg-surface3 [&>*]:shadow-lg",
50
+ scorePanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr_3fr]" : "grid-rows-[2fr_3fr_3fr]" : spanPanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr]" : "grid-rows-[2fr_3fr]" : traceCollapsed ? "grid-rows-[auto]" : "grid-rows-[1fr]"
51
+ ),
52
+ children: [
53
+ tracePanelSlot,
54
+ spanPanelSlot,
55
+ scorePanelSlot
56
+ ]
57
+ }
58
+ )
59
+ ] });
46
60
  }
47
61
 
48
62
  exports.TracesLayout = TracesLayout;
@@ -1 +1 @@
1
- {"version":3,"file":"traces-layout.cjs.js","sources":["../../../../src/domains/traces/components/traces-layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport interface TracesLayoutProps {\n /** The trace list (left column). */\n listSlot: ReactNode;\n /** The trace data panel (right column, top). When null/undefined, the whole right column collapses. */\n tracePanelSlot?: ReactNode;\n /** The span data panel (right column, middle). Only rendered when truthy. */\n spanPanelSlot?: ReactNode;\n /** The score data panel (right column, bottom). Only rendered when truthy. */\n scorePanelSlot?: ReactNode;\n /** When the trace panel is collapsed, the right column's grid-rows squash the trace row to `auto`. */\n traceCollapsed?: boolean;\n /** Widens the side panel column (e.g. when the span detail is shown inside the trace panel). */\n sidePanelWide?: boolean;\n}\n\n/**\n * Pure 2-column layout shell for the traces page. Owns no state and fetches no data — pass slots in.\n * Right-column row template adapts based on which panels are present.\n */\nexport function TracesLayout({\n listSlot,\n tracePanelSlot,\n spanPanelSlot,\n scorePanelSlot,\n traceCollapsed,\n sidePanelWide,\n}: TracesLayoutProps) {\n const hasSidePanel = !!tracePanelSlot;\n\n return (\n <div\n className={cn(\n 'grid max-h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out',\n hasSidePanel ? (sidePanelWide ? 'grid-cols-[1fr_4fr]' : 'grid-cols-[1fr_1fr]') : 'grid-cols-[1fr]',\n )}\n >\n {listSlot}\n\n {hasSidePanel && (\n <div\n className={cn(\n 'grid max-h-full gap-4 overflow-auto',\n // Fill the page height so the trace panel reaches the bottom; when collapsed\n // the column shrinks to content (items-start on the outer grid).\n !traceCollapsed && 'h-full',\n scorePanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr_3fr]'\n : 'grid-rows-[2fr_3fr_3fr]'\n : spanPanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr]'\n : 'grid-rows-[2fr_3fr]'\n : traceCollapsed\n ? 'grid-rows-[auto]'\n : 'grid-rows-[1fr]',\n )}\n >\n {tracePanelSlot}\n {spanPanelSlot}\n {scorePanelSlot}\n </div>\n )}\n </div>\n );\n}\n"],"names":["jsxs","cn"],"mappings":";;;;;;;AAsBO,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAC,cAAA;AAEvB,EAAA,uBACEA,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAWC,WAAA;AAAA,QACT,uGAAA;AAAA,QACA,YAAA,GAAgB,aAAA,GAAgB,qBAAA,GAAwB,qBAAA,GAAyB;AAAA,OACnF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,QAEA,YAAA,oBACCD,eAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAWC,WAAA;AAAA,cACT,qCAAA;AAAA;AAAA;AAAA,cAGA,CAAC,cAAA,IAAkB,QAAA;AAAA,cACnB,cAAA,GACI,iBACE,0BAAA,GACA,yBAAA,GACF,gBACE,cAAA,GACE,sBAAA,GACA,qBAAA,GACF,cAAA,GACE,kBAAA,GACA;AAAA,aACV;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,cAAA;AAAA,cACA,aAAA;AAAA,cACA;AAAA;AAAA;AAAA;AACH;AAAA;AAAA,GAEJ;AAEJ;;;;"}
1
+ {"version":3,"file":"traces-layout.cjs.js","sources":["../../../../src/domains/traces/components/traces-layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport interface TracesLayoutProps {\n /** The trace list (left column). */\n listSlot: ReactNode;\n /** The trace data panel (side panel, top). When null/undefined, the side panel is not rendered. */\n tracePanelSlot?: ReactNode;\n /** The span data panel (side panel, middle). Only rendered when truthy. */\n spanPanelSlot?: ReactNode;\n /** The score data panel (side panel, bottom). Only rendered when truthy. */\n scorePanelSlot?: ReactNode;\n /** When the trace panel is collapsed, the side panel's grid-rows squash the trace row to `auto`. */\n traceCollapsed?: boolean;\n /**\n * Side panel width, driven by how many columns the trace panel shows:\n * `half` (trace only), `wide` (trace + one side column), `full` (messages + trace + span —\n * covers the whole positioned ancestor, i.e. stops at the main nav).\n */\n sidePanelWidth?: TracesSidePanelWidth;\n}\n\nexport type TracesSidePanelWidth = 'half' | 'wide' | 'full';\n\nconst SIDE_PANEL_WIDTH_CLASS: Record<TracesSidePanelWidth, string> = {\n half: 'w-1/2',\n wide: 'w-4/5',\n full: 'w-full',\n};\n\n/**\n * Layout shell for the traces page. Owns no state and fetches no data — pass slots in.\n *\n * The list lives in a 2-column grid whose right column is an empty spacer; the side panel\n * is rendered as an `absolute inset-y-0 right-0` overlay whose width mirrors the spacer\n * column, so it spans the full height of its nearest positioned ancestor while the list\n * stays interactive on the left. Consumers control the coverage by choosing which ancestor\n * is `relative` (e.g. the app frame, so the overlay also covers the route header).\n */\nexport function TracesLayout({\n listSlot,\n tracePanelSlot,\n spanPanelSlot,\n scorePanelSlot,\n traceCollapsed,\n sidePanelWidth = 'half',\n}: TracesLayoutProps) {\n const hasSidePanel = !!tracePanelSlot;\n const isHalf = sidePanelWidth === 'half';\n\n return (\n <>\n <div\n className={cn(\n 'grid h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out',\n hasSidePanel ? (isHalf ? 'grid-cols-[1fr_1fr]' : 'grid-cols-[1fr_4fr]') : 'grid-cols-[1fr]',\n )}\n >\n {listSlot}\n {hasSidePanel && <div aria-hidden />}\n </div>\n\n {hasSidePanel && (\n <div\n role=\"dialog\"\n aria-label=\"Trace details\"\n data-trace-side-panel\n className={cn(\n // z-50 matches the route Header (a z-50 grid sibling in the app frame) so the panel,\n // rendered later in the DOM, paints above it while body-level portals stay on top.\n 'absolute inset-y-0 right-0 z-50 min-w-0 p-3',\n 'transition-[width] duration-300 ease-in-out',\n SIDE_PANEL_WIDTH_CLASS[sidePanelWidth],\n 'grid gap-4 overflow-auto [&>*]:rounded-lg [&>*]:bg-surface3 [&>*]:shadow-lg',\n scorePanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr_3fr]'\n : 'grid-rows-[2fr_3fr_3fr]'\n : spanPanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr]'\n : 'grid-rows-[2fr_3fr]'\n : traceCollapsed\n ? 'grid-rows-[auto]'\n : 'grid-rows-[1fr]',\n )}\n >\n {tracePanelSlot}\n {spanPanelSlot}\n {scorePanelSlot}\n </div>\n )}\n </>\n );\n}\n"],"names":["jsxs","Fragment","cn","jsx"],"mappings":";;;;;;;AAwBA,MAAM,sBAAA,GAA+D;AAAA,EACnE,IAAA,EAAM,OAAA;AAAA,EACN,IAAA,EAAM,OAAA;AAAA,EACN,IAAA,EAAM;AACR,CAAA;AAWO,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA,GAAiB;AACnB,CAAA,EAAsB;AACpB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAC,cAAA;AACvB,EAAA,MAAM,SAAS,cAAA,KAAmB,MAAA;AAElC,EAAA,uBACEA,eAAA,CAAAC,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAD,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAWE,WAAA;AAAA,UACT,mGAAA;AAAA,UACA,YAAA,GAAgB,MAAA,GAAS,qBAAA,GAAwB,qBAAA,GAAyB;AAAA,SAC5E;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,QAAA;AAAA,UACA,YAAA,oBAAgBC,cAAA,CAAC,KAAA,EAAA,EAAI,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA;AAAA,KACpC;AAAA,IAEC,YAAA,oBACCH,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,eAAA;AAAA,QACX,uBAAA,EAAqB,IAAA;AAAA,QACrB,SAAA,EAAWE,WAAA;AAAA;AAAA;AAAA,UAGT,6CAAA;AAAA,UACA,6CAAA;AAAA,UACA,uBAAuB,cAAc,CAAA;AAAA,UACrC,6EAAA;AAAA,UACA,cAAA,GACI,iBACE,0BAAA,GACA,yBAAA,GACF,gBACE,cAAA,GACE,sBAAA,GACA,qBAAA,GACF,cAAA,GACE,kBAAA,GACA;AAAA,SACV;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,cAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA;AAAA;AAAA;AACH,GAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -1,44 +1,58 @@
1
- import { jsxs } from 'react/jsx-runtime';
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { c as cn } from '../../../cn-B4oPhFx9.js';
3
3
 
4
+ const SIDE_PANEL_WIDTH_CLASS = {
5
+ half: "w-1/2",
6
+ wide: "w-4/5",
7
+ full: "w-full"
8
+ };
4
9
  function TracesLayout({
5
10
  listSlot,
6
11
  tracePanelSlot,
7
12
  spanPanelSlot,
8
13
  scorePanelSlot,
9
14
  traceCollapsed,
10
- sidePanelWide
15
+ sidePanelWidth = "half"
11
16
  }) {
12
17
  const hasSidePanel = !!tracePanelSlot;
13
- return /* @__PURE__ */ jsxs(
14
- "div",
15
- {
16
- className: cn(
17
- "grid max-h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out",
18
- hasSidePanel ? sidePanelWide ? "grid-cols-[1fr_4fr]" : "grid-cols-[1fr_1fr]" : "grid-cols-[1fr]"
19
- ),
20
- children: [
21
- listSlot,
22
- hasSidePanel && /* @__PURE__ */ jsxs(
23
- "div",
24
- {
25
- className: cn(
26
- "grid max-h-full gap-4 overflow-auto",
27
- // Fill the page height so the trace panel reaches the bottom; when collapsed
28
- // the column shrinks to content (items-start on the outer grid).
29
- !traceCollapsed && "h-full",
30
- scorePanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr_3fr]" : "grid-rows-[2fr_3fr_3fr]" : spanPanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr]" : "grid-rows-[2fr_3fr]" : traceCollapsed ? "grid-rows-[auto]" : "grid-rows-[1fr]"
31
- ),
32
- children: [
33
- tracePanelSlot,
34
- spanPanelSlot,
35
- scorePanelSlot
36
- ]
37
- }
38
- )
39
- ]
40
- }
41
- );
18
+ const isHalf = sidePanelWidth === "half";
19
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
20
+ /* @__PURE__ */ jsxs(
21
+ "div",
22
+ {
23
+ className: cn(
24
+ "grid h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out",
25
+ hasSidePanel ? isHalf ? "grid-cols-[1fr_1fr]" : "grid-cols-[1fr_4fr]" : "grid-cols-[1fr]"
26
+ ),
27
+ children: [
28
+ listSlot,
29
+ hasSidePanel && /* @__PURE__ */ jsx("div", { "aria-hidden": true })
30
+ ]
31
+ }
32
+ ),
33
+ hasSidePanel && /* @__PURE__ */ jsxs(
34
+ "div",
35
+ {
36
+ role: "dialog",
37
+ "aria-label": "Trace details",
38
+ "data-trace-side-panel": true,
39
+ className: cn(
40
+ // z-50 matches the route Header (a z-50 grid sibling in the app frame) so the panel,
41
+ // rendered later in the DOM, paints above it while body-level portals stay on top.
42
+ "absolute inset-y-0 right-0 z-50 min-w-0 p-3",
43
+ "transition-[width] duration-300 ease-in-out",
44
+ SIDE_PANEL_WIDTH_CLASS[sidePanelWidth],
45
+ "grid gap-4 overflow-auto [&>*]:rounded-lg [&>*]:bg-surface3 [&>*]:shadow-lg",
46
+ scorePanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr_3fr]" : "grid-rows-[2fr_3fr_3fr]" : spanPanelSlot ? traceCollapsed ? "grid-rows-[auto_3fr]" : "grid-rows-[2fr_3fr]" : traceCollapsed ? "grid-rows-[auto]" : "grid-rows-[1fr]"
47
+ ),
48
+ children: [
49
+ tracePanelSlot,
50
+ spanPanelSlot,
51
+ scorePanelSlot
52
+ ]
53
+ }
54
+ )
55
+ ] });
42
56
  }
43
57
 
44
58
  export { TracesLayout };
@@ -1 +1 @@
1
- {"version":3,"file":"traces-layout.es.js","sources":["../../../../src/domains/traces/components/traces-layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport interface TracesLayoutProps {\n /** The trace list (left column). */\n listSlot: ReactNode;\n /** The trace data panel (right column, top). When null/undefined, the whole right column collapses. */\n tracePanelSlot?: ReactNode;\n /** The span data panel (right column, middle). Only rendered when truthy. */\n spanPanelSlot?: ReactNode;\n /** The score data panel (right column, bottom). Only rendered when truthy. */\n scorePanelSlot?: ReactNode;\n /** When the trace panel is collapsed, the right column's grid-rows squash the trace row to `auto`. */\n traceCollapsed?: boolean;\n /** Widens the side panel column (e.g. when the span detail is shown inside the trace panel). */\n sidePanelWide?: boolean;\n}\n\n/**\n * Pure 2-column layout shell for the traces page. Owns no state and fetches no data — pass slots in.\n * Right-column row template adapts based on which panels are present.\n */\nexport function TracesLayout({\n listSlot,\n tracePanelSlot,\n spanPanelSlot,\n scorePanelSlot,\n traceCollapsed,\n sidePanelWide,\n}: TracesLayoutProps) {\n const hasSidePanel = !!tracePanelSlot;\n\n return (\n <div\n className={cn(\n 'grid max-h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out',\n hasSidePanel ? (sidePanelWide ? 'grid-cols-[1fr_4fr]' : 'grid-cols-[1fr_1fr]') : 'grid-cols-[1fr]',\n )}\n >\n {listSlot}\n\n {hasSidePanel && (\n <div\n className={cn(\n 'grid max-h-full gap-4 overflow-auto',\n // Fill the page height so the trace panel reaches the bottom; when collapsed\n // the column shrinks to content (items-start on the outer grid).\n !traceCollapsed && 'h-full',\n scorePanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr_3fr]'\n : 'grid-rows-[2fr_3fr_3fr]'\n : spanPanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr]'\n : 'grid-rows-[2fr_3fr]'\n : traceCollapsed\n ? 'grid-rows-[auto]'\n : 'grid-rows-[1fr]',\n )}\n >\n {tracePanelSlot}\n {spanPanelSlot}\n {scorePanelSlot}\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";;;AAsBO,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAC,cAAA;AAEvB,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,uGAAA;AAAA,QACA,YAAA,GAAgB,aAAA,GAAgB,qBAAA,GAAwB,qBAAA,GAAyB;AAAA,OACnF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,QAEA,YAAA,oBACC,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA;AAAA,cACT,qCAAA;AAAA;AAAA;AAAA,cAGA,CAAC,cAAA,IAAkB,QAAA;AAAA,cACnB,cAAA,GACI,iBACE,0BAAA,GACA,yBAAA,GACF,gBACE,cAAA,GACE,sBAAA,GACA,qBAAA,GACF,cAAA,GACE,kBAAA,GACA;AAAA,aACV;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,cAAA;AAAA,cACA,aAAA;AAAA,cACA;AAAA;AAAA;AAAA;AACH;AAAA;AAAA,GAEJ;AAEJ;;;;"}
1
+ {"version":3,"file":"traces-layout.es.js","sources":["../../../../src/domains/traces/components/traces-layout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport interface TracesLayoutProps {\n /** The trace list (left column). */\n listSlot: ReactNode;\n /** The trace data panel (side panel, top). When null/undefined, the side panel is not rendered. */\n tracePanelSlot?: ReactNode;\n /** The span data panel (side panel, middle). Only rendered when truthy. */\n spanPanelSlot?: ReactNode;\n /** The score data panel (side panel, bottom). Only rendered when truthy. */\n scorePanelSlot?: ReactNode;\n /** When the trace panel is collapsed, the side panel's grid-rows squash the trace row to `auto`. */\n traceCollapsed?: boolean;\n /**\n * Side panel width, driven by how many columns the trace panel shows:\n * `half` (trace only), `wide` (trace + one side column), `full` (messages + trace + span —\n * covers the whole positioned ancestor, i.e. stops at the main nav).\n */\n sidePanelWidth?: TracesSidePanelWidth;\n}\n\nexport type TracesSidePanelWidth = 'half' | 'wide' | 'full';\n\nconst SIDE_PANEL_WIDTH_CLASS: Record<TracesSidePanelWidth, string> = {\n half: 'w-1/2',\n wide: 'w-4/5',\n full: 'w-full',\n};\n\n/**\n * Layout shell for the traces page. Owns no state and fetches no data — pass slots in.\n *\n * The list lives in a 2-column grid whose right column is an empty spacer; the side panel\n * is rendered as an `absolute inset-y-0 right-0` overlay whose width mirrors the spacer\n * column, so it spans the full height of its nearest positioned ancestor while the list\n * stays interactive on the left. Consumers control the coverage by choosing which ancestor\n * is `relative` (e.g. the app frame, so the overlay also covers the route header).\n */\nexport function TracesLayout({\n listSlot,\n tracePanelSlot,\n spanPanelSlot,\n scorePanelSlot,\n traceCollapsed,\n sidePanelWidth = 'half',\n}: TracesLayoutProps) {\n const hasSidePanel = !!tracePanelSlot;\n const isHalf = sidePanelWidth === 'half';\n\n return (\n <>\n <div\n className={cn(\n 'grid h-full min-h-0 items-start gap-4 transition-[grid-template-columns] duration-300 ease-in-out',\n hasSidePanel ? (isHalf ? 'grid-cols-[1fr_1fr]' : 'grid-cols-[1fr_4fr]') : 'grid-cols-[1fr]',\n )}\n >\n {listSlot}\n {hasSidePanel && <div aria-hidden />}\n </div>\n\n {hasSidePanel && (\n <div\n role=\"dialog\"\n aria-label=\"Trace details\"\n data-trace-side-panel\n className={cn(\n // z-50 matches the route Header (a z-50 grid sibling in the app frame) so the panel,\n // rendered later in the DOM, paints above it while body-level portals stay on top.\n 'absolute inset-y-0 right-0 z-50 min-w-0 p-3',\n 'transition-[width] duration-300 ease-in-out',\n SIDE_PANEL_WIDTH_CLASS[sidePanelWidth],\n 'grid gap-4 overflow-auto [&>*]:rounded-lg [&>*]:bg-surface3 [&>*]:shadow-lg',\n scorePanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr_3fr]'\n : 'grid-rows-[2fr_3fr_3fr]'\n : spanPanelSlot\n ? traceCollapsed\n ? 'grid-rows-[auto_3fr]'\n : 'grid-rows-[2fr_3fr]'\n : traceCollapsed\n ? 'grid-rows-[auto]'\n : 'grid-rows-[1fr]',\n )}\n >\n {tracePanelSlot}\n {spanPanelSlot}\n {scorePanelSlot}\n </div>\n )}\n </>\n );\n}\n"],"names":[],"mappings":";;;AAwBA,MAAM,sBAAA,GAA+D;AAAA,EACnE,IAAA,EAAM,OAAA;AAAA,EACN,IAAA,EAAM,OAAA;AAAA,EACN,IAAA,EAAM;AACR,CAAA;AAWO,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA,GAAiB;AACnB,CAAA,EAAsB;AACpB,EAAA,MAAM,YAAA,GAAe,CAAC,CAAC,cAAA;AACvB,EAAA,MAAM,SAAS,cAAA,KAAmB,MAAA;AAElC,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,UACT,mGAAA;AAAA,UACA,YAAA,GAAgB,MAAA,GAAS,qBAAA,GAAwB,qBAAA,GAAyB;AAAA,SAC5E;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,QAAA;AAAA,UACA,YAAA,oBAAgB,GAAA,CAAC,KAAA,EAAA,EAAI,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA;AAAA,KACpC;AAAA,IAEC,YAAA,oBACC,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,eAAA;AAAA,QACX,uBAAA,EAAqB,IAAA;AAAA,QACrB,SAAA,EAAW,EAAA;AAAA;AAAA;AAAA,UAGT,6CAAA;AAAA,UACA,6CAAA;AAAA,UACA,uBAAuB,cAAc,CAAA;AAAA,UACrC,6EAAA;AAAA,UACA,cAAA,GACI,iBACE,0BAAA,GACA,yBAAA,GACF,gBACE,cAAA,GACE,sBAAA,GACA,qBAAA,GACF,cAAA,GACE,kBAAA,GACA;AAAA,SACV;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,cAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA;AAAA;AAAA;AACH,GAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -8,27 +8,44 @@ const domains_traces_utils_toSearchableSpans = require('../utils/to-searchable-s
8
8
  require('date-fns');
9
9
 
10
10
  const IMMUTABLE_CACHE_TIME = 1e3 * 60 * 60 * 24 * 30;
11
+ const traceSpansQueryOptions = (client, traceId) => reactQuery.queryOptions({
12
+ queryKey: ["trace-spans", traceId],
13
+ queryFn: async () => {
14
+ if (!traceId) {
15
+ throw new Error("Trace ID is required");
16
+ }
17
+ const res = await client.getTrace(traceId);
18
+ return res;
19
+ },
20
+ enabled: !!traceId,
21
+ staleTime: (query) => {
22
+ const data = query.state.data;
23
+ const isFinished = data?.spans.every((span) => Boolean(span.endedAt));
24
+ return isFinished ? IMMUTABLE_CACHE_TIME : 0;
25
+ }
26
+ });
11
27
  function useTraceSpans(traceId) {
12
28
  const client = react.useMastraClient();
13
29
  return reactQuery.useQuery({
14
- queryKey: ["trace-spans", traceId],
15
- queryFn: async () => {
16
- if (!traceId) {
17
- throw new Error("Trace ID is required");
18
- }
19
- const res = await client.getTrace(traceId);
20
- return res;
21
- },
30
+ ...traceSpansQueryOptions(client, traceId),
22
31
  // Builds each span's search haystack once per fetch, cached with the query.
23
- select: domains_traces_utils_toSearchableSpans.selectSearchableSpans,
24
- enabled: !!traceId,
25
- staleTime: (query) => {
26
- const data = query.state.data;
27
- const isFinished = data?.spans.every((span) => Boolean(span.endedAt));
28
- return isFinished ? IMMUTABLE_CACHE_TIME : 0;
29
- }
32
+ select: domains_traces_utils_toSearchableSpans.selectSearchableSpans
33
+ });
34
+ }
35
+ function useTraceSpansQueries(traceIds, select, fallback) {
36
+ const client = react.useMastraClient();
37
+ return reactQuery.useQueries({
38
+ queries: traceIds.map((traceId) => ({
39
+ ...traceSpansQueryOptions(client, traceId),
40
+ select: (data) => select(traceId, data)
41
+ })),
42
+ combine: (results) => results.map(
43
+ (result, index) => result.data === void 0 ? fallback(traceIds[index] ?? "") : result.data
44
+ )
30
45
  });
31
46
  }
32
47
 
48
+ exports.traceSpansQueryOptions = traceSpansQueryOptions;
33
49
  exports.useTraceSpans = useTraceSpans;
50
+ exports.useTraceSpansQueries = useTraceSpansQueries;
34
51
  //# sourceMappingURL=use-trace-spans.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\n/**\n * Every span of a single trace, with its full payload.\n *\n * The lightweight projection exists to keep blob columns off the read path of a\n * *list*, where the cost is paid once per trace on screen. A trace that is open\n * has already narrowed that to one, and the panel both renders and searches\n * these spans -- `input`, `output` and `attributes` included -- so the\n * projection would only hide content the reader is looking at.\n */\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n const isFinished = data?.spans.every(span => Boolean(span.endedAt));\n return isFinished ? IMMUTABLE_CACHE_TIME : 0;\n },\n });\n}\n"],"names":["useMastraClient","useQuery","selectSearchableSpans"],"mappings":";;;;;;;;;AAMA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAW5C,SAAS,cACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAASA,qBAAA,EAAgB;AAE/B,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAA,EAAQC,4DAAA;AAAA,IACR,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AACzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,UAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAClE,MAAA,OAAO,aAAa,oBAAA,GAAuB,CAAA;AAAA,IAC7C;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-trace-spans.cjs.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import type { MastraClient } from '@mastra/client-js';\nimport { useMastraClient } from '@mastra/react';\nimport { queryOptions, useQueries, useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\n/**\n * Key, fetcher and stale policy of the `trace-spans` query. Every observer of this key must\n * share these (rather than only the key) so one observer with a stricter `staleTime` does not\n * refetch data another one considers fresh.\n */\nexport const traceSpansQueryOptions = (client: MastraClient, traceId: string | null | undefined) =>\n queryOptions({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n const isFinished = data?.spans.every(span => Boolean(span.endedAt));\n return isFinished ? IMMUTABLE_CACHE_TIME : 0;\n },\n });\n\n/**\n * Every span of a single trace, with its full payload.\n *\n * The lightweight projection exists to keep blob columns off the read path of a\n * *list*, where the cost is paid once per trace on screen. A trace that is open\n * has already narrowed that to one, and the panel both renders and searches\n * these spans -- `input`, `output` and `attributes` included -- so the\n * projection would only hide content the reader is looking at.\n */\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n ...traceSpansQueryOptions(client, traceId),\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n });\n}\n\nexport type TraceSpansData = Awaited<ReturnType<MastraClient['getTrace']>>;\n\n/**\n * Observes the `trace-spans` query of several traces at once and projects each one with `select`.\n * Traces still loading (or failed) yield `fallback(traceId)` so the result always lines up with `traceIds`.\n */\nexport function useTraceSpansQueries<T>(\n traceIds: string[],\n select: (traceId: string, data: TraceSpansData) => T,\n fallback: (traceId: string) => T,\n): T[] {\n const client = useMastraClient();\n\n return useQueries({\n queries: traceIds.map(traceId => ({\n ...traceSpansQueryOptions(client, traceId),\n select: (data: TraceSpansData) => select(traceId, data),\n })),\n combine: results =>\n results.map((result, index) =>\n result.data === undefined ? fallback(traceIds[index] ?? '') : (result.data as T),\n ),\n });\n}\n"],"names":["queryOptions","useMastraClient","useQuery","selectSearchableSpans","useQueries"],"mappings":";;;;;;;;;AAOA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAO5C,MAAM,sBAAA,GAAyB,CAAC,MAAA,EAAsB,OAAA,KAC3DA,uBAAA,CAAa;AAAA,EACX,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,EACjC,SAAS,YAAY;AACnB,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,IACxC;AACA,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAAA,EACA,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,EACX,WAAW,CAAA,KAAA,KAAS;AAClB,IAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AACzB,IAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,UAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAClE,IAAA,OAAO,aAAa,oBAAA,GAAuB,CAAA;AAAA,EAC7C;AACF,CAAC;AAWI,SAAS,cACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAASC,qBAAA,EAAgB;AAE/B,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,GAAG,sBAAA,CAAuB,MAAA,EAAQ,OAAO,CAAA;AAAA;AAAA,IAEzC,MAAA,EAAQC;AAAA,GACT,CAAA;AACH;AAQO,SAAS,oBAAA,CACd,QAAA,EACA,MAAA,EACA,QAAA,EACK;AACL,EAAA,MAAM,SAASF,qBAAA,EAAgB;AAE/B,EAAA,OAAOG,qBAAA,CAAW;AAAA,IAChB,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,MAAY;AAAA,MAChC,GAAG,sBAAA,CAAuB,MAAA,EAAQ,OAAO,CAAA;AAAA,MACzC,MAAA,EAAQ,CAAC,IAAA,KAAyB,MAAA,CAAO,SAAS,IAAI;AAAA,KACxD,CAAE,CAAA;AAAA,IACF,OAAA,EAAS,aACP,OAAA,CAAQ,GAAA;AAAA,MAAI,CAAC,MAAA,EAAQ,KAAA,KACnB,MAAA,CAAO,IAAA,KAAS,MAAA,GAAY,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,IAAK,EAAE,CAAA,GAAK,MAAA,CAAO;AAAA;AACxE,GACH,CAAA;AACH;;;;;;"}
@@ -1,30 +1,45 @@
1
1
  import { useMastraClient } from '@mastra/react';
2
- import { useQuery } from '@tanstack/react-query';
2
+ import { useQuery, queryOptions, useQueries } from '@tanstack/react-query';
3
3
  import { selectSearchableSpans } from '../utils/to-searchable-spans.es.js';
4
4
  import 'date-fns';
5
5
 
6
6
  const IMMUTABLE_CACHE_TIME = 1e3 * 60 * 60 * 24 * 30;
7
+ const traceSpansQueryOptions = (client, traceId) => queryOptions({
8
+ queryKey: ["trace-spans", traceId],
9
+ queryFn: async () => {
10
+ if (!traceId) {
11
+ throw new Error("Trace ID is required");
12
+ }
13
+ const res = await client.getTrace(traceId);
14
+ return res;
15
+ },
16
+ enabled: !!traceId,
17
+ staleTime: (query) => {
18
+ const data = query.state.data;
19
+ const isFinished = data?.spans.every((span) => Boolean(span.endedAt));
20
+ return isFinished ? IMMUTABLE_CACHE_TIME : 0;
21
+ }
22
+ });
7
23
  function useTraceSpans(traceId) {
8
24
  const client = useMastraClient();
9
25
  return useQuery({
10
- queryKey: ["trace-spans", traceId],
11
- queryFn: async () => {
12
- if (!traceId) {
13
- throw new Error("Trace ID is required");
14
- }
15
- const res = await client.getTrace(traceId);
16
- return res;
17
- },
26
+ ...traceSpansQueryOptions(client, traceId),
18
27
  // Builds each span's search haystack once per fetch, cached with the query.
19
- select: selectSearchableSpans,
20
- enabled: !!traceId,
21
- staleTime: (query) => {
22
- const data = query.state.data;
23
- const isFinished = data?.spans.every((span) => Boolean(span.endedAt));
24
- return isFinished ? IMMUTABLE_CACHE_TIME : 0;
25
- }
28
+ select: selectSearchableSpans
29
+ });
30
+ }
31
+ function useTraceSpansQueries(traceIds, select, fallback) {
32
+ const client = useMastraClient();
33
+ return useQueries({
34
+ queries: traceIds.map((traceId) => ({
35
+ ...traceSpansQueryOptions(client, traceId),
36
+ select: (data) => select(traceId, data)
37
+ })),
38
+ combine: (results) => results.map(
39
+ (result, index) => result.data === void 0 ? fallback(traceIds[index] ?? "") : result.data
40
+ )
26
41
  });
27
42
  }
28
43
 
29
- export { useTraceSpans };
44
+ export { traceSpansQueryOptions, useTraceSpans, useTraceSpansQueries };
30
45
  //# sourceMappingURL=use-trace-spans.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-trace-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\n/**\n * Every span of a single trace, with its full payload.\n *\n * The lightweight projection exists to keep blob columns off the read path of a\n * *list*, where the cost is paid once per trace on screen. A trace that is open\n * has already narrowed that to one, and the panel both renders and searches\n * these spans -- `input`, `output` and `attributes` included -- so the\n * projection would only hide content the reader is looking at.\n */\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n const isFinished = data?.spans.every(span => Boolean(span.endedAt));\n return isFinished ? IMMUTABLE_CACHE_TIME : 0;\n },\n });\n}\n"],"names":[],"mappings":";;;;;AAMA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAW5C,SAAS,cACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,IACjC,SAAS,YAAY;AACnB,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,MACxC;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAA,EAAQ,qBAAA;AAAA,IACR,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,WAAW,CAAA,KAAA,KAAS;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AACzB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,UAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAClE,MAAA,OAAO,aAAa,oBAAA,GAAuB,CAAA;AAAA,IAC7C;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-trace-spans.es.js","sources":["../../../../src/domains/traces/hooks/use-trace-spans.ts"],"sourcesContent":["import type { MastraClient } from '@mastra/client-js';\nimport { useMastraClient } from '@mastra/react';\nimport { queryOptions, useQueries, useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport type { SearchableSpan } from '../types';\nimport { selectSearchableSpans } from '../utils';\n\nconst IMMUTABLE_CACHE_TIME = 1000 * 60 * 60 * 24 * 30; // 30 days, massive cache, span data is immutable\n\n/**\n * Key, fetcher and stale policy of the `trace-spans` query. Every observer of this key must\n * share these (rather than only the key) so one observer with a stricter `staleTime` does not\n * refetch data another one considers fresh.\n */\nexport const traceSpansQueryOptions = (client: MastraClient, traceId: string | null | undefined) =>\n queryOptions({\n queryKey: ['trace-spans', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n const res = await client.getTrace(traceId);\n return res;\n },\n enabled: !!traceId,\n staleTime: query => {\n const data = query.state.data;\n const isFinished = data?.spans.every(span => Boolean(span.endedAt));\n return isFinished ? IMMUTABLE_CACHE_TIME : 0;\n },\n });\n\n/**\n * Every span of a single trace, with its full payload.\n *\n * The lightweight projection exists to keep blob columns off the read path of a\n * *list*, where the cost is paid once per trace on screen. A trace that is open\n * has already narrowed that to one, and the panel both renders and searches\n * these spans -- `input`, `output` and `attributes` included -- so the\n * projection would only hide content the reader is looking at.\n */\nexport function useTraceSpans(\n traceId: string | null | undefined,\n): UseQueryResult<{ traceId: string; spans: SearchableSpan[] } | null> {\n const client = useMastraClient();\n\n return useQuery({\n ...traceSpansQueryOptions(client, traceId),\n // Builds each span's search haystack once per fetch, cached with the query.\n select: selectSearchableSpans,\n });\n}\n\nexport type TraceSpansData = Awaited<ReturnType<MastraClient['getTrace']>>;\n\n/**\n * Observes the `trace-spans` query of several traces at once and projects each one with `select`.\n * Traces still loading (or failed) yield `fallback(traceId)` so the result always lines up with `traceIds`.\n */\nexport function useTraceSpansQueries<T>(\n traceIds: string[],\n select: (traceId: string, data: TraceSpansData) => T,\n fallback: (traceId: string) => T,\n): T[] {\n const client = useMastraClient();\n\n return useQueries({\n queries: traceIds.map(traceId => ({\n ...traceSpansQueryOptions(client, traceId),\n select: (data: TraceSpansData) => select(traceId, data),\n })),\n combine: results =>\n results.map((result, index) =>\n result.data === undefined ? fallback(traceIds[index] ?? '') : (result.data as T),\n ),\n });\n}\n"],"names":[],"mappings":";;;;;AAOA,MAAM,oBAAA,GAAuB,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAO5C,MAAM,sBAAA,GAAyB,CAAC,MAAA,EAAsB,OAAA,KAC3D,YAAA,CAAa;AAAA,EACX,QAAA,EAAU,CAAC,aAAA,EAAe,OAAO,CAAA;AAAA,EACjC,SAAS,YAAY;AACnB,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,IACxC;AACA,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA;AACzC,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAAA,EACA,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,EACX,WAAW,CAAA,KAAA,KAAS;AAClB,IAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,IAAA;AACzB,IAAA,MAAM,UAAA,GAAa,MAAM,KAAA,CAAM,KAAA,CAAM,UAAQ,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAClE,IAAA,OAAO,aAAa,oBAAA,GAAuB,CAAA;AAAA,EAC7C;AACF,CAAC;AAWI,SAAS,cACd,OAAA,EACqE;AACrE,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,GAAG,sBAAA,CAAuB,MAAA,EAAQ,OAAO,CAAA;AAAA;AAAA,IAEzC,MAAA,EAAQ;AAAA,GACT,CAAA;AACH;AAQO,SAAS,oBAAA,CACd,QAAA,EACA,MAAA,EACA,QAAA,EACK;AACL,EAAA,MAAM,SAAS,eAAA,EAAgB;AAE/B,EAAA,OAAO,UAAA,CAAW;AAAA,IAChB,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,MAAY;AAAA,MAChC,GAAG,sBAAA,CAAuB,MAAA,EAAQ,OAAO,CAAA;AAAA,MACzC,MAAA,EAAQ,CAAC,IAAA,KAAyB,MAAA,CAAO,SAAS,IAAI;AAAA,KACxD,CAAE,CAAA;AAAA,IACF,OAAA,EAAS,aACP,OAAA,CAAQ,GAAA;AAAA,MAAI,CAAC,MAAA,EAAQ,KAAA,KACnB,MAAA,CAAO,IAAA,KAAS,MAAA,GAAY,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,IAAK,EAAE,CAAA,GAAK,MAAA,CAAO;AAAA;AACxE,GACH,CAAA;AACH;;;;"}
@@ -9,6 +9,7 @@ const TRACE_ID_PARAM = "traceId";
9
9
  const SPAN_ID_PARAM = "spanId";
10
10
  const TAB_PARAM = "tab";
11
11
  const SCORE_ID_PARAM = "scoreId";
12
+ const HIGHLIGHT_SPAN_IDS_PARAM = "highlightSpanIds";
12
13
  const DAY_MS = 24 * 60 * 60 * 1e3;
13
14
  const PRESET_MS = {
14
15
  "last-24h": DAY_MS,
@@ -23,6 +24,7 @@ function clearSelectionParams(params) {
23
24
  params.delete(domains_traces_traceFilters.TRACE_ANCHOR_SPAN_ID_PARAM);
24
25
  params.delete(TAB_PARAM);
25
26
  params.delete(SCORE_ID_PARAM);
27
+ params.delete(HIGHLIGHT_SPAN_IDS_PARAM);
26
28
  }
27
29
  function useTraceUrlState(searchParams, setSearchParams, options) {
28
30
  const { onRemoveAll } = options ?? {};
@@ -54,6 +56,11 @@ function useTraceUrlState(searchParams, setSearchParams, options) {
54
56
  const tabParam = searchParams.get(TAB_PARAM);
55
57
  const spanTabParam = tabParam === "feedback" ? "feedback" : tabParam === "details" ? "details" : void 0;
56
58
  const scoreIdParam = searchParams.get(SCORE_ID_PARAM) || void 0;
59
+ const highlightSpanIdsRaw = searchParams.get(HIGHLIGHT_SPAN_IDS_PARAM);
60
+ const highlightSpanIdsParam = React.useMemo(
61
+ () => highlightSpanIdsRaw ? highlightSpanIdsRaw.split(",").filter(Boolean) : [],
62
+ [highlightSpanIdsRaw]
63
+ );
57
64
  const listMode = React.useMemo(() => {
58
65
  const value = searchParams.get(domains_traces_traceFilters.TRACE_LIST_MODE_PARAM);
59
66
  return value && domains_traces_traceFilters.TRACE_LIST_MODE_VALUES.has(value) ? value : "traces";
@@ -89,6 +96,7 @@ function useTraceUrlState(searchParams, setSearchParams, options) {
89
96
  }
90
97
  next.delete(TAB_PARAM);
91
98
  next.delete(SCORE_ID_PARAM);
99
+ next.delete(HIGHLIGHT_SPAN_IDS_PARAM);
92
100
  return next;
93
101
  },
94
102
  { replace: true }
@@ -180,6 +188,27 @@ function useTraceUrlState(searchParams, setSearchParams, options) {
180
188
  },
181
189
  [searchParams, setSearchParams]
182
190
  );
191
+ const handleHighlightSpans = React.useCallback(
192
+ (spanIds) => {
193
+ setSearchParams(
194
+ (prev) => {
195
+ const next = new URLSearchParams(prev);
196
+ const [firstSpanId] = spanIds;
197
+ if (!firstSpanId) {
198
+ next.delete(HIGHLIGHT_SPAN_IDS_PARAM);
199
+ return next;
200
+ }
201
+ next.set(HIGHLIGHT_SPAN_IDS_PARAM, spanIds.join(","));
202
+ next.set(SPAN_ID_PARAM, firstSpanId);
203
+ next.delete(TAB_PARAM);
204
+ next.delete(SCORE_ID_PARAM);
205
+ return next;
206
+ },
207
+ { replace: true }
208
+ );
209
+ },
210
+ [setSearchParams]
211
+ );
183
212
  const applyFilterTokens = React.useCallback(
184
213
  (tokens) => {
185
214
  setSearchParams(
@@ -287,6 +316,7 @@ function useTraceUrlState(searchParams, setSearchParams, options) {
287
316
  anchorSpanIdParam,
288
317
  spanTabParam,
289
318
  scoreIdParam,
319
+ highlightSpanIdsParam,
290
320
  listMode,
291
321
  selectedEntityOption,
292
322
  selectedStatus,
@@ -298,6 +328,7 @@ function useTraceUrlState(searchParams, setSearchParams, options) {
298
328
  handleSpanTabChange,
299
329
  handleSpanChangeWithTab,
300
330
  handleScoreChange,
331
+ handleHighlightSpans,
301
332
  handleListModeChange,
302
333
  handleFilterTokensChange,
303
334
  handleDateChange,