@mastra/playground-ui 58.0.0 → 58.1.0-alpha.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 (176) hide show
  1. package/dist/{Badge-TD55_qZJ.js → Badge-Bzn8Z-_I.js} +2 -2
  2. package/dist/Badge-Bzn8Z-_I.js.map +1 -0
  3. package/dist/{Badge-BEeYtjmv.cjs → Badge-DFNxcz-r.cjs} +2 -2
  4. package/dist/Badge-DFNxcz-r.cjs.map +1 -0
  5. package/dist/{ask-user-jDUt7hgT.js → ask-user-DtF4a9Vr.js} +2 -2
  6. package/dist/{ask-user-jDUt7hgT.js.map → ask-user-DtF4a9Vr.js.map} +1 -1
  7. package/dist/{ask-user-BPpgiE7k.cjs → ask-user-pPTuoPKI.cjs} +2 -2
  8. package/dist/{ask-user-BPpgiE7k.cjs.map → ask-user-pPTuoPKI.cjs.map} +1 -1
  9. package/dist/{chat-notification-CmdRGO_D.js → chat-notification-C4P2InUX.js} +2 -2
  10. package/dist/{chat-notification-CmdRGO_D.js.map → chat-notification-C4P2InUX.js.map} +1 -1
  11. package/dist/{chat-notification-DJykWtoj.cjs → chat-notification-HP18KxlS.cjs} +2 -2
  12. package/dist/{chat-notification-DJykWtoj.cjs.map → chat-notification-HP18KxlS.cjs.map} +1 -1
  13. package/dist/{chat-signal-xs3FkPts.cjs → chat-signal-BP9RN6Rh.cjs} +2 -2
  14. package/dist/{chat-signal-xs3FkPts.cjs.map → chat-signal-BP9RN6Rh.cjs.map} +1 -1
  15. package/dist/{chat-signal-Vg8pGXwH.js → chat-signal-CQnmFp3V.js} +2 -2
  16. package/dist/{chat-signal-Vg8pGXwH.js.map → chat-signal-CQnmFp3V.js.map} +1 -1
  17. package/dist/components/Badge.cjs.js +1 -1
  18. package/dist/components/Badge.es.js +1 -1
  19. package/dist/components/DataList.cjs.js +1 -1
  20. package/dist/components/DataList.es.js +1 -1
  21. package/dist/components/ItemList.cjs.js +1 -1
  22. package/dist/components/ItemList.es.js +1 -1
  23. package/dist/components/LogsDataList.cjs.js +1 -1
  24. package/dist/components/LogsDataList.es.js +1 -1
  25. package/dist/components/MetricsCard.cjs.js +1 -1
  26. package/dist/components/MetricsCard.es.js +1 -1
  27. package/dist/components/MetricsCardGroup.cjs.js +2 -11
  28. package/dist/components/MetricsCardGroup.cjs.js.map +1 -1
  29. package/dist/components/MetricsCardGroup.es.js +2 -11
  30. package/dist/components/MetricsCardGroup.es.js.map +1 -1
  31. package/dist/components/MetricsKpiCard.cjs.js +1 -1
  32. package/dist/components/MetricsKpiCard.es.js +1 -1
  33. package/dist/components/MetricsLineChart.cjs.js +2 -1
  34. package/dist/components/MetricsLineChart.cjs.js.map +1 -1
  35. package/dist/components/MetricsLineChart.es.js +1 -1
  36. package/dist/components/PageHeader.cjs.js +1 -1
  37. package/dist/components/PageHeader.es.js +1 -1
  38. package/dist/components/Workflow.cjs.js +1 -1
  39. package/dist/components/Workflow.es.js +1 -1
  40. package/dist/components/ai/ask-user.cjs.js +1 -1
  41. package/dist/components/ai/ask-user.es.js +1 -1
  42. package/dist/components/ai/chat-event.cjs.js +2 -2
  43. package/dist/components/ai/chat-event.es.js +3 -3
  44. package/dist/components/ai/plan.cjs.js +1 -1
  45. package/dist/components/ai/plan.es.js +1 -1
  46. package/dist/components/ai/task-list.cjs.js +370 -55
  47. package/dist/components/ai/task-list.cjs.js.map +1 -1
  48. package/dist/components/ai/task-list.es.js +374 -58
  49. package/dist/components/ai/task-list.es.js.map +1 -1
  50. package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
  51. package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
  52. package/dist/domains/chat/messages/renderers/message-text.cjs.js +1 -1
  53. package/dist/domains/chat/messages/renderers/message-text.es.js +1 -1
  54. package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
  55. package/dist/domains/chat/messages/signal-badge.es.js +1 -1
  56. package/dist/domains/chat/messages/tripwire-notice.cjs.js +1 -1
  57. package/dist/domains/chat/messages/tripwire-notice.es.js +1 -1
  58. package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
  59. package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
  60. package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +1 -1
  61. package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +1 -1
  62. package/dist/domains/logs/components/logs-list-view.cjs.js +1 -1
  63. package/dist/domains/logs/components/logs-list-view.es.js +1 -1
  64. package/dist/domains/metrics/components/kpi-card-view.cjs.js +1 -1
  65. package/dist/domains/metrics/components/kpi-card-view.es.js +1 -1
  66. package/dist/domains/metrics/components/latency-card-view.cjs.js +33 -24
  67. package/dist/domains/metrics/components/latency-card-view.cjs.js.map +1 -1
  68. package/dist/domains/metrics/components/latency-card-view.es.js +34 -25
  69. package/dist/domains/metrics/components/latency-card-view.es.js.map +1 -1
  70. package/dist/domains/metrics/components/memory-card-view.cjs.js +3 -3
  71. package/dist/domains/metrics/components/memory-card-view.cjs.js.map +1 -1
  72. package/dist/domains/metrics/components/memory-card-view.es.js +3 -3
  73. package/dist/domains/metrics/components/memory-card-view.es.js.map +1 -1
  74. package/dist/domains/metrics/components/model-usage-cost-card-view.cjs.js +1 -1
  75. package/dist/domains/metrics/components/model-usage-cost-card-view.es.js +1 -1
  76. package/dist/domains/metrics/components/scores-card-view.cjs.js +4 -4
  77. package/dist/domains/metrics/components/scores-card-view.cjs.js.map +1 -1
  78. package/dist/domains/metrics/components/scores-card-view.es.js +4 -4
  79. package/dist/domains/metrics/components/scores-card-view.es.js.map +1 -1
  80. package/dist/domains/metrics/components/token-usage-by-agent-card-view.cjs.js +3 -3
  81. package/dist/domains/metrics/components/token-usage-by-agent-card-view.cjs.js.map +1 -1
  82. package/dist/domains/metrics/components/token-usage-by-agent-card-view.es.js +3 -3
  83. package/dist/domains/metrics/components/token-usage-by-agent-card-view.es.js.map +1 -1
  84. package/dist/domains/metrics/components/token-usage-timeline-card-view.cjs.js +10 -9
  85. package/dist/domains/metrics/components/token-usage-timeline-card-view.cjs.js.map +1 -1
  86. package/dist/domains/metrics/components/token-usage-timeline-card-view.es.js +10 -9
  87. package/dist/domains/metrics/components/token-usage-timeline-card-view.es.js.map +1 -1
  88. package/dist/domains/metrics/components/traces-volume-card-view.cjs.js +4 -4
  89. package/dist/domains/metrics/components/traces-volume-card-view.cjs.js.map +1 -1
  90. package/dist/domains/metrics/components/traces-volume-card-view.es.js +4 -4
  91. package/dist/domains/metrics/components/traces-volume-card-view.es.js.map +1 -1
  92. package/dist/domains/metrics/hooks/use-latency-metrics.cjs.js +11 -11
  93. package/dist/domains/metrics/hooks/use-latency-metrics.cjs.js.map +1 -1
  94. package/dist/domains/metrics/hooks/use-latency-metrics.es.js +12 -11
  95. package/dist/domains/metrics/hooks/use-latency-metrics.es.js.map +1 -1
  96. package/dist/domains/metrics/hooks/use-token-usage-timeseries.cjs.js +4 -12
  97. package/dist/domains/metrics/hooks/use-token-usage-timeseries.cjs.js.map +1 -1
  98. package/dist/domains/metrics/hooks/use-token-usage-timeseries.es.js +4 -12
  99. package/dist/domains/metrics/hooks/use-token-usage-timeseries.es.js.map +1 -1
  100. package/dist/domains/metrics/hooks.cjs.js +3 -0
  101. package/dist/domains/metrics/hooks.cjs.js.map +1 -1
  102. package/dist/domains/metrics/hooks.es.js +1 -0
  103. package/dist/domains/metrics/hooks.es.js.map +1 -1
  104. package/dist/domains/metrics/metrics-interval.cjs.js +18 -0
  105. package/dist/domains/metrics/metrics-interval.cjs.js.map +1 -0
  106. package/dist/domains/metrics/metrics-interval.d.ts +2 -0
  107. package/dist/domains/metrics/metrics-interval.es.js +13 -0
  108. package/dist/domains/metrics/metrics-interval.es.js.map +1 -0
  109. package/dist/domains/metrics.cjs.js +3 -0
  110. package/dist/domains/metrics.cjs.js.map +1 -1
  111. package/dist/domains/metrics.es.js +1 -0
  112. package/dist/domains/metrics.es.js.map +1 -1
  113. package/dist/domains/traces/components/span-type-legend.cjs.js +1 -1
  114. package/dist/domains/traces/components/span-type-legend.es.js +1 -1
  115. package/dist/domains/traces/components/traces-list-view.cjs.js +1 -1
  116. package/dist/domains/traces/components/traces-list-view.es.js +1 -1
  117. package/dist/ee/signals/components/entity-index-compact-grid.cjs.js +1 -1
  118. package/dist/ee/signals/components/entity-index-compact-grid.es.js +1 -1
  119. package/dist/ee/signals/components/entity-index-list.cjs.js +1 -1
  120. package/dist/ee/signals/components/entity-index-list.es.js +1 -1
  121. package/dist/ee/signals/settings/trace-signal-settings.cjs.js +1 -1
  122. package/dist/ee/signals/settings/trace-signal-settings.es.js +1 -1
  123. package/dist/{logs-data-list-YL9yLKF3.cjs → logs-data-list-BHvJOeec.cjs} +2 -2
  124. package/dist/{logs-data-list-YL9yLKF3.cjs.map → logs-data-list-BHvJOeec.cjs.map} +1 -1
  125. package/dist/{logs-data-list-5BAeLU57.js → logs-data-list-CgDcNIvS.js} +2 -2
  126. package/dist/{logs-data-list-5BAeLU57.js.map → logs-data-list-CgDcNIvS.js.map} +1 -1
  127. package/dist/{metrics-card-Bzm6m1dy.js → metrics-card-C2RTi5Ew.js} +7 -7
  128. package/dist/metrics-card-C2RTi5Ew.js.map +1 -0
  129. package/dist/{metrics-card-DCCHIG-z.cjs → metrics-card-DzcVJTAN.cjs} +7 -7
  130. package/dist/metrics-card-DzcVJTAN.cjs.map +1 -0
  131. package/dist/{metrics-kpi-card-BrnFhFQm.js → metrics-kpi-card-BVCuXeDa.js} +21 -10
  132. package/dist/metrics-kpi-card-BVCuXeDa.js.map +1 -0
  133. package/dist/{metrics-kpi-card-Bhb4R4z0.cjs → metrics-kpi-card-DoIeHfv6.cjs} +21 -10
  134. package/dist/metrics-kpi-card-DoIeHfv6.cjs.map +1 -0
  135. package/dist/{metrics-line-chart-0FR3SYSt.cjs → metrics-line-chart-BNNRRxM8.cjs} +61 -25
  136. package/dist/metrics-line-chart-BNNRRxM8.cjs.map +1 -0
  137. package/dist/{metrics-line-chart-knlgw8bV.js → metrics-line-chart-CT_pqJtC.js} +62 -27
  138. package/dist/metrics-line-chart-CT_pqJtC.js.map +1 -0
  139. package/dist/new/layout/page-header.cjs.js +1 -1
  140. package/dist/new/layout/page-header.es.js +1 -1
  141. package/dist/{page-header-CyXAezlZ.js → page-header-BGyZw13s.js} +2 -2
  142. package/dist/page-header-BGyZw13s.js.map +1 -0
  143. package/dist/{page-header-Dk3s3XtC.cjs → page-header-CqvBk1wE.cjs} +2 -2
  144. package/dist/page-header-CqvBk1wE.cjs.map +1 -0
  145. package/dist/src/domains/metrics/components/latency-card-view.d.ts +4 -1
  146. package/dist/src/domains/metrics/hooks/index.d.ts +1 -0
  147. package/dist/src/domains/metrics/hooks/use-latency-metrics.d.ts +2 -2
  148. package/dist/src/domains/metrics/hooks/use-token-usage-timeseries.d.ts +2 -1
  149. package/dist/src/domains/metrics/metrics-interval.d.ts +7 -0
  150. package/dist/src/ds/components/MetricsCardGroup/metrics-card-group.d.ts +3 -8
  151. package/dist/src/ds/components/MetricsLineChart/index.d.ts +1 -0
  152. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart-legend.d.ts +6 -0
  153. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.d.ts +6 -4
  154. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.stories.d.ts +1 -0
  155. package/dist/src/ds/components/ai/task-list/task-graph-node.d.ts +8 -0
  156. package/dist/src/ds/components/ai/task-list/task-graph.d.ts +8 -0
  157. package/dist/src/ds/components/ai/task-list/task-list.d.ts +4 -8
  158. package/dist/src/ds/components/ai/task-list/task-list.stories.d.ts +1 -1
  159. package/dist/src/ds/components/ai/task-list/use-focused-row-scroll.d.ts +12 -0
  160. package/dist/src/ds/new/layout/page-header/page-header.stories.d.ts +1 -0
  161. package/dist/style.css +304 -14
  162. package/dist/{traces-data-list-Dvi0s56v.js → traces-data-list-B5MkMMBi.js} +2 -2
  163. package/dist/{traces-data-list-Dvi0s56v.js.map → traces-data-list-B5MkMMBi.js.map} +1 -1
  164. package/dist/{traces-data-list-Dam8-XW-.cjs → traces-data-list-D3k50j4n.cjs} +2 -2
  165. package/dist/{traces-data-list-Dam8-XW-.cjs.map → traces-data-list-D3k50j4n.cjs.map} +1 -1
  166. package/package.json +7 -7
  167. package/dist/Badge-BEeYtjmv.cjs.map +0 -1
  168. package/dist/Badge-TD55_qZJ.js.map +0 -1
  169. package/dist/metrics-card-Bzm6m1dy.js.map +0 -1
  170. package/dist/metrics-card-DCCHIG-z.cjs.map +0 -1
  171. package/dist/metrics-kpi-card-Bhb4R4z0.cjs.map +0 -1
  172. package/dist/metrics-kpi-card-BrnFhFQm.js.map +0 -1
  173. package/dist/metrics-line-chart-0FR3SYSt.cjs.map +0 -1
  174. package/dist/metrics-line-chart-knlgw8bV.js.map +0 -1
  175. package/dist/page-header-CyXAezlZ.js.map +0 -1
  176. package/dist/page-header-Dk3s3XtC.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"token-usage-timeline-card-view.es.js","sources":["../../../../src/domains/metrics/components/token-usage-timeline-card-view.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { MetricsCard } from '../../../ds/components/MetricsCard';\nimport { MetricsLineChart } from '../../../ds/components/MetricsLineChart';\nimport { Tab, TabContent, TabList, Tabs } from '../../../ds/components/Tabs';\nimport type { TokenTimelinePoint, TokenUsageTimeSeriesInterval } from '../hooks/use-token-usage-timeseries';\nimport { CHART_COLORS, formatCompact, formatCost } from './metrics-utils';\n\ntype TokenUsageTimelineTab = 'tokens' | 'cost';\n\nfunction sumMetric(dataKey: 'input' | 'output' | 'cost', formatter: (value: number) => string = formatCompact) {\n return (data: Record<string, unknown>[]) => ({\n value: formatter(data.reduce((sum, point) => sum + (typeof point[dataKey] === 'number' ? point[dataKey] : 0), 0)),\n });\n}\n\nconst tokenSeries = [\n {\n dataKey: 'input',\n label: 'Input tokens',\n color: CHART_COLORS.blue,\n aggregate: sumMetric('input'),\n },\n {\n dataKey: 'output',\n label: 'Output tokens',\n color: CHART_COLORS.yellow,\n aggregate: sumMetric('output'),\n },\n];\n\nfunction isTokenUsageTimelineTab(value: string): value is TokenUsageTimelineTab {\n return value === 'tokens' || value === 'cost';\n}\n\nexport interface TokenUsageTimelineCardViewProps {\n data: TokenTimelinePoint[] | undefined;\n interval: TokenUsageTimeSeriesInterval | undefined;\n isLoading: boolean;\n isError: boolean;\n actions?: ReactNode;\n}\n\nexport function TokenUsageTimelineCardView({\n data,\n interval = '1d',\n isLoading,\n isError,\n actions,\n}: TokenUsageTimelineCardViewProps) {\n const [activeTab, setActiveTab] = useState<TokenUsageTimelineTab>('tokens');\n\n const points = data ?? [];\n const chartPoints = points.map(point => ({ ...point }));\n const hasData = points.length > 0;\n const totalTokens = points.reduce((sum, point) => sum + point.total, 0);\n const costPoints = points.filter(point => point.cost != null && point.cost > 0);\n const costChartPoints = costPoints.map(point => ({ ...point }));\n const uniqueCostUnits = new Set(costPoints.map(point => point.costUnit).filter((unit): unit is string => !!unit));\n const hasSingleCostUnit = uniqueCostUnits.size === 1 && costPoints.every(point => point.costUnit != null);\n const costUnit = hasSingleCostUnit ? ([...uniqueCostUnits][0] ?? null) : null;\n const totalCost = hasSingleCostUnit ? costPoints.reduce((sum, point) => sum + (point.cost ?? 0), 0) : 0;\n const hasCostData = hasSingleCostUnit && totalCost > 0;\n const description = interval === '1h' ? 'Input and output tokens per hour.' : 'Input and output tokens per day.';\n\n const costSeries = [\n {\n dataKey: 'cost',\n label: 'Cost',\n color: CHART_COLORS.purple,\n aggregate: sumMetric('cost', value => formatCost(value, costUnit)),\n },\n ];\n\n return (\n <MetricsCard>\n <MetricsCard.TopBar>\n <MetricsCard.TitleAndDescription title=\"Token usage over time\" description={description} />\n {hasData &&\n (activeTab === 'cost' && hasCostData ? (\n <MetricsCard.Summary value={formatCost(totalCost, costUnit)} label=\"Total cost\" />\n ) : (\n <MetricsCard.Summary value={formatCompact(totalTokens)} label=\"Total tokens\" />\n ))}\n {hasData && actions ? <MetricsCard.Actions>{actions}</MetricsCard.Actions> : null}\n </MetricsCard.TopBar>\n {isLoading ? (\n <MetricsCard.Loading />\n ) : isError ? (\n <MetricsCard.Error message=\"Failed to load token usage timeline\" />\n ) : (\n <MetricsCard.Content>\n {!hasData ? (\n <MetricsCard.NoData message=\"No token usage data yet\" />\n ) : (\n <Tabs\n defaultTab=\"tokens\"\n value={activeTab}\n onValueChange={value => {\n if (isTokenUsageTimelineTab(value)) setActiveTab(value);\n }}\n className=\"overflow-visible\"\n >\n <TabList>\n <Tab value=\"tokens\">Tokens</Tab>\n <Tab value=\"cost\">Cost</Tab>\n </TabList>\n <TabContent value=\"tokens\">\n <MetricsLineChart data={chartPoints} series={tokenSeries} />\n </TabContent>\n <TabContent value=\"cost\">\n {hasCostData ? (\n <MetricsLineChart data={costChartPoints} series={costSeries} />\n ) : (\n <MetricsCard.NoData message=\"No cost data yet\" />\n )}\n </TabContent>\n </Tabs>\n )}\n </MetricsCard.Content>\n )}\n </MetricsCard>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-usage-timeline-card-view.es.js","sources":["../../../../src/domains/metrics/components/token-usage-timeline-card-view.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { MetricsCard } from '../../../ds/components/MetricsCard';\nimport { MetricsLineChart, MetricsLineChartLegend } from '../../../ds/components/MetricsLineChart';\nimport { Tab, TabContent, TabList, Tabs } from '../../../ds/components/Tabs';\nimport type { TokenTimelinePoint, TokenUsageTimeSeriesInterval } from '../hooks/use-token-usage-timeseries';\nimport { CHART_COLORS, formatCompact, formatCost } from './metrics-utils';\n\ntype TokenUsageTimelineTab = 'tokens' | 'cost';\n\nfunction sumMetric(dataKey: 'input' | 'output' | 'cost', formatter: (value: number) => string = formatCompact) {\n return (data: Record<string, unknown>[]) => ({\n value: formatter(data.reduce((sum, point) => sum + (typeof point[dataKey] === 'number' ? point[dataKey] : 0), 0)),\n });\n}\n\nconst tokenSeries = [\n {\n dataKey: 'input',\n label: 'Input tokens',\n color: CHART_COLORS.blue,\n aggregate: sumMetric('input'),\n },\n {\n dataKey: 'output',\n label: 'Output tokens',\n color: CHART_COLORS.yellow,\n aggregate: sumMetric('output'),\n },\n];\n\nfunction isTokenUsageTimelineTab(value: string): value is TokenUsageTimelineTab {\n return value === 'tokens' || value === 'cost';\n}\n\nexport interface TokenUsageTimelineCardViewProps {\n data: TokenTimelinePoint[] | undefined;\n interval: TokenUsageTimeSeriesInterval | undefined;\n isLoading: boolean;\n isError: boolean;\n actions?: ReactNode;\n}\n\nexport function TokenUsageTimelineCardView({\n data,\n interval = '1d',\n isLoading,\n isError,\n actions,\n}: TokenUsageTimelineCardViewProps) {\n const [activeTab, setActiveTab] = useState<TokenUsageTimelineTab>('tokens');\n\n const points = data ?? [];\n const chartPoints = points.map(point => ({ ...point }));\n const hasData = points.length > 0;\n const costPoints = points.filter(point => point.cost != null && point.cost > 0);\n const costChartPoints = costPoints.map(point => ({ ...point }));\n const uniqueCostUnits = new Set(costPoints.map(point => point.costUnit).filter((unit): unit is string => !!unit));\n const hasSingleCostUnit = uniqueCostUnits.size === 1 && costPoints.every(point => point.costUnit != null);\n const costUnit = hasSingleCostUnit ? ([...uniqueCostUnits][0] ?? null) : null;\n const totalCost = hasSingleCostUnit ? costPoints.reduce((sum, point) => sum + (point.cost ?? 0), 0) : 0;\n const hasCostData = hasSingleCostUnit && totalCost > 0;\n const description = interval === '1h' ? 'Input and output tokens per hour.' : 'Input and output tokens per day.';\n\n const costSeries = [\n {\n dataKey: 'cost',\n label: 'Cost',\n color: CHART_COLORS.purple,\n aggregate: sumMetric('cost', value => formatCost(value, costUnit)),\n },\n ];\n\n return (\n <MetricsCard>\n <MetricsCard.TopBar>\n <MetricsCard.TitleAndDescription title=\"Token usage over time\" description={description} />\n {hasData && actions ? <MetricsCard.Actions>{actions}</MetricsCard.Actions> : null}\n </MetricsCard.TopBar>\n {isLoading ? (\n <MetricsCard.Loading />\n ) : isError ? (\n <MetricsCard.Error message=\"Failed to load token usage timeline\" />\n ) : (\n <MetricsCard.Content>\n {!hasData ? (\n <MetricsCard.NoData message=\"No token usage data yet\" />\n ) : (\n <Tabs\n defaultTab=\"tokens\"\n value={activeTab}\n onValueChange={value => {\n if (isTokenUsageTimelineTab(value)) setActiveTab(value);\n }}\n className=\"overflow-visible\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2 [&>:first-child]:w-auto\">\n <TabList>\n <Tab value=\"tokens\">Tokens</Tab>\n <Tab value=\"cost\">Cost</Tab>\n </TabList>\n {activeTab === 'tokens' ? (\n <MetricsLineChartLegend data={chartPoints} series={tokenSeries} />\n ) : hasCostData ? (\n <MetricsLineChartLegend data={costChartPoints} series={costSeries} />\n ) : null}\n </div>\n <TabContent value=\"tokens\" className=\"pt-3\">\n <MetricsLineChart data={chartPoints} series={tokenSeries} showLegend={false} />\n </TabContent>\n <TabContent value=\"cost\" className=\"pt-3\">\n {hasCostData ? (\n <MetricsLineChart data={costChartPoints} series={costSeries} showLegend={false} />\n ) : (\n <MetricsCard.NoData message=\"No cost data yet\" />\n )}\n </TabContent>\n </Tabs>\n )}\n </MetricsCard.Content>\n )}\n </MetricsCard>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5
5
  const jsxRuntime = require('react/jsx-runtime');
6
6
  const React = require('react');
7
7
  const horizontalBars = require('../../../horizontal-bars-BkVi2dEb.cjs');
8
- const metricsCard = require('../../../metrics-card-DCCHIG-z.cjs');
8
+ const metricsCard = require('../../../metrics-card-DzcVJTAN.cjs');
9
9
  const tabsContent = require('../../../tabs-content-DlCJoQUW.cjs');
10
10
  const tabsRoot = require('../../../tabs-root-COCL6jcx.cjs');
11
11
  const tabsTab = require('../../../tabs-tab-DFmRMdi3.cjs');
@@ -80,7 +80,7 @@ function TracesVolumeCardView({
80
80
  /* @__PURE__ */ jsxRuntime.jsx(tabsTab.Tab, { value: "workflows", children: "Workflows" }),
81
81
  /* @__PURE__ */ jsxRuntime.jsx(tabsTab.Tab, { value: "tools", children: "Tools" })
82
82
  ] }),
83
- /* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "agents", children: data.agentData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
83
+ /* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "agents", className: "pt-3", children: data.agentData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
84
84
  VolumeBars,
85
85
  {
86
86
  data: data.agentData,
@@ -89,7 +89,7 @@ function TracesVolumeCardView({
89
89
  LinkComponent
90
90
  }
91
91
  ) : /* @__PURE__ */ jsxRuntime.jsx(metricsCard.MetricsCard.NoData, { message: "No agent data yet" }) }),
