@hotmeshio/long-tail 0.23.1 → 0.23.2

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 (277) hide show
  1. package/build/api/escalations/index.d.ts +1 -0
  2. package/build/api/escalations/index.js +4 -1
  3. package/build/api/escalations/list.d.ts +5 -0
  4. package/build/api/escalations/list.js +19 -5
  5. package/build/api/escalations/related.d.ts +18 -0
  6. package/build/api/escalations/related.js +205 -0
  7. package/build/api/roles.js +4 -0
  8. package/build/api/scan-codes/present.js +5 -1
  9. package/build/api/settings.d.ts +1 -1
  10. package/build/api/settings.js +3 -1
  11. package/build/modules/display.d.ts +15 -0
  12. package/build/modules/display.js +27 -0
  13. package/build/routes/escalations/index.js +3 -0
  14. package/build/routes/escalations/list.js +2 -0
  15. package/build/routes/escalations/related.d.ts +7 -0
  16. package/build/routes/escalations/related.js +60 -0
  17. package/build/scripts/consolidation-sim.d.ts +25 -0
  18. package/build/scripts/consolidation-sim.js +141 -0
  19. package/build/sdk/index.d.ts +12 -0
  20. package/build/sdk/index.js +2 -0
  21. package/build/services/escalation/grouped-list.d.ts +19 -0
  22. package/build/services/escalation/grouped-list.js +54 -0
  23. package/build/services/escalation/index.d.ts +4 -0
  24. package/build/services/escalation/index.js +9 -1
  25. package/build/services/escalation/queries.d.ts +17 -13
  26. package/build/services/escalation/queries.js +31 -40
  27. package/build/services/escalation/read-scope-sql.d.ts +13 -0
  28. package/build/services/escalation/read-scope-sql.js +19 -0
  29. package/build/services/escalation/related.d.ts +58 -0
  30. package/build/services/escalation/related.js +196 -0
  31. package/build/services/role/index.js +6 -0
  32. package/build/services/role/seed.js +4 -0
  33. package/build/services/scan-code/validate-facts.d.ts +1 -1
  34. package/build/services/scan-code/validate-facts.js +12 -1
  35. package/build/shared/form-validation/x-lt-scan.d.ts +8 -0
  36. package/build/shared/form-validation/x-lt-scan.js +20 -1
  37. package/build/shared/list-schema/index.d.ts +3 -0
  38. package/build/shared/list-schema/index.js +27 -0
  39. package/build/shared/list-schema/template.d.ts +14 -0
  40. package/build/shared/list-schema/template.js +85 -0
  41. package/build/shared/list-schema/types.d.ts +154 -0
  42. package/build/shared/list-schema/types.js +55 -0
  43. package/build/shared/list-schema/validate.d.ts +12 -0
  44. package/build/shared/list-schema/validate.js +204 -0
  45. package/build/shared/roles/segment.d.ts +22 -0
  46. package/build/shared/roles/segment.js +42 -0
  47. package/build/start/adapters.js +2 -0
  48. package/build/system/mcp-servers/admin/users.js +8 -0
  49. package/build/tsconfig.tsbuildinfo +1 -1
  50. package/build/types/index.d.ts +2 -2
  51. package/build/types/index.js +2 -1
  52. package/build/types/scan-code/constants.d.ts +7 -0
  53. package/build/types/scan-code/constants.js +7 -1
  54. package/build/types/scan-code/response.d.ts +3 -2
  55. package/build/types/scan-code/rule.d.ts +6 -1
  56. package/build/types/startup.d.ts +8 -0
  57. package/dashboard/dist/assets/{AdminDashboard-DKrqLGjn.js → AdminDashboard-BPWsgMfZ.js} +2 -2
  58. package/dashboard/dist/assets/{AdminDashboard-DKrqLGjn.js.map → AdminDashboard-BPWsgMfZ.js.map} +1 -1
  59. package/dashboard/dist/assets/{AgentConfigPage-BoQhRW6U.js → AgentConfigPage-De9imyo5.js} +2 -2
  60. package/dashboard/dist/assets/{AgentConfigPage-BoQhRW6U.js.map → AgentConfigPage-De9imyo5.js.map} +1 -1
  61. package/dashboard/dist/assets/{AgentDetailPage-DZhzuZmO.js → AgentDetailPage-B6o96Y5G.js} +3 -3
  62. package/dashboard/dist/assets/{AgentDetailPage-DZhzuZmO.js.map → AgentDetailPage-B6o96Y5G.js.map} +1 -1
  63. package/dashboard/dist/assets/{AgentsPage-5MynmbWX.js → AgentsPage-DMEmiK_W.js} +2 -2
  64. package/dashboard/dist/assets/{AgentsPage-5MynmbWX.js.map → AgentsPage-DMEmiK_W.js.map} +1 -1
  65. package/dashboard/dist/assets/AvailableEscalationsPage-DeYMngwE.js +2 -0
  66. package/dashboard/dist/assets/AvailableEscalationsPage-DeYMngwE.js.map +1 -0
  67. package/dashboard/dist/assets/{BotPicker-C3LR6Sqy.js → BotPicker-DDmpgGHZ.js} +2 -2
  68. package/dashboard/dist/assets/{BotPicker-C3LR6Sqy.js.map → BotPicker-DDmpgGHZ.js.map} +1 -1
  69. package/dashboard/dist/assets/{BulkAssignModal-COjoOIIH.js → BulkAssignModal-BqlklomG.js} +2 -2
  70. package/dashboard/dist/assets/{BulkAssignModal-COjoOIIH.js.map → BulkAssignModal-BqlklomG.js.map} +1 -1
  71. package/dashboard/dist/assets/CapabilitiesPage-DOtjDTbK.js +2 -0
  72. package/dashboard/dist/assets/{CapabilitiesPage-DKxLvOfB.js.map → CapabilitiesPage-DOtjDTbK.js.map} +1 -1
  73. package/dashboard/dist/assets/{CollapsibleSection-Cz5sRx-r.js → CollapsibleSection-CLr8LP0V.js} +2 -2
  74. package/dashboard/dist/assets/{CollapsibleSection-Cz5sRx-r.js.map → CollapsibleSection-CLr8LP0V.js.map} +1 -1
  75. package/dashboard/dist/assets/{ConfirmDeleteModal-Beq1vQtY.js → ConfirmDeleteModal-DW4DrPur.js} +2 -2
  76. package/dashboard/dist/assets/{ConfirmDeleteModal-Beq1vQtY.js.map → ConfirmDeleteModal-DW4DrPur.js.map} +1 -1
  77. package/dashboard/dist/assets/CountdownTimer-DxX72PwV.js +2 -0
  78. package/dashboard/dist/assets/CountdownTimer-DxX72PwV.js.map +1 -0
  79. package/dashboard/dist/assets/{CredentialsPage-DhiHiPsG.js → CredentialsPage-CObc9Rs5.js} +2 -2
  80. package/dashboard/dist/assets/{CredentialsPage-DhiHiPsG.js.map → CredentialsPage-CObc9Rs5.js.map} +1 -1
  81. package/dashboard/dist/assets/{CronLabel-C9SkawB-.js → CronLabel-Bb8GoNY5.js} +2 -2
  82. package/dashboard/dist/assets/{CronLabel-C9SkawB-.js.map → CronLabel-Bb8GoNY5.js.map} +1 -1
  83. package/dashboard/dist/assets/DataTable-FjFhx0SE.js +2 -0
  84. package/dashboard/dist/assets/DataTable-FjFhx0SE.js.map +1 -0
  85. package/dashboard/dist/assets/{ElapsedCell-BeK1SUDK.js → ElapsedCell-CmGhVlYl.js} +2 -2
  86. package/dashboard/dist/assets/{ElapsedCell-BeK1SUDK.js.map → ElapsedCell-CmGhVlYl.js.map} +1 -1
  87. package/dashboard/dist/assets/{EntityTimelinePanel-BThdefKj.js → EntityTimelinePanel-B4Jwy1w3.js} +2 -2
  88. package/dashboard/dist/assets/{EntityTimelinePanel-BThdefKj.js.map → EntityTimelinePanel-B4Jwy1w3.js.map} +1 -1
  89. package/dashboard/dist/assets/{EscalationListSchemaPage-DlDIYb-p.js → EscalationListSchemaPage-CZZbZ4Aa.js} +2 -2
  90. package/dashboard/dist/assets/{EscalationListSchemaPage-DlDIYb-p.js.map → EscalationListSchemaPage-CZZbZ4Aa.js.map} +1 -1
  91. package/dashboard/dist/assets/{EscalationSchemaPage-CQt-Embr.js → EscalationSchemaPage-D0ko59_S.js} +3 -3
  92. package/dashboard/dist/assets/{EscalationSchemaPage-CQt-Embr.js.map → EscalationSchemaPage-D0ko59_S.js.map} +1 -1
  93. package/dashboard/dist/assets/EscalationTimeline-BcnJEKFD.js +2 -0
  94. package/dashboard/dist/assets/EscalationTimeline-BcnJEKFD.js.map +1 -0
  95. package/dashboard/dist/assets/{EscalationTitleSelect-Dewrv8wX.js → EscalationTitleSelect-P0q5sck4.js} +2 -2
  96. package/dashboard/dist/assets/{EscalationTitleSelect-Dewrv8wX.js.map → EscalationTitleSelect-P0q5sck4.js.map} +1 -1
  97. package/dashboard/dist/assets/{EscalationsOverview-BzH-Y-5x.js → EscalationsOverview-BLPmh4AF.js} +2 -2
  98. package/dashboard/dist/assets/{EscalationsOverview-BzH-Y-5x.js.map → EscalationsOverview-BLPmh4AF.js.map} +1 -1
  99. package/dashboard/dist/assets/{EventTable-C97m6IZv.js → EventTable-gBzi5tIS.js} +2 -2
  100. package/dashboard/dist/assets/{EventTable-C97m6IZv.js.map → EventTable-gBzi5tIS.js.map} +1 -1
  101. package/dashboard/dist/assets/{FilterBar-D-6xVHIw.js → FilterBar-BulSsWb2.js} +2 -2
  102. package/dashboard/dist/assets/{FilterBar-D-6xVHIw.js.map → FilterBar-BulSsWb2.js.map} +1 -1
  103. package/dashboard/dist/assets/FormattedValue-BMHRrvrL.js +2 -0
  104. package/dashboard/dist/assets/FormattedValue-BMHRrvrL.js.map +1 -0
  105. package/dashboard/dist/assets/{GraphInvokePage-Bwi8EF9Y.js → GraphInvokePage--997yNRr.js} +2 -2
  106. package/dashboard/dist/assets/{GraphInvokePage-Bwi8EF9Y.js.map → GraphInvokePage--997yNRr.js.map} +1 -1
  107. package/dashboard/dist/assets/{HomePage-Z_Q03C0z.js → HomePage-CwXFz--v.js} +2 -2
  108. package/dashboard/dist/assets/{HomePage-Z_Q03C0z.js.map → HomePage-CwXFz--v.js.map} +1 -1
  109. package/dashboard/dist/assets/{ListToolbar-_jWTw5no.js → ListToolbar-Df4qZryJ.js} +2 -2
  110. package/dashboard/dist/assets/{ListToolbar-_jWTw5no.js.map → ListToolbar-Df4qZryJ.js.map} +1 -1
  111. package/dashboard/dist/assets/{McpOverview-CjqTuP0N.js → McpOverview-DrogIAKJ.js} +2 -2
  112. package/dashboard/dist/assets/{McpOverview-CjqTuP0N.js.map → McpOverview-DrogIAKJ.js.map} +1 -1
  113. package/dashboard/dist/assets/{McpQueryDetailPage-leCsje1U.js → McpQueryDetailPage-CJmvCAE6.js} +2 -2
  114. package/dashboard/dist/assets/{McpQueryDetailPage-leCsje1U.js.map → McpQueryDetailPage-CJmvCAE6.js.map} +1 -1
  115. package/dashboard/dist/assets/{McpQueryPage-C-PyXYX4.js → McpQueryPage-lygo4Yq0.js} +2 -2
  116. package/dashboard/dist/assets/{McpQueryPage-C-PyXYX4.js.map → McpQueryPage-lygo4Yq0.js.map} +1 -1
  117. package/dashboard/dist/assets/{McpRunDetailPage-JDrr3uUQ.js → McpRunDetailPage-hvns2sCm.js} +2 -2
  118. package/dashboard/dist/assets/{McpRunDetailPage-JDrr3uUQ.js.map → McpRunDetailPage-hvns2sCm.js.map} +1 -1
  119. package/dashboard/dist/assets/{McpRunsPage-DERXQLgZ.js → McpRunsPage-C2_7spTX.js} +2 -2
  120. package/dashboard/dist/assets/{McpRunsPage-DERXQLgZ.js.map → McpRunsPage-C2_7spTX.js.map} +1 -1
  121. package/dashboard/dist/assets/{OperationsPage-B2DA7n9m.js → OperationsPage-BlK8WlsY.js} +3 -3
  122. package/dashboard/dist/assets/OperationsPage-BlK8WlsY.js.map +1 -0
  123. package/dashboard/dist/assets/OperatorDashboard-BeWBiMGX.js +2 -0
  124. package/dashboard/dist/assets/OperatorDashboard-BeWBiMGX.js.map +1 -0
  125. package/dashboard/dist/assets/{PersonaDetailPage-ChXwJ6u5.js → PersonaDetailPage-CNHpsX_i.js} +2 -2
  126. package/dashboard/dist/assets/{PersonaDetailPage-ChXwJ6u5.js.map → PersonaDetailPage-CNHpsX_i.js.map} +1 -1
  127. package/dashboard/dist/assets/{PersonasPage-BFFxncSE.js → PersonasPage-ChASEZRg.js} +2 -2
  128. package/dashboard/dist/assets/{PersonasPage-BFFxncSE.js.map → PersonasPage-ChASEZRg.js.map} +1 -1
  129. package/dashboard/dist/assets/PortalPage-D5Lk-PKF.js +2 -0
  130. package/dashboard/dist/assets/PortalPage-D5Lk-PKF.js.map +1 -0
  131. package/dashboard/dist/assets/{ProcessDetailPage-D7EYwW-j.js → ProcessDetailPage-DNgCIwRl.js} +2 -2
  132. package/dashboard/dist/assets/{ProcessDetailPage-D7EYwW-j.js.map → ProcessDetailPage-DNgCIwRl.js.map} +1 -1
  133. package/dashboard/dist/assets/{ProcessesListPage-CakYRtnE.js → ProcessesListPage-pRjWuWlH.js} +2 -2
  134. package/dashboard/dist/assets/{ProcessesListPage-CakYRtnE.js.map → ProcessesListPage-pRjWuWlH.js.map} +1 -1
  135. package/dashboard/dist/assets/ResolverForm-CKIOAGtY.js +8 -0
  136. package/dashboard/dist/assets/ResolverForm-CKIOAGtY.js.map +1 -0
  137. package/dashboard/dist/assets/{RoleDetailPage-CKbGwezP.js → RoleDetailPage-Bh_UcfYY.js} +2 -2
  138. package/dashboard/dist/assets/{RoleDetailPage-CKbGwezP.js.map → RoleDetailPage-Bh_UcfYY.js.map} +1 -1
  139. package/dashboard/dist/assets/{RolesPage-Czu7Zku4.js → RolesPage-CK17N7zz.js} +2 -2
  140. package/dashboard/dist/assets/{RolesPage-Czu7Zku4.js.map → RolesPage-CK17N7zz.js.map} +1 -1
  141. package/dashboard/dist/assets/{RunAsSelector-6BLScYTX.js → RunAsSelector-BEKUP0p2.js} +2 -2
  142. package/dashboard/dist/assets/{RunAsSelector-6BLScYTX.js.map → RunAsSelector-BEKUP0p2.js.map} +1 -1
  143. package/dashboard/dist/assets/{ScanCodesPage-Cv9q8Bvt.js → ScanCodesPage-Bd0Pflqx.js} +2 -2
  144. package/dashboard/dist/assets/{ScanCodesPage-Cv9q8Bvt.js.map → ScanCodesPage-Bd0Pflqx.js.map} +1 -1
  145. package/dashboard/dist/assets/{ScanSchemeDetailPage-BxazXYIc.js → ScanSchemeDetailPage-CnuhozmJ.js} +2 -2
  146. package/dashboard/dist/assets/{ScanSchemeDetailPage-BxazXYIc.js.map → ScanSchemeDetailPage-CnuhozmJ.js.map} +1 -1
  147. package/dashboard/dist/assets/ScanStationPage-CoLc-q3h.js +2 -0
  148. package/dashboard/dist/assets/ScanStationPage-CoLc-q3h.js.map +1 -0
  149. package/dashboard/dist/assets/{StickyPagination-DsdtYoXR.js → StickyPagination-COrfvkBi.js} +2 -2
  150. package/dashboard/dist/assets/{StickyPagination-DsdtYoXR.js.map → StickyPagination-COrfvkBi.js.map} +1 -1
  151. package/dashboard/dist/assets/{StreamMessageDetail-CT3FQoT3.js → StreamMessageDetail-Cif2egLy.js} +2 -2
  152. package/dashboard/dist/assets/{StreamMessageDetail-CT3FQoT3.js.map → StreamMessageDetail-Cif2egLy.js.map} +1 -1
  153. package/dashboard/dist/assets/{SwimlaneTimeline-C8TjkJ10.js → SwimlaneTimeline-BnZYTrAh.js} +2 -2
  154. package/dashboard/dist/assets/{SwimlaneTimeline-C8TjkJ10.js.map → SwimlaneTimeline-BnZYTrAh.js.map} +1 -1
  155. package/dashboard/dist/assets/{TaskDetailPage-DGUzdBFN.js → TaskDetailPage-DEz_dqyR.js} +2 -2
  156. package/dashboard/dist/assets/{TaskDetailPage-DGUzdBFN.js.map → TaskDetailPage-DEz_dqyR.js.map} +1 -1
  157. package/dashboard/dist/assets/{TasksListPage-BVIP6-EZ.js → TasksListPage-oEfEGj0_.js} +2 -2
  158. package/dashboard/dist/assets/{TasksListPage-BVIP6-EZ.js.map → TasksListPage-oEfEGj0_.js.map} +1 -1
  159. package/dashboard/dist/assets/{TimeAgo-C-rd9F9g.js → TimeAgo-Dz5TgZZZ.js} +2 -2
  160. package/dashboard/dist/assets/{TimeAgo-C-rd9F9g.js.map → TimeAgo-Dz5TgZZZ.js.map} +1 -1
  161. package/dashboard/dist/assets/{TimestampCell-DPbchDOI.js → TimestampCell-BUTgE244.js} +2 -2
  162. package/dashboard/dist/assets/{TimestampCell-DPbchDOI.js.map → TimestampCell-BUTgE244.js.map} +1 -1
  163. package/dashboard/dist/assets/{ToolTestPanel-DAUC8DHK.js → ToolTestPanel-BS4g6vt-.js} +2 -2
  164. package/dashboard/dist/assets/{ToolTestPanel-DAUC8DHK.js.map → ToolTestPanel-BS4g6vt-.js.map} +1 -1
  165. package/dashboard/dist/assets/{TopicDetailPage-70mMKBzG.js → TopicDetailPage-C_I6JIVD.js} +2 -2
  166. package/dashboard/dist/assets/{TopicDetailPage-70mMKBzG.js.map → TopicDetailPage-C_I6JIVD.js.map} +1 -1
  167. package/dashboard/dist/assets/{TopicsPage-CE3hBthn.js → TopicsPage-Cr6-wfhJ.js} +2 -2
  168. package/dashboard/dist/assets/{TopicsPage-CE3hBthn.js.map → TopicsPage-Cr6-wfhJ.js.map} +1 -1
  169. package/dashboard/dist/assets/{UserName-BDBDA-LR.js → UserName-ZFpWMaFF.js} +2 -2
  170. package/dashboard/dist/assets/{UserName-BDBDA-LR.js.map → UserName-ZFpWMaFF.js.map} +1 -1
  171. package/dashboard/dist/assets/{WorkflowExecutionPage-BbkLZ1co.js → WorkflowExecutionPage-ByPixDZW.js} +2 -2
  172. package/dashboard/dist/assets/{WorkflowExecutionPage-BbkLZ1co.js.map → WorkflowExecutionPage-ByPixDZW.js.map} +1 -1
  173. package/dashboard/dist/assets/{WorkflowsDashboard-Bp1L7Ggz.js → WorkflowsDashboard-CWsJdMdR.js} +2 -2
  174. package/dashboard/dist/assets/{WorkflowsDashboard-Bp1L7Ggz.js.map → WorkflowsDashboard-CWsJdMdR.js.map} +1 -1
  175. package/dashboard/dist/assets/{WorkflowsOverview-IeTKHAi4.js → WorkflowsOverview-Dk9gyqZN.js} +2 -2
  176. package/dashboard/dist/assets/{WorkflowsOverview-IeTKHAi4.js.map → WorkflowsOverview-Dk9gyqZN.js.map} +1 -1
  177. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DtKCXnKt.js → YamlWorkflowDetailPage-CHwcrsaT.js} +2 -2
  178. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DtKCXnKt.js.map → YamlWorkflowDetailPage-CHwcrsaT.js.map} +1 -1
  179. package/dashboard/dist/assets/{YamlWorkflowsPage-CEcZBV_3.js → YamlWorkflowsPage-B5jRX2Ph.js} +2 -2
  180. package/dashboard/dist/assets/{YamlWorkflowsPage-CEcZBV_3.js.map → YamlWorkflowsPage-B5jRX2Ph.js.map} +1 -1
  181. package/dashboard/dist/assets/{agents-BT-sEk81.js → agents-Dd7E-27d.js} +2 -2
  182. package/dashboard/dist/assets/{agents-BT-sEk81.js.map → agents-Dd7E-27d.js.map} +1 -1
  183. package/dashboard/dist/assets/{bots-DRoAdLek.js → bots-CpaYjZTk.js} +2 -2
  184. package/dashboard/dist/assets/{bots-DRoAdLek.js.map → bots-CpaYjZTk.js.map} +1 -1
  185. package/dashboard/dist/assets/{capabilities-Bc-nJk6y.js → capabilities-CNjg_qv1.js} +2 -2
  186. package/dashboard/dist/assets/{capabilities-Bc-nJk6y.js.map → capabilities-CNjg_qv1.js.map} +1 -1
  187. package/dashboard/dist/assets/{controlplane-aXceSIRf.js → controlplane-DgmvnAtU.js} +2 -2
  188. package/dashboard/dist/assets/{controlplane-aXceSIRf.js.map → controlplane-DgmvnAtU.js.map} +1 -1
  189. package/dashboard/dist/assets/escalation-columns-Uj4U9g5H.js +2 -0
  190. package/dashboard/dist/assets/escalation-columns-Uj4U9g5H.js.map +1 -0
  191. package/dashboard/dist/assets/{index-C3VTJcrp.js → index-BFASQ7_X.js} +2 -2
  192. package/dashboard/dist/assets/{index-C3VTJcrp.js.map → index-BFASQ7_X.js.map} +1 -1
  193. package/dashboard/dist/assets/{index-DH03y-UT.js → index-BT1Ms5Q5.js} +2 -2
  194. package/dashboard/dist/assets/{index-DH03y-UT.js.map → index-BT1Ms5Q5.js.map} +1 -1
  195. package/dashboard/dist/assets/{index-Djsoi8DI.js → index-BrwqtXRh.js} +2 -2
  196. package/dashboard/dist/assets/{index-Djsoi8DI.js.map → index-BrwqtXRh.js.map} +1 -1
  197. package/dashboard/dist/assets/index-BsHVgWH6.js +13 -0
  198. package/dashboard/dist/assets/{index-BEPKAjna.js.map → index-BsHVgWH6.js.map} +1 -1
  199. package/dashboard/dist/assets/index-ByBy9M3L.js +2 -0
  200. package/dashboard/dist/assets/{index-BCFEQEMC.js.map → index-ByBy9M3L.js.map} +1 -1
  201. package/dashboard/dist/assets/{index-CZyO9hRb.js → index-C_K7OlzT.js} +2 -2
  202. package/dashboard/dist/assets/{index-CZyO9hRb.js.map → index-C_K7OlzT.js.map} +1 -1
  203. package/dashboard/dist/assets/{index-Ba-s5Yb5.js → index-CnOvJz6U.js} +2 -2
  204. package/dashboard/dist/assets/{index-Ba-s5Yb5.js.map → index-CnOvJz6U.js.map} +1 -1
  205. package/dashboard/dist/assets/{index-CcgmR-7-.js → index-CtlBjl8o.js} +2 -2
  206. package/dashboard/dist/assets/{index-CcgmR-7-.js.map → index-CtlBjl8o.js.map} +1 -1
  207. package/dashboard/dist/assets/{index-DBxpyIw5.js → index-D4Dlznn9.js} +2 -2
  208. package/dashboard/dist/assets/{index-DBxpyIw5.js.map → index-D4Dlznn9.js.map} +1 -1
  209. package/dashboard/dist/assets/{index-BUYokcrl.js → index-LRYC__mE.js} +30 -30
  210. package/dashboard/dist/assets/index-LRYC__mE.js.map +1 -0
  211. package/dashboard/dist/assets/{index-DcppjzP5.css → index-MYI2_Xb3.css} +1 -1
  212. package/dashboard/dist/assets/index-OfO0173w.js +3 -0
  213. package/dashboard/dist/assets/index-OfO0173w.js.map +1 -0
  214. package/dashboard/dist/assets/{index-h2gX31B2.js → index-RIFT3RlO.js} +2 -2
  215. package/dashboard/dist/assets/{index-h2gX31B2.js.map → index-RIFT3RlO.js.map} +1 -1
  216. package/dashboard/dist/assets/{index-CuBGGwXf.js → index-x5z73M9N.js} +2 -2
  217. package/dashboard/dist/assets/{index-CuBGGwXf.js.map → index-x5z73M9N.js.map} +1 -1
  218. package/dashboard/dist/assets/{knowledge-BhW8V-Hq.js → knowledge-Cci_r6Kl.js} +2 -2
  219. package/dashboard/dist/assets/{knowledge-BhW8V-Hq.js.map → knowledge-Cci_r6Kl.js.map} +1 -1
  220. package/dashboard/dist/assets/{mcp-BYfSMQzh.js → mcp-NY4iL0L-.js} +2 -2
  221. package/dashboard/dist/assets/{mcp-BYfSMQzh.js.map → mcp-NY4iL0L-.js.map} +1 -1
  222. package/dashboard/dist/assets/{mcp-query-DUJoOk_q.js → mcp-query-CbvZo_I_.js} +2 -2
  223. package/dashboard/dist/assets/{mcp-query-DUJoOk_q.js.map → mcp-query-CbvZo_I_.js.map} +1 -1
  224. package/dashboard/dist/assets/{personas-jT1O_SB4.js → personas-Fy-f7QQd.js} +2 -2
  225. package/dashboard/dist/assets/{personas-jT1O_SB4.js.map → personas-Fy-f7QQd.js.map} +1 -1
  226. package/dashboard/dist/assets/{pipelines-Bp-wIaz2.js → pipelines-DKiuozxV.js} +2 -2
  227. package/dashboard/dist/assets/{pipelines-Bp-wIaz2.js.map → pipelines-DKiuozxV.js.map} +1 -1
  228. package/dashboard/dist/assets/{tasks-CCrvnXbz.js → tasks-CdM1Rkk9.js} +2 -2
  229. package/dashboard/dist/assets/{tasks-CCrvnXbz.js.map → tasks-CdM1Rkk9.js.map} +1 -1
  230. package/dashboard/dist/assets/{topics-Blft0I1L.js → topics-XNy2mf3n.js} +2 -2
  231. package/dashboard/dist/assets/{topics-Blft0I1L.js.map → topics-XNy2mf3n.js.map} +1 -1
  232. package/dashboard/dist/assets/{useDebouncedValue-BYqbcism.js → useDebouncedValue-CyGcU3_S.js} +2 -2
  233. package/dashboard/dist/assets/{useDebouncedValue-BYqbcism.js.map → useDebouncedValue-CyGcU3_S.js.map} +1 -1
  234. package/dashboard/dist/assets/{useNamespace-BfxJAUgG.js → useNamespace-C2RIh_IN.js} +2 -2
  235. package/dashboard/dist/assets/{useNamespace-BfxJAUgG.js.map → useNamespace-C2RIh_IN.js.map} +1 -1
  236. package/dashboard/dist/assets/{useYamlActivityEvents-BukJuWpb.js → useYamlActivityEvents-CDiV5fjf.js} +2 -2
  237. package/dashboard/dist/assets/{useYamlActivityEvents-BukJuWpb.js.map → useYamlActivityEvents-CDiV5fjf.js.map} +1 -1
  238. package/dashboard/dist/assets/validate-DcGWN82Y.js +2 -0
  239. package/dashboard/dist/assets/validate-DcGWN82Y.js.map +1 -0
  240. package/dashboard/dist/assets/{yaml-workflows-DeRWqMGk.js → yaml-workflows-CH8UrouH.js} +2 -2
  241. package/dashboard/dist/assets/{yaml-workflows-DeRWqMGk.js.map → yaml-workflows-CH8UrouH.js.map} +1 -1
  242. package/dashboard/dist/index.html +2 -2
  243. package/docs/api/http/escalations.md +46 -0
  244. package/docs/api/sdk/escalations.md +16 -0
  245. package/docs/code-owned-configuration.md +12 -0
  246. package/docs/hitl/portal.md +2 -0
  247. package/docs/hitl/x-lt-list-schema.md +88 -1
  248. package/docs/hitl/x-lt-scan.md +4 -1
  249. package/docs/scan-codes.md +7 -1
  250. package/package.json +2 -1
  251. package/dashboard/dist/assets/AvailableEscalationsPage-CWMyy3IL.js +0 -2
  252. package/dashboard/dist/assets/AvailableEscalationsPage-CWMyy3IL.js.map +0 -1
  253. package/dashboard/dist/assets/CapabilitiesPage-DKxLvOfB.js +0 -2
  254. package/dashboard/dist/assets/CountdownTimer-BUBl_4mP.js +0 -2
  255. package/dashboard/dist/assets/CountdownTimer-BUBl_4mP.js.map +0 -1
  256. package/dashboard/dist/assets/DataTable-spX1dFyb.js +0 -2
  257. package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +0 -1
  258. package/dashboard/dist/assets/EscalationListView-DTIVuym4.js +0 -2
  259. package/dashboard/dist/assets/EscalationListView-DTIVuym4.js.map +0 -1
  260. package/dashboard/dist/assets/EscalationTimeline-DNKNp6pL.js +0 -2
  261. package/dashboard/dist/assets/EscalationTimeline-DNKNp6pL.js.map +0 -1
  262. package/dashboard/dist/assets/OperationsPage-B2DA7n9m.js.map +0 -1
  263. package/dashboard/dist/assets/OperatorDashboard-C8RtPv8P.js +0 -2
  264. package/dashboard/dist/assets/OperatorDashboard-C8RtPv8P.js.map +0 -1
  265. package/dashboard/dist/assets/PortalPage-Xk1zVneM.js +0 -2
  266. package/dashboard/dist/assets/PortalPage-Xk1zVneM.js.map +0 -1
  267. package/dashboard/dist/assets/ResolverForm-BwVOJUpJ.js +0 -8
  268. package/dashboard/dist/assets/ResolverForm-BwVOJUpJ.js.map +0 -1
  269. package/dashboard/dist/assets/ScanStationPage-Cg8LCFR7.js +0 -2
  270. package/dashboard/dist/assets/ScanStationPage-Cg8LCFR7.js.map +0 -1
  271. package/dashboard/dist/assets/escalation-columns-Bf09Q89t.js +0 -2
  272. package/dashboard/dist/assets/escalation-columns-Bf09Q89t.js.map +0 -1
  273. package/dashboard/dist/assets/index-BCFEQEMC.js +0 -2
  274. package/dashboard/dist/assets/index-BEPKAjna.js +0 -13
  275. package/dashboard/dist/assets/index-BUYokcrl.js.map +0 -1
  276. package/dashboard/dist/assets/index-D1mKf_qz.js +0 -3
  277. package/dashboard/dist/assets/index-D1mKf_qz.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"yaml-workflows-DeRWqMGk.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-CH8UrouH.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-BUYokcrl.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-LRYC__mE.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
