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

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 +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"trace-data-panel-view.cjs.js","sources":["../../../../src/domains/traces/components/trace-data-panel-view.tsx"],"sourcesContent":["import {\n CircleGaugeIcon,\n ChevronsDownUpIcon,\n ChevronsUpDownIcon,\n DownloadIcon,\n Link2Icon,\n Loader2Icon,\n MoreHorizontalIcon,\n SaveIcon,\n WrenchIcon,\n} from 'lucide-react';\nimport { useEffect, useId, useMemo, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { getAllSpanIds } from '../hooks/get-all-span-ids';\nimport { useDownloadTraceJson } from '../hooks/use-download-trace-json';\nimport { useTraceSearch } from '../hooks/use-trace-search';\nimport type { TraceUsageSummary } from '../trace-list-columns';\nimport type { SearchableSpan } from '../types';\nimport { formatHierarchicalSpans } from './format-hierarchical-spans';\nimport { TraceSummaryDescription } from './trace-summary-description';\nimport { TraceTimeline } from './trace-timeline';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DataPanel } from '@/ds/components/DataPanel';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { SearchFieldBlock } from '@/ds/components/FormFieldBlocks';\nimport { Notice } from '@/ds/components/Notice';\nimport { Tab, TabContent, TabList, Tabs } from '@/ds/components/Tabs';\nimport type { LinkComponent } from '@/ds/types/link-component';\nimport { useScrollToFirstHighlight } from '@/hooks/use-scroll-to-first-highlight';\nimport { useTextHighlight } from '@/hooks/use-text-highlight';\nimport { truncateString } from '@/lib/truncate-string';\n\nexport type TraceDataPanelPlacement = 'traces-list' | 'trace-page';\n\nexport type TraceDataPanelTab = 'details' | 'partial-thread' | 'scores' | 'feedback';\n\nexport interface TraceDataPanelViewProps {\n traceId: string;\n /** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */\n spans: SearchableSpan[] | undefined;\n isLoading?: boolean;\n onClose: () => void;\n onSpanSelect?: (spanId: string | undefined) => void;\n onEvaluateTrace?: () => void;\n /** When set, an \"Add full trace to dataset\" button appears; the consumer owns the dialog. */\n onSaveAsDatasetItem?: (args: { traceId: string; rootSpanId: string | undefined }) => void;\n /** When set, an \"Add tool mocks to item\" button appears; the consumer owns the dialog. */\n onAddTraceMocksToItem?: (args: { traceId: string }) => void;\n initialSpanId?: string | null;\n onPrevious?: () => void;\n onNext?: () => void;\n collapsed?: boolean;\n onCollapsedChange?: (collapsed: boolean) => void;\n placement: TraceDataPanelPlacement;\n timelineChartWidth?: 'wide' | 'default';\n /** When both are provided, renders an \"Open trace page\" button. */\n LinkComponent?: LinkComponent;\n traceHref?: string;\n /** When provided, the entity name in the trace summary links to the entity's page. */\n entityHref?: string;\n /** Token and estimated-cost totals shown in the compact trace summary. */\n usage?: TraceUsageSummary;\n /**\n * Span treated as the displayed root of the timeline. Required for branch\n * subtrees from `getBranch` where the anchor has a real parent that's outside\n * `spans`. When omitted, the span with no parent is used (trace case).\n */\n anchorSpanId?: string;\n /**\n * Whether to render the \"Evaluating traces and saving them as dataset items is\n * available in Mastra Studio\" info notice when neither `onEvaluateTrace` nor\n * `onSaveAsDatasetItem` is provided. Defaults to `true`. Pass `false` when this\n * panel is rendered inside Studio in a context that intentionally omits those\n * handlers (e.g. inline below an experiment result).\n */\n showUnavailableFeaturesMsg?: boolean;\n /**\n * When provided, the panel content becomes tabbed (\"Details\" / \"Scores\"); the slot\n * renders whatever trace-level scoring UI the consumer wants.\n */\n scoresTabSlot?: (args: { traceId: string; rootSpanId: string | undefined }) => ReactNode;\n /** Optional count shown in the \"Scores\" tab label. */\n scoresTabBadge?: ReactNode;\n /**\n * When provided, a \"Feedback\" tab appears; the slot renders the trace-level\n * feedback UI. Trace feedback is not scoped to a span — the span panel owns that.\n */\n feedbackTabSlot?: (args: { traceId: string }) => ReactNode;\n /** Optional count shown in the \"Feedback\" tab label. */\n feedbackTabBadge?: ReactNode;\n /** When provided, a \"Messages\" tab renders the trace as one reconstructed agent turn. */\n partialThreadTabSlot?: (args: { traceId: string }) => ReactNode;\n activeTab?: TraceDataPanelTab;\n onTabChange?: (tab: TraceDataPanelTab) => void;\n /**\n * When provided, the panel splits into two columns inside the same card: the\n * trace content on the left, this slot (typically the span detail) on the right.\n */\n spanPanelSlot?: ReactNode;\n /** Extra classes applied to the panel root (e.g. `h-full` on the trace page). */\n className?: string;\n}\n\nexport function TraceDataPanelView({\n traceId,\n spans,\n isLoading,\n onClose,\n onSpanSelect,\n onEvaluateTrace,\n onSaveAsDatasetItem,\n onAddTraceMocksToItem,\n initialSpanId,\n onPrevious,\n onNext,\n collapsed: controlledCollapsed,\n onCollapsedChange,\n placement,\n timelineChartWidth = 'default',\n LinkComponent,\n traceHref,\n entityHref,\n usage,\n anchorSpanId,\n showUnavailableFeaturesMsg = true,\n scoresTabSlot,\n scoresTabBadge,\n feedbackTabSlot,\n feedbackTabBadge,\n partialThreadTabSlot,\n activeTab,\n onTabChange,\n spanPanelSlot,\n className,\n}: TraceDataPanelViewProps) {\n const isOnTracePage = placement === 'trace-page';\n const [internalCollapsed, setInternalCollapsed] = useState(false);\n const collapsed = controlledCollapsed ?? internalCollapsed;\n const setCollapsed = onCollapsedChange ?? setInternalCollapsed;\n\n const { download: downloadTraceJson, isPending: isDownloadingTrace } = useDownloadTraceJson();\n\n const [selectedSpanId, setSelectedSpanId] = useState<string | undefined>(initialSpanId ?? undefined);\n\n // Sync selected span when initialSpanId or trace data changes\n useEffect(() => {\n // No span requested: clear immediately.\n if (!initialSpanId) {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n return;\n }\n // Span requested: wait for trace data before deciding so an in-flight\n // fetch doesn't wipe a URL-provided selection. Callers that default their\n // spans to `[]` while loading only say so through `isLoading`.\n if (isLoading || !spans) return;\n\n const found = spans.find(s => s.spanId === initialSpanId);\n if (found) {\n setSelectedSpanId(initialSpanId);\n onSpanSelect?.(initialSpanId);\n } else {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialSpanId, spans, isLoading]);\n\n const searchFieldName = useId();\n const { query, setQuery, results, payloadOnlyMatchIds } = useTraceSearch(spans ?? []);\n\n const hierarchicalSpans = useMemo(\n () =>\n formatHierarchicalSpans(\n // Carried on the span rather than drilled as a prop: the tree is rebuilt here and\n // rendered several components deeper.\n results.map(span => ({ ...span, matchedInPayloadOnly: payloadOnlyMatchIds.has(span.spanId) })),\n anchorSpanId,\n ),\n [results, payloadOnlyMatchIds, anchorSpanId],\n );\n\n const [expandedSpanIds, setExpandedSpanIds] = useState<string[]>([]);\n\n useEffect(() => {\n if (hierarchicalSpans.length > 0) {\n setExpandedSpanIds(getAllSpanIds(hierarchicalSpans));\n }\n }, [hierarchicalSpans]);\n\n const rootSpan = useMemo(\n () => (anchorSpanId ? spans?.find(s => s.spanId === anchorSpanId) : spans?.find(s => s.parentSpanId == null)),\n [spans, anchorSpanId],\n );\n const handleSpanClick = (id: string) => {\n const newId = selectedSpanId === id ? undefined : id;\n setSelectedSpanId(newId);\n onSpanSelect?.(newId);\n };\n\n const traceActionsMenu = (\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button size=\"md\" tooltip=\"Trace actions\" aria-label=\"Trace actions\">\n <MoreHorizontalIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\">\n {!isOnTracePage && onCollapsedChange && (\n <DropdownMenu.Item onSelect={() => setCollapsed(!collapsed)}>\n {collapsed ? <ChevronsUpDownIcon /> : <ChevronsDownUpIcon />}\n {collapsed ? 'Expand panel' : 'Collapse panel'}\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onEvaluateTrace && (\n <DropdownMenu.Item onSelect={onEvaluateTrace}>\n <CircleGaugeIcon />\n Evaluate trace\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onSaveAsDatasetItem && (\n <DropdownMenu.Item onSelect={() => onSaveAsDatasetItem({ traceId, rootSpanId: rootSpan?.spanId })}>\n <SaveIcon />\n Add full trace to dataset\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onAddTraceMocksToItem && (\n <DropdownMenu.Item onSelect={() => onAddTraceMocksToItem({ traceId })}>\n <WrenchIcon />\n Add tool mocks to item\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && LinkComponent && traceHref && (\n <DropdownMenu.Item render={<LinkComponent href={traceHref} />}>\n <Link2Icon />\n Open trace page\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item disabled={isDownloadingTrace} onSelect={() => downloadTraceJson(traceId)}>\n {isDownloadingTrace ? <Loader2Icon className=\"animate-spin\" /> : <DownloadIcon />}\n Download trace JSON\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n );\n\n return (\n <DataPanel collapsed={collapsed} className={className}>\n <DataPanel.Header>\n {isOnTracePage ? (\n <>\n <DataPanel.Heading>Trace Timeline</DataPanel.Heading>\n <ButtonsGroup className=\"ml-auto shrink-0\">{traceActionsMenu}</ButtonsGroup>\n </>\n ) : (\n <>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <DataPanel.Heading>\n Trace <b># {truncateString(traceId, 12)}</b>\n </DataPanel.Heading>\n {!collapsed && rootSpan && (\n <TraceSummaryDescription\n rootSpan={rootSpan}\n usage={usage}\n entityHref={entityHref}\n LinkComponent={LinkComponent}\n />\n )}\n </div>\n <ButtonsGroup className=\"ml-auto shrink-0 self-start\">\n {traceActionsMenu}\n {(onPrevious || onNext) && (\n <DataPanel.NextPrevNav\n onPrevious={onPrevious}\n onNext={onNext}\n previousLabel=\"Previous trace\"\n nextLabel=\"Next trace\"\n />\n )}\n <DataPanel.CloseButton onClick={onClose} />\n </ButtonsGroup>\n </>\n )}\n </DataPanel.Header>\n\n {!collapsed && (\n <SplitWithSpanPanel spanPanelSlot={spanPanelSlot} highlightQuery={query} spanPanelKey={selectedSpanId}>\n {isLoading ? (\n <DataPanel.LoadingData>Loading trace...</DataPanel.LoadingData>\n ) : !spans?.length ? (\n <DataPanel.NoData>No spans found for this trace.</DataPanel.NoData>\n ) : (\n <DataPanel.Content>\n {(() => {\n const detailsBody = (\n <>\n {!isOnTracePage &&\n !onEvaluateTrace &&\n !onSaveAsDatasetItem &&\n !onAddTraceMocksToItem &&\n showUnavailableFeaturesMsg && (\n <Notice variant=\"info\" className=\"mb-6\">\n <Notice.Message>\n Evaluating traces and saving them as dataset items is available in Mastra Studio (local or\n deployed).\n </Notice.Message>\n </Notice>\n )}\n\n {/* The timeline stays mounted even with no results, because it\n hosts the search field: unmounting it would strand the user\n with a query they can no longer clear. */}\n <TraceTimeline\n hierarchicalSpans={hierarchicalSpans}\n onSpanClick={handleSpanClick}\n selectedSpanId={selectedSpanId}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n chartWidth={timelineChartWidth}\n leadingSlot={\n <SearchFieldBlock\n name={searchFieldName}\n label=\"Search spans\"\n labelIsHidden\n placeholder=\"Search spans...\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n onReset={() => setQuery('')}\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n />\n }\n />\n\n {hierarchicalSpans.length === 0 && <DataPanel.NoData>No spans match your search.</DataPanel.NoData>}\n </>\n );\n\n // No extra tab slots → render details directly without the Tabs wrapper.\n if (!partialThreadTabSlot && !scoresTabSlot && !feedbackTabSlot) return detailsBody;\n\n return (\n <Tabs<TraceDataPanelTab>\n defaultTab=\"details\"\n value={activeTab}\n onValueChange={onTabChange}\n className={\n activeTab === 'partial-thread' || activeTab === 'scores' || activeTab === 'feedback'\n ? 'grid h-full min-h-0 grid-rows-[auto_1fr]'\n : undefined\n }\n >\n <TabList variant=\"pill-ghost\" className=\"px-0\">\n <Tab value=\"details\">Spans</Tab>\n {partialThreadTabSlot && <Tab value=\"partial-thread\">Messages</Tab>}\n {feedbackTabSlot && (\n <Tab value=\"feedback\">Feedback{feedbackTabBadge != null && <> ({feedbackTabBadge})</>}</Tab>\n )}\n {scoresTabSlot && (\n <Tab value=\"scores\">Scores{scoresTabBadge != null && <> ({scoresTabBadge})</>}</Tab>\n )}\n </TabList>\n\n <TabContent value=\"details\">{detailsBody}</TabContent>\n {partialThreadTabSlot && (\n <TabContent value=\"partial-thread\" className=\"h-full min-h-0\">\n {partialThreadTabSlot({ traceId })}\n </TabContent>\n )}\n {feedbackTabSlot && (\n <TabContent value=\"feedback\" className=\"h-full min-h-0\">\n {feedbackTabSlot({ traceId })}\n </TabContent>\n )}\n {scoresTabSlot && (\n <TabContent value=\"scores\" className=\"h-full min-h-0\">\n {scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId })}\n </TabContent>\n )}\n </Tabs>\n );\n })()}\n </DataPanel.Content>\n )}\n </SplitWithSpanPanel>\n )}\n </DataPanel>\n );\n}\n\n/**\n * Renders the trace content as-is, or — when a span panel is provided — as a\n * two-column split inside the same card, with the span detail on the right.\n * Search matches — span names in the timeline tree as well as values in the span\n * detail — are highlighted while a query is active.\n */\nfunction SplitWithSpanPanel({\n spanPanelSlot,\n highlightQuery,\n spanPanelKey,\n children,\n}: {\n spanPanelSlot?: ReactNode;\n highlightQuery: string;\n /** Identity of the span shown in the panel; changing it re-triggers the match scroll. */\n spanPanelKey?: string;\n children: ReactNode;\n}) {\n // A single hook call on the common ancestor covers both the timeline tree and\n // the span detail, so span names and payload values highlight together.\n const { ref: highlightRef } = useTextHighlight<HTMLDivElement>(highlightQuery);\n\n // Scoped to the span-panel column only: a match deep in a large payload sits below\n // the fold, so the first painted match is brought into view when the panel opens.\n // The timeline column must never be scrolled by this.\n const { ref: scrollToMatchRef } = useScrollToFirstHighlight<HTMLDivElement>(highlightQuery, spanPanelKey);\n\n if (!spanPanelSlot) {\n return (\n <div ref={highlightRef} className=\"flex min-h-0 flex-1 flex-col overflow-hidden\">\n {children}\n </div>\n );\n }\n\n return (\n <div ref={highlightRef} className=\"grid min-h-0 flex-1 grid-cols-[1fr_1fr]\">\n <div className=\"flex min-h-0 flex-col overflow-hidden\">{children}</div>\n {/* Searchable: the span detail is where a match hides inside a large payload. */}\n <div\n ref={scrollToMatchRef}\n data-highlight\n className=\"animate-in border-border1 fade-in-0 flex min-h-0 flex-col overflow-hidden border-l duration-300\"\n >\n {spanPanelSlot}\n </div>\n </div>\n );\n}\n"],"names":["useState","useDownloadTraceJson","useEffect","useId","useTraceSearch","useMemo","formatHierarchicalSpans","getAllSpanIds","DropdownMenu","jsx","Button","MoreHorizontalIcon","jsxs","ChevronsUpDownIcon","ChevronsDownUpIcon","CircleGaugeIcon","SaveIcon","WrenchIcon","Link2Icon","Loader2Icon","DownloadIcon","DataPanel","Fragment","ButtonsGroup","truncateString","TraceSummaryDescription","Notice","TraceTimeline","SearchFieldBlock","Tabs","TabList","Tab","TabContent","useTextHighlight","useScrollToFirstHighlight"],"mappings":"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"}
1
+ {"version":3,"file":"trace-data-panel-view.cjs.js","sources":["../../../../src/domains/traces/components/trace-data-panel-view.tsx"],"sourcesContent":["import {\n CircleGaugeIcon,\n ChevronsDownUpIcon,\n ChevronsUpDownIcon,\n DownloadIcon,\n Link2Icon,\n Loader2Icon,\n MoreHorizontalIcon,\n SaveIcon,\n WrenchIcon,\n} from 'lucide-react';\nimport { useEffect, useId, useMemo, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { getAllSpanIds } from '../hooks/get-all-span-ids';\nimport { useDownloadTraceJson } from '../hooks/use-download-trace-json';\nimport { useTraceSearch } from '../hooks/use-trace-search';\nimport type { TraceUsageSummary } from '../trace-list-columns';\nimport type { SearchableSpan } from '../types';\nimport { formatHierarchicalSpans } from './format-hierarchical-spans';\nimport { TraceSummaryDescription } from './trace-summary-description';\nimport { TraceTimeline } from './trace-timeline';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DataPanel } from '@/ds/components/DataPanel';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { SearchFieldBlock } from '@/ds/components/FormFieldBlocks';\nimport { Notice } from '@/ds/components/Notice';\nimport { Tab, TabContent, TabList, Tabs } from '@/ds/components/Tabs';\nimport type { LinkComponent } from '@/ds/types/link-component';\nimport { useScrollToFirstHighlight } from '@/hooks/use-scroll-to-first-highlight';\nimport { useTextHighlight } from '@/hooks/use-text-highlight';\nimport { truncateString } from '@/lib/truncate-string';\nimport { cn } from '@/lib/utils';\n\nexport type TraceDataPanelPlacement = 'traces-list' | 'trace-page';\n\nexport type TraceDataPanelTab = 'details' | 'scores' | 'feedback';\n\nexport interface TraceDataPanelViewProps {\n traceId: string;\n /** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */\n spans: SearchableSpan[] | undefined;\n isLoading?: boolean;\n onClose: () => void;\n onSpanSelect?: (spanId: string | undefined) => void;\n onEvaluateTrace?: () => void;\n /** When set, an \"Add full trace to dataset\" button appears; the consumer owns the dialog. */\n onSaveAsDatasetItem?: (args: { traceId: string; rootSpanId: string | undefined }) => void;\n /** When set, an \"Add tool mocks to item\" button appears; the consumer owns the dialog. */\n onAddTraceMocksToItem?: (args: { traceId: string }) => void;\n initialSpanId?: string | null;\n onPrevious?: () => void;\n onNext?: () => void;\n collapsed?: boolean;\n onCollapsedChange?: (collapsed: boolean) => void;\n placement: TraceDataPanelPlacement;\n timelineChartWidth?: 'wide' | 'default';\n /** When both are provided, renders an \"Open trace page\" button. */\n LinkComponent?: LinkComponent;\n traceHref?: string;\n /** When provided, the entity name in the trace summary links to the entity's page. */\n entityHref?: string;\n /** Token and estimated-cost totals shown in the compact trace summary. */\n usage?: TraceUsageSummary;\n /**\n * Span treated as the displayed root of the timeline. Required for branch\n * subtrees from `getBranch` where the anchor has a real parent that's outside\n * `spans`. When omitted, the span with no parent is used (trace case).\n */\n anchorSpanId?: string;\n /**\n * Whether to render the \"Evaluating traces and saving them as dataset items is\n * available in Mastra Studio\" info notice when neither `onEvaluateTrace` nor\n * `onSaveAsDatasetItem` is provided. Defaults to `true`. Pass `false` when this\n * panel is rendered inside Studio in a context that intentionally omits those\n * handlers (e.g. inline below an experiment result).\n */\n showUnavailableFeaturesMsg?: boolean;\n /**\n * When provided, the panel content becomes tabbed (\"Details\" / \"Scores\"); the slot\n * renders whatever trace-level scoring UI the consumer wants.\n */\n scoresTabSlot?: (args: { traceId: string; rootSpanId: string | undefined }) => ReactNode;\n /** Optional count shown in the \"Scores\" tab label. */\n scoresTabBadge?: ReactNode;\n /**\n * When provided, a \"Feedback\" tab appears; the slot renders the trace-level\n * feedback UI. Trace feedback is not scoped to a span — the span panel owns that.\n */\n feedbackTabSlot?: (args: { traceId: string }) => ReactNode;\n /** Optional count shown in the \"Feedback\" tab label. */\n feedbackTabBadge?: ReactNode;\n activeTab?: TraceDataPanelTab;\n onTabChange?: (tab: TraceDataPanelTab) => void;\n /** Span ids to feature in the timeline; every other span is faded. */\n featuredSpanIds?: string[];\n /**\n * Rendered as a column to the left of the timeline inside the same card;\n * typically the reconstructed agent turn (\"Messages\").\n */\n messagesPanelSlot?: ReactNode;\n /**\n * Rendered as a column to the right of the timeline inside the same card;\n * typically the span detail.\n */\n spanPanelSlot?: ReactNode;\n /** Extra classes applied to the panel root (e.g. `h-full` on the trace page). */\n className?: string;\n}\n\nexport function TraceDataPanelView({\n traceId,\n spans,\n isLoading,\n onClose,\n onSpanSelect,\n onEvaluateTrace,\n onSaveAsDatasetItem,\n onAddTraceMocksToItem,\n initialSpanId,\n onPrevious,\n onNext,\n collapsed: controlledCollapsed,\n onCollapsedChange,\n placement,\n timelineChartWidth = 'default',\n LinkComponent,\n traceHref,\n entityHref,\n usage,\n anchorSpanId,\n showUnavailableFeaturesMsg = true,\n scoresTabSlot,\n scoresTabBadge,\n feedbackTabSlot,\n feedbackTabBadge,\n activeTab,\n onTabChange,\n featuredSpanIds,\n messagesPanelSlot,\n spanPanelSlot,\n className,\n}: TraceDataPanelViewProps) {\n const isOnTracePage = placement === 'trace-page';\n const [internalCollapsed, setInternalCollapsed] = useState(false);\n const collapsed = controlledCollapsed ?? internalCollapsed;\n const setCollapsed = onCollapsedChange ?? setInternalCollapsed;\n\n const { download: downloadTraceJson, isPending: isDownloadingTrace } = useDownloadTraceJson();\n\n const [selectedSpanId, setSelectedSpanId] = useState<string | undefined>(initialSpanId ?? undefined);\n\n // Sync selected span when initialSpanId or trace data changes\n useEffect(() => {\n // No span requested: clear immediately.\n if (!initialSpanId) {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n return;\n }\n // Span requested: wait for trace data before deciding so an in-flight\n // fetch doesn't wipe a URL-provided selection. Callers that default their\n // spans to `[]` while loading only say so through `isLoading`.\n if (isLoading || !spans) return;\n\n const found = spans.find(s => s.spanId === initialSpanId);\n if (found) {\n setSelectedSpanId(initialSpanId);\n onSpanSelect?.(initialSpanId);\n } else {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialSpanId, spans, isLoading]);\n\n const searchFieldName = useId();\n const { query, setQuery, results, payloadOnlyMatchIds } = useTraceSearch(spans ?? []);\n\n const hierarchicalSpans = useMemo(\n () =>\n formatHierarchicalSpans(\n // Carried on the span rather than drilled as a prop: the tree is rebuilt here and\n // rendered several components deeper.\n results.map(span => ({ ...span, matchedInPayloadOnly: payloadOnlyMatchIds.has(span.spanId) })),\n anchorSpanId,\n ),\n [results, payloadOnlyMatchIds, anchorSpanId],\n );\n\n const [expandedSpanIds, setExpandedSpanIds] = useState<string[]>([]);\n\n useEffect(() => {\n if (hierarchicalSpans.length > 0) {\n setExpandedSpanIds(getAllSpanIds(hierarchicalSpans));\n }\n }, [hierarchicalSpans]);\n\n const rootSpan = useMemo(\n () => (anchorSpanId ? spans?.find(s => s.spanId === anchorSpanId) : spans?.find(s => s.parentSpanId == null)),\n [spans, anchorSpanId],\n );\n const handleSpanClick = (id: string) => {\n const newId = selectedSpanId === id ? undefined : id;\n setSelectedSpanId(newId);\n onSpanSelect?.(newId);\n };\n\n const traceActionsMenu = (\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button size=\"md\" tooltip=\"Trace actions\" aria-label=\"Trace actions\">\n <MoreHorizontalIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\">\n {!isOnTracePage && onCollapsedChange && (\n <DropdownMenu.Item onSelect={() => setCollapsed(!collapsed)}>\n {collapsed ? <ChevronsUpDownIcon /> : <ChevronsDownUpIcon />}\n {collapsed ? 'Expand panel' : 'Collapse panel'}\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onEvaluateTrace && (\n <DropdownMenu.Item onSelect={onEvaluateTrace}>\n <CircleGaugeIcon />\n Evaluate trace\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onSaveAsDatasetItem && (\n <DropdownMenu.Item onSelect={() => onSaveAsDatasetItem({ traceId, rootSpanId: rootSpan?.spanId })}>\n <SaveIcon />\n Add full trace to dataset\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onAddTraceMocksToItem && (\n <DropdownMenu.Item onSelect={() => onAddTraceMocksToItem({ traceId })}>\n <WrenchIcon />\n Add tool mocks to item\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && LinkComponent && traceHref && (\n <DropdownMenu.Item render={<LinkComponent href={traceHref} />}>\n <Link2Icon />\n Open trace page\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item disabled={isDownloadingTrace} onSelect={() => downloadTraceJson(traceId)}>\n {isDownloadingTrace ? <Loader2Icon className=\"animate-spin\" /> : <DownloadIcon />}\n Download trace JSON\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n );\n\n return (\n <DataPanel collapsed={collapsed} className={className}>\n <DataPanel.Header>\n {isOnTracePage ? (\n <>\n <DataPanel.Heading>Trace Timeline</DataPanel.Heading>\n <ButtonsGroup className=\"ml-auto shrink-0\">{traceActionsMenu}</ButtonsGroup>\n </>\n ) : (\n <>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <DataPanel.Heading>\n Trace <b># {truncateString(traceId, 12)}</b>\n </DataPanel.Heading>\n {!collapsed && rootSpan && (\n <TraceSummaryDescription\n rootSpan={rootSpan}\n usage={usage}\n entityHref={entityHref}\n LinkComponent={LinkComponent}\n />\n )}\n </div>\n <ButtonsGroup className=\"ml-auto shrink-0 self-start\">\n {traceActionsMenu}\n {(onPrevious || onNext) && (\n <DataPanel.NextPrevNav\n onPrevious={onPrevious}\n onNext={onNext}\n previousLabel=\"Previous trace\"\n nextLabel=\"Next trace\"\n />\n )}\n <DataPanel.CloseButton onClick={onClose} />\n </ButtonsGroup>\n </>\n )}\n </DataPanel.Header>\n\n {!collapsed && (\n <TracePanelColumns\n messagesPanelSlot={messagesPanelSlot}\n spanPanelSlot={spanPanelSlot}\n highlightQuery={query}\n spanPanelKey={selectedSpanId}\n >\n {isLoading ? (\n <DataPanel.LoadingData>Loading trace...</DataPanel.LoadingData>\n ) : !spans?.length ? (\n <DataPanel.NoData>No spans found for this trace.</DataPanel.NoData>\n ) : (\n (() => {\n const detailsBody = (\n <DataPanel.Content>\n {!isOnTracePage &&\n !onEvaluateTrace &&\n !onSaveAsDatasetItem &&\n !onAddTraceMocksToItem &&\n showUnavailableFeaturesMsg && (\n <Notice variant=\"info\" className=\"mb-6\">\n <Notice.Message>\n Evaluating traces and saving them as dataset items is available in Mastra Studio (local or\n deployed).\n </Notice.Message>\n </Notice>\n )}\n\n {/* The timeline stays mounted even with no results, because it\n hosts the search field: unmounting it would strand the user\n with a query they can no longer clear. */}\n <TraceTimeline\n hierarchicalSpans={hierarchicalSpans}\n onSpanClick={handleSpanClick}\n selectedSpanId={selectedSpanId}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n featuredSpanIds={featuredSpanIds}\n chartWidth={timelineChartWidth}\n leadingSlot={\n <SearchFieldBlock\n name={searchFieldName}\n label=\"Search spans\"\n labelIsHidden\n placeholder=\"Search spans...\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n onReset={() => setQuery('')}\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n />\n }\n />\n\n {hierarchicalSpans.length === 0 && <DataPanel.NoData>No spans match your search.</DataPanel.NoData>}\n </DataPanel.Content>\n );\n\n // No extra tab slots → render details directly without the Tabs wrapper.\n if (!scoresTabSlot && !feedbackTabSlot) return detailsBody;\n\n // The tab list sits in a header row so it lines up with the Messages and\n // span-detail headers in the neighbouring columns.\n return (\n <Tabs<TraceDataPanelTab>\n defaultTab=\"details\"\n value={activeTab}\n onValueChange={onTabChange}\n className=\"grid h-full min-h-0 grid-rows-[auto_1fr]\"\n >\n {/* Pill tabs carry their own p-1, so shrink the header padding to keep min-h-14. */}\n <DataPanel.Header className=\"py-2\">\n <TabList variant=\"pill-ghost\" className=\"px-0\">\n <Tab value=\"details\">Spans</Tab>\n {feedbackTabSlot && (\n <Tab value=\"feedback\">Feedback{feedbackTabBadge != null && <> ({feedbackTabBadge})</>}</Tab>\n )}\n {scoresTabSlot && (\n <Tab value=\"scores\">Scores{scoresTabBadge != null && <> ({scoresTabBadge})</>}</Tab>\n )}\n </TabList>\n </DataPanel.Header>\n\n <TabContent value=\"details\" className=\"min-h-0 py-0\">\n {detailsBody}\n </TabContent>\n {feedbackTabSlot && (\n <TabContent value=\"feedback\" className=\"h-full min-h-0 py-0\">\n <DataPanel.Content>{feedbackTabSlot({ traceId })}</DataPanel.Content>\n </TabContent>\n )}\n {scoresTabSlot && (\n <TabContent value=\"scores\" className=\"h-full min-h-0 py-0\">\n <DataPanel.Content>{scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId })}</DataPanel.Content>\n </TabContent>\n )}\n </Tabs>\n );\n })()\n )}\n </TracePanelColumns>\n )}\n </DataPanel>\n );\n}\n\n/**\n * Lays out the card body as three columns — `[messages] [trace] [span]` — inside the\n * same card. Both side cells always exist and collapse to `0fr` when their slot is\n * absent, so opening/closing a column animates via `grid-template-columns` rather\n * than mounting/unmounting a DOM column (which cannot be transitioned).\n * Search matches — span names in the timeline tree as well as values in the span\n * detail — are highlighted while a query is active.\n */\nfunction TracePanelColumns({\n messagesPanelSlot,\n spanPanelSlot,\n highlightQuery,\n spanPanelKey,\n children,\n}: {\n messagesPanelSlot?: ReactNode;\n spanPanelSlot?: ReactNode;\n highlightQuery: string;\n /** Identity of the span shown in the panel; changing it re-triggers the match scroll. */\n spanPanelKey?: string;\n children: ReactNode;\n}) {\n // A single hook call on the common ancestor covers both the timeline tree and\n // the span detail, so span names and payload values highlight together.\n const { ref: highlightRef } = useTextHighlight<HTMLDivElement>(highlightQuery);\n\n // Scoped to the span-panel column only: a match deep in a large payload sits below\n // the fold, so the first painted match is brought into view when the panel opens.\n // The timeline column must never be scrolled by this.\n const { ref: scrollToMatchRef } = useScrollToFirstHighlight<HTMLDivElement>(highlightQuery, spanPanelKey);\n\n const columns = messagesPanelSlot\n ? spanPanelSlot\n ? 'grid-cols-[1fr_1fr_1fr]'\n : 'grid-cols-[1fr_1fr_0fr]'\n : spanPanelSlot\n ? 'grid-cols-[0fr_1fr_1fr]'\n : 'grid-cols-[0fr_1fr_0fr]';\n\n return (\n <div\n ref={highlightRef}\n data-trace-columns\n className={cn('grid min-h-0 flex-1 transition-[grid-template-columns] duration-300 ease-in-out', columns)}\n >\n <div\n className={cn(\n 'flex min-h-0 min-w-0 flex-col overflow-hidden',\n messagesPanelSlot && 'animate-in border-r border-border1 duration-300 fade-in-0',\n )}\n >\n {messagesPanelSlot}\n </div>\n <div className=\"flex min-h-0 min-w-0 flex-col overflow-hidden\">{children}</div>\n {/* Searchable: the span detail is where a match hides inside a large payload. */}\n <div\n ref={scrollToMatchRef}\n data-highlight\n className={cn(\n 'flex min-h-0 min-w-0 flex-col overflow-hidden',\n spanPanelSlot && 'animate-in border-l border-border1 duration-300 fade-in-0',\n )}\n >\n {spanPanelSlot}\n </div>\n </div>\n );\n}\n"],"names":["useState","useDownloadTraceJson","useEffect","useId","useTraceSearch","useMemo","formatHierarchicalSpans","getAllSpanIds","DropdownMenu","jsx","Button","MoreHorizontalIcon","jsxs","ChevronsUpDownIcon","ChevronsDownUpIcon","CircleGaugeIcon","SaveIcon","WrenchIcon","Link2Icon","Loader2Icon","DownloadIcon","DataPanel","Fragment","ButtonsGroup","truncateString","TraceSummaryDescription","Notice","TraceTimeline","SearchFieldBlock","Tabs","TabList","Tab","TabContent","useTextHighlight","useScrollToFirstHighlight","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA8GO,SAAS,kBAAA,CAAmB;AAAA,EACjC,OAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA,qBAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,EAAW,mBAAA;AAAA,EACX,iBAAA;AAAA,EACA,SAAA;AAAA,EACA,kBAAA,GAAqB,SAAA;AAAA,EACrB,aAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA,0BAAA,GAA6B,IAAA;AAAA,EAC7B,aAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACA,iBAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,EAA4B;AAC1B,EAAA,MAAM,gBAAgB,SAAA,KAAc,YAAA;AACpC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIA,eAAS,KAAK,CAAA;AAChE,EAAA,MAAM,YAAY,mBAAA,IAAuB,iBAAA;AACzC,EAAA,MAAM,eAAe,iBAAA,IAAqB,oBAAA;AAE1C,EAAA,MAAM,EAAE,QAAA,EAAU,iBAAA,EAAmB,SAAA,EAAW,kBAAA,KAAuBC,8DAAA,EAAqB;AAE5F,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAID,cAAA,CAA6B,iBAAiB,MAAS,CAAA;AAGnG,EAAAE,eAAA,CAAU,MAAM;AAEd,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,iBAAA,CAAkB,MAAS,CAAA;AAC3B,MAAA,YAAA,GAAe,MAAS,CAAA;AACxB,MAAA;AAAA,IACF;AAIA,IAAA,IAAI,SAAA,IAAa,CAAC,KAAA,EAAO;AAEzB,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,WAAW,aAAa,CAAA;AACxD,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,iBAAA,CAAkB,aAAa,CAAA;AAC/B,MAAA,YAAA,GAAe,aAAa,CAAA;AAAA,IAC9B,CAAA,MAAO;AACL,MAAA,iBAAA,CAAkB,MAAS,CAAA;AAC3B,MAAA,YAAA,GAAe,MAAS,CAAA;AAAA,IAC1B;AAAA,EAEF,CAAA,EAAG,CAAC,aAAA,EAAe,KAAA,EAAO,SAAS,CAAC,CAAA;AAEpC,EAAA,MAAM,kBAAkBC,WAAA,EAAM;AAC9B,EAAA,MAAM,EAAE,OAAO,QAAA,EAAU,OAAA,EAAS,qBAAoB,GAAIC,kDAAA,CAAe,KAAA,IAAS,EAAE,CAAA;AAEpF,EAAA,MAAM,iBAAA,GAAoBC,aAAA;AAAA,IACxB,MACEC,yEAAA;AAAA;AAAA;AAAA,MAGE,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,MAAS,EAAE,GAAG,IAAA,EAAM,oBAAA,EAAsB,mBAAA,CAAoB,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA,EAAE,CAAE,CAAA;AAAA,MAC7F;AAAA,KACF;AAAA,IACF,CAAC,OAAA,EAAS,mBAAA,EAAqB,YAAY;AAAA,GAC7C;AAEA,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAIN,cAAA,CAAmB,EAAE,CAAA;AAEnE,EAAAE,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,iBAAA,CAAkB,SAAS,CAAA,EAAG;AAChC,MAAA,kBAAA,CAAmBK,gDAAA,CAAc,iBAAiB,CAAC,CAAA;AAAA,IACrD;AAAA,EACF,CAAA,EAAG,CAAC,iBAAiB,CAAC,CAAA;AAEtB,EAAA,MAAM,QAAA,GAAWF,aAAA;AAAA,IACf,MAAO,YAAA,GAAe,KAAA,EAAO,IAAA,CAAK,OAAK,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,GAAI,KAAA,EAAO,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,gBAAgB,IAAI,CAAA;AAAA,IAC3G,CAAC,OAAO,YAAY;AAAA,GACtB;AACA,EAAA,MAAM,eAAA,GAAkB,CAAC,EAAA,KAAe;AACtC,IAAA,MAAM,KAAA,GAAQ,cAAA,KAAmB,EAAA,GAAK,MAAA,GAAY,EAAA;AAClD,IAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,IAAA,YAAA,GAAe,KAAK,CAAA;AAAA,EACtB,CAAA;AAEA,EAAA,MAAM,gBAAA,mCACHG,yBAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAC,cAAA;AAAA,MAACD,yBAAA,CAAa,OAAA;AAAA,MAAb;AAAA,QACC,MAAA,kBACEC,cAAA,CAACC,aAAA,EAAA,EAAO,IAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,eAAA,EAAgB,YAAA,EAAW,eAAA,EACnD,QAAA,kBAAAD,cAAA,CAACE,8BAAA,EAAA,EAAmB,CAAA,EACtB;AAAA;AAAA,KAEJ;AAAA,oBACAC,eAAA,CAACJ,yBAAA,CAAa,OAAA,EAAb,EAAqB,OAAM,KAAA,EACzB,QAAA,EAAA;AAAA,MAAA,CAAC,aAAA,IAAiB,iBAAA,oBACjBI,eAAA,CAACJ,yBAAA,CAAa,IAAA,EAAb,EAAkB,QAAA,EAAU,MAAM,YAAA,CAAa,CAAC,SAAS,CAAA,EACvD,QAAA,EAAA;AAAA,QAAA,SAAA,mBAAYC,cAAA,CAACI,8BAAA,EAAA,EAAmB,CAAA,mBAAKJ,cAAA,CAACK,8BAAA,EAAA,EAAmB,CAAA;AAAA,QACzD,YAAY,cAAA,GAAiB;AAAA,OAAA,EAChC,CAAA;AAAA,MAED,CAAC,iBAAiB,eAAA,oBACjBF,eAAA,CAACJ,0BAAa,IAAA,EAAb,EAAkB,UAAU,eAAA,EAC3B,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAACM,2BAAA,EAAA,EAAgB,CAAA;AAAA,QAAE;AAAA,OAAA,EAErB,CAAA;AAAA,MAED,CAAC,aAAA,IAAiB,mBAAA,oBACjBH,eAAA,CAACJ,yBAAA,CAAa,MAAb,EAAkB,QAAA,EAAU,MAAM,mBAAA,CAAoB,EAAE,OAAA,EAAS,UAAA,EAAY,QAAA,EAAU,MAAA,EAAQ,CAAA,EAC9F,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAACO,oBAAA,EAAA,EAAS,CAAA;AAAA,QAAE;AAAA,OAAA,EAEd,CAAA;AAAA,MAED,CAAC,aAAA,IAAiB,qBAAA,oBACjBJ,eAAA,CAACJ,yBAAA,CAAa,IAAA,EAAb,EAAkB,QAAA,EAAU,MAAM,qBAAA,CAAsB,EAAE,OAAA,EAAS,CAAA,EAClE,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAACQ,sBAAA,EAAA,EAAW,CAAA;AAAA,QAAE;AAAA,OAAA,EAEhB,CAAA;AAAA,MAED,CAAC,aAAA,IAAiB,aAAA,IAAiB,SAAA,oBAClCL,eAAA,CAACJ,yBAAA,CAAa,IAAA,EAAb,EAAkB,MAAA,kBAAQC,cAAA,CAAC,aAAA,EAAA,EAAc,IAAA,EAAM,WAAW,CAAA,EACzD,QAAA,EAAA;AAAA,wBAAAA,cAAA,CAACS,qBAAA,EAAA,EAAU,CAAA;AAAA,QAAE;AAAA,OAAA,EAEf,CAAA;AAAA,sBAEFN,eAAA,CAACJ,yBAAA,CAAa,IAAA,EAAb,EAAkB,QAAA,EAAU,oBAAoB,QAAA,EAAU,MAAM,iBAAA,CAAkB,OAAO,CAAA,EACvF,QAAA,EAAA;AAAA,QAAA,kBAAA,kCAAsBW,uBAAA,EAAA,EAAY,SAAA,EAAU,cAAA,EAAe,CAAA,kCAAMC,wBAAA,EAAA,EAAa,CAAA;AAAA,QAAG;AAAA,OAAA,EAEpF;AAAA,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAGF,EAAA,uBACER,eAAA,CAACS,mBAAA,EAAA,EAAU,SAAA,EAAsB,SAAA,EAC/B,QAAA,EAAA;AAAA,oBAAAZ,cAAA,CAACY,mBAAA,CAAU,MAAA,EAAV,EACE,QAAA,EAAA,aAAA,mBACCT,eAAA,CAAAU,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAAb,cAAA,CAACY,mBAAA,CAAU,OAAA,EAAV,EAAkB,QAAA,EAAA,gBAAA,EAAc,CAAA;AAAA,sBACjCZ,cAAA,CAACc,yBAAA,EAAA,EAAa,SAAA,EAAU,kBAAA,EAAoB,QAAA,EAAA,gBAAA,EAAiB;AAAA,KAAA,EAC/D,oBAEAX,eAAA,CAAAU,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAAV,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,oCAAA,EACb,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAACS,mBAAA,CAAU,SAAV,EAAkB,QAAA,EAAA;AAAA,UAAA,QAAA;AAAA,0CACV,GAAA,EAAA,EAAE,QAAA,EAAA;AAAA,YAAA,IAAA;AAAA,YAAGG,mCAAA,CAAe,SAAS,EAAE;AAAA,WAAA,EAAE;AAAA,SAAA,EAC1C,CAAA;AAAA,QACC,CAAC,aAAa,QAAA,oBACbf,cAAA;AAAA,UAACgB,yEAAA;AAAA,UAAA;AAAA,YACC,QAAA;AAAA,YACA,KAAA;AAAA,YACA,UAAA;AAAA,YACA;AAAA;AAAA;AACF,OAAA,EAEJ,CAAA;AAAA,sBACAb,eAAA,CAACW,yBAAA,EAAA,EAAa,SAAA,EAAU,6BAAA,EACrB,QAAA,EAAA;AAAA,QAAA,gBAAA;AAAA,QAAA,CACC,cAAc,MAAA,qBACdd,cAAA;AAAA,UAACY,mBAAA,CAAU,WAAA;AAAA,UAAV;AAAA,YACC,UAAA;AAAA,YACA,MAAA;AAAA,YACA,aAAA,EAAc,gBAAA;AAAA,YACd,SAAA,EAAU;AAAA;AAAA,SACZ;AAAA,wBAEFZ,cAAA,CAACY,mBAAA,CAAU,WAAA,EAAV,EAAsB,SAAS,OAAA,EAAS;AAAA,OAAA,EAC3C;AAAA,KAAA,EACF,CAAA,EAEJ,CAAA;AAAA,IAEC,CAAC,SAAA,oBACAZ,cAAA;AAAA,MAAC,iBAAA;AAAA,MAAA;AAAA,QACC,iBAAA;AAAA,QACA,aAAA;AAAA,QACA,cAAA,EAAgB,KAAA;AAAA,QAChB,YAAA,EAAc,cAAA;AAAA,QAEb,sCACCA,cAAA,CAACY,mBAAA,CAAU,WAAA,EAAV,EAAsB,8BAAgB,CAAA,GACrC,CAAC,KAAA,EAAO,MAAA,kCACTA,mBAAA,CAAU,MAAA,EAAV,EAAiB,QAAA,EAAA,gCAAA,EAA8B,KAE/C,MAAM;AACL,UAAA,MAAM,WAAA,mBACJT,eAAA,CAACS,mBAAA,CAAU,OAAA,EAAV,EACE,QAAA,EAAA;AAAA,YAAA,CAAC,iBACA,CAAC,eAAA,IACD,CAAC,mBAAA,IACD,CAAC,yBACD,0BAAA,oBACEZ,cAAA,CAACiB,iBAAO,OAAA,EAAQ,MAAA,EAAO,WAAU,MAAA,EAC/B,QAAA,kBAAAjB,cAAA,CAACiB,cAAO,OAAA,EAAP,EAAe,mHAGhB,CAAA,EACF,CAAA;AAAA,4BAMJjB,cAAA;AAAA,cAACkB,qDAAA;AAAA,cAAA;AAAA,gBACC,iBAAA;AAAA,gBACA,WAAA,EAAa,eAAA;AAAA,gBACb,cAAA;AAAA,gBACA,eAAA;AAAA,gBACA,kBAAA;AAAA,gBACA,eAAA;AAAA,gBACA,UAAA,EAAY,kBAAA;AAAA,gBACZ,WAAA,kBACElB,cAAA;AAAA,kBAACmB,iCAAA;AAAA,kBAAA;AAAA,oBACC,IAAA,EAAM,eAAA;AAAA,oBACN,KAAA,EAAM,cAAA;AAAA,oBACN,aAAA,EAAa,IAAA;AAAA,oBACb,WAAA,EAAY,iBAAA;AAAA,oBACZ,KAAA,EAAO,KAAA;AAAA,oBACP,QAAA,EAAU,CAAA,CAAA,KAAK,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,oBACtC,OAAA,EAAS,MAAM,QAAA,CAAS,EAAE,CAAA;AAAA,oBAC1B,IAAA,EAAK,IAAA;AAAA,oBACL,OAAA,EAAQ,SAAA;AAAA,oBACR,SAAA,EAAU;AAAA;AAAA;AACZ;AAAA,aAEJ;AAAA,YAEC,kBAAkB,MAAA,KAAW,CAAA,mCAAMP,mBAAA,CAAU,MAAA,EAAV,EAAiB,QAAA,EAAA,6BAAA,EAA2B;AAAA,WAAA,EAClF,CAAA;AAIF,UAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,eAAA,EAAiB,OAAO,WAAA;AAI/C,UAAA,uBACET,eAAA;AAAA,YAACiB,aAAA;AAAA,YAAA;AAAA,cACC,UAAA,EAAW,SAAA;AAAA,cACX,KAAA,EAAO,SAAA;AAAA,cACP,aAAA,EAAe,WAAA;AAAA,cACf,SAAA,EAAU,0CAAA;AAAA,cAGV,QAAA,EAAA;AAAA,gCAAApB,cAAA,CAACY,mBAAA,CAAU,MAAA,EAAV,EAAiB,SAAA,EAAU,MAAA,EAC1B,0CAACS,gBAAA,EAAA,EAAQ,OAAA,EAAQ,YAAA,EAAa,SAAA,EAAU,MAAA,EACtC,QAAA,EAAA;AAAA,kCAAArB,cAAA,CAACsB,WAAA,EAAA,EAAI,KAAA,EAAM,SAAA,EAAU,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,kBACzB,eAAA,oBACCnB,eAAA,CAACmB,WAAA,EAAA,EAAI,KAAA,EAAM,UAAA,EAAW,QAAA,EAAA;AAAA,oBAAA,UAAA;AAAA,oBAAS,gBAAA,IAAoB,wBAAQnB,eAAA,CAAAU,mBAAA,EAAA,EAAE,QAAA,EAAA;AAAA,sBAAA,IAAA;AAAA,sBAAG,gBAAA;AAAA,sBAAiB;AAAA,qBAAA,EAAC;AAAA,mBAAA,EAAI,CAAA;AAAA,kBAEvF,aAAA,oBACCV,eAAA,CAACmB,WAAA,EAAA,EAAI,KAAA,EAAM,QAAA,EAAS,QAAA,EAAA;AAAA,oBAAA,QAAA;AAAA,oBAAO,cAAA,IAAkB,wBAAQnB,eAAA,CAAAU,mBAAA,EAAA,EAAE,QAAA,EAAA;AAAA,sBAAA,IAAA;AAAA,sBAAG,cAAA;AAAA,sBAAe;AAAA,qBAAA,EAAC;AAAA,mBAAA,EAAI;AAAA,iBAAA,EAElF,CAAA,EACF,CAAA;AAAA,+CAECU,sBAAA,EAAA,EAAW,KAAA,EAAM,SAAA,EAAU,SAAA,EAAU,gBACnC,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,gBACC,mCACCvB,cAAA,CAACuB,sBAAA,EAAA,EAAW,KAAA,EAAM,UAAA,EAAW,WAAU,qBAAA,EACrC,QAAA,kBAAAvB,cAAA,CAACY,mBAAA,CAAU,OAAA,EAAV,EAAmB,QAAA,EAAA,eAAA,CAAgB,EAAE,OAAA,EAAS,GAAE,CAAA,EACnD,CAAA;AAAA,gBAED,iCACCZ,cAAA,CAACuB,sBAAA,EAAA,EAAW,OAAM,QAAA,EAAS,SAAA,EAAU,uBACnC,QAAA,kBAAAvB,cAAA,CAACY,mBAAA,CAAU,SAAV,EAAmB,QAAA,EAAA,aAAA,CAAc,EAAE,OAAA,EAAS,UAAA,EAAY,UAAU,MAAA,EAAQ,GAAE,CAAA,EAC/E;AAAA;AAAA;AAAA,WAEJ;AAAA,QAEJ,CAAA;AAAG;AAAA;AAEP,GAAA,EAEJ,CAAA;AAEJ;AAUA,SAAS,iBAAA,CAAkB;AAAA,EACzB,iBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAOG;AAGD,EAAA,MAAM,EAAE,GAAA,EAAK,YAAA,EAAa,GAAIY,wCAAiC,cAAc,CAAA;AAK7E,EAAA,MAAM,EAAE,GAAA,EAAK,gBAAA,EAAiB,GAAIC,yDAAA,CAA0C,gBAAgB,YAAY,CAAA;AAExG,EAAA,MAAM,UAAU,iBAAA,GACZ,aAAA,GACE,yBAAA,GACA,yBAAA,GACF,gBACE,yBAAA,GACA,yBAAA;AAEN,EAAA,uBACEtB,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,YAAA;AAAA,MACL,oBAAA,EAAkB,IAAA;AAAA,MAClB,SAAA,EAAWuB,WAAA,CAAG,iFAAA,EAAmF,OAAO,CAAA;AAAA,MAExG,QAAA,EAAA;AAAA,wBAAA1B,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW0B,WAAA;AAAA,cACT,+CAAA;AAAA,cACA,iBAAA,IAAqB;AAAA,aACvB;AAAA,YAEC,QAAA,EAAA;AAAA;AAAA,SACH;AAAA,wBACA1B,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+CAAA,EAAiD,QAAA,EAAS,CAAA;AAAA,wBAEzEA,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,gBAAA;AAAA,YACL,gBAAA,EAAc,IAAA;AAAA,YACd,SAAA,EAAW0B,WAAA;AAAA,cACT,+CAAA;AAAA,cACA,aAAA,IAAiB;AAAA,aACnB;AAAA,YAEC,QAAA,EAAA;AAAA;AAAA;AACH;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -19,6 +19,7 @@ import { T as TabContent } from '../../../tabs-content-CLgmU6S_.js';
19
19
  import { useScrollToFirstHighlight } from '../../../hooks/use-scroll-to-first-highlight.es.js';
20
20
  import { useTextHighlight } from '../../../hooks/use-text-highlight.es.js';
21
21
  import { truncateString } from '../../../utils/truncate-string.es.js';
22
+ import { c as cn } from '../../../cn-B4oPhFx9.js';
22
23
 
23
24
  function TraceDataPanelView({
24
25
  traceId,
@@ -46,9 +47,10 @@ function TraceDataPanelView({
46
47
  scoresTabBadge,
47
48
  feedbackTabSlot,
48
49
  feedbackTabBadge,
49
- partialThreadTabSlot,
50
50
  activeTab,
51
51
  onTabChange,
52
+ featuredSpanIds,
53
+ messagesPanelSlot,
52
54
  spanPanelSlot,
53
55
  className
54
56
  }) {
@@ -171,77 +173,86 @@ function TraceDataPanelView({
171
173
  /* @__PURE__ */ jsx(DataPanel.CloseButton, { onClick: onClose })
172
174
  ] })
173
175
  ] }) }),
