@hotmeshio/long-tail 0.14.1 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/build/api/escalations/bulk.d.ts +18 -0
  2. package/build/api/escalations/bulk.js +49 -1
  3. package/build/api/escalations/helpers.d.ts +11 -1
  4. package/build/api/escalations/helpers.js +30 -3
  5. package/build/api/escalations/index.d.ts +1 -1
  6. package/build/api/escalations/index.js +2 -1
  7. package/build/routes/escalations/bulk.js +6 -0
  8. package/build/sdk/index.d.ts +4 -0
  9. package/build/sdk/index.js +1 -0
  10. package/build/services/escalation/bulk.d.ts +27 -0
  11. package/build/services/escalation/bulk.js +39 -0
  12. package/build/services/escalation/sql.d.ts +17 -0
  13. package/build/services/escalation/sql.js +44 -1
  14. package/build/shared/form-validation/field-validator.js +6 -4
  15. package/build/shared/form-validation/index.d.ts +2 -0
  16. package/build/shared/form-validation/index.js +2 -0
  17. package/build/shared/form-validation/validate-resolver-payload.d.ts +2 -0
  18. package/build/shared/form-validation/validate-resolver-payload.js +19 -0
  19. package/build/shared/form-validation/x-lt-options.d.ts +22 -0
  20. package/build/shared/form-validation/x-lt-options.js +51 -0
  21. package/build/shared/form-validation/x-lt-require-sum.d.ts +30 -0
  22. package/build/shared/form-validation/x-lt-require-sum.js +59 -0
  23. package/build/system/mcp-servers/admin/escalations.js +13 -1
  24. package/build/system/mcp-servers/admin/schemas.d.ts +10 -0
  25. package/build/system/mcp-servers/admin/schemas.js +6 -2
  26. package/build/system/seed/tool-manifests-admin.d.ts +88 -0
  27. package/build/system/seed/tool-manifests-admin.js +2 -1
  28. package/build/tsconfig.tsbuildinfo +1 -1
  29. package/dashboard/dist/assets/{AdminDashboard-C4h1R-lz.js → AdminDashboard-CUqnrc7h.js} +2 -2
  30. package/dashboard/dist/assets/{AdminDashboard-C4h1R-lz.js.map → AdminDashboard-CUqnrc7h.js.map} +1 -1
  31. package/dashboard/dist/assets/{AgentConfigPage-EWC8VQ7R.js → AgentConfigPage-lmUOwyHO.js} +6 -6
  32. package/dashboard/dist/assets/{AgentConfigPage-EWC8VQ7R.js.map → AgentConfigPage-lmUOwyHO.js.map} +1 -1
  33. package/dashboard/dist/assets/{AgentDetailPage-DaLfa80d.js → AgentDetailPage-C_xAw6aF.js} +3 -3
  34. package/dashboard/dist/assets/{AgentDetailPage-DaLfa80d.js.map → AgentDetailPage-C_xAw6aF.js.map} +1 -1
  35. package/dashboard/dist/assets/{AgentsPage-islj_zrh.js → AgentsPage-CHCGAkpN.js} +2 -2
  36. package/dashboard/dist/assets/{AgentsPage-islj_zrh.js.map → AgentsPage-CHCGAkpN.js.map} +1 -1
  37. package/dashboard/dist/assets/AvailableEscalationsPage-BvQdHMl2.js +2 -0
  38. package/dashboard/dist/assets/AvailableEscalationsPage-BvQdHMl2.js.map +1 -0
  39. package/dashboard/dist/assets/BotPicker-Dsr8Yyj_.js +2 -0
  40. package/dashboard/dist/assets/{BotPicker-CnX8xfka.js.map → BotPicker-Dsr8Yyj_.js.map} +1 -1
  41. package/dashboard/dist/assets/BulkAssignModal-CbUftMR2.js +2 -0
  42. package/dashboard/dist/assets/BulkAssignModal-CbUftMR2.js.map +1 -0
  43. package/dashboard/dist/assets/CapabilitiesPage-CPNUJPHs.js +2 -0
  44. package/dashboard/dist/assets/{CapabilitiesPage-DK7wGMFt.js.map → CapabilitiesPage-CPNUJPHs.js.map} +1 -1
  45. package/dashboard/dist/assets/{CollapsibleSection-WqEpMTyx.js → CollapsibleSection-DffGX2tR.js} +2 -2
  46. package/dashboard/dist/assets/{CollapsibleSection-WqEpMTyx.js.map → CollapsibleSection-DffGX2tR.js.map} +1 -1
  47. package/dashboard/dist/assets/CountdownTimer-Bb_VuJc8.js +2 -0
  48. package/dashboard/dist/assets/CountdownTimer-Bb_VuJc8.js.map +1 -0
  49. package/dashboard/dist/assets/{CredentialsPage-CfT60FiU.js → CredentialsPage-UXnD_Rau.js} +2 -2
  50. package/dashboard/dist/assets/{CredentialsPage-CfT60FiU.js.map → CredentialsPage-UXnD_Rau.js.map} +1 -1
  51. package/dashboard/dist/assets/{CronLabel-ds7dLz6S.js → CronLabel-CctUYUlI.js} +2 -2
  52. package/dashboard/dist/assets/{CronLabel-ds7dLz6S.js.map → CronLabel-CctUYUlI.js.map} +1 -1
  53. package/dashboard/dist/assets/{DataTable-Bir0Xs1p.js → DataTable-DFPMeqyQ.js} +2 -2
  54. package/dashboard/dist/assets/DataTable-DFPMeqyQ.js.map +1 -0
  55. package/dashboard/dist/assets/{DropZone-DovkhN2p.js → DropZone-7UoXQ4qL.js} +2 -2
  56. package/dashboard/dist/assets/{DropZone-DovkhN2p.js.map → DropZone-7UoXQ4qL.js.map} +1 -1
  57. package/dashboard/dist/assets/{ElapsedCell-DRQhFky_.js → ElapsedCell-C7_Y8xXn.js} +2 -2
  58. package/dashboard/dist/assets/{ElapsedCell-DRQhFky_.js.map → ElapsedCell-C7_Y8xXn.js.map} +1 -1
  59. package/dashboard/dist/assets/{EntityTimelinePanel-nCgWdmpK.js → EntityTimelinePanel-pRu91gZK.js} +2 -2
  60. package/dashboard/dist/assets/{EntityTimelinePanel-nCgWdmpK.js.map → EntityTimelinePanel-pRu91gZK.js.map} +1 -1
  61. package/dashboard/dist/assets/{EscalationListSchemaPage-DBCnPMG9.js → EscalationListSchemaPage-B3f2mjqg.js} +3 -3
  62. package/dashboard/dist/assets/{EscalationListSchemaPage-DBCnPMG9.js.map → EscalationListSchemaPage-B3f2mjqg.js.map} +1 -1
  63. package/dashboard/dist/assets/{EscalationSchemaPage-DfzRTqhV.js → EscalationSchemaPage-AJ85FRZy.js} +3 -3
  64. package/dashboard/dist/assets/{EscalationSchemaPage-DfzRTqhV.js.map → EscalationSchemaPage-AJ85FRZy.js.map} +1 -1
  65. package/dashboard/dist/assets/{EscalationsOverview-CWd2Ivso.js → EscalationsOverview-DMLLWzjS.js} +2 -2
  66. package/dashboard/dist/assets/{EscalationsOverview-CWd2Ivso.js.map → EscalationsOverview-DMLLWzjS.js.map} +1 -1
  67. package/dashboard/dist/assets/{EventTable-Dm9Fbab1.js → EventTable-BlNuCTN6.js} +2 -2
  68. package/dashboard/dist/assets/{EventTable-Dm9Fbab1.js.map → EventTable-BlNuCTN6.js.map} +1 -1
  69. package/dashboard/dist/assets/{FilterBar-DR4cJvTB.js → FilterBar-B-rkcWkV.js} +2 -2
  70. package/dashboard/dist/assets/{FilterBar-DR4cJvTB.js.map → FilterBar-B-rkcWkV.js.map} +1 -1
  71. package/dashboard/dist/assets/{GraphInvokePage-DQt64Ru0.js → GraphInvokePage-Bkt5tAFo.js} +2 -2
  72. package/dashboard/dist/assets/{GraphInvokePage-DQt64Ru0.js.map → GraphInvokePage-Bkt5tAFo.js.map} +1 -1
  73. package/dashboard/dist/assets/{HomePage-D7qNiqtw.js → HomePage-CIE9bCFQ.js} +2 -2
  74. package/dashboard/dist/assets/{HomePage-D7qNiqtw.js.map → HomePage-CIE9bCFQ.js.map} +1 -1
  75. package/dashboard/dist/assets/{ListToolbar-BdZkpRMo.js → ListToolbar-C_-Utxqm.js} +2 -2
  76. package/dashboard/dist/assets/{ListToolbar-BdZkpRMo.js.map → ListToolbar-C_-Utxqm.js.map} +1 -1
  77. package/dashboard/dist/assets/{McpOverview-DHAEYY1b.js → McpOverview-c0p171OK.js} +2 -2
  78. package/dashboard/dist/assets/{McpOverview-DHAEYY1b.js.map → McpOverview-c0p171OK.js.map} +1 -1
  79. package/dashboard/dist/assets/{McpQueryDetailPage-BfGhRO_c.js → McpQueryDetailPage-B61I9-dM.js} +3 -3
  80. package/dashboard/dist/assets/{McpQueryDetailPage-BfGhRO_c.js.map → McpQueryDetailPage-B61I9-dM.js.map} +1 -1
  81. package/dashboard/dist/assets/McpQueryPage-Viqi13Fa.js +2 -0
  82. package/dashboard/dist/assets/{McpQueryPage-3EXLX1Eq.js.map → McpQueryPage-Viqi13Fa.js.map} +1 -1
  83. package/dashboard/dist/assets/{McpRunDetailPage-DHI0F65P.js → McpRunDetailPage-CiAx_xyV.js} +2 -2
  84. package/dashboard/dist/assets/{McpRunDetailPage-DHI0F65P.js.map → McpRunDetailPage-CiAx_xyV.js.map} +1 -1
  85. package/dashboard/dist/assets/{McpRunsPage-C6-KpYCY.js → McpRunsPage-BpfvNRbE.js} +2 -2
  86. package/dashboard/dist/assets/{McpRunsPage-C6-KpYCY.js.map → McpRunsPage-BpfvNRbE.js.map} +1 -1
  87. package/dashboard/dist/assets/{NamespacePill-BeifzjUm.js → NamespacePill-CKp_9EaI.js} +2 -2
  88. package/dashboard/dist/assets/{NamespacePill-BeifzjUm.js.map → NamespacePill-CKp_9EaI.js.map} +1 -1
  89. package/dashboard/dist/assets/OperationsPage-DGKwUE6h.js +3 -0
  90. package/dashboard/dist/assets/OperationsPage-DGKwUE6h.js.map +1 -0
  91. package/dashboard/dist/assets/{OperatorDashboard-DLp9gCTA.js → OperatorDashboard-ha-05tgB.js} +2 -2
  92. package/dashboard/dist/assets/{OperatorDashboard-DLp9gCTA.js.map → OperatorDashboard-ha-05tgB.js.map} +1 -1
  93. package/dashboard/dist/assets/{PageHeader-BpeBHqyc.js → PageHeader-CDDpHpdv.js} +2 -2
  94. package/dashboard/dist/assets/{PageHeader-BpeBHqyc.js.map → PageHeader-CDDpHpdv.js.map} +1 -1
  95. package/dashboard/dist/assets/{PageHeaderWithStats-JXeUFa_g.js → PageHeaderWithStats-DIWH6fRv.js} +2 -2
  96. package/dashboard/dist/assets/{PageHeaderWithStats-JXeUFa_g.js.map → PageHeaderWithStats-DIWH6fRv.js.map} +1 -1
  97. package/dashboard/dist/assets/{PersonaDetailPage-DFv4Zwmq.js → PersonaDetailPage-DMH-D1ns.js} +2 -2
  98. package/dashboard/dist/assets/{PersonaDetailPage-DFv4Zwmq.js.map → PersonaDetailPage-DMH-D1ns.js.map} +1 -1
  99. package/dashboard/dist/assets/{PersonasPage-C52o87Zv.js → PersonasPage-YLjCcQcU.js} +2 -2
  100. package/dashboard/dist/assets/{PersonasPage-C52o87Zv.js.map → PersonasPage-YLjCcQcU.js.map} +1 -1
  101. package/dashboard/dist/assets/{ProcessDetailPage-CKCxXogl.js → ProcessDetailPage-W5_2FJHn.js} +2 -2
  102. package/dashboard/dist/assets/{ProcessDetailPage-CKCxXogl.js.map → ProcessDetailPage-W5_2FJHn.js.map} +1 -1
  103. package/dashboard/dist/assets/{ProcessesListPage-D1bxIy7-.js → ProcessesListPage-5f_2S9ER.js} +2 -2
  104. package/dashboard/dist/assets/{ProcessesListPage-D1bxIy7-.js.map → ProcessesListPage-5f_2S9ER.js.map} +1 -1
  105. package/dashboard/dist/assets/{RoleDetailPage-_MrbOGW_.js → RoleDetailPage-CuDTO13n.js} +3 -3
  106. package/dashboard/dist/assets/{RoleDetailPage-_MrbOGW_.js.map → RoleDetailPage-CuDTO13n.js.map} +1 -1
  107. package/dashboard/dist/assets/{RolePill-EocCXZh0.js → RolePill-C0hExOmI.js} +2 -2
  108. package/dashboard/dist/assets/{RolePill-EocCXZh0.js.map → RolePill-C0hExOmI.js.map} +1 -1
  109. package/dashboard/dist/assets/{RolesPage-ZVCkB4iF.js → RolesPage-McMYumsZ.js} +2 -2
  110. package/dashboard/dist/assets/{RolesPage-ZVCkB4iF.js.map → RolesPage-McMYumsZ.js.map} +1 -1
  111. package/dashboard/dist/assets/RunAsSelector-CC87e67k.js +2 -0
  112. package/dashboard/dist/assets/{RunAsSelector-BAqa1Tya.js.map → RunAsSelector-CC87e67k.js.map} +1 -1
  113. package/dashboard/dist/assets/{ScanCodesPage-b7WkFiy-.js → ScanCodesPage-Zk6Jorv_.js} +2 -2
  114. package/dashboard/dist/assets/{ScanCodesPage-b7WkFiy-.js.map → ScanCodesPage-Zk6Jorv_.js.map} +1 -1
  115. package/dashboard/dist/assets/ScanSchemeDetailPage-B79pya8o.js +2 -0
  116. package/dashboard/dist/assets/ScanSchemeDetailPage-B79pya8o.js.map +1 -0
  117. package/dashboard/dist/assets/ScanStationPage-BLlHMmd_.js +2 -0
  118. package/dashboard/dist/assets/{ScanStationPage-CPC9CdCR.js.map → ScanStationPage-BLlHMmd_.js.map} +1 -1
  119. package/dashboard/dist/assets/{ScopeBadge-H5dEqeHi.js → ScopeBadge-BBQvz4pj.js} +2 -2
  120. package/dashboard/dist/assets/{ScopeBadge-H5dEqeHi.js.map → ScopeBadge-BBQvz4pj.js.map} +1 -1
  121. package/dashboard/dist/assets/StatusBadge-BDeUwPtb.js +2 -0
  122. package/dashboard/dist/assets/StatusBadge-BDeUwPtb.js.map +1 -0
  123. package/dashboard/dist/assets/{StickyPagination-CgSzarlP.js → StickyPagination-CnJgQPU1.js} +2 -2
  124. package/dashboard/dist/assets/{StickyPagination-CgSzarlP.js.map → StickyPagination-CnJgQPU1.js.map} +1 -1
  125. package/dashboard/dist/assets/{StreamMessageDetail-B4E3S5RB.js → StreamMessageDetail-CU5wrqO_.js} +2 -2
  126. package/dashboard/dist/assets/{StreamMessageDetail-B4E3S5RB.js.map → StreamMessageDetail-CU5wrqO_.js.map} +1 -1
  127. package/dashboard/dist/assets/{SwimlaneTimeline-BkcjucMZ.js → SwimlaneTimeline-D5m-_zgy.js} +2 -2
  128. package/dashboard/dist/assets/{SwimlaneTimeline-BkcjucMZ.js.map → SwimlaneTimeline-D5m-_zgy.js.map} +1 -1
  129. package/dashboard/dist/assets/{TagInput-Ch5u6iPH.js → TagInput-BXxXs1JD.js} +2 -2
  130. package/dashboard/dist/assets/{TagInput-Ch5u6iPH.js.map → TagInput-BXxXs1JD.js.map} +1 -1
  131. package/dashboard/dist/assets/{TaskDetailPage-D7e8x2gX.js → TaskDetailPage-SvVSH39Q.js} +2 -2
  132. package/dashboard/dist/assets/{TaskDetailPage-D7e8x2gX.js.map → TaskDetailPage-SvVSH39Q.js.map} +1 -1
  133. package/dashboard/dist/assets/{TaskQueuePill-Bz146p-P.js → TaskQueuePill-BKGJBVZG.js} +2 -2
  134. package/dashboard/dist/assets/{TaskQueuePill-Bz146p-P.js.map → TaskQueuePill-BKGJBVZG.js.map} +1 -1
  135. package/dashboard/dist/assets/{TasksListPage-B4mxP9Ey.js → TasksListPage-BtpwvxkS.js} +2 -2
  136. package/dashboard/dist/assets/{TasksListPage-B4mxP9Ey.js.map → TasksListPage-BtpwvxkS.js.map} +1 -1
  137. package/dashboard/dist/assets/{TimeAgo-D6sbYsUO.js → TimeAgo-BPODA7Dm.js} +2 -2
  138. package/dashboard/dist/assets/{TimeAgo-D6sbYsUO.js.map → TimeAgo-BPODA7Dm.js.map} +1 -1
  139. package/dashboard/dist/assets/{TimestampCell-DFDf3NAT.js → TimestampCell-DEQXlxbH.js} +2 -2
  140. package/dashboard/dist/assets/{TimestampCell-DFDf3NAT.js.map → TimestampCell-DEQXlxbH.js.map} +1 -1
  141. package/dashboard/dist/assets/{ToolPill-sj8OkBB0.js → ToolPill-BY6zLSfA.js} +2 -2
  142. package/dashboard/dist/assets/{ToolPill-sj8OkBB0.js.map → ToolPill-BY6zLSfA.js.map} +1 -1
  143. package/dashboard/dist/assets/{ToolTestPanel-DbWw0-Le.js → ToolTestPanel-Ztc0pRSh.js} +2 -2
  144. package/dashboard/dist/assets/{ToolTestPanel-DbWw0-Le.js.map → ToolTestPanel-Ztc0pRSh.js.map} +1 -1
  145. package/dashboard/dist/assets/{TopicDetailPage-C6CPcvuO.js → TopicDetailPage-BmpEqg-Q.js} +4 -4
  146. package/dashboard/dist/assets/{TopicDetailPage-C6CPcvuO.js.map → TopicDetailPage-BmpEqg-Q.js.map} +1 -1
  147. package/dashboard/dist/assets/{TopicsPage-C8_XpeT2.js → TopicsPage-BVW5y6vE.js} +2 -2
  148. package/dashboard/dist/assets/{TopicsPage-C8_XpeT2.js.map → TopicsPage-BVW5y6vE.js.map} +1 -1
  149. package/dashboard/dist/assets/UserName-D915g7ba.js +2 -0
  150. package/dashboard/dist/assets/{UserName-CIoJvf_e.js.map → UserName-D915g7ba.js.map} +1 -1
  151. package/dashboard/dist/assets/WorkflowExecutionPage-CIl9ESgk.js +2 -0
  152. package/dashboard/dist/assets/WorkflowExecutionPage-CIl9ESgk.js.map +1 -0
  153. package/dashboard/dist/assets/{WorkflowPill-BcA7S3gI.js → WorkflowPill-qp5UF3-y.js} +2 -2
  154. package/dashboard/dist/assets/{WorkflowPill-BcA7S3gI.js.map → WorkflowPill-qp5UF3-y.js.map} +1 -1
  155. package/dashboard/dist/assets/{WorkflowsDashboard-y2L_zwnf.js → WorkflowsDashboard-DtkaGgdZ.js} +2 -2
  156. package/dashboard/dist/assets/{WorkflowsDashboard-y2L_zwnf.js.map → WorkflowsDashboard-DtkaGgdZ.js.map} +1 -1
  157. package/dashboard/dist/assets/{WorkflowsOverview-ChE1Mm3P.js → WorkflowsOverview-DANXhmXb.js} +2 -2
  158. package/dashboard/dist/assets/{WorkflowsOverview-ChE1Mm3P.js.map → WorkflowsOverview-DANXhmXb.js.map} +1 -1
  159. package/dashboard/dist/assets/{YamlWorkflowDetailPage-D0aY_inb.js → YamlWorkflowDetailPage-m6Ub7qtE.js} +2 -2
  160. package/dashboard/dist/assets/{YamlWorkflowDetailPage-D0aY_inb.js.map → YamlWorkflowDetailPage-m6Ub7qtE.js.map} +1 -1
  161. package/dashboard/dist/assets/{YamlWorkflowsPage-DJ0JitPs.js → YamlWorkflowsPage-5MOsxbLW.js} +2 -2
  162. package/dashboard/dist/assets/{YamlWorkflowsPage-DJ0JitPs.js.map → YamlWorkflowsPage-5MOsxbLW.js.map} +1 -1
  163. package/dashboard/dist/assets/{agents-Bu5Ly_ER.js → agents-DacpnIqz.js} +2 -2
  164. package/dashboard/dist/assets/{agents-Bu5Ly_ER.js.map → agents-DacpnIqz.js.map} +1 -1
  165. package/dashboard/dist/assets/{bots-Cb14wZ1Y.js → bots-El47Xy5a.js} +2 -2
  166. package/dashboard/dist/assets/{bots-Cb14wZ1Y.js.map → bots-El47Xy5a.js.map} +1 -1
  167. package/dashboard/dist/assets/{capabilities-DeHLk9JJ.js → capabilities-DGC__Aob.js} +2 -2
  168. package/dashboard/dist/assets/{capabilities-DeHLk9JJ.js.map → capabilities-DGC__Aob.js.map} +1 -1
  169. package/dashboard/dist/assets/{controlplane-YBZ3SbA6.js → controlplane-Bzx-qd8m.js} +2 -2
  170. package/dashboard/dist/assets/{controlplane-YBZ3SbA6.js.map → controlplane-Bzx-qd8m.js.map} +1 -1
  171. package/dashboard/dist/assets/{escalation-columns-CA9DQlhA.js → escalation-columns-BmY7BriY.js} +2 -2
  172. package/dashboard/dist/assets/{escalation-columns-CA9DQlhA.js.map → escalation-columns-BmY7BriY.js.map} +1 -1
  173. package/dashboard/dist/assets/{index-D5MSJsiW.js → index-B4ZNPgcz.js} +2 -2
  174. package/dashboard/dist/assets/{index-D5MSJsiW.js.map → index-B4ZNPgcz.js.map} +1 -1
  175. package/dashboard/dist/assets/index-BPK2cB4Q.js +6 -0
  176. package/dashboard/dist/assets/index-BPK2cB4Q.js.map +1 -0
  177. package/dashboard/dist/assets/{index-B0qNe7Ux.js → index-Bwlnpbpd.js} +2 -2
  178. package/dashboard/dist/assets/{index-B0qNe7Ux.js.map → index-Bwlnpbpd.js.map} +1 -1
  179. package/dashboard/dist/assets/{index-CQriisJy.js → index-CHwg51qz.js} +2 -2
  180. package/dashboard/dist/assets/{index-CQriisJy.js.map → index-CHwg51qz.js.map} +1 -1
  181. package/dashboard/dist/assets/index-CJV2pWNH.css +1 -0
  182. package/dashboard/dist/assets/{index-BaDimDGQ.js → index-Ce6ghhpn.js} +2 -2
  183. package/dashboard/dist/assets/{index-BaDimDGQ.js.map → index-Ce6ghhpn.js.map} +1 -1
  184. package/dashboard/dist/assets/{index-B4Nea96C.js → index-Cfw6FARc.js} +2 -2
  185. package/dashboard/dist/assets/{index-B4Nea96C.js.map → index-Cfw6FARc.js.map} +1 -1
  186. package/dashboard/dist/assets/{index-BAKroiNw.js → index-CoIh4ipz.js} +2 -2
  187. package/dashboard/dist/assets/{index-BAKroiNw.js.map → index-CoIh4ipz.js.map} +1 -1
  188. package/dashboard/dist/assets/index-Cqc7Wu5Y.js +3 -0
  189. package/dashboard/dist/assets/index-Cqc7Wu5Y.js.map +1 -0
  190. package/dashboard/dist/assets/index-DH_xm9UQ.js +2 -0
  191. package/dashboard/dist/assets/{index-chMUPSOd.js.map → index-DH_xm9UQ.js.map} +1 -1
  192. package/dashboard/dist/assets/{index-B7fE-rND.js → index-DYz57kr_.js} +2 -2
  193. package/dashboard/dist/assets/{index-B7fE-rND.js.map → index-DYz57kr_.js.map} +1 -1
  194. package/dashboard/dist/assets/{index-YUv7aNb4.js → index-DpsVlk5z.js} +2 -2
  195. package/dashboard/dist/assets/{index-YUv7aNb4.js.map → index-DpsVlk5z.js.map} +1 -1
  196. package/dashboard/dist/assets/{index-Ntul2ZC1.js → index-SU2xrnBD.js} +29 -28
  197. package/dashboard/dist/assets/index-SU2xrnBD.js.map +1 -0
  198. package/dashboard/dist/assets/{index-BRmgxeZM.js → index-ZtpEajtq.js} +3 -3
  199. package/dashboard/dist/assets/{index-BRmgxeZM.js.map → index-ZtpEajtq.js.map} +1 -1
  200. package/dashboard/dist/assets/{knowledge-B1HqYuB2.js → knowledge-k-5jr2BN.js} +2 -2
  201. package/dashboard/dist/assets/{knowledge-B1HqYuB2.js.map → knowledge-k-5jr2BN.js.map} +1 -1
  202. package/dashboard/dist/assets/{mcp-dhihqJpH.js → mcp-BEqxxlW9.js} +2 -2
  203. package/dashboard/dist/assets/{mcp-dhihqJpH.js.map → mcp-BEqxxlW9.js.map} +1 -1
  204. package/dashboard/dist/assets/{mcp-query-B_gkB7JK.js → mcp-query-qXTlQfc_.js} +2 -2
  205. package/dashboard/dist/assets/{mcp-query-B_gkB7JK.js.map → mcp-query-qXTlQfc_.js.map} +1 -1
  206. package/dashboard/dist/assets/{personas-Bw_OlfI6.js → personas-jJEDmBtg.js} +2 -2
  207. package/dashboard/dist/assets/{personas-Bw_OlfI6.js.map → personas-jJEDmBtg.js.map} +1 -1
  208. package/dashboard/dist/assets/{pipelines-BYwn0LXY.js → pipelines-BNPJh69x.js} +2 -2
  209. package/dashboard/dist/assets/{pipelines-BYwn0LXY.js.map → pipelines-BNPJh69x.js.map} +1 -1
  210. package/dashboard/dist/assets/{tasks-t6bPmJ7P.js → tasks-DhD71qXJ.js} +2 -2
  211. package/dashboard/dist/assets/{tasks-t6bPmJ7P.js.map → tasks-DhD71qXJ.js.map} +1 -1
  212. package/dashboard/dist/assets/{topics-Bgo9xw80.js → topics-CrXwwuW-.js} +2 -2
  213. package/dashboard/dist/assets/{topics-Bgo9xw80.js.map → topics-CrXwwuW-.js.map} +1 -1
  214. package/dashboard/dist/assets/{useEventHooks-BJbMbg_h.js → useEventHooks-DL7R0ASv.js} +2 -2
  215. package/dashboard/dist/assets/{useEventHooks-BJbMbg_h.js.map → useEventHooks-DL7R0ASv.js.map} +1 -1
  216. package/dashboard/dist/assets/{useNamespace-CaXJuSFG.js → useNamespace-ETqzJakA.js} +2 -2
  217. package/dashboard/dist/assets/{useNamespace-CaXJuSFG.js.map → useNamespace-ETqzJakA.js.map} +1 -1
  218. package/dashboard/dist/assets/{useYamlActivityEvents-B47LQrDk.js → useYamlActivityEvents-SqY67S-F.js} +2 -2
  219. package/dashboard/dist/assets/{useYamlActivityEvents-B47LQrDk.js.map → useYamlActivityEvents-SqY67S-F.js.map} +1 -1
  220. package/dashboard/dist/assets/{users-D0jvzUqW.js → users-DF8dTbOo.js} +2 -2
  221. package/dashboard/dist/assets/{users-D0jvzUqW.js.map → users-DF8dTbOo.js.map} +1 -1
  222. package/dashboard/dist/assets/{vendor-icons-BPsNpK3Y.js → vendor-icons-BgsXTN4h.js} +145 -140
  223. package/dashboard/dist/assets/vendor-icons-BgsXTN4h.js.map +1 -0
  224. package/dashboard/dist/assets/{workflows-DRoZRrMH.js → workflows-Bdke7fzx.js} +2 -2
  225. package/dashboard/dist/assets/{workflows-DRoZRrMH.js.map → workflows-Bdke7fzx.js.map} +1 -1
  226. package/dashboard/dist/assets/{yaml-workflows-BdhYyIef.js → yaml-workflows-UMxHYunb.js} +2 -2
  227. package/dashboard/dist/assets/{yaml-workflows-BdhYyIef.js.map → yaml-workflows-UMxHYunb.js.map} +1 -1
  228. package/dashboard/dist/index.html +3 -3
  229. package/docs/api/http/escalations.md +29 -0
  230. package/docs/dashboard.md +2 -0
  231. package/docs/events.md +1 -1
  232. package/docs/hitl/form.md +1 -0
  233. package/docs/hitl/x-lt-footer.md +6 -0
  234. package/docs/hitl/x-lt-list-schema.md +4 -2
  235. package/docs/hitl/x-lt-validation.md +62 -1
  236. package/docs/hitl-guide.md +3 -0
  237. package/package.json +1 -1
  238. package/dashboard/dist/assets/AvailableEscalationsPage-B8NjwwKQ.js +0 -2
  239. package/dashboard/dist/assets/AvailableEscalationsPage-B8NjwwKQ.js.map +0 -1
  240. package/dashboard/dist/assets/BotPicker-CnX8xfka.js +0 -2
  241. package/dashboard/dist/assets/CapabilitiesPage-DK7wGMFt.js +0 -2
  242. package/dashboard/dist/assets/CountdownTimer-BvQw_3WJ.js +0 -2
  243. package/dashboard/dist/assets/CountdownTimer-BvQw_3WJ.js.map +0 -1
  244. package/dashboard/dist/assets/CustomDurationPicker-D-iY1f4n.js +0 -2
  245. package/dashboard/dist/assets/CustomDurationPicker-D-iY1f4n.js.map +0 -1
  246. package/dashboard/dist/assets/DataTable-Bir0Xs1p.js.map +0 -1
  247. package/dashboard/dist/assets/McpQueryPage-3EXLX1Eq.js +0 -2
  248. package/dashboard/dist/assets/OperationsPage-BNW7uris.js +0 -3
  249. package/dashboard/dist/assets/OperationsPage-BNW7uris.js.map +0 -1
  250. package/dashboard/dist/assets/RunAsSelector-BAqa1Tya.js +0 -2
  251. package/dashboard/dist/assets/ScanSchemeDetailPage-BCsEgS-s.js +0 -2
  252. package/dashboard/dist/assets/ScanSchemeDetailPage-BCsEgS-s.js.map +0 -1
  253. package/dashboard/dist/assets/ScanStationPage-CPC9CdCR.js +0 -2
  254. package/dashboard/dist/assets/StatusBadge-DkgllZHv.js +0 -2
  255. package/dashboard/dist/assets/StatusBadge-DkgllZHv.js.map +0 -1
  256. package/dashboard/dist/assets/UserName-CIoJvf_e.js +0 -2
  257. package/dashboard/dist/assets/WorkflowExecutionPage-Bq3kSkRr.js +0 -2
  258. package/dashboard/dist/assets/WorkflowExecutionPage-Bq3kSkRr.js.map +0 -1
  259. package/dashboard/dist/assets/index-B5jxf81r.css +0 -1
  260. package/dashboard/dist/assets/index-BhurEB5s.js +0 -6
  261. package/dashboard/dist/assets/index-BhurEB5s.js.map +0 -1
  262. package/dashboard/dist/assets/index-Ntul2ZC1.js.map +0 -1
  263. package/dashboard/dist/assets/index-chMUPSOd.js +0 -2
  264. package/dashboard/dist/assets/index-uWUJXqGS.js +0 -3
  265. package/dashboard/dist/assets/index-uWUJXqGS.js.map +0 -1
  266. package/dashboard/dist/assets/vendor-icons-BPsNpK3Y.js.map +0 -1
