@hotmeshio/long-tail 0.14.0 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/escalations/bulk.d.ts +18 -0
- package/build/api/escalations/bulk.js +49 -1
- package/build/api/escalations/claim.d.ts +4 -1
- package/build/api/escalations/claim.js +6 -2
- package/build/api/escalations/helpers.d.ts +11 -1
- package/build/api/escalations/helpers.js +30 -3
- package/build/api/escalations/index.d.ts +1 -1
- package/build/api/escalations/index.js +2 -1
- package/build/index.js +4 -0
- package/build/routes/escalations/bulk.js +6 -0
- package/build/routes/escalations/single.js +3 -1
- package/build/sdk/index.d.ts +5 -0
- package/build/sdk/index.js +1 -0
- package/build/services/escalation/bulk.d.ts +27 -0
- package/build/services/escalation/bulk.js +39 -0
- package/build/services/escalation/crud.d.ts +10 -2
- package/build/services/escalation/crud.js +20 -12
- package/build/services/escalation/sql.d.ts +17 -0
- package/build/services/escalation/sql.js +44 -1
- package/build/system/mcp-servers/admin/escalations.js +13 -1
- package/build/system/mcp-servers/admin/schemas.d.ts +10 -0
- package/build/system/mcp-servers/admin/schemas.js +6 -2
- package/build/system/seed/tool-manifests-admin.d.ts +88 -0
- package/build/system/seed/tool-manifests-admin.js +2 -1
- package/dashboard/dist/assets/{AdminDashboard-DeZsR4pA.js → AdminDashboard-BS3wd7Zg.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DeZsR4pA.js.map → AdminDashboard-BS3wd7Zg.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-Bi5ZAsjf.js → AgentConfigPage-4C9aU0dj.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-Bi5ZAsjf.js.map → AgentConfigPage-4C9aU0dj.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CIbKor5E.js → AgentDetailPage-B6uvDnMF.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CIbKor5E.js.map → AgentDetailPage-B6uvDnMF.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-CRFZ6KDu.js → AgentsPage-vtxdvdrQ.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CRFZ6KDu.js.map → AgentsPage-vtxdvdrQ.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C9VKPhD6.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-C9VKPhD6.js.map +1 -0
- package/dashboard/dist/assets/BotPicker-CkY9u7nD.js +2 -0
- package/dashboard/dist/assets/{BotPicker-dUpw1wW6.js.map → BotPicker-CkY9u7nD.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-OIbUDYlC.js +2 -0
- package/dashboard/dist/assets/BulkAssignModal-OIbUDYlC.js.map +1 -0
- package/dashboard/dist/assets/CapabilitiesPage-Bkbq_GO6.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-Ca2jEln-.js.map → CapabilitiesPage-Bkbq_GO6.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BXlR5QmW.js → CollapsibleSection-Zuz9HkFL.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BXlR5QmW.js.map → CollapsibleSection-Zuz9HkFL.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-CGnk4Bw_.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-CGnk4Bw_.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-CGyCCzGh.js → CredentialsPage-CAmDMnzV.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CGyCCzGh.js.map → CredentialsPage-CAmDMnzV.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CAu2hmQf.js → CronLabel-DX2woCPZ.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CAu2hmQf.js.map → CronLabel-DX2woCPZ.js.map} +1 -1
- package/dashboard/dist/assets/{DataTable-Bir0Xs1p.js → DataTable-DFPMeqyQ.js} +2 -2
- package/dashboard/dist/assets/DataTable-DFPMeqyQ.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-DovkhN2p.js → DropZone-7UoXQ4qL.js} +2 -2
- package/dashboard/dist/assets/{DropZone-DovkhN2p.js.map → DropZone-7UoXQ4qL.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-B1eoCzEw.js → ElapsedCell-D2old1NF.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-B1eoCzEw.js.map → ElapsedCell-D2old1NF.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-CIOyjwjM.js → EntityTimelinePanel-m9baDiW0.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-CIOyjwjM.js.map → EntityTimelinePanel-m9baDiW0.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DQNQ7o_4.js → EscalationListSchemaPage-BPr7Ou8c.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DQNQ7o_4.js.map → EscalationListSchemaPage-BPr7Ou8c.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DFgDn4R3.js → EscalationSchemaPage-83n5JyAh.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DFgDn4R3.js.map → EscalationSchemaPage-83n5JyAh.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DfbKtXVZ.js → EscalationsOverview-CDJ5wRlq.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DfbKtXVZ.js.map → EscalationsOverview-CDJ5wRlq.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-CZPkvhao.js → EventTable-DRUHkKtv.js} +2 -2
- package/dashboard/dist/assets/{EventTable-CZPkvhao.js.map → EventTable-DRUHkKtv.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-CYjKK9Cp.js → FilterBar-C06DK5Oa.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-CYjKK9Cp.js.map → FilterBar-C06DK5Oa.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DY9u42vt.js → GraphInvokePage-DSlyTmyq.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DY9u42vt.js.map → GraphInvokePage-DSlyTmyq.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-p_CYlGnh.js → HomePage-DXzDBkQV.js} +2 -2
- package/dashboard/dist/assets/{HomePage-p_CYlGnh.js.map → HomePage-DXzDBkQV.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Dz-1RXSH.js → ListToolbar-BvpGFFYp.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Dz-1RXSH.js.map → ListToolbar-BvpGFFYp.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BUI9sVTk.js → McpOverview-C2atR_B6.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BUI9sVTk.js.map → McpOverview-C2atR_B6.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-CVN_UAB3.js → McpQueryDetailPage-BUxPspjB.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-CVN_UAB3.js.map → McpQueryDetailPage-BUxPspjB.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-CM_Fgl9G.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-DRTKSPDR.js.map → McpQueryPage-CM_Fgl9G.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-CTb1AxR3.js → McpRunDetailPage-Bo9vXQBA.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-CTb1AxR3.js.map → McpRunDetailPage-Bo9vXQBA.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BWLwjVd0.js → McpRunsPage-BwsgvGtg.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BWLwjVd0.js.map → McpRunsPage-BwsgvGtg.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-BeifzjUm.js → NamespacePill-CKp_9EaI.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-BeifzjUm.js.map → NamespacePill-CKp_9EaI.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-BftWAJ9m.js +3 -0
- package/dashboard/dist/assets/OperationsPage-BftWAJ9m.js.map +1 -0
- package/dashboard/dist/assets/{OperatorDashboard-DGs9kPOZ.js → OperatorDashboard-CKjrYYFi.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-DGs9kPOZ.js.map → OperatorDashboard-CKjrYYFi.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BpeBHqyc.js → PageHeader-CDDpHpdv.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BpeBHqyc.js.map → PageHeader-CDDpHpdv.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-JXeUFa_g.js → PageHeaderWithStats-DIWH6fRv.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-JXeUFa_g.js.map → PageHeaderWithStats-DIWH6fRv.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-C33MgXUY.js → PersonaDetailPage-BsIPtBxZ.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-C33MgXUY.js.map → PersonaDetailPage-BsIPtBxZ.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BbLOHq5X.js → PersonasPage-62hANmNf.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BbLOHq5X.js.map → PersonasPage-62hANmNf.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-zwd0HCJl.js → ProcessDetailPage-DS_t9DcR.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-zwd0HCJl.js.map → ProcessDetailPage-DS_t9DcR.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DnfmK6jf.js → ProcessesListPage-Ch2tSICc.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DnfmK6jf.js.map → ProcessesListPage-Ch2tSICc.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-axZtFPC_.js → RoleDetailPage-DVbtnTvn.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-axZtFPC_.js.map → RoleDetailPage-DVbtnTvn.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-EocCXZh0.js → RolePill-C0hExOmI.js} +2 -2
- package/dashboard/dist/assets/{RolePill-EocCXZh0.js.map → RolePill-C0hExOmI.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DN6yqH7-.js → RolesPage-CK6FjD5P.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DN6yqH7-.js.map → RolesPage-CK6FjD5P.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-ImueSaJ4.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-DrGsUhL8.js.map → RunAsSelector-ImueSaJ4.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-BmQjEyWZ.js → ScanCodesPage-CDqLJuCq.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-BmQjEyWZ.js.map → ScanCodesPage-CDqLJuCq.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-DO6qtJdM.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-DO6qtJdM.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-ID3xMhds.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-ID3xMhds.js.map +1 -0
- package/dashboard/dist/assets/{ScopeBadge-H5dEqeHi.js → ScopeBadge-BBQvz4pj.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-H5dEqeHi.js.map → ScopeBadge-BBQvz4pj.js.map} +1 -1
- package/dashboard/dist/assets/StatusBadge-BDeUwPtb.js +2 -0
- package/dashboard/dist/assets/StatusBadge-BDeUwPtb.js.map +1 -0
- package/dashboard/dist/assets/{StickyPagination-9VkHiOsT.js → StickyPagination-XA1krmz5.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-9VkHiOsT.js.map → StickyPagination-XA1krmz5.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-C37J6Qyz.js → StreamMessageDetail-DziA1g1e.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-C37J6Qyz.js.map → StreamMessageDetail-DziA1g1e.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-NVGsBIX-.js → SwimlaneTimeline-DTNEnHiF.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-NVGsBIX-.js.map → SwimlaneTimeline-DTNEnHiF.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-Ch5u6iPH.js → TagInput-BXxXs1JD.js} +2 -2
- package/dashboard/dist/assets/{TagInput-Ch5u6iPH.js.map → TagInput-BXxXs1JD.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-5sbMHi5U.js → TaskDetailPage-U19sJHAI.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-5sbMHi5U.js.map → TaskDetailPage-U19sJHAI.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-Bz146p-P.js → TaskQueuePill-BKGJBVZG.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-Bz146p-P.js.map → TaskQueuePill-BKGJBVZG.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-C9AN7IBb.js → TasksListPage-jc4Xk7kI.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-C9AN7IBb.js.map → TasksListPage-jc4Xk7kI.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CsbQGlSd.js → TimeAgo-GWgJ0LVq.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CsbQGlSd.js.map → TimeAgo-GWgJ0LVq.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DlbIkV-G.js → TimestampCell-Dk1TVsFV.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DlbIkV-G.js.map → TimestampCell-Dk1TVsFV.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-sj8OkBB0.js → ToolPill-BY6zLSfA.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-sj8OkBB0.js.map → ToolPill-BY6zLSfA.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-BKbLocvr.js → ToolTestPanel-BKcqnR68.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-BKbLocvr.js.map → ToolTestPanel-BKcqnR68.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-fOnTfDso.js → TopicDetailPage-D8GcDu_0.js} +4 -4
- package/dashboard/dist/assets/{TopicDetailPage-fOnTfDso.js.map → TopicDetailPage-D8GcDu_0.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BoVkp7DM.js → TopicsPage-BT9LV3yH.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BoVkp7DM.js.map → TopicsPage-BT9LV3yH.js.map} +1 -1
- package/dashboard/dist/assets/UserName-BrwZnLjU.js +2 -0
- package/dashboard/dist/assets/{UserName-0gjVPU_U.js.map → UserName-BrwZnLjU.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-CldfHwky.js +2 -0
- package/dashboard/dist/assets/WorkflowExecutionPage-CldfHwky.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowPill-BcA7S3gI.js → WorkflowPill-qp5UF3-y.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-BcA7S3gI.js.map → WorkflowPill-qp5UF3-y.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-Bzvz6tTY.js → WorkflowsDashboard-DkyGkxW1.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-Bzvz6tTY.js.map → WorkflowsDashboard-DkyGkxW1.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BkcRU4Ej.js → WorkflowsOverview-DACADuUE.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BkcRU4Ej.js.map → WorkflowsOverview-DACADuUE.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CmM78sYi.js → YamlWorkflowDetailPage-DSAjzido.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CmM78sYi.js.map → YamlWorkflowDetailPage-DSAjzido.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-Dp6vG1au.js → YamlWorkflowsPage-CqoSFz5B.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-Dp6vG1au.js.map → YamlWorkflowsPage-CqoSFz5B.js.map} +1 -1
- package/dashboard/dist/assets/{agents-MeqzOPD6.js → agents-Cg_e-aaf.js} +2 -2
- package/dashboard/dist/assets/{agents-MeqzOPD6.js.map → agents-Cg_e-aaf.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DTGXnvX_.js → bots-B047yNJ0.js} +2 -2
- package/dashboard/dist/assets/{bots-DTGXnvX_.js.map → bots-B047yNJ0.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-BjlARR7F.js → capabilities-CI1dbCDk.js} +2 -2
- package/dashboard/dist/assets/{capabilities-BjlARR7F.js.map → capabilities-CI1dbCDk.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DMYI0OaL.js → controlplane-Cy7snw7f.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DMYI0OaL.js.map → controlplane-Cy7snw7f.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BMO_H3cb.js → escalation-columns-BNrONMYj.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BMO_H3cb.js.map → escalation-columns-BNrONMYj.js.map} +1 -1
- package/dashboard/dist/assets/index-B6Grf1WQ.js +6 -0
- package/dashboard/dist/assets/index-B6Grf1WQ.js.map +1 -0
- package/dashboard/dist/assets/{index-D3iDAWK2.js → index-Bf3hVGXZ.js} +2 -2
- package/dashboard/dist/assets/{index-D3iDAWK2.js.map → index-Bf3hVGXZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-D6kXz3H8.js → index-Bxd2sXqz.js} +2 -2
- package/dashboard/dist/assets/{index-D6kXz3H8.js.map → index-Bxd2sXqz.js.map} +1 -1
- package/dashboard/dist/assets/index-CJV2pWNH.css +1 -0
- package/dashboard/dist/assets/{index-CGCD5hTX.js → index-COKZW8Xx.js} +2 -2
- package/dashboard/dist/assets/{index-CGCD5hTX.js.map → index-COKZW8Xx.js.map} +1 -1
- package/dashboard/dist/assets/{index-k5vcLICm.js → index-C_y0lQ_o.js} +3 -3
- package/dashboard/dist/assets/{index-k5vcLICm.js.map → index-C_y0lQ_o.js.map} +1 -1
- package/dashboard/dist/assets/{index-3QEnMBNG.js → index-DAUV3eJ-.js} +2 -2
- package/dashboard/dist/assets/{index-3QEnMBNG.js.map → index-DAUV3eJ-.js.map} +1 -1
- package/dashboard/dist/assets/{index-DuhqzYwC.js → index-DVtIMrTb.js} +2 -2
- package/dashboard/dist/assets/{index-DuhqzYwC.js.map → index-DVtIMrTb.js.map} +1 -1
- package/dashboard/dist/assets/index-Ds5rGe-i.js +3 -0
- package/dashboard/dist/assets/index-Ds5rGe-i.js.map +1 -0
- package/dashboard/dist/assets/{index-B3FzpDEG.js → index-DyTb77Jb.js} +2 -2
- package/dashboard/dist/assets/{index-B3FzpDEG.js.map → index-DyTb77Jb.js.map} +1 -1
- package/dashboard/dist/assets/{index-Ch-OS1pk.js → index-Uk6N1qiH.js} +2 -2
- package/dashboard/dist/assets/{index-Ch-OS1pk.js.map → index-Uk6N1qiH.js.map} +1 -1
- package/dashboard/dist/assets/index-X3_AxcUk.js +2 -0
- package/dashboard/dist/assets/{index-Dsgqxdyh.js.map → index-X3_AxcUk.js.map} +1 -1
- package/dashboard/dist/assets/{index-BU4oujVO.js → index-lGfBW1PB.js} +29 -28
- package/dashboard/dist/assets/index-lGfBW1PB.js.map +1 -0
- package/dashboard/dist/assets/{index-CkkOh8y9.js → index-nUmEwQrg.js} +2 -2
- package/dashboard/dist/assets/{index-CkkOh8y9.js.map → index-nUmEwQrg.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-DAV1Jy7b.js → knowledge-DsIUzscY.js} +2 -2
- package/dashboard/dist/assets/{knowledge-DAV1Jy7b.js.map → knowledge-DsIUzscY.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CivbxL1P.js → mcp-D889kZ-c.js} +2 -2
- package/dashboard/dist/assets/{mcp-CivbxL1P.js.map → mcp-D889kZ-c.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-CGvWNrgo.js → mcp-query-Cs9J2pVT.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-CGvWNrgo.js.map → mcp-query-Cs9J2pVT.js.map} +1 -1
- package/dashboard/dist/assets/metadata-display-DHjqWkLG.js +2 -0
- package/dashboard/dist/assets/metadata-display-DHjqWkLG.js.map +1 -0
- package/dashboard/dist/assets/{personas-lI3aUr6t.js → personas-xHB16O-Q.js} +2 -2
- package/dashboard/dist/assets/{personas-lI3aUr6t.js.map → personas-xHB16O-Q.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-DjPfnTmx.js → pipelines-DnTPjw1v.js} +2 -2
- package/dashboard/dist/assets/{pipelines-DjPfnTmx.js.map → pipelines-DnTPjw1v.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-Co_S55BO.js → tasks-BcDvp6dL.js} +2 -2
- package/dashboard/dist/assets/{tasks-Co_S55BO.js.map → tasks-BcDvp6dL.js.map} +1 -1
- package/dashboard/dist/assets/{topics-2IGhZXBi.js → topics-DXw6BNy5.js} +2 -2
- package/dashboard/dist/assets/{topics-2IGhZXBi.js.map → topics-DXw6BNy5.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-D0C5yke4.js → useEventHooks-C-bsD8zP.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-D0C5yke4.js.map → useEventHooks-C-bsD8zP.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-LG52DTT-.js → useNamespace-wZCsEF6O.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-LG52DTT-.js.map → useNamespace-wZCsEF6O.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-1IZGVpWC.js → useYamlActivityEvents-Cu_o4-ow.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-1IZGVpWC.js.map → useYamlActivityEvents-Cu_o4-ow.js.map} +1 -1
- package/dashboard/dist/assets/{users-C-eHT1i6.js → users-XpCq_umD.js} +2 -2
- package/dashboard/dist/assets/{users-C-eHT1i6.js.map → users-XpCq_umD.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-BPsNpK3Y.js → vendor-icons-BgsXTN4h.js} +145 -140
- package/dashboard/dist/assets/vendor-icons-BgsXTN4h.js.map +1 -0
- package/dashboard/dist/assets/{workflows-C16CeY4e.js → workflows-CMxHVqQ8.js} +2 -2
- package/dashboard/dist/assets/{workflows-C16CeY4e.js.map → workflows-CMxHVqQ8.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BBenayT9.js → yaml-workflows-kxOF5yEC.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BBenayT9.js.map → yaml-workflows-kxOF5yEC.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +34 -1
- package/docs/dashboard.md +2 -0
- package/docs/events.md +1 -1
- package/docs/hitl/iframe.md +56 -6
- package/docs/hitl/x-lt-footer.md +6 -0
- package/docs/hitl/x-lt-list-schema.md +4 -2
- package/package.json +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-DDsmXjpi.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-DDsmXjpi.js.map +0 -1
- package/dashboard/dist/assets/BotPicker-dUpw1wW6.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-Ca2jEln-.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-rnoWmFqx.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-rnoWmFqx.js.map +0 -1
- package/dashboard/dist/assets/CustomDurationPicker-hlnadaFt.js +0 -2
- package/dashboard/dist/assets/CustomDurationPicker-hlnadaFt.js.map +0 -1
- package/dashboard/dist/assets/DataTable-Bir0Xs1p.js.map +0 -1
- package/dashboard/dist/assets/McpQueryPage-DRTKSPDR.js +0 -2
- package/dashboard/dist/assets/OperationsPage-BSl_oUAJ.js +0 -3
- package/dashboard/dist/assets/OperationsPage-BSl_oUAJ.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-DrGsUhL8.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-VODehqGs.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-VODehqGs.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-Y-9Gs7t5.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-Y-9Gs7t5.js.map +0 -1
- package/dashboard/dist/assets/StatusBadge-DkgllZHv.js +0 -2
- package/dashboard/dist/assets/StatusBadge-DkgllZHv.js.map +0 -1
- package/dashboard/dist/assets/UserName-0gjVPU_U.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-B28OxTS_.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-B28OxTS_.js.map +0 -1
- package/dashboard/dist/assets/index-B5jxf81r.css +0 -1
- package/dashboard/dist/assets/index-BU4oujVO.js.map +0 -1
- package/dashboard/dist/assets/index-Dsgqxdyh.js +0 -2
- package/dashboard/dist/assets/index-DuyzcDuV.js +0 -6
- package/dashboard/dist/assets/index-DuyzcDuV.js.map +0 -1
- package/dashboard/dist/assets/index-LF1gEc6w.js +0 -3
- package/dashboard/dist/assets/index-LF1gEc6w.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-BPsNpK3Y.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Ch-OS1pk.js","sources":["../../src/hooks/useExpandedRows.ts","../../src/pages/mcp/servers/helpers.ts","../../src/pages/mcp/servers/ServerRow.tsx","../../src/pages/mcp/servers/McpServersPage.tsx"],"sourcesContent":["import { useState, useCallback } from 'react';\n\n/**\n * Track expanded row IDs with localStorage persistence.\n *\n * Resilient: if a stored ID no longer exists in the data, it's silently ignored.\n * Never blocks rendering — reads from localStorage synchronously on mount,\n * writes asynchronously on change.\n */\nexport function useExpandedRows(storageKey: string): {\n expandedIds: Set<string>;\n toggle: (id: string) => void;\n isExpanded: (id: string) => boolean;\n} {\n const [expandedIds, setExpandedIds] = useState<Set<string>>(() => {\n try {\n const raw = localStorage.getItem(storageKey);\n if (raw) {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return new Set(parsed);\n }\n } catch { /* corrupted or unavailable — start empty */ }\n return new Set();\n });\n\n const persist = useCallback((next: Set<string>) => {\n try {\n localStorage.setItem(storageKey, JSON.stringify([...next]));\n } catch { /* quota exceeded or unavailable — ignore */ }\n }, [storageKey]);\n\n const toggle = useCallback((id: string) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n persist(next);\n return next;\n });\n }, [persist]);\n\n const isExpanded = useCallback((id: string) => expandedIds.has(id), [expandedIds]);\n\n return { expandedIds, toggle, isExpanded };\n}\n","import type { McpServerRecord, McpToolManifest } from '../../../api/types';\n\nexport function isBuiltIn(row: McpServerRecord): boolean {\n return !!(row.metadata as Record<string, unknown> | null)?.builtin\n || !!(row.transport_config as Record<string, unknown> | null)?.builtin;\n}\n\n/** Check if a server or any of its tools match the search term */\nexport function matchesSearch(server: McpServerRecord, search: string): boolean {\n if (!search) return true;\n const q = search.toLowerCase();\n if (server.name.toLowerCase().includes(q)) return true;\n if (server.description?.toLowerCase().includes(q)) return true;\n if ((server.tags ?? []).some((t) => t.toLowerCase().includes(q))) return true;\n const tools = (server.tool_manifest ?? []) as McpToolManifest[];\n return tools.some(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n}\n\n/** Filter tools within a server that match the search term */\nexport function filterTools(tools: McpToolManifest[], search: string): McpToolManifest[] {\n if (!search) return tools;\n const q = search.toLowerCase();\n return tools.filter(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n}\n","import { ChevronRight, Pencil, Trash2, Plug, Unplug, Play } from 'lucide-react';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport {\n useConnectMcpServer,\n useDisconnectMcpServer,\n} from '../../../api/mcp';\nimport { StatusBadge } from '../../../components/common/display/StatusBadge';\nimport { ToolPill } from '../../../components/common/display/ToolPill';\nimport { ServerName } from '../../../components/common/display/ServerName';\n\nimport type { McpServerRecord, McpToolManifest } from '../../../api/types';\nimport { isBuiltIn } from './helpers';\n\nexport function ServerRow({\n server,\n expanded,\n onToggle,\n onEdit,\n onDelete,\n onTryTool,\n connect,\n disconnect,\n visibleTools,\n}: {\n server: McpServerRecord;\n expanded: boolean;\n onToggle: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onTryTool: (tool: McpToolManifest) => void;\n connect: ReturnType<typeof useConnectMcpServer>;\n disconnect: ReturnType<typeof useDisconnectMcpServer>;\n visibleTools: McpToolManifest[];\n}) {\n const allTools = (server.tool_manifest ?? []) as McpToolManifest[];\n const builtin = isBuiltIn(server);\n const tags = server.tags ?? [];\n\n return (\n <>\n {/* Server header row */}\n <tr\n onClick={allTools.length > 0 ? onToggle : undefined}\n className={`group/row border-b border-surface-border/50 transition-colors duration-100 ${\n allTools.length > 0 ? 'cursor-pointer row-hover' : ''\n }`}\n >\n {/* Name + tags */}\n <td className=\"px-6 py-2.5\">\n <div className=\"flex items-center gap-3\">\n <span className={`transition-transform duration-150 ${expanded ? 'rotate-90' : ''} ${allTools.length === 0 ? 'opacity-0' : 'text-text-tertiary'}`}>\n <ChevronRight size={14} />\n </span>\n <span className=\"flex items-center gap-1.5\">\n <ServerName name={server.name} serverId={server.id} short={false} />\n {allTools.length > 0 && (\n <sup className=\"text-2xs font-normal text-accent/70\">{allTools.length}</sup>\n )}\n </span>\n {tags.length > 0 && (\n <div className=\"flex gap-1 ml-auto shrink-0\">\n {tags.slice(0, 3).map((tag) => (\n <span key={tag} className=\"inline-block px-1.5 py-0 text-2xs text-text-tertiary bg-surface-sunken rounded\">\n {tag}\n </span>\n ))}\n {tags.length > 3 && (\n <span className=\"text-2xs text-text-quaternary\" title={tags.slice(3).join(', ')}>…</span>\n )}\n </div>\n )}\n </div>\n </td>\n\n {/* Status */}\n <td className=\"px-4 py-2.5 w-28 whitespace-nowrap\">\n <StatusBadge status={server.status} />\n </td>\n\n {/* Actions */}\n <td className=\"px-4 py-2.5 w-16\">\n <RowActionGroup>\n {!builtin && (\n server.status === 'connected' ? (\n <RowAction\n icon={Unplug}\n title=\"Disconnect server\"\n onClick={() => disconnect.mutate(server.id)}\n />\n ) : (\n <RowAction\n icon={Plug}\n title=\"Connect server\"\n onClick={() => connect.mutate(server.id)}\n colorClass=\"text-text-tertiary hover:text-status-success\"\n />\n )\n )}\n <RowAction\n icon={Pencil}\n title=\"Edit server\"\n onClick={onEdit}\n />\n {!builtin && (\n <RowAction\n icon={Trash2}\n title=\"Delete server\"\n onClick={onDelete}\n colorClass=\"text-text-tertiary hover:text-status-error\"\n />\n )}\n </RowActionGroup>\n </td>\n </tr>\n\n {/* Expanded tool rows — real table rows for column alignment */}\n {expanded && visibleTools.map((tool) => (\n <tr\n key={tool.name}\n onClick={() => onTryTool(tool)}\n className=\"group/row cursor-pointer hover:bg-surface-hover/50 transition-colors border-b border-surface-border/15\"\n >\n {/* Tool name + description */}\n <td className=\"pl-14 pr-6 py-2.5\">\n <ToolPill name={tool.name} size=\"md\" />\n {tool.description && (\n <p className=\"text-2xs leading-snug text-text-quaternary mt-0.5\">{tool.description}</p>\n )}\n </td>\n\n {/* Status — empty for tools */}\n <td className=\"px-4 py-2.5 w-28\" />\n\n {/* Actions — play on hover */}\n <td className=\"px-4 py-2.5 w-16\">\n <div className=\"flex items-center justify-end\">\n <button\n onClick={(e) => { e.stopPropagation(); onTryTool(tool); }}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-accent\"\n title=\"Try tool\"\n >\n <Play className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n </button>\n </div>\n </td>\n </tr>\n ))}\n </>\n );\n}\n","import { useState, useMemo, useEffect } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n useMcpServers,\n useConnectMcpServer,\n useDisconnectMcpServer,\n useDeleteMcpServer,\n} from '../../../api/mcp';\nimport { EmptyState } from '../../../components/common/display/EmptyState';\nimport { ConfirmDeleteModal } from '../../../components/common/modal/ConfirmDeleteModal';\nimport type { McpServerRecord, McpToolManifest } from '../../../api/types';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useExpandedRows } from '../../../hooks/useExpandedRows';\nimport { ToolTestPanel } from '../../../components/common/test/ToolTestPanel';\nimport { matchesSearch, filterTools } from './helpers';\nimport { ServerRow } from './ServerRow';\n\nexport function McpServersPage() {\n const navigate = useNavigate();\n const { filters, setFilter, pagination } = useFilterParams({\n filters: { status: '', search: '', tag: '' },\n });\n\n const { data, isLoading } = useMcpServers({\n status: filters.status || undefined,\n search: filters.search || undefined,\n tags: filters.tag || undefined,\n });\n const connect = useConnectMcpServer();\n const disconnect = useDisconnectMcpServer();\n const deleteServer = useDeleteMcpServer();\n\n const [confirmDelete, setConfirmDelete] = useState<McpServerRecord | null>(null);\n const { expandedIds, toggle: toggleExpand } = useExpandedRows('lt:expanded:mcp-servers');\n const [tryTool, setTryTool] = useState<{\n serverId: string;\n serverName: string;\n tool: McpToolManifest;\n } | null>(null);\n\n const servers = data?.servers ?? [];\n const total = data?.total ?? 0;\n\n // Derive unique tags from current result set for the filter dropdown\n const tagOptions = useMemo(() => {\n const allTags = new Set<string>();\n for (const s of servers) {\n for (const t of s.tags ?? []) allTags.add(t);\n }\n return [...allTags].sort().map((t) => ({ value: t, label: t }));\n }, [servers]);\n\n // Client-side search filtering for tool-level matches within expanded rows\n const filteredServers = useMemo(() => {\n if (!filters.search) return servers;\n return servers.filter((s) => matchesSearch(s, filters.search));\n }, [servers, filters.search]);\n\n // Auto-expand servers whose tools match the search (so results are visible)\n useEffect(() => {\n if (!filters.search) return;\n const q = filters.search.toLowerCase();\n for (const s of filteredServers) {\n const tools = (s.tool_manifest ?? []) as McpToolManifest[];\n const hasToolMatch = tools.some(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n if (hasToolMatch && !expandedIds.has(s.id)) {\n toggleExpand(s.id);\n }\n }\n }, [filters.search, filteredServers]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleDelete = () => {\n if (!confirmDelete) return;\n deleteServer.mutate(confirmDelete.id, {\n onSuccess: () => setConfirmDelete(null),\n });\n };\n\n if (isLoading) {\n return (\n <div>\n <PageHeader title=\"Servers & Tools\" />\n <div className=\"animate-pulse space-y-0\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-14 border-b last:border-b-0 px-6 flex items-center\">\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div>\n <PageHeader\n title=\"Servers & Tools\"\n docsHash=\"#docs:dashboard.md:mcp-server-tools\"\n actions={\n <button\n onClick={() => navigate('/mcp/servers/new')}\n className=\"btn-primary text-xs\"\n >\n Register Server\n </button>\n }\n />\n\n <p className=\"text-sm text-text-secondary mb-6 max-w-2xl leading-relaxed\">\n Registered MCP servers and their available tools. Each server exposes tools that can be used by the MCP Tool Designer.\n </p>\n\n <FilterBar>\n <FilterInput\n label=\"Search\"\n value={filters.search}\n onChange={(v) => setFilter('search', v)}\n placeholder=\"Server or tool name...\"\n />\n <FilterSelect\n label=\"Tag\"\n value={filters.tag}\n onChange={(v) => setFilter('tag', v)}\n options={tagOptions}\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={[\n { value: 'registered', label: 'Registered' },\n { value: 'connected', label: 'Connected' },\n { value: 'error', label: 'Error' },\n { value: 'disconnected', label: 'Disconnected' },\n ]}\n />\n </FilterBar>\n\n <div className={`flex gap-0 ${tryTool ? '' : ''}`}>\n {/* Server list */}\n <div className={`${tryTool ? 'flex-1 min-w-0' : 'w-full'} transition-all`}>\n {filteredServers.length === 0 ? (\n <EmptyState title=\"No servers found\" />\n ) : (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"sticky top-[2.75rem] z-10 bg-surface px-6 py-3 text-left text-2xs font-semibold uppercase tracking-widest text-text-tertiary\">\n Server / Tool\n </th>\n <th className=\"sticky top-[2.75rem] z-10 bg-surface px-4 py-3 text-left text-2xs font-semibold uppercase tracking-widest text-text-tertiary w-28\">\n Status\n </th>\n <th className=\"sticky top-[2.75rem] z-10 bg-surface w-16\" />\n </tr>\n </thead>\n <tbody>\n {filteredServers.map((server) => (\n <ServerRow\n key={server.id}\n server={server}\n expanded={expandedIds.has(server.id)}\n onToggle={() => toggleExpand(server.id)}\n onEdit={() => navigate(`/mcp/servers/${server.id}`)}\n onDelete={() => setConfirmDelete(server)}\n onTryTool={(tool) =>\n setTryTool({\n serverId: server.id,\n serverName: server.name,\n tool,\n })\n }\n connect={connect}\n disconnect={disconnect}\n visibleTools={filterTools(\n (server.tool_manifest ?? []) as McpToolManifest[],\n filters.search,\n )}\n />\n ))}\n </tbody>\n </table>\n )}\n\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Test panel — slides in from right */}\n {tryTool && (\n <div className=\"w-[380px] shrink-0 sticky top-0 max-h-screen overflow-y-auto\">\n <ToolTestPanel\n serverId={tryTool.serverId}\n serverName={tryTool.serverName}\n tool={tryTool.tool}\n onClose={() => setTryTool(null)}\n />\n </div>\n )}\n </div>\n\n {/* Delete confirmation modal */}\n <ConfirmDeleteModal\n open={!!confirmDelete}\n onClose={() => setConfirmDelete(null)}\n onConfirm={handleDelete}\n title=\"Delete MCP Server\"\n description={\n <>\n Delete{' '}\n <span className=\"font-medium text-text-primary\">{confirmDelete?.name}</span>?\n This will remove the server registration.\n </>\n }\n isPending={deleteServer.isPending}\n error={deleteServer.error as Error | null}\n />\n </div>\n );\n}\n"],"names":["useExpandedRows","storageKey","expandedIds","setExpandedIds","useState","raw","parsed","persist","useCallback","next","toggle","id","prev","isExpanded","isBuiltIn","row","_a","_b","matchesSearch","server","search","q","t","filterTools","tools","ServerRow","expanded","onToggle","onEdit","onDelete","onTryTool","connect","disconnect","visibleTools","allTools","builtin","tags","jsxs","Fragment","jsx","ChevronRight","ServerName","tag","StatusBadge","RowActionGroup","RowAction","Unplug","Plug","Pencil","Trash2","tool","ToolPill","e","Play","McpServersPage","navigate","useNavigate","filters","setFilter","pagination","useFilterParams","data","isLoading","useMcpServers","useConnectMcpServer","useDisconnectMcpServer","deleteServer","useDeleteMcpServer","confirmDelete","setConfirmDelete","toggleExpand","tryTool","setTryTool","servers","total","tagOptions","useMemo","allTags","s","filteredServers","useEffect","handleDelete","PageHeader","_","i","FilterBar","FilterInput","v","FilterSelect","EmptyState","StickyPagination","ToolTestPanel","ConfirmDeleteModal"],"mappings":"u5BASO,SAASA,EAAgBC,EAI9B,CACA,KAAM,CAACC,EAAaC,CAAc,EAAIC,EAAAA,SAAsB,IAAM,CAChE,GAAI,CACF,MAAMC,EAAM,aAAa,QAAQJ,CAAU,EAC3C,GAAII,EAAK,CACP,MAAMC,EAAS,KAAK,MAAMD,CAAG,EAC7B,GAAI,MAAM,QAAQC,CAAM,EAAG,OAAO,IAAI,IAAIA,CAAM,CAClD,CACF,MAAQ,CAA+C,CACvD,WAAW,GACb,CAAC,EAEKC,EAAUC,cAAaC,GAAsB,CACjD,GAAI,CACF,aAAa,QAAQR,EAAY,KAAK,UAAU,CAAC,GAAGQ,CAAI,CAAC,CAAC,CAC5D,MAAQ,CAA+C,CACzD,EAAG,CAACR,CAAU,CAAC,EAETS,EAASF,cAAaG,GAAe,CACzCR,EAAgBS,GAAS,CACvB,MAAMH,EAAO,IAAI,IAAIG,CAAI,EACzB,OAAIH,EAAK,IAAIE,CAAE,EACbF,EAAK,OAAOE,CAAE,EAEdF,EAAK,IAAIE,CAAE,EAEbJ,EAAQE,CAAI,EACLA,CACT,CAAC,CACH,EAAG,CAACF,CAAO,CAAC,EAENM,EAAaL,cAAaG,GAAeT,EAAY,IAAIS,CAAE,EAAG,CAACT,CAAW,CAAC,EAEjF,MAAO,CAAE,YAAAA,EAAa,OAAAQ,EAAQ,WAAAG,CAAA,CAChC,CC7CO,SAASC,EAAUC,EAA+B,SACvD,MAAO,CAAC,GAAEC,EAAAD,EAAI,WAAJ,MAAAC,EAAiD,UACtD,CAAC,GAAEC,EAAAF,EAAI,mBAAJ,MAAAE,EAAyD,QACnE,CAGO,SAASC,GAAcC,EAAyBC,EAAyB,OAC9E,GAAI,CAACA,EAAQ,MAAO,GACpB,MAAMC,EAAID,EAAO,YAAA,EAGjB,OAFID,EAAO,KAAK,YAAA,EAAc,SAASE,CAAC,IACpCL,EAAAG,EAAO,cAAP,MAAAH,EAAoB,cAAc,SAASK,KAC1CF,EAAO,MAAQ,CAAA,GAAI,KAAMG,GAAMA,EAAE,YAAA,EAAc,SAASD,CAAC,CAAC,EAAU,IAC1DF,EAAO,eAAiB,CAAA,GAC1B,KACVG,GAAA,OAAM,OAAAA,EAAE,KAAK,cAAc,SAASD,CAAC,KAAKL,EAAAM,EAAE,cAAF,YAAAN,EAAe,cAAc,SAASK,IAAC,CAEtF,CAGO,SAASE,GAAYC,EAA0BJ,EAAmC,CACvF,GAAI,CAACA,EAAQ,OAAOI,EACpB,MAAMH,EAAID,EAAO,YAAA,EACjB,OAAOI,EAAM,OACVF,GAAA,OAAM,OAAAA,EAAE,KAAK,cAAc,SAASD,CAAC,KAAKL,EAAAM,EAAE,cAAF,YAAAN,EAAe,cAAc,SAASK,IAAC,CAEtF,CCdO,SAASI,GAAU,CACxB,OAAAN,EACA,SAAAO,EACA,SAAAC,EACA,OAAAC,EACA,SAAAC,EACA,UAAAC,EACA,QAAAC,EACA,WAAAC,EACA,aAAAC,CACF,EAUG,CACD,MAAMC,EAAYf,EAAO,eAAiB,CAAA,EACpCgB,EAAUrB,EAAUK,CAAM,EAC1BiB,EAAOjB,EAAO,MAAQ,CAAA,EAE5B,OACEkB,EAAAA,KAAAC,WAAA,CAEE,SAAA,CAAAD,EAAAA,KAAC,KAAA,CACC,QAASH,EAAS,OAAS,EAAIP,EAAW,OAC1C,UAAW,8EACTO,EAAS,OAAS,EAAI,2BAA6B,EACrD,GAGA,SAAA,CAAAK,EAAAA,IAAC,MAAG,UAAU,cACZ,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAE,MAAC,QAAK,UAAW,qCAAqCb,EAAW,YAAc,EAAE,IAAIQ,EAAS,SAAW,EAAI,YAAc,oBAAoB,GAC7I,eAACM,EAAA,CAAa,KAAM,GAAI,EAC1B,EACAH,EAAAA,KAAC,OAAA,CAAK,UAAU,4BACd,SAAA,CAAAE,EAAAA,IAACE,EAAA,CAAW,KAAMtB,EAAO,KAAM,SAAUA,EAAO,GAAI,MAAO,EAAA,CAAO,EACjEe,EAAS,OAAS,GACjBK,EAAAA,IAAC,OAAI,UAAU,sCAAuC,WAAS,MAAA,CAAO,CAAA,EAE1E,EACCH,EAAK,OAAS,GACbC,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACZ,SAAA,CAAAD,EAAK,MAAM,EAAG,CAAC,EAAE,IAAKM,GACrBH,EAAAA,IAAC,OAAA,CAAe,UAAU,iFACvB,SAAAG,CAAA,EADQA,CAEX,CACD,EACAN,EAAK,OAAS,GACbG,EAAAA,IAAC,QAAK,UAAU,gCAAgC,MAAOH,EAAK,MAAM,CAAC,EAAE,KAAK,IAAI,EAAG,SAAA,GAAA,CAAQ,CAAA,CAAA,CAE7F,CAAA,CAAA,CAEJ,CAAA,CACF,EAGAG,EAAAA,IAAC,MAAG,UAAU,qCACZ,eAACI,EAAA,CAAY,OAAQxB,EAAO,MAAA,CAAQ,CAAA,CACtC,EAGAoB,MAAC,KAAA,CAAG,UAAU,mBACZ,gBAACK,EAAA,CACE,SAAA,CAAA,CAACT,IACAhB,EAAO,SAAW,YAChBoB,EAAAA,IAACM,EAAA,CACC,KAAMC,EACN,MAAM,oBACN,QAAS,IAAMd,EAAW,OAAOb,EAAO,EAAE,CAAA,CAAA,EAG5CoB,EAAAA,IAACM,EAAA,CACC,KAAME,EACN,MAAM,iBACN,QAAS,IAAMhB,EAAQ,OAAOZ,EAAO,EAAE,EACvC,WAAW,8CAAA,CAAA,GAIjBoB,EAAAA,IAACM,EAAA,CACC,KAAMG,EACN,MAAM,cACN,QAASpB,CAAA,CAAA,EAEV,CAACO,GACAI,EAAAA,IAACM,EAAA,CACC,KAAMI,EACN,MAAM,gBACN,QAASpB,EACT,WAAW,4CAAA,CAAA,CACb,CAAA,CAEJ,CAAA,CACF,CAAA,CAAA,CAAA,EAIDH,GAAYO,EAAa,IAAKiB,GAC7Bb,EAAAA,KAAC,KAAA,CAEC,QAAS,IAAMP,EAAUoB,CAAI,EAC7B,UAAU,yGAGV,SAAA,CAAAb,EAAAA,KAAC,KAAA,CAAG,UAAU,oBACZ,SAAA,CAAAE,EAAAA,IAACY,EAAA,CAAS,KAAMD,EAAK,KAAM,KAAK,KAAK,EACpCA,EAAK,aACJX,EAAAA,IAAC,KAAE,UAAU,oDAAqD,WAAK,WAAA,CAAY,CAAA,EAEvF,EAGAA,EAAAA,IAAC,KAAA,CAAG,UAAU,kBAAA,CAAmB,QAGhC,KAAA,CAAG,UAAU,mBACZ,SAAAA,MAAC,MAAA,CAAI,UAAU,gCACb,SAAAA,EAAAA,IAAC,SAAA,CACC,QAAUa,GAAM,CAAEA,EAAE,gBAAA,EAAmBtB,EAAUoB,CAAI,CAAG,EACxD,UAAU,gGACV,MAAM,WAEN,SAAAX,EAAAA,IAACc,EAAA,CAAK,UAAU,cAAc,YAAa,GAAA,CAAK,CAAA,CAAA,EAEpD,CAAA,CACF,CAAA,CAAA,EA1BKH,EAAK,IAAA,CA4Bb,CAAA,EACH,CAEJ,CCjIO,SAASI,IAAiB,CAC/B,MAAMC,EAAWC,EAAA,EACX,CAAE,QAAAC,EAAS,UAAAC,EAAW,WAAAC,CAAA,EAAeC,EAAgB,CACzD,QAAS,CAAE,OAAQ,GAAI,OAAQ,GAAI,IAAK,EAAA,CAAG,CAC5C,EAEK,CAAE,KAAAC,EAAM,UAAAC,CAAA,EAAcC,EAAc,CACxC,OAAQN,EAAQ,QAAU,OAC1B,OAAQA,EAAQ,QAAU,OAC1B,KAAMA,EAAQ,KAAO,MAAA,CACtB,EACK1B,EAAUiC,EAAA,EACVhC,EAAaiC,EAAA,EACbC,EAAeC,EAAA,EAEf,CAACC,EAAeC,CAAgB,EAAIjE,EAAAA,SAAiC,IAAI,EACzE,CAAE,YAAAF,EAAa,OAAQoE,CAAA,EAAiBtE,EAAgB,yBAAyB,EACjF,CAACuE,EAASC,CAAU,EAAIpE,EAAAA,SAIpB,IAAI,EAERqE,GAAUZ,GAAA,YAAAA,EAAM,UAAW,CAAA,EAC3Ba,GAAQb,GAAA,YAAAA,EAAM,QAAS,EAGvBc,EAAaC,EAAAA,QAAQ,IAAM,CAC/B,MAAMC,MAAc,IACpB,UAAWC,KAAKL,EACd,UAAWnD,KAAKwD,EAAE,MAAQ,CAAA,EAAID,EAAQ,IAAIvD,CAAC,EAE7C,MAAO,CAAC,GAAGuD,CAAO,EAAE,OAAO,IAAKvD,IAAO,CAAE,MAAOA,EAAG,MAAOA,GAAI,CAChE,EAAG,CAACmD,CAAO,CAAC,EAGNM,EAAkBH,EAAAA,QAAQ,IACzBnB,EAAQ,OACNgB,EAAQ,OAAQK,GAAM5D,GAAc4D,EAAGrB,EAAQ,MAAM,CAAC,EADjCgB,EAE3B,CAACA,EAAShB,EAAQ,MAAM,CAAC,EAG5BuB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACvB,EAAQ,OAAQ,OACrB,MAAMpC,EAAIoC,EAAQ,OAAO,YAAA,EACzB,UAAWqB,KAAKC,GACCD,EAAE,eAAiB,CAAA,GACP,KACxBxD,GAAA,OAAM,OAAAA,EAAE,KAAK,cAAc,SAASD,CAAC,KAAKL,EAAAM,EAAE,cAAF,YAAAN,EAAe,cAAc,SAASK,IAAC,GAEhE,CAACnB,EAAY,IAAI4E,EAAE,EAAE,GACvCR,EAAaQ,EAAE,EAAE,CAGvB,EAAG,CAACrB,EAAQ,OAAQsB,CAAe,CAAC,EAEpC,MAAME,EAAe,IAAM,CACpBb,GACLF,EAAa,OAAOE,EAAc,GAAI,CACpC,UAAW,IAAMC,EAAiB,IAAI,CAAA,CACvC,CACH,EAEA,OAAIP,SAEC,MAAA,CACC,SAAA,CAAAvB,EAAAA,IAAC2C,EAAA,CAAW,MAAM,iBAAA,CAAkB,EACpC3C,EAAAA,IAAC,MAAA,CAAI,UAAU,0BACZ,SAAA,MAAM,KAAK,CAAE,OAAQ,CAAA,CAAG,EAAE,IAAI,CAAC4C,EAAGC,IACjC7C,EAAAA,IAAC,MAAA,CAAY,UAAU,uDACrB,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,sCAAA,CAAuC,CAAA,EAD9C6C,CAEV,CACD,CAAA,CACH,CAAA,EACF,SAKD,MAAA,CACC,SAAA,CAAA7C,EAAAA,IAAC2C,EAAA,CACC,MAAM,kBACN,SAAS,sCACT,QACE3C,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMgB,EAAS,kBAAkB,EAC1C,UAAU,sBACX,SAAA,iBAAA,CAAA,CAED,CAAA,EAIJhB,EAAAA,IAAC,IAAA,CAAE,UAAU,6DAA6D,SAAA,yHAE1E,SAEC8C,EAAA,CACC,SAAA,CAAA9C,EAAAA,IAAC+C,EAAA,CACC,MAAM,SACN,MAAO7B,EAAQ,OACf,SAAW8B,GAAM7B,EAAU,SAAU6B,CAAC,EACtC,YAAY,wBAAA,CAAA,EAEdhD,EAAAA,IAACiD,EAAA,CACC,MAAM,MACN,MAAO/B,EAAQ,IACf,SAAW8B,GAAM7B,EAAU,MAAO6B,CAAC,EACnC,QAASZ,CAAA,CAAA,EAEXpC,EAAAA,IAACiD,EAAA,CACC,MAAM,SACN,MAAO/B,EAAQ,OACf,SAAW8B,GAAM7B,EAAU,SAAU6B,CAAC,EACtC,QAAS,CACP,CAAE,MAAO,aAAc,MAAO,YAAA,EAC9B,CAAE,MAAO,YAAa,MAAO,WAAA,EAC7B,CAAE,MAAO,QAAS,MAAO,OAAA,EACzB,CAAE,MAAO,eAAgB,MAAO,cAAA,CAAe,CACjD,CAAA,CACF,EACF,SAEC,MAAA,CAAI,UAAW,cAEd,SAAA,CAAAlD,OAAC,OAAI,UAAW,GAAGkC,EAAU,iBAAmB,QAAQ,kBACrD,SAAA,CAAAQ,EAAgB,SAAW,EAC1BxC,EAAAA,IAACkD,EAAA,CAAW,MAAM,mBAAmB,EAErCpD,EAAAA,KAAC,QAAA,CAAM,UAAU,SACf,SAAA,CAAAE,MAAC,QAAA,CACC,SAAAF,EAAAA,KAAC,KAAA,CAAG,UAAU,WACZ,SAAA,CAAAE,EAAAA,IAAC,KAAA,CAAG,UAAU,+HAA+H,SAAA,gBAE7I,EACAA,EAAAA,IAAC,KAAA,CAAG,UAAU,oIAAoI,SAAA,SAElJ,EACAA,EAAAA,IAAC,KAAA,CAAG,UAAU,2CAAA,CAA4C,CAAA,CAAA,CAC5D,CAAA,CACF,EACAA,EAAAA,IAAC,QAAA,CACE,SAAAwC,EAAgB,IAAK5D,GACpBoB,EAAAA,IAACd,GAAA,CAEC,OAAAN,EACA,SAAUjB,EAAY,IAAIiB,EAAO,EAAE,EACnC,SAAU,IAAMmD,EAAanD,EAAO,EAAE,EACtC,OAAQ,IAAMoC,EAAS,gBAAgBpC,EAAO,EAAE,EAAE,EAClD,SAAU,IAAMkD,EAAiBlD,CAAM,EACvC,UAAY+B,GACVsB,EAAW,CACT,SAAUrD,EAAO,GACjB,WAAYA,EAAO,KACnB,KAAA+B,CAAA,CACD,EAEH,QAAAnB,EACA,WAAAC,EACA,aAAcT,GACXJ,EAAO,eAAiB,CAAA,EACzBsC,EAAQ,MAAA,CACV,EAlBKtC,EAAO,EAAA,CAoBf,CAAA,CACH,CAAA,EACF,EAGFoB,EAAAA,IAACmD,EAAA,CACC,KAAM/B,EAAW,KACjB,WAAYA,EAAW,WAAWe,CAAK,EACvC,aAAcf,EAAW,QACzB,MAAAe,EACA,SAAUf,EAAW,SACrB,iBAAkBA,EAAW,WAAA,CAAA,CAC/B,EACF,EAGCY,GACChC,EAAAA,IAAC,MAAA,CAAI,UAAU,+DACb,SAAAA,EAAAA,IAACoD,EAAA,CACC,SAAUpB,EAAQ,SAClB,WAAYA,EAAQ,WACpB,KAAMA,EAAQ,KACd,QAAS,IAAMC,EAAW,IAAI,CAAA,CAAA,CAChC,CACF,CAAA,EAEJ,EAGAjC,EAAAA,IAACqD,EAAA,CACC,KAAM,CAAC,CAACxB,EACR,QAAS,IAAMC,EAAiB,IAAI,EACpC,UAAWY,EACX,MAAM,oBACN,YACE5C,EAAAA,KAAAC,WAAA,CAAE,SAAA,CAAA,SACO,IACPC,EAAAA,IAAC,OAAA,CAAK,UAAU,gCAAiC,0BAAe,KAAK,EAAO,6CAAA,EAE9E,EAEF,UAAW2B,EAAa,UACxB,MAAOA,EAAa,KAAA,CAAA,CACtB,EACF,CAEJ"}
|
|
1
|
+
{"version":3,"file":"index-Uk6N1qiH.js","sources":["../../src/hooks/useExpandedRows.ts","../../src/pages/mcp/servers/helpers.ts","../../src/pages/mcp/servers/ServerRow.tsx","../../src/pages/mcp/servers/McpServersPage.tsx"],"sourcesContent":["import { useState, useCallback } from 'react';\n\n/**\n * Track expanded row IDs with localStorage persistence.\n *\n * Resilient: if a stored ID no longer exists in the data, it's silently ignored.\n * Never blocks rendering — reads from localStorage synchronously on mount,\n * writes asynchronously on change.\n */\nexport function useExpandedRows(storageKey: string): {\n expandedIds: Set<string>;\n toggle: (id: string) => void;\n isExpanded: (id: string) => boolean;\n} {\n const [expandedIds, setExpandedIds] = useState<Set<string>>(() => {\n try {\n const raw = localStorage.getItem(storageKey);\n if (raw) {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return new Set(parsed);\n }\n } catch { /* corrupted or unavailable — start empty */ }\n return new Set();\n });\n\n const persist = useCallback((next: Set<string>) => {\n try {\n localStorage.setItem(storageKey, JSON.stringify([...next]));\n } catch { /* quota exceeded or unavailable — ignore */ }\n }, [storageKey]);\n\n const toggle = useCallback((id: string) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n persist(next);\n return next;\n });\n }, [persist]);\n\n const isExpanded = useCallback((id: string) => expandedIds.has(id), [expandedIds]);\n\n return { expandedIds, toggle, isExpanded };\n}\n","import type { McpServerRecord, McpToolManifest } from '../../../api/types';\n\nexport function isBuiltIn(row: McpServerRecord): boolean {\n return !!(row.metadata as Record<string, unknown> | null)?.builtin\n || !!(row.transport_config as Record<string, unknown> | null)?.builtin;\n}\n\n/** Check if a server or any of its tools match the search term */\nexport function matchesSearch(server: McpServerRecord, search: string): boolean {\n if (!search) return true;\n const q = search.toLowerCase();\n if (server.name.toLowerCase().includes(q)) return true;\n if (server.description?.toLowerCase().includes(q)) return true;\n if ((server.tags ?? []).some((t) => t.toLowerCase().includes(q))) return true;\n const tools = (server.tool_manifest ?? []) as McpToolManifest[];\n return tools.some(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n}\n\n/** Filter tools within a server that match the search term */\nexport function filterTools(tools: McpToolManifest[], search: string): McpToolManifest[] {\n if (!search) return tools;\n const q = search.toLowerCase();\n return tools.filter(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n}\n","import { ChevronRight, Pencil, Trash2, Plug, Unplug, Play } from 'lucide-react';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport {\n useConnectMcpServer,\n useDisconnectMcpServer,\n} from '../../../api/mcp';\nimport { StatusBadge } from '../../../components/common/display/StatusBadge';\nimport { ToolPill } from '../../../components/common/display/ToolPill';\nimport { ServerName } from '../../../components/common/display/ServerName';\n\nimport type { McpServerRecord, McpToolManifest } from '../../../api/types';\nimport { isBuiltIn } from './helpers';\n\nexport function ServerRow({\n server,\n expanded,\n onToggle,\n onEdit,\n onDelete,\n onTryTool,\n connect,\n disconnect,\n visibleTools,\n}: {\n server: McpServerRecord;\n expanded: boolean;\n onToggle: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onTryTool: (tool: McpToolManifest) => void;\n connect: ReturnType<typeof useConnectMcpServer>;\n disconnect: ReturnType<typeof useDisconnectMcpServer>;\n visibleTools: McpToolManifest[];\n}) {\n const allTools = (server.tool_manifest ?? []) as McpToolManifest[];\n const builtin = isBuiltIn(server);\n const tags = server.tags ?? [];\n\n return (\n <>\n {/* Server header row */}\n <tr\n onClick={allTools.length > 0 ? onToggle : undefined}\n className={`group/row border-b border-surface-border/50 transition-colors duration-100 ${\n allTools.length > 0 ? 'cursor-pointer row-hover' : ''\n }`}\n >\n {/* Name + tags */}\n <td className=\"px-6 py-2.5\">\n <div className=\"flex items-center gap-3\">\n <span className={`transition-transform duration-150 ${expanded ? 'rotate-90' : ''} ${allTools.length === 0 ? 'opacity-0' : 'text-text-tertiary'}`}>\n <ChevronRight size={14} />\n </span>\n <span className=\"flex items-center gap-1.5\">\n <ServerName name={server.name} serverId={server.id} short={false} />\n {allTools.length > 0 && (\n <sup className=\"text-2xs font-normal text-accent/70\">{allTools.length}</sup>\n )}\n </span>\n {tags.length > 0 && (\n <div className=\"flex gap-1 ml-auto shrink-0\">\n {tags.slice(0, 3).map((tag) => (\n <span key={tag} className=\"inline-block px-1.5 py-0 text-2xs text-text-tertiary bg-surface-sunken rounded\">\n {tag}\n </span>\n ))}\n {tags.length > 3 && (\n <span className=\"text-2xs text-text-quaternary\" title={tags.slice(3).join(', ')}>…</span>\n )}\n </div>\n )}\n </div>\n </td>\n\n {/* Status */}\n <td className=\"px-4 py-2.5 w-28 whitespace-nowrap\">\n <StatusBadge status={server.status} />\n </td>\n\n {/* Actions */}\n <td className=\"px-4 py-2.5 w-16\">\n <RowActionGroup>\n {!builtin && (\n server.status === 'connected' ? (\n <RowAction\n icon={Unplug}\n title=\"Disconnect server\"\n onClick={() => disconnect.mutate(server.id)}\n />\n ) : (\n <RowAction\n icon={Plug}\n title=\"Connect server\"\n onClick={() => connect.mutate(server.id)}\n colorClass=\"text-text-tertiary hover:text-status-success\"\n />\n )\n )}\n <RowAction\n icon={Pencil}\n title=\"Edit server\"\n onClick={onEdit}\n />\n {!builtin && (\n <RowAction\n icon={Trash2}\n title=\"Delete server\"\n onClick={onDelete}\n colorClass=\"text-text-tertiary hover:text-status-error\"\n />\n )}\n </RowActionGroup>\n </td>\n </tr>\n\n {/* Expanded tool rows — real table rows for column alignment */}\n {expanded && visibleTools.map((tool) => (\n <tr\n key={tool.name}\n onClick={() => onTryTool(tool)}\n className=\"group/row cursor-pointer hover:bg-surface-hover/50 transition-colors border-b border-surface-border/15\"\n >\n {/* Tool name + description */}\n <td className=\"pl-14 pr-6 py-2.5\">\n <ToolPill name={tool.name} size=\"md\" />\n {tool.description && (\n <p className=\"text-2xs leading-snug text-text-quaternary mt-0.5\">{tool.description}</p>\n )}\n </td>\n\n {/* Status — empty for tools */}\n <td className=\"px-4 py-2.5 w-28\" />\n\n {/* Actions — play on hover */}\n <td className=\"px-4 py-2.5 w-16\">\n <div className=\"flex items-center justify-end\">\n <button\n onClick={(e) => { e.stopPropagation(); onTryTool(tool); }}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-accent\"\n title=\"Try tool\"\n >\n <Play className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n </button>\n </div>\n </td>\n </tr>\n ))}\n </>\n );\n}\n","import { useState, useMemo, useEffect } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n useMcpServers,\n useConnectMcpServer,\n useDisconnectMcpServer,\n useDeleteMcpServer,\n} from '../../../api/mcp';\nimport { EmptyState } from '../../../components/common/display/EmptyState';\nimport { ConfirmDeleteModal } from '../../../components/common/modal/ConfirmDeleteModal';\nimport type { McpServerRecord, McpToolManifest } from '../../../api/types';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useExpandedRows } from '../../../hooks/useExpandedRows';\nimport { ToolTestPanel } from '../../../components/common/test/ToolTestPanel';\nimport { matchesSearch, filterTools } from './helpers';\nimport { ServerRow } from './ServerRow';\n\nexport function McpServersPage() {\n const navigate = useNavigate();\n const { filters, setFilter, pagination } = useFilterParams({\n filters: { status: '', search: '', tag: '' },\n });\n\n const { data, isLoading } = useMcpServers({\n status: filters.status || undefined,\n search: filters.search || undefined,\n tags: filters.tag || undefined,\n });\n const connect = useConnectMcpServer();\n const disconnect = useDisconnectMcpServer();\n const deleteServer = useDeleteMcpServer();\n\n const [confirmDelete, setConfirmDelete] = useState<McpServerRecord | null>(null);\n const { expandedIds, toggle: toggleExpand } = useExpandedRows('lt:expanded:mcp-servers');\n const [tryTool, setTryTool] = useState<{\n serverId: string;\n serverName: string;\n tool: McpToolManifest;\n } | null>(null);\n\n const servers = data?.servers ?? [];\n const total = data?.total ?? 0;\n\n // Derive unique tags from current result set for the filter dropdown\n const tagOptions = useMemo(() => {\n const allTags = new Set<string>();\n for (const s of servers) {\n for (const t of s.tags ?? []) allTags.add(t);\n }\n return [...allTags].sort().map((t) => ({ value: t, label: t }));\n }, [servers]);\n\n // Client-side search filtering for tool-level matches within expanded rows\n const filteredServers = useMemo(() => {\n if (!filters.search) return servers;\n return servers.filter((s) => matchesSearch(s, filters.search));\n }, [servers, filters.search]);\n\n // Auto-expand servers whose tools match the search (so results are visible)\n useEffect(() => {\n if (!filters.search) return;\n const q = filters.search.toLowerCase();\n for (const s of filteredServers) {\n const tools = (s.tool_manifest ?? []) as McpToolManifest[];\n const hasToolMatch = tools.some(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n if (hasToolMatch && !expandedIds.has(s.id)) {\n toggleExpand(s.id);\n }\n }\n }, [filters.search, filteredServers]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleDelete = () => {\n if (!confirmDelete) return;\n deleteServer.mutate(confirmDelete.id, {\n onSuccess: () => setConfirmDelete(null),\n });\n };\n\n if (isLoading) {\n return (\n <div>\n <PageHeader title=\"Servers & Tools\" />\n <div className=\"animate-pulse space-y-0\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-14 border-b last:border-b-0 px-6 flex items-center\">\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div>\n <PageHeader\n title=\"Servers & Tools\"\n docsHash=\"#docs:dashboard.md:mcp-server-tools\"\n actions={\n <button\n onClick={() => navigate('/mcp/servers/new')}\n className=\"btn-primary text-xs\"\n >\n Register Server\n </button>\n }\n />\n\n <p className=\"text-sm text-text-secondary mb-6 max-w-2xl leading-relaxed\">\n Registered MCP servers and their available tools. Each server exposes tools that can be used by the MCP Tool Designer.\n </p>\n\n <FilterBar>\n <FilterInput\n label=\"Search\"\n value={filters.search}\n onChange={(v) => setFilter('search', v)}\n placeholder=\"Server or tool name...\"\n />\n <FilterSelect\n label=\"Tag\"\n value={filters.tag}\n onChange={(v) => setFilter('tag', v)}\n options={tagOptions}\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={[\n { value: 'registered', label: 'Registered' },\n { value: 'connected', label: 'Connected' },\n { value: 'error', label: 'Error' },\n { value: 'disconnected', label: 'Disconnected' },\n ]}\n />\n </FilterBar>\n\n <div className={`flex gap-0 ${tryTool ? '' : ''}`}>\n {/* Server list */}\n <div className={`${tryTool ? 'flex-1 min-w-0' : 'w-full'} transition-all`}>\n {filteredServers.length === 0 ? (\n <EmptyState title=\"No servers found\" />\n ) : (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"sticky top-[2.75rem] z-10 bg-surface px-6 py-3 text-left text-2xs font-semibold uppercase tracking-widest text-text-tertiary\">\n Server / Tool\n </th>\n <th className=\"sticky top-[2.75rem] z-10 bg-surface px-4 py-3 text-left text-2xs font-semibold uppercase tracking-widest text-text-tertiary w-28\">\n Status\n </th>\n <th className=\"sticky top-[2.75rem] z-10 bg-surface w-16\" />\n </tr>\n </thead>\n <tbody>\n {filteredServers.map((server) => (\n <ServerRow\n key={server.id}\n server={server}\n expanded={expandedIds.has(server.id)}\n onToggle={() => toggleExpand(server.id)}\n onEdit={() => navigate(`/mcp/servers/${server.id}`)}\n onDelete={() => setConfirmDelete(server)}\n onTryTool={(tool) =>\n setTryTool({\n serverId: server.id,\n serverName: server.name,\n tool,\n })\n }\n connect={connect}\n disconnect={disconnect}\n visibleTools={filterTools(\n (server.tool_manifest ?? []) as McpToolManifest[],\n filters.search,\n )}\n />\n ))}\n </tbody>\n </table>\n )}\n\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Test panel — slides in from right */}\n {tryTool && (\n <div className=\"w-[380px] shrink-0 sticky top-0 max-h-screen overflow-y-auto\">\n <ToolTestPanel\n serverId={tryTool.serverId}\n serverName={tryTool.serverName}\n tool={tryTool.tool}\n onClose={() => setTryTool(null)}\n />\n </div>\n )}\n </div>\n\n {/* Delete confirmation modal */}\n <ConfirmDeleteModal\n open={!!confirmDelete}\n onClose={() => setConfirmDelete(null)}\n onConfirm={handleDelete}\n title=\"Delete MCP Server\"\n description={\n <>\n Delete{' '}\n <span className=\"font-medium text-text-primary\">{confirmDelete?.name}</span>?\n This will remove the server registration.\n </>\n }\n isPending={deleteServer.isPending}\n error={deleteServer.error as Error | null}\n />\n </div>\n );\n}\n"],"names":["useExpandedRows","storageKey","expandedIds","setExpandedIds","useState","raw","parsed","persist","useCallback","next","toggle","id","prev","isExpanded","isBuiltIn","row","_a","_b","matchesSearch","server","search","q","t","filterTools","tools","ServerRow","expanded","onToggle","onEdit","onDelete","onTryTool","connect","disconnect","visibleTools","allTools","builtin","tags","jsxs","Fragment","jsx","ChevronRight","ServerName","tag","StatusBadge","RowActionGroup","RowAction","Unplug","Plug","Pencil","Trash2","tool","ToolPill","e","Play","McpServersPage","navigate","useNavigate","filters","setFilter","pagination","useFilterParams","data","isLoading","useMcpServers","useConnectMcpServer","useDisconnectMcpServer","deleteServer","useDeleteMcpServer","confirmDelete","setConfirmDelete","toggleExpand","tryTool","setTryTool","servers","total","tagOptions","useMemo","allTags","s","filteredServers","useEffect","handleDelete","PageHeader","_","i","FilterBar","FilterInput","v","FilterSelect","EmptyState","StickyPagination","ToolTestPanel","ConfirmDeleteModal"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as d,j as s}from"./vendor-query-RUZdMvN6.js";import{c as F,d as C,b as u}from"./index-lGfBW1PB.js";import{u as M,a as T,b as O,S as $,c as A,d as D,e as R}from"./StreamMessageDetail-DziA1g1e.js";import{u as z}from"./useFilterParams-crmlBw_l.js";import{u as E}from"./useNamespace-wZCsEF6O.js";import{b as L}from"./api-path-u2Jf9QXS.js";import{D as I}from"./DataTable-DFPMeqyQ.js";import{S as U}from"./StickyPagination-XA1krmz5.js";import{F as q,b as x,a as _}from"./FilterBar-C06DK5Oa.js";import{P as B}from"./PageHeader-CDDpHpdv.js";import{L as V}from"./ListToolbar-BvpGFFYp.js";import{X as H,a0 as J}from"./vendor-icons-BgsXTN4h.js";import"./vendor-react-CdqEC2zv.js";import"./controlplane-Cy7snw7f.js";import"./EmptyState-lpUFYfun.js";function W(l,n){if(l.length<=n)return l;const a=Math.floor((n-1)/2);return`${l.slice(0,a)}…${l.slice(-a)}`}function ce(){const{namespace:l,available:n}=E("namespace"),{filters:a,setFilter:t,pagination:r,sort:c,setSort:h}=z({filters:{namespace:"",source:"worker",status:"",stream_name:"",msg_type:"",topic:"",workflow_name:"",jid:"",aid:""}}),[m,g]=d.useState(null),v=d.useMemo(()=>n.map(e=>({value:e,label:e})),[n]),{data:i,isLoading:b,refetch:j,isFetching:w}=M({namespace:a.namespace||l,source:a.source||"worker",limit:r.pageSize,offset:r.offset,sort_by:c.sort_by||"created_at",order:c.order||"desc",status:a.status||void 0,stream_name:a.stream_name||void 0,msg_type:a.msg_type||void 0,topic:a.topic||void 0,workflow_name:a.workflow_name||void 0,jid:a.jid||void 0,aid:a.aid||void 0}),p=(i==null?void 0:i.messages)??[],f=(i==null?void 0:i.total)??0,o=d.useMemo(()=>m?p.find(e=>e.id===m.id&&e.source===m.source)??m:null,[p,m]),S=!!o,[k,N]=d.useState(null);d.useEffect(()=>{o&&N(o)},[o]);const y=o??k,P=[{key:"stream_name",label:"Stream",sortable:!0,render:e=>s.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s.jsx("span",{className:`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${D[e.status]}`,title:A[e.status]}),s.jsx("span",{className:"font-mono text-xs text-text-secondary truncate",title:e.stream_name,children:e.stream_name})]})},{key:"source",label:"Source",render:e=>s.jsx("span",{className:R,children:e.source}),className:"w-24"},{key:"created_at",label:"Created",sortable:!0,render:e=>s.jsx(u,{date:e.created_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}),className:"w-32"},{key:"reserved_at",label:"Reserved",render:e=>e.reserved_at?s.jsx(u,{date:e.reserved_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}):s.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"w-32"},{key:"expired_at",label:"Processed",render:e=>e.expired_at?s.jsx(u,{date:e.expired_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}):s.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"w-32"},{key:"priority",label:"Pri",sortable:!0,render:e=>s.jsx("span",{className:"text-xs text-text-secondary",children:e.priority}),className:"w-14 text-right"},{key:"retry_attempt",label:"Retries",render:e=>s.jsxs("span",{className:"text-xs text-text-secondary whitespace-nowrap",children:[e.retry_attempt,"/",e.max_retry_attempts]}),className:"w-20"}];return s.jsxs("div",{className:"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16",children:[s.jsxs("div",{className:"flex-1 min-w-0 pt-10 pr-10",children:[s.jsx(B,{title:"Messages",docsHash:"#docs:dashboard.md:messages"}),s.jsxs(q,{actions:s.jsx(V,{onRefresh:()=>j(),isFetching:w,apiPath:L("/controlplane/stream-messages",{namespace:a.namespace||l,source:a.source||"worker",limit:r.pageSize,offset:r.offset,sort_by:c.sort_by||"created_at",order:c.order||"desc",status:a.status||void 0,stream_name:a.stream_name||void 0,msg_type:a.msg_type||void 0,topic:a.topic||void 0,workflow_name:a.workflow_name||void 0,jid:a.jid||void 0,aid:a.aid||void 0})}),children:[s.jsx(x,{label:"Namespace",value:a.namespace,onChange:e=>t("namespace",e),options:v,required:!0}),s.jsx(x,{label:"Source",value:a.source,onChange:e=>t("source",e),options:T,required:!0}),s.jsx(x,{label:"Status",value:a.status,onChange:e=>t("status",e),options:O}),s.jsx(_,{label:"Stream",value:a.stream_name,onChange:e=>t("stream_name",e),placeholder:"Filter by stream name…"}),s.jsx(_,{label:"Job ID",value:a.jid,onChange:e=>t("jid",e),placeholder:"Filter by jid…"}),[{key:"topic",label:"Topic",value:a.topic},{key:"workflow_name",label:"Workflow",value:a.workflow_name},{key:"aid",label:"Activity",value:a.aid},{key:"msg_type",label:"Type",value:a.msg_type}].filter(e=>e.value).map(e=>s.jsxs("button",{onClick:()=>t(e.key,""),className:"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors",title:`Clear ${e.label} filter: ${e.value}`,children:[e.label,": ",W(e.value,12),s.jsx(H,{className:"w-2.5 h-2.5"})]},e.key))]}),s.jsx(I,{columns:P,data:p,keyFn:e=>`${e.source}:${e.id}`,isLoading:b,emptyMessage:"No stream messages found",onRowClick:e=>g(e),activeRowKey:o?`${o.source}:${o.id}`:null,sort:c,onSort:h,layout:"fixed"}),s.jsx(U,{page:r.page,totalPages:r.totalPages(f),onPageChange:r.setPage,total:f,pageSize:r.pageSize,onPageSizeChange:r.setPageSize})]}),s.jsx(F,{open:S,width:416,className:"self-stretch",children:s.jsx("div",{className:"h-full pl-4",children:s.jsx(C,{views:[{id:"detail",icon:J,label:"Message Detail",content:y?s.jsx($,{message:y,filters:{onFilterStatus:e=>t("status",e),onFilterStreamName:e=>t("stream_name",e),onFilterMsgType:e=>t("msg_type",e),onFilterTopic:e=>t("topic",e),onFilterWorkflow:e=>t("workflow_name",e),onFilterJid:e=>t("jid",e),onFilterAid:e=>t("aid",e)}}):null}],activeId:"detail",onViewChange:()=>{},onClose:()=>g(null),stickyClassName:"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9"})})})]})}export{ce as StreamMessagesPage};
|
|
2
|
+
//# sourceMappingURL=index-X3_AxcUk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Dsgqxdyh.js","sources":["../../src/pages/admin/streams/StreamMessagesPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from 'react';\nimport { X, MessageSquare } from 'lucide-react';\nimport { SlidePanel, SlidePanelViews } from '../../../components/common/layout/SlidePanel';\nimport { useStreamMessages, type StreamMessage } from '../../../api/stream-messages';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useNamespace } from '../../../hooks/useNamespace';\nimport { buildApiPath } from '../../../lib/api-path';\nimport { DataTable, type Column } from '../../../components/common/data/DataTable';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { ListToolbar } from '../../../components/common/data/ListToolbar';\nimport { StreamMessageDetail } from './StreamMessageDetail';\nimport { STATUS_DOT, STATUS_LABEL, STATUS_OPTIONS, SOURCE_OPTIONS, SOURCE_BADGE } from './constants';\n\nfunction truncateMiddle(str: string, max: number): string {\n if (str.length <= max) return str;\n const half = Math.floor((max - 1) / 2);\n return `${str.slice(0, half)}…${str.slice(-half)}`;\n}\n\nexport function StreamMessagesPage() {\n const { namespace, available } = useNamespace('namespace');\n\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { namespace: '', source: 'worker', status: '', stream_name: '', msg_type: '', topic: '', workflow_name: '', jid: '', aid: '' },\n });\n\n const [selected, setSelected] = useState<StreamMessage | null>(null);\n\n const namespaceOptions = useMemo(\n () => available.map((id) => ({ value: id, label: id })),\n [available],\n );\n\n const { data, isLoading, refetch, isFetching } = useStreamMessages({\n namespace: filters.namespace || namespace,\n source: (filters.source as 'engine' | 'worker') || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: (filters.status as any) || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n });\n\n const messages = data?.messages ?? [];\n const total = data?.total ?? 0;\n\n const activeMessage = useMemo(() => {\n if (!selected) return null;\n return messages.find((m) => m.id === selected.id && m.source === selected.source) ?? selected;\n }, [messages, selected]);\n\n const panelOpen = !!activeMessage;\n\n // Hold the last message through the panel's closing animation so the detail\n // content stays rendered while the panel slides shut.\n const [lastMessage, setLastMessage] = useState<StreamMessage | null>(null);\n useEffect(() => {\n if (activeMessage) setLastMessage(activeMessage);\n }, [activeMessage]);\n const displayMessage = activeMessage ?? lastMessage;\n\n // Status and type live as the dot and the detail panel — the row itself\n // stays one flexible stream column plus fixed narrow facts, so the table\n // shrinks with the container (same shape as the executions list).\n const columns: Column<StreamMessage>[] = [\n {\n key: 'stream_name',\n label: 'Stream',\n sortable: true,\n render: (row) => (\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className={`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${STATUS_DOT[row.status]}`}\n title={STATUS_LABEL[row.status]}\n />\n <span className=\"font-mono text-xs text-text-secondary truncate\" title={row.stream_name}>\n {row.stream_name}\n </span>\n </div>\n ),\n },\n {\n key: 'source',\n label: 'Source',\n render: (row) => <span className={SOURCE_BADGE}>{row.source}</span>,\n className: 'w-24',\n },\n {\n key: 'created_at',\n label: 'Created',\n sortable: true,\n render: (row) => <DateValue date={row.created_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n },\n {\n key: 'reserved_at',\n label: 'Reserved',\n render: (row) => row.reserved_at\n ? <DateValue date={row.reserved_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'expired_at',\n label: 'Processed',\n render: (row) => row.expired_at\n ? <DateValue date={row.expired_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'priority',\n label: 'Pri',\n sortable: true,\n render: (row) => <span className=\"text-xs text-text-secondary\">{row.priority}</span>,\n className: 'w-14 text-right',\n },\n {\n key: 'retry_attempt',\n label: 'Retries',\n render: (row) => (\n <span className=\"text-xs text-text-secondary whitespace-nowrap\">\n {row.retry_attempt}/{row.max_retry_attempts}\n </span>\n ),\n className: 'w-20',\n },\n ];\n\n return (\n // Master-list flow beside a full-height panel: the left column is a plain\n // page-scrolling list (FilterBar and table headers stick against the main\n // scroll, exactly like the executions list). The panel column spans the\n // page height; its sticky viewport stays pinned with its own scroll.\n // Negative margins let the panel span the full middle row; the left\n // column re-adds those gutters for its own content.\n <div className=\"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16\">\n <div className=\"flex-1 min-w-0 pt-10 pr-10\">\n <PageHeader title=\"Messages\" docsHash=\"#docs:dashboard.md:messages\" />\n\n <FilterBar actions={\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={buildApiPath('/controlplane/stream-messages', {\n namespace: filters.namespace || namespace,\n source: filters.source || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: filters.status || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n })}\n />\n }>\n <FilterSelect\n label=\"Namespace\"\n value={filters.namespace}\n onChange={(v) => setFilter('namespace', v)}\n options={namespaceOptions}\n required\n />\n <FilterSelect\n label=\"Source\"\n value={filters.source}\n onChange={(v) => setFilter('source', v)}\n options={SOURCE_OPTIONS}\n required\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={STATUS_OPTIONS}\n />\n <FilterInput\n label=\"Stream\"\n value={filters.stream_name}\n onChange={(v) => setFilter('stream_name', v)}\n placeholder=\"Filter by stream name…\"\n />\n <FilterInput\n label=\"Job ID\"\n value={filters.jid}\n onChange={(v) => setFilter('jid', v)}\n placeholder=\"Filter by jid…\"\n />\n {/* Active dimension filter pills — inline in the sticky bar */}\n {[\n { key: 'topic', label: 'Topic', value: filters.topic },\n { key: 'workflow_name', label: 'Workflow', value: filters.workflow_name },\n { key: 'aid', label: 'Activity', value: filters.aid },\n { key: 'msg_type', label: 'Type', value: filters.msg_type },\n ].filter((f) => f.value).map((f) => (\n <button\n key={f.key}\n onClick={() => setFilter(f.key as any, '')}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors\"\n title={`Clear ${f.label} filter: ${f.value}`}\n >\n {f.label}: {truncateMiddle(f.value, 12)}\n <X className=\"w-2.5 h-2.5\" />\n </button>\n ))}\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={messages}\n keyFn={(row) => `${row.source}:${row.id}`}\n isLoading={isLoading}\n emptyMessage=\"No stream messages found\"\n onRowClick={(row) => setSelected(row)}\n activeRowKey={activeMessage ? `${activeMessage.source}:${activeMessage.id}` : null}\n sort={sort}\n onSort={setSort}\n layout=\"fixed\"\n />\n\n {/* Direct child of the tall column so sticky works; its -mx-10 fills\n the column's pr-10, ending flush at the panel's edge. */}\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Detail panel — spans the page height; the sticky viewport keeps the\n chrome pinned to the visible area with its own scroll. */}\n <SlidePanel open={panelOpen} width={416} className=\"self-stretch\">\n <div className=\"h-full pl-4\">\n <SlidePanelViews\n views={[{\n id: 'detail',\n icon: MessageSquare,\n label: 'Message Detail',\n content: displayMessage ? (\n <StreamMessageDetail\n message={displayMessage}\n filters={{\n onFilterStatus: (v) => setFilter('status', v),\n onFilterStreamName: (v) => setFilter('stream_name', v),\n onFilterMsgType: (v) => setFilter('msg_type', v),\n onFilterTopic: (v) => setFilter('topic', v),\n onFilterWorkflow: (v) => setFilter('workflow_name', v),\n onFilterJid: (v) => setFilter('jid', v),\n onFilterAid: (v) => setFilter('aid', v),\n }}\n />\n ) : null,\n }]}\n activeId=\"detail\"\n onViewChange={() => {}}\n onClose={() => setSelected(null)}\n stickyClassName=\"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9\"\n />\n </div>\n </SlidePanel>\n </div>\n );\n}\n"],"names":["truncateMiddle","str","max","half","StreamMessagesPage","namespace","available","useNamespace","filters","setFilter","pagination","sort","setSort","useFilterParams","selected","setSelected","useState","namespaceOptions","useMemo","id","data","isLoading","refetch","isFetching","useStreamMessages","messages","total","activeMessage","m","panelOpen","lastMessage","setLastMessage","useEffect","displayMessage","columns","row","jsxs","jsx","STATUS_DOT","STATUS_LABEL","SOURCE_BADGE","DateValue","PageHeader","FilterBar","ListToolbar","buildApiPath","FilterSelect","v","SOURCE_OPTIONS","STATUS_OPTIONS","FilterInput","f","X","DataTable","StickyPagination","SlidePanel","SlidePanelViews","MessageSquare","StreamMessageDetail"],"mappings":"yuBAgBA,SAASA,EAAeC,EAAaC,EAAqB,CACxD,GAAID,EAAI,QAAUC,EAAK,OAAOD,EAC9B,MAAME,EAAO,KAAK,OAAOD,EAAM,GAAK,CAAC,EACrC,MAAO,GAAGD,EAAI,MAAM,EAAGE,CAAI,CAAC,IAAIF,EAAI,MAAM,CAACE,CAAI,CAAC,EAClD,CAEO,SAASC,IAAqB,CACnC,KAAM,CAAE,UAAAC,EAAW,UAAAC,GAAcC,EAAa,WAAW,EAEnD,CAAE,QAAAC,EAAS,UAAAC,EAAW,WAAAC,EAAY,KAAAC,EAAM,QAAAC,CAAA,EAAYC,EAAgB,CACxE,QAAS,CAAE,UAAW,GAAI,OAAQ,SAAU,OAAQ,GAAI,YAAa,GAAI,SAAU,GAAI,MAAO,GAAI,cAAe,GAAI,IAAK,GAAI,IAAK,EAAA,CAAG,CACvI,EAEK,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAA+B,IAAI,EAE7DC,EAAmBC,EAAAA,QACvB,IAAMZ,EAAU,IAAKa,IAAQ,CAAE,MAAOA,EAAI,MAAOA,CAAA,EAAK,EACtD,CAACb,CAAS,CAAA,EAGN,CAAE,KAAAc,EAAM,UAAAC,EAAW,QAAAC,EAAS,WAAAC,CAAA,EAAeC,EAAkB,CACjE,UAAWhB,EAAQ,WAAaH,EAChC,OAASG,EAAQ,QAAkC,SACnD,MAAOE,EAAW,SAClB,OAAQA,EAAW,OACnB,QAASC,EAAK,SAAW,aACzB,MAAOA,EAAK,OAAS,OACrB,OAASH,EAAQ,QAAkB,OACnC,YAAaA,EAAQ,aAAe,OACpC,SAAUA,EAAQ,UAAY,OAC9B,MAAOA,EAAQ,OAAS,OACxB,cAAeA,EAAQ,eAAiB,OACxC,IAAKA,EAAQ,KAAO,OACpB,IAAKA,EAAQ,KAAO,MAAA,CACrB,EAEKiB,GAAWL,GAAA,YAAAA,EAAM,WAAY,CAAA,EAC7BM,GAAQN,GAAA,YAAAA,EAAM,QAAS,EAEvBO,EAAgBT,EAAAA,QAAQ,IACvBJ,EACEW,EAAS,KAAMG,GAAMA,EAAE,KAAOd,EAAS,IAAMc,EAAE,SAAWd,EAAS,MAAM,GAAKA,EAD/D,KAErB,CAACW,EAAUX,CAAQ,CAAC,EAEjBe,EAAY,CAAC,CAACF,EAId,CAACG,EAAaC,CAAc,EAAIf,EAAAA,SAA+B,IAAI,EACzEgB,EAAAA,UAAU,IAAM,CACVL,KAA8BA,CAAa,CACjD,EAAG,CAACA,CAAa,CAAC,EAClB,MAAMM,EAAiBN,GAAiBG,EAKlCI,EAAmC,CACvC,CACE,IAAK,cACL,MAAO,SACP,SAAU,GACV,OAASC,GACPC,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAAC,OAAA,CACC,UAAW,8CAA8CC,EAAWH,EAAI,MAAM,CAAC,GAC/E,MAAOI,EAAaJ,EAAI,MAAM,CAAA,CAAA,EAEhCE,EAAAA,IAAC,QAAK,UAAU,iDAAiD,MAAOF,EAAI,YACzE,WAAI,WAAA,CACP,CAAA,CAAA,CACF,CAAA,EAGJ,CACE,IAAK,SACL,MAAO,SACP,OAASA,GAAQE,EAAAA,IAAC,QAAK,UAAWG,EAAe,WAAI,OAAO,EAC5D,UAAW,MAAA,EAEb,CACE,IAAK,aACL,MAAO,UACP,SAAU,GACV,OAASL,GAAQE,MAACI,EAAA,CAAU,KAAMN,EAAI,WAAY,OAAO,WAAW,UAAU,+CAAA,CAAgD,EAC9H,UAAW,MAAA,EAEb,CACE,IAAK,cACL,MAAO,WACP,OAASA,GAAQA,EAAI,YACjBE,MAACI,GAAU,KAAMN,EAAI,YAAa,OAAO,WAAW,UAAU,gDAAgD,QAC7G,OAAA,CAAK,UAAU,6BAA6B,SAAA,IAAC,EAClD,UAAW,MAAA,EAEb,CACE,IAAK,aACL,MAAO,YACP,OAASA,GAAQA,EAAI,WACjBE,MAACI,GAAU,KAAMN,EAAI,WAAY,OAAO,WAAW,UAAU,gDAAgD,QAC5G,OAAA,CAAK,UAAU,6BAA6B,SAAA,IAAC,EAClD,UAAW,MAAA,EAEb,CACE,IAAK,WACL,MAAO,MACP,SAAU,GACV,OAASA,GAAQE,EAAAA,IAAC,QAAK,UAAU,8BAA+B,WAAI,SAAS,EAC7E,UAAW,iBAAA,EAEb,CACE,IAAK,gBACL,MAAO,UACP,OAASF,GACPC,EAAAA,KAAC,OAAA,CAAK,UAAU,gDACb,SAAA,CAAAD,EAAI,cAAc,IAAEA,EAAI,kBAAA,EAC3B,EAEF,UAAW,MAAA,CACb,EAGF,OAOEC,EAAAA,KAAC,MAAA,CAAI,UAAU,kDACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,6BACb,SAAA,CAAAC,EAAAA,IAACK,EAAA,CAAW,MAAM,WAAW,SAAS,8BAA8B,EAEpEN,OAACO,GAAU,QACXN,EAAAA,IAACO,EAAA,CACC,UAAW,IAAMtB,EAAA,EACjB,WAAAC,EACA,QAASsB,EAAa,gCAAiC,CACrD,UAAWrC,EAAQ,WAAaH,EAChC,OAAQG,EAAQ,QAAU,SAC1B,MAAOE,EAAW,SAClB,OAAQA,EAAW,OACnB,QAASC,EAAK,SAAW,aACzB,MAAOA,EAAK,OAAS,OACrB,OAAQH,EAAQ,QAAU,OAC1B,YAAaA,EAAQ,aAAe,OACpC,SAAUA,EAAQ,UAAY,OAC9B,MAAOA,EAAQ,OAAS,OACxB,cAAeA,EAAQ,eAAiB,OACxC,IAAKA,EAAQ,KAAO,OACpB,IAAKA,EAAQ,KAAO,MAAA,CACrB,CAAA,CAAA,EAGH,SAAA,CAAA6B,EAAAA,IAACS,EAAA,CACC,MAAM,YACN,MAAOtC,EAAQ,UACf,SAAWuC,GAAMtC,EAAU,YAAasC,CAAC,EACzC,QAAS9B,EACT,SAAQ,EAAA,CAAA,EAEVoB,EAAAA,IAACS,EAAA,CACC,MAAM,SACN,MAAOtC,EAAQ,OACf,SAAWuC,GAAMtC,EAAU,SAAUsC,CAAC,EACtC,QAASC,EACT,SAAQ,EAAA,CAAA,EAEVX,EAAAA,IAACS,EAAA,CACC,MAAM,SACN,MAAOtC,EAAQ,OACf,SAAWuC,GAAMtC,EAAU,SAAUsC,CAAC,EACtC,QAASE,CAAA,CAAA,EAEXZ,EAAAA,IAACa,EAAA,CACC,MAAM,SACN,MAAO1C,EAAQ,YACf,SAAWuC,GAAMtC,EAAU,cAAesC,CAAC,EAC3C,YAAY,wBAAA,CAAA,EAEdV,EAAAA,IAACa,EAAA,CACC,MAAM,SACN,MAAO1C,EAAQ,IACf,SAAWuC,GAAMtC,EAAU,MAAOsC,CAAC,EACnC,YAAY,gBAAA,CAAA,EAGb,CACC,CAAE,IAAK,QAAS,MAAO,QAAS,MAAOvC,EAAQ,KAAA,EAC/C,CAAE,IAAK,gBAAiB,MAAO,WAAY,MAAOA,EAAQ,aAAA,EAC1D,CAAE,IAAK,MAAO,MAAO,WAAY,MAAOA,EAAQ,GAAA,EAChD,CAAE,IAAK,WAAY,MAAO,OAAQ,MAAOA,EAAQ,QAAA,CAAS,EAC1D,OAAQ2C,GAAMA,EAAE,KAAK,EAAE,IAAKA,GAC5Bf,EAAAA,KAAC,SAAA,CAEC,QAAS,IAAM3B,EAAU0C,EAAE,IAAY,EAAE,EACzC,UAAU,2IACV,MAAO,SAASA,EAAE,KAAK,YAAYA,EAAE,KAAK,GAEzC,SAAA,CAAAA,EAAE,MAAM,KAAGnD,EAAemD,EAAE,MAAO,EAAE,EACtCd,EAAAA,IAACe,EAAA,CAAE,UAAU,aAAA,CAAc,CAAA,CAAA,EANtBD,EAAE,GAAA,CAQV,CAAA,EACH,EAEEd,EAAAA,IAACgB,EAAA,CACC,QAAAnB,EACA,KAAMT,EACN,MAAQU,GAAQ,GAAGA,EAAI,MAAM,IAAIA,EAAI,EAAE,GACvC,UAAAd,EACA,aAAa,2BACb,WAAac,GAAQpB,EAAYoB,CAAG,EACpC,aAAcR,EAAgB,GAAGA,EAAc,MAAM,IAAIA,EAAc,EAAE,GAAK,KAC9E,KAAAhB,EACA,OAAQC,EACR,OAAO,OAAA,CAAA,EAKTyB,EAAAA,IAACiB,EAAA,CACC,KAAM5C,EAAW,KACjB,WAAYA,EAAW,WAAWgB,CAAK,EACvC,aAAchB,EAAW,QACzB,MAAAgB,EACA,SAAUhB,EAAW,SACrB,iBAAkBA,EAAW,WAAA,CAAA,CAC/B,EACF,EAIA2B,EAAAA,IAACkB,EAAA,CAAW,KAAM1B,EAAW,MAAO,IAAK,UAAU,eACjD,SAAAQ,EAAAA,IAAC,MAAA,CAAI,UAAU,cACb,SAAAA,EAAAA,IAACmB,EAAA,CACC,MAAO,CAAC,CACN,GAAI,SACJ,KAAMC,EACN,MAAO,iBACP,QAASxB,EACPI,EAAAA,IAACqB,EAAA,CACC,QAASzB,EACT,QAAS,CACP,eAAiBc,GAAMtC,EAAU,SAAUsC,CAAC,EAC5C,mBAAqBA,GAAMtC,EAAU,cAAesC,CAAC,EACrD,gBAAkBA,GAAMtC,EAAU,WAAYsC,CAAC,EAC/C,cAAgBA,GAAMtC,EAAU,QAASsC,CAAC,EAC1C,iBAAmBA,GAAMtC,EAAU,gBAAiBsC,CAAC,EACrD,YAAcA,GAAMtC,EAAU,MAAOsC,CAAC,EACtC,YAAcA,GAAMtC,EAAU,MAAOsC,CAAC,CAAA,CACxC,CAAA,EAEA,IAAA,CACL,EACD,SAAS,SACT,aAAc,IAAM,CAAC,EACrB,QAAS,IAAMhC,EAAY,IAAI,EAC/B,gBAAgB,gDAAA,CAAA,EAEpB,CAAA,CACF,CAAA,CAAA,CACF,CAEJ"}
|
|
1
|
+
{"version":3,"file":"index-X3_AxcUk.js","sources":["../../src/pages/admin/streams/StreamMessagesPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from 'react';\nimport { X, MessageSquare } from 'lucide-react';\nimport { SlidePanel, SlidePanelViews } from '../../../components/common/layout/SlidePanel';\nimport { useStreamMessages, type StreamMessage } from '../../../api/stream-messages';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useNamespace } from '../../../hooks/useNamespace';\nimport { buildApiPath } from '../../../lib/api-path';\nimport { DataTable, type Column } from '../../../components/common/data/DataTable';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { ListToolbar } from '../../../components/common/data/ListToolbar';\nimport { StreamMessageDetail } from './StreamMessageDetail';\nimport { STATUS_DOT, STATUS_LABEL, STATUS_OPTIONS, SOURCE_OPTIONS, SOURCE_BADGE } from './constants';\n\nfunction truncateMiddle(str: string, max: number): string {\n if (str.length <= max) return str;\n const half = Math.floor((max - 1) / 2);\n return `${str.slice(0, half)}…${str.slice(-half)}`;\n}\n\nexport function StreamMessagesPage() {\n const { namespace, available } = useNamespace('namespace');\n\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { namespace: '', source: 'worker', status: '', stream_name: '', msg_type: '', topic: '', workflow_name: '', jid: '', aid: '' },\n });\n\n const [selected, setSelected] = useState<StreamMessage | null>(null);\n\n const namespaceOptions = useMemo(\n () => available.map((id) => ({ value: id, label: id })),\n [available],\n );\n\n const { data, isLoading, refetch, isFetching } = useStreamMessages({\n namespace: filters.namespace || namespace,\n source: (filters.source as 'engine' | 'worker') || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: (filters.status as any) || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n });\n\n const messages = data?.messages ?? [];\n const total = data?.total ?? 0;\n\n const activeMessage = useMemo(() => {\n if (!selected) return null;\n return messages.find((m) => m.id === selected.id && m.source === selected.source) ?? selected;\n }, [messages, selected]);\n\n const panelOpen = !!activeMessage;\n\n // Hold the last message through the panel's closing animation so the detail\n // content stays rendered while the panel slides shut.\n const [lastMessage, setLastMessage] = useState<StreamMessage | null>(null);\n useEffect(() => {\n if (activeMessage) setLastMessage(activeMessage);\n }, [activeMessage]);\n const displayMessage = activeMessage ?? lastMessage;\n\n // Status and type live as the dot and the detail panel — the row itself\n // stays one flexible stream column plus fixed narrow facts, so the table\n // shrinks with the container (same shape as the executions list).\n const columns: Column<StreamMessage>[] = [\n {\n key: 'stream_name',\n label: 'Stream',\n sortable: true,\n render: (row) => (\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className={`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${STATUS_DOT[row.status]}`}\n title={STATUS_LABEL[row.status]}\n />\n <span className=\"font-mono text-xs text-text-secondary truncate\" title={row.stream_name}>\n {row.stream_name}\n </span>\n </div>\n ),\n },\n {\n key: 'source',\n label: 'Source',\n render: (row) => <span className={SOURCE_BADGE}>{row.source}</span>,\n className: 'w-24',\n },\n {\n key: 'created_at',\n label: 'Created',\n sortable: true,\n render: (row) => <DateValue date={row.created_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n },\n {\n key: 'reserved_at',\n label: 'Reserved',\n render: (row) => row.reserved_at\n ? <DateValue date={row.reserved_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'expired_at',\n label: 'Processed',\n render: (row) => row.expired_at\n ? <DateValue date={row.expired_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'priority',\n label: 'Pri',\n sortable: true,\n render: (row) => <span className=\"text-xs text-text-secondary\">{row.priority}</span>,\n className: 'w-14 text-right',\n },\n {\n key: 'retry_attempt',\n label: 'Retries',\n render: (row) => (\n <span className=\"text-xs text-text-secondary whitespace-nowrap\">\n {row.retry_attempt}/{row.max_retry_attempts}\n </span>\n ),\n className: 'w-20',\n },\n ];\n\n return (\n // Master-list flow beside a full-height panel: the left column is a plain\n // page-scrolling list (FilterBar and table headers stick against the main\n // scroll, exactly like the executions list). The panel column spans the\n // page height; its sticky viewport stays pinned with its own scroll.\n // Negative margins let the panel span the full middle row; the left\n // column re-adds those gutters for its own content.\n <div className=\"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16\">\n <div className=\"flex-1 min-w-0 pt-10 pr-10\">\n <PageHeader title=\"Messages\" docsHash=\"#docs:dashboard.md:messages\" />\n\n <FilterBar actions={\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={buildApiPath('/controlplane/stream-messages', {\n namespace: filters.namespace || namespace,\n source: filters.source || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: filters.status || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n })}\n />\n }>\n <FilterSelect\n label=\"Namespace\"\n value={filters.namespace}\n onChange={(v) => setFilter('namespace', v)}\n options={namespaceOptions}\n required\n />\n <FilterSelect\n label=\"Source\"\n value={filters.source}\n onChange={(v) => setFilter('source', v)}\n options={SOURCE_OPTIONS}\n required\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={STATUS_OPTIONS}\n />\n <FilterInput\n label=\"Stream\"\n value={filters.stream_name}\n onChange={(v) => setFilter('stream_name', v)}\n placeholder=\"Filter by stream name…\"\n />\n <FilterInput\n label=\"Job ID\"\n value={filters.jid}\n onChange={(v) => setFilter('jid', v)}\n placeholder=\"Filter by jid…\"\n />\n {/* Active dimension filter pills — inline in the sticky bar */}\n {[\n { key: 'topic', label: 'Topic', value: filters.topic },\n { key: 'workflow_name', label: 'Workflow', value: filters.workflow_name },\n { key: 'aid', label: 'Activity', value: filters.aid },\n { key: 'msg_type', label: 'Type', value: filters.msg_type },\n ].filter((f) => f.value).map((f) => (\n <button\n key={f.key}\n onClick={() => setFilter(f.key as any, '')}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors\"\n title={`Clear ${f.label} filter: ${f.value}`}\n >\n {f.label}: {truncateMiddle(f.value, 12)}\n <X className=\"w-2.5 h-2.5\" />\n </button>\n ))}\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={messages}\n keyFn={(row) => `${row.source}:${row.id}`}\n isLoading={isLoading}\n emptyMessage=\"No stream messages found\"\n onRowClick={(row) => setSelected(row)}\n activeRowKey={activeMessage ? `${activeMessage.source}:${activeMessage.id}` : null}\n sort={sort}\n onSort={setSort}\n layout=\"fixed\"\n />\n\n {/* Direct child of the tall column so sticky works; its -mx-10 fills\n the column's pr-10, ending flush at the panel's edge. */}\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Detail panel — spans the page height; the sticky viewport keeps the\n chrome pinned to the visible area with its own scroll. */}\n <SlidePanel open={panelOpen} width={416} className=\"self-stretch\">\n <div className=\"h-full pl-4\">\n <SlidePanelViews\n views={[{\n id: 'detail',\n icon: MessageSquare,\n label: 'Message Detail',\n content: displayMessage ? (\n <StreamMessageDetail\n message={displayMessage}\n filters={{\n onFilterStatus: (v) => setFilter('status', v),\n onFilterStreamName: (v) => setFilter('stream_name', v),\n onFilterMsgType: (v) => setFilter('msg_type', v),\n onFilterTopic: (v) => setFilter('topic', v),\n onFilterWorkflow: (v) => setFilter('workflow_name', v),\n onFilterJid: (v) => setFilter('jid', v),\n onFilterAid: (v) => setFilter('aid', v),\n }}\n />\n ) : null,\n }]}\n activeId=\"detail\"\n onViewChange={() => {}}\n onClose={() => setSelected(null)}\n stickyClassName=\"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9\"\n />\n </div>\n </SlidePanel>\n </div>\n );\n}\n"],"names":["truncateMiddle","str","max","half","StreamMessagesPage","namespace","available","useNamespace","filters","setFilter","pagination","sort","setSort","useFilterParams","selected","setSelected","useState","namespaceOptions","useMemo","id","data","isLoading","refetch","isFetching","useStreamMessages","messages","total","activeMessage","m","panelOpen","lastMessage","setLastMessage","useEffect","displayMessage","columns","row","jsxs","jsx","STATUS_DOT","STATUS_LABEL","SOURCE_BADGE","DateValue","PageHeader","FilterBar","ListToolbar","buildApiPath","FilterSelect","v","SOURCE_OPTIONS","STATUS_OPTIONS","FilterInput","f","X","DataTable","StickyPagination","SlidePanel","SlidePanelViews","MessageSquare","StreamMessageDetail"],"mappings":"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"}
|