174
- !collapsed && /* @__PURE__ */ jsx(SplitWithSpanPanel, { spanPanelSlot, highlightQuery: query, spanPanelKey: selectedSpanId, children: isLoading ? /* @__PURE__ */ jsx(DataPanel.LoadingData, { children: "Loading trace..." }) : !spans?.length ? /* @__PURE__ */ jsx(DataPanel.NoData, { children: "No spans found for this trace." }) : /* @__PURE__ */ jsx(DataPanel.Content, { children: (() => {
175
- const detailsBody = /* @__PURE__ */ jsxs(Fragment, { children: [
176
- !isOnTracePage && !onEvaluateTrace && !onSaveAsDatasetItem && !onAddTraceMocksToItem && showUnavailableFeaturesMsg && /* @__PURE__ */ jsx(Notice, { variant: "info", className: "mb-6", children: /* @__PURE__ */ jsx(Notice.Message, { children: "Evaluating traces and saving them as dataset items is available in Mastra Studio (local or deployed)." }) }),
177
- /* @__PURE__ */ jsx(
178
- TraceTimeline,
179
- {
180
- hierarchicalSpans,
181
- onSpanClick: handleSpanClick,
182
- selectedSpanId,
183
- expandedSpanIds,
184
- setExpandedSpanIds,
185
- chartWidth: timelineChartWidth,
186
- leadingSlot: /* @__PURE__ */ jsx(
187
- SearchFieldBlock,
176
+ !collapsed && /* @__PURE__ */ jsx(
177
+ TracePanelColumns,
178
+ {
179
+ messagesPanelSlot,
180
+ spanPanelSlot,
181
+ highlightQuery: query,
182
+ spanPanelKey: selectedSpanId,
183
+ children: isLoading ? /* @__PURE__ */ jsx(DataPanel.LoadingData, { children: "Loading trace..." }) : !spans?.length ? /* @__PURE__ */ jsx(DataPanel.NoData, { children: "No spans found for this trace." }) : (() => {
184
+ const detailsBody = /* @__PURE__ */ jsxs(DataPanel.Content, { children: [
185
+ !isOnTracePage && !onEvaluateTrace && !onSaveAsDatasetItem && !onAddTraceMocksToItem && showUnavailableFeaturesMsg && /* @__PURE__ */ jsx(Notice, { variant: "info", className: "mb-6", children: /* @__PURE__ */ jsx(Notice.Message, { children: "Evaluating traces and saving them as dataset items is available in Mastra Studio (local or deployed)." }) }),
186
+ /* @__PURE__ */ jsx(
187
+ TraceTimeline,
188
188
  {
189
- name: searchFieldName,
190
- label: "Search spans",
191
- labelIsHidden: true,
192
- placeholder: "Search spans...",
193
- value: query,
194
- onChange: (e) => setQuery(e.target.value),
195
- onReset: () => setQuery(""),
196
- size: "sm",
197
- variant: "outline",
198
- className: "w-full"
189
+ hierarchicalSpans,
190
+ onSpanClick: handleSpanClick,
191
+ selectedSpanId,
192
+ expandedSpanIds,
193
+ setExpandedSpanIds,
194
+ featuredSpanIds,
195
+ chartWidth: timelineChartWidth,
196
+ leadingSlot: /* @__PURE__ */ jsx(
197
+ SearchFieldBlock,
198
+ {
199
+ name: searchFieldName,
200
+ label: "Search spans",
201
+ labelIsHidden: true,
202
+ placeholder: "Search spans...",
203
+ value: query,
204
+ onChange: (e) => setQuery(e.target.value),
205
+ onReset: () => setQuery(""),
206
+ size: "sm",
207
+ variant: "outline",
208
+ className: "w-full"
209
+ }
210
+ )
199
211
  }
200
- )
201
- }
202
- ),
203
- hierarchicalSpans.length === 0 && /* @__PURE__ */ jsx(DataPanel.NoData, { children: "No spans match your search." })
204
- ] });
205
- if (!partialThreadTabSlot && !scoresTabSlot && !feedbackTabSlot) return detailsBody;
206
- return /* @__PURE__ */ jsxs(
207
- Tabs,
208
- {
209
- defaultTab: "details",
210
- value: activeTab,
211
- onValueChange: onTabChange,
212
- className: activeTab === "partial-thread" || activeTab === "scores" || activeTab === "feedback" ? "grid h-full min-h-0 grid-rows-[auto_1fr]" : void 0,
213
- children: [
214
- /* @__PURE__ */ jsxs(TabList, { variant: "pill-ghost", className: "px-0", children: [
215
- /* @__PURE__ */ jsx(Tab, { value: "details", children: "Spans" }),
216
- partialThreadTabSlot && /* @__PURE__ */ jsx(Tab, { value: "partial-thread", children: "Messages" }),
217
- feedbackTabSlot && /* @__PURE__ */ jsxs(Tab, { value: "feedback", children: [
218
- "Feedback",
219
- feedbackTabBadge != null && /* @__PURE__ */ jsxs(Fragment, { children: [
220
- " (",
221
- feedbackTabBadge,
222
- ")"
223
- ] })
224
- ] }),
225
- scoresTabSlot && /* @__PURE__ */ jsxs(Tab, { value: "scores", children: [
226
- "Scores",
227
- scoresTabBadge != null && /* @__PURE__ */ jsxs(Fragment, { children: [
228
- " (",
229
- scoresTabBadge,
230
- ")"
231
- ] })
232
- ] })
233
- ] }),
234
- /* @__PURE__ */ jsx(TabContent, { value: "details", children: detailsBody }),
235
- partialThreadTabSlot && /* @__PURE__ */ jsx(TabContent, { value: "partial-thread", className: "h-full min-h-0", children: partialThreadTabSlot({ traceId }) }),
236
- feedbackTabSlot && /* @__PURE__ */ jsx(TabContent, { value: "feedback", className: "h-full min-h-0", children: feedbackTabSlot({ traceId }) }),
237
- scoresTabSlot && /* @__PURE__ */ jsx(TabContent, { value: "scores", className: "h-full min-h-0", children: scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId }) })
238
- ]
239
- }
240
- );
241
- })() }) })
212
+ ),
213
+ hierarchicalSpans.length === 0 && /* @__PURE__ */ jsx(DataPanel.NoData, { children: "No spans match your search." })
214
+ ] });
215
+ if (!scoresTabSlot && !feedbackTabSlot) return detailsBody;
216
+ return /* @__PURE__ */ jsxs(
217
+ Tabs,
218
+ {
219
+ defaultTab: "details",
220
+ value: activeTab,
221
+ onValueChange: onTabChange,
222
+ className: "grid h-full min-h-0 grid-rows-[auto_1fr]",
223
+ children: [
224
+ /* @__PURE__ */ jsx(DataPanel.Header, { className: "py-2", children: /* @__PURE__ */ jsxs(TabList, { variant: "pill-ghost", className: "px-0", children: [
225
+ /* @__PURE__ */ jsx(Tab, { value: "details", children: "Spans" }),
226
+ feedbackTabSlot && /* @__PURE__ */ jsxs(Tab, { value: "feedback", children: [
227
+ "Feedback",
228
+ feedbackTabBadge != null && /* @__PURE__ */ jsxs(Fragment, { children: [
229
+ " (",
230
+ feedbackTabBadge,
231
+ ")"
232
+ ] })
233
+ ] }),
234
+ scoresTabSlot && /* @__PURE__ */ jsxs(Tab, { value: "scores", children: [
235
+ "Scores",
236
+ scoresTabBadge != null && /* @__PURE__ */ jsxs(Fragment, { children: [
237
+ " (",
238
+ scoresTabBadge,
239
+ ")"
240
+ ] })
241
+ ] })
242
+ ] }) }),
243
+ /* @__PURE__ */ jsx(TabContent, { value: "details", className: "min-h-0 py-0", children: detailsBody }),
244
+ feedbackTabSlot && /* @__PURE__ */ jsx(TabContent, { value: "feedback", className: "h-full min-h-0 py-0", children: /* @__PURE__ */ jsx(DataPanel.Content, { children: feedbackTabSlot({ traceId }) }) }),
245
+ scoresTabSlot && /* @__PURE__ */ jsx(TabContent, { value: "scores", className: "h-full min-h-0 py-0", children: /* @__PURE__ */ jsx(DataPanel.Content, { children: scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId }) }) })
246
+ ]
247
+ }
248
+ );
249
+ })()
250
+ }
251
+ )
242
252
  ] });
