@hotmeshio/long-tail 0.30.3 → 0.30.5

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 (261) hide show
  1. package/build/api/escalations/index.d.ts +1 -0
  2. package/build/api/escalations/index.js +5 -2
  3. package/build/api/escalations/roster-action.d.ts +11 -0
  4. package/build/api/escalations/roster-action.js +47 -30
  5. package/build/api/escalations/roster-scan.d.ts +26 -0
  6. package/build/api/escalations/roster-scan.js +114 -0
  7. package/build/api/scan-codes/context.d.ts +9 -1
  8. package/build/api/scan-codes/context.js +16 -1
  9. package/build/api/scan-codes/execute.js +6 -1
  10. package/build/api/scan-codes/fill-labels.d.ts +8 -0
  11. package/build/api/scan-codes/fill-labels.js +23 -2
  12. package/build/api/scan-codes/hold.js +2 -0
  13. package/build/api/scan-codes/located.d.ts +10 -0
  14. package/build/api/scan-codes/located.js +74 -0
  15. package/build/api/scan-codes/open.d.ts +9 -0
  16. package/build/api/scan-codes/open.js +99 -0
  17. package/build/api/scan-codes/present.js +1 -0
  18. package/build/api/scan-codes/verb-fill.js +1 -1
  19. package/build/api/scan-codes/verbs-subject.d.ts +3 -1
  20. package/build/api/scan-codes/verbs-subject.js +7 -4
  21. package/build/routes/escalations/resolve.js +18 -0
  22. package/build/services/role/index.d.ts +2 -0
  23. package/build/services/role/index.js +7 -0
  24. package/build/services/role/scan-done.js +4 -1
  25. package/build/services/role/sql.d.ts +1 -0
  26. package/build/services/role/sql.js +3 -1
  27. package/build/services/role/types.d.ts +2 -0
  28. package/build/services/scan-code/index.d.ts +1 -1
  29. package/build/services/scan-code/index.js +2 -1
  30. package/build/services/scan-code/parse.d.ts +5 -1
  31. package/build/services/scan-code/parse.js +8 -2
  32. package/build/services/scan-code/validate-station.d.ts +13 -0
  33. package/build/services/scan-code/validate-station.js +81 -0
  34. package/build/services/scan-code/validate-subject.js +33 -6
  35. package/build/services/scan-code/validate.js +12 -18
  36. package/build/system/mcp-servers/admin/schemas.d.ts +471 -4
  37. package/build/system/mcp-servers/admin/schemas.js +32 -4
  38. package/build/system/mcp-servers/human-queue-lookups.d.ts +7 -0
  39. package/build/system/mcp-servers/human-queue-lookups.js +31 -0
  40. package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -0
  41. package/build/system/mcp-servers/human-queue-schemas.js +4 -1
  42. package/build/system/mcp-servers/human-queue.d.ts +1 -0
  43. package/build/system/mcp-servers/human-queue.js +3 -0
  44. package/build/system/seed/tool-manifests-escalation.js +2 -2
  45. package/build/tsconfig.tsbuildinfo +1 -1
  46. package/build/types/index.d.ts +1 -1
  47. package/build/types/scan-choice.d.ts +2 -4
  48. package/build/types/scan-code/constants.d.ts +1 -0
  49. package/build/types/scan-code/constants.js +1 -0
  50. package/build/types/scan-code/response.d.ts +22 -4
  51. package/build/types/scan-code/rule.d.ts +62 -4
  52. package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js → AdminDashboard-D12QiMM5.js} +2 -2
  53. package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js.map → AdminDashboard-D12QiMM5.js.map} +1 -1
  54. package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js → AgentConfigPage-BKQd9b8m.js} +2 -2
  55. package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js.map → AgentConfigPage-BKQd9b8m.js.map} +1 -1
  56. package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js → AgentDetailPage-ie-DxsIj.js} +3 -3
  57. package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js.map → AgentDetailPage-ie-DxsIj.js.map} +1 -1
  58. package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js → AgentsPage-Nqm2DxCP.js} +2 -2
  59. package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js.map → AgentsPage-Nqm2DxCP.js.map} +1 -1
  60. package/dashboard/dist/assets/{AvailableEscalationsPage-GFn8Sgg1.js → AvailableEscalationsPage-BRKyG5qZ.js} +2 -2
  61. package/dashboard/dist/assets/{AvailableEscalationsPage-GFn8Sgg1.js.map → AvailableEscalationsPage-BRKyG5qZ.js.map} +1 -1
  62. package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js → BotPicker-BizdmeJp.js} +2 -2
  63. package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js.map → BotPicker-BizdmeJp.js.map} +1 -1
  64. package/dashboard/dist/assets/{BulkAssignModal-CmLVxkz-.js → BulkAssignModal-BWfzPrRk.js} +2 -2
  65. package/dashboard/dist/assets/{BulkAssignModal-CmLVxkz-.js.map → BulkAssignModal-BWfzPrRk.js.map} +1 -1
  66. package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js → CapabilitiesPage-DT8q7Zlh.js} +2 -2
  67. package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js.map → CapabilitiesPage-DT8q7Zlh.js.map} +1 -1
  68. package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js → CollapsibleSection-al5mqR4O.js} +2 -2
  69. package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js.map → CollapsibleSection-al5mqR4O.js.map} +1 -1
  70. package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js → ConfirmDeleteModal-BrlVktv2.js} +2 -2
  71. package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js.map → ConfirmDeleteModal-BrlVktv2.js.map} +1 -1
  72. package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js → ConnectedAppsPage-CLAsJ2yQ.js} +2 -2
  73. package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js.map → ConnectedAppsPage-CLAsJ2yQ.js.map} +1 -1
  74. package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js → CountdownTimer-D2D68exl.js} +2 -2
  75. package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js.map → CountdownTimer-D2D68exl.js.map} +1 -1
  76. package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js → CredentialsPage-DWrZbEI0.js} +2 -2
  77. package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js.map → CredentialsPage-DWrZbEI0.js.map} +1 -1
  78. package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js → CronLabel-DuXR8iWq.js} +2 -2
  79. package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js.map → CronLabel-DuXR8iWq.js.map} +1 -1
  80. package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js → ElapsedCell-ronqG5-E.js} +2 -2
  81. package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js.map → ElapsedCell-ronqG5-E.js.map} +1 -1
  82. package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js → EntityTimelinePanel-CKsktd84.js} +2 -2
  83. package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js.map → EntityTimelinePanel-CKsktd84.js.map} +1 -1
  84. package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js → EscalationListSchemaPage-C954ngy3.js} +3 -3
  85. package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js.map → EscalationListSchemaPage-C954ngy3.js.map} +1 -1
  86. package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js → EscalationSchemaPage-Dij9K0ON.js} +2 -2
  87. package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js.map → EscalationSchemaPage-Dij9K0ON.js.map} +1 -1
  88. package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js → EscalationTimeline-DT2Owdl0.js} +2 -2
  89. package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js.map → EscalationTimeline-DT2Owdl0.js.map} +1 -1
  90. package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js → EscalationTitleSelect-BdbfMA98.js} +2 -2
  91. package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js.map → EscalationTitleSelect-BdbfMA98.js.map} +1 -1
  92. package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js → EscalationsOverview-niahs84P.js} +2 -2
  93. package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js.map → EscalationsOverview-niahs84P.js.map} +1 -1
  94. package/dashboard/dist/assets/{EventTable-2ywJsOLy.js → EventTable-DuLMBrSx.js} +2 -2
  95. package/dashboard/dist/assets/{EventTable-2ywJsOLy.js.map → EventTable-DuLMBrSx.js.map} +1 -1
  96. package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js → FilterBar-jtY6KNpL.js} +2 -2
  97. package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js.map → FilterBar-jtY6KNpL.js.map} +1 -1
  98. package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js → GraphInvokePage-DSRAI0Zt.js} +2 -2
  99. package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js.map → GraphInvokePage-DSRAI0Zt.js.map} +1 -1
  100. package/dashboard/dist/assets/{HomePage-67xXjKjN.js → HomePage-BUlSnCg8.js} +2 -2
  101. package/dashboard/dist/assets/{HomePage-67xXjKjN.js.map → HomePage-BUlSnCg8.js.map} +1 -1
  102. package/dashboard/dist/assets/{LinePage-CMsYtukW.js → LinePage-BJKhVM9Y.js} +3 -3
  103. package/dashboard/dist/assets/{LinePage-CMsYtukW.js.map → LinePage-BJKhVM9Y.js.map} +1 -1
  104. package/dashboard/dist/assets/{LinesPage-pwL46mOS.js → LinesPage-CrpJua3_.js} +3 -3
  105. package/dashboard/dist/assets/{LinesPage-pwL46mOS.js.map → LinesPage-CrpJua3_.js.map} +1 -1
  106. package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js → ListToolbar-BN0UPt0L.js} +2 -2
  107. package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js.map → ListToolbar-BN0UPt0L.js.map} +1 -1
  108. package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js → McpOverview-BgbJXYPh.js} +2 -2
  109. package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js.map → McpOverview-BgbJXYPh.js.map} +1 -1
  110. package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js → McpQueryDetailPage-BNjm2nrc.js} +2 -2
  111. package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js.map → McpQueryDetailPage-BNjm2nrc.js.map} +1 -1
  112. package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js → McpQueryPage-DplR8wP9.js} +2 -2
  113. package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js.map → McpQueryPage-DplR8wP9.js.map} +1 -1
  114. package/dashboard/dist/assets/{McpRunDetailPage-qHRQ1pEY.js → McpRunDetailPage-BHVEcKV5.js} +2 -2
  115. package/dashboard/dist/assets/{McpRunDetailPage-qHRQ1pEY.js.map → McpRunDetailPage-BHVEcKV5.js.map} +1 -1
  116. package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js → McpRunsPage-CtlLagcs.js} +2 -2
  117. package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js.map → McpRunsPage-CtlLagcs.js.map} +1 -1
  118. package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js → OperationsPage-DH67bcW9.js} +3 -3
  119. package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js.map → OperationsPage-DH67bcW9.js.map} +1 -1
  120. package/dashboard/dist/assets/{OperatorDashboard-el5BquXN.js → OperatorDashboard-CMkgMewd.js} +2 -2
  121. package/dashboard/dist/assets/{OperatorDashboard-el5BquXN.js.map → OperatorDashboard-CMkgMewd.js.map} +1 -1
  122. package/dashboard/dist/assets/{PersonaDetailPage-B_tb8gfl.js → PersonaDetailPage-Cs1FFdNq.js} +2 -2
  123. package/dashboard/dist/assets/{PersonaDetailPage-B_tb8gfl.js.map → PersonaDetailPage-Cs1FFdNq.js.map} +1 -1
  124. package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js → PersonasPage-CHTRdneF.js} +2 -2
  125. package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js.map → PersonasPage-CHTRdneF.js.map} +1 -1
  126. package/dashboard/dist/assets/{PortalPage-e_rBb1do.js → PortalPage-ChB5pBTZ.js} +2 -2
  127. package/dashboard/dist/assets/{PortalPage-e_rBb1do.js.map → PortalPage-ChB5pBTZ.js.map} +1 -1
  128. package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js → ProcessDetailPage-CzyqSfal.js} +2 -2
  129. package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js.map → ProcessDetailPage-CzyqSfal.js.map} +1 -1
  130. package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js → ProcessesListPage-rOwNkaU9.js} +2 -2
  131. package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js.map → ProcessesListPage-rOwNkaU9.js.map} +1 -1
  132. package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js → ResolverForm-DibnlZ-A.js} +2 -2
  133. package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js.map → ResolverForm-DibnlZ-A.js.map} +1 -1
  134. package/dashboard/dist/assets/{RoleDetailPage-DtU7vsJm.js → RoleDetailPage-Bv9R7iQC.js} +3 -3
  135. package/dashboard/dist/assets/{RoleDetailPage-DtU7vsJm.js.map → RoleDetailPage-Bv9R7iQC.js.map} +1 -1
  136. package/dashboard/dist/assets/{RolesPage-BE7RWt9q.js → RolesPage-CUP7EH5U.js} +2 -2
  137. package/dashboard/dist/assets/{RolesPage-BE7RWt9q.js.map → RolesPage-CUP7EH5U.js.map} +1 -1
  138. package/dashboard/dist/assets/{RosterWidget-BJMx0a8Z.js → RosterWidget-DZtmQcjU.js} +2 -2
  139. package/dashboard/dist/assets/RosterWidget-DZtmQcjU.js.map +1 -0
  140. package/dashboard/dist/assets/{RunAsSelector-Co6s9bqA.js → RunAsSelector-B9-1vgZr.js} +2 -2
  141. package/dashboard/dist/assets/{RunAsSelector-Co6s9bqA.js.map → RunAsSelector-B9-1vgZr.js.map} +1 -1
  142. package/dashboard/dist/assets/{ScanCodesPage-C2TETaj5.js → ScanCodesPage-KN_e2rJl.js} +2 -2
  143. package/dashboard/dist/assets/{ScanCodesPage-C2TETaj5.js.map → ScanCodesPage-KN_e2rJl.js.map} +1 -1
  144. package/dashboard/dist/assets/{ScanSchemeDetailPage-C2UgU8l-.js → ScanSchemeDetailPage-CqItQ67Y.js} +4 -4
  145. package/dashboard/dist/assets/{ScanSchemeDetailPage-C2UgU8l-.js.map → ScanSchemeDetailPage-CqItQ67Y.js.map} +1 -1
  146. package/dashboard/dist/assets/ScanStationPage-B0qbUOwc.js +2 -0
  147. package/dashboard/dist/assets/ScanStationPage-B0qbUOwc.js.map +1 -0
  148. package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js → SchemeMatchFields-CL7TKnw3.js} +2 -2
  149. package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js.map → SchemeMatchFields-CL7TKnw3.js.map} +1 -1
  150. package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js → StickyPagination-CUwxfBQH.js} +2 -2
  151. package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js.map → StickyPagination-CUwxfBQH.js.map} +1 -1
  152. package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js → StreamMessageDetail-DOjcO7d2.js} +2 -2
  153. package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js.map → StreamMessageDetail-DOjcO7d2.js.map} +1 -1
  154. package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js → SwimlaneTimeline-SPMpoLHP.js} +2 -2
  155. package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js.map → SwimlaneTimeline-SPMpoLHP.js.map} +1 -1
  156. package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js → TaskDetailPage-DvfzR2IQ.js} +2 -2
  157. package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js.map → TaskDetailPage-DvfzR2IQ.js.map} +1 -1
  158. package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js → TasksListPage-Jp6wmL7t.js} +2 -2
  159. package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js.map → TasksListPage-Jp6wmL7t.js.map} +1 -1
  160. package/dashboard/dist/assets/{TimeAgo-CHTelacB.js → TimeAgo-BCQA0Gb_.js} +2 -2
  161. package/dashboard/dist/assets/{TimeAgo-CHTelacB.js.map → TimeAgo-BCQA0Gb_.js.map} +1 -1
  162. package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js → TimestampCell-xhdMHDQt.js} +2 -2
  163. package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js.map → TimestampCell-xhdMHDQt.js.map} +1 -1
  164. package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js → ToolTestPanel-D8M3ITrJ.js} +2 -2
  165. package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js.map → ToolTestPanel-D8M3ITrJ.js.map} +1 -1
  166. package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js → TopicDetailPage-DdBJQp31.js} +2 -2
  167. package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js.map → TopicDetailPage-DdBJQp31.js.map} +1 -1
  168. package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js → TopicsPage-vpvsynD9.js} +2 -2
  169. package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js.map → TopicsPage-vpvsynD9.js.map} +1 -1
  170. package/dashboard/dist/assets/{UserName-DKXnK7DD.js → UserName-BK6Lzsdw.js} +2 -2
  171. package/dashboard/dist/assets/{UserName-DKXnK7DD.js.map → UserName-BK6Lzsdw.js.map} +1 -1
  172. package/dashboard/dist/assets/{WorkflowExecutionPage-Crf7AIFc.js → WorkflowExecutionPage-DkM1TS4I.js} +2 -2
  173. package/dashboard/dist/assets/{WorkflowExecutionPage-Crf7AIFc.js.map → WorkflowExecutionPage-DkM1TS4I.js.map} +1 -1
  174. package/dashboard/dist/assets/{WorkflowsDashboard--isjt06C.js → WorkflowsDashboard-g_N4y3QS.js} +2 -2
  175. package/dashboard/dist/assets/{WorkflowsDashboard--isjt06C.js.map → WorkflowsDashboard-g_N4y3QS.js.map} +1 -1
  176. package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js → WorkflowsOverview-Drjo-Lu-.js} +2 -2
  177. package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js.map → WorkflowsOverview-Drjo-Lu-.js.map} +1 -1
  178. package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js → YamlWorkflowDetailPage-CLltNHjZ.js} +2 -2
  179. package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js.map → YamlWorkflowDetailPage-CLltNHjZ.js.map} +1 -1
  180. package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js → YamlWorkflowsPage-CxQCB-Zi.js} +2 -2
  181. package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js.map → YamlWorkflowsPage-CxQCB-Zi.js.map} +1 -1
  182. package/dashboard/dist/assets/{agents-CHjbjHXA.js → agents-Dk25jjhj.js} +2 -2
  183. package/dashboard/dist/assets/{agents-CHjbjHXA.js.map → agents-Dk25jjhj.js.map} +1 -1
  184. package/dashboard/dist/assets/{bots-WrUhEPWs.js → bots-bRkCqhlq.js} +2 -2
  185. package/dashboard/dist/assets/{bots-WrUhEPWs.js.map → bots-bRkCqhlq.js.map} +1 -1
  186. package/dashboard/dist/assets/{capabilities-CunMmkj8.js → capabilities-DARawLry.js} +2 -2
  187. package/dashboard/dist/assets/{capabilities-CunMmkj8.js.map → capabilities-DARawLry.js.map} +1 -1
  188. package/dashboard/dist/assets/{controlplane-D6IZIZoh.js → controlplane-DKccxxs6.js} +2 -2
  189. package/dashboard/dist/assets/{controlplane-D6IZIZoh.js.map → controlplane-DKccxxs6.js.map} +1 -1
  190. package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js → escalation-columns-BaYuzMYf.js} +2 -2
  191. package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js.map → escalation-columns-BaYuzMYf.js.map} +1 -1
  192. package/dashboard/dist/assets/{escalation-items-DFGRwo49.js → escalation-items-CwbNFnsH.js} +2 -2
  193. package/dashboard/dist/assets/{escalation-items-DFGRwo49.js.map → escalation-items-CwbNFnsH.js.map} +1 -1
  194. package/dashboard/dist/assets/{index-B8qrHwp9.js → index-BZgtzkkG.js} +2 -2
  195. package/dashboard/dist/assets/{index-B8qrHwp9.js.map → index-BZgtzkkG.js.map} +1 -1
  196. package/dashboard/dist/assets/{index-DRw0FXdX.js → index-Bx9HVzuT.js} +2 -2
  197. package/dashboard/dist/assets/{index-DRw0FXdX.js.map → index-Bx9HVzuT.js.map} +1 -1
  198. package/dashboard/dist/assets/{index-ygxyAKcc.js → index-CU2UW2y6.js} +14 -14
  199. package/dashboard/dist/assets/index-CU2UW2y6.js.map +1 -0
  200. package/dashboard/dist/assets/{index-OuKQ_0eB.js → index-Cf6qCgTf.js} +2 -2
  201. package/dashboard/dist/assets/{index-OuKQ_0eB.js.map → index-Cf6qCgTf.js.map} +1 -1
  202. package/dashboard/dist/assets/{index-DRK7M1_9.js → index-CtrSYqmL.js} +2 -2
  203. package/dashboard/dist/assets/{index-DRK7M1_9.js.map → index-CtrSYqmL.js.map} +1 -1
  204. package/dashboard/dist/assets/{index-Bo8QU31k.js → index-D1uliPqS.js} +2 -2
  205. package/dashboard/dist/assets/{index-Bo8QU31k.js.map → index-D1uliPqS.js.map} +1 -1
  206. package/dashboard/dist/assets/{index-B95LbYhW.js → index-DU-1gMks.js} +2 -2
  207. package/dashboard/dist/assets/{index-B95LbYhW.js.map → index-DU-1gMks.js.map} +1 -1
  208. package/dashboard/dist/assets/{index-CpCchhQv.js → index-DU2QCbgH.js} +2 -2
  209. package/dashboard/dist/assets/{index-CpCchhQv.js.map → index-DU2QCbgH.js.map} +1 -1
  210. package/dashboard/dist/assets/{index-BZFSXEkr.js → index-DgpL_Lgc.js} +2 -2
  211. package/dashboard/dist/assets/{index-BZFSXEkr.js.map → index-DgpL_Lgc.js.map} +1 -1
  212. package/dashboard/dist/assets/{index-boT612Jo.js → index-E_hJ7vtX.js} +2 -2
  213. package/dashboard/dist/assets/{index-boT612Jo.js.map → index-E_hJ7vtX.js.map} +1 -1
  214. package/dashboard/dist/assets/{index-DCJ483vt.js → index-dShcvdg3.js} +2 -2
  215. package/dashboard/dist/assets/{index-DCJ483vt.js.map → index-dShcvdg3.js.map} +1 -1
  216. package/dashboard/dist/assets/{index-C7EIu1mG.js → index-hKOlahpE.js} +2 -2
  217. package/dashboard/dist/assets/{index-C7EIu1mG.js.map → index-hKOlahpE.js.map} +1 -1
  218. package/dashboard/dist/assets/index-kzifJWbM.js +3 -0
  219. package/dashboard/dist/assets/index-kzifJWbM.js.map +1 -0
  220. package/dashboard/dist/assets/{knowledge-BubJBTwg.js → knowledge-DOe5ks-E.js} +2 -2
  221. package/dashboard/dist/assets/{knowledge-BubJBTwg.js.map → knowledge-DOe5ks-E.js.map} +1 -1
  222. package/dashboard/dist/assets/{machines-DSm5NFgs.js → machines-Zq_00v7k.js} +2 -2
  223. package/dashboard/dist/assets/{machines-DSm5NFgs.js.map → machines-Zq_00v7k.js.map} +1 -1
  224. package/dashboard/dist/assets/{mcp-D6MckqOV.js → mcp-BL8kD0oh.js} +2 -2
  225. package/dashboard/dist/assets/{mcp-D6MckqOV.js.map → mcp-BL8kD0oh.js.map} +1 -1
  226. package/dashboard/dist/assets/{mcp-query-VyCdOag6.js → mcp-query-BpokmJWi.js} +2 -2
  227. package/dashboard/dist/assets/{mcp-query-VyCdOag6.js.map → mcp-query-BpokmJWi.js.map} +1 -1
  228. package/dashboard/dist/assets/{personas-CyJc10xe.js → personas-BubCnQZ8.js} +2 -2
  229. package/dashboard/dist/assets/{personas-CyJc10xe.js.map → personas-BubCnQZ8.js.map} +1 -1
  230. package/dashboard/dist/assets/{pipelines-B2inDtx3.js → pipelines--DUoMx7K.js} +2 -2
  231. package/dashboard/dist/assets/{pipelines-B2inDtx3.js.map → pipelines--DUoMx7K.js.map} +1 -1
  232. package/dashboard/dist/assets/{tasks-DOP4d3M6.js → tasks-CJXN4OB4.js} +2 -2
  233. package/dashboard/dist/assets/{tasks-DOP4d3M6.js.map → tasks-CJXN4OB4.js.map} +1 -1
  234. package/dashboard/dist/assets/{topics-CNOjSWpX.js → topics-CAG08Ruo.js} +2 -2
  235. package/dashboard/dist/assets/{topics-CNOjSWpX.js.map → topics-CAG08Ruo.js.map} +1 -1
  236. package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js → useDebouncedValue-DQ2D8cm2.js} +2 -2
  237. package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js.map → useDebouncedValue-DQ2D8cm2.js.map} +1 -1
  238. package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js → useNamespace-DjEVAlJQ.js} +2 -2
  239. package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js.map → useNamespace-DjEVAlJQ.js.map} +1 -1
  240. package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js → useYamlActivityEvents-etcpfIwo.js} +2 -2
  241. package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js.map → useYamlActivityEvents-etcpfIwo.js.map} +1 -1
  242. package/dashboard/dist/assets/{validate-CAin6WM_.js → validate-YJK_6a7m.js} +2 -2
  243. package/dashboard/dist/assets/{validate-CAin6WM_.js.map → validate-YJK_6a7m.js.map} +1 -1
  244. package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js → yaml-workflows-D97Bz6li.js} +2 -2
  245. package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js.map → yaml-workflows-D97Bz6li.js.map} +1 -1
  246. package/dashboard/dist/index.html +1 -1
  247. package/docs/api/http/escalations.md +15 -0
  248. package/docs/api/mcp/human-queue.md +5 -1
  249. package/docs/dashboard.md +3 -3
  250. package/docs/hitl/lookups.md +2 -0
  251. package/docs/hitl/x-lt-roster.md +2 -0
  252. package/docs/hitl/x-lt-scan.md +12 -0
  253. package/docs/mcp.md +2 -0
  254. package/docs/scan-codes.md +87 -5
  255. package/package.json +1 -1
  256. package/dashboard/dist/assets/RosterWidget-BJMx0a8Z.js.map +0 -1
  257. package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js +0 -2
  258. package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js.map +0 -1
  259. package/dashboard/dist/assets/index-P-DlgAWj.js +0 -3
  260. package/dashboard/dist/assets/index-P-DlgAWj.js.map +0 -1
  261. package/dashboard/dist/assets/index-ygxyAKcc.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{j as d}from"./vendor-query-DvWWuNIB.js";import{a$ as M,bf as C,g as F}from"./index-ygxyAKcc.js";import{U as H}from"./UserName-DKXnK7DD.js";const $={LINK:"link",ESCALATION:"escalation",ESCALATION_LIST:"escalation-list",INVOKE:"invoke",ROSTER:"roster"},G=new Set(Object.values($));function U(t){return typeof t=="string"&&G.has(t)}function Y(t){return U(t==null?void 0:t["x-lt-widget"])}const w=new Set(["__proto__","constructor","prototype"]);function O(t){const n=[];for(const r of t.split(".")){const e=r.match(/^([^[\]]*)((?:\[\d+\])*)$/);if(!e)throw new Error(`invalid x-lt-bind path segment: "${r}"`);const[,s,i]=e;if(s){if(w.has(s))throw new Error(`x-lt-bind path may not target "${s}"`);n.push({key:s})}for(const o of i.match(/\d+/g)??[])n.push({index:Number(o)})}if(n.length===0)throw new Error(`empty x-lt-bind path: "${t}"`);return n}function B(t,n,r){const e=O(n);let s=t;for(let o=0;o<e.length-1;o++){const a=e[o],l=e[o+1],c="key"in a?a.key:a.index,u="index"in l;(s[c]==null||typeof s[c]!="object")&&(s[c]=u?[]:{}),s=s[c]}const i=e[e.length-1];s["key"in i?i.key:i.index]=r}function m(t,n){let r=t;for(const e of O(n)){if(r==null||typeof r!="object")return;r=r["key"in e?e.key:e.index]}return r}function k(t,n){const r=n==null?void 0:n["x-lt-bind"];return typeof r=="string"&&r.length>0?r:t}function v(t,n){const r=n==null?void 0:n.properties;if(!r)return{...t};const e={};for(const[s,i]of Object.entries(r))s in t&&(Y(i)||B(e,k(s,i),t[s]));return e}function tt(t,n){const r=n==null?void 0:n.properties;if(!r)return t?{...t}:{};const e={};for(const[s,i]of Object.entries(r)){const o=m(t,k(s,i));o!==void 0&&(e[s]=o)}return e}const R=["escalation","metadata","envelope","payload","resolver","lookup","input","roster"],K=/\{\{\s*([^{}]+?)\s*\}\}/g,p="—";function A(t){if(t==null)return p;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return p}}function S(t,n){return t.replace(K,(r,e)=>{const s=e.indexOf("."),i=s===-1?e:e.slice(0,s);if(!R.includes(i))return p;const o=n[i];if(s===-1)return A(o);try{return A(m(o,e.slice(s+1)))}catch{return p}})}function P(t){const n=t==null?void 0:t["x-lt-help"];if(typeof n=="string"&&n.trim().length>0)return n;const r=t==null?void 0:t["x-lt-context"];return typeof r=="string"&&r.trim().length>0?r:null}function nt(t,n){const r=P(t);return r?S(r,n):null}function rt({isTerminal:t,status:n,claimed:r,claimedByMe:e}){return t?n==="cancelled"?"This escalation was cancelled. The record is shown for reference.":"This escalation has been resolved. The submitted form is shown for reference.":e?"You have claimed this escalation. Fill out the form and submit to resolve it.":r?"Another user has claimed this escalation. It unlocks if their claim expires or is released.":"Claim this escalation to enable the form."}const E=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/,_="—",y={AGE:"age",AGO:"ago",DATE:"date",USER:"user"};function h(t){return t===y.AGE||t===y.AGO}function et({raw:t,format:n}){if(!t||t===_)return d.jsx("span",{className:"text-text-quaternary",children:_});if(n===y.USER)return d.jsx(H,{userId:t,className:"block truncate"});const r=E.test(t)||!Number.isNaN(new Date(t).getTime())&&(h(n)||n===y.DATE);return h(n)&&r?d.jsx("span",{title:C(t),className:"tabular-nums whitespace-nowrap",children:M(t)}):r&&(n===y.DATE||E.test(t))?d.jsx(F,{date:t,format:"datetime",className:"text-text-primary whitespace-nowrap"}):d.jsx(d.Fragment,{children:t})}function st(t){if(!t)return!1;try{const n=JSON.stringify(t);return n.includes("envelope.")||n.includes("payload.")}catch{return!1}}const V="accumulate_items",J="accumulate_max",T="batch_items",x="batch_filled_at",I="batch_filled_by",W="batch_keys",q="batch_pending";function f(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function N(t,n){return t.at.localeCompare(n.at)||t.itemKey.localeCompare(n.itemKey)}function it(t,n){const r=t.metadata??{},e=n==null?void 0:n[V];if(f(e)){const i=Object.entries(e).map(([a,l])=>{const c=f(l)?l:{};return{itemKey:a,at:typeof c.at=="string"?c.at:"",...f(c.payload)?{payload:c.payload}:{},...typeof c.actor=="string"?{actor:c.actor}:{},...typeof c.reciprocalId=="string"?{reciprocalId:c.reciprocalId}:{}}}).sort(N),o=r[J];return{kind:"accumulate",count:i.length,max:typeof o=="number"?o:null,items:i,pending:[]}}const s=r[q];if(Array.isArray(s)){const i=f(n==null?void 0:n[T])?n[T]:{},o=f(n==null?void 0:n[x])?n[x]:{},a=f(n==null?void 0:n[I])?n[I]:{},l=Object.entries(i).map(([u,b])=>({itemKey:u,at:typeof o[u]=="string"?o[u]:"",...f(b)?{payload:b}:{},...typeof a[u]=="string"?{actor:a[u]}:{}})).sort(N),c=r[W];return{kind:"batch",count:l.length,max:Array.isArray(c)?c.length:null,items:l,pending:s.filter(u=>typeof u=="string")}}return null}function ot(t){if(!t)return"";const n=Object.entries(t).slice(0,3).map(([e,s])=>{const i=typeof s=="object"&&s!==null?JSON.stringify(s):String(s);return`${e}: ${i.length>24?`${i.slice(0,23)}…`:i}`}),r=Object.keys(t).length-n.length;return r>0?`${n.join(" · ")} · +${r}`:n.join(" · ")}const ct="x-lt-item-label",j=/\{\{\s*([^{}]+?)\s*\}\}/g,D="item",g="—";function z(t){if(t==null||t==="")return null;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return null}}function L(t,n,r){const e=t.indexOf(".");if((e===-1?t:t.slice(0,e))===D)try{return z(e===-1?n:m(n,t.slice(e+1)))}catch{return null}const i=S(`{{${t}}}`,r);return i===g?null:i}function at(t,n,r={}){if(typeof t!="string"||!t.trim())return null;let e=0,s=0;const i=t.replace(j,(o,a)=>{s+=1;const l=L(a,n,r);return l===null?g:(e+=1,l)}).trim();return s>0&&e===0?null:i||null}function lt(t,n,r={}){return t.replace(j,(e,s)=>!n&&s.split(".")[0]===D?g:L(s,n??{},r)??g)}export{_ as E,et as F,R as H,ct as I,S as a,nt as b,v as c,rt as d,it as e,st as f,m as g,U as h,at as i,lt as j,h as k,tt as m,ot as s};
