@mastra/playground-ui 51.2.0-alpha.0 → 51.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/dist/Composer.css +1 -4
  3. package/dist/components/Composer.cjs.js +1 -1
  4. package/dist/components/Composer.cjs.js.map +1 -1
  5. package/dist/components/Composer.es.js +1 -1
  6. package/dist/components/Composer.es.js.map +1 -1
  7. package/dist/components/LogsDataList.cjs.js +1 -0
  8. package/dist/components/LogsDataList.cjs.js.map +1 -1
  9. package/dist/components/LogsDataList.es.js +1 -0
  10. package/dist/components/LogsDataList.es.js.map +1 -1
  11. package/dist/components/MainSidebar.cjs.js +1 -1
  12. package/dist/components/MainSidebar.cjs.js.map +1 -1
  13. package/dist/components/MainSidebar.es.js +1 -1
  14. package/dist/components/MainSidebar.es.js.map +1 -1
  15. package/dist/components/ai/tool-call.cjs.js +1 -1
  16. package/dist/components/ai/tool-call.cjs.js.map +1 -1
  17. package/dist/components/ai/tool-call.es.js +1 -1
  18. package/dist/components/ai/tool-call.es.js.map +1 -1
  19. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  20. package/dist/domains/traces/components/span-data-panel-view.cjs.js.map +1 -1
  21. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  22. package/dist/domains/traces/components/span-data-panel-view.es.js.map +1 -1
  23. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +16 -5
  24. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  25. package/dist/domains/traces/components/trace-data-panel-view.es.js +16 -5
  26. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  27. package/dist/src/domains/traces/components/trace-data-panel-view.d.ts +11 -2
  28. package/dist/style.css +9 -0
  29. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"trace-data-panel-view.es.js","sources":["../../../../src/domains/traces/components/trace-data-panel-view.tsx"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport {\n CircleGaugeIcon,\n ChevronsDownUpIcon,\n ChevronsUpDownIcon,\n DownloadIcon,\n Link2Icon,\n Loader2Icon,\n SaveIcon,\n WrenchIcon,\n} from 'lucide-react';\nimport { useEffect, 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 type { TraceUsageSummary } from '../trace-list-columns';\nimport { formatHierarchicalSpans } from './format-hierarchical-spans';\nimport { TraceKeysAndValues } from './trace-keys-and-values';\nimport { TraceTimeline } from './trace-timeline';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DataPanel } from '@/ds/components/DataPanel';\nimport { Notice } from '@/ds/components/Notice';\nimport { Tab, TabContent, TabList, Tabs } from '@/ds/components/Tabs';\nimport type { LinkComponent } from '@/ds/types/link-component';\nimport { truncateString } from '@/lib/truncate-string';\n\nexport type TraceDataPanelPlacement = 'traces-list' | 'trace-page';\n\nexport type TraceDataPanelTab = 'details' | 'scores';\n\nexport interface TraceDataPanelViewProps {\n traceId: string;\n /** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */\n spans: LightSpanRecord[] | undefined;\n /**\n * Token and estimated-cost totals for the trace (from `useTraceUsage`).\n * Rendered in the trace summary when the panel is in the list side-panel\n * placement; the trace page renders its own `TraceKeysAndValues` instead.\n */\n usage?: TraceUsageSummary;\n isLoading?: boolean;\n onClose: () => void;\n onSpanSelect?: (spanId: string | undefined) => void;\n onEvaluateTrace?: () => void;\n /** When set, a \"Save as Dataset Item\" 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 /**\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 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 usage,\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 anchorSpanId,\n showUnavailableFeaturesMsg = true,\n scoresTabSlot,\n scoresTabBadge,\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 hierarchicalSpans = useMemo(() => formatHierarchicalSpans(spans ?? [], anchorSpanId), [spans, anchorSpanId]);\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 isSubtrace = anchorSpanId !== undefined && rootSpan?.parentSpanId != null;\n\n const handleSpanClick = (id: string) => {\n const newId = selectedSpanId === id ? undefined : id;\n setSelectedSpanId(newId);\n onSpanSelect?.(newId);\n };\n\n const showOpenTracePageLink = !isOnTracePage && LinkComponent && traceHref;\n\n // Shared across both header layouts (list side panel and full trace page) so a trace can be\n // downloaded from wherever it's being inspected.\n const downloadTraceButton = (\n <Button\n size=\"md\"\n tooltip=\"Download trace JSON\"\n aria-label=\"Download trace JSON\"\n disabled={isDownloadingTrace}\n onClick={() => downloadTraceJson(traceId)}\n >\n {isDownloadingTrace ? <Loader2Icon className=\"animate-spin\" /> : <DownloadIcon />}\n </Button>\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\">{downloadTraceButton}</ButtonsGroup>\n </>\n ) : (\n <>\n <DataPanel.Heading>\n Trace <b># {truncateString(traceId, 12)}</b>\n </DataPanel.Heading>\n <ButtonsGroup className=\"ml-auto shrink-0\">\n {onCollapsedChange && (\n <Button\n size=\"md\"\n tooltip={collapsed ? 'Expand panel' : 'Collapse panel'}\n onClick={() => setCollapsed(!collapsed)}\n >\n {collapsed ? <ChevronsUpDownIcon /> : <ChevronsDownUpIcon />}\n </Button>\n )}\n {onEvaluateTrace && (\n <Button size=\"md\" tooltip=\"Evaluate trace\" aria-label=\"Evaluate trace\" onClick={onEvaluateTrace}>\n <CircleGaugeIcon />\n </Button>\n )}\n {onSaveAsDatasetItem && (\n <Button\n size=\"md\"\n tooltip=\"Save as Dataset Item\"\n aria-label=\"Save as Dataset Item\"\n onClick={() => onSaveAsDatasetItem({ traceId, rootSpanId: rootSpan?.spanId })}\n >\n <SaveIcon />\n </Button>\n )}\n {onAddTraceMocksToItem && (\n <Button\n size=\"md\"\n tooltip=\"Add tool mocks to item\"\n aria-label=\"Add tool mocks to item\"\n onClick={() => onAddTraceMocksToItem({ traceId })}\n >\n <WrenchIcon />\n </Button>\n )}\n {(onPrevious || onNext) && (\n <DataPanel.NextPrevNav\n onPrevious={onPrevious}\n onNext={onNext}\n previousLabel=\"Previous trace\"\n nextLabel=\"Next trace\"\n />\n )}\n {showOpenTracePageLink && (\n <Button\n as={LinkComponent}\n href={traceHref}\n size=\"md\"\n tooltip=\"Open trace page\"\n aria-label=\"Open trace page\"\n >\n <Link2Icon />\n </Button>\n )}\n {downloadTraceButton}\n <DataPanel.CloseButton onClick={onClose} />\n </ButtonsGroup>\n </>\n )}\n </DataPanel.Header>\n\n {!collapsed && (\n <SplitWithSpanPanel spanPanelSlot={spanPanelSlot}>\n {isLoading ? (\n <DataPanel.LoadingData>Loading trace...</DataPanel.LoadingData>\n ) : hierarchicalSpans.length === 0 ? (\n <DataPanel.NoData>No spans found for this trace.</DataPanel.NoData>\n ) : (\n <DataPanel.Content>\n {(() => {\n const detailsBody = (\n <>\n {!isOnTracePage && rootSpan && (\n <TraceKeysAndValues rootSpan={rootSpan} usage={isSubtrace ? undefined : usage} className=\"mb-6\" />\n )}\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 <TraceTimeline\n hierarchicalSpans={hierarchicalSpans}\n onSpanClick={handleSpanClick}\n selectedSpanId={selectedSpanId}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n chartWidth={timelineChartWidth}\n />\n </>\n );\n\n // No scores slot → render details directly without the Tabs wrapper.\n if (!scoresTabSlot) return detailsBody;\n\n return (\n <Tabs<TraceDataPanelTab>\n defaultTab=\"details\"\n value={activeTab}\n onValueChange={onTabChange}\n className={activeTab === 'scores' ? 'grid h-full min-h-0 grid-rows-[auto_1fr]' : undefined}\n >\n <TabList variant=\"pill-ghost\">\n <Tab value=\"details\">Details</Tab>\n <Tab value=\"scores\">Evaluations {scoresTabBadge != null && <>({scoresTabBadge})</>}</Tab>\n </TabList>\n\n <TabContent value=\"details\">{detailsBody}</TabContent>\n <TabContent value=\"scores\" className=\"h-full min-h-0\">\n {scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId })}\n </TabContent>\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 */\nfunction SplitWithSpanPanel({ spanPanelSlot, children }: { spanPanelSlot?: ReactNode; children: ReactNode }) {\n if (!spanPanelSlot) return <>{children}</>;\n\n return (\n <div 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 <div className=\"animate-in border-border1 fade-in-0 flex min-h-0 flex-col overflow-hidden border-l duration-300\">\n {spanPanelSlot}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA2FO,SAAS,kBAAA,CAAmB;AAAA,EACjC,OAAA;AAAA,EACA,KAAA;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,YAAA;AAAA,EACA,0BAAA,GAA6B,IAAA;AAAA,EAC7B,aAAA;AAAA,EACA,cAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,EAA4B;AAC1B,EAAA,MAAM,gBAAgB,SAAA,KAAc,YAAA;AACpC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,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,KAAuB,oBAAA,EAAqB;AAE5F,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,QAAA,CAA6B,iBAAiB,MAAS,CAAA;AAGnG,EAAA,SAAA,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,iBAAA,GAAoB,OAAA,CAAQ,MAAM,uBAAA,CAAwB,KAAA,IAAS,EAAC,EAAG,YAAY,CAAA,EAAG,CAAC,KAAA,EAAO,YAAY,CAAC,CAAA;AAEjH,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,QAAA,CAAmB,EAAE,CAAA;AAEnE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,iBAAA,CAAkB,SAAS,CAAA,EAAG;AAChC,MAAA,kBAAA,CAAmB,aAAA,CAAc,iBAAiB,CAAC,CAAA;AAAA,IACrD;AAAA,EACF,CAAA,EAAG,CAAC,iBAAiB,CAAC,CAAA;AAEtB,EAAA,MAAM,QAAA,GAAW,OAAA;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,UAAA,GAAa,YAAA,KAAiB,MAAA,IAAa,QAAA,EAAU,YAAA,IAAgB,IAAA;AAE3E,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,qBAAA,GAAwB,CAAC,aAAA,IAAiB,aAAA,IAAiB,SAAA;AAIjE,EAAA,MAAM,mBAAA,mBACJ,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,IAAA;AAAA,MACL,OAAA,EAAQ,qBAAA;AAAA,MACR,YAAA,EAAW,qBAAA;AAAA,MACX,QAAA,EAAU,kBAAA;AAAA,MACV,OAAA,EAAS,MAAM,iBAAA,CAAkB,OAAO,CAAA;AAAA,MAEvC,+CAAqB,GAAA,CAAC,WAAA,EAAA,EAAY,WAAU,cAAA,EAAe,CAAA,uBAAM,YAAA,EAAA,EAAa;AAAA;AAAA,GACjF;AAGF,EAAA,uBACE,IAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAsB,SAAA,EAC/B,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,SAAA,CAAU,MAAA,EAAV,EACE,QAAA,EAAA,aAAA,mBACC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,SAAA,CAAU,OAAA,EAAV,EAAkB,QAAA,EAAA,gBAAA,EAAc,CAAA;AAAA,sBACjC,GAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,kBAAA,EAAoB,QAAA,EAAA,mBAAA,EAAoB;AAAA,KAAA,EAClE,oBAEA,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,SAAA,CAAU,SAAV,EAAkB,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,6BACV,GAAA,EAAA,EAAE,QAAA,EAAA;AAAA,UAAA,IAAA;AAAA,UAAG,cAAA,CAAe,SAAS,EAAE;AAAA,SAAA,EAAE;AAAA,OAAA,EAC1C,CAAA;AAAA,sBACA,IAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,kBAAA,EACrB,QAAA,EAAA;AAAA,QAAA,iBAAA,oBACC,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAS,YAAY,cAAA,GAAiB,gBAAA;AAAA,YACtC,OAAA,EAAS,MAAM,YAAA,CAAa,CAAC,SAAS,CAAA;AAAA,YAErC,QAAA,EAAA,SAAA,mBAAY,GAAA,CAAC,kBAAA,EAAA,EAAmB,CAAA,uBAAM,kBAAA,EAAA,EAAmB;AAAA;AAAA,SAC5D;AAAA,QAED,eAAA,oBACC,GAAA,CAAC,MAAA,EAAA,EAAO,IAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,gBAAA,EAAiB,YAAA,EAAW,gBAAA,EAAiB,OAAA,EAAS,eAAA,EAC9E,QAAA,kBAAA,GAAA,CAAC,mBAAgB,CAAA,EACnB,CAAA;AAAA,QAED,mBAAA,oBACC,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAQ,sBAAA;AAAA,YACR,YAAA,EAAW,sBAAA;AAAA,YACX,OAAA,EAAS,MAAM,mBAAA,CAAoB,EAAE,SAAS,UAAA,EAAY,QAAA,EAAU,QAAQ,CAAA;AAAA,YAE5E,8BAAC,QAAA,EAAA,EAAS;AAAA;AAAA,SACZ;AAAA,QAED,qBAAA,oBACC,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAQ,wBAAA;AAAA,YACR,YAAA,EAAW,wBAAA;AAAA,YACX,OAAA,EAAS,MAAM,qBAAA,CAAsB,EAAE,SAAS,CAAA;AAAA,YAEhD,8BAAC,UAAA,EAAA,EAAW;AAAA;AAAA,SACd;AAAA,QAAA,CAEA,cAAc,MAAA,qBACd,GAAA;AAAA,UAAC,SAAA,CAAU,WAAA;AAAA,UAAV;AAAA,YACC,UAAA;AAAA,YACA,MAAA;AAAA,YACA,aAAA,EAAc,gBAAA;AAAA,YACd,SAAA,EAAU;AAAA;AAAA,SACZ;AAAA,QAED,qBAAA,oBACC,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,EAAA,EAAI,aAAA;AAAA,YACJ,IAAA,EAAM,SAAA;AAAA,YACN,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAQ,iBAAA;AAAA,YACR,YAAA,EAAW,iBAAA;AAAA,YAEX,8BAAC,SAAA,EAAA,EAAU;AAAA;AAAA,SACb;AAAA,QAED,mBAAA;AAAA,wBACD,GAAA,CAAC,SAAA,CAAU,WAAA,EAAV,EAAsB,SAAS,OAAA,EAAS;AAAA,OAAA,EAC3C;AAAA,KAAA,EACF,CAAA,EAEJ,CAAA;AAAA,IAEC,CAAC,SAAA,oBACA,GAAA,CAAC,kBAAA,EAAA,EAAmB,aAAA,EACjB,sCACC,GAAA,CAAC,SAAA,CAAU,WAAA,EAAV,EAAsB,QAAA,EAAA,kBAAA,EAAgB,CAAA,GACrC,kBAAkB,MAAA,KAAW,CAAA,mBAC/B,GAAA,CAAC,SAAA,CAAU,MAAA,EAAV,EAAiB,QAAA,EAAA,gCAAA,EAA8B,CAAA,mBAEhD,GAAA,CAAC,SAAA,CAAU,OAAA,EAAV,EACG,QAAA,EAAA,CAAA,MAAM;AACN,MAAA,MAAM,8BACJ,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,QAAA,CAAC,aAAA,IAAiB,QAAA,oBACjB,GAAA,CAAC,kBAAA,EAAA,EAAmB,QAAA,EAAoB,OAAO,UAAA,GAAa,MAAA,GAAY,KAAA,EAAO,SAAA,EAAU,MAAA,EAAO,CAAA;AAAA,QAGjG,CAAC,iBACA,CAAC,eAAA,IACD,CAAC,mBAAA,IACD,CAAC,yBACD,0BAAA,oBACE,GAAA,CAAC,UAAO,OAAA,EAAQ,MAAA,EAAO,WAAU,MAAA,EAC/B,QAAA,kBAAA,GAAA,CAAC,OAAO,OAAA,EAAP,EAAe,mHAGhB,CAAA,EACF,CAAA;AAAA,wBAGJ,GAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,iBAAA;AAAA,YACA,WAAA,EAAa,eAAA;AAAA,YACb,cAAA;AAAA,YACA,eAAA;AAAA,YACA,kBAAA;AAAA,YACA,UAAA,EAAY;AAAA;AAAA;AACd,OAAA,EACF,CAAA;AAIF,MAAA,IAAI,CAAC,eAAe,OAAO,WAAA;AAE3B,MAAA,uBACE,IAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,UAAA,EAAW,SAAA;AAAA,UACX,KAAA,EAAO,SAAA;AAAA,UACP,aAAA,EAAe,WAAA;AAAA,UACf,SAAA,EAAW,SAAA,KAAc,QAAA,GAAW,0CAAA,GAA6C,MAAA;AAAA,UAEjF,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,OAAA,EAAA,EAAQ,SAAQ,YAAA,EACf,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,GAAA,EAAA,EAAI,KAAA,EAAM,SAAA,EAAU,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,8BAC5B,IAAA,CAAC,GAAA,EAAA,EAAI,KAAA,EAAM,QAAA,EAAS,QAAA,EAAA;AAAA,gBAAA,cAAA;AAAA,gBAAa,cAAA,IAAkB,wBAAQ,IAAA,CAAA,QAAA,EAAA,EAAE,QAAA,EAAA;AAAA,kBAAA,GAAA;AAAA,kBAAE,cAAA;AAAA,kBAAe;AAAA,iBAAA,EAAC;AAAA,eAAA,EAAI;AAAA,aAAA,EACrF,CAAA;AAAA,4BAEA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,SAAA,EAAW,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,4BACzC,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,QAAA,EAAS,SAAA,EAAU,gBAAA,EAClC,QAAA,EAAA,aAAA,CAAc,EAAE,OAAA,EAAS,UAAA,EAAY,QAAA,EAAU,MAAA,EAAQ,CAAA,EAC1D;AAAA;AAAA;AAAA,OACF;AAAA,IAEJ,CAAA,KACF,CAAA,EAEJ;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAMA,SAAS,kBAAA,CAAmB,EAAE,aAAA,EAAe,QAAA,EAAS,EAAuD;AAC3G,EAAA,IAAI,CAAC,aAAA,EAAe,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AAEvC,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yCAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uCAAA,EAAyC,QAAA,EAAS,CAAA;AAAA,oBACjE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iGAAA,EACZ,QAAA,EAAA,aAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"trace-data-panel-view.es.js","sources":["../../../../src/domains/traces/components/trace-data-panel-view.tsx"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport {\n CircleGaugeIcon,\n ChevronsDownUpIcon,\n ChevronsUpDownIcon,\n DownloadIcon,\n Link2Icon,\n Loader2Icon,\n SaveIcon,\n WrenchIcon,\n} from 'lucide-react';\nimport { useEffect, 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 type { TraceUsageSummary } from '../trace-list-columns';\nimport { formatHierarchicalSpans } from './format-hierarchical-spans';\nimport { TraceKeysAndValues } from './trace-keys-and-values';\nimport { TraceTimeline } from './trace-timeline';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DataPanel } from '@/ds/components/DataPanel';\nimport { Notice } from '@/ds/components/Notice';\nimport { Tab, TabContent, TabList, Tabs } from '@/ds/components/Tabs';\nimport type { LinkComponent } from '@/ds/types/link-component';\nimport { truncateString } from '@/lib/truncate-string';\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: LightSpanRecord[] | undefined;\n /**\n * Token and estimated-cost totals for the trace (from `useTraceUsage`).\n * Rendered in the trace summary when the panel is in the list side-panel\n * placement; the trace page renders its own `TraceKeysAndValues` instead.\n */\n usage?: TraceUsageSummary;\n isLoading?: boolean;\n onClose: () => void;\n onSpanSelect?: (spanId: string | undefined) => void;\n onEvaluateTrace?: () => void;\n /** When set, a \"Save as Dataset Item\" 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 /**\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 /**\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 usage,\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 anchorSpanId,\n showUnavailableFeaturesMsg = true,\n scoresTabSlot,\n scoresTabBadge,\n feedbackTabSlot,\n feedbackTabBadge,\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 hierarchicalSpans = useMemo(() => formatHierarchicalSpans(spans ?? [], anchorSpanId), [spans, anchorSpanId]);\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 isSubtrace = anchorSpanId !== undefined && rootSpan?.parentSpanId != null;\n\n const handleSpanClick = (id: string) => {\n const newId = selectedSpanId === id ? undefined : id;\n setSelectedSpanId(newId);\n onSpanSelect?.(newId);\n };\n\n const showOpenTracePageLink = !isOnTracePage && LinkComponent && traceHref;\n\n // Shared across both header layouts (list side panel and full trace page) so a trace can be\n // downloaded from wherever it's being inspected.\n const downloadTraceButton = (\n <Button\n size=\"md\"\n tooltip=\"Download trace JSON\"\n aria-label=\"Download trace JSON\"\n disabled={isDownloadingTrace}\n onClick={() => downloadTraceJson(traceId)}\n >\n {isDownloadingTrace ? <Loader2Icon className=\"animate-spin\" /> : <DownloadIcon />}\n </Button>\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\">{downloadTraceButton}</ButtonsGroup>\n </>\n ) : (\n <>\n <DataPanel.Heading>\n Trace <b># {truncateString(traceId, 12)}</b>\n </DataPanel.Heading>\n <ButtonsGroup className=\"ml-auto shrink-0\">\n {onCollapsedChange && (\n <Button\n size=\"md\"\n tooltip={collapsed ? 'Expand panel' : 'Collapse panel'}\n onClick={() => setCollapsed(!collapsed)}\n >\n {collapsed ? <ChevronsUpDownIcon /> : <ChevronsDownUpIcon />}\n </Button>\n )}\n {onEvaluateTrace && (\n <Button size=\"md\" tooltip=\"Evaluate trace\" aria-label=\"Evaluate trace\" onClick={onEvaluateTrace}>\n <CircleGaugeIcon />\n </Button>\n )}\n {onSaveAsDatasetItem && (\n <Button\n size=\"md\"\n tooltip=\"Save as Dataset Item\"\n aria-label=\"Save as Dataset Item\"\n onClick={() => onSaveAsDatasetItem({ traceId, rootSpanId: rootSpan?.spanId })}\n >\n <SaveIcon />\n </Button>\n )}\n {onAddTraceMocksToItem && (\n <Button\n size=\"md\"\n tooltip=\"Add tool mocks to item\"\n aria-label=\"Add tool mocks to item\"\n onClick={() => onAddTraceMocksToItem({ traceId })}\n >\n <WrenchIcon />\n </Button>\n )}\n {(onPrevious || onNext) && (\n <DataPanel.NextPrevNav\n onPrevious={onPrevious}\n onNext={onNext}\n previousLabel=\"Previous trace\"\n nextLabel=\"Next trace\"\n />\n )}\n {showOpenTracePageLink && (\n <Button\n as={LinkComponent}\n href={traceHref}\n size=\"md\"\n tooltip=\"Open trace page\"\n aria-label=\"Open trace page\"\n >\n <Link2Icon />\n </Button>\n )}\n {downloadTraceButton}\n <DataPanel.CloseButton onClick={onClose} />\n </ButtonsGroup>\n </>\n )}\n </DataPanel.Header>\n\n {!collapsed && (\n <SplitWithSpanPanel spanPanelSlot={spanPanelSlot}>\n {isLoading ? (\n <DataPanel.LoadingData>Loading trace...</DataPanel.LoadingData>\n ) : hierarchicalSpans.length === 0 ? (\n <DataPanel.NoData>No spans found for this trace.</DataPanel.NoData>\n ) : (\n <DataPanel.Content>\n {(() => {\n const detailsBody = (\n <>\n {!isOnTracePage && rootSpan && (\n <TraceKeysAndValues rootSpan={rootSpan} usage={isSubtrace ? undefined : usage} className=\"mb-6\" />\n )}\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 <TraceTimeline\n hierarchicalSpans={hierarchicalSpans}\n onSpanClick={handleSpanClick}\n selectedSpanId={selectedSpanId}\n expandedSpanIds={expandedSpanIds}\n setExpandedSpanIds={setExpandedSpanIds}\n chartWidth={timelineChartWidth}\n />\n </>\n );\n\n // No extra tab slots → render details directly without the Tabs wrapper.\n if (!scoresTabSlot && !feedbackTabSlot) return detailsBody;\n\n return (\n <Tabs<TraceDataPanelTab>\n defaultTab=\"details\"\n value={activeTab}\n onValueChange={onTabChange}\n className={\n 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\">Details</Tab>\n {scoresTabSlot && (\n <Tab value=\"scores\">Evaluations {scoresTabBadge != null && <>({scoresTabBadge})</>}</Tab>\n )}\n {feedbackTabSlot && (\n <Tab value=\"feedback\">Feedback {feedbackTabBadge != null && <>({feedbackTabBadge})</>}</Tab>\n )}\n </TabList>\n\n <TabContent value=\"details\">{detailsBody}</TabContent>\n {scoresTabSlot && (\n <TabContent value=\"scores\" className=\"h-full min-h-0\">\n {scoresTabSlot({ traceId, rootSpanId: rootSpan?.spanId })}\n </TabContent>\n )}\n {feedbackTabSlot && (\n <TabContent value=\"feedback\" className=\"h-full min-h-0\">\n {feedbackTabSlot({ traceId })}\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 */\nfunction SplitWithSpanPanel({ spanPanelSlot, children }: { spanPanelSlot?: ReactNode; children: ReactNode }) {\n if (!spanPanelSlot) return <>{children}</>;\n\n return (\n <div 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 <div className=\"animate-in border-border1 fade-in-0 flex min-h-0 flex-col overflow-hidden border-l duration-300\">\n {spanPanelSlot}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { TraceUsageSummary } from '../trace-list-columns';
4
4
  import { LinkComponent } from '../../../ds/types/link-component';
5
5
  export type TraceDataPanelPlacement = 'traces-list' | 'trace-page';
6
- export type TraceDataPanelTab = 'details' | 'scores';
6
+ export type TraceDataPanelTab = 'details' | 'scores' | 'feedback';
7
7
  export interface TraceDataPanelViewProps {
8
8
  traceId: string;
9
9
  /** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */
@@ -61,6 +61,15 @@ export interface TraceDataPanelViewProps {
61
61
  }) => ReactNode;
62
62
  /** Optional count shown in the "Scores" tab label. */
63
63
  scoresTabBadge?: ReactNode;
64
+ /**
65
+ * When provided, a "Feedback" tab appears; the slot renders the trace-level
66
+ * feedback UI. Trace feedback is not scoped to a span — the span panel owns that.
67
+ */
68
+ feedbackTabSlot?: (args: {
69
+ traceId: string;
70
+ }) => ReactNode;
71
+ /** Optional count shown in the "Feedback" tab label. */
72
+ feedbackTabBadge?: ReactNode;
64
73
  activeTab?: TraceDataPanelTab;
65
74
  onTabChange?: (tab: TraceDataPanelTab) => void;
66
75
  /**
@@ -71,4 +80,4 @@ export interface TraceDataPanelViewProps {
71
80
  /** Extra classes applied to the panel root (e.g. `h-full` on the trace page). */
72
81
  className?: string;
73
82
  }
74
- export declare function TraceDataPanelView({ traceId, spans, usage, isLoading, onClose, onSpanSelect, onEvaluateTrace, onSaveAsDatasetItem, onAddTraceMocksToItem, initialSpanId, onPrevious, onNext, collapsed: controlledCollapsed, onCollapsedChange, placement, timelineChartWidth, LinkComponent, traceHref, anchorSpanId, showUnavailableFeaturesMsg, scoresTabSlot, scoresTabBadge, activeTab, onTabChange, spanPanelSlot, className, }: TraceDataPanelViewProps): import("react").JSX.Element;
83
+ export declare function TraceDataPanelView({ traceId, spans, usage, isLoading, onClose, onSpanSelect, onEvaluateTrace, onSaveAsDatasetItem, onAddTraceMocksToItem, initialSpanId, onPrevious, onNext, collapsed: controlledCollapsed, onCollapsedChange, placement, timelineChartWidth, LinkComponent, traceHref, anchorSpanId, showUnavailableFeaturesMsg, scoresTabSlot, scoresTabBadge, feedbackTabSlot, feedbackTabBadge, activeTab, onTabChange, spanPanelSlot, className, }: TraceDataPanelViewProps): import("react").JSX.Element;
package/dist/style.css CHANGED
@@ -3549,6 +3549,10 @@
3549
3549
  border-radius: 22px;
3550
3550
  }
3551
3551
 
3552
+ .rounded-\[23px\] {
3553
+ border-radius: 23px;
3554
+ }
3555
+
3552
3556
  .rounded-\[inherit\] {
3553
3557
  border-radius: inherit;
3554
3558
  }
@@ -5416,6 +5420,11 @@
5416
5420
  line-height: var(--leading-ui-xs);
5417
5421
  }
5418
5422
 
5423
+ .font-\[450\] {
5424
+ --tw-font-weight: 450;
5425
+ font-weight: 450;
5426
+ }
5427
+
5419
5428
  .font-bold {
5420
5429
  --tw-font-weight: var(--font-weight-bold);
5421
5430
  font-weight: var(--font-weight-bold);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mastra/playground-ui",
3
3
  "type": "module",
4
- "version": "51.2.0-alpha.0",
4
+ "version": "51.2.0",
5
5
  "description": "Mastra Playground components",
6
6
  "sideEffects": [
7
7
  "**/*.css"
@@ -161,8 +161,8 @@
161
161
  "react": ">=19.0.0",
162
162
  "react-dom": ">=19.0.0",
163
163
  "tailwindcss": "^4.0.0",
164
- "@mastra/client-js": "^1.42.2-alpha.0",
165
- "@mastra/react": "1.4.7-alpha.0"
164
+ "@mastra/client-js": "^1.42.2",
165
+ "@mastra/react": "1.4.7"
166
166
  },
167
167
  "devDependencies": {
168
168
  "@storybook/addon-a11y": "^10.4.1",
@@ -202,11 +202,11 @@
202
202
  "vite-plugin-dts": "^4.5.4",
203
203
  "vite-plugin-lib-inject-css": "^2.2.2",
204
204
  "vitest": "4.1.10",
205
- "@internal/lint": "0.0.126",
206
- "@mastra/core": "1.63.0-alpha.0",
207
- "@mastra/client-js": "^1.42.2-alpha.0",
208
- "@mastra/react": "1.4.7-alpha.0",
209
- "@mastra/memory": "1.28.0"
205
+ "@mastra/client-js": "^1.42.2",
206
+ "@internal/lint": "0.0.127",
207
+ "@mastra/memory": "1.28.0",
208
+ "@mastra/react": "1.4.7",
209
+ "@mastra/core": "1.63.0"
210
210
  },
211
211
  "homepage": "https://mastra.ai",
212
212
  "repository": {