243
253
  }
244
- function SplitWithSpanPanel({
254
+ function TracePanelColumns({
255
+ messagesPanelSlot,
245
256
  spanPanelSlot,
246
257
  highlightQuery,
247
258
  spanPanelKey,
@@ -249,21 +260,40 @@ function SplitWithSpanPanel({
249
260
  }) {
250
261
  const { ref: highlightRef } = useTextHighlight(highlightQuery);
251
262
  const { ref: scrollToMatchRef } = useScrollToFirstHighlight(highlightQuery, spanPanelKey);
252
- if (!spanPanelSlot) {
253
- return /* @__PURE__ */ jsx("div", { ref: highlightRef, className: "flex min-h-0 flex-1 flex-col overflow-hidden", children });
254
- }
255
- return /* @__PURE__ */ jsxs("div", { ref: highlightRef, className: "grid min-h-0 flex-1 grid-cols-[1fr_1fr]", children: [
256
- /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-col overflow-hidden", children }),
257
- /* @__PURE__ */ jsx(
258
- "div",
259
- {
260
- ref: scrollToMatchRef,
261
- "data-highlight": true,
262
- className: "animate-in border-border1 fade-in-0 flex min-h-0 flex-col overflow-hidden border-l duration-300",
263
- children: spanPanelSlot
264
- }
265
- )
266
- ] });
263
+ const columns = messagesPanelSlot ? spanPanelSlot ? "grid-cols-[1fr_1fr_1fr]" : "grid-cols-[1fr_1fr_0fr]" : spanPanelSlot ? "grid-cols-[0fr_1fr_1fr]" : "grid-cols-[0fr_1fr_0fr]";
264
+ return /* @__PURE__ */ jsxs(
265
+ "div",
266
+ {
267
+ ref: highlightRef,
268
+ "data-trace-columns": true,
269
+ className: cn("grid min-h-0 flex-1 transition-[grid-template-columns] duration-300 ease-in-out", columns),
270
+ children: [
271
+ /* @__PURE__ */ jsx(
272
+ "div",
273
+ {
274
+ className: cn(
275
+ "flex min-h-0 min-w-0 flex-col overflow-hidden",
276
+ messagesPanelSlot && "animate-in border-r border-border1 duration-300 fade-in-0"
277
+ ),
278
+ children: messagesPanelSlot
279
+ }
280
+ ),
281
+ /* @__PURE__ */ jsx("div", { className: "flex min-h-0 min-w-0 flex-col overflow-hidden", children }),
282
+ /* @__PURE__ */ jsx(
283
+ "div",
284
+ {
285
+ ref: scrollToMatchRef,
286
+ "data-highlight": true,
287
+ className: cn(
288
+ "flex min-h-0 min-w-0 flex-col overflow-hidden",
289
+ spanPanelSlot && "animate-in border-l border-border1 duration-300 fade-in-0"
290
+ ),
291
+ children: spanPanelSlot
292
+ }
293
+ )
294
+ ]
295
+ }
296
+ );
267
297
  }
268
298
 
269
299
  export { TraceDataPanelView };
@@ -1 +1 @@
1
- {"version":3,"file":"trace-data-panel-view.es.js","sources":["../../../../src/domains/traces/components/trace-data-panel-view.tsx"],"sourcesContent":["import {\n CircleGaugeIcon,\n ChevronsDownUpIcon,\n ChevronsUpDownIcon,\n DownloadIcon,\n Link2Icon,\n Loader2Icon,\n MoreHorizontalIcon,\n SaveIcon,\n WrenchIcon,\n} from 'lucide-react';\nimport { useEffect, useId, useMemo, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { getAllSpanIds } from '../hooks/get-all-span-ids';\nimport { useDownloadTraceJson } from '../hooks/use-download-trace-json';\nimport { useTraceSearch } from '../hooks/use-trace-search';\nimport type { TraceUsageSummary } from '../trace-list-columns';\nimport type { SearchableSpan } from '../types';\nimport { formatHierarchicalSpans } from './format-hierarchical-spans';\nimport { TraceSummaryDescription } from './trace-summary-description';\nimport { TraceTimeline } from './trace-timeline';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DataPanel } from '@/ds/components/DataPanel';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { SearchFieldBlock } from '@/ds/components/FormFieldBlocks';\nimport { Notice } from '@/ds/components/Notice';\nimport { Tab, TabContent, TabList, Tabs } from '@/ds/components/Tabs';\nimport type { LinkComponent } from '@/ds/types/link-component';\nimport { useScrollToFirstHighlight } from '@/hooks/use-scroll-to-first-highlight';\nimport { useTextHighlight } from '@/hooks/use-text-highlight';\nimport { truncateString } from '@/lib/truncate-string';\n\nexport type TraceDataPanelPlacement = 'traces-list' | 'trace-page';\n\nexport type TraceDataPanelTab = 'details' | 'partial-thread' | 'scores' | 'feedback';\n\nexport interface TraceDataPanelViewProps {\n traceId: string;\n /** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */\n spans: SearchableSpan[] | undefined;\n isLoading?: boolean;\n onClose: () => void;\n onSpanSelect?: (spanId: string | undefined) => void;\n onEvaluateTrace?: () => void;\n /** When set, an \"Add full trace to dataset\" button appears; the consumer owns the dialog. */\n onSaveAsDatasetItem?: (args: { traceId: string; rootSpanId: string | undefined }) => void;\n /** When set, an \"Add tool mocks to item\" button appears; the consumer owns the dialog. */\n onAddTraceMocksToItem?: (args: { traceId: string }) => void;\n initialSpanId?: string | null;\n onPrevious?: () => void;\n onNext?: () => void;\n collapsed?: boolean;\n onCollapsedChange?: (collapsed: boolean) => void;\n placement: TraceDataPanelPlacement;\n timelineChartWidth?: 'wide' | 'default';\n /** When both are provided, renders an \"Open trace page\" button. */\n LinkComponent?: LinkComponent;\n traceHref?: string;\n /** When provided, the entity name in the trace summary links to the entity's page. */\n entityHref?: string;\n /** Token and estimated-cost totals shown in the compact trace summary. */\n usage?: TraceUsageSummary;\n /**\n * Span treated as the displayed root of the timeline. Required for branch\n * subtrees from `getBranch` where the anchor has a real parent that's outside\n * `spans`. When omitted, the span with no parent is used (trace case).\n */\n anchorSpanId?: string;\n /**\n * Whether to render the \"Evaluating traces and saving them as dataset items is\n * available in Mastra Studio\" info notice when neither `onEvaluateTrace` nor\n * `onSaveAsDatasetItem` is provided. Defaults to `true`. Pass `false` when this\n * panel is rendered inside Studio in a context that intentionally omits those\n * handlers (e.g. inline below an experiment result).\n */\n showUnavailableFeaturesMsg?: boolean;\n /**\n * When provided, the panel content becomes tabbed (\"Details\" / \"Scores\"); the slot\n * renders whatever trace-level scoring UI the consumer wants.\n */\n scoresTabSlot?: (args: { traceId: string; rootSpanId: string | undefined }) => ReactNode;\n /** Optional count shown in the \"Scores\" tab label. */\n scoresTabBadge?: ReactNode;\n /**\n * When provided, a \"Feedback\" tab appears; the slot renders the trace-level\n * feedback UI. Trace feedback is not scoped to a span — the span panel owns that.\n */\n feedbackTabSlot?: (args: { traceId: string }) => ReactNode;\n /** Optional count shown in the \"Feedback\" tab label. */\n feedbackTabBadge?: ReactNode;\n /** When provided, a \"Messages\" tab renders the trace as one reconstructed agent turn. */\n partialThreadTabSlot?: (args: { traceId: string }) => ReactNode;\n activeTab?: TraceDataPanelTab;\n onTabChange?: (tab: TraceDataPanelTab) => void;\n /**\n * When provided, the panel splits into two columns inside the same card: the\n * trace content on the left, this slot (typically the span detail) on the right.\n */\n spanPanelSlot?: ReactNode;\n /** Extra classes applied to the panel root (e.g. `h-full` on the trace page). */\n className?: string;\n}\n\nexport function TraceDataPanelView({\n traceId,\n spans,\n isLoading,\n onClose,\n onSpanSelect,\n onEvaluateTrace,\n onSaveAsDatasetItem,\n onAddTraceMocksToItem,\n initialSpanId,\n onPrevious,\n onNext,\n collapsed: controlledCollapsed,\n onCollapsedChange,\n placement,\n timelineChartWidth = 'default',\n LinkComponent,\n traceHref,\n entityHref,\n usage,\n anchorSpanId,\n showUnavailableFeaturesMsg = true,\n scoresTabSlot,\n scoresTabBadge,\n feedbackTabSlot,\n feedbackTabBadge,\n partialThreadTabSlot,\n activeTab,\n onTabChange,\n spanPanelSlot,\n className,\n}: TraceDataPanelViewProps) {\n const isOnTracePage = placement === 'trace-page';\n const [internalCollapsed, setInternalCollapsed] = useState(false);\n const collapsed = controlledCollapsed ?? internalCollapsed;\n const setCollapsed = onCollapsedChange ?? setInternalCollapsed;\n\n const { download: downloadTraceJson, isPending: isDownloadingTrace } = useDownloadTraceJson();\n\n const [selectedSpanId, setSelectedSpanId] = useState<string | undefined>(initialSpanId ?? undefined);\n\n // Sync selected span when initialSpanId or trace data changes\n useEffect(() => {\n // No span requested: clear immediately.\n if (!initialSpanId) {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n return;\n }\n // Span requested: wait for trace data before deciding so an in-flight\n // fetch doesn't wipe a URL-provided selection. Callers that default their\n // spans to `[]` while loading only say so through `isLoading`.\n if (isLoading || !spans) return;\n\n const found = spans.find(s => s.spanId === initialSpanId);\n if (found) {\n setSelectedSpanId(initialSpanId);\n onSpanSelect?.(initialSpanId);\n } else {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialSpanId, spans, isLoading]);\n\n const searchFieldName = useId();\n const { query, setQuery, results, payloadOnlyMatchIds } = useTraceSearch(spans ?? []);\n\n const hierarchicalSpans = useMemo(\n () =>\n formatHierarchicalSpans(\n // Carried on the span rather than drilled as a prop: the tree is rebuilt here and\n // rendered several components deeper.\n results.map(span => ({ ...span, matchedInPayloadOnly: payloadOnlyMatchIds.has(span.spanId) })),\n anchorSpanId,\n ),\n [results, payloadOnlyMatchIds, anchorSpanId],\n );\n\n const [expandedSpanIds, setExpandedSpanIds] = useState<string[]>([]);\n\n useEffect(() => {\n if (hierarchicalSpans.length > 0) {\n setExpandedSpanIds(getAllSpanIds(hierarchicalSpans));\n }\n }, [hierarchicalSpans]);\n\n const rootSpan = useMemo(\n () => (anchorSpanId ? spans?.find(s => s.spanId === anchorSpanId) : spans?.find(s => s.parentSpanId == null)),\n [spans, anchorSpanId],\n );\n const handleSpanClick = (id: string) => {\n const newId = selectedSpanId === id ? undefined : id;\n setSelectedSpanId(newId);\n onSpanSelect?.(newId);\n };\n\n const traceActionsMenu = (\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button size=\"md\" tooltip=\"Trace actions\" aria-label=\"Trace actions\">\n <MoreHorizontalIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\">\n {!isOnTracePage && onCollapsedChange && (\n <DropdownMenu.Item onSelect={() => setCollapsed(!collapsed)}>\n {collapsed ? <ChevronsUpDownIcon /> : <ChevronsDownUpIcon />}\n {collapsed ? 'Expand panel' : 'Collapse panel'}\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onEvaluateTrace && (\n <DropdownMenu.Item onSelect={onEvaluateTrace}>\n <CircleGaugeIcon />\n Evaluate trace\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onSaveAsDatasetItem && (\n <DropdownMenu.Item onSelect={() => onSaveAsDatasetItem({ traceId, rootSpanId: rootSpan?.spanId })}>\n <SaveIcon />\n Add full trace to dataset\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onAddTraceMocksToItem && (\n <DropdownMenu.Item onSelect={() => onAddTraceMocksToItem({ traceId })}>\n <WrenchIcon />\n Add tool mocks to item\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && LinkComponent && traceHref && (\n <DropdownMenu.Item render={<LinkComponent href={traceHref} />}>\n <Link2Icon />\n Open trace page\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item disabled={isDownloadingTrace} onSelect={() => downloadTraceJson(traceId)}>\n {isDownloadingTrace ? <Loader2Icon className=\"animate-spin\" /> : <DownloadIcon />}\n Download trace JSON\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n );\n\n return (\n <DataPanel collapsed={collapsed} className={className}>\n <DataPanel.Header>\n {isOnTracePage ? (\n <>\n <DataPanel.Heading>Trace Timeline</DataPanel.Heading>\n <ButtonsGroup className=\"ml-auto shrink-0\">{traceActionsMenu}</ButtonsGroup>\n </>\n ) : (\n <>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <DataPanel.Heading>\n Trace <b># {truncateString(traceId, 12)}</b>\n </DataPanel.Heading>\n {!collapsed && rootSpan && (\n <TraceSummaryDescription\n rootSpan={rootSpan}\n usage={usage}\n entityHref={entityHref}\n LinkComponent={LinkComponent}\n />\n )}\n </div>\n <ButtonsGroup className=\"ml-auto shrink-0 self-start\">\n {traceActionsMenu}\n {(onPrevious || onNext) && (\n <DataPanel.NextPrevNav\n onPrevious={onPrevious}\n onNext={onNext}\n previousLabel=\"Previous trace\"\n nextLabel=\"Next trace\"\n />\n )}\n <DataPanel.CloseButton onClick={onClose} />\n </ButtonsGroup>\n </>\n )}\n </DataPanel.Header>\n\n {!collapsed && (\n <SplitWithSpanPanel spanPanelSlot={spanPanelSlot} highlightQuery={query} spanPanelKey={selectedSpanId}>\n {isLoading ? (\n <DataPanel.LoadingData>Loading trace...</DataPanel.LoadingData>\n ) : !spans?.length ? (\n <DataPanel.NoData>No spans found for this trace.</DataPanel.NoData>\n ) : (\n <DataPanel.Content>\n {(() => {\n const detailsBody = (\n <>\n {!isOnTracePage &&\n !onEvaluateTrace &&\n !onSaveAsDatasetItem &&\n !onAddTraceMocksToItem &&\n showUnavailableFeaturesMsg && (\n <Notice variant=\"info\" className=\"mb-6\">\n <Notice.Message>\n Evaluating traces and saving them as dataset items is available in Mastra Studio (local or\n deployed).\n </Notice.Message>\n </Notice>\n )}\n\n {/* The timeline stays mounted even with no results, because it\n hosts the search field: unmounting it would strand the user\n with a query they can no longer clear. */}\n <TraceTimeline\n hierarchicalSpans={hierarchicalSpans}\n onSpanClick={handleSpanClick}\n selectedSpanId={selectedSpanId}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n chartWidth={timelineChartWidth}\n leadingSlot={\n <SearchFieldBlock\n name={searchFieldName}\n label=\"Search spans\"\n labelIsHidden\n placeholder=\"Search spans...\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n onReset={() => setQuery('')}\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n />\n }\n />\n\n {hierarchicalSpans.length === 0 && <DataPanel.NoData>No spans match your search.</DataPanel.NoData>}\n </>\n );\n\n // No extra tab slots → render details directly without the Tabs wrapper.\n if (!partialThreadTabSlot && !scoresTabSlot && !feedbackTabSlot) return detailsBody;\n\n return (\n <Tabs<TraceDataPanelTab>\n defaultTab=\"details\"\n value={activeTab}\n onValueChange={onTabChange}\n className={\n activeTab === 'partial-thread' || activeTab === 'scores' || activeTab === 'feedback'\n ? 'grid h-full min-h-0 grid-rows-[auto_1fr]'\n : undefined\n }\n >\n <TabList variant=\"pill-ghost\" className=\"px-0\">\n <Tab value=\"details\">Spans</Tab>\n {partialThreadTabSlot && <Tab value=\"partial-thread\">Messages</Tab>}\n {feedbackTabSlot && (\n <Tab value=\"feedback\">Feedback{feedbackTabBadge != null && <> ({feedbackTabBadge})</>}</Tab>\n )}\n {scoresTabSlot && (\n <Tab value=\"scores\">Scores{scoresTabBadge != null && <> ({scoresTabBadge})</>}</Tab>\n )}\n </TabList>\n\n <TabContent value=\"details\">{detailsBody}</TabContent>\n {partialThreadTabSlot && (\n <TabContent value=\"partial-thread\" className=\"h-full min-h-0\">\n {partialThreadTabSlot({ traceId })}\n </TabContent>\n )}\n {feedbackTabSlot && (\n <TabContent value=\"feedback\" className=\"h-full min-h-0\">\n {feedbackTabSlot({ traceId })}\n </TabContent>\n )}\n {scoresTabSlot && (\n <TabContent value=\"scores\" className=\"h-full min-h-0\">\n {scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId })}\n </TabContent>\n )}\n </Tabs>\n );\n })()}\n </DataPanel.Content>\n )}\n </SplitWithSpanPanel>\n )}\n </DataPanel>\n );\n}\n\n/**\n * Renders the trace content as-is, or — when a span panel is provided — as a\n * two-column split inside the same card, with the span detail on the right.\n * Search matches — span names in the timeline tree as well as values in the span\n * detail — are highlighted while a query is active.\n */\nfunction SplitWithSpanPanel({\n spanPanelSlot,\n highlightQuery,\n spanPanelKey,\n children,\n}: {\n spanPanelSlot?: ReactNode;\n highlightQuery: string;\n /** Identity of the span shown in the panel; changing it re-triggers the match scroll. */\n spanPanelKey?: string;\n children: ReactNode;\n}) {\n // A single hook call on the common ancestor covers both the timeline tree and\n // the span detail, so span names and payload values highlight together.\n const { ref: highlightRef } = useTextHighlight<HTMLDivElement>(highlightQuery);\n\n // Scoped to the span-panel column only: a match deep in a large payload sits below\n // the fold, so the first painted match is brought into view when the panel opens.\n // The timeline column must never be scrolled by this.\n const { ref: scrollToMatchRef } = useScrollToFirstHighlight<HTMLDivElement>(highlightQuery, spanPanelKey);\n\n if (!spanPanelSlot) {\n return (\n <div ref={highlightRef} className=\"flex min-h-0 flex-1 flex-col overflow-hidden\">\n {children}\n </div>\n );\n }\n\n return (\n <div ref={highlightRef} className=\"grid min-h-0 flex-1 grid-cols-[1fr_1fr]\">\n <div className=\"flex min-h-0 flex-col overflow-hidden\">{children}</div>\n {/* Searchable: the span detail is where a match hides inside a large payload. */}\n <div\n ref={scrollToMatchRef}\n data-highlight\n className=\"animate-in border-border1 fade-in-0 flex min-h-0 flex-col overflow-hidden border-l duration-300\"\n >\n {spanPanelSlot}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trace-data-panel-view.es.js","sources":["../../../../src/domains/traces/components/trace-data-panel-view.tsx"],"sourcesContent":["import {\n CircleGaugeIcon,\n ChevronsDownUpIcon,\n ChevronsUpDownIcon,\n DownloadIcon,\n Link2Icon,\n Loader2Icon,\n MoreHorizontalIcon,\n SaveIcon,\n WrenchIcon,\n} from 'lucide-react';\nimport { useEffect, useId, useMemo, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { getAllSpanIds } from '../hooks/get-all-span-ids';\nimport { useDownloadTraceJson } from '../hooks/use-download-trace-json';\nimport { useTraceSearch } from '../hooks/use-trace-search';\nimport type { TraceUsageSummary } from '../trace-list-columns';\nimport type { SearchableSpan } from '../types';\nimport { formatHierarchicalSpans } from './format-hierarchical-spans';\nimport { TraceSummaryDescription } from './trace-summary-description';\nimport { TraceTimeline } from './trace-timeline';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DataPanel } from '@/ds/components/DataPanel';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { SearchFieldBlock } from '@/ds/components/FormFieldBlocks';\nimport { Notice } from '@/ds/components/Notice';\nimport { Tab, TabContent, TabList, Tabs } from '@/ds/components/Tabs';\nimport type { LinkComponent } from '@/ds/types/link-component';\nimport { useScrollToFirstHighlight } from '@/hooks/use-scroll-to-first-highlight';\nimport { useTextHighlight } from '@/hooks/use-text-highlight';\nimport { truncateString } from '@/lib/truncate-string';\nimport { cn } from '@/lib/utils';\n\nexport type TraceDataPanelPlacement = 'traces-list' | 'trace-page';\n\nexport type TraceDataPanelTab = 'details' | 'scores' | 'feedback';\n\nexport interface TraceDataPanelViewProps {\n traceId: string;\n /** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */\n spans: SearchableSpan[] | undefined;\n isLoading?: boolean;\n onClose: () => void;\n onSpanSelect?: (spanId: string | undefined) => void;\n onEvaluateTrace?: () => void;\n /** When set, an \"Add full trace to dataset\" button appears; the consumer owns the dialog. */\n onSaveAsDatasetItem?: (args: { traceId: string; rootSpanId: string | undefined }) => void;\n /** When set, an \"Add tool mocks to item\" button appears; the consumer owns the dialog. */\n onAddTraceMocksToItem?: (args: { traceId: string }) => void;\n initialSpanId?: string | null;\n onPrevious?: () => void;\n onNext?: () => void;\n collapsed?: boolean;\n onCollapsedChange?: (collapsed: boolean) => void;\n placement: TraceDataPanelPlacement;\n timelineChartWidth?: 'wide' | 'default';\n /** When both are provided, renders an \"Open trace page\" button. */\n LinkComponent?: LinkComponent;\n traceHref?: string;\n /** When provided, the entity name in the trace summary links to the entity's page. */\n entityHref?: string;\n /** Token and estimated-cost totals shown in the compact trace summary. */\n usage?: TraceUsageSummary;\n /**\n * Span treated as the displayed root of the timeline. Required for branch\n * subtrees from `getBranch` where the anchor has a real parent that's outside\n * `spans`. When omitted, the span with no parent is used (trace case).\n */\n anchorSpanId?: string;\n /**\n * Whether to render the \"Evaluating traces and saving them as dataset items is\n * available in Mastra Studio\" info notice when neither `onEvaluateTrace` nor\n * `onSaveAsDatasetItem` is provided. Defaults to `true`. Pass `false` when this\n * panel is rendered inside Studio in a context that intentionally omits those\n * handlers (e.g. inline below an experiment result).\n */\n showUnavailableFeaturesMsg?: boolean;\n /**\n * When provided, the panel content becomes tabbed (\"Details\" / \"Scores\"); the slot\n * renders whatever trace-level scoring UI the consumer wants.\n */\n scoresTabSlot?: (args: { traceId: string; rootSpanId: string | undefined }) => ReactNode;\n /** Optional count shown in the \"Scores\" tab label. */\n scoresTabBadge?: ReactNode;\n /**\n * When provided, a \"Feedback\" tab appears; the slot renders the trace-level\n * feedback UI. Trace feedback is not scoped to a span — the span panel owns that.\n */\n feedbackTabSlot?: (args: { traceId: string }) => ReactNode;\n /** Optional count shown in the \"Feedback\" tab label. */\n feedbackTabBadge?: ReactNode;\n activeTab?: TraceDataPanelTab;\n onTabChange?: (tab: TraceDataPanelTab) => void;\n /** Span ids to feature in the timeline; every other span is faded. */\n featuredSpanIds?: string[];\n /**\n * Rendered as a column to the left of the timeline inside the same card;\n * typically the reconstructed agent turn (\"Messages\").\n */\n messagesPanelSlot?: ReactNode;\n /**\n * Rendered as a column to the right of the timeline inside the same card;\n * typically the span detail.\n */\n spanPanelSlot?: ReactNode;\n /** Extra classes applied to the panel root (e.g. `h-full` on the trace page). */\n className?: string;\n}\n\nexport function TraceDataPanelView({\n traceId,\n spans,\n isLoading,\n onClose,\n onSpanSelect,\n onEvaluateTrace,\n onSaveAsDatasetItem,\n onAddTraceMocksToItem,\n initialSpanId,\n onPrevious,\n onNext,\n collapsed: controlledCollapsed,\n onCollapsedChange,\n placement,\n timelineChartWidth = 'default',\n LinkComponent,\n traceHref,\n entityHref,\n usage,\n anchorSpanId,\n showUnavailableFeaturesMsg = true,\n scoresTabSlot,\n scoresTabBadge,\n feedbackTabSlot,\n feedbackTabBadge,\n activeTab,\n onTabChange,\n featuredSpanIds,\n messagesPanelSlot,\n spanPanelSlot,\n className,\n}: TraceDataPanelViewProps) {\n const isOnTracePage = placement === 'trace-page';\n const [internalCollapsed, setInternalCollapsed] = useState(false);\n const collapsed = controlledCollapsed ?? internalCollapsed;\n const setCollapsed = onCollapsedChange ?? setInternalCollapsed;\n\n const { download: downloadTraceJson, isPending: isDownloadingTrace } = useDownloadTraceJson();\n\n const [selectedSpanId, setSelectedSpanId] = useState<string | undefined>(initialSpanId ?? undefined);\n\n // Sync selected span when initialSpanId or trace data changes\n useEffect(() => {\n // No span requested: clear immediately.\n if (!initialSpanId) {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n return;\n }\n // Span requested: wait for trace data before deciding so an in-flight\n // fetch doesn't wipe a URL-provided selection. Callers that default their\n // spans to `[]` while loading only say so through `isLoading`.\n if (isLoading || !spans) return;\n\n const found = spans.find(s => s.spanId === initialSpanId);\n if (found) {\n setSelectedSpanId(initialSpanId);\n onSpanSelect?.(initialSpanId);\n } else {\n setSelectedSpanId(undefined);\n onSpanSelect?.(undefined);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialSpanId, spans, isLoading]);\n\n const searchFieldName = useId();\n const { query, setQuery, results, payloadOnlyMatchIds } = useTraceSearch(spans ?? []);\n\n const hierarchicalSpans = useMemo(\n () =>\n formatHierarchicalSpans(\n // Carried on the span rather than drilled as a prop: the tree is rebuilt here and\n // rendered several components deeper.\n results.map(span => ({ ...span, matchedInPayloadOnly: payloadOnlyMatchIds.has(span.spanId) })),\n anchorSpanId,\n ),\n [results, payloadOnlyMatchIds, anchorSpanId],\n );\n\n const [expandedSpanIds, setExpandedSpanIds] = useState<string[]>([]);\n\n useEffect(() => {\n if (hierarchicalSpans.length > 0) {\n setExpandedSpanIds(getAllSpanIds(hierarchicalSpans));\n }\n }, [hierarchicalSpans]);\n\n const rootSpan = useMemo(\n () => (anchorSpanId ? spans?.find(s => s.spanId === anchorSpanId) : spans?.find(s => s.parentSpanId == null)),\n [spans, anchorSpanId],\n );\n const handleSpanClick = (id: string) => {\n const newId = selectedSpanId === id ? undefined : id;\n setSelectedSpanId(newId);\n onSpanSelect?.(newId);\n };\n\n const traceActionsMenu = (\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button size=\"md\" tooltip=\"Trace actions\" aria-label=\"Trace actions\">\n <MoreHorizontalIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\">\n {!isOnTracePage && onCollapsedChange && (\n <DropdownMenu.Item onSelect={() => setCollapsed(!collapsed)}>\n {collapsed ? <ChevronsUpDownIcon /> : <ChevronsDownUpIcon />}\n {collapsed ? 'Expand panel' : 'Collapse panel'}\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onEvaluateTrace && (\n <DropdownMenu.Item onSelect={onEvaluateTrace}>\n <CircleGaugeIcon />\n Evaluate trace\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onSaveAsDatasetItem && (\n <DropdownMenu.Item onSelect={() => onSaveAsDatasetItem({ traceId, rootSpanId: rootSpan?.spanId })}>\n <SaveIcon />\n Add full trace to dataset\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && onAddTraceMocksToItem && (\n <DropdownMenu.Item onSelect={() => onAddTraceMocksToItem({ traceId })}>\n <WrenchIcon />\n Add tool mocks to item\n </DropdownMenu.Item>\n )}\n {!isOnTracePage && LinkComponent && traceHref && (\n <DropdownMenu.Item render={<LinkComponent href={traceHref} />}>\n <Link2Icon />\n Open trace page\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item disabled={isDownloadingTrace} onSelect={() => downloadTraceJson(traceId)}>\n {isDownloadingTrace ? <Loader2Icon className=\"animate-spin\" /> : <DownloadIcon />}\n Download trace JSON\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n );\n\n return (\n <DataPanel collapsed={collapsed} className={className}>\n <DataPanel.Header>\n {isOnTracePage ? (\n <>\n <DataPanel.Heading>Trace Timeline</DataPanel.Heading>\n <ButtonsGroup className=\"ml-auto shrink-0\">{traceActionsMenu}</ButtonsGroup>\n </>\n ) : (\n <>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <DataPanel.Heading>\n Trace <b># {truncateString(traceId, 12)}</b>\n </DataPanel.Heading>\n {!collapsed && rootSpan && (\n <TraceSummaryDescription\n rootSpan={rootSpan}\n usage={usage}\n entityHref={entityHref}\n LinkComponent={LinkComponent}\n />\n )}\n </div>\n <ButtonsGroup className=\"ml-auto shrink-0 self-start\">\n {traceActionsMenu}\n {(onPrevious || onNext) && (\n <DataPanel.NextPrevNav\n onPrevious={onPrevious}\n onNext={onNext}\n previousLabel=\"Previous trace\"\n nextLabel=\"Next trace\"\n />\n )}\n <DataPanel.CloseButton onClick={onClose} />\n </ButtonsGroup>\n </>\n )}\n </DataPanel.Header>\n\n {!collapsed && (\n <TracePanelColumns\n messagesPanelSlot={messagesPanelSlot}\n spanPanelSlot={spanPanelSlot}\n highlightQuery={query}\n spanPanelKey={selectedSpanId}\n >\n {isLoading ? (\n <DataPanel.LoadingData>Loading trace...</DataPanel.LoadingData>\n ) : !spans?.length ? (\n <DataPanel.NoData>No spans found for this trace.</DataPanel.NoData>\n ) : (\n (() => {\n const detailsBody = (\n <DataPanel.Content>\n {!isOnTracePage &&\n !onEvaluateTrace &&\n !onSaveAsDatasetItem &&\n !onAddTraceMocksToItem &&\n showUnavailableFeaturesMsg && (\n <Notice variant=\"info\" className=\"mb-6\">\n <Notice.Message>\n Evaluating traces and saving them as dataset items is available in Mastra Studio (local or\n deployed).\n </Notice.Message>\n </Notice>\n )}\n\n {/* The timeline stays mounted even with no results, because it\n hosts the search field: unmounting it would strand the user\n with a query they can no longer clear. */}\n <TraceTimeline\n hierarchicalSpans={hierarchicalSpans}\n onSpanClick={handleSpanClick}\n selectedSpanId={selectedSpanId}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n featuredSpanIds={featuredSpanIds}\n chartWidth={timelineChartWidth}\n leadingSlot={\n <SearchFieldBlock\n name={searchFieldName}\n label=\"Search spans\"\n labelIsHidden\n placeholder=\"Search spans...\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n onReset={() => setQuery('')}\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n />\n }\n />\n\n {hierarchicalSpans.length === 0 && <DataPanel.NoData>No spans match your search.</DataPanel.NoData>}\n </DataPanel.Content>\n );\n\n // No extra tab slots → render details directly without the Tabs wrapper.\n if (!scoresTabSlot && !feedbackTabSlot) return detailsBody;\n\n // The tab list sits in a header row so it lines up with the Messages and\n // span-detail headers in the neighbouring columns.\n return (\n <Tabs<TraceDataPanelTab>\n defaultTab=\"details\"\n value={activeTab}\n onValueChange={onTabChange}\n className=\"grid h-full min-h-0 grid-rows-[auto_1fr]\"\n >\n {/* Pill tabs carry their own p-1, so shrink the header padding to keep min-h-14. */}\n <DataPanel.Header className=\"py-2\">\n <TabList variant=\"pill-ghost\" className=\"px-0\">\n <Tab value=\"details\">Spans</Tab>\n {feedbackTabSlot && (\n <Tab value=\"feedback\">Feedback{feedbackTabBadge != null && <> ({feedbackTabBadge})</>}</Tab>\n )}\n {scoresTabSlot && (\n <Tab value=\"scores\">Scores{scoresTabBadge != null && <> ({scoresTabBadge})</>}</Tab>\n )}\n </TabList>\n </DataPanel.Header>\n\n <TabContent value=\"details\" className=\"min-h-0 py-0\">\n {detailsBody}\n </TabContent>\n {feedbackTabSlot && (\n <TabContent value=\"feedback\" className=\"h-full min-h-0 py-0\">\n <DataPanel.Content>{feedbackTabSlot({ traceId })}</DataPanel.Content>\n </TabContent>\n )}\n {scoresTabSlot && (\n <TabContent value=\"scores\" className=\"h-full min-h-0 py-0\">\n <DataPanel.Content>{scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId })}</DataPanel.Content>\n </TabContent>\n )}\n </Tabs>\n );\n })()\n )}\n </TracePanelColumns>\n )}\n </DataPanel>\n );\n}\n\n/**\n * Lays out the card body as three columns — `[messages] [trace] [span]` — inside the\n * same card. Both side cells always exist and collapse to `0fr` when their slot is\n * absent, so opening/closing a column animates via `grid-template-columns` rather\n * than mounting/unmounting a DOM column (which cannot be transitioned).\n * Search matches — span names in the timeline tree as well as values in the span\n * detail — are highlighted while a query is active.\n */\nfunction TracePanelColumns({\n messagesPanelSlot,\n spanPanelSlot,\n highlightQuery,\n spanPanelKey,\n children,\n}: {\n messagesPanelSlot?: ReactNode;\n spanPanelSlot?: ReactNode;\n highlightQuery: string;\n /** Identity of the span shown in the panel; changing it re-triggers the match scroll. */\n spanPanelKey?: string;\n children: ReactNode;\n}) {\n // A single hook call on the common ancestor covers both the timeline tree and\n // the span detail, so span names and payload values highlight together.\n const { ref: highlightRef } = useTextHighlight<HTMLDivElement>(highlightQuery);\n\n // Scoped to the span-panel column only: a match deep in a large payload sits below\n // the fold, so the first painted match is brought into view when the panel opens.\n // The timeline column must never be scrolled by this.\n const { ref: scrollToMatchRef } = useScrollToFirstHighlight<HTMLDivElement>(highlightQuery, spanPanelKey);\n\n const columns = messagesPanelSlot\n ? spanPanelSlot\n ? 'grid-cols-[1fr_1fr_1fr]'\n : 'grid-cols-[1fr_1fr_0fr]'\n : spanPanelSlot\n ? 'grid-cols-[0fr_1fr_1fr]'\n : 'grid-cols-[0fr_1fr_0fr]';\n\n return (\n <div\n ref={highlightRef}\n data-trace-columns\n className={cn('grid min-h-0 flex-1 transition-[grid-template-columns] duration-300 ease-in-out', columns)}\n >\n <div\n className={cn(\n 'flex min-h-0 min-w-0 flex-col overflow-hidden',\n messagesPanelSlot && 'animate-in border-r border-border1 duration-300 fade-in-0',\n )}\n >\n {messagesPanelSlot}\n </div>\n <div className=\"flex min-h-0 min-w-0 flex-col overflow-hidden\">{children}</div>\n {/* Searchable: the span detail is where a match hides inside a large payload. */}\n <div\n ref={scrollToMatchRef}\n data-highlight\n className={cn(\n 'flex min-h-0 min-w-0 flex-col overflow-hidden',\n spanPanelSlot && 'animate-in border-l border-border1 duration-300 fade-in-0',\n )}\n >\n {spanPanelSlot}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -54,22 +54,20 @@ function TraceTimeline({
54
54
  ]
55
55
  }
56
56
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
57
- (usedSpanTypes.length > 0 || leadingSlot) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-3 px-2 py-1.5", children: [
58
- leadingSlot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: leadingSlot }),
59
- usedSpanTypes.map((type) => {
60
- const spanUI = domains_traces_components_shared.getSpanTypeUi(type);
61
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-sm text-neutral3 flex shrink-0 items-center gap-1", children: [
62
- /* @__PURE__ */ jsxRuntime.jsx(
63
- "span",
64
- {
65
- className: "inline-block size-1.5 shrink-0 rounded-full",
66
- style: { backgroundColor: spanUI?.color }
67
- }
68
- ),
69
- spanUI?.label || type
70
- ] }, type);
71
- })
72
- ] }),
57
+ leadingSlot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pt-1.5", children: leadingSlot }),
58
+ usedSpanTypes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-end gap-3 px-2 py-1.5", children: usedSpanTypes.map((type) => {
59
+ const spanUI = domains_traces_components_shared.getSpanTypeUi(type);
60
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-ui-sm text-neutral3 flex shrink-0 items-center gap-1", children: [
61
+ /* @__PURE__ */ jsxRuntime.jsx(
62
+ "span",
63
+ {
64
+ className: "inline-block size-1.5 shrink-0 rounded-full",
65
+ style: { backgroundColor: spanUI?.color }
66
+ }
67
+ ),
68
+ spanUI?.label || type
69
+ ] }, type);
70
+ }) }),
73
71
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
74
72
  domains_traces_components_traceTimelineSpan.TraceTimelineSpan,
75
73
  {
@@ -1 +1 @@
1
- {"version":3,"file":"trace-timeline.cjs.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":["useMemo","types","spanTypePrefixes","jsxs","cn","jsx","Spinner","Fragment","getSpanTypeUi","TraceTimelineSpan"],"mappings":"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"}
1
+ {"version":3,"file":"trace-timeline.cjs.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":["useMemo","types","spanTypePrefixes","jsxs","cn","jsx","Spinner","Fragment","getSpanTypeUi","TraceTimelineSpan"],"mappings":"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"}