2
- //# sourceMappingURL=escalation-items-DFGRwo49.js.map
1
+ import{j as d}from"./vendor-query-DvWWuNIB.js";import{b0 as M,bg as C,g as F}from"./index-CU2UW2y6.js";import{U as H}from"./UserName-BK6Lzsdw.js";const $={LINK:"link",ESCALATION:"escalation",ESCALATION_LIST:"escalation-list",INVOKE:"invoke",ROSTER:"roster"},G=new Set(Object.values($));function U(t){return typeof t=="string"&&G.has(t)}function Y(t){return U(t==null?void 0:t["x-lt-widget"])}const w=new Set(["__proto__","constructor","prototype"]);function O(t){const n=[];for(const r of t.split(".")){const e=r.match(/^([^[\]]*)((?:\[\d+\])*)$/);if(!e)throw new Error(`invalid x-lt-bind path segment: "${r}"`);const[,s,i]=e;if(s){if(w.has(s))throw new Error(`x-lt-bind path may not target "${s}"`);n.push({key:s})}for(const o of i.match(/\d+/g)??[])n.push({index:Number(o)})}if(n.length===0)throw new Error(`empty x-lt-bind path: "${t}"`);return n}function B(t,n,r){const e=O(n);let s=t;for(let o=0;o<e.length-1;o++){const a=e[o],l=e[o+1],c="key"in a?a.key:a.index,u="index"in l;(s[c]==null||typeof s[c]!="object")&&(s[c]=u?[]:{}),s=s[c]}const i=e[e.length-1];s["key"in i?i.key:i.index]=r}function m(t,n){let r=t;for(const e of O(n)){if(r==null||typeof r!="object")return;r=r["key"in e?e.key:e.index]}return r}function k(t,n){const r=n==null?void 0:n["x-lt-bind"];return typeof r=="string"&&r.length>0?r:t}function v(t,n){const r=n==null?void 0:n.properties;if(!r)return{...t};const e={};for(const[s,i]of Object.entries(r))s in t&&(Y(i)||B(e,k(s,i),t[s]));return e}function tt(t,n){const r=n==null?void 0:n.properties;if(!r)return t?{...t}:{};const e={};for(const[s,i]of Object.entries(r)){const o=m(t,k(s,i));o!==void 0&&(e[s]=o)}return e}const R=["escalation","metadata","envelope","payload","resolver","lookup","input","roster"],K=/\{\{\s*([^{}]+?)\s*\}\}/g,p="—";function A(t){if(t==null)return p;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return p}}function S(t,n){return t.replace(K,(r,e)=>{const s=e.indexOf("."),i=s===-1?e:e.slice(0,s);if(!R.includes(i))return p;const o=n[i];if(s===-1)return A(o);try{return A(m(o,e.slice(s+1)))}catch{return p}})}function P(t){const n=t==null?void 0:t["x-lt-help"];if(typeof n=="string"&&n.trim().length>0)return n;const r=t==null?void 0:t["x-lt-context"];return typeof r=="string"&&r.trim().length>0?r:null}function nt(t,n){const r=P(t);return r?S(r,n):null}function rt({isTerminal:t,status:n,claimed:r,claimedByMe:e}){return t?n==="cancelled"?"This escalation was cancelled. The record is shown for reference.":"This escalation has been resolved. The submitted form is shown for reference.":e?"You have claimed this escalation. Fill out the form and submit to resolve it.":r?"Another user has claimed this escalation. It unlocks if their claim expires or is released.":"Claim this escalation to enable the form."}const E=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/,_="—",y={AGE:"age",AGO:"ago",DATE:"date",USER:"user"};function h(t){return t===y.AGE||t===y.AGO}function et({raw:t,format:n}){if(!t||t===_)return d.jsx("span",{className:"text-text-quaternary",children:_});if(n===y.USER)return d.jsx(H,{userId:t,className:"block truncate"});const r=E.test(t)||!Number.isNaN(new Date(t).getTime())&&(h(n)||n===y.DATE);return h(n)&&r?d.jsx("span",{title:C(t),className:"tabular-nums whitespace-nowrap",children:M(t)}):r&&(n===y.DATE||E.test(t))?d.jsx(F,{date:t,format:"datetime",className:"text-text-primary whitespace-nowrap"}):d.jsx(d.Fragment,{children:t})}function st(t){if(!t)return!1;try{const n=JSON.stringify(t);return n.includes("envelope.")||n.includes("payload.")}catch{return!1}}const V="accumulate_items",J="accumulate_max",T="batch_items",x="batch_filled_at",I="batch_filled_by",W="batch_keys",q="batch_pending";function f(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function N(t,n){return t.at.localeCompare(n.at)||t.itemKey.localeCompare(n.itemKey)}function it(t,n){const r=t.metadata??{},e=n==null?void 0:n[V];if(f(e)){const i=Object.entries(e).map(([a,l])=>{const c=f(l)?l:{};return{itemKey:a,at:typeof c.at=="string"?c.at:"",...f(c.payload)?{payload:c.payload}:{},...typeof c.actor=="string"?{actor:c.actor}:{},...typeof c.reciprocalId=="string"?{reciprocalId:c.reciprocalId}:{}}}).sort(N),o=r[J];return{kind:"accumulate",count:i.length,max:typeof o=="number"?o:null,items:i,pending:[]}}const s=r[q];if(Array.isArray(s)){const i=f(n==null?void 0:n[T])?n[T]:{},o=f(n==null?void 0:n[x])?n[x]:{},a=f(n==null?void 0:n[I])?n[I]:{},l=Object.entries(i).map(([u,b])=>({itemKey:u,at:typeof o[u]=="string"?o[u]:"",...f(b)?{payload:b}:{},...typeof a[u]=="string"?{actor:a[u]}:{}})).sort(N),c=r[W];return{kind:"batch",count:l.length,max:Array.isArray(c)?c.length:null,items:l,pending:s.filter(u=>typeof u=="string")}}return null}function ot(t){if(!t)return"";const n=Object.entries(t).slice(0,3).map(([e,s])=>{const i=typeof s=="object"&&s!==null?JSON.stringify(s):String(s);return`${e}: ${i.length>24?`${i.slice(0,23)}…`:i}`}),r=Object.keys(t).length-n.length;return r>0?`${n.join(" · ")} · +${r}`:n.join(" · ")}const ct="x-lt-item-label",j=/\{\{\s*([^{}]+?)\s*\}\}/g,D="item",g="—";function z(t){if(t==null||t==="")return null;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return null}}function L(t,n,r){const e=t.indexOf(".");if((e===-1?t:t.slice(0,e))===D)try{return z(e===-1?n:m(n,t.slice(e+1)))}catch{return null}const i=S(`{{${t}}}`,r);return i===g?null:i}function at(t,n,r={}){if(typeof t!="string"||!t.trim())return null;let e=0,s=0;const i=t.replace(j,(o,a)=>{s+=1;const l=L(a,n,r);return l===null?g:(e+=1,l)}).trim();return s>0&&e===0?null:i||null}function lt(t,n,r={}){return t.replace(j,(e,s)=>!n&&s.split(".")[0]===D?g:L(s,n??{},r)??g)}export{_ as E,et as F,R as H,ct as I,S as a,nt as b,v as c,rt as d,it as e,st as f,m as g,U as h,at as i,lt as j,h as k,tt as m,ot as s};
2
+ //# sourceMappingURL=escalation-items-CwbNFnsH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"escalation-items-DFGRwo49.js","sources":["../../../shared/form-validation/display-only-widgets.ts","../../../shared/form-validation/x-lt-bind.ts","../../../shared/form-validation/x-lt-help.ts","../../src/components/common/display/FormattedValue.tsx","../../src/lib/schema-needs-envelope.ts","../../src/lib/escalation-items.ts"],"sourcesContent":["/**\n * Widgets that render from the escalation context and produce no answer of\n * their own: navigation links, embedded records and lists, and invoke\n * controls. Their form slot exists only to place them in the layout, so\n * the payload mapper drops them and the server never sees a value.\n */\nexport const DISPLAY_ONLY_WIDGET_NAMES = {\n LINK: 'link',\n ESCALATION: 'escalation',\n ESCALATION_LIST: 'escalation-list',\n INVOKE: 'invoke',\n ROSTER: 'roster',\n} as const;\n\nexport const DISPLAY_ONLY_WIDGETS: ReadonlySet<string> = new Set(Object.values(DISPLAY_ONLY_WIDGET_NAMES));\n\nexport function isDisplayOnlyWidget(name: unknown): boolean {\n return typeof name === 'string' && DISPLAY_ONLY_WIDGETS.has(name);\n}\n\n/** Whether a property definition renders a display-only widget. */\nexport function isDisplayOnlyField(def: Record<string, unknown> | null | undefined): boolean {\n return isDisplayOnlyWidget(def?.['x-lt-widget']);\n}\n","/**\n * x-lt-bind — maps the escalation FORM (flat field values the user edits) to and\n * from the PAYLOAD (the nested JSON the workflow consumes). A form_schema property\n * may declare `x-lt-bind: \"a.b[0].c\"`, the path its value occupies in the payload;\n * a property with no bind sits at its own name at the root (1:1). This module is\n * isomorphic — the dashboard renders forms with it, and the API layer inverts a\n * submitted payload through it to validate against the form contract. One\n * implementation, both sides.\n *\n * mapPayloadToForm — payload → flat form values, to PREFILL/display the form\n * (server-side: to validate a submitted payload)\n * mapFormToPayload — flat form values → payload, the shape submitted/stored\n */\nimport { isDisplayOnlyField } from './display-only-widgets';\n\ntype PathSeg = { key: string } | { index: number };\n\nconst BLOCKED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Parse a bind path — dot keys with optional `[n]` indices. Rejects pollution keys. */\nexport function parsePath(path: string): PathSeg[] {\n const segs: PathSeg[] = [];\n for (const raw of path.split('.')) {\n const m = raw.match(/^([^[\\]]*)((?:\\[\\d+\\])*)$/);\n if (!m) throw new Error(`invalid x-lt-bind path segment: \"${raw}\"`);\n const [, name, brackets] = m;\n if (name) {\n if (BLOCKED_KEYS.has(name)) throw new Error(`x-lt-bind path may not target \"${name}\"`);\n segs.push({ key: name });\n }\n for (const b of brackets.match(/\\d+/g) ?? []) segs.push({ index: Number(b) });\n }\n if (segs.length === 0) throw new Error(`empty x-lt-bind path: \"${path}\"`);\n return segs;\n}\n\n/** Set `value` at `path` inside `root`, creating intermediate objects/arrays. */\nexport function setDeep(root: Record<string, any>, path: string, value: unknown): void {\n const segs = parsePath(path);\n let node: any = root;\n for (let i = 0; i < segs.length - 1; i++) {\n const seg = segs[i];\n const next = segs[i + 1];\n const childKey = 'key' in seg ? seg.key : seg.index;\n const wantArray = 'index' in next;\n if (node[childKey] == null || typeof node[childKey] !== 'object') {\n node[childKey] = wantArray ? [] : {};\n }\n node = node[childKey];\n }\n const last = segs[segs.length - 1];\n node['key' in last ? last.key : last.index] = value;\n}\n\n/** Read the value at `path` inside `root` (undefined if any segment is missing). */\nexport function getDeep(root: unknown, path: string): unknown {\n let node: any = root;\n for (const seg of parsePath(path)) {\n if (node == null || typeof node !== 'object') return undefined;\n node = node['key' in seg ? seg.key : seg.index];\n }\n return node;\n}\n\n/** The bind path for a form property (its `x-lt-bind`, or the property name). */\nexport function bindPathFor(propName: string, propDef: Record<string, any> | undefined): string {\n const bind = propDef?.['x-lt-bind'];\n return typeof bind === 'string' && bind.length > 0 ? bind : propName;\n}\n\n/**\n * Assemble the payload from the form's flat values. A field absent from\n * `formValues` is omitted (so clearing/deleting a field drops it from the\n * payload). Unknown keys not declared in the schema are dropped, and so are\n * display-only widget fields, which carry no answer. With no schema\n * properties, values pass through unchanged.\n */\nexport function mapFormToPayload(\n formValues: Record<string, any>,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return { ...formValues };\n const payload: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n if (!(name in formValues)) continue;\n if (isDisplayOnlyField(def as Record<string, unknown>)) continue;\n setDeep(payload, bindPathFor(name, def as Record<string, any>), formValues[name]);\n }\n return payload;\n}\n\n/**\n * Reverse of {@link mapFormToPayload}: pull each form field's value out of the\n * payload via its bind path, to prefill/display the form. A field whose bound\n * path is missing from the payload is omitted (the caller falls back to the\n * schema default).\n */\nexport function mapPayloadToForm(\n payload: Record<string, any> | null | undefined,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return payload ? { ...payload } : {};\n const form: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n const v = getDeep(payload, bindPathFor(name, def as Record<string, any>));\n if (v !== undefined) form[name] = v;\n }\n return form;\n}\n","/**\n * x-lt-help — the form's guidance content, rendered in the side panel beside\n * the resolve form. A form_schema may declare schema-level `x-lt-help`: a\n * markdown string whose `{{domain.path}}` tokens interpolate values from the\n * escalation surface, so help text can reference the live record:\n *\n * {{escalation.role}} — any column on the escalation row\n * {{metadata.schema_version}} — the row's metadata dict\n * {{envelope.formDefaults.customer.name}} — the workflow-sent input envelope\n * {{payload.category}} — the escalation context payload\n * {{resolver.notes}} — the submitted resolver payload\n * {{lookup.materials.items}} — versioned knowledge lookups pinned on the row\n * {{roster.orders.outstanding}} (a roster field's counts, x-lt-roster.ts)\n *\n * Paths reuse the x-lt-bind syntax (`a.b[0].c`). A missing value renders as an\n * em dash. `x-lt-context` is accepted as the plain-text fallback source when\n * `x-lt-help` is absent.\n */\nimport { getDeep } from './x-lt-bind';\n\n/** The token domains a help template may reference. `input` is the invoke-form name for the live values `resolver` also carries. */\nexport const HELP_DOMAINS = ['escalation', 'metadata', 'envelope', 'payload', 'resolver', 'lookup', 'input', 'roster'] as const;\nexport type HelpDomain = (typeof HELP_DOMAINS)[number];\n\nexport type HelpTokenContext = Partial<Record<HelpDomain, Record<string, unknown> | null>>;\n\nconst TOKEN_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst MISSING_VALUE = '—';\n\nfunction formatTokenValue(value: unknown): string {\n if (value === undefined || value === null) return MISSING_VALUE;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return MISSING_VALUE;\n }\n}\n\n/** Replace every `{{domain.path}}` token with its value from the context. */\nexport function interpolateHelp(template: string, ctx: HelpTokenContext): string {\n return template.replace(TOKEN_PATTERN, (_match, rawPath: string) => {\n const dot = rawPath.indexOf('.');\n const domain = (dot === -1 ? rawPath : rawPath.slice(0, dot)) as HelpDomain;\n if (!HELP_DOMAINS.includes(domain)) return MISSING_VALUE;\n const root = ctx[domain];\n if (dot === -1) return formatTokenValue(root);\n try {\n return formatTokenValue(getDeep(root, rawPath.slice(dot + 1)));\n } catch {\n return MISSING_VALUE;\n }\n });\n}\n\n/** The schema's help source: `x-lt-help` first, `x-lt-context` as fallback. */\nexport function resolveHelpSource(schema: Record<string, unknown> | null | undefined): string | null {\n const help = schema?.['x-lt-help'];\n if (typeof help === 'string' && help.trim().length > 0) return help;\n const context = schema?.['x-lt-context'];\n if (typeof context === 'string' && context.trim().length > 0) return context;\n return null;\n}\n\n/** The schema's help content, interpolated. Null when the schema declares none. */\nexport function buildHelpMarkdown(\n schema: Record<string, unknown> | null | undefined,\n ctx: HelpTokenContext,\n): string | null {\n const source = resolveHelpSource(schema);\n return source ? interpolateHelp(source, ctx) : null;\n}\n\nexport interface HelpStateHint {\n isTerminal: boolean;\n status?: string;\n claimed: boolean;\n claimedByMe: boolean;\n}\n\n/**\n * State-aware guidance shown when the schema carries no help content — the\n * panel always tells the user what this page expects of them right now.\n */\nexport function defaultHelpMarkdown({ isTerminal, status, claimed, claimedByMe }: HelpStateHint): string {\n if (isTerminal) {\n return status === 'cancelled'\n ? 'This escalation was cancelled. The record is shown for reference.'\n : 'This escalation has been resolved. The submitted form is shown for reference.';\n }\n if (claimedByMe) return 'You have claimed this escalation. Fill out the form and submit to resolve it.';\n if (claimed) return 'Another user has claimed this escalation. It unlocks if their claim expires or is released.';\n return 'Claim this escalation to enable the form.';\n}\n","import { DateValue } from './DateValue';\nimport { UserName } from './UserName';\nimport { formatAgoCompact } from '../../../lib/format';\nimport { formatDisplayDateTime } from '../../../lib/display-zone';\n\nconst ISO_DATETIME = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/;\nexport const EM_DASH = '—';\n\n/** Value formats an author may name on a column, card field, or fact. `ago` is the spoken form of `age`. */\nexport const FIELD_FORMATS = {\n AGE: 'age',\n AGO: 'ago',\n DATE: 'date',\n USER: 'user',\n} as const;\n\n/** True when the format renders as an age that ages with the clock. */\nexport function isAgeFormat(format?: string): boolean {\n return format === FIELD_FORMATS.AGE || format === FIELD_FORMATS.AGO;\n}\n\n/**\n * Render a value with a little care: `age`/`ago` turns a timestamp into a\n * compact age (\"12m\", \"3h\") with the absolute time as its tooltip; `date`\n * renders the full date, hoverable, and so does any ISO datetime with no\n * format; `user` resolves a user id to a display name; an empty value a quiet\n * em dash; anything else plain text.\n */\nexport function FormattedValue({ raw, format }: { raw: string; format?: string }) {\n if (!raw || raw === EM_DASH) return <span className=\"text-text-quaternary\">{EM_DASH}</span>;\n if (format === FIELD_FORMATS.USER) return <UserName userId={raw} className=\"block truncate\" />;\n const isDate = ISO_DATETIME.test(raw) || !Number.isNaN(new Date(raw).getTime()) && (isAgeFormat(format) || format === FIELD_FORMATS.DATE);\n if (isAgeFormat(format) && isDate) {\n return <span title={formatDisplayDateTime(raw)} className=\"tabular-nums whitespace-nowrap\">{formatAgoCompact(raw)}</span>;\n }\n if (isDate && (format === FIELD_FORMATS.DATE || ISO_DATETIME.test(raw))) {\n return <DateValue date={raw} format=\"datetime\" className=\"text-text-primary whitespace-nowrap\" />;\n }\n return <>{raw}</>;\n}\n","/**\n * List rows arrive without the heavyweight `envelope`/`escalation_payload`\n * columns by default. A surface driven by an x-lt schema fragment opts back in\n * only when the fragment actually interpolates those domains — `envelope.` or\n * `payload.` in any token, condition, or source path. `metadata.` and\n * `resolver.` ride the slim rows and never trigger the opt-in.\n */\nexport function schemaNeedsEnvelope(fragment: unknown): boolean {\n if (!fragment) return false;\n try {\n const s = JSON.stringify(fragment);\n return s.includes('envelope.') || s.includes('payload.');\n } catch {\n return false;\n }\n}\n","import type { LTEscalationRecord } from '../api/types';\nimport { interpolateHelp, type HelpTokenContext } from './x-lt-help';\nimport { getDeep } from './x-lt-bind';\n\n/** One held item of an accumulator or batch row, in the shape the workflow receives. */\nexport interface EscalationItem {\n itemKey: string;\n payload?: Record<string, unknown>;\n /** ISO-8601 from the database clock; empty for a batch item with no stamp. */\n at: string;\n actor?: string;\n reciprocalId?: string;\n}\n\nexport interface EscalationItems {\n kind: 'accumulate' | 'batch';\n count: number;\n /** The count trigger (accumulate) or the declared size (batch); null when unbounded. */\n max: number | null;\n items: EscalationItem[];\n /** Batch only: declared keys still awaiting submission. */\n pending: string[];\n}\n\nconst ACCUMULATE_ITEMS = 'accumulate_items';\nconst ACCUMULATE_MAX = 'accumulate_max';\nconst BATCH_ITEMS = 'batch_items';\nconst BATCH_FILLED_AT = 'batch_filled_at';\nconst BATCH_FILLED_BY = 'batch_filled_by';\nconst BATCH_KEYS = 'batch_keys';\nconst BATCH_PENDING = 'batch_pending';\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return !!v && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction byArrival(a: EscalationItem, b: EscalationItem): number {\n return a.at.localeCompare(b.at) || a.itemKey.localeCompare(b.itemKey);\n}\n\n/**\n * The held items of a row, or null when the row is neither an accumulator\n * nor a batch. Mirrors the server's items view so the panel and the API\n * agree on order (arrival, then key).\n */\nexport function escalationItems(\n esc: Pick<LTEscalationRecord, 'metadata'>,\n envelope: Record<string, unknown> | null,\n): EscalationItems | null {\n const metadata = (esc.metadata ?? {}) as Record<string, unknown>;\n const store = envelope?.[ACCUMULATE_ITEMS];\n if (isRecord(store)) {\n const items = Object.entries(store).map(([itemKey, entry]) => {\n const e = isRecord(entry) ? entry : {};\n return {\n itemKey,\n at: typeof e.at === 'string' ? e.at : '',\n ...(isRecord(e.payload) ? { payload: e.payload } : {}),\n ...(typeof e.actor === 'string' ? { actor: e.actor } : {}),\n ...(typeof e.reciprocalId === 'string' ? { reciprocalId: e.reciprocalId } : {}),\n } as EscalationItem;\n }).sort(byArrival);\n const max = metadata[ACCUMULATE_MAX];\n return { kind: 'accumulate', count: items.length, max: typeof max === 'number' ? max : null, items, pending: [] };\n }\n const pending = metadata[BATCH_PENDING];\n if (Array.isArray(pending)) {\n const filled = isRecord(envelope?.[BATCH_ITEMS]) ? (envelope![BATCH_ITEMS] as Record<string, unknown>) : {};\n const stamps = isRecord(envelope?.[BATCH_FILLED_AT]) ? (envelope![BATCH_FILLED_AT] as Record<string, unknown>) : {};\n const actors = isRecord(envelope?.[BATCH_FILLED_BY]) ? (envelope![BATCH_FILLED_BY] as Record<string, unknown>) : {};\n const items = Object.entries(filled).map(([itemKey, payload]) => ({\n itemKey,\n at: typeof stamps[itemKey] === 'string' ? (stamps[itemKey] as string) : '',\n ...(isRecord(payload) ? { payload } : {}),\n ...(typeof actors[itemKey] === 'string' ? { actor: actors[itemKey] as string } : {}),\n } as EscalationItem)).sort(byArrival);\n const keys = metadata[BATCH_KEYS];\n return {\n kind: 'batch',\n count: items.length,\n max: Array.isArray(keys) ? keys.length : null,\n items,\n pending: pending.filter((k): k is string => typeof k === 'string'),\n };\n }\n return null;\n}\n\n/** A one-line summary of an item payload for the list row. */\nexport function summarizePayload(payload: Record<string, unknown> | undefined): string {\n if (!payload) return '';\n const parts = Object.entries(payload).slice(0, 3).map(([k, v]) => {\n const text = typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n return `${k}: ${text.length > 24 ? `${text.slice(0, 23)}…` : text}`;\n });\n const more = Object.keys(payload).length - parts.length;\n return more > 0 ? `${parts.join(' · ')} · +${more}` : parts.join(' · ');\n}\n\n/** The container role's form-schema key naming how each held item displays. */\nexport const ITEM_LABEL_KEY = 'x-lt-item-label';\n\nconst TOKEN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst ITEM_DOMAIN = 'item';\nconst MISSING = '—';\n\nfunction formatValue(value: unknown): string | null {\n if (value === undefined || value === null || value === '') return null;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n}\n\n/** One token's value: `item.*` from the held item, every other domain as help tokens resolve it. */\nfunction tokenValue(path: string, item: EscalationItem, ctx: HelpTokenContext): string | null {\n const dot = path.indexOf('.');\n const domain = dot === -1 ? path : path.slice(0, dot);\n if (domain === ITEM_DOMAIN) {\n try {\n return formatValue(dot === -1 ? item : getDeep(item, path.slice(dot + 1)));\n } catch {\n return null;\n }\n }\n const value = interpolateHelp(`{{${path}}}`, ctx);\n return value === MISSING ? null : value;\n}\n\n/**\n * An item's display label from the role's `x-lt-item-label` template, whose\n * `{{item.*}}` tokens read the held item (itemKey, payload, actor, at) beside\n * the usual escalation domains. Null when there is no template or every token\n * it names is missing, so the caller falls back to the item key.\n */\nexport function itemLabel(\n template: unknown,\n item: EscalationItem,\n ctx: HelpTokenContext = {},\n): string | null {\n if (typeof template !== 'string' || !template.trim()) return null;\n let resolved = 0;\n let tokens = 0;\n const label = template.replace(TOKEN, (_match, rawPath: string) => {\n tokens += 1;\n const value = tokenValue(rawPath, item, ctx);\n if (value === null) return MISSING;\n resolved += 1;\n return value;\n }).trim();\n if (tokens > 0 && resolved === 0) return null;\n return label || null;\n}\n\n/** A template over `{{item.*}}` and the escalation domains; missing tokens read as an em dash. */\nexport function interpolateItemTemplate(template: string, item: EscalationItem | undefined, ctx: HelpTokenContext = {}): string {\n return template.replace(TOKEN, (_match, rawPath: string) => {\n if (!item && rawPath.split('.')[0] === ITEM_DOMAIN) return MISSING;\n return tokenValue(rawPath, item ?? ({} as EscalationItem), ctx) ?? MISSING;\n });\n}\n"],"names":["DISPLAY_ONLY_WIDGET_NAMES","DISPLAY_ONLY_WIDGETS","isDisplayOnlyWidget","name","isDisplayOnlyField","def","BLOCKED_KEYS","parsePath","path","segs","raw","m","brackets","b","setDeep","root","value","node","i","seg","next","childKey","wantArray","last","getDeep","bindPathFor","propName","propDef","bind","mapFormToPayload","formValues","formSchema","props","payload","mapPayloadToForm","form","v","HELP_DOMAINS","TOKEN_PATTERN","MISSING_VALUE","formatTokenValue","interpolateHelp","template","ctx","_match","rawPath","dot","domain","resolveHelpSource","schema","help","context","buildHelpMarkdown","source","defaultHelpMarkdown","isTerminal","status","claimed","claimedByMe","ISO_DATETIME","EM_DASH","FIELD_FORMATS","isAgeFormat","format","FormattedValue","jsx","UserName","isDate","formatDisplayDateTime","formatAgoCompact","DateValue","schemaNeedsEnvelope","fragment","s","ACCUMULATE_ITEMS","ACCUMULATE_MAX","BATCH_ITEMS","BATCH_FILLED_AT","BATCH_FILLED_BY","BATCH_KEYS","BATCH_PENDING","isRecord","byArrival","a","escalationItems","esc","envelope","metadata","store","items","itemKey","entry","e","max","pending","filled","stamps","actors","keys","k","summarizePayload","parts","text","more","ITEM_LABEL_KEY","TOKEN","ITEM_DOMAIN","MISSING","formatValue","tokenValue","item","itemLabel","resolved","tokens","label","interpolateItemTemplate"],"mappings":"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"}
1
+ {"version":3,"file":"escalation-items-CwbNFnsH.js","sources":["../../../shared/form-validation/display-only-widgets.ts","../../../shared/form-validation/x-lt-bind.ts","../../../shared/form-validation/x-lt-help.ts","../../src/components/common/display/FormattedValue.tsx","../../src/lib/schema-needs-envelope.ts","../../src/lib/escalation-items.ts"],"sourcesContent":["/**\n * Widgets that render from the escalation context and produce no answer of\n * their own: navigation links, embedded records and lists, and invoke\n * controls. Their form slot exists only to place them in the layout, so\n * the payload mapper drops them and the server never sees a value.\n */\nexport const DISPLAY_ONLY_WIDGET_NAMES = {\n LINK: 'link',\n ESCALATION: 'escalation',\n ESCALATION_LIST: 'escalation-list',\n INVOKE: 'invoke',\n ROSTER: 'roster',\n} as const;\n\nexport const DISPLAY_ONLY_WIDGETS: ReadonlySet<string> = new Set(Object.values(DISPLAY_ONLY_WIDGET_NAMES));\n\nexport function isDisplayOnlyWidget(name: unknown): boolean {\n return typeof name === 'string' && DISPLAY_ONLY_WIDGETS.has(name);\n}\n\n/** Whether a property definition renders a display-only widget. */\nexport function isDisplayOnlyField(def: Record<string, unknown> | null | undefined): boolean {\n return isDisplayOnlyWidget(def?.['x-lt-widget']);\n}\n","/**\n * x-lt-bind — maps the escalation FORM (flat field values the user edits) to and\n * from the PAYLOAD (the nested JSON the workflow consumes). A form_schema property\n * may declare `x-lt-bind: \"a.b[0].c\"`, the path its value occupies in the payload;\n * a property with no bind sits at its own name at the root (1:1). This module is\n * isomorphic — the dashboard renders forms with it, and the API layer inverts a\n * submitted payload through it to validate against the form contract. One\n * implementation, both sides.\n *\n * mapPayloadToForm — payload → flat form values, to PREFILL/display the form\n * (server-side: to validate a submitted payload)\n * mapFormToPayload — flat form values → payload, the shape submitted/stored\n */\nimport { isDisplayOnlyField } from './display-only-widgets';\n\ntype PathSeg = { key: string } | { index: number };\n\nconst BLOCKED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Parse a bind path — dot keys with optional `[n]` indices. Rejects pollution keys. */\nexport function parsePath(path: string): PathSeg[] {\n const segs: PathSeg[] = [];\n for (const raw of path.split('.')) {\n const m = raw.match(/^([^[\\]]*)((?:\\[\\d+\\])*)$/);\n if (!m) throw new Error(`invalid x-lt-bind path segment: \"${raw}\"`);\n const [, name, brackets] = m;\n if (name) {\n if (BLOCKED_KEYS.has(name)) throw new Error(`x-lt-bind path may not target \"${name}\"`);\n segs.push({ key: name });\n }\n for (const b of brackets.match(/\\d+/g) ?? []) segs.push({ index: Number(b) });\n }\n if (segs.length === 0) throw new Error(`empty x-lt-bind path: \"${path}\"`);\n return segs;\n}\n\n/** Set `value` at `path` inside `root`, creating intermediate objects/arrays. */\nexport function setDeep(root: Record<string, any>, path: string, value: unknown): void {\n const segs = parsePath(path);\n let node: any = root;\n for (let i = 0; i < segs.length - 1; i++) {\n const seg = segs[i];\n const next = segs[i + 1];\n const childKey = 'key' in seg ? seg.key : seg.index;\n const wantArray = 'index' in next;\n if (node[childKey] == null || typeof node[childKey] !== 'object') {\n node[childKey] = wantArray ? [] : {};\n }\n node = node[childKey];\n }\n const last = segs[segs.length - 1];\n node['key' in last ? last.key : last.index] = value;\n}\n\n/** Read the value at `path` inside `root` (undefined if any segment is missing). */\nexport function getDeep(root: unknown, path: string): unknown {\n let node: any = root;\n for (const seg of parsePath(path)) {\n if (node == null || typeof node !== 'object') return undefined;\n node = node['key' in seg ? seg.key : seg.index];\n }\n return node;\n}\n\n/** The bind path for a form property (its `x-lt-bind`, or the property name). */\nexport function bindPathFor(propName: string, propDef: Record<string, any> | undefined): string {\n const bind = propDef?.['x-lt-bind'];\n return typeof bind === 'string' && bind.length > 0 ? bind : propName;\n}\n\n/**\n * Assemble the payload from the form's flat values. A field absent from\n * `formValues` is omitted (so clearing/deleting a field drops it from the\n * payload). Unknown keys not declared in the schema are dropped, and so are\n * display-only widget fields, which carry no answer. With no schema\n * properties, values pass through unchanged.\n */\nexport function mapFormToPayload(\n formValues: Record<string, any>,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return { ...formValues };\n const payload: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n if (!(name in formValues)) continue;\n if (isDisplayOnlyField(def as Record<string, unknown>)) continue;\n setDeep(payload, bindPathFor(name, def as Record<string, any>), formValues[name]);\n }\n return payload;\n}\n\n/**\n * Reverse of {@link mapFormToPayload}: pull each form field's value out of the\n * payload via its bind path, to prefill/display the form. A field whose bound\n * path is missing from the payload is omitted (the caller falls back to the\n * schema default).\n */\nexport function mapPayloadToForm(\n payload: Record<string, any> | null | undefined,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return payload ? { ...payload } : {};\n const form: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n const v = getDeep(payload, bindPathFor(name, def as Record<string, any>));\n if (v !== undefined) form[name] = v;\n }\n return form;\n}\n","/**\n * x-lt-help — the form's guidance content, rendered in the side panel beside\n * the resolve form. A form_schema may declare schema-level `x-lt-help`: a\n * markdown string whose `{{domain.path}}` tokens interpolate values from the\n * escalation surface, so help text can reference the live record:\n *\n * {{escalation.role}} — any column on the escalation row\n * {{metadata.schema_version}} — the row's metadata dict\n * {{envelope.formDefaults.customer.name}} — the workflow-sent input envelope\n * {{payload.category}} — the escalation context payload\n * {{resolver.notes}} — the submitted resolver payload\n * {{lookup.materials.items}} — versioned knowledge lookups pinned on the row\n * {{roster.orders.outstanding}} (a roster field's counts, x-lt-roster.ts)\n *\n * Paths reuse the x-lt-bind syntax (`a.b[0].c`). A missing value renders as an\n * em dash. `x-lt-context` is accepted as the plain-text fallback source when\n * `x-lt-help` is absent.\n */\nimport { getDeep } from './x-lt-bind';\n\n/** The token domains a help template may reference. `input` is the invoke-form name for the live values `resolver` also carries. */\nexport const HELP_DOMAINS = ['escalation', 'metadata', 'envelope', 'payload', 'resolver', 'lookup', 'input', 'roster'] as const;\nexport type HelpDomain = (typeof HELP_DOMAINS)[number];\n\nexport type HelpTokenContext = Partial<Record<HelpDomain, Record<string, unknown> | null>>;\n\nconst TOKEN_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst MISSING_VALUE = '—';\n\nfunction formatTokenValue(value: unknown): string {\n if (value === undefined || value === null) return MISSING_VALUE;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return MISSING_VALUE;\n }\n}\n\n/** Replace every `{{domain.path}}` token with its value from the context. */\nexport function interpolateHelp(template: string, ctx: HelpTokenContext): string {\n return template.replace(TOKEN_PATTERN, (_match, rawPath: string) => {\n const dot = rawPath.indexOf('.');\n const domain = (dot === -1 ? rawPath : rawPath.slice(0, dot)) as HelpDomain;\n if (!HELP_DOMAINS.includes(domain)) return MISSING_VALUE;\n const root = ctx[domain];\n if (dot === -1) return formatTokenValue(root);\n try {\n return formatTokenValue(getDeep(root, rawPath.slice(dot + 1)));\n } catch {\n return MISSING_VALUE;\n }\n });\n}\n\n/** The schema's help source: `x-lt-help` first, `x-lt-context` as fallback. */\nexport function resolveHelpSource(schema: Record<string, unknown> | null | undefined): string | null {\n const help = schema?.['x-lt-help'];\n if (typeof help === 'string' && help.trim().length > 0) return help;\n const context = schema?.['x-lt-context'];\n if (typeof context === 'string' && context.trim().length > 0) return context;\n return null;\n}\n\n/** The schema's help content, interpolated. Null when the schema declares none. */\nexport function buildHelpMarkdown(\n schema: Record<string, unknown> | null | undefined,\n ctx: HelpTokenContext,\n): string | null {\n const source = resolveHelpSource(schema);\n return source ? interpolateHelp(source, ctx) : null;\n}\n\nexport interface HelpStateHint {\n isTerminal: boolean;\n status?: string;\n claimed: boolean;\n claimedByMe: boolean;\n}\n\n/**\n * State-aware guidance shown when the schema carries no help content — the\n * panel always tells the user what this page expects of them right now.\n */\nexport function defaultHelpMarkdown({ isTerminal, status, claimed, claimedByMe }: HelpStateHint): string {\n if (isTerminal) {\n return status === 'cancelled'\n ? 'This escalation was cancelled. The record is shown for reference.'\n : 'This escalation has been resolved. The submitted form is shown for reference.';\n }\n if (claimedByMe) return 'You have claimed this escalation. Fill out the form and submit to resolve it.';\n if (claimed) return 'Another user has claimed this escalation. It unlocks if their claim expires or is released.';\n return 'Claim this escalation to enable the form.';\n}\n","import { DateValue } from './DateValue';\nimport { UserName } from './UserName';\nimport { formatAgoCompact } from '../../../lib/format';\nimport { formatDisplayDateTime } from '../../../lib/display-zone';\n\nconst ISO_DATETIME = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/;\nexport const EM_DASH = '—';\n\n/** Value formats an author may name on a column, card field, or fact. `ago` is the spoken form of `age`. */\nexport const FIELD_FORMATS = {\n AGE: 'age',\n AGO: 'ago',\n DATE: 'date',\n USER: 'user',\n} as const;\n\n/** True when the format renders as an age that ages with the clock. */\nexport function isAgeFormat(format?: string): boolean {\n return format === FIELD_FORMATS.AGE || format === FIELD_FORMATS.AGO;\n}\n\n/**\n * Render a value with a little care: `age`/`ago` turns a timestamp into a\n * compact age (\"12m\", \"3h\") with the absolute time as its tooltip; `date`\n * renders the full date, hoverable, and so does any ISO datetime with no\n * format; `user` resolves a user id to a display name; an empty value a quiet\n * em dash; anything else plain text.\n */\nexport function FormattedValue({ raw, format }: { raw: string; format?: string }) {\n if (!raw || raw === EM_DASH) return <span className=\"text-text-quaternary\">{EM_DASH}</span>;\n if (format === FIELD_FORMATS.USER) return <UserName userId={raw} className=\"block truncate\" />;\n const isDate = ISO_DATETIME.test(raw) || !Number.isNaN(new Date(raw).getTime()) && (isAgeFormat(format) || format === FIELD_FORMATS.DATE);\n if (isAgeFormat(format) && isDate) {\n return <span title={formatDisplayDateTime(raw)} className=\"tabular-nums whitespace-nowrap\">{formatAgoCompact(raw)}</span>;\n }\n if (isDate && (format === FIELD_FORMATS.DATE || ISO_DATETIME.test(raw))) {\n return <DateValue date={raw} format=\"datetime\" className=\"text-text-primary whitespace-nowrap\" />;\n }\n return <>{raw}</>;\n}\n","/**\n * List rows arrive without the heavyweight `envelope`/`escalation_payload`\n * columns by default. A surface driven by an x-lt schema fragment opts back in\n * only when the fragment actually interpolates those domains — `envelope.` or\n * `payload.` in any token, condition, or source path. `metadata.` and\n * `resolver.` ride the slim rows and never trigger the opt-in.\n */\nexport function schemaNeedsEnvelope(fragment: unknown): boolean {\n if (!fragment) return false;\n try {\n const s = JSON.stringify(fragment);\n return s.includes('envelope.') || s.includes('payload.');\n } catch {\n return false;\n }\n}\n","import type { LTEscalationRecord } from '../api/types';\nimport { interpolateHelp, type HelpTokenContext } from './x-lt-help';\nimport { getDeep } from './x-lt-bind';\n\n/** One held item of an accumulator or batch row, in the shape the workflow receives. */\nexport interface EscalationItem {\n itemKey: string;\n payload?: Record<string, unknown>;\n /** ISO-8601 from the database clock; empty for a batch item with no stamp. */\n at: string;\n actor?: string;\n reciprocalId?: string;\n}\n\nexport interface EscalationItems {\n kind: 'accumulate' | 'batch';\n count: number;\n /** The count trigger (accumulate) or the declared size (batch); null when unbounded. */\n max: number | null;\n items: EscalationItem[];\n /** Batch only: declared keys still awaiting submission. */\n pending: string[];\n}\n\nconst ACCUMULATE_ITEMS = 'accumulate_items';\nconst ACCUMULATE_MAX = 'accumulate_max';\nconst BATCH_ITEMS = 'batch_items';\nconst BATCH_FILLED_AT = 'batch_filled_at';\nconst BATCH_FILLED_BY = 'batch_filled_by';\nconst BATCH_KEYS = 'batch_keys';\nconst BATCH_PENDING = 'batch_pending';\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return !!v && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction byArrival(a: EscalationItem, b: EscalationItem): number {\n return a.at.localeCompare(b.at) || a.itemKey.localeCompare(b.itemKey);\n}\n\n/**\n * The held items of a row, or null when the row is neither an accumulator\n * nor a batch. Mirrors the server's items view so the panel and the API\n * agree on order (arrival, then key).\n */\nexport function escalationItems(\n esc: Pick<LTEscalationRecord, 'metadata'>,\n envelope: Record<string, unknown> | null,\n): EscalationItems | null {\n const metadata = (esc.metadata ?? {}) as Record<string, unknown>;\n const store = envelope?.[ACCUMULATE_ITEMS];\n if (isRecord(store)) {\n const items = Object.entries(store).map(([itemKey, entry]) => {\n const e = isRecord(entry) ? entry : {};\n return {\n itemKey,\n at: typeof e.at === 'string' ? e.at : '',\n ...(isRecord(e.payload) ? { payload: e.payload } : {}),\n ...(typeof e.actor === 'string' ? { actor: e.actor } : {}),\n ...(typeof e.reciprocalId === 'string' ? { reciprocalId: e.reciprocalId } : {}),\n } as EscalationItem;\n }).sort(byArrival);\n const max = metadata[ACCUMULATE_MAX];\n return { kind: 'accumulate', count: items.length, max: typeof max === 'number' ? max : null, items, pending: [] };\n }\n const pending = metadata[BATCH_PENDING];\n if (Array.isArray(pending)) {\n const filled = isRecord(envelope?.[BATCH_ITEMS]) ? (envelope![BATCH_ITEMS] as Record<string, unknown>) : {};\n const stamps = isRecord(envelope?.[BATCH_FILLED_AT]) ? (envelope![BATCH_FILLED_AT] as Record<string, unknown>) : {};\n const actors = isRecord(envelope?.[BATCH_FILLED_BY]) ? (envelope![BATCH_FILLED_BY] as Record<string, unknown>) : {};\n const items = Object.entries(filled).map(([itemKey, payload]) => ({\n itemKey,\n at: typeof stamps[itemKey] === 'string' ? (stamps[itemKey] as string) : '',\n ...(isRecord(payload) ? { payload } : {}),\n ...(typeof actors[itemKey] === 'string' ? { actor: actors[itemKey] as string } : {}),\n } as EscalationItem)).sort(byArrival);\n const keys = metadata[BATCH_KEYS];\n return {\n kind: 'batch',\n count: items.length,\n max: Array.isArray(keys) ? keys.length : null,\n items,\n pending: pending.filter((k): k is string => typeof k === 'string'),\n };\n }\n return null;\n}\n\n/** A one-line summary of an item payload for the list row. */\nexport function summarizePayload(payload: Record<string, unknown> | undefined): string {\n if (!payload) return '';\n const parts = Object.entries(payload).slice(0, 3).map(([k, v]) => {\n const text = typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n return `${k}: ${text.length > 24 ? `${text.slice(0, 23)}…` : text}`;\n });\n const more = Object.keys(payload).length - parts.length;\n return more > 0 ? `${parts.join(' · ')} · +${more}` : parts.join(' · ');\n}\n\n/** The container role's form-schema key naming how each held item displays. */\nexport const ITEM_LABEL_KEY = 'x-lt-item-label';\n\nconst TOKEN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst ITEM_DOMAIN = 'item';\nconst MISSING = '—';\n\nfunction formatValue(value: unknown): string | null {\n if (value === undefined || value === null || value === '') return null;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n}\n\n/** One token's value: `item.*` from the held item, every other domain as help tokens resolve it. */\nfunction tokenValue(path: string, item: EscalationItem, ctx: HelpTokenContext): string | null {\n const dot = path.indexOf('.');\n const domain = dot === -1 ? path : path.slice(0, dot);\n if (domain === ITEM_DOMAIN) {\n try {\n return formatValue(dot === -1 ? item : getDeep(item, path.slice(dot + 1)));\n } catch {\n return null;\n }\n }\n const value = interpolateHelp(`{{${path}}}`, ctx);\n return value === MISSING ? null : value;\n}\n\n/**\n * An item's display label from the role's `x-lt-item-label` template, whose\n * `{{item.*}}` tokens read the held item (itemKey, payload, actor, at) beside\n * the usual escalation domains. Null when there is no template or every token\n * it names is missing, so the caller falls back to the item key.\n */\nexport function itemLabel(\n template: unknown,\n item: EscalationItem,\n ctx: HelpTokenContext = {},\n): string | null {\n if (typeof template !== 'string' || !template.trim()) return null;\n let resolved = 0;\n let tokens = 0;\n const label = template.replace(TOKEN, (_match, rawPath: string) => {\n tokens += 1;\n const value = tokenValue(rawPath, item, ctx);\n if (value === null) return MISSING;\n resolved += 1;\n return value;\n }).trim();\n if (tokens > 0 && resolved === 0) return null;\n return label || null;\n}\n\n/** A template over `{{item.*}}` and the escalation domains; missing tokens read as an em dash. */\nexport function interpolateItemTemplate(template: string, item: EscalationItem | undefined, ctx: HelpTokenContext = {}): string {\n return template.replace(TOKEN, (_match, rawPath: string) => {\n if (!item && rawPath.split('.')[0] === ITEM_DOMAIN) return MISSING;\n return tokenValue(rawPath, item ?? ({} as EscalationItem), ctx) ?? MISSING;\n });\n}\n"],"names":["DISPLAY_ONLY_WIDGET_NAMES","DISPLAY_ONLY_WIDGETS","isDisplayOnlyWidget","name","isDisplayOnlyField","def","BLOCKED_KEYS","parsePath","path","segs","raw","m","brackets","b","setDeep","root","value","node","i","seg","next","childKey","wantArray","last","getDeep","bindPathFor","propName","propDef","bind","mapFormToPayload","formValues","formSchema","props","payload","mapPayloadToForm","form","v","HELP_DOMAINS","TOKEN_PATTERN","MISSING_VALUE","formatTokenValue","interpolateHelp","template","ctx","_match","rawPath","dot","domain","resolveHelpSource","schema","help","context","buildHelpMarkdown","source","defaultHelpMarkdown","isTerminal","status","claimed","claimedByMe","ISO_DATETIME","EM_DASH","FIELD_FORMATS","isAgeFormat","format","FormattedValue","jsx","UserName","isDate","formatDisplayDateTime","formatAgoCompact","DateValue","schemaNeedsEnvelope","fragment","s","ACCUMULATE_ITEMS","ACCUMULATE_MAX","BATCH_ITEMS","BATCH_FILLED_AT","BATCH_FILLED_BY","BATCH_KEYS","BATCH_PENDING","isRecord","byArrival","a","escalationItems","esc","envelope","metadata","store","items","itemKey","entry","e","max","pending","filled","stamps","actors","keys","k","summarizePayload","parts","text","more","ITEM_LABEL_KEY","TOKEN","ITEM_DOMAIN","MISSING","formatValue","tokenValue","item","itemLabel","resolved","tokens","label","interpolateItemTemplate"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as n,j as s}from"./vendor-query-DvWWuNIB.js";import{aH as h,e as g}from"./index-ygxyAKcc.js";import{D as y}from"./DataTable-FjFhx0SE.js";import{F as C,b as j}from"./FilterBar-Dy0b7wwf.js";import{R as q,a as u}from"./RowActions-Bdd7z4eB.js";import{u as R}from"./useFilterParams-DBRw1Hcv.js";import{P as b}from"./PageHeader-DiGWAQlR.js";import{T as _}from"./TaskQueuePill-sUA1nZe-.js";import{W as N}from"./WorkflowPill-CKHip3hH.js";import{aB as v,E as S,h as E}from"./vendor-icons-en0_uSRD.js";import{u as I}from"./vendor-react-_9U4mKFr.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";function G(){const r=I(),{data:c,isLoading:m}=h(),{filters:t,setFilter:i}=R({filters:{search:"",queue:""}}),[a,p]=n.useState(t.search);n.useEffect(()=>{if(a===t.search)return;const e=setTimeout(()=>i("search",a),g);return()=>clearTimeout(e)},[a,i,t.search]);const o=c??[],d=n.useMemo(()=>[...new Set(o.map(e=>e.task_queue).filter(Boolean))].sort(),[o]),f=n.useMemo(()=>{let e=o;if(t.search){const l=t.search.toLowerCase();e=e.filter(w=>w.name.toLowerCase().includes(l))}return t.queue&&(e=e.filter(l=>l.task_queue===t.queue)),e},[o,t]),k=[{key:"name",label:"Workflow",render:e=>s.jsx(N,{type:e.name})},{key:"task_queue",label:"Queue",render:e=>s.jsx(_,{queue:e.task_queue}),className:"whitespace-nowrap"},{key:"registered",label:"Status",render:e=>e.registered?s.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-2xs font-medium bg-accent/10 text-accent",children:[s.jsx(v,{className:"w-3 h-3"}),"Certified"]}):s.jsx("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded text-2xs font-medium bg-surface-sunken text-text-tertiary",children:"Durable"}),className:"whitespace-nowrap"},{key:"actions",label:"",render:e=>s.jsx(q,{children:e.registered?s.jsx(u,{icon:S,title:"View config",onClick:()=>r(`/workflows/registry/${encodeURIComponent(e.name)}`)}):s.jsx(u,{icon:E,title:"Register workflow",onClick:()=>r(`/workflows/registry/new?workflow_type=${encodeURIComponent(e.name)}&task_queue=${encodeURIComponent(e.task_queue)}`)})}),className:"w-16 text-right"}],x=e=>{e.registered?r(`/workflows/registry/${encodeURIComponent(e.name)}`):r(`/workflows/registry/new?workflow_type=${encodeURIComponent(e.name)}&task_queue=${encodeURIComponent(e.task_queue)}`)};return s.jsxs("div",{children:[s.jsx(b,{title:"Workers",docsHash:"#docs:dashboard.md:task-queues"}),s.jsxs(C,{children:[s.jsx("input",{type:"text",placeholder:"Search workers...",value:a,onChange:e=>p(e.target.value),className:"input text-2xs py-1 px-2 w-56"}),s.jsx(j,{label:"Queue",value:t.queue,onChange:e=>i("queue",e),options:d.map(e=>({value:e,label:e}))})]}),s.jsx(y,{columns:k,data:f,keyFn:e=>e.name,onRowClick:x,isLoading:m,emptyMessage:"No active workers"})]})}export{G as WorkersPage};
2
- //# sourceMappingURL=index-B8qrHwp9.js.map
1
+ import{a as n,j as s}from"./vendor-query-DvWWuNIB.js";import{aI as h,e as g}from"./index-CU2UW2y6.js";import{D as y}from"./DataTable-FjFhx0SE.js";import{F as C,b as j}from"./FilterBar-jtY6KNpL.js";import{R as q,a as u}from"./RowActions-Bdd7z4eB.js";import{u as R}from"./useFilterParams-DBRw1Hcv.js";import{P as b}from"./PageHeader-DiGWAQlR.js";import{T as _}from"./TaskQueuePill-sUA1nZe-.js";import{W as N}from"./WorkflowPill-CKHip3hH.js";import{aB as v,E as I,h as S}from"./vendor-icons-en0_uSRD.js";import{u as E}from"./vendor-react-_9U4mKFr.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";function G(){const r=E(),{data:c,isLoading:m}=h(),{filters:t,setFilter:i}=R({filters:{search:"",queue:""}}),[a,p]=n.useState(t.search);n.useEffect(()=>{if(a===t.search)return;const e=setTimeout(()=>i("search",a),g);return()=>clearTimeout(e)},[a,i,t.search]);const o=c??[],d=n.useMemo(()=>[...new Set(o.map(e=>e.task_queue).filter(Boolean))].sort(),[o]),f=n.useMemo(()=>{let e=o;if(t.search){const l=t.search.toLowerCase();e=e.filter(w=>w.name.toLowerCase().includes(l))}return t.queue&&(e=e.filter(l=>l.task_queue===t.queue)),e},[o,t]),k=[{key:"name",label:"Workflow",render:e=>s.jsx(N,{type:e.name})},{key:"task_queue",label:"Queue",render:e=>s.jsx(_,{queue:e.task_queue}),className:"whitespace-nowrap"},{key:"registered",label:"Status",render:e=>e.registered?s.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-2xs font-medium bg-accent/10 text-accent",children:[s.jsx(v,{className:"w-3 h-3"}),"Certified"]}):s.jsx("span",{className:"inline-flex items-center px-1.5 py-0.5 rounded text-2xs font-medium bg-surface-sunken text-text-tertiary",children:"Durable"}),className:"whitespace-nowrap"},{key:"actions",label:"",render:e=>s.jsx(q,{children:e.registered?s.jsx(u,{icon:I,title:"View config",onClick:()=>r(`/workflows/registry/${encodeURIComponent(e.name)}`)}):s.jsx(u,{icon:S,title:"Register workflow",onClick:()=>r(`/workflows/registry/new?workflow_type=${encodeURIComponent(e.name)}&task_queue=${encodeURIComponent(e.task_queue)}`)})}),className:"w-16 text-right"}],x=e=>{e.registered?r(`/workflows/registry/${encodeURIComponent(e.name)}`):r(`/workflows/registry/new?workflow_type=${encodeURIComponent(e.name)}&task_queue=${encodeURIComponent(e.task_queue)}`)};return s.jsxs("div",{children:[s.jsx(b,{title:"Workers",docsHash:"#docs:dashboard.md:task-queues"}),s.jsxs(C,{children:[s.jsx("input",{type:"text",placeholder:"Search workers...",value:a,onChange:e=>p(e.target.value),className:"input text-2xs py-1 px-2 w-56"}),s.jsx(j,{label:"Queue",value:t.queue,onChange:e=>i("queue",e),options:d.map(e=>({value:e,label:e}))})]}),s.jsx(y,{columns:k,data:f,keyFn:e=>e.name,onRowClick:x,isLoading:m,emptyMessage:"No active workers"})]})}export{G as WorkersPage};
2
+ //# sourceMappingURL=index-BZgtzkkG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-B8qrHwp9.js","sources":["../../src/pages/workflows/workers/WorkersPage.tsx"],"sourcesContent":["import { SEARCH_DEBOUNCE_MS } from '../../../lib/realtime-refresh';\nimport { useState, useEffect, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Plus, Eye, ShieldCheck } from 'lucide-react';\nimport { useActiveWorkers } from '../../../api/workflows';\nimport { DataTable, type Column } from '../../../components/common/data/DataTable';\nimport { FilterBar, FilterSelect } from '../../../components/common/data/FilterBar';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport type { ActiveWorker } from '../../../api/types';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { TaskQueuePill } from '../../../components/common/display/TaskQueuePill';\nimport { WorkflowPill } from '../../../components/common/display/WorkflowPill';\n\n// ── Page ──────────────────────────────────────────────────────────────────────\n\nexport function WorkersPage() {\n const navigate = useNavigate();\n const { data, isLoading } = useActiveWorkers();\n const { filters, setFilter } = useFilterParams({\n filters: { search: '', queue: '' },\n });\n\n const [searchInput, setSearchInput] = useState(filters.search);\n\n useEffect(() => {\n if (searchInput === filters.search) return;\n const timer = setTimeout(() => setFilter('search', searchInput), SEARCH_DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [searchInput, setFilter, filters.search]);\n\n const allWorkers = data ?? [];\n\n const queues = useMemo(\n () => [...new Set(allWorkers.map((w) => w.task_queue).filter(Boolean))].sort(),\n [allWorkers],\n );\n\n const workers = useMemo(() => {\n let result = allWorkers;\n if (filters.search) {\n const q = filters.search.toLowerCase();\n result = result.filter((w) => w.name.toLowerCase().includes(q));\n }\n if (filters.queue) result = result.filter((w) => w.task_queue === filters.queue);\n return result;\n }, [allWorkers, filters]);\n\n const columns: Column<ActiveWorker>[] = [\n {\n key: 'name',\n label: 'Workflow',\n render: (row) => <WorkflowPill type={row.name} />,\n },\n {\n key: 'task_queue',\n label: 'Queue',\n render: (row) => <TaskQueuePill queue={row.task_queue} />,\n className: 'whitespace-nowrap',\n },\n {\n key: 'registered',\n label: 'Status',\n render: (row) => row.registered\n ? <span className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-2xs font-medium bg-accent/10 text-accent\"><ShieldCheck className=\"w-3 h-3\" />Certified</span>\n : <span className=\"inline-flex items-center px-1.5 py-0.5 rounded text-2xs font-medium bg-surface-sunken text-text-tertiary\">Durable</span>,\n className: 'whitespace-nowrap',\n },\n {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n {row.registered ? (\n <RowAction\n icon={Eye}\n title=\"View config\"\n onClick={() => navigate(`/workflows/registry/${encodeURIComponent(row.name)}`)}\n />\n ) : (\n <RowAction\n icon={Plus}\n title=\"Register workflow\"\n onClick={() => navigate(`/workflows/registry/new?workflow_type=${encodeURIComponent(row.name)}&task_queue=${encodeURIComponent(row.task_queue)}`)}\n />\n )}\n </RowActionGroup>\n ),\n className: 'w-16 text-right',\n },\n ];\n\n const handleRowClick = (row: ActiveWorker) => {\n if (row.registered) {\n navigate(`/workflows/registry/${encodeURIComponent(row.name)}`);\n } else {\n navigate(`/workflows/registry/new?workflow_type=${encodeURIComponent(row.name)}&task_queue=${encodeURIComponent(row.task_queue)}`);\n }\n };\n\n return (\n <div>\n <PageHeader title=\"Workers\" docsHash=\"#docs:dashboard.md:task-queues\" />\n\n <FilterBar>\n <input\n type=\"text\"\n placeholder=\"Search workers...\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n className=\"input text-2xs py-1 px-2 w-56\"\n />\n <FilterSelect\n label=\"Queue\"\n value={filters.queue}\n onChange={(v) => setFilter('queue', v)}\n options={queues.map((q) => ({ value: q, label: q }))}\n />\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={workers}\n keyFn={(row) => row.name}\n onRowClick={handleRowClick}\n isLoading={isLoading}\n emptyMessage=\"No active workers\"\n />\n </div>\n );\n}\n"],"names":["WorkersPage","navigate","useNavigate","data","isLoading","useActiveWorkers","filters","setFilter","useFilterParams","searchInput","setSearchInput","useState","useEffect","timer","SEARCH_DEBOUNCE_MS","allWorkers","queues","useMemo","w","workers","result","q","columns","row","WorkflowPill","TaskQueuePill","jsxs","jsx","ShieldCheck","RowActionGroup","RowAction","Eye","Plus","handleRowClick","PageHeader","FilterBar","FilterSelect","v","DataTable"],"mappings":"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"}
1
+ {"version":3,"file":"index-BZgtzkkG.js","sources":["../../src/pages/workflows/workers/WorkersPage.tsx"],"sourcesContent":["import { SEARCH_DEBOUNCE_MS } from '../../../lib/realtime-refresh';\nimport { useState, useEffect, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Plus, Eye, ShieldCheck } from 'lucide-react';\nimport { useActiveWorkers } from '../../../api/workflows';\nimport { DataTable, type Column } from '../../../components/common/data/DataTable';\nimport { FilterBar, FilterSelect } from '../../../components/common/data/FilterBar';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport type { ActiveWorker } from '../../../api/types';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { TaskQueuePill } from '../../../components/common/display/TaskQueuePill';\nimport { WorkflowPill } from '../../../components/common/display/WorkflowPill';\n\n// ── Page ──────────────────────────────────────────────────────────────────────\n\nexport function WorkersPage() {\n const navigate = useNavigate();\n const { data, isLoading } = useActiveWorkers();\n const { filters, setFilter } = useFilterParams({\n filters: { search: '', queue: '' },\n });\n\n const [searchInput, setSearchInput] = useState(filters.search);\n\n useEffect(() => {\n if (searchInput === filters.search) return;\n const timer = setTimeout(() => setFilter('search', searchInput), SEARCH_DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [searchInput, setFilter, filters.search]);\n\n const allWorkers = data ?? [];\n\n const queues = useMemo(\n () => [...new Set(allWorkers.map((w) => w.task_queue).filter(Boolean))].sort(),\n [allWorkers],\n );\n\n const workers = useMemo(() => {\n let result = allWorkers;\n if (filters.search) {\n const q = filters.search.toLowerCase();\n result = result.filter((w) => w.name.toLowerCase().includes(q));\n }\n if (filters.queue) result = result.filter((w) => w.task_queue === filters.queue);\n return result;\n }, [allWorkers, filters]);\n\n const columns: Column<ActiveWorker>[] = [\n {\n key: 'name',\n label: 'Workflow',\n render: (row) => <WorkflowPill type={row.name} />,\n },\n {\n key: 'task_queue',\n label: 'Queue',\n render: (row) => <TaskQueuePill queue={row.task_queue} />,\n className: 'whitespace-nowrap',\n },\n {\n key: 'registered',\n label: 'Status',\n render: (row) => row.registered\n ? <span className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-2xs font-medium bg-accent/10 text-accent\"><ShieldCheck className=\"w-3 h-3\" />Certified</span>\n : <span className=\"inline-flex items-center px-1.5 py-0.5 rounded text-2xs font-medium bg-surface-sunken text-text-tertiary\">Durable</span>,\n className: 'whitespace-nowrap',\n },\n {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n {row.registered ? (\n <RowAction\n icon={Eye}\n title=\"View config\"\n onClick={() => navigate(`/workflows/registry/${encodeURIComponent(row.name)}`)}\n />\n ) : (\n <RowAction\n icon={Plus}\n title=\"Register workflow\"\n onClick={() => navigate(`/workflows/registry/new?workflow_type=${encodeURIComponent(row.name)}&task_queue=${encodeURIComponent(row.task_queue)}`)}\n />\n )}\n </RowActionGroup>\n ),\n className: 'w-16 text-right',\n },\n ];\n\n const handleRowClick = (row: ActiveWorker) => {\n if (row.registered) {\n navigate(`/workflows/registry/${encodeURIComponent(row.name)}`);\n } else {\n navigate(`/workflows/registry/new?workflow_type=${encodeURIComponent(row.name)}&task_queue=${encodeURIComponent(row.task_queue)}`);\n }\n };\n\n return (\n <div>\n <PageHeader title=\"Workers\" docsHash=\"#docs:dashboard.md:task-queues\" />\n\n <FilterBar>\n <input\n type=\"text\"\n placeholder=\"Search workers...\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n className=\"input text-2xs py-1 px-2 w-56\"\n />\n <FilterSelect\n label=\"Queue\"\n value={filters.queue}\n onChange={(v) => setFilter('queue', v)}\n options={queues.map((q) => ({ value: q, label: q }))}\n />\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={workers}\n keyFn={(row) => row.name}\n onRowClick={handleRowClick}\n isLoading={isLoading}\n emptyMessage=\"No active workers\"\n />\n </div>\n );\n}\n"],"names":["WorkersPage","navigate","useNavigate","data","isLoading","useActiveWorkers","filters","setFilter","useFilterParams","searchInput","setSearchInput","useState","useEffect","timer","SEARCH_DEBOUNCE_MS","allWorkers","queues","useMemo","w","workers","result","q","columns","row","WorkflowPill","TaskQueuePill","jsxs","jsx","ShieldCheck","RowActionGroup","RowAction","Eye","Plus","handleRowClick","PageHeader","FilterBar","FilterSelect","v","DataTable"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as d,j as s}from"./vendor-query-DvWWuNIB.js";import{h as F,i as C,g as u}from"./index-ygxyAKcc.js";import{u as M,a as T,b as O,S as $,c as A,d as D,e as R}from"./StreamMessageDetail-D5Rk7pn7.js";import{u as z}from"./useFilterParams-DBRw1Hcv.js";import{u as E}from"./useNamespace-BWHvUKtK.js";import{b as L}from"./api-path-u2Jf9QXS.js";import{D as I}from"./DataTable-FjFhx0SE.js";import{S as U}from"./StickyPagination-miUdVAKw.js";import{F as q,b as x,a as _}from"./FilterBar-Dy0b7wwf.js";import{P as B}from"./PageHeader-DiGWAQlR.js";import{L as V}from"./ListToolbar-CJmvGy2B.js";import{X as H,a4 as J}from"./vendor-icons-en0_uSRD.js";import"./vendor-react-_9U4mKFr.js";import"./controlplane-D6IZIZoh.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";function W(l,n){if(l.length<=n)return l;const a=Math.floor((n-1)/2);return`${l.slice(0,a)}…${l.slice(-a)}`}function me(){const{namespace:l,available:n}=E("namespace"),{filters:a,setFilter:t,pagination:r,sort:c,setSort:h}=z({filters:{namespace:"",source:"worker",status:"",stream_name:"",msg_type:"",topic:"",workflow_name:"",jid:"",aid:""}}),[m,g]=d.useState(null),v=d.useMemo(()=>n.map(e=>({value:e,label:e})),[n]),{data:i,isLoading:b,refetch:j,isFetching:w}=M({namespace:a.namespace||l,source:a.source||"worker",limit:r.pageSize,offset:r.offset,sort_by:c.sort_by||"created_at",order:c.order||"desc",status:a.status||void 0,stream_name:a.stream_name||void 0,msg_type:a.msg_type||void 0,topic:a.topic||void 0,workflow_name:a.workflow_name||void 0,jid:a.jid||void 0,aid:a.aid||void 0}),p=(i==null?void 0:i.messages)??[],f=(i==null?void 0:i.total)??0,o=d.useMemo(()=>m?p.find(e=>e.id===m.id&&e.source===m.source)??m:null,[p,m]),S=!!o,[k,N]=d.useState(null);d.useEffect(()=>{o&&N(o)},[o]);const y=o??k,P=[{key:"stream_name",label:"Stream",sortable:!0,render:e=>s.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s.jsx("span",{className:`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${D[e.status]}`,title:A[e.status]}),s.jsx("span",{className:"font-mono text-xs text-text-secondary truncate",title:e.stream_name,children:e.stream_name})]})},{key:"source",label:"Source",render:e=>s.jsx("span",{className:R,children:e.source}),className:"w-24"},{key:"created_at",label:"Created",sortable:!0,render:e=>s.jsx(u,{date:e.created_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}),className:"w-32"},{key:"reserved_at",label:"Reserved",render:e=>e.reserved_at?s.jsx(u,{date:e.reserved_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}):s.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"w-32"},{key:"expired_at",label:"Processed",render:e=>e.expired_at?s.jsx(u,{date:e.expired_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}):s.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"w-32"},{key:"priority",label:"Pri",sortable:!0,render:e=>s.jsx("span",{className:"text-xs text-text-secondary",children:e.priority}),className:"w-14 text-right"},{key:"retry_attempt",label:"Retries",render:e=>s.jsxs("span",{className:"text-xs text-text-secondary whitespace-nowrap",children:[e.retry_attempt,"/",e.max_retry_attempts]}),className:"w-20"}];return s.jsxs("div",{className:"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16",children:[s.jsxs("div",{className:"flex-1 min-w-0 pt-10 pr-10",children:[s.jsx(B,{title:"Messages",docsHash:"#docs:dashboard.md:messages"}),s.jsxs(q,{actions:s.jsx(V,{onRefresh:()=>j(),isFetching:w,apiPath:L("/controlplane/stream-messages",{namespace:a.namespace||l,source:a.source||"worker",limit:r.pageSize,offset:r.offset,sort_by:c.sort_by||"created_at",order:c.order||"desc",status:a.status||void 0,stream_name:a.stream_name||void 0,msg_type:a.msg_type||void 0,topic:a.topic||void 0,workflow_name:a.workflow_name||void 0,jid:a.jid||void 0,aid:a.aid||void 0})}),children:[s.jsx(x,{label:"Namespace",value:a.namespace,onChange:e=>t("namespace",e),options:v,required:!0}),s.jsx(x,{label:"Source",value:a.source,onChange:e=>t("source",e),options:T,required:!0}),s.jsx(x,{label:"Status",value:a.status,onChange:e=>t("status",e),options:O}),s.jsx(_,{label:"Stream",value:a.stream_name,onChange:e=>t("stream_name",e),placeholder:"Filter by stream name…"}),s.jsx(_,{label:"Job ID",value:a.jid,onChange:e=>t("jid",e),placeholder:"Filter by jid…"}),[{key:"topic",label:"Topic",value:a.topic},{key:"workflow_name",label:"Workflow",value:a.workflow_name},{key:"aid",label:"Activity",value:a.aid},{key:"msg_type",label:"Type",value:a.msg_type}].filter(e=>e.value).map(e=>s.jsxs("button",{onClick:()=>t(e.key,""),className:"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors",title:`Clear ${e.label} filter: ${e.value}`,children:[e.label,": ",W(e.value,12),s.jsx(H,{className:"w-2.5 h-2.5"})]},e.key))]}),s.jsx(I,{columns:P,data:p,keyFn:e=>`${e.source}:${e.id}`,isLoading:b,emptyMessage:"No stream messages found",onRowClick:e=>g(e),activeRowKey:o?`${o.source}:${o.id}`:null,sort:c,onSort:h,layout:"fixed"}),s.jsx(U,{page:r.page,totalPages:r.totalPages(f),onPageChange:r.setPage,total:f,pageSize:r.pageSize,onPageSizeChange:r.setPageSize})]}),s.jsx(F,{open:S,width:416,className:"self-stretch",children:s.jsx("div",{className:"h-full pl-4",children:s.jsx(C,{views:[{id:"detail",icon:J,label:"Message Detail",content:y?s.jsx($,{message:y,filters:{onFilterStatus:e=>t("status",e),onFilterStreamName:e=>t("stream_name",e),onFilterMsgType:e=>t("msg_type",e),onFilterTopic:e=>t("topic",e),onFilterWorkflow:e=>t("workflow_name",e),onFilterJid:e=>t("jid",e),onFilterAid:e=>t("aid",e)}}):null}],activeId:"detail",onViewChange:()=>{},onClose:()=>g(null),stickyClassName:"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9"})})})]})}export{me as StreamMessagesPage};
2
- //# sourceMappingURL=index-DRw0FXdX.js.map
1
+ import{a as d,j as s}from"./vendor-query-DvWWuNIB.js";import{h as F,i as C,g as u}from"./index-CU2UW2y6.js";import{u as M,a as T,b as O,S as $,c as A,d as D,e as R}from"./StreamMessageDetail-DOjcO7d2.js";import{u as z}from"./useFilterParams-DBRw1Hcv.js";import{u as E}from"./useNamespace-DjEVAlJQ.js";import{b as L}from"./api-path-u2Jf9QXS.js";import{D as I}from"./DataTable-FjFhx0SE.js";import{S as U}from"./StickyPagination-CUwxfBQH.js";import{F as q,b as x,a as _}from"./FilterBar-jtY6KNpL.js";import{P as B}from"./PageHeader-DiGWAQlR.js";import{L as V}from"./ListToolbar-BN0UPt0L.js";import{X as H,a4 as J}from"./vendor-icons-en0_uSRD.js";import"./vendor-react-_9U4mKFr.js";import"./controlplane-DKccxxs6.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";function W(l,n){if(l.length<=n)return l;const a=Math.floor((n-1)/2);return`${l.slice(0,a)}…${l.slice(-a)}`}function me(){const{namespace:l,available:n}=E("namespace"),{filters:a,setFilter:t,pagination:r,sort:c,setSort:h}=z({filters:{namespace:"",source:"worker",status:"",stream_name:"",msg_type:"",topic:"",workflow_name:"",jid:"",aid:""}}),[m,g]=d.useState(null),v=d.useMemo(()=>n.map(e=>({value:e,label:e})),[n]),{data:i,isLoading:b,refetch:j,isFetching:w}=M({namespace:a.namespace||l,source:a.source||"worker",limit:r.pageSize,offset:r.offset,sort_by:c.sort_by||"created_at",order:c.order||"desc",status:a.status||void 0,stream_name:a.stream_name||void 0,msg_type:a.msg_type||void 0,topic:a.topic||void 0,workflow_name:a.workflow_name||void 0,jid:a.jid||void 0,aid:a.aid||void 0}),p=(i==null?void 0:i.messages)??[],f=(i==null?void 0:i.total)??0,o=d.useMemo(()=>m?p.find(e=>e.id===m.id&&e.source===m.source)??m:null,[p,m]),S=!!o,[k,N]=d.useState(null);d.useEffect(()=>{o&&N(o)},[o]);const y=o??k,P=[{key:"stream_name",label:"Stream",sortable:!0,render:e=>s.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s.jsx("span",{className:`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${D[e.status]}`,title:A[e.status]}),s.jsx("span",{className:"font-mono text-xs text-text-secondary truncate",title:e.stream_name,children:e.stream_name})]})},{key:"source",label:"Source",render:e=>s.jsx("span",{className:R,children:e.source}),className:"w-24"},{key:"created_at",label:"Created",sortable:!0,render:e=>s.jsx(u,{date:e.created_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}),className:"w-32"},{key:"reserved_at",label:"Reserved",render:e=>e.reserved_at?s.jsx(u,{date:e.reserved_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}):s.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"w-32"},{key:"expired_at",label:"Processed",render:e=>e.expired_at?s.jsx(u,{date:e.expired_at,format:"relative",className:"text-xs text-text-secondary whitespace-nowrap"}):s.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"w-32"},{key:"priority",label:"Pri",sortable:!0,render:e=>s.jsx("span",{className:"text-xs text-text-secondary",children:e.priority}),className:"w-14 text-right"},{key:"retry_attempt",label:"Retries",render:e=>s.jsxs("span",{className:"text-xs text-text-secondary whitespace-nowrap",children:[e.retry_attempt,"/",e.max_retry_attempts]}),className:"w-20"}];return s.jsxs("div",{className:"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16",children:[s.jsxs("div",{className:"flex-1 min-w-0 pt-10 pr-10",children:[s.jsx(B,{title:"Messages",docsHash:"#docs:dashboard.md:messages"}),s.jsxs(q,{actions:s.jsx(V,{onRefresh:()=>j(),isFetching:w,apiPath:L("/controlplane/stream-messages",{namespace:a.namespace||l,source:a.source||"worker",limit:r.pageSize,offset:r.offset,sort_by:c.sort_by||"created_at",order:c.order||"desc",status:a.status||void 0,stream_name:a.stream_name||void 0,msg_type:a.msg_type||void 0,topic:a.topic||void 0,workflow_name:a.workflow_name||void 0,jid:a.jid||void 0,aid:a.aid||void 0})}),children:[s.jsx(x,{label:"Namespace",value:a.namespace,onChange:e=>t("namespace",e),options:v,required:!0}),s.jsx(x,{label:"Source",value:a.source,onChange:e=>t("source",e),options:T,required:!0}),s.jsx(x,{label:"Status",value:a.status,onChange:e=>t("status",e),options:O}),s.jsx(_,{label:"Stream",value:a.stream_name,onChange:e=>t("stream_name",e),placeholder:"Filter by stream name…"}),s.jsx(_,{label:"Job ID",value:a.jid,onChange:e=>t("jid",e),placeholder:"Filter by jid…"}),[{key:"topic",label:"Topic",value:a.topic},{key:"workflow_name",label:"Workflow",value:a.workflow_name},{key:"aid",label:"Activity",value:a.aid},{key:"msg_type",label:"Type",value:a.msg_type}].filter(e=>e.value).map(e=>s.jsxs("button",{onClick:()=>t(e.key,""),className:"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors",title:`Clear ${e.label} filter: ${e.value}`,children:[e.label,": ",W(e.value,12),s.jsx(H,{className:"w-2.5 h-2.5"})]},e.key))]}),s.jsx(I,{columns:P,data:p,keyFn:e=>`${e.source}:${e.id}`,isLoading:b,emptyMessage:"No stream messages found",onRowClick:e=>g(e),activeRowKey:o?`${o.source}:${o.id}`:null,sort:c,onSort:h,layout:"fixed"}),s.jsx(U,{page:r.page,totalPages:r.totalPages(f),onPageChange:r.setPage,total:f,pageSize:r.pageSize,onPageSizeChange:r.setPageSize})]}),s.jsx(F,{open:S,width:416,className:"self-stretch",children:s.jsx("div",{className:"h-full pl-4",children:s.jsx(C,{views:[{id:"detail",icon:J,label:"Message Detail",content:y?s.jsx($,{message:y,filters:{onFilterStatus:e=>t("status",e),onFilterStreamName:e=>t("stream_name",e),onFilterMsgType:e=>t("msg_type",e),onFilterTopic:e=>t("topic",e),onFilterWorkflow:e=>t("workflow_name",e),onFilterJid:e=>t("jid",e),onFilterAid:e=>t("aid",e)}}):null}],activeId:"detail",onViewChange:()=>{},onClose:()=>g(null),stickyClassName:"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9"})})})]})}export{me as StreamMessagesPage};
2
+ //# sourceMappingURL=index-Bx9HVzuT.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-DRw0FXdX.js","sources":["../../src/pages/admin/streams/StreamMessagesPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from 'react';\nimport { X, MessageSquare } from 'lucide-react';\nimport { SlidePanel, SlidePanelViews } from '../../../components/common/layout/SlidePanel';\nimport { useStreamMessages, type StreamMessage } from '../../../api/stream-messages';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useNamespace } from '../../../hooks/useNamespace';\nimport { buildApiPath } from '../../../lib/api-path';\nimport { DataTable, type Column } from '../../../components/common/data/DataTable';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { ListToolbar } from '../../../components/common/data/ListToolbar';\nimport { StreamMessageDetail } from './StreamMessageDetail';\nimport { STATUS_DOT, STATUS_LABEL, STATUS_OPTIONS, SOURCE_OPTIONS, SOURCE_BADGE } from './constants';\n\nfunction truncateMiddle(str: string, max: number): string {\n if (str.length <= max) return str;\n const half = Math.floor((max - 1) / 2);\n return `${str.slice(0, half)}…${str.slice(-half)}`;\n}\n\nexport function StreamMessagesPage() {\n const { namespace, available } = useNamespace('namespace');\n\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { namespace: '', source: 'worker', status: '', stream_name: '', msg_type: '', topic: '', workflow_name: '', jid: '', aid: '' },\n });\n\n const [selected, setSelected] = useState<StreamMessage | null>(null);\n\n const namespaceOptions = useMemo(\n () => available.map((id) => ({ value: id, label: id })),\n [available],\n );\n\n const { data, isLoading, refetch, isFetching } = useStreamMessages({\n namespace: filters.namespace || namespace,\n source: (filters.source as 'engine' | 'worker') || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: (filters.status as any) || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n });\n\n const messages = data?.messages ?? [];\n const total = data?.total ?? 0;\n\n const activeMessage = useMemo(() => {\n if (!selected) return null;\n return messages.find((m) => m.id === selected.id && m.source === selected.source) ?? selected;\n }, [messages, selected]);\n\n const panelOpen = !!activeMessage;\n\n // Hold the last message through the panel's closing animation so the detail\n // content stays rendered while the panel slides shut.\n const [lastMessage, setLastMessage] = useState<StreamMessage | null>(null);\n useEffect(() => {\n if (activeMessage) setLastMessage(activeMessage);\n }, [activeMessage]);\n const displayMessage = activeMessage ?? lastMessage;\n\n // Status and type live as the dot and the detail panel — the row itself\n // stays one flexible stream column plus fixed narrow facts, so the table\n // shrinks with the container (same shape as the executions list).\n const columns: Column<StreamMessage>[] = [\n {\n key: 'stream_name',\n label: 'Stream',\n sortable: true,\n render: (row) => (\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className={`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${STATUS_DOT[row.status]}`}\n title={STATUS_LABEL[row.status]}\n />\n <span className=\"font-mono text-xs text-text-secondary truncate\" title={row.stream_name}>\n {row.stream_name}\n </span>\n </div>\n ),\n },\n {\n key: 'source',\n label: 'Source',\n render: (row) => <span className={SOURCE_BADGE}>{row.source}</span>,\n className: 'w-24',\n },\n {\n key: 'created_at',\n label: 'Created',\n sortable: true,\n render: (row) => <DateValue date={row.created_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n },\n {\n key: 'reserved_at',\n label: 'Reserved',\n render: (row) => row.reserved_at\n ? <DateValue date={row.reserved_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'expired_at',\n label: 'Processed',\n render: (row) => row.expired_at\n ? <DateValue date={row.expired_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'priority',\n label: 'Pri',\n sortable: true,\n render: (row) => <span className=\"text-xs text-text-secondary\">{row.priority}</span>,\n className: 'w-14 text-right',\n },\n {\n key: 'retry_attempt',\n label: 'Retries',\n render: (row) => (\n <span className=\"text-xs text-text-secondary whitespace-nowrap\">\n {row.retry_attempt}/{row.max_retry_attempts}\n </span>\n ),\n className: 'w-20',\n },\n ];\n\n return (\n // Master-list flow beside a full-height panel: the left column is a plain\n // page-scrolling list (FilterBar and table headers stick against the main\n // scroll, exactly like the executions list). The panel column spans the\n // page height; its sticky viewport stays pinned with its own scroll.\n // Negative margins let the panel span the full middle row; the left\n // column re-adds those gutters for its own content.\n <div className=\"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16\">\n <div className=\"flex-1 min-w-0 pt-10 pr-10\">\n <PageHeader title=\"Messages\" docsHash=\"#docs:dashboard.md:messages\" />\n\n <FilterBar actions={\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={buildApiPath('/controlplane/stream-messages', {\n namespace: filters.namespace || namespace,\n source: filters.source || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: filters.status || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n })}\n />\n }>\n <FilterSelect\n label=\"Namespace\"\n value={filters.namespace}\n onChange={(v) => setFilter('namespace', v)}\n options={namespaceOptions}\n required\n />\n <FilterSelect\n label=\"Source\"\n value={filters.source}\n onChange={(v) => setFilter('source', v)}\n options={SOURCE_OPTIONS}\n required\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={STATUS_OPTIONS}\n />\n <FilterInput\n label=\"Stream\"\n value={filters.stream_name}\n onChange={(v) => setFilter('stream_name', v)}\n placeholder=\"Filter by stream name…\"\n />\n <FilterInput\n label=\"Job ID\"\n value={filters.jid}\n onChange={(v) => setFilter('jid', v)}\n placeholder=\"Filter by jid…\"\n />\n {/* Active dimension filter pills — inline in the sticky bar */}\n {[\n { key: 'topic', label: 'Topic', value: filters.topic },\n { key: 'workflow_name', label: 'Workflow', value: filters.workflow_name },\n { key: 'aid', label: 'Activity', value: filters.aid },\n { key: 'msg_type', label: 'Type', value: filters.msg_type },\n ].filter((f) => f.value).map((f) => (\n <button\n key={f.key}\n onClick={() => setFilter(f.key as any, '')}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors\"\n title={`Clear ${f.label} filter: ${f.value}`}\n >\n {f.label}: {truncateMiddle(f.value, 12)}\n <X className=\"w-2.5 h-2.5\" />\n </button>\n ))}\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={messages}\n keyFn={(row) => `${row.source}:${row.id}`}\n isLoading={isLoading}\n emptyMessage=\"No stream messages found\"\n onRowClick={(row) => setSelected(row)}\n activeRowKey={activeMessage ? `${activeMessage.source}:${activeMessage.id}` : null}\n sort={sort}\n onSort={setSort}\n layout=\"fixed\"\n />\n\n {/* Direct child of the tall column so sticky works; its -mx-10 fills\n the column's pr-10, ending flush at the panel's edge. */}\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Detail panel — spans the page height; the sticky viewport keeps the\n chrome pinned to the visible area with its own scroll. */}\n <SlidePanel open={panelOpen} width={416} className=\"self-stretch\">\n <div className=\"h-full pl-4\">\n <SlidePanelViews\n views={[{\n id: 'detail',\n icon: MessageSquare,\n label: 'Message Detail',\n content: displayMessage ? (\n <StreamMessageDetail\n message={displayMessage}\n filters={{\n onFilterStatus: (v) => setFilter('status', v),\n onFilterStreamName: (v) => setFilter('stream_name', v),\n onFilterMsgType: (v) => setFilter('msg_type', v),\n onFilterTopic: (v) => setFilter('topic', v),\n onFilterWorkflow: (v) => setFilter('workflow_name', v),\n onFilterJid: (v) => setFilter('jid', v),\n onFilterAid: (v) => setFilter('aid', v),\n }}\n />\n ) : null,\n }]}\n activeId=\"detail\"\n onViewChange={() => {}}\n onClose={() => setSelected(null)}\n stickyClassName=\"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9\"\n />\n </div>\n </SlidePanel>\n </div>\n );\n}\n"],"names":["truncateMiddle","str","max","half","StreamMessagesPage","namespace","available","useNamespace","filters","setFilter","pagination","sort","setSort","useFilterParams","selected","setSelected","useState","namespaceOptions","useMemo","id","data","isLoading","refetch","isFetching","useStreamMessages","messages","total","activeMessage","m","panelOpen","lastMessage","setLastMessage","useEffect","displayMessage","columns","row","jsxs","jsx","STATUS_DOT","STATUS_LABEL","SOURCE_BADGE","DateValue","PageHeader","FilterBar","ListToolbar","buildApiPath","FilterSelect","v","SOURCE_OPTIONS","STATUS_OPTIONS","FilterInput","f","X","DataTable","StickyPagination","SlidePanel","SlidePanelViews","MessageSquare","StreamMessageDetail"],"mappings":"kxBAgBA,SAASA,EAAeC,EAAaC,EAAqB,CACxD,GAAID,EAAI,QAAUC,EAAK,OAAOD,EAC9B,MAAME,EAAO,KAAK,OAAOD,EAAM,GAAK,CAAC,EACrC,MAAO,GAAGD,EAAI,MAAM,EAAGE,CAAI,CAAC,IAAIF,EAAI,MAAM,CAACE,CAAI,CAAC,EAClD,CAEO,SAASC,IAAqB,CACnC,KAAM,CAAE,UAAAC,EAAW,UAAAC,GAAcC,EAAa,WAAW,EAEnD,CAAE,QAAAC,EAAS,UAAAC,EAAW,WAAAC,EAAY,KAAAC,EAAM,QAAAC,CAAA,EAAYC,EAAgB,CACxE,QAAS,CAAE,UAAW,GAAI,OAAQ,SAAU,OAAQ,GAAI,YAAa,GAAI,SAAU,GAAI,MAAO,GAAI,cAAe,GAAI,IAAK,GAAI,IAAK,EAAA,CAAG,CACvI,EAEK,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAA+B,IAAI,EAE7DC,EAAmBC,EAAAA,QACvB,IAAMZ,EAAU,IAAKa,IAAQ,CAAE,MAAOA,EAAI,MAAOA,CAAA,EAAK,EACtD,CAACb,CAAS,CAAA,EAGN,CAAE,KAAAc,EAAM,UAAAC,EAAW,QAAAC,EAAS,WAAAC,CAAA,EAAeC,EAAkB,CACjE,UAAWhB,EAAQ,WAAaH,EAChC,OAASG,EAAQ,QAAkC,SACnD,MAAOE,EAAW,SAClB,OAAQA,EAAW,OACnB,QAASC,EAAK,SAAW,aACzB,MAAOA,EAAK,OAAS,OACrB,OAASH,EAAQ,QAAkB,OACnC,YAAaA,EAAQ,aAAe,OACpC,SAAUA,EAAQ,UAAY,OAC9B,MAAOA,EAAQ,OAAS,OACxB,cAAeA,EAAQ,eAAiB,OACxC,IAAKA,EAAQ,KAAO,OACpB,IAAKA,EAAQ,KAAO,MAAA,CACrB,EAEKiB,GAAWL,GAAA,YAAAA,EAAM,WAAY,CAAA,EAC7BM,GAAQN,GAAA,YAAAA,EAAM,QAAS,EAEvBO,EAAgBT,EAAAA,QAAQ,IACvBJ,EACEW,EAAS,KAAMG,GAAMA,EAAE,KAAOd,EAAS,IAAMc,EAAE,SAAWd,EAAS,MAAM,GAAKA,EAD/D,KAErB,CAACW,EAAUX,CAAQ,CAAC,EAEjBe,EAAY,CAAC,CAACF,EAId,CAACG,EAAaC,CAAc,EAAIf,EAAAA,SAA+B,IAAI,EACzEgB,EAAAA,UAAU,IAAM,CACVL,KAA8BA,CAAa,CACjD,EAAG,CAACA,CAAa,CAAC,EAClB,MAAMM,EAAiBN,GAAiBG,EAKlCI,EAAmC,CACvC,CACE,IAAK,cACL,MAAO,SACP,SAAU,GACV,OAASC,GACPC,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAAC,OAAA,CACC,UAAW,8CAA8CC,EAAWH,EAAI,MAAM,CAAC,GAC/E,MAAOI,EAAaJ,EAAI,MAAM,CAAA,CAAA,EAEhCE,EAAAA,IAAC,QAAK,UAAU,iDAAiD,MAAOF,EAAI,YACzE,WAAI,WAAA,CACP,CAAA,CAAA,CACF,CAAA,EAGJ,CACE,IAAK,SACL,MAAO,SACP,OAASA,GAAQE,EAAAA,IAAC,QAAK,UAAWG,EAAe,WAAI,OAAO,EAC5D,UAAW,MAAA,EAEb,CACE,IAAK,aACL,MAAO,UACP,SAAU,GACV,OAASL,GAAQE,MAACI,EAAA,CAAU,KAAMN,EAAI,WAAY,OAAO,WAAW,UAAU,+CAAA,CAAgD,EAC9H,UAAW,MAAA,EAEb,CACE,IAAK,cACL,MAAO,WACP,OAASA,GAAQA,EAAI,YACjBE,MAACI,GAAU,KAAMN,EAAI,YAAa,OAAO,WAAW,UAAU,gDAAgD,QAC7G,OAAA,CAAK,UAAU,6BAA6B,SAAA,IAAC,EAClD,UAAW,MAAA,EAEb,CACE,IAAK,aACL,MAAO,YACP,OAASA,GAAQA,EAAI,WACjBE,MAACI,GAAU,KAAMN,EAAI,WAAY,OAAO,WAAW,UAAU,gDAAgD,QAC5G,OAAA,CAAK,UAAU,6BAA6B,SAAA,IAAC,EAClD,UAAW,MAAA,EAEb,CACE,IAAK,WACL,MAAO,MACP,SAAU,GACV,OAASA,GAAQE,EAAAA,IAAC,QAAK,UAAU,8BAA+B,WAAI,SAAS,EAC7E,UAAW,iBAAA,EAEb,CACE,IAAK,gBACL,MAAO,UACP,OAASF,GACPC,EAAAA,KAAC,OAAA,CAAK,UAAU,gDACb,SAAA,CAAAD,EAAI,cAAc,IAAEA,EAAI,kBAAA,EAC3B,EAEF,UAAW,MAAA,CACb,EAGF,OAOEC,EAAAA,KAAC,MAAA,CAAI,UAAU,kDACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,6BACb,SAAA,CAAAC,EAAAA,IAACK,EAAA,CAAW,MAAM,WAAW,SAAS,8BAA8B,EAEpEN,OAACO,GAAU,QACXN,EAAAA,IAACO,EAAA,CACC,UAAW,IAAMtB,EAAA,EACjB,WAAAC,EACA,QAASsB,EAAa,gCAAiC,CACrD,UAAWrC,EAAQ,WAAaH,EAChC,OAAQG,EAAQ,QAAU,SAC1B,MAAOE,EAAW,SAClB,OAAQA,EAAW,OACnB,QAASC,EAAK,SAAW,aACzB,MAAOA,EAAK,OAAS,OACrB,OAAQH,EAAQ,QAAU,OAC1B,YAAaA,EAAQ,aAAe,OACpC,SAAUA,EAAQ,UAAY,OAC9B,MAAOA,EAAQ,OAAS,OACxB,cAAeA,EAAQ,eAAiB,OACxC,IAAKA,EAAQ,KAAO,OACpB,IAAKA,EAAQ,KAAO,MAAA,CACrB,CAAA,CAAA,EAGH,SAAA,CAAA6B,EAAAA,IAACS,EAAA,CACC,MAAM,YACN,MAAOtC,EAAQ,UACf,SAAWuC,GAAMtC,EAAU,YAAasC,CAAC,EACzC,QAAS9B,EACT,SAAQ,EAAA,CAAA,EAEVoB,EAAAA,IAACS,EAAA,CACC,MAAM,SACN,MAAOtC,EAAQ,OACf,SAAWuC,GAAMtC,EAAU,SAAUsC,CAAC,EACtC,QAASC,EACT,SAAQ,EAAA,CAAA,EAEVX,EAAAA,IAACS,EAAA,CACC,MAAM,SACN,MAAOtC,EAAQ,OACf,SAAWuC,GAAMtC,EAAU,SAAUsC,CAAC,EACtC,QAASE,CAAA,CAAA,EAEXZ,EAAAA,IAACa,EAAA,CACC,MAAM,SACN,MAAO1C,EAAQ,YACf,SAAWuC,GAAMtC,EAAU,cAAesC,CAAC,EAC3C,YAAY,wBAAA,CAAA,EAEdV,EAAAA,IAACa,EAAA,CACC,MAAM,SACN,MAAO1C,EAAQ,IACf,SAAWuC,GAAMtC,EAAU,MAAOsC,CAAC,EACnC,YAAY,gBAAA,CAAA,EAGb,CACC,CAAE,IAAK,QAAS,MAAO,QAAS,MAAOvC,EAAQ,KAAA,EAC/C,CAAE,IAAK,gBAAiB,MAAO,WAAY,MAAOA,EAAQ,aAAA,EAC1D,CAAE,IAAK,MAAO,MAAO,WAAY,MAAOA,EAAQ,GAAA,EAChD,CAAE,IAAK,WAAY,MAAO,OAAQ,MAAOA,EAAQ,QAAA,CAAS,EAC1D,OAAQ2C,GAAMA,EAAE,KAAK,EAAE,IAAKA,GAC5Bf,EAAAA,KAAC,SAAA,CAEC,QAAS,IAAM3B,EAAU0C,EAAE,IAAY,EAAE,EACzC,UAAU,2IACV,MAAO,SAASA,EAAE,KAAK,YAAYA,EAAE,KAAK,GAEzC,SAAA,CAAAA,EAAE,MAAM,KAAGnD,EAAemD,EAAE,MAAO,EAAE,EACtCd,EAAAA,IAACe,EAAA,CAAE,UAAU,aAAA,CAAc,CAAA,CAAA,EANtBD,EAAE,GAAA,CAQV,CAAA,EACH,EAEEd,EAAAA,IAACgB,EAAA,CACC,QAAAnB,EACA,KAAMT,EACN,MAAQU,GAAQ,GAAGA,EAAI,MAAM,IAAIA,EAAI,EAAE,GACvC,UAAAd,EACA,aAAa,2BACb,WAAac,GAAQpB,EAAYoB,CAAG,EACpC,aAAcR,EAAgB,GAAGA,EAAc,MAAM,IAAIA,EAAc,EAAE,GAAK,KAC9E,KAAAhB,EACA,OAAQC,EACR,OAAO,OAAA,CAAA,EAKTyB,EAAAA,IAACiB,EAAA,CACC,KAAM5C,EAAW,KACjB,WAAYA,EAAW,WAAWgB,CAAK,EACvC,aAAchB,EAAW,QACzB,MAAAgB,EACA,SAAUhB,EAAW,SACrB,iBAAkBA,EAAW,WAAA,CAAA,CAC/B,EACF,EAIA2B,EAAAA,IAACkB,EAAA,CAAW,KAAM1B,EAAW,MAAO,IAAK,UAAU,eACjD,SAAAQ,EAAAA,IAAC,MAAA,CAAI,UAAU,cACb,SAAAA,EAAAA,IAACmB,EAAA,CACC,MAAO,CAAC,CACN,GAAI,SACJ,KAAMC,EACN,MAAO,iBACP,QAASxB,EACPI,EAAAA,IAACqB,EAAA,CACC,QAASzB,EACT,QAAS,CACP,eAAiBc,GAAMtC,EAAU,SAAUsC,CAAC,EAC5C,mBAAqBA,GAAMtC,EAAU,cAAesC,CAAC,EACrD,gBAAkBA,GAAMtC,EAAU,WAAYsC,CAAC,EAC/C,cAAgBA,GAAMtC,EAAU,QAASsC,CAAC,EAC1C,iBAAmBA,GAAMtC,EAAU,gBAAiBsC,CAAC,EACrD,YAAcA,GAAMtC,EAAU,MAAOsC,CAAC,EACtC,YAAcA,GAAMtC,EAAU,MAAOsC,CAAC,CAAA,CACxC,CAAA,EAEA,IAAA,CACL,EACD,SAAS,SACT,aAAc,IAAM,CAAC,EACrB,QAAS,IAAMhC,EAAY,IAAI,EAC/B,gBAAgB,gDAAA,CAAA,EAEpB,CAAA,CACF,CAAA,CAAA,CACF,CAEJ"}
1
+ {"version":3,"file":"index-Bx9HVzuT.js","sources":["../../src/pages/admin/streams/StreamMessagesPage.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from 'react';\nimport { X, MessageSquare } from 'lucide-react';\nimport { SlidePanel, SlidePanelViews } from '../../../components/common/layout/SlidePanel';\nimport { useStreamMessages, type StreamMessage } from '../../../api/stream-messages';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useNamespace } from '../../../hooks/useNamespace';\nimport { buildApiPath } from '../../../lib/api-path';\nimport { DataTable, type Column } from '../../../components/common/data/DataTable';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { DateValue } from '../../../components/common/display/DateValue';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { ListToolbar } from '../../../components/common/data/ListToolbar';\nimport { StreamMessageDetail } from './StreamMessageDetail';\nimport { STATUS_DOT, STATUS_LABEL, STATUS_OPTIONS, SOURCE_OPTIONS, SOURCE_BADGE } from './constants';\n\nfunction truncateMiddle(str: string, max: number): string {\n if (str.length <= max) return str;\n const half = Math.floor((max - 1) / 2);\n return `${str.slice(0, half)}…${str.slice(-half)}`;\n}\n\nexport function StreamMessagesPage() {\n const { namespace, available } = useNamespace('namespace');\n\n const { filters, setFilter, pagination, sort, setSort } = useFilterParams({\n filters: { namespace: '', source: 'worker', status: '', stream_name: '', msg_type: '', topic: '', workflow_name: '', jid: '', aid: '' },\n });\n\n const [selected, setSelected] = useState<StreamMessage | null>(null);\n\n const namespaceOptions = useMemo(\n () => available.map((id) => ({ value: id, label: id })),\n [available],\n );\n\n const { data, isLoading, refetch, isFetching } = useStreamMessages({\n namespace: filters.namespace || namespace,\n source: (filters.source as 'engine' | 'worker') || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: (filters.status as any) || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n });\n\n const messages = data?.messages ?? [];\n const total = data?.total ?? 0;\n\n const activeMessage = useMemo(() => {\n if (!selected) return null;\n return messages.find((m) => m.id === selected.id && m.source === selected.source) ?? selected;\n }, [messages, selected]);\n\n const panelOpen = !!activeMessage;\n\n // Hold the last message through the panel's closing animation so the detail\n // content stays rendered while the panel slides shut.\n const [lastMessage, setLastMessage] = useState<StreamMessage | null>(null);\n useEffect(() => {\n if (activeMessage) setLastMessage(activeMessage);\n }, [activeMessage]);\n const displayMessage = activeMessage ?? lastMessage;\n\n // Status and type live as the dot and the detail panel — the row itself\n // stays one flexible stream column plus fixed narrow facts, so the table\n // shrinks with the container (same shape as the executions list).\n const columns: Column<StreamMessage>[] = [\n {\n key: 'stream_name',\n label: 'Stream',\n sortable: true,\n render: (row) => (\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className={`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${STATUS_DOT[row.status]}`}\n title={STATUS_LABEL[row.status]}\n />\n <span className=\"font-mono text-xs text-text-secondary truncate\" title={row.stream_name}>\n {row.stream_name}\n </span>\n </div>\n ),\n },\n {\n key: 'source',\n label: 'Source',\n render: (row) => <span className={SOURCE_BADGE}>{row.source}</span>,\n className: 'w-24',\n },\n {\n key: 'created_at',\n label: 'Created',\n sortable: true,\n render: (row) => <DateValue date={row.created_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />,\n className: 'w-32',\n },\n {\n key: 'reserved_at',\n label: 'Reserved',\n render: (row) => row.reserved_at\n ? <DateValue date={row.reserved_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'expired_at',\n label: 'Processed',\n render: (row) => row.expired_at\n ? <DateValue date={row.expired_at} format=\"relative\" className=\"text-xs text-text-secondary whitespace-nowrap\" />\n : <span className=\"text-xs text-text-tertiary\">—</span>,\n className: 'w-32',\n },\n {\n key: 'priority',\n label: 'Pri',\n sortable: true,\n render: (row) => <span className=\"text-xs text-text-secondary\">{row.priority}</span>,\n className: 'w-14 text-right',\n },\n {\n key: 'retry_attempt',\n label: 'Retries',\n render: (row) => (\n <span className=\"text-xs text-text-secondary whitespace-nowrap\">\n {row.retry_attempt}/{row.max_retry_attempts}\n </span>\n ),\n className: 'w-20',\n },\n ];\n\n return (\n // Master-list flow beside a full-height panel: the left column is a plain\n // page-scrolling list (FilterBar and table headers stick against the main\n // scroll, exactly like the executions list). The panel column spans the\n // page height; its sticky viewport stays pinned with its own scroll.\n // Negative margins let the panel span the full middle row; the left\n // column re-adds those gutters for its own content.\n <div className=\"flex items-stretch min-w-0 -mt-10 -mr-10 -mb-16\">\n <div className=\"flex-1 min-w-0 pt-10 pr-10\">\n <PageHeader title=\"Messages\" docsHash=\"#docs:dashboard.md:messages\" />\n\n <FilterBar actions={\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={buildApiPath('/controlplane/stream-messages', {\n namespace: filters.namespace || namespace,\n source: filters.source || 'worker',\n limit: pagination.pageSize,\n offset: pagination.offset,\n sort_by: sort.sort_by || 'created_at',\n order: sort.order || 'desc',\n status: filters.status || undefined,\n stream_name: filters.stream_name || undefined,\n msg_type: filters.msg_type || undefined,\n topic: filters.topic || undefined,\n workflow_name: filters.workflow_name || undefined,\n jid: filters.jid || undefined,\n aid: filters.aid || undefined,\n })}\n />\n }>\n <FilterSelect\n label=\"Namespace\"\n value={filters.namespace}\n onChange={(v) => setFilter('namespace', v)}\n options={namespaceOptions}\n required\n />\n <FilterSelect\n label=\"Source\"\n value={filters.source}\n onChange={(v) => setFilter('source', v)}\n options={SOURCE_OPTIONS}\n required\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={STATUS_OPTIONS}\n />\n <FilterInput\n label=\"Stream\"\n value={filters.stream_name}\n onChange={(v) => setFilter('stream_name', v)}\n placeholder=\"Filter by stream name…\"\n />\n <FilterInput\n label=\"Job ID\"\n value={filters.jid}\n onChange={(v) => setFilter('jid', v)}\n placeholder=\"Filter by jid…\"\n />\n {/* Active dimension filter pills — inline in the sticky bar */}\n {[\n { key: 'topic', label: 'Topic', value: filters.topic },\n { key: 'workflow_name', label: 'Workflow', value: filters.workflow_name },\n { key: 'aid', label: 'Activity', value: filters.aid },\n { key: 'msg_type', label: 'Type', value: filters.msg_type },\n ].filter((f) => f.value).map((f) => (\n <button\n key={f.key}\n onClick={() => setFilter(f.key as any, '')}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-2xs font-mono rounded-full bg-accent/15 text-accent hover:bg-accent/25 transition-colors\"\n title={`Clear ${f.label} filter: ${f.value}`}\n >\n {f.label}: {truncateMiddle(f.value, 12)}\n <X className=\"w-2.5 h-2.5\" />\n </button>\n ))}\n </FilterBar>\n\n <DataTable\n columns={columns}\n data={messages}\n keyFn={(row) => `${row.source}:${row.id}`}\n isLoading={isLoading}\n emptyMessage=\"No stream messages found\"\n onRowClick={(row) => setSelected(row)}\n activeRowKey={activeMessage ? `${activeMessage.source}:${activeMessage.id}` : null}\n sort={sort}\n onSort={setSort}\n layout=\"fixed\"\n />\n\n {/* Direct child of the tall column so sticky works; its -mx-10 fills\n the column's pr-10, ending flush at the panel's edge. */}\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Detail panel — spans the page height; the sticky viewport keeps the\n chrome pinned to the visible area with its own scroll. */}\n <SlidePanel open={panelOpen} width={416} className=\"self-stretch\">\n <div className=\"h-full pl-4\">\n <SlidePanelViews\n views={[{\n id: 'detail',\n icon: MessageSquare,\n label: 'Message Detail',\n content: displayMessage ? (\n <StreamMessageDetail\n message={displayMessage}\n filters={{\n onFilterStatus: (v) => setFilter('status', v),\n onFilterStreamName: (v) => setFilter('stream_name', v),\n onFilterMsgType: (v) => setFilter('msg_type', v),\n onFilterTopic: (v) => setFilter('topic', v),\n onFilterWorkflow: (v) => setFilter('workflow_name', v),\n onFilterJid: (v) => setFilter('jid', v),\n onFilterAid: (v) => setFilter('aid', v),\n }}\n />\n ) : null,\n }]}\n activeId=\"detail\"\n onViewChange={() => {}}\n onClose={() => setSelected(null)}\n stickyClassName=\"sticky top-0 z-10 h-[calc(100vh-5.25rem)] pt-9\"\n />\n </div>\n </SlidePanel>\n </div>\n );\n}\n"],"names":["truncateMiddle","str","max","half","StreamMessagesPage","namespace","available","useNamespace","filters","setFilter","pagination","sort","setSort","useFilterParams","selected","setSelected","useState","namespaceOptions","useMemo","id","data","isLoading","refetch","isFetching","useStreamMessages","messages","total","activeMessage","m","panelOpen","lastMessage","setLastMessage","useEffect","displayMessage","columns","row","jsxs","jsx","STATUS_DOT","STATUS_LABEL","SOURCE_BADGE","DateValue","PageHeader","FilterBar","ListToolbar","buildApiPath","FilterSelect","v","SOURCE_OPTIONS","STATUS_OPTIONS","FilterInput","f","X","DataTable","StickyPagination","SlidePanel","SlidePanelViews","MessageSquare","StreamMessageDetail"],"mappings":"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"}