@hotmeshio/long-tail 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/README.md +4 -4
  2. package/build/api/escalations/accumulate.d.ts +96 -0
  3. package/build/api/escalations/accumulate.js +516 -0
  4. package/build/api/escalations/index.d.ts +1 -0
  5. package/build/api/escalations/index.js +10 -1
  6. package/build/api/roles.d.ts +4 -5
  7. package/build/api/roles.js +53 -4
  8. package/build/api/scan-codes/execute.js +2 -0
  9. package/build/api/scan-codes/verbs.d.ts +15 -0
  10. package/build/api/scan-codes/verbs.js +65 -0
  11. package/build/index.js +60 -0
  12. package/build/lib/db/schemas/036_role_portals.sql +12 -0
  13. package/build/routes/escalations/accumulate.d.ts +7 -0
  14. package/build/routes/escalations/accumulate.js +150 -0
  15. package/build/routes/escalations/index.js +5 -0
  16. package/build/sdk/index.d.ts +25 -0
  17. package/build/sdk/index.js +8 -0
  18. package/build/services/escalation/accumulate.d.ts +81 -0
  19. package/build/services/escalation/accumulate.js +154 -0
  20. package/build/services/escalation/index.d.ts +1 -0
  21. package/build/services/escalation/index.js +1 -0
  22. package/build/services/mcp/playwright-server/schemas.d.ts +2 -2
  23. package/build/services/orchestrator/condition.d.ts +40 -3
  24. package/build/services/orchestrator/condition.js +42 -2
  25. package/build/services/role/index.js +1 -0
  26. package/build/services/role/seed.js +6 -1
  27. package/build/services/role/sql.d.ts +6 -3
  28. package/build/services/role/sql.js +7 -2
  29. package/build/services/role/types.d.ts +38 -10
  30. package/build/services/role/types.js +10 -1
  31. package/build/services/scan-code/validate.js +16 -0
  32. package/build/shared/form-validation/display-only-widgets.d.ts +16 -0
  33. package/build/shared/form-validation/display-only-widgets.js +25 -0
  34. package/build/shared/form-validation/index.d.ts +2 -0
  35. package/build/shared/form-validation/index.js +2 -0
  36. package/build/shared/form-validation/x-lt-bind.d.ts +2 -14
  37. package/build/shared/form-validation/x-lt-bind.js +12 -8
  38. package/build/shared/form-validation/x-lt-invoke.d.ts +38 -0
  39. package/build/shared/form-validation/x-lt-invoke.js +103 -0
  40. package/build/system/mcp-servers/admin/escalations.js +39 -0
  41. package/build/system/mcp-servers/admin/schemas.d.ts +192 -13
  42. package/build/system/mcp-servers/admin/schemas.js +39 -3
  43. package/build/system/mcp-servers/admin/users.js +1 -0
  44. package/build/system/mcp-servers/docs.js +4 -0
  45. package/build/system/mcp-servers/human-queue-schemas.d.ts +85 -0
  46. package/build/system/mcp-servers/human-queue-schemas.js +19 -1
  47. package/build/system/mcp-servers/human-queue.d.ts +2 -0
  48. package/build/system/mcp-servers/human-queue.js +77 -0
  49. package/build/system/seed/tool-manifests-admin.d.ts +922 -103
  50. package/build/system/seed/tool-manifests-admin.js +4 -1
  51. package/build/system/seed/tool-manifests-escalation.d.ts +174 -0
  52. package/build/system/seed/tool-manifests-escalation.js +56 -0
  53. package/build/tsconfig.tsbuildinfo +1 -1
  54. package/build/types/escalation.d.ts +52 -0
  55. package/build/types/escalation.js +29 -1
  56. package/build/types/index.d.ts +2 -2
  57. package/build/types/index.js +3 -1
  58. package/build/types/scan-code.d.ts +24 -0
  59. package/build/types/scan-code.js +9 -0
  60. package/build/types/startup.d.ts +20 -0
  61. package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js → AdminDashboard-uarpHB88.js} +2 -2
  62. package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js.map → AdminDashboard-uarpHB88.js.map} +1 -1
  63. package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js → AgentConfigPage-BcUaDD5E.js} +6 -6
  64. package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js.map → AgentConfigPage-BcUaDD5E.js.map} +1 -1
  65. package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js → AgentDetailPage-BaZBhK6i.js} +3 -3
  66. package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js.map → AgentDetailPage-BaZBhK6i.js.map} +1 -1
  67. package/dashboard/dist/assets/AgentsPage-CuVFSDc4.js +2 -0
  68. package/dashboard/dist/assets/{AgentsPage-7JJBHku8.js.map → AgentsPage-CuVFSDc4.js.map} +1 -1
  69. package/dashboard/dist/assets/AvailableEscalationsPage-iO5NyyIK.js +2 -0
  70. package/dashboard/dist/assets/AvailableEscalationsPage-iO5NyyIK.js.map +1 -0
  71. package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js → BotPicker-CClMby6B.js} +2 -2
  72. package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js.map → BotPicker-CClMby6B.js.map} +1 -1
  73. package/dashboard/dist/assets/BulkAssignModal-BL8FRgkN.js +2 -0
  74. package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BL8FRgkN.js.map} +1 -1
  75. package/dashboard/dist/assets/CapabilitiesPage-D53ogPor.js +2 -0
  76. package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-D53ogPor.js.map} +1 -1
  77. package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-ow8jpbtD.js} +2 -2
  78. package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js.map → CollapsibleSection-ow8jpbtD.js.map} +1 -1
  79. package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-CeEDt9iJ.js} +2 -2
  80. package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js.map → ConfirmDeleteModal-CeEDt9iJ.js.map} +1 -1
  81. package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js → CountdownTimer-CSqyZMCG.js} +2 -2
  82. package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-CSqyZMCG.js.map} +1 -1
  83. package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js → CredentialsPage-Dx7SxA23.js} +2 -2
  84. package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-Dx7SxA23.js.map} +1 -1
  85. package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js → CronLabel-LYPxpvNN.js} +2 -2
  86. package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js.map → CronLabel-LYPxpvNN.js.map} +1 -1
  87. package/dashboard/dist/assets/DataTable-spX1dFyb.js +2 -0
  88. package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +1 -0
  89. package/dashboard/dist/assets/{DropZone-XlcY8hEH.js → DropZone-f1o-GLM8.js} +2 -2
  90. package/dashboard/dist/assets/{DropZone-XlcY8hEH.js.map → DropZone-f1o-GLM8.js.map} +1 -1
  91. package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js → ElapsedCell-BZJTSm9N.js} +2 -2
  92. package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js.map → ElapsedCell-BZJTSm9N.js.map} +1 -1
  93. package/dashboard/dist/assets/EntityTimelinePanel-0wIIW2en.js +2 -0
  94. package/dashboard/dist/assets/{EntityTimelinePanel-CkF-oW-m.js.map → EntityTimelinePanel-0wIIW2en.js.map} +1 -1
  95. package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js → EscalationListSchemaPage-CoYvtMzj.js} +3 -3
  96. package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js.map → EscalationListSchemaPage-CoYvtMzj.js.map} +1 -1
  97. package/dashboard/dist/assets/EscalationListView-DWFHPufv.js +2 -0
  98. package/dashboard/dist/assets/EscalationListView-DWFHPufv.js.map +1 -0
  99. package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js → EscalationSchemaPage-C9Xu_A25.js} +3 -3
  100. package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js.map → EscalationSchemaPage-C9Xu_A25.js.map} +1 -1
  101. package/dashboard/dist/assets/EscalationTimeline-D8W2LNNk.js +2 -0
  102. package/dashboard/dist/assets/EscalationTimeline-D8W2LNNk.js.map +1 -0
  103. package/dashboard/dist/assets/EscalationTitleSelect-DLK8NWMp.js +2 -0
  104. package/dashboard/dist/assets/EscalationTitleSelect-DLK8NWMp.js.map +1 -0
  105. package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js → EscalationsOverview-CW57FaP9.js} +2 -2
  106. package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js.map → EscalationsOverview-CW57FaP9.js.map} +1 -1
  107. package/dashboard/dist/assets/{EventTable-Ike2xchn.js → EventTable-D1ctWhKf.js} +2 -2
  108. package/dashboard/dist/assets/{EventTable-Ike2xchn.js.map → EventTable-D1ctWhKf.js.map} +1 -1
  109. package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js → FilterBar-C-iur-Nj.js} +2 -2
  110. package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js.map → FilterBar-C-iur-Nj.js.map} +1 -1
  111. package/dashboard/dist/assets/GraphInvokePage-CcA_44M4.js +2 -0
  112. package/dashboard/dist/assets/{GraphInvokePage-CKtvWowP.js.map → GraphInvokePage-CcA_44M4.js.map} +1 -1
  113. package/dashboard/dist/assets/HomePage-Dc085ghJ.js +2 -0
  114. package/dashboard/dist/assets/{HomePage-BQ3Q791Q.js.map → HomePage-Dc085ghJ.js.map} +1 -1
  115. package/dashboard/dist/assets/ListToolbar-h_ziBt4O.js +2 -0
  116. package/dashboard/dist/assets/{ListToolbar-DdJzj472.js.map → ListToolbar-h_ziBt4O.js.map} +1 -1
  117. package/dashboard/dist/assets/{McpOverview-BbtrduWn.js → McpOverview-qXXhbNWV.js} +2 -2
  118. package/dashboard/dist/assets/{McpOverview-BbtrduWn.js.map → McpOverview-qXXhbNWV.js.map} +1 -1
  119. package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js → McpQueryDetailPage-SEzSbZrd.js} +2 -2
  120. package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js.map → McpQueryDetailPage-SEzSbZrd.js.map} +1 -1
  121. package/dashboard/dist/assets/McpQueryPage-Cy0V0kv9.js +2 -0
  122. package/dashboard/dist/assets/{McpQueryPage-CfJy7HZ7.js.map → McpQueryPage-Cy0V0kv9.js.map} +1 -1
  123. package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js → McpRunDetailPage-DjJO5vSb.js} +2 -2
  124. package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js.map → McpRunDetailPage-DjJO5vSb.js.map} +1 -1
  125. package/dashboard/dist/assets/McpRunsPage-BfjiJ8mM.js +2 -0
  126. package/dashboard/dist/assets/{McpRunsPage-D7QXjW9z.js.map → McpRunsPage-BfjiJ8mM.js.map} +1 -1
  127. package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js → NamespacePill-DADRJOUl.js} +2 -2
  128. package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js.map → NamespacePill-DADRJOUl.js.map} +1 -1
  129. package/dashboard/dist/assets/OperationsPage-dJcER0T_.js +3 -0
  130. package/dashboard/dist/assets/OperationsPage-dJcER0T_.js.map +1 -0
  131. package/dashboard/dist/assets/OperatorDashboard-zCkW4eqk.js +2 -0
  132. package/dashboard/dist/assets/{OperatorDashboard-sXNDh1Ph.js.map → OperatorDashboard-zCkW4eqk.js.map} +1 -1
  133. package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js → PageHeader-Csq434-v.js} +2 -2
  134. package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js.map → PageHeader-Csq434-v.js.map} +1 -1
  135. package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js → PageHeaderWithStats-CSnk1p5A.js} +2 -2
  136. package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js.map → PageHeaderWithStats-CSnk1p5A.js.map} +1 -1
  137. package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js → PersonaDetailPage-Cx6L3Jvu.js} +2 -2
  138. package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js.map → PersonaDetailPage-Cx6L3Jvu.js.map} +1 -1
  139. package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js → PersonasPage-DOgGUlJl.js} +2 -2
  140. package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js.map → PersonasPage-DOgGUlJl.js.map} +1 -1
  141. package/dashboard/dist/assets/PortalPage-BKuL1BeJ.js +2 -0
  142. package/dashboard/dist/assets/PortalPage-BKuL1BeJ.js.map +1 -0
  143. package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js → ProcessDetailPage-BFcFSDUv.js} +2 -2
  144. package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js.map → ProcessDetailPage-BFcFSDUv.js.map} +1 -1
  145. package/dashboard/dist/assets/ProcessesListPage-BaHV2cXp.js +2 -0
  146. package/dashboard/dist/assets/{ProcessesListPage-CjwVKe32.js.map → ProcessesListPage-BaHV2cXp.js.map} +1 -1
  147. package/dashboard/dist/assets/ResolverForm-Bgc0Zrya.js +7 -0
  148. package/dashboard/dist/assets/ResolverForm-Bgc0Zrya.js.map +1 -0
  149. package/dashboard/dist/assets/RoleDetailPage-BPY6i3CU.js +8 -0
  150. package/dashboard/dist/assets/RoleDetailPage-BPY6i3CU.js.map +1 -0
  151. package/dashboard/dist/assets/{RolePill-DhnVPK4q.js → RolePill-BafrASDX.js} +2 -2
  152. package/dashboard/dist/assets/{RolePill-DhnVPK4q.js.map → RolePill-BafrASDX.js.map} +1 -1
  153. package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js → RolesPage-DSqqKPbv.js} +2 -2
  154. package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js.map → RolesPage-DSqqKPbv.js.map} +1 -1
  155. package/dashboard/dist/assets/RunAsSelector-B29iWwel.js +2 -0
  156. package/dashboard/dist/assets/{RunAsSelector-fFMt1bGe.js.map → RunAsSelector-B29iWwel.js.map} +1 -1
  157. package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js → ScanCodesPage-S8aAJfnC.js} +2 -2
  158. package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js.map → ScanCodesPage-S8aAJfnC.js.map} +1 -1
  159. package/dashboard/dist/assets/{ScanSchemeDetailPage-eKQpmsC_.js → ScanSchemeDetailPage-CUBRAtmJ.js} +2 -2
  160. package/dashboard/dist/assets/{ScanSchemeDetailPage-eKQpmsC_.js.map → ScanSchemeDetailPage-CUBRAtmJ.js.map} +1 -1
  161. package/dashboard/dist/assets/ScanStationPage-R9t1-CeQ.js +2 -0
  162. package/dashboard/dist/assets/{ScanStationPage-C1_ppDoZ.js.map → ScanStationPage-R9t1-CeQ.js.map} +1 -1
  163. package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js → ScopeBadge-b6MIBiYD.js} +2 -2
  164. package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js.map → ScopeBadge-b6MIBiYD.js.map} +1 -1
  165. package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js → StickyPagination-CkW_A507.js} +2 -2
  166. package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js.map → StickyPagination-CkW_A507.js.map} +1 -1
  167. package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js → StreamMessageDetail-yzWX0wac.js} +2 -2
  168. package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js.map → StreamMessageDetail-yzWX0wac.js.map} +1 -1
  169. package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js → SwimlaneTimeline-Cf4DXFxj.js} +2 -2
  170. package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js.map → SwimlaneTimeline-Cf4DXFxj.js.map} +1 -1
  171. package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js → TagInput-ZrIIrEUP.js} +2 -2
  172. package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js.map → TagInput-ZrIIrEUP.js.map} +1 -1
  173. package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js → TaskDetailPage-DCDcEps9.js} +2 -2
  174. package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js.map → TaskDetailPage-DCDcEps9.js.map} +1 -1
  175. package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js → TaskQueuePill-DkQ1uc6y.js} +2 -2
  176. package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js.map → TaskQueuePill-DkQ1uc6y.js.map} +1 -1
  177. package/dashboard/dist/assets/TasksListPage-BBATgpf7.js +2 -0
  178. package/dashboard/dist/assets/{TasksListPage-BB1f79lL.js.map → TasksListPage-BBATgpf7.js.map} +1 -1
  179. package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js → TimeAgo-CSNVEjch.js} +2 -2
  180. package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js.map → TimeAgo-CSNVEjch.js.map} +1 -1
  181. package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js → TimestampCell-Du1nBrPn.js} +2 -2
  182. package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js.map → TimestampCell-Du1nBrPn.js.map} +1 -1
  183. package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js → ToolPill-Baxm02L6.js} +2 -2
  184. package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js.map → ToolPill-Baxm02L6.js.map} +1 -1
  185. package/dashboard/dist/assets/ToolTestPanel-CF-h_5Rg.js +2 -0
  186. package/dashboard/dist/assets/{ToolTestPanel-Bwe3J5lj.js.map → ToolTestPanel-CF-h_5Rg.js.map} +1 -1
  187. package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js → TopicDetailPage-Dr1UmWcp.js} +3 -3
  188. package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js.map → TopicDetailPage-Dr1UmWcp.js.map} +1 -1
  189. package/dashboard/dist/assets/TopicsPage-CUUo-Ylf.js +2 -0
  190. package/dashboard/dist/assets/{TopicsPage-C1gxBUap.js.map → TopicsPage-CUUo-Ylf.js.map} +1 -1
  191. package/dashboard/dist/assets/{UserName-BzXJUE6q.js → UserName-kBh1dc39.js} +2 -2
  192. package/dashboard/dist/assets/{UserName-BzXJUE6q.js.map → UserName-kBh1dc39.js.map} +1 -1
  193. package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js → WorkflowExecutionPage-CCRSbnDx.js} +2 -2
  194. package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js.map → WorkflowExecutionPage-CCRSbnDx.js.map} +1 -1
  195. package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js → WorkflowPill-ZepbO_ny.js} +2 -2
  196. package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js.map → WorkflowPill-ZepbO_ny.js.map} +1 -1
  197. package/dashboard/dist/assets/WorkflowsDashboard-BNQVvyek.js +2 -0
  198. package/dashboard/dist/assets/{WorkflowsDashboard-CZAqRk1N.js.map → WorkflowsDashboard-BNQVvyek.js.map} +1 -1
  199. package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js → WorkflowsOverview-DswubNJN.js} +2 -2
  200. package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js.map → WorkflowsOverview-DswubNJN.js.map} +1 -1
  201. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js → YamlWorkflowDetailPage-Cw9Dlmup.js} +11 -11
  202. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js.map → YamlWorkflowDetailPage-Cw9Dlmup.js.map} +1 -1
  203. package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js → YamlWorkflowsPage-DB8xnIXy.js} +2 -2
  204. package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js.map → YamlWorkflowsPage-DB8xnIXy.js.map} +1 -1
  205. package/dashboard/dist/assets/{agents-gV0Ys-sY.js → agents-BwEnf6N9.js} +2 -2
  206. package/dashboard/dist/assets/{agents-gV0Ys-sY.js.map → agents-BwEnf6N9.js.map} +1 -1
  207. package/dashboard/dist/assets/{bots-B97itB3I.js → bots-CCmJTT2u.js} +2 -2
  208. package/dashboard/dist/assets/{bots-B97itB3I.js.map → bots-CCmJTT2u.js.map} +1 -1
  209. package/dashboard/dist/assets/{capabilities-CR9xZgGd.js → capabilities-BZHgp_nh.js} +2 -2
  210. package/dashboard/dist/assets/{capabilities-CR9xZgGd.js.map → capabilities-BZHgp_nh.js.map} +1 -1
  211. package/dashboard/dist/assets/{constants-BHkpVaqx.js → constants-CeBBTzf5.js} +2 -2
  212. package/dashboard/dist/assets/{constants-BHkpVaqx.js.map → constants-CeBBTzf5.js.map} +1 -1
  213. package/dashboard/dist/assets/{controlplane-YxvP1KCa.js → controlplane-CyfwUlFA.js} +2 -2
  214. package/dashboard/dist/assets/{controlplane-YxvP1KCa.js.map → controlplane-CyfwUlFA.js.map} +1 -1
  215. package/dashboard/dist/assets/escalation-columns-BJPTNmLW.js +2 -0
  216. package/dashboard/dist/assets/escalation-columns-BJPTNmLW.js.map +1 -0
  217. package/dashboard/dist/assets/index-3gbd5neL.js +67 -0
  218. package/dashboard/dist/assets/index-3gbd5neL.js.map +1 -0
  219. package/dashboard/dist/assets/index-BAAVTyZ-.js +2 -0
  220. package/dashboard/dist/assets/{index-BQpV-DTG.js.map → index-BAAVTyZ-.js.map} +1 -1
  221. package/dashboard/dist/assets/{index-B9BBCqLI.js → index-BC6Jenlo.js} +2 -2
  222. package/dashboard/dist/assets/{index-B9BBCqLI.js.map → index-BC6Jenlo.js.map} +1 -1
  223. package/dashboard/dist/assets/index-C7KHqOTQ.js +2 -0
  224. package/dashboard/dist/assets/{index-Bp9KBLT5.js.map → index-C7KHqOTQ.js.map} +1 -1
  225. package/dashboard/dist/assets/index-CDrqqbSR.js +3 -0
  226. package/dashboard/dist/assets/index-CDrqqbSR.js.map +1 -0
  227. package/dashboard/dist/assets/index-CVwzCZ43.js +2 -0
  228. package/dashboard/dist/assets/{index-CFbo9FU9.js.map → index-CVwzCZ43.js.map} +1 -1
  229. package/dashboard/dist/assets/index-CaGF6TCC.js +2 -0
  230. package/dashboard/dist/assets/index-CaGF6TCC.js.map +1 -0
  231. package/dashboard/dist/assets/index-ClVbfe4z.js +13 -0
  232. package/dashboard/dist/assets/{index-Cfvkl2J0.js.map → index-ClVbfe4z.js.map} +1 -1
  233. package/dashboard/dist/assets/{index-DMeaiKgf.js → index-CuVkSmj5.js} +2 -2
  234. package/dashboard/dist/assets/{index-DMeaiKgf.js.map → index-CuVkSmj5.js.map} +1 -1
  235. package/dashboard/dist/assets/{index-ipqwPavs.js → index-DAuX_PlL.js} +2 -2
  236. package/dashboard/dist/assets/{index-ipqwPavs.js.map → index-DAuX_PlL.js.map} +1 -1
  237. package/dashboard/dist/assets/{index-CIpHj4di.js → index-DBWS5QL8.js} +2 -2
  238. package/dashboard/dist/assets/{index-CIpHj4di.js.map → index-DBWS5QL8.js.map} +1 -1
  239. package/dashboard/dist/assets/index-DIWCI6HC.js +2 -0
  240. package/dashboard/dist/assets/{index-CUZ6LYye.js.map → index-DIWCI6HC.js.map} +1 -1
  241. package/dashboard/dist/assets/{index-DwOnWeu8.js → index-DZ8X_Gp4.js} +2 -2
  242. package/dashboard/dist/assets/{index-DwOnWeu8.js.map → index-DZ8X_Gp4.js.map} +1 -1
  243. package/dashboard/dist/assets/index-Dh8MJl3L.css +1 -0
  244. package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js → knowledge-CqyLhUMg.js} +2 -2
  245. package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js.map → knowledge-CqyLhUMg.js.map} +1 -1
  246. package/dashboard/dist/assets/{mcp-CH13hNH2.js → mcp-Cvu6bFYH.js} +2 -2
  247. package/dashboard/dist/assets/{mcp-CH13hNH2.js.map → mcp-Cvu6bFYH.js.map} +1 -1
  248. package/dashboard/dist/assets/{mcp-query-Duydd3JA.js → mcp-query-qC6A3e9l.js} +2 -2
  249. package/dashboard/dist/assets/{mcp-query-Duydd3JA.js.map → mcp-query-qC6A3e9l.js.map} +1 -1
  250. package/dashboard/dist/assets/metadata-display-COo3mMCr.js +2 -0
  251. package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +1 -0
  252. package/dashboard/dist/assets/{personas-mDk4lLQS.js → personas-BKN_lJuV.js} +2 -2
  253. package/dashboard/dist/assets/{personas-mDk4lLQS.js.map → personas-BKN_lJuV.js.map} +1 -1
  254. package/dashboard/dist/assets/{pipelines-B5GcgCeF.js → pipelines-BldIfv85.js} +2 -2
  255. package/dashboard/dist/assets/{pipelines-B5GcgCeF.js.map → pipelines-BldIfv85.js.map} +1 -1
  256. package/dashboard/dist/assets/{tasks-CItmNsRp.js → tasks-B-Uay8uL.js} +2 -2
  257. package/dashboard/dist/assets/{tasks-CItmNsRp.js.map → tasks-B-Uay8uL.js.map} +1 -1
  258. package/dashboard/dist/assets/{topics-CJYG7BX5.js → topics-438EQogt.js} +2 -2
  259. package/dashboard/dist/assets/{topics-CJYG7BX5.js.map → topics-438EQogt.js.map} +1 -1
  260. package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js +2 -0
  261. package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js.map +1 -0
  262. package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js → useDebouncedValue-Cw8hYZ8y.js} +2 -2
  263. package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js.map → useDebouncedValue-Cw8hYZ8y.js.map} +1 -1
  264. package/dashboard/dist/assets/{useNamespace-CHty0HAS.js → useNamespace-D1218GQ8.js} +2 -2
  265. package/dashboard/dist/assets/{useNamespace-CHty0HAS.js.map → useNamespace-D1218GQ8.js.map} +1 -1
  266. package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js → useYamlActivityEvents-BAQf_y_U.js} +2 -2
  267. package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js.map → useYamlActivityEvents-BAQf_y_U.js.map} +1 -1
  268. package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js → vendor-icons-B7OcUM6b.js} +2 -2
  269. package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js.map → vendor-icons-B7OcUM6b.js.map} +1 -1
  270. package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js → yaml-workflows-CN01gEB0.js} +2 -2
  271. package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js.map → yaml-workflows-CN01gEB0.js.map} +1 -1
  272. package/dashboard/dist/index.html +3 -3
  273. package/docs/accumulator.md +113 -0
  274. package/docs/api/http/escalations.md +89 -0
  275. package/docs/api/http/roles.md +1 -0
  276. package/docs/api/sdk/escalations.md +91 -0
  277. package/docs/api/sdk/roles.md +2 -0
  278. package/docs/architecture.md +1 -1
  279. package/docs/code-owned-configuration.md +2 -1
  280. package/docs/dashboard.md +10 -4
  281. package/docs/hitl/design.md +1 -1
  282. package/docs/hitl/escalation.md +37 -1
  283. package/docs/hitl/invoke-form.md +4 -0
  284. package/docs/hitl/pinned-views.md +4 -0
  285. package/docs/hitl/portal.md +97 -0
  286. package/docs/hitl/resolution.md +41 -0
  287. package/docs/hitl/x-lt-embed.md +1 -1
  288. package/docs/hitl/x-lt-invoke.md +95 -0
  289. package/docs/hitl/x-lt-list-schema.md +3 -1
  290. package/docs/hitl/x-lt-widget.md +1 -0
  291. package/docs/hitl-guide.md +8 -1
  292. package/docs/scan-codes.md +15 -2
  293. package/docs/sdk.md +1 -1
  294. package/docs/workflows.md +2 -2
  295. package/package.json +4 -2
  296. package/dashboard/dist/assets/AgentsPage-7JJBHku8.js +0 -2
  297. package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js +0 -2
  298. package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js.map +0 -1
  299. package/dashboard/dist/assets/BulkAssignModal-NJBcoj-f.js +0 -2
  300. package/dashboard/dist/assets/CapabilitiesPage-F8dpNn9B.js +0 -2
  301. package/dashboard/dist/assets/DataTable-7C7riavf.js +0 -2
  302. package/dashboard/dist/assets/DataTable-7C7riavf.js.map +0 -1
  303. package/dashboard/dist/assets/EntityTimelinePanel-CkF-oW-m.js +0 -2
  304. package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js +0 -2
  305. package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js.map +0 -1
  306. package/dashboard/dist/assets/GraphInvokePage-CKtvWowP.js +0 -2
  307. package/dashboard/dist/assets/HomePage-BQ3Q791Q.js +0 -2
  308. package/dashboard/dist/assets/ListToolbar-DdJzj472.js +0 -2
  309. package/dashboard/dist/assets/McpQueryPage-CfJy7HZ7.js +0 -2
  310. package/dashboard/dist/assets/McpRunsPage-D7QXjW9z.js +0 -2
  311. package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js +0 -3
  312. package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js.map +0 -1
  313. package/dashboard/dist/assets/OperatorDashboard-sXNDh1Ph.js +0 -2
  314. package/dashboard/dist/assets/ProcessesListPage-CjwVKe32.js +0 -2
  315. package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js +0 -3
  316. package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js.map +0 -1
  317. package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js +0 -8
  318. package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js.map +0 -1
  319. package/dashboard/dist/assets/RunAsSelector-fFMt1bGe.js +0 -2
  320. package/dashboard/dist/assets/ScanStationPage-C1_ppDoZ.js +0 -2
  321. package/dashboard/dist/assets/TasksListPage-BB1f79lL.js +0 -2
  322. package/dashboard/dist/assets/ToolTestPanel-Bwe3J5lj.js +0 -2
  323. package/dashboard/dist/assets/TopicsPage-C1gxBUap.js +0 -2
  324. package/dashboard/dist/assets/WorkflowsDashboard-CZAqRk1N.js +0 -2
  325. package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js +0 -2
  326. package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js.map +0 -1
  327. package/dashboard/dist/assets/index-3ezfWLkE.js +0 -6
  328. package/dashboard/dist/assets/index-3ezfWLkE.js.map +0 -1
  329. package/dashboard/dist/assets/index-BQpV-DTG.js +0 -2
  330. package/dashboard/dist/assets/index-Bp9KBLT5.js +0 -2
  331. package/dashboard/dist/assets/index-Bpvfr4OW.css +0 -1
  332. package/dashboard/dist/assets/index-CFbo9FU9.js +0 -2
  333. package/dashboard/dist/assets/index-CIwlVfvV.js +0 -67
  334. package/dashboard/dist/assets/index-CIwlVfvV.js.map +0 -1
  335. package/dashboard/dist/assets/index-CUZ6LYye.js +0 -2
  336. package/dashboard/dist/assets/index-Cfvkl2J0.js +0 -13
  337. package/dashboard/dist/assets/index-SGyrXGp8.js +0 -3
  338. package/dashboard/dist/assets/index-SGyrXGp8.js.map +0 -1
  339. package/dashboard/dist/assets/invoke-context-DrVyUEfs.js +0 -2
  340. package/dashboard/dist/assets/invoke-context-DrVyUEfs.js.map +0 -1
  341. package/dashboard/dist/assets/metadata-display--TzK0REC.js +0 -2
  342. package/dashboard/dist/assets/metadata-display--TzK0REC.js.map +0 -1
  343. package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js +0 -2
  344. package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js.map +0 -1
  345. package/docs/compilation.md +0 -152
  346. package/docs/compiler.md +0 -311
  347. package/docs/contributing.md +0 -56
  348. package/docs/design-principles.md +0 -245
  349. package/docs/schema-exchange.md +0 -173
  350. package/docs/self-test.md +0 -106
  351. package/docs/story.md +0 -184