14
  <link rel="modulepreload" crossorigin href="./assets/vendor-icons-CeVtUKyP.js">
15
- <link rel="stylesheet" crossorigin href="./assets/index-DcppjzP5.css">
15
+ <link rel="stylesheet" crossorigin href="./assets/index-MYI2_Xb3.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="root"></div>
@@ -62,6 +62,7 @@ GET /api/escalations
62
62
  | `available` | `true`/`false` | `true` = unclaimed/expired only; `false` = held now |
63
63
  | `jeopardy` | `1`/`true` | Only rows past their role's priority threshold — the exact predicate behind the Pace Board's priority count, so a jeopardy list's total equals the badge. Age from the role's `priority_facet` metadata timestamp (`created_at` when unset) against `priority_threshold_minutes` (`sla_minutes` when unset); undialed roles contribute no rows |
64
64
  | `orderBy` | array of `{field, direction?, numeric?}` | Sort by column or `metadata.<key>` |
65
+ | `groupBy` | string | A metadata key: the page holds whole groups of rows sharing it (a row without it is a group of one), `total` counts groups, and the response adds `groups: [{ key, ids }]` in page order. A role's grouped `facet-table` sends it |
65
66
 
66
67
  When any faceted parameter is present the request runs through the scoped faceted query.
67
68
  Example (URL-encode the JSON values):
