@hotmeshio/long-tail 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/dist/assets/AdminDashboard-Bb6zouF5.js +2 -0
- package/dashboard/dist/assets/{AdminDashboard-45Ya2uzl.js.map → AdminDashboard-Bb6zouF5.js.map} +1 -1
- package/dashboard/dist/assets/AgentConfigPage-DqHEK73E.js +13 -0
- package/dashboard/dist/assets/AgentConfigPage-DqHEK73E.js.map +1 -0
- package/dashboard/dist/assets/AgentDetailPage-WwA573u9.js +4 -0
- package/dashboard/dist/assets/AgentDetailPage-WwA573u9.js.map +1 -0
- package/dashboard/dist/assets/AgentsPage-BZkZ_hXN.js +2 -0
- package/dashboard/dist/assets/{AgentsPage--I4d5y9J.js.map → AgentsPage-BZkZ_hXN.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C-Df3ZsZ.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-C-Df3ZsZ.js.map +1 -0
- package/dashboard/dist/assets/BotPicker-CwfVVWxh.js +2 -0
- package/dashboard/dist/assets/{BotPicker-DgbzCesR.js.map → BotPicker-CwfVVWxh.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-DJEQ_5dV.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-B2S8_Gsc.js.map → CapabilitiesPage-DJEQ_5dV.js.map} +1 -1
- package/dashboard/dist/assets/CollapsibleSection-DaFQGU6S.js +2 -0
- package/dashboard/dist/assets/{CollapsibleSection-4Eo3b5ha.js.map → CollapsibleSection-DaFQGU6S.js.map} +1 -1
- package/dashboard/dist/assets/ConfirmDeleteModal-dOxidrSR.js +2 -0
- package/dashboard/dist/assets/{ConfirmDeleteModal-Bac7RmDD.js.map → ConfirmDeleteModal-dOxidrSR.js.map} +1 -1
- package/dashboard/dist/assets/CopyableId-DmLF-RqZ.js +2 -0
- package/dashboard/dist/assets/{CopyableId-BhwdwAJN.js.map → CopyableId-DmLF-RqZ.js.map} +1 -1
- package/dashboard/dist/assets/CredentialsPage-D-tkqdhu.js +2 -0
- package/dashboard/dist/assets/{CredentialsPage-CSEBaYx1.js.map → CredentialsPage-D-tkqdhu.js.map} +1 -1
- package/dashboard/dist/assets/CronLabel-C6iCjsXd.js +2 -0
- package/dashboard/dist/assets/{CronLabel-DV2v2FlP.js.map → CronLabel-C6iCjsXd.js.map} +1 -1
- package/dashboard/dist/assets/CustomDurationPicker--wCtBkmT.js +2 -0
- package/dashboard/dist/assets/{CustomDurationPicker-B_Oxq_nK.js.map → CustomDurationPicker--wCtBkmT.js.map} +1 -1
- package/dashboard/dist/assets/DataTable-D9yuBv0w.js +2 -0
- package/dashboard/dist/assets/{DataTable-etck0Zmp.js.map → DataTable-D9yuBv0w.js.map} +1 -1
- package/dashboard/dist/assets/DropZone-2mGyDo1P.js +2 -0
- package/dashboard/dist/assets/{DropZone-BDpzHWsI.js.map → DropZone-2mGyDo1P.js.map} +1 -1
- package/dashboard/dist/assets/ElapsedCell-DKoH0bqR.js +2 -0
- package/dashboard/dist/assets/{ElapsedCell-D35Z-HSJ.js.map → ElapsedCell-DKoH0bqR.js.map} +1 -1
- package/dashboard/dist/assets/EmptyState-BcsfPq9T.js +2 -0
- package/dashboard/dist/assets/{EmptyState-Bk3_P-b8.js.map → EmptyState-BcsfPq9T.js.map} +1 -1
- package/dashboard/dist/assets/EscalationsOverview-C6A4Q9Ne.js +2 -0
- package/dashboard/dist/assets/{EscalationsOverview-Bt6gGFW4.js.map → EscalationsOverview-C6A4Q9Ne.js.map} +1 -1
- package/dashboard/dist/assets/EventTable-DWxH0vMp.js +2 -0
- package/dashboard/dist/assets/{EventTable-BMk93q8A.js.map → EventTable-DWxH0vMp.js.map} +1 -1
- package/dashboard/dist/assets/EventTopicPill-BUxxvpNg.js +2 -0
- package/dashboard/dist/assets/{EventTopicPill-9LcMnLF0.js.map → EventTopicPill-BUxxvpNg.js.map} +1 -1
- package/dashboard/dist/assets/FilterBar-Ck4K4rzu.js +2 -0
- package/dashboard/dist/assets/{FilterBar-CZGTOMoo.js.map → FilterBar-Ck4K4rzu.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-Tlu1j8fK.js +2 -0
- package/dashboard/dist/assets/{HomePage-Dtk7mgmf.js.map → HomePage-Tlu1j8fK.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-DuON-br0.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-CJEzypCM.js.map → ListToolbar-DuON-br0.js.map} +1 -1
- package/dashboard/dist/assets/McpOverview-byott48x.js +2 -0
- package/dashboard/dist/assets/{McpOverview-ChUa4l3t.js.map → McpOverview-byott48x.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryDetailPage-ieZPpcPn.js +5 -0
- package/dashboard/dist/assets/{McpQueryDetailPage-04CTIN0v.js.map → McpQueryDetailPage-ieZPpcPn.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-BOO0ACYO.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-DFnHFdbr.js.map → McpQueryPage-BOO0ACYO.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-Di8s7-u9.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-B95c3bFw.js.map → McpRunDetailPage-Di8s7-u9.js.map} +1 -1
- package/dashboard/dist/assets/McpRunsPage-DdUVqUFi.js +2 -0
- package/dashboard/dist/assets/{McpRunsPage-DS43YmLU.js.map → McpRunsPage-DdUVqUFi.js.map} +1 -1
- package/dashboard/dist/assets/Modal-DEODGeqx.js +2 -0
- package/dashboard/dist/assets/{Modal-EUrK2c_A.js.map → Modal-DEODGeqx.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-oGmDbNYv.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-DBF_AbRH.js.map → OperatorDashboard-oGmDbNYv.js.map} +1 -1
- package/dashboard/dist/assets/PageHeader-DLjHNYHX.js +2 -0
- package/dashboard/dist/assets/{PageHeader-BuUnJ5NY.js.map → PageHeader-DLjHNYHX.js.map} +1 -1
- package/dashboard/dist/assets/PageHeaderWithStats-Oljg3n4j.js +2 -0
- package/dashboard/dist/assets/{PageHeaderWithStats-cQKaJBAM.js.map → PageHeaderWithStats-Oljg3n4j.js.map} +1 -1
- package/dashboard/dist/assets/PriorityBadge-DfQY9St9.js +2 -0
- package/dashboard/dist/assets/{PriorityBadge-Bl0_pgex.js.map → PriorityBadge-DfQY9St9.js.map} +1 -1
- package/dashboard/dist/assets/ProcessDetailPage-Da-miMYZ.js +2 -0
- package/dashboard/dist/assets/{ProcessDetailPage-DgeXrHon.js.map → ProcessDetailPage-Da-miMYZ.js.map} +1 -1
- package/dashboard/dist/assets/ProcessesListPage-CW-2yFw_.js +2 -0
- package/dashboard/dist/assets/{ProcessesListPage-BGiiH4dW.js.map → ProcessesListPage-CW-2yFw_.js.map} +1 -1
- package/dashboard/dist/assets/RolePill-Bp10-WfX.js +2 -0
- package/dashboard/dist/assets/{RolePill-DsYF2JN9.js.map → RolePill-Bp10-WfX.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-Bg_hEu9H.js +2 -0
- package/dashboard/dist/assets/{RolesPage-CQ7vPamb.js.map → RolesPage-Bg_hEu9H.js.map} +1 -1
- package/dashboard/dist/assets/RowActions-Dg-Fsm5O.js +2 -0
- package/dashboard/dist/assets/{RowActions-DBpvm3Jy.js.map → RowActions-Dg-Fsm5O.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-hYP59xHH.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-ZLKGTYP_.js.map → RunAsSelector-hYP59xHH.js.map} +1 -1
- package/dashboard/dist/assets/ServerName-C9lUCFYb.js +2 -0
- package/dashboard/dist/assets/{ServerName-B5-E7gZD.js.map → ServerName-C9lUCFYb.js.map} +1 -1
- package/dashboard/dist/assets/StatCard-DlgF0CJC.js +2 -0
- package/dashboard/dist/assets/{StatCard-B7ySTryP.js.map → StatCard-DlgF0CJC.js.map} +1 -1
- package/dashboard/dist/assets/StatusBadge-XQlNFwmH.js +2 -0
- package/dashboard/dist/assets/{StatusBadge-DNXTk01O.js.map → StatusBadge-XQlNFwmH.js.map} +1 -1
- package/dashboard/dist/assets/StepIndicator-CuUIGxKk.js +2 -0
- package/dashboard/dist/assets/{StepIndicator-ftNmaJsu.js.map → StepIndicator-CuUIGxKk.js.map} +1 -1
- package/dashboard/dist/assets/StickyPagination-F9FZsRy9.js +2 -0
- package/dashboard/dist/assets/{StickyPagination-CI5AyVVd.js.map → StickyPagination-F9FZsRy9.js.map} +1 -1
- package/dashboard/dist/assets/SwimlaneTimeline-2JHwAM2f.js +2 -0
- package/dashboard/dist/assets/{SwimlaneTimeline-BA4aFrHf.js.map → SwimlaneTimeline-2JHwAM2f.js.map} +1 -1
- package/dashboard/dist/assets/TagInput-Dkljw_WI.js +2 -0
- package/dashboard/dist/assets/{TagInput-DfbVwc27.js.map → TagInput-Dkljw_WI.js.map} +1 -1
- package/dashboard/dist/assets/TaskDetailPage--9FEVeTB.js +2 -0
- package/dashboard/dist/assets/TaskDetailPage--9FEVeTB.js.map +1 -0
- package/dashboard/dist/assets/TaskQueuePill-DPwm25Cc.js +2 -0
- package/dashboard/dist/assets/{TaskQueuePill-Dtsa8CPO.js.map → TaskQueuePill-DPwm25Cc.js.map} +1 -1
- package/dashboard/dist/assets/TasksListPage-kCH4r-70.js +2 -0
- package/dashboard/dist/assets/{TasksListPage-Cw46VTuA.js.map → TasksListPage-kCH4r-70.js.map} +1 -1
- package/dashboard/dist/assets/TimeAgo-RPbch7Te.js +2 -0
- package/dashboard/dist/assets/{TimeAgo-Cx1kK1id.js.map → TimeAgo-RPbch7Te.js.map} +1 -1
- package/dashboard/dist/assets/TimestampCell-Dgpl-lKv.js +2 -0
- package/dashboard/dist/assets/{TimestampCell-VDp4nVn6.js.map → TimestampCell-Dgpl-lKv.js.map} +1 -1
- package/dashboard/dist/assets/ToolPill-D_DIWFJ5.js +2 -0
- package/dashboard/dist/assets/{ToolPill-BNaTJhu8.js.map → ToolPill-D_DIWFJ5.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-D1TWdZQi.js +2 -0
- package/dashboard/dist/assets/{ToolTestPanel-BickLBjP.js.map → ToolTestPanel-D1TWdZQi.js.map} +1 -1
- package/dashboard/dist/assets/UserName-BXZGXJsU.js +2 -0
- package/dashboard/dist/assets/{UserName-DCdb6xnk.js.map → UserName-BXZGXJsU.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-DWlNYb2M.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-BZfxY1iB.js.map → WorkflowExecutionPage-DWlNYb2M.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowPill-BbgVTGgI.js +2 -0
- package/dashboard/dist/assets/{WorkflowPill-BzhfqGa-.js.map → WorkflowPill-BbgVTGgI.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-Dgq8RcD6.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-B7M8kPoH.js.map → WorkflowsDashboard-Dgq8RcD6.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsOverview-DnInrUPO.js +2 -0
- package/dashboard/dist/assets/{WorkflowsOverview-1V8vQ-mo.js.map → WorkflowsOverview-DnInrUPO.js.map} +1 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-z1Z9J-mc.js +2 -0
- package/dashboard/dist/assets/YamlWorkflowsPage-z1Z9J-mc.js.map +1 -0
- package/dashboard/dist/assets/{agents-SXs4tMLb.js → agents-C9RLPt1z.js} +2 -2
- package/dashboard/dist/assets/{agents-SXs4tMLb.js.map → agents-C9RLPt1z.js.map} +1 -1
- package/dashboard/dist/assets/{bots-Ci5aCzDK.js → bots-zyUDnQhH.js} +2 -2
- package/dashboard/dist/assets/{bots-Ci5aCzDK.js.map → bots-zyUDnQhH.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-BiPTCZeL.js → controlplane-v-5KV6pl.js} +2 -2
- package/dashboard/dist/assets/{controlplane-BiPTCZeL.js.map → controlplane-v-5KV6pl.js.map} +1 -1
- package/dashboard/dist/assets/escalation-BseAikei.js +2 -0
- package/dashboard/dist/assets/escalation-BseAikei.js.map +1 -0
- package/dashboard/dist/assets/escalation-columns-Cs2CkkEs.js +2 -0
- package/dashboard/dist/assets/escalation-columns-Cs2CkkEs.js.map +1 -0
- package/dashboard/dist/assets/helpers-DVICI_VA.js +2 -0
- package/dashboard/dist/assets/{helpers-CQZkvg6D.js.map → helpers-DVICI_VA.js.map} +1 -1
- package/dashboard/dist/assets/index-BMIU7Im5.js +63 -0
- package/dashboard/dist/assets/index-BMIU7Im5.js.map +1 -0
- package/dashboard/dist/assets/index-BP76o_S8.js +2 -0
- package/dashboard/dist/assets/{index-DV0_tQW3.js.map → index-BP76o_S8.js.map} +1 -1
- package/dashboard/dist/assets/index-BzBZo8Sn.js +2 -0
- package/dashboard/dist/assets/{index-C7FUIcaY.js.map → index-BzBZo8Sn.js.map} +1 -1
- package/dashboard/dist/assets/index-C0TSBQw8.js +2 -0
- package/dashboard/dist/assets/{index-COiEQlp9.js.map → index-C0TSBQw8.js.map} +1 -1
- package/dashboard/dist/assets/index-CPpNn3z2.js +6 -0
- package/dashboard/dist/assets/{index-DOE7HCzb.js.map → index-CPpNn3z2.js.map} +1 -1
- package/dashboard/dist/assets/index-D2tDlpuv.js +2 -0
- package/dashboard/dist/assets/{index-Bp5f2OWJ.js.map → index-D2tDlpuv.js.map} +1 -1
- package/dashboard/dist/assets/index-DDFK1A8T.js +2 -0
- package/dashboard/dist/assets/{index-q4T_i7zT.js.map → index-DDFK1A8T.js.map} +1 -1
- package/dashboard/dist/assets/index-DVFm5329.js +5 -0
- package/dashboard/dist/assets/index-DVFm5329.js.map +1 -0
- package/dashboard/dist/assets/index-DyqdoZPY.js +2 -0
- package/dashboard/dist/assets/{index-CSsOukxa.js.map → index-DyqdoZPY.js.map} +1 -1
- package/dashboard/dist/assets/index-M17tP_HX.js +15 -0
- package/dashboard/dist/assets/{index-DtbAmRkr.js.map → index-M17tP_HX.js.map} +1 -1
- package/dashboard/dist/assets/index-XCEX7Zof.js +2 -0
- package/dashboard/dist/assets/{index-hfravTJF.js.map → index-XCEX7Zof.js.map} +1 -1
- package/dashboard/dist/assets/index-tK8lfgAj.js +2 -0
- package/dashboard/dist/assets/index-tK8lfgAj.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-D8osen1O.js → knowledge-BhK8xuod.js} +2 -2
- package/dashboard/dist/assets/{knowledge-D8osen1O.js.map → knowledge-BhK8xuod.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CUFhWTyT.js → mcp-CWFliwjc.js} +2 -2
- package/dashboard/dist/assets/{mcp-CUFhWTyT.js.map → mcp-CWFliwjc.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-n1t4sNm7.js → mcp-query-Dm7_m5Fi.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-n1t4sNm7.js.map → mcp-query-Dm7_m5Fi.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-runs-BkRnXbcq.js → mcp-runs-aBDudwEi.js} +2 -2
- package/dashboard/dist/assets/{mcp-runs-BkRnXbcq.js.map → mcp-runs-aBDudwEi.js.map} +1 -1
- package/dashboard/dist/assets/namespaces-C45c4uoO.js +2 -0
- package/dashboard/dist/assets/{namespaces-CacF05ft.js.map → namespaces-C45c4uoO.js.map} +1 -1
- package/dashboard/dist/assets/{roles-CjLCgM_6.js → roles-BMAzzeHR.js} +2 -2
- package/dashboard/dist/assets/{roles-CjLCgM_6.js.map → roles-BMAzzeHR.js.map} +1 -1
- package/dashboard/dist/assets/settings-D0v7RI3o.js +2 -0
- package/dashboard/dist/assets/settings-D0v7RI3o.js.map +1 -0
- package/dashboard/dist/assets/{tasks-BLCzIHol.js → tasks-DwEUQ6my.js} +2 -2
- package/dashboard/dist/assets/{tasks-BLCzIHol.js.map → tasks-DwEUQ6my.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-AwwZnweF.js → useEventHooks-BccPxFR6.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-AwwZnweF.js.map → useEventHooks-BccPxFR6.js.map} +1 -1
- package/dashboard/dist/assets/{useExpandedRows-Cg9iq6Vy.js → useExpandedRows-CkcEntB-.js} +2 -2
- package/dashboard/dist/assets/{useExpandedRows-Cg9iq6Vy.js.map → useExpandedRows-CkcEntB-.js.map} +1 -1
- package/dashboard/dist/assets/{useFilterParams-CGRYFw_A.js → useFilterParams-DZCAaBC7.js} +2 -2
- package/dashboard/dist/assets/{useFilterParams-CGRYFw_A.js.map → useFilterParams-DZCAaBC7.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-9Zs0PXY6.js → useYamlActivityEvents-BBioXSKA.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-9Zs0PXY6.js.map → useYamlActivityEvents-BBioXSKA.js.map} +1 -1
- package/dashboard/dist/assets/{users-BtLRzvZE.js → users-CCHT00of.js} +2 -2
- package/dashboard/dist/assets/{users-BtLRzvZE.js.map → users-CCHT00of.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-1qQ3NKfa.js → vendor-icons-E6836lXZ.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-1qQ3NKfa.js.map → vendor-icons-E6836lXZ.js.map} +1 -1
- package/dashboard/dist/assets/vendor-query-B2UbickB.js +18 -0
- package/dashboard/dist/assets/vendor-query-B2UbickB.js.map +1 -0
- package/dashboard/dist/assets/vendor-react-CX88sFS5.js +22 -0
- package/dashboard/dist/assets/vendor-react-CX88sFS5.js.map +1 -0
- package/dashboard/dist/assets/{workflows-B9xdIsfM.js → workflows-DNZf6Pmq.js} +2 -2
- package/dashboard/dist/assets/{workflows-B9xdIsfM.js.map → workflows-DNZf6Pmq.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-xOJxyEsQ.js → yaml-workflows-BKZdGciI.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-xOJxyEsQ.js.map → yaml-workflows-BKZdGciI.js.map} +1 -1
- package/dashboard/dist/index.html +4 -4
- package/package.json +2 -2
- package/dashboard/dist/assets/AdminDashboard-45Ya2uzl.js +0 -2
- package/dashboard/dist/assets/AgentConfigPage-BOASC5vi.js +0 -13
- package/dashboard/dist/assets/AgentConfigPage-BOASC5vi.js.map +0 -1
- package/dashboard/dist/assets/AgentDetailPage-5M7JTcFz.js +0 -4
- package/dashboard/dist/assets/AgentDetailPage-5M7JTcFz.js.map +0 -1
- package/dashboard/dist/assets/AgentsPage--I4d5y9J.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CXUkRz18.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CXUkRz18.js.map +0 -1
- package/dashboard/dist/assets/BotPicker-DgbzCesR.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-B2S8_Gsc.js +0 -2
- package/dashboard/dist/assets/CollapsibleSection-4Eo3b5ha.js +0 -2
- package/dashboard/dist/assets/ConfirmDeleteModal-Bac7RmDD.js +0 -2
- package/dashboard/dist/assets/CopyableId-BhwdwAJN.js +0 -2
- package/dashboard/dist/assets/CredentialsPage-CSEBaYx1.js +0 -2
- package/dashboard/dist/assets/CronLabel-DV2v2FlP.js +0 -2
- package/dashboard/dist/assets/CustomDurationPicker-B_Oxq_nK.js +0 -2
- package/dashboard/dist/assets/DataTable-etck0Zmp.js +0 -2
- package/dashboard/dist/assets/DropZone-BDpzHWsI.js +0 -2
- package/dashboard/dist/assets/ElapsedCell-D35Z-HSJ.js +0 -2
- package/dashboard/dist/assets/EmptyState-Bk3_P-b8.js +0 -2
- package/dashboard/dist/assets/EscalationsOverview-Bt6gGFW4.js +0 -2
- package/dashboard/dist/assets/EventTable-BMk93q8A.js +0 -2
- package/dashboard/dist/assets/EventTopicPill-9LcMnLF0.js +0 -2
- package/dashboard/dist/assets/FilterBar-CZGTOMoo.js +0 -2
- package/dashboard/dist/assets/HomePage-Dtk7mgmf.js +0 -2
- package/dashboard/dist/assets/ListToolbar-CJEzypCM.js +0 -2
- package/dashboard/dist/assets/McpOverview-ChUa4l3t.js +0 -2
- package/dashboard/dist/assets/McpQueryDetailPage-04CTIN0v.js +0 -5
- package/dashboard/dist/assets/McpQueryPage-DFnHFdbr.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-B95c3bFw.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-DS43YmLU.js +0 -2
- package/dashboard/dist/assets/Modal-EUrK2c_A.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-DBF_AbRH.js +0 -2
- package/dashboard/dist/assets/PageHeader-BuUnJ5NY.js +0 -2
- package/dashboard/dist/assets/PageHeaderWithStats-cQKaJBAM.js +0 -2
- package/dashboard/dist/assets/PriorityBadge-Bl0_pgex.js +0 -2
- package/dashboard/dist/assets/ProcessDetailPage-DgeXrHon.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-BGiiH4dW.js +0 -2
- package/dashboard/dist/assets/RolePill-DsYF2JN9.js +0 -2
- package/dashboard/dist/assets/RolesPage-CQ7vPamb.js +0 -2
- package/dashboard/dist/assets/RowActions-DBpvm3Jy.js +0 -2
- package/dashboard/dist/assets/RunAsSelector-ZLKGTYP_.js +0 -2
- package/dashboard/dist/assets/ServerName-B5-E7gZD.js +0 -2
- package/dashboard/dist/assets/StatCard-B7ySTryP.js +0 -2
- package/dashboard/dist/assets/StatusBadge-DNXTk01O.js +0 -2
- package/dashboard/dist/assets/StepIndicator-ftNmaJsu.js +0 -2
- package/dashboard/dist/assets/StickyPagination-CI5AyVVd.js +0 -2
- package/dashboard/dist/assets/SwimlaneTimeline-BA4aFrHf.js +0 -2
- package/dashboard/dist/assets/TagInput-DfbVwc27.js +0 -2
- package/dashboard/dist/assets/TaskDetailPage-A_kHjYRn.js +0 -2
- package/dashboard/dist/assets/TaskDetailPage-A_kHjYRn.js.map +0 -1
- package/dashboard/dist/assets/TaskQueuePill-Dtsa8CPO.js +0 -2
- package/dashboard/dist/assets/TasksListPage-Cw46VTuA.js +0 -2
- package/dashboard/dist/assets/TimeAgo-Cx1kK1id.js +0 -2
- package/dashboard/dist/assets/TimestampCell-VDp4nVn6.js +0 -2
- package/dashboard/dist/assets/ToolPill-BNaTJhu8.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-BickLBjP.js +0 -2
- package/dashboard/dist/assets/UserName-DCdb6xnk.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-BZfxY1iB.js +0 -2
- package/dashboard/dist/assets/WorkflowPill-BzhfqGa-.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-B7M8kPoH.js +0 -2
- package/dashboard/dist/assets/WorkflowsOverview-1V8vQ-mo.js +0 -2
- package/dashboard/dist/assets/YamlWorkflowsPage-BteCRoV5.js +0 -2
- package/dashboard/dist/assets/YamlWorkflowsPage-BteCRoV5.js.map +0 -1
- package/dashboard/dist/assets/escalation-D-zr9D9G.js +0 -2
- package/dashboard/dist/assets/escalation-D-zr9D9G.js.map +0 -1
- package/dashboard/dist/assets/escalation-columns-Bpp7Sdbd.js +0 -2
- package/dashboard/dist/assets/escalation-columns-Bpp7Sdbd.js.map +0 -1
- package/dashboard/dist/assets/helpers-CQZkvg6D.js +0 -2
- package/dashboard/dist/assets/index-Bp5f2OWJ.js +0 -2
- package/dashboard/dist/assets/index-C7FUIcaY.js +0 -2
- package/dashboard/dist/assets/index-COiEQlp9.js +0 -2
- package/dashboard/dist/assets/index-CSsOukxa.js +0 -2
- package/dashboard/dist/assets/index-DOE7HCzb.js +0 -6
- package/dashboard/dist/assets/index-DV0_tQW3.js +0 -2
- package/dashboard/dist/assets/index-Da8R5Fn_.js +0 -281
- package/dashboard/dist/assets/index-Da8R5Fn_.js.map +0 -1
- package/dashboard/dist/assets/index-DtbAmRkr.js +0 -15
- package/dashboard/dist/assets/index-DzL5pT70.js +0 -5
- package/dashboard/dist/assets/index-DzL5pT70.js.map +0 -1
- package/dashboard/dist/assets/index-OTsFiHXP.js +0 -2
- package/dashboard/dist/assets/index-OTsFiHXP.js.map +0 -1
- package/dashboard/dist/assets/index-hfravTJF.js +0 -2
- package/dashboard/dist/assets/index-q4T_i7zT.js +0 -2
- package/dashboard/dist/assets/namespaces-CacF05ft.js +0 -2
- package/dashboard/dist/assets/vendor-query-DLp59M9_.js +0 -35
- package/dashboard/dist/assets/vendor-query-DLp59M9_.js.map +0 -1
- package/dashboard/dist/assets/vendor-react-Co3Y8ikm.js +0 -26
- package/dashboard/dist/assets/vendor-react-Co3Y8ikm.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DVFm5329.js","sources":["../../src/pages/operator/escalation-detail/EscalationActionBar.tsx","../../src/pages/operator/escalation-detail/EscalationHero.tsx","../../src/components/common/display/SimpleMarkdown.tsx","../../src/components/escalation/RoundsExhaustedContext.tsx","../../src/components/escalation/TriageContext.tsx","../../src/components/escalation/ResolverForm.tsx","../../src/pages/operator/escalation-detail/ResolverSection.tsx","../../src/pages/operator/escalation-detail/EscalationDetailSections.tsx","../../src/pages/operator/escalation-detail/EscalationDetailPage.tsx"],"sourcesContent":["import { useState, useCallback } from 'react';\nimport { CountdownTimer } from '../../../components/common/display/CountdownTimer';\nimport { UserName } from '../../../components/common/display/UserName';\nimport { CustomDurationPicker } from '../../../components/common/form/CustomDurationPicker';\nimport { useClaimDurations } from '../../../hooks/useClaimDurations';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ActionBarMode =\n | 'available' // unclaimed — show claim controls\n | 'claimed_by_me' // I own it — show resolve/escalate/release\n | 'claimed_by_other'// someone else has it\n | 'terminal'; // resolved or cancelled — nothing to do\n\nexport type ActiveView = 'resolve' | 'escalate' | 'release';\n\nexport interface EscalationActionBarProps {\n mode: ActionBarMode;\n // Active view (controlled by parent)\n activeView: ActiveView;\n onActiveViewChange: (view: ActiveView) => void;\n // Claim\n onClaim: (minutes: number) => void;\n claimPending: boolean;\n // Resolve — JSON lives in viewport, bar reads it for submit\n workflowType: string | null;\n json: string;\n onResolve: (payload: Record<string, unknown>) => void;\n resolvePending: boolean;\n resolveError: Error | null;\n // Triage (controlled by parent — callout + overlay render in page body)\n requestTriage: boolean;\n triageNotes: string;\n // Escalate\n currentRole: string;\n escalationTargets: string[];\n onEscalate: (role: string) => void;\n escalatePending: boolean;\n escalateError: Error | null;\n // Release\n onRelease: () => void;\n releasePending: boolean;\n // Other user\n assignedTo?: string | null;\n assignedUntil?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function EscalationActionBar(props: EscalationActionBarProps) {\n const {\n mode, activeView, onActiveViewChange,\n onClaim, claimPending,\n workflowType, json, onResolve, resolvePending, resolveError,\n requestTriage, triageNotes,\n currentRole, escalationTargets, onEscalate, escalatePending, escalateError,\n onRelease, releasePending,\n assignedTo, assignedUntil,\n } = props;\n\n const claimDurations = useClaimDurations();\n const [duration, setDuration] = useState('30');\n const [customMinutes, setCustomMinutes] = useState(0);\n const [parseError, setParseError] = useState('');\n const [escalateTarget, setEscalateTarget] = useState('');\n\n const isCustom = duration === 'custom';\n const onCustomChange = useCallback((m: number) => setCustomMinutes(m), []);\n\n if (mode === 'terminal') return null;\n\n const handleClaim = () => {\n const minutes = isCustom ? customMinutes : parseInt(duration);\n if (!minutes || minutes <= 0) return;\n onClaim(minutes);\n };\n\n const handleSubmitResolve = () => {\n setParseError('');\n\n // When triage is requested, ignore the form payload entirely.\n // Only the triage flag and notes matter — the form data (e.g.\n // approved: true) must NOT leak through, as it would confuse\n // the triage workflow into thinking the issue is already resolved.\n if (requestTriage) {\n const payload: Record<string, unknown> = {\n _lt: { needsTriage: true },\n };\n if (triageNotes.trim()) payload.notes = triageNotes.trim();\n onResolve(payload);\n return;\n }\n\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(json);\n } catch {\n setParseError('Invalid JSON');\n return;\n }\n onResolve(payload);\n };\n\n const tabClass = (active: boolean) =>\n `text-xs transition-colors ${active ? 'text-accent font-medium' : 'text-text-tertiary hover:text-accent'}`;\n\n return (\n <div className=\"sticky h-[80px] bg-surface/95 backdrop-blur-sm border-t border-surface-border -mx-10 px-10 pt-3 pb-5 z-10\" style={{ bottom: 'calc(var(--feed-height, 0px) - 8px)' }} data-testid=\"escalation-action-bar\">\n\n {/* ── Available: claim ── */}\n {mode === 'available' && (\n <div data-testid=\"claim-bar\">\n {/* Duration tab row */}\n <div className=\"flex items-center gap-4 mb-2\">\n {claimDurations.map((opt) => (\n <button\n key={opt.value}\n onClick={() => { setDuration(opt.value); setCustomMinutes(0); }}\n className={tabClass(!isCustom && duration === opt.value)}\n >\n {opt.label}\n </button>\n ))}\n <button\n onClick={() => setDuration('custom')}\n className={tabClass(isCustom)}\n >\n Other\n </button>\n </div>\n {/* Action row — right-aligned */}\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-1\" />\n {isCustom && (\n <CustomDurationPicker onChange={onCustomChange} compact autoFocus />\n )}\n <button\n onClick={handleClaim}\n disabled={claimPending || (isCustom && customMinutes <= 0)}\n className=\"btn-primary text-xs\"\n >\n {claimPending ? 'Claiming...' : 'Claim'}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Claimed by other ── */}\n {mode === 'claimed_by_other' && (\n <div className=\"flex items-center gap-4\" data-testid=\"claimed-other-bar\">\n <p className=\"text-sm text-text-secondary\">\n Claimed by <span className=\"font-medium text-text-primary\">{assignedTo ? <UserName userId={assignedTo} /> : 'unknown'}</span>\n </p>\n {assignedUntil && <CountdownTimer until={assignedUntil} />}\n </div>\n )}\n\n {/* ── Claimed by me ── */}\n {mode === 'claimed_by_me' && (\n <div data-testid=\"action-bar\">\n {/* Tab row */}\n <div className=\"flex items-center gap-4 mb-2\">\n <button\n onClick={() => onActiveViewChange('resolve')}\n className={tabClass(activeView === 'resolve')}\n >\n {workflowType ? 'Resolve' : 'Acknowledge'}\n </button>\n {escalationTargets.length > 0 && (\n <button\n onClick={() => onActiveViewChange('escalate')}\n className={tabClass(activeView === 'escalate')}\n >\n Escalate\n </button>\n )}\n <button\n onClick={() => onActiveViewChange('release')}\n className={`text-xs transition-colors ${activeView === 'release' ? 'text-status-error font-medium' : 'text-text-tertiary hover:text-status-error'}`}\n >\n Release\n </button>\n </div>\n\n {/* ── Resolve controls ── */}\n {activeView === 'resolve' && (\n workflowType ? (\n <div className=\"flex items-center gap-4\">\n <div className=\"flex-1\" />\n\n {parseError && <span className=\"text-xs text-status-error\">{parseError}</span>}\n {resolveError && <span className=\"text-xs text-status-error\">{resolveError.message}</span>}\n\n <button\n onClick={handleSubmitResolve}\n disabled={resolvePending}\n className=\"btn-primary text-xs\"\n >\n {resolvePending ? 'Submitting...' : requestTriage ? 'Send to Triage' : 'Submit'}\n </button>\n </div>\n ) : (\n <div className=\"flex items-center\">\n <span className=\"text-xs text-text-secondary\">Notification — acknowledge to resolve</span>\n <div className=\"flex-1\" />\n {resolveError && <span className=\"text-xs text-status-error mr-3\">{resolveError.message}</span>}\n <button\n onClick={() => onResolve({ acknowledged: true })}\n disabled={resolvePending}\n className=\"btn-primary text-xs\"\n >\n {resolvePending ? 'Acknowledging...' : 'Acknowledge'}\n </button>\n </div>\n )\n )}\n\n {/* ── Escalate controls ── */}\n {activeView === 'escalate' && (\n <div className=\"flex items-center gap-3\">\n <span className=\"text-xs text-text-secondary\">\n From <span className=\"font-medium text-text-primary\">{currentRole}</span> to\n </span>\n <select\n value={escalateTarget}\n onChange={(e) => setEscalateTarget(e.target.value)}\n className=\"select text-xs\"\n data-testid=\"escalate-select\"\n >\n <option value=\"\">Select role...</option>\n {escalationTargets.map((role) => (\n <option key={role} value={role}>{role}</option>\n ))}\n </select>\n <div className=\"flex-1\" />\n {escalateError && <span className=\"text-xs text-status-error\">{escalateError.message}</span>}\n <button\n onClick={() => onEscalate(escalateTarget)}\n disabled={!escalateTarget || escalatePending}\n className=\"btn-primary text-xs\"\n >\n {escalatePending ? 'Escalating...' : 'Escalate'}\n </button>\n </div>\n )}\n\n {/* ── Release controls ── */}\n {activeView === 'release' && (\n <div className=\"flex items-center gap-3\">\n <span className=\"text-xs text-text-secondary\">Release back to pool?</span>\n <div className=\"flex-1\" />\n <button onClick={() => onActiveViewChange('resolve')} className=\"btn-secondary text-xs\">\n Cancel\n </button>\n <button\n onClick={onRelease}\n disabled={releasePending}\n className=\"btn-primary text-xs bg-status-error hover:bg-status-error/80\"\n >\n {releasePending ? 'Releasing...' : 'Yes, Release'}\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Bell, User } from 'lucide-react';\nimport { StatusBadge } from '../../../components/common/display/StatusBadge';\nimport { RolePill } from '../../../components/common/display/RolePill';\nimport { CountdownTimer } from '../../../components/common/display/CountdownTimer';\nimport { Collapsible } from '../../../components/common/layout/Collapsible';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { CopyableId } from '../../../components/common/display/CopyableId';\nimport { UserName } from '../../../components/common/display/UserName';\nimport { isAckEscalation } from '../../../lib/escalation';\nimport type { LTEscalationRecord } from '../../../api/types';\n\nexport function EscalationHero({\n esc,\n claimedByMe: _claimedByMe,\n claimed,\n isTerminal,\n traceUrl,\n}: {\n esc: LTEscalationRecord;\n claimedByMe: boolean;\n claimed: boolean;\n isTerminal: boolean;\n traceUrl: string | null;\n}) {\n const [showDetails, setShowDetails] = useState(false);\n const isAck = isAckEscalation(esc);\n\n return (\n <>\n {/* Title */}\n <div className=\"flex items-center gap-3 mb-2\">\n {isAck && <Bell className=\"w-5 h-5 text-text-tertiary shrink-0\" />}\n <p className=\"text-[1.5rem] leading-snug font-light text-text-secondary\">\n {esc.type}{esc.subtype ? ` / ${esc.subtype}` : ''}\n </p>\n </div>\n\n {/* Description */}\n {esc.description && (\n <p className=\"text-sm leading-relaxed text-text-tertiary mb-4\">\n {esc.description}\n </p>\n )}\n\n {/* Meta bar — labeled sections, baseline-aligned values */}\n <div className=\"flex flex-wrap items-end gap-x-6 gap-y-3 mt-4 mb-2\">\n {/* Status */}\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">Status</p>\n <span className=\"mb-1 inline-block\"><StatusBadge status={esc.status} /></span>\n </div>\n\n {/* Role */}\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">Role</p>\n <RolePill role={esc.role} size=\"md\" />\n </div>\n\n {/* Created */}\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">Created</p>\n <span className=\"inline-flex items-center mb-1 text-xs text-text-secondary\">\n <DateValue date={esc.created_at} />\n </span>\n </div>\n\n {/* Claimed by */}\n {esc.assigned_to && (\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">Claimed by</p>\n <span className=\"inline-flex items-center gap-1.5 text-xs font-medium text-text-primary\">\n <User className=\"w-3 h-3 shrink-0 text-accent/75\" />\n <UserName userId={esc.assigned_to} />\n </span>\n </div>\n )}\n\n {/* Time left */}\n {claimed && !isTerminal && esc.assigned_until && (\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">Time left</p>\n <span className=\"inline-flex items-center h-5\"><CountdownTimer until={esc.assigned_until} /></span>\n </div>\n )}\n\n {/* Resolved */}\n {esc.resolved_at && (\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">Resolved</p>\n <span className=\"inline-flex items-center h-5 text-xs text-text-secondary\">\n <DateValue date={esc.resolved_at} />\n </span>\n </div>\n )}\n\n {/* Details toggle */}\n <div>\n <button\n onClick={() => setShowDetails(!showDetails)}\n className=\"inline-flex items-center gap-1 h-5 text-xs text-text-tertiary hover:text-accent transition-colors\"\n >\n Details\n <svg\n className={`w-3 h-3 transition-transform duration-200 ${showDetails ? 'rotate-180' : ''}`}\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n </div>\n </div>\n\n <Collapsible open={showDetails}>\n <div className=\"mt-4 bg-surface-raised border border-surface-border rounded-md p-4 flex flex-wrap gap-x-8 gap-y-4\">\n <div className=\"text-left\">\n <span className=\"text-[11px] font-medium text-text-secondary uppercase tracking-wide\">Priority</span>\n <p className=\"text-[12px] text-text-primary mt-0.5\">P{esc.priority}</p>\n </div>\n <CopyableId label=\"Escalation ID\" value={esc.id} />\n {esc.task_id && (\n <CopyableId label=\"Task\" value={esc.task_id} href={`/workflows/tasks/detail/${esc.task_id}`} />\n )}\n <CopyableId label=\"Workflow\" value={esc.workflow_type} />\n <CopyableId label=\"Workflow ID\" value={esc.workflow_id} />\n <CopyableId label=\"Task Queue\" value={esc.task_queue} />\n {esc.origin_id && esc.origin_id !== esc.workflow_id && (\n <CopyableId label=\"Origin\" value={esc.origin_id} />\n )}\n {esc.trace_id && (\n <CopyableId\n label=\"Trace\"\n value={esc.trace_id}\n href={traceUrl ? traceUrl.replace('{traceId}', esc.trace_id) : undefined}\n external\n />\n )}\n </div>\n </Collapsible>\n </>\n );\n}\n","/**\n * Lightweight markdown-to-HTML renderer for simple patterns.\n * No external dependency — handles bold, italic, code, links, headers, lists.\n */\n\nfunction renderInline(text: string): string {\n return text\n // Code spans\n .replace(/`([^`]+)`/g, '<code class=\"px-1 py-0.5 bg-surface-sunken rounded text-xs font-mono\">$1</code>')\n // Bold + italic\n .replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, '<strong><em>$1</em></strong>')\n // Bold\n .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n // Italic\n .replace(/\\*(.+?)\\*/g, '<em>$1</em>')\n // Links\n .replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" class=\"text-accent-primary hover:underline\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>');\n}\n\nexport function SimpleMarkdown({ content, compact }: { content: string; compact?: boolean }) {\n // Extract fenced code blocks before line-by-line processing\n const segments: Array<{ type: 'code'; lang: string; code: string } | { type: 'text'; text: string }> = [];\n const fencePattern = /^```(\\w*)\\n([\\s\\S]*?)^```$/gm;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = fencePattern.exec(content)) !== null) {\n if (match.index > lastIndex) {\n segments.push({ type: 'text', text: content.slice(lastIndex, match.index) });\n }\n segments.push({ type: 'code', lang: match[1], code: match[2].replace(/\\n$/, '') });\n lastIndex = match.index + match[0].length;\n }\n if (lastIndex < content.length) {\n segments.push({ type: 'text', text: content.slice(lastIndex) });\n }\n\n const sizeClasses = compact\n ? { text: 'text-xs', heading: 'text-xs', list: 'text-xs', code: 'text-[11px]' }\n : { text: 'text-sm', heading: 'text-sm', list: 'text-sm', code: 'text-xs' };\n\n const allParts: string[] = [];\n for (const segment of segments) {\n if (segment.type === 'code') {\n const escaped = segment.code.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n allParts.push(\n `<pre class=\"my-2 p-2.5 bg-surface-sunken rounded-md overflow-x-auto\"><code class=\"${sizeClasses.code} font-mono text-text-secondary leading-relaxed\">${escaped}</code></pre>`,\n );\n continue;\n }\n allParts.push(...renderTextBlock(segment.text, sizeClasses));\n }\n\n return (\n <div\n className=\"prose-sm\"\n dangerouslySetInnerHTML={{ __html: allParts.join('\\n') }}\n />\n );\n}\n\nfunction renderTextBlock(\n text: string,\n sz: { text: string; heading: string; list: string; code: string },\n): string[] {\n const lines = text.split('\\n');\n const htmlParts: string[] = [];\n let inList = false;\n let inTable = false;\n let tableRows: string[][] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Table rows\n if (trimmed.startsWith('|') && trimmed.endsWith('|')) {\n const cells = trimmed.slice(1, -1).split('|').map((c) => c.trim());\n // Skip separator rows (|---|---|)\n if (cells.every((c) => /^[-:]+$/.test(c))) continue;\n if (!inTable) {\n inTable = true;\n tableRows = [];\n }\n tableRows.push(cells);\n continue;\n }\n if (inTable) {\n inTable = false;\n const [header, ...body] = tableRows;\n htmlParts.push('<div class=\"overflow-x-auto my-2\"><table class=\"text-xs w-full\"><thead><tr>');\n for (const h of header) {\n htmlParts.push(`<th class=\"text-left py-1 px-2 border-b border-border text-text-secondary font-medium\">${renderInline(h)}</th>`);\n }\n htmlParts.push('</tr></thead><tbody>');\n for (const row of body) {\n htmlParts.push('<tr>');\n for (const cell of row) {\n htmlParts.push(`<td class=\"py-1 px-2 border-b border-border/50\">${renderInline(cell)}</td>`);\n }\n htmlParts.push('</tr>');\n }\n htmlParts.push('</tbody></table></div>');\n tableRows = [];\n }\n\n // Empty line\n if (!trimmed) {\n if (inList) { htmlParts.push('</ul>'); inList = false; }\n continue;\n }\n\n // Headers\n if (trimmed.startsWith('### ')) {\n if (inList) { htmlParts.push('</ul>'); inList = false; }\n htmlParts.push(`<h4 class=\"${sz.heading} font-semibold text-text-primary mt-3 mb-1\">${renderInline(trimmed.slice(4))}</h4>`);\n continue;\n }\n if (trimmed.startsWith('## ')) {\n if (inList) { htmlParts.push('</ul>'); inList = false; }\n htmlParts.push(`<h3 class=\"${sz.heading} font-semibold text-text-primary mt-3 mb-1\">${renderInline(trimmed.slice(3))}</h3>`);\n continue;\n }\n\n // Horizontal rule\n if (/^[-*_]{3,}$/.test(trimmed)) {\n if (inList) { htmlParts.push('</ul>'); inList = false; }\n htmlParts.push('<hr class=\"border-border my-3\" />');\n continue;\n }\n\n // List items\n if (/^[-*] /.test(trimmed)) {\n if (!inList) { htmlParts.push('<ul class=\"space-y-1 my-1\">'); inList = true; }\n htmlParts.push(`<li class=\"${sz.list} text-text-secondary flex gap-2\"><span class=\"text-text-tertiary shrink-0\">-</span><span>${renderInline(trimmed.slice(2))}</span></li>`);\n continue;\n }\n\n // Paragraph\n if (inList) { htmlParts.push('</ul>'); inList = false; }\n htmlParts.push(`<p class=\"${sz.text} text-text-secondary my-1\">${renderInline(trimmed)}</p>`);\n }\n\n // Flush any remaining table\n if (inTable && tableRows.length) {\n const [header, ...body] = tableRows;\n htmlParts.push('<div class=\"overflow-x-auto my-2\"><table class=\"text-xs w-full\"><thead><tr>');\n for (const h of header) {\n htmlParts.push(`<th class=\"text-left py-1 px-2 border-b border-border text-text-secondary font-medium\">${renderInline(h)}</th>`);\n }\n htmlParts.push('</tr></thead><tbody>');\n for (const row of body) {\n htmlParts.push('<tr>');\n for (const cell of row) {\n htmlParts.push(`<td class=\"py-1 px-2 border-b border-border/50\">${renderInline(cell)}</td>`);\n }\n htmlParts.push('</tr>');\n }\n htmlParts.push('</tbody></table></div>');\n }\n\n if (inList) htmlParts.push('</ul>');\n\n return htmlParts;\n}\n","import { useState } from 'react';\nimport { Link } from 'react-router-dom';\n\nimport { JsonViewer } from '../common/data/JsonViewer';\nimport { SimpleMarkdown } from '../common/display/SimpleMarkdown';\n\ninterface RoundsExhaustedContextProps {\n payload: Record<string, unknown>;\n isTerminal?: boolean;\n resolverPayload?: Record<string, unknown> | null;\n onRetryTriage?: () => void;\n isRetrying?: boolean;\n}\n\nfunction SectionLabel({ children }: { children: React.ReactNode }) {\n return (\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">{children}</p>\n );\n}\n\nexport function RoundsExhaustedContext({ payload, isTerminal, resolverPayload, onRetryTriage, isRetrying }: RoundsExhaustedContextProps) {\n const title = payload.title as string | undefined;\n const summary = payload.summary as string | undefined;\n const diagnosis = payload.diagnosis as string | undefined;\n const toolCalls = payload.tool_calls_made as number | undefined;\n const result = payload.result as Record<string, unknown> | null | undefined;\n\n // Detect triage resolution\n const ltMeta = resolverPayload?._lt as Record<string, unknown> | undefined;\n const wasTriaged = ltMeta?.triaged === true;\n const triageWorkflowId = ltMeta?.triageWorkflowId as string | undefined;\n const isResolvedByTriage = isTerminal && wasTriaged;\n\n const [showResult, setShowResult] = useState(false);\n\n // Resolved by triage — show success state\n if (isResolvedByTriage) {\n return (\n <div className=\"rounded-md border border-status-success/30 bg-surface-raised\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-surface-border\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"w-4 h-4 text-status-success shrink-0\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M8 1a7 7 0 110 14A7 7 0 018 1zm3.36 4.65a.5.5 0 00-.72 0L7 9.29 5.36 7.65a.5.5 0 10-.72.7l2 2a.5.5 0 00.72 0l4-4a.5.5 0 000-.7z\" />\n </svg>\n <span className=\"text-xs font-medium text-status-success\">Resolved by AI Triage</span>\n </div>\n {typeof toolCalls === 'number' && (\n <span className=\"text-[10px] font-mono px-2 py-0.5 rounded-full bg-status-success/10 text-status-success\">\n {toolCalls} tool calls used\n </span>\n )}\n </div>\n\n {/* Body */}\n <div className=\"px-4 py-4 space-y-4\">\n {title && (\n <p className=\"text-sm font-medium text-text-primary\">{title}</p>\n )}\n\n {diagnosis && (\n <div>\n <SectionLabel>Triage diagnosis</SectionLabel>\n <div className=\"text-xs text-text-primary leading-relaxed\">\n <SimpleMarkdown content={diagnosis} />\n </div>\n </div>\n )}\n\n <div className=\"flex items-center gap-3\">\n {triageWorkflowId && (\n <Link\n to={`/workflows/executions/${triageWorkflowId}`}\n className=\"text-[10px] text-accent hover:underline\"\n >\n View triage execution\n </Link>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n // Default: warning state\n return (\n <div className=\"rounded-md border border-status-warning/30 bg-surface-raised\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-surface-border\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"w-4 h-4 text-status-warning shrink-0\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M8 1a7 7 0 110 14A7 7 0 018 1zm0 3a.75.75 0 00-.75.75v3.5a.75.75 0 001.5 0v-3.5A.75.75 0 008 4zm0 7a.75.75 0 100-1.5.75.75 0 000 1.5z\" />\n </svg>\n <span className=\"text-xs font-medium text-status-warning\">Tool Rounds Exhausted</span>\n </div>\n {typeof toolCalls === 'number' && (\n <span className=\"text-[10px] font-mono px-2 py-0.5 rounded-full bg-status-warning/10 text-status-warning\">\n {toolCalls} tool calls used\n </span>\n )}\n </div>\n\n {/* Body */}\n <div className=\"px-4 py-4 space-y-4\">\n {title && (\n <p className=\"text-sm font-medium text-text-primary\">{title}</p>\n )}\n\n {summary && (\n <div>\n <SectionLabel>What happened</SectionLabel>\n <div className=\"text-xs text-text-secondary leading-relaxed\">\n <SimpleMarkdown content={summary} />\n </div>\n </div>\n )}\n\n {diagnosis && (\n <div>\n <SectionLabel>What went wrong</SectionLabel>\n <div className=\"text-xs text-text-primary leading-relaxed\">\n <SimpleMarkdown content={diagnosis} />\n </div>\n </div>\n )}\n\n {result != null && (\n <div>\n <button\n onClick={() => setShowResult(!showResult)}\n className=\"flex items-center gap-1 text-[10px] font-semibold uppercase tracking-widest text-text-tertiary hover:text-text-secondary transition-colors\"\n >\n <svg className={`w-3 h-3 transition-transform ${showResult ? 'rotate-90' : ''}`} viewBox=\"0 0 12 12\" fill=\"currentColor\">\n <path d=\"M4.5 2l4 4-4 4\" />\n </svg>\n Partial results\n </button>\n {showResult && (\n <div className=\"mt-2\">\n <JsonViewer data={result} defaultMode=\"tree\" />\n </div>\n )}\n </div>\n )}\n\n {onRetryTriage && !isTerminal && (\n <div className=\"pt-2\">\n <button\n onClick={onRetryTriage}\n disabled={isRetrying}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-xs font-medium bg-accent text-text-inverse rounded-md hover:bg-accent/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 14 14\" fill=\"currentColor\">\n <path d=\"M7 1a6 6 0 100 12A6 6 0 007 1zm2.5 6.5l-3.5 2V5.5l3.5 2z\" />\n </svg>\n {isRetrying ? 'Sending to triage...' : 'Retry with AI Triage'}\n </button>\n </div>\n )}\n </div>\n </div>\n );\n}\n","interface TriageData {\n diagnosis?: string;\n actions_taken?: string[];\n tool_calls_made?: number;\n confidence?: number;\n recommendation?: string;\n correctedData?: Record<string, unknown>;\n originalData?: Record<string, unknown>;\n}\n\ntype Diff = { key: string; label: string; original: unknown; corrected: unknown };\n\n/**\n * Renders a triage summary when escalation payload contains `_triage`.\n *\n * Fully generic — no knowledge of workflow types or field semantics.\n * Diffs `_triage.originalData` against the payload to detect changes.\n * Follows the unboxed section pattern used throughout the dashboard.\n */\nexport function TriageContext({ triage, payload }: {\n triage: TriageData;\n payload: Record<string, unknown>;\n}) {\n const confidence = triage.confidence ?? 0;\n const confidenceColor =\n confidence >= 0.8 ? 'text-status-success' :\n confidence >= 0.5 ? 'text-status-pending' :\n 'text-status-error';\n\n // Generic diff: compare originalData fields to current payload\n const diffs = computeDiffs(triage.originalData, payload);\n\n return (\n <div className=\"space-y-5\">\n {/* Diagnosis + metadata — unboxed, natural flow */}\n {triage.diagnosis && (\n <p className=\"text-sm text-text-primary leading-relaxed\">\n {triage.diagnosis}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-3 text-xs text-text-tertiary\">\n {triage.tool_calls_made != null && (\n <span>{triage.tool_calls_made} tool call{triage.tool_calls_made !== 1 ? 's' : ''}</span>\n )}\n {triage.tool_calls_made != null && <span className=\"text-text-quaternary\">·</span>}\n <span className={`font-medium ${confidenceColor}`}>\n {Math.round(confidence * 100)}% confidence\n </span>\n </div>\n\n {triage.actions_taken && triage.actions_taken.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {triage.actions_taken.map((action, i) => (\n <span\n key={i}\n className=\"inline-flex items-center gap-1.5 px-2 py-0.5 text-[11px]\n text-text-secondary\"\n >\n <svg className=\"w-3 h-3 text-status-success shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {action}\n </span>\n ))}\n </div>\n )}\n\n {triage.recommendation && (\n <p className=\"text-[11px] text-text-tertiary italic\">\n {triage.recommendation}\n </p>\n )}\n\n {/* Generic before/after diffs — separated by subtle dividers */}\n {diffs.length > 0 && (\n <div className=\"space-y-4 pt-2\">\n {diffs.map((diff) => (\n <DiffRow key={diff.key} diff={diff} />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Generic diff computation\n// ---------------------------------------------------------------------------\n\nfunction computeDiffs(\n original: Record<string, unknown> | undefined,\n current: Record<string, unknown>,\n): Diff[] {\n if (!original) return [];\n\n const diffs: Diff[] = [];\n for (const key of Object.keys(original)) {\n if (key.startsWith('_')) continue;\n const origVal = original[key];\n const currVal = current[key];\n if (currVal === undefined) continue;\n\n if (JSON.stringify(origVal) !== JSON.stringify(currVal)) {\n diffs.push({\n key,\n label: key.replace(/[_-]/g, ' '),\n original: origVal,\n corrected: currVal,\n });\n }\n }\n return diffs;\n}\n\n// ---------------------------------------------------------------------------\n// Diff row — clean, unboxed before/after\n// ---------------------------------------------------------------------------\n\nfunction DiffRow({ diff }: { diff: Diff }) {\n const origStr = renderValue(diff.original);\n const corrStr = renderValue(diff.corrected);\n\n // Both are primitives — side by side with subtle separator\n if (origStr !== null && corrStr !== null) {\n return (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-3\">\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal\">(original)</span>\n </p>\n <p className=\"text-sm text-text-tertiary leading-relaxed line-through decoration-text-tertiary/30\">\n {origStr}\n </p>\n </div>\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal text-status-success\">(corrected)</span>\n </p>\n <p className=\"text-sm text-text-primary leading-relaxed\">\n {corrStr}\n </p>\n </div>\n </div>\n );\n }\n\n // Complex values — stacked\n return (\n <div className=\"space-y-3\">\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal\">(original)</span>\n </p>\n <pre className=\"text-xs text-text-tertiary font-mono whitespace-pre-wrap leading-relaxed\">\n {typeof diff.original === 'object' ? JSON.stringify(diff.original, null, 2) : String(diff.original)}\n </pre>\n </div>\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal text-status-success\">(corrected)</span>\n </p>\n <pre className=\"text-xs text-text-primary font-mono whitespace-pre-wrap leading-relaxed\">\n {typeof diff.corrected === 'object' ? JSON.stringify(diff.corrected, null, 2) : String(diff.corrected)}\n </pre>\n </div>\n </div>\n );\n}\n\n/** Render a value as a string if it's a primitive, null otherwise */\nfunction renderValue(val: unknown): string | null {\n if (val === null || val === undefined) return 'null';\n if (typeof val === 'string') return val;\n if (typeof val === 'number' || typeof val === 'boolean') return String(val);\n return null;\n}\n","import { useState, useEffect, useCallback } from 'react';\n\ntype JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\n/**\n * Renders a JSON object as an editable form with typed inputs.\n *\n * - Strings → text input (textarea if > 80 chars)\n * - Booleans → toggle switch\n * - Numbers → number input\n * - Null → disabled placeholder\n * - Objects → nested section\n * - Arrays of strings → tag display\n * - Keys starting with `_` → hidden (preserved in output)\n *\n * Calls `onChange` with the full JSON string on every edit.\n */\nexport function ResolverForm({ value, onChange }: {\n value: string;\n onChange: (json: string) => void;\n}) {\n const [data, setData] = useState<Record<string, JsonValue>>({});\n const [hidden, setHidden] = useState<Record<string, JsonValue>>({});\n const [formSchema, setFormSchema] = useState<Record<string, any> | null>(null);\n const [parseError, setParseError] = useState(false);\n\n // Parse incoming JSON\n useEffect(() => {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n const visible: Record<string, JsonValue> = {};\n const internal: Record<string, JsonValue> = {};\n for (const [k, v] of Object.entries(parsed)) {\n if (k.startsWith('_')) {\n internal[k] = v as JsonValue;\n } else {\n visible[k] = v as JsonValue;\n }\n }\n setData(visible);\n setHidden(internal);\n setFormSchema(\n internal._form_schema && typeof internal._form_schema === 'object'\n ? internal._form_schema as Record<string, any>\n : null,\n );\n setParseError(false);\n }\n } catch {\n setParseError(true);\n }\n }, [value]);\n\n const emitChange = useCallback((updated: Record<string, JsonValue>) => {\n setData(updated);\n onChange(JSON.stringify({ ...updated, ...hidden }, null, 2));\n }, [hidden, onChange]);\n\n const updateField = useCallback((key: string, val: JsonValue) => {\n emitChange({ ...data, [key]: val });\n }, [data, emitChange]);\n\n if (parseError) {\n return (\n <p className=\"text-xs text-status-error\">\n Unable to parse resolver data as form. Use the JSON editor below.\n </p>\n );\n }\n\n const entries = Object.entries(data);\n if (entries.length === 0) {\n return (\n <p className=\"text-xs text-text-tertiary italic\">\n No resolver fields defined.\n </p>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n {entries.map(([key, val]) => (\n <FieldRow\n key={key}\n fieldKey={key}\n value={val}\n onChange={(v) => updateField(key, v)}\n schema={formSchema}\n />\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Field row — renders appropriate input per type\n// ---------------------------------------------------------------------------\n\nfunction FieldRow({ fieldKey, value, onChange, schema }: {\n fieldKey: string;\n value: JsonValue;\n onChange: (v: JsonValue) => void;\n schema?: Record<string, any> | null;\n}) {\n const label = fieldKey.replace(/[_-]/g, ' ');\n const fieldSchema = schema?.properties?.[fieldKey] as Record<string, any> | undefined;\n\n // Boolean → checkbox\n if (typeof value === 'boolean') {\n return (\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={value}\n onChange={(e) => onChange(e.target.checked)}\n className=\"w-3.5 h-3.5 rounded accent-accent\"\n />\n <span className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary\">\n {label}\n </span>\n </label>\n );\n }\n\n // Number\n if (typeof value === 'number') {\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n <input\n type=\"number\"\n value={value}\n onChange={(e) => onChange(parseFloat(e.target.value) || 0)}\n step=\"any\"\n className=\"input text-sm w-full mt-1\"\n />\n </div>\n );\n }\n\n // String\n if (typeof value === 'string') {\n const isPassword = fieldSchema?.format === 'password';\n const enumValues = fieldSchema?.enum as string[] | undefined;\n const helperText = fieldSchema?.description as string | undefined;\n\n if (enumValues?.length) {\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <p className=\"text-[10px] text-text-tertiary mt-0.5\">{helperText}</p>}\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input text-sm w-full mt-1\"\n >\n {enumValues.map((opt) => (\n <option key={opt} value={opt}>{opt}</option>\n ))}\n </select>\n </div>\n );\n }\n\n if (isPassword) {\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <p className=\"text-[10px] text-text-tertiary mt-0.5\">{helperText}</p>}\n <input\n type=\"password\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input text-sm w-full mt-1\"\n autoComplete=\"off\"\n />\n </div>\n );\n }\n\n if (value.length > 80) {\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <p className=\"text-[10px] text-text-tertiary mt-0.5\">{helperText}</p>}\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input text-sm w-full mt-1 leading-relaxed\"\n rows={Math.min(6, Math.ceil(value.length / 60))}\n />\n </div>\n );\n }\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <p className=\"text-[10px] text-text-tertiary mt-0.5\">{helperText}</p>}\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input text-sm w-full mt-1\"\n />\n </div>\n );\n }\n\n // Null\n if (value === null) {\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n <p className=\"text-xs text-text-tertiary italic mt-1\">null</p>\n </div>\n );\n }\n\n // Array of primitives\n if (Array.isArray(value)) {\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n <div className=\"flex flex-wrap gap-1.5 mt-1\">\n {value.map((item, i) => (\n <span\n key={i}\n className=\"px-2 py-0.5 text-[11px] font-mono bg-surface-sunken rounded text-text-secondary\"\n >\n {String(item)}\n </span>\n ))}\n </div>\n </div>\n );\n }\n\n // Nested object → recursive\n if (typeof value === 'object') {\n const entries = Object.entries(value);\n return (\n <div>\n <FieldLabel>{label}</FieldLabel>\n <div className=\"ml-4 mt-2 pl-4 border-l border-accent-faint space-y-3\">\n {entries.map(([k, v]) => (\n <FieldRow\n key={k}\n fieldKey={k}\n value={v}\n onChange={(updated) => onChange({ ...value, [k]: updated })}\n />\n ))}\n </div>\n </div>\n );\n }\n\n return null;\n}\n\nfunction FieldLabel({ children }: { children: React.ReactNode }) {\n return (\n <label className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary\">\n {children}\n </label>\n );\n}\n","import { useState } from 'react';\nimport { ResolverForm } from '../../../components/escalation/ResolverForm';\n\nexport function ResolverSection({\n json,\n onJsonChange,\n requestTriage,\n onRequestTriageChange,\n triageNotes,\n onTriageNotesChange,\n}: {\n json: string;\n onJsonChange: (v: string) => void;\n requestTriage: boolean;\n onRequestTriageChange: (v: boolean) => void;\n triageNotes: string;\n onTriageNotesChange: (v: string) => void;\n}) {\n const [resolverView, setResolverView] = useState<'form' | 'json'>('form');\n\n return (\n <>\n {/* Toolbar row: form/JSON toggle + triage callout */}\n <div className=\"flex items-center justify-between mb-3\">\n {requestTriage ? (\n <button\n onClick={() => onRequestTriageChange(false)}\n className=\"group flex items-center gap-2 text-left\"\n data-testid=\"triage-cancel\"\n >\n <span className=\"flex items-center justify-center w-5 h-5 rounded-full bg-accent/10 text-accent shrink-0\">\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </span>\n <span className=\"text-xs text-text-secondary group-hover:text-text-primary transition-colors\">\n AI Triage active.{' '}\n <span className=\"text-accent group-hover:underline\">Cancel</span>\n </span>\n </button>\n ) : (\n <button\n onClick={() => onRequestTriageChange(true)}\n className=\"group flex items-center gap-2.5 text-left my-4\"\n data-testid=\"triage-callout\"\n >\n <span className=\"flex items-center justify-center w-6 h-6 rounded-full bg-accent/10 text-accent shrink-0 animate-[triage-glow_6s_ease-in-out_infinite]\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.663 17h4.674M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z\" />\n </svg>\n </span>\n <span className=\"text-[13px] text-text-secondary group-hover:text-text-primary transition-colors\">\n This form doesn't capture the issue?{' '}\n <span className=\"text-accent group-hover:underline\">Request AI Triage</span>\n </span>\n </button>\n )}\n\n {!requestTriage && (\n <button\n onClick={() => setResolverView(resolverView === 'form' ? 'json' : 'form')}\n className=\"text-[10px] text-text-tertiary hover:text-accent transition-colors\"\n >\n {resolverView === 'form' ? 'Raw JSON' : 'Form'}\n </button>\n )}\n </div>\n\n <div className=\"relative min-h-[200px]\">\n {/* Form controls */}\n <div className={requestTriage ? 'pointer-events-none select-none' : ''}>\n {resolverView === 'form' ? (\n <ResolverForm value={json} onChange={onJsonChange} />\n ) : (\n <textarea\n value={json}\n onChange={(e) => onJsonChange(e.target.value)}\n className=\"input-json w-full\"\n rows={8}\n spellCheck={false}\n data-testid=\"resolve-json\"\n />\n )}\n </div>\n\n {/* Triage overlay — occludes the form when AI Triage is checked */}\n {requestTriage && (\n <div\n className=\"absolute inset-0 z-10 flex flex-col bg-surface/90 backdrop-blur-[2px] rounded-md border border-accent/20 p-5\"\n data-testid=\"triage-overlay\"\n >\n <p className=\"text-xs text-text-secondary mb-3 leading-relaxed\">\n The resolution form will not be submitted. Describe the issue\n so AI triage can diagnose and fix it using available tools.\n The corrected result will come back as a new escalation for\n your review.\n </p>\n <textarea\n value={triageNotes}\n onChange={(e) => onTriageNotesChange(e.target.value)}\n placeholder=\"e.g. Content is in Spanish — needs translation to English before review...\"\n className=\"input text-xs w-full flex-1 min-h-[80px] resize-none\"\n autoFocus\n data-testid=\"triage-notes\"\n />\n </div>\n )}\n </div>\n </>\n );\n}\n","import { Link } from 'react-router-dom';\nimport { KeyRound } from 'lucide-react';\nimport { CollapsibleSection } from '../../../components/common/layout/CollapsibleSection';\nimport { JsonViewer } from '../../../components/common/data/JsonViewer';\nimport { RoundsExhaustedContext } from '../../../components/escalation/RoundsExhaustedContext';\nimport { TriageContext } from '../../../components/escalation/TriageContext';\nimport { ResolverSection } from './ResolverSection';\nimport type { ActiveView } from './EscalationActionBar';\n\ninterface EscalationContextProps {\n isRoundsExhausted: boolean;\n payloadObj: Record<string, unknown> | null;\n isTerminal: boolean;\n resolverPayload: Record<string, unknown> | null;\n onRetryTriage: () => Promise<void>;\n isRetrying: boolean;\n}\n\nexport function EscalationContextBlocks({\n isRoundsExhausted,\n payloadObj,\n isTerminal,\n resolverPayload,\n onRetryTriage,\n isRetrying,\n}: EscalationContextProps) {\n return (\n <>\n {/* Rounds-exhausted structured context */}\n {isRoundsExhausted && payloadObj && (\n <div className=\"mt-8\">\n <RoundsExhaustedContext\n payload={payloadObj}\n isTerminal={isTerminal}\n resolverPayload={resolverPayload}\n onRetryTriage={onRetryTriage}\n isRetrying={isRetrying}\n />\n </div>\n )}\n\n {/* Missing credential context */}\n {payloadObj?.category === 'missing_credential' && (\n <div className=\"mt-8 bg-status-warning/10 border border-status-warning/30 rounded-md px-5 py-4 flex items-start gap-3\">\n <KeyRound size={20} className=\"text-status-warning mt-0.5 shrink-0\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary mb-1\">Missing Credential</p>\n <p className=\"text-xs text-text-secondary mb-3\">\n This workflow requires a <span className=\"font-medium capitalize\">{String(payloadObj.provider)}</span> credential\n to continue. Register one and then resolve this escalation to retry.\n </p>\n <Link\n to=\"/credentials\"\n className=\"btn-primary text-xs inline-flex items-center gap-1.5\"\n >\n <KeyRound size={12} />\n Go to Credentials\n </Link>\n </div>\n </div>\n )}\n </>\n );\n}\n\ninterface CollapsibleSectionsProps {\n collapsed: Record<string, boolean>;\n toggleSection: (key: string) => void;\n esc: {\n envelope?: unknown;\n workflow_type?: string | null;\n metadata?: unknown;\n };\n escalationPayload: unknown;\n resolverPayload: unknown;\n triageData?: Record<string, unknown>;\n payloadObj: Record<string, unknown> | null;\n isTerminal: boolean;\n claimedByMe: boolean;\n activeView: ActiveView;\n metadataFormSchema: unknown;\n json: string;\n onJsonChange: (v: string) => void;\n requestTriage: boolean;\n onRequestTriageChange: (v: boolean) => void;\n triageNotes: string;\n onTriageNotesChange: (v: string) => void;\n}\n\nexport function EscalationCollapsibleSections({\n collapsed,\n toggleSection,\n esc,\n escalationPayload,\n resolverPayload,\n triageData,\n payloadObj,\n isTerminal,\n claimedByMe,\n activeView,\n metadataFormSchema,\n json,\n onJsonChange,\n requestTriage,\n onRequestTriageChange,\n triageNotes,\n onTriageNotesChange,\n}: CollapsibleSectionsProps) {\n return (\n <div className=\"mt-8 space-y-6\">\n {/* Input/Output */}\n <CollapsibleSection\n title=\"Input / Output\"\n sectionKey=\"context\"\n isCollapsed={collapsed.context ?? true}\n onToggle={toggleSection}\n contentClassName=\"mt-4 ml-9\"\n >\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {!!esc.envelope && (\n <div>\n <JsonViewer data={esc.envelope} label=\"Input Envelope\" />\n </div>\n )}\n {escalationPayload != null && (\n <div>\n <JsonViewer data={escalationPayload} label=\"Escalation Context\" />\n </div>\n )}\n </div>\n\n {resolverPayload != null && (\n <div className=\"max-w-xl\">\n <JsonViewer data={resolverPayload} label=\"Resolver Payload\" />\n </div>\n )}\n </div>\n </CollapsibleSection>\n\n {/* Triage context */}\n {triageData && payloadObj && (\n <CollapsibleSection\n title=\"AI Triage\"\n sectionKey=\"triage\"\n isCollapsed={!!collapsed.triage}\n onToggle={toggleSection}\n contentClassName=\"mt-4 ml-9\"\n >\n <TriageContext triage={triageData} payload={payloadObj} />\n </CollapsibleSection>\n )}\n\n {/* Resolver form */}\n {!isTerminal && claimedByMe && activeView === 'resolve' && !!(esc.workflow_type || metadataFormSchema) && (\n <CollapsibleSection\n title=\"Submit Your Resolution\"\n sectionKey=\"resolver\"\n isCollapsed={!!collapsed.resolver}\n onToggle={toggleSection}\n contentClassName=\"mt-4 ml-9\"\n >\n <ResolverSection\n json={json}\n onJsonChange={onJsonChange}\n requestTriage={requestTriage}\n onRequestTriageChange={onRequestTriageChange}\n triageNotes={triageNotes}\n onTriageNotesChange={onTriageNotesChange}\n />\n </CollapsibleSection>\n )}\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { useAuth } from '../../../hooks/useAuth';\nimport {\n useEscalation,\n useClaimEscalation,\n useResolveEscalation,\n useEscalateToRole,\n} from '../../../api/escalations';\nimport { useEscalationTargets } from '../../../api/roles';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { isEffectivelyClaimed } from '../../../lib/escalation';\nimport { useWorkflowConfigs } from '../../../api/workflows';\nimport { useSettings } from '../../../api/settings';\nimport { useEscalationDetailEvents } from '../../../hooks/useEventHooks';\nimport { EscalationActionBar } from './EscalationActionBar';\nimport { EscalationHero } from './EscalationHero';\nimport type { ActionBarMode, ActiveView } from './EscalationActionBar';\nimport { EscalationContextBlocks, EscalationCollapsibleSections } from './EscalationDetailSections';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction safeParse(value: string | null | undefined): unknown {\n if (!value) return null;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction hasTriageData(payload: string | null | undefined): boolean {\n if (!payload) return false;\n try {\n const p = JSON.parse(payload);\n return !!(p && typeof p === 'object' && p._triage);\n } catch { return false; }\n}\n\n// ---------------------------------------------------------------------------\n// Main page\n// ---------------------------------------------------------------------------\n\nexport function EscalationDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { user } = useAuth();\n const navigate = useNavigate();\n const { data: esc, isLoading } = useEscalation(id!);\n useEscalationDetailEvents(id);\n const claim = useClaimEscalation();\n const resolve = useResolveEscalation();\n const escalate = useEscalateToRole();\n const { data: escalationTargets } = useEscalationTargets(esc?.role ?? '');\n const { data: workflowConfigs } = useWorkflowConfigs();\n const { data: settings } = useSettings();\n\n const wfConfig = workflowConfigs?.find((c) => c.workflow_type === esc?.workflow_type);\n const traceUrl = settings?.telemetry?.traceUrl ?? null;\n const [activeView, setActiveView] = useState<ActiveView>('resolve');\n const [json, setJson] = useState('{}');\n\n // Section collapse state\n const [collapsed, setCollapsed] = useState<Record<string, boolean>>({ context: false });\n const toggleSection = (key: string) =>\n setCollapsed((prev) => ({ ...prev, [key]: !prev[key] }));\n\n const [requestTriage, setRequestTriage] = useState(false);\n const [triageNotes, setTriageNotes] = useState('');\n const resolverSchema = wfConfig?.resolver_schema ?? null;\n const metadataFormSchema = (esc?.metadata as any)?.form_schema ?? null;\n const effectiveSchema = metadataFormSchema ?? resolverSchema;\n useEffect(() => {\n const formSchema = metadataFormSchema ?? (resolverSchema?.properties ? resolverSchema : null);\n if (formSchema?.properties) {\n const initial: Record<string, any> = { _form_schema: formSchema };\n for (const [key, def] of Object.entries(formSchema.properties)) {\n const fieldDef = def as Record<string, any>;\n initial[key] = fieldDef.default ?? '';\n }\n setJson(JSON.stringify(initial, null, 2));\n } else {\n setJson(effectiveSchema ? JSON.stringify(effectiveSchema, null, 2) : '{}');\n }\n }, [effectiveSchema, metadataFormSchema, resolverSchema]);\n\n const hasTriage = hasTriageData(esc?.escalation_payload);\n const isRoundsExhausted = esc?.subtype === 'rounds_exhausted';\n const isWaitForHuman = esc?.subtype === 'wait_for_human';\n useEffect(() => {\n if (hasTriage || isRoundsExhausted) {\n setCollapsed((prev) => ({ ...prev, context: true }));\n }\n if (isWaitForHuman && metadataFormSchema) {\n setCollapsed((prev) => ({ ...prev, context: true, resolver: false }));\n }\n }, [hasTriage, isRoundsExhausted, isWaitForHuman, metadataFormSchema]);\n\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-8\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-32 bg-surface-sunken rounded w-full\" />\n </div>\n );\n }\n\n if (!esc) {\n return <p className=\"text-sm text-text-secondary\">Escalation not found.</p>;\n }\n\n const claimed = isEffectivelyClaimed(esc);\n const claimedByMe = claimed && esc.assigned_to === user?.userId;\n const claimedByOther = claimed && !claimedByMe;\n const isTerminal = esc.status === 'resolved' || esc.status === 'cancelled';\n\n const escalationPayload = safeParse(esc.escalation_payload);\n const resolverPayload = safeParse(esc.resolver_payload);\n\n const payloadObj = (typeof escalationPayload === 'object' && escalationPayload !== null && !Array.isArray(escalationPayload))\n ? escalationPayload as Record<string, unknown>\n : null;\n const triageData = payloadObj?._triage as Record<string, unknown> | undefined;\n\n const actionBarMode: ActionBarMode = isTerminal\n ? 'terminal'\n : claimedByMe\n ? 'claimed_by_me'\n : claimedByOther\n ? 'claimed_by_other'\n : 'available';\n\n const handleClaim = (durationMinutes: number) => {\n claim.mutate({ id: esc.id, durationMinutes });\n setCollapsed({ context: true, triage: true, resolver: false });\n };\n\n const goBack = () => navigate(-1);\n\n const handleResolve = async (payload: Record<string, unknown>) => {\n await resolve.mutateAsync({ id: esc.id, resolverPayload: payload });\n goBack();\n };\n\n const handleEscalate = async (targetRole: string) => {\n if (!targetRole) return;\n await escalate.mutateAsync({ id: esc.id, targetRole });\n goBack();\n };\n\n const handleRetryTriage = async () => {\n if (!claimedByMe) {\n await claim.mutateAsync({ id: esc.id, durationMinutes: 30 });\n }\n const diagnosis = (payloadObj?.diagnosis as string) || esc.description || '';\n await resolve.mutateAsync({\n id: esc.id,\n resolverPayload: { _lt: { needsTriage: true }, notes: diagnosis },\n });\n goBack();\n };\n\n const handleRelease = async () => {\n await claim.mutateAsync({ id: esc.id, durationMinutes: 0 });\n goBack();\n };\n\n return (\n <div className=\"min-h-[calc(100vh-9rem)] flex flex-col\">\n <PageHeader title=\"Escalation\" />\n\n <EscalationHero\n esc={esc}\n claimedByMe={claimedByMe}\n claimed={claimed}\n isTerminal={isTerminal}\n traceUrl={traceUrl}\n />\n\n <EscalationContextBlocks\n isRoundsExhausted={isRoundsExhausted}\n payloadObj={payloadObj}\n isTerminal={isTerminal}\n resolverPayload={resolverPayload as Record<string, unknown> | null}\n onRetryTriage={handleRetryTriage}\n isRetrying={claim.isPending || resolve.isPending}\n />\n\n <EscalationCollapsibleSections\n collapsed={collapsed}\n toggleSection={toggleSection}\n esc={esc}\n escalationPayload={escalationPayload}\n resolverPayload={resolverPayload}\n triageData={triageData}\n payloadObj={payloadObj}\n isTerminal={isTerminal}\n claimedByMe={claimedByMe}\n activeView={activeView}\n metadataFormSchema={metadataFormSchema}\n json={json}\n onJsonChange={setJson}\n requestTriage={requestTriage}\n onRequestTriageChange={setRequestTriage}\n triageNotes={triageNotes}\n onTriageNotesChange={setTriageNotes}\n />\n\n <div className=\"flex-1\" />\n\n <EscalationActionBar\n mode={actionBarMode}\n activeView={activeView}\n onActiveViewChange={setActiveView}\n onClaim={handleClaim}\n claimPending={claim.isPending}\n workflowType={esc.workflow_type}\n json={json}\n onResolve={handleResolve}\n resolvePending={resolve.isPending}\n resolveError={resolve.error as Error | null}\n requestTriage={requestTriage}\n triageNotes={triageNotes}\n currentRole={esc.role}\n escalationTargets={escalationTargets?.targets ?? []}\n onEscalate={handleEscalate}\n escalatePending={escalate.isPending}\n escalateError={escalate.error as Error | null}\n onRelease={handleRelease}\n releasePending={claim.isPending}\n assignedTo={esc.assigned_to}\n assignedUntil={esc.assigned_until}\n />\n </div>\n );\n}\n"],"names":["EscalationActionBar","props","mode","activeView","onActiveViewChange","onClaim","claimPending","workflowType","json","onResolve","resolvePending","resolveError","requestTriage","triageNotes","currentRole","escalationTargets","onEscalate","escalatePending","escalateError","onRelease","releasePending","assignedTo","assignedUntil","claimDurations","useClaimDurations","duration","setDuration","useState","customMinutes","setCustomMinutes","parseError","setParseError","escalateTarget","setEscalateTarget","isCustom","onCustomChange","useCallback","handleClaim","minutes","handleSubmitResolve","payload","tabClass","active","jsxs","opt","jsx","CustomDurationPicker","UserName","CountdownTimer","e","role","EscalationHero","esc","_claimedByMe","claimed","isTerminal","traceUrl","showDetails","setShowDetails","isAck","isAckEscalation","Fragment","Bell","StatusBadge","RolePill","DateValue","User","Collapsible","CopyableId","renderInline","text","SimpleMarkdown","content","compact","segments","fencePattern","lastIndex","match","sizeClasses","allParts","segment","escaped","renderTextBlock","sz","lines","htmlParts","inList","inTable","tableRows","line","trimmed","cells","c","header","body","h","row","cell","SectionLabel","children","RoundsExhaustedContext","resolverPayload","onRetryTriage","isRetrying","title","summary","diagnosis","toolCalls","result","ltMeta","wasTriaged","triageWorkflowId","isResolvedByTriage","showResult","setShowResult","Link","JsonViewer","TriageContext","triage","confidence","confidenceColor","diffs","computeDiffs","action","i","diff","DiffRow","original","current","key","origVal","currVal","origStr","renderValue","corrStr","val","ResolverForm","value","onChange","data","setData","hidden","setHidden","formSchema","setFormSchema","useEffect","parsed","visible","internal","k","v","emitChange","updated","updateField","entries","FieldRow","fieldKey","schema","label","fieldSchema","_a","FieldLabel","isPassword","enumValues","helperText","item","ResolverSection","onJsonChange","onRequestTriageChange","onTriageNotesChange","resolverView","setResolverView","EscalationContextBlocks","isRoundsExhausted","payloadObj","KeyRound","EscalationCollapsibleSections","collapsed","toggleSection","escalationPayload","triageData","claimedByMe","metadataFormSchema","CollapsibleSection","safeParse","hasTriageData","p","EscalationDetailPage","id","useParams","user","useAuth","navigate","useNavigate","isLoading","useEscalation","useEscalationDetailEvents","claim","useClaimEscalation","resolve","useResolveEscalation","escalate","useEscalateToRole","useEscalationTargets","workflowConfigs","useWorkflowConfigs","settings","useSettings","wfConfig","setActiveView","setJson","setCollapsed","prev","setRequestTriage","setTriageNotes","resolverSchema","_b","effectiveSchema","initial","def","fieldDef","hasTriage","isWaitForHuman","isEffectivelyClaimed","claimedByOther","actionBarMode","durationMinutes","goBack","handleResolve","handleEscalate","targetRole","handleRetryTriage","handleRelease","PageHeader"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{c as k,u as R,b as J,j as e,a as o}from"./vendor-query-B2UbickB.js";import{P as O}from"./PageHeader-DLjHNYHX.js";import{b as g}from"./index-BMIU7Im5.js";import{M as A}from"./Modal-DEODGeqx.js";import{R as F,C as w}from"./constants-BHkpVaqx.js";import{ah as b,m as M,a1 as D}from"./vendor-icons-E6836lXZ.js";import"./vendor-react-CX88sFS5.js";function I(){return R({queryKey:["maintenance"],queryFn:()=>g("/config/maintenance")})}function _(){const t=J();return k({mutationFn:r=>g("/config/maintenance",{method:"PUT",body:JSON.stringify(r)}),onSuccess:()=>{t.invalidateQueries({queryKey:["maintenance"]})}})}function q(){return k({mutationFn:t=>g("/dba/prune",{method:"POST",body:JSON.stringify(t)})})}function h({checked:t,onToggle:r,label:n,hint:s,value:l,onChange:c}){return e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2.5 cursor-pointer w-64 shrink-0",children:[e.jsx("input",{type:"checkbox",checked:t,onChange:i=>r(i.target.checked),className:"w-4 h-4 rounded border-border accent-accent shrink-0"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-xs text-text-primary",children:n}),e.jsx("p",{className:"text-[10px] text-text-tertiary",children:s})]})]}),e.jsx("select",{value:l,onChange:i=>c(i.target.value),disabled:!t,className:`select text-xs w-36 transition-opacity ${t?"":"opacity-40 cursor-not-allowed"}`,children:F.map(i=>e.jsx("option",{value:i.value,children:i.label},i.value))})]})}function f({checked:t,onChange:r,label:n,description:s}){return e.jsxs("label",{className:"flex items-start gap-2.5 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t,onChange:l=>r(l.target.checked),className:"w-4 h-4 mt-0.5 rounded border-border accent-accent shrink-0"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-xs text-text-primary",children:n}),e.jsx("p",{className:"text-[10px] text-text-tertiary",children:s})]})]})}function U(){return e.jsxs("div",{className:"flex items-start gap-2 mt-2 px-3 py-2 rounded bg-surface-sunken",children:[e.jsx(b,{className:"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5"}),e.jsx("p",{className:"text-[10px] text-text-tertiary leading-relaxed",children:"Stripping preserves workflow results and timeline data needed for the execution detail view. Transient jobs are internal bookkeeping that accumulates over time."})]})}const j={pruneJobs:!0,expire:"30 days",engineStreams:!0,engineStreamsExpire:"1 day",workerStreams:!0,workerStreamsExpire:"90 days",stripAttributes:!1,pruneTransient:!1};function S(t){return t.pruneJobs||t.engineStreams||t.workerStreams||t.stripAttributes||t.pruneTransient}function C({fields:t,onChange:r}){const n=(s,l)=>r({...t,[s]:l});return e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-10",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4",children:"Delete Expired Data"}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(h,{checked:t.pruneJobs,onToggle:s=>n("pruneJobs",s),label:"Jobs",hint:"Hard-delete completed job rows",value:t.expire,onChange:s=>n("expire",s)}),e.jsx(h,{checked:t.engineStreams,onToggle:s=>n("engineStreams",s),label:"Engine streams",hint:"Internal routing (prune aggressively)",value:t.engineStreamsExpire,onChange:s=>n("engineStreamsExpire",s)}),e.jsx(h,{checked:t.workerStreams,onToggle:s=>n("workerStreams",s),label:"Worker streams",hint:"Activity payloads for execution playback",value:t.workerStreamsExpire,onChange:s=>n("workerStreamsExpire",s)})]})]}),e.jsxs("div",{className:"lg:w-72",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4",children:"Cleanup"}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(f,{checked:t.stripAttributes,onChange:s=>n("stripAttributes",s),label:"Strip execution artifacts",description:"Remove step-level detail from completed jobs. Return data and export history are preserved."}),e.jsx(f,{checked:t.pruneTransient,onChange:s=>n("pruneTransient",s),label:"Delete transient jobs",description:"Orphaned jobs without an entity type. Usually safe to remove."}),e.jsx(U,{})]})]})]})}function u({label:t,value:r}){return e.jsxs("div",{children:[e.jsx("p",{className:"text-lg font-light text-text-primary",children:r.toLocaleString()}),e.jsx("p",{className:"text-[10px] text-text-tertiary",children:t})]})}function W(){const t=q(),[r,n]=o.useState(j),[s,l]=o.useState(null),[c,i]=o.useState(!1),a=()=>{l(null),t.mutate({expire:r.expire,jobs:r.pruneJobs,engineStreams:r.engineStreams,engineStreamsExpire:r.engineStreamsExpire,workerStreams:r.workerStreams,workerStreamsExpire:r.workerStreamsExpire,attributes:r.stripAttributes,pruneTransient:r.pruneTransient},{onSuccess:x=>{l(x),i(!1)}})};return e.jsxs("div",{className:"space-y-8",children:[e.jsx(C,{fields:r,onChange:n}),e.jsxs("div",{className:"flex items-center justify-between pt-2 border-t border-surface-border",children:[e.jsx("p",{className:"text-[10px] text-text-tertiary",children:S(r)?"This action permanently deletes data and cannot be undone.":"Select at least one operation to enable pruning."}),e.jsx("button",{onClick:()=>i(!0),disabled:!S(r)||t.isPending,className:"bg-status-error text-white px-4 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-40 shrink-0",children:t.isPending?"Pruning...":"Prune Now"})]}),s&&e.jsxs("div",{className:"bg-surface-sunken rounded-md px-4 py-3",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-2",children:"Results"}),e.jsxs("div",{className:"flex flex-wrap gap-6",children:[s.jobs!=null&&s.jobs>0&&e.jsx(u,{label:"Jobs deleted",value:s.jobs}),s.engineStreams!=null&&s.engineStreams>0&&e.jsx(u,{label:"Engine streams",value:s.engineStreams}),s.workerStreams!=null&&s.workerStreams>0&&e.jsx(u,{label:"Worker streams",value:s.workerStreams}),s.streams!=null&&s.engineStreams==null&&s.streams>0&&e.jsx(u,{label:"Streams",value:s.streams}),s.attributes!=null&&s.attributes>0&&e.jsx(u,{label:"Artifacts stripped",value:s.attributes}),s.transient!=null&&s.transient>0&&e.jsx(u,{label:"Transient deleted",value:s.transient}),s.marked!=null&&s.marked>0&&e.jsx(u,{label:"Marked pruned",value:s.marked}),Object.values(s).every(x=>!x||x===0)&&e.jsx("p",{className:"text-xs text-text-tertiary",children:"Nothing to prune within the selected retention windows."})]})]}),t.error&&e.jsx("p",{className:"text-xs text-status-error",children:t.error.message}),e.jsx(A,{open:c,onClose:()=>i(!1),title:"Confirm Prune",children:e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-text-secondary",children:"This will permanently delete data. This action cannot be undone."}),e.jsxs("ul",{className:"text-xs text-text-secondary space-y-1 list-disc list-inside",children:[r.pruneJobs&&e.jsxs("li",{children:["Delete jobs older than ",r.expire]}),r.engineStreams&&e.jsxs("li",{children:["Delete engine streams older than ",r.engineStreamsExpire]}),r.workerStreams&&e.jsxs("li",{children:["Delete worker streams older than ",r.workerStreamsExpire]}),r.stripAttributes&&e.jsx("li",{children:"Strip execution artifacts from completed jobs"}),r.pruneTransient&&e.jsx("li",{children:"Delete transient (entity-less) jobs"})]}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:()=>i(!1),className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:a,className:"bg-status-error text-white px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity",disabled:t.isPending,children:t.isPending?"Pruning...":"Confirm Prune"})]})]})})]})}function v(t){var i;if(!((i=t==null?void 0:t.rules)!=null&&i.length))return j;const r=t.rules,n=r.find(a=>a.target==="streams"&&a.action==="delete"),s=r.find(a=>a.target==="jobs"&&a.action==="delete"&&a.hasEntity===!1),l=r.find(a=>a.target==="jobs"&&a.action==="prune"&&a.hasEntity===!0),c=r.find(a=>a.target==="jobs"&&a.action==="delete"&&a.pruned===!0);return{pruneJobs:!!c,expire:(c==null?void 0:c.olderThan)??"180 days",engineStreams:!!n,engineStreamsExpire:(n==null?void 0:n.olderThan)??"1 day",workerStreams:!!n,workerStreamsExpire:(n==null?void 0:n.olderThan)??"90 days",stripAttributes:!!l,pruneTransient:!!s}}function $(t){const r=[];return t.engineStreams&&r.push({target:"streams",action:"delete",olderThan:t.engineStreamsExpire}),t.workerStreams&&t.workerStreamsExpire!==t.engineStreamsExpire&&r.push({target:"streams",action:"delete",olderThan:t.workerStreamsExpire}),t.pruneTransient&&r.push({target:"jobs",action:"delete",olderThan:t.expire,hasEntity:!1}),t.stripAttributes&&r.push({target:"jobs",action:"prune",olderThan:t.expire,hasEntity:!0}),t.pruneJobs&&r.push({target:"jobs",action:"delete",olderThan:t.expire,pruned:!0}),r}function N(t){var r;return((r=w.find(n=>n.value===t))==null?void 0:r.label)??""}function H(){const{data:t,isLoading:r}=I(),n=_(),[s,l]=o.useState(""),[c,i]=o.useState(j),[a,x]=o.useState(""),p=o.useCallback(()=>{t!=null&&t.config&&(l(t.config.schedule),i(v(t.config)),x(JSON.stringify({schedule:t.config.schedule,fields:v(t.config)})))},[t]);o.useEffect(()=>{p()},[p]);const E=JSON.stringify({schedule:s,fields:c}),y=a!==""&&E!==a,m=(t==null?void 0:t.active)??!1,T=()=>{const d=$(c);n.mutate({schedule:s,rules:d},{onSuccess:()=>{x(JSON.stringify({schedule:s,fields:c}))}})},P=()=>{p()};return r?e.jsx("div",{className:"animate-pulse h-40 bg-surface-sunken rounded"}):e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-10",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4",children:"Schedule"}),e.jsxs("div",{className:"flex items-end gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] text-text-tertiary mb-1",children:"Cron Expression"}),e.jsx("input",{type:"text",value:s,onChange:d=>l(d.target.value),placeholder:"0 2 * * *",className:"input text-xs font-mono w-48"})]}),e.jsx("div",{children:e.jsxs("div",{className:"flex items-center gap-1.5 h-8",children:[e.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${m?"bg-status-success":"bg-text-tertiary"}`}),e.jsx("span",{className:`text-xs ${m?"text-status-success":"text-text-tertiary"}`,children:m?"Active":"Inactive"})]})}),N(s)&&e.jsx("p",{className:"text-xs text-text-tertiary h-8 flex items-center",children:N(s)})]}),e.jsx("div",{className:"flex flex-wrap gap-1.5 mt-3",children:w.map(d=>e.jsx("button",{type:"button",onClick:()=>l(d.value),className:`px-2.5 py-1 text-[10px] rounded-full transition-colors ${s===d.value?"bg-accent/10 text-accent font-medium":"bg-surface-sunken text-text-tertiary hover:text-text-secondary"}`,children:d.label},d.value))})]}),e.jsxs("div",{className:"lg:w-72",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4",children:"How It Works"}),e.jsxs("div",{className:"flex items-start gap-2 px-3 py-2 rounded bg-surface-sunken",children:[e.jsx(b,{className:"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5"}),e.jsx("p",{className:"text-[10px] text-text-tertiary leading-relaxed",children:"Rules execute sequentially on each cron cycle. Engine streams can be pruned aggressively since they only contain internal routing data. Worker streams should be retained longer to preserve execution playback and input enrichment."})]})]})]}),e.jsx(C,{fields:c,onChange:i}),e.jsxs("div",{className:"flex items-center justify-between pt-2 border-t border-surface-border",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[y&&e.jsx("button",{onClick:P,className:"text-[10px] text-text-tertiary hover:text-text-primary transition-colors",children:"Revert changes"}),n.error&&e.jsx("p",{className:"text-xs text-status-error",children:n.error.message})]}),e.jsx("button",{onClick:T,disabled:!y||!s.trim()||n.isPending,className:"btn-primary text-xs disabled:opacity-40 shrink-0",children:n.isPending?"Saving...":"Save Schedule"})]})]})}function L({mode:t,onChange:r}){const n=(s,l,c)=>e.jsxs("button",{onClick:()=>r(s),className:`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md transition-colors ${t===s?"bg-accent/10 text-accent font-medium":"text-text-tertiary hover:text-text-secondary hover:bg-surface-hover"}`,children:[l,c]});return e.jsxs("div",{className:"flex gap-1 p-0.5 bg-surface-sunken rounded-lg w-fit",children:[n("prune",e.jsx(M,{className:"w-3.5 h-3.5"}),"Prune Now"),n("schedule",e.jsx(D,{className:"w-3.5 h-3.5"}),"Schedule")]})}function Y(){const[t,r]=o.useState("schedule");return e.jsxs("div",{children:[e.jsx(O,{title:"DB Maintenance",docsHash:"#docs:dashboard.md:db-maintenance",actions:e.jsx(L,{mode:t,onChange:r})}),e.jsxs("div",{className:"flex items-start gap-2 px-4 py-3 mb-8 rounded-md bg-accent/5 border border-accent/10",children:[e.jsx(b,{className:"w-4 h-4 text-accent shrink-0 mt-0.5"}),e.jsx("p",{className:"text-xs text-text-secondary leading-relaxed",children:"Completed process data grows indefinitely. Schedule regular pruning to keep the database lean and queries fast. Worker streams are retained longer than engine streams to preserve execution playback."})]}),t==="prune"?e.jsx(W,{}):e.jsx(H,{})]})}export{Y as MaintenancePage};
|
|
2
|
+
//# sourceMappingURL=index-DyqdoZPY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-CSsOukxa.js","sources":["../../src/api/maintenance.ts","../../src/pages/admin/maintenance/controls.tsx","../../src/pages/admin/maintenance/PruneSection.tsx","../../src/pages/admin/maintenance/ScheduleSection.tsx","../../src/pages/admin/maintenance/MaintenancePage.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface MaintenanceRule {\n target: 'streams' | 'jobs';\n action: 'delete' | 'prune';\n olderThan: string;\n hasEntity?: boolean;\n pruned?: boolean;\n}\n\nexport interface MaintenanceConfig {\n schedule: string;\n rules: MaintenanceRule[];\n}\n\nexport interface PruneOptions {\n expire?: string;\n jobs?: boolean;\n streams?: boolean;\n engineStreams?: boolean;\n engineStreamsExpire?: string;\n workerStreams?: boolean;\n workerStreamsExpire?: string;\n attributes?: boolean;\n entities?: string[];\n pruneTransient?: boolean;\n keepHmark?: boolean;\n}\n\nexport interface PruneResult {\n jobs?: number;\n streams?: number;\n engineStreams?: number;\n workerStreams?: number;\n attributes?: number;\n transient?: number;\n marked?: number;\n}\n\n// ── Maintenance config ────────────────────────────────────────────────────────\n\nexport function useMaintenanceConfig() {\n return useQuery<{ config: MaintenanceConfig; active: boolean }>({\n queryKey: ['maintenance'],\n queryFn: () => apiFetch('/config/maintenance'),\n });\n}\n\nexport function useUpdateMaintenanceConfig() {\n const queryClient = useQueryClient();\n return useMutation<\n { config: MaintenanceConfig; restarted: boolean },\n Error,\n MaintenanceConfig\n >({\n mutationFn: (config) =>\n apiFetch('/config/maintenance', {\n method: 'PUT',\n body: JSON.stringify(config),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['maintenance'] });\n },\n });\n}\n\n// ── DBA operations ────────────────────────────────────────────────────────────\n\nexport function usePrune() {\n return useMutation<PruneResult, Error, PruneOptions>({\n mutationFn: (options) =>\n apiFetch('/dba/prune', {\n method: 'POST',\n body: JSON.stringify(options),\n }),\n });\n}\n\nexport function useDeploy() {\n return useMutation<{ ok: boolean }, Error, void>({\n mutationFn: () =>\n apiFetch('/dba/deploy', { method: 'POST' }),\n });\n}\n","import { Info } from 'lucide-react';\nimport { RETENTION_PERIOD_OPTIONS } from '../../../lib/constants';\n\n// ── Retention row (checkbox + label + select) ───────────────────────────────\n\nexport function RetentionRow({ checked, onToggle, label, hint, value, onChange }: {\n checked: boolean;\n onToggle: (v: boolean) => void;\n label: string;\n hint: string;\n value: string;\n onChange: (v: string) => void;\n}) {\n return (\n <div className=\"flex items-center gap-4\">\n <label className=\"flex items-center gap-2.5 cursor-pointer w-64 shrink-0\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"w-4 h-4 rounded border-border accent-accent shrink-0\"\n />\n <div>\n <span className=\"text-xs text-text-primary\">{label}</span>\n <p className=\"text-[10px] text-text-tertiary\">{hint}</p>\n </div>\n </label>\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n disabled={!checked}\n className={`select text-xs w-36 transition-opacity ${!checked ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n );\n}\n\n// ── Cleanup checkbox ────────────────────────────────────────────────────────\n\nexport function CleanupCheck({ checked, onChange, label, description }: {\n checked: boolean;\n onChange: (v: boolean) => void;\n label: string;\n description: string;\n}) {\n return (\n <label className=\"flex items-start gap-2.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"w-4 h-4 mt-0.5 rounded border-border accent-accent shrink-0\"\n />\n <div>\n <span className=\"text-xs text-text-primary\">{label}</span>\n <p className=\"text-[10px] text-text-tertiary\">{description}</p>\n </div>\n </label>\n );\n}\n\n// ── Cleanup callout ─────────────────────────────────────────────────────────\n\nexport function CleanupCallout() {\n return (\n <div className=\"flex items-start gap-2 mt-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-[10px] text-text-tertiary leading-relaxed\">\n Stripping preserves workflow results and timeline data needed for the execution detail view.\n Transient jobs are internal bookkeeping that accumulates over time.\n </p>\n </div>\n );\n}\n\n// ── Prune fields state shape (shared between both panels) ───────────────────\n\nexport interface PruneFields {\n pruneJobs: boolean;\n expire: string;\n engineStreams: boolean;\n engineStreamsExpire: string;\n workerStreams: boolean;\n workerStreamsExpire: string;\n stripAttributes: boolean;\n pruneTransient: boolean;\n}\n\nexport const DEFAULT_PRUNE_FIELDS: PruneFields = {\n pruneJobs: true,\n expire: '30 days',\n engineStreams: true,\n engineStreamsExpire: '1 day',\n workerStreams: true,\n workerStreamsExpire: '90 days',\n stripAttributes: false,\n pruneTransient: false,\n};\n\nexport function hasSelection(f: PruneFields): boolean {\n return f.pruneJobs || f.engineStreams || f.workerStreams || f.stripAttributes || f.pruneTransient;\n}\n\n// ── Prune fields editor (reused by both Prune Now and Schedule) ─────────────\n\nexport function PruneFieldsEditor({ fields, onChange }: {\n fields: PruneFields;\n onChange: (f: PruneFields) => void;\n}) {\n const set = <K extends keyof PruneFields>(key: K, value: PruneFields[K]) =>\n onChange({ ...fields, [key]: value });\n\n return (\n <div className=\"grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-10\">\n {/* Left: delete data — the aligned 3 */}\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Delete Expired Data\n </p>\n <div className=\"space-y-3\">\n <RetentionRow\n checked={fields.pruneJobs} onToggle={(v) => set('pruneJobs', v)}\n label=\"Jobs\" hint=\"Hard-delete completed job rows\"\n value={fields.expire} onChange={(v) => set('expire', v)}\n />\n <RetentionRow\n checked={fields.engineStreams} onToggle={(v) => set('engineStreams', v)}\n label=\"Engine streams\" hint=\"Internal routing (prune aggressively)\"\n value={fields.engineStreamsExpire} onChange={(v) => set('engineStreamsExpire', v)}\n />\n <RetentionRow\n checked={fields.workerStreams} onToggle={(v) => set('workerStreams', v)}\n label=\"Worker streams\" hint=\"Activity payloads for execution playback\"\n value={fields.workerStreamsExpire} onChange={(v) => set('workerStreamsExpire', v)}\n />\n </div>\n </div>\n\n {/* Right: cleanup operations */}\n <div className=\"lg:w-72\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Cleanup\n </p>\n <div className=\"space-y-4\">\n <CleanupCheck\n checked={fields.stripAttributes} onChange={(v) => set('stripAttributes', v)}\n label=\"Strip execution artifacts\"\n description=\"Remove step-level detail from completed jobs. Return data and export history are preserved.\"\n />\n <CleanupCheck\n checked={fields.pruneTransient} onChange={(v) => set('pruneTransient', v)}\n label=\"Delete transient jobs\"\n description=\"Orphaned jobs without an entity type. Usually safe to remove.\"\n />\n <CleanupCallout />\n </div>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { usePrune, type PruneResult } from '../../../api/maintenance';\nimport { Modal } from '../../../components/common/modal/Modal';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, hasSelection, type PruneFields } from './controls';\n\nfunction ResultCard({ label, value }: { label: string; value: number }) {\n return (\n <div>\n <p className=\"text-lg font-light text-text-primary\">{value.toLocaleString()}</p>\n <p className=\"text-[10px] text-text-tertiary\">{label}</p>\n </div>\n );\n}\n\nexport function PruneSection() {\n const prune = usePrune();\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [result, setResult] = useState<PruneResult | null>(null);\n const [showConfirm, setShowConfirm] = useState(false);\n\n const handlePrune = () => {\n setResult(null);\n prune.mutate(\n {\n expire: fields.expire,\n jobs: fields.pruneJobs,\n engineStreams: fields.engineStreams,\n engineStreamsExpire: fields.engineStreamsExpire,\n workerStreams: fields.workerStreams,\n workerStreamsExpire: fields.workerStreamsExpire,\n attributes: fields.stripAttributes,\n pruneTransient: fields.pruneTransient,\n },\n {\n onSuccess: (data) => {\n setResult(data);\n setShowConfirm(false);\n },\n },\n );\n };\n\n return (\n <div className=\"space-y-8\">\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <p className=\"text-[10px] text-text-tertiary\">\n {!hasSelection(fields)\n ? 'Select at least one operation to enable pruning.'\n : 'This action permanently deletes data and cannot be undone.'}\n </p>\n <button\n onClick={() => setShowConfirm(true)}\n disabled={!hasSelection(fields) || prune.isPending}\n className=\"bg-status-error text-white px-4 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-40 shrink-0\"\n >\n {prune.isPending ? 'Pruning...' : 'Prune Now'}\n </button>\n </div>\n\n {/* Results */}\n {result && (\n <div className=\"bg-surface-sunken rounded-md px-4 py-3\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-2\">\n Results\n </p>\n <div className=\"flex flex-wrap gap-6\">\n {result.jobs != null && result.jobs > 0 && <ResultCard label=\"Jobs deleted\" value={result.jobs} />}\n {result.engineStreams != null && result.engineStreams > 0 && <ResultCard label=\"Engine streams\" value={result.engineStreams} />}\n {result.workerStreams != null && result.workerStreams > 0 && <ResultCard label=\"Worker streams\" value={result.workerStreams} />}\n {result.streams != null && result.engineStreams == null && result.streams > 0 && <ResultCard label=\"Streams\" value={result.streams} />}\n {result.attributes != null && result.attributes > 0 && <ResultCard label=\"Artifacts stripped\" value={result.attributes} />}\n {result.transient != null && result.transient > 0 && <ResultCard label=\"Transient deleted\" value={result.transient} />}\n {result.marked != null && result.marked > 0 && <ResultCard label=\"Marked pruned\" value={result.marked} />}\n {Object.values(result).every((v) => !v || v === 0) && (\n <p className=\"text-xs text-text-tertiary\">Nothing to prune within the selected retention windows.</p>\n )}\n </div>\n </div>\n )}\n\n {prune.error && (\n <p className=\"text-xs text-status-error\">{(prune.error as Error).message}</p>\n )}\n\n {/* Confirm modal */}\n <Modal open={showConfirm} onClose={() => setShowConfirm(false)} title=\"Confirm Prune\">\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">\n This will permanently delete data. This action cannot be undone.\n </p>\n <ul className=\"text-xs text-text-secondary space-y-1 list-disc list-inside\">\n {fields.pruneJobs && <li>Delete jobs older than {fields.expire}</li>}\n {fields.engineStreams && <li>Delete engine streams older than {fields.engineStreamsExpire}</li>}\n {fields.workerStreams && <li>Delete worker streams older than {fields.workerStreamsExpire}</li>}\n {fields.stripAttributes && <li>Strip execution artifacts from completed jobs</li>}\n {fields.pruneTransient && <li>Delete transient (entity-less) jobs</li>}\n </ul>\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={() => setShowConfirm(false)} className=\"btn-secondary text-xs\">Cancel</button>\n <button\n onClick={handlePrune}\n className=\"bg-status-error text-white px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity\"\n disabled={prune.isPending}\n >\n {prune.isPending ? 'Pruning...' : 'Confirm Prune'}\n </button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { Info } from 'lucide-react';\nimport {\n useMaintenanceConfig,\n useUpdateMaintenanceConfig,\n type MaintenanceConfig,\n} from '../../../api/maintenance';\nimport { CRON_PRESETS } from '../../../lib/constants';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, type PruneFields } from './controls';\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Convert a MaintenanceConfig (rules array) into PruneFields for the editor. */\nfunction configToFields(config: MaintenanceConfig | undefined): PruneFields {\n if (!config?.rules?.length) return DEFAULT_PRUNE_FIELDS;\n const r = config.rules;\n const streamDelete = r.find((x) => x.target === 'streams' && x.action === 'delete');\n const jobDeleteTransient = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.hasEntity === false);\n const jobPrune = r.find((x) => x.target === 'jobs' && x.action === 'prune' && x.hasEntity === true);\n const jobDeletePruned = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.pruned === true);\n return {\n pruneJobs: !!jobDeletePruned,\n expire: jobDeletePruned?.olderThan ?? '180 days',\n engineStreams: !!streamDelete,\n engineStreamsExpire: streamDelete?.olderThan ?? '1 day',\n workerStreams: !!streamDelete,\n workerStreamsExpire: streamDelete?.olderThan ?? '90 days',\n stripAttributes: !!jobPrune,\n pruneTransient: !!jobDeleteTransient,\n };\n}\n\n/** Convert PruneFields back to a MaintenanceConfig rules array. */\nfunction fieldsToRules(f: PruneFields): MaintenanceConfig['rules'] {\n const rules: MaintenanceConfig['rules'] = [];\n if (f.engineStreams) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.engineStreamsExpire });\n }\n if (f.workerStreams && f.workerStreamsExpire !== f.engineStreamsExpire) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.workerStreamsExpire });\n }\n if (f.pruneTransient) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, hasEntity: false });\n }\n if (f.stripAttributes) {\n rules.push({ target: 'jobs', action: 'prune', olderThan: f.expire, hasEntity: true });\n }\n if (f.pruneJobs) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, pruned: true });\n }\n return rules;\n}\n\nfunction describeCron(expr: string): string {\n return CRON_PRESETS.find((p) => p.value === expr)?.label ?? '';\n}\n\n// ── Main ────────────────────────────────────────────────────────────────────\n\nexport function ScheduleSection() {\n const { data, isLoading } = useMaintenanceConfig();\n const updateConfig = useUpdateMaintenanceConfig();\n\n const [schedule, setSchedule] = useState('');\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [savedSnapshot, setSavedSnapshot] = useState('');\n\n // Sync from server config when loaded\n const syncFromServer = useCallback(() => {\n if (!data?.config) return;\n setSchedule(data.config.schedule);\n setFields(configToFields(data.config));\n setSavedSnapshot(JSON.stringify({ schedule: data.config.schedule, fields: configToFields(data.config) }));\n }, [data]);\n\n useEffect(() => { syncFromServer(); }, [syncFromServer]);\n\n const currentSnapshot = JSON.stringify({ schedule, fields });\n const isDirty = savedSnapshot !== '' && currentSnapshot !== savedSnapshot;\n const active = data?.active ?? false;\n\n const handleSave = () => {\n const rules = fieldsToRules(fields);\n updateConfig.mutate(\n { schedule, rules },\n {\n onSuccess: () => {\n setSavedSnapshot(JSON.stringify({ schedule, fields }));\n },\n },\n );\n };\n\n const handleRevert = () => {\n syncFromServer();\n };\n\n if (isLoading) {\n return <div className=\"animate-pulse h-40 bg-surface-sunken rounded\" />;\n }\n\n return (\n <div className=\"space-y-8\">\n {/* Cron schedule + status */}\n <div className=\"grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-10\">\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Schedule\n </p>\n <div className=\"flex items-end gap-4\">\n <div>\n <label className=\"block text-[10px] text-text-tertiary mb-1\">Cron Expression</label>\n <input\n type=\"text\"\n value={schedule}\n onChange={(e) => setSchedule(e.target.value)}\n placeholder=\"0 2 * * *\"\n className=\"input text-xs font-mono w-48\"\n />\n </div>\n <div>\n <div className=\"flex items-center gap-1.5 h-8\">\n <span className={`w-1.5 h-1.5 rounded-full ${active ? 'bg-status-success' : 'bg-text-tertiary'}`} />\n <span className={`text-xs ${active ? 'text-status-success' : 'text-text-tertiary'}`}>\n {active ? 'Active' : 'Inactive'}\n </span>\n </div>\n </div>\n {describeCron(schedule) && (\n <p className=\"text-xs text-text-tertiary h-8 flex items-center\">{describeCron(schedule)}</p>\n )}\n </div>\n\n {/* Preset pills */}\n <div className=\"flex flex-wrap gap-1.5 mt-3\">\n {CRON_PRESETS.map((preset) => (\n <button\n key={preset.value}\n type=\"button\"\n onClick={() => setSchedule(preset.value)}\n className={`px-2.5 py-1 text-[10px] rounded-full transition-colors ${\n schedule === preset.value\n ? 'bg-accent/10 text-accent font-medium'\n : 'bg-surface-sunken text-text-tertiary hover:text-text-secondary'\n }`}\n >\n {preset.label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"lg:w-72\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n How It Works\n </p>\n <div className=\"flex items-start gap-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-[10px] text-text-tertiary leading-relaxed\">\n Rules execute sequentially on each cron cycle. Engine streams can be pruned aggressively\n since they only contain internal routing data. Worker streams should be retained longer\n to preserve execution playback and input enrichment.\n </p>\n </div>\n </div>\n </div>\n\n {/* Same prune fields as Prune Now */}\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <div className=\"flex items-center gap-3\">\n {isDirty && (\n <button\n onClick={handleRevert}\n className=\"text-[10px] text-text-tertiary hover:text-text-primary transition-colors\"\n >\n Revert changes\n </button>\n )}\n {updateConfig.error && (\n <p className=\"text-xs text-status-error\">{(updateConfig.error as Error).message}</p>\n )}\n </div>\n <button\n onClick={handleSave}\n disabled={!isDirty || !schedule.trim() || updateConfig.isPending}\n className=\"btn-primary text-xs disabled:opacity-40 shrink-0\"\n >\n {updateConfig.isPending ? 'Saving...' : 'Save Schedule'}\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Trash2, Clock, Info } from 'lucide-react';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { PruneSection } from './PruneSection';\nimport { ScheduleSection } from './ScheduleSection';\n\ntype Mode = 'prune' | 'schedule';\n\nfunction ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {\n const btn = (m: Mode, icon: React.ReactNode, label: string) => (\n <button\n onClick={() => onChange(m)}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md transition-colors ${\n mode === m\n ? 'bg-accent/10 text-accent font-medium'\n : 'text-text-tertiary hover:text-text-secondary hover:bg-surface-hover'\n }`}\n >\n {icon}\n {label}\n </button>\n );\n\n return (\n <div className=\"flex gap-1 p-0.5 bg-surface-sunken rounded-lg w-fit\">\n {btn('prune', <Trash2 className=\"w-3.5 h-3.5\" />, 'Prune Now')}\n {btn('schedule', <Clock className=\"w-3.5 h-3.5\" />, 'Schedule')}\n </div>\n );\n}\n\nexport function MaintenancePage() {\n const [mode, setMode] = useState<Mode>('schedule');\n\n return (\n <div>\n <PageHeader\n title=\"DB Maintenance\"\n docsHash=\"#docs:dashboard.md:db-maintenance\"\n actions={<ModeToggle mode={mode} onChange={setMode} />}\n />\n\n <div className=\"flex items-start gap-2 px-4 py-3 mb-8 rounded-md bg-accent/5 border border-accent/10\">\n <Info className=\"w-4 h-4 text-accent shrink-0 mt-0.5\" />\n <p className=\"text-xs text-text-secondary leading-relaxed\">\n Completed process data grows indefinitely.\n Schedule regular pruning to keep the database lean and queries fast.\n Worker streams are retained longer than engine streams to preserve execution playback.\n </p>\n </div>\n\n {mode === 'prune' ? <PruneSection /> : <ScheduleSection />}\n </div>\n );\n}\n"],"names":["useMaintenanceConfig","useQuery","apiFetch","useUpdateMaintenanceConfig","queryClient","useQueryClient","useMutation","config","usePrune","options","RetentionRow","checked","onToggle","label","hint","value","onChange","jsxDEV","e","RETENTION_PERIOD_OPTIONS","opt","CleanupCheck","description","CleanupCallout","Info","DEFAULT_PRUNE_FIELDS","hasSelection","f","PruneFieldsEditor","fields","set","key","v","ResultCard","PruneSection","prune","setFields","useState","result","setResult","showConfirm","setShowConfirm","handlePrune","data","Modal","configToFields","_a","r","streamDelete","x","jobDeleteTransient","jobPrune","jobDeletePruned","fieldsToRules","rules","describeCron","expr","CRON_PRESETS","p","ScheduleSection","isLoading","updateConfig","schedule","setSchedule","savedSnapshot","setSavedSnapshot","syncFromServer","useCallback","useEffect","currentSnapshot","isDirty","active","handleSave","handleRevert","preset","ModeToggle","mode","btn","m","icon","Trash2","Clock","MaintenancePage","setMode","PageHeader"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-DyqdoZPY.js","sources":["../../src/api/maintenance.ts","../../src/pages/admin/maintenance/controls.tsx","../../src/pages/admin/maintenance/PruneSection.tsx","../../src/pages/admin/maintenance/ScheduleSection.tsx","../../src/pages/admin/maintenance/MaintenancePage.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface MaintenanceRule {\n target: 'streams' | 'jobs';\n action: 'delete' | 'prune';\n olderThan: string;\n hasEntity?: boolean;\n pruned?: boolean;\n}\n\nexport interface MaintenanceConfig {\n schedule: string;\n rules: MaintenanceRule[];\n}\n\nexport interface PruneOptions {\n expire?: string;\n jobs?: boolean;\n streams?: boolean;\n engineStreams?: boolean;\n engineStreamsExpire?: string;\n workerStreams?: boolean;\n workerStreamsExpire?: string;\n attributes?: boolean;\n entities?: string[];\n pruneTransient?: boolean;\n keepHmark?: boolean;\n}\n\nexport interface PruneResult {\n jobs?: number;\n streams?: number;\n engineStreams?: number;\n workerStreams?: number;\n attributes?: number;\n transient?: number;\n marked?: number;\n}\n\n// ── Maintenance config ────────────────────────────────────────────────────────\n\nexport function useMaintenanceConfig() {\n return useQuery<{ config: MaintenanceConfig; active: boolean }>({\n queryKey: ['maintenance'],\n queryFn: () => apiFetch('/config/maintenance'),\n });\n}\n\nexport function useUpdateMaintenanceConfig() {\n const queryClient = useQueryClient();\n return useMutation<\n { config: MaintenanceConfig; restarted: boolean },\n Error,\n MaintenanceConfig\n >({\n mutationFn: (config) =>\n apiFetch('/config/maintenance', {\n method: 'PUT',\n body: JSON.stringify(config),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['maintenance'] });\n },\n });\n}\n\n// ── DBA operations ────────────────────────────────────────────────────────────\n\nexport function usePrune() {\n return useMutation<PruneResult, Error, PruneOptions>({\n mutationFn: (options) =>\n apiFetch('/dba/prune', {\n method: 'POST',\n body: JSON.stringify(options),\n }),\n });\n}\n\nexport function useDeploy() {\n return useMutation<{ ok: boolean }, Error, void>({\n mutationFn: () =>\n apiFetch('/dba/deploy', { method: 'POST' }),\n });\n}\n","import { Info } from 'lucide-react';\nimport { RETENTION_PERIOD_OPTIONS } from '../../../lib/constants';\n\n// ── Retention row (checkbox + label + select) ───────────────────────────────\n\nexport function RetentionRow({ checked, onToggle, label, hint, value, onChange }: {\n checked: boolean;\n onToggle: (v: boolean) => void;\n label: string;\n hint: string;\n value: string;\n onChange: (v: string) => void;\n}) {\n return (\n <div className=\"flex items-center gap-4\">\n <label className=\"flex items-center gap-2.5 cursor-pointer w-64 shrink-0\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"w-4 h-4 rounded border-border accent-accent shrink-0\"\n />\n <div>\n <span className=\"text-xs text-text-primary\">{label}</span>\n <p className=\"text-[10px] text-text-tertiary\">{hint}</p>\n </div>\n </label>\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n disabled={!checked}\n className={`select text-xs w-36 transition-opacity ${!checked ? 'opacity-40 cursor-not-allowed' : ''}`}\n >\n {RETENTION_PERIOD_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n );\n}\n\n// ── Cleanup checkbox ────────────────────────────────────────────────────────\n\nexport function CleanupCheck({ checked, onChange, label, description }: {\n checked: boolean;\n onChange: (v: boolean) => void;\n label: string;\n description: string;\n}) {\n return (\n <label className=\"flex items-start gap-2.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n className=\"w-4 h-4 mt-0.5 rounded border-border accent-accent shrink-0\"\n />\n <div>\n <span className=\"text-xs text-text-primary\">{label}</span>\n <p className=\"text-[10px] text-text-tertiary\">{description}</p>\n </div>\n </label>\n );\n}\n\n// ── Cleanup callout ─────────────────────────────────────────────────────────\n\nexport function CleanupCallout() {\n return (\n <div className=\"flex items-start gap-2 mt-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-[10px] text-text-tertiary leading-relaxed\">\n Stripping preserves workflow results and timeline data needed for the execution detail view.\n Transient jobs are internal bookkeeping that accumulates over time.\n </p>\n </div>\n );\n}\n\n// ── Prune fields state shape (shared between both panels) ───────────────────\n\nexport interface PruneFields {\n pruneJobs: boolean;\n expire: string;\n engineStreams: boolean;\n engineStreamsExpire: string;\n workerStreams: boolean;\n workerStreamsExpire: string;\n stripAttributes: boolean;\n pruneTransient: boolean;\n}\n\nexport const DEFAULT_PRUNE_FIELDS: PruneFields = {\n pruneJobs: true,\n expire: '30 days',\n engineStreams: true,\n engineStreamsExpire: '1 day',\n workerStreams: true,\n workerStreamsExpire: '90 days',\n stripAttributes: false,\n pruneTransient: false,\n};\n\nexport function hasSelection(f: PruneFields): boolean {\n return f.pruneJobs || f.engineStreams || f.workerStreams || f.stripAttributes || f.pruneTransient;\n}\n\n// ── Prune fields editor (reused by both Prune Now and Schedule) ─────────────\n\nexport function PruneFieldsEditor({ fields, onChange }: {\n fields: PruneFields;\n onChange: (f: PruneFields) => void;\n}) {\n const set = <K extends keyof PruneFields>(key: K, value: PruneFields[K]) =>\n onChange({ ...fields, [key]: value });\n\n return (\n <div className=\"grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-10\">\n {/* Left: delete data — the aligned 3 */}\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Delete Expired Data\n </p>\n <div className=\"space-y-3\">\n <RetentionRow\n checked={fields.pruneJobs} onToggle={(v) => set('pruneJobs', v)}\n label=\"Jobs\" hint=\"Hard-delete completed job rows\"\n value={fields.expire} onChange={(v) => set('expire', v)}\n />\n <RetentionRow\n checked={fields.engineStreams} onToggle={(v) => set('engineStreams', v)}\n label=\"Engine streams\" hint=\"Internal routing (prune aggressively)\"\n value={fields.engineStreamsExpire} onChange={(v) => set('engineStreamsExpire', v)}\n />\n <RetentionRow\n checked={fields.workerStreams} onToggle={(v) => set('workerStreams', v)}\n label=\"Worker streams\" hint=\"Activity payloads for execution playback\"\n value={fields.workerStreamsExpire} onChange={(v) => set('workerStreamsExpire', v)}\n />\n </div>\n </div>\n\n {/* Right: cleanup operations */}\n <div className=\"lg:w-72\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Cleanup\n </p>\n <div className=\"space-y-4\">\n <CleanupCheck\n checked={fields.stripAttributes} onChange={(v) => set('stripAttributes', v)}\n label=\"Strip execution artifacts\"\n description=\"Remove step-level detail from completed jobs. Return data and export history are preserved.\"\n />\n <CleanupCheck\n checked={fields.pruneTransient} onChange={(v) => set('pruneTransient', v)}\n label=\"Delete transient jobs\"\n description=\"Orphaned jobs without an entity type. Usually safe to remove.\"\n />\n <CleanupCallout />\n </div>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { usePrune, type PruneResult } from '../../../api/maintenance';\nimport { Modal } from '../../../components/common/modal/Modal';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, hasSelection, type PruneFields } from './controls';\n\nfunction ResultCard({ label, value }: { label: string; value: number }) {\n return (\n <div>\n <p className=\"text-lg font-light text-text-primary\">{value.toLocaleString()}</p>\n <p className=\"text-[10px] text-text-tertiary\">{label}</p>\n </div>\n );\n}\n\nexport function PruneSection() {\n const prune = usePrune();\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [result, setResult] = useState<PruneResult | null>(null);\n const [showConfirm, setShowConfirm] = useState(false);\n\n const handlePrune = () => {\n setResult(null);\n prune.mutate(\n {\n expire: fields.expire,\n jobs: fields.pruneJobs,\n engineStreams: fields.engineStreams,\n engineStreamsExpire: fields.engineStreamsExpire,\n workerStreams: fields.workerStreams,\n workerStreamsExpire: fields.workerStreamsExpire,\n attributes: fields.stripAttributes,\n pruneTransient: fields.pruneTransient,\n },\n {\n onSuccess: (data) => {\n setResult(data);\n setShowConfirm(false);\n },\n },\n );\n };\n\n return (\n <div className=\"space-y-8\">\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <p className=\"text-[10px] text-text-tertiary\">\n {!hasSelection(fields)\n ? 'Select at least one operation to enable pruning.'\n : 'This action permanently deletes data and cannot be undone.'}\n </p>\n <button\n onClick={() => setShowConfirm(true)}\n disabled={!hasSelection(fields) || prune.isPending}\n className=\"bg-status-error text-white px-4 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity disabled:opacity-40 shrink-0\"\n >\n {prune.isPending ? 'Pruning...' : 'Prune Now'}\n </button>\n </div>\n\n {/* Results */}\n {result && (\n <div className=\"bg-surface-sunken rounded-md px-4 py-3\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-2\">\n Results\n </p>\n <div className=\"flex flex-wrap gap-6\">\n {result.jobs != null && result.jobs > 0 && <ResultCard label=\"Jobs deleted\" value={result.jobs} />}\n {result.engineStreams != null && result.engineStreams > 0 && <ResultCard label=\"Engine streams\" value={result.engineStreams} />}\n {result.workerStreams != null && result.workerStreams > 0 && <ResultCard label=\"Worker streams\" value={result.workerStreams} />}\n {result.streams != null && result.engineStreams == null && result.streams > 0 && <ResultCard label=\"Streams\" value={result.streams} />}\n {result.attributes != null && result.attributes > 0 && <ResultCard label=\"Artifacts stripped\" value={result.attributes} />}\n {result.transient != null && result.transient > 0 && <ResultCard label=\"Transient deleted\" value={result.transient} />}\n {result.marked != null && result.marked > 0 && <ResultCard label=\"Marked pruned\" value={result.marked} />}\n {Object.values(result).every((v) => !v || v === 0) && (\n <p className=\"text-xs text-text-tertiary\">Nothing to prune within the selected retention windows.</p>\n )}\n </div>\n </div>\n )}\n\n {prune.error && (\n <p className=\"text-xs text-status-error\">{(prune.error as Error).message}</p>\n )}\n\n {/* Confirm modal */}\n <Modal open={showConfirm} onClose={() => setShowConfirm(false)} title=\"Confirm Prune\">\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">\n This will permanently delete data. This action cannot be undone.\n </p>\n <ul className=\"text-xs text-text-secondary space-y-1 list-disc list-inside\">\n {fields.pruneJobs && <li>Delete jobs older than {fields.expire}</li>}\n {fields.engineStreams && <li>Delete engine streams older than {fields.engineStreamsExpire}</li>}\n {fields.workerStreams && <li>Delete worker streams older than {fields.workerStreamsExpire}</li>}\n {fields.stripAttributes && <li>Strip execution artifacts from completed jobs</li>}\n {fields.pruneTransient && <li>Delete transient (entity-less) jobs</li>}\n </ul>\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={() => setShowConfirm(false)} className=\"btn-secondary text-xs\">Cancel</button>\n <button\n onClick={handlePrune}\n className=\"bg-status-error text-white px-3 py-1.5 rounded-md text-xs hover:opacity-90 transition-opacity\"\n disabled={prune.isPending}\n >\n {prune.isPending ? 'Pruning...' : 'Confirm Prune'}\n </button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { Info } from 'lucide-react';\nimport {\n useMaintenanceConfig,\n useUpdateMaintenanceConfig,\n type MaintenanceConfig,\n} from '../../../api/maintenance';\nimport { CRON_PRESETS } from '../../../lib/constants';\nimport { PruneFieldsEditor, DEFAULT_PRUNE_FIELDS, type PruneFields } from './controls';\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Convert a MaintenanceConfig (rules array) into PruneFields for the editor. */\nfunction configToFields(config: MaintenanceConfig | undefined): PruneFields {\n if (!config?.rules?.length) return DEFAULT_PRUNE_FIELDS;\n const r = config.rules;\n const streamDelete = r.find((x) => x.target === 'streams' && x.action === 'delete');\n const jobDeleteTransient = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.hasEntity === false);\n const jobPrune = r.find((x) => x.target === 'jobs' && x.action === 'prune' && x.hasEntity === true);\n const jobDeletePruned = r.find((x) => x.target === 'jobs' && x.action === 'delete' && x.pruned === true);\n return {\n pruneJobs: !!jobDeletePruned,\n expire: jobDeletePruned?.olderThan ?? '180 days',\n engineStreams: !!streamDelete,\n engineStreamsExpire: streamDelete?.olderThan ?? '1 day',\n workerStreams: !!streamDelete,\n workerStreamsExpire: streamDelete?.olderThan ?? '90 days',\n stripAttributes: !!jobPrune,\n pruneTransient: !!jobDeleteTransient,\n };\n}\n\n/** Convert PruneFields back to a MaintenanceConfig rules array. */\nfunction fieldsToRules(f: PruneFields): MaintenanceConfig['rules'] {\n const rules: MaintenanceConfig['rules'] = [];\n if (f.engineStreams) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.engineStreamsExpire });\n }\n if (f.workerStreams && f.workerStreamsExpire !== f.engineStreamsExpire) {\n rules.push({ target: 'streams', action: 'delete', olderThan: f.workerStreamsExpire });\n }\n if (f.pruneTransient) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, hasEntity: false });\n }\n if (f.stripAttributes) {\n rules.push({ target: 'jobs', action: 'prune', olderThan: f.expire, hasEntity: true });\n }\n if (f.pruneJobs) {\n rules.push({ target: 'jobs', action: 'delete', olderThan: f.expire, pruned: true });\n }\n return rules;\n}\n\nfunction describeCron(expr: string): string {\n return CRON_PRESETS.find((p) => p.value === expr)?.label ?? '';\n}\n\n// ── Main ────────────────────────────────────────────────────────────────────\n\nexport function ScheduleSection() {\n const { data, isLoading } = useMaintenanceConfig();\n const updateConfig = useUpdateMaintenanceConfig();\n\n const [schedule, setSchedule] = useState('');\n const [fields, setFields] = useState<PruneFields>(DEFAULT_PRUNE_FIELDS);\n const [savedSnapshot, setSavedSnapshot] = useState('');\n\n // Sync from server config when loaded\n const syncFromServer = useCallback(() => {\n if (!data?.config) return;\n setSchedule(data.config.schedule);\n setFields(configToFields(data.config));\n setSavedSnapshot(JSON.stringify({ schedule: data.config.schedule, fields: configToFields(data.config) }));\n }, [data]);\n\n useEffect(() => { syncFromServer(); }, [syncFromServer]);\n\n const currentSnapshot = JSON.stringify({ schedule, fields });\n const isDirty = savedSnapshot !== '' && currentSnapshot !== savedSnapshot;\n const active = data?.active ?? false;\n\n const handleSave = () => {\n const rules = fieldsToRules(fields);\n updateConfig.mutate(\n { schedule, rules },\n {\n onSuccess: () => {\n setSavedSnapshot(JSON.stringify({ schedule, fields }));\n },\n },\n );\n };\n\n const handleRevert = () => {\n syncFromServer();\n };\n\n if (isLoading) {\n return <div className=\"animate-pulse h-40 bg-surface-sunken rounded\" />;\n }\n\n return (\n <div className=\"space-y-8\">\n {/* Cron schedule + status */}\n <div className=\"grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-10\">\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n Schedule\n </p>\n <div className=\"flex items-end gap-4\">\n <div>\n <label className=\"block text-[10px] text-text-tertiary mb-1\">Cron Expression</label>\n <input\n type=\"text\"\n value={schedule}\n onChange={(e) => setSchedule(e.target.value)}\n placeholder=\"0 2 * * *\"\n className=\"input text-xs font-mono w-48\"\n />\n </div>\n <div>\n <div className=\"flex items-center gap-1.5 h-8\">\n <span className={`w-1.5 h-1.5 rounded-full ${active ? 'bg-status-success' : 'bg-text-tertiary'}`} />\n <span className={`text-xs ${active ? 'text-status-success' : 'text-text-tertiary'}`}>\n {active ? 'Active' : 'Inactive'}\n </span>\n </div>\n </div>\n {describeCron(schedule) && (\n <p className=\"text-xs text-text-tertiary h-8 flex items-center\">{describeCron(schedule)}</p>\n )}\n </div>\n\n {/* Preset pills */}\n <div className=\"flex flex-wrap gap-1.5 mt-3\">\n {CRON_PRESETS.map((preset) => (\n <button\n key={preset.value}\n type=\"button\"\n onClick={() => setSchedule(preset.value)}\n className={`px-2.5 py-1 text-[10px] rounded-full transition-colors ${\n schedule === preset.value\n ? 'bg-accent/10 text-accent font-medium'\n : 'bg-surface-sunken text-text-tertiary hover:text-text-secondary'\n }`}\n >\n {preset.label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"lg:w-72\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-4\">\n How It Works\n </p>\n <div className=\"flex items-start gap-2 px-3 py-2 rounded bg-surface-sunken\">\n <Info className=\"w-3.5 h-3.5 text-text-tertiary shrink-0 mt-0.5\" />\n <p className=\"text-[10px] text-text-tertiary leading-relaxed\">\n Rules execute sequentially on each cron cycle. Engine streams can be pruned aggressively\n since they only contain internal routing data. Worker streams should be retained longer\n to preserve execution playback and input enrichment.\n </p>\n </div>\n </div>\n </div>\n\n {/* Same prune fields as Prune Now */}\n <PruneFieldsEditor fields={fields} onChange={setFields} />\n\n {/* Action bar */}\n <div className=\"flex items-center justify-between pt-2 border-t border-surface-border\">\n <div className=\"flex items-center gap-3\">\n {isDirty && (\n <button\n onClick={handleRevert}\n className=\"text-[10px] text-text-tertiary hover:text-text-primary transition-colors\"\n >\n Revert changes\n </button>\n )}\n {updateConfig.error && (\n <p className=\"text-xs text-status-error\">{(updateConfig.error as Error).message}</p>\n )}\n </div>\n <button\n onClick={handleSave}\n disabled={!isDirty || !schedule.trim() || updateConfig.isPending}\n className=\"btn-primary text-xs disabled:opacity-40 shrink-0\"\n >\n {updateConfig.isPending ? 'Saving...' : 'Save Schedule'}\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Trash2, Clock, Info } from 'lucide-react';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { PruneSection } from './PruneSection';\nimport { ScheduleSection } from './ScheduleSection';\n\ntype Mode = 'prune' | 'schedule';\n\nfunction ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {\n const btn = (m: Mode, icon: React.ReactNode, label: string) => (\n <button\n onClick={() => onChange(m)}\n className={`flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md transition-colors ${\n mode === m\n ? 'bg-accent/10 text-accent font-medium'\n : 'text-text-tertiary hover:text-text-secondary hover:bg-surface-hover'\n }`}\n >\n {icon}\n {label}\n </button>\n );\n\n return (\n <div className=\"flex gap-1 p-0.5 bg-surface-sunken rounded-lg w-fit\">\n {btn('prune', <Trash2 className=\"w-3.5 h-3.5\" />, 'Prune Now')}\n {btn('schedule', <Clock className=\"w-3.5 h-3.5\" />, 'Schedule')}\n </div>\n );\n}\n\nexport function MaintenancePage() {\n const [mode, setMode] = useState<Mode>('schedule');\n\n return (\n <div>\n <PageHeader\n title=\"DB Maintenance\"\n docsHash=\"#docs:dashboard.md:db-maintenance\"\n actions={<ModeToggle mode={mode} onChange={setMode} />}\n />\n\n <div className=\"flex items-start gap-2 px-4 py-3 mb-8 rounded-md bg-accent/5 border border-accent/10\">\n <Info className=\"w-4 h-4 text-accent shrink-0 mt-0.5\" />\n <p className=\"text-xs text-text-secondary leading-relaxed\">\n Completed process data grows indefinitely.\n Schedule regular pruning to keep the database lean and queries fast.\n Worker streams are retained longer than engine streams to preserve execution playback.\n </p>\n </div>\n\n {mode === 'prune' ? <PruneSection /> : <ScheduleSection />}\n </div>\n );\n}\n"],"names":["useMaintenanceConfig","useQuery","apiFetch","useUpdateMaintenanceConfig","queryClient","useQueryClient","useMutation","config","usePrune","options","RetentionRow","checked","onToggle","label","hint","value","onChange","jsxs","jsx","e","RETENTION_PERIOD_OPTIONS","opt","CleanupCheck","description","CleanupCallout","Info","DEFAULT_PRUNE_FIELDS","hasSelection","f","PruneFieldsEditor","fields","set","key","v","ResultCard","PruneSection","prune","setFields","useState","result","setResult","showConfirm","setShowConfirm","handlePrune","data","Modal","configToFields","_a","streamDelete","x","jobDeleteTransient","jobPrune","jobDeletePruned","fieldsToRules","rules","describeCron","expr","CRON_PRESETS","p","ScheduleSection","isLoading","updateConfig","schedule","setSchedule","savedSnapshot","setSavedSnapshot","syncFromServer","useCallback","useEffect","currentSnapshot","isDirty","active","handleSave","handleRevert","preset","ModeToggle","mode","btn","m","icon","Trash2","Clock","MaintenancePage","setMode","PageHeader"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import{a as x,j as e}from"./vendor-query-B2UbickB.js";import{e as Z,i as ee,u as B,j as te,b as se}from"./workflows-DNZf6Pmq.js";import{D as re}from"./DataTable-D9yuBv0w.js";import{C as ae}from"./ConfirmDeleteModal-dOxidrSR.js";import{F as ne,b as E}from"./FilterBar-Ck4K4rzu.js";import{R as oe,a as I}from"./RowActions-Dg-Fsm5O.js";import{u as le}from"./useFilterParams-DZCAaBC7.js";import{P as Q}from"./PageHeader-DLjHNYHX.js";import{R as L}from"./RolePill-Bp10-WfX.js";import{T as ie}from"./TaskQueuePill-DPwm25Cc.js";import{W as ce}from"./WorkflowPill-BbgVTGgI.js";import{a6 as O,S as ue,f as A,a9 as de,P as xe,aa as me,ab as pe,U as F,X as H,h as z,H as V,c as $}from"./vendor-icons-E6836lXZ.js";import{c as Y,e as he,f as fe}from"./vendor-react-CX88sFS5.js";import{S as we}from"./StepIndicator-CuUIGxKk.js";import{u as ve}from"./roles-BMAzzeHR.js";import{B as je}from"./BotPicker-CwfVVWxh.js";import"./index-BMIU7Im5.js";import"./EmptyState-BcsfPq9T.js";import"./Modal-DEODGeqx.js";import"./bots-zyUDnQhH.js";function ke(t,r){const l=r.toLowerCase();return t.workflow_type.toLowerCase().includes(l)||(t.description??"").toLowerCase().includes(l)}function Ve(){const t=Y(),{data:r,isLoading:l}=Z(),d=ee(),{filters:a,setFilter:i}=le({filters:{search:"",queue:"",role:"",tier:""}}),[u,y]=x.useState(a.search),[p,N]=x.useState(null);x.useEffect(()=>{if(u===a.search)return;const s=setTimeout(()=>i("search",u),300);return()=>clearTimeout(s)},[u,i,a.search]);const o=r??[],m=x.useMemo(()=>[...new Set(o.map(s=>s.task_queue).filter(Boolean))].sort(),[o]),c=x.useMemo(()=>[...new Set(o.flatMap(s=>s.roles??[]))].sort(),[o]),n=x.useMemo(()=>{let s=o;return a.search&&(s=s.filter(f=>ke(f,a.search))),a.queue&&(s=s.filter(f=>f.task_queue===a.queue)),a.role&&(s=s.filter(f=>(f.roles??[]).includes(a.role))),a.tier&&(s=s.filter(f=>f.tier===a.tier)),s},[o,a]),_=[{key:"workflow_type",label:"Workflow",className:"max-w-xs",render:s=>e.jsxs("div",{className:"min-w-0",children:[e.jsx(ce,{type:s.workflow_type,size:"md",variant:s.tier==="certified"?"certified":s.tier==="configured"?"configured":"durable"}),s.description&&e.jsx("p",{className:"text-[10px] leading-tight text-text-quaternary mt-0.5",children:s.description})]})},{key:"task_queue",label:"Queue",render:s=>s.task_queue?e.jsx(ie,{queue:s.task_queue}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"whitespace-nowrap"},{key:"tier",label:"Tier",render:s=>s.tier==="certified"?e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-medium text-text-secondary",children:[e.jsx(O,{className:"w-3 h-3"}),"Certified"]}):s.tier==="configured"?e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-medium text-text-secondary",children:[e.jsx(ue,{className:"w-3 h-3"}),"Configured"]}):e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-medium text-text-secondary",children:[e.jsx(A,{className:"w-3 h-3"}),"Durable"]}),className:"whitespace-nowrap"},{key:"roles",label:"Access",render:s=>{if(!s.registered)return e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"});const f=s.roles??[],w=s.invocation_roles??[];return!f.length&&!w.length?e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}):e.jsxs("div",{className:"space-y-1.5",children:[f.length>0&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{title:"Escalation roles",children:e.jsx(O,{className:"w-3 h-3 text-text-quaternary shrink-0"})}),e.jsx("div",{className:"flex gap-1 flex-wrap",children:f.map(b=>e.jsx(L,{role:b},`e-${b}`))})]}),w.length>0&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{title:"Invocation roles",children:e.jsx(de,{className:"w-3 h-3 text-text-quaternary shrink-0"})}),e.jsx("div",{className:"flex gap-1 flex-wrap",children:w.map(b=>e.jsx(L,{role:b},`i-${b}`))})]})]})}},{key:"actions",label:"",render:s=>e.jsxs(oe,{children:[s.invocable&&e.jsx(I,{icon:xe,title:"Invoke workflow",onClick:()=>t(`/workflows/start?type=${encodeURIComponent(s.workflow_type)}&mode=now`),colorClass:"text-text-tertiary hover:text-status-success"}),s.tier==="durable"&&e.jsx(I,{icon:A,title:"Configure workflow",onClick:()=>t(`/workflows/registry/new?workflow_type=${encodeURIComponent(s.workflow_type)}&task_queue=${encodeURIComponent(s.task_queue??"")}`),colorClass:"text-text-tertiary hover:text-status-info"}),s.tier==="configured"&&e.jsx(I,{icon:me,title:"Certify workflow",onClick:()=>t(`/workflows/registry/${encodeURIComponent(s.workflow_type)}`),colorClass:"text-text-tertiary hover:text-status-success"}),s.registered&&e.jsx(I,{icon:pe,title:"Remove configuration",onClick:()=>N(s.workflow_type),colorClass:"text-text-tertiary hover:text-status-warning"})]}),className:"w-16 text-right"}],R=()=>{p&&d.mutate(p,{onSuccess:()=>N(null)})},C=s=>{s.registered?t(`/workflows/registry/${encodeURIComponent(s.workflow_type)}`):t(`/workflows/registry/new?workflow_type=${encodeURIComponent(s.workflow_type)}&task_queue=${encodeURIComponent(s.task_queue??"")}`)};return e.jsxs("div",{children:[e.jsx(Q,{title:"Workflow Registry",docsHash:"#docs:dashboard.md:workflow-registry",actions:e.jsx("button",{onClick:()=>t("/workflows/registry/new"),className:"btn-primary text-xs",children:"Register Workflow"})}),e.jsxs(ne,{children:[e.jsx("input",{type:"text",placeholder:"Search workflow type...",value:u,onChange:s=>y(s.target.value),className:"input text-[11px] py-1 px-2 w-56"}),e.jsx(E,{label:"Queue",value:a.queue,onChange:s=>i("queue",s),options:m.map(s=>({value:s,label:s}))}),e.jsx(E,{label:"Tier",value:a.tier,onChange:s=>i("tier",s),options:[{value:"certified",label:"Certified"},{value:"configured",label:"Configured"},{value:"durable",label:"Durable"}]}),e.jsx(E,{label:"Role",value:a.role,onChange:s=>i("role",s),options:c.map(s=>({value:s,label:s}))})]}),e.jsx(re,{columns:_,data:n,keyFn:s=>s.workflow_type,onRowClick:C,isLoading:l,emptyMessage:"No workflows found"}),e.jsx(ae,{open:!!p,onClose:()=>N(null),onConfirm:R,title:"De-certify Workflow",description:e.jsxs(e.Fragment,{children:["Remove certification from ",e.jsx("span",{className:"font-mono font-medium text-text-primary",children:p}),"? This removes interceptor guarantees, escalation chains, and invocation role constraints. The workflow will continue running as a standard durable workflow."]}),isPending:d.isPending,error:d.error})]})}function S(t){return t.split(",").map(r=>r.trim()).filter(Boolean)}const T={workflow_type:"",description:"",task_queue:"",default_role:"reviewer",invocable:!1,roles:"",invocation_roles:"",consumes:"",envelope_schema:"",resolver_schema:"",cron_schedule:"",execute_as:"",certified:!1};function ge(t){const r=(t.roles??[]).join(", "),l=(t.consumes??[]).join(", ");return{workflow_type:t.workflow_type,description:t.description??"",task_queue:t.task_queue??"",default_role:t.default_role,invocable:t.invocable,roles:r,invocation_roles:(t.invocation_roles??[]).join(", "),consumes:l,envelope_schema:t.envelope_schema?JSON.stringify(t.envelope_schema,null,2):"",resolver_schema:t.resolver_schema?JSON.stringify(t.resolver_schema,null,2):"",cron_schedule:t.cron_schedule??"",execute_as:t.execute_as??"",certified:!!(r||l)}}const U=["Identity","Invocation","Advanced"];function P(t){if(!t.trim())return!0;try{return JSON.parse(t),!0}catch{return!1}}function J(t,r){return t===1?!!r.workflow_type.trim():t===2?P(r.envelope_schema):t===3?P(r.resolver_schema):!0}const g="label",j="hint",G="input-json w-full";function D({selected:t,onChange:r,single:l,placeholder:d}){const{data:a}=ve(),i=(a==null?void 0:a.roles)??[],[u,y]=x.useState(!1),p=x.useRef(null);x.useEffect(()=>{const c=n=>{p.current&&!p.current.contains(n.target)&&y(!1)};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[]);const N=c=>{l?(r(t.includes(c)?[]:[c]),y(!1)):r(t.includes(c)?t.filter(n=>n!==c):[...t,c])},o=c=>{r(t.filter(n=>n!==c))},m=d??(l?"Select role...":"Add roles...");return e.jsxs("div",{ref:p,className:"relative",children:[e.jsxs("button",{type:"button",onClick:()=>y(!u),className:"flex flex-wrap items-center gap-1.5 w-full min-h-[34px] px-2 py-1.5 bg-surface-sunken border border-surface-border rounded-md text-left cursor-pointer hover:border-accent/40 transition-colors focus:ring-1 focus:ring-accent focus:outline-none",children:[t.length===0&&e.jsx("span",{className:"text-xs text-text-tertiary",children:m}),t.map(c=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-lg bg-accent/[0.08] text-text-secondary text-[11px]",children:[e.jsx(F,{className:"w-2.5 h-2.5 shrink-0 text-accent/75"}),c,e.jsx("span",{role:"button",onClick:n=>{n.stopPropagation(),o(c)},className:"ml-0.5 hover:text-status-error transition-colors",children:e.jsx(H,{className:"w-2.5 h-2.5"})})]},c)),e.jsx(z,{className:`w-3.5 h-3.5 ml-auto shrink-0 text-text-tertiary transition-transform ${u?"rotate-180":""}`})]}),u&&e.jsx("div",{className:"absolute z-20 mt-1 w-full bg-white border border-surface-border rounded-md shadow-lg max-h-48 overflow-y-auto",children:i.length===0?e.jsx("p",{className:"px-3 py-2 text-xs text-text-tertiary",children:"No roles defined"}):i.map(c=>{const n=t.includes(c);return e.jsxs("button",{type:"button",onClick:()=>N(c),className:`flex items-center gap-2 w-full px-3 py-1.5 text-left text-xs transition-colors ${n?"bg-accent/[0.06] text-accent":"text-text-primary hover:bg-surface-sunken"}`,children:[e.jsx(F,{className:"w-3 h-3 shrink-0 text-accent/60"}),e.jsx("span",{className:"flex-1",children:c}),n&&e.jsx(V,{className:"w-3 h-3 shrink-0"})]},c)})})]})}function ye({options:t,selected:r,onChange:l,placeholder:d}){const[a,i]=x.useState(!1),u=x.useRef(null);x.useEffect(()=>{const o=m=>{u.current&&!u.current.contains(m.target)&&i(!1)};return document.addEventListener("mousedown",o),()=>document.removeEventListener("mousedown",o)},[]);const y=o=>{l(r.includes(o)?r.filter(m=>m!==o):[...r,o])},p=o=>{l(r.filter(m=>m!==o))},N=d??"Add workflows...";return e.jsxs("div",{ref:u,className:"relative",children:[e.jsxs("button",{type:"button",onClick:()=>i(!a),className:"flex flex-wrap items-center gap-1.5 w-full min-h-[34px] px-2 py-1.5 bg-surface-sunken border border-surface-border rounded-md text-left cursor-pointer hover:border-accent/40 transition-colors focus:ring-1 focus:ring-accent focus:outline-none",children:[r.length===0&&e.jsx("span",{className:"text-xs text-text-tertiary",children:N}),r.map(o=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-lg bg-accent/[0.08] text-text-secondary text-[11px] font-mono",children:[e.jsx($,{className:"w-2.5 h-2.5 shrink-0 text-accent/75"}),o,e.jsx("span",{role:"button",onClick:m=>{m.stopPropagation(),p(o)},className:"ml-0.5 hover:text-status-error transition-colors",children:e.jsx(H,{className:"w-2.5 h-2.5"})})]},o)),e.jsx(z,{className:`w-3.5 h-3.5 ml-auto shrink-0 text-text-tertiary transition-transform ${a?"rotate-180":""}`})]}),a&&e.jsx("div",{className:"absolute z-20 mt-1 w-full bg-white border border-surface-border rounded-md shadow-lg max-h-48 overflow-y-auto",children:t.length===0?e.jsx("p",{className:"px-3 py-2 text-xs text-text-tertiary",children:"No registered workflows"}):t.map(o=>{const m=r.includes(o);return e.jsxs("button",{type:"button",onClick:()=>y(o),className:`flex items-center gap-2 w-full px-3 py-1.5 text-left text-xs font-mono transition-colors ${m?"bg-accent/[0.06] text-accent":"text-text-primary hover:bg-surface-sunken"}`,children:[e.jsx($,{className:"w-3 h-3 shrink-0 text-accent/60"}),e.jsx("span",{className:"flex-1",children:o}),m&&e.jsx(V,{className:"w-3 h-3 shrink-0"})]},o)})})]})}function W(t){return S(t)}function M(t){return t.join(", ")}function Ne({form:t,set:r}){const{data:l}=B(),d=(l??[]).map(a=>a.workflow_type).filter(a=>a!==t.workflow_type);return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Resolver Schema"}),e.jsx("textarea",{value:t.resolver_schema,onChange:a=>r("resolver_schema",a.target.value),placeholder:`{
|
|
2
|
+
"properties": {
|
|
3
|
+
"approved": { "type": "boolean", "default": false, "description": "Approve?" },
|
|
4
|
+
"notes": { "type": "string", "default": "", "description": "Reviewer notes" }
|
|
5
|
+
}
|
|
6
|
+
}`,className:G,rows:8,spellCheck:!1}),e.jsxs("p",{className:j,children:["Default form template for resolving escalations from this workflow. Use ",e.jsx("span",{className:"font-mono",children:"properties"})," with ",e.jsx("span",{className:"font-mono",children:"type"}),", ",e.jsx("span",{className:"font-mono",children:"default"}),", ",e.jsx("span",{className:"font-mono",children:"description"}),", ",e.jsx("span",{className:"font-mono",children:"enum"}),", and ",e.jsx("span",{className:"font-mono",children:"format"})," for typed form fields."]}),t.resolver_schema.trim()&&!P(t.resolver_schema)&&e.jsx("p",{className:"text-[10px] text-status-error mt-1",children:"Invalid JSON"})]}),e.jsx("div",{className:"flex gap-6 pt-1",children:e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.certified,onChange:a=>r("certified",a.target.checked),className:"w-4 h-4 rounded border-border accent-accent"}),e.jsx("span",{className:"text-xs text-text-primary font-medium",children:"Certify for HITL Escalation"})]})}),e.jsx("p",{className:j,children:"Certified workflows use the interceptor to wrap executions — failures escalate to human reviewers instead of throwing."}),t.certified?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Default Escalation Role"}),e.jsx(D,{selected:W(t.default_role),onChange:a=>r("default_role",a[0]??""),single:!0,placeholder:"Select escalation role..."}),e.jsx("p",{className:j,children:"When this workflow escalates, assign to users with this role"})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Escalation Roles"}),e.jsx(D,{selected:W(t.roles),onChange:a=>r("roles",M(a)),placeholder:"Select who can resolve escalations..."}),e.jsx("p",{className:j,children:"Users with any of these roles can claim and resolve escalations from this workflow."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Consumes"}),e.jsx(ye,{options:d,selected:W(t.consumes),onChange:a=>r("consumes",M(a)),placeholder:"Select workflow dependencies..."}),e.jsx("p",{className:j,children:"Output from these upstream workflows will be injected into the input envelope for this workflow."})]})]}):e.jsx("div",{className:"py-4 px-4 bg-surface-sunken/50 rounded-md text-center",children:e.jsxs("p",{className:"text-xs text-text-tertiary",children:["This workflow will run as standard durable without the interceptor. Enable"," ",e.jsx("span",{className:"font-medium text-text-secondary",children:"Certify for HITL Escalation"})," ","to add automatic escalation routing and role-based resolution."]})})]})}function be(t){return S(t)}function _e(t){return t.join(", ")}function Ce({form:t,set:r,editing:l,durableTypes:d=[]}){const a=!l&&d.length>0;return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Workflow Type"}),a&&!t.workflow_type?e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-xs text-text-secondary",children:"Select a durable workflow to register:"}),e.jsx("div",{className:"grid gap-1",children:d.map(i=>e.jsx("button",{onClick:()=>r("workflow_type",i),className:"flex items-center gap-2 px-3 py-2 text-left text-xs font-mono rounded-md border border-surface-border hover:border-accent/50 hover:bg-accent/[0.04] transition-colors",children:i},i))}),e.jsxs("div",{className:"flex items-center gap-2 pt-1",children:[e.jsx("span",{className:"text-[10px] text-text-tertiary",children:"or"}),e.jsx("input",{type:"text",onChange:i=>r("workflow_type",i.target.value),placeholder:"Enter a workflow type manually",className:"input font-mono flex-1"})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("input",{type:"text",value:t.workflow_type,onChange:i=>r("workflow_type",i.target.value),disabled:l,placeholder:"reviewContent",className:"input font-mono w-full"}),!l&&t.workflow_type&&d.length>0&&e.jsx("button",{onClick:()=>r("workflow_type",""),className:"text-[10px] text-accent hover:underline mt-1",children:"Choose from durable workflows"})]}),e.jsx("p",{className:j,children:"Register a workflow to configure invocation schemas and dashboard visibility. Certification for HITL escalation is optional (step 3)."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Description"}),e.jsx("input",{type:"text",value:t.description,onChange:i=>r("description",i.target.value),placeholder:"AI-powered content moderation with human escalation",className:"input text-xs w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Task Queue"}),e.jsx("input",{type:"text",value:t.task_queue,onChange:i=>r("task_queue",i.target.value),placeholder:"lt-review",className:"input font-mono w-full"}),e.jsx("p",{className:j,children:"Durable task queue this workflow listens on"})]})]})}function Se({form:t,set:r}){return e.jsxs("div",{className:"space-y-5",children:[e.jsx("div",{className:"flex gap-6 pt-1",children:e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.invocable,onChange:l=>r("invocable",l.target.checked),className:"w-4 h-4 rounded border-border accent-accent"}),e.jsx("span",{className:"text-xs text-text-primary font-medium",children:"Invocable"})]})}),e.jsx("p",{className:j,children:"Allow this workflow to be started from the dashboard or API."}),t.invocable&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Run As"}),e.jsx(je,{selected:t.execute_as,onChange:l=>r("execute_as",l)}),e.jsx("p",{className:j,children:"Choose a bot to execute this workflow under its identity and credentials. Default runs as the invoking user."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Invocation Roles"}),e.jsx(D,{selected:be(t.invocation_roles),onChange:l=>r("invocation_roles",_e(l)),placeholder:"Select who can start this workflow..."}),e.jsx("p",{className:j,children:"Only users with these roles can start this workflow. Leave empty to allow all authenticated users."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Envelope Schema"}),e.jsx("textarea",{value:t.envelope_schema,onChange:l=>r("envelope_schema",l.target.value),placeholder:`{
|
|
7
|
+
"data": {
|
|
8
|
+
"contentId": "example-123",
|
|
9
|
+
"content": "Text to review"
|
|
10
|
+
},
|
|
11
|
+
"metadata": {
|
|
12
|
+
"source": "dashboard"
|
|
13
|
+
}
|
|
14
|
+
}`,className:G,rows:8,spellCheck:!1}),e.jsxs("p",{className:j,children:["Pre-fills the JSON editor when invoking this workflow. Should include ",e.jsx("span",{className:"font-mono",children:"data"})," (workflow input) and optional ",e.jsx("span",{className:"font-mono",children:"metadata"})," (context)."]}),t.envelope_schema.trim()&&!P(t.envelope_schema)&&e.jsx("p",{className:"text-[10px] text-status-error mt-1",children:"Invalid JSON"})]})]}),!t.invocable&&e.jsx("div",{className:"py-4 px-4 bg-surface-sunken/50 rounded-md text-center",children:e.jsxs("p",{className:"text-xs text-text-tertiary",children:["Enable ",e.jsx("span",{className:"font-medium text-text-secondary",children:"Invocable"})," above to configure who can start this workflow and set an input template."]})})]})}function Ye(){const{workflowType:t}=he(),r=!t,l=Y(),{data:d,isLoading:a}=B(),i=te(),u=(d==null?void 0:d.find(h=>h.workflow_type===t))??null,y=new Set(["mcpQuery","mcpDeterministic","mcpQueryRouter","mcpTriage","mcpTriageRouter","mcpTriageDeterministic","insightQuery"]),{data:p}=se({limit:500}),N=x.useMemo(()=>{const h=new Set((d??[]).map(v=>v.workflow_type));return[...new Set(((p==null?void 0:p.jobs)??[]).map(v=>v.entity))].filter(v=>!h.has(v)&&!y.has(v)).sort()},[d,p]),[o,m]=fe(),c=x.useMemo(()=>{if(!r)return T;const h=o.get("workflow_type")??"",k=o.get("task_queue")??"";return!h&&!k?T:{...T,workflow_type:h,task_queue:k}},[r,o]),[n,_]=x.useState(c),[R,C]=x.useState(""),[s,f]=x.useState(!1),w=parseInt(o.get("step")||"1",10),b=x.useCallback(h=>{m(k=>{const v=new URLSearchParams(k);return v.set("step",String(h)),v},{replace:!1})},[m]);x.useEffect(()=>{if(!s){if(r){_(c),f(!0);return}u&&(_(ge(u)),f(!0))}},[u,r,s,c]);const q=(h,k)=>_(v=>({...v,[h]:k})),K=()=>{if(!n.workflow_type.trim())return;C("");let h=null,k=null;try{n.envelope_schema.trim()&&(h=JSON.parse(n.envelope_schema))}catch{C("Invalid JSON in Envelope Schema");return}try{n.resolver_schema.trim()&&(k=JSON.parse(n.resolver_schema))}catch{C("Invalid JSON in Resolver Schema");return}i.mutate({workflow_type:n.workflow_type.trim(),description:n.description.trim()||null,task_queue:n.task_queue.trim()||null,default_role:n.default_role.trim()||"reviewer",invocable:n.invocable,roles:S(n.roles),invocation_roles:S(n.invocation_roles),consumes:S(n.consumes),envelope_schema:h,resolver_schema:k,cron_schedule:n.cron_schedule.trim()||null,execute_as:n.execute_as.trim()||null},{onSuccess:()=>{l("/workflows/registry")}})};if(a)return e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-48"}),e.jsx("div",{className:"h-60 bg-surface-sunken rounded"})]});if(!r&&!u)return e.jsx("p",{className:"text-sm text-text-secondary",children:"Config not found."});const X=w===U.length;return e.jsxs("div",{children:[e.jsx(Q,{title:r?"Register Workflow":(u==null?void 0:u.workflow_type)??""}),e.jsxs("div",{className:"max-w-3xl",children:[e.jsx(we,{steps:U,currentStep:w-1,onStepClick:h=>b(h+1)}),e.jsxs("div",{className:"min-h-[360px] py-2",children:[w===1&&e.jsx(Ce,{form:n,set:q,editing:!!u,durableTypes:N}),w===2&&e.jsx(Se,{form:n,set:q}),w===3&&e.jsx(Ne,{form:n,set:q})]}),(R||i.error)&&e.jsx("p",{className:"text-xs text-status-error mt-4",children:R||i.error.message}),e.jsxs("div",{className:"flex justify-between items-center pt-4 border-t border-surface-border mt-4",children:[e.jsx("div",{children:w>1&&e.jsx("button",{onClick:()=>b(w-1),className:"btn-secondary text-xs",children:"Back"})}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx("button",{onClick:()=>l("/workflows/registry"),className:"btn-ghost text-xs",children:"Cancel"}),X?e.jsx("button",{onClick:K,disabled:!J(w,n)||i.isPending,className:"btn-primary text-xs",children:i.isPending?"Saving...":u?"Save":"Create"}):e.jsx("button",{onClick:()=>b(w+1),disabled:!J(w,n),className:"btn-primary text-xs",children:"Next"})]})]})]})]})}export{Ye as WorkflowConfigDetailPage,Ve as WorkflowConfigsPage};
|
|
15
|
+
//# sourceMappingURL=index-M17tP_HX.js.map
|