92
- /* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "workflows", children: data.workflowData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
92
+ /* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "workflows", className: "pt-3", children: data.workflowData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
93
93
  VolumeBars,
94
94
  {
95
95
  data: data.workflowData,
@@ -98,7 +98,7 @@ function TracesVolumeCardView({
98
98
  LinkComponent
99
99
  }
100
100
  ) : /* @__PURE__ */ jsxRuntime.jsx(metricsCard.MetricsCard.NoData, { message: "No workflow data yet" }) }),
101
- /* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "tools", children: data.toolData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
101
+ /* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "tools", className: "pt-3", children: data.toolData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
102
102
  VolumeBars,
103
103
  {
104
104
  data: data.toolData,
@@ -1 +1 @@
1
- {"version":3,"file":"traces-volume-card-view.cjs.js","sources":["../../../../src/domains/metrics/components/traces-volume-card-view.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { HorizontalBars } from '../../../ds/components/HorizontalBars/horizontal-bars';\nimport { MetricsCard } from '../../../ds/components/MetricsCard/metrics-card';\nimport { TabContent } from '../../../ds/components/Tabs/tabs-content';\nimport { TabList } from '../../../ds/components/Tabs/tabs-list';\nimport { Tabs } from '../../../ds/components/Tabs/tabs-root';\nimport { Tab } from '../../../ds/components/Tabs/tabs-tab';\nimport type { LinkComponent } from '../../../ds/types/link-component';\nimport type { VolumeRow } from '../hooks/use-trace-volume-metrics';\nimport { CHART_COLORS, formatCompact } from './metrics-utils';\n\nexport type VolumeTab = 'agents' | 'workflows' | 'tools';\n\nfunction VolumeBars({\n data,\n rowHrefs,\n errorHrefs,\n LinkComponent,\n}: {\n data: VolumeRow[];\n rowHrefs?: (row: VolumeRow) => string | undefined;\n errorHrefs?: (row: VolumeRow) => string | undefined;\n LinkComponent?: LinkComponent;\n}) {\n return (\n <HorizontalBars\n LinkComponent={LinkComponent}\n data={data.map(d => {\n const errorHref = errorHrefs?.(d);\n const rowHref = rowHrefs?.(d);\n // HorizontalBars ignores per-segment `hrefs` whenever a row-level\n // `href` is set (to avoid nested anchors). When we want the Errors\n // segment to drill somewhere different from the rest of the row,\n // drop the row-level link and split navigation across segments\n // instead so each target is reachable.\n if (errorHref) {\n return {\n name: d.name,\n values: [d.completed, d.errors],\n hrefs: [rowHref, errorHref],\n };\n }\n return {\n name: d.name,\n values: [d.completed, d.errors],\n href: rowHref,\n };\n })}\n segments={[\n { label: 'Completed', color: CHART_COLORS.blueDark },\n { label: 'Errors', color: CHART_COLORS.pink },\n ]}\n maxVal={Math.max(...data.map(d => d.completed + d.errors))}\n fmt={formatCompact}\n />\n );\n}\n\nexport interface TracesVolumeCardViewProps {\n data: { agentData: VolumeRow[]; workflowData: VolumeRow[]; toolData: VolumeRow[] } | undefined;\n isLoading: boolean;\n isError: boolean;\n /** Optional drilldown: returns href for clicking a whole bar row. */\n getRowHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /** Optional drilldown: returns href for clicking the \"Errors\" segment of a bar. */\n getErrorSegmentHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /**\n * Optional slot for top-bar action buttons.\n * Pass a function to receive the active tab so actions can scope themselves to the current entity type.\n */\n actions?: ReactNode | ((tab: VolumeTab) => ReactNode);\n /** Override how drilldown links are rendered (e.g. router-aware adapter). Defaults to `<a>`. */\n LinkComponent?: LinkComponent;\n}\n\nexport function TracesVolumeCardView({\n data,\n isLoading,\n isError,\n getRowHref,\n getErrorSegmentHref,\n actions,\n LinkComponent,\n}: TracesVolumeCardViewProps) {\n const [activeTab, setActiveTab] = useState<VolumeTab>('agents');\n const renderedActions = typeof actions === 'function' ? actions(activeTab) : actions;\n const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);\n const total = data\n ? [...data.agentData, ...data.workflowData, ...data.toolData].reduce((s, d) => s + d.completed + d.errors, 0)\n : 0;\n\n const tabRowHrefs = (tab: VolumeTab) => (getRowHref ? (row: VolumeRow) => getRowHref(tab, row) : undefined);\n const tabErrorHrefs = (tab: VolumeTab) =>\n getErrorSegmentHref ? (row: VolumeRow) => getErrorSegmentHref(tab, row) : undefined;\n\n return (\n <MetricsCard>\n <MetricsCard.TopBar>\n <MetricsCard.TitleAndDescription title=\"Trace Volume\" description=\"Runs and call counts.\" />\n {hasData && <MetricsCard.Summary value={formatCompact(total)} label=\"Total runs\" />}\n {renderedActions ? <MetricsCard.Actions>{renderedActions}</MetricsCard.Actions> : null}\n </MetricsCard.TopBar>\n {isLoading ? (\n <MetricsCard.Loading />\n ) : isError ? (\n <MetricsCard.Error message=\"Failed to load trace volume data\" />\n ) : (\n <MetricsCard.Content>\n {!hasData ? (\n <MetricsCard.NoData message=\"No trace volume data yet\" />\n ) : (\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n defaultTab=\"agents\"\n className=\"grid h-full grid-rows-[auto_1fr] overflow-y-auto\"\n >\n <TabList>\n <Tab value=\"agents\">Agents</Tab>\n <Tab value=\"workflows\">Workflows</Tab>\n <Tab value=\"tools\">Tools</Tab>\n </TabList>\n <TabContent value=\"agents\">\n {data.agentData.length > 0 ? (\n <VolumeBars\n data={data.agentData}\n rowHrefs={tabRowHrefs('agents')}\n errorHrefs={tabErrorHrefs('agents')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No agent data yet\" />\n )}\n </TabContent>\n <TabContent value=\"workflows\">\n {data.workflowData.length > 0 ? (\n <VolumeBars\n data={data.workflowData}\n rowHrefs={tabRowHrefs('workflows')}\n errorHrefs={tabErrorHrefs('workflows')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No workflow data yet\" />\n )}\n </TabContent>\n <TabContent value=\"tools\">\n {data.toolData.length > 0 ? (\n <VolumeBars\n data={data.toolData}\n rowHrefs={tabRowHrefs('tools')}\n errorHrefs={tabErrorHrefs('tools')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No tool data yet\" />\n )}\n </TabContent>\n </Tabs>\n )}\n </MetricsCard.Content>\n )}\n </MetricsCard>\n );\n}\n"],"names":["jsx","HorizontalBars","CHART_COLORS","formatCompact","useState","MetricsCard","jsxs","Tabs","TabList","Tab","TabContent"],"mappings":"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"}
1
+ {"version":3,"file":"traces-volume-card-view.cjs.js","sources":["../../../../src/domains/metrics/components/traces-volume-card-view.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { HorizontalBars } from '../../../ds/components/HorizontalBars/horizontal-bars';\nimport { MetricsCard } from '../../../ds/components/MetricsCard/metrics-card';\nimport { TabContent } from '../../../ds/components/Tabs/tabs-content';\nimport { TabList } from '../../../ds/components/Tabs/tabs-list';\nimport { Tabs } from '../../../ds/components/Tabs/tabs-root';\nimport { Tab } from '../../../ds/components/Tabs/tabs-tab';\nimport type { LinkComponent } from '../../../ds/types/link-component';\nimport type { VolumeRow } from '../hooks/use-trace-volume-metrics';\nimport { CHART_COLORS, formatCompact } from './metrics-utils';\n\nexport type VolumeTab = 'agents' | 'workflows' | 'tools';\n\nfunction VolumeBars({\n data,\n rowHrefs,\n errorHrefs,\n LinkComponent,\n}: {\n data: VolumeRow[];\n rowHrefs?: (row: VolumeRow) => string | undefined;\n errorHrefs?: (row: VolumeRow) => string | undefined;\n LinkComponent?: LinkComponent;\n}) {\n return (\n <HorizontalBars\n LinkComponent={LinkComponent}\n data={data.map(d => {\n const errorHref = errorHrefs?.(d);\n const rowHref = rowHrefs?.(d);\n // HorizontalBars ignores per-segment `hrefs` whenever a row-level\n // `href` is set (to avoid nested anchors). When we want the Errors\n // segment to drill somewhere different from the rest of the row,\n // drop the row-level link and split navigation across segments\n // instead so each target is reachable.\n if (errorHref) {\n return {\n name: d.name,\n values: [d.completed, d.errors],\n hrefs: [rowHref, errorHref],\n };\n }\n return {\n name: d.name,\n values: [d.completed, d.errors],\n href: rowHref,\n };\n })}\n segments={[\n { label: 'Completed', color: CHART_COLORS.blueDark },\n { label: 'Errors', color: CHART_COLORS.pink },\n ]}\n maxVal={Math.max(...data.map(d => d.completed + d.errors))}\n fmt={formatCompact}\n />\n );\n}\n\nexport interface TracesVolumeCardViewProps {\n data: { agentData: VolumeRow[]; workflowData: VolumeRow[]; toolData: VolumeRow[] } | undefined;\n isLoading: boolean;\n isError: boolean;\n /** Optional drilldown: returns href for clicking a whole bar row. */\n getRowHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /** Optional drilldown: returns href for clicking the \"Errors\" segment of a bar. */\n getErrorSegmentHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /**\n * Optional slot for top-bar action buttons.\n * Pass a function to receive the active tab so actions can scope themselves to the current entity type.\n */\n actions?: ReactNode | ((tab: VolumeTab) => ReactNode);\n /** Override how drilldown links are rendered (e.g. router-aware adapter). Defaults to `<a>`. */\n LinkComponent?: LinkComponent;\n}\n\nexport function TracesVolumeCardView({\n data,\n isLoading,\n isError,\n getRowHref,\n getErrorSegmentHref,\n actions,\n LinkComponent,\n}: TracesVolumeCardViewProps) {\n const [activeTab, setActiveTab] = useState<VolumeTab>('agents');\n const renderedActions = typeof actions === 'function' ? actions(activeTab) : actions;\n const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);\n const total = data\n ? [...data.agentData, ...data.workflowData, ...data.toolData].reduce((s, d) => s + d.completed + d.errors, 0)\n : 0;\n\n const tabRowHrefs = (tab: VolumeTab) => (getRowHref ? (row: VolumeRow) => getRowHref(tab, row) : undefined);\n const tabErrorHrefs = (tab: VolumeTab) =>\n getErrorSegmentHref ? (row: VolumeRow) => getErrorSegmentHref(tab, row) : undefined;\n\n return (\n <MetricsCard>\n <MetricsCard.TopBar>\n <MetricsCard.TitleAndDescription title=\"Trace Volume\" description=\"Runs and call counts.\" />\n {hasData && <MetricsCard.Summary value={formatCompact(total)} label=\"Total runs\" />}\n {renderedActions ? <MetricsCard.Actions>{renderedActions}</MetricsCard.Actions> : null}\n </MetricsCard.TopBar>\n {isLoading ? (\n <MetricsCard.Loading />\n ) : isError ? (\n <MetricsCard.Error message=\"Failed to load trace volume data\" />\n ) : (\n <MetricsCard.Content>\n {!hasData ? (\n <MetricsCard.NoData message=\"No trace volume data yet\" />\n ) : (\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n defaultTab=\"agents\"\n className=\"grid h-full grid-rows-[auto_1fr] overflow-y-auto\"\n >\n <TabList>\n <Tab value=\"agents\">Agents</Tab>\n <Tab value=\"workflows\">Workflows</Tab>\n <Tab value=\"tools\">Tools</Tab>\n </TabList>\n <TabContent value=\"agents\" className=\"pt-3\">\n {data.agentData.length > 0 ? (\n <VolumeBars\n data={data.agentData}\n rowHrefs={tabRowHrefs('agents')}\n errorHrefs={tabErrorHrefs('agents')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No agent data yet\" />\n )}\n </TabContent>\n <TabContent value=\"workflows\" className=\"pt-3\">\n {data.workflowData.length > 0 ? (\n <VolumeBars\n data={data.workflowData}\n rowHrefs={tabRowHrefs('workflows')}\n errorHrefs={tabErrorHrefs('workflows')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No workflow data yet\" />\n )}\n </TabContent>\n <TabContent value=\"tools\" className=\"pt-3\">\n {data.toolData.length > 0 ? (\n <VolumeBars\n data={data.toolData}\n rowHrefs={tabRowHrefs('tools')}\n errorHrefs={tabErrorHrefs('tools')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No tool data yet\" />\n )}\n </TabContent>\n </Tabs>\n )}\n </MetricsCard.Content>\n )}\n </MetricsCard>\n );\n}\n"],"names":["jsx","HorizontalBars","CHART_COLORS","formatCompact","useState","MetricsCard","jsxs","Tabs","TabList","Tab","TabContent"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { useState } from 'react';
3
3
  import { H as HorizontalBars } from '../../../horizontal-bars-nTOFylzc.js';
4
- import { M as MetricsCard } from '../../../metrics-card-Bzm6m1dy.js';
4
+ import { M as MetricsCard } from '../../../metrics-card-C2RTi5Ew.js';
5
5
  import { T as TabContent } from '../../../tabs-content-7ODUUdQ0.js';
6
6
  import { a as Tabs, T as TabList } from '../../../tabs-root-UNPxoGhW.js';
7
7
  import { T as Tab } from '../../../tabs-tab-DluwCnDF.js';
@@ -76,7 +76,7 @@ function TracesVolumeCardView({
76
76
  /* @__PURE__ */ jsx(Tab, { value: "workflows", children: "Workflows" }),
77
77
  /* @__PURE__ */ jsx(Tab, { value: "tools", children: "Tools" })
78
78
  ] }),
79
- /* @__PURE__ */ jsx(TabContent, { value: "agents", children: data.agentData.length > 0 ? /* @__PURE__ */ jsx(
79
+ /* @__PURE__ */ jsx(TabContent, { value: "agents", className: "pt-3", children: data.agentData.length > 0 ? /* @__PURE__ */ jsx(
80
80
  VolumeBars,
81
81
  {
82
82
  data: data.agentData,
@@ -85,7 +85,7 @@ function TracesVolumeCardView({
85
85
  LinkComponent
86
86
  }
87
87
  ) : /* @__PURE__ */ jsx(MetricsCard.NoData, { message: "No agent data yet" }) }),
88
- /* @__PURE__ */ jsx(TabContent, { value: "workflows", children: data.workflowData.length > 0 ? /* @__PURE__ */ jsx(
88
+ /* @__PURE__ */ jsx(TabContent, { value: "workflows", className: "pt-3", children: data.workflowData.length > 0 ? /* @__PURE__ */ jsx(
89
89
  VolumeBars,
90
90
  {
91
91
  data: data.workflowData,
@@ -94,7 +94,7 @@ function TracesVolumeCardView({
94
94
  LinkComponent
95
95
  }
96
96
  ) : /* @__PURE__ */ jsx(MetricsCard.NoData, { message: "No workflow data yet" }) }),
97
- /* @__PURE__ */ jsx(TabContent, { value: "tools", children: data.toolData.length > 0 ? /* @__PURE__ */ jsx(
97
+ /* @__PURE__ */ jsx(TabContent, { value: "tools", className: "pt-3", children: data.toolData.length > 0 ? /* @__PURE__ */ jsx(
98
98
  VolumeBars,
99
99
  {
100
100
  data: data.toolData,
@@ -1 +1 @@
1
- {"version":3,"file":"traces-volume-card-view.es.js","sources":["../../../../src/domains/metrics/components/traces-volume-card-view.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { HorizontalBars } from '../../../ds/components/HorizontalBars/horizontal-bars';\nimport { MetricsCard } from '../../../ds/components/MetricsCard/metrics-card';\nimport { TabContent } from '../../../ds/components/Tabs/tabs-content';\nimport { TabList } from '../../../ds/components/Tabs/tabs-list';\nimport { Tabs } from '../../../ds/components/Tabs/tabs-root';\nimport { Tab } from '../../../ds/components/Tabs/tabs-tab';\nimport type { LinkComponent } from '../../../ds/types/link-component';\nimport type { VolumeRow } from '../hooks/use-trace-volume-metrics';\nimport { CHART_COLORS, formatCompact } from './metrics-utils';\n\nexport type VolumeTab = 'agents' | 'workflows' | 'tools';\n\nfunction VolumeBars({\n data,\n rowHrefs,\n errorHrefs,\n LinkComponent,\n}: {\n data: VolumeRow[];\n rowHrefs?: (row: VolumeRow) => string | undefined;\n errorHrefs?: (row: VolumeRow) => string | undefined;\n LinkComponent?: LinkComponent;\n}) {\n return (\n <HorizontalBars\n LinkComponent={LinkComponent}\n data={data.map(d => {\n const errorHref = errorHrefs?.(d);\n const rowHref = rowHrefs?.(d);\n // HorizontalBars ignores per-segment `hrefs` whenever a row-level\n // `href` is set (to avoid nested anchors). When we want the Errors\n // segment to drill somewhere different from the rest of the row,\n // drop the row-level link and split navigation across segments\n // instead so each target is reachable.\n if (errorHref) {\n return {\n name: d.name,\n values: [d.completed, d.errors],\n hrefs: [rowHref, errorHref],\n };\n }\n return {\n name: d.name,\n values: [d.completed, d.errors],\n href: rowHref,\n };\n })}\n segments={[\n { label: 'Completed', color: CHART_COLORS.blueDark },\n { label: 'Errors', color: CHART_COLORS.pink },\n ]}\n maxVal={Math.max(...data.map(d => d.completed + d.errors))}\n fmt={formatCompact}\n />\n );\n}\n\nexport interface TracesVolumeCardViewProps {\n data: { agentData: VolumeRow[]; workflowData: VolumeRow[]; toolData: VolumeRow[] } | undefined;\n isLoading: boolean;\n isError: boolean;\n /** Optional drilldown: returns href for clicking a whole bar row. */\n getRowHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /** Optional drilldown: returns href for clicking the \"Errors\" segment of a bar. */\n getErrorSegmentHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /**\n * Optional slot for top-bar action buttons.\n * Pass a function to receive the active tab so actions can scope themselves to the current entity type.\n */\n actions?: ReactNode | ((tab: VolumeTab) => ReactNode);\n /** Override how drilldown links are rendered (e.g. router-aware adapter). Defaults to `<a>`. */\n LinkComponent?: LinkComponent;\n}\n\nexport function TracesVolumeCardView({\n data,\n isLoading,\n isError,\n getRowHref,\n getErrorSegmentHref,\n actions,\n LinkComponent,\n}: TracesVolumeCardViewProps) {\n const [activeTab, setActiveTab] = useState<VolumeTab>('agents');\n const renderedActions = typeof actions === 'function' ? actions(activeTab) : actions;\n const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);\n const total = data\n ? [...data.agentData, ...data.workflowData, ...data.toolData].reduce((s, d) => s + d.completed + d.errors, 0)\n : 0;\n\n const tabRowHrefs = (tab: VolumeTab) => (getRowHref ? (row: VolumeRow) => getRowHref(tab, row) : undefined);\n const tabErrorHrefs = (tab: VolumeTab) =>\n getErrorSegmentHref ? (row: VolumeRow) => getErrorSegmentHref(tab, row) : undefined;\n\n return (\n <MetricsCard>\n <MetricsCard.TopBar>\n <MetricsCard.TitleAndDescription title=\"Trace Volume\" description=\"Runs and call counts.\" />\n {hasData && <MetricsCard.Summary value={formatCompact(total)} label=\"Total runs\" />}\n {renderedActions ? <MetricsCard.Actions>{renderedActions}</MetricsCard.Actions> : null}\n </MetricsCard.TopBar>\n {isLoading ? (\n <MetricsCard.Loading />\n ) : isError ? (\n <MetricsCard.Error message=\"Failed to load trace volume data\" />\n ) : (\n <MetricsCard.Content>\n {!hasData ? (\n <MetricsCard.NoData message=\"No trace volume data yet\" />\n ) : (\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n defaultTab=\"agents\"\n className=\"grid h-full grid-rows-[auto_1fr] overflow-y-auto\"\n >\n <TabList>\n <Tab value=\"agents\">Agents</Tab>\n <Tab value=\"workflows\">Workflows</Tab>\n <Tab value=\"tools\">Tools</Tab>\n </TabList>\n <TabContent value=\"agents\">\n {data.agentData.length > 0 ? (\n <VolumeBars\n data={data.agentData}\n rowHrefs={tabRowHrefs('agents')}\n errorHrefs={tabErrorHrefs('agents')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No agent data yet\" />\n )}\n </TabContent>\n <TabContent value=\"workflows\">\n {data.workflowData.length > 0 ? (\n <VolumeBars\n data={data.workflowData}\n rowHrefs={tabRowHrefs('workflows')}\n errorHrefs={tabErrorHrefs('workflows')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No workflow data yet\" />\n )}\n </TabContent>\n <TabContent value=\"tools\">\n {data.toolData.length > 0 ? (\n <VolumeBars\n data={data.toolData}\n rowHrefs={tabRowHrefs('tools')}\n errorHrefs={tabErrorHrefs('tools')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No tool data yet\" />\n )}\n </TabContent>\n </Tabs>\n )}\n </MetricsCard.Content>\n )}\n </MetricsCard>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAcA,SAAS,UAAA,CAAW;AAAA,EAClB,IAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,aAAA;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,CAAA,CAAA,KAAK;AAClB,QAAA,MAAM,SAAA,GAAY,aAAa,CAAC,CAAA;AAChC,QAAA,MAAM,OAAA,GAAU,WAAW,CAAC,CAAA;AAM5B,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,OAAO;AAAA,YACL,MAAM,CAAA,CAAE,IAAA;AAAA,YACR,MAAA,EAAQ,CAAC,CAAA,CAAE,SAAA,EAAW,EAAE,MAAM,CAAA;AAAA,YAC9B,KAAA,EAAO,CAAC,OAAA,EAAS,SAAS;AAAA,WAC5B;AAAA,QACF;AACA,QAAA,OAAO;AAAA,UACL,MAAM,CAAA,CAAE,IAAA;AAAA,UACR,MAAA,EAAQ,CAAC,CAAA,CAAE,SAAA,EAAW,EAAE,MAAM,CAAA;AAAA,UAC9B,IAAA,EAAM;AAAA,SACR;AAAA,MACF,CAAC,CAAA;AAAA,MACD,QAAA,EAAU;AAAA,QACR,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,aAAa,QAAA,EAAS;AAAA,QACnD,EAAE,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,aAAa,IAAA;AAAK,OAC9C;AAAA,MACA,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,MAAM,CAAC,CAAA;AAAA,MACzD,GAAA,EAAK;AAAA;AAAA,GACP;AAEJ;AAmBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,IAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,mBAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAoB,QAAQ,CAAA;AAC9D,EAAA,MAAM,kBAAkB,OAAO,OAAA,KAAY,UAAA,GAAa,OAAA,CAAQ,SAAS,CAAA,GAAI,OAAA;AAC7E,EAAA,MAAM,OAAA,GAAU,CAAC,CAAC,IAAA,KAAS,KAAK,SAAA,CAAU,MAAA,GAAS,CAAA,IAAK,IAAA,CAAK,YAAA,CAAa,MAAA,GAAS,CAAA,IAAK,IAAA,CAAK,SAAS,MAAA,GAAS,CAAA,CAAA;AAC/G,EAAA,MAAM,KAAA,GAAQ,OACV,CAAC,GAAG,KAAK,SAAA,EAAW,GAAG,IAAA,CAAK,YAAA,EAAc,GAAG,IAAA,CAAK,QAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,EAAE,SAAA,GAAY,CAAA,CAAE,MAAA,EAAQ,CAAC,CAAA,GAC1G,CAAA;AAEJ,EAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAAoB,UAAA,GAAa,CAAC,GAAA,KAAmB,UAAA,CAAW,GAAA,EAAK,GAAG,CAAA,GAAI,MAAA;AACjG,EAAA,MAAM,aAAA,GAAgB,CAAC,GAAA,KACrB,mBAAA,GAAsB,CAAC,GAAA,KAAmB,mBAAA,CAAoB,GAAA,EAAK,GAAG,CAAA,GAAI,MAAA;AAE5E,EAAA,4BACG,WAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,WAAA,CAAY,QAAZ,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,YAAY,mBAAA,EAAZ,EAAgC,KAAA,EAAM,cAAA,EAAe,aAAY,uBAAA,EAAwB,CAAA;AAAA,MACzF,OAAA,oBAAW,GAAA,CAAC,WAAA,CAAY,OAAA,EAAZ,EAAoB,OAAO,aAAA,CAAc,KAAK,CAAA,EAAG,KAAA,EAAM,YAAA,EAAa,CAAA;AAAA,MAChF,kCAAkB,GAAA,CAAC,WAAA,CAAY,OAAA,EAAZ,EAAqB,2BAAgB,CAAA,GAAyB;AAAA,KAAA,EACpF,CAAA;AAAA,IACC,SAAA,mBACC,GAAA,CAAC,WAAA,CAAY,OAAA,EAAZ,EAAoB,CAAA,GACnB,OAAA,mBACF,GAAA,CAAC,WAAA,CAAY,KAAA,EAAZ,EAAkB,OAAA,EAAQ,kCAAA,EAAmC,oBAE9D,GAAA,CAAC,WAAA,CAAY,OAAA,EAAZ,EACE,QAAA,EAAA,CAAC,OAAA,mBACA,GAAA,CAAC,WAAA,CAAY,MAAA,EAAZ,EAAmB,OAAA,EAAQ,0BAAA,EAA2B,CAAA,mBAEvD,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,SAAA;AAAA,QACP,aAAA,EAAe,YAAA;AAAA,QACf,UAAA,EAAW,QAAA;AAAA,QACX,SAAA,EAAU,kDAAA;AAAA,QAEV,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,OAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,GAAA,EAAA,EAAI,KAAA,EAAM,QAAA,EAAS,QAAA,EAAA,QAAA,EAAM,CAAA;AAAA,4BAC1B,GAAA,CAAC,GAAA,EAAA,EAAI,KAAA,EAAM,WAAA,EAAY,QAAA,EAAA,WAAA,EAAS,CAAA;AAAA,4BAChC,GAAA,CAAC,GAAA,EAAA,EAAI,KAAA,EAAM,OAAA,EAAQ,QAAA,EAAA,OAAA,EAAK;AAAA,WAAA,EAC1B,CAAA;AAAA,8BACC,UAAA,EAAA,EAAW,KAAA,EAAM,UACf,QAAA,EAAA,IAAA,CAAK,SAAA,CAAU,SAAS,CAAA,mBACvB,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,MAAM,IAAA,CAAK,SAAA;AAAA,cACX,QAAA,EAAU,YAAY,QAAQ,CAAA;AAAA,cAC9B,UAAA,EAAY,cAAc,QAAQ,CAAA;AAAA,cAClC;AAAA;AAAA,8BAGF,GAAA,CAAC,WAAA,CAAY,QAAZ,EAAmB,OAAA,EAAQ,qBAAoB,CAAA,EAEpD,CAAA;AAAA,8BACC,UAAA,EAAA,EAAW,KAAA,EAAM,aACf,QAAA,EAAA,IAAA,CAAK,YAAA,CAAa,SAAS,CAAA,mBAC1B,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,MAAM,IAAA,CAAK,YAAA;AAAA,cACX,QAAA,EAAU,YAAY,WAAW,CAAA;AAAA,cACjC,UAAA,EAAY,cAAc,WAAW,CAAA;AAAA,cACrC;AAAA;AAAA,8BAGF,GAAA,CAAC,WAAA,CAAY,QAAZ,EAAmB,OAAA,EAAQ,wBAAuB,CAAA,EAEvD,CAAA;AAAA,8BACC,UAAA,EAAA,EAAW,KAAA,EAAM,SACf,QAAA,EAAA,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,mBACtB,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,MAAM,IAAA,CAAK,QAAA;AAAA,cACX,QAAA,EAAU,YAAY,OAAO,CAAA;AAAA,cAC7B,UAAA,EAAY,cAAc,OAAO,CAAA;AAAA,cACjC;AAAA;AAAA,8BAGF,GAAA,CAAC,WAAA,CAAY,QAAZ,EAAmB,OAAA,EAAQ,oBAAmB,CAAA,EAEnD;AAAA;AAAA;AAAA,KACF,EAEJ;AAAA,GAAA,EAEJ,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"traces-volume-card-view.es.js","sources":["../../../../src/domains/metrics/components/traces-volume-card-view.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { HorizontalBars } from '../../../ds/components/HorizontalBars/horizontal-bars';\nimport { MetricsCard } from '../../../ds/components/MetricsCard/metrics-card';\nimport { TabContent } from '../../../ds/components/Tabs/tabs-content';\nimport { TabList } from '../../../ds/components/Tabs/tabs-list';\nimport { Tabs } from '../../../ds/components/Tabs/tabs-root';\nimport { Tab } from '../../../ds/components/Tabs/tabs-tab';\nimport type { LinkComponent } from '../../../ds/types/link-component';\nimport type { VolumeRow } from '../hooks/use-trace-volume-metrics';\nimport { CHART_COLORS, formatCompact } from './metrics-utils';\n\nexport type VolumeTab = 'agents' | 'workflows' | 'tools';\n\nfunction VolumeBars({\n data,\n rowHrefs,\n errorHrefs,\n LinkComponent,\n}: {\n data: VolumeRow[];\n rowHrefs?: (row: VolumeRow) => string | undefined;\n errorHrefs?: (row: VolumeRow) => string | undefined;\n LinkComponent?: LinkComponent;\n}) {\n return (\n <HorizontalBars\n LinkComponent={LinkComponent}\n data={data.map(d => {\n const errorHref = errorHrefs?.(d);\n const rowHref = rowHrefs?.(d);\n // HorizontalBars ignores per-segment `hrefs` whenever a row-level\n // `href` is set (to avoid nested anchors). When we want the Errors\n // segment to drill somewhere different from the rest of the row,\n // drop the row-level link and split navigation across segments\n // instead so each target is reachable.\n if (errorHref) {\n return {\n name: d.name,\n values: [d.completed, d.errors],\n hrefs: [rowHref, errorHref],\n };\n }\n return {\n name: d.name,\n values: [d.completed, d.errors],\n href: rowHref,\n };\n })}\n segments={[\n { label: 'Completed', color: CHART_COLORS.blueDark },\n { label: 'Errors', color: CHART_COLORS.pink },\n ]}\n maxVal={Math.max(...data.map(d => d.completed + d.errors))}\n fmt={formatCompact}\n />\n );\n}\n\nexport interface TracesVolumeCardViewProps {\n data: { agentData: VolumeRow[]; workflowData: VolumeRow[]; toolData: VolumeRow[] } | undefined;\n isLoading: boolean;\n isError: boolean;\n /** Optional drilldown: returns href for clicking a whole bar row. */\n getRowHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /** Optional drilldown: returns href for clicking the \"Errors\" segment of a bar. */\n getErrorSegmentHref?: (tab: VolumeTab, row: VolumeRow) => string | undefined;\n /**\n * Optional slot for top-bar action buttons.\n * Pass a function to receive the active tab so actions can scope themselves to the current entity type.\n */\n actions?: ReactNode | ((tab: VolumeTab) => ReactNode);\n /** Override how drilldown links are rendered (e.g. router-aware adapter). Defaults to `<a>`. */\n LinkComponent?: LinkComponent;\n}\n\nexport function TracesVolumeCardView({\n data,\n isLoading,\n isError,\n getRowHref,\n getErrorSegmentHref,\n actions,\n LinkComponent,\n}: TracesVolumeCardViewProps) {\n const [activeTab, setActiveTab] = useState<VolumeTab>('agents');\n const renderedActions = typeof actions === 'function' ? actions(activeTab) : actions;\n const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);\n const total = data\n ? [...data.agentData, ...data.workflowData, ...data.toolData].reduce((s, d) => s + d.completed + d.errors, 0)\n : 0;\n\n const tabRowHrefs = (tab: VolumeTab) => (getRowHref ? (row: VolumeRow) => getRowHref(tab, row) : undefined);\n const tabErrorHrefs = (tab: VolumeTab) =>\n getErrorSegmentHref ? (row: VolumeRow) => getErrorSegmentHref(tab, row) : undefined;\n\n return (\n <MetricsCard>\n <MetricsCard.TopBar>\n <MetricsCard.TitleAndDescription title=\"Trace Volume\" description=\"Runs and call counts.\" />\n {hasData && <MetricsCard.Summary value={formatCompact(total)} label=\"Total runs\" />}\n {renderedActions ? <MetricsCard.Actions>{renderedActions}</MetricsCard.Actions> : null}\n </MetricsCard.TopBar>\n {isLoading ? (\n <MetricsCard.Loading />\n ) : isError ? (\n <MetricsCard.Error message=\"Failed to load trace volume data\" />\n ) : (\n <MetricsCard.Content>\n {!hasData ? (\n <MetricsCard.NoData message=\"No trace volume data yet\" />\n ) : (\n <Tabs\n value={activeTab}\n onValueChange={setActiveTab}\n defaultTab=\"agents\"\n className=\"grid h-full grid-rows-[auto_1fr] overflow-y-auto\"\n >\n <TabList>\n <Tab value=\"agents\">Agents</Tab>\n <Tab value=\"workflows\">Workflows</Tab>\n <Tab value=\"tools\">Tools</Tab>\n </TabList>\n <TabContent value=\"agents\" className=\"pt-3\">\n {data.agentData.length > 0 ? (\n <VolumeBars\n data={data.agentData}\n rowHrefs={tabRowHrefs('agents')}\n errorHrefs={tabErrorHrefs('agents')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No agent data yet\" />\n )}\n </TabContent>\n <TabContent value=\"workflows\" className=\"pt-3\">\n {data.workflowData.length > 0 ? (\n <VolumeBars\n data={data.workflowData}\n rowHrefs={tabRowHrefs('workflows')}\n errorHrefs={tabErrorHrefs('workflows')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No workflow data yet\" />\n )}\n </TabContent>\n <TabContent value=\"tools\" className=\"pt-3\">\n {data.toolData.length > 0 ? (\n <VolumeBars\n data={data.toolData}\n rowHrefs={tabRowHrefs('tools')}\n errorHrefs={tabErrorHrefs('tools')}\n LinkComponent={LinkComponent}\n />\n ) : (\n <MetricsCard.NoData message=\"No tool data yet\" />\n )}\n </TabContent>\n </Tabs>\n )}\n </MetricsCard.Content>\n )}\n </MetricsCard>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -4,14 +4,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const react = require('@mastra/react');
6
6
  const reactQuery = require('@tanstack/react-query');
7
+ const domains_metrics_metricsInterval = require('../metrics-interval.cjs.js');
7
8
  const domains_metrics_hooks_useMetricsFilters = require('./use-metrics-filters.cjs.js');
8
9
 
9
- const LATENCY_INTERVAL = "1h";
10
- async function fetchPercentiles(client, metricName, filters) {
10
+ async function fetchPercentiles(client, metricName, filters, interval) {
11
11
  const res = await client.getMetricPercentiles({
12
12
  name: metricName,
13
13
  percentiles: [0.5, 0.95],
14
- interval: LATENCY_INTERVAL,
14
+ interval,
15
15
  filters
16
16
  });
17
17
  const p50Series = res.series.find((s) => s.percentile === 0.5);
@@ -22,7 +22,7 @@ async function fetchPercentiles(client, metricName, filters) {
22
22
  const ts = new Date(p.timestamp);
23
23
  const tsMs = ts.getTime();
24
24
  return {
25
- time: ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
25
+ time: domains_metrics_metricsInterval.formatMetricsBucketLabel(ts, interval),
26
26
  tsMs,
27
27
  p50: Math.round(p.value),
28
28
  p95: Math.round(p95Map.get(tsMs) ?? 0)
@@ -31,20 +31,20 @@ async function fetchPercentiles(client, metricName, filters) {
31
31
  }
32
32
  function useLatencyMetrics() {
33
33
  const client = react.useMastraClient();
34
- const { filters, filterKey } = domains_metrics_hooks_useMetricsFilters.useMetricsFilters();
34
+ const { timestamp, filters, filterKey } = domains_metrics_hooks_useMetricsFilters.useMetricsFilters();
35
+ const interval = domains_metrics_metricsInterval.chooseMetricsInterval(timestamp);
35
36
  return reactQuery.useQuery({
36
- queryKey: ["metrics", "latency", filterKey],
37
+ queryKey: ["metrics", "latency", filterKey, interval],
37
38
  queryFn: async () => {
38
39
  const [agentData, workflowData, toolData] = await Promise.all([
39
- fetchPercentiles(client, "mastra_agent_duration_ms", filters),
40
- fetchPercentiles(client, "mastra_workflow_duration_ms", filters),
41
- fetchPercentiles(client, "mastra_tool_duration_ms", filters)
40
+ fetchPercentiles(client, "mastra_agent_duration_ms", filters, interval),
41
+ fetchPercentiles(client, "mastra_workflow_duration_ms", filters, interval),
42
+ fetchPercentiles(client, "mastra_tool_duration_ms", filters, interval)
42
43
  ]);
43
- return { agentData, workflowData, toolData, interval: LATENCY_INTERVAL };
44
+ return { agentData, workflowData, toolData, interval };
44
45
  }
45
46
  });
46
47
  }
47
48
 
48
- exports.LATENCY_INTERVAL = LATENCY_INTERVAL;
49
49
  exports.useLatencyMetrics = useLatencyMetrics;
50
50
  //# sourceMappingURL=use-latency-metrics.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-latency-metrics.cjs.js","sources":["../../../../src/domains/metrics/hooks/use-latency-metrics.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport interface LatencyPoint {\n [key: string]: unknown;\n time: string;\n /** Raw timestamp (ms since epoch) for the bucket this point represents.\n * Used by drilldown clicks to compute a narrow time window. */\n tsMs: number;\n p50: number;\n p95: number;\n}\n\nexport const LATENCY_INTERVAL: '1h' = '1h';\n\nasync function fetchPercentiles(\n client: ReturnType<typeof useMastraClient>,\n metricName: string,\n filters: Record<string, unknown>,\n): Promise<LatencyPoint[]> {\n const res = await client.getMetricPercentiles({\n name: metricName,\n percentiles: [0.5, 0.95],\n interval: LATENCY_INTERVAL,\n filters,\n });\n\n const p50Series = res.series.find(s => s.percentile === 0.5);\n const p95Series = res.series.find(s => s.percentile === 0.95);\n\n if (!p50Series || !p95Series) return [];\n\n const p95Map = new Map(p95Series.points.map(p => [new Date(p.timestamp).getTime(), p.value]));\n\n return p50Series.points.map(p => {\n const ts = new Date(p.timestamp);\n const tsMs = ts.getTime();\n return {\n time: ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }),\n tsMs,\n p50: Math.round(p.value),\n p95: Math.round(p95Map.get(tsMs) ?? 0),\n };\n });\n}\n\nexport function useLatencyMetrics() {\n const client = useMastraClient();\n const { filters, filterKey } = useMetricsFilters();\n\n return useQuery({\n queryKey: ['metrics', 'latency', filterKey],\n queryFn: async () => {\n const [agentData, workflowData, toolData] = await Promise.all([\n fetchPercentiles(client, 'mastra_agent_duration_ms', filters),\n fetchPercentiles(client, 'mastra_workflow_duration_ms', filters),\n fetchPercentiles(client, 'mastra_tool_duration_ms', filters),\n ]);\n return { agentData, workflowData, toolData, interval: LATENCY_INTERVAL };\n },\n });\n}\n"],"names":["useMastraClient","useMetricsFilters","useQuery"],"mappings":";;;;;;;;AAcO,MAAM,gBAAA,GAAyB;AAEtC,eAAe,gBAAA,CACb,MAAA,EACA,UAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,oBAAA,CAAqB;AAAA,IAC5C,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,GAAA,EAAK,IAAI,CAAA;AAAA,IACvB,QAAA,EAAU,gBAAA;AAAA,IACV;AAAA,GACD,CAAA;AAED,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,GAAG,CAAA;AAC3D,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,IAAI,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,SAAkB,EAAC;AAEtC,EAAA,MAAM,SAAS,IAAI,GAAA,CAAI,UAAU,MAAA,CAAO,GAAA,CAAI,OAAK,CAAC,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAE5F,EAAA,OAAO,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK;AAC/B,IAAA,MAAM,EAAA,GAAK,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,GAAG,OAAA,EAAQ;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,EAAA,CAAG,kBAAA,CAAmB,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,SAAA,EAAW,MAAA,EAAQ,KAAA,EAAO,CAAA;AAAA,MAC1F,IAAA;AAAA,MACA,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA;AAAA,MACvB,KAAK,IAAA,CAAK,KAAA,CAAM,OAAO,GAAA,CAAI,IAAI,KAAK,CAAC;AAAA,KACvC;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,SAASA,qBAAA,EAAgB;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAIC,yDAAA,EAAkB;AAEjD,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,SAAA,EAAW,SAAA,EAAW,SAAS,CAAA;AAAA,IAC1C,SAAS,YAAY;AACnB,MAAA,MAAM,CAAC,SAAA,EAAW,YAAA,EAAc,QAAQ,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QAC5D,gBAAA,CAAiB,MAAA,EAAQ,0BAAA,EAA4B,OAAO,CAAA;AAAA,QAC5D,gBAAA,CAAiB,MAAA,EAAQ,6BAAA,EAA+B,OAAO,CAAA;AAAA,QAC/D,gBAAA,CAAiB,MAAA,EAAQ,yBAAA,EAA2B,OAAO;AAAA,OAC5D,CAAA;AACD,MAAA,OAAO,EAAE,SAAA,EAAW,YAAA,EAAc,QAAA,EAAU,UAAU,gBAAA,EAAiB;AAAA,IACzE;AAAA,GACD,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"use-latency-metrics.cjs.js","sources":["../../../../src/domains/metrics/hooks/use-latency-metrics.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { chooseMetricsInterval, formatMetricsBucketLabel } from '../metrics-interval';\nimport type { MetricsInterval } from '../metrics-interval';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport interface LatencyPoint {\n [key: string]: unknown;\n time: string;\n /** Raw timestamp (ms since epoch) for the bucket this point represents.\n * Used by drilldown clicks to compute a narrow time window. */\n tsMs: number;\n p50: number;\n p95: number;\n}\n\nasync function fetchPercentiles(\n client: ReturnType<typeof useMastraClient>,\n metricName: string,\n filters: Record<string, unknown>,\n interval: MetricsInterval,\n): Promise<LatencyPoint[]> {\n const res = await client.getMetricPercentiles({\n name: metricName,\n percentiles: [0.5, 0.95],\n interval,\n filters,\n });\n\n const p50Series = res.series.find(s => s.percentile === 0.5);\n const p95Series = res.series.find(s => s.percentile === 0.95);\n\n if (!p50Series || !p95Series) return [];\n\n const p95Map = new Map(p95Series.points.map(p => [new Date(p.timestamp).getTime(), p.value]));\n\n return p50Series.points.map(p => {\n const ts = new Date(p.timestamp);\n const tsMs = ts.getTime();\n return {\n time: formatMetricsBucketLabel(ts, interval),\n tsMs,\n p50: Math.round(p.value),\n p95: Math.round(p95Map.get(tsMs) ?? 0),\n };\n });\n}\n\nexport function useLatencyMetrics() {\n const client = useMastraClient();\n const { timestamp, filters, filterKey } = useMetricsFilters();\n const interval = chooseMetricsInterval(timestamp);\n\n return useQuery({\n queryKey: ['metrics', 'latency', filterKey, interval],\n queryFn: async () => {\n const [agentData, workflowData, toolData] = await Promise.all([\n fetchPercentiles(client, 'mastra_agent_duration_ms', filters, interval),\n fetchPercentiles(client, 'mastra_workflow_duration_ms', filters, interval),\n fetchPercentiles(client, 'mastra_tool_duration_ms', filters, interval),\n ]);\n return { agentData, workflowData, toolData, interval };\n },\n });\n}\n"],"names":["formatMetricsBucketLabel","useMastraClient","useMetricsFilters","chooseMetricsInterval","useQuery"],"mappings":";;;;;;;;;AAgBA,eAAe,gBAAA,CACb,MAAA,EACA,UAAA,EACA,OAAA,EACA,QAAA,EACyB;AACzB,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,oBAAA,CAAqB;AAAA,IAC5C,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,GAAA,EAAK,IAAI,CAAA;AAAA,IACvB,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,GAAG,CAAA;AAC3D,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,IAAI,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,SAAkB,EAAC;AAEtC,EAAA,MAAM,SAAS,IAAI,GAAA,CAAI,UAAU,MAAA,CAAO,GAAA,CAAI,OAAK,CAAC,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAE5F,EAAA,OAAO,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK;AAC/B,IAAA,MAAM,EAAA,GAAK,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,GAAG,OAAA,EAAQ;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAMA,wDAAA,CAAyB,EAAA,EAAI,QAAQ,CAAA;AAAA,MAC3C,IAAA;AAAA,MACA,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA;AAAA,MACvB,KAAK,IAAA,CAAK,KAAA,CAAM,OAAO,GAAA,CAAI,IAAI,KAAK,CAAC;AAAA,KACvC;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,SAASC,qBAAA,EAAgB;AAC/B,EAAA,MAAM,EAAE,SAAA,EAAW,OAAA,EAAS,SAAA,KAAcC,yDAAA,EAAkB;AAC5D,EAAA,MAAM,QAAA,GAAWC,sDAAsB,SAAS,CAAA;AAEhD,EAAA,OAAOC,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,SAAA,EAAW,SAAA,EAAW,WAAW,QAAQ,CAAA;AAAA,IACpD,SAAS,YAAY;AACnB,MAAA,MAAM,CAAC,SAAA,EAAW,YAAA,EAAc,QAAQ,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QAC5D,gBAAA,CAAiB,MAAA,EAAQ,0BAAA,EAA4B,OAAA,EAAS,QAAQ,CAAA;AAAA,QACtE,gBAAA,CAAiB,MAAA,EAAQ,6BAAA,EAA+B,OAAA,EAAS,QAAQ,CAAA;AAAA,QACzE,gBAAA,CAAiB,MAAA,EAAQ,yBAAA,EAA2B,OAAA,EAAS,QAAQ;AAAA,OACtE,CAAA;AACD,MAAA,OAAO,EAAE,SAAA,EAAW,YAAA,EAAc,QAAA,EAAU,QAAA,EAAS;AAAA,IACvD;AAAA,GACD,CAAA;AACH;;;;"}
@@ -1,13 +1,13 @@
1
1
  import { useMastraClient } from '@mastra/react';
2
2
  import { useQuery } from '@tanstack/react-query';
3
+ import { chooseMetricsInterval, formatMetricsBucketLabel } from '../metrics-interval.es.js';
3
4
  import { useMetricsFilters } from './use-metrics-filters.es.js';
4
5
 
5
- const LATENCY_INTERVAL = "1h";
6
- async function fetchPercentiles(client, metricName, filters) {
6
+ async function fetchPercentiles(client, metricName, filters, interval) {
7
7
  const res = await client.getMetricPercentiles({
8
8
  name: metricName,
9
9
  percentiles: [0.5, 0.95],
10
- interval: LATENCY_INTERVAL,
10
+ interval,
11
11
  filters
12
12
  });
13
13
  const p50Series = res.series.find((s) => s.percentile === 0.5);
@@ -18,7 +18,7 @@ async function fetchPercentiles(client, metricName, filters) {
18
18
  const ts = new Date(p.timestamp);
19
19
  const tsMs = ts.getTime();
20
20
  return {
21
- time: ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
21
+ time: formatMetricsBucketLabel(ts, interval),
22
22
  tsMs,
23
23
  p50: Math.round(p.value),
24
24
  p95: Math.round(p95Map.get(tsMs) ?? 0)
@@ -27,19 +27,20 @@ async function fetchPercentiles(client, metricName, filters) {
27
27
  }
28
28
  function useLatencyMetrics() {
29
29
  const client = useMastraClient();
30
- const { filters, filterKey } = useMetricsFilters();
30
+ const { timestamp, filters, filterKey } = useMetricsFilters();
31
+ const interval = chooseMetricsInterval(timestamp);
31
32
  return useQuery({
32
- queryKey: ["metrics", "latency", filterKey],
33
+ queryKey: ["metrics", "latency", filterKey, interval],
33
34
  queryFn: async () => {
34
35
  const [agentData, workflowData, toolData] = await Promise.all([
35
- fetchPercentiles(client, "mastra_agent_duration_ms", filters),
36
- fetchPercentiles(client, "mastra_workflow_duration_ms", filters),
37
- fetchPercentiles(client, "mastra_tool_duration_ms", filters)
36
+ fetchPercentiles(client, "mastra_agent_duration_ms", filters, interval),
37
+ fetchPercentiles(client, "mastra_workflow_duration_ms", filters, interval),
38
+ fetchPercentiles(client, "mastra_tool_duration_ms", filters, interval)
38
39
  ]);
39
- return { agentData, workflowData, toolData, interval: LATENCY_INTERVAL };
40
+ return { agentData, workflowData, toolData, interval };
40
41
  }
41
42
  });
42
43
  }
43
44
 
44
- export { LATENCY_INTERVAL, useLatencyMetrics };
45
+ export { useLatencyMetrics };
45
46
  //# sourceMappingURL=use-latency-metrics.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-latency-metrics.es.js","sources":["../../../../src/domains/metrics/hooks/use-latency-metrics.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport interface LatencyPoint {\n [key: string]: unknown;\n time: string;\n /** Raw timestamp (ms since epoch) for the bucket this point represents.\n * Used by drilldown clicks to compute a narrow time window. */\n tsMs: number;\n p50: number;\n p95: number;\n}\n\nexport const LATENCY_INTERVAL: '1h' = '1h';\n\nasync function fetchPercentiles(\n client: ReturnType<typeof useMastraClient>,\n metricName: string,\n filters: Record<string, unknown>,\n): Promise<LatencyPoint[]> {\n const res = await client.getMetricPercentiles({\n name: metricName,\n percentiles: [0.5, 0.95],\n interval: LATENCY_INTERVAL,\n filters,\n });\n\n const p50Series = res.series.find(s => s.percentile === 0.5);\n const p95Series = res.series.find(s => s.percentile === 0.95);\n\n if (!p50Series || !p95Series) return [];\n\n const p95Map = new Map(p95Series.points.map(p => [new Date(p.timestamp).getTime(), p.value]));\n\n return p50Series.points.map(p => {\n const ts = new Date(p.timestamp);\n const tsMs = ts.getTime();\n return {\n time: ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }),\n tsMs,\n p50: Math.round(p.value),\n p95: Math.round(p95Map.get(tsMs) ?? 0),\n };\n });\n}\n\nexport function useLatencyMetrics() {\n const client = useMastraClient();\n const { filters, filterKey } = useMetricsFilters();\n\n return useQuery({\n queryKey: ['metrics', 'latency', filterKey],\n queryFn: async () => {\n const [agentData, workflowData, toolData] = await Promise.all([\n fetchPercentiles(client, 'mastra_agent_duration_ms', filters),\n fetchPercentiles(client, 'mastra_workflow_duration_ms', filters),\n fetchPercentiles(client, 'mastra_tool_duration_ms', filters),\n ]);\n return { agentData, workflowData, toolData, interval: LATENCY_INTERVAL };\n },\n });\n}\n"],"names":[],"mappings":";;;;AAcO,MAAM,gBAAA,GAAyB;AAEtC,eAAe,gBAAA,CACb,MAAA,EACA,UAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,oBAAA,CAAqB;AAAA,IAC5C,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,GAAA,EAAK,IAAI,CAAA;AAAA,IACvB,QAAA,EAAU,gBAAA;AAAA,IACV;AAAA,GACD,CAAA;AAED,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,GAAG,CAAA;AAC3D,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,IAAI,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,SAAkB,EAAC;AAEtC,EAAA,MAAM,SAAS,IAAI,GAAA,CAAI,UAAU,MAAA,CAAO,GAAA,CAAI,OAAK,CAAC,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAE5F,EAAA,OAAO,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK;AAC/B,IAAA,MAAM,EAAA,GAAK,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,GAAG,OAAA,EAAQ;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,EAAA,CAAG,kBAAA,CAAmB,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,SAAA,EAAW,MAAA,EAAQ,KAAA,EAAO,CAAA;AAAA,MAC1F,IAAA;AAAA,MACA,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA;AAAA,MACvB,KAAK,IAAA,CAAK,KAAA,CAAM,OAAO,GAAA,CAAI,IAAI,KAAK,CAAC;AAAA,KACvC;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,SAAS,eAAA,EAAgB;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAI,iBAAA,EAAkB;AAEjD,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,SAAA,EAAW,SAAA,EAAW,SAAS,CAAA;AAAA,IAC1C,SAAS,YAAY;AACnB,MAAA,MAAM,CAAC,SAAA,EAAW,YAAA,EAAc,QAAQ,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QAC5D,gBAAA,CAAiB,MAAA,EAAQ,0BAAA,EAA4B,OAAO,CAAA;AAAA,QAC5D,gBAAA,CAAiB,MAAA,EAAQ,6BAAA,EAA+B,OAAO,CAAA;AAAA,QAC/D,gBAAA,CAAiB,MAAA,EAAQ,yBAAA,EAA2B,OAAO;AAAA,OAC5D,CAAA;AACD,MAAA,OAAO,EAAE,SAAA,EAAW,YAAA,EAAc,QAAA,EAAU,UAAU,gBAAA,EAAiB;AAAA,IACzE;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"use-latency-metrics.es.js","sources":["../../../../src/domains/metrics/hooks/use-latency-metrics.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { chooseMetricsInterval, formatMetricsBucketLabel } from '../metrics-interval';\nimport type { MetricsInterval } from '../metrics-interval';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport interface LatencyPoint {\n [key: string]: unknown;\n time: string;\n /** Raw timestamp (ms since epoch) for the bucket this point represents.\n * Used by drilldown clicks to compute a narrow time window. */\n tsMs: number;\n p50: number;\n p95: number;\n}\n\nasync function fetchPercentiles(\n client: ReturnType<typeof useMastraClient>,\n metricName: string,\n filters: Record<string, unknown>,\n interval: MetricsInterval,\n): Promise<LatencyPoint[]> {\n const res = await client.getMetricPercentiles({\n name: metricName,\n percentiles: [0.5, 0.95],\n interval,\n filters,\n });\n\n const p50Series = res.series.find(s => s.percentile === 0.5);\n const p95Series = res.series.find(s => s.percentile === 0.95);\n\n if (!p50Series || !p95Series) return [];\n\n const p95Map = new Map(p95Series.points.map(p => [new Date(p.timestamp).getTime(), p.value]));\n\n return p50Series.points.map(p => {\n const ts = new Date(p.timestamp);\n const tsMs = ts.getTime();\n return {\n time: formatMetricsBucketLabel(ts, interval),\n tsMs,\n p50: Math.round(p.value),\n p95: Math.round(p95Map.get(tsMs) ?? 0),\n };\n });\n}\n\nexport function useLatencyMetrics() {\n const client = useMastraClient();\n const { timestamp, filters, filterKey } = useMetricsFilters();\n const interval = chooseMetricsInterval(timestamp);\n\n return useQuery({\n queryKey: ['metrics', 'latency', filterKey, interval],\n queryFn: async () => {\n const [agentData, workflowData, toolData] = await Promise.all([\n fetchPercentiles(client, 'mastra_agent_duration_ms', filters, interval),\n fetchPercentiles(client, 'mastra_workflow_duration_ms', filters, interval),\n fetchPercentiles(client, 'mastra_tool_duration_ms', filters, interval),\n ]);\n return { agentData, workflowData, toolData, interval };\n },\n });\n}\n"],"names":[],"mappings":";;;;;AAgBA,eAAe,gBAAA,CACb,MAAA,EACA,UAAA,EACA,OAAA,EACA,QAAA,EACyB;AACzB,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,oBAAA,CAAqB;AAAA,IAC5C,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EAAa,CAAC,GAAA,EAAK,IAAI,CAAA;AAAA,IACvB,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,GAAG,CAAA;AAC3D,EAAA,MAAM,YAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,eAAe,IAAI,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,SAAkB,EAAC;AAEtC,EAAA,MAAM,SAAS,IAAI,GAAA,CAAI,UAAU,MAAA,CAAO,GAAA,CAAI,OAAK,CAAC,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAE5F,EAAA,OAAO,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK;AAC/B,IAAA,MAAM,EAAA,GAAK,IAAI,IAAA,CAAK,CAAA,CAAE,SAAS,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,GAAG,OAAA,EAAQ;AACxB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,wBAAA,CAAyB,EAAA,EAAI,QAAQ,CAAA;AAAA,MAC3C,IAAA;AAAA,MACA,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA;AAAA,MACvB,KAAK,IAAA,CAAK,KAAA,CAAM,OAAO,GAAA,CAAI,IAAI,KAAK,CAAC;AAAA,KACvC;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,iBAAA,GAAoB;AAClC,EAAA,MAAM,SAAS,eAAA,EAAgB;AAC/B,EAAA,MAAM,EAAE,SAAA,EAAW,OAAA,EAAS,SAAA,KAAc,iBAAA,EAAkB;AAC5D,EAAA,MAAM,QAAA,GAAW,sBAAsB,SAAS,CAAA;AAEhD,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,CAAC,SAAA,EAAW,SAAA,EAAW,WAAW,QAAQ,CAAA;AAAA,IACpD,SAAS,YAAY;AACnB,MAAA,MAAM,CAAC,SAAA,EAAW,YAAA,EAAc,QAAQ,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QAC5D,gBAAA,CAAiB,MAAA,EAAQ,0BAAA,EAA4B,OAAA,EAAS,QAAQ,CAAA;AAAA,QACtE,gBAAA,CAAiB,MAAA,EAAQ,6BAAA,EAA+B,OAAA,EAAS,QAAQ,CAAA;AAAA,QACzE,gBAAA,CAAiB,MAAA,EAAQ,yBAAA,EAA2B,OAAA,EAAS,QAAQ;AAAA,OACtE,CAAA;AACD,MAAA,OAAO,EAAE,SAAA,EAAW,YAAA,EAAc,QAAA,EAAU,QAAA,EAAS;AAAA,IACvD;AAAA,GACD,CAAA;AACH;;;;"}
@@ -4,17 +4,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const react = require('@mastra/react');
6
6
  const reactQuery = require('@tanstack/react-query');
7
+ const domains_metrics_metricsInterval = require('../metrics-interval.cjs.js');
7
8
  const domains_metrics_hooks_useMetricsFilters = require('./use-metrics-filters.cjs.js');
8
9
 
9
- function chooseTokenUsageInterval(datePreset) {
10
- return datePreset === "24h" ? "1h" : "1d";
11
- }
12
- function formatTime(ts, interval) {
13
- if (interval === "1h") {
14
- return ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false });
15
- }
16
- return ts.toLocaleDateString("en-US", { month: "short", day: "2-digit" });
17
- }
18
10
  function addSeriesPoints(pointMap, series, key) {
19
11
  for (const point of series?.points ?? []) {
20
12
  const tsMs = new Date(point.timestamp).getTime();
@@ -45,8 +37,8 @@ function toCostUnit(entry) {
45
37
  }
46
38
  function useTokenUsageTimeSeries() {
47
39
  const client = react.useMastraClient();
48
- const { datePreset, filters, filterKey } = domains_metrics_hooks_useMetricsFilters.useMetricsFilters();
49
- const interval = chooseTokenUsageInterval(datePreset);
40
+ const { timestamp, filters, filterKey } = domains_metrics_hooks_useMetricsFilters.useMetricsFilters();
41
+ const interval = domains_metrics_metricsInterval.chooseMetricsInterval(timestamp);
50
42
  return reactQuery.useQuery({
51
43
  queryKey: ["metrics", "token-usage-timeseries", filterKey, interval],
52
44
  queryFn: async () => {
@@ -70,7 +62,7 @@ function useTokenUsageTimeSeries() {
70
62
  const data = Array.from(pointMap.values()).sort((a, b) => a.tsMs - b.tsMs).map((point) => {
71
63
  const ts = new Date(point.tsMs);
72
64
  return {
73
- time: formatTime(ts, interval),
65
+ time: domains_metrics_metricsInterval.formatMetricsBucketLabel(ts, interval),
74
66
  tsMs: point.tsMs,
75
67
  input: point.input,
76
68
  output: point.output,
@@ -1 +1 @@
1
- {"version":3,"file":"use-token-usage-timeseries.cjs.js","sources":["../../../../src/domains/metrics/hooks/use-token-usage-timeseries.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport type TokenUsageTimeSeriesInterval = '1h' | '1d';\n\nexport interface TokenTimelinePoint {\n time: string;\n tsMs: number;\n input: number;\n output: number;\n total: number;\n cost: number | null;\n costUnit: string | null;\n}\n\nexport interface TokenUsageTimeSeriesData {\n data: TokenTimelinePoint[];\n interval: TokenUsageTimeSeriesInterval;\n}\n\ntype TimeSeriesPoint = {\n timestamp: string | Date;\n value: number;\n estimatedCost?: number | null;\n};\n\ntype SeriesWithCost = {\n costUnit?: string | null;\n points: TimeSeriesPoint[];\n};\n\ntype TokenTimelineAccumulator = {\n tsMs: number;\n input: number;\n output: number;\n cost: number | null;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nfunction chooseTokenUsageInterval(\n datePreset: ReturnType<typeof useMetricsFilters>['datePreset'],\n): TokenUsageTimeSeriesInterval {\n return datePreset === '24h' ? '1h' : '1d';\n}\n\nfunction formatTime(ts: Date, interval: TokenUsageTimeSeriesInterval): string {\n if (interval === '1h') {\n return ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });\n }\n return ts.toLocaleDateString('en-US', { month: 'short', day: '2-digit' });\n}\n\nfunction addSeriesPoints(\n pointMap: Map<number, TokenTimelineAccumulator>,\n series: SeriesWithCost | undefined,\n key: 'input' | 'output',\n) {\n for (const point of series?.points ?? []) {\n const tsMs = new Date(point.timestamp).getTime();\n if (!Number.isFinite(tsMs)) continue;\n\n const existing = pointMap.get(tsMs) ?? {\n tsMs,\n input: 0,\n output: 0,\n cost: null,\n costUnits: new Set<string>(),\n hasUnknownCostUnit: false,\n };\n\n existing[key] += point.value;\n\n if (point.estimatedCost != null) {\n existing.cost = (existing.cost ?? 0) + point.estimatedCost;\n if (series?.costUnit) {\n existing.costUnits.add(series.costUnit);\n } else {\n existing.hasUnknownCostUnit = true;\n }\n }\n\n pointMap.set(tsMs, existing);\n }\n}\n\nfunction toCostUnit(entry: TokenTimelineAccumulator): string | null {\n if (entry.cost == null || entry.hasUnknownCostUnit || entry.costUnits.size !== 1) return null;\n return [...entry.costUnits][0] ?? null;\n}\n\nexport function useTokenUsageTimeSeries() {\n const client = useMastraClient();\n const { datePreset, filters, filterKey } = useMetricsFilters();\n const interval = chooseTokenUsageInterval(datePreset);\n\n return useQuery({\n queryKey: ['metrics', 'token-usage-timeseries', filterKey, interval],\n queryFn: async (): Promise<TokenUsageTimeSeriesData> => {\n const [inputRes, outputRes] = await Promise.all([\n client.getMetricTimeSeries({\n name: ['mastra_model_total_input_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n client.getMetricTimeSeries({\n name: ['mastra_model_total_output_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n ]);\n\n const pointMap = new Map<number, TokenTimelineAccumulator>();\n addSeriesPoints(pointMap, inputRes.series[0], 'input');\n addSeriesPoints(pointMap, outputRes.series[0], 'output');\n\n const data = Array.from(pointMap.values())\n .sort((a, b) => a.tsMs - b.tsMs)\n .map(point => {\n const ts = new Date(point.tsMs);\n return {\n time: formatTime(ts, interval),\n tsMs: point.tsMs,\n input: point.input,\n output: point.output,\n total: point.input + point.output,\n cost: point.cost,\n costUnit: toCostUnit(point),\n };\n });\n\n return { data, interval };\n },\n });\n}\n"],"names":["useMastraClient","useMetricsFilters","useQuery"],"mappings":"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"}
1
+ {"version":3,"file":"use-token-usage-timeseries.cjs.js","sources":["../../../../src/domains/metrics/hooks/use-token-usage-timeseries.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { chooseMetricsInterval, formatMetricsBucketLabel } from '../metrics-interval';\nimport type { MetricsInterval } from '../metrics-interval';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport type TokenUsageTimeSeriesInterval = MetricsInterval;\n\nexport interface TokenTimelinePoint {\n time: string;\n tsMs: number;\n input: number;\n output: number;\n total: number;\n cost: number | null;\n costUnit: string | null;\n}\n\nexport interface TokenUsageTimeSeriesData {\n data: TokenTimelinePoint[];\n interval: TokenUsageTimeSeriesInterval;\n}\n\ntype TimeSeriesPoint = {\n timestamp: string | Date;\n value: number;\n estimatedCost?: number | null;\n};\n\ntype SeriesWithCost = {\n costUnit?: string | null;\n points: TimeSeriesPoint[];\n};\n\ntype TokenTimelineAccumulator = {\n tsMs: number;\n input: number;\n output: number;\n cost: number | null;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nfunction addSeriesPoints(\n pointMap: Map<number, TokenTimelineAccumulator>,\n series: SeriesWithCost | undefined,\n key: 'input' | 'output',\n) {\n for (const point of series?.points ?? []) {\n const tsMs = new Date(point.timestamp).getTime();\n if (!Number.isFinite(tsMs)) continue;\n\n const existing = pointMap.get(tsMs) ?? {\n tsMs,\n input: 0,\n output: 0,\n cost: null,\n costUnits: new Set<string>(),\n hasUnknownCostUnit: false,\n };\n\n existing[key] += point.value;\n\n if (point.estimatedCost != null) {\n existing.cost = (existing.cost ?? 0) + point.estimatedCost;\n if (series?.costUnit) {\n existing.costUnits.add(series.costUnit);\n } else {\n existing.hasUnknownCostUnit = true;\n }\n }\n\n pointMap.set(tsMs, existing);\n }\n}\n\nfunction toCostUnit(entry: TokenTimelineAccumulator): string | null {\n if (entry.cost == null || entry.hasUnknownCostUnit || entry.costUnits.size !== 1) return null;\n return [...entry.costUnits][0] ?? null;\n}\n\nexport function useTokenUsageTimeSeries() {\n const client = useMastraClient();\n const { timestamp, filters, filterKey } = useMetricsFilters();\n const interval = chooseMetricsInterval(timestamp);\n\n return useQuery({\n queryKey: ['metrics', 'token-usage-timeseries', filterKey, interval],\n queryFn: async (): Promise<TokenUsageTimeSeriesData> => {\n const [inputRes, outputRes] = await Promise.all([\n client.getMetricTimeSeries({\n name: ['mastra_model_total_input_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n client.getMetricTimeSeries({\n name: ['mastra_model_total_output_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n ]);\n\n const pointMap = new Map<number, TokenTimelineAccumulator>();\n addSeriesPoints(pointMap, inputRes.series[0], 'input');\n addSeriesPoints(pointMap, outputRes.series[0], 'output');\n\n const data = Array.from(pointMap.values())\n .sort((a, b) => a.tsMs - b.tsMs)\n .map(point => {\n const ts = new Date(point.tsMs);\n return {\n time: formatMetricsBucketLabel(ts, interval),\n tsMs: point.tsMs,\n input: point.input,\n output: point.output,\n total: point.input + point.output,\n cost: point.cost,\n costUnit: toCostUnit(point),\n };\n });\n\n return { data, interval };\n },\n });\n}\n"],"names":["useMastraClient","useMetricsFilters","chooseMetricsInterval","useQuery","formatMetricsBucketLabel"],"mappings":"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"}
@@ -1,16 +1,8 @@
1
1
  import { useMastraClient } from '@mastra/react';
2
2
  import { useQuery } from '@tanstack/react-query';
3
+ import { chooseMetricsInterval, formatMetricsBucketLabel } from '../metrics-interval.es.js';
3
4
  import { useMetricsFilters } from './use-metrics-filters.es.js';
4
5
 
5
- function chooseTokenUsageInterval(datePreset) {
6
- return datePreset === "24h" ? "1h" : "1d";
7
- }
8
- function formatTime(ts, interval) {
9
- if (interval === "1h") {
10
- return ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false });
11
- }
12
- return ts.toLocaleDateString("en-US", { month: "short", day: "2-digit" });
13
- }
14
6
  function addSeriesPoints(pointMap, series, key) {
15
7
  for (const point of series?.points ?? []) {
16
8
  const tsMs = new Date(point.timestamp).getTime();
@@ -41,8 +33,8 @@ function toCostUnit(entry) {
41
33
  }
42
34
  function useTokenUsageTimeSeries() {
43
35
  const client = useMastraClient();
44
- const { datePreset, filters, filterKey } = useMetricsFilters();
45
- const interval = chooseTokenUsageInterval(datePreset);
36
+ const { timestamp, filters, filterKey } = useMetricsFilters();
37
+ const interval = chooseMetricsInterval(timestamp);
46
38
  return useQuery({
47
39
  queryKey: ["metrics", "token-usage-timeseries", filterKey, interval],
48
40
  queryFn: async () => {
@@ -66,7 +58,7 @@ function useTokenUsageTimeSeries() {
66
58
  const data = Array.from(pointMap.values()).sort((a, b) => a.tsMs - b.tsMs).map((point) => {
67
59
  const ts = new Date(point.tsMs);
68
60
  return {
69
- time: formatTime(ts, interval),
61
+ time: formatMetricsBucketLabel(ts, interval),
70
62
  tsMs: point.tsMs,
71
63
  input: point.input,
72
64
  output: point.output,
@@ -1 +1 @@
1
- {"version":3,"file":"use-token-usage-timeseries.es.js","sources":["../../../../src/domains/metrics/hooks/use-token-usage-timeseries.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport type TokenUsageTimeSeriesInterval = '1h' | '1d';\n\nexport interface TokenTimelinePoint {\n time: string;\n tsMs: number;\n input: number;\n output: number;\n total: number;\n cost: number | null;\n costUnit: string | null;\n}\n\nexport interface TokenUsageTimeSeriesData {\n data: TokenTimelinePoint[];\n interval: TokenUsageTimeSeriesInterval;\n}\n\ntype TimeSeriesPoint = {\n timestamp: string | Date;\n value: number;\n estimatedCost?: number | null;\n};\n\ntype SeriesWithCost = {\n costUnit?: string | null;\n points: TimeSeriesPoint[];\n};\n\ntype TokenTimelineAccumulator = {\n tsMs: number;\n input: number;\n output: number;\n cost: number | null;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nfunction chooseTokenUsageInterval(\n datePreset: ReturnType<typeof useMetricsFilters>['datePreset'],\n): TokenUsageTimeSeriesInterval {\n return datePreset === '24h' ? '1h' : '1d';\n}\n\nfunction formatTime(ts: Date, interval: TokenUsageTimeSeriesInterval): string {\n if (interval === '1h') {\n return ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });\n }\n return ts.toLocaleDateString('en-US', { month: 'short', day: '2-digit' });\n}\n\nfunction addSeriesPoints(\n pointMap: Map<number, TokenTimelineAccumulator>,\n series: SeriesWithCost | undefined,\n key: 'input' | 'output',\n) {\n for (const point of series?.points ?? []) {\n const tsMs = new Date(point.timestamp).getTime();\n if (!Number.isFinite(tsMs)) continue;\n\n const existing = pointMap.get(tsMs) ?? {\n tsMs,\n input: 0,\n output: 0,\n cost: null,\n costUnits: new Set<string>(),\n hasUnknownCostUnit: false,\n };\n\n existing[key] += point.value;\n\n if (point.estimatedCost != null) {\n existing.cost = (existing.cost ?? 0) + point.estimatedCost;\n if (series?.costUnit) {\n existing.costUnits.add(series.costUnit);\n } else {\n existing.hasUnknownCostUnit = true;\n }\n }\n\n pointMap.set(tsMs, existing);\n }\n}\n\nfunction toCostUnit(entry: TokenTimelineAccumulator): string | null {\n if (entry.cost == null || entry.hasUnknownCostUnit || entry.costUnits.size !== 1) return null;\n return [...entry.costUnits][0] ?? null;\n}\n\nexport function useTokenUsageTimeSeries() {\n const client = useMastraClient();\n const { datePreset, filters, filterKey } = useMetricsFilters();\n const interval = chooseTokenUsageInterval(datePreset);\n\n return useQuery({\n queryKey: ['metrics', 'token-usage-timeseries', filterKey, interval],\n queryFn: async (): Promise<TokenUsageTimeSeriesData> => {\n const [inputRes, outputRes] = await Promise.all([\n client.getMetricTimeSeries({\n name: ['mastra_model_total_input_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n client.getMetricTimeSeries({\n name: ['mastra_model_total_output_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n ]);\n\n const pointMap = new Map<number, TokenTimelineAccumulator>();\n addSeriesPoints(pointMap, inputRes.series[0], 'input');\n addSeriesPoints(pointMap, outputRes.series[0], 'output');\n\n const data = Array.from(pointMap.values())\n .sort((a, b) => a.tsMs - b.tsMs)\n .map(point => {\n const ts = new Date(point.tsMs);\n return {\n time: formatTime(ts, interval),\n tsMs: point.tsMs,\n input: point.input,\n output: point.output,\n total: point.input + point.output,\n cost: point.cost,\n costUnit: toCostUnit(point),\n };\n });\n\n return { data, interval };\n },\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-token-usage-timeseries.es.js","sources":["../../../../src/domains/metrics/hooks/use-token-usage-timeseries.tsx"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { chooseMetricsInterval, formatMetricsBucketLabel } from '../metrics-interval';\nimport type { MetricsInterval } from '../metrics-interval';\nimport { useMetricsFilters } from './use-metrics-filters';\n\nexport type TokenUsageTimeSeriesInterval = MetricsInterval;\n\nexport interface TokenTimelinePoint {\n time: string;\n tsMs: number;\n input: number;\n output: number;\n total: number;\n cost: number | null;\n costUnit: string | null;\n}\n\nexport interface TokenUsageTimeSeriesData {\n data: TokenTimelinePoint[];\n interval: TokenUsageTimeSeriesInterval;\n}\n\ntype TimeSeriesPoint = {\n timestamp: string | Date;\n value: number;\n estimatedCost?: number | null;\n};\n\ntype SeriesWithCost = {\n costUnit?: string | null;\n points: TimeSeriesPoint[];\n};\n\ntype TokenTimelineAccumulator = {\n tsMs: number;\n input: number;\n output: number;\n cost: number | null;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nfunction addSeriesPoints(\n pointMap: Map<number, TokenTimelineAccumulator>,\n series: SeriesWithCost | undefined,\n key: 'input' | 'output',\n) {\n for (const point of series?.points ?? []) {\n const tsMs = new Date(point.timestamp).getTime();\n if (!Number.isFinite(tsMs)) continue;\n\n const existing = pointMap.get(tsMs) ?? {\n tsMs,\n input: 0,\n output: 0,\n cost: null,\n costUnits: new Set<string>(),\n hasUnknownCostUnit: false,\n };\n\n existing[key] += point.value;\n\n if (point.estimatedCost != null) {\n existing.cost = (existing.cost ?? 0) + point.estimatedCost;\n if (series?.costUnit) {\n existing.costUnits.add(series.costUnit);\n } else {\n existing.hasUnknownCostUnit = true;\n }\n }\n\n pointMap.set(tsMs, existing);\n }\n}\n\nfunction toCostUnit(entry: TokenTimelineAccumulator): string | null {\n if (entry.cost == null || entry.hasUnknownCostUnit || entry.costUnits.size !== 1) return null;\n return [...entry.costUnits][0] ?? null;\n}\n\nexport function useTokenUsageTimeSeries() {\n const client = useMastraClient();\n const { timestamp, filters, filterKey } = useMetricsFilters();\n const interval = chooseMetricsInterval(timestamp);\n\n return useQuery({\n queryKey: ['metrics', 'token-usage-timeseries', filterKey, interval],\n queryFn: async (): Promise<TokenUsageTimeSeriesData> => {\n const [inputRes, outputRes] = await Promise.all([\n client.getMetricTimeSeries({\n name: ['mastra_model_total_input_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n client.getMetricTimeSeries({\n name: ['mastra_model_total_output_tokens'],\n interval,\n aggregation: 'sum',\n filters,\n }),\n ]);\n\n const pointMap = new Map<number, TokenTimelineAccumulator>();\n addSeriesPoints(pointMap, inputRes.series[0], 'input');\n addSeriesPoints(pointMap, outputRes.series[0], 'output');\n\n const data = Array.from(pointMap.values())\n .sort((a, b) => a.tsMs - b.tsMs)\n .map(point => {\n const ts = new Date(point.tsMs);\n return {\n time: formatMetricsBucketLabel(ts, interval),\n tsMs: point.tsMs,\n input: point.input,\n output: point.output,\n total: point.input + point.output,\n cost: point.cost,\n costUnit: toCostUnit(point),\n };\n });\n\n return { data, interval };\n },\n });\n}\n"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ const domains_metrics_hooks_useTopActiveThreadsMetrics = require('./hooks/use-to
19
19
  const domains_metrics_hooks_useTopResourcesByThreadsMetrics = require('./hooks/use-top-resources-by-threads-metrics.cjs.js');
20
20
  const domains_metrics_hooks_useDrilldown = require('./hooks/use-drilldown.cjs.js');
21
21
  const domains_metrics_drilldown = require('./drilldown.cjs.js');
22
+ const domains_metrics_metricsInterval = require('./metrics-interval.cjs.js');
22
23
  const domains_metrics_metricsFilters = require('./metrics-filters.cjs.js');
23
24
 
24
25
 
@@ -45,6 +46,8 @@ exports.useDrilldown = domains_metrics_hooks_useDrilldown.useDrilldown;
45
46
  exports.buildLogsDrilldownUrl = domains_metrics_drilldown.buildLogsDrilldownUrl;
46
47
  exports.buildTracesDrilldownUrl = domains_metrics_drilldown.buildTracesDrilldownUrl;
47
48
  exports.narrowWindowToBucket = domains_metrics_drilldown.narrowWindowToBucket;
49
+ exports.chooseMetricsInterval = domains_metrics_metricsInterval.chooseMetricsInterval;
50
+ exports.formatMetricsBucketLabel = domains_metrics_metricsInterval.formatMetricsBucketLabel;
48
51
  exports.applyMetricsPropertyFilterTokens = domains_metrics_metricsFilters.applyMetricsPropertyFilterTokens;
49
52
  exports.buildMetricsDimensionalFilter = domains_metrics_metricsFilters.buildMetricsDimensionalFilter;
50
53
  exports.clearSavedMetricsFilters = domains_metrics_metricsFilters.clearSavedMetricsFilters;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"hooks.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -15,5 +15,6 @@ export { useTopActiveThreadsMetrics } from './hooks/use-top-active-threads-metri
15
15
  export { useTopResourcesByThreadsMetrics } from './hooks/use-top-resources-by-threads-metrics.es.js';
16
16
  export { useDrilldown } from './hooks/use-drilldown.es.js';
17
17
  export { buildLogsDrilldownUrl, buildTracesDrilldownUrl, narrowWindowToBucket } from './drilldown.es.js';
18
+ export { chooseMetricsInterval, formatMetricsBucketLabel } from './metrics-interval.es.js';
18
19
  export { applyMetricsPropertyFilterTokens, buildMetricsDimensionalFilter, clearSavedMetricsFilters, createMetricsPropertyFilterFields, getMetricsPropertyFilterTokens, hasAnyMetricsFilterParams, loadMetricsFiltersFromStorage, saveMetricsFiltersToStorage } from './metrics-filters.es.js';
19
20
  //# sourceMappingURL=hooks.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"hooks.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const HOURLY_MAX_RANGE_MS = 48 * 60 * 60 * 1e3;
6
+ function chooseMetricsInterval({ start, end }) {
7
+ return end.getTime() - start.getTime() <= HOURLY_MAX_RANGE_MS ? "1h" : "1d";
8
+ }
9
+ function formatMetricsBucketLabel(ts, interval) {
10
+ if (interval === "1h") {
11
+ return ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false });
12
+ }
13
+ return ts.toLocaleDateString("en-US", { month: "short", day: "2-digit" });
14
+ }
15
+
16
+ exports.chooseMetricsInterval = chooseMetricsInterval;
17
+ exports.formatMetricsBucketLabel = formatMetricsBucketLabel;
18
+ //# sourceMappingURL=metrics-interval.cjs.js.map