@@ -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-Ntul2ZC1.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-SU2xrnBD.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="./assets/vendor-query-RUZdMvN6.js">
13
13
  <link rel="modulepreload" crossorigin href="./assets/vendor-react-CdqEC2zv.js">
14
- <link rel="modulepreload" crossorigin href="./assets/vendor-icons-BPsNpK3Y.js">
15
- <link rel="stylesheet" crossorigin href="./assets/index-B5jxf81r.css">
14
+ <link rel="modulepreload" crossorigin href="./assets/vendor-icons-BgsXTN4h.js">
15
+ <link rel="stylesheet" crossorigin href="./assets/index-CJV2pWNH.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="root"></div>
@@ -14,6 +14,8 @@ pending ──► claimed ──► resolved
14
14
 
15
15
  Claiming is implicit: `assigned_to` is set and `assigned_until` is set to a future timestamp. When the claim expires, the escalation becomes available again without any status change — it remains `pending`.
16
16
 
17
+ Admins can override a live claim without touching status: [bulk-assign](#bulk-assign-escalations) with `reassign: true` hands the claim to another user (publishes `claimed`), and [bulk-unassign](#bulk-unassign) returns it to the pool (publishes `released`). The `reassigned` event names the role move ([bulk-escalate](#bulk-escalate-to-role)) only.
18
+
17
19
  `cancelled` is a terminal state. A cancelled escalation cannot be claimed, resolved, or re-cancelled. When a workflow is terminated (`POST /api/workflows/:workflowId/terminate`), HotMesh automatically cancels any pending escalations tied to that workflow. Escalations can also be cancelled directly via `POST /api/escalations/:id/cancel`.
18
20
 
19
21
  ## Work-Surface Scope
@@ -621,6 +623,8 @@ POST /api/escalations/bulk-assign
621
623
 
622
624
  Assign multiple escalations to a specific user, by id-set or by query (exactly one). Superadmins can assign anyone. Admins can only assign to users who hold the escalation's role.
623
625
 
626
+ **Rows under a live claim are skipped** by a plain assign and counted in the response's `skipped` — assignment is claim-on-behalf, and an active claim wins. To take over live claims, pass `reassign: true` (ids form; admin/superadmin only): the takeover is one guarded statement, the displaced holder's in-flight resolve fails its claim assertion, and each taken row's `claimed` event carries `reassigned_from`.
627
+
624
628
  The query form is one atomic statement: selection and claim happen in the same UPDATE, so a row that re-parks between a search and an ids-assign is still captured. Use it whenever the population is describable by role + facets.
625
629
 
626
630
  **Request body:**
@@ -631,6 +635,7 @@ The query form is one atomic statement: selection and claim happen in the same U
631
635
  | `query` | `object` | | `{ role, facets? }` selector (query form); `role` is required, `facets` filter by metadata containment |
632
636
  | `targetUserId` | `string` | | User ID to assign the escalations to |
633
637
  | `durationMinutes` | `integer` | 30 | How long each assignment lasts |
638
+ | `reassign` | `boolean` | false | Also take over rows under a live claim (ids form only; requires admin/superadmin) |
634
639
 
635
640
  **Example request (ids form):**
636
641
 
@@ -656,6 +661,30 @@ The query form is one atomic statement: selection and claim happen in the same U
656
661
  { "error": "Target user does not hold the \"reviewer\" role" }
657
662
  ```
658
663
 
664
+ ## Bulk unassign
665
+
666
+ ```
667
+ POST /api/escalations/bulk-unassign
668
+ ```
669
+
670
+ Return claimed escalations to the available pool — the admin override of someone else's live claim (a holder returning their own item uses release). One guarded statement: unclaimed and terminal rows are skipped, and each returned row publishes a `released` event carrying `released_by` (the acting admin) and `unassigned_from` (the displaced holder).
671
+
672
+ **RBAC:** admin or superadmin (global escalation access).
673
+
674
+ **Request body:**
675
+
676
+ | Field | Type | Description |
677
+ |-------|------|-------------|
678
+ | `ids` | `string[]` | Escalation UUIDs to return to the pool |
679
+
680
+ **Response 200:**
681
+
682
+ ```json
683
+ { "unassigned": 2, "skipped": 1 }
684
+ ```
685
+
686
+ `skipped` counts rows that were unclaimed or terminal at call time.
687
+
659
688
  ## Bulk escalate to role
660
689
 
661
690
  ```
package/docs/dashboard.md CHANGED
@@ -339,6 +339,8 @@ The central queue for all escalation activity across every workflow.
339
339
  - **Metadata value affordances** — each metadata key/value row in the list carries a three-icon triad on hover: **filter** (filter the current role's queue to rows where the key equals this value), **search** (the same facet match across all roles), and **history** (open the entity's cross-queue interval timeline in the right panel — every station this value has moved through, with durations and gaps). Filter-present, search-present, history-past. The history affordance renders for string values, since the timeline's GIN containment match serves JSON-string facets.
340
340
  - **Rich list view** — when the list is scoped to exactly one role (`?role=<role>`) and that role owns a [list schema](#escalations-list-schema), a role-authored view renders in place of the table (the live item as a card, plus a load-on-demand history), with a **Table view** toggle back to the columns.
341
341
  - **Claim** — click the claim action to lock an escalation to your user. Only users with matching roles see pending escalations. The queue list and aggregate stats reflect `read_all` memberships — a member scoped to `read_self` lands directly on their own assigned item in user mode rather than browsing the full queue.
342
+ - **Bulk actions (admin)** — row checkboxes surface a selection bar with **Claim**, **Assign**, **Unassign**, **Escalate** (move to another role), and **Cancel**. Assign opens a modal to pick the target user and claim duration; rows under a live claim are skipped unless the modal's takeover checkbox (shown when the selection includes live claims) is checked, which reassigns them — admin/superadmin only. Unassign returns claimed rows to the available pool. The response reports how many rows were skipped. When the list is scoped to a single role, the Cancel button and its confirmation speak the role form's `x-lt-labels.cancel` vocabulary (`false` hides the verb).
343
+ - **Admin claim override (detail page)** — when an item is claimed by someone else, admins and superadmins see **Reassign…** (hand the claim to another user via the assign modal, takeover implied) and **Return to queue** (unassign) in the action bar.
342
344
  - **Resolve** — after claiming, submit a resolver payload. The form is pre-filled from the role's versioned `form_schema` field defaults and from the workflow's seeded `envelope.formDefaults` (reverse-mapped through each field's `x-lt-bind`). The dashboard maps the flat form to the nested payload via `x-lt-bind` and the submitted payload is stored as-is. Resolution triggers a workflow re-run with the resolver data injected. A `member` whose `write_scope` is `self` can resolve only items already assigned to them; `write_scope=none` is read-only.
343
345
  - **Side panel** — a slide-in beside the resolve form with switchable views, selected by the icon set at its top: **Help** (the form's `x-lt-help` markdown, `{{domain.path}}`-interpolated against the live record, or a state-aware hint such as "Claim this escalation to enable the form"), **Details** (status, role, priority, claim provenance, timestamps, and — for builders — identifier links), **AI Analysis** (what triage diagnosed and corrected — shown when AI is enabled and triage data is present), **Metadata** (the row's metadata values), **Context** (input envelope, escalation context, resolver payload), and **Record** (the raw escalation JSON, builders only). The panel and form share the width as a flex set — the form column narrows as the panel expands. It opens expanded on Help when the form carries `x-lt-help`, stays hidden otherwise, and the page-header panel button toggles it either way.
344
346
 
package/docs/events.md CHANGED
@@ -79,7 +79,7 @@ System families declare the fields they populate. Which fields exist is a functi
79
79
 
80
80
  `status` is a **per-family vocabulary**, not one global enum: workflow `started|in_progress|running|completed|failed`; task `created|in_progress|completed|needs_intervention|failed`; escalation `pending|claimed|released|resolved|cancelled|expired`.
81
81
 
82
- Escalation subjects carry the **role** (the queue) as the organizing token. Subscribe to one queue (`system.escalation.{role}.>`), one verb across queues (`system.escalation.*.*.created`), or one item across role hops (`system.escalation.*.{id}.>`). The role token is sanitized to subject-safe characters (`[A-Za-z0-9_-]`); a `reassigned` event publishes under **both** the departing and arriving role so either queue's subscribers observe the move.
82
+ User-level assignment changes travel as claim state: an admin reassign publishes `claimed` (with `reassigned_from` in the delta) and an unassign publishes `released` (with `released_by`) — `reassigned` names the ROLE move only. Escalation subjects carry the **role** (the queue) as the organizing token. Subscribe to one queue (`system.escalation.{role}.>`), one verb across queues (`system.escalation.*.*.created`), or one item across role hops (`system.escalation.*.{id}.>`). The role token is sanitized to subject-safe characters (`[A-Za-z0-9_-]`); a `reassigned` event publishes under **both** the departing and arriving role so either queue's subscribers observe the move.
83
83
 
84
84
  #### Escalation `data` — one wire shape
85
85
 
package/docs/hitl/form.md CHANGED
@@ -32,6 +32,7 @@ Declare `title` on every field whose key isn't already a readable label — it i
32
32
  | `number` | Number input |
33
33
  | `string` | Text input (default) |
34
34
  | `string` + `enum` | Dropdown select |
35
+ | `string`/`number` + `x-lt-options` | Dropdown select — options resolved from the escalation context (see [x-lt-validation.md](x-lt-validation.md#dynamic-select-options-x-lt-options)) |
35
36
  | `null` | Read-only "null" display |
36
37
  | `array` | Tag display (read-only) |
37
38
  | `object` | Nested section with recursive fields, or a widget (see [x-lt-widget.md](x-lt-widget.md)) |
@@ -50,6 +50,12 @@ you want to Send to Service? This removes the item from the work queue," and
50
50
  confirms with "Yes, Send to Service". The default label follows the same
51
51
  shape with "Cancel".
52
52
 
53
+ The label carries beyond the footer: when a list page is scoped to a single
54
+ role (`?role=`), the admin selection bar's Cancel button and its bulk
55
+ confirmation speak the same `x-lt-labels.cancel` — and `cancel: false` removes
56
+ the bulk verb there too. One authored word governs every surface that can
57
+ cancel the role's items.
58
+
53
59
  ## `x-lt-submit-on-claim` — the one-gesture claim
54
60
 
55
61
  When true, clicking Claim also resolves the escalation in the same gesture,
@@ -16,7 +16,7 @@ Every string is a markdown/text template run through the same `{{domain.path}}`
16
16
  | `x-lt-help` | schema | Optional markdown header, interpolated with the active row |
17
17
  | `x-lt-active` | schema | The live item card: `{ title, subtitle?, body?, fields?: [{ label, value }] }` |
18
18
  | `x-lt-history` | schema | History column: `{ row: { title, subtitle?, meta? }, limit?, status? }` |
19
- | `x-lt-columns` | schema | Column definitions for `facet-table` layout: `[{ label, value, format?, priority? }]` |
19
+ | `x-lt-columns` | schema | Column definitions for `facet-table` layout: `[{ label, value, format?, priority?, width? }]` |
20
20
  | `x-lt-group-by` | schema | `facet-board`: the `"domain.path"` whose value identifies each entity |
21
21
  | `x-lt-card` | schema | `facet-board`: the per-entity card — `{ title, state?, fields?: [{ label, value, format? }] }` |
22
22
  | `x-lt-row-action` | schema | The per-row action button: `{ action?, label?, durationMinutes? }` — see below |
@@ -38,7 +38,7 @@ Every layout carries a persistent action button — the active card's CTA, a tra
38
38
  }
39
39
  ```
40
40
 
41
- `claim` is one click: the row is claimed for the template's duration and the detail page opens already claimed — the fast path for working a queue. The button appears only on claimable rows (pending, no live claim window), and a rejected claim (someone else won the race) surfaces its message inline. `view` opens the detail page — for read-only templates where claiming from the list is wrong. Row and card clicks continue to navigate; the button is the deliberate gesture.
41
+ `claim` is one click: the row is claimed for the template's duration and the detail page opens already claimed — the fast path for working a queue. The button renders on every row for layout uniformity; on rows past the gesture (resolved, cancelled, or under a live claim) it shows disabled at half opacity, and a rejected claim (someone else won the race) surfaces its message inline. `view` opens the detail page — for read-only templates where claiming from the list is wrong. Row and card clicks continue to navigate; the button is the deliberate gesture.
42
42
 
43
43
  On My Escalations (`/escalations/queue`) every row is already held by the viewer, so a `claim` template renders as a View action there: the button opens the detail page with the default "View" label. Authored `view` actions keep their label.
44
44
 
@@ -102,6 +102,8 @@ Use when the queue contains many concurrent rows and the role's context is best
102
102
 
103
103
  A status dot precedes the first column automatically. ISO datetime values render as a readable relative date with a full-timestamp tooltip. Missing token values render as an em dash. Clicking any row navigates to the detail page. The table stands alone — `x-lt-help` and `x-lt-active` are ignored in this layout; totals live in the pagination bar.
104
104
 
105
+ Column widths follow the fixed-table model: a column with an authored `width` (any CSS width — `"40%"`, `"12rem"`) keeps it, and the rest share the remainder evenly. When no column declares a width, the first column gets 40% — the identity is nearly always the row's most important value.
106
+
105
107
  The table renders through the same engine as the platform's built-in tables: padded cells, a sticky header, and a card fold at narrow widths — **a table never scrolls horizontally, it folds**. Below the fold threshold each row becomes a console card: `priority: 1` columns form the card's title line, `priority: 2` columns fold into label/value pairs, and `priority: 3` columns are dropped. Undeclared, the first column is the identity and the rest fold — declare priorities when the author knows which columns matter at a glance.
106
108
 
107
109
  The seeded `print` role (ortho pipeline) is the reference example for this layout, including fold priorities.
@@ -93,6 +93,36 @@ When `envelope.min_score` is `60`, submitting a score of `45` blocks with "Minim
93
93
 
94
94
  ---
95
95
 
96
+ ## Dynamic Select Options (`x-lt-options`)
97
+
98
+ A select's option list can ride the escalation instead of the schema. The field-level token names a `"domain.path"`; the array of strings or numbers at that path becomes the field's options — one static role form, per-row legal values:
99
+
100
+ ```json
101
+ {
102
+ "properties": {
103
+ "left_quantity": {
104
+ "type": "number",
105
+ "default": 0,
106
+ "x-lt-options": "envelope.left_quantity_options"
107
+ },
108
+ "designation": {
109
+ "type": "string",
110
+ "x-lt-options": "envelope.return_stations"
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ When the envelope carries `left_quantity_options: [0, 1, 2, 3]`, the field renders as a dropdown offering exactly those values — an out-of-range answer is structurally impossible. The workflow mints only the small per-row array; the form itself stays on the role.
117
+
118
+ - A static `enum` takes precedence when both are present — the same static-over-dynamic rule as the bounds tokens.
119
+ - The declared `type` governs the value: a number-typed field emits the picked option as a number, a string-typed field as a string.
120
+ - While the current value is outside the option list (an empty init, options that shrank per-row), the select opens on an explicit disabled **Choose…** placeholder — never an implicit first option.
121
+ - A path that resolves to nothing (missing, empty array, no scalar entries) yields no options: the field renders as the plain input for its type and membership is not enforced for that submission.
122
+ - Membership is enforced on both sides of the wire: the dashboard constrains the choices, and an enforced role's server gate rejects a payload whose value is outside the row's resolved list with the canonical 422 (`Must be one of: 0, 1, 2, 3`).
123
+
124
+ ---
125
+
96
126
  ## Checklist Completion (`x-lt-require-all`)
97
127
 
98
128
  A checklist-widget field can require every item to be checked before submission:
@@ -143,6 +173,29 @@ The token is an array of groups; each group is an array of property names and en
143
173
 
144
174
  ---
145
175
 
176
+ ## Require a Combined Quantity (`x-lt-require-sum`)
177
+
178
+ For a group of **quantity** fields, `x-lt-require-any` is the wrong guard: `0` is an answer there, so counts defaulting to `0` vacuously satisfy the group. `x-lt-require-sum` reads the members as numbers and demands their sum reach a minimum — a Left quantity and a Right quantity can both default to `0`, and an all-zero submission still blocks:
179
+
180
+ ```json
181
+ {
182
+ "x-lt-require-sum": [{ "fields": ["left_quantity", "right_quantity"] }],
183
+ "properties": {
184
+ "left_quantity": { "type": "number", "title": "Left Quantity", "default": 0 },
185
+ "right_quantity": { "type": "number", "title": "Right Quantity", "default": 0 }
186
+ }
187
+ }
188
+ ```
189
+
190
+ The token is an array of groups; each group is `{ "fields": [...], "minimum": N }` and enforces independently. `minimum` defaults to `1` — the plain "at least one side must be positive" reading. Numbers contribute their value, numeric strings coerce, and everything else (empty, missing, non-numeric) contributes `0`.
191
+
192
+ - Visibility composes the same way as `x-lt-require-any`: a member hidden by `x-lt-showIf` (or naming no schema property) contributes nothing and is not demanded, and a group whose members are all hidden is waived.
193
+ - An unsatisfied group yields one violation on the group's first visible field: `Combined value of Left Quantity, Right Quantity must be at least 1` (member titles, falling back to keys).
194
+ - Composes with `required` and `x-lt-require-any` — each guard reports independently.
195
+ - The same pass runs on both sides of the wire — the dashboard panel blocks the submit, and an enforced role's server gate rejects a violating payload with the canonical 422.
196
+
197
+ ---
198
+
146
199
  ## Pattern Guard
147
200
 
148
201
  Apply a regular expression guard with `pattern`. If the input does not match, the field blocks submission. Provide `x-lt-pattern-error` for a human-readable error message; otherwise the generic "Invalid format" is shown.
@@ -163,7 +216,7 @@ Apply a regular expression guard with `pattern`. If the input does not match, th
163
216
 
164
217
  ## Dynamic Bounds — `"domain.path"` Resolution
165
218
 
166
- `x-lt-minimum`, `x-lt-maximum`, `x-lt-min-length`, and `x-lt-max-length` all accept a `"domain.path"` string. The value is resolved from the escalation context at the moment of submission — the same domain/path convention as `x-lt-showIf` and `x-lt-help` tokens.
219
+ `x-lt-minimum`, `x-lt-maximum`, `x-lt-min-length`, `x-lt-max-length`, and `x-lt-options` all accept a `"domain.path"` string. The value is resolved from the escalation context at the moment of submission — the same domain/path convention as `x-lt-showIf` and `x-lt-help` tokens.
167
220
 
168
221
  | Domain | Resolves against |
169
222
  |--------|-----------------|
@@ -216,3 +269,11 @@ The error panel updates in real-time as fields are corrected — fixing a field
216
269
  - `checks` — checklist widget with `x-lt-source: 'envelope.checklist_items'`
217
270
 
218
271
  The `quality-reviewer` role is seeded with two test escalations that carry different `min_score` and `max_notes_length` values so every dynamic bound is exercisable without code changes.
272
+
273
+ `examples/workflows/parameterized-form/` is the reference for per-row form parameterization:
274
+
275
+ - `left_quantity` / `right_quantity` — number selects with `x-lt-options` from `envelope.left_quantity_options` / `envelope.right_quantity_options`, both defaulting to `0`
276
+ - `designation` — string select with `x-lt-options` from `envelope.return_stations`
277
+ - `x-lt-require-sum` — the quantity pair must total at least 1
278
+
279
+ The `verdict-reviewer` role is seeded with two test escalations whose envelopes carry different quantity ranges and station lists, so the same role form offers different legal values per row.
@@ -103,6 +103,8 @@ Ordered as a learning path — each file adds one capability to the same form:
103
103
  | `x-lt-widget` | field | Rich control: `file-upload`, `code-editor`, `signature`, `rich-text`, `markdown`, `checklist`, `attachment` (alias `image`) |
104
104
  | `x-lt-source` | field | Data path for context-driven widgets: `"domain.path"` |
105
105
  | `x-lt-require-all` | field | Checklist completion guard — every item must be checked, except items declared `required: false` |
106
+ | `x-lt-require-any` | schema | At-least-one guard — each `string[]` group needs a value in one visible member; `0`/`false` count as answers |
107
+ | `x-lt-require-sum` | schema | Quantity-group guard — the numeric values of `{ fields, minimum? }` must total at least `minimum` (default 1) |
106
108
  | `x-lt-language` | field | Syntax hint for the `code-editor` widget |
107
109
  | `accept` | field | File-type filter for `file-upload` (e.g. `".pdf,.png"`) |
108
110
  | `x-lt-bind` | field | Path in the resolver payload (e.g. `"customer.email"`) |
@@ -110,6 +112,7 @@ Ordered as a learning path — each file adds one capability to the same form:
110
112
  | `x-lt-showIf` | field | Show field when a value is truthy at `domain.path`; prefix `!` to invert; `=VALUE` / `!=VALUE` compare the string form |
111
113
  | `x-lt-hide-if-empty` | field | `true` — suppress the field when its value is null, `""`, `false`, or `0` |
112
114
  | `x-lt-section` | field | Section group label |
115
+ | `x-lt-options` | field | Dynamic select options — resolves a `"domain.path"` to the field's option list; static `enum` wins |
113
116
  | `x-lt-minimum` | field | Dynamic lower bound — resolves a `"domain.path"` from the escalation context |
114
117
  | `x-lt-maximum` | field | Dynamic upper bound — resolves a `"domain.path"` from the escalation context |
115
118
  | `x-lt-min-length` | field | Dynamic minimum string length — resolves a `"domain.path"` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.14.1",
3
+ "version": "0.14.4",
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",
@@ -1,2 +0,0 @@
1
- import{j as e,a as f}from"./vendor-query-RUZdMvN6.js";import{u as Et,l as Ft,m as Xe,n as ze,p as _t,w as $t,o as Lt,q as Bt,r as Rt,s as zt,t as qt,v as Dt,x as It,y as Ut,i as Vt,z as Gt,A as Ht,B as Qt,E as Jt,G as Kt,H as Wt,I as Xt,K as Yt,L as Zt,M as es,O as ts,Q as ss,R as as}from"./index-Ntul2ZC1.js";import{i as ns}from"./task-queues-7-sHKPsN.js";import{f as rs}from"./useEventHooks-BJbMbg_h.js";import{X as te,ag as is,ah as ls,C as os,b as cs,ai as ds,aj as us,t as xs,s as ms,ak as hs,B as ps,al as qe,am as fs,Q as gs,P as bs,g as ys,an as js}from"./vendor-icons-BPsNpK3Y.js";import{u as pe,C as Ye,a as vs}from"./CustomDurationPicker-D-iY1f4n.js";import{m as Ns,E as Cs,a as ks}from"./escalation-columns-CA9DQlhA.js";import{i as ws,s as Ss,E as Ps}from"./CountdownTimer-BvQw_3WJ.js";import{u as Ms}from"./useFilterParams-crmlBw_l.js";import{u as Ze}from"./useDebouncedValue-C4P2jQuh.js";import{b as As}from"./api-path-u2Jf9QXS.js";import{D as Ts}from"./DataTable-Bir0Xs1p.js";import{S as Os}from"./StickyPagination-CgSzarlP.js";import{P as Es}from"./constants-BHkpVaqx.js";import{M as fe}from"./Modal-BU7No9NH.js";import{u as Fs}from"./users-D0jvzUqW.js";import{R as _s,a as $s}from"./RowActions-eYrzgQSj.js";import{L as Ls}from"./ListToolbar-BdZkpRMo.js";import{L as De,u as Bs,f as Rs,a as zs}from"./vendor-react-CdqEC2zv.js";import"./EntityTimelinePanel-nCgWdmpK.js";import"./FilterBar-DR4cJvTB.js";import"./PriorityBadge-BETdj4M-.js";import"./RolePill-EocCXZh0.js";import"./WorkflowPill-BcA7S3gI.js";import"./StatusBadge-DkgllZHv.js";import"./EmptyState-lpUFYfun.js";const qs=["<","<=",">",">=","="],Ds=["priority","created_at","updated_at","status","role"],z="input text-xs py-1",Ie="select text-xs py-1",Z="text-text-tertiary hover:text-text-primary transition-colors";function Ue(t){return t==="true"?!0:t==="false"?!1:t.trim()!==""&&!Number.isNaN(Number(t))?Number(t):t}const Is=t=>Object.entries(t??{}).map(([s,l])=>({key:s,value:String(l)})),Us=t=>(t??[]).map(s=>{const[l,i]=Object.entries(s)[0]??["",""];return{key:l,value:String(i)}});function R({title:t,hint:s,children:l}){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}),s&&e.jsx("span",{className:"text-2xs font-mono text-text-tertiary/70",children:s})]}),l]})}function ee({value:t,onChange:s,placeholder:l}){return e.jsx("input",{list:"lt-facet-keys",className:`${z} w-40`,placeholder:l,value:t,onChange:i=>s(i.target.value)})}function Vs({value:t,onChange:s,facetKeys:l=[],search:i="",onSearchChange:p}){const m=Is(t.facets),h=Us(t.block),d=t.range??[],x=t.exists??[],g=t.orderBy??[],C=r=>{const u={};for(const o of r)o.key&&(u[o.key]=Ue(o.value));s({...t,facets:Object.keys(u).length?u:void 0})},S=r=>{const u=r.filter(o=>o.key).map(o=>({[o.key]:Ue(o.value)}));s({...t,block:u.length?u:void 0})},P=r=>s({...t,range:r.length?r:void 0}),j=r=>s({...t,exists:r.length?r:void 0}),k=r=>s({...t,orderBy:r.length?r:void 0});return e.jsxs("div",{className:"text-xs",children:[e.jsx("datalist",{id:"lt-facet-keys",children:l.map(r=>e.jsx("option",{value:r},r))}),e.jsxs("datalist",{id:"lt-sort-fields",children:[Ds.map(r=>e.jsx("option",{value:r},r)),l.map(r=>e.jsx("option",{value:`metadata.${r}`},r))]}),p&&e.jsx(R,{title:"Match id",hint:"id · workflow · origin",children:e.jsx("input",{className:`${z} w-full`,placeholder:"Exact escalation, workflow, or origin id…",value:i,onChange:r=>p(r.target.value)})}),e.jsx(R,{title:"Has facet",hint:"metadata @>",children:[...m,{key:"",value:""}].map((r,u)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(ee,{value:r.key,placeholder:"key",onChange:o=>{const c=[...m];c[u]={...r,key:o},C(c)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${z} w-40`,placeholder:"value",value:r.value,onChange:o=>{const c=[...m];c[u]={...r,value:o.target.value},C(c)}}),u<m.length&&e.jsx("button",{className:Z,onClick:()=>C(m.filter((o,c)=>c!==u)),children:"×"})]},u))}),e.jsx(R,{title:"Range",hint:"numeric",children:[...d,{facet:"",op:"<=",value:0}].map((r,u)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(ee,{value:r.facet,placeholder:"numeric facet",onChange:o=>{const c=[...d];c[u]={...r,facet:o},P(c.filter(a=>a.facet))}}),e.jsx("select",{className:Ie,value:r.op,onChange:o=>{const c=[...d];c[u]={...r,op:o.target.value},P(c.filter(a=>a.facet))},children:qs.map(o=>e.jsx("option",{value:o,children:o},o))}),e.jsx("input",{type:"number",className:`${z} w-24`,value:r.value,onChange:o=>{const c=[...d];c[u]={...r,value:Number(o.target.value)},P(c.filter(a=>a.facet))}}),u<d.length&&e.jsx("button",{className:Z,onClick:()=>P(d.filter((o,c)=>c!==u)),children:"×"})]},u))}),e.jsx(R,{title:"Has key",hint:"metadata ? key",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[x.map(r=>e.jsxs("span",{className:"flex items-center gap-1 rounded bg-accent/15 px-1.5 py-0.5 text-accent",children:[r,e.jsx("button",{className:"text-accent/70 hover:text-accent",onClick:()=>j(x.filter(u=>u!==r)),children:"×"})]},r)),e.jsx(ee,{value:"",placeholder:"+ key",onChange:r=>{r&&!x.includes(r)&&j([...x,r])}})]})}),e.jsx(R,{title:"Exclude",hint:"NOT @>",children:[...h,{key:"",value:""}].map((r,u)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(ee,{value:r.key,placeholder:"key",onChange:o=>{const c=[...h];c[u]={...r,key:o},S(c)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${z} w-40`,placeholder:"value",value:r.value,onChange:o=>{const c=[...h];c[u]={...r,value:o.target.value},S(c)}}),u<h.length&&e.jsx("button",{className:Z,onClick:()=>S(h.filter((o,c)=>c!==u)),children:"×"})]},u))}),e.jsx(R,{title:"Sort by",children:[...g,{field:"",direction:"asc"}].map((r,u)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx("input",{list:"lt-sort-fields",className:`${z} w-44`,placeholder:"column or metadata.key",value:r.field,onChange:o=>{const c=[...g];c[u]={...r,field:o.target.value},k(c.filter(a=>a.field))}}),e.jsxs("select",{className:Ie,value:r.direction??"asc",onChange:o=>{const c=[...g];c[u]={...r,direction:o.target.value},k(c.filter(a=>a.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:!!r.numeric,onChange:o=>{const c=[...g];c[u]={...r,numeric:o.target.checked},k(c.filter(a=>a.field))}}),"num"]}),u<g.length&&e.jsx("button",{className:Z,onClick:()=>k(g.filter((o,c)=>c!==u)),children:"×"})]},u))})]})}function Gs({value:t,onChange:s,facetKeys:l,search:i,onSearchChange:p,activeFacetCount:m,onClear:h,onClose:d}){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:[m>0&&e.jsx("button",{onClick:h,className:"text-2xs text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"}),e.jsx("button",{onClick:d,className:"p-1 rounded hover:bg-surface-hover text-text-tertiary hover:text-text-primary transition-colors",title:"Close",children:e.jsx(te,{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(Vs,{value:t,onChange:s,facetKeys:l,search:i,onSearchChange:p})]})]})}const Ve="created_at";function me(t){return t.replace(/^metadata\./,"")}function Hs({orderBy:t,onChange:s}){const l=t==null?void 0:t[0],i=(l==null?void 0:l.field)??Ve,p=(l==null?void 0:l.direction)??"desc",m=i===Ve,h=d=>s([{...l??{},field:i,direction:d}]);return e.jsxs("div",{className:"flex items-center gap-1.5",children:[!m&&e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full border border-accent/25 bg-accent/8 px-2 py-0.5 text-2xs font-medium text-accent/90",children:[e.jsx("span",{className:"text-text-quaternary",children:"sort"}),e.jsx("span",{className:"font-mono max-w-[120px] truncate",title:i,children:me(i)}),e.jsx("button",{onClick:()=>s(void 0),className:"ml-0.5 -mr-0.5 flex items-center text-text-quaternary hover:text-status-error transition-colors","aria-label":"Reset sort to created date",children:e.jsx(te,{className:"w-2.5 h-2.5"})})]}),e.jsxs("div",{className:"flex items-center rounded overflow-hidden border border-surface-border",role:"radiogroup","aria-label":"Sort direction",children:[e.jsx("button",{type:"button",role:"radio","aria-checked":p==="desc",onClick:()=>h("desc"),className:`px-1.5 py-1 transition-colors ${p==="desc"?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:m?"Newest first":`${me(i)} descending`,children:e.jsx(is,{className:"w-3.5 h-3.5"})}),e.jsx("button",{type:"button",role:"radio","aria-checked":p==="asc",onClick:()=>h("asc"),className:`px-1.5 py-1 border-l border-surface-border transition-colors ${p==="asc"?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:m?"Oldest first":`${me(i)} ascending`,children:e.jsx(ls,{className:"w-3.5 h-3.5"})})]})]})}const Qs=t=>t.isPriorityPending||t.isClaimPending||t.isAssignPending||t.isTriagePending||t.isCancelPending,he="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",Ge=`${he} appearance-none cursor-pointer`,Js="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 Ks(t){var d;const s=Qs(t),l=pe(),{data:i}=Et(),p=Ft(),m=p!==null?p:((d=i==null?void 0:i.ai)==null?void 0:d.enabled)===!0,h=t.selectedCount>0;return e.jsx("div",{className:`grid transition-all duration-200 ease-in-out ${h?"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:x=>{x.target.value&&(t.onSetPriority(parseInt(x.target.value)),x.target.value="")},disabled:s,className:Ge,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Priority…"}),Es.map(x=>e.jsx("option",{value:x.value,children:x.label},x.value))]}),e.jsxs("select",{onChange:x=>{x.target.value&&(t.onClaim(parseInt(x.target.value)),x.target.value="")},disabled:s,className:Ge,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Claim for…"}),l.map(x=>e.jsx("option",{value:x.value,children:x.label},x.value))]}),e.jsx("button",{onClick:t.onAssign,disabled:s,className:he,children:t.isAssignPending?"Assigning…":"Assign to…"}),m&&e.jsx("button",{onClick:t.onTriage,disabled:s,className:he,children:t.isTriagePending?"Triaging…":"Triage"}),e.jsx("button",{onClick:t.onCancel,disabled:s,className:Js,children:t.isCancelPending?"Cancelling…":"Cancel"}),e.jsx("div",{className:"flex-1"}),s&&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 Ws({open:t,onClose:s,selectedCount:l,selectedRoles:i,onSubmit:p,isPending:m}){const{isSuperAdmin:h}=Xe(),d=pe(),[x,g]=f.useState("user"),[C,S]=f.useState(null),[P,j]=f.useState(""),[k,r]=f.useState("30"),[u,o]=f.useState(0),c=f.useCallback(y=>o(y),[]),a=!h&&i.length===1?i[0]:void 0,N=Ze(P,250),{data:w,isLoading:M}=Fs({role:a,status:"active",search:N.trim()||void 0,limit:200}),A=(w==null?void 0:w.users)??[],T=()=>{g("user"),S(null),j(""),r("30"),o(0),s()},O=y=>{S(y),g("duration")},q=()=>{g("user")},D=()=>{if(!C)return;const y=k==="custom"?u:parseInt(k);!y||y<=0||p(C.id,y)};return e.jsx(fe,{open:t,onClose:T,title:"Assign Escalations",children:e.jsxs("div",{className:"space-y-4",children:[x==="user"&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Select a user to assign"," ",e.jsx("span",{className:"font-medium text-text-primary",children:l})," ","escalation(s) to:"]}),e.jsx("input",{type:"text",value:P,onChange:y=>j(y.target.value),placeholder:"Search by name or email...",className:"input text-xs w-full",autoFocus:!0}),e.jsxs("div",{className:"max-h-60 overflow-y-auto border border-surface-border rounded-lg divide-y divide-surface-border",children:[M&&e.jsx("p",{className:"text-xs text-text-tertiary p-3",children:"Loading users..."}),!M&&A.length===0&&e.jsx("p",{className:"text-xs text-text-tertiary p-3",children:"No users found"}),A.map(y=>e.jsxs("button",{onClick:()=>O(y),className:"w-full text-left px-3 py-2 hover:bg-surface-hover transition-colors",children:[e.jsx("p",{className:"text-xs font-medium text-text-primary",children:y.display_name||y.external_id}),y.email&&e.jsx("p",{className:"text-2xs text-text-tertiary",children:y.email})]},y.id))]}),e.jsx("div",{className:"flex justify-end pt-2",children:e.jsx("button",{onClick:T,className:"btn-secondary text-xs",children:"Cancel"})})]}),x==="duration"&&C&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Assign to"," ",e.jsx("span",{className:"font-medium text-text-primary",children:C.display_name||C.external_id})," ","for:"]}),e.jsxs("select",{value:k,onChange:y=>{r(y.target.value),o(0)},className:"select w-full text-sm",children:[d.map(y=>e.jsx("option",{value:y.value,children:y.label},y.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),k==="custom"&&e.jsx(Ye,{onChange:c,autoFocus:!0}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:q,className:"btn-secondary text-xs",children:"Back"}),e.jsx("button",{onClick:D,disabled:m,className:"btn-primary text-xs",children:m?"Assigning...":"Assign"})]})]})]})})}function Xs({open:t,onClose:s,selectedCount:l,onSubmit:i,isPending:p}){const[m,h]=f.useState(""),d=()=>{i(m||void 0)};return e.jsx(fe,{open:t,onClose:s,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:l})," 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:m,onChange:x=>h(x.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:s,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:d,disabled:p,className:"btn-primary text-xs",children:p?"Submitting...":"Submit for Triage"})]})]})})}function G(t,s,l){return i=>{t.mutate(i,{onSuccess:()=>{s(),l==null||l()}})}}function Ys(t){const s=()=>[...t.selectedIds];return{handleSetPriority:d=>{G(t.setPriority,t.clearSelection)({ids:s(),priority:d})},handleBulkClaim:d=>{G(t.bulkClaim,t.clearSelection)({ids:s(),durationMinutes:d})},handleBulkTriage:d=>{G(t.bulkTriage,t.clearSelection,t.closeTriageModal)({ids:s(),hint:d})},handleBulkAssign:(d,x)=>{G(t.bulkAssign,t.clearSelection,t.closeAssignModal)({ids:s(),targetUserId:d,durationMinutes:x})},handleBulkCancel:()=>{G(t.bulkCancel,t.clearSelection,t.closeCancelModal)({ids:s()})}}}function Zs({claimTarget:t,onClose:s,claimDuration:l,onDurationChange:i,claimDurations:p,onCustomClaimChange:m,onClaim:h,isPending:d}){return e.jsx(fe,{open:!!t,onClose:s,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:l,onChange:x=>{i(x.target.value)},className:"select w-full text-sm",children:[p.map(x=>e.jsx("option",{value:x.value,children:x.label},x.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),l==="custom"&&e.jsx(Ye,{onChange:m,autoFocus:!0}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:s,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:h,className:"btn-primary text-xs",disabled:d,children:d?"Claiming...":"Claim"})]})]})})}const et={pending:"--lt-status-queued-graphic",claimed:"--lt-status-claimed-graphic",resolved:"--lt-status-success-graphic",cancelled:"--lt-text-quaternary",expired:"--lt-text-tertiary"},tt="--lt-text-quaternary";function ea(t){return et[t]??tt}const H=Object.fromEntries(Object.entries(et).map(([t,s])=>[t,`rgb(var(${s}))`])),He=40,ta=64,sa=24,Qe=3;function st(t){return t<6e4?`${Math.round(t/1e3)}s`:t<36e5?`${Math.round(t/6e4)}m`:t<864e5?`${(t/36e5).toFixed(1)}h`:`${(t/864e5).toFixed(1)}d`}function Je(t){const s=Date.now()-t;return s<6e4?"just now":s<36e5?`${Math.round(s/6e4)}m ago`:s<864e5?`${Math.round(s/36e5)}h ago`:`${Math.round(s/864e5)}d ago`}function Ke(t){return t.replace(/-/g," ").replace(/\b\w/g,s=>s.toUpperCase())}function aa(t,s){return t?[...s.filter(i=>i in t),...Object.keys(t).filter(i=>!s.includes(i))].map(i=>[i,t[i]]):[]}function na({e:t}){const s=t.endMs-t.startMs;if(s<=0)return null;const l=H.pending,i=H.claimed,p=t.status==="cancelled"||t.status==="expired"?H.cancelled:H.resolved;let m=100,h=0,d=0;return t.claimedMs!==null?(m=Math.max(0,Math.min(100,(t.claimedMs-t.startMs)/s*100)),t.isOpen?h=100-m:(h=Math.max(0,Math.min(100-m,(t.endMs-t.claimedMs)/s*100)),d=Math.max(0,100-m-h))):t.isOpen||(d=100,m=0),e.jsxs("div",{className:"mt-2 h-0.5 rounded-full overflow-hidden flex bg-surface-sunken",children:[m>0&&e.jsx("div",{style:{width:`${m}%`,backgroundColor:l,opacity:.6}}),h>0&&e.jsx("div",{style:{width:`${h}%`,backgroundColor:i,opacity:.6}}),d>0&&e.jsx("div",{style:{width:`${d}%`,backgroundColor:p,opacity:.6}})]})}function ra({gapMs:t,heightPx:s}){return e.jsx("div",{className:"relative flex items-center justify-center",style:{height:s},children:t>=6e4&&e.jsx("span",{className:"text-2xs text-text-quaternary font-mono bg-surface px-2 relative z-10",children:st(t)})})}function We({e:t,highlightKeys:s,onRowClick:l}){const[i,p]=f.useState(!1),m=H[t.displayStatus]??`rgb(var(${tt}))`,h=aa(t.metadata,s),d=i?h:h.slice(0,Qe),x=h.length-Qe;return e.jsxs("div",{className:"cursor-pointer max-w-[460px] min-w-[260px] w-full bg-surface-raised rounded-lg shadow-sm border border-surface-border/60 px-3.5 pt-2.5 pb-2 hover:shadow-md hover:border-surface-border transition-all duration-150",style:{borderTopWidth:"3px",borderTopColor:m},onClick:()=>l==null?void 0:l(t),children:[e.jsxs("div",{className:"flex items-baseline gap-2 mb-1.5",children:[e.jsx("span",{className:"text-2xs font-bold uppercase tracking-widest text-text-quaternary shrink-0",children:Ke(t.role)}),e.jsxs("span",{className:"text-xs font-semibold text-text-primary truncate",title:t.type,children:[t.type,t.subtype&&t.subtype!==t.type&&t.subtype!==""&&e.jsxs("span",{className:"font-normal text-text-tertiary",children:[" · ",t.subtype]})]})]}),d.length>0&&e.jsxs("div",{className:"border-t border-surface-border/40 pt-1 space-y-px",children:[d.map(([g,C])=>{const S=String(C),P=s.includes(g);return e.jsxs("div",{className:"group/row flex items-center gap-1.5 -mx-1 px-1 py-[2px] rounded",children:[e.jsx("span",{className:`shrink-0 w-[60px] text-2xs font-mono uppercase tracking-wide truncate ${P?"text-accent":"text-text-quaternary"}`,title:g,children:g}),e.jsx("span",{className:`flex-1 min-w-0 text-2xs font-medium truncate ${P?"text-text-primary":"text-text-tertiary"}`,title:S,children:S}),e.jsxs("span",{className:"flex items-center gap-px shrink-0 opacity-0 group-hover/row:opacity-100 transition-opacity",children:[e.jsx(De,{to:ze(g,C,t.role),className:"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors",title:`Filter ${Ke(t.role)}: ${g} = ${S}`,onClick:j=>j.stopPropagation(),children:e.jsx(ds,{className:"w-2.5 h-2.5"})}),e.jsx(De,{to:ze(g,C),className:"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors",title:`Search all: ${g} = ${S}`,onClick:j=>j.stopPropagation(),children:e.jsx(us,{className:"w-2.5 h-2.5"})})]})]},g)}),x>0&&e.jsx("button",{className:"flex items-center gap-0.5 text-2xs text-text-quaternary hover:text-accent transition-colors mt-0.5 -mx-1 px-1 py-px",onClick:g=>{g.stopPropagation(),p(C=>!C)},children:i?e.jsxs(e.Fragment,{children:[e.jsx(xs,{className:"w-2.5 h-2.5"})," less"]}):e.jsxs(e.Fragment,{children:[e.jsx(ms,{className:"w-2.5 h-2.5"})," ",x," more"]})})]}),e.jsx(na,{e:t})]})}function ia({escalations:t,highlightKeys:s=[],onRowClick:l,total:i,page:p,totalPages:m,onPageChange:h}){var o,c;const d=Date.now(),g=t.map(a=>{const N=new Date(a.created_at).getTime(),w=a.resolved_at?new Date(a.resolved_at).getTime():null,M=a.claimed_at?new Date(a.claimed_at).getTime():null,A=!w&&a.status!=="cancelled"&&a.status!=="expired",T=w??(A?d:N+3e4),O=a.status==="pending"&&ws(a)?"claimed":a.status;return{...a,startMs:N,claimedMs:M,endMs:T,isOpen:A,displayStatus:O}});if(g.length===0)return e.jsx("p",{className:"mt-12 text-center text-sm text-text-tertiary",children:"No escalations matched."});const C=g.length,P=Math.max(Math.abs((((o=g[C-1])==null?void 0:o.startMs)??0)-(((c=g[0])==null?void 0:c.startMs)??0)),1)/Math.max(C-1,1),j=ta/Math.max(P,1),r=new Set(g.map(a=>new Date(a.startMs).toDateString())).size>1;function u(a){const N=new Date(a),w=N.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});return r?N.toLocaleDateString([],{month:"short",day:"numeric"})+" "+w:w}return e.jsxs("div",{className:"mt-4 pb-24",children:[e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"absolute left-1/2 -translate-x-px inset-y-0 w-px bg-surface-border/80"}),g.map((a,N)=>{const w=g[N-1],M=w?Math.abs(a.startMs-w.startMs):null,A=M!==null?Math.max(sa,Math.round(M*j)):0,T=N%2===0,O=ea(a.displayStatus),q=`rgb(var(${O}))`,D=a.endMs-a.startMs,y=a.isOpen?Je(a.startMs):`${Je(a.startMs)} · ${st(D)}`;return e.jsxs("div",{children:[N>0&&e.jsx(ra,{gapMs:M,heightPx:A}),e.jsxs("div",{className:"flex items-center",children:[e.jsx("div",{className:"flex-1 flex justify-end items-center",children:T?e.jsxs("div",{className:"flex items-center",children:[e.jsx(We,{e:a,highlightKeys:s,onRowClick:l}),e.jsx("div",{className:"flex-shrink-0 h-px bg-surface-border/70",style:{width:He}})]}):e.jsx("span",{className:"text-2xs text-text-quaternary font-mono tabular-nums pr-3",children:y})}),e.jsx("div",{className:"relative z-10 flex-shrink-0 w-3.5 h-3.5 rounded-full border-2 border-surface cursor-pointer transition-all duration-150 hover:scale-[1.5]",style:{backgroundColor:q,boxShadow:`0 0 0 3px rgb(var(${O}) / 0.16), 0 1px 3px rgb(var(${O}) / 0.19)`},onClick:()=>l==null?void 0:l(a)}),e.jsx("div",{className:"flex-1 flex justify-start items-center",children:T?e.jsx("span",{className:"text-2xs text-text-quaternary font-mono tabular-nums pl-3",children:y}):e.jsxs("div",{className:"flex items-center",children:[e.jsx("div",{className:"flex-shrink-0 h-px bg-surface-border/70",style:{width:He}}),e.jsx(We,{e:a,highlightKeys:s,onRowClick:l})]})})]}),e.jsx("div",{className:"flex justify-center relative z-10 mt-0.5",children:e.jsx("span",{className:"text-2xs text-text-quaternary font-mono tabular-nums bg-surface px-1.5",children:u(a.startMs)})})]},a.id)})]}),m>1&&e.jsxs("div",{className:"sticky bottom-0 z-20 bg-surface/95 backdrop-blur-sm border-t border-surface-border -mx-page-x px-page-x pt-2 pb-4 flex items-center justify-between mt-10",children:[e.jsxs("span",{className:"text-2xs text-text-tertiary",children:["Page ",e.jsx("span",{className:"font-medium text-text-secondary",children:p})," ","of ",e.jsx("span",{className:"font-medium text-text-secondary",children:m})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>h(p-1),disabled:p<=1,className:"p-1.5 rounded hover:bg-surface-hover disabled:opacity-30 text-text-tertiary hover:text-text-primary transition-colors disabled:cursor-not-allowed",children:e.jsx(os,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>h(p+1),disabled:p>=m,className:"p-1.5 rounded hover:bg-surface-hover disabled:opacity-30 text-text-tertiary hover:text-text-primary transition-colors disabled:cursor-not-allowed",children:e.jsx(cs,{className:"w-4 h-4"})})]})]})]})}function Fa(){var Ee,Fe,_e,$e,Le,Be,Re;const t=Bs(),{filters:s,setFilter:l,pagination:i}=Ms({filters:{role:"",type:"",priority:"",status:"available",search:""}});rs({role:s.role||null,verbs:["created","claimed"]});const p=Ze(s.search,300),m=pe(),[h,d]=f.useState(null),[x,g]=f.useState("30"),[C,S]=f.useState(0),P=f.useCallback(n=>S(n),[]),[j,k]=f.useState(new Set),[r,u]=f.useState(!1),[o,c]=Rs(),a=f.useMemo(()=>_t(o),[o]),N=f.useCallback(n=>{c(b=>{const v=new URLSearchParams(b);return $t(v,n),v.delete("page"),v})},[c]),{data:w}=Lt(r),M=Bt(a)+(s.search?1:0),A="facet-query",{setPanel:T,closePanel:O,open:q,ownerKey:D}=Rt();f.useEffect(()=>{if(!r){O(A);return}T(e.jsx(Gs,{value:a,onChange:N,facetKeys:(w==null?void 0:w.keys)??[],search:s.search??"",onSearchChange:n=>l("search",n),activeFacetCount:M,onClear:()=>{N({}),l("search","")},onClose:()=>u(!1)}),{width:420,key:A})},[r,a,N,w,s.search,l,M,T,O]);const y=q&&D===A,se=f.useRef(!1);f.useEffect(()=>{if(y){se.current=!0;return}se.current&&(se.current=!1,u(!1))},[y]);const[at,ae]=f.useState(!1),[nt,ne]=f.useState(!1),[rt,re]=f.useState(!1),it=f.useCallback(n=>N({...a,orderBy:n}),[a,N]),Q=zs(),{data:J}=zt(),ge=qt(),lt=f.useCallback(()=>{var v;const n=window.prompt("Pin label:");if(!(n!=null&&n.trim()))return;const b=((v=J==null?void 0:J.preferences)==null?void 0:v.pinnedViews)??[];ge.mutate({pinnedViews:[...b,{id:Dt(),label:n.trim(),url:Q.pathname+Q.search,badge:!0}]})},[Q.pathname,Q.search,J,ge]),{canBulk:ot}=It(),{kiosk:ie}=Ut(),be=a.facets?Object.keys(a.facets):[],le=o.get("view"),ye=f.useCallback(n=>{c(b=>{const v=new URLSearchParams(b);return n?v.set("view",n):v.delete("view"),v},{replace:!0})},[c]),_=le==="timeline",ct=f.useCallback(n=>{const{[n]:b,...v}=a.facets??{};N({...a,facets:Object.keys(v).length>0?v:void 0})},[a,N]),je=Vt(),ve=Gt(),Ne=Ht(),oe=Qt(),ce=Jt(),K=Kt(),{data:de}=Wt(),{data:$}=Xt(),{data:ue}=Yt(),{user:W,isSuperAdmin:dt,hasRoleType:ut}=Xe(),Ce=dt||ut("admin"),ke=f.useMemo(()=>new Set(((W==null?void 0:W.roles)??[]).map(n=>n.role)),[W]),xt=f.useMemo(()=>{const n=($==null?void 0:$.roles)??[];return(Ce?n:n.filter(v=>ke.has(v.role)&&!ns(v.role))).map(v=>({value:v.role,label:Zt(v)})).sort((v,Ot)=>v.label.localeCompare(Ot.label))},[$,Ce,ke]);f.useEffect(()=>{k(new Set)},[s.role,s.type,s.priority,s.status,p,i.page,i.pageSize]);const I=s.status||"",U=I==="available",xe=I==="claimed",we=xe?"pending":I==="resolved"?"resolved":I==="cancelled"?"cancelled":I==="expired"?"expired":void 0,L=s.role||(((Ee=a.roles)==null?void 0:Ee.length)===1?a.roles[0]:null),Se=es(L??"",void 0,!!L),V=((Fe=Se.data)==null?void 0:Fe.list_schema)??null,Pe=!L||Se.isFetched,Me=100,Ae={role:s.role||void 0,type:s.type||void 0,priority:s.priority?parseInt(s.priority):void 0,limit:_?Me:i.pageSize,offset:i.offset,sort_by:"created_at",order:"desc",search:p||void 0,...a,include:Ss(V)?"envelope":void 0},mt=ts({...Ae,enabled:U&&Pe}),ht=ss({status:we,claimed:xe||void 0,...Ae,enabled:!U&&Pe}),pt=U?mt:ht,{data:B,isLoading:ft,error:X,refetch:gt,isFetching:bt}=pt,yt=As(`/escalations${U?"/available":""}`,{status:we,claimed:xe||void 0,role:s.role||void 0,type:s.type||void 0,priority:s.priority||void 0,search:p||void 0,sort_by:"created_at",order:"desc",limit:i.pageSize,offset:i.offset,facets:a.facets&&Object.keys(a.facets).length?JSON.stringify(a.facets):void 0,block:(_e=a.block)!=null&&_e.length?JSON.stringify(a.block):void 0,range:($e=a.range)!=null&&$e.length?JSON.stringify(a.range):void 0,exists:(Le=a.exists)!=null&&Le.length?JSON.stringify(a.exists):void 0,roles:(Be=a.roles)!=null&&Be.length?JSON.stringify(a.roles):void 0,orderBy:(Re=a.orderBy)!=null&&Re.length?JSON.stringify(a.orderBy):void 0,available:a.available!=null?String(a.available):void 0}),F=(B==null?void 0:B.escalations)??[],E=(B==null?void 0:B.total)??0,Te=!!L&&!!V&&!!V["x-lt-layout"]&&V["x-lt-layout"]!=="table",Y=Te&&!_&&(le?le==="rich":!0),Oe=f.useMemo(()=>{if(!a.jeopardy||!L)return null;const n=(($==null?void 0:$.roles)??[]).find(v=>v.role===L),b=(n==null?void 0:n.priority_threshold_minutes)??(n==null?void 0:n.sla_minutes)??null;return b!=null?as(b*6e4):null},[a.jeopardy,L,$]),jt=f.useMemo(()=>{const n=new Set;for(const b of F)j.has(b.id)&&n.add(b.role);return[...n]},[F,j]),vt=f.useCallback(()=>k(new Set),[]),Nt=()=>{if(!h)return;const n=x==="custom"?C:parseInt(x);!n||n<=0||je.mutate({id:h.id,durationMinutes:n},{onSuccess:()=>{d(null),t(`/escalations/detail/${h.id}`)}})},{handleSetPriority:Ct,handleBulkClaim:kt,handleBulkTriage:wt,handleBulkAssign:St,handleBulkCancel:Pt}=Ys({selectedIds:j,clearSelection:vt,setPriority:ve,bulkClaim:Ne,bulkTriage:ce,bulkAssign:oe,bulkCancel:K,closeTriageModal:()=>ae(!1),closeAssignModal:()=>ne(!1),closeCancelModal:()=>re(!1)}),Mt=n=>{const b=new Set(j);b.has(n)?b.delete(n):b.add(n),k(b)},At=()=>{j.size===F.length?k(new Set):k(new Set(F.map(n=>n.id)))},Tt=[ot?{key:"select",label:e.jsx("input",{type:"checkbox",checked:F.length>0&&j.size===F.length,onChange:At,className:"rounded"}),render:n=>e.jsx("input",{type:"checkbox",checked:j.has(n.id),onChange:b=>{b.stopPropagation(),Mt(n.id)},onClick:b=>b.stopPropagation(),className:"rounded"}),className:"w-10",priority:1}:{key:"spacer",label:"",render:()=>null,className:"w-10",priority:3},...Ns({highlightKeys:be}),{key:"actions",label:"",render:n=>e.jsx(_s,{children:e.jsx($s,{icon:hs,title:"Claim escalation",onClick:()=>d(n),alwaysVisible:!0,colorClass:"text-accent/40 hover:text-accent",size:"sm"})}),className:"w-10 text-right"}];return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-10 min-w-0",children:[e.jsx(Cs,{role:s.role,options:xt,onChange:n=>l("role",n),locked:ie}),!ie&&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(ps,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsx(ks,{filters:s,setFilter:l,roles:(de==null?void 0:de.roles)??[],types:(ue==null?void 0:ue.types)??[],showStatus:!0,showSearch:!1,showRole:!ie,actions:e.jsxs(e.Fragment,{children:[_&&e.jsxs("span",{className:"text-2xs text-text-tertiary whitespace-nowrap",children:[E>100&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"font-medium text-text-secondary",children:[(i.page-1)*100+1,"–",Math.min(i.page*100,E)]})," of "]}),e.jsx("span",{className:"font-medium text-text-secondary",children:E})," ",E===1?"escalation":"escalations"]}),e.jsx(Hs,{orderBy:a.orderBy,onChange:it}),e.jsx("span",{className:"h-3.5 w-px bg-surface-border shrink-0"}),e.jsx(Ls,{onRefresh:()=>gt(),isFetching:bt,apiPath:yt}),Te&&!_&&e.jsx("button",{onClick:()=>ye(Y?"table":"rich"),className:"ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:Y?"Table view":"Rich view",children:Y?e.jsx(qe,{className:"w-4 h-4"}):e.jsx(fs,{className:"w-4 h-4"})}),M>0&&e.jsx("button",{onClick:()=>ye(_?"table":"timeline"),className:"ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:_?"Table view":"Timeline view",children:_?e.jsx(qe,{className:"w-4 h-4"}):e.jsx(gs,{className:"w-4 h-4"})}),e.jsx("button",{onClick:lt,className:"ml-2 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(bs,{className:"w-4 h-4"})}),e.jsxs("button",{onClick:()=>u(n=>!n),className:"relative ml-2 inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:"Faceted query",children:[e.jsx(ys,{className:"w-4 h-4"}),M>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:M})]})]})}),e.jsx(Ks,{selectedCount:j.size,onClearSelection:()=>k(new Set),onSetPriority:Ct,onClaim:kt,onAssign:()=>ne(!0),onTriage:()=>ae(!0),onCancel:()=>re(!0),isPriorityPending:ve.isPending,isClaimPending:Ne.isPending,isAssignPending:oe.isPending,isTriagePending:ce.isPending,isCancelPending:K.isPending}),(a.facets&&Object.keys(a.facets).length>0||a.jeopardy)&&e.jsxs("div",{className:"sticky top-14 z-30 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:[a.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(js,{className:"w-2.5 h-2.5",strokeWidth:2.5}),"in jeopardy",Oe&&e.jsxs("span",{className:"font-mono font-normal opacity-90",children:["> ",Oe]}),e.jsx("button",{onClick:()=>N({...a,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(te,{className:"w-2.5 h-2.5"})})]}),Object.entries(a.facets??{}).map(([n,b])=>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:n}),e.jsx("span",{className:"text-text-quaternary",children:"="}),e.jsx("span",{className:"font-mono max-w-[160px] truncate",title:String(b),children:String(b)}),e.jsx("button",{onClick:()=>ct(n),className:"ml-0.5 -mr-0.5 flex items-center text-text-quaternary hover:text-status-error transition-colors","aria-label":`Remove ${n} filter`,children:e.jsx(te,{className:"w-2.5 h-2.5"})})]},n)),Object.keys(a.facets??{}).length>1&&e.jsx("button",{onClick:()=>N({...a,facets:void 0}),className:"text-2xs text-text-quaternary hover:text-text-secondary transition-colors px-1",children:"clear all"})]}),X&&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:X.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${X.message}`}),_?e.jsx(ia,{escalations:F,highlightKeys:be,onRowClick:n=>t(`/escalations/detail/${n.id}`,{state:{from:"/escalations/available"}}),total:E,page:i.page,totalPages:Math.ceil(E/Me),onPageChange:i.setPage}):Y?e.jsx(Ps,{role:L,listSchema:V,activeEscalations:F,onRowClick:n=>t(`/escalations/detail/${n.id}`,{state:{from:"/escalations/available"}}),onOpenGroup:n=>t(n),onAddFacet:(n,b)=>N({...a,facets:{...a.facets??{},[n]:typeof b=="object"&&b!==null?JSON.stringify(b):b}}),total:E,page:i.page,totalPages:i.totalPages(E),pageSize:i.pageSize,onPageChange:i.setPage,onPageSizeChange:i.setPageSize}):e.jsxs(e.Fragment,{children:[e.jsx(Ts,{columns:Tt,data:F,layout:"fixed",keyFn:n=>n.id,onRowClick:n=>t(`/escalations/detail/${n.id}`,{state:{from:"/escalations/available"}}),isLoading:ft,emptyMessage:X?"Unable to load data":"No escalations"}),e.jsx(Os,{page:i.page,totalPages:i.totalPages(E),onPageChange:i.setPage,total:E,pageSize:i.pageSize,onPageSizeChange:i.setPageSize})]}),e.jsx(Zs,{claimTarget:h,onClose:()=>d(null),claimDuration:x,onDurationChange:n=>{g(n),S(0)},claimDurations:m,customClaimMinutes:C,onCustomClaimChange:P,onClaim:Nt,isPending:je.isPending}),e.jsx(Xs,{open:at,onClose:()=>ae(!1),selectedCount:j.size,onSubmit:wt,isPending:ce.isPending}),e.jsx(Ws,{open:nt,onClose:()=>ne(!1),selectedCount:j.size,selectedRoles:jt,onSubmit:St,isPending:oe.isPending}),e.jsx(vs,{open:rt,onClose:()=>re(!1),onConfirm:Pt,selectedCount:j.size,isPending:K.isPending,error:K.error})]})}export{Fa as AvailableEscalationsPage};
2
- //# sourceMappingURL=AvailableEscalationsPage-B8NjwwKQ.js.map