@@ -40,6 +40,10 @@ A role may declare `default_pins: [{ label, url, badge? }]` (edited on Role Deta
40
40
 
41
41
  Membership *is* the persona's bookmark set — no per-user setup. Duplicate labels across a user's roles collapse to the first role's pin.
42
42
 
43
+ ## Portal
44
+
45
+ A role can lay its pins out as pages: `portals` is a list of named matrices, each an array of rows of pins, rendered at `/portal/<role>/<key>` as a grid of live list panels. Members choose one from the global menu, each also leads the role's group in the nav, and a kiosk role lands on its first portal as home. See [portal.md](portal.md).
46
+
43
47
  ## Reference Example
44
48
 
45
49
  The `fleet-servicer` seed (`examples/seed-fleet-sim.ts`) ships a facet-board list schema, jeopardy dials, and three default pins — the board, a badged "Needs harvesting" facet query, and a badged jeopardy view — so the whole persona story is exercisable from the dashboard. The seeded `reviewer` user is a member.
@@ -0,0 +1,97 @@
1
+ # Portals: a role's pinned views as pages
2
+
3
+ A role can declare **portals**: named matrices of pinned views, each rendered as a single page of live list panels at `/portal/<role>/<key>`. A matrix is an array of rows, each row an array of cells, each cell a pin. One row with one cell fills the page with that view. Two rows, the first holding one cell and the second three, give a full-width band over three columns. A 2x2 splits one queue by region, each cell the same role scoped to a different facet. Cells carry nothing but the pin, so everything a pin already says composes for free: the view (`view=rich`, `table`, `timeline`), facet scopes, jeopardy, link variables, and the live count.
4
+
5
+ A role carries several portals because screens serve different purposes. One shows urgent items by facility on the floor, four facilities in a 2x2. Another is the day's focus for the team, one panel per person, each named for them and scoped to their facets, so everyone sees their own list under their own name. Members choose a portal from the global menu, where the kiosk queue picker already lives, and each portal also appears as a row under the role's group in the left nav. A kiosk role lands on its first portal as home.
6
+
7
+ ---
8
+
9
+ ## Declaring portals
10
+
11
+ `portals` on the role: a list of `{ key, label, rows }`. `key` is a short url-safe slug, unique within the role, and the portal's address segment. `label` is the name shown in the menu and the nav. `rows` is the matrix: up to 4 rows of up to 6 cells, every row holding at least one cell, every cell `{ label, url, badge? }` with a dashboard-relative `url`, the `default_pins` shape.
12
+
13
+ ```typescript
14
+ roles: [
15
+ {
16
+ role: 'printer-fleet',
17
+ portals: [
18
+ {
19
+ key: 'floor',
20
+ label: 'Floor screen',
21
+ rows: [
22
+ [{ label: 'Fleet board', url: '/escalations/available?role=printer-fleet&view=rich' }],
23
+ [
24
+ { label: 'North', url: '/escalations/available?role=printer-fleet&facets=%7B%22facility%22%3A%22north%22%7D&view=table', badge: true },
25
+ { label: 'South', url: '/escalations/available?role=printer-fleet&facets=%7B%22facility%22%3A%22south%22%7D&view=table', badge: true },
26
+ { label: 'Harvest queue', url: '/escalations/available?role=printer-harvest&view=table', badge: true },
27
+ ],
28
+ ],
29
+ },
30
+ {
31
+ key: 'focus',
32
+ label: 'Focus of the day',
33
+ rows: [[
34
+ { label: 'Jim', url: '/escalations/available?role=printer-fleet&facets=%7B%22owner%22%3A%22jim%22%7D' },
35
+ { label: 'Sally', url: '/escalations/available?role=printer-fleet&facets=%7B%22owner%22%3A%22sally%22%7D' },
36
+ { label: 'Anu', url: '/escalations/available?role=printer-fleet&facets=%7B%22owner%22%3A%22anu%22%7D' },
37
+ ]],
38
+ },
39
+ ],
40
+ },
41
+ ],
42
+ ```
43
+
44
+ ### Counts above the panels
45
+
46
+ A portal may lead with **counts**: `counts` is a list of `{ label, url, blurb? }` (up to 8). Each becomes a tile above the panels showing the live total of its list URL, the same number a pin badge carries, under the label and over the blurb, and the tile opens the list. A queue's counts read at a glance before its lists do:
47
+
48
+ ```typescript
49
+ {
50
+ key: 'review-desk',
51
+ label: 'Review desk',
52
+ counts: [
53
+ { label: 'Waiting', url: '/escalations/available?role=reviewer', blurb: 'Unclaimed items in the queue' },
54
+ { label: 'In progress', url: '/escalations/available?role=reviewer&status=claimed', blurb: 'Claimed and being worked' },
55
+ { label: 'Resolved', url: '/escalations/available?role=reviewer&status=resolved', blurb: 'Closed out by a reviewer' },
56
+ { label: 'Expired', url: '/escalations/available?role=reviewer&status=expired', blurb: 'Timed out before anyone acted' },
57
+ { label: 'Cancelled', url: '/escalations/available?role=reviewer&status=cancelled', blurb: 'Withdrawn by the workflow' },
58
+ ],
59
+ rows: [[
60
+ { label: 'Waiting', url: '/escalations/available?role=reviewer&view=table&layout=compact', badge: true },
61
+ { label: 'In progress', url: '/escalations/available?role=reviewer&status=claimed&view=table&layout=compact', badge: true },
62
+ ]],
63
+ }
64
+ ```
65
+
66
+ The `reviewer` role in the examples' start config (`index.ts`) declares exactly this portal, in code, with `reset: true` so it applies on every boot.
67
+
68
+ The same field rides `PATCH /api/roles/:role` and the `update_role` MCP tool. `null` clears every portal. Under code-owned configuration the declaration is compared in order and applied on every boot, so reordering portals or rows is a change.
69
+
70
+ ## Composing them in the dashboard
71
+
72
+ Role Detail carries a **Portal** section listing the role's portals. The editor draws what it produces: each portal a bounded sheet with a title band, each cell its own small panel, and dashed placeholders wherever a view can be added. Edits build the page's draft; **Save** writes them with the rest of the role, one `PATCH` into the role's `portals` column:
73
+
74
+ - **New portal**: type a name, then **Start it with a view** over the role's default pins and the admin's own pins. The first pick creates the portal; its key derives from the name. **Label and URL** adds a view that is not yet pinned.
75
+ - Each portal shows a sketch of its shape, its editable name, its key, **Open**, and a remove control. Each row lists its cells with an editable panel title (name a cell for the person or place it serves), the view its URL asks for (`rich`, `table`, `timeline`, or `default` when the role's list schema decides), the URL, and the device binding of any link variable it references.
76
+ - Each row ends with **Add a view to this row** (up to six); below the matrix, **Start a new row with a view** (up to four rows). Removing the last cell of a row removes the row; removing the last cell of a portal removes the portal.
77
+ - A **counts** strip leads each portal's body: **Add a count** picks a pin whose total becomes a tile; each tile's title and blurb edit in place.
78
+
79
+ ## The page
80
+
81
+ A portal page fills the content area with one grid row per declared row, each dividing its width evenly among its cells. Each panel is a bounded sheet with a tinted title band and its own scroll, drawn with the same components as the escalations list: the rich view when the role owns a non-table list schema and the pin does not ask for another, the table when it asks for one or the schema is plain, the timeline when asked. Count tiles, when declared, sit in one row above the panels: label, large number, blurb, each a link to its list. The band of every panel shows the pin's label, the live total, a view toggle (table or rich, when the role offers both), the sort direction, a refresh, and a link to the full view. The toggle and sort hold for the visit; the pin stays as authored. Rows open the item detail page, which returns to the portal. Up to 25 rows render per panel, then a quiet "N more in the full view" link. A narrow window stacks the cells in declaration order.
82
+
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
+
85
+ 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
+
87
+ ## Choosing a portal
88
+
89
+ The global menu (the user menu in the header) lists **Portals**: every portal of the roles the viewer belongs to, grouped by role when more than one role declares any; global viewers see every role's. A device dedicated to a portal, a screen on the floor, opens the menu once and lands there, the same gesture as choosing a kiosk queue. The left nav repeats each portal as a row leading the role's pinned group.
90
+
91
+ ## Kiosk
92
+
93
+ Kiosk home is the role's first portal when it declares any, and the role's escalation list otherwise. The station queue picker follows the same rule. `/portal` is on the kiosk allow-list beside the list, detail, and scan screens. See [Kiosk mode](../scan-codes.md#kiosk-mode--the-locked-station-viewport).
94
+
95
+ ## Reference example
96
+
97
+ The `printer-fleet` seed (`examples/seed-fleet-sim.ts`) declares two portals: **Floor screen**, the fleet board over the two facility tables and the harvest queue, and **By model**, one panel per printer model. Open Admin → Roles → printer-fleet → Portal to see them composed, and the user menu's Portals section to open either.
@@ -109,6 +109,47 @@ Each item validates against the same versioned role form a single-item resolve u
109
109
 
110
110
  Item keys are non-empty strings up to 128 characters; prefer URL-friendly names (`u1-L`). Payload keys inside each item are caller-owned — the platform reserves no names inside `batch_items` values. Every fill stamps `envelope.batch_filled_at[itemKey]` with the database clock in the same statement, so the row carries the collection timeline as row truth. After an SLA expiry (`conditional` returns `false`) the terminal row retains the partial `batch_items` and their timestamps — read them back with `GET /api/escalations/:id` or `getEscalationBySignalKey` from an activity.
111
111
 
112
+ ### Accumulator items
113
+
114
+ An accumulator escalation (a `conditionalAccumulator` wait declared with `accumulate: {...}`, see [Creating Escalations](escalation.md#open-accumulation--items-arrive-over-time)) holds items added over time. Add by id, by signal key, or by metadata facet:
115
+
116
+ ```typescript
117
+ const first = await lt.escalations.accumulate({
118
+ id: binId,
119
+ itemKey: orderId,
120
+ payload: { weight: 2 }, // optional; validates against the bin role's form
121
+ reciprocal: { id: bagEscalationId }, // optional; the bag's own row is written in the same statement
122
+ });
123
+ // → { outcome: 'accepted', count: 1, remaining: 11, escalationId,
124
+ // reciprocal: { outcome: 'completed', count: 1, escalationId, signaled: true } }
125
+
126
+ const second = await lt.escalations.accumulateBySignalKey({
127
+ signalKey: homeSignalId,
128
+ itemKey: 'order-2',
129
+ });
130
+
131
+ const last = await lt.escalations.accumulateByMetadata({
132
+ key: 'binKey',
133
+ value: binKey,
134
+ itemKey: 'order-12',
135
+ });
136
+ // → { outcome: 'completed', count: 12, remaining: 0, signaled: true, workflowId }
137
+
138
+ await lt.escalations.removeItem({ id: binId, itemKey: 'order-2' });
139
+ // → { outcome: 'removed', count: 11, escalationId }
140
+
141
+ const held = await lt.escalations.getItems({ id: binId });
142
+ // → { kind: 'accumulate', count, max, items: [{ itemKey, payload?, at, actor?, reciprocalId? }, ...] }
143
+ ```
144
+
145
+ Interim adds return `accepted` with the count held and the slots remaining (`null` when unbounded) and publish `escalation.updated` carrying `item_key`, `count`, `actor`, and `reciprocal_id`; the add that reaches `max` returns `completed`, the row resolved with `{ $accumulated, $trigger: 'count' }` as `resolver_payload` and the workflow woke with it, in the same statement. A key already held returns 409 (`duplicate-item`, safe under scanner double-reads); a full cap returns 409 (`full`); a row that is not an accumulator returns 400. Removals return the new count, publish `escalation.updated` with `removed: true`, and never wake the waiter.
146
+
147
+ Adds are claim-agnostic, the same rationale as batch fills: a container collects contributions from many hands. `assertClaim: true` (by-id form) opts into the caller's own live-claim assertion inside the guarded statement. Every add records the actor on the entry and merges `resolved_by` into the row's metadata, so the completing add's stamp is the resolution provenance and `$resolution` rides the completing wake.
148
+
149
+ A reciprocal names a second row by `id`, `signalKey`, or `key`/`value`; it is RBAC-gated before the statement (404 when the caller cannot see it, 403 when they see it but cannot act on it) and written in the same statement as the container, both or neither. The reciprocal row holds the container's id as its item key; a member declared `accumulate: { max: 1 }` completes and wakes on that add. When the reciprocal blocks the add, the response names why (`reciprocal-full`, `reciprocal-duplicate`, `reciprocal-terminal`, `reciprocal-not-accumulator`) and the container is untouched.
150
+
151
+ Item keys are non-empty strings up to 128 characters. Reserved accumulate keys (`accumulate_count`, `accumulate_max`, `accumulate_keys`) cannot appear in the `metadata` patch. A plain `resolve` on an accumulator row is the hand-close: the workflow receives the collection merged with the resolver payload under `$trigger: 'resolve'`, and the row stores the same. After the window closes the row is `expired` with the collection stored as `resolver_payload`, exactly what the workflow received.
152
+
112
153
  ### Resolving a set atomically
113
154
 
114
155
  When one decision settles a set of waits — each with its own payload — use `resolveAllOrNone`:
@@ -1,6 +1,6 @@
1
1
  # Embed and Navigation Widgets
2
2
 
3
- Three display-only widgets that surface related information inside an escalation's resolver form without leaving the page. All three produce **no resolver payload** they must never appear in the schema's `required` array and are always declared `readOnly: true`.
3
+ Three display-only widgets that surface related information inside an escalation's resolver form without leaving the page. All three produce **no resolver payload**: their keys are dropped from the submitted payload, they must never appear in the schema's `required` array, and they are always declared `readOnly: true`. The [`invoke`](x-lt-invoke.md) widget, which starts a workflow from the form, follows the same rules.
4
4
 
5
5
  | Widget | Token | What it shows |
6
6
  |--------|-------|---------------|
@@ -0,0 +1,95 @@
1
+ # x-lt-invoke — start a workflow from the form
2
+
3
+ A role's `form_schema` can place a control that starts another workflow: a link, an icon-link, or a button that either fires the workflow at once with a payload mapped from the escalation, or opens the workflow's own invoke form in a dialog, prefilled from the same mapping. The control reuses the Invoke Tool page end to end: the same per-caller list decides who sees it, the same `input_schema` gate validates the payload, the same registered icon leads the label, and the run's outcome arrives over the same live events.
4
+
5
+ The field is display-only. It carries no answer, is dropped from the resolver payload, and must never appear in `required`.
6
+
7
+ ```jsonc
8
+ "print_pamphlet": {
9
+ "type": "string",
10
+ "readOnly": true,
11
+ "x-lt-widget": "invoke",
12
+ "x-lt-invoke": {
13
+ "workflow": "printPamphlet",
14
+ "data": { "order": { "id": "{{metadata.orderId}}" }, "copies": 1 },
15
+ "metadata": { "escalationId": "{{escalation.id}}" },
16
+ "modal": true
17
+ },
18
+ "title": "Print pamphlet",
19
+ "description": "Prints the patient pamphlet for this order",
20
+ "x-lt-section": "Tools",
21
+ "x-lt-span": 2,
22
+ "x-lt-showIf": "metadata.orderId"
23
+ }
24
+ ```
25
+
26
+ ## The declaration
27
+
28
+ | Key | Type | Meaning |
29
+ |-----|------|---------|
30
+ | `workflow` | string | The `workflow_type` to start. Required. |
31
+ | `data` | object | The nested `data` the invoke API receives. Leaves interpolate `{{domain.path}}` tokens against the escalation context. Defaults to `{}`. |
32
+ | `metadata` | object | Extra run metadata, merged over the workflow's declared `envelopeSchema.metadata`. Same interpolation. |
33
+ | `modal` | boolean | `true` opens the workflow's invoke form prefilled; `false` (default) posts `data` at once. |
34
+ | `confirm` | string | Direct mode only: a prompt shown before the post. Tokens interpolate. |
35
+ | `variant` | `"link"` \| `"button"` | The control's shape. Defaults to `link`. |
36
+ | `icon` | boolean | Lead the label with the workflow's registered icon, the one the registry picker sets and the Invoke Tool page shows. Defaults to `true`. |
37
+
38
+ The field's `title` is the label; without one the workflow type reads as a title (`printPamphlet` → **Print Pamphlet**). `description` renders as the helper line beneath it. Every layout token composes: `x-lt-section`, `x-lt-span`, `x-lt-showIf`, `x-lt-order`.
39
+
40
+ ## Mapping values
41
+
42
+ `data` is written once, in the shape the workflow receives. In direct mode it is posted as resolved. In modal mode the same object prefills the workflow's `input_schema` by inverting each field's `x-lt-bind`, so a field bound to `printer.serialNumber` opens holding `data.printer.serialNumber`. A workflow without an `input_schema` gets its envelope template form with `data` merged over the template.
43
+
44
+ Interpolation keeps types:
45
+
46
+ | Leaf | Resolves to |
47
+ |------|-------------|
48
+ | `"{{metadata.copies}}"` | The raw context value: a number stays a number, a boolean a boolean, an array an array |
49
+ | `"ORD-{{metadata.orderId}}"` | A string |
50
+ | A token whose value is missing or null | The key is omitted, so the workflow's own defaults apply |
51
+ | A mixed string with any missing segment | The key is omitted |
52
+ | `1`, `true`, `"plain text"` | Passed through unchanged |
53
+
54
+ Objects and arrays recurse. The domains are the escalation form's: `escalation`, `metadata`, `envelope`, `payload`, `lookup`, and the live `resolver` values, so a mapping can carry what the operator has typed so far.
55
+
56
+ ## Who sees it
57
+
58
+ The control renders only for workflows the signed-in user may invoke, read from the same per-caller list that drives the Invoke Tool page and its nav entry. A workflow outside that list leaves no trace in the form. The server runs the same predicate on the post. The control follows the form's claim state: it is live once the operator has claimed the escalation, and it leaves the form once the escalation is resolved, cancelled, or expired.
59
+
60
+ One request serves every invoke field on the page, and the list is shared with the rest of the dashboard's cache.
61
+
62
+ ## Direct mode
63
+
64
+ Clicking the control posts `data` with the workflow's declared metadata (plus the field's `metadata` mapping) and the `certified` flag the workflow is registered with. The control gives way to **Working…** while the run is in flight, then reads **Completed** with the returned `data` as an outline beneath, or **Failed** with the reason. The outcome arrives over the same `system.workflow.{id}.completed` and `.failed` events the Invoke Tool page follows. Once the run has settled the control returns beneath the result, ready for another run. A warning offers to reconnect live events when they are off.
65
+
66
+ When the target declares an `input_schema`, the payload is checked against it before the post with the shared validation pass. Violations, from that check or from a server 422, list beneath the control with an **Open form** action that opens the workflow's form prefilled, so the operator completes what the mapping could not supply. A mapping meant for direct mode should satisfy the schema on its own; declare `confirm` when the action deserves a second look.
67
+
68
+ ## Modal mode
69
+
70
+ `"modal": true` opens the workflow's invoke form in a dialog headed by its icon and title: the full x-lt-* form when the workflow declares an `input_schema`, with pinned lookups resolved, conditional sections, and the shared validation pass; the envelope template form otherwise. Prefilled values sit in their fields ready to be changed. Issues and the form's `x-lt-help` render inside the dialog.
71
+
72
+ Submit posts exactly as the Invoke Tool page does, and the dialog becomes a receipt with one action. While the run works it shows the workflow's icon and **Working…** with a Close control; closing leaves the run going. On completion it reads **Completed** with the returned `data` as an outline and a **Done** button. On failure it reads **Failed** with the reason, **Try again** returns to the form holding what was typed, and Close dismisses. The backdrop does not dismiss the dialog; Escape and the close control do. Each opening starts clean.
73
+
74
+ ## Example
75
+
76
+ The `printer-fleet` role's work form offers the fleet tools for the machine on screen. Its escalations carry `metadata.serialNumber`, the same facet the fleet-tools serial lookup reads, so the dialog opens with the serial already chosen:
77
+
78
+ ```typescript
79
+ fleet_tools: {
80
+ type: 'string',
81
+ readOnly: true,
82
+ 'x-lt-widget': 'invoke',
83
+ 'x-lt-invoke': {
84
+ workflow: 'fleetTools',
85
+ modal: true,
86
+ data: { printer: { serialNumber: '{{metadata.serialNumber}}' } },
87
+ },
88
+ 'x-lt-section': 'Tools',
89
+ 'x-lt-span': 2,
90
+ title: 'Fleet tools',
91
+ description: 'Reprint a label, change filament, or report this machine offline',
92
+ }
93
+ ```
94
+
95
+ See [`examples/seed-fleet-sim.ts`](../../examples/seed-fleet-sim.ts) for the role and [invoke-form.md](invoke-form.md) for the `fleetTools` form it opens.
@@ -21,7 +21,9 @@ Every string is a markdown/text template run through the same `{{domain.path}}`
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 |
23
23
 
24
- `format: "age"` on a `facet-table` column or `facet-board` field renders a timestamp as a compact age (`12m`, `3h`, `2d`) with the absolute time as its tooltip, repainted each minute — aging interim states are scannable at a glance.
24
+ `format: "age"` (or its spoken twin `"ago"`) on a `facet-table` column or `facet-board` field renders a timestamp as a compact age (`12m`, `3h`, `2d`) with the absolute time as its tooltip, repainted each minute — aging interim states are scannable at a glance. `format: "date"` renders the full date the dashboard uses everywhere, hoverable for the exact time; a bare ISO timestamp with no format renders the same way. Both readings of a date column are useful: age for pace, date for the record.
25
+
26
+ The `facet-table` renders at the table's dense setting: small type and tight side padding, so a row of six values fits without truncating. When no column declares a `width`, the first column holds 200px and the rest share the remainder; the row action sizes to its label.
25
27
 
26
28
  `format: "user"` resolves a user-id token — `{{escalation.assigned_to}}` — to that person's display name. Resolution is batched: every id on a page is coalesced into one `POST /api/users/names` request returning display fields only (no secrets, scopes, or metadata), cached by id for the session and not refetched on window focus; a user edit invalidates the cache. It truncates with an ellipsis and carries the full name on hover; an unassigned row shows a quiet em dash. `assigned_to` is the claimant while the item is worked and stays as the resolver once it is resolved, so one column reads correctly across the row's whole life. The built-in table and timeline views carry this user column by default; authored templates opt in per column.
27
29
 
@@ -15,6 +15,7 @@ For rich inputs beyond standard HTML types, set `x-lt-widget` on any field:
15
15
  | `"link"` | ReadOnly navigation link. URL is an `x-lt-href` template with `{{domain.path}}` tokens. See [x-lt-embed.md](x-lt-embed.md). |
16
16
  | `"escalation"` | ReadOnly embedded escalation card. ID sourced from `x-lt-source`; optional `x-lt-fields` surfaces any metadata or resolver detail. See [x-lt-embed.md](x-lt-embed.md). |
17
17
  | `"escalation-list"` | ReadOnly embedded escalation list. Driven by an `x-lt-query` facet object; columns from `x-lt-columns`. See [x-lt-embed.md](x-lt-embed.md). |
18
+ | `"invoke"` | ReadOnly control that starts a workflow, directly or in a prefilled dialog. Target and payload mapping in `x-lt-invoke`. See [x-lt-invoke.md](x-lt-invoke.md). |
18
19
 
19
20
  ---
20
21
 
@@ -23,6 +23,8 @@ This works because the form is data: a JSON Schema stored on the role, versioned
23
23
  | A role-authored list page — document views, facet tables, entity card boards | List schema | [x-lt-list-schema.md](hitl/x-lt-list-schema.md) |
24
24
  | Rename the resolve footer, or claim-and-submit in one gesture | Footer tokens | [x-lt-footer.md](hitl/x-lt-footer.md) |
25
25
  | Block the resolve until embedded work drains, then auto-close when it does | `x-lt-submit-guard` | [x-lt-embed.md](hitl/x-lt-embed.md) |
26
+ | Start another workflow from inside the form, mapped from the record, directly or in a prefilled dialog | `x-lt-invoke` | [x-lt-invoke.md](hitl/x-lt-invoke.md) |
27
+ | A role's pinned views laid out as named pages of live panels | `portals` on the role | [portal.md](hitl/portal.md) |
26
28
  | A fully custom UI nothing above can express | Iframe viewport | [iframe.md](hitl/iframe.md) |
27
29
  | The same rich form for starting a workflow from the Invoke Tool page | `inputSchema` on the worker config | [invoke-form.md](hitl/invoke-form.md) |
28
30
 
@@ -91,9 +93,13 @@ Ordered as a learning path — each file adds one capability to the same form:
91
93
  | Custom widgets (checklist, file upload, code editor, signature, markdown) | [x-lt-widget.md](hitl/x-lt-widget.md) |
92
94
  | List schema (`active-history`, `active`, `facet-table`, `facet-board` cards) | [x-lt-list-schema.md](hitl/x-lt-list-schema.md) |
93
95
  | Embedded widgets (`link`, `escalation`, `escalation-list`) and the submit guard | [x-lt-embed.md](hitl/x-lt-embed.md) |
96
+ | Starting a workflow from the form (`x-lt-invoke`) | [x-lt-invoke.md](hitl/x-lt-invoke.md) |
97
+ | Pinned views, role default pins, link variables | [pinned-views.md](hitl/pinned-views.md) |
98
+ | Role portals: named matrices of pins rendered as pages | [portal.md](hitl/portal.md) |
94
99
  | Footer labels, claim-and-submit, and the list-driven "start" action | [x-lt-footer.md](hitl/x-lt-footer.md) |
95
100
  | Iframe viewport protocol | [iframe.md](hitl/iframe.md) |
96
101
  | Claim lifecycle, resolving from system code, outcome recording, cancellation | [resolution.md](hitl/resolution.md) |
102
+ | Open accumulators: the contract, guarantees, and operations for containers that fill over time | [accumulator.md](accumulator.md) |
97
103
  | Role routing, RBAC, scope, chains | [roles.md](hitl/roles.md) |
98
104
  | Pinned views, user preferences, role default pins | [pinned-views.md](hitl/pinned-views.md) |
99
105
  | Design principles, error display, instruction copy, custom stylesheets | [design.md](hitl/design.md) |
@@ -105,7 +111,8 @@ Ordered as a learning path — each file adds one capability to the same form:
105
111
  | Keyword | Level | Purpose |
106
112
  |---------|-------|---------|
107
113
  | `input.*` | domain | The live form values on the Invoke surface (alias of `resolver.*`) for `x-lt-showIf`, `x-lt-help`, and `x-lt-options` |
108
- | `x-lt-widget` | field | Rich control: `file-upload`, `code-editor`, `json`, `signature`, `rich-text`, `markdown`, `checklist`, `attachment` (alias `image`) |
114
+ | `x-lt-widget` | field | Rich control: `file-upload`, `code-editor`, `json`, `signature`, `rich-text`, `markdown`, `checklist`, `attachment` (alias `image`); display-only `link`, `escalation`, `escalation-list`, `invoke` |
115
+ | `x-lt-invoke` | field | With `x-lt-widget: "invoke"`: the workflow to start and the `{{domain.path}}` mapping into its payload; `modal` opens the workflow's form prefilled, otherwise the post fires directly and the run reports in place |
109
116
  | `x-lt-source` | field | Data path for context-driven widgets: `"domain.path"` or an ordered array of paths (first to resolve wins); may embed `{{domain.path}}` interpolation segments |
110
117
  | `x-lt-require-all` | field | Checklist completion guard — every item must be checked, except items declared `required: false` |
111
118
  | `x-lt-default-checked` | field | Checklist first-load default — an unanswered field initializes to every item checked (affirm-then-exception); saved answers are never clobbered |
@@ -98,6 +98,7 @@ Verbs are the canonical escalation actions:
98
98
  | `resolve` | Atomic claim + resolve with a canned payload | `resolverPayload`, `metadata` |
99
99
  | `escalate` | Create an escalation in another queue, optionally closing the located one | `targetRole`, `closeCurrent`, `escalationType`, `description`, `metadata` |
100
100
  | `cancel` | Claim-as-lock, then cancel | — |
101
+ | `accumulate` | Add the scanned item to an open accumulator escalation | `itemKey`, `resolverPayload`, `metadata`, `accumulate: { containerFacet, containerRoles, reciprocal }` |
101
102
 
102
103
  String values inside `resolverPayload` and `metadata` interpolate
103
104
  `{scan.target}`, `{scan.category}`, and `{scan.scannedAt}`. Every mutating
@@ -105,6 +106,17 @@ verb stamps provenance facets onto the row it touches — `scanScheme`,
105
106
  `scanCategory`, `scanActionName`, `scannedAt` — so scan-driven transitions
106
107
  stay queryable.
107
108
 
109
+ `accumulate` has two modes. With `params.accumulate.containerFacet` the
110
+ scanned target is the ITEM: the step locates the item's own pending row
111
+ through the scheme facet, reads that facet from the row (a bag row carrying
112
+ `binKey: "B-7"`), and adds the target to the pending accumulator whose
113
+ metadata carries the same value, writing the item's row as the reciprocal in
114
+ the same statement (`reciprocal: false` skips it; `containerRoles` names the
115
+ container queues). Without it the scanned target is the CONTAINER and the step
116
+ adds `params.itemKey` (a template) to it. An item with no row or no container
117
+ facet falls through to the next step; a container already holding the item
118
+ reports a conflict.
119
+
108
120
  Ordering is the power move: put the expected state first and a broad
109
121
  `show-detail` last. A machine whose twin is in the wrong queue still answers
110
122
  the scan — with where the twin actually is. **The scan is also a state
@@ -229,8 +241,9 @@ set with the same `PATCH /api/roles/:role` as every other dial). When the
229
241
  signed-in user is a **member of exactly that one role** — the station-login
230
242
  shape — the dashboard locks the viewport: the left nav is gone entirely, the
231
243
  role's escalation list is home (`/` and every other surface redirect to it),
232
- and the session is held to the list, the escalation detail page, and the scan
233
- screens (choice, badge). The header toolbar and event feed remain. A user
244
+ and the session is held to the list, the escalation detail page, the role's
245
+ portals, and the scan screens (choice, badge). A role that declares
246
+ [portals](./hitl/portal.md) lands on its first one as home instead of the list. The header toolbar and event feed remain. A user
234
247
  holding more than one role, or an admin-type grant, always gets full chrome —
235
248
  kiosk is for the single-role floor login, never a way to hide the product from
236
249
  a real operator.
package/docs/sdk.md CHANGED
@@ -63,7 +63,7 @@ The client mirrors the REST route structure:
63
63
  | Namespace | REST equivalent | Key operations |
64
64
  |-----------|----------------|----------------|
65
65
  | `lt.tasks` | `/api/tasks` | `list`, `get`, `listProcesses`, `getProcess`, `getProcessStats` |
66
- | `lt.escalations` | `/api/escalations` | `list`, `listAvailable`, `get`, `claim`, `release`, `resolve`, `escalate`, `bulkClaim`, `bulkAssign`, `findByMetadata`, `claimByMetadata`, `resolveByMetadata`, `resolveBatchItem`, `resolveBatchItemBySignalKey`, `resolveBatchItemByMetadata`, `aggregateByFacets`, `timelineByFacet` — see the [Escalations SDK reference](api/sdk/escalations.md) |
66
+ | `lt.escalations` | `/api/escalations` | `list`, `listAvailable`, `get`, `claim`, `release`, `resolve`, `escalate`, `bulkClaim`, `bulkAssign`, `findByMetadata`, `claimByMetadata`, `resolveByMetadata`, `resolveBatchItem`, `resolveBatchItemBySignalKey`, `resolveBatchItemByMetadata`, `accumulate`, `accumulateBySignalKey`, `accumulateByMetadata`, `removeItem`, `removeItemBySignalKey`, `removeItemByMetadata`, `getItems`, `aggregateByFacets`, `timelineByFacet` — see the [Escalations SDK reference](api/sdk/escalations.md) |
67
67
  | `lt.workflows` | `/api/workflows` | `invoke`, `getStatus`, `getResult`, `terminate`, `listWorkers`, `listDiscovered`, `listConfigs`, `getConfig`, `upsertConfig` |
68
68
  | `lt.yamlWorkflows` | `/api/yaml-workflows` | `list`, `get`, `create`, `deploy`, `activate`, `invoke`, `archive` |
69
69
  | `lt.users` | `/api/users` | `list`, `get`, `create`, `update`, `delete`, `getRoles`, `addRole`, `removeRole` |
package/docs/workflows.md CHANGED
@@ -50,7 +50,7 @@ A pipeline workflow is a compiled deterministic workflow. It is generated from a
50
50
 
51
51
  In the dashboard, pipeline workflows display a Wand2 (magic wand) icon in purple. They are managed from the **MCP Pipeline Tools** page and created through the **Pipeline Designer**.
52
52
 
53
- See the [Compilation Pipeline](compilation.md) guide for the full lifecycle from dynamic execution to deployed pipeline.
53
+ See the [Compilation Pipeline](https://github.com/hotmeshio/long-tail/blob/main/docs/donotpublish/compilation.md) guide for the full lifecycle from dynamic execution to deployed pipeline.
54
54
 
55
55
  ## Contents
56
56
 
@@ -713,4 +713,4 @@ The durable code is the spec — developer-friendly, familiar, testable with sta
713
713
  (write and test here) (deploy and run this)
714
714
  ```
715
715
 
716
- Write procedural because it's productive. Compile because it's fast. See the [Compiler Guide](compiler.md) for details.
716
+ Write procedural because it's productive. Compile because it's fast. See the [Compiler Guide](https://github.com/hotmeshio/long-tail/blob/main/docs/donotpublish/compiler.md) for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "Long Tail Workflows — Durable AI workflows with human-in-the-loop escalation. Powered by PostgreSQL.",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -16,6 +16,8 @@
16
16
  "!build/examples/",
17
17
  "docs/",
18
18
  "!docs/img/",
19
+ "!docs/donotcommit/",
20
+ "!docs/donotpublish/",
19
21
  "dashboard/dist/",
20
22
  "LICENSE",
21
23
  "README.md"
@@ -73,7 +75,7 @@
73
75
  "@anthropic-ai/sdk": "^0.92.0",
74
76
  "@aws-sdk/client-s3": "^3.1017.0",
75
77
  "@aws-sdk/s3-request-presigner": "^3.1045.0",
76
- "@hotmeshio/hotmesh": "^0.28.1",
78
+ "@hotmeshio/hotmesh": "^0.29.0",
77
79
  "@modelcontextprotocol/sdk": "^1.27.1",
78
80
  "@opentelemetry/exporter-trace-otlp-proto": "^0.215.0",
79
81
  "@opentelemetry/resources": "^2.5.1",
@@ -1,2 +0,0 @@
1
- import{j as t}from"./vendor-query-DvWWuNIB.js";import{u as f}from"./agents-gV0Ys-sY.js";import{c as b,y as v,bl as j,g as N}from"./index-CIwlVfvV.js";import{u as y}from"./useFilterParams-DBRw1Hcv.js";import{b as P}from"./api-path-u2Jf9QXS.js";import{D as w}from"./DataTable-7C7riavf.js";import{S}from"./StickyPagination-B91Pk9xh.js";import{F as k,b as A}from"./FilterBar-DMOR-O1c.js";import{P as _}from"./PageHeader-Di5Sz3an.js";import{L as C}from"./ListToolbar-DdJzj472.js";import{g as F}from"./vendor-icons-DeBdvyKJ.js";import{u as z}from"./vendor-react-_9U4mKFr.js";import"./EmptyState-DgC_6njU.js";const L=[{value:"active",label:"Active"},{value:"inactive",label:"Inactive"},{value:"paused",label:"Paused"},{value:"error",label:"Error"}],T=[{key:"name",label:"Agent",render:e=>t.jsxs("div",{className:"flex items-center gap-2.5 min-w-0",children:[t.jsx("span",{className:`w-2.5 h-2.5 rounded-full dot-ring shrink-0 ${e.status==="active"?"bg-status-success":e.status==="paused"?"bg-status-warning":e.status==="error"?"bg-status-error":"bg-surface-border"}`}),t.jsx("span",{className:"text-xs font-medium text-text-primary whitespace-nowrap",children:e.id}),e.description&&t.jsx("p",{className:"flex-1 min-w-0 truncate text-2xs text-text-tertiary",children:e.description})]})},{key:"knowledge_domain",label:"Knowledge",render:e=>e.knowledge_domain?t.jsx("span",{className:"text-2xs font-mono text-text-secondary whitespace-nowrap",children:e.knowledge_domain}):t.jsx("span",{className:"text-text-quaternary",children:"—"}),className:"w-28"},{key:"schedules",label:"Schedules",render:e=>{var r,i;const s=(r=e.behaviors)==null?void 0:r.schedules,a=s!=null&&s.length?s.map(c=>c.cron):(i=e.behaviors)!=null&&i.cron?[e.behaviors.cron]:[];return a.length?t.jsxs("span",{className:"text-2xs font-mono text-text-secondary whitespace-nowrap",children:[a[0],a.length>1?` +${a.length-1}`:""]}):t.jsx("span",{className:"text-text-quaternary",children:"—"})},className:"w-28"},{key:"subscriptions",label:"Subscriptions",render:e=>{var i;const s=e.subscription_count??0,a=e.sub_topics??[];if(!s)return t.jsx("span",{className:"text-text-quaternary",children:"—"});const r=((i=a[0])==null?void 0:i.replace(/^lt\.events\./,""))??"";return t.jsxs("span",{className:"text-2xs font-mono text-text-secondary whitespace-nowrap",children:[r,s>1?` +${s-1}`:""]})},className:"w-36"},{key:"last_run_at",label:"Last Run",render:e=>e.last_run_at?t.jsx("span",{className:"whitespace-nowrap",children:t.jsx(N,{date:e.last_run_at})}):t.jsx("span",{className:"text-text-quaternary",children:"—"}),className:"w-32"}];function G(){var p;const e=z(),{data:s}=b(),a=v(),r=a!==null?a:!!((p=s==null?void 0:s.ai)!=null&&p.enabled),i=r?"Agent":"Automation",c=r?"Agents":"Automations";j();const{filters:u,setFilter:d,pagination:n}=y({filters:{status:""}}),{data:o,isLoading:x,refetch:g,isFetching:h}=f({status:u.status||void 0,limit:n.pageSize,offset:n.offset}),m=(o==null?void 0:o.total)??0;return t.jsxs("div",{children:[t.jsx(_,{title:c,docsHash:"#docs:agents.md",actions:t.jsxs("button",{onClick:()=>e("/agents/new"),className:"flex items-center gap-2 px-4 py-2 text-sm rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors",children:[t.jsx(F,{className:"w-4 h-4"})," Create ",i]})}),t.jsx(k,{actions:t.jsx(C,{onRefresh:()=>g(),isFetching:h,apiPath:P("/agents",{limit:n.pageSize,offset:n.offset,status:u.status||void 0})}),children:t.jsx(A,{label:"Status",value:u.status,onChange:l=>d("status",l),options:L})}),t.jsx(w,{columns:T,data:(o==null?void 0:o.agents)??[],keyFn:l=>l.id,onRowClick:l=>e(`/agents/${l.id}`),isLoading:x,emptyMessage:`No ${c.toLowerCase()} found`}),t.jsx(S,{page:n.page,totalPages:n.totalPages(m),onPageChange:n.setPage,total:m,pageSize:n.pageSize,onPageSizeChange:n.setPageSize})]})}export{G as AgentsPage};
2
- //# sourceMappingURL=AgentsPage-7JJBHku8.js.map
@@ -1,2 +0,0 @@
1
- import{a as b,j as e}from"./vendor-query-DvWWuNIB.js";import{w as Rt,x as Lt,c as _t,y as Bt,M as We,z as _e,A as Ut,B as zt,E as qt,G as Dt,H as Vt,I as It,K as Gt,L as Ht,O as Qt,Q as Wt,R as Kt,r as Yt,T as Xt,U as Zt,V as Jt,W as es,X as ts,Y as ss,Z as as,_ as ns,$ as rs,a0 as is,a1 as ls,a2 as os,a3 as cs,a4 as ds,a5 as us,a6 as xs}from"./index-CIwlVfvV.js";import{a as Ke,u as Ye,L as Be,f as ms}from"./vendor-react-_9U4mKFr.js";import{i as hs}from"./task-queues-7-sHKPsN.js";import{X as se,ai as ps,aj as fs,d as gs,e as bs,ak as ys,b as vs,s as js,C as Ns,U as Cs,al as ks,w as ws,am as Ss,an as Ps,Y as Ms,i as Ts,ao as As,P as Es,ap as Os}from"./vendor-icons-DeBdvyKJ.js";import{u as Xe,C as $s,r as Fs,B as Rs,a as Ls}from"./BulkAssignModal-NJBcoj-f.js";import{m as _s,E as Bs,a as Us}from"./escalation-columns-uq-IV2aj.js";import{i as Ze,s as zs,E as qs}from"./EscalationListView-AHW2xtlr.js";import{u as Ds}from"./useFilterParams-DBRw1Hcv.js";import{u as Vs}from"./useDebouncedValue-BrwgXcp8.js";import{D as Is}from"./DataTable-7C7riavf.js";import{S as Gs}from"./StickyPagination-B91Pk9xh.js";import{P as Hs}from"./constants-BHkpVaqx.js";import{R as Qs,a as Ws}from"./RowActions-Bdd7z4eB.js";import{U as Ks}from"./UserName-BzXJUE6q.js";import"./EntityTimelinePanel-CkF-oW-m.js";import"./FilterBar-DMOR-O1c.js";import"./PriorityBadge-r33mpDju.js";import"./RolePill-DhnVPK4q.js";import"./WorkflowPill--AYMW7u_.js";import"./CountdownTimer-BxDub9d2.js";import"./StatusBadge-DHVwxre2.js";import"./EmptyState-DgC_6njU.js";function Ys(){const{pathname:t,search:s}=Ke(),i=Ye(),{resolveUrl:n}=Rt();b.useEffect(()=>{const m=t+s;if(Lt(m).length===0)return;const x=n(m);x!==m&&i(x,{replace:!0})},[t,s,n,i])}const Xs=["<","<=",">",">=","="],Zs=["priority","created_at","updated_at","status","role"],B="input text-xs py-1",Ue="select text-xs py-1",J="text-text-tertiary hover:text-text-primary transition-colors";function ze(t){return t==="true"?!0:t==="false"?!1:t.trim()!==""&&!Number.isNaN(Number(t))?Number(t):t}const Js=t=>Object.entries(t??{}).map(([s,i])=>({key:s,value:String(i)})),ea=t=>(t??[]).map(s=>{const[i,n]=Object.entries(s)[0]??["",""];return{key:i,value:String(n)}});function L({title:t,hint:s,children:i}){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})]}),i]})}function ee({value:t,onChange:s,placeholder:i}){return e.jsx("input",{list:"lt-facet-keys",className:`${B} w-40`,placeholder:i,value:t,onChange:n=>s(n.target.value)})}function ta({value:t,onChange:s,facetKeys:i=[],search:n="",onSearchChange:m}){const x=Js(t.facets),h=ea(t.block),f=t.range??[],o=t.exists??[],y=t.orderBy??[],N=r=>{const u={};for(const d of r)d.key&&(u[d.key]=ze(d.value));s({...t,facets:Object.keys(u).length?u:void 0})},S=r=>{const u=r.filter(d=>d.key).map(d=>({[d.key]:ze(d.value)}));s({...t,block:u.length?u:void 0})},M=r=>s({...t,range:r.length?r:void 0}),j=r=>s({...t,exists:r.length?r:void 0}),P=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:i.map(r=>e.jsx("option",{value:r},r))}),e.jsxs("datalist",{id:"lt-sort-fields",children:[Zs.map(r=>e.jsx("option",{value:r},r)),i.map(r=>e.jsx("option",{value:`metadata.${r}`},r))]}),m&&e.jsx(L,{title:"Match id",hint:"id · workflow · origin",children:e.jsx("input",{className:`${B} w-full`,placeholder:"Exact escalation, workflow, or origin id…",value:n,onChange:r=>m(r.target.value)})}),e.jsx(L,{title:"Has facet",hint:"metadata @>",children:[...x,{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:d=>{const l=[...x];l[u]={...r,key:d},N(l)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${B} w-40`,placeholder:"value",value:r.value,onChange:d=>{const l=[...x];l[u]={...r,value:d.target.value},N(l)}}),u<x.length&&e.jsx("button",{className:J,onClick:()=>N(x.filter((d,l)=>l!==u)),children:"×"})]},u))}),e.jsx(L,{title:"Range",hint:"numeric",children:[...f,{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:d=>{const l=[...f];l[u]={...r,facet:d},M(l.filter(c=>c.facet))}}),e.jsx("select",{className:Ue,value:r.op,onChange:d=>{const l=[...f];l[u]={...r,op:d.target.value},M(l.filter(c=>c.facet))},children:Xs.map(d=>e.jsx("option",{value:d,children:d},d))}),e.jsx("input",{type:"number",className:`${B} w-24`,value:r.value,onChange:d=>{const l=[...f];l[u]={...r,value:Number(d.target.value)},M(l.filter(c=>c.facet))}}),u<f.length&&e.jsx("button",{className:J,onClick:()=>M(f.filter((d,l)=>l!==u)),children:"×"})]},u))}),e.jsx(L,{title:"Has key",hint:"metadata ? key",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[o.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(o.filter(u=>u!==r)),children:"×"})]},r)),e.jsx(ee,{value:"",placeholder:"+ key",onChange:r=>{r&&!o.includes(r)&&j([...o,r])}})]})}),e.jsx(L,{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:d=>{const l=[...h];l[u]={...r,key:d},S(l)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${B} w-40`,placeholder:"value",value:r.value,onChange:d=>{const l=[...h];l[u]={...r,value:d.target.value},S(l)}}),u<h.length&&e.jsx("button",{className:J,onClick:()=>S(h.filter((d,l)=>l!==u)),children:"×"})]},u))}),e.jsx(L,{title:"Sort by",children:[...y,{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:`${B} w-44`,placeholder:"column or metadata.key",value:r.field,onChange:d=>{const l=[...y];l[u]={...r,field:d.target.value},P(l.filter(c=>c.field))}}),e.jsxs("select",{className:Ue,value:r.direction??"asc",onChange:d=>{const l=[...y];l[u]={...r,direction:d.target.value},P(l.filter(c=>c.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:d=>{const l=[...y];l[u]={...r,numeric:d.target.checked},P(l.filter(c=>c.field))}}),"num"]}),u<y.length&&e.jsx("button",{className:J,onClick:()=>P(y.filter((d,l)=>l!==u)),children:"×"})]},u))})]})}function sa({value:t,onChange:s,facetKeys:i,search:n,onSearchChange:m,activeFacetCount:x,onClear:h,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:[x>0&&e.jsx("button",{onClick:h,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(se,{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(ta,{value:t,onChange:s,facetKeys:i,search:n,onSearchChange:m})]})]})}const qe="created_at";function he(t){return t.replace(/^metadata\./,"")}function aa({orderBy:t,onChange:s}){const i=t==null?void 0:t[0],n=(i==null?void 0:i.field)??qe,m=(i==null?void 0:i.direction)??"desc",x=n===qe,h=f=>s([{...i??{},field:n,direction:f}]);return e.jsxs("div",{className:"flex items-center gap-1.5",children:[!x&&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:n,children:he(n)}),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(se,{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":m==="desc",onClick:()=>h("desc"),className:`px-1.5 py-1 transition-colors ${m==="desc"?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:x?"Newest first":`${he(n)} descending`,children:e.jsx(ps,{className:"w-3.5 h-3.5"})}),e.jsx("button",{type:"button",role:"radio","aria-checked":m==="asc",onClick:()=>h("asc"),className:`px-1.5 py-1 border-l border-surface-border transition-colors ${m==="asc"?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:x?"Oldest first":`${he(n)} ascending`,children:e.jsx(fs,{className:"w-3.5 h-3.5"})})]})]})}const na=t=>t.isPriorityPending||t.isClaimPending||t.isAssignPending||t.isUnassignPending||t.isTriagePending||t.isCancelPending,te="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",De=`${te} appearance-none cursor-pointer`,ra="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 ia(t){var f;const s=na(t),i=Xe(),{data:n}=_t(),m=Bt(),x=m!==null?m:((f=n==null?void 0:n.ai)==null?void 0:f.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:o=>{o.target.value&&(t.onSetPriority(parseInt(o.target.value)),o.target.value="")},disabled:s,className:De,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Priority…"}),Hs.map(o=>e.jsx("option",{value:o.value,children:o.label},o.value))]}),e.jsxs("select",{onChange:o=>{o.target.value&&(t.onClaim(parseInt(o.target.value)),o.target.value="")},disabled:s,className:De,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Claim for…"}),i.map(o=>e.jsx("option",{value:o.value,children:o.label},o.value))]}),e.jsx("button",{onClick:t.onAssign,disabled:s,className:te,children:t.isAssignPending?"Assigning…":"Assign to…"}),e.jsx("button",{onClick:t.onUnassign,disabled:s,className:te,children:t.isUnassignPending?"Unassigning…":"Unassign"}),x&&e.jsx("button",{onClick:t.onTriage,disabled:s,className:te,children:t.isTriagePending?"Triaging…":"Triage"}),t.cancelLabel!==!1&&e.jsx("button",{onClick:t.onCancel,disabled:s,className:ra,children:t.isCancelPending?t.cancelLabel?`${t.cancelLabel}…`:"Cancelling…":t.cancelLabel||"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 la({open:t,onClose:s,selectedCount:i,onSubmit:n,isPending:m}){const[x,h]=b.useState(""),f=()=>{n(x||void 0)};return e.jsx(We,{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:i})," 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:x,onChange:o=>h(o.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:f,disabled:m,className:"btn-primary text-xs",children:m?"Submitting...":"Submit for Triage"})]})]})})}function _(t,s,i){return n=>{t.mutate(n,{onSuccess:()=>{s(),i==null||i()}})}}function oa(t){const s=()=>[...t.selectedIds];return{handleSetPriority:o=>{_(t.setPriority,t.clearSelection)({ids:s(),priority:o})},handleBulkClaim:o=>{_(t.bulkClaim,t.clearSelection)({ids:s(),durationMinutes:o})},handleBulkTriage:o=>{_(t.bulkTriage,t.clearSelection,t.closeTriageModal)({ids:s(),hint:o})},handleBulkAssign:(o,y,N)=>{_(t.bulkAssign,t.clearSelection,t.closeAssignModal)({ids:s(),targetUserId:o,durationMinutes:y,reassign:N})},handleBulkUnassign:()=>{_(t.bulkUnassign,t.clearSelection)({ids:s()})},handleBulkCancel:()=>{_(t.bulkCancel,t.clearSelection,t.closeCancelModal)({ids:s()})}}}function ca({claimTarget:t,onClose:s,claimDuration:i,onDurationChange:n,claimDurations:m,onCustomClaimChange:x,onClaim:h,isPending:f}){return e.jsx(We,{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:i,onChange:o=>{n(o.target.value)},className:"select w-full text-sm",children:[m.map(o=>e.jsx("option",{value:o.value,children:o.label},o.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),i==="custom"&&e.jsx($s,{onChange:x,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:f,children:f?"Claiming...":"Claim"})]})]})})}const Je={pending:"--lt-status-queued-graphic",claimed:"--lt-status-claimed-graphic",resolved:"--lt-status-success-graphic",cancelled:"--lt-text-quaternary",expired:"--lt-text-tertiary"},et="--lt-text-quaternary";function da(t){return Je[t]??et}const I=Object.fromEntries(Object.entries(Je).map(([t,s])=>[t,`rgb(var(${s}))`])),Ve=40,ua=64,xa=24,Ie=3;function tt(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 Ge(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 He(t){return t.replace(/-/g," ").replace(/\b\w/g,s=>s.toUpperCase())}function ma(t,s){return t?[...s.filter(n=>n in t),...Object.keys(t).filter(n=>!s.includes(n))].map(n=>[n,t[n]]):[]}function ha({e:t}){const s=t.endMs-t.startMs;if(s<=0)return null;const i=I.pending,n=I.claimed,m=t.status==="cancelled"||t.status==="expired"?I.cancelled:I.resolved;let x=100,h=0,f=0;return t.claimedMs!==null?(x=Math.max(0,Math.min(100,(t.claimedMs-t.startMs)/s*100)),t.isOpen?h=100-x:(h=Math.max(0,Math.min(100-x,(t.endMs-t.claimedMs)/s*100)),f=Math.max(0,100-x-h))):t.isOpen||(f=100,x=0),e.jsxs("div",{className:"mt-2 h-0.5 rounded-full overflow-hidden flex bg-surface-sunken",children:[x>0&&e.jsx("div",{style:{width:`${x}%`,backgroundColor:i,opacity:.6}}),h>0&&e.jsx("div",{style:{width:`${h}%`,backgroundColor:n,opacity:.6}}),f>0&&e.jsx("div",{style:{width:`${f}%`,backgroundColor:m,opacity:.6}})]})}function pa({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:tt(t)})})}function Qe({e:t,highlightKeys:s,onRowClick:i}){const[n,m]=b.useState(!1),x=I[t.displayStatus]??`rgb(var(${et}))`,h=ma(t.metadata,s),f=n?h:h.slice(0,Ie),o=h.length-Ie;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:x},onClick:()=>i==null?void 0:i(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:He(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]})]})]}),f.length>0&&e.jsxs("div",{className:"border-t border-surface-border/40 pt-1 space-y-px",children:[f.map(([y,N])=>{const S=String(N),M=s.includes(y);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 ${M?"text-accent":"text-text-quaternary"}`,title:y,children:y}),e.jsx("span",{className:`flex-1 min-w-0 text-2xs font-medium truncate ${M?"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(Be,{to:_e(y,N,t.role),className:"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors",title:`Filter ${He(t.role)}: ${y} = ${S}`,onClick:j=>j.stopPropagation(),children:e.jsx(ys,{className:"w-2.5 h-2.5"})}),e.jsx(Be,{to:_e(y,N),className:"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors",title:`Search all: ${y} = ${S}`,onClick:j=>j.stopPropagation(),children:e.jsx(vs,{className:"w-2.5 h-2.5"})})]})]},y)}),o>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:y=>{y.stopPropagation(),m(N=>!N)},children:n?e.jsxs(e.Fragment,{children:[e.jsx(js,{className:"w-2.5 h-2.5"})," less"]}):e.jsxs(e.Fragment,{children:[e.jsx(Ns,{className:"w-2.5 h-2.5"})," ",o," more"]})})]}),e.jsx(ha,{e:t}),t.assigned_to&&e.jsxs("div",{className:"mt-1 flex items-center justify-end gap-1 text-2xs text-text-tertiary",children:[e.jsx(Cs,{className:"w-3 h-3 shrink-0",strokeWidth:1.5}),e.jsx(Ks,{userId:t.assigned_to,className:"truncate max-w-[70%]"})]})]})}function fa({escalations:t,highlightKeys:s=[],onRowClick:i,total:n,page:m,totalPages:x,onPageChange:h}){var d,l;const f=Date.now(),y=t.map(c=>{const k=new Date(c.created_at).getTime(),w=c.resolved_at?new Date(c.resolved_at).getTime():null,g=c.claimed_at?new Date(c.claimed_at).getTime():null,C=!w&&c.status!=="cancelled"&&c.status!=="expired",$=w??(C?f:k+3e4),E=c.status==="pending"&&Ze(c)?"claimed":c.status;return{...c,startMs:k,claimedMs:g,endMs:$,isOpen:C,displayStatus:E}});if(y.length===0)return e.jsx("p",{className:"mt-12 text-center text-sm text-text-tertiary",children:"No escalations matched."});const N=y.length,M=Math.max(Math.abs((((d=y[N-1])==null?void 0:d.startMs)??0)-(((l=y[0])==null?void 0:l.startMs)??0)),1)/Math.max(N-1,1),j=ua/Math.max(M,1),r=new Set(y.map(c=>new Date(c.startMs).toDateString())).size>1;function u(c){const k=new Date(c),w=k.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});return r?k.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"}),y.map((c,k)=>{const w=y[k-1],g=w?Math.abs(c.startMs-w.startMs):null,C=g!==null?Math.max(xa,Math.round(g*j)):0,$=k%2===0,E=da(c.displayStatus),U=`rgb(var(${E}))`,G=c.endMs-c.startMs,z=c.isOpen?Ge(c.startMs):`${Ge(c.startMs)} · ${tt(G)}`;return e.jsxs("div",{children:[k>0&&e.jsx(pa,{gapMs:g,heightPx:C}),e.jsxs("div",{className:"flex items-center",children:[e.jsx("div",{className:"flex-1 flex justify-end items-center",children:$?e.jsxs("div",{className:"flex items-center",children:[e.jsx(Qe,{e:c,highlightKeys:s,onRowClick:i}),e.jsx("div",{className:"flex-shrink-0 h-px bg-surface-border/70",style:{width:Ve}})]}):e.jsx("span",{className:"text-2xs text-text-quaternary font-mono tabular-nums pr-3",children:z})}),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:U,boxShadow:`0 0 0 3px rgb(var(${E}) / 0.16), 0 1px 3px rgb(var(${E}) / 0.19)`},onClick:()=>i==null?void 0:i(c)}),e.jsx("div",{className:"flex-1 flex justify-start items-center",children:$?e.jsx("span",{className:"text-2xs text-text-quaternary font-mono tabular-nums pl-3",children:z}):e.jsxs("div",{className:"flex items-center",children:[e.jsx("div",{className:"flex-shrink-0 h-px bg-surface-border/70",style:{width:Ve}}),e.jsx(Qe,{e:c,highlightKeys:s,onRowClick:i})]})})]}),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(c.startMs)})})]},c.id)})]}),x>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:m})," ","of ",e.jsx("span",{className:"font-medium text-text-secondary",children:x})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>h(m-1),disabled:m<=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(gs,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>h(m+1),disabled:m>=x,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(bs,{className:"w-4 h-4"})})]})]})]})}function za(){var Fe,Re,Le;Ys();const t=Ye(),{filters:s,setFilter:i,pagination:n}=Ds({filters:{role:"",type:"",priority:"",status:"available",search:""}});Ut({role:s.role||null,verbs:["created","claimed"]});const m=Vs(s.search),x=Xe(),[h,f]=b.useState(null),[o,y]=b.useState("30"),[N,S]=b.useState(0),M=b.useCallback(a=>S(a),[]),[j,P]=b.useState(new Set),r=b.useRef(null),u=b.useRef(null),d=b.useCallback(a=>{var v;if((v=u.current)==null||v.disconnect(),u.current=null,!a||typeof ResizeObserver>"u")return;const p=new ResizeObserver(()=>{var Z;(Z=r.current)==null||Z.style.setProperty("--lt-sticky-top",`${a.offsetHeight-1}px`)});p.observe(a),u.current=p},[]),[l,c]=b.useState(!1),[k,w]=ms(),g=b.useMemo(()=>zt(k),[k]),C=b.useCallback(a=>{w(p=>{const v=new URLSearchParams(p);return qt(v,a),v.delete("page"),v})},[w]),{data:$}=Dt(l),E=Vt(g)+(s.search?1:0),U="facet-query",{setPanel:G,closePanel:z,open:st,ownerKey:at}=It();b.useEffect(()=>{if(!l){z(U);return}G(e.jsx(sa,{value:g,onChange:C,facetKeys:($==null?void 0:$.keys)??[],search:s.search??"",onSearchChange:a=>i("search",a),activeFacetCount:E,onClear:()=>{C({}),i("search","")},onClose:()=>c(!1)}),{width:420,key:U})},[l,g,C,$,s.search,i,E,G,z]);const pe=st&&at===U,ae=b.useRef(!1);b.useEffect(()=>{if(pe){ae.current=!0;return}ae.current&&(ae.current=!1,c(!1))},[pe]);const[nt,ne]=b.useState(!1),[rt,re]=b.useState(!1),[it,ie]=b.useState(!1),lt=b.useCallback(a=>C({...g,orderBy:a}),[g,C]),H=Ke(),{data:Q}=Gt(),fe=Ht(),ot=b.useCallback(()=>{var v;const a=window.prompt("Pin label:");if(!(a!=null&&a.trim()))return;const p=((v=Q==null?void 0:Q.preferences)==null?void 0:v.pinnedViews)??[];fe.mutate({pinnedViews:[...p,{id:Qt(),label:a.trim(),url:H.pathname+H.search,badge:!0}]})},[H.pathname,H.search,Q,fe]),{canBulk:ct}=Wt(),{kiosk:le}=Kt(),ge=g.facets?Object.keys(g.facets):[],oe=k.get("view"),dt=b.useCallback(a=>{w(p=>{const v=new URLSearchParams(p);return a?v.set("view",a):v.delete("view"),v},{replace:!0})},[w]),q=oe==="timeline",ut=b.useCallback(a=>{const{[a]:p,...v}=g.facets??{};C({...g,facets:Object.keys(v).length>0?v:void 0})},[g,C]),be=Yt(),ye=Xt(),ve=Zt(),ce=Jt(),je=es(),de=ts(),W=ss(),{data:ue}=as(),{data:F}=ns(),{data:xe}=rs(),{user:K,isSuperAdmin:xt,hasRoleType:mt}=is(),Ne=xt||mt("admin"),Ce=b.useMemo(()=>new Set(((K==null?void 0:K.roles)??[]).map(a=>a.role)),[K]),ht=b.useMemo(()=>{const a=(F==null?void 0:F.roles)??[];return(Ne?a:a.filter(v=>Ce.has(v.role)&&!hs(v.role))).map(v=>({value:v.role,label:ls(v)})).sort((v,Z)=>v.label.localeCompare(Z.label))},[F,Ne,Ce]);b.useEffect(()=>{P(new Set)},[s.role,s.type,s.priority,s.status,m,n.page,n.pageSize]);const D=s.status||"",Y=D==="available",ke=D==="claimed",pt=ke?"pending":D==="resolved"?"resolved":D==="cancelled"?"cancelled":D==="expired"?"expired":void 0,T=s.role||(((Fe=g.roles)==null?void 0:Fe.length)===1?g.roles[0]:null),we=os(T??"",void 0,!!T),ft=cs(T??"",void 0,!!T),me=T?Fs((Re=ft.data)==null?void 0:Re.form_schema).cancel:void 0,V=((Le=we.data)==null?void 0:Le.list_schema)??null,Se=!T||we.isFetched,Pe=100,Me={role:s.role||void 0,type:s.type||void 0,priority:s.priority?parseInt(s.priority):void 0,limit:q?Pe:n.pageSize,offset:n.offset,sort_by:"created_at",order:"desc",search:m||void 0,...g,include:zs(V)?"envelope":void 0},gt=ds({...Me,enabled:Y&&Se}),bt=us({status:pt,claimed:ke||void 0,...Me,enabled:!Y&&Se}),yt=Y?gt:bt,{data:R,isLoading:vt,error:X,refetch:jt,isFetching:Te}=yt,A=(R==null?void 0:R.escalations)??[],O=(R==null?void 0:R.total)??0,Ae=!!T&&!!V&&!!V["x-lt-layout"]&&V["x-lt-layout"]!=="table",Ee=Ae&&!q&&(oe?oe==="rich":!0),Oe=q?"timeline":Ee?"rich":"table",$e=b.useMemo(()=>{if(!g.jeopardy||!T)return null;const a=((F==null?void 0:F.roles)??[]).find(v=>v.role===T),p=(a==null?void 0:a.priority_threshold_minutes)??(a==null?void 0:a.sla_minutes)??null;return p!=null?xs(p*6e4):null},[g.jeopardy,T,F]),Nt=b.useMemo(()=>{const a=new Set;for(const p of A)j.has(p.id)&&a.add(p.role);return[...a]},[A,j]),Ct=b.useMemo(()=>A.filter(a=>j.has(a.id)&&Ze(a)).length,[A,j]),kt=b.useCallback(()=>P(new Set),[]),wt=()=>{if(!h)return;const a=o==="custom"?N:parseInt(o);!a||a<=0||be.mutate({id:h.id,durationMinutes:a},{onSuccess:()=>{f(null),t(`/escalations/detail/${h.id}`)}})},{handleSetPriority:St,handleBulkClaim:Pt,handleBulkTriage:Mt,handleBulkAssign:Tt,handleBulkUnassign:At,handleBulkCancel:Et}=oa({selectedIds:j,clearSelection:kt,setPriority:ye,bulkClaim:ve,bulkTriage:de,bulkAssign:ce,bulkUnassign:je,bulkCancel:W,closeTriageModal:()=>ne(!1),closeAssignModal:()=>re(!1),closeCancelModal:()=>ie(!1)}),Ot=a=>{const p=new Set(j);p.has(a)?p.delete(a):p.add(a),P(p)},$t=()=>{j.size===A.length?P(new Set):P(new Set(A.map(a=>a.id)))},Ft=[ct?{key:"select",label:e.jsx("input",{type:"checkbox",checked:A.length>0&&j.size===A.length,onChange:$t,className:"rounded"}),render:a=>e.jsx("input",{type:"checkbox",checked:j.has(a.id),onChange:p=>{p.stopPropagation(),Ot(a.id)},onClick:p=>p.stopPropagation(),className:"rounded"}),className:"w-10",priority:1}:{key:"spacer",label:"",render:()=>null,className:"w-10",priority:3},..._s({highlightKeys:ge}),{key:"actions",label:"",render:a=>e.jsx(Qs,{children:e.jsx(Ws,{icon:ks,title:"Claim escalation",onClick:()=>f(a),alwaysVisible:!0,colorClass:"text-accent/40 hover:text-accent",size:"sm"})}),className:"w-10 text-right"}];return e.jsxs("div",{ref:r,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-10 min-w-0",children:[e.jsx(Bs,{role:s.role,options:ht,onChange:a=>i("role",a),locked:le}),!le&&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(ws,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsxs("div",{ref:d,className:"sticky top-0 z-20 bg-surface",children:[e.jsx(Us,{filters:s,setFilter:i,roles:(ue==null?void 0:ue.roles)??[],types:(xe==null?void 0:xe.types)??[],showStatus:!0,showSearch:!1,showRole:!le,actions:e.jsxs(e.Fragment,{children:[q&&e.jsxs("span",{className:"text-2xs text-text-tertiary whitespace-nowrap",children:[O>100&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"font-medium text-text-secondary",children:[(n.page-1)*100+1,"–",Math.min(n.page*100,O)]})," of "]}),e.jsx("span",{className:"font-medium text-text-secondary",children:O})," ",O===1?"escalation":"escalations"]}),e.jsx(aa,{orderBy:g.orderBy,onChange:lt}),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:Ss},{key:"rich",title:"Rich view",Icon:Ps},{key:"timeline",title:"Timeline view",Icon:Ms}].filter(a=>a.key!=="rich"||Ae).map(({key:a,title:p,Icon:v})=>e.jsx("button",{role:"radio","aria-checked":Oe===a,onClick:()=>dt(a),className:`px-1.5 py-1 transition-colors ${Oe===a?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:p,children:e.jsx(v,{className:"w-3.5 h-3.5"})},a))}),e.jsxs("button",{onClick:()=>c(a=>!a),"aria-pressed":l,className:`relative rounded border border-surface-border px-1.5 py-1 transition-colors ${l?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:"Faceted query",children:[e.jsx(Ts,{className:"w-3.5 h-3.5"}),E>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:E})]}),e.jsxs("div",{className:"flex items-center gap-0.5",children:[e.jsx("button",{onClick:()=>jt(),disabled:Te,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(As,{className:`w-4 h-4 ${Te?"animate-spin":""}`})}),e.jsx("button",{onClick:ot,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(Es,{className:"w-4 h-4"})})]})]})}),e.jsx(ia,{selectedCount:j.size,onClearSelection:()=>P(new Set),onSetPriority:St,onClaim:Pt,onAssign:()=>re(!0),onUnassign:At,onTriage:()=>ne(!0),onCancel:()=>ie(!0),isPriorityPending:ye.isPending,isClaimPending:ve.isPending,isAssignPending:ce.isPending,isUnassignPending:je.isPending,isTriagePending:de.isPending,isCancelPending:W.isPending,cancelLabel:me}),(g.facets&&Object.keys(g.facets).length>0||g.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:[g.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(Os,{className:"w-2.5 h-2.5",strokeWidth:2.5}),"in jeopardy",$e&&e.jsxs("span",{className:"font-mono font-normal opacity-90",children:["> ",$e]}),e.jsx("button",{onClick:()=>C({...g,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(se,{className:"w-2.5 h-2.5"})})]}),Object.entries(g.facets??{}).map(([a,p])=>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:a}),e.jsx("span",{className:"text-text-quaternary",children:"="}),e.jsx("span",{className:"font-mono max-w-[160px] truncate",title:String(p),children:String(p)}),e.jsx("button",{onClick:()=>ut(a),className:"ml-0.5 -mr-0.5 flex items-center text-text-quaternary hover:text-status-error transition-colors","aria-label":`Remove ${a} filter`,children:e.jsx(se,{className:"w-2.5 h-2.5"})})]},a)),Object.keys(g.facets??{}).length>1&&e.jsx("button",{onClick:()=>C({...g,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}`}),q?e.jsx(fa,{escalations:A,highlightKeys:ge,onRowClick:a=>t(`/escalations/detail/${a.id}`,{state:{from:"/escalations/available"}}),total:O,page:n.page,totalPages:Math.ceil(O/Pe),onPageChange:n.setPage}):Ee?e.jsx(qs,{role:T,listSchema:V,activeEscalations:A,onRowClick:a=>t(`/escalations/detail/${a.id}`,{state:{from:"/escalations/available"}}),onOpenGroup:a=>t(a),onAddFacet:(a,p)=>C({...g,facets:{...g.facets??{},[a]:typeof p=="object"&&p!==null?JSON.stringify(p):p}}),total:O,page:n.page,totalPages:n.totalPages(O),pageSize:n.pageSize,onPageChange:n.setPage,onPageSizeChange:n.setPageSize}):e.jsxs(e.Fragment,{children:[e.jsx(Is,{columns:Ft,data:A,layout:"fixed",keyFn:a=>a.id,onRowClick:a=>t(`/escalations/detail/${a.id}`,{state:{from:"/escalations/available"}}),isLoading:vt,emptyMessage:X?"Unable to load data":"No escalations"}),e.jsx(Gs,{page:n.page,totalPages:n.totalPages(O),onPageChange:n.setPage,total:O,pageSize:n.pageSize,onPageSizeChange:n.setPageSize})]}),e.jsx(ca,{claimTarget:h,onClose:()=>f(null),claimDuration:o,onDurationChange:a=>{y(a),S(0)},claimDurations:x,customClaimMinutes:N,onCustomClaimChange:M,onClaim:wt,isPending:be.isPending}),e.jsx(la,{open:nt,onClose:()=>ne(!1),selectedCount:j.size,onSubmit:Mt,isPending:de.isPending}),e.jsx(Rs,{open:rt,onClose:()=>re(!1),selectedCount:j.size,selectedRoles:Nt,claimedCount:Ct,onSubmit:Tt,isPending:ce.isPending}),e.jsx(Ls,{open:it,onClose:()=>ie(!1),onConfirm:Et,selectedCount:j.size,isPending:W.isPending,error:W.error,actionLabel:typeof me=="string"?me:void 0})]})}export{za as AvailableEscalationsPage};
2
- //# sourceMappingURL=AvailableEscalationsPage-lz5qwSjg.js.map