@hotmeshio/long-tail 0.24.1 → 0.25.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/build/api/escalations/accumulate.js +8 -4
- package/build/api/escalations/metadata.js +4 -3
- package/build/api/escalations/related.d.ts +1 -1
- package/build/api/escalations/related.js +28 -18
- package/build/lib/db/schemas/040_oauth_client_consent.sql +15 -0
- package/build/modules/config.d.ts +4 -0
- package/build/modules/config.js +4 -0
- package/build/modules/maintenance.d.ts +1 -1
- package/build/modules/maintenance.js +1 -1
- package/build/services/auth/oauth-server/index.d.ts +1 -1
- package/build/services/auth/oauth-server/index.js +2 -1
- package/build/services/auth/oauth-server/sql.d.ts +7 -4
- package/build/services/auth/oauth-server/sql.js +10 -4
- package/build/services/auth/oauth-server/store.d.ts +8 -1
- package/build/services/auth/oauth-server/store.js +31 -2
- package/build/services/escalation/accumulate.d.ts +3 -1
- package/build/services/escalation/facet-sql.js +4 -2
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +4 -1
- package/build/services/escalation/related-extremes.d.ts +17 -0
- package/build/services/escalation/related-extremes.js +65 -0
- package/build/services/escalation/related.d.ts +4 -0
- package/build/services/escalation/related.js +2 -0
- package/build/services/escalation/resolver-validation.js +7 -0
- package/build/services/escalation/roster.d.ts +13 -0
- package/build/services/escalation/roster.js +37 -0
- package/build/services/escalation/submit-guard.d.ts +3 -0
- package/build/services/escalation/submit-guard.js +21 -2
- package/build/services/maintenance/index.js +1 -1
- package/build/services/mcp/server-tools.js +1 -1
- package/build/shared/form-validation/display-only-widgets.d.ts +1 -0
- package/build/shared/form-validation/display-only-widgets.js +1 -0
- package/build/shared/form-validation/index.d.ts +1 -0
- package/build/shared/form-validation/index.js +1 -0
- package/build/shared/form-validation/validate-resolver-payload.d.ts +1 -0
- package/build/shared/form-validation/validate-resolver-payload.js +2 -1
- package/build/shared/form-validation/x-lt-help.d.ts +1 -1
- package/build/shared/form-validation/x-lt-help.js +2 -1
- package/build/shared/form-validation/x-lt-roster.d.ts +92 -0
- package/build/shared/form-validation/x-lt-roster.js +234 -0
- package/build/shared/form-validation/x-lt-show-if.d.ts +8 -0
- package/build/shared/form-validation/x-lt-show-if.js +13 -0
- package/build/shared/form-validation/x-lt-submit-guard.d.ts +14 -1
- package/build/shared/form-validation/x-lt-submit-guard.js +4 -1
- package/build/shared/list-schema/aggregate.d.ts +19 -0
- package/build/shared/list-schema/aggregate.js +66 -0
- package/build/shared/list-schema/index.d.ts +2 -0
- package/build/shared/list-schema/index.js +7 -1
- package/build/shared/list-schema/types.d.ts +15 -2
- package/build/shared/list-schema/types.js +6 -1
- package/build/shared/list-schema/validate.js +28 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/dashboard/dist/assets/{AdminDashboard-B3mkMIOT.js → AdminDashboard-DWVRAu63.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-B3mkMIOT.js.map → AdminDashboard-DWVRAu63.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CQj2B678.js → AgentConfigPage-Exjtjbvp.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-CQj2B678.js.map → AgentConfigPage-Exjtjbvp.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CzrD8JJI.js → AgentDetailPage-nDbZo6RB.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CzrD8JJI.js.map → AgentDetailPage-nDbZo6RB.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-jg2OFwyW.js → AgentsPage-Dsk9iHps.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-jg2OFwyW.js.map → AgentsPage-Dsk9iHps.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-D1mCqj8Z.js +2 -0
- package/dashboard/dist/assets/{AvailableEscalationsPage-IS28XBRe.js.map → AvailableEscalationsPage-D1mCqj8Z.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-DvEJFpwS.js → BotPicker-u5760MWZ.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-DvEJFpwS.js.map → BotPicker-u5760MWZ.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-BoQCi-YC.js → BulkAssignModal-CtISXXmW.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-BoQCi-YC.js.map → BulkAssignModal-CtISXXmW.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-kwlrcb_t.js → CapabilitiesPage-BKIlrQfU.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-kwlrcb_t.js.map → CapabilitiesPage-BKIlrQfU.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-UMIV4KIj.js → CollapsibleSection-DlBVTFqc.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-UMIV4KIj.js.map → CollapsibleSection-DlBVTFqc.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-C5puwMg7.js → ConfirmDeleteModal-Pabkchg_.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-C5puwMg7.js.map → ConfirmDeleteModal-Pabkchg_.js.map} +1 -1
- package/dashboard/dist/assets/{ConnectedAppsPage-drZa65kP.js → ConnectedAppsPage-DG2YZGN3.js} +2 -2
- package/dashboard/dist/assets/{ConnectedAppsPage-drZa65kP.js.map → ConnectedAppsPage-DG2YZGN3.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-5t8S2qMi.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-5t8S2qMi.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-CaFQ6vLb.js → CredentialsPage-CPVbYQow.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CaFQ6vLb.js.map → CredentialsPage-CPVbYQow.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-Co5j7tzW.js → CronLabel-C7UbTrO-.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-Co5j7tzW.js.map → CronLabel-C7UbTrO-.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-B1Tdfddc.js → DropZone-DCZpORx-.js} +2 -2
- package/dashboard/dist/assets/{DropZone-B1Tdfddc.js.map → DropZone-DCZpORx-.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-WJyE9G0T.js → ElapsedCell-Yz7-LbtE.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-WJyE9G0T.js.map → ElapsedCell-Yz7-LbtE.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-CDFFfX9d.js → EntityTimelinePanel-xgPRdKEq.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-CDFFfX9d.js.map → EntityTimelinePanel-xgPRdKEq.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-CMrUlaKI.js → EscalationListSchemaPage-CqCd-y6B.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-CMrUlaKI.js.map → EscalationListSchemaPage-CqCd-y6B.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-Dx2Lyfrz.js → EscalationSchemaPage-D8YVQNph.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-Dx2Lyfrz.js.map → EscalationSchemaPage-D8YVQNph.js.map} +1 -1
- package/dashboard/dist/assets/EscalationTimeline-D6jrDcBb.js +2 -0
- package/dashboard/dist/assets/{EscalationTimeline-d3nvshOk.js.map → EscalationTimeline-D6jrDcBb.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-DWQieOM9.js → EscalationTitleSelect-CGGT-QTu.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-DWQieOM9.js.map → EscalationTitleSelect-CGGT-QTu.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BX8Cpi0X.js → EscalationsOverview-B7O4ttP4.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BX8Cpi0X.js.map → EscalationsOverview-B7O4ttP4.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-D1-ITVXS.js → EventTable-DJniXnhe.js} +2 -2
- package/dashboard/dist/assets/{EventTable-D1-ITVXS.js.map → EventTable-DJniXnhe.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-ABC9ctin.js → FilterBar-f-LEKcHI.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-ABC9ctin.js.map → FilterBar-f-LEKcHI.js.map} +1 -1
- package/dashboard/dist/assets/{FormattedValue-k27T4bG7.js → FormattedValue-CUtv1g3k.js} +2 -2
- package/dashboard/dist/assets/{FormattedValue-k27T4bG7.js.map → FormattedValue-CUtv1g3k.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DKUErxWc.js → GraphInvokePage-CR0MtYv8.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DKUErxWc.js.map → GraphInvokePage-CR0MtYv8.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-C6u9dIpR.js → HomePage-HVw7T5ER.js} +2 -2
- package/dashboard/dist/assets/{HomePage-C6u9dIpR.js.map → HomePage-HVw7T5ER.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-gA5rFzkz.js → ListToolbar-CTGK5BXW.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-gA5rFzkz.js.map → ListToolbar-CTGK5BXW.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BOPo3J_i.js → McpOverview-B2bbKKu2.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BOPo3J_i.js.map → McpOverview-B2bbKKu2.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BRVVi0Zh.js → McpQueryDetailPage-DgLxwwJy.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BRVVi0Zh.js.map → McpQueryDetailPage-DgLxwwJy.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-Dmbb6SAc.js → McpQueryPage-CSkczeJP.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-Dmbb6SAc.js.map → McpQueryPage-CSkczeJP.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-CrUsDPRD.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-bMXNO-6V.js.map → McpRunDetailPage-CrUsDPRD.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-Bi9AMWja.js → McpRunsPage-twxFdTtJ.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-Bi9AMWja.js.map → McpRunsPage-twxFdTtJ.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-DwM5pNA4.js → NamespacePill-CSZT2fA4.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-DwM5pNA4.js.map → NamespacePill-CSZT2fA4.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-CvR74ZUJ.js → OperationsPage-gOVMrL_a.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-CvR74ZUJ.js.map → OperationsPage-gOVMrL_a.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-BoeZIyup.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-DctmZw10.js.map → OperatorDashboard-BoeZIyup.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-CMd3f4bz.js → PageHeader-C4z1ExF7.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-CMd3f4bz.js.map → PageHeader-C4z1ExF7.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DHj8Mqox.js → PageHeaderWithStats-B_f_Sz_Q.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DHj8Mqox.js.map → PageHeaderWithStats-B_f_Sz_Q.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-Ubqm2rQH.js → PersonaDetailPage-CDktk1mi.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-Ubqm2rQH.js.map → PersonaDetailPage-CDktk1mi.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BpFL2rpo.js → PersonasPage-Bs097x07.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BpFL2rpo.js.map → PersonasPage-Bs097x07.js.map} +1 -1
- package/dashboard/dist/assets/PortalPage-DjfjerpF.js +2 -0
- package/dashboard/dist/assets/{PortalPage-Dfc_Q02R.js.map → PortalPage-DjfjerpF.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-liJspvQh.js → ProcessDetailPage-B30RatjD.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-liJspvQh.js.map → ProcessDetailPage-B30RatjD.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-C3OM5ZUy.js → ProcessesListPage-DrvjzgWT.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-C3OM5ZUy.js.map → ProcessesListPage-DrvjzgWT.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-Bl8Pibyz.js +8 -0
- package/dashboard/dist/assets/ResolverForm-Bl8Pibyz.js.map +1 -0
- package/dashboard/dist/assets/{RoleDetailPage-CrlYCh-R.js → RoleDetailPage-ClYgn-3d.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-CrlYCh-R.js.map → RoleDetailPage-ClYgn-3d.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-Di2CAHuD.js → RolePill-Bw_n7EpR.js} +2 -2
- package/dashboard/dist/assets/{RolePill-Di2CAHuD.js.map → RolePill-Bw_n7EpR.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-BaazL_pt.js → RolesPage-B_3qWsvQ.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-BaazL_pt.js.map → RolesPage-B_3qWsvQ.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-DxuV0fa1.js → RunAsSelector-CbJT50Hp.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-DxuV0fa1.js.map → RunAsSelector-CbJT50Hp.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-C0mvmYTq.js → ScanCodesPage-CIIDuh8w.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-C0mvmYTq.js.map → ScanCodesPage-CIIDuh8w.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CiJgt5dZ.js → ScanSchemeDetailPage-Bd3P3eyh.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CiJgt5dZ.js.map → ScanSchemeDetailPage-Bd3P3eyh.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-BiO34nov.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-BiO34nov.js.map +1 -0
- package/dashboard/dist/assets/{ScopeBadge-CSItPVOH.js → ScopeBadge-CKgfwTy3.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CSItPVOH.js.map → ScopeBadge-CKgfwTy3.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CqbjVY6T.js → StickyPagination-BNOuYZ1m.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CqbjVY6T.js.map → StickyPagination-BNOuYZ1m.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-wX3i0aqs.js → StreamMessageDetail-ALVUnfF1.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-wX3i0aqs.js.map → StreamMessageDetail-ALVUnfF1.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-C50PsFoV.js → SwimlaneTimeline-B5b8-xqI.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-C50PsFoV.js.map → SwimlaneTimeline-B5b8-xqI.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-CAgdLN_b.js → TagInput-B6fMAqxd.js} +2 -2
- package/dashboard/dist/assets/{TagInput-CAgdLN_b.js.map → TagInput-B6fMAqxd.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-bbNSv4Ae.js → TaskDetailPage-CoV3WcTA.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-bbNSv4Ae.js.map → TaskDetailPage-CoV3WcTA.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-h0oorVMe.js → TaskQueuePill-BnDp_DE6.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-h0oorVMe.js.map → TaskQueuePill-BnDp_DE6.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CDWnm_d9.js → TasksListPage-CkMmOYOE.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CDWnm_d9.js.map → TasksListPage-CkMmOYOE.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BLjqlfoX.js → TimeAgo-DVkFgECX.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BLjqlfoX.js.map → TimeAgo-DVkFgECX.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-CnW0ENb5.js → TimestampCell-CfTc6Txy.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-CnW0ENb5.js.map → TimestampCell-CfTc6Txy.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-CQCsVdzD.js → ToolPill-BRZWo4l8.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-CQCsVdzD.js.map → ToolPill-BRZWo4l8.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-DkMgCB-k.js → ToolTestPanel-kvqZqM0A.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-DkMgCB-k.js.map → ToolTestPanel-kvqZqM0A.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-g3pljKKX.js → TopicDetailPage-CjkAAyy8.js} +4 -4
- package/dashboard/dist/assets/{TopicDetailPage-g3pljKKX.js.map → TopicDetailPage-CjkAAyy8.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CVcCYdy-.js → TopicsPage-CJZnv50y.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CVcCYdy-.js.map → TopicsPage-CJZnv50y.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-D6zGIK2i.js → UserName-CPJPZnN1.js} +2 -2
- package/dashboard/dist/assets/{UserName-D6zGIK2i.js.map → UserName-CPJPZnN1.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-46UV5pJd.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-B8g81FCJ.js.map → WorkflowExecutionPage-46UV5pJd.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-Dg7BDTyM.js → WorkflowPill-Cly9Ln_3.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-Dg7BDTyM.js.map → WorkflowPill-Cly9Ln_3.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-nxT3bv6W.js → WorkflowsDashboard-DtxYdQbQ.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-nxT3bv6W.js.map → WorkflowsDashboard-DtxYdQbQ.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-grI-KAI2.js → WorkflowsOverview-Cg4LSfck.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-grI-KAI2.js.map → WorkflowsOverview-Cg4LSfck.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BoZ-hfBE.js → YamlWorkflowDetailPage-Del-RCgi.js} +12 -12
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BoZ-hfBE.js.map → YamlWorkflowDetailPage-Del-RCgi.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-Bf04rwRv.js → YamlWorkflowsPage-BF6Jtx24.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-Bf04rwRv.js.map → YamlWorkflowsPage-BF6Jtx24.js.map} +1 -1
- package/dashboard/dist/assets/{agents-Dphpdi8l.js → agents-wL-3dMOX.js} +2 -2
- package/dashboard/dist/assets/{agents-Dphpdi8l.js.map → agents-wL-3dMOX.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DIFE298x.js → bots-D72EsztP.js} +2 -2
- package/dashboard/dist/assets/{bots-DIFE298x.js.map → bots-D72EsztP.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-D7Y7LClY.js → capabilities-DXFo6bRb.js} +2 -2
- package/dashboard/dist/assets/{capabilities-D7Y7LClY.js.map → capabilities-DXFo6bRb.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-D1TGcYsS.js → controlplane-gQdOgVtH.js} +2 -2
- package/dashboard/dist/assets/{controlplane-D1TGcYsS.js.map → controlplane-gQdOgVtH.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-CSE5wfWQ.js +2 -0
- package/dashboard/dist/assets/escalation-columns-CSE5wfWQ.js.map +1 -0
- package/dashboard/dist/assets/escalation-items-BIgBWbaw.js +2 -0
- package/dashboard/dist/assets/escalation-items-BIgBWbaw.js.map +1 -0
- package/dashboard/dist/assets/{index-CeCtqujG.js → index-BaCDL5fh.js} +38 -38
- package/dashboard/dist/assets/index-BaCDL5fh.js.map +1 -0
- package/dashboard/dist/assets/{index-Dl_8hbYI.js → index-Btm8FtTQ.js} +2 -2
- package/dashboard/dist/assets/{index-Dl_8hbYI.js.map → index-Btm8FtTQ.js.map} +1 -1
- package/dashboard/dist/assets/index-BvH8T-jb.js +2 -0
- package/dashboard/dist/assets/{index-CxdjT1Yk.js.map → index-BvH8T-jb.js.map} +1 -1
- package/dashboard/dist/assets/{index-HLu98Sqh.js → index-C-QQ5rKF.js} +2 -2
- package/dashboard/dist/assets/{index-HLu98Sqh.js.map → index-C-QQ5rKF.js.map} +1 -1
- package/dashboard/dist/assets/{index-DpKOr311.js → index-C1iuZ4Q5.js} +2 -2
- package/dashboard/dist/assets/{index-DpKOr311.js.map → index-C1iuZ4Q5.js.map} +1 -1
- package/dashboard/dist/assets/{index-ChV7pBjM.js → index-CDxOQ84B.js} +2 -2
- package/dashboard/dist/assets/{index-ChV7pBjM.js.map → index-CDxOQ84B.js.map} +1 -1
- package/dashboard/dist/assets/index-CED9cLE2.js +3 -0
- package/dashboard/dist/assets/index-CED9cLE2.js.map +1 -0
- package/dashboard/dist/assets/index-CnU7Jjz3.css +1 -0
- package/dashboard/dist/assets/{index-DAvi5_2T.js → index-CptTEhWp.js} +2 -2
- package/dashboard/dist/assets/{index-DAvi5_2T.js.map → index-CptTEhWp.js.map} +1 -1
- package/dashboard/dist/assets/{index-ag2pCAPu.js → index-Cu0xdX2t.js} +2 -2
- package/dashboard/dist/assets/{index-ag2pCAPu.js.map → index-Cu0xdX2t.js.map} +1 -1
- package/dashboard/dist/assets/index-D1lfq5iZ.js +13 -0
- package/dashboard/dist/assets/{index-gkxPN7Vx.js.map → index-D1lfq5iZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dy1wWu2e.js → index-czgLyfSo.js} +2 -2
- package/dashboard/dist/assets/{index-Dy1wWu2e.js.map → index-czgLyfSo.js.map} +1 -1
- package/dashboard/dist/assets/{index-DN-kX7hL.js → index-h1Useskt.js} +2 -2
- package/dashboard/dist/assets/{index-DN-kX7hL.js.map → index-h1Useskt.js.map} +1 -1
- package/dashboard/dist/assets/{index-BzYcUPdD.js → index-ujGmmwl6.js} +2 -2
- package/dashboard/dist/assets/{index-BzYcUPdD.js.map → index-ujGmmwl6.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-DnMs-SOJ.js → knowledge-150lsM68.js} +2 -2
- package/dashboard/dist/assets/{knowledge-DnMs-SOJ.js.map → knowledge-150lsM68.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CwW-K3r4.js → mcp-CRtY4v5W.js} +2 -2
- package/dashboard/dist/assets/{mcp-CwW-K3r4.js.map → mcp-CRtY4v5W.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-BZt5e8_Q.js → mcp-query-CDsSMaYq.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-BZt5e8_Q.js.map → mcp-query-CDsSMaYq.js.map} +1 -1
- package/dashboard/dist/assets/{personas-UA-Xn60f.js → personas-C2Wm4ng1.js} +2 -2
- package/dashboard/dist/assets/{personas-UA-Xn60f.js.map → personas-C2Wm4ng1.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Cu3PARum.js → pipelines-BH0F9-jf.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Cu3PARum.js.map → pipelines-BH0F9-jf.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BO6h8GJE.js → tasks-BkUVpaOa.js} +2 -2
- package/dashboard/dist/assets/{tasks-BO6h8GJE.js.map → tasks-BkUVpaOa.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CWjCR-17.js → topics-Crl8HKHq.js} +2 -2
- package/dashboard/dist/assets/{topics-CWjCR-17.js.map → topics-Crl8HKHq.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-6t0jx1RB.js → useDebouncedValue-Dk3r5xo-.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-6t0jx1RB.js.map → useDebouncedValue-Dk3r5xo-.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CqpoQx6D.js → useNamespace-BXuyHKAs.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CqpoQx6D.js.map → useNamespace-BXuyHKAs.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-hmCQQwzB.js → useYamlActivityEvents-DSlkjQfb.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-hmCQQwzB.js.map → useYamlActivityEvents-DSlkjQfb.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-CeVtUKyP.js → vendor-icons-C_DQEeBy.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-CeVtUKyP.js.map → vendor-icons-C_DQEeBy.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-ziUdZhKY.js → yaml-workflows-B230v5Za.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-ziUdZhKY.js.map → yaml-workflows-B230v5Za.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/faceted-routing.md +14 -1
- package/docs/hitl/x-lt-embed.md +4 -1
- package/docs/hitl/x-lt-list-schema.md +19 -2
- package/docs/hitl/x-lt-roster.md +112 -0
- package/docs/hitl/x-lt-show-if.md +15 -0
- package/docs/hitl/x-lt-widget.md +1 -0
- package/docs/hitl-guide.md +3 -1
- package/docs/maintenance.md +3 -3
- package/docs/mcp.md +2 -0
- package/docs/scan-codes.md +4 -0
- package/docs/schema-enforcement.md +5 -0
- package/package.json +2 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-IS28XBRe.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-LG03dVgR.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-LG03dVgR.js.map +0 -1
- package/dashboard/dist/assets/EscalationTimeline-d3nvshOk.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-bMXNO-6V.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-DctmZw10.js +0 -2
- package/dashboard/dist/assets/PortalPage-Dfc_Q02R.js +0 -2
- package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js +0 -8
- package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-DzGaXc40.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-DzGaXc40.js.map +0 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-B8g81FCJ.js +0 -2
- package/dashboard/dist/assets/escalation-columns-cwZE6xyo.js +0 -2
- package/dashboard/dist/assets/escalation-columns-cwZE6xyo.js.map +0 -1
- package/dashboard/dist/assets/index-CeCtqujG.js.map +0 -1
- package/dashboard/dist/assets/index-CniRa65p.js +0 -3
- package/dashboard/dist/assets/index-CniRa65p.js.map +0 -1
- package/dashboard/dist/assets/index-CxdjT1Yk.js +0 -2
- package/dashboard/dist/assets/index-gkxPN7Vx.js +0 -13
- package/dashboard/dist/assets/index-m9A3UYst.css +0 -1
- package/dashboard/dist/assets/validate-BIRn4a6d.js +0 -2
- package/dashboard/dist/assets/validate-BIRn4a6d.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as l,b as a,c as s}from"./vendor-query-DvWWuNIB.js";import{m as r}from"./index-
|
|
2
|
-
//# sourceMappingURL=yaml-workflows-
|
|
1
|
+
import{u as l,b as a,c as s}from"./vendor-query-DvWWuNIB.js";import{m as r}from"./index-BaCDL5fh.js";function f(e={}){const o=new URLSearchParams;return e.status&&o.set("status",e.status),e.graph_topic&&o.set("graph_topic",e.graph_topic),e.app_id&&o.set("app_id",e.app_id),e.search&&o.set("search",e.search),e.set_id&&o.set("set_id",e.set_id),e.limit&&o.set("limit",String(e.limit)),e.offset!==void 0&&o.set("offset",String(e.offset)),l({queryKey:["yamlWorkflows",e],queryFn:()=>r(`/yaml-workflows?${o}`)})}function m(){return l({queryKey:["yamlWorkflowAppIds"],queryFn:()=>r("/yaml-workflows/app-ids")})}function c(e){return l({queryKey:["yamlWorkflows",e],queryFn:()=>r(`/yaml-workflows/${e}`),enabled:!!e})}function w(){const e=a();return s({mutationFn:o=>r("/yaml-workflows",{method:"POST",body:JSON.stringify(o)}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function k(){const e=a();return s({mutationFn:o=>r(`/yaml-workflows/${o}/deploy`,{method:"POST"}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function p(){const e=a();return s({mutationFn:o=>r(`/yaml-workflows/${o}/activate`,{method:"POST"}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function d(){const e=a();return s({mutationFn:({id:o,data:t,sync:n,execute_as:u})=>r(`/yaml-workflows/${o}/invoke`,{method:"POST",body:JSON.stringify({data:t,sync:n,...u?{execute_as:u}:{}})}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function h(){const e=a();return s({mutationFn:({id:o,task_queue:t,compilation_feedback:n})=>r(`/yaml-workflows/${o}/regenerate`,{method:"POST",body:JSON.stringify({task_queue:t,compilation_feedback:n})}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function q(){const e=a();return s({mutationFn:o=>r(`/yaml-workflows/${o}/archive`,{method:"POST"}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function W(){const e=a();return s({mutationFn:o=>r(`/yaml-workflows/${o}/restore`,{method:"POST"}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"}),e.invalidateQueries({queryKey:["yamlWorkflow"],refetchType:"all"})}})}function S(){const e=a();return s({mutationFn:({id:o,...t})=>r(`/yaml-workflows/${o}`,{method:"PUT",body:JSON.stringify(t)}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function v(){const e=a();return s({mutationFn:o=>r(`/yaml-workflows/${o}`,{method:"DELETE"}),onSuccess:()=>{e.invalidateQueries({queryKey:["yamlWorkflows"],refetchType:"all"})}})}function T(e){return l({queryKey:["yamlWorkflows",e,"versions"],queryFn:()=>r(`/yaml-workflows/${e}/versions`),enabled:!!e})}function F(e,o){return l({queryKey:["yamlWorkflows",e,"versions",o],queryFn:()=>r(`/yaml-workflows/${e}/versions/${o}`),enabled:!!e&&o!==null})}export{m as a,S as b,c,T as d,k as e,p as f,q as g,W as h,v as i,h as j,F as k,d as l,w as m,f as u};
|
|
2
|
+
//# sourceMappingURL=yaml-workflows-B230v5Za.js.map
|
package/dashboard/dist/assets/{yaml-workflows-ziUdZhKY.js.map → yaml-workflows-B230v5Za.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-workflows-ziUdZhKY.js","sources":["../../src/api/yaml-workflows.ts"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\nimport type { LTYamlWorkflowRecord, LTYamlWorkflowStatus, LTYamlWorkflowVersion } from './types';\n\ninterface YamlWorkflowListResponse {\n workflows: LTYamlWorkflowRecord[];\n total: number;\n}\n\ninterface YamlWorkflowFilters {\n status?: LTYamlWorkflowStatus;\n graph_topic?: string;\n app_id?: string;\n search?: string;\n set_id?: string;\n limit?: number;\n offset?: number;\n}\n\nexport function useYamlWorkflows(filters: YamlWorkflowFilters = {}) {\n const params = new URLSearchParams();\n if (filters.status) params.set('status', filters.status);\n if (filters.graph_topic) params.set('graph_topic', filters.graph_topic);\n if (filters.app_id) params.set('app_id', filters.app_id);\n if (filters.search) params.set('search', filters.search);\n if (filters.set_id) params.set('set_id', filters.set_id);\n if (filters.limit) params.set('limit', String(filters.limit));\n if (filters.offset !== undefined) params.set('offset', String(filters.offset));\n\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', filters],\n queryFn: () => apiFetch(`/yaml-workflows?${params}`),\n });\n}\n\nexport function useYamlWorkflowAppIds() {\n return useQuery<{ app_ids: string[] }>({\n queryKey: ['yamlWorkflowAppIds'],\n queryFn: () => apiFetch('/yaml-workflows/app-ids'),\n });\n}\n\nexport function useYamlWorkflowByTopic(graphTopic: string | undefined, appId?: string) {\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', 'byTopic', graphTopic, appId],\n queryFn: () => {\n const params = new URLSearchParams({ graph_topic: graphTopic!, limit: '1' });\n if (appId) params.set('app_id', appId);\n return apiFetch(`/yaml-workflows?${params}`);\n },\n enabled: !!graphTopic,\n });\n}\n\nexport function useYamlWorkflow(id: string) {\n return useQuery<LTYamlWorkflowRecord>({\n queryKey: ['yamlWorkflows', id],\n queryFn: () => apiFetch(`/yaml-workflows/${id}`),\n enabled: !!id,\n });\n}\n\nexport function useCreateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (input: {\n workflow_id: string;\n task_queue: string;\n workflow_name: string;\n name: string;\n description?: string;\n app_id?: string;\n subscribes?: string;\n tags?: string[];\n compilation_feedback?: string;\n }) =>\n apiFetch<LTYamlWorkflowRecord>('/yaml-workflows', {\n method: 'POST',\n body: JSON.stringify(input),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeployYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/deploy`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useActivateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/activate`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useInvokeYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, data, sync, execute_as }: { id: string; data: Record<string, unknown>; sync?: boolean; execute_as?: string }) =>\n apiFetch<{ result?: unknown; job_id?: string }>(`/yaml-workflows/${id}/invoke`, {\n method: 'POST',\n body: JSON.stringify({ data, sync, ...(execute_as ? { execute_as } : {}) }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRegenerateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, task_queue, compilation_feedback }: { id: string; task_queue?: string; compilation_feedback?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/regenerate`, {\n method: 'POST',\n body: JSON.stringify({ task_queue, compilation_feedback }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useArchiveYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/archive`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRestoreYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/restore`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflow'], refetchType: 'all' });\n },\n });\n}\n\nexport function useUpdateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, ...updates }: { id: string; yaml_content?: string; name?: string; description?: string; input_schema?: Record<string, unknown>; output_schema?: Record<string, unknown>; tags?: string[]; app_id?: string; graph_topic?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeleteYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<{ deleted: boolean }>(`/yaml-workflows/${id}`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Cron scheduling ─────────────────────────────────────────────\n\nexport function useSetYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, cron_schedule, cron_envelope, execute_as }: {\n id: string;\n cron_schedule: string;\n cron_envelope?: Record<string, unknown> | null;\n execute_as?: string | null;\n }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'PUT',\n body: JSON.stringify({ cron_schedule, cron_envelope, execute_as }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useClearYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Version history ─────────────────────────────────────────────\n\nexport function useYamlWorkflowVersions(id: string) {\n return useQuery<{ versions: LTYamlWorkflowVersion[]; total: number }>({\n queryKey: ['yamlWorkflows', id, 'versions'],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions`),\n enabled: !!id,\n });\n}\n\nexport function useYamlWorkflowVersion(id: string, version: number | null) {\n return useQuery<LTYamlWorkflowVersion>({\n queryKey: ['yamlWorkflows', id, 'versions', version],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions/${version}`),\n enabled: !!id && version !== null,\n });\n}\n"],"names":["useYamlWorkflows","filters","params","useQuery","apiFetch","useYamlWorkflowAppIds","useYamlWorkflow","id","useCreateYamlWorkflow","queryClient","useQueryClient","useMutation","input","useDeployYamlWorkflow","useActivateYamlWorkflow","useInvokeYamlWorkflow","data","sync","execute_as","useRegenerateYamlWorkflow","task_queue","compilation_feedback","useArchiveYamlWorkflow","useRestoreYamlWorkflow","useUpdateYamlWorkflow","updates","useDeleteYamlWorkflow","useYamlWorkflowVersions","useYamlWorkflowVersion","version"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"yaml-workflows-B230v5Za.js","sources":["../../src/api/yaml-workflows.ts"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\nimport type { LTYamlWorkflowRecord, LTYamlWorkflowStatus, LTYamlWorkflowVersion } from './types';\n\ninterface YamlWorkflowListResponse {\n workflows: LTYamlWorkflowRecord[];\n total: number;\n}\n\ninterface YamlWorkflowFilters {\n status?: LTYamlWorkflowStatus;\n graph_topic?: string;\n app_id?: string;\n search?: string;\n set_id?: string;\n limit?: number;\n offset?: number;\n}\n\nexport function useYamlWorkflows(filters: YamlWorkflowFilters = {}) {\n const params = new URLSearchParams();\n if (filters.status) params.set('status', filters.status);\n if (filters.graph_topic) params.set('graph_topic', filters.graph_topic);\n if (filters.app_id) params.set('app_id', filters.app_id);\n if (filters.search) params.set('search', filters.search);\n if (filters.set_id) params.set('set_id', filters.set_id);\n if (filters.limit) params.set('limit', String(filters.limit));\n if (filters.offset !== undefined) params.set('offset', String(filters.offset));\n\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', filters],\n queryFn: () => apiFetch(`/yaml-workflows?${params}`),\n });\n}\n\nexport function useYamlWorkflowAppIds() {\n return useQuery<{ app_ids: string[] }>({\n queryKey: ['yamlWorkflowAppIds'],\n queryFn: () => apiFetch('/yaml-workflows/app-ids'),\n });\n}\n\nexport function useYamlWorkflowByTopic(graphTopic: string | undefined, appId?: string) {\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', 'byTopic', graphTopic, appId],\n queryFn: () => {\n const params = new URLSearchParams({ graph_topic: graphTopic!, limit: '1' });\n if (appId) params.set('app_id', appId);\n return apiFetch(`/yaml-workflows?${params}`);\n },\n enabled: !!graphTopic,\n });\n}\n\nexport function useYamlWorkflow(id: string) {\n return useQuery<LTYamlWorkflowRecord>({\n queryKey: ['yamlWorkflows', id],\n queryFn: () => apiFetch(`/yaml-workflows/${id}`),\n enabled: !!id,\n });\n}\n\nexport function useCreateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (input: {\n workflow_id: string;\n task_queue: string;\n workflow_name: string;\n name: string;\n description?: string;\n app_id?: string;\n subscribes?: string;\n tags?: string[];\n compilation_feedback?: string;\n }) =>\n apiFetch<LTYamlWorkflowRecord>('/yaml-workflows', {\n method: 'POST',\n body: JSON.stringify(input),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeployYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/deploy`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useActivateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/activate`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useInvokeYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, data, sync, execute_as }: { id: string; data: Record<string, unknown>; sync?: boolean; execute_as?: string }) =>\n apiFetch<{ result?: unknown; job_id?: string }>(`/yaml-workflows/${id}/invoke`, {\n method: 'POST',\n body: JSON.stringify({ data, sync, ...(execute_as ? { execute_as } : {}) }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRegenerateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, task_queue, compilation_feedback }: { id: string; task_queue?: string; compilation_feedback?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/regenerate`, {\n method: 'POST',\n body: JSON.stringify({ task_queue, compilation_feedback }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useArchiveYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/archive`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRestoreYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/restore`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflow'], refetchType: 'all' });\n },\n });\n}\n\nexport function useUpdateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, ...updates }: { id: string; yaml_content?: string; name?: string; description?: string; input_schema?: Record<string, unknown>; output_schema?: Record<string, unknown>; tags?: string[]; app_id?: string; graph_topic?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeleteYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<{ deleted: boolean }>(`/yaml-workflows/${id}`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Cron scheduling ─────────────────────────────────────────────\n\nexport function useSetYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, cron_schedule, cron_envelope, execute_as }: {\n id: string;\n cron_schedule: string;\n cron_envelope?: Record<string, unknown> | null;\n execute_as?: string | null;\n }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'PUT',\n body: JSON.stringify({ cron_schedule, cron_envelope, execute_as }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useClearYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Version history ─────────────────────────────────────────────\n\nexport function useYamlWorkflowVersions(id: string) {\n return useQuery<{ versions: LTYamlWorkflowVersion[]; total: number }>({\n queryKey: ['yamlWorkflows', id, 'versions'],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions`),\n enabled: !!id,\n });\n}\n\nexport function useYamlWorkflowVersion(id: string, version: number | null) {\n return useQuery<LTYamlWorkflowVersion>({\n queryKey: ['yamlWorkflows', id, 'versions', version],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions/${version}`),\n enabled: !!id && version !== null,\n });\n}\n"],"names":["useYamlWorkflows","filters","params","useQuery","apiFetch","useYamlWorkflowAppIds","useYamlWorkflow","id","useCreateYamlWorkflow","queryClient","useQueryClient","useMutation","input","useDeployYamlWorkflow","useActivateYamlWorkflow","useInvokeYamlWorkflow","data","sync","execute_as","useRegenerateYamlWorkflow","task_queue","compilation_feedback","useArchiveYamlWorkflow","useRestoreYamlWorkflow","useUpdateYamlWorkflow","updates","useDeleteYamlWorkflow","useYamlWorkflowVersions","useYamlWorkflowVersion","version"],"mappings":"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"}
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
9
9
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
10
10
|
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
11
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
+
<script type="module" crossorigin src="./assets/index-BaCDL5fh.js"></script>
|
|
12
12
|
<link rel="modulepreload" crossorigin href="./assets/vendor-query-DvWWuNIB.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="./assets/vendor-react-_9U4mKFr.js">
|
|
14
|
-
<link rel="modulepreload" crossorigin href="./assets/vendor-icons-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
14
|
+
<link rel="modulepreload" crossorigin href="./assets/vendor-icons-C_DQEeBy.js">
|
|
15
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CnU7Jjz3.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|
package/docs/faceted-routing.md
CHANGED
|
@@ -54,7 +54,7 @@ interface FacetQuery {
|
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
`orderBy.field` is either a whitelisted top-level column (`priority`, `created_at`,
|
|
57
|
-
`updated_at`, `status`, `role`) or a metadata path written as `metadata.<key>` (extracted as
|
|
57
|
+
`updated_at`, `resolved_at`, `status`, `role`) or a metadata path written as `metadata.<key>` (extracted as
|
|
58
58
|
text, or numeric when `numeric` is set). Every value is parameterized; only validated column
|
|
59
59
|
names / metadata keys and a fixed operator set are ever interpolated.
|
|
60
60
|
|
|
@@ -123,6 +123,19 @@ Values are strings — jsonb containment is type-sensitive, so numeric facets
|
|
|
123
123
|
are not templatable. Link variables are a view convenience: RBAC read scope
|
|
124
124
|
still governs what any query can return.
|
|
125
125
|
|
|
126
|
+
`{lt:me}` is built in: it always reads the signed-in user's id, so one pin
|
|
127
|
+
means "mine" for whoever signs in on a shared station. Every completing
|
|
128
|
+
resolve records its completer in the row's `metadata.resolved_by` (resolves,
|
|
129
|
+
batch fills, both rows of an accumulate add, scan acts), so a role can pin a
|
|
130
|
+
"My recent work" list, newest first:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
/escalations?status=resolved&facets={"resolved_by":"{lt:me}"}&orderBy=[{"field":"resolved_at","direction":"desc"}]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`resolved_at` sorts with rows that have no completion time last, in either
|
|
137
|
+
direction.
|
|
138
|
+
|
|
126
139
|
A bound link variable also **scopes the Pace Board** — the same device value
|
|
127
140
|
narrows the board's station counts, time-in-state mix, and entity timelines,
|
|
128
141
|
not just the pins. See [Operations — Scoping the board](operations.md#scoping-the-board).
|
package/docs/hitl/x-lt-embed.md
CHANGED
|
@@ -8,6 +8,8 @@ Three display-only widgets that surface related information inside an escalation
|
|
|
8
8
|
| `"escalation"` | `x-lt-source`, `x-lt-fields` | A single embedded escalation record, with a flexible facts panel |
|
|
9
9
|
| `"escalation-list"` | `x-lt-query`, `x-lt-columns` | A compact in-form list of escalations driven by a facet query |
|
|
10
10
|
|
|
11
|
+
A [roster](x-lt-roster.md) (`x-lt-widget: "roster"`) follows the same rules: every member a container row expects, each marked waiting, in, or flagged.
|
|
12
|
+
|
|
11
13
|
---
|
|
12
14
|
|
|
13
15
|
## Link widget (`x-lt-widget: "link"`)
|
|
@@ -201,7 +203,7 @@ Inline row actions: each row gains a button that fires a canned resolve against
|
|
|
201
203
|
|-------|------|-------------|
|
|
202
204
|
| `label` | `string` | Button text |
|
|
203
205
|
| `resolverPayload` | `object` | The canned payload. String leaves interpolate `{{domain.path}}` tokens against the row's own context; booleans and numbers pass through typed |
|
|
204
|
-
| `confirm` | `string` | Optional
|
|
206
|
+
| `confirm` | `string` | Optional confirmation asked in place, beside the row, before firing; tokens interpolate per row |
|
|
205
207
|
|
|
206
208
|
On success the row updates in place through the standard query invalidation — no navigation. A rejected resolve (validation failure, lost claim) shows the server's message inline in the row; the detail link stays available, so the full form remains the path for rejects and anything the canned payload can't express.
|
|
207
209
|
|
|
@@ -241,6 +243,7 @@ A top-level form_schema token (a peer of `x-lt-help`) that keeps the resolve but
|
|
|
241
243
|
| `mustBeEmpty` | `boolean` | The gate condition (default `true`) |
|
|
242
244
|
| `message` | `string` | Shown beside the disabled submit; `{{count}}` carries the live row count, `{{domain.path}}` tokens also interpolate |
|
|
243
245
|
| `autoResolveWhenEmpty` | `boolean` | Auto-submit the claimed parent the moment the query is confirmed empty |
|
|
246
|
+
| `roster` | `string` | In place of `query`: a [roster](x-lt-roster.md#completeness-roster-and-the-roster-guard) field whose outstanding entries hold the submit; `{{count}}` is the outstanding count |
|
|
244
247
|
|
|
245
248
|
The guard and an escalation-list embed declaring the same query resolve through one shared mapping — the count and the visible rows always agree, whatever the scope. Pair it with an `escalation-list` embed on the same query so the operator sees exactly which rows are holding the gate.
|
|
246
249
|
|
|
@@ -193,6 +193,23 @@ The cell reads `3 · Standard 2 · Express 1`: the count, then each split value
|
|
|
193
193
|
|
|
194
194
|
`labels` maps split values to display text. A `role` chip opens that role's list filtered to the row's facets.
|
|
195
195
|
|
|
196
|
+
`display` reads a count as text. An exact count wins, then `default`; `{n}` reads the count:
|
|
197
|
+
|
|
198
|
+
```jsonc
|
|
199
|
+
{ "label": "Coming", "related": "coming", "display": { "0": "Ready", "default": "Waiting on {n}" } }
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The cell reads *Ready* or *Waiting on 3*, with its split chips beside it and the count in its tooltip.
|
|
203
|
+
|
|
204
|
+
`aggregate: "min"` or `"max"` shows the least or greatest value across the set instead of a count. `value` names it: `{{item.payload.<path>}}` on an `items` set, `{{metadata.<key>}}` on a `query` set. `format` renders it as on any column:
|
|
205
|
+
|
|
206
|
+
```jsonc
|
|
207
|
+
{ "label": "Earliest commit", "related": "contents", "aggregate": "min",
|
|
208
|
+
"value": "{{item.payload.commitBy}}", "format": "date" }
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Values compare as numbers when every value is a number, otherwise as text, so ISO dates and instants order by time. Strings, numbers and booleans count as values; an item without one is skipped, and a row whose set holds none shows an em dash. A min or max column takes no `splitBy` or `display`.
|
|
212
|
+
|
|
196
213
|
### Row detail
|
|
197
214
|
|
|
198
215
|
`x-lt-row-detail` lists sections a row expands into. Each section loads when the row opens, and lists its set's rows with its own columns:
|
|
@@ -214,7 +231,7 @@ Item sections read `{{item.itemKey}}`, `{{item.payload.*}}`, `{{item.actor}}` an
|
|
|
214
231
|
|
|
215
232
|
### Grouped rows
|
|
216
233
|
|
|
217
|
-
On a `facet-table`, `x-lt-group-by: "metadata.<key>"` reads every row sharing that facet as one line, expanding to its members. The list pages by groups, so a page holds whole groups and the total counts groups; a row without the facet is a group of one. Plain columns fold across a group with `group: "first" | "min" | "max" | "sum" | "count" | "distinct"` (default `first`); `min` and `max` compare numbers as numbers and instants as text, and `distinct` lists each value once ("standard, express"). Related columns merge across the group: counts and splits add. A container split finer (one bin per service level in the same tub) keeps reading as one line per tub.
|
|
234
|
+
On a `facet-table`, `x-lt-group-by: "metadata.<key>"` reads every row sharing that facet as one line, expanding to its members. The list pages by groups, so a page holds whole groups and the total counts groups; a row without the facet is a group of one. Plain columns fold across a group with `group: "first" | "min" | "max" | "sum" | "count" | "distinct"` (default `first`); `min` and `max` compare numbers as numbers and instants as text, and `distinct` lists each value once ("standard, express"). Related columns merge across the group: counts and splits add, and a min or max takes the least or greatest across the group. A container split finer (one bin per service level in the same tub) keeps reading as one line per tub.
|
|
218
235
|
|
|
219
236
|
Containment reads by indentation and band: an open line takes a light band; its members are rows of the same table, stepped in under it on a stronger band; a row's detail sections step in past their row on that row's band. The facets carry the hierarchy, so nothing repeats beneath the line that states it: a member leaves blank every value it shares with its group (the group line already shows it), and a detail section drops a column whose every row restates a facet the opened row carries (a lane's look-ahead needs no Service column). A section's first column always stays.
|
|
220
237
|
|
|
@@ -226,7 +243,7 @@ Related sets read under the viewer's own read scope, as every list does:
|
|
|
226
243
|
- A query set counts only roles the viewer reads in full. The roles it cannot count are named in the cell's tooltip and in each expansion (*partial*). Granting `read` on those roles is the dial that widens the view.
|
|
227
244
|
- A viewer who cannot read the host role gets a 404.
|
|
228
245
|
|
|
229
|
-
The server reads the declaration from the role's stored list schema at the version the page rendered, never from the request. `POST /api/escalations/related` aggregates one page of rows in one statement per declared (set, split) pair, whatever the page size or item count; a query set's facet match is served by the metadata GIN index. `POST /api/escalations/related/rows` reads one row's set for its expansion. The list refreshes the sets live on the list tier, from the row's own role events and from the roles each set reads: a query set's roles, and the roles of the reciprocal rows an item split reads, so a held item whose own row changes moves its split. A change refreshes the list when the path that makes it publishes an escalation event on that row's role.
|
|
246
|
+
The server reads the declaration from the role's stored list schema at the version the page rendered, never from the request. `POST /api/escalations/related` aggregates one page of rows in one statement per declared (set, split) pair or (set, min/max value) pair, whatever the page size or item count; a query set's facet match is served by the metadata GIN index. `POST /api/escalations/related/rows` reads one row's set for its expansion. The list refreshes the sets live on the list tier, from the row's own role events and from the roles each set reads: a query set's roles, and the roles of the reciprocal rows an item split reads, so a held item whose own row changes moves its split. A change refreshes the list when the path that makes it publishes an escalation event on that row's role.
|
|
230
247
|
|
|
231
248
|
A role's list schema is validated wherever it is written (the role API, the MCP tool, the startup apply): a column naming an undeclared set, an unknown split path, or a malformed query is refused with the path that failed. Keys outside this vocabulary stay free-form.
|
|
232
249
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Roster (`x-lt-widget: "roster"`)
|
|
2
|
+
|
|
3
|
+
A roster lists every member a container row expects, each marked **waiting**, **in**, or **flagged**, with the count in its heading ("3 of 5 in · 1 Missing"). The person works from it: a member that arrives ticks in, an action on a member resolves its row in place, and the rest of the form can wait until every member is accounted for.
|
|
4
|
+
|
|
5
|
+
Like the other [embed widgets](x-lt-embed.md), a roster is display-only: declare it `readOnly`, keep it out of `required`, and it contributes nothing to the resolver payload.
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
"orders": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"readOnly": true,
|
|
11
|
+
"title": "Orders in this box",
|
|
12
|
+
"description": "Scan each bag into the box. Mark a bag missing if it is not in the bin.",
|
|
13
|
+
"x-lt-widget": "roster",
|
|
14
|
+
"x-lt-roster": {
|
|
15
|
+
"expected": { "query": { "roles": ["packing"], "facets": { "packingBox": "{{escalation.id}}" } } },
|
|
16
|
+
"key": "{{metadata.orderId}}",
|
|
17
|
+
"in": ["items", "resolver.bags"],
|
|
18
|
+
"flagged": [
|
|
19
|
+
{ "when": "resolver.outcome=missing", "label": "Missing" },
|
|
20
|
+
{ "when": "resolver.outcome=needs-manager", "label": "With a manager" }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"x-lt-columns": [
|
|
24
|
+
{ "label": "Order", "value": "{{metadata.orderId}}" },
|
|
25
|
+
{ "label": "PO", "value": "{{metadata.po}}" }
|
|
26
|
+
],
|
|
27
|
+
"x-lt-actions": [
|
|
28
|
+
{ "label": "Missing", "when": "waiting",
|
|
29
|
+
"resolverPayload": { "outcome": "missing" },
|
|
30
|
+
"confirm": "Mark {{metadata.orderId}} missing?" },
|
|
31
|
+
{ "label": "Send to a manager", "when": "waiting",
|
|
32
|
+
"resolverPayload": { "outcome": "needs-manager" } }
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## `x-lt-roster`
|
|
38
|
+
|
|
39
|
+
| Field | Description |
|
|
40
|
+
|-------|-------------|
|
|
41
|
+
| `expected` | The members the row expects. One of `query`, `list`, or `batch` (below). |
|
|
42
|
+
| `key` | For a `query` set: a template naming each member row's entry. Default `{{escalation.id}}`. |
|
|
43
|
+
| `in` | Where arrivals are read. `items` reads the row's held keys (its accumulated items, or a batch's filled keys); any other entry is a `domain.path` naming a string or an array, such as a scan field in the live form (`resolver.bags`, a field the form declares). Default `["items"]`. |
|
|
44
|
+
| `flagged` | Rules over each member row's own context: `when` is an [`x-lt-showIf`](x-lt-show-if.md) condition (or an array of them), `label` is the text the entry shows. The first matching rule wins. |
|
|
45
|
+
|
|
46
|
+
### Expected sets
|
|
47
|
+
|
|
48
|
+
| Set | Shape | Entries |
|
|
49
|
+
|-----|-------|---------|
|
|
50
|
+
| `query` | `{ "role": "...", "roles": [...], "facets": {...}, "status": "..." }` | Member rows matching the role(s) and facets. Facet values are `{{domain.path}}` templates over the host row. Every status is read unless `status` names one, so a member resolved as missing stays on the roster. Up to 200 rows. |
|
|
51
|
+
| `list` | `"metadata.members"` | The keys in an array on the host row. |
|
|
52
|
+
| `batch` | `true`, with optional `"labels": "envelope.boxLabels"` | The row's batch keys; a batch key is in once filled. `labels` names a per-key map whose entry each column reads as `{{item.label.*}}`. |
|
|
53
|
+
|
|
54
|
+
Stamp the container's id on each member row when the container opens (`packingBox` above). The expected set is then the container's own, and a member that joins the source later never appears on it.
|
|
55
|
+
|
|
56
|
+
### State
|
|
57
|
+
|
|
58
|
+
An entry is **in** when its key is held or appears in an `in` source, **flagged** when its member row matches a `flagged` rule, and **waiting** otherwise. In reads before flagged: a member a manager confirms into the box reads in, even though its own row was resolved as "needs a manager".
|
|
59
|
+
|
|
60
|
+
## Columns
|
|
61
|
+
|
|
62
|
+
`x-lt-columns` take the same `{ label, value, format }` entries as the [escalation list](x-lt-embed.md#x-lt-columns-optional). Values read the member row's domains for a `query` set (the host row's otherwise), beside `{{item.*}}`:
|
|
63
|
+
|
|
64
|
+
| Token | Value |
|
|
65
|
+
|-------|-------|
|
|
66
|
+
| `{{item.itemKey}}` | The entry key |
|
|
67
|
+
| `{{item.label.*}}` | The entry's value in a batch `labels` map |
|
|
68
|
+
| `{{item.payload.*}}`, `{{item.actor}}`, `{{item.at}}` | The held item, once it is in |
|
|
69
|
+
|
|
70
|
+
Without `x-lt-columns`, each entry shows its key.
|
|
71
|
+
|
|
72
|
+
## Actions
|
|
73
|
+
|
|
74
|
+
`x-lt-actions` resolve the entry's member row through the standard resolve endpoint, as the [escalation list's actions](x-lt-embed.md#x-lt-actions-optional) do: RBAC and `enforce_schema` apply, the resolve records the viewer in the row's `metadata.resolved_by`, and a refused action shows the server's reason on the entry.
|
|
75
|
+
|
|
76
|
+
| Field | Description |
|
|
77
|
+
|-------|-------------|
|
|
78
|
+
| `label` | Button text |
|
|
79
|
+
| `resolverPayload` | The canned payload; string leaves interpolate against the member row |
|
|
80
|
+
| `when` | The entry state(s) that offer the action: `"waiting"` (default), `"in"`, `"flagged"`, or an array |
|
|
81
|
+
| `confirm` | A confirmation asked in place, beside the entry, before firing |
|
|
82
|
+
|
|
83
|
+
An entry with no member row (a `list` or `batch` set) offers no actions.
|
|
84
|
+
|
|
85
|
+
Moving work to another person is a resolve with an outcome. "Send to a manager" above resolves the member row with `outcome: "needs-manager"`; the member's workflow opens a row in the manager's role, where only a manager can resolve it, and the manager's confirm adds the bag to the box.
|
|
86
|
+
|
|
87
|
+
## Completeness: `roster.*` and the roster guard
|
|
88
|
+
|
|
89
|
+
Each roster's counts join the form context as `roster.<field>`: `expected`, `in`, `flagged`, `waiting`, and `outstanding` (entries neither in nor flagged). [`x-lt-showIf`](x-lt-show-if.md) and help tokens read them, so the steps that follow can wait for the roster:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
"weight": {
|
|
93
|
+
"type": "number",
|
|
94
|
+
"title": "Box weight",
|
|
95
|
+
"description": "Weigh the closed box.",
|
|
96
|
+
"x-lt-showIf": "roster.orders.outstanding=0"
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
A [submit guard](x-lt-embed.md#submit-guard-x-lt-submit-guard) can name the roster. The submit stays disabled while entries are outstanding:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
"x-lt-submit-guard": { "roster": "orders", "message": "{{count}} orders are still unaccounted for" }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`{{count}}` is the outstanding count. A roster guard never auto-submits; the person finishes the steps the roster revealed.
|
|
107
|
+
|
|
108
|
+
**Enforced on both sides.** For roles that set `enforce_schema`, the server computes the same roster at resolve, from the same shared code: `roster.*` showIf conditions evaluate as the form showed them, and a resolve with an outstanding entry is refused with the guard's message as a `422`, on every surface. The server reads member rows regardless of the resolver's read scope, so a resolver who cannot see a member never clears the guard. Give the people who work the roster `read` on the member role so the list they see matches.
|
|
109
|
+
|
|
110
|
+
## Live updates
|
|
111
|
+
|
|
112
|
+
The roster reads member rows through the same list query as every list, so it refreshes on the same escalation events: a bag scanned at another station, or added from another device, ticks in without a reload. A scan into a form field ticks its entry in at once.
|
|
@@ -41,6 +41,7 @@ Each entry uses the same grammar as a single condition. A hidden field is skippe
|
|
|
41
41
|
| `escalation` | Top-level escalation row fields (`role`, `status`, `priority`, …) |
|
|
42
42
|
| `resolver` | The submitted resolver payload — **live**: reacts in real time as the user edits the form |
|
|
43
43
|
| `input` | The same live form values under the invoke form's name (see [invoke-form.md](invoke-form.md)) |
|
|
44
|
+
| `roster` | Each [roster](x-lt-roster.md) field's counts — **live**: `roster.orders.outstanding=0` shows a field once every member is accounted for |
|
|
44
45
|
|
|
45
46
|
Conditions based on `metadata`, `payload`, `envelope`, and `escalation` are static (read from the stored row). Conditions based on `resolver` are dynamic — the field appears or disappears immediately as the user edits a sibling field, without a page reload.
|
|
46
47
|
|
|
@@ -148,3 +149,17 @@ A field with `"x-lt-hide-if-empty": true` is suppressed entirely when its value
|
|
|
148
149
|
```
|
|
149
150
|
|
|
150
151
|
`x-lt-hide-if-empty` is evaluated against the field's current value in form state. It is distinct from `x-lt-showIf`, which evaluates against a path in the escalation context.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## `x-lt-hidden`
|
|
156
|
+
|
|
157
|
+
A field with `"x-lt-hidden": true` never renders. Use it for a value the form carries but no one on the form answers: a discriminant the workflow or an API caller sets. The value passes through to the resolver payload unchanged, and where the schema is enforced it is checked against the field's `type` and `enum`. A hidden field is never required, even when it is listed in `required`.
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
"type": {
|
|
161
|
+
"type": "string",
|
|
162
|
+
"enum": ["release", "reset", "cancel"],
|
|
163
|
+
"x-lt-hidden": true
|
|
164
|
+
}
|
|
165
|
+
```
|
package/docs/hitl/x-lt-widget.md
CHANGED
|
@@ -15,6 +15,7 @@ For rich inputs beyond standard HTML types, set `x-lt-widget` on any field:
|
|
|
15
15
|
| `"link"` | ReadOnly navigation link. URL is an `x-lt-href` template with `{{domain.path}}` tokens. See [x-lt-embed.md](x-lt-embed.md). |
|
|
16
16
|
| `"escalation"` | ReadOnly embedded escalation card. ID sourced from `x-lt-source`; optional `x-lt-fields` surfaces any metadata or resolver detail. See [x-lt-embed.md](x-lt-embed.md). |
|
|
17
17
|
| `"escalation-list"` | ReadOnly embedded escalation list. Driven by an `x-lt-query` facet object; columns from `x-lt-columns`. See [x-lt-embed.md](x-lt-embed.md). |
|
|
18
|
+
| `"roster"` | ReadOnly list of every member a container row expects, each waiting, in, or flagged. Driven by `x-lt-roster`. See [x-lt-roster.md](x-lt-roster.md). |
|
|
18
19
|
| `"invoke"` | ReadOnly control that starts a workflow, directly or in a prefilled dialog. Target and payload mapping in `x-lt-invoke`. See [x-lt-invoke.md](x-lt-invoke.md). |
|
|
19
20
|
| `"textarea"` | Alias of `format: "textarea"`: a multi-line text box. |
|
|
20
21
|
|
package/docs/hitl-guide.md
CHANGED
|
@@ -23,6 +23,7 @@ This works because the form is data: a JSON Schema stored on the role, versioned
|
|
|
23
23
|
| A role-authored list page — document views, facet tables, entity card boards | List schema | [x-lt-list-schema.md](hitl/x-lt-list-schema.md) |
|
|
24
24
|
| Rename the resolve footer, or claim-and-submit in one gesture | Footer tokens | [x-lt-footer.md](hitl/x-lt-footer.md) |
|
|
25
25
|
| Block the resolve until embedded work drains, then auto-close when it does | `x-lt-submit-guard` | [x-lt-embed.md](hitl/x-lt-embed.md) |
|
|
26
|
+
| Show every member a container expects, check each off as it arrives, and hold the rest of the form until all are accounted for | `x-lt-roster` | [x-lt-roster.md](hitl/x-lt-roster.md) |
|
|
26
27
|
| Start another workflow from inside the form, mapped from the record, directly or in a prefilled dialog | `x-lt-invoke` | [x-lt-invoke.md](hitl/x-lt-invoke.md) |
|
|
27
28
|
| Fill a field by scanning a container, checked against what the record expects | `x-lt-scan` | [x-lt-scan.md](hitl/x-lt-scan.md) |
|
|
28
29
|
| A role's pinned views laid out as named pages of live panels | `portals` on the role | [portal.md](hitl/portal.md) |
|
|
@@ -89,11 +90,12 @@ Ordered as a learning path — each file adds one capability to the same form:
|
|
|
89
90
|
| Versioned knowledge lookups, the `lookup.*` domain, cascading selects | [lookups.md](hitl/lookups.md) |
|
|
90
91
|
| Field types, formats, required, read-only | [form.md](hitl/form.md) |
|
|
91
92
|
| Pre-submission validation guards (min, max, pattern, dynamic bounds) | [x-lt-validation.md](hitl/x-lt-validation.md) |
|
|
92
|
-
| Conditional visibility (`x-lt-showIf`, `x-lt-hide-if-empty`) | [x-lt-show-if.md](hitl/x-lt-show-if.md) |
|
|
93
|
+
| Conditional visibility (`x-lt-showIf`, `x-lt-hide-if-empty`, `x-lt-hidden`) | [x-lt-show-if.md](hitl/x-lt-show-if.md) |
|
|
93
94
|
| Layout, ordering, sections, binding, help panel | [x-lt-layout.md](hitl/x-lt-layout.md) |
|
|
94
95
|
| Custom widgets (checklist, file upload, code editor, signature, markdown) | [x-lt-widget.md](hitl/x-lt-widget.md) |
|
|
95
96
|
| List schema (`active-history`, `active`, `facet-table`, `facet-board` cards) | [x-lt-list-schema.md](hitl/x-lt-list-schema.md) |
|
|
96
97
|
| Embedded widgets (`link`, `escalation`, `escalation-list`) and the submit guard | [x-lt-embed.md](hitl/x-lt-embed.md) |
|
|
98
|
+
| Rosters of expected members, their states, actions, and the roster guard (`x-lt-roster`) | [x-lt-roster.md](hitl/x-lt-roster.md) |
|
|
97
99
|
| Starting a workflow from the form (`x-lt-invoke`) | [x-lt-invoke.md](hitl/x-lt-invoke.md) |
|
|
98
100
|
| Scan fields and scan-to-submit (`x-lt-scan`, `x-lt-scan-submit`) | [x-lt-scan.md](hitl/x-lt-scan.md) |
|
|
99
101
|
| Pinned views, role default pins, link variables | [pinned-views.md](hitl/pinned-views.md) |
|
package/docs/maintenance.md
CHANGED
|
@@ -62,7 +62,7 @@ Six categories of data are subject to maintenance:
|
|
|
62
62
|
| **Entity jobs** | Job rows where `entity` is set. These represent actual workflow instances -- the rows that back `Durable.Client.workflow.search()` calls and execution exports. Deleting them removes the workflow record entirely. |
|
|
63
63
|
| **Pruned jobs** | Entity jobs that have already had their execution artifacts stripped (the `pruned_at` column is not `NULL`). These retain core data but no longer carry execution scaffolding. They can be hard-deleted after a longer retention window. |
|
|
64
64
|
| **Terminal escalations** | Escalation rows in a terminal status (`resolved`, `cancelled`, `expired`). Terminal rows are inert audit records -- every engine state transition guards on `status = 'pending'`, so aging them out is safe for live waiters, claims, and signal delivery. The engine-owned prune deletes in atomic batches until the retention horizon is drained. Pending rows are never touched. |
|
|
65
|
-
| **OAuth server rows** | The `/mcp` authorization server's records. Refresh tokens and authorization codes past expiry, or rotated out, longer ago than the window; then grants left with neither, or revoked longer ago than the window; then clients registered longer ago than the window
|
|
65
|
+
| **OAuth server rows** | The `/mcp` authorization server's records. Refresh tokens and authorization codes past expiry, or rotated out, longer ago than the window; then grants left with neither, or revoked longer ago than the window; then clients registered longer ago than the window that no one ever consented to. A client still holding a live refresh token keeps its grant, and a client anyone has consented to keeps its registration, so the app can reconnect with the client id it holds. |
|
|
66
66
|
|
|
67
67
|
## Prune vs. delete
|
|
68
68
|
|
|
@@ -97,9 +97,9 @@ The default configuration (`modules/maintenance.ts`, enabled with `maintenance:
|
|
|
97
97
|
| 2. Delete transient jobs older than 30 days | Removes activity-level bookkeeping rows that have no associated workflow entity. |
|
|
98
98
|
| 3. Prune entity jobs older than 30 days | Strips execution artifacts from workflow instances while preserving core data. Exports and search remain functional. |
|
|
99
99
|
| 4. Delete pruned jobs older than 180 days | Hard-deletes workflow instances that were pruned at least 180 days ago. This is the final removal. |
|
|
100
|
-
| 5. Delete OAuth server rows older than 7 days | Removes expired codes and tokens, unused or revoked grants, and clients
|
|
100
|
+
| 5. Delete OAuth server rows older than 7 days | Removes expired codes and tokens, unused or revoked grants, and clients never consented to. |
|
|
101
101
|
|
|
102
|
-
A custom `rules` list replaces the defaults
|
|
102
|
+
A custom `rules` list replaces the defaults. The `oauth` rule is optional: the OAuth server sweeps its own tables as it is used (see [Connect with OAuth](mcp.md#connect-with-oauth)), and the rule adds a sweep on this schedule with its own window.
|
|
103
103
|
|
|
104
104
|
Rules execute sequentially. If one fails, the remaining rules still run; failures are logged and do not halt the cycle.
|
|
105
105
|
|
package/docs/mcp.md
CHANGED
|
@@ -207,6 +207,8 @@ Allow as me appears only when it grants more than read-only: when you can write
|
|
|
207
207
|
|
|
208
208
|
Access tokens last 5 minutes; the client refreshes them silently with a refresh token that rotates on each use and lasts 30 days. Every request reads the grant: a client acts with your roles as they are now, and a disconnected app, a revoked token or a deactivated account stops working on the next request. Disconnect a client under **Connected apps** in the user menu; the same happens when the client revokes its token.
|
|
209
209
|
|
|
210
|
+
The server keeps its tables bounded on its own. Each process sweeps them on an OAuth write, at most once every `OAUTH_SWEEP_SECONDS` (default 600), deleting rows dead for longer than `OAUTH_RETENTION_DAYS` (default 7): spent and expired codes and refresh tokens, revoked or unused grants, and clients registered but never consented to. A live grant and its current refresh token are kept, and so is any client someone has consented to.
|
|
211
|
+
|
|
210
212
|
**Enable it** with `auth.oauthServer` in `start()`, or `LT_OAUTH_ISSUER` in the environment:
|
|
211
213
|
|
|
212
214
|
```typescript
|
package/docs/scan-codes.md
CHANGED
|
@@ -566,6 +566,10 @@ to continue. The badge scan primes the session and the pending action
|
|
|
566
566
|
completes on its own. With a live grant the stop-over never appears — the
|
|
567
567
|
identity layer is invisible when all is well.
|
|
568
568
|
|
|
569
|
+
While a grant is live, the shell header shows the badged person and the
|
|
570
|
+
minutes left on every page, so a person working a list or a form sees when
|
|
571
|
+
to badge again. It clears when the grant lapses or is used up.
|
|
572
|
+
|
|
569
573
|
A field can take a scan while the form is open: with
|
|
570
574
|
[`x-lt-scan`](hitl/x-lt-scan.md), scanning a container into a claimed form
|
|
571
575
|
fills its container field (checked against what the record expects), and
|
|
@@ -46,6 +46,11 @@ specific first:
|
|
|
46
46
|
A role that enforces but declares no schema has no contract to enforce, and
|
|
47
47
|
its resolves proceed unchanged.
|
|
48
48
|
|
|
49
|
+
The same opt-in enforces a form's [submit guard](hitl/x-lt-embed.md#submit-guard-x-lt-submit-guard).
|
|
50
|
+
A form with a [roster](hitl/x-lt-roster.md) has its roster counts computed
|
|
51
|
+
at resolve from the same shared code the dashboard renders with, so
|
|
52
|
+
`roster.*` showIf conditions and a roster guard hold on every surface.
|
|
53
|
+
|
|
49
54
|
## The rejection shape
|
|
50
55
|
|
|
51
56
|
Every surface reports violations with one canonical body
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/long-tail",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Long Tail Workflows — Durable AI workflows with human-in-the-loop escalation. Powered by PostgreSQL.",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@anthropic-ai/sdk": "^0.92.0",
|
|
79
79
|
"@aws-sdk/client-s3": "^3.1017.0",
|
|
80
80
|
"@aws-sdk/s3-request-presigner": "^3.1045.0",
|
|
81
|
-
"@hotmeshio/hotmesh": "^0.31.
|
|
81
|
+
"@hotmeshio/hotmesh": "^0.31.2",
|
|
82
82
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
83
83
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.215.0",
|
|
84
84
|
"@opentelemetry/resources": "^2.5.1",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as m,j as e}from"./vendor-query-DvWWuNIB.js";import{w as ut,x as mt,c as xt,y as ht,M as Se,z as gt,A as ft,B as pt,E as bt,G as yt,H as jt,I as vt,K as Ct,L as kt,O as Nt,Q as wt,r as Pt,R as St,T as Rt,U as Et,V as Tt,W as At,X as Bt,Y as Ot,Z as Lt,_ as Mt,$ as Ft,a0 as zt,a1 as It,a2 as Ut,a3 as Vt,a4 as _t,a5 as $t,a6 as qt}from"./index-CeCtqujG.js";import{a as Re,u as Ee,f as Ht}from"./vendor-react-_9U4mKFr.js";import{i as Kt}from"./task-queues-7-sHKPsN.js";import{X as re,aj as Dt,x as Gt,ak as Qt,al as Wt,_ as Yt,i as Xt,am as Jt,P as Zt,an as es}from"./vendor-icons-CeVtUKyP.js";import{u as Te,C as ts,r as ss,B as as,a as ns}from"./BulkAssignModal-BoQCi-YC.js";import{E as is}from"./EscalationTitleSelect-DWQieOM9.js";import{u as ls,E as rs,a as os,t as cs}from"./EscalationTimeline-d3nvshOk.js";import{m as ds,E as us,a as ms}from"./escalation-columns-cwZE6xyo.js";import{u as xs}from"./useFilterParams-DBRw1Hcv.js";import{u as hs}from"./useDebouncedValue-6t0jx1RB.js";import{D as gs}from"./DataTable-FjFhx0SE.js";import{S as fs}from"./StickyPagination-CqbjVY6T.js";import{P as ps}from"./constants-CeBBTzf5.js";import{R as bs,a as ys}from"./RowActions-Bdd7z4eB.js";import{i as js}from"./validate-BIRn4a6d.js";import"./UserName-D6zGIK2i.js";import"./FormattedValue-k27T4bG7.js";import"./CountdownTimer-LG03dVgR.js";import"./EntityTimelinePanel-CDFFfX9d.js";import"./FilterBar-ABC9ctin.js";import"./PriorityBadge-r33mpDju.js";import"./RolePill-Di2CAHuD.js";import"./WorkflowPill-Dg7BDTyM.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";import"./StatusBadge-DHVwxre2.js";function vs(){const{pathname:t,search:n}=Re(),u=Ee(),{resolveUrl:l}=ut();m.useEffect(()=>{const g=t+n;if(mt(g).length===0)return;const p=l(g);p!==g&&u(p,{replace:!0})},[t,n,l,u])}const Cs=["<","<=",">",">=","="],ks=["priority","created_at","updated_at","status","role"],O="input text-xs py-1",Ne="select text-xs py-1",H="text-text-tertiary hover:text-text-primary transition-colors";function we(t){return t==="true"?!0:t==="false"?!1:t.trim()!==""&&!Number.isNaN(Number(t))?Number(t):t}const Ns=t=>Object.entries(t??{}).map(([n,u])=>({key:n,value:String(u)})),ws=t=>(t??[]).map(n=>{const[u,l]=Object.entries(n)[0]??["",""];return{key:u,value:String(l)}});function A({title:t,hint:n,children:u}){return e.jsxs("div",{className:"border-t border-surface-border/50 py-3 first:border-t-0 first:pt-1",children:[e.jsxs("div",{className:"mb-1.5 flex items-baseline justify-between",children:[e.jsx("span",{className:"text-2xs font-medium uppercase tracking-wide text-text-tertiary",children:t}),n&&e.jsx("span",{className:"text-2xs font-mono text-text-tertiary/70",children:n})]}),u]})}function K({value:t,onChange:n,placeholder:u}){return e.jsx("input",{list:"lt-facet-keys",className:`${O} w-40`,placeholder:u,value:t,onChange:l=>n(l.target.value)})}function Ps({value:t,onChange:n,facetKeys:u=[],search:l="",onSearchChange:g}){const p=Ns(t.facets),b=ws(t.block),f=t.range??[],r=t.exists??[],k=t.orderBy??[],P=a=>{const o={};for(const c of a)c.key&&(o[c.key]=we(c.value));n({...t,facets:Object.keys(o).length?o:void 0})},E=a=>{const o=a.filter(c=>c.key).map(c=>({[c.key]:we(c.value)}));n({...t,block:o.length?o:void 0})},T=a=>n({...t,range:a.length?a:void 0}),y=a=>n({...t,exists:a.length?a:void 0}),v=a=>n({...t,orderBy:a.length?a:void 0});return e.jsxs("div",{className:"text-xs",children:[e.jsx("datalist",{id:"lt-facet-keys",children:u.map(a=>e.jsx("option",{value:a},a))}),e.jsxs("datalist",{id:"lt-sort-fields",children:[ks.map(a=>e.jsx("option",{value:a},a)),u.map(a=>e.jsx("option",{value:`metadata.${a}`},a))]}),g&&e.jsx(A,{title:"Match id",hint:"id · workflow · origin",children:e.jsx("input",{className:`${O} w-full`,placeholder:"Exact escalation, workflow, or origin id…",value:l,onChange:a=>g(a.target.value)})}),e.jsx(A,{title:"Has facet",hint:"metadata @>",children:[...p,{key:"",value:""}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.key,placeholder:"key",onChange:c=>{const i=[...p];i[o]={...a,key:c},P(i)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${O} w-40`,placeholder:"value",value:a.value,onChange:c=>{const i=[...p];i[o]={...a,value:c.target.value},P(i)}}),o<p.length&&e.jsx("button",{className:H,onClick:()=>P(p.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Range",hint:"numeric",children:[...f,{facet:"",op:"<=",value:0}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.facet,placeholder:"numeric facet",onChange:c=>{const i=[...f];i[o]={...a,facet:c},T(i.filter(j=>j.facet))}}),e.jsx("select",{className:Ne,value:a.op,onChange:c=>{const i=[...f];i[o]={...a,op:c.target.value},T(i.filter(j=>j.facet))},children:Cs.map(c=>e.jsx("option",{value:c,children:c},c))}),e.jsx("input",{type:"number",className:`${O} w-24`,value:a.value,onChange:c=>{const i=[...f];i[o]={...a,value:Number(c.target.value)},T(i.filter(j=>j.facet))}}),o<f.length&&e.jsx("button",{className:H,onClick:()=>T(f.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Has key",hint:"metadata ? key",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[r.map(a=>e.jsxs("span",{className:"flex items-center gap-1 rounded bg-accent/15 px-1.5 py-0.5 text-accent",children:[a,e.jsx("button",{className:"text-accent/70 hover:text-accent",onClick:()=>y(r.filter(o=>o!==a)),children:"×"})]},a)),e.jsx(K,{value:"",placeholder:"+ key",onChange:a=>{a&&!r.includes(a)&&y([...r,a])}})]})}),e.jsx(A,{title:"Exclude",hint:"NOT @>",children:[...b,{key:"",value:""}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.key,placeholder:"key",onChange:c=>{const i=[...b];i[o]={...a,key:c},E(i)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${O} w-40`,placeholder:"value",value:a.value,onChange:c=>{const i=[...b];i[o]={...a,value:c.target.value},E(i)}}),o<b.length&&e.jsx("button",{className:H,onClick:()=>E(b.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Sort by",children:[...k,{field:"",direction:"asc"}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx("input",{list:"lt-sort-fields",className:`${O} w-44`,placeholder:"column or metadata.key",value:a.field,onChange:c=>{const i=[...k];i[o]={...a,field:c.target.value},v(i.filter(j=>j.field))}}),e.jsxs("select",{className:Ne,value:a.direction??"asc",onChange:c=>{const i=[...k];i[o]={...a,direction:c.target.value},v(i.filter(j=>j.field))},children:[e.jsx("option",{value:"asc",children:"asc"}),e.jsx("option",{value:"desc",children:"desc"})]}),e.jsxs("label",{className:"flex items-center gap-1 text-text-tertiary",children:[e.jsx("input",{type:"checkbox",checked:!!a.numeric,onChange:c=>{const i=[...k];i[o]={...a,numeric:c.target.checked},v(i.filter(j=>j.field))}}),"num"]}),o<k.length&&e.jsx("button",{className:H,onClick:()=>v(k.filter((c,i)=>i!==o)),children:"×"})]},o))})]})}function Ss({value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g,activeFacetCount:p,onClear:b,onClose:f}){return e.jsxs("div",{className:"h-full overflow-y-auto",children:[e.jsxs("div",{className:"sticky top-0 z-10 flex items-center justify-between px-4 py-3 bg-surface-raised border-b border-surface-border/50",children:[e.jsx("span",{className:"text-xs font-semibold text-text-primary",children:"Faceted query"}),e.jsxs("div",{className:"flex items-center gap-2",children:[p>0&&e.jsx("button",{onClick:b,className:"text-2xs text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"}),e.jsx("button",{onClick:f,className:"p-1 rounded hover:bg-surface-hover text-text-tertiary hover:text-text-primary transition-colors",title:"Close",children:e.jsx(re,{className:"w-4 h-4"})})]})]}),e.jsxs("div",{className:"px-4 py-2",children:[e.jsxs("p",{className:"mb-2 text-2xs leading-snug text-text-tertiary",children:["Precise metadata facets plus exact correlation-id lookup — they compose in one SQL query. Facet keys are the ones that actually exist in your visible escalations. Set status to ",e.jsx("span",{className:"font-medium",children:"All"})," to find an order across every status; the whole query is shareable via the URL."]}),e.jsx(Ps,{value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g})]})]})}const Rs=t=>t.isPriorityPending||t.isClaimPending||t.isAssignPending||t.isUnassignPending||t.isTriagePending||t.isCancelPending,D="inline-flex items-center h-7 px-2.5 text-2xs font-medium text-text-secondary bg-surface border border-surface-border rounded-[4px] hover:border-accent/50 hover:text-text-primary transition-colors disabled:opacity-50 disabled:hover:border-surface-border",Pe=`${D} appearance-none cursor-pointer`,Es="inline-flex items-center h-7 px-2.5 text-2xs font-medium text-status-error bg-surface border border-status-error/30 rounded-[4px] hover:border-status-error hover:bg-status-error/5 transition-colors disabled:opacity-50";function Ts(t){var f;const n=Rs(t),u=Te(),{data:l}=xt(),g=ht(),p=g!==null?g:((f=l==null?void 0:l.ai)==null?void 0:f.enabled)===!0,b=t.selectedCount>0;return e.jsx("div",{className:`grid transition-all duration-200 ease-in-out ${b?"grid-rows-[1fr] opacity-100":"grid-rows-[0fr] opacity-0 pointer-events-none"}`,children:e.jsx("div",{className:"overflow-hidden",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-2 py-2.5 pl-3 pr-2 mt-4 mb-3 bg-surface-sunken/60 border-l-2 border-l-accent",children:[e.jsxs("span",{className:"text-2xs font-semibold uppercase tracking-wider text-accent tabular-nums",children:[t.selectedCount," selected"]}),e.jsx("div",{className:"mx-1 h-4 w-px bg-surface-border"}),e.jsxs("select",{onChange:r=>{r.target.value&&(t.onSetPriority(parseInt(r.target.value)),r.target.value="")},disabled:n,className:Pe,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Priority…"}),ps.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value))]}),e.jsxs("select",{onChange:r=>{r.target.value&&(t.onClaim(parseInt(r.target.value)),r.target.value="")},disabled:n,className:Pe,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Claim for…"}),u.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value))]}),e.jsx("button",{onClick:t.onAssign,disabled:n,className:D,children:t.isAssignPending?"Assigning…":"Assign to…"}),e.jsx("button",{onClick:t.onUnassign,disabled:n,className:D,children:t.isUnassignPending?"Unassigning…":"Unassign"}),p&&e.jsx("button",{onClick:t.onTriage,disabled:n,className:D,children:t.isTriagePending?"Triaging…":"Triage"}),t.cancelLabel!==!1&&e.jsx("button",{onClick:t.onCancel,disabled:n,className:Es,children:t.isCancelPending?t.cancelLabel?`${t.cancelLabel}…`:"Cancelling…":t.cancelLabel||"Cancel"}),e.jsx("div",{className:"flex-1"}),n&&e.jsx("span",{className:"text-2xs text-text-tertiary animate-pulse",children:"Processing…"}),e.jsx("button",{onClick:t.onClearSelection,className:"px-1 text-2xs font-medium text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"})]})})})}function As({open:t,onClose:n,selectedCount:u,onSubmit:l,isPending:g}){const[p,b]=m.useState(""),f=()=>{l(p||void 0)};return e.jsx(Se,{open:t,onClose:n,title:"Submit for AI Triage",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Submit ",e.jsx("span",{className:"font-medium text-text-primary",children:u})," escalation(s) for AI triage? The triage orchestrator will take over resolution."]}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-xs font-medium text-text-secondary block mb-1",children:["Triage hint ",e.jsx("span",{className:"text-text-tertiary",children:"(optional)"})]}),e.jsx("input",{type:"text",value:p,onChange:r=>b(r.target.value),placeholder:"e.g., image_orientation",className:"input text-xs font-mono w-full"}),e.jsx("p",{className:"text-2xs text-text-tertiary mt-1",children:"Guides the triage workflow on what remediation to apply"})]}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:n,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:f,disabled:g,className:"btn-primary text-xs",children:g?"Submitting...":"Submit for Triage"})]})]})})}function B(t,n,u){return l=>{t.mutate(l,{onSuccess:()=>{n(),u==null||u()}})}}function Bs(t){const n=()=>[...t.selectedIds];return{handleSetPriority:r=>{B(t.setPriority,t.clearSelection)({ids:n(),priority:r})},handleBulkClaim:r=>{B(t.bulkClaim,t.clearSelection)({ids:n(),durationMinutes:r})},handleBulkTriage:r=>{B(t.bulkTriage,t.clearSelection,t.closeTriageModal)({ids:n(),hint:r})},handleBulkAssign:(r,k,P)=>{B(t.bulkAssign,t.clearSelection,t.closeAssignModal)({ids:n(),targetUserId:r,durationMinutes:k,reassign:P})},handleBulkUnassign:()=>{B(t.bulkUnassign,t.clearSelection)({ids:n()})},handleBulkCancel:()=>{B(t.bulkCancel,t.clearSelection,t.closeCancelModal)({ids:n()})}}}function Os({claimTarget:t,onClose:n,claimDuration:u,onDurationChange:l,claimDurations:g,onCustomClaimChange:p,onClaim:b,isPending:f}){return e.jsx(Se,{open:!!t,onClose:n,title:"Claim Escalation",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Claim ",e.jsx("span",{className:"font-medium text-text-primary",children:t==null?void 0:t.type})," for:"]}),e.jsxs("select",{value:u,onChange:r=>{l(r.target.value)},className:"select w-full text-sm",children:[g.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),u==="custom"&&e.jsx(ts,{onChange:p,autoFocus:!0}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:n,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:b,className:"btn-primary text-xs",disabled:f,children:f?"Claiming...":"Claim"})]})]})})}function ra(){var ke;vs();const t=Ee(),{filters:n,setFilter:u,pagination:l}=xs({filters:{role:"",type:"",subtype:"",priority:"",status:"available",search:""}});gt({role:n.role||null,verbs:["created","claimed","updated"]});const g=hs(n.search),p=Te(),[b,f]=m.useState(null),[r,k]=m.useState("30"),[P,E]=m.useState(0),T=m.useCallback(s=>E(s),[]),[y,v]=m.useState(new Set),a=m.useRef(null),o=m.useRef(null),c=m.useCallback(s=>{var x;if((x=o.current)==null||x.disconnect(),o.current=null,!s||typeof ResizeObserver>"u")return;const d=new ResizeObserver(()=>{var q;(q=a.current)==null||q.style.setProperty("--lt-sticky-top",`${s.offsetHeight-1}px`)});d.observe(s),o.current=d},[]),[i,j]=m.useState(!1),[L,M]=Ht(),h=m.useMemo(()=>ft(L),[L]),N=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return pt(x,s),x.delete("page"),x})},[M]),{data:F}=bt(i),z=yt(h)+(n.search?1:0),G="facet-query",{setPanel:oe,closePanel:ce,open:Ae,ownerKey:Be}=jt();m.useEffect(()=>{if(!i){ce(G);return}oe(e.jsx(Ss,{value:h,onChange:N,facetKeys:(F==null?void 0:F.keys)??[],search:n.search??"",onSearchChange:s=>u("search",s),activeFacetCount:z,onClear:()=>{N({}),u("search","")},onClose:()=>j(!1)}),{width:420,key:G})},[i,h,N,F,n.search,u,z,oe,ce]);const de=Ae&&Be===G,Q=m.useRef(!1);m.useEffect(()=>{if(de){Q.current=!0;return}Q.current&&(Q.current=!1,j(!1))},[de]);const[Oe,W]=m.useState(!1),[Le,Y]=m.useState(!1),[Me,X]=m.useState(!1),Fe=m.useCallback(s=>N({...h,orderBy:s}),[h,N]),I=Re(),{data:U}=vt(),ue=Ct(),ze=m.useCallback(()=>{var x;const s=window.prompt("Pin label:");if(!(s!=null&&s.trim()))return;const d=((x=U==null?void 0:U.preferences)==null?void 0:x.pinnedViews)??[];ue.mutate({pinnedViews:[...d,{id:kt(),label:s.trim(),url:I.pathname+I.search,badge:!0}]})},[I.pathname,I.search,U,ue]),{canBulk:Ie}=Nt(),{kiosk:J}=wt(),me=h.facets?Object.keys(h.facets):[],Ue=L.get("view"),Ve=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return s?x.set("view",s):x.delete("view"),x},{replace:!0})},[M]),Z=Ue==="timeline",_e=m.useCallback(s=>{const{[s]:d,...x}=h.facets??{};N({...h,facets:Object.keys(x).length>0?x:void 0})},[h,N]),xe=Pt(),he=St(),ge=Rt(),ee=Et(),fe=Tt(),te=At(),V=Bt(),{data:se}=Ot(),{data:S}=Lt(),{data:ae}=Mt(),{user:_,isSuperAdmin:$e,hasRoleType:qe}=Ft(),pe=$e||qe("admin"),be=m.useMemo(()=>new Set(((_==null?void 0:_.roles)??[]).map(s=>s.role)),[_]),He=m.useMemo(()=>{const s=(S==null?void 0:S.roles)??[];return(pe?s:s.filter(x=>be.has(x.role)&&!Kt(x.role))).map(x=>({value:x.role,label:zt(x)})).sort((x,q)=>x.label.localeCompare(q.label))},[S,pe,be]);m.useEffect(()=>{v(new Set)},[n.role,n.type,n.subtype,n.priority,n.status,g,l.page,l.pageSize]);const ne=m.useMemo(()=>({...It(L,$t.AVAILABLE),search:g||void 0}),[L,g]),ye=100,{escalations:C,total:w,groups:Ke,listSchema:De,listSchemaVersion:Ge,singleRole:R,hasRichView:je,isLoading:Qe,isFetching:ve,error:$,refetch:We}=ls(ne,{limit:Z?ye:l.pageSize,offset:l.offset}),Ye=Ut(R??"",void 0,!!R),ie=R?ss((ke=Ye.data)==null?void 0:ke.form_schema).cancel:void 0,le=Vt(ne.view,je),Xe=le===qt.RICH,Ce=m.useMemo(()=>{if(!h.jeopardy||!R)return null;const s=((S==null?void 0:S.roles)??[]).find(x=>x.role===R),d=(s==null?void 0:s.priority_threshold_minutes)??(s==null?void 0:s.sla_minutes)??null;return d!=null?_t(d*6e4):null},[h.jeopardy,R,S]),Je=m.useMemo(()=>{const s=new Set;for(const d of C)y.has(d.id)&&s.add(d.role);return[...s]},[C,y]),Ze=m.useMemo(()=>C.filter(s=>y.has(s.id)&&js(s)).length,[C,y]),et=m.useCallback(()=>v(new Set),[]),tt=()=>{if(!b)return;const s=r==="custom"?P:parseInt(r);!s||s<=0||xe.mutate({id:b.id,durationMinutes:s},{onSuccess:()=>{f(null),t(`/escalations/detail/${b.id}`)}})},{handleSetPriority:st,handleBulkClaim:at,handleBulkTriage:nt,handleBulkAssign:it,handleBulkUnassign:lt,handleBulkCancel:rt}=Bs({selectedIds:y,clearSelection:et,setPriority:he,bulkClaim:ge,bulkTriage:te,bulkAssign:ee,bulkUnassign:fe,bulkCancel:V,closeTriageModal:()=>W(!1),closeAssignModal:()=>Y(!1),closeCancelModal:()=>X(!1)}),ot=s=>{const d=new Set(y);d.has(s)?d.delete(s):d.add(s),v(d)},ct=()=>{y.size===C.length?v(new Set):v(new Set(C.map(s=>s.id)))},dt=[Ie?{key:"select",label:e.jsx("input",{type:"checkbox",checked:C.length>0&&y.size===C.length,onChange:ct,className:"rounded"}),render:s=>e.jsx("input",{type:"checkbox",checked:y.has(s.id),onChange:d=>{d.stopPropagation(),ot(s.id)},onClick:d=>d.stopPropagation(),className:"rounded"}),className:"w-10",priority:1}:{key:"spacer",label:"",render:()=>null,className:"w-10",priority:3},...ds({highlightKeys:me}),{key:"actions",label:"",render:s=>e.jsx(bs,{children:e.jsx(ys,{icon:Dt,title:"Claim escalation",onClick:()=>f(s),alwaysVisible:!0,colorClass:"text-accent/40 hover:text-accent",size:"sm"})}),className:"w-10 text-right"}];return e.jsxs("div",{ref:a,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-10 min-w-0",children:[e.jsx(is,{role:n.role,options:He,onChange:s=>u("role",s),locked:J}),!J&&e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:all-escalations"},className:"text-text-quaternary hover:text-accent transition-colors mt-1 shrink-0",title:"Open docs for this page",children:e.jsx(Gt,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsxs("div",{ref:c,className:"sticky top-0 z-20 bg-surface",children:[e.jsx(us,{filters:n,setFilter:u,roles:(se==null?void 0:se.roles)??[],types:(ae==null?void 0:ae.types)??[],showStatus:!0,showSearch:!1,showRole:!J,actions:e.jsxs(e.Fragment,{children:[Z&&e.jsxs("span",{className:"text-2xs text-text-tertiary whitespace-nowrap",children:[w>100&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"font-medium text-text-secondary",children:[(l.page-1)*100+1,"–",Math.min(l.page*100,w)]})," of "]}),e.jsx("span",{className:"font-medium text-text-secondary",children:w})," ",w===1?"escalation":"escalations"]}),e.jsx(rs,{orderBy:h.orderBy,onChange:Fe}),e.jsx("div",{role:"radiogroup","aria-label":"List view",className:"flex items-center rounded overflow-hidden border border-surface-border",children:[{key:"table",title:"Table view",Icon:Qt},{key:"rich",title:"Rich view",Icon:Wt},{key:"timeline",title:"Timeline view",Icon:Yt}].filter(s=>s.key!=="rich"||je).map(({key:s,title:d,Icon:x})=>e.jsx("button",{role:"radio","aria-checked":le===s,onClick:()=>Ve(s),className:`px-1.5 py-1 transition-colors ${le===s?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:d,children:e.jsx(x,{className:"w-3.5 h-3.5"})},s))}),e.jsxs("button",{onClick:()=>j(s=>!s),"aria-pressed":i,className:`relative rounded border border-surface-border px-1.5 py-1 transition-colors ${i?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:"Faceted query",children:[e.jsx(Xt,{className:"w-3.5 h-3.5"}),z>0&&e.jsx("span",{className:"absolute -right-1 -top-1 flex h-3.5 min-w-[14px] items-center justify-center rounded-full bg-accent px-0.5 text-2xs font-medium text-text-inverse",children:z})]}),e.jsxs("div",{className:"flex items-center gap-0.5",children:[e.jsx("button",{onClick:()=>We(),disabled:ve,className:"inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover disabled:opacity-50",title:"Refresh",children:e.jsx(Jt,{className:`w-4 h-4 ${ve?"animate-spin":""}`})}),e.jsx("button",{onClick:ze,className:"inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:"Pin this view — save the current filters to your Pinned section","data-testid":"pin-current-view",children:e.jsx(Zt,{className:"w-4 h-4"})})]})]})}),e.jsx(Ts,{selectedCount:y.size,onClearSelection:()=>v(new Set),onSetPriority:st,onClaim:at,onAssign:()=>Y(!0),onUnassign:lt,onTriage:()=>W(!0),onCancel:()=>X(!0),isPriorityPending:he.isPending,isClaimPending:ge.isPending,isAssignPending:ee.isPending,isUnassignPending:fe.isPending,isTriagePending:te.isPending,isCancelPending:V.isPending,cancelLabel:ie}),(h.facets&&Object.keys(h.facets).length>0||h.jeopardy)&&e.jsxs("div",{className:"bg-surface/98 backdrop-blur-sm border-b border-surface-border/30 -mx-page-x px-page-x py-2 flex items-center gap-1.5 flex-wrap",children:[h.jeopardy&&e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-status-error px-2.5 py-0.5 text-2xs font-semibold text-text-inverse",children:[e.jsx(es,{className:"w-2.5 h-2.5",strokeWidth:2.5}),"in jeopardy",Ce&&e.jsxs("span",{className:"font-mono font-normal opacity-90",children:["> ",Ce]}),e.jsx("button",{onClick:()=>N({...h,jeopardy:void 0}),className:"ml-0.5 -mr-0.5 flex items-center text-text-inverse/70 hover:text-text-inverse transition-colors","aria-label":"Clear jeopardy filter",children:e.jsx(re,{className:"w-2.5 h-2.5"})})]}),Object.entries(h.facets??{}).map(([s,d])=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full border border-accent/25 bg-accent/8 px-2.5 py-0.5 text-2xs font-medium text-accent/90",children:[e.jsx("span",{className:"font-mono text-text-tertiary",children:s}),e.jsx("span",{className:"text-text-quaternary",children:"="}),e.jsx("span",{className:"font-mono max-w-[160px] truncate",title:String(d),children:String(d)}),e.jsx("button",{onClick:()=>_e(s),className:"ml-0.5 -mr-0.5 flex items-center text-text-quaternary hover:text-status-error transition-colors","aria-label":`Remove ${s} filter`,children:e.jsx(re,{className:"w-2.5 h-2.5"})})]},s)),Object.keys(h.facets??{}).length>1&&e.jsx("button",{onClick:()=>N({...h,facets:void 0}),className:"text-2xs text-text-quaternary hover:text-text-secondary transition-colors px-1",children:"clear all"})]})]}),$&&e.jsx("div",{className:"mb-4 px-4 py-3 rounded-md bg-status-error/10 border border-status-error/20 text-xs text-status-error",children:$.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${$.message}`}),Z?e.jsx(os,{escalations:C,highlightKeys:me,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),total:w,page:l.page,totalPages:Math.ceil(w/ye),onPageChange:l.setPage}):Xe?e.jsx(ms,{role:R,listSchema:De,listSchemaVersion:Ge,activeEscalations:C,groups:Ke,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),onOpenGroup:s=>t(s),onAddFacet:(s,d)=>N({...h,facets:{...h.facets??{},[s]:typeof d=="object"&&d!==null?JSON.stringify(d):d}}),total:w,page:l.page,totalPages:l.totalPages(w),pageSize:l.pageSize,onPageChange:l.setPage,onPageSizeChange:l.setPageSize}):e.jsxs(e.Fragment,{children:[e.jsx(gs,{columns:dt,data:C,layout:"fixed",...cs(ne.layout),keyFn:s=>s.id,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),isLoading:Qe,emptyMessage:$?"Unable to load data":"No escalations"}),e.jsx(fs,{page:l.page,totalPages:l.totalPages(w),onPageChange:l.setPage,total:w,pageSize:l.pageSize,onPageSizeChange:l.setPageSize})]}),e.jsx(Os,{claimTarget:b,onClose:()=>f(null),claimDuration:r,onDurationChange:s=>{k(s),E(0)},claimDurations:p,customClaimMinutes:P,onCustomClaimChange:T,onClaim:tt,isPending:xe.isPending}),e.jsx(As,{open:Oe,onClose:()=>W(!1),selectedCount:y.size,onSubmit:nt,isPending:te.isPending}),e.jsx(as,{open:Le,onClose:()=>Y(!1),selectedCount:y.size,selectedRoles:Je,claimedCount:Ze,onSubmit:it,isPending:ee.isPending}),e.jsx(ns,{open:Me,onClose:()=>X(!1),onConfirm:rt,selectedCount:y.size,isPending:V.isPending,error:V.error,actionLabel:typeof ie=="string"?ie:void 0})]})}export{ra as AvailableEscalationsPage};
|
|
2
|
-
//# sourceMappingURL=AvailableEscalationsPage-IS28XBRe.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{g as h,a as p}from"./validate-BIRn4a6d.js";import{a as y,j as x}from"./vendor-query-DvWWuNIB.js";import{bi as C,aE as S,bj as j}from"./index-CeCtqujG.js";const D="accumulate_items",O="accumulate_max",b="batch_items",_="batch_filled_at",A="batch_filled_by",L="batch_keys",N="batch_pending";function l(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function I(t,r){return t.at.localeCompare(r.at)||t.itemKey.localeCompare(r.itemKey)}function R(t,r){const s=t.metadata??{},o=r==null?void 0:r[D];if(l(o)){const a=Object.entries(o).map(([m,e])=>{const c=l(e)?e:{};return{itemKey:m,at:typeof c.at=="string"?c.at:"",...l(c.payload)?{payload:c.payload}:{},...typeof c.actor=="string"?{actor:c.actor}:{},...typeof c.reciprocalId=="string"?{reciprocalId:c.reciprocalId}:{}}}).sort(I),u=s[O];return{kind:"accumulate",count:a.length,max:typeof u=="number"?u:null,items:a,pending:[]}}const n=s[N];if(Array.isArray(n)){const a=l(r==null?void 0:r[b])?r[b]:{},u=l(r==null?void 0:r[_])?r[_]:{},m=l(r==null?void 0:r[A])?r[A]:{},e=Object.entries(a).map(([i,d])=>({itemKey:i,at:typeof u[i]=="string"?u[i]:"",...l(d)?{payload:d}:{},...typeof m[i]=="string"?{actor:m[i]}:{}})).sort(I),c=s[L];return{kind:"batch",count:e.length,max:Array.isArray(c)?c.length:null,items:e,pending:n.filter(i=>typeof i=="string")}}return null}function U(t){if(!t)return"";const r=Object.entries(t).slice(0,3).map(([o,n])=>{const a=typeof n=="object"&&n!==null?JSON.stringify(n):String(n);return`${o}: ${a.length>24?`${a.slice(0,23)}…`:a}`}),s=Object.keys(t).length-r.length;return s>0?`${r.join(" · ")} · +${s}`:r.join(" · ")}const Y="x-lt-item-label",T=/\{\{\s*([^{}]+?)\s*\}\}/g,E="item",g="—";function H(t){if(t==null||t==="")return null;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return null}}function M(t,r,s){const o=t.indexOf(".");if((o===-1?t:t.slice(0,o))===E)try{return H(o===-1?r:h(r,t.slice(o+1)))}catch{return null}const a=p(`{{${t}}}`,s);return a===g?null:a}function F(t,r,s={}){if(typeof t!="string"||!t.trim())return null;let o=0,n=0;const a=t.replace(T,(u,m)=>{n+=1;const e=M(m,r,s);return e===null?g:(o+=1,e)}).trim();return n>0&&o===0?null:a||null}function G(t,r,s={}){return t.replace(T,(o,n)=>!r&&n.split(".")[0]===E?g:M(n,r??{},s)??g)}const f=[{maxMs:0,color:"text-status-error"},{maxMs:300*1e3,color:"text-status-error"},{maxMs:900*1e3,color:"text-status-warning"},{maxMs:1/0,color:"text-text-secondary"}];function k(t){if(t<=0)return f[0].color;for(const r of f)if(t<r.maxMs)return r.color;return f[f.length-1].color}function J({until:t}){const[r,s]=y.useState(()=>new Date(t).getTime()-Date.now());y.useEffect(()=>{const n=setInterval(()=>{s(new Date(t).getTime()-Date.now())},1e3);return()=>clearInterval(n)},[t]);const o=y.useMemo(()=>{const n=new Date(t);return[{label:"ms",value:String(Math.max(0,r))},{label:"until",value:n.toISOString()},{label:"local",value:C(n,"MMM d, yyyy h:mm:ss a")}]},[t,r]);return x.jsx(S,{options:o,children:x.jsx("span",{className:`text-xs font-mono ${k(r)}`,children:j(r)})})}export{J as C,Y as I,G as a,R as e,F as i,U as s};
|
|
2
|
-
//# sourceMappingURL=CountdownTimer-LG03dVgR.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CountdownTimer-LG03dVgR.js","sources":["../../src/lib/escalation-items.ts","../../src/components/common/display/CountdownTimer.tsx"],"sourcesContent":["import type { LTEscalationRecord } from '../api/types';\nimport { interpolateHelp, type HelpTokenContext } from './x-lt-help';\nimport { getDeep } from './x-lt-bind';\n\n/** One held item of an accumulator or batch row, in the shape the workflow receives. */\nexport interface EscalationItem {\n itemKey: string;\n payload?: Record<string, unknown>;\n /** ISO-8601 from the database clock; empty for a batch item with no stamp. */\n at: string;\n actor?: string;\n reciprocalId?: string;\n}\n\nexport interface EscalationItems {\n kind: 'accumulate' | 'batch';\n count: number;\n /** The count trigger (accumulate) or the declared size (batch); null when unbounded. */\n max: number | null;\n items: EscalationItem[];\n /** Batch only: declared keys still awaiting submission. */\n pending: string[];\n}\n\nconst ACCUMULATE_ITEMS = 'accumulate_items';\nconst ACCUMULATE_MAX = 'accumulate_max';\nconst BATCH_ITEMS = 'batch_items';\nconst BATCH_FILLED_AT = 'batch_filled_at';\nconst BATCH_FILLED_BY = 'batch_filled_by';\nconst BATCH_KEYS = 'batch_keys';\nconst BATCH_PENDING = 'batch_pending';\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return !!v && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction byArrival(a: EscalationItem, b: EscalationItem): number {\n return a.at.localeCompare(b.at) || a.itemKey.localeCompare(b.itemKey);\n}\n\n/**\n * The held items of a row, or null when the row is neither an accumulator\n * nor a batch. Mirrors the server's items view so the panel and the API\n * agree on order (arrival, then key).\n */\nexport function escalationItems(\n esc: Pick<LTEscalationRecord, 'metadata'>,\n envelope: Record<string, unknown> | null,\n): EscalationItems | null {\n const metadata = (esc.metadata ?? {}) as Record<string, unknown>;\n const store = envelope?.[ACCUMULATE_ITEMS];\n if (isRecord(store)) {\n const items = Object.entries(store).map(([itemKey, entry]) => {\n const e = isRecord(entry) ? entry : {};\n return {\n itemKey,\n at: typeof e.at === 'string' ? e.at : '',\n ...(isRecord(e.payload) ? { payload: e.payload } : {}),\n ...(typeof e.actor === 'string' ? { actor: e.actor } : {}),\n ...(typeof e.reciprocalId === 'string' ? { reciprocalId: e.reciprocalId } : {}),\n } as EscalationItem;\n }).sort(byArrival);\n const max = metadata[ACCUMULATE_MAX];\n return { kind: 'accumulate', count: items.length, max: typeof max === 'number' ? max : null, items, pending: [] };\n }\n const pending = metadata[BATCH_PENDING];\n if (Array.isArray(pending)) {\n const filled = isRecord(envelope?.[BATCH_ITEMS]) ? (envelope![BATCH_ITEMS] as Record<string, unknown>) : {};\n const stamps = isRecord(envelope?.[BATCH_FILLED_AT]) ? (envelope![BATCH_FILLED_AT] as Record<string, unknown>) : {};\n const actors = isRecord(envelope?.[BATCH_FILLED_BY]) ? (envelope![BATCH_FILLED_BY] as Record<string, unknown>) : {};\n const items = Object.entries(filled).map(([itemKey, payload]) => ({\n itemKey,\n at: typeof stamps[itemKey] === 'string' ? (stamps[itemKey] as string) : '',\n ...(isRecord(payload) ? { payload } : {}),\n ...(typeof actors[itemKey] === 'string' ? { actor: actors[itemKey] as string } : {}),\n } as EscalationItem)).sort(byArrival);\n const keys = metadata[BATCH_KEYS];\n return {\n kind: 'batch',\n count: items.length,\n max: Array.isArray(keys) ? keys.length : null,\n items,\n pending: pending.filter((k): k is string => typeof k === 'string'),\n };\n }\n return null;\n}\n\n/** A one-line summary of an item payload for the list row. */\nexport function summarizePayload(payload: Record<string, unknown> | undefined): string {\n if (!payload) return '';\n const parts = Object.entries(payload).slice(0, 3).map(([k, v]) => {\n const text = typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n return `${k}: ${text.length > 24 ? `${text.slice(0, 23)}…` : text}`;\n });\n const more = Object.keys(payload).length - parts.length;\n return more > 0 ? `${parts.join(' · ')} · +${more}` : parts.join(' · ');\n}\n\n/** The container role's form-schema key naming how each held item displays. */\nexport const ITEM_LABEL_KEY = 'x-lt-item-label';\n\nconst TOKEN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst ITEM_DOMAIN = 'item';\nconst MISSING = '—';\n\nfunction formatValue(value: unknown): string | null {\n if (value === undefined || value === null || value === '') return null;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n}\n\n/** One token's value: `item.*` from the held item, every other domain as help tokens resolve it. */\nfunction tokenValue(path: string, item: EscalationItem, ctx: HelpTokenContext): string | null {\n const dot = path.indexOf('.');\n const domain = dot === -1 ? path : path.slice(0, dot);\n if (domain === ITEM_DOMAIN) {\n try {\n return formatValue(dot === -1 ? item : getDeep(item, path.slice(dot + 1)));\n } catch {\n return null;\n }\n }\n const value = interpolateHelp(`{{${path}}}`, ctx);\n return value === MISSING ? null : value;\n}\n\n/**\n * An item's display label from the role's `x-lt-item-label` template, whose\n * `{{item.*}}` tokens read the held item (itemKey, payload, actor, at) beside\n * the usual escalation domains. Null when there is no template or every token\n * it names is missing, so the caller falls back to the item key.\n */\nexport function itemLabel(\n template: unknown,\n item: EscalationItem,\n ctx: HelpTokenContext = {},\n): string | null {\n if (typeof template !== 'string' || !template.trim()) return null;\n let resolved = 0;\n let tokens = 0;\n const label = template.replace(TOKEN, (_match, rawPath: string) => {\n tokens += 1;\n const value = tokenValue(rawPath, item, ctx);\n if (value === null) return MISSING;\n resolved += 1;\n return value;\n }).trim();\n if (tokens > 0 && resolved === 0) return null;\n return label || null;\n}\n\n/** A template over `{{item.*}}` and the escalation domains; missing tokens read as an em dash. */\nexport function interpolateItemTemplate(template: string, item: EscalationItem | undefined, ctx: HelpTokenContext = {}): string {\n return template.replace(TOKEN, (_match, rawPath: string) => {\n if (!item && rawPath.split('.')[0] === ITEM_DOMAIN) return MISSING;\n return tokenValue(rawPath, item ?? ({} as EscalationItem), ctx) ?? MISSING;\n });\n}\n","import { useState, useEffect, useMemo } from 'react';\nimport { format as fnsFormat } from 'date-fns';\nimport { formatRemaining } from '../../../lib/format';\nimport { DateTooltip } from './DateTooltip';\n\nconst COUNTDOWN_THRESHOLDS = [\n { maxMs: 0, color: 'text-status-error' },\n { maxMs: 5 * 60 * 1000, color: 'text-status-error' },\n { maxMs: 15 * 60 * 1000, color: 'text-status-warning' },\n { maxMs: Infinity, color: 'text-text-secondary' },\n] as const;\n\nfunction countdownColor(remainingMs: number): string {\n if (remainingMs <= 0) return COUNTDOWN_THRESHOLDS[0].color;\n for (const t of COUNTDOWN_THRESHOLDS) {\n if (remainingMs < t.maxMs) return t.color;\n }\n return COUNTDOWN_THRESHOLDS[COUNTDOWN_THRESHOLDS.length - 1].color;\n}\n\nexport function CountdownTimer({ until }: { until: string }) {\n const [remaining, setRemaining] = useState(() => new Date(until).getTime() - Date.now());\n\n useEffect(() => {\n const interval = setInterval(() => {\n setRemaining(new Date(until).getTime() - Date.now());\n }, 1000);\n return () => clearInterval(interval);\n }, [until]);\n\n const options = useMemo(() => {\n const d = new Date(until);\n return [\n { label: 'ms', value: String(Math.max(0, remaining)) },\n { label: 'until', value: d.toISOString() },\n { label: 'local', value: fnsFormat(d, 'MMM d, yyyy h:mm:ss a') },\n ];\n }, [until, remaining]);\n\n return (\n <DateTooltip options={options}>\n <span className={`text-xs font-mono ${countdownColor(remaining)}`}>\n {formatRemaining(remaining)}\n </span>\n </DateTooltip>\n );\n}\n"],"names":["ACCUMULATE_ITEMS","ACCUMULATE_MAX","BATCH_ITEMS","BATCH_FILLED_AT","BATCH_FILLED_BY","BATCH_KEYS","BATCH_PENDING","isRecord","v","byArrival","a","b","escalationItems","esc","envelope","metadata","store","items","itemKey","entry","e","max","pending","filled","stamps","actors","payload","keys","k","summarizePayload","parts","text","more","ITEM_LABEL_KEY","TOKEN","ITEM_DOMAIN","MISSING","formatValue","value","tokenValue","path","item","ctx","dot","getDeep","interpolateHelp","itemLabel","template","resolved","tokens","label","_match","rawPath","interpolateItemTemplate","COUNTDOWN_THRESHOLDS","countdownColor","remainingMs","t","CountdownTimer","until","remaining","setRemaining","useState","useEffect","interval","options","useMemo","d","fnsFormat","jsx","DateTooltip","formatRemaining"],"mappings":"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"}
|