@mastra/playground-ui 68.0.0-alpha.2 → 68.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FilterBar-CQl04O6t.cjs → FilterBar-BSP2UTjc.cjs} +2 -2
- package/dist/{FilterBar-CQl04O6t.cjs.map → FilterBar-BSP2UTjc.cjs.map} +1 -1
- package/dist/{FilterBar-BgW2dqRQ.js → FilterBar-PSQ1OwqH.js} +2 -2
- package/dist/{FilterBar-BgW2dqRQ.js.map → FilterBar-PSQ1OwqH.js.map} +1 -1
- package/dist/KnowledgePageGraph.css +55 -0
- package/dist/{MarkdownRenderer-2GOXQJEv.js → MarkdownRenderer-CI30RqdB.js} +19 -6
- package/dist/MarkdownRenderer-CI30RqdB.js.map +1 -0
- package/dist/{MarkdownRenderer-CB8Z_CHc.cjs → MarkdownRenderer-y65WGBhC.cjs} +19 -6
- package/dist/MarkdownRenderer-y65WGBhC.cjs.map +1 -0
- package/dist/{MetricsCard-CEB-f2sv.cjs → MetricsCard-BEwiS7Pe.cjs} +8 -8
- package/dist/MetricsCard-BEwiS7Pe.cjs.map +1 -0
- package/dist/{MetricsCard-M8awJ2B_.js → MetricsCard-ua6C6b8a.js} +10 -10
- package/dist/MetricsCard-ua6C6b8a.js.map +1 -0
- package/dist/{MetricsLineChart-BhHoduO0.js → MetricsLineChart-4SwxBbQx.js} +14 -3
- package/dist/MetricsLineChart-4SwxBbQx.js.map +1 -0
- package/dist/{MetricsLineChart-CjBm4IXu.cjs → MetricsLineChart-tZxsauau.cjs} +13 -2
- package/dist/MetricsLineChart-tZxsauau.cjs.map +1 -0
- package/dist/{MetricsStackedBarChart-BdMlKv6G.cjs → MetricsStackedBarChart-CDLE76IB.cjs} +2 -2
- package/dist/{MetricsStackedBarChart-BdMlKv6G.cjs.map → MetricsStackedBarChart-CDLE76IB.cjs.map} +1 -1
- package/dist/{MetricsStackedBarChart-BRuA6MTE.js → MetricsStackedBarChart-D2QyS4-z.js} +2 -2
- package/dist/{MetricsStackedBarChart-BRuA6MTE.js.map → MetricsStackedBarChart-D2QyS4-z.js.map} +1 -1
- package/dist/{activity-rJ1NQl_2.js → activity-C8Ql81WM.js} +2 -2
- package/dist/{activity-rJ1NQl_2.js.map → activity-C8Ql81WM.js.map} +1 -1
- package/dist/{activity-DyB5H3gF.cjs → activity-CcQZeDYi.cjs} +2 -2
- package/dist/{activity-DyB5H3gF.cjs.map → activity-CcQZeDYi.cjs.map} +1 -1
- package/dist/components/DateTimeRangePicker.cjs.js +1 -1
- package/dist/components/DateTimeRangePicker.es.js +1 -1
- package/dist/components/FilterBar.cjs.js +2 -2
- package/dist/components/FilterBar.es.js +2 -2
- package/dist/components/MarkdownRenderer.cjs.js +1 -1
- package/dist/components/MarkdownRenderer.es.js +1 -1
- package/dist/components/MetricsCard.cjs.js +1 -1
- package/dist/components/MetricsCard.es.js +1 -1
- package/dist/components/MetricsLineChart.cjs.js +1 -1
- package/dist/components/MetricsLineChart.es.js +1 -1
- package/dist/components/MetricsStackedBarChart.cjs.js +1 -1
- package/dist/components/MetricsStackedBarChart.es.js +1 -1
- package/dist/components/SavedViews.cjs.js +1 -1
- package/dist/components/SavedViews.es.js +1 -1
- package/dist/components/ai/activity.cjs.js +1 -1
- package/dist/components/ai/activity.es.js +1 -1
- package/dist/components/ai/plan.cjs.js +1 -1
- package/dist/components/ai/plan.es.js +1 -1
- package/dist/components/ai/tool-approval.cjs.js +1 -1
- package/dist/components/ai/tool-approval.es.js +1 -1
- package/dist/components/ai/tool-call.cjs.js +2 -2
- package/dist/components/ai/tool-call.es.js +2 -2
- package/dist/{date-time-range-picker-CTt7Od0P.cjs → date-time-range-picker-CWGjoR3j.cjs} +40 -13
- package/dist/date-time-range-picker-CWGjoR3j.cjs.map +1 -0
- package/dist/{date-time-range-picker-DKh1K9Iy.js → date-time-range-picker-CdSiXwB4.js} +40 -13
- package/dist/date-time-range-picker-CdSiXwB4.js.map +1 -0
- package/dist/domains/chat/activity/activity-stretch-line.cjs.js +1 -1
- package/dist/domains/chat/activity/activity-stretch-line.es.js +1 -1
- package/dist/domains/chat/activity/components/activity-fold.cjs.js +1 -1
- package/dist/domains/chat/activity/components/activity-fold.es.js +1 -1
- package/dist/domains/chat/activity/components/activity-timed-trigger.cjs.js +1 -1
- package/dist/domains/chat/activity/components/activity-timed-trigger.es.js +1 -1
- package/dist/domains/chat/activity/components/calls-panel.cjs.js +1 -1
- package/dist/domains/chat/activity/components/calls-panel.es.js +1 -1
- package/dist/domains/chat/activity/components/stretch-content.cjs.js +1 -1
- package/dist/domains/chat/activity/components/stretch-content.es.js +1 -1
- package/dist/domains/chat/activity/components/stretch-thought.cjs.js +1 -1
- package/dist/domains/chat/activity/components/stretch-thought.es.js +1 -1
- package/dist/domains/chat/activity/model/activity-segments.cjs.js +1 -1
- package/dist/domains/chat/activity/model/activity-segments.es.js +1 -1
- package/dist/domains/chat/activity/model/activity-words.cjs.js +2 -2
- package/dist/domains/chat/activity/model/activity-words.es.js +2 -2
- package/dist/domains/chat/components/badge-wrapper.cjs.js +1 -1
- package/dist/domains/chat/components/badge-wrapper.es.js +1 -1
- package/dist/domains/chat/knowledge/knowledge-links.cjs.js +52 -6
- package/dist/domains/chat/knowledge/knowledge-links.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/knowledge-links.es.js +53 -9
- package/dist/domains/chat/knowledge/knowledge-links.es.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js +10 -3
- package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js +10 -3
- package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js +8 -3
- package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge.es.js +8 -3
- package/dist/domains/chat/knowledge/pinned-knowledge.es.js.map +1 -1
- package/dist/domains/chat/knowledge.cjs.js +2 -0
- package/dist/domains/chat/knowledge.es.js +2 -2
- package/dist/domains/chat/messages/message-row.cjs.js +3 -3
- package/dist/domains/chat/messages/message-row.es.js +3 -3
- package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
- package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
- package/dist/domains/chat/messages/reasoning-content.cjs.js +1 -1
- package/dist/domains/chat/messages/reasoning-content.es.js +1 -1
- package/dist/domains/chat/messages/renderers/message-text.cjs.js +35 -1
- package/dist/domains/chat/messages/renderers/message-text.cjs.js.map +1 -1
- package/dist/domains/chat/messages/renderers/message-text.es.js +36 -2
- package/dist/domains/chat/messages/renderers/message-text.es.js.map +1 -1
- package/dist/domains/chat/messages/renderers/reasoning-part-renderer.cjs.js +1 -1
- package/dist/domains/chat/messages/renderers/reasoning-part-renderer.es.js +1 -1
- package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
- package/dist/domains/chat/messages/signal-badge.es.js +1 -1
- package/dist/domains/chat/messages/skill-message.cjs.js +2 -2
- package/dist/domains/chat/messages/skill-message.es.js +2 -2
- package/dist/domains/chat/messages/system-reminder-badge.cjs.js +1 -1
- package/dist/domains/chat/messages/system-reminder-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge-wrapper.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge-wrapper.es.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/file-tree-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/file-tree-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js +80 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.d.ts +1 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.es.js +78 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js +163 -13
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js +165 -15
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js +51 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.d.ts +1 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js +49 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js +7 -2
- package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/mcp-task-chip.es.js +7 -2
- package/dist/domains/chat/tools/badges/mcp-task-chip.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-details.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-details.es.js +2 -2
- package/dist/domains/chat/tools/badges/observation-renderer.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/observation-renderer.es.js +1 -1
- package/dist/domains/chat/tools/badges/sandbox-execution-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/sandbox-execution-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/tool-approval-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/tool-approval-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/tool-badge.cjs.js +9 -4
- package/dist/domains/chat/tools/badges/tool-badge.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/tool-badge.es.js +9 -4
- package/dist/domains/chat/tools/badges/tool-badge.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js +81 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.d.ts +1 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js +77 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js +11 -2
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js +11 -2
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/workflow-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/workflow-badge.es.js +1 -1
- package/dist/domains/chat/tools/connect-prompt-tool.cjs.js +79 -4
- package/dist/domains/chat/tools/connect-prompt-tool.cjs.js.map +1 -1
- package/dist/domains/chat/tools/connect-prompt-tool.es.js +79 -4
- package/dist/domains/chat/tools/connect-prompt-tool.es.js.map +1 -1
- package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js +238 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.d.ts +1 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.es.js +237 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.es.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request.cjs.js +40 -0
- package/dist/domains/chat/tools/mcp-input-request.cjs.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request.d.ts +1 -0
- package/dist/domains/chat/tools/mcp-input-request.es.js +33 -0
- package/dist/domains/chat/tools/mcp-input-request.es.js.map +1 -0
- package/dist/domains/chat/tools/tool-card-kind.cjs.js +9 -4
- package/dist/domains/chat/tools/tool-card-kind.cjs.js.map +1 -1
- package/dist/domains/chat/tools/tool-card-kind.es.js +9 -5
- package/dist/domains/chat/tools/tool-card-kind.es.js.map +1 -1
- package/dist/domains/chat/tools/tool-card.cjs.js +1 -1
- package/dist/domains/chat/tools/tool-card.es.js +1 -1
- package/dist/domains/chat/tools/tool-groups.cjs.js +1 -1
- package/dist/domains/chat/tools/tool-groups.es.js +1 -1
- package/dist/domains/chat.cjs.js +5 -3
- package/dist/domains/chat.es.js +4 -4
- package/dist/domains/connect/types.cjs.js.map +1 -1
- package/dist/domains/connect/types.es.js.map +1 -1
- package/dist/domains/connect/use-user-connect.cjs.js +19 -2
- package/dist/domains/connect/use-user-connect.cjs.js.map +1 -1
- package/dist/domains/connect/use-user-connect.es.js +19 -2
- package/dist/domains/connect/use-user-connect.es.js.map +1 -1
- package/dist/domains/dashboards/components/dashboard-renderer.cjs.js +4 -3
- package/dist/domains/dashboards/components/dashboard-renderer.cjs.js.map +1 -1
- package/dist/domains/dashboards/components/dashboard-renderer.es.js +4 -3
- package/dist/domains/dashboards/components/dashboard-renderer.es.js.map +1 -1
- package/dist/domains/dashboards/components/widget-chrome.cjs.js +1 -1
- package/dist/domains/dashboards/components/widget-chrome.es.js +1 -1
- package/dist/domains/dashboards/components/widget-error.cjs.js +1 -1
- package/dist/domains/dashboards/components/widget-error.es.js +1 -1
- package/dist/domains/dashboards/hooks/use-widget-views.cjs.js +4 -3
- package/dist/domains/dashboards/hooks/use-widget-views.cjs.js.map +1 -1
- package/dist/domains/dashboards/hooks/use-widget-views.es.js +4 -3
- package/dist/domains/dashboards/hooks/use-widget-views.es.js.map +1 -1
- package/dist/domains/dashboards/kinds/scores/scores-widget.cjs.js +9 -6
- package/dist/domains/dashboards/kinds/scores/scores-widget.cjs.js.map +1 -1
- package/dist/domains/dashboards/kinds/scores/scores-widget.es.js +9 -6
- package/dist/domains/dashboards/kinds/scores/scores-widget.es.js.map +1 -1
- package/dist/domains/dashboards/kinds/table/table-tabs.cjs.js +2 -2
- package/dist/domains/dashboards/kinds/table/table-tabs.es.js +2 -2
- package/dist/domains/dashboards/kinds/table/table-widget.cjs.js +1 -1
- package/dist/domains/dashboards/kinds/table/table-widget.es.js +1 -1
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.cjs.js +6 -5
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.cjs.js.map +1 -1
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.es.js +6 -5
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.es.js.map +1 -1
- package/dist/domains/dashboards/lib/chrome.cjs.js +9 -2
- package/dist/domains/dashboards/lib/chrome.cjs.js.map +1 -1
- package/dist/domains/dashboards/lib/chrome.es.js +9 -2
- package/dist/domains/dashboards/lib/chrome.es.js.map +1 -1
- package/dist/domains/dashboards/widget-kind.cjs.js.map +1 -1
- package/dist/domains/dashboards/widget-kind.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js +48 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js.map +1 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.d.ts +1 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.es.js +47 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.es.js.map +1 -0
- package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js +63 -5
- package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageDetail.es.js +64 -6
- package/dist/domains/knowledge/components/KnowledgePageDetail.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js +485 -47
- package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js +487 -50
- package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js +1051 -123
- package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageGraph.es.js +1054 -126
- package/dist/domains/knowledge/components/KnowledgePageGraph.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js +75 -3
- package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageTree.es.js +76 -4
- package/dist/domains/knowledge/components/KnowledgePageTree.es.js.map +1 -1
- package/dist/domains/knowledge/lib/circleText.cjs.js +9 -0
- package/dist/domains/knowledge/lib/circleText.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/circleText.d.ts +1 -0
- package/dist/domains/knowledge/lib/circleText.es.js +8 -0
- package/dist/domains/knowledge/lib/circleText.es.js.map +1 -0
- package/dist/domains/knowledge/lib/fitViewport.cjs.js +82 -0
- package/dist/domains/knowledge/lib/fitViewport.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/fitViewport.d.ts +1 -0
- package/dist/domains/knowledge/lib/fitViewport.es.js +73 -0
- package/dist/domains/knowledge/lib/fitViewport.es.js.map +1 -0
- package/dist/domains/knowledge/lib/graphShape.cjs.js +524 -0
- package/dist/domains/knowledge/lib/graphShape.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/graphShape.d.ts +1 -0
- package/dist/domains/knowledge/lib/graphShape.es.js +499 -0
- package/dist/domains/knowledge/lib/graphShape.es.js.map +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.cjs.js +11 -0
- package/dist/domains/knowledge/lib/linkCountsText.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.d.ts +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.es.js +10 -0
- package/dist/domains/knowledge/lib/linkCountsText.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageAddress.cjs.js +29 -0
- package/dist/domains/knowledge/lib/pageAddress.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/pageAddress.d.ts +1 -0
- package/dist/domains/knowledge/lib/pageAddress.es.js +27 -0
- package/dist/domains/knowledge/lib/pageAddress.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageGraph.cjs.js +11 -11
- package/dist/domains/knowledge/lib/pageGraph.cjs.js.map +1 -1
- package/dist/domains/knowledge/lib/pageGraph.es.js +11 -11
- package/dist/domains/knowledge/lib/pageGraph.es.js.map +1 -1
- package/dist/domains/knowledge/lib/pageRefs.cjs.js +69 -0
- package/dist/domains/knowledge/lib/pageRefs.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/pageRefs.d.ts +1 -0
- package/dist/domains/knowledge/lib/pageRefs.es.js +66 -0
- package/dist/domains/knowledge/lib/pageRefs.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageTree.cjs.js +5 -0
- package/dist/domains/knowledge/lib/pageTree.cjs.js.map +1 -1
- package/dist/domains/knowledge/lib/pageTree.es.js +5 -1
- package/dist/domains/knowledge/lib/pageTree.es.js.map +1 -1
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js +82 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +1 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js +78 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js.map +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.cjs.js +77 -0
- package/dist/domains/knowledge/lib/tooltipSide.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.d.ts +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.es.js +75 -0
- package/dist/domains/knowledge/lib/tooltipSide.es.js.map +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js +65 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.d.ts +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.es.js +62 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.es.js.map +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.cjs.js +15 -0
- package/dist/domains/knowledge/lib/useStableWhile.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.d.ts +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.es.js +14 -0
- package/dist/domains/knowledge/lib/useStableWhile.es.js.map +1 -0
- package/dist/domains/metrics/components/agent-runs-card.cjs.js +3 -3
- package/dist/domains/metrics/components/agent-runs-card.es.js +3 -3
- package/dist/domains/metrics/components/breakdown/breakdown-tab-body.cjs.js +1 -1
- package/dist/domains/metrics/components/breakdown/breakdown-tab-body.es.js +1 -1
- package/dist/domains/metrics/components/breakdown-card.cjs.js +1 -1
- package/dist/domains/metrics/components/breakdown-card.es.js +1 -1
- package/dist/domains/metrics/components/chart-area.cjs.js +1 -1
- package/dist/domains/metrics/components/chart-area.es.js +1 -1
- package/dist/domains/metrics/components/chart-card-error.cjs.js +1 -1
- package/dist/domains/metrics/components/chart-card-error.es.js +1 -1
- package/dist/domains/metrics/components/chart-card.cjs.js +1 -1
- package/dist/domains/metrics/components/chart-card.es.js +1 -1
- package/dist/domains/metrics/components/date-range-selector.cjs.js +1 -1
- package/dist/domains/metrics/components/date-range-selector.es.js +1 -1
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.cjs.js +3 -2
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.cjs.js.map +1 -1
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.es.js +3 -2
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.es.js.map +1 -1
- package/dist/domains/metrics/components/failure-rate-card.cjs.js +3 -2
- package/dist/domains/metrics/components/failure-rate-card.cjs.js.map +1 -1
- package/dist/domains/metrics/components/failure-rate-card.es.js +3 -2
- package/dist/domains/metrics/components/failure-rate-card.es.js.map +1 -1
- package/dist/domains/metrics/components/latency-card.cjs.js +3 -2
- package/dist/domains/metrics/components/latency-card.cjs.js.map +1 -1
- package/dist/domains/metrics/components/latency-card.es.js +3 -2
- package/dist/domains/metrics/components/latency-card.es.js.map +1 -1
- package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
- package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
- package/dist/domains/metrics/components/scores-card.cjs.js +2 -1
- package/dist/domains/metrics/components/scores-card.cjs.js.map +1 -1
- package/dist/domains/metrics/components/scores-card.es.js +2 -1
- package/dist/domains/metrics/components/scores-card.es.js.map +1 -1
- package/dist/domains/metrics/components/token-usage-card.cjs.js +3 -3
- package/dist/domains/metrics/components/token-usage-card.es.js +3 -3
- package/dist/domains/metrics/components/trace-aggregate-card.cjs.js +1 -1
- package/dist/domains/metrics/components/trace-aggregate-card.es.js +1 -1
- package/dist/domains/observability/components/observability-histogram.cjs.js +1 -1
- package/dist/domains/observability/components/observability-histogram.es.js +1 -1
- package/dist/domains/scores/components/trace-scores-list.cjs.js +2 -2
- package/dist/domains/scores/components/trace-scores-list.es.js +2 -2
- package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
- package/dist/domains/skills/skill-simple-form.es.js +1 -1
- package/dist/domains/spans/components/spans-filter-bar.cjs.js +2 -2
- package/dist/domains/spans/components/spans-filter-bar.es.js +2 -2
- package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
- package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
- package/dist/domains/threads/components/threads-filter-bar.cjs.js +2 -2
- package/dist/domains/threads/components/threads-filter-bar.es.js +2 -2
- package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
- package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -2
- package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-tools-section.es.js +1 -1
- package/dist/domains/traces/components/span-timeline-row.cjs.js +1 -1
- package/dist/domains/traces/components/span-timeline-row.es.js +1 -1
- package/dist/domains/traces/components/span-timing-hover-card.cjs.js +1 -1
- package/dist/domains/traces/components/span-timing-hover-card.es.js +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js +8 -2
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.es.js +8 -2
- package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
- package/dist/domains/traces/components/trace-error-cell.cjs.js +1 -1
- package/dist/domains/traces/components/trace-error-cell.es.js +1 -1
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +2 -2
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +2 -2
- package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
- package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
- package/dist/domains/workflows/runs/workflow-run-list.cjs.js +1 -1
- package/dist/domains/workflows/runs/workflow-run-list.es.js +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +2 -2
- package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +2 -2
- package/dist/domains/workflows/workflow/use-workflow-trigger.cjs.js +3 -3
- package/dist/domains/workflows/workflow/use-workflow-trigger.es.js +3 -3
- package/dist/domains/workflows/workflow/workflow-input-data.cjs.js +1 -1
- package/dist/domains/workflows/workflow/workflow-input-data.es.js +1 -1
- package/dist/domains/workflows/workflow/workflow-suspended-steps.cjs.js +2 -2
- package/dist/domains/workflows/workflow/workflow-suspended-steps.es.js +2 -2
- package/dist/domains/workflows/workflow/workflow-time-travel-form.cjs.js +2 -2
- package/dist/domains/workflows/workflow/workflow-time-travel-form.es.js +2 -2
- package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
- package/dist/domains/workspace/components/workspace-markdown-preview.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-markdown-preview.es.js +1 -1
- package/dist/{filter-bar-time-range-mg9JeYue.js → filter-bar-time-range-qlV8p7hp.js} +2 -2
- package/dist/{filter-bar-time-range-mg9JeYue.js.map → filter-bar-time-range-qlV8p7hp.js.map} +1 -1
- package/dist/{filter-bar-time-range-BA-pXMlo.cjs → filter-bar-time-range-zdM024JD.cjs} +2 -2
- package/dist/{filter-bar-time-range-BA-pXMlo.cjs.map → filter-bar-time-range-zdM024JD.cjs.map} +1 -1
- package/dist/lib/form/dynamic-form.cjs.js +2 -2
- package/dist/lib/form/dynamic-form.es.js +2 -2
- package/dist/lib/form/json-draft.cjs.js +1 -1
- package/dist/lib/form/json-draft.es.js +1 -1
- package/dist/lib/form/zod-provider.cjs.js +1 -1
- package/dist/lib/form/zod-provider.es.js +1 -1
- package/dist/{span-payload-primitives-B3RdahsC.js → span-payload-primitives-CKKIAVPJ.js} +4 -4
- package/dist/{span-payload-primitives-B3RdahsC.js.map → span-payload-primitives-CKKIAVPJ.js.map} +1 -1
- package/dist/{span-payload-primitives-_2d-pAOD.cjs → span-payload-primitives-D4tHWN2W.cjs} +4 -4
- package/dist/{span-payload-primitives-_2d-pAOD.cjs.map → span-payload-primitives-D4tHWN2W.cjs.map} +1 -1
- package/dist/src/domains/chat/knowledge/knowledge-links.d.ts +32 -4
- package/dist/src/domains/chat/knowledge/pinned-knowledge-data.d.ts +2 -0
- package/dist/src/domains/chat/tools/badges/knowledge-body-range.d.ts +12 -0
- package/dist/src/domains/chat/tools/badges/knowledge-tool-badge.d.ts +5 -2
- package/dist/src/domains/chat/tools/badges/mcp-input-request-badge.d.ts +18 -0
- package/dist/src/domains/chat/tools/badges/tool-badge.d.ts +4 -1
- package/dist/src/domains/chat/tools/badges/use-deferred-input-request.d.ts +44 -0
- package/dist/src/domains/chat/tools/badges/use-mcp-task-progress.d.ts +6 -1
- package/dist/src/domains/chat/tools/connect-prompt-tool.d.ts +10 -1
- package/dist/src/domains/chat/tools/mcp-input-request-tool.d.ts +18 -0
- package/dist/src/domains/chat/tools/mcp-input-request.d.ts +40 -0
- package/dist/src/domains/chat/tools/tool-card-kind.d.ts +4 -2
- package/dist/src/domains/chat/tools/tool-card.d.ts +1 -1
- package/dist/src/domains/connect/types.d.ts +16 -0
- package/dist/src/domains/dashboards/components/dashboard-renderer.d.ts +4 -2
- package/dist/src/domains/dashboards/hooks/use-widget-views.d.ts +4 -3
- package/dist/src/domains/dashboards/index.d.ts +1 -1
- package/dist/src/domains/dashboards/kinds/scores/scores-widget.d.ts +1 -1
- package/dist/src/domains/dashboards/lib/chrome.d.ts +6 -4
- package/dist/src/domains/dashboards/widget-kind.d.ts +12 -0
- package/dist/src/domains/knowledge/components/KnowledgePageCard.d.ts +23 -0
- package/dist/src/domains/knowledge/components/KnowledgePageExplorer.d.ts +29 -0
- package/dist/src/domains/knowledge/components/KnowledgePageGraph.d.ts +27 -1
- package/dist/src/domains/knowledge/components/KnowledgePageTree.d.ts +2 -1
- package/dist/src/domains/knowledge/lib/circleText.d.ts +2 -0
- package/dist/src/domains/knowledge/lib/fitViewport.d.ts +67 -0
- package/dist/src/domains/knowledge/lib/graphShape.d.ts +131 -0
- package/dist/src/domains/knowledge/lib/linkCountsText.d.ts +5 -0
- package/dist/src/domains/knowledge/lib/pageAddress.d.ts +5 -0
- package/dist/src/domains/knowledge/lib/pageGraph.d.ts +4 -4
- package/dist/src/domains/knowledge/lib/pageRefs.d.ts +15 -0
- package/dist/src/domains/knowledge/lib/pageTree.d.ts +2 -0
- package/dist/src/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +13 -0
- package/dist/src/domains/knowledge/lib/tooltipSide.d.ts +40 -0
- package/dist/src/domains/knowledge/lib/useLeavingNodes.d.ts +14 -0
- package/dist/src/domains/knowledge/lib/useStableWhile.d.ts +5 -0
- package/dist/src/domains/knowledge/pageTypes.d.ts +6 -1
- package/dist/src/ds/components/DateTimeRangePicker/date-time-range-picker.d.ts +12 -1
- package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +8 -1
- package/dist/src/ds/components/MetricsCard/metrics-card-headline.d.ts +1 -1
- package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.d.ts +8 -0
- package/dist/src/ds/components/ai/tool-call/tool-phrases.d.ts +6 -0
- package/dist/style.css +73 -2
- package/dist/{tool-approval-1qiB4hhG.cjs → tool-approval-CJvPDL7D.cjs} +4 -4
- package/dist/{tool-approval-1qiB4hhG.cjs.map → tool-approval-CJvPDL7D.cjs.map} +1 -1
- package/dist/{tool-approval-B6MFcaKV.js → tool-approval-DyN11vFA.js} +4 -4
- package/dist/{tool-approval-B6MFcaKV.js.map → tool-approval-DyN11vFA.js.map} +1 -1
- package/dist/{tool-call-Bu66PkD-.cjs → tool-call-DBn14X-3.cjs} +9 -3
- package/dist/{tool-call-Bu66PkD-.cjs.map → tool-call-DBn14X-3.cjs.map} +1 -1
- package/dist/{tool-call-Ch9-jjXU.js → tool-call-Dsj43lvJ.js} +9 -3
- package/dist/{tool-call-Ch9-jjXU.js.map → tool-call-Dsj43lvJ.js.map} +1 -1
- package/dist/{tool-card-DrqPZfPQ.cjs → tool-card-BOLXeKIp.cjs} +167 -126
- package/dist/tool-card-BOLXeKIp.cjs.map +1 -0
- package/dist/{tool-card-sO6P2Qj4.js → tool-card-HZ5bm7ue.js} +168 -127
- package/dist/tool-card-HZ5bm7ue.js.map +1 -0
- package/dist/{tool-presentation-DvCsb_kz.js → tool-presentation-CvibOP1J.js} +6 -1
- package/dist/tool-presentation-CvibOP1J.js.map +1 -0
- package/dist/{tool-presentation-CQlDEwgS.cjs → tool-presentation-D6nzVruN.cjs} +6 -1
- package/dist/tool-presentation-D6nzVruN.cjs.map +1 -0
- package/package.json +11 -11
- package/dist/MarkdownRenderer-2GOXQJEv.js.map +0 -1
- package/dist/MarkdownRenderer-CB8Z_CHc.cjs.map +0 -1
- package/dist/MetricsCard-CEB-f2sv.cjs.map +0 -1
- package/dist/MetricsCard-M8awJ2B_.js.map +0 -1
- package/dist/MetricsLineChart-BhHoduO0.js.map +0 -1
- package/dist/MetricsLineChart-CjBm4IXu.cjs.map +0 -1
- package/dist/date-time-range-picker-CTt7Od0P.cjs.map +0 -1
- package/dist/date-time-range-picker-DKh1K9Iy.js.map +0 -1
- package/dist/domains/knowledge/lib/pageLayout.cjs.js +0 -49
- package/dist/domains/knowledge/lib/pageLayout.cjs.js.map +0 -1
- package/dist/domains/knowledge/lib/pageLayout.d.ts +0 -1
- package/dist/domains/knowledge/lib/pageLayout.es.js +0 -48
- package/dist/domains/knowledge/lib/pageLayout.es.js.map +0 -1
- package/dist/src/domains/knowledge/lib/pageLayout.d.ts +0 -24
- package/dist/tool-card-DrqPZfPQ.cjs.map +0 -1
- package/dist/tool-card-sO6P2Qj4.js.map +0 -1
- package/dist/tool-presentation-CQlDEwgS.cjs.map +0 -1
- package/dist/tool-presentation-DvCsb_kz.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as ToolCard, n as ToolCardInner } from "../../../tool-card-
|
|
1
|
+
export { t as ToolCard, n as ToolCardInner } from "../../../tool-card-HZ5bm7ue.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_tool_call = require("../../../tool-call-
|
|
2
|
+
const require_tool_call = require("../../../tool-call-DBn14X-3.cjs");
|
|
3
3
|
const require_domains_chat_messages_signal_data = require("../messages/signal-data.cjs.js");
|
|
4
4
|
const require_domains_chat_messages_renderers_tool_part = require("../messages/renderers/tool-part.cjs.js");
|
|
5
5
|
const require_domains_chat_tools_tool_card_kind = require("./tool-card-kind.cjs.js");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as groupConsecutive } from "../../../tool-call-
|
|
1
|
+
import { u as groupConsecutive } from "../../../tool-call-Dsj43lvJ.js";
|
|
2
2
|
import { isSignalData } from "../messages/signal-data.es.js";
|
|
3
3
|
import { isToolPart, readToolPart } from "../messages/renderers/tool-part.es.js";
|
|
4
4
|
import { toolCardKind, toolInteraction } from "./tool-card-kind.es.js";
|
package/dist/domains/chat.cjs.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_domains_chat_messages_signal_data = require("./chat/messages/signal-data.cjs.js");
|
|
3
|
+
const require_domains_chat_knowledge_pinned_knowledge_data = require("./chat/knowledge/pinned-knowledge-data.cjs.js");
|
|
4
|
+
const require_domains_chat_knowledge_knowledge_links = require("./chat/knowledge/knowledge-links.cjs.js");
|
|
2
5
|
const require_domains_chat_context_chat_context = require("./chat/context/chat-context.cjs.js");
|
|
3
6
|
const require_domains_chat_components_badge_wrapper = require("./chat/components/badge-wrapper.cjs.js");
|
|
4
7
|
const require_domains_chat_components_loading_badge = require("./chat/components/loading-badge.cjs.js");
|
|
@@ -7,9 +10,6 @@ const require_domains_chat_components_section_label = require("./chat/components
|
|
|
7
10
|
const require_domains_chat_context_dataset_save_context_value = require("./chat/context/dataset-save-context-value.cjs.js");
|
|
8
11
|
const require_domains_chat_context_dataset_save_context = require("./chat/context/dataset-save-context.cjs.js");
|
|
9
12
|
const require_domains_chat_context_tool_call_context = require("./chat/context/tool-call-context.cjs.js");
|
|
10
|
-
const require_domains_chat_messages_signal_data = require("./chat/messages/signal-data.cjs.js");
|
|
11
|
-
const require_domains_chat_knowledge_pinned_knowledge_data = require("./chat/knowledge/pinned-knowledge-data.cjs.js");
|
|
12
|
-
const require_domains_chat_knowledge_knowledge_links = require("./chat/knowledge/knowledge-links.cjs.js");
|
|
13
13
|
const require_domains_chat_knowledge_pinned_knowledge = require("./chat/knowledge/pinned-knowledge.cjs.js");
|
|
14
14
|
const require_domains_chat_tools_badges_knowledge_tool_badge = require("./chat/tools/badges/knowledge-tool-badge.cjs.js");
|
|
15
15
|
const require_domains_chat_messages_renderers_tool_part = require("./chat/messages/renderers/tool-part.cjs.js");
|
|
@@ -52,5 +52,7 @@ exports.useChatRunning = require_domains_chat_context_chat_context.useChatRunnin
|
|
|
52
52
|
exports.useChatSend = require_domains_chat_context_chat_context.useChatSend;
|
|
53
53
|
exports.useChatTasks = require_domains_chat_context_chat_context.useChatTasks;
|
|
54
54
|
exports.useDatasetSaveContext = require_domains_chat_context_dataset_save_context_value.useDatasetSaveContext;
|
|
55
|
+
exports.useHasKnowledgeLinks = require_domains_chat_knowledge_knowledge_links.useHasKnowledgeLinks;
|
|
56
|
+
exports.useKnowledgeLinksContext = require_domains_chat_knowledge_knowledge_links.useKnowledgeLinksContext;
|
|
55
57
|
exports.useOptionalToolCall = require_domains_chat_context_tool_call_context.useOptionalToolCall;
|
|
56
58
|
exports.useToolCall = require_domains_chat_context_tool_call_context.useToolCall;
|
package/dist/domains/chat.es.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { formatSignalValue, getMcpEventSignalInfo, getNotificationMetadata, getSignalType, isRecord, isSignalData, isUserSignalType, signalContentsToText, toReactiveSignalData } from "./chat/messages/signal-data.es.js";
|
|
2
|
+
import { knowledgePageHref, pinnedKnowledgeFromSignal } from "./chat/knowledge/pinned-knowledge-data.es.js";
|
|
3
|
+
import { KnowledgeLinksProvider, KnowledgePageLink, useHasKnowledgeLinks, useKnowledgeLinksContext } from "./chat/knowledge/knowledge-links.es.js";
|
|
1
4
|
import { ChatAgentContext, ChatMessagesContext, ChatRunningContext, ChatSendContext, ChatTasksContext, useChatMessages, useChatRunning, useChatSend, useChatTasks } from "./chat/context/chat-context.es.js";
|
|
2
5
|
import { BadgeWrapper } from "./chat/components/badge-wrapper.es.js";
|
|
3
6
|
import { LoadingBadge } from "./chat/components/loading-badge.es.js";
|
|
@@ -6,12 +9,9 @@ import { SectionLabel } from "./chat/components/section-label.es.js";
|
|
|
6
9
|
import { useDatasetSaveContext } from "./chat/context/dataset-save-context-value.es.js";
|
|
7
10
|
import { DatasetSaveProvider } from "./chat/context/dataset-save-context.es.js";
|
|
8
11
|
import { ToolCallProvider, useOptionalToolCall, useToolCall } from "./chat/context/tool-call-context.es.js";
|
|
9
|
-
import { formatSignalValue, getMcpEventSignalInfo, getNotificationMetadata, getSignalType, isRecord, isSignalData, isUserSignalType, signalContentsToText, toReactiveSignalData } from "./chat/messages/signal-data.es.js";
|
|
10
|
-
import { knowledgePageHref, pinnedKnowledgeFromSignal } from "./chat/knowledge/pinned-knowledge-data.es.js";
|
|
11
|
-
import { KnowledgeLinksProvider, KnowledgePageLink } from "./chat/knowledge/knowledge-links.es.js";
|
|
12
12
|
import { PinnedKnowledgeActivity } from "./chat/knowledge/pinned-knowledge.es.js";
|
|
13
13
|
import { KNOWLEDGE_TOOLS, knowledgeCard } from "./chat/tools/badges/knowledge-tool-badge.es.js";
|
|
14
14
|
import { isToolPart, readToolPart } from "./chat/messages/renderers/tool-part.es.js";
|
|
15
15
|
import { DatasetSaveAction, SaveFullConversationAction } from "./chat/messages/dataset-save-action.es.js";
|
|
16
16
|
import { AssistantMessageActions } from "./chat/messages/assistant-message-actions.es.js";
|
|
17
|
-
export { AssistantMessageActions, BadgeWrapper, ChatAgentContext, ChatMessagesContext, ChatRunningContext, ChatSendContext, ChatTasksContext, DatasetSaveAction, DatasetSaveProvider, KNOWLEDGE_TOOLS, KnowledgeLinksProvider, KnowledgePageLink, LoadingBadge, NetworkChoiceMetadataDialogTrigger, PinnedKnowledgeActivity, SaveFullConversationAction, SectionLabel, ToolCallProvider, formatSignalValue, getMcpEventSignalInfo, getNotificationMetadata, getSignalType, isRecord, isSignalData, isToolPart, isUserSignalType, knowledgeCard, knowledgePageHref, pinnedKnowledgeFromSignal, readToolPart, signalContentsToText, toReactiveSignalData, useChatMessages, useChatRunning, useChatSend, useChatTasks, useDatasetSaveContext, useOptionalToolCall, useToolCall };
|
|
17
|
+
export { AssistantMessageActions, BadgeWrapper, ChatAgentContext, ChatMessagesContext, ChatRunningContext, ChatSendContext, ChatTasksContext, DatasetSaveAction, DatasetSaveProvider, KNOWLEDGE_TOOLS, KnowledgeLinksProvider, KnowledgePageLink, LoadingBadge, NetworkChoiceMetadataDialogTrigger, PinnedKnowledgeActivity, SaveFullConversationAction, SectionLabel, ToolCallProvider, formatSignalValue, getMcpEventSignalInfo, getNotificationMetadata, getSignalType, isRecord, isSignalData, isToolPart, isUserSignalType, knowledgeCard, knowledgePageHref, pinnedKnowledgeFromSignal, readToolPart, signalContentsToText, toReactiveSignalData, useChatMessages, useChatRunning, useChatSend, useChatTasks, useDatasetSaveContext, useHasKnowledgeLinks, useKnowledgeLinksContext, useOptionalToolCall, useToolCall };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs.js","names":[],"sources":["../../../src/domains/connect/types.ts"],"sourcesContent":["/**\n * Wire contract of the end-user connect surface that `userConnectRoutes()`\n * from `@mastra/connect` mounts on the dev server (default base path\n * `/connect`). These routes are custom `apiRoutes`, so they are not part of\n * the `@mastra/client-js` SDK — the shapes below mirror\n * `packages/connect/src/user-connect-routes.ts` and must stay in sync with it.\n */\n\nexport interface UserConnectAuthField {\n name: string;\n /**\n * Where the value goes in a headless auth call: `credentials` are\n * exchanged with the provider, `params` configure the flow (e.g. an MCP\n * server URL). Missing (older servers) is treated as `credentials`.\n */\n target?: 'credentials' | 'params' | null;\n label?: string | null;\n description?: string | null;\n placeholder?: string | null;\n secret?: boolean | null;\n required?: boolean | null;\n order?: number | null;\n}\n\n/** JSON redemption of the launch gate (`Accept: application/json`). */\nexport interface UserConnectLaunchTokenResponse {\n /**\n * Nango connect session token for headless authorization, or null when the\n * server could not extract one — the client then falls back to the hosted\n * popup through the same gate's 302 flow.\n */\n sessionToken: string | null;\n expiresAt: string;\n}\n\nexport interface UserConnectProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n authFields: UserConnectAuthField[] | null;\n}\n\nexport interface UserConnectProvidersResponse {\n providers: UserConnectProvider[];\n}\n\nexport type UserConnectionScope = 'global' | 'user';\n\nexport interface UserConnection {\n id: string;\n integrationId: string;\n /**\n * Display metadata resolved server-side against the FULL platform catalog\n * (not the policy-filtered provider list), so rows for de-allowlisted\n * providers still render properly. Null when the catalog has no entry or\n * the lookup failed.\n */\n displayName: string | null;\n logoUrl: string | null;\n status: string;\n accountLabel: string | null;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectionsResponse {\n connections: UserConnection[];\n}\n\nexport interface UserConnectSessionResponse {\n connectionId: string;\n integrationId: string;\n /**\n * Server-relative launch-gate path (`{basePath}/connections/:id/launch`).\n * The popup navigates here — same-origin with the Mastra server and\n * authenticated — and the server verifies this browser owns the pending\n * session before 302ing into the vendor OAuth flow. The raw vendor connect\n * URL is never exposed to the browser.\n */\n launchUrl: string;\n expiresAt: string | null;\n}\n\nexport interface UserConnectionStatusResponse {\n id: string;\n status: string;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectErrorBody {\n error: { code: string; message: string };\n}\n\n/**\n * One provider in the structured output of the built-in `request_connection`\n * tool (`@mastra/connect`'s `ConnectPromptProvider`). Chat renders these as a\n * connect card.\n */\nexport interface ConnectPromptProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n /** Fields the UI must collect before starting headless authorization. */\n authFields: UserConnectAuthField[] | null;\n connected: boolean;\n scope: UserConnectionScope | null;\n}\n\n/** Structured output of the built-in `request_connection` tool. */\nexport interface ConnectPromptPayload {\n type: 'connect-prompt';\n requestedProvider?: string;\n providers: ConnectPromptProvider[];\n}\n\n/** Narrows an arbitrary tool output to a connect-prompt payload. */\nexport function isConnectPromptPayload(output: unknown): output is ConnectPromptPayload {\n return (\n typeof output === 'object' &&\n output !== null &&\n (output as { type?: unknown }).type === 'connect-prompt' &&\n Array.isArray((output as { providers?: unknown }).providers)\n );\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"types.cjs.js","names":[],"sources":["../../../src/domains/connect/types.ts"],"sourcesContent":["/**\n * Wire contract of the end-user connect surface that `userConnectRoutes()`\n * from `@mastra/connect` mounts on the dev server (default base path\n * `/connect`). These routes are custom `apiRoutes`, so they are not part of\n * the `@mastra/client-js` SDK — the shapes below mirror\n * `packages/connect/src/user-connect-routes.ts` and must stay in sync with it.\n */\n\nexport interface UserConnectAuthField {\n name: string;\n /**\n * Where the value goes in a headless auth call: `credentials` are\n * exchanged with the provider, `params` configure the flow (e.g. an MCP\n * server URL). Missing (older servers) is treated as `credentials`.\n */\n target?: 'credentials' | 'params' | null;\n label?: string | null;\n description?: string | null;\n placeholder?: string | null;\n secret?: boolean | null;\n required?: boolean | null;\n order?: number | null;\n}\n\n/** JSON redemption of the launch gate (`Accept: application/json`). */\nexport interface UserConnectLaunchTokenResponse {\n /**\n * Nango connect session token for headless authorization, or null when the\n * server could not extract one — the client then falls back to the hosted\n * popup through the same gate's 302 flow.\n */\n sessionToken: string | null;\n expiresAt: string;\n}\n\nexport interface UserConnectProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n authFields: UserConnectAuthField[] | null;\n}\n\nexport interface UserConnectProvidersResponse {\n providers: UserConnectProvider[];\n}\n\nexport type UserConnectionScope = 'global' | 'user';\n\nexport interface UserConnection {\n id: string;\n integrationId: string;\n /**\n * Display metadata resolved server-side against the FULL platform catalog\n * (not the policy-filtered provider list), so rows for de-allowlisted\n * providers still render properly. Null when the catalog has no entry or\n * the lookup failed.\n */\n displayName: string | null;\n logoUrl: string | null;\n status: string;\n accountLabel: string | null;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectionsResponse {\n connections: UserConnection[];\n}\n\nexport interface UserConnectSessionResponse {\n connectionId: string;\n integrationId: string;\n /**\n * Server-relative launch-gate path (`{basePath}/connections/:id/launch`).\n * The popup navigates here — same-origin with the Mastra server and\n * authenticated — and the server verifies this browser owns the pending\n * session before 302ing into the vendor OAuth flow. The raw vendor connect\n * URL is never exposed to the browser.\n */\n launchUrl: string;\n expiresAt: string | null;\n}\n\nexport interface UserConnectionStatusResponse {\n id: string;\n status: string;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectErrorBody {\n error: { code: string; message: string };\n}\n\n/**\n * One provider in the structured output of the built-in `request_connection`\n * tool (`@mastra/connect`'s `ConnectPromptProvider`). Chat renders these as a\n * connect card.\n */\nexport interface ConnectPromptProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n /** Fields the UI must collect before starting headless authorization. */\n authFields: UserConnectAuthField[] | null;\n connected: boolean;\n scope: UserConnectionScope | null;\n}\n\n/** Structured output of the built-in `request_connection` tool. */\nexport interface ConnectPromptPayload {\n type: 'connect-prompt';\n requestedProvider?: string;\n providers: ConnectPromptProvider[];\n /** Outcome for the model once a paused prompt resumes, e.g. \"Linear connected successfully.\" */\n message?: string;\n /** Why the connection failed, when a paused prompt resumed without one. */\n error?: string;\n}\n\n/**\n * What the card resumes a paused `request_connection` call with once the\n * connection settles: `active`, or `failed` with the reason the card showed.\n */\nexport type ConnectPromptResume =\n | { provider: string; status: 'active' }\n | { provider: string; status: 'failed'; error: string };\n\n/** Narrows an arbitrary tool output to a connect-prompt payload. */\nexport function isConnectPromptPayload(output: unknown): output is ConnectPromptPayload {\n return (\n typeof output === 'object' &&\n output !== null &&\n (output as { type?: unknown }).type === 'connect-prompt' &&\n Array.isArray((output as { providers?: unknown }).providers)\n );\n}\n"],"mappings":";;;AAiIA,SAAgB,uBAAuB,QAAiD;CACtF,OACE,OAAO,WAAW,YAClB,WAAW,QACV,OAA8B,SAAS,oBACxC,MAAM,QAAS,OAAmC,SAAS;AAE/D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.es.js","names":[],"sources":["../../../src/domains/connect/types.ts"],"sourcesContent":["/**\n * Wire contract of the end-user connect surface that `userConnectRoutes()`\n * from `@mastra/connect` mounts on the dev server (default base path\n * `/connect`). These routes are custom `apiRoutes`, so they are not part of\n * the `@mastra/client-js` SDK — the shapes below mirror\n * `packages/connect/src/user-connect-routes.ts` and must stay in sync with it.\n */\n\nexport interface UserConnectAuthField {\n name: string;\n /**\n * Where the value goes in a headless auth call: `credentials` are\n * exchanged with the provider, `params` configure the flow (e.g. an MCP\n * server URL). Missing (older servers) is treated as `credentials`.\n */\n target?: 'credentials' | 'params' | null;\n label?: string | null;\n description?: string | null;\n placeholder?: string | null;\n secret?: boolean | null;\n required?: boolean | null;\n order?: number | null;\n}\n\n/** JSON redemption of the launch gate (`Accept: application/json`). */\nexport interface UserConnectLaunchTokenResponse {\n /**\n * Nango connect session token for headless authorization, or null when the\n * server could not extract one — the client then falls back to the hosted\n * popup through the same gate's 302 flow.\n */\n sessionToken: string | null;\n expiresAt: string;\n}\n\nexport interface UserConnectProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n authFields: UserConnectAuthField[] | null;\n}\n\nexport interface UserConnectProvidersResponse {\n providers: UserConnectProvider[];\n}\n\nexport type UserConnectionScope = 'global' | 'user';\n\nexport interface UserConnection {\n id: string;\n integrationId: string;\n /**\n * Display metadata resolved server-side against the FULL platform catalog\n * (not the policy-filtered provider list), so rows for de-allowlisted\n * providers still render properly. Null when the catalog has no entry or\n * the lookup failed.\n */\n displayName: string | null;\n logoUrl: string | null;\n status: string;\n accountLabel: string | null;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectionsResponse {\n connections: UserConnection[];\n}\n\nexport interface UserConnectSessionResponse {\n connectionId: string;\n integrationId: string;\n /**\n * Server-relative launch-gate path (`{basePath}/connections/:id/launch`).\n * The popup navigates here — same-origin with the Mastra server and\n * authenticated — and the server verifies this browser owns the pending\n * session before 302ing into the vendor OAuth flow. The raw vendor connect\n * URL is never exposed to the browser.\n */\n launchUrl: string;\n expiresAt: string | null;\n}\n\nexport interface UserConnectionStatusResponse {\n id: string;\n status: string;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectErrorBody {\n error: { code: string; message: string };\n}\n\n/**\n * One provider in the structured output of the built-in `request_connection`\n * tool (`@mastra/connect`'s `ConnectPromptProvider`). Chat renders these as a\n * connect card.\n */\nexport interface ConnectPromptProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n /** Fields the UI must collect before starting headless authorization. */\n authFields: UserConnectAuthField[] | null;\n connected: boolean;\n scope: UserConnectionScope | null;\n}\n\n/** Structured output of the built-in `request_connection` tool. */\nexport interface ConnectPromptPayload {\n type: 'connect-prompt';\n requestedProvider?: string;\n providers: ConnectPromptProvider[];\n}\n\n/** Narrows an arbitrary tool output to a connect-prompt payload. */\nexport function isConnectPromptPayload(output: unknown): output is ConnectPromptPayload {\n return (\n typeof output === 'object' &&\n output !== null &&\n (output as { type?: unknown }).type === 'connect-prompt' &&\n Array.isArray((output as { providers?: unknown }).providers)\n );\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"types.es.js","names":[],"sources":["../../../src/domains/connect/types.ts"],"sourcesContent":["/**\n * Wire contract of the end-user connect surface that `userConnectRoutes()`\n * from `@mastra/connect` mounts on the dev server (default base path\n * `/connect`). These routes are custom `apiRoutes`, so they are not part of\n * the `@mastra/client-js` SDK — the shapes below mirror\n * `packages/connect/src/user-connect-routes.ts` and must stay in sync with it.\n */\n\nexport interface UserConnectAuthField {\n name: string;\n /**\n * Where the value goes in a headless auth call: `credentials` are\n * exchanged with the provider, `params` configure the flow (e.g. an MCP\n * server URL). Missing (older servers) is treated as `credentials`.\n */\n target?: 'credentials' | 'params' | null;\n label?: string | null;\n description?: string | null;\n placeholder?: string | null;\n secret?: boolean | null;\n required?: boolean | null;\n order?: number | null;\n}\n\n/** JSON redemption of the launch gate (`Accept: application/json`). */\nexport interface UserConnectLaunchTokenResponse {\n /**\n * Nango connect session token for headless authorization, or null when the\n * server could not extract one — the client then falls back to the hosted\n * popup through the same gate's 302 flow.\n */\n sessionToken: string | null;\n expiresAt: string;\n}\n\nexport interface UserConnectProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n authFields: UserConnectAuthField[] | null;\n}\n\nexport interface UserConnectProvidersResponse {\n providers: UserConnectProvider[];\n}\n\nexport type UserConnectionScope = 'global' | 'user';\n\nexport interface UserConnection {\n id: string;\n integrationId: string;\n /**\n * Display metadata resolved server-side against the FULL platform catalog\n * (not the policy-filtered provider list), so rows for de-allowlisted\n * providers still render properly. Null when the catalog has no entry or\n * the lookup failed.\n */\n displayName: string | null;\n logoUrl: string | null;\n status: string;\n accountLabel: string | null;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectionsResponse {\n connections: UserConnection[];\n}\n\nexport interface UserConnectSessionResponse {\n connectionId: string;\n integrationId: string;\n /**\n * Server-relative launch-gate path (`{basePath}/connections/:id/launch`).\n * The popup navigates here — same-origin with the Mastra server and\n * authenticated — and the server verifies this browser owns the pending\n * session before 302ing into the vendor OAuth flow. The raw vendor connect\n * URL is never exposed to the browser.\n */\n launchUrl: string;\n expiresAt: string | null;\n}\n\nexport interface UserConnectionStatusResponse {\n id: string;\n status: string;\n scope: UserConnectionScope;\n}\n\nexport interface UserConnectErrorBody {\n error: { code: string; message: string };\n}\n\n/**\n * One provider in the structured output of the built-in `request_connection`\n * tool (`@mastra/connect`'s `ConnectPromptProvider`). Chat renders these as a\n * connect card.\n */\nexport interface ConnectPromptProvider {\n id: string;\n displayName: string | null;\n logoUrl: string | null;\n authType: string | null;\n /** Fields the UI must collect before starting headless authorization. */\n authFields: UserConnectAuthField[] | null;\n connected: boolean;\n scope: UserConnectionScope | null;\n}\n\n/** Structured output of the built-in `request_connection` tool. */\nexport interface ConnectPromptPayload {\n type: 'connect-prompt';\n requestedProvider?: string;\n providers: ConnectPromptProvider[];\n /** Outcome for the model once a paused prompt resumes, e.g. \"Linear connected successfully.\" */\n message?: string;\n /** Why the connection failed, when a paused prompt resumed without one. */\n error?: string;\n}\n\n/**\n * What the card resumes a paused `request_connection` call with once the\n * connection settles: `active`, or `failed` with the reason the card showed.\n */\nexport type ConnectPromptResume =\n | { provider: string; status: 'active' }\n | { provider: string; status: 'failed'; error: string };\n\n/** Narrows an arbitrary tool output to a connect-prompt payload. */\nexport function isConnectPromptPayload(output: unknown): output is ConnectPromptPayload {\n return (\n typeof output === 'object' &&\n output !== null &&\n (output as { type?: unknown }).type === 'connect-prompt' &&\n Array.isArray((output as { providers?: unknown }).providers)\n );\n}\n"],"mappings":";;AAiIA,SAAgB,uBAAuB,QAAiD;CACtF,OACE,OAAO,WAAW,YAClB,WAAW,QACV,OAA8B,SAAS,oBACxC,MAAM,QAAS,OAAmC,SAAS;AAE/D"}
|
|
@@ -116,6 +116,23 @@ function useConnectSurface() {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
var connectionsQueryKey = ["user-connect", "connections"];
|
|
119
|
+
/**
|
|
120
|
+
* A connection that activates or goes away changes which tools resolve for
|
|
121
|
+
* this user, so the connection list and every agent / tool listing are
|
|
122
|
+
* refetched. The server drops its cached tool snapshot when it reports the
|
|
123
|
+
* change, so the refetch already sees the new tools.
|
|
124
|
+
*/
|
|
125
|
+
function invalidateAfterConnectionChange(queryClient) {
|
|
126
|
+
return Promise.all([
|
|
127
|
+
connectionsQueryKey,
|
|
128
|
+
["agent"],
|
|
129
|
+
["agents"],
|
|
130
|
+
["tools"]
|
|
131
|
+
].map(async (queryKey) => {
|
|
132
|
+
await queryClient.cancelQueries({ queryKey });
|
|
133
|
+
await queryClient.invalidateQueries({ queryKey });
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
119
136
|
/** Lists the caller's visible connections (global + their own). */
|
|
120
137
|
function useUserConnections({ enabled }) {
|
|
121
138
|
const connectFetch = useConnectFetch();
|
|
@@ -171,7 +188,7 @@ function useConnectionStatus({ connectionId }) {
|
|
|
171
188
|
};
|
|
172
189
|
throw error;
|
|
173
190
|
}
|
|
174
|
-
if (status.status !== "pending") queryClient
|
|
191
|
+
if (status.status !== "pending") invalidateAfterConnectionChange(queryClient);
|
|
175
192
|
return status;
|
|
176
193
|
}
|
|
177
194
|
});
|
|
@@ -375,7 +392,7 @@ function useDisconnectUserConnection() {
|
|
|
375
392
|
const queryClient = (0, _tanstack_react_query.useQueryClient)();
|
|
376
393
|
return (0, _tanstack_react_query.useMutation)({
|
|
377
394
|
mutationFn: ({ connectionId }) => connectFetch(`/connections/${encodeURIComponent(connectionId)}`, { method: "DELETE" }),
|
|
378
|
-
onSuccess: () => queryClient
|
|
395
|
+
onSuccess: () => invalidateAfterConnectionChange(queryClient)
|
|
379
396
|
});
|
|
380
397
|
}
|
|
381
398
|
exports.CONNECT_BASE_PATH = CONNECT_BASE_PATH;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-user-connect.cjs.js","names":["useMastraClient","useCallback","useQuery","useMutation","useQueryClient","useState","useRef","splitHeadlessAuthValues","headlessAuthFields","startHeadlessAuth","HeadlessAuthError","supportsHeadlessAuth","headlessAuthRequiresForm"],"sources":["../../../src/domains/connect/use-user-connect.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport {\n HeadlessAuthError,\n headlessAuthFields,\n headlessAuthRequiresForm,\n splitHeadlessAuthValues,\n startHeadlessAuth,\n supportsHeadlessAuth,\n} from './headless-connect';\nimport type { HeadlessAuthHandle } from './headless-connect';\nimport type {\n UserConnectErrorBody,\n UserConnectLaunchTokenResponse,\n UserConnectProvider,\n UserConnectProvidersResponse,\n UserConnectSessionResponse,\n UserConnectionStatusResponse,\n UserConnectionsResponse,\n} from './types';\n\n/** Default mount prefix of `userConnectRoutes()` on the dev server. */\nexport const CONNECT_BASE_PATH = '/connect';\n\nexport class UserConnectRequestError extends Error {\n status: number;\n code: string | null;\n\n constructor(status: number, code: string | null, message: string) {\n super(message);\n this.name = 'UserConnectRequestError';\n this.status = status;\n this.code = code;\n }\n}\n\ntype ConnectFetch = <T>(path: string, init?: RequestInit) => Promise<T>;\n\n/**\n * Fetches against the dev server's mounted connect routes. Custom `apiRoutes`\n * live outside the `/api` prefix, so this goes around the SDK while reusing\n * its base URL, auth headers, credentials mode, and refresh-aware fetch.\n */\nfunction useConnectFetch(): ConnectFetch {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback<ConnectFetch>(\n async (path, init) => {\n const fetchFn = customFetch ?? fetch;\n const response = await fetchFn(`${baseUrl}${CONNECT_BASE_PATH}${path}`, {\n ...init,\n headers: { ...headers, ...init?.headers },\n credentials,\n });\n if (!response.ok) {\n let code: string | null = null;\n let message = `Request failed with status ${response.status}`;\n try {\n const body = (await response.json()) as Partial<UserConnectErrorBody>;\n if (body?.error) {\n code = body.error.code ?? null;\n message = body.error.message ?? message;\n }\n } catch {\n // Non-JSON error body (e.g. a plain 404 for unmounted routes).\n }\n throw new UserConnectRequestError(response.status, code, message);\n }\n if (response.status === 204) return undefined as never;\n return (await response.json()) as never;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\n/**\n * Resolves a server-relative launch-gate path (returned by the session route\n * as `launchUrl`) against the SDK's base URL for top-level popup navigation.\n * The launch route is authenticated by the browser's session cookie — the\n * server re-verifies that this browser owns the pending session before\n * redirecting into the vendor OAuth flow.\n */\nexport function useConnectLaunchHref(): (launchUrl: string) => string {\n const client = useMastraClient();\n const { baseUrl } = client.options;\n return useCallback((launchUrl: string) => (baseUrl ? `${baseUrl}${launchUrl}` : launchUrl), [baseUrl]);\n}\n\n/**\n * Redeems the launch gate for a headless session token (`Accept:\n * application/json`) instead of following its hosted 302. The gate runs the\n * same ownership assertion in both modes; a `null` token means the server\n * could not extract one and the caller falls back to the hosted popup.\n */\nfunction useRedeemLaunchToken(): (launchUrl: string) => Promise<UserConnectLaunchTokenResponse> {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback(\n async launchUrl => {\n const fetchFn = customFetch ?? fetch;\n // `launchUrl` is the full server-relative gate path (it already carries\n // the connect mount prefix), so it resolves against the bare base URL.\n const response = await fetchFn(`${baseUrl ?? ''}${launchUrl}`, {\n headers: { ...headers, accept: 'application/json' },\n credentials,\n });\n if (!response.ok) {\n throw new UserConnectRequestError(response.status, null, `Request failed with status ${response.status}`);\n }\n return (await response.json()) as UserConnectLaunchTokenResponse;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\nexport type ConnectSurface =\n | { status: 'ready'; providers: UserConnectProvidersResponse['providers'] }\n | { status: 'not-mounted' }\n | { status: 'unauthenticated' };\n\n/**\n * Capability detection for the end-user connect surface: probes\n * `GET /connect/providers` and distinguishes a working surface from the two\n * setup gaps (routes not mounted → 404, no end-user identity → 401).\n */\nexport function useConnectSurface() {\n const connectFetch = useConnectFetch();\n\n return useQuery<ConnectSurface, UserConnectRequestError>({\n queryKey: ['user-connect', 'surface'],\n retry: false,\n queryFn: async () => {\n try {\n const body = await connectFetch<UserConnectProvidersResponse>('/providers');\n return { status: 'ready', providers: body.providers };\n } catch (error) {\n if (error instanceof UserConnectRequestError) {\n if (error.status === 404) return { status: 'not-mounted' };\n if (error.status === 401) return { status: 'unauthenticated' };\n }\n throw error;\n }\n },\n });\n}\n\nconst connectionsQueryKey = ['user-connect', 'connections'] as const;\n\n/** Lists the caller's visible connections (global + their own). */\nexport function useUserConnections({ enabled }: { enabled: boolean }) {\n const connectFetch = useConnectFetch();\n\n return useQuery<UserConnectionsResponse['connections'], UserConnectRequestError>({\n queryKey: connectionsQueryKey,\n enabled,\n retry: false,\n queryFn: async () => {\n const body = await connectFetch<UserConnectionsResponse>('/connections');\n return body.connections;\n },\n });\n}\n\n/** Creates a connect session for a provider; the caller drives the popup. */\nexport function useCreateConnectSession() {\n const connectFetch = useConnectFetch();\n\n return useMutation<UserConnectSessionResponse, UserConnectRequestError, { provider: string }>({\n mutationFn: ({ provider }) =>\n connectFetch<UserConnectSessionResponse>(`/${encodeURIComponent(provider)}/sessions`, { method: 'POST' }),\n });\n}\n\n/** 2s interval with a 5 minute cap, mirroring the hosted connect page. */\nconst STATUS_POLL_INTERVAL_MS = 2_000;\nconst STATUS_MAX_POLLS = 150;\n\n/**\n * Polls a pending connection until it leaves `pending`. A 404 counts as still\n * pending — the platform row may not be visible until the provider handshake\n * lands. Polling stops once the status settles (or after the 5 minute cap);\n * the connections list is refreshed when it does.\n */\nexport function useConnectionStatus({ connectionId }: { connectionId: string | null }) {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useQuery<UserConnectionStatusResponse, UserConnectRequestError>({\n queryKey: ['user-connect', 'connection-status', connectionId],\n enabled: connectionId !== null,\n retry: false,\n refetchInterval: query => {\n const status = query.state.data?.status;\n if (status !== undefined && status !== 'pending') return false;\n if (query.state.dataUpdateCount >= STATUS_MAX_POLLS) return false;\n return STATUS_POLL_INTERVAL_MS;\n },\n queryFn: async () => {\n let status: UserConnectionStatusResponse;\n try {\n status = await connectFetch<UserConnectionStatusResponse>(\n `/connections/${encodeURIComponent(connectionId ?? '')}/status`,\n );\n } catch (error) {\n if (error instanceof UserConnectRequestError && error.status === 404) {\n return { id: connectionId ?? '', status: 'pending', scope: 'user' };\n }\n throw error;\n }\n if (status.status !== 'pending') {\n void queryClient.invalidateQueries({ queryKey: connectionsQueryKey });\n }\n return status;\n },\n });\n}\n\nexport interface PendingConnect {\n provider: string;\n connectionId: string;\n /**\n * `headless` — the Nango SDK drives the provider's own consent popup (or no\n * popup at all for collected credentials). `hosted` — a popup navigated\n * through the launch gate's 302 into the hosted connect page.\n */\n mode: 'headless' | 'hosted';\n /** Shown when the popup was blocked so the user can finish the flow manually. */\n fallbackUrl: string | null;\n}\n\n/**\n * What a caller passes to `connect()`: the provider's id plus the auth shape\n * when known. Callers that only know the id (older payloads) always get the\n * hosted flow.\n */\nexport type ConnectTarget = Pick<UserConnectProvider, 'id'> &\n Partial<Pick<UserConnectProvider, 'authType' | 'authFields'>>;\n\n/**\n * Grace period after the vendor popup closes before an unsettled flow is\n * abandoned — the activation webhook often lands a few seconds after the\n * vendor window closes itself.\n */\nconst POPUP_CLOSE_GRACE_MS = 15_000;\n/** Wall-clock cap matching the status poll's 5 minute budget. */\nconst PENDING_TIMEOUT_MS = STATUS_POLL_INTERVAL_MS * STATUS_MAX_POLLS;\n\nexport interface UsePendingConnectOptions {\n /** Overrides for the abandonment timings (primarily for tests). */\n popupCloseGraceMs?: number;\n pendingTimeoutMs?: number;\n}\n\n/**\n * Outcome of the most recently settled flow: `active` when the connection\n * activated, `failed` for everything else (non-active settle, poll failure,\n * abandoned popup, poll budget). Cleared when a new flow starts.\n */\nexport interface SettledConnect {\n provider: string;\n status: 'active' | 'failed';\n /** Human-readable failure detail (blocked popup, closed window, rejected credentials). */\n message?: string;\n}\n\n/** Window features for the hosted connect popup. */\nconst POPUP_FEATURES = 'popup,width=600,height=720';\n\n/**\n * Drives one add-connection flow end to end. Providers whose auth the browser\n * can complete headlessly go through the launch gate's JSON redemption: the\n * released session token keys the Nango SDK, which opens the provider's own\n * consent popup (or submits collected credentials with no popup). Everything\n * else gets the hosted flow — a popup opened synchronously in the click\n * gesture (so popup blockers allow it) and navigated through the launch\n * gate's 302. Either way the connection status is polled until it settles.\n * The pending state always resolves — on settle, on a poll or auth failure,\n * when the popup closes without settling (after a grace period), or at the\n * poll budget — so the Connect action is never stuck disabled.\n */\nexport function usePendingConnect(options: UsePendingConnectOptions = {}) {\n const { popupCloseGraceMs = POPUP_CLOSE_GRACE_MS, pendingTimeoutMs = PENDING_TIMEOUT_MS } = options;\n const session = useCreateConnectSession();\n const resolveLaunchHref = useConnectLaunchHref();\n const redeemLaunchToken = useRedeemLaunchToken();\n const [pending, setPending] = useState<PendingConnect | null>(null);\n const [settled, setSettled] = useState<SettledConnect | null>(null);\n const [connectedProviders, setConnectedProviders] = useState<ReadonlySet<string>>(new Set());\n const popupRef = useRef<Pick<Window, 'closed'> | null>(null);\n const headlessRef = useRef<HeadlessAuthHandle | null>(null);\n // Mirrors `pending` for async guards (the SDK promise settles outside the\n // render cycle); written directly at every transition so a cancel is never\n // raced by a trailing rejection.\n const pendingRef = useRef<PendingConnect | null>(null);\n const status = useConnectionStatus({ connectionId: pending?.connectionId ?? null });\n\n useEffect(() => {\n pendingRef.current = pending;\n }, [pending]);\n\n // Close the provider popup if the surface unmounts mid-flow.\n useEffect(\n () => () => {\n headlessRef.current?.close();\n headlessRef.current = null;\n },\n [],\n );\n\n // Settle only on a status response for the connection currently pending —\n // a stale result from a previous flow must not clear or mark a newer one.\n const statusData = status.data;\n useEffect(() => {\n if (!pending || statusData === undefined) return;\n if (statusData.id !== pending.connectionId || statusData.status === 'pending') return;\n const { provider } = pending;\n if (statusData.status === 'active') {\n setConnectedProviders(previous => (previous.has(provider) ? previous : new Set([...previous, provider])));\n }\n // The provider window closes itself on active settles; drop the handle so\n // a trailing SDK rejection cannot re-settle this flow.\n headlessRef.current = null;\n pendingRef.current = null;\n setSettled({ provider, status: statusData.status === 'active' ? 'active' : 'failed' });\n setPending(null);\n }, [pending, statusData]);\n\n // A failed poll hands the Connect action back instead of leaving it stuck.\n useEffect(() => {\n if (!status.isError || !pending) return;\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }, [status.isError, pending]);\n\n // Abandonment: the popup closed without the flow settling (grace period for\n // the trailing webhook) or the poll budget ran out.\n useEffect(() => {\n if (!pending) return;\n const startedAt = Date.now();\n let closedAt: number | null = null;\n const tickMs = Math.min(1_000, popupCloseGraceMs);\n const timer = window.setInterval(() => {\n if (popupRef.current?.closed) closedAt ??= Date.now();\n const abandoned = closedAt !== null && Date.now() - closedAt >= popupCloseGraceMs;\n const timedOut = Date.now() - startedAt >= pendingTimeoutMs;\n if (abandoned || timedOut) {\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }\n }, tickMs);\n return () => window.clearInterval(timer);\n }, [pending, popupCloseGraceMs, pendingTimeoutMs]);\n\n const beginHeadless = useCallback(\n async (provider: ConnectTarget, created: UserConnectSessionResponse, values?: Record<string, string>) => {\n let sessionToken: string | null = null;\n try {\n sessionToken = (await redeemLaunchToken(created.launchUrl)).sessionToken;\n } catch {\n // Redemption failure (older platform, transient error) is not fatal —\n // the hosted flow below still works through the gate's 302.\n }\n if (!sessionToken) {\n // Opened after an await, so a blocker may stop it; the fallback link\n // in the pending state covers that.\n const launchHref = resolveLaunchHref(created.launchUrl);\n const popup = window.open(launchHref, 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n return;\n }\n\n const split = values ? splitHeadlessAuthValues(headlessAuthFields(provider), values) : {};\n const handle = startHeadlessAuth({\n sessionToken,\n integrationId: created.integrationId,\n authType: provider.authType,\n credentials: split.credentials,\n params: split.params,\n });\n headlessRef.current = handle;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'headless',\n fallbackUrl: null,\n };\n pendingRef.current = next;\n setPending(next);\n // Success needs no action here — the activation webhook lands on the\n // platform and the status poll settles the flow. Failures settle it now.\n handle.result.catch((error: unknown) => {\n if (pendingRef.current?.connectionId !== created.connectionId) return;\n headlessRef.current = null;\n pendingRef.current = null;\n const message = error instanceof HeadlessAuthError ? error.message : 'Could not authorize this connection.';\n setSettled({ provider: provider.id, status: 'failed', message });\n setPending(null);\n });\n },\n [redeemLaunchToken, resolveLaunchHref],\n );\n\n const connect = useCallback(\n (provider: ConnectTarget, values?: Record<string, string>) => {\n setSettled(null);\n headlessRef.current?.close();\n headlessRef.current = null;\n\n // Headless needs both the capability and the inputs: a caller without a\n // form (no `values`) can only run flows whose fields are all optional —\n // anything else falls back to the hosted page, which renders the form.\n const headless =\n supportsHeadlessAuth(provider.authType, provider.authFields) &&\n (values !== undefined || !headlessAuthRequiresForm(provider));\n // Hosted flows open the popup synchronously in the click gesture so\n // popup blockers allow it; headless flows never navigate to a hosted\n // page, so no window opens here.\n const popup = headless ? null : window.open('', 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n session.mutate(\n { provider: provider.id },\n {\n onSuccess: created => {\n if (headless) {\n void beginHeadless(provider, created, values);\n return;\n }\n // The popup enters OAuth through the server's launch gate, which\n // verifies this browser owns the pending session before\n // redirecting — the raw vendor URL never reaches the page.\n const launchHref = resolveLaunchHref(created.launchUrl);\n if (popup) {\n popup.location.href = launchHref;\n }\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n },\n onError: () => {\n popup?.close();\n popupRef.current = null;\n },\n },\n );\n },\n [session, resolveLaunchHref, beginHeadless],\n );\n\n /** Abandons the in-flight flow: closes the provider window, hands the Connect action back. */\n const cancel = useCallback(() => {\n headlessRef.current?.close();\n headlessRef.current = null;\n popupRef.current = null;\n pendingRef.current = null;\n setPending(null);\n setSettled(null);\n }, []);\n\n return {\n pending,\n connect,\n cancel,\n /** Outcome of the most recently settled flow; null while none settled or a flow is in progress. */\n settled,\n /** Providers whose connection settled `active` during this hook's lifetime. */\n connectedProviders,\n isCreating: session.isPending,\n createError: session.isError ? session.error : null,\n };\n}\n\n/** Disconnects one of the caller's own connections. */\nexport function useDisconnectUserConnection() {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useMutation<void, UserConnectRequestError, { connectionId: string }>({\n mutationFn: ({ connectionId }) =>\n connectFetch<void>(`/connections/${encodeURIComponent(connectionId)}`, { method: 'DELETE' }),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: connectionsQueryKey }),\n });\n}\n"],"mappings":";;;;;;;AAwBA,IAAa,oBAAoB;AAEjC,IAAa,0BAAb,cAA6C,MAAM;CACjD;CACA;CAEA,YAAY,QAAgB,MAAqB,SAAiB;EAChE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,OAAO;CACd;AACF;;;;;;AASA,SAAS,kBAAgC;CAEvC,MAAM,EAAE,SAAS,SAAS,aAAa,OAAO,iBAAA,GAD/BA,cAAAA,gBAAAA,CAC+C,CAAA,CAAO;CAErE,QAAA,GAAOC,MAAAA,YAAAA,CACL,OAAO,MAAM,SAAS;EAEpB,MAAM,WAAW,OADD,eAAe,MAAA,CACA,GAAG,UAAU,oBAAoB,QAAQ;GACtE,GAAG;GACH,SAAS;IAAE,GAAG;IAAS,GAAG,MAAM;GAAQ;GACxC;EACF,CAAC;EACD,IAAI,CAAC,SAAS,IAAI;GAChB,IAAI,OAAsB;GAC1B,IAAI,UAAU,8BAA8B,SAAS;GACrD,IAAI;IACF,MAAM,OAAQ,MAAM,SAAS,KAAK;IAClC,IAAI,MAAM,OAAO;KACf,OAAO,KAAK,MAAM,QAAQ;KAC1B,UAAU,KAAK,MAAM,WAAW;IAClC;GACF,QAAQ,CAER;GACA,MAAM,IAAI,wBAAwB,SAAS,QAAQ,MAAM,OAAO;EAClE;EACA,IAAI,SAAS,WAAW,KAAK,OAAO,KAAA;EACpC,OAAQ,MAAM,SAAS,KAAK;CAC9B,GACA;EAAC;EAAS;EAAS;EAAa;CAAW,CAC7C;AACF;;;;;;;;AASA,SAAgB,uBAAsD;CAEpE,MAAM,EAAE,aAAA,GADOD,cAAAA,gBAAAA,CACK,CAAA,CAAO;CAC3B,QAAA,GAAOC,MAAAA,YAAAA,EAAa,cAAuB,UAAU,GAAG,UAAU,cAAc,WAAY,CAAC,OAAO,CAAC;AACvG;;;;;;;AAQA,SAAS,uBAAuF;CAE9F,MAAM,EAAE,SAAS,SAAS,aAAa,OAAO,iBAAA,GAD/BD,cAAAA,gBAAAA,CAC+C,CAAA,CAAO;CAErE,QAAA,GAAOC,MAAAA,YAAAA,CACL,OAAM,cAAa;EAIjB,MAAM,WAAW,OAHD,eAAe,MAAA,CAGA,GAAG,WAAW,KAAK,aAAa;GAC7D,SAAS;IAAE,GAAG;IAAS,QAAQ;GAAmB;GAClD;EACF,CAAC;EACD,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,wBAAwB,SAAS,QAAQ,MAAM,8BAA8B,SAAS,QAAQ;EAE1G,OAAQ,MAAM,SAAS,KAAK;CAC9B,GACA;EAAC;EAAS;EAAS;EAAa;CAAW,CAC7C;AACF;;;;;;AAYA,SAAgB,oBAAoB;CAClC,MAAM,eAAe,gBAAgB;CAErC,QAAA,GAAOC,sBAAAA,SAAAA,CAAkD;EACvD,UAAU,CAAC,gBAAgB,SAAS;EACpC,OAAO;EACP,SAAS,YAAY;GACnB,IAAI;IAEF,OAAO;KAAE,QAAQ;KAAS,YAAW,MADlB,aAA2C,YAAY,EAAA,CAChC;IAAU;GACtD,SAAS,OAAO;IACd,IAAI,iBAAiB,yBAAyB;KAC5C,IAAI,MAAM,WAAW,KAAK,OAAO,EAAE,QAAQ,cAAc;KACzD,IAAI,MAAM,WAAW,KAAK,OAAO,EAAE,QAAQ,kBAAkB;IAC/D;IACA,MAAM;GACR;EACF;CACF,CAAC;AACH;AAEA,IAAM,sBAAsB,CAAC,gBAAgB,aAAa;;AAG1D,SAAgB,mBAAmB,EAAE,WAAiC;CACpE,MAAM,eAAe,gBAAgB;CAErC,QAAA,GAAOA,sBAAAA,SAAAA,CAA0E;EAC/E,UAAU;EACV;EACA,OAAO;EACP,SAAS,YAAY;GAEnB,QAAO,MADY,aAAsC,cAAc,EAAA,CAC3D;EACd;CACF,CAAC;AACH;;AAGA,SAAgB,0BAA0B;CACxC,MAAM,eAAe,gBAAgB;CAErC,QAAA,GAAOC,sBAAAA,YAAAA,CAAuF,EAC5F,aAAa,EAAE,eACb,aAAyC,IAAI,mBAAmB,QAAQ,EAAE,YAAY,EAAE,QAAQ,OAAO,CAAC,EAC5G,CAAC;AACH;;AAGA,IAAM,0BAA0B;AAChC,IAAM,mBAAmB;;;;;;;AAQzB,SAAgB,oBAAoB,EAAE,gBAAiD;CACrF,MAAM,eAAe,gBAAgB;CACrC,MAAM,eAAA,GAAcC,sBAAAA,eAAAA,CAAe;CAEnC,QAAA,GAAOF,sBAAAA,SAAAA,CAAgE;EACrE,UAAU;GAAC;GAAgB;GAAqB;EAAY;EAC5D,SAAS,iBAAiB;EAC1B,OAAO;EACP,kBAAiB,UAAS;GACxB,MAAM,SAAS,MAAM,MAAM,MAAM;GACjC,IAAI,WAAW,KAAA,KAAa,WAAW,WAAW,OAAO;GACzD,IAAI,MAAM,MAAM,mBAAmB,kBAAkB,OAAO;GAC5D,OAAO;EACT;EACA,SAAS,YAAY;GACnB,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,aACb,gBAAgB,mBAAmB,gBAAgB,EAAE,EAAE,QACzD;GACF,SAAS,OAAO;IACd,IAAI,iBAAiB,2BAA2B,MAAM,WAAW,KAC/D,OAAO;KAAE,IAAI,gBAAgB;KAAI,QAAQ;KAAW,OAAO;IAAO;IAEpE,MAAM;GACR;GACA,IAAI,OAAO,WAAW,WACpB,YAAiB,kBAAkB,EAAE,UAAU,oBAAoB,CAAC;GAEtE,OAAO;EACT;CACF,CAAC;AACH;;;;;;AA4BA,IAAM,uBAAuB;;AAE7B,IAAM,qBAAqB,0BAA0B;;AAqBrD,IAAM,iBAAiB;;;;;;;;;;;;;AAcvB,SAAgB,kBAAkB,UAAoC,CAAC,GAAG;CACxE,MAAM,EAAE,oBAAoB,sBAAsB,mBAAmB,uBAAuB;CAC5F,MAAM,UAAU,wBAAwB;CACxC,MAAM,oBAAoB,qBAAqB;CAC/C,MAAM,oBAAoB,qBAAqB;CAC/C,MAAM,CAAC,SAAS,eAAA,GAAcG,MAAAA,SAAAA,CAAgC,IAAI;CAClE,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAgC,IAAI;CAClE,MAAM,CAAC,oBAAoB,0BAAA,GAAyBA,MAAAA,SAAAA,iBAA8B,IAAI,IAAI,CAAC;CAC3F,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAsC,IAAI;CAC3D,MAAM,eAAA,GAAcA,MAAAA,OAAAA,CAAkC,IAAI;CAI1D,MAAM,cAAA,GAAaA,MAAAA,OAAAA,CAA8B,IAAI;CACrD,MAAM,SAAS,oBAAoB,EAAE,cAAc,SAAS,gBAAgB,KAAK,CAAC;CAElF,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,WAAW,UAAU;CACvB,GAAG,CAAC,OAAO,CAAC;CAGZ,CAAA,GAAA,MAAA,UAAA,aACc;EACV,YAAY,SAAS,MAAM;EAC3B,YAAY,UAAU;CACxB,GACA,CAAC,CACH;CAIA,MAAM,aAAa,OAAO;CAC1B,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,WAAW,eAAe,KAAA,GAAW;EAC1C,IAAI,WAAW,OAAO,QAAQ,gBAAgB,WAAW,WAAW,WAAW;EAC/E,MAAM,EAAE,aAAa;EACrB,IAAI,WAAW,WAAW,UACxB,uBAAsB,aAAa,SAAS,IAAI,QAAQ,IAAI,2BAAW,IAAI,IAAI,CAAC,GAAG,UAAU,QAAQ,CAAC,CAAE;EAI1G,YAAY,UAAU;EACtB,WAAW,UAAU;EACrB,WAAW;GAAE;GAAU,QAAQ,WAAW,WAAW,WAAW,WAAW;EAAS,CAAC;EACrF,WAAW,IAAI;CACjB,GAAG,CAAC,SAAS,UAAU,CAAC;CAGxB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,OAAO,WAAW,CAAC,SAAS;EAEjC,WAAW,UAAU;EACrB,YAAY,SAAS,MAAM;EAC3B,YAAY,UAAU;EACtB,WAAW;GAAE,UAAU,QAAQ;GAAU,QAAQ;EAAS,CAAC;EAC3D,WAAW,IAAI;CACjB,GAAG,CAAC,OAAO,SAAS,OAAO,CAAC;CAI5B,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI,WAA0B;EAC9B,MAAM,SAAS,KAAK,IAAI,KAAO,iBAAiB;EAChD,MAAM,QAAQ,OAAO,kBAAkB;GACrC,IAAI,SAAS,SAAS,QAAQ,aAAa,KAAK,IAAI;GACpD,MAAM,YAAY,aAAa,QAAQ,KAAK,IAAI,IAAI,YAAY;GAChE,MAAM,WAAW,KAAK,IAAI,IAAI,aAAa;GAC3C,IAAI,aAAa,UAAU;IAEzB,WAAW,UAAU;IACrB,YAAY,SAAS,MAAM;IAC3B,YAAY,UAAU;IACtB,WAAW;KAAE,UAAU,QAAQ;KAAU,QAAQ;IAAS,CAAC;IAC3D,WAAW,IAAI;GACjB;EACF,GAAG,MAAM;EACT,aAAa,OAAO,cAAc,KAAK;CACzC,GAAG;EAAC;EAAS;EAAmB;CAAgB,CAAC;CAEjD,MAAM,iBAAA,GAAgBL,MAAAA,YAAAA,CACpB,OAAO,UAAyB,SAAqC,WAAoC;EACvG,IAAI,eAA8B;EAClC,IAAI;GACF,gBAAgB,MAAM,kBAAkB,QAAQ,SAAS,EAAA,CAAG;EAC9D,QAAQ,CAGR;EACA,IAAI,CAAC,cAAc;GAGjB,MAAM,aAAa,kBAAkB,QAAQ,SAAS;GACtD,MAAM,QAAQ,OAAO,KAAK,YAAY,kBAAkB,cAAc;GACtE,SAAS,UAAU;GACnB,MAAM,OAAuB;IAC3B,UAAU,SAAS;IACnB,cAAc,QAAQ;IACtB,MAAM;IACN,aAAa,QAAQ,OAAO;GAC9B;GACA,WAAW,UAAU;GACrB,WAAW,IAAI;GACf;EACF;EAEA,MAAM,QAAQ,SAASM,yCAAAA,wBAAwBC,yCAAAA,mBAAmB,QAAQ,GAAG,MAAM,IAAI,CAAC;EACxF,MAAM,SAASC,yCAAAA,kBAAkB;GAC/B;GACA,eAAe,QAAQ;GACvB,UAAU,SAAS;GACnB,aAAa,MAAM;GACnB,QAAQ,MAAM;EAChB,CAAC;EACD,YAAY,UAAU;EACtB,MAAM,OAAuB;GAC3B,UAAU,SAAS;GACnB,cAAc,QAAQ;GACtB,MAAM;GACN,aAAa;EACf;EACA,WAAW,UAAU;EACrB,WAAW,IAAI;EAGf,OAAO,OAAO,OAAO,UAAmB;GACtC,IAAI,WAAW,SAAS,iBAAiB,QAAQ,cAAc;GAC/D,YAAY,UAAU;GACtB,WAAW,UAAU;GACrB,MAAM,UAAU,iBAAiBC,yCAAAA,oBAAoB,MAAM,UAAU;GACrE,WAAW;IAAE,UAAU,SAAS;IAAI,QAAQ;IAAU;GAAQ,CAAC;GAC/D,WAAW,IAAI;EACjB,CAAC;CACH,GACA,CAAC,mBAAmB,iBAAiB,CACvC;CA+DA,OAAO;EACL;EACA,UAAA,GA/DcT,MAAAA,YAAAA,EACb,UAAyB,WAAoC;GAC5D,WAAW,IAAI;GACf,YAAY,SAAS,MAAM;GAC3B,YAAY,UAAU;GAKtB,MAAM,WACJU,yCAAAA,qBAAqB,SAAS,UAAU,SAAS,UAAU,MAC1D,WAAW,KAAA,KAAa,CAACC,yCAAAA,yBAAyB,QAAQ;GAI7D,MAAM,QAAQ,WAAW,OAAO,OAAO,KAAK,IAAI,kBAAkB,cAAc;GAChF,SAAS,UAAU;GACnB,QAAQ,OACN,EAAE,UAAU,SAAS,GAAG,GACxB;IACE,YAAW,YAAW;KACpB,IAAI,UAAU;MACZ,cAAmB,UAAU,SAAS,MAAM;MAC5C;KACF;KAIA,MAAM,aAAa,kBAAkB,QAAQ,SAAS;KACtD,IAAI,OACF,MAAM,SAAS,OAAO;KAExB,MAAM,OAAuB;MAC3B,UAAU,SAAS;MACnB,cAAc,QAAQ;MACtB,MAAM;MACN,aAAa,QAAQ,OAAO;KAC9B;KACA,WAAW,UAAU;KACrB,WAAW,IAAI;IACjB;IACA,eAAe;KACb,OAAO,MAAM;KACb,SAAS,UAAU;IACrB;GACF,CACF;EACF,GACA;GAAC;GAAS;GAAmB;EAAa,CAe1C;EACA,SAAA,GAZaX,MAAAA,YAAAA,OAAkB;GAC/B,YAAY,SAAS,MAAM;GAC3B,YAAY,UAAU;GACtB,SAAS,UAAU;GACnB,WAAW,UAAU;GACrB,WAAW,IAAI;GACf,WAAW,IAAI;EACjB,GAAG,CAAC,CAKF;;EAEA;;EAEA;EACA,YAAY,QAAQ;EACpB,aAAa,QAAQ,UAAU,QAAQ,QAAQ;CACjD;AACF;;AAGA,SAAgB,8BAA8B;CAC5C,MAAM,eAAe,gBAAgB;CACrC,MAAM,eAAA,GAAcG,sBAAAA,eAAAA,CAAe;CAEnC,QAAA,GAAOD,sBAAAA,YAAAA,CAAqE;EAC1E,aAAa,EAAE,mBACb,aAAmB,gBAAgB,mBAAmB,YAAY,KAAK,EAAE,QAAQ,SAAS,CAAC;EAC7F,iBAAiB,YAAY,kBAAkB,EAAE,UAAU,oBAAoB,CAAC;CAClF,CAAC;AACH"}
|
|
1
|
+
{"version":3,"file":"use-user-connect.cjs.js","names":["useMastraClient","useCallback","useQuery","useMutation","useQueryClient","useState","useRef","splitHeadlessAuthValues","headlessAuthFields","startHeadlessAuth","HeadlessAuthError","supportsHeadlessAuth","headlessAuthRequiresForm"],"sources":["../../../src/domains/connect/use-user-connect.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport type { QueryClient } from '@tanstack/react-query';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport {\n HeadlessAuthError,\n headlessAuthFields,\n headlessAuthRequiresForm,\n splitHeadlessAuthValues,\n startHeadlessAuth,\n supportsHeadlessAuth,\n} from './headless-connect';\nimport type { HeadlessAuthHandle } from './headless-connect';\nimport type {\n UserConnectErrorBody,\n UserConnectLaunchTokenResponse,\n UserConnectProvider,\n UserConnectProvidersResponse,\n UserConnectSessionResponse,\n UserConnectionStatusResponse,\n UserConnectionsResponse,\n} from './types';\n\n/** Default mount prefix of `userConnectRoutes()` on the dev server. */\nexport const CONNECT_BASE_PATH = '/connect';\n\nexport class UserConnectRequestError extends Error {\n status: number;\n code: string | null;\n\n constructor(status: number, code: string | null, message: string) {\n super(message);\n this.name = 'UserConnectRequestError';\n this.status = status;\n this.code = code;\n }\n}\n\ntype ConnectFetch = <T>(path: string, init?: RequestInit) => Promise<T>;\n\n/**\n * Fetches against the dev server's mounted connect routes. Custom `apiRoutes`\n * live outside the `/api` prefix, so this goes around the SDK while reusing\n * its base URL, auth headers, credentials mode, and refresh-aware fetch.\n */\nfunction useConnectFetch(): ConnectFetch {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback<ConnectFetch>(\n async (path, init) => {\n const fetchFn = customFetch ?? fetch;\n const response = await fetchFn(`${baseUrl}${CONNECT_BASE_PATH}${path}`, {\n ...init,\n headers: { ...headers, ...init?.headers },\n credentials,\n });\n if (!response.ok) {\n let code: string | null = null;\n let message = `Request failed with status ${response.status}`;\n try {\n const body = (await response.json()) as Partial<UserConnectErrorBody>;\n if (body?.error) {\n code = body.error.code ?? null;\n message = body.error.message ?? message;\n }\n } catch {\n // Non-JSON error body (e.g. a plain 404 for unmounted routes).\n }\n throw new UserConnectRequestError(response.status, code, message);\n }\n if (response.status === 204) return undefined as never;\n return (await response.json()) as never;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\n/**\n * Resolves a server-relative launch-gate path (returned by the session route\n * as `launchUrl`) against the SDK's base URL for top-level popup navigation.\n * The launch route is authenticated by the browser's session cookie — the\n * server re-verifies that this browser owns the pending session before\n * redirecting into the vendor OAuth flow.\n */\nexport function useConnectLaunchHref(): (launchUrl: string) => string {\n const client = useMastraClient();\n const { baseUrl } = client.options;\n return useCallback((launchUrl: string) => (baseUrl ? `${baseUrl}${launchUrl}` : launchUrl), [baseUrl]);\n}\n\n/**\n * Redeems the launch gate for a headless session token (`Accept:\n * application/json`) instead of following its hosted 302. The gate runs the\n * same ownership assertion in both modes; a `null` token means the server\n * could not extract one and the caller falls back to the hosted popup.\n */\nfunction useRedeemLaunchToken(): (launchUrl: string) => Promise<UserConnectLaunchTokenResponse> {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback(\n async launchUrl => {\n const fetchFn = customFetch ?? fetch;\n // `launchUrl` is the full server-relative gate path (it already carries\n // the connect mount prefix), so it resolves against the bare base URL.\n const response = await fetchFn(`${baseUrl ?? ''}${launchUrl}`, {\n headers: { ...headers, accept: 'application/json' },\n credentials,\n });\n if (!response.ok) {\n throw new UserConnectRequestError(response.status, null, `Request failed with status ${response.status}`);\n }\n return (await response.json()) as UserConnectLaunchTokenResponse;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\nexport type ConnectSurface =\n | { status: 'ready'; providers: UserConnectProvidersResponse['providers'] }\n | { status: 'not-mounted' }\n | { status: 'unauthenticated' };\n\n/**\n * Capability detection for the end-user connect surface: probes\n * `GET /connect/providers` and distinguishes a working surface from the two\n * setup gaps (routes not mounted → 404, no end-user identity → 401).\n */\nexport function useConnectSurface() {\n const connectFetch = useConnectFetch();\n\n return useQuery<ConnectSurface, UserConnectRequestError>({\n queryKey: ['user-connect', 'surface'],\n retry: false,\n queryFn: async () => {\n try {\n const body = await connectFetch<UserConnectProvidersResponse>('/providers');\n return { status: 'ready', providers: body.providers };\n } catch (error) {\n if (error instanceof UserConnectRequestError) {\n if (error.status === 404) return { status: 'not-mounted' };\n if (error.status === 401) return { status: 'unauthenticated' };\n }\n throw error;\n }\n },\n });\n}\n\nconst connectionsQueryKey = ['user-connect', 'connections'] as const;\n\n/**\n * A connection that activates or goes away changes which tools resolve for\n * this user, so the connection list and every agent / tool listing are\n * refetched. The server drops its cached tool snapshot when it reports the\n * change, so the refetch already sees the new tools.\n */\nfunction invalidateAfterConnectionChange(queryClient: QueryClient) {\n return Promise.all(\n [connectionsQueryKey, ['agent'], ['agents'], ['tools']].map(async queryKey => {\n // A first fetch still in flight would otherwise be reused by the\n // invalidation, and its pre-change answer would land as fresh data.\n await queryClient.cancelQueries({ queryKey });\n await queryClient.invalidateQueries({ queryKey });\n }),\n );\n}\n\n/** Lists the caller's visible connections (global + their own). */\nexport function useUserConnections({ enabled }: { enabled: boolean }) {\n const connectFetch = useConnectFetch();\n\n return useQuery<UserConnectionsResponse['connections'], UserConnectRequestError>({\n queryKey: connectionsQueryKey,\n enabled,\n retry: false,\n queryFn: async () => {\n const body = await connectFetch<UserConnectionsResponse>('/connections');\n return body.connections;\n },\n });\n}\n\n/** Creates a connect session for a provider; the caller drives the popup. */\nexport function useCreateConnectSession() {\n const connectFetch = useConnectFetch();\n\n return useMutation<UserConnectSessionResponse, UserConnectRequestError, { provider: string }>({\n mutationFn: ({ provider }) =>\n connectFetch<UserConnectSessionResponse>(`/${encodeURIComponent(provider)}/sessions`, { method: 'POST' }),\n });\n}\n\n/** 2s interval with a 5 minute cap, mirroring the hosted connect page. */\nconst STATUS_POLL_INTERVAL_MS = 2_000;\nconst STATUS_MAX_POLLS = 150;\n\n/**\n * Polls a pending connection until it leaves `pending`. A 404 counts as still\n * pending — the platform row may not be visible until the provider handshake\n * lands. Polling stops once the status settles (or after the 5 minute cap);\n * the connections list is refreshed when it does.\n */\nexport function useConnectionStatus({ connectionId }: { connectionId: string | null }) {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useQuery<UserConnectionStatusResponse, UserConnectRequestError>({\n queryKey: ['user-connect', 'connection-status', connectionId],\n enabled: connectionId !== null,\n retry: false,\n refetchInterval: query => {\n const status = query.state.data?.status;\n if (status !== undefined && status !== 'pending') return false;\n if (query.state.dataUpdateCount >= STATUS_MAX_POLLS) return false;\n return STATUS_POLL_INTERVAL_MS;\n },\n queryFn: async () => {\n let status: UserConnectionStatusResponse;\n try {\n status = await connectFetch<UserConnectionStatusResponse>(\n `/connections/${encodeURIComponent(connectionId ?? '')}/status`,\n );\n } catch (error) {\n if (error instanceof UserConnectRequestError && error.status === 404) {\n return { id: connectionId ?? '', status: 'pending', scope: 'user' };\n }\n throw error;\n }\n if (status.status !== 'pending') {\n void invalidateAfterConnectionChange(queryClient);\n }\n return status;\n },\n });\n}\n\nexport interface PendingConnect {\n provider: string;\n connectionId: string;\n /**\n * `headless` — the Nango SDK drives the provider's own consent popup (or no\n * popup at all for collected credentials). `hosted` — a popup navigated\n * through the launch gate's 302 into the hosted connect page.\n */\n mode: 'headless' | 'hosted';\n /** Shown when the popup was blocked so the user can finish the flow manually. */\n fallbackUrl: string | null;\n}\n\n/**\n * What a caller passes to `connect()`: the provider's id plus the auth shape\n * when known. Callers that only know the id (older payloads) always get the\n * hosted flow.\n */\nexport type ConnectTarget = Pick<UserConnectProvider, 'id'> &\n Partial<Pick<UserConnectProvider, 'authType' | 'authFields'>>;\n\n/**\n * Grace period after the vendor popup closes before an unsettled flow is\n * abandoned — the activation webhook often lands a few seconds after the\n * vendor window closes itself.\n */\nconst POPUP_CLOSE_GRACE_MS = 15_000;\n/** Wall-clock cap matching the status poll's 5 minute budget. */\nconst PENDING_TIMEOUT_MS = STATUS_POLL_INTERVAL_MS * STATUS_MAX_POLLS;\n\nexport interface UsePendingConnectOptions {\n /** Overrides for the abandonment timings (primarily for tests). */\n popupCloseGraceMs?: number;\n pendingTimeoutMs?: number;\n}\n\n/**\n * Outcome of the most recently settled flow: `active` when the connection\n * activated, `failed` for everything else (non-active settle, poll failure,\n * abandoned popup, poll budget). Cleared when a new flow starts.\n */\nexport interface SettledConnect {\n provider: string;\n status: 'active' | 'failed';\n /** Human-readable failure detail (blocked popup, closed window, rejected credentials). */\n message?: string;\n}\n\n/** Window features for the hosted connect popup. */\nconst POPUP_FEATURES = 'popup,width=600,height=720';\n\n/**\n * Drives one add-connection flow end to end. Providers whose auth the browser\n * can complete headlessly go through the launch gate's JSON redemption: the\n * released session token keys the Nango SDK, which opens the provider's own\n * consent popup (or submits collected credentials with no popup). Everything\n * else gets the hosted flow — a popup opened synchronously in the click\n * gesture (so popup blockers allow it) and navigated through the launch\n * gate's 302. Either way the connection status is polled until it settles.\n * The pending state always resolves — on settle, on a poll or auth failure,\n * when the popup closes without settling (after a grace period), or at the\n * poll budget — so the Connect action is never stuck disabled.\n */\nexport function usePendingConnect(options: UsePendingConnectOptions = {}) {\n const { popupCloseGraceMs = POPUP_CLOSE_GRACE_MS, pendingTimeoutMs = PENDING_TIMEOUT_MS } = options;\n const session = useCreateConnectSession();\n const resolveLaunchHref = useConnectLaunchHref();\n const redeemLaunchToken = useRedeemLaunchToken();\n const [pending, setPending] = useState<PendingConnect | null>(null);\n const [settled, setSettled] = useState<SettledConnect | null>(null);\n const [connectedProviders, setConnectedProviders] = useState<ReadonlySet<string>>(new Set());\n const popupRef = useRef<Pick<Window, 'closed'> | null>(null);\n const headlessRef = useRef<HeadlessAuthHandle | null>(null);\n // Mirrors `pending` for async guards (the SDK promise settles outside the\n // render cycle); written directly at every transition so a cancel is never\n // raced by a trailing rejection.\n const pendingRef = useRef<PendingConnect | null>(null);\n const status = useConnectionStatus({ connectionId: pending?.connectionId ?? null });\n\n useEffect(() => {\n pendingRef.current = pending;\n }, [pending]);\n\n // Close the provider popup if the surface unmounts mid-flow.\n useEffect(\n () => () => {\n headlessRef.current?.close();\n headlessRef.current = null;\n },\n [],\n );\n\n // Settle only on a status response for the connection currently pending —\n // a stale result from a previous flow must not clear or mark a newer one.\n const statusData = status.data;\n useEffect(() => {\n if (!pending || statusData === undefined) return;\n if (statusData.id !== pending.connectionId || statusData.status === 'pending') return;\n const { provider } = pending;\n if (statusData.status === 'active') {\n setConnectedProviders(previous => (previous.has(provider) ? previous : new Set([...previous, provider])));\n }\n // The provider window closes itself on active settles; drop the handle so\n // a trailing SDK rejection cannot re-settle this flow.\n headlessRef.current = null;\n pendingRef.current = null;\n setSettled({ provider, status: statusData.status === 'active' ? 'active' : 'failed' });\n setPending(null);\n }, [pending, statusData]);\n\n // A failed poll hands the Connect action back instead of leaving it stuck.\n useEffect(() => {\n if (!status.isError || !pending) return;\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }, [status.isError, pending]);\n\n // Abandonment: the popup closed without the flow settling (grace period for\n // the trailing webhook) or the poll budget ran out.\n useEffect(() => {\n if (!pending) return;\n const startedAt = Date.now();\n let closedAt: number | null = null;\n const tickMs = Math.min(1_000, popupCloseGraceMs);\n const timer = window.setInterval(() => {\n if (popupRef.current?.closed) closedAt ??= Date.now();\n const abandoned = closedAt !== null && Date.now() - closedAt >= popupCloseGraceMs;\n const timedOut = Date.now() - startedAt >= pendingTimeoutMs;\n if (abandoned || timedOut) {\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }\n }, tickMs);\n return () => window.clearInterval(timer);\n }, [pending, popupCloseGraceMs, pendingTimeoutMs]);\n\n const beginHeadless = useCallback(\n async (provider: ConnectTarget, created: UserConnectSessionResponse, values?: Record<string, string>) => {\n let sessionToken: string | null = null;\n try {\n sessionToken = (await redeemLaunchToken(created.launchUrl)).sessionToken;\n } catch {\n // Redemption failure (older platform, transient error) is not fatal —\n // the hosted flow below still works through the gate's 302.\n }\n if (!sessionToken) {\n // Opened after an await, so a blocker may stop it; the fallback link\n // in the pending state covers that.\n const launchHref = resolveLaunchHref(created.launchUrl);\n const popup = window.open(launchHref, 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n return;\n }\n\n const split = values ? splitHeadlessAuthValues(headlessAuthFields(provider), values) : {};\n const handle = startHeadlessAuth({\n sessionToken,\n integrationId: created.integrationId,\n authType: provider.authType,\n credentials: split.credentials,\n params: split.params,\n });\n headlessRef.current = handle;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'headless',\n fallbackUrl: null,\n };\n pendingRef.current = next;\n setPending(next);\n // Success needs no action here — the activation webhook lands on the\n // platform and the status poll settles the flow. Failures settle it now.\n handle.result.catch((error: unknown) => {\n if (pendingRef.current?.connectionId !== created.connectionId) return;\n headlessRef.current = null;\n pendingRef.current = null;\n const message = error instanceof HeadlessAuthError ? error.message : 'Could not authorize this connection.';\n setSettled({ provider: provider.id, status: 'failed', message });\n setPending(null);\n });\n },\n [redeemLaunchToken, resolveLaunchHref],\n );\n\n const connect = useCallback(\n (provider: ConnectTarget, values?: Record<string, string>) => {\n setSettled(null);\n headlessRef.current?.close();\n headlessRef.current = null;\n\n // Headless needs both the capability and the inputs: a caller without a\n // form (no `values`) can only run flows whose fields are all optional —\n // anything else falls back to the hosted page, which renders the form.\n const headless =\n supportsHeadlessAuth(provider.authType, provider.authFields) &&\n (values !== undefined || !headlessAuthRequiresForm(provider));\n // Hosted flows open the popup synchronously in the click gesture so\n // popup blockers allow it; headless flows never navigate to a hosted\n // page, so no window opens here.\n const popup = headless ? null : window.open('', 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n session.mutate(\n { provider: provider.id },\n {\n onSuccess: created => {\n if (headless) {\n void beginHeadless(provider, created, values);\n return;\n }\n // The popup enters OAuth through the server's launch gate, which\n // verifies this browser owns the pending session before\n // redirecting — the raw vendor URL never reaches the page.\n const launchHref = resolveLaunchHref(created.launchUrl);\n if (popup) {\n popup.location.href = launchHref;\n }\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n },\n onError: () => {\n popup?.close();\n popupRef.current = null;\n },\n },\n );\n },\n [session, resolveLaunchHref, beginHeadless],\n );\n\n /** Abandons the in-flight flow: closes the provider window, hands the Connect action back. */\n const cancel = useCallback(() => {\n headlessRef.current?.close();\n headlessRef.current = null;\n popupRef.current = null;\n pendingRef.current = null;\n setPending(null);\n setSettled(null);\n }, []);\n\n return {\n pending,\n connect,\n cancel,\n /** Outcome of the most recently settled flow; null while none settled or a flow is in progress. */\n settled,\n /** Providers whose connection settled `active` during this hook's lifetime. */\n connectedProviders,\n isCreating: session.isPending,\n createError: session.isError ? session.error : null,\n };\n}\n\n/** Disconnects one of the caller's own connections. */\nexport function useDisconnectUserConnection() {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useMutation<void, UserConnectRequestError, { connectionId: string }>({\n mutationFn: ({ connectionId }) =>\n connectFetch<void>(`/connections/${encodeURIComponent(connectionId)}`, { method: 'DELETE' }),\n onSuccess: () => invalidateAfterConnectionChange(queryClient),\n });\n}\n"],"mappings":"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"}
|
|
@@ -115,6 +115,23 @@ function useConnectSurface() {
|
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
117
|
var connectionsQueryKey = ["user-connect", "connections"];
|
|
118
|
+
/**
|
|
119
|
+
* A connection that activates or goes away changes which tools resolve for
|
|
120
|
+
* this user, so the connection list and every agent / tool listing are
|
|
121
|
+
* refetched. The server drops its cached tool snapshot when it reports the
|
|
122
|
+
* change, so the refetch already sees the new tools.
|
|
123
|
+
*/
|
|
124
|
+
function invalidateAfterConnectionChange(queryClient) {
|
|
125
|
+
return Promise.all([
|
|
126
|
+
connectionsQueryKey,
|
|
127
|
+
["agent"],
|
|
128
|
+
["agents"],
|
|
129
|
+
["tools"]
|
|
130
|
+
].map(async (queryKey) => {
|
|
131
|
+
await queryClient.cancelQueries({ queryKey });
|
|
132
|
+
await queryClient.invalidateQueries({ queryKey });
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
118
135
|
/** Lists the caller's visible connections (global + their own). */
|
|
119
136
|
function useUserConnections({ enabled }) {
|
|
120
137
|
const connectFetch = useConnectFetch();
|
|
@@ -170,7 +187,7 @@ function useConnectionStatus({ connectionId }) {
|
|
|
170
187
|
};
|
|
171
188
|
throw error;
|
|
172
189
|
}
|
|
173
|
-
if (status.status !== "pending") queryClient
|
|
190
|
+
if (status.status !== "pending") invalidateAfterConnectionChange(queryClient);
|
|
174
191
|
return status;
|
|
175
192
|
}
|
|
176
193
|
});
|
|
@@ -374,7 +391,7 @@ function useDisconnectUserConnection() {
|
|
|
374
391
|
const queryClient = useQueryClient();
|
|
375
392
|
return useMutation({
|
|
376
393
|
mutationFn: ({ connectionId }) => connectFetch(`/connections/${encodeURIComponent(connectionId)}`, { method: "DELETE" }),
|
|
377
|
-
onSuccess: () => queryClient
|
|
394
|
+
onSuccess: () => invalidateAfterConnectionChange(queryClient)
|
|
378
395
|
});
|
|
379
396
|
}
|
|
380
397
|
export { CONNECT_BASE_PATH, UserConnectRequestError, useConnectLaunchHref, useConnectSurface, useConnectionStatus, useCreateConnectSession, useDisconnectUserConnection, usePendingConnect, useUserConnections };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-user-connect.es.js","names":[],"sources":["../../../src/domains/connect/use-user-connect.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport {\n HeadlessAuthError,\n headlessAuthFields,\n headlessAuthRequiresForm,\n splitHeadlessAuthValues,\n startHeadlessAuth,\n supportsHeadlessAuth,\n} from './headless-connect';\nimport type { HeadlessAuthHandle } from './headless-connect';\nimport type {\n UserConnectErrorBody,\n UserConnectLaunchTokenResponse,\n UserConnectProvider,\n UserConnectProvidersResponse,\n UserConnectSessionResponse,\n UserConnectionStatusResponse,\n UserConnectionsResponse,\n} from './types';\n\n/** Default mount prefix of `userConnectRoutes()` on the dev server. */\nexport const CONNECT_BASE_PATH = '/connect';\n\nexport class UserConnectRequestError extends Error {\n status: number;\n code: string | null;\n\n constructor(status: number, code: string | null, message: string) {\n super(message);\n this.name = 'UserConnectRequestError';\n this.status = status;\n this.code = code;\n }\n}\n\ntype ConnectFetch = <T>(path: string, init?: RequestInit) => Promise<T>;\n\n/**\n * Fetches against the dev server's mounted connect routes. Custom `apiRoutes`\n * live outside the `/api` prefix, so this goes around the SDK while reusing\n * its base URL, auth headers, credentials mode, and refresh-aware fetch.\n */\nfunction useConnectFetch(): ConnectFetch {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback<ConnectFetch>(\n async (path, init) => {\n const fetchFn = customFetch ?? fetch;\n const response = await fetchFn(`${baseUrl}${CONNECT_BASE_PATH}${path}`, {\n ...init,\n headers: { ...headers, ...init?.headers },\n credentials,\n });\n if (!response.ok) {\n let code: string | null = null;\n let message = `Request failed with status ${response.status}`;\n try {\n const body = (await response.json()) as Partial<UserConnectErrorBody>;\n if (body?.error) {\n code = body.error.code ?? null;\n message = body.error.message ?? message;\n }\n } catch {\n // Non-JSON error body (e.g. a plain 404 for unmounted routes).\n }\n throw new UserConnectRequestError(response.status, code, message);\n }\n if (response.status === 204) return undefined as never;\n return (await response.json()) as never;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\n/**\n * Resolves a server-relative launch-gate path (returned by the session route\n * as `launchUrl`) against the SDK's base URL for top-level popup navigation.\n * The launch route is authenticated by the browser's session cookie — the\n * server re-verifies that this browser owns the pending session before\n * redirecting into the vendor OAuth flow.\n */\nexport function useConnectLaunchHref(): (launchUrl: string) => string {\n const client = useMastraClient();\n const { baseUrl } = client.options;\n return useCallback((launchUrl: string) => (baseUrl ? `${baseUrl}${launchUrl}` : launchUrl), [baseUrl]);\n}\n\n/**\n * Redeems the launch gate for a headless session token (`Accept:\n * application/json`) instead of following its hosted 302. The gate runs the\n * same ownership assertion in both modes; a `null` token means the server\n * could not extract one and the caller falls back to the hosted popup.\n */\nfunction useRedeemLaunchToken(): (launchUrl: string) => Promise<UserConnectLaunchTokenResponse> {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback(\n async launchUrl => {\n const fetchFn = customFetch ?? fetch;\n // `launchUrl` is the full server-relative gate path (it already carries\n // the connect mount prefix), so it resolves against the bare base URL.\n const response = await fetchFn(`${baseUrl ?? ''}${launchUrl}`, {\n headers: { ...headers, accept: 'application/json' },\n credentials,\n });\n if (!response.ok) {\n throw new UserConnectRequestError(response.status, null, `Request failed with status ${response.status}`);\n }\n return (await response.json()) as UserConnectLaunchTokenResponse;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\nexport type ConnectSurface =\n | { status: 'ready'; providers: UserConnectProvidersResponse['providers'] }\n | { status: 'not-mounted' }\n | { status: 'unauthenticated' };\n\n/**\n * Capability detection for the end-user connect surface: probes\n * `GET /connect/providers` and distinguishes a working surface from the two\n * setup gaps (routes not mounted → 404, no end-user identity → 401).\n */\nexport function useConnectSurface() {\n const connectFetch = useConnectFetch();\n\n return useQuery<ConnectSurface, UserConnectRequestError>({\n queryKey: ['user-connect', 'surface'],\n retry: false,\n queryFn: async () => {\n try {\n const body = await connectFetch<UserConnectProvidersResponse>('/providers');\n return { status: 'ready', providers: body.providers };\n } catch (error) {\n if (error instanceof UserConnectRequestError) {\n if (error.status === 404) return { status: 'not-mounted' };\n if (error.status === 401) return { status: 'unauthenticated' };\n }\n throw error;\n }\n },\n });\n}\n\nconst connectionsQueryKey = ['user-connect', 'connections'] as const;\n\n/** Lists the caller's visible connections (global + their own). */\nexport function useUserConnections({ enabled }: { enabled: boolean }) {\n const connectFetch = useConnectFetch();\n\n return useQuery<UserConnectionsResponse['connections'], UserConnectRequestError>({\n queryKey: connectionsQueryKey,\n enabled,\n retry: false,\n queryFn: async () => {\n const body = await connectFetch<UserConnectionsResponse>('/connections');\n return body.connections;\n },\n });\n}\n\n/** Creates a connect session for a provider; the caller drives the popup. */\nexport function useCreateConnectSession() {\n const connectFetch = useConnectFetch();\n\n return useMutation<UserConnectSessionResponse, UserConnectRequestError, { provider: string }>({\n mutationFn: ({ provider }) =>\n connectFetch<UserConnectSessionResponse>(`/${encodeURIComponent(provider)}/sessions`, { method: 'POST' }),\n });\n}\n\n/** 2s interval with a 5 minute cap, mirroring the hosted connect page. */\nconst STATUS_POLL_INTERVAL_MS = 2_000;\nconst STATUS_MAX_POLLS = 150;\n\n/**\n * Polls a pending connection until it leaves `pending`. A 404 counts as still\n * pending — the platform row may not be visible until the provider handshake\n * lands. Polling stops once the status settles (or after the 5 minute cap);\n * the connections list is refreshed when it does.\n */\nexport function useConnectionStatus({ connectionId }: { connectionId: string | null }) {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useQuery<UserConnectionStatusResponse, UserConnectRequestError>({\n queryKey: ['user-connect', 'connection-status', connectionId],\n enabled: connectionId !== null,\n retry: false,\n refetchInterval: query => {\n const status = query.state.data?.status;\n if (status !== undefined && status !== 'pending') return false;\n if (query.state.dataUpdateCount >= STATUS_MAX_POLLS) return false;\n return STATUS_POLL_INTERVAL_MS;\n },\n queryFn: async () => {\n let status: UserConnectionStatusResponse;\n try {\n status = await connectFetch<UserConnectionStatusResponse>(\n `/connections/${encodeURIComponent(connectionId ?? '')}/status`,\n );\n } catch (error) {\n if (error instanceof UserConnectRequestError && error.status === 404) {\n return { id: connectionId ?? '', status: 'pending', scope: 'user' };\n }\n throw error;\n }\n if (status.status !== 'pending') {\n void queryClient.invalidateQueries({ queryKey: connectionsQueryKey });\n }\n return status;\n },\n });\n}\n\nexport interface PendingConnect {\n provider: string;\n connectionId: string;\n /**\n * `headless` — the Nango SDK drives the provider's own consent popup (or no\n * popup at all for collected credentials). `hosted` — a popup navigated\n * through the launch gate's 302 into the hosted connect page.\n */\n mode: 'headless' | 'hosted';\n /** Shown when the popup was blocked so the user can finish the flow manually. */\n fallbackUrl: string | null;\n}\n\n/**\n * What a caller passes to `connect()`: the provider's id plus the auth shape\n * when known. Callers that only know the id (older payloads) always get the\n * hosted flow.\n */\nexport type ConnectTarget = Pick<UserConnectProvider, 'id'> &\n Partial<Pick<UserConnectProvider, 'authType' | 'authFields'>>;\n\n/**\n * Grace period after the vendor popup closes before an unsettled flow is\n * abandoned — the activation webhook often lands a few seconds after the\n * vendor window closes itself.\n */\nconst POPUP_CLOSE_GRACE_MS = 15_000;\n/** Wall-clock cap matching the status poll's 5 minute budget. */\nconst PENDING_TIMEOUT_MS = STATUS_POLL_INTERVAL_MS * STATUS_MAX_POLLS;\n\nexport interface UsePendingConnectOptions {\n /** Overrides for the abandonment timings (primarily for tests). */\n popupCloseGraceMs?: number;\n pendingTimeoutMs?: number;\n}\n\n/**\n * Outcome of the most recently settled flow: `active` when the connection\n * activated, `failed` for everything else (non-active settle, poll failure,\n * abandoned popup, poll budget). Cleared when a new flow starts.\n */\nexport interface SettledConnect {\n provider: string;\n status: 'active' | 'failed';\n /** Human-readable failure detail (blocked popup, closed window, rejected credentials). */\n message?: string;\n}\n\n/** Window features for the hosted connect popup. */\nconst POPUP_FEATURES = 'popup,width=600,height=720';\n\n/**\n * Drives one add-connection flow end to end. Providers whose auth the browser\n * can complete headlessly go through the launch gate's JSON redemption: the\n * released session token keys the Nango SDK, which opens the provider's own\n * consent popup (or submits collected credentials with no popup). Everything\n * else gets the hosted flow — a popup opened synchronously in the click\n * gesture (so popup blockers allow it) and navigated through the launch\n * gate's 302. Either way the connection status is polled until it settles.\n * The pending state always resolves — on settle, on a poll or auth failure,\n * when the popup closes without settling (after a grace period), or at the\n * poll budget — so the Connect action is never stuck disabled.\n */\nexport function usePendingConnect(options: UsePendingConnectOptions = {}) {\n const { popupCloseGraceMs = POPUP_CLOSE_GRACE_MS, pendingTimeoutMs = PENDING_TIMEOUT_MS } = options;\n const session = useCreateConnectSession();\n const resolveLaunchHref = useConnectLaunchHref();\n const redeemLaunchToken = useRedeemLaunchToken();\n const [pending, setPending] = useState<PendingConnect | null>(null);\n const [settled, setSettled] = useState<SettledConnect | null>(null);\n const [connectedProviders, setConnectedProviders] = useState<ReadonlySet<string>>(new Set());\n const popupRef = useRef<Pick<Window, 'closed'> | null>(null);\n const headlessRef = useRef<HeadlessAuthHandle | null>(null);\n // Mirrors `pending` for async guards (the SDK promise settles outside the\n // render cycle); written directly at every transition so a cancel is never\n // raced by a trailing rejection.\n const pendingRef = useRef<PendingConnect | null>(null);\n const status = useConnectionStatus({ connectionId: pending?.connectionId ?? null });\n\n useEffect(() => {\n pendingRef.current = pending;\n }, [pending]);\n\n // Close the provider popup if the surface unmounts mid-flow.\n useEffect(\n () => () => {\n headlessRef.current?.close();\n headlessRef.current = null;\n },\n [],\n );\n\n // Settle only on a status response for the connection currently pending —\n // a stale result from a previous flow must not clear or mark a newer one.\n const statusData = status.data;\n useEffect(() => {\n if (!pending || statusData === undefined) return;\n if (statusData.id !== pending.connectionId || statusData.status === 'pending') return;\n const { provider } = pending;\n if (statusData.status === 'active') {\n setConnectedProviders(previous => (previous.has(provider) ? previous : new Set([...previous, provider])));\n }\n // The provider window closes itself on active settles; drop the handle so\n // a trailing SDK rejection cannot re-settle this flow.\n headlessRef.current = null;\n pendingRef.current = null;\n setSettled({ provider, status: statusData.status === 'active' ? 'active' : 'failed' });\n setPending(null);\n }, [pending, statusData]);\n\n // A failed poll hands the Connect action back instead of leaving it stuck.\n useEffect(() => {\n if (!status.isError || !pending) return;\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }, [status.isError, pending]);\n\n // Abandonment: the popup closed without the flow settling (grace period for\n // the trailing webhook) or the poll budget ran out.\n useEffect(() => {\n if (!pending) return;\n const startedAt = Date.now();\n let closedAt: number | null = null;\n const tickMs = Math.min(1_000, popupCloseGraceMs);\n const timer = window.setInterval(() => {\n if (popupRef.current?.closed) closedAt ??= Date.now();\n const abandoned = closedAt !== null && Date.now() - closedAt >= popupCloseGraceMs;\n const timedOut = Date.now() - startedAt >= pendingTimeoutMs;\n if (abandoned || timedOut) {\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }\n }, tickMs);\n return () => window.clearInterval(timer);\n }, [pending, popupCloseGraceMs, pendingTimeoutMs]);\n\n const beginHeadless = useCallback(\n async (provider: ConnectTarget, created: UserConnectSessionResponse, values?: Record<string, string>) => {\n let sessionToken: string | null = null;\n try {\n sessionToken = (await redeemLaunchToken(created.launchUrl)).sessionToken;\n } catch {\n // Redemption failure (older platform, transient error) is not fatal —\n // the hosted flow below still works through the gate's 302.\n }\n if (!sessionToken) {\n // Opened after an await, so a blocker may stop it; the fallback link\n // in the pending state covers that.\n const launchHref = resolveLaunchHref(created.launchUrl);\n const popup = window.open(launchHref, 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n return;\n }\n\n const split = values ? splitHeadlessAuthValues(headlessAuthFields(provider), values) : {};\n const handle = startHeadlessAuth({\n sessionToken,\n integrationId: created.integrationId,\n authType: provider.authType,\n credentials: split.credentials,\n params: split.params,\n });\n headlessRef.current = handle;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'headless',\n fallbackUrl: null,\n };\n pendingRef.current = next;\n setPending(next);\n // Success needs no action here — the activation webhook lands on the\n // platform and the status poll settles the flow. Failures settle it now.\n handle.result.catch((error: unknown) => {\n if (pendingRef.current?.connectionId !== created.connectionId) return;\n headlessRef.current = null;\n pendingRef.current = null;\n const message = error instanceof HeadlessAuthError ? error.message : 'Could not authorize this connection.';\n setSettled({ provider: provider.id, status: 'failed', message });\n setPending(null);\n });\n },\n [redeemLaunchToken, resolveLaunchHref],\n );\n\n const connect = useCallback(\n (provider: ConnectTarget, values?: Record<string, string>) => {\n setSettled(null);\n headlessRef.current?.close();\n headlessRef.current = null;\n\n // Headless needs both the capability and the inputs: a caller without a\n // form (no `values`) can only run flows whose fields are all optional —\n // anything else falls back to the hosted page, which renders the form.\n const headless =\n supportsHeadlessAuth(provider.authType, provider.authFields) &&\n (values !== undefined || !headlessAuthRequiresForm(provider));\n // Hosted flows open the popup synchronously in the click gesture so\n // popup blockers allow it; headless flows never navigate to a hosted\n // page, so no window opens here.\n const popup = headless ? null : window.open('', 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n session.mutate(\n { provider: provider.id },\n {\n onSuccess: created => {\n if (headless) {\n void beginHeadless(provider, created, values);\n return;\n }\n // The popup enters OAuth through the server's launch gate, which\n // verifies this browser owns the pending session before\n // redirecting — the raw vendor URL never reaches the page.\n const launchHref = resolveLaunchHref(created.launchUrl);\n if (popup) {\n popup.location.href = launchHref;\n }\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n },\n onError: () => {\n popup?.close();\n popupRef.current = null;\n },\n },\n );\n },\n [session, resolveLaunchHref, beginHeadless],\n );\n\n /** Abandons the in-flight flow: closes the provider window, hands the Connect action back. */\n const cancel = useCallback(() => {\n headlessRef.current?.close();\n headlessRef.current = null;\n popupRef.current = null;\n pendingRef.current = null;\n setPending(null);\n setSettled(null);\n }, []);\n\n return {\n pending,\n connect,\n cancel,\n /** Outcome of the most recently settled flow; null while none settled or a flow is in progress. */\n settled,\n /** Providers whose connection settled `active` during this hook's lifetime. */\n connectedProviders,\n isCreating: session.isPending,\n createError: session.isError ? session.error : null,\n };\n}\n\n/** Disconnects one of the caller's own connections. */\nexport function useDisconnectUserConnection() {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useMutation<void, UserConnectRequestError, { connectionId: string }>({\n mutationFn: ({ connectionId }) =>\n connectFetch<void>(`/connections/${encodeURIComponent(connectionId)}`, { method: 'DELETE' }),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: connectionsQueryKey }),\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-user-connect.es.js","names":[],"sources":["../../../src/domains/connect/use-user-connect.ts"],"sourcesContent":["import { useMastraClient } from '@mastra/react';\nimport type { QueryClient } from '@tanstack/react-query';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport {\n HeadlessAuthError,\n headlessAuthFields,\n headlessAuthRequiresForm,\n splitHeadlessAuthValues,\n startHeadlessAuth,\n supportsHeadlessAuth,\n} from './headless-connect';\nimport type { HeadlessAuthHandle } from './headless-connect';\nimport type {\n UserConnectErrorBody,\n UserConnectLaunchTokenResponse,\n UserConnectProvider,\n UserConnectProvidersResponse,\n UserConnectSessionResponse,\n UserConnectionStatusResponse,\n UserConnectionsResponse,\n} from './types';\n\n/** Default mount prefix of `userConnectRoutes()` on the dev server. */\nexport const CONNECT_BASE_PATH = '/connect';\n\nexport class UserConnectRequestError extends Error {\n status: number;\n code: string | null;\n\n constructor(status: number, code: string | null, message: string) {\n super(message);\n this.name = 'UserConnectRequestError';\n this.status = status;\n this.code = code;\n }\n}\n\ntype ConnectFetch = <T>(path: string, init?: RequestInit) => Promise<T>;\n\n/**\n * Fetches against the dev server's mounted connect routes. Custom `apiRoutes`\n * live outside the `/api` prefix, so this goes around the SDK while reusing\n * its base URL, auth headers, credentials mode, and refresh-aware fetch.\n */\nfunction useConnectFetch(): ConnectFetch {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback<ConnectFetch>(\n async (path, init) => {\n const fetchFn = customFetch ?? fetch;\n const response = await fetchFn(`${baseUrl}${CONNECT_BASE_PATH}${path}`, {\n ...init,\n headers: { ...headers, ...init?.headers },\n credentials,\n });\n if (!response.ok) {\n let code: string | null = null;\n let message = `Request failed with status ${response.status}`;\n try {\n const body = (await response.json()) as Partial<UserConnectErrorBody>;\n if (body?.error) {\n code = body.error.code ?? null;\n message = body.error.message ?? message;\n }\n } catch {\n // Non-JSON error body (e.g. a plain 404 for unmounted routes).\n }\n throw new UserConnectRequestError(response.status, code, message);\n }\n if (response.status === 204) return undefined as never;\n return (await response.json()) as never;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\n/**\n * Resolves a server-relative launch-gate path (returned by the session route\n * as `launchUrl`) against the SDK's base URL for top-level popup navigation.\n * The launch route is authenticated by the browser's session cookie — the\n * server re-verifies that this browser owns the pending session before\n * redirecting into the vendor OAuth flow.\n */\nexport function useConnectLaunchHref(): (launchUrl: string) => string {\n const client = useMastraClient();\n const { baseUrl } = client.options;\n return useCallback((launchUrl: string) => (baseUrl ? `${baseUrl}${launchUrl}` : launchUrl), [baseUrl]);\n}\n\n/**\n * Redeems the launch gate for a headless session token (`Accept:\n * application/json`) instead of following its hosted 302. The gate runs the\n * same ownership assertion in both modes; a `null` token means the server\n * could not extract one and the caller falls back to the hosted popup.\n */\nfunction useRedeemLaunchToken(): (launchUrl: string) => Promise<UserConnectLaunchTokenResponse> {\n const client = useMastraClient();\n const { baseUrl, headers, credentials, fetch: customFetch } = client.options;\n\n return useCallback(\n async launchUrl => {\n const fetchFn = customFetch ?? fetch;\n // `launchUrl` is the full server-relative gate path (it already carries\n // the connect mount prefix), so it resolves against the bare base URL.\n const response = await fetchFn(`${baseUrl ?? ''}${launchUrl}`, {\n headers: { ...headers, accept: 'application/json' },\n credentials,\n });\n if (!response.ok) {\n throw new UserConnectRequestError(response.status, null, `Request failed with status ${response.status}`);\n }\n return (await response.json()) as UserConnectLaunchTokenResponse;\n },\n [baseUrl, headers, credentials, customFetch],\n );\n}\n\nexport type ConnectSurface =\n | { status: 'ready'; providers: UserConnectProvidersResponse['providers'] }\n | { status: 'not-mounted' }\n | { status: 'unauthenticated' };\n\n/**\n * Capability detection for the end-user connect surface: probes\n * `GET /connect/providers` and distinguishes a working surface from the two\n * setup gaps (routes not mounted → 404, no end-user identity → 401).\n */\nexport function useConnectSurface() {\n const connectFetch = useConnectFetch();\n\n return useQuery<ConnectSurface, UserConnectRequestError>({\n queryKey: ['user-connect', 'surface'],\n retry: false,\n queryFn: async () => {\n try {\n const body = await connectFetch<UserConnectProvidersResponse>('/providers');\n return { status: 'ready', providers: body.providers };\n } catch (error) {\n if (error instanceof UserConnectRequestError) {\n if (error.status === 404) return { status: 'not-mounted' };\n if (error.status === 401) return { status: 'unauthenticated' };\n }\n throw error;\n }\n },\n });\n}\n\nconst connectionsQueryKey = ['user-connect', 'connections'] as const;\n\n/**\n * A connection that activates or goes away changes which tools resolve for\n * this user, so the connection list and every agent / tool listing are\n * refetched. The server drops its cached tool snapshot when it reports the\n * change, so the refetch already sees the new tools.\n */\nfunction invalidateAfterConnectionChange(queryClient: QueryClient) {\n return Promise.all(\n [connectionsQueryKey, ['agent'], ['agents'], ['tools']].map(async queryKey => {\n // A first fetch still in flight would otherwise be reused by the\n // invalidation, and its pre-change answer would land as fresh data.\n await queryClient.cancelQueries({ queryKey });\n await queryClient.invalidateQueries({ queryKey });\n }),\n );\n}\n\n/** Lists the caller's visible connections (global + their own). */\nexport function useUserConnections({ enabled }: { enabled: boolean }) {\n const connectFetch = useConnectFetch();\n\n return useQuery<UserConnectionsResponse['connections'], UserConnectRequestError>({\n queryKey: connectionsQueryKey,\n enabled,\n retry: false,\n queryFn: async () => {\n const body = await connectFetch<UserConnectionsResponse>('/connections');\n return body.connections;\n },\n });\n}\n\n/** Creates a connect session for a provider; the caller drives the popup. */\nexport function useCreateConnectSession() {\n const connectFetch = useConnectFetch();\n\n return useMutation<UserConnectSessionResponse, UserConnectRequestError, { provider: string }>({\n mutationFn: ({ provider }) =>\n connectFetch<UserConnectSessionResponse>(`/${encodeURIComponent(provider)}/sessions`, { method: 'POST' }),\n });\n}\n\n/** 2s interval with a 5 minute cap, mirroring the hosted connect page. */\nconst STATUS_POLL_INTERVAL_MS = 2_000;\nconst STATUS_MAX_POLLS = 150;\n\n/**\n * Polls a pending connection until it leaves `pending`. A 404 counts as still\n * pending — the platform row may not be visible until the provider handshake\n * lands. Polling stops once the status settles (or after the 5 minute cap);\n * the connections list is refreshed when it does.\n */\nexport function useConnectionStatus({ connectionId }: { connectionId: string | null }) {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useQuery<UserConnectionStatusResponse, UserConnectRequestError>({\n queryKey: ['user-connect', 'connection-status', connectionId],\n enabled: connectionId !== null,\n retry: false,\n refetchInterval: query => {\n const status = query.state.data?.status;\n if (status !== undefined && status !== 'pending') return false;\n if (query.state.dataUpdateCount >= STATUS_MAX_POLLS) return false;\n return STATUS_POLL_INTERVAL_MS;\n },\n queryFn: async () => {\n let status: UserConnectionStatusResponse;\n try {\n status = await connectFetch<UserConnectionStatusResponse>(\n `/connections/${encodeURIComponent(connectionId ?? '')}/status`,\n );\n } catch (error) {\n if (error instanceof UserConnectRequestError && error.status === 404) {\n return { id: connectionId ?? '', status: 'pending', scope: 'user' };\n }\n throw error;\n }\n if (status.status !== 'pending') {\n void invalidateAfterConnectionChange(queryClient);\n }\n return status;\n },\n });\n}\n\nexport interface PendingConnect {\n provider: string;\n connectionId: string;\n /**\n * `headless` — the Nango SDK drives the provider's own consent popup (or no\n * popup at all for collected credentials). `hosted` — a popup navigated\n * through the launch gate's 302 into the hosted connect page.\n */\n mode: 'headless' | 'hosted';\n /** Shown when the popup was blocked so the user can finish the flow manually. */\n fallbackUrl: string | null;\n}\n\n/**\n * What a caller passes to `connect()`: the provider's id plus the auth shape\n * when known. Callers that only know the id (older payloads) always get the\n * hosted flow.\n */\nexport type ConnectTarget = Pick<UserConnectProvider, 'id'> &\n Partial<Pick<UserConnectProvider, 'authType' | 'authFields'>>;\n\n/**\n * Grace period after the vendor popup closes before an unsettled flow is\n * abandoned — the activation webhook often lands a few seconds after the\n * vendor window closes itself.\n */\nconst POPUP_CLOSE_GRACE_MS = 15_000;\n/** Wall-clock cap matching the status poll's 5 minute budget. */\nconst PENDING_TIMEOUT_MS = STATUS_POLL_INTERVAL_MS * STATUS_MAX_POLLS;\n\nexport interface UsePendingConnectOptions {\n /** Overrides for the abandonment timings (primarily for tests). */\n popupCloseGraceMs?: number;\n pendingTimeoutMs?: number;\n}\n\n/**\n * Outcome of the most recently settled flow: `active` when the connection\n * activated, `failed` for everything else (non-active settle, poll failure,\n * abandoned popup, poll budget). Cleared when a new flow starts.\n */\nexport interface SettledConnect {\n provider: string;\n status: 'active' | 'failed';\n /** Human-readable failure detail (blocked popup, closed window, rejected credentials). */\n message?: string;\n}\n\n/** Window features for the hosted connect popup. */\nconst POPUP_FEATURES = 'popup,width=600,height=720';\n\n/**\n * Drives one add-connection flow end to end. Providers whose auth the browser\n * can complete headlessly go through the launch gate's JSON redemption: the\n * released session token keys the Nango SDK, which opens the provider's own\n * consent popup (or submits collected credentials with no popup). Everything\n * else gets the hosted flow — a popup opened synchronously in the click\n * gesture (so popup blockers allow it) and navigated through the launch\n * gate's 302. Either way the connection status is polled until it settles.\n * The pending state always resolves — on settle, on a poll or auth failure,\n * when the popup closes without settling (after a grace period), or at the\n * poll budget — so the Connect action is never stuck disabled.\n */\nexport function usePendingConnect(options: UsePendingConnectOptions = {}) {\n const { popupCloseGraceMs = POPUP_CLOSE_GRACE_MS, pendingTimeoutMs = PENDING_TIMEOUT_MS } = options;\n const session = useCreateConnectSession();\n const resolveLaunchHref = useConnectLaunchHref();\n const redeemLaunchToken = useRedeemLaunchToken();\n const [pending, setPending] = useState<PendingConnect | null>(null);\n const [settled, setSettled] = useState<SettledConnect | null>(null);\n const [connectedProviders, setConnectedProviders] = useState<ReadonlySet<string>>(new Set());\n const popupRef = useRef<Pick<Window, 'closed'> | null>(null);\n const headlessRef = useRef<HeadlessAuthHandle | null>(null);\n // Mirrors `pending` for async guards (the SDK promise settles outside the\n // render cycle); written directly at every transition so a cancel is never\n // raced by a trailing rejection.\n const pendingRef = useRef<PendingConnect | null>(null);\n const status = useConnectionStatus({ connectionId: pending?.connectionId ?? null });\n\n useEffect(() => {\n pendingRef.current = pending;\n }, [pending]);\n\n // Close the provider popup if the surface unmounts mid-flow.\n useEffect(\n () => () => {\n headlessRef.current?.close();\n headlessRef.current = null;\n },\n [],\n );\n\n // Settle only on a status response for the connection currently pending —\n // a stale result from a previous flow must not clear or mark a newer one.\n const statusData = status.data;\n useEffect(() => {\n if (!pending || statusData === undefined) return;\n if (statusData.id !== pending.connectionId || statusData.status === 'pending') return;\n const { provider } = pending;\n if (statusData.status === 'active') {\n setConnectedProviders(previous => (previous.has(provider) ? previous : new Set([...previous, provider])));\n }\n // The provider window closes itself on active settles; drop the handle so\n // a trailing SDK rejection cannot re-settle this flow.\n headlessRef.current = null;\n pendingRef.current = null;\n setSettled({ provider, status: statusData.status === 'active' ? 'active' : 'failed' });\n setPending(null);\n }, [pending, statusData]);\n\n // A failed poll hands the Connect action back instead of leaving it stuck.\n useEffect(() => {\n if (!status.isError || !pending) return;\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }, [status.isError, pending]);\n\n // Abandonment: the popup closed without the flow settling (grace period for\n // the trailing webhook) or the poll budget ran out.\n useEffect(() => {\n if (!pending) return;\n const startedAt = Date.now();\n let closedAt: number | null = null;\n const tickMs = Math.min(1_000, popupCloseGraceMs);\n const timer = window.setInterval(() => {\n if (popupRef.current?.closed) closedAt ??= Date.now();\n const abandoned = closedAt !== null && Date.now() - closedAt >= popupCloseGraceMs;\n const timedOut = Date.now() - startedAt >= pendingTimeoutMs;\n if (abandoned || timedOut) {\n // The ref is cleared before close() so the rejection it triggers no-ops.\n pendingRef.current = null;\n headlessRef.current?.close();\n headlessRef.current = null;\n setSettled({ provider: pending.provider, status: 'failed' });\n setPending(null);\n }\n }, tickMs);\n return () => window.clearInterval(timer);\n }, [pending, popupCloseGraceMs, pendingTimeoutMs]);\n\n const beginHeadless = useCallback(\n async (provider: ConnectTarget, created: UserConnectSessionResponse, values?: Record<string, string>) => {\n let sessionToken: string | null = null;\n try {\n sessionToken = (await redeemLaunchToken(created.launchUrl)).sessionToken;\n } catch {\n // Redemption failure (older platform, transient error) is not fatal —\n // the hosted flow below still works through the gate's 302.\n }\n if (!sessionToken) {\n // Opened after an await, so a blocker may stop it; the fallback link\n // in the pending state covers that.\n const launchHref = resolveLaunchHref(created.launchUrl);\n const popup = window.open(launchHref, 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n return;\n }\n\n const split = values ? splitHeadlessAuthValues(headlessAuthFields(provider), values) : {};\n const handle = startHeadlessAuth({\n sessionToken,\n integrationId: created.integrationId,\n authType: provider.authType,\n credentials: split.credentials,\n params: split.params,\n });\n headlessRef.current = handle;\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'headless',\n fallbackUrl: null,\n };\n pendingRef.current = next;\n setPending(next);\n // Success needs no action here — the activation webhook lands on the\n // platform and the status poll settles the flow. Failures settle it now.\n handle.result.catch((error: unknown) => {\n if (pendingRef.current?.connectionId !== created.connectionId) return;\n headlessRef.current = null;\n pendingRef.current = null;\n const message = error instanceof HeadlessAuthError ? error.message : 'Could not authorize this connection.';\n setSettled({ provider: provider.id, status: 'failed', message });\n setPending(null);\n });\n },\n [redeemLaunchToken, resolveLaunchHref],\n );\n\n const connect = useCallback(\n (provider: ConnectTarget, values?: Record<string, string>) => {\n setSettled(null);\n headlessRef.current?.close();\n headlessRef.current = null;\n\n // Headless needs both the capability and the inputs: a caller without a\n // form (no `values`) can only run flows whose fields are all optional —\n // anything else falls back to the hosted page, which renders the form.\n const headless =\n supportsHeadlessAuth(provider.authType, provider.authFields) &&\n (values !== undefined || !headlessAuthRequiresForm(provider));\n // Hosted flows open the popup synchronously in the click gesture so\n // popup blockers allow it; headless flows never navigate to a hosted\n // page, so no window opens here.\n const popup = headless ? null : window.open('', 'mastra-connect', POPUP_FEATURES);\n popupRef.current = popup;\n session.mutate(\n { provider: provider.id },\n {\n onSuccess: created => {\n if (headless) {\n void beginHeadless(provider, created, values);\n return;\n }\n // The popup enters OAuth through the server's launch gate, which\n // verifies this browser owns the pending session before\n // redirecting — the raw vendor URL never reaches the page.\n const launchHref = resolveLaunchHref(created.launchUrl);\n if (popup) {\n popup.location.href = launchHref;\n }\n const next: PendingConnect = {\n provider: provider.id,\n connectionId: created.connectionId,\n mode: 'hosted',\n fallbackUrl: popup ? null : launchHref,\n };\n pendingRef.current = next;\n setPending(next);\n },\n onError: () => {\n popup?.close();\n popupRef.current = null;\n },\n },\n );\n },\n [session, resolveLaunchHref, beginHeadless],\n );\n\n /** Abandons the in-flight flow: closes the provider window, hands the Connect action back. */\n const cancel = useCallback(() => {\n headlessRef.current?.close();\n headlessRef.current = null;\n popupRef.current = null;\n pendingRef.current = null;\n setPending(null);\n setSettled(null);\n }, []);\n\n return {\n pending,\n connect,\n cancel,\n /** Outcome of the most recently settled flow; null while none settled or a flow is in progress. */\n settled,\n /** Providers whose connection settled `active` during this hook's lifetime. */\n connectedProviders,\n isCreating: session.isPending,\n createError: session.isError ? session.error : null,\n };\n}\n\n/** Disconnects one of the caller's own connections. */\nexport function useDisconnectUserConnection() {\n const connectFetch = useConnectFetch();\n const queryClient = useQueryClient();\n\n return useMutation<void, UserConnectRequestError, { connectionId: string }>({\n mutationFn: ({ connectionId }) =>\n connectFetch<void>(`/connections/${encodeURIComponent(connectionId)}`, { method: 'DELETE' }),\n onSuccess: () => invalidateAfterConnectionChange(queryClient),\n });\n}\n"],"mappings":";;;;;;AAyBA,IAAa,oBAAoB;AAEjC,IAAa,0BAAb,cAA6C,MAAM;CACjD;CACA;CAEA,YAAY,QAAgB,MAAqB,SAAiB;EAChE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,OAAO;CACd;AACF;;;;;;AASA,SAAS,kBAAgC;CAEvC,MAAM,EAAE,SAAS,SAAS,aAAa,OAAO,gBAD/B,gBAC+C,CAAA,CAAO;CAErE,OAAO,YACL,OAAO,MAAM,SAAS;EAEpB,MAAM,WAAW,OADD,eAAe,MAAA,CACA,GAAG,UAAU,oBAAoB,QAAQ;GACtE,GAAG;GACH,SAAS;IAAE,GAAG;IAAS,GAAG,MAAM;GAAQ;GACxC;EACF,CAAC;EACD,IAAI,CAAC,SAAS,IAAI;GAChB,IAAI,OAAsB;GAC1B,IAAI,UAAU,8BAA8B,SAAS;GACrD,IAAI;IACF,MAAM,OAAQ,MAAM,SAAS,KAAK;IAClC,IAAI,MAAM,OAAO;KACf,OAAO,KAAK,MAAM,QAAQ;KAC1B,UAAU,KAAK,MAAM,WAAW;IAClC;GACF,QAAQ,CAER;GACA,MAAM,IAAI,wBAAwB,SAAS,QAAQ,MAAM,OAAO;EAClE;EACA,IAAI,SAAS,WAAW,KAAK,OAAO,KAAA;EACpC,OAAQ,MAAM,SAAS,KAAK;CAC9B,GACA;EAAC;EAAS;EAAS;EAAa;CAAW,CAC7C;AACF;;;;;;;;AASA,SAAgB,uBAAsD;CAEpE,MAAM,EAAE,YADO,gBACK,CAAA,CAAO;CAC3B,OAAO,aAAa,cAAuB,UAAU,GAAG,UAAU,cAAc,WAAY,CAAC,OAAO,CAAC;AACvG;;;;;;;AAQA,SAAS,uBAAuF;CAE9F,MAAM,EAAE,SAAS,SAAS,aAAa,OAAO,gBAD/B,gBAC+C,CAAA,CAAO;CAErE,OAAO,YACL,OAAM,cAAa;EAIjB,MAAM,WAAW,OAHD,eAAe,MAAA,CAGA,GAAG,WAAW,KAAK,aAAa;GAC7D,SAAS;IAAE,GAAG;IAAS,QAAQ;GAAmB;GAClD;EACF,CAAC;EACD,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,wBAAwB,SAAS,QAAQ,MAAM,8BAA8B,SAAS,QAAQ;EAE1G,OAAQ,MAAM,SAAS,KAAK;CAC9B,GACA;EAAC;EAAS;EAAS;EAAa;CAAW,CAC7C;AACF;;;;;;AAYA,SAAgB,oBAAoB;CAClC,MAAM,eAAe,gBAAgB;CAErC,OAAO,SAAkD;EACvD,UAAU,CAAC,gBAAgB,SAAS;EACpC,OAAO;EACP,SAAS,YAAY;GACnB,IAAI;IAEF,OAAO;KAAE,QAAQ;KAAS,YAAW,MADlB,aAA2C,YAAY,EAAA,CAChC;IAAU;GACtD,SAAS,OAAO;IACd,IAAI,iBAAiB,yBAAyB;KAC5C,IAAI,MAAM,WAAW,KAAK,OAAO,EAAE,QAAQ,cAAc;KACzD,IAAI,MAAM,WAAW,KAAK,OAAO,EAAE,QAAQ,kBAAkB;IAC/D;IACA,MAAM;GACR;EACF;CACF,CAAC;AACH;AAEA,IAAM,sBAAsB,CAAC,gBAAgB,aAAa;;;;;;;AAQ1D,SAAS,gCAAgC,aAA0B;CACjE,OAAO,QAAQ,IACb;EAAC;EAAqB,CAAC,OAAO;EAAG,CAAC,QAAQ;EAAG,CAAC,OAAO;CAAC,CAAC,CAAC,IAAI,OAAM,aAAY;EAG5E,MAAM,YAAY,cAAc,EAAE,SAAS,CAAC;EAC5C,MAAM,YAAY,kBAAkB,EAAE,SAAS,CAAC;CAClD,CAAC,CACH;AACF;;AAGA,SAAgB,mBAAmB,EAAE,WAAiC;CACpE,MAAM,eAAe,gBAAgB;CAErC,OAAO,SAA0E;EAC/E,UAAU;EACV;EACA,OAAO;EACP,SAAS,YAAY;GAEnB,QAAO,MADY,aAAsC,cAAc,EAAA,CAC3D;EACd;CACF,CAAC;AACH;;AAGA,SAAgB,0BAA0B;CACxC,MAAM,eAAe,gBAAgB;CAErC,OAAO,YAAuF,EAC5F,aAAa,EAAE,eACb,aAAyC,IAAI,mBAAmB,QAAQ,EAAE,YAAY,EAAE,QAAQ,OAAO,CAAC,EAC5G,CAAC;AACH;;AAGA,IAAM,0BAA0B;AAChC,IAAM,mBAAmB;;;;;;;AAQzB,SAAgB,oBAAoB,EAAE,gBAAiD;CACrF,MAAM,eAAe,gBAAgB;CACrC,MAAM,cAAc,eAAe;CAEnC,OAAO,SAAgE;EACrE,UAAU;GAAC;GAAgB;GAAqB;EAAY;EAC5D,SAAS,iBAAiB;EAC1B,OAAO;EACP,kBAAiB,UAAS;GACxB,MAAM,SAAS,MAAM,MAAM,MAAM;GACjC,IAAI,WAAW,KAAA,KAAa,WAAW,WAAW,OAAO;GACzD,IAAI,MAAM,MAAM,mBAAmB,kBAAkB,OAAO;GAC5D,OAAO;EACT;EACA,SAAS,YAAY;GACnB,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,aACb,gBAAgB,mBAAmB,gBAAgB,EAAE,EAAE,QACzD;GACF,SAAS,OAAO;IACd,IAAI,iBAAiB,2BAA2B,MAAM,WAAW,KAC/D,OAAO;KAAE,IAAI,gBAAgB;KAAI,QAAQ;KAAW,OAAO;IAAO;IAEpE,MAAM;GACR;GACA,IAAI,OAAO,WAAW,WACpB,gCAAqC,WAAW;GAElD,OAAO;EACT;CACF,CAAC;AACH;;;;;;AA4BA,IAAM,uBAAuB;;AAE7B,IAAM,qBAAqB,0BAA0B;;AAqBrD,IAAM,iBAAiB;;;;;;;;;;;;;AAcvB,SAAgB,kBAAkB,UAAoC,CAAC,GAAG;CACxE,MAAM,EAAE,oBAAoB,sBAAsB,mBAAmB,uBAAuB;CAC5F,MAAM,UAAU,wBAAwB;CACxC,MAAM,oBAAoB,qBAAqB;CAC/C,MAAM,oBAAoB,qBAAqB;CAC/C,MAAM,CAAC,SAAS,cAAc,SAAgC,IAAI;CAClE,MAAM,CAAC,SAAS,cAAc,SAAgC,IAAI;CAClE,MAAM,CAAC,oBAAoB,yBAAyB,yBAA8B,IAAI,IAAI,CAAC;CAC3F,MAAM,WAAW,OAAsC,IAAI;CAC3D,MAAM,cAAc,OAAkC,IAAI;CAI1D,MAAM,aAAa,OAA8B,IAAI;CACrD,MAAM,SAAS,oBAAoB,EAAE,cAAc,SAAS,gBAAgB,KAAK,CAAC;CAElF,gBAAgB;EACd,WAAW,UAAU;CACvB,GAAG,CAAC,OAAO,CAAC;CAGZ,sBACc;EACV,YAAY,SAAS,MAAM;EAC3B,YAAY,UAAU;CACxB,GACA,CAAC,CACH;CAIA,MAAM,aAAa,OAAO;CAC1B,gBAAgB;EACd,IAAI,CAAC,WAAW,eAAe,KAAA,GAAW;EAC1C,IAAI,WAAW,OAAO,QAAQ,gBAAgB,WAAW,WAAW,WAAW;EAC/E,MAAM,EAAE,aAAa;EACrB,IAAI,WAAW,WAAW,UACxB,uBAAsB,aAAa,SAAS,IAAI,QAAQ,IAAI,2BAAW,IAAI,IAAI,CAAC,GAAG,UAAU,QAAQ,CAAC,CAAE;EAI1G,YAAY,UAAU;EACtB,WAAW,UAAU;EACrB,WAAW;GAAE;GAAU,QAAQ,WAAW,WAAW,WAAW,WAAW;EAAS,CAAC;EACrF,WAAW,IAAI;CACjB,GAAG,CAAC,SAAS,UAAU,CAAC;CAGxB,gBAAgB;EACd,IAAI,CAAC,OAAO,WAAW,CAAC,SAAS;EAEjC,WAAW,UAAU;EACrB,YAAY,SAAS,MAAM;EAC3B,YAAY,UAAU;EACtB,WAAW;GAAE,UAAU,QAAQ;GAAU,QAAQ;EAAS,CAAC;EAC3D,WAAW,IAAI;CACjB,GAAG,CAAC,OAAO,SAAS,OAAO,CAAC;CAI5B,gBAAgB;EACd,IAAI,CAAC,SAAS;EACd,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI,WAA0B;EAC9B,MAAM,SAAS,KAAK,IAAI,KAAO,iBAAiB;EAChD,MAAM,QAAQ,OAAO,kBAAkB;GACrC,IAAI,SAAS,SAAS,QAAQ,aAAa,KAAK,IAAI;GACpD,MAAM,YAAY,aAAa,QAAQ,KAAK,IAAI,IAAI,YAAY;GAChE,MAAM,WAAW,KAAK,IAAI,IAAI,aAAa;GAC3C,IAAI,aAAa,UAAU;IAEzB,WAAW,UAAU;IACrB,YAAY,SAAS,MAAM;IAC3B,YAAY,UAAU;IACtB,WAAW;KAAE,UAAU,QAAQ;KAAU,QAAQ;IAAS,CAAC;IAC3D,WAAW,IAAI;GACjB;EACF,GAAG,MAAM;EACT,aAAa,OAAO,cAAc,KAAK;CACzC,GAAG;EAAC;EAAS;EAAmB;CAAgB,CAAC;CAEjD,MAAM,gBAAgB,YACpB,OAAO,UAAyB,SAAqC,WAAoC;EACvG,IAAI,eAA8B;EAClC,IAAI;GACF,gBAAgB,MAAM,kBAAkB,QAAQ,SAAS,EAAA,CAAG;EAC9D,QAAQ,CAGR;EACA,IAAI,CAAC,cAAc;GAGjB,MAAM,aAAa,kBAAkB,QAAQ,SAAS;GACtD,MAAM,QAAQ,OAAO,KAAK,YAAY,kBAAkB,cAAc;GACtE,SAAS,UAAU;GACnB,MAAM,OAAuB;IAC3B,UAAU,SAAS;IACnB,cAAc,QAAQ;IACtB,MAAM;IACN,aAAa,QAAQ,OAAO;GAC9B;GACA,WAAW,UAAU;GACrB,WAAW,IAAI;GACf;EACF;EAEA,MAAM,QAAQ,SAAS,wBAAwB,mBAAmB,QAAQ,GAAG,MAAM,IAAI,CAAC;EACxF,MAAM,SAAS,kBAAkB;GAC/B;GACA,eAAe,QAAQ;GACvB,UAAU,SAAS;GACnB,aAAa,MAAM;GACnB,QAAQ,MAAM;EAChB,CAAC;EACD,YAAY,UAAU;EACtB,MAAM,OAAuB;GAC3B,UAAU,SAAS;GACnB,cAAc,QAAQ;GACtB,MAAM;GACN,aAAa;EACf;EACA,WAAW,UAAU;EACrB,WAAW,IAAI;EAGf,OAAO,OAAO,OAAO,UAAmB;GACtC,IAAI,WAAW,SAAS,iBAAiB,QAAQ,cAAc;GAC/D,YAAY,UAAU;GACtB,WAAW,UAAU;GACrB,MAAM,UAAU,iBAAiB,oBAAoB,MAAM,UAAU;GACrE,WAAW;IAAE,UAAU,SAAS;IAAI,QAAQ;IAAU;GAAQ,CAAC;GAC/D,WAAW,IAAI;EACjB,CAAC;CACH,GACA,CAAC,mBAAmB,iBAAiB,CACvC;CA+DA,OAAO;EACL;EACA,SA/Dc,aACb,UAAyB,WAAoC;GAC5D,WAAW,IAAI;GACf,YAAY,SAAS,MAAM;GAC3B,YAAY,UAAU;GAKtB,MAAM,WACJ,qBAAqB,SAAS,UAAU,SAAS,UAAU,MAC1D,WAAW,KAAA,KAAa,CAAC,yBAAyB,QAAQ;GAI7D,MAAM,QAAQ,WAAW,OAAO,OAAO,KAAK,IAAI,kBAAkB,cAAc;GAChF,SAAS,UAAU;GACnB,QAAQ,OACN,EAAE,UAAU,SAAS,GAAG,GACxB;IACE,YAAW,YAAW;KACpB,IAAI,UAAU;MACZ,cAAmB,UAAU,SAAS,MAAM;MAC5C;KACF;KAIA,MAAM,aAAa,kBAAkB,QAAQ,SAAS;KACtD,IAAI,OACF,MAAM,SAAS,OAAO;KAExB,MAAM,OAAuB;MAC3B,UAAU,SAAS;MACnB,cAAc,QAAQ;MACtB,MAAM;MACN,aAAa,QAAQ,OAAO;KAC9B;KACA,WAAW,UAAU;KACrB,WAAW,IAAI;IACjB;IACA,eAAe;KACb,OAAO,MAAM;KACb,SAAS,UAAU;IACrB;GACF,CACF;EACF,GACA;GAAC;GAAS;GAAmB;EAAa,CAe1C;EACA,QAZa,kBAAkB;GAC/B,YAAY,SAAS,MAAM;GAC3B,YAAY,UAAU;GACtB,SAAS,UAAU;GACnB,WAAW,UAAU;GACrB,WAAW,IAAI;GACf,WAAW,IAAI;EACjB,GAAG,CAAC,CAKF;;EAEA;;EAEA;EACA,YAAY,QAAQ;EACpB,aAAa,QAAQ,UAAU,QAAQ,QAAQ;CACjD;AACF;;AAGA,SAAgB,8BAA8B;CAC5C,MAAM,eAAe,gBAAgB;CACrC,MAAM,cAAc,eAAe;CAEnC,OAAO,YAAqE;EAC1E,aAAa,EAAE,mBACb,aAAmB,gBAAgB,mBAAmB,YAAY,KAAK,EAAE,QAAQ,SAAS,CAAC;EAC7F,iBAAiB,gCAAgC,WAAW;CAC9D,CAAC;AACH"}
|
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_ErrorBoundary = require("../../../ErrorBoundary-B5GjmA6V.cjs");
|
|
3
3
|
const require_domains_dashboards_components_dashboard_grid = require("./dashboard-grid.cjs.js");
|
|
4
4
|
const require_domains_metrics_hooks_use_metrics = require("../../metrics/hooks/use-metrics.cjs.js");
|
|
5
|
-
const require_MetricsCard = require("../../../MetricsCard-
|
|
5
|
+
const require_MetricsCard = require("../../../MetricsCard-BEwiS7Pe.cjs");
|
|
6
6
|
const require_domains_dashboards_kinds = require("../kinds.cjs.js");
|
|
7
7
|
const require_domains_dashboards_lib_prepare_widget = require("../lib/prepare-widget.cjs.js");
|
|
8
8
|
const require_domains_dashboards_components_widget_error = require("./widget-error.cjs.js");
|
|
@@ -18,7 +18,7 @@ var spanOf = (widget) => isDashboardSpan(widget.span) ? widget.span : 12;
|
|
|
18
18
|
* owns the range and filters. Each widget is checked and rendered on its own: one that fails to
|
|
19
19
|
* parse, query or render shows its own error, and the rest of the dashboard still renders.
|
|
20
20
|
*/
|
|
21
|
-
function DashboardRenderer({ definition, scope, onDrilldown, kinds = [], className }) {
|
|
21
|
+
function DashboardRenderer({ definition, scope, onDrilldown, expand, kinds = [], className }) {
|
|
22
22
|
const { datePreset, customRange, filterTokens } = require_domains_metrics_hooks_use_metrics.useMetrics();
|
|
23
23
|
const pageKey = JSON.stringify([
|
|
24
24
|
datePreset,
|
|
@@ -57,7 +57,8 @@ function DashboardRenderer({ definition, scope, onDrilldown, kinds = [], classNa
|
|
|
57
57
|
widget: prepared.widget,
|
|
58
58
|
views: prepared.views,
|
|
59
59
|
scope,
|
|
60
|
-
onDrilldown
|
|
60
|
+
onDrilldown,
|
|
61
|
+
expand
|
|
61
62
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_domains_dashboards_components_widget_error.WidgetError, {
|
|
62
63
|
widget: heading,
|
|
63
64
|
message: prepared.message
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-renderer.cjs.js","names":["DASHBOARD_WIDGET_SPANS","useMetrics","BUILT_IN_WIDGET_KINDS","dashboardDefinitionEnvelopeSchema","MetricsCard","describeIssue","migrateDashboardDefinition","prepareWidget","DashboardGrid","DashboardGridRow","DashboardGridCell","ErrorBoundary","WidgetError"],"sources":["../../../../src/domains/dashboards/components/dashboard-renderer.tsx"],"sourcesContent":["import type { DashboardDefinition } from '@mastra/client-js';\nimport {\n DASHBOARD_WIDGET_SPANS,\n dashboardDefinitionEnvelopeSchema,\n migrateDashboardDefinition,\n} from '@mastra/core/storage/dashboards';\nimport { useMetrics } from '../../metrics/hooks/use-metrics';\nimport { BUILT_IN_WIDGET_KINDS } from '../kinds';\nimport type { DashboardScope, OnDashboardDrilldown } from '../lib/definition';\nimport { describeIssue, prepareWidget } from '../lib/prepare-widget';\nimport type { PreparedWidget, StoredWidget } from '../lib/prepare-widget';\nimport type { AnyWidgetKind } from '../widget-kind';\nimport { DashboardGrid, DashboardGridCell, DashboardGridRow } from './dashboard-grid';\nimport type { DashboardSpan } from './dashboard-grid';\nimport { WidgetError } from './widget-error';\nimport { ErrorBoundary } from '@/ds/components/ErrorBoundary';\nimport { MetricsCard } from '@/ds/components/MetricsCard';\n\nexport type DashboardRendererProps = {\n definition: DashboardDefinition;\n /** Which widgets, views and columns show: `org` spans several projects, `project` is one. */\n scope: DashboardScope;\n /** Opens a drilldown; each host routes to its own Traces or Logs page. */\n onDrilldown?: OnDashboardDrilldown;\n /** Kinds beyond the built-in ones; a kind of the same name replaces the built-in. */\n kinds?: AnyWidgetKind[];\n className?: string;\n};\n\n/** Whether a stored widget's `span` is one the grid lays out. */\nconst isDashboardSpan = (span: unknown): span is DashboardSpan => DASHBOARD_WIDGET_SPANS.some(s => s === span);\ntype ShownCell = { widget: StoredWidget; prepared: Exclude<PreparedWidget, { ok: 'hidden' }> };\nconst isShown = (cell: { widget: StoredWidget; prepared: PreparedWidget }): cell is ShownCell =>\n cell.prepared.ok !== 'hidden';\n\nconst spanOf = (widget: StoredWidget) => (isDashboardSpan(widget.span) ? widget.span : 12);\n\n/**\n * Lays a dashboard definition out on a 12-column grid inside the page's `MetricsProvider`, which\n * owns the range and filters. Each widget is checked and rendered on its own: one that fails to\n * parse, query or render shows its own error, and the rest of the dashboard still renders.\n */\nexport function DashboardRenderer({
|
|
1
|
+
{"version":3,"file":"dashboard-renderer.cjs.js","names":["DASHBOARD_WIDGET_SPANS","useMetrics","BUILT_IN_WIDGET_KINDS","dashboardDefinitionEnvelopeSchema","MetricsCard","describeIssue","migrateDashboardDefinition","prepareWidget","DashboardGrid","DashboardGridRow","DashboardGridCell","ErrorBoundary","WidgetError"],"sources":["../../../../src/domains/dashboards/components/dashboard-renderer.tsx"],"sourcesContent":["import type { DashboardDefinition } from '@mastra/client-js';\nimport {\n DASHBOARD_WIDGET_SPANS,\n dashboardDefinitionEnvelopeSchema,\n migrateDashboardDefinition,\n} from '@mastra/core/storage/dashboards';\nimport { useMetrics } from '../../metrics/hooks/use-metrics';\nimport { BUILT_IN_WIDGET_KINDS } from '../kinds';\nimport type { DashboardScope, OnDashboardDrilldown } from '../lib/definition';\nimport { describeIssue, prepareWidget } from '../lib/prepare-widget';\nimport type { PreparedWidget, StoredWidget } from '../lib/prepare-widget';\nimport type { AnyWidgetKind, DashboardExpand } from '../widget-kind';\nimport { DashboardGrid, DashboardGridCell, DashboardGridRow } from './dashboard-grid';\nimport type { DashboardSpan } from './dashboard-grid';\nimport { WidgetError } from './widget-error';\nimport { ErrorBoundary } from '@/ds/components/ErrorBoundary';\nimport { MetricsCard } from '@/ds/components/MetricsCard';\n\nexport type DashboardRendererProps = {\n definition: DashboardDefinition;\n /** Which widgets, views and columns show: `org` spans several projects, `project` is one. */\n scope: DashboardScope;\n /** Opens a drilldown; each host routes to its own Traces or Logs page. */\n onDrilldown?: OnDashboardDrilldown;\n /** Where chart cards expand to, e.g. the host's query page; see `DashboardExpand`. */\n expand?: DashboardExpand;\n /** Kinds beyond the built-in ones; a kind of the same name replaces the built-in. */\n kinds?: AnyWidgetKind[];\n className?: string;\n};\n\n/** Whether a stored widget's `span` is one the grid lays out. */\nconst isDashboardSpan = (span: unknown): span is DashboardSpan => DASHBOARD_WIDGET_SPANS.some(s => s === span);\ntype ShownCell = { widget: StoredWidget; prepared: Exclude<PreparedWidget, { ok: 'hidden' }> };\nconst isShown = (cell: { widget: StoredWidget; prepared: PreparedWidget }): cell is ShownCell =>\n cell.prepared.ok !== 'hidden';\n\nconst spanOf = (widget: StoredWidget) => (isDashboardSpan(widget.span) ? widget.span : 12);\n\n/**\n * Lays a dashboard definition out on a 12-column grid inside the page's `MetricsProvider`, which\n * owns the range and filters. Each widget is checked and rendered on its own: one that fails to\n * parse, query or render shows its own error, and the rest of the dashboard still renders.\n */\nexport function DashboardRenderer({\n definition,\n scope,\n onDrilldown,\n expand,\n kinds = [],\n className,\n}: DashboardRendererProps) {\n // A widget that threw renders again once the page's range or filters change, or the widget does.\n const { datePreset, customRange, filterTokens } = useMetrics();\n const pageKey = JSON.stringify([datePreset, customRange, filterTokens]);\n const registry = new Map([...BUILT_IN_WIDGET_KINDS, ...kinds].map(k => [k.kind, k]));\n\n const envelope = dashboardDefinitionEnvelopeSchema.safeParse(definition);\n if (!envelope.success) {\n return <MetricsCard.Error message={`This dashboard can't be shown. ${describeIssue(envelope.error.issues[0])}`} />;\n }\n // Each widget is parsed on its own below, so one that doesn't fit the current version shows its own error.\n const { rows } = migrateDashboardDefinition(envelope.data);\n\n // A row whose widgets are all hidden on this page isn't drawn, so it leaves no gap in the grid.\n const shown = rows\n .map((row, rowIndex) => ({\n rowIndex,\n widgets: row.widgets\n .map(widget => ({ widget, prepared: prepareWidget(widget, registry, scope) }))\n .filter(isShown),\n }))\n .filter(row => row.widgets.length > 0);\n\n return (\n <DashboardGrid className={className}>\n {shown.map(({ rowIndex, widgets }) => (\n <DashboardGridRow key={rowIndex}>\n {widgets.map(({ widget, prepared }) => {\n // Unparsed, the title may be anything; the error card shows it only when it's text.\n const heading = { id: widget.id, title: typeof widget.title === 'string' ? widget.title : undefined };\n return (\n <DashboardGridCell key={widget.id} id={widget.id} span={spanOf(widget)}>\n <ErrorBoundary\n resetKeys={[pageKey, JSON.stringify(widget)]}\n variant=\"inline\"\n fallback={({ error }) => <WidgetError widget={heading} message={error.message} />}\n >\n {prepared.ok ? (\n <prepared.kind.component\n widget={prepared.widget}\n views={prepared.views}\n scope={scope}\n onDrilldown={onDrilldown}\n expand={expand}\n />\n ) : (\n <WidgetError widget={heading} message={prepared.message} />\n )}\n </ErrorBoundary>\n </DashboardGridCell>\n );\n })}\n </DashboardGridRow>\n ))}\n </DashboardGrid>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAgCA,IAAM,mBAAmB,SAAyCA,gCAAAA,uBAAuB,MAAK,MAAK,MAAM,IAAI;AAE7G,IAAM,WAAW,SACf,KAAK,SAAS,OAAO;AAEvB,IAAM,UAAU,WAA0B,gBAAgB,OAAO,IAAI,IAAI,OAAO,OAAO;;;;;;AAOvF,SAAgB,kBAAkB,EAChC,YACA,OACA,aACA,QACA,QAAQ,CAAC,GACT,aACyB;CAEzB,MAAM,EAAE,YAAY,aAAa,iBAAiBC,0CAAAA,WAAW;CAC7D,MAAM,UAAU,KAAK,UAAU;EAAC;EAAY;EAAa;CAAY,CAAC;CACtE,MAAM,WAAW,IAAI,IAAI,CAAC,GAAGC,iCAAAA,uBAAuB,GAAG,KAAK,CAAC,CAAC,KAAI,MAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CAEnF,MAAM,WAAWC,gCAAAA,kCAAkC,UAAU,UAAU;CACvE,IAAI,CAAC,SAAS,SACZ,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACC,oBAAAA,YAAY,OAAb,EAAmB,SAAS,kCAAkCC,8CAAAA,cAAc,SAAS,MAAM,OAAO,EAAE,IAAM,CAAA;CAGnH,MAAM,EAAE,UAAA,GAASC,gCAAAA,2BAAAA,CAA2B,SAAS,IAAI;CAGzD,MAAM,QAAQ,KACX,KAAK,KAAK,cAAc;EACvB;EACA,SAAS,IAAI,QACV,KAAI,YAAW;GAAE;GAAQ,UAAUC,8CAAAA,cAAc,QAAQ,UAAU,KAAK;EAAE,EAAE,CAAC,CAC7E,OAAO,OAAO;CACnB,EAAE,CAAC,CACF,QAAO,QAAO,IAAI,QAAQ,SAAS,CAAC;CAEvC,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,qDAAAA,eAAD;EAA0B;EACvB,UAAA,MAAM,KAAK,EAAE,UAAU,cACtB,iBAAA,GAAA,kBAAA,IAAA,CAACC,qDAAAA,kBAAD,EAAA,UACG,QAAQ,KAAK,EAAE,QAAQ,eAAe;GAErC,MAAM,UAAU;IAAE,IAAI,OAAO;IAAI,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ,KAAA;GAAU;GACpG,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,qDAAAA,mBAAD;IAAmC,IAAI,OAAO;IAAI,MAAM,OAAO,MAAM;IACnE,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sBAAAA,eAAD;KACE,WAAW,CAAC,SAAS,KAAK,UAAU,MAAM,CAAC;KAC3C,SAAQ;KACR,WAAW,EAAE,YAAY,iBAAA,GAAA,kBAAA,IAAA,CAACC,mDAAAA,aAAD;MAAa,QAAQ;MAAS,SAAS,MAAM;KAAU,CAAA;KAE/E,UAAA,SAAS,KACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAS,KAAK,WAAf;MACE,QAAQ,SAAS;MACjB,OAAO,SAAS;MACT;MACM;MACL;KACT,CAAA,IAED,iBAAA,GAAA,kBAAA,IAAA,CAACA,mDAAAA,aAAD;MAAa,QAAQ;MAAS,SAAS,SAAS;KAAU,CAAA;IAE/C,CAAA;GACE,GAlBK,OAAO,EAkBZ;EAEvB,CAAC,EACe,GA1BK,QA0BL,CACnB;CACY,CAAA;AAEnB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as ErrorBoundary } from "../../../ErrorBoundary-Cat3KU86.js";
|
|
2
2
|
import { DashboardGrid, DashboardGridCell, DashboardGridRow } from "./dashboard-grid.es.js";
|
|
3
3
|
import { useMetrics } from "../../metrics/hooks/use-metrics.es.js";
|
|
4
|
-
import { t as MetricsCard } from "../../../MetricsCard-
|
|
4
|
+
import { t as MetricsCard } from "../../../MetricsCard-ua6C6b8a.js";
|
|
5
5
|
import { BUILT_IN_WIDGET_KINDS } from "../kinds.es.js";
|
|
6
6
|
import { describeIssue, prepareWidget } from "../lib/prepare-widget.es.js";
|
|
7
7
|
import { WidgetError } from "./widget-error.es.js";
|
|
@@ -17,7 +17,7 @@ var spanOf = (widget) => isDashboardSpan(widget.span) ? widget.span : 12;
|
|
|
17
17
|
* owns the range and filters. Each widget is checked and rendered on its own: one that fails to
|
|
18
18
|
* parse, query or render shows its own error, and the rest of the dashboard still renders.
|
|
19
19
|
*/
|
|
20
|
-
function DashboardRenderer({ definition, scope, onDrilldown, kinds = [], className }) {
|
|
20
|
+
function DashboardRenderer({ definition, scope, onDrilldown, expand, kinds = [], className }) {
|
|
21
21
|
const { datePreset, customRange, filterTokens } = useMetrics();
|
|
22
22
|
const pageKey = JSON.stringify([
|
|
23
23
|
datePreset,
|
|
@@ -56,7 +56,8 @@ function DashboardRenderer({ definition, scope, onDrilldown, kinds = [], classNa
|
|
|
56
56
|
widget: prepared.widget,
|
|
57
57
|
views: prepared.views,
|
|
58
58
|
scope,
|
|
59
|
-
onDrilldown
|
|
59
|
+
onDrilldown,
|
|
60
|
+
expand
|
|
60
61
|
}) : /* @__PURE__ */ jsx(WidgetError, {
|
|
61
62
|
widget: heading,
|
|
62
63
|
message: prepared.message
|