@@ -1433,3 +1434,48 @@ One entity's ordered interval sequence — every escalation the entity facet app
1433
1434
  **Response 400** — same validation class as the aggregate: a rejected filter field, an invalid window, a malformed facet key.
1434
1435
 
1435
1436
  **Response 403** — timelines always take the full gate: an entity's movement history is item-level disclosure. The caller must hold `read_all` on every role in scope (for `entity`, every role in the derived system); a roleless query requires a global principal.
1437
+
1438
+ ## Related sets
1439
+
1440
+ The related sets a role's `list_schema` declares under `x-lt-related` (see [List Schema](../../hitl/x-lt-list-schema.md#related-sets)), read for list rows. The server reads the declaration from the stored list schema; the caller names the role, the rows, and the schema version it rendered. Every count and row is scoped to the caller's read scope; a role the caller cannot read answers 404.
1441
+
1442
+ ```
1443
+ POST /api/escalations/related
1444
+ ```
1445
+
1446
+ Body: `{ role, ids, version? }`, with up to 100 ids (one page). One statement runs per declared (set, split) pair, whatever the page size.
1447
+
1448
+ **Response 200:**
1449
+
1450
+ ```json
1451
+ {
1452
+ "version": 3,
1453
+ "sets": {
1454
+ "contents": {
1455
+ "source": "items",
1456
+ "roles": ["order-stage"],
1457
+ "aggregates": {
1458
+ "reciprocal.metadata.serviceLevel": {
1459
+ "6f1c…": { "count": 3, "splits": { "standard": 2, "express": 1 } }
1460
+ }
1461
+ }
1462
+ },
1463
+ "coming": {
1464
+ "source": "query",
1465
+ "roles": ["order-prep", "order-check", "order-stage"],
1466
+ "roleLabels": { "order-prep": "Order · Prep", "order-check": "Order · Check", "order-stage": "Order · Staged" },
1467
+ "restricted": [],
1468
+ "aggregates": { "role": { "6f1c…": { "count": 2, "splits": { "order-check": 1, "order-prep": 1 } } } }
1469
+ }
1470
+ }
1471
+ }
1472
+ ```
1473
+
1474
+ `aggregates` is keyed by `splitBy` (`""` when a column is unsplit), then row id. `hidden` counts items whose reciprocal row the caller cannot read; `unresolved` marks a row whose facet templates did not resolve; `restricted` names query roles outside the caller's full read scope (not counted). `roles` names the roles whose rows a set reads, so a list can follow their events: a query set's resolved roles in order, or, for an item set split by `reciprocal.metadata.<key>`, the roles of the readable reciprocal rows. 400 for a bad body or a segment naming no sequence; 422 when the stored declaration no longer validates.
1475
+
1476
+ ```
1477
+ POST /api/escalations/related/rows
1478
+ ```
1479
+
1480
+ Body: `{ role, id, set, version?, limit? }` (`limit` 1..100, default 25). Returns `{ source, rows, total }`; an items row is `{ item: { itemKey, payload, at, actor?, reciprocalId? }, escalation }` (the reciprocal row, or null when unreadable), a query row is `{ escalation }` in role order then age, with `restricted` and `roleLabels`.
1481
+
@@ -1224,3 +1224,19 @@ interface StationMetric {
1224
1224
  `pending` reflects the live queue depth regardless of period. `claimed`, `resolved`, and both percentile objects use the lookback window. `priority_count` covers pending, unclaimed items whose age exceeds the role's threshold — age from the `priority_facet` metadata timestamp (`created_at` when unset) against `priority_threshold_minutes` (`sla_minutes` when unset); stations with neither threshold always return `0`. `throughput_pct` is `null` when `target_per_hour` is not set.
1225
1225
 
1226
1226
  **Auth:** Same RBAC as `getStats` — callers see only the stations for roles they hold.
1227
+
1228
+ ## getRelated / getRelatedRows
1229
+
1230
+ Read the related sets a role's list schema declares (`x-lt-related`) for list rows, under the caller's read scope. Mirrors `POST /api/escalations/related` and `/related/rows`.
1231
+
1232
+ ```typescript
1233
+ const page = await client.escalations.getRelated({ role: 'consolidate', ids: rows.map((r) => r.id) });
1234
+ // page.data.sets.contents.aggregates['reciprocal.metadata.serviceLevel'][rowId]
1235
+ // → { count: 3, splits: { standard: 2, express: 1 } }
1236
+
1237
+ const orders = await client.escalations.getRelatedRows({ role: 'consolidate', id: rowId, set: 'contents' });
1238
+ // orders.data.rows → [{ item: { itemKey, at, reciprocalId }, escalation }]
1239
+ ```
1240
+
1241
+ `list` and `listAvailable` take `groupBy` (a metadata key) to page by groups of rows sharing it: the response adds `groups: [{ key, ids }]` and `total` counts groups.
1242
+
@@ -157,3 +157,15 @@ dedicated advisory lock, separate from the migration lock. Single-statement
157
157
  applies are also individually race-safe: every upsert carries an
158
158
  `IS DISTINCT FROM` guard, so an identical declaration arriving from two
159
159
  containers writes once and no-ops once.
160
+
161
+ ## Display time zone
162
+
163
+ `display.timeZone` (an IANA name) renders every dashboard date in that zone, so a floor reads its own time on every screen: list columns, station facts, and detail pages alike. Unset, dates render in the viewer's browser zone. An unknown zone fails the boot.
164
+
165
+ ```typescript
166
+ await start({
167
+ // …
168
+ display: { timeZone: 'America/Chicago' },
169
+ });
170
+ ```
171
+
@@ -82,6 +82,8 @@ A portal page fills the content area with one grid row per declared row, each di
82
82
 
83
83
  **Fitting a screen.** A panel on a wall screen is read, not scrolled, so a pin can ask the table to spend its width tightly: `?view=table&layout=compact` keeps the table a table however narrow the panel, tightens every cell, and holds the non-identity columns (assignee, role, priority) back until the panel is wide enough, so a narrow cell reads as a tight list of item and age and twenty rows fit where the folded layout showed four. `layout=cards` asks for the folded console-card layout on purpose. Without `layout`, the table folds on its own below the card threshold. The hint rides the URL like `view`, so it works on the full list page too, and it is the seam for a compact timeline later: a series of tight offset lines that fit the whole story in the panel.
84
84
 
85
+ A rich panel carries the role's whole list schema, so related columns, row expansion, and grouped rows (see [Related sets](x-lt-list-schema.md#related-sets)) read on a wall screen as they do on the list page.
86
+
85
87
  A portal page shows without the left nav, as kiosk does: it is a screen read from across a room, and the panels are the page. The header stays, so the user menu still switches portals. Any signed-in user may open a portal. Panels read through the same role-scoped endpoints as the list page, so RBAC is unchanged: each viewer sees exactly what their read scope returns, and a queue outside it renders empty. Link variables resolve per device at render time, exactly as pins in the nav do. One event subscription per queue named by the cells keeps every panel current, on the LIST refresh tier.
86
88
 
87
89
  ## Choosing a portal
@@ -17,7 +17,9 @@ Every string is a markdown/text template run through the same `{{domain.path}}`
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
19
  | `x-lt-columns` | schema | Column definitions for `facet-table` layout: `[{ label, value, format?, priority?, width? }]` |
20
- | `x-lt-group-by` | schema | `facet-board`: the `"domain.path"` whose value identifies each entity |
20
+ | `x-lt-group-by` | schema | `facet-board`: the `"domain.path"` whose value identifies each entity. `facet-table`: a `"metadata.<key>"` whose rows read as one line (see [Grouped rows](#grouped-rows)) |
21
+ | `x-lt-related` | schema | `facet-table`: named related sets, a row's items or rows in other roles (see [Related sets](#related-sets)) |
22
+ | `x-lt-row-detail` | schema | `facet-table`: sections a row expands into, each listing a related set |
21
23
  | `x-lt-card` | schema | `facet-board`: the per-entity card — `{ title, state?, fields?: [{ label, value, format? }] }` |
22
24
  | `x-lt-row-action` | schema | The per-row action button: `{ action?, label?, durationMinutes? }` — see below |
23
25
 
@@ -144,3 +146,88 @@ Cards are fully interactive (`x-lt-group-by` should be a `metadata.*` path so th
144
146
  - **The header magnifier** opens the card's refine dialog — the entity identity plus every field bound to a pure `{{metadata.KEY}}` token, as touch-sized toggle rows. Selections AND into one query: **Filter <role>**, **Search everywhere**, or **Add to filters** (merge into the live set). The same row gesture the facet table carries, always visible — no hover required.
145
147
 
146
148
  The reference: `examples/seed-fleet-sim.ts` — one advert per machine, a `format: "age"` "Since" field, and role default pins (see [pinned-views.md](pinned-views.md)).
149
+
150
+
151
+ ---
152
+
153
+ ## Related sets
154
+
155
+ A `facet-table` row is often a **container**: it holds items (an accumulator or batch row), and other rows are on their way to it. A related set names one of those collections once; columns and row details refer to it by name.
156
+
157
+ ```jsonc
158
+ "x-lt-related": {
159
+ "contents": { "source": "items" },
160
+ "coming": {
161
+ "source": "query",
162
+ "query": {
163
+ "segment": "order-prep", // or "roles": ["order-prep", "order-check"]
164
+ "facets": { "destination": "{{metadata.destination}}" },
165
+ "narrow": { "serviceLevel": "{{metadata.lane}}" }, // applies when the row has a lane
166
+ "status": "pending" // the default
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ - **`items`**: the row's held items (`envelope.accumulate_items`, or a batch row's `batch_items`). Each item reads through its own `payload` and, for a reciprocal add, through the **reciprocal row** (the item's own escalation).
173
+ - **`query`**: rows in other roles whose metadata contains the row's facets. Facet values are `{{domain.path}}` templates over the host row; a lone token keeps the value's JSON type, so a numeric facet matches a numeric facet. `roles` lists the roles in display order; `segment` names a Pace Board sequence by its first role (the chain composed with `parent_role`), so the sequence and its station titles come from the board. A host whose facets do not resolve shows an em dash and runs no query. `status` defaults to `pending`, which includes claimed rows: a claim leaves a row pending, so an order someone is working still counts as coming. `narrow` facets apply only when the row resolves them, so the facets drive the hierarchy: a lane (a bin carrying `lane`) looks ahead to its own service level only, a bin without lanes to its whole destination, and a grouped tub reads the union of its lanes.
174
+
175
+ A schema declares up to 4 sets; a query names up to 12 roles.
176
+
177
+ ### Related columns
178
+
179
+ A column with `related` aggregates its set for each row:
180
+
181
+ ```jsonc
182
+ { "label": "Holds", "related": "contents", "aggregate": "count",
183
+ "splitBy": "reciprocal.metadata.serviceLevel", "labels": { "standard": "Standard", "express": "Express" } },
184
+ { "label": "Coming", "related": "coming", "aggregate": "count", "splitBy": "role" }
185
+ ```
186
+
187
+ The cell reads `3 · Standard 2 · Express 1`: the count, then each split value as a chip. `splitBy` takes:
188
+
189
+ | Set | `splitBy` |
190
+ |-----|-----------|
191
+ | `items` | `payload.<path>` or `reciprocal.metadata.<key>` |
192
+ | `query` | `role` (chips in sequence order, labeled by role title) or `metadata.<key>` |
193
+
194
+ `labels` maps split values to display text. A `role` chip opens that role's list filtered to the row's facets.
195
+
196
+ ### Row detail
197
+
198
+ `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:
199
+
200
+ ```jsonc
201
+ "x-lt-row-detail": [
202
+ { "related": "contents", "label": "Holds", "columns": [
203
+ { "label": "Order", "value": "{{item.itemKey}}" },
204
+ { "label": "Service", "value": "{{metadata.serviceLevel}}" },
205
+ { "label": "Placed", "value": "{{item.at}}", "format": "date" } ] },
206
+ { "related": "coming", "label": "Coming", "columns": [
207
+ { "label": "Order", "value": "{{metadata.orderId}}" },
208
+ { "label": "At", "value": "{{escalation.role}}", "format": "role" },
209
+ { "label": "Since", "value": "{{escalation.created_at}}", "format": "age" } ] }
210
+ ]
211
+ ```
212
+
213
+ Item sections read `{{item.itemKey}}`, `{{item.payload.*}}`, `{{item.actor}}` and `{{item.at}}` beside the reciprocal row's domains; query sections read each related row's own domains. `format: "role"` renders a role name as its title. A sub-row opens its own row: an item's reciprocal row, or the related row. A section shows up to its `limit` rows (default 25, at most 100) with the total. The expansion folds with the table at narrow widths and inside a portal panel.
214
+
215
+ ### Grouped rows
216
+
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.
218
+
219
+ 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
+
221
+ ### Scope and cost
222
+
223
+ Related sets read under the viewer's own read scope, as every list does:
224
+
225
+ - An item total comes from the host row, so it shows whenever the row does. A split counts only reciprocal rows the viewer reads; when none are readable the cell shows the total with *split restricted*.
226
+ - 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
+ - A viewer who cannot read the host role gets a 404.
228
+
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.
230
+
231
+ 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
+
233
+ The reference: `examples/workflows/consolidation/` (roles seeded by `examples/seed-consolidation.ts`). Orders walk two stations and are staged; containers per destination read what they hold by service level and what is coming by station. `npm run consolidation:sim` drives a floor over HTTP; `KEEP=1` leaves it mid-flight.
@@ -35,16 +35,19 @@ A form field that takes a scan. While a claimed form is open and editable, a sca
35
35
  | `expect` | Context paths (`metadata.*`, `envelope.*`, `lookup.*`, …) whose values the field accepts. A path that holds a list contributes every entry. |
36
36
  | `expect-error` | The message for a scan outside `expect`; `{{expected}}` lists what the field accepts. Default: `Expected {{expected}}`. |
37
37
  | `multiplicity` | Array fields: `"count"` admits a value as many times as `expect` lists it (a part expected twice takes two scans); otherwise each expected value is admitted once. |
38
+ | `prompt` | Array fields: the instruction shown while the field is empty. Default: the field's `description`. |
38
39
 
39
40
  A string field is replaced by a scan. An array field appends, up to `maxItems`. Manufacturer barcodes compare as GTINs, so a UPC-A matches its 14-digit form.
40
41
 
42
+ An array scan field reads as a checklist: its prompt while empty, `n of N` beside the label, and a remove control on each scanned value while the form is editable. `N` is what `expect` admits (each listing under `multiplicity: "count"`, each distinct value otherwise), or `maxItems`, so the count and the admission gate agree. A removed value is admitted again on the next scan.
43
+
41
44
  ## Which field takes the scan
42
45
 
43
46
  The focused field, when it accepts the scan's scheme. Otherwise the first field in `x-lt-order` that accepts it and still has room. Otherwise the first field that accepts it.
44
47
 
45
48
  ## Expected values are checked on both sides
46
49
 
47
- A scan outside `expect` shows as an error under the form and leaves the field as it was. The same check runs in the shared validator at submit, so a typed value outside `expect` is a field error in the form and a 422 from the API.
50
+ A scan outside `expect` shows as an error directly under the field that refused it, and leaves the field as it was; an accepted scan shows a confirmation in the same place. Either way the field scrolls into view. The same check runs in the shared validator at submit, so a typed value outside `expect` is a field error in the form and a 422 from the API.
48
51
 
49
52
  ## `x-lt-scan-submit`
50
53
 
@@ -246,10 +246,16 @@ fill renders as a dash.
246
246
  "facts": [
247
247
  { "label": "Bin", "value": "{item.binCode}" },
248
248
  { "label": "Clinic", "value": "{item.facilityName}" },
249
- { "label": "Bags", "value": "{item.memberCount}" }
249
+ { "label": "Bags", "value": "{item.memberCount}" },
250
+ { "label": "Ship by", "value": "{item.releaseAt}", "format": "date" }
250
251
  ]
251
252
  ```
252
253
 
254
+ A fact with `format` (`date`, `age`, `ago`) reads one token: the station
255
+ receives the raw value and renders it with the list's formatter, so an ISO
256
+ instant in metadata reads the same on the station as in a list column (and
257
+ in the deployment's display time zone, when one is set).
258
+
253
259
  Without `facts`, the station lists the row's metadata, leaving out the
254
260
  bookkeeping a bench never acts on: scan provenance (`scannedAt`,
255
261
  `scanScheme`, `scanCategory`, `scanStation`, `scanActionName`),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.23.1",
3
+ "version": "0.23.2",
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",
@@ -48,6 +48,7 @@
48
48
  "ortho:populate": "ts-node scripts/ortho-populate.ts",
49
49
  "twin:farm": "ts-node scripts/twin-farm.ts",
50
50
  "printers:cycle": "ts-node scripts/printer-cycle.ts",
51
+ "consolidation:sim": "ts-node scripts/consolidation-sim.ts",
51
52
  "dashboard:install": "cd dashboard && npm install",
52
53
  "dashboard:dev": "cd dashboard && npm run dev",
53
54
  "dashboard:build": "cd dashboard && npm run build",
@@ -1,2 +0,0 @@
1
- import{a as m,j as e}from"./vendor-query-DvWWuNIB.js";import{w as ct,x as dt,c as ut,y as mt,M as Se,z as xt,A as ht,B as gt,E as ft,G as pt,H as bt,I as yt,K as jt,L as vt,O as Ct,Q as kt,r as Nt,R as wt,T as Pt,U as St,V as Et,W as Rt,X as Tt,Y as At,Z as Bt,_ as Ot,$ as Lt,a0 as Mt,a1 as Ft,a2 as zt,a3 as It,a4 as Ut,a5 as _t,a6 as $t}from"./index-BUYokcrl.js";import{a as Ee,u as Re,f as Vt}from"./vendor-react-_9U4mKFr.js";import{i as qt}from"./task-queues-7-sHKPsN.js";import{X as re,aj as Ht,x as Kt,ak as Dt,al as Gt,_ as Qt,i as Wt,am as Yt,P as Xt,an as Jt}from"./vendor-icons-CeVtUKyP.js";import{u as Te,C as Zt,r as es,B as ts,a as ss}from"./BulkAssignModal-COjoOIIH.js";import{E as as}from"./EscalationTitleSelect-Dewrv8wX.js";import{u as ns,E as is,a as ls,t as rs}from"./EscalationTimeline-DNKNp6pL.js";import{i as os,E as cs}from"./EscalationListView-DTIVuym4.js";import{u as ds}from"./useFilterParams-DBRw1Hcv.js";import{u as us}from"./useDebouncedValue-BYqbcism.js";import{D as ms}from"./DataTable-spX1dFyb.js";import{S as xs}from"./StickyPagination-DsdtYoXR.js";import{P as hs}from"./constants-CeBBTzf5.js";import{m as gs,E as fs}from"./escalation-columns-Bf09Q89t.js";import{R as ps,a as bs}from"./RowActions-Bdd7z4eB.js";import"./UserName-BDBDA-LR.js";import"./StatusBadge-DHVwxre2.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";import"./EntityTimelinePanel-BThdefKj.js";import"./FilterBar-D-6xVHIw.js";import"./PriorityBadge-r33mpDju.js";import"./RolePill-Di2CAHuD.js";import"./WorkflowPill-Dg7BDTyM.js";import"./CountdownTimer-BUBl_4mP.js";function ys(){const{pathname:t,search:n}=Ee(),u=Re(),{resolveUrl:l}=ct();m.useEffect(()=>{const g=t+n;if(dt(g).length===0)return;const p=l(g);p!==g&&u(p,{replace:!0})},[t,n,l,u])}const js=["<","<=",">",">=","="],vs=["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 Cs=t=>Object.entries(t??{}).map(([n,u])=>({key:n,value:String(u)})),ks=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 Ns({value:t,onChange:n,facetKeys:u=[],search:l="",onSearchChange:g}){const p=Cs(t.facets),b=ks(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})},R=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:[vs.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:js.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},R(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},R(i)}}),o<b.length&&e.jsx("button",{className:H,onClick:()=>R(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 ws({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(Ns,{value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g})]})]})}const Ps=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`,Ss="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 Es(t){var f;const n=Ps(t),u=Te(),{data:l}=ut(),g=mt(),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…"}),hs.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:Ss,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 Rs({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 Ts(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 As({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(Zt,{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 na(){var ke;ys();const t=Re(),{filters:n,setFilter:u,pagination:l}=ds({filters:{role:"",type:"",subtype:"",priority:"",status:"available",search:""}});xt({role:n.role||null,verbs:["created","claimed"]});const g=us(n.search),p=Te(),[b,f]=m.useState(null),[r,k]=m.useState("30"),[P,R]=m.useState(0),T=m.useCallback(s=>R(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]=Vt(),h=m.useMemo(()=>ht(L),[L]),N=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return gt(x,s),x.delete("page"),x})},[M]),{data:F}=ft(i),z=pt(h)+(n.search?1:0),G="facet-query",{setPanel:oe,closePanel:ce,open:Ae,ownerKey:Be}=bt();m.useEffect(()=>{if(!i){ce(G);return}oe(e.jsx(ws,{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=Ee(),{data:U}=yt(),ue=jt(),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:vt(),label:s.trim(),url:I.pathname+I.search,badge:!0}]})},[I.pathname,I.search,U,ue]),{canBulk:Ie}=Ct(),{kiosk:J}=kt(),me=h.facets?Object.keys(h.facets):[],Ue=L.get("view"),_e=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=Nt(),he=wt(),ge=Pt(),ee=St(),fe=Et(),te=Rt(),_=Tt(),{data:se}=At(),{data:S}=Bt(),{data:ae}=Ot(),{user:$,isSuperAdmin:Ve,hasRoleType:qe}=Lt(),pe=Ve||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)&&!qt(x.role))).map(x=>({value:x.role,label:Mt(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(()=>({...Ft(L,_t.AVAILABLE),search:g||void 0}),[L,g]),ye=100,{escalations:C,total:w,listSchema:Ke,singleRole:E,hasRichView:je,isLoading:De,isFetching:ve,error:V,refetch:Ge}=ns(ne,{limit:Z?ye:l.pageSize,offset:l.offset}),Qe=zt(E??"",void 0,!!E),ie=E?es((ke=Qe.data)==null?void 0:ke.form_schema).cancel:void 0,le=It(ne.view,je),We=le===$t.RICH,Ce=m.useMemo(()=>{if(!h.jeopardy||!E)return null;const s=((S==null?void 0:S.roles)??[]).find(x=>x.role===E),d=(s==null?void 0:s.priority_threshold_minutes)??(s==null?void 0:s.sla_minutes)??null;return d!=null?Ut(d*6e4):null},[h.jeopardy,E,S]),Ye=m.useMemo(()=>{const s=new Set;for(const d of C)y.has(d.id)&&s.add(d.role);return[...s]},[C,y]),Xe=m.useMemo(()=>C.filter(s=>y.has(s.id)&&os(s)).length,[C,y]),Je=m.useCallback(()=>v(new Set),[]),Ze=()=>{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:et,handleBulkClaim:tt,handleBulkTriage:st,handleBulkAssign:at,handleBulkUnassign:nt,handleBulkCancel:it}=Ts({selectedIds:y,clearSelection:Je,setPriority:he,bulkClaim:ge,bulkTriage:te,bulkAssign:ee,bulkUnassign:fe,bulkCancel:_,closeTriageModal:()=>W(!1),closeAssignModal:()=>Y(!1),closeCancelModal:()=>X(!1)}),lt=s=>{const d=new Set(y);d.has(s)?d.delete(s):d.add(s),v(d)},rt=()=>{y.size===C.length?v(new Set):v(new Set(C.map(s=>s.id)))},ot=[Ie?{key:"select",label:e.jsx("input",{type:"checkbox",checked:C.length>0&&y.size===C.length,onChange:rt,className:"rounded"}),render:s=>e.jsx("input",{type:"checkbox",checked:y.has(s.id),onChange:d=>{d.stopPropagation(),lt(s.id)},onClick:d=>d.stopPropagation(),className:"rounded"}),className:"w-10",priority:1}:{key:"spacer",label:"",render:()=>null,className:"w-10",priority:3},...gs({highlightKeys:me}),{key:"actions",label:"",render:s=>e.jsx(ps,{children:e.jsx(bs,{icon:Ht,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(as,{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(Kt,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsxs("div",{ref:c,className:"sticky top-0 z-20 bg-surface",children:[e.jsx(fs,{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(is,{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:Dt},{key:"rich",title:"Rich view",Icon:Gt},{key:"timeline",title:"Timeline view",Icon:Qt}].filter(s=>s.key!=="rich"||je).map(({key:s,title:d,Icon:x})=>e.jsx("button",{role:"radio","aria-checked":le===s,onClick:()=>_e(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(Wt,{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:()=>Ge(),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(Yt,{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(Xt,{className:"w-4 h-4"})})]})]})}),e.jsx(Es,{selectedCount:y.size,onClearSelection:()=>v(new Set),onSetPriority:et,onClaim:tt,onAssign:()=>Y(!0),onUnassign:nt,onTriage:()=>W(!0),onCancel:()=>X(!0),isPriorityPending:he.isPending,isClaimPending:ge.isPending,isAssignPending:ee.isPending,isUnassignPending:fe.isPending,isTriagePending:te.isPending,isCancelPending:_.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(Jt,{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"})]})]}),V&&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:V.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${V.message}`}),Z?e.jsx(ls,{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}):We?e.jsx(cs,{role:E,listSchema:Ke,activeEscalations:C,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(ms,{columns:ot,data:C,layout:"fixed",...rs(ne.layout),keyFn:s=>s.id,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),isLoading:De,emptyMessage:V?"Unable to load data":"No escalations"}),e.jsx(xs,{page:l.page,totalPages:l.totalPages(w),onPageChange:l.setPage,total:w,pageSize:l.pageSize,onPageSizeChange:l.setPageSize})]}),e.jsx(As,{claimTarget:b,onClose:()=>f(null),claimDuration:r,onDurationChange:s=>{k(s),R(0)},claimDurations:p,customClaimMinutes:P,onCustomClaimChange:T,onClaim:Ze,isPending:xe.isPending}),e.jsx(Rs,{open:Oe,onClose:()=>W(!1),selectedCount:y.size,onSubmit:st,isPending:te.isPending}),e.jsx(ts,{open:Le,onClose:()=>Y(!1),selectedCount:y.size,selectedRoles:Ye,claimedCount:Xe,onSubmit:at,isPending:ee.isPending}),e.jsx(ss,{open:Me,onClose:()=>X(!1),onConfirm:it,selectedCount:y.size,isPending:_.isPending,error:_.error,actionLabel:typeof ie=="string"?ie:void 0})]})}export{na as AvailableEscalationsPage};
2
- //# sourceMappingURL=AvailableEscalationsPage-CWMyy3IL.js.map