@hotmeshio/long-tail 0.28.1 → 0.28.3

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 (222) hide show
  1. package/build/lib/events/publish.js +3 -2
  2. package/build/lib/machines/transport/nats-bus.d.ts +2 -0
  3. package/build/lib/machines/transport/stream-bus.d.ts +2 -0
  4. package/build/lib/machines/transport/stream-bus.js +8 -2
  5. package/build/lib/machines/transport/streams.d.ts +2 -1
  6. package/build/lib/machines/transport/streams.js +3 -2
  7. package/build/lib/messaging/memory.js +7 -3
  8. package/build/lib/messaging/nats/permissions.js +1 -0
  9. package/build/lib/messaging/nats/streams.d.ts +18 -4
  10. package/build/lib/messaging/nats/streams.js +55 -10
  11. package/build/services/machines/gateway/dispatcher.js +18 -6
  12. package/build/services/machines/gateway/executor.d.ts +6 -1
  13. package/build/services/machines/gateway/executor.js +19 -2
  14. package/build/services/machines/gateway/log.d.ts +1 -0
  15. package/build/services/machines/gateway/log.js +1 -0
  16. package/build/services/machines/gateway/plan-escalation.js +21 -3
  17. package/build/services/machines/gateway/state.d.ts +4 -0
  18. package/build/services/machines/gateway/state.js +1 -1
  19. package/build/services/machines/leadership.d.ts +2 -0
  20. package/build/services/machines/leadership.js +7 -1
  21. package/build/services/machines/select.d.ts +1 -1
  22. package/build/services/machines/select.js +2 -2
  23. package/build/services/machines/surface.js +8 -2
  24. package/build/types/messaging.d.ts +5 -1
  25. package/dashboard/dist/assets/{AdminDashboard-Bm7VG65H.js → AdminDashboard-DRE0hSDS.js} +2 -2
  26. package/dashboard/dist/assets/{AdminDashboard-Bm7VG65H.js.map → AdminDashboard-DRE0hSDS.js.map} +1 -1
  27. package/dashboard/dist/assets/{AgentConfigPage-aJF7Sdbc.js → AgentConfigPage-BuflQGgy.js} +2 -2
  28. package/dashboard/dist/assets/{AgentConfigPage-aJF7Sdbc.js.map → AgentConfigPage-BuflQGgy.js.map} +1 -1
  29. package/dashboard/dist/assets/{AgentDetailPage-GwwghhxT.js → AgentDetailPage-BiL9FB7i.js} +2 -2
  30. package/dashboard/dist/assets/{AgentDetailPage-GwwghhxT.js.map → AgentDetailPage-BiL9FB7i.js.map} +1 -1
  31. package/dashboard/dist/assets/{AgentsPage-DVvCzZyg.js → AgentsPage-C4ZxCNxt.js} +2 -2
  32. package/dashboard/dist/assets/{AgentsPage-DVvCzZyg.js.map → AgentsPage-C4ZxCNxt.js.map} +1 -1
  33. package/dashboard/dist/assets/{AvailableEscalationsPage-Cxmcji_K.js → AvailableEscalationsPage-B5p8QJvI.js} +2 -2
  34. package/dashboard/dist/assets/{AvailableEscalationsPage-Cxmcji_K.js.map → AvailableEscalationsPage-B5p8QJvI.js.map} +1 -1
  35. package/dashboard/dist/assets/{BotPicker-CofRxk4L.js → BotPicker-B7V77PnY.js} +2 -2
  36. package/dashboard/dist/assets/{BotPicker-CofRxk4L.js.map → BotPicker-B7V77PnY.js.map} +1 -1
  37. package/dashboard/dist/assets/{BulkAssignModal-BARWuz4L.js → BulkAssignModal-DcGVMQqm.js} +2 -2
  38. package/dashboard/dist/assets/{BulkAssignModal-BARWuz4L.js.map → BulkAssignModal-DcGVMQqm.js.map} +1 -1
  39. package/dashboard/dist/assets/{CapabilitiesPage-BJAWVNEx.js → CapabilitiesPage-DmbC1pEs.js} +2 -2
  40. package/dashboard/dist/assets/{CapabilitiesPage-BJAWVNEx.js.map → CapabilitiesPage-DmbC1pEs.js.map} +1 -1
  41. package/dashboard/dist/assets/{CollapsibleSection-CtgoaG75.js → CollapsibleSection-C81S1qic.js} +2 -2
  42. package/dashboard/dist/assets/{CollapsibleSection-CtgoaG75.js.map → CollapsibleSection-C81S1qic.js.map} +1 -1
  43. package/dashboard/dist/assets/{ConfirmDeleteModal-BYXXBWs6.js → ConfirmDeleteModal-3RFyWN9Q.js} +2 -2
  44. package/dashboard/dist/assets/{ConfirmDeleteModal-BYXXBWs6.js.map → ConfirmDeleteModal-3RFyWN9Q.js.map} +1 -1
  45. package/dashboard/dist/assets/{ConnectedAppsPage-D0JkzWa7.js → ConnectedAppsPage-B0D2OvTD.js} +2 -2
  46. package/dashboard/dist/assets/{ConnectedAppsPage-D0JkzWa7.js.map → ConnectedAppsPage-B0D2OvTD.js.map} +1 -1
  47. package/dashboard/dist/assets/{CountdownTimer-BcFxdZYN.js → CountdownTimer-iAG28fzG.js} +2 -2
  48. package/dashboard/dist/assets/{CountdownTimer-BcFxdZYN.js.map → CountdownTimer-iAG28fzG.js.map} +1 -1
  49. package/dashboard/dist/assets/{CredentialsPage-DPSY20rV.js → CredentialsPage-DoFwNvFv.js} +2 -2
  50. package/dashboard/dist/assets/{CredentialsPage-DPSY20rV.js.map → CredentialsPage-DoFwNvFv.js.map} +1 -1
  51. package/dashboard/dist/assets/{CronLabel-Dg_Oew_Y.js → CronLabel-C1Bb2wo4.js} +2 -2
  52. package/dashboard/dist/assets/{CronLabel-Dg_Oew_Y.js.map → CronLabel-C1Bb2wo4.js.map} +1 -1
  53. package/dashboard/dist/assets/{ElapsedCell-Dm3G5fK2.js → ElapsedCell-DZs1I1JW.js} +2 -2
  54. package/dashboard/dist/assets/{ElapsedCell-Dm3G5fK2.js.map → ElapsedCell-DZs1I1JW.js.map} +1 -1
  55. package/dashboard/dist/assets/{EntityTimelinePanel-CrEEP04e.js → EntityTimelinePanel-Du1O6Oly.js} +2 -2
  56. package/dashboard/dist/assets/{EntityTimelinePanel-CrEEP04e.js.map → EntityTimelinePanel-Du1O6Oly.js.map} +1 -1
  57. package/dashboard/dist/assets/{EscalationListSchemaPage-wOInXcjs.js → EscalationListSchemaPage-CrpBhC0e.js} +2 -2
  58. package/dashboard/dist/assets/{EscalationListSchemaPage-wOInXcjs.js.map → EscalationListSchemaPage-CrpBhC0e.js.map} +1 -1
  59. package/dashboard/dist/assets/{EscalationSchemaPage-CrIj_g9d.js → EscalationSchemaPage-Co59lcuD.js} +2 -2
  60. package/dashboard/dist/assets/{EscalationSchemaPage-CrIj_g9d.js.map → EscalationSchemaPage-Co59lcuD.js.map} +1 -1
  61. package/dashboard/dist/assets/{EscalationTimeline-CeAsl5IT.js → EscalationTimeline-B_fzNsX5.js} +2 -2
  62. package/dashboard/dist/assets/{EscalationTimeline-CeAsl5IT.js.map → EscalationTimeline-B_fzNsX5.js.map} +1 -1
  63. package/dashboard/dist/assets/{EscalationTitleSelect-D8qpCYiy.js → EscalationTitleSelect-C2Goebjo.js} +2 -2
  64. package/dashboard/dist/assets/{EscalationTitleSelect-D8qpCYiy.js.map → EscalationTitleSelect-C2Goebjo.js.map} +1 -1
  65. package/dashboard/dist/assets/{EscalationsOverview-CvaqVPsr.js → EscalationsOverview-Cgmrl8Zc.js} +2 -2
  66. package/dashboard/dist/assets/{EscalationsOverview-CvaqVPsr.js.map → EscalationsOverview-Cgmrl8Zc.js.map} +1 -1
  67. package/dashboard/dist/assets/{EventTable-Be0JuEl6.js → EventTable-BdEiu3Fv.js} +2 -2
  68. package/dashboard/dist/assets/{EventTable-Be0JuEl6.js.map → EventTable-BdEiu3Fv.js.map} +1 -1
  69. package/dashboard/dist/assets/{FilterBar-BVyAjIgv.js → FilterBar-CzKYBOMC.js} +2 -2
  70. package/dashboard/dist/assets/{FilterBar-BVyAjIgv.js.map → FilterBar-CzKYBOMC.js.map} +1 -1
  71. package/dashboard/dist/assets/{GraphInvokePage-D_QigJeD.js → GraphInvokePage-CcDFhY53.js} +2 -2
  72. package/dashboard/dist/assets/{GraphInvokePage-D_QigJeD.js.map → GraphInvokePage-CcDFhY53.js.map} +1 -1
  73. package/dashboard/dist/assets/{HomePage-C1haeuNy.js → HomePage-Xahqcdu9.js} +2 -2
  74. package/dashboard/dist/assets/{HomePage-C1haeuNy.js.map → HomePage-Xahqcdu9.js.map} +1 -1
  75. package/dashboard/dist/assets/{LinePage-CWD5pv1g.js → LinePage-DKwhGunp.js} +2 -2
  76. package/dashboard/dist/assets/{LinePage-CWD5pv1g.js.map → LinePage-DKwhGunp.js.map} +1 -1
  77. package/dashboard/dist/assets/{LinesPage-NqChsKcO.js → LinesPage-BXZVO4MC.js} +2 -2
  78. package/dashboard/dist/assets/{LinesPage-NqChsKcO.js.map → LinesPage-BXZVO4MC.js.map} +1 -1
  79. package/dashboard/dist/assets/{ListToolbar-BZCNrTh6.js → ListToolbar-orQsOdl_.js} +2 -2
  80. package/dashboard/dist/assets/{ListToolbar-BZCNrTh6.js.map → ListToolbar-orQsOdl_.js.map} +1 -1
  81. package/dashboard/dist/assets/{McpOverview-yJTYnh1z.js → McpOverview-pSnadtSM.js} +2 -2
  82. package/dashboard/dist/assets/{McpOverview-yJTYnh1z.js.map → McpOverview-pSnadtSM.js.map} +1 -1
  83. package/dashboard/dist/assets/{McpQueryDetailPage-ChuLpJ4u.js → McpQueryDetailPage-BCAJ3rKO.js} +2 -2
  84. package/dashboard/dist/assets/{McpQueryDetailPage-ChuLpJ4u.js.map → McpQueryDetailPage-BCAJ3rKO.js.map} +1 -1
  85. package/dashboard/dist/assets/{McpQueryPage-9S-v9soF.js → McpQueryPage-CRyXeRp5.js} +2 -2
  86. package/dashboard/dist/assets/{McpQueryPage-9S-v9soF.js.map → McpQueryPage-CRyXeRp5.js.map} +1 -1
  87. package/dashboard/dist/assets/{McpRunDetailPage-BhrcfxD5.js → McpRunDetailPage-BHppCztI.js} +2 -2
  88. package/dashboard/dist/assets/{McpRunDetailPage-BhrcfxD5.js.map → McpRunDetailPage-BHppCztI.js.map} +1 -1
  89. package/dashboard/dist/assets/{McpRunsPage-C5_i8_Zx.js → McpRunsPage-Cd9yCT-_.js} +2 -2
  90. package/dashboard/dist/assets/{McpRunsPage-C5_i8_Zx.js.map → McpRunsPage-Cd9yCT-_.js.map} +1 -1
  91. package/dashboard/dist/assets/{OperationsPage-C03CeU5P.js → OperationsPage-BtnthZgj.js} +2 -2
  92. package/dashboard/dist/assets/{OperationsPage-C03CeU5P.js.map → OperationsPage-BtnthZgj.js.map} +1 -1
  93. package/dashboard/dist/assets/{OperatorDashboard-BzC134Jt.js → OperatorDashboard-B4_OBhYh.js} +2 -2
  94. package/dashboard/dist/assets/{OperatorDashboard-BzC134Jt.js.map → OperatorDashboard-B4_OBhYh.js.map} +1 -1
  95. package/dashboard/dist/assets/{PersonaDetailPage-D0mY9L6j.js → PersonaDetailPage-BAYjM9qf.js} +2 -2
  96. package/dashboard/dist/assets/{PersonaDetailPage-D0mY9L6j.js.map → PersonaDetailPage-BAYjM9qf.js.map} +1 -1
  97. package/dashboard/dist/assets/{PersonasPage-FFlm5Eug.js → PersonasPage-6HsOp-1y.js} +2 -2
  98. package/dashboard/dist/assets/{PersonasPage-FFlm5Eug.js.map → PersonasPage-6HsOp-1y.js.map} +1 -1
  99. package/dashboard/dist/assets/{PortalPage-Cpc25uO-.js → PortalPage-6OMr7KtJ.js} +2 -2
  100. package/dashboard/dist/assets/{PortalPage-Cpc25uO-.js.map → PortalPage-6OMr7KtJ.js.map} +1 -1
  101. package/dashboard/dist/assets/{ProcessDetailPage-Di2J7KwY.js → ProcessDetailPage-AidH_h7z.js} +2 -2
  102. package/dashboard/dist/assets/{ProcessDetailPage-Di2J7KwY.js.map → ProcessDetailPage-AidH_h7z.js.map} +1 -1
  103. package/dashboard/dist/assets/{ProcessesListPage-BEXwU3Z0.js → ProcessesListPage-BWKoKbXk.js} +2 -2
  104. package/dashboard/dist/assets/{ProcessesListPage-BEXwU3Z0.js.map → ProcessesListPage-BWKoKbXk.js.map} +1 -1
  105. package/dashboard/dist/assets/{ResolverForm-2ks-3jXC.js → ResolverForm-BaSvhLoT.js} +2 -2
  106. package/dashboard/dist/assets/ResolverForm-BaSvhLoT.js.map +1 -0
  107. package/dashboard/dist/assets/{RoleDetailPage-DqoOk0xc.js → RoleDetailPage-D_30TDVh.js} +2 -2
  108. package/dashboard/dist/assets/{RoleDetailPage-DqoOk0xc.js.map → RoleDetailPage-D_30TDVh.js.map} +1 -1
  109. package/dashboard/dist/assets/{RolesPage-CPmo8Srr.js → RolesPage-T2hH_MV5.js} +2 -2
  110. package/dashboard/dist/assets/{RolesPage-CPmo8Srr.js.map → RolesPage-T2hH_MV5.js.map} +1 -1
  111. package/dashboard/dist/assets/{RosterWidget-D2yovCKw.js → RosterWidget-DG6Rcx4P.js} +2 -2
  112. package/dashboard/dist/assets/{RosterWidget-D2yovCKw.js.map → RosterWidget-DG6Rcx4P.js.map} +1 -1
  113. package/dashboard/dist/assets/{RunAsSelector-CMv96On6.js → RunAsSelector-M2h9U6PP.js} +2 -2
  114. package/dashboard/dist/assets/{RunAsSelector-CMv96On6.js.map → RunAsSelector-M2h9U6PP.js.map} +1 -1
  115. package/dashboard/dist/assets/{ScanCodesPage-CA6cTT-M.js → ScanCodesPage-lB_WxoZw.js} +2 -2
  116. package/dashboard/dist/assets/{ScanCodesPage-CA6cTT-M.js.map → ScanCodesPage-lB_WxoZw.js.map} +1 -1
  117. package/dashboard/dist/assets/{ScanSchemeDetailPage-DnctN5-H.js → ScanSchemeDetailPage-C3VLg61H.js} +2 -2
  118. package/dashboard/dist/assets/{ScanSchemeDetailPage-DnctN5-H.js.map → ScanSchemeDetailPage-C3VLg61H.js.map} +1 -1
  119. package/dashboard/dist/assets/{ScanStationPage-Bk8RwkKL.js → ScanStationPage-CVET1_4r.js} +2 -2
  120. package/dashboard/dist/assets/{ScanStationPage-Bk8RwkKL.js.map → ScanStationPage-CVET1_4r.js.map} +1 -1
  121. package/dashboard/dist/assets/{StickyPagination-B0FSuUgs.js → StickyPagination-BdjseWXr.js} +2 -2
  122. package/dashboard/dist/assets/{StickyPagination-B0FSuUgs.js.map → StickyPagination-BdjseWXr.js.map} +1 -1
  123. package/dashboard/dist/assets/{StreamMessageDetail-BwZEvMpP.js → StreamMessageDetail-DJCBxETh.js} +2 -2
  124. package/dashboard/dist/assets/{StreamMessageDetail-BwZEvMpP.js.map → StreamMessageDetail-DJCBxETh.js.map} +1 -1
  125. package/dashboard/dist/assets/{SwimlaneTimeline-BDVQEaMw.js → SwimlaneTimeline-DiXm9jIk.js} +2 -2
  126. package/dashboard/dist/assets/{SwimlaneTimeline-BDVQEaMw.js.map → SwimlaneTimeline-DiXm9jIk.js.map} +1 -1
  127. package/dashboard/dist/assets/{TaskDetailPage-BOlv3iGB.js → TaskDetailPage-m8CQFN4w.js} +2 -2
  128. package/dashboard/dist/assets/{TaskDetailPage-BOlv3iGB.js.map → TaskDetailPage-m8CQFN4w.js.map} +1 -1
  129. package/dashboard/dist/assets/{TasksListPage-e2teY0bD.js → TasksListPage-DHBSUhZC.js} +2 -2
  130. package/dashboard/dist/assets/{TasksListPage-e2teY0bD.js.map → TasksListPage-DHBSUhZC.js.map} +1 -1
  131. package/dashboard/dist/assets/{TimeAgo-Cvkpf_b3.js → TimeAgo-Cq3bKUd-.js} +2 -2
  132. package/dashboard/dist/assets/{TimeAgo-Cvkpf_b3.js.map → TimeAgo-Cq3bKUd-.js.map} +1 -1
  133. package/dashboard/dist/assets/{TimestampCell-B3btAV0N.js → TimestampCell-e5gRR_FY.js} +2 -2
  134. package/dashboard/dist/assets/{TimestampCell-B3btAV0N.js.map → TimestampCell-e5gRR_FY.js.map} +1 -1
  135. package/dashboard/dist/assets/{ToolTestPanel-B03nebR7.js → ToolTestPanel-Bg0ss9oN.js} +2 -2
  136. package/dashboard/dist/assets/{ToolTestPanel-B03nebR7.js.map → ToolTestPanel-Bg0ss9oN.js.map} +1 -1
  137. package/dashboard/dist/assets/{TopicDetailPage-DBRWne3O.js → TopicDetailPage-DhPiCfOO.js} +2 -2
  138. package/dashboard/dist/assets/{TopicDetailPage-DBRWne3O.js.map → TopicDetailPage-DhPiCfOO.js.map} +1 -1
  139. package/dashboard/dist/assets/{TopicsPage-CVe2M9HD.js → TopicsPage-BqZaVv3d.js} +2 -2
  140. package/dashboard/dist/assets/{TopicsPage-CVe2M9HD.js.map → TopicsPage-BqZaVv3d.js.map} +1 -1
  141. package/dashboard/dist/assets/{UserName-B_q_qp6V.js → UserName-C6ZNHHKN.js} +2 -2
  142. package/dashboard/dist/assets/{UserName-B_q_qp6V.js.map → UserName-C6ZNHHKN.js.map} +1 -1
  143. package/dashboard/dist/assets/{WorkflowExecutionPage-Bh_dr9tM.js → WorkflowExecutionPage-BUqIhtcr.js} +2 -2
  144. package/dashboard/dist/assets/{WorkflowExecutionPage-Bh_dr9tM.js.map → WorkflowExecutionPage-BUqIhtcr.js.map} +1 -1
  145. package/dashboard/dist/assets/{WorkflowsDashboard-DA6Mj7qH.js → WorkflowsDashboard-BKxhC_hT.js} +2 -2
  146. package/dashboard/dist/assets/{WorkflowsDashboard-DA6Mj7qH.js.map → WorkflowsDashboard-BKxhC_hT.js.map} +1 -1
  147. package/dashboard/dist/assets/{WorkflowsOverview-B1kBLj-a.js → WorkflowsOverview-018s2q_p.js} +2 -2
  148. package/dashboard/dist/assets/{WorkflowsOverview-B1kBLj-a.js.map → WorkflowsOverview-018s2q_p.js.map} +1 -1
  149. package/dashboard/dist/assets/{YamlWorkflowDetailPage-6GJM8QIX.js → YamlWorkflowDetailPage-C2zcXDr1.js} +2 -2
  150. package/dashboard/dist/assets/{YamlWorkflowDetailPage-6GJM8QIX.js.map → YamlWorkflowDetailPage-C2zcXDr1.js.map} +1 -1
  151. package/dashboard/dist/assets/{YamlWorkflowsPage-Bu811C7f.js → YamlWorkflowsPage-aVcNZNu6.js} +2 -2
  152. package/dashboard/dist/assets/{YamlWorkflowsPage-Bu811C7f.js.map → YamlWorkflowsPage-aVcNZNu6.js.map} +1 -1
  153. package/dashboard/dist/assets/{agents-MPk_GnYz.js → agents-DRaaJUue.js} +2 -2
  154. package/dashboard/dist/assets/{agents-MPk_GnYz.js.map → agents-DRaaJUue.js.map} +1 -1
  155. package/dashboard/dist/assets/{bots-2RihE2Tc.js → bots-C4N90NCj.js} +2 -2
  156. package/dashboard/dist/assets/{bots-2RihE2Tc.js.map → bots-C4N90NCj.js.map} +1 -1
  157. package/dashboard/dist/assets/{capabilities-CC4iwJ1P.js → capabilities-BoRWifSC.js} +2 -2
  158. package/dashboard/dist/assets/{capabilities-CC4iwJ1P.js.map → capabilities-BoRWifSC.js.map} +1 -1
  159. package/dashboard/dist/assets/{controlplane-Bmkic8BH.js → controlplane-DGZAxi7J.js} +2 -2
  160. package/dashboard/dist/assets/{controlplane-Bmkic8BH.js.map → controlplane-DGZAxi7J.js.map} +1 -1
  161. package/dashboard/dist/assets/{escalation-columns-B0lhUUrQ.js → escalation-columns-DJbfsH_m.js} +2 -2
  162. package/dashboard/dist/assets/{escalation-columns-B0lhUUrQ.js.map → escalation-columns-DJbfsH_m.js.map} +1 -1
  163. package/dashboard/dist/assets/{escalation-items-7WFpPo46.js → escalation-items-C8iJZEA8.js} +2 -2
  164. package/dashboard/dist/assets/{escalation-items-7WFpPo46.js.map → escalation-items-C8iJZEA8.js.map} +1 -1
  165. package/dashboard/dist/assets/{index-CvJsvqIc.js → index-3HaFP00M.js} +2 -2
  166. package/dashboard/dist/assets/{index-CvJsvqIc.js.map → index-3HaFP00M.js.map} +1 -1
  167. package/dashboard/dist/assets/{index-CmsmwCyv.js → index-BFxHIfQ_.js} +2 -2
  168. package/dashboard/dist/assets/{index-CmsmwCyv.js.map → index-BFxHIfQ_.js.map} +1 -1
  169. package/dashboard/dist/assets/{index-C2CLfGwL.js → index-BhS9XSy8.js} +2 -2
  170. package/dashboard/dist/assets/{index-C2CLfGwL.js.map → index-BhS9XSy8.js.map} +1 -1
  171. package/dashboard/dist/assets/{index-DSUtfDXx.js → index-BuSUevzO.js} +2 -2
  172. package/dashboard/dist/assets/{index-DSUtfDXx.js.map → index-BuSUevzO.js.map} +1 -1
  173. package/dashboard/dist/assets/{index-Da6ycKyf.js → index-CXXc9sUr.js} +2 -2
  174. package/dashboard/dist/assets/index-CXXc9sUr.js.map +1 -0
  175. package/dashboard/dist/assets/{index-D-ilRyfy.js → index-CeeSFnl-.js} +2 -2
  176. package/dashboard/dist/assets/{index-D-ilRyfy.js.map → index-CeeSFnl-.js.map} +1 -1
  177. package/dashboard/dist/assets/{index-CcArGkzI.js → index-CjjRxpVe.js} +2 -2
  178. package/dashboard/dist/assets/index-CjjRxpVe.js.map +1 -0
  179. package/dashboard/dist/assets/{index-CRWsB7ZC.js → index-CyL-6CAa.js} +2 -2
  180. package/dashboard/dist/assets/{index-CRWsB7ZC.js.map → index-CyL-6CAa.js.map} +1 -1
  181. package/dashboard/dist/assets/{index-C3AeFihz.js → index-DIU89TX3.js} +2 -2
  182. package/dashboard/dist/assets/{index-C3AeFihz.js.map → index-DIU89TX3.js.map} +1 -1
  183. package/dashboard/dist/assets/{index-B_XV1rwu.js → index-DMKLnxt8.js} +2 -2
  184. package/dashboard/dist/assets/{index-B_XV1rwu.js.map → index-DMKLnxt8.js.map} +1 -1
  185. package/dashboard/dist/assets/{index-CTOv3G7a.js → index-DeyA88jq.js} +2 -2
  186. package/dashboard/dist/assets/{index-CTOv3G7a.js.map → index-DeyA88jq.js.map} +1 -1
  187. package/dashboard/dist/assets/{index-CBri8fYM.js → index-DhKGp4QK.js} +2 -2
  188. package/dashboard/dist/assets/{index-CBri8fYM.js.map → index-DhKGp4QK.js.map} +1 -1
  189. package/dashboard/dist/assets/{index-CkMHS-hG.js → index-pzbGpihI.js} +3 -3
  190. package/dashboard/dist/assets/{index-CkMHS-hG.js.map → index-pzbGpihI.js.map} +1 -1
  191. package/dashboard/dist/assets/{knowledge-Bpbg20DC.js → knowledge-BWo3OCJc.js} +2 -2
  192. package/dashboard/dist/assets/{knowledge-Bpbg20DC.js.map → knowledge-BWo3OCJc.js.map} +1 -1
  193. package/dashboard/dist/assets/{machines-BqOZZU-3.js → machines-LEYY_yar.js} +2 -2
  194. package/dashboard/dist/assets/{machines-BqOZZU-3.js.map → machines-LEYY_yar.js.map} +1 -1
  195. package/dashboard/dist/assets/{mcp-CmcUXYce.js → mcp-_0kFRcyT.js} +2 -2
  196. package/dashboard/dist/assets/{mcp-CmcUXYce.js.map → mcp-_0kFRcyT.js.map} +1 -1
  197. package/dashboard/dist/assets/{mcp-query-C8buQxN9.js → mcp-query-BzmN0lc5.js} +2 -2
  198. package/dashboard/dist/assets/{mcp-query-C8buQxN9.js.map → mcp-query-BzmN0lc5.js.map} +1 -1
  199. package/dashboard/dist/assets/{personas-C2n5oDmY.js → personas-kE4PMrgo.js} +2 -2
  200. package/dashboard/dist/assets/{personas-C2n5oDmY.js.map → personas-kE4PMrgo.js.map} +1 -1
  201. package/dashboard/dist/assets/{pipelines-RKpSkFz7.js → pipelines-DYDNaypF.js} +2 -2
  202. package/dashboard/dist/assets/{pipelines-RKpSkFz7.js.map → pipelines-DYDNaypF.js.map} +1 -1
  203. package/dashboard/dist/assets/{tasks-Dab4hExW.js → tasks-ClJ-mbj9.js} +2 -2
  204. package/dashboard/dist/assets/{tasks-Dab4hExW.js.map → tasks-ClJ-mbj9.js.map} +1 -1
  205. package/dashboard/dist/assets/{topics-FTMNP7r3.js → topics-oHX4vbqe.js} +2 -2
  206. package/dashboard/dist/assets/{topics-FTMNP7r3.js.map → topics-oHX4vbqe.js.map} +1 -1
  207. package/dashboard/dist/assets/{useDebouncedValue-B_1u1YIk.js → useDebouncedValue-C97KADrj.js} +2 -2
  208. package/dashboard/dist/assets/{useDebouncedValue-B_1u1YIk.js.map → useDebouncedValue-C97KADrj.js.map} +1 -1
  209. package/dashboard/dist/assets/{useNamespace-HUeAI7Qb.js → useNamespace-Kje0Rn7j.js} +2 -2
  210. package/dashboard/dist/assets/{useNamespace-HUeAI7Qb.js.map → useNamespace-Kje0Rn7j.js.map} +1 -1
  211. package/dashboard/dist/assets/{useYamlActivityEvents-Cax54qHH.js → useYamlActivityEvents-DMz-HKFv.js} +2 -2
  212. package/dashboard/dist/assets/{useYamlActivityEvents-Cax54qHH.js.map → useYamlActivityEvents-DMz-HKFv.js.map} +1 -1
  213. package/dashboard/dist/assets/{validate-DxOaV7QS.js → validate-hUqjWN63.js} +2 -2
  214. package/dashboard/dist/assets/{validate-DxOaV7QS.js.map → validate-hUqjWN63.js.map} +1 -1
  215. package/dashboard/dist/assets/{yaml-workflows-BgY1XHJx.js → yaml-workflows-64vfmKJx.js} +2 -2
  216. package/dashboard/dist/assets/{yaml-workflows-BgY1XHJx.js.map → yaml-workflows-64vfmKJx.js.map} +1 -1
  217. package/dashboard/dist/index.html +1 -1
  218. package/docs/machines.md +3 -3
  219. package/package.json +1 -1
  220. package/dashboard/dist/assets/ResolverForm-2ks-3jXC.js.map +0 -1
  221. package/dashboard/dist/assets/index-CcArGkzI.js.map +0 -1
  222. package/dashboard/dist/assets/index-Da6ycKyf.js.map +0 -1
@@ -18,12 +18,13 @@ const index_1 = require("./index");
18
18
  const matching_1 = require("./matching");
19
19
  const logger_1 = require("../logger");
20
20
  /**
21
- * Fire-and-forget publish helper. Swallows errors (best-effort).
21
+ * Fire-and-forget publish helper. Swallows errors (best-effort). The publish
22
+ * is noted at debug: a line's wire can carry many events a second.
22
23
  */
23
24
  function fireAndForget(event) {
24
25
  if (!index_1.eventRegistry.hasAdapters)
25
26
  return Promise.resolve();
26
- logger_1.loggerRegistry.info(`[lt-pub] ${event.type} ${event.workflowId || ''} ${event.escalationId || event.taskId || ''}`);
27
+ logger_1.loggerRegistry.debug(`[lt-pub] ${event.type} ${event.workflowId || ''} ${event.escalationId || event.taskId || ''}`);
27
28
  return index_1.eventRegistry.publish(event).catch(() => { });
28
29
  }
29
30
  /**
@@ -20,6 +20,8 @@ export interface NatsBusOptions {
20
20
  /** The codecs of every line on this site, so the streams keep all their subjects. */
21
21
  siteCodecs?: StreamCodec[];
22
22
  nakDelayMs?: number;
23
+ /** Told once when the consumer can deliver nothing more, so the line can give its lead up and contend again. */
24
+ onLost?: (reason: string) => void;
23
25
  }
24
26
  export declare class NatsMachineBus implements MachineBus {
25
27
  private readonly opts;
@@ -24,6 +24,8 @@ export interface StreamBusOptions {
24
24
  /** The codecs of every line on this site; the streams keep all their subjects, whichever line starts last. */
25
25
  siteCodecs?: StreamCodec[];
26
26
  nakDelayMs?: number;
27
+ /** Told once when the consumer can deliver nothing more, so the line can give its lead up and contend again. */
28
+ onLost?: (reason: string) => void;
27
29
  }
28
30
  export declare class StreamMachineBus implements MachineBus {
29
31
  private readonly opts;
@@ -30,6 +30,12 @@ class StreamMachineBus {
30
30
  await streams.ensureStream(spec);
31
31
  const consumer = (0, streams_1.lineEventConsumerSpec)(codec, siteId, lineId, this.durableName);
32
32
  await streams.ensureConsumer(streams_1.LINE_STREAM.EVENTS, consumer);
33
+ const held = await streams.describeConsumer(streams_1.LINE_STREAM.EVENTS, consumer.name);
34
+ const reads = [...(held?.filterSubjects ?? [])].sort().join(', ');
35
+ const wants = [...consumer.filterSubjects].sort().join(', ');
36
+ if (reads !== wants) {
37
+ throw new Error(`${consumer.name} reads ${reads || 'nothing'} and not ${wants}; the consumer did not follow the line`);
38
+ }
33
39
  const events = await streams.describeStream(streams_1.LINE_STREAM.EVENTS);
34
40
  const missing = events ? (0, streams_1.uncoveredSubjects)(events, consumer.filterSubjects) : consumer.filterSubjects;
35
41
  if (missing.length) {
@@ -38,8 +44,8 @@ class StreamMachineBus {
38
44
  this.session = await mqtt_session_1.MqttSession.open(this.opts.mqtt, controllerId);
39
45
  }
40
46
  async consume(handler) {
41
- const { streams, pubsub, codec, siteId, lineId, nakDelayMs = 1_000 } = this.opts;
42
- this.subs.push(await streams.consume(streams_1.LINE_STREAM.EVENTS, this.durableName, (m) => this.queue.run(() => handler({ topic: (0, protocol_1.toTopic)(m.subject), payload: m.payload, deliveries: m.deliveries })), { nakDelayMs }));
47
+ const { streams, pubsub, codec, siteId, lineId, nakDelayMs = 1_000, onLost } = this.opts;
48
+ this.subs.push(await streams.consume(streams_1.LINE_STREAM.EVENTS, this.durableName, (m) => this.queue.run(() => handler({ topic: (0, protocol_1.toTopic)(m.subject), payload: m.payload, deliveries: m.deliveries })), { nakDelayMs, onLost }));
43
49
  for (const subject of (0, streams_1.telemetrySubjects)(codec, siteId, lineId)) {
44
50
  this.subs.push(pubsub.subscribe(subject, (m) => void this.queue.run(() => handler({ topic: (0, protocol_1.toTopic)(m.subject), payload: m.payload, deliveries: 1 }))));
45
51
  }
@@ -16,7 +16,8 @@ export declare function filterToSubject(filter: string): string;
16
16
  /**
17
17
  * The site's streams: every line under each codec's root, since lines on
18
18
  * different protocols share one site NATS. A root alone means the generic
19
- * layout; several codecs give the union of their subjects, in order.
19
+ * layout; several codecs give the union of their subjects, sorted, so every
20
+ * line asks the site for the same stream whichever codec it lists first.
20
21
  */
21
22
  export declare function lineStreamSpecs(codecs: StreamCodec | string | (StreamCodec | string)[]): StreamSpec[];
22
23
  /** Whether a stream subject pattern keeps everything a consumer filter would read. */
@@ -31,11 +31,12 @@ function subjectsFor(codec, channels, siteId, lineId) {
31
31
  /**
32
32
  * The site's streams: every line under each codec's root, since lines on
33
33
  * different protocols share one site NATS. A root alone means the generic
34
- * layout; several codecs give the union of their subjects, in order.
34
+ * layout; several codecs give the union of their subjects, sorted, so every
35
+ * line asks the site for the same stream whichever codec it lists first.
35
36
  */
36
37
  function lineStreamSpecs(codecs) {
37
38
  const list = (Array.isArray(codecs) ? codecs : [codecs]).map(codecOf);
38
- const union = (channel) => [...new Set(list.flatMap((c) => subjectsFor(c, c.channels[channel])))];
39
+ const union = (channel) => [...new Set(list.flatMap((c) => subjectsFor(c, c.channels[channel])))].sort();
39
40
  return [
40
41
  { name: exports.LINE_STREAM.EVENTS, subjects: union('events'), maxAgeMs: 30 * DAY_MS },
41
42
  { name: exports.LINE_STREAM.TELEMETRY, subjects: union('telemetry'), maxAgeMs: 3 * DAY_MS },
@@ -39,16 +39,20 @@ class MemoryStreams {
39
39
  async describeStream(name) {
40
40
  return this.streams.get(name)?.spec ?? null;
41
41
  }
42
+ /** An existing consumer keeps its place while its subjects match; one whose subjects changed starts again. */
42
43
  async ensureConsumer(stream, spec) {
43
44
  const s = this.stream(stream);
44
45
  const existing = s.consumers.get(spec.name);
45
- if (existing) {
46
- existing.spec = { ...existing.spec, filterSubjects: spec.filterSubjects };
46
+ const same = (a, b) => [...a].sort().join('|') === [...b].sort().join('|');
47
+ if (existing && same(existing.spec.filterSubjects, spec.filterSubjects))
47
48
  return;
48
- }
49
49
  const floor = (spec.startAt ?? constants_1.START_AT.NEW) === constants_1.START_AT.ALL ? 0 : s.seq;
50
50
  s.consumers.set(spec.name, { spec, floor, settled: new Set(), deliveries: new Map(), retryAt: new Map() });
51
51
  }
52
+ async describeConsumer(stream, name) {
53
+ const spec = this.streams.get(stream)?.consumers.get(name)?.spec;
54
+ return spec ? { ...spec, filterSubjects: [...spec.filterSubjects] } : null;
55
+ }
52
56
  async append(subject, payload) {
53
57
  const now = Date.now();
54
58
  for (const s of this.streams.values()) {
@@ -15,6 +15,7 @@ function jsPermissions({ streams, durable }) {
15
15
  `$JS.API.CONSUMER.CREATE.${s}.${durable}`,
16
16
  `$JS.API.CONSUMER.CREATE.${s}.${durable}.>`,
17
17
  `$JS.API.CONSUMER.DURABLE.CREATE.${s}.${durable}`,
18
+ `$JS.API.CONSUMER.DELETE.${s}.${durable}`,
18
19
  `$JS.API.CONSUMER.MSG.NEXT.${s}.${durable}`,
19
20
  `$JS.ACK.${s}.${durable}.>`,
20
21
  ]);
@@ -1,18 +1,31 @@
1
1
  /**
2
2
  * Durable streams on JetStream. A spec becomes a file-backed stream or an
3
- * explicit-ack durable consumer; ensuring either is safe on every boot, and an
4
- * existing consumer keeps its position while its subjects follow the spec.
3
+ * explicit-ack durable consumer; ensuring either is safe on every boot and
4
+ * from several lines at once. An existing consumer keeps its position while
5
+ * its subjects match the spec; one whose subjects changed is made again, since
6
+ * a position in another protocol's messages means nothing to this one.
5
7
  */
6
8
  import { type ConsumerConfig, type JetStreamClient, type JetStreamManager, type StreamConfig } from 'nats';
7
9
  import type { ConsumerSpec, Delivery, LTConsumeOptions, LTStreamMessage, LTStreams, LTSubscription, StreamSpec, Subject } from '../../../types/messaging';
8
10
  export declare function streamConfig(spec: StreamSpec): Partial<StreamConfig>;
9
11
  export declare function consumerConfig(spec: ConsumerSpec): Partial<ConsumerConfig>;
10
- /** Create the stream, or update an existing one to the spec. */
12
+ /**
13
+ * Create the stream, or update an existing one to the spec. Two lines may
14
+ * ensure the same stream at once: the create that loses the race finds the
15
+ * stream in use and updates it instead.
16
+ */
11
17
  export declare function ensureStream(jsm: JetStreamManager, spec: StreamSpec): Promise<void>;
12
18
  /** The stream as JetStream holds it, or null when there is none. */
13
19
  export declare function describeStream(jsm: JetStreamManager, name: string): Promise<StreamSpec | null>;
14
- /** Create the consumer, or move an existing one to the spec's subjects without losing its place. */
20
+ /**
21
+ * Create the consumer, or keep an existing one whose subjects match the spec,
22
+ * position and all. One whose subjects differ is deleted and made again at
23
+ * the stream's newest message, since its old position was in another
24
+ * protocol's messages.
25
+ */
15
26
  export declare function ensureConsumer(jsm: JetStreamManager, stream: string, spec: ConsumerSpec): Promise<void>;
27
+ /** The consumer as JetStream holds it, or null when there is none. */
28
+ export declare function describeConsumer(jsm: JetStreamManager, stream: string, name: string): Promise<ConsumerSpec | null>;
16
29
  export declare function payloadOf(m: {
17
30
  data: Uint8Array;
18
31
  }): string;
@@ -23,6 +36,7 @@ export declare class NatsStreams implements LTStreams {
23
36
  ensureStream(spec: StreamSpec): Promise<void>;
24
37
  ensureConsumer(stream: string, spec: ConsumerSpec): Promise<void>;
25
38
  describeStream(name: string): Promise<StreamSpec | null>;
39
+ describeConsumer(stream: string, name: string): Promise<ConsumerSpec | null>;
26
40
  append(subject: Subject, payload: string): Promise<void>;
27
41
  /** One message at a time: the next is not taken until the handler settles this one. */
28
42
  consume(stream: string, consumer: string, handler: (m: LTStreamMessage) => Promise<Delivery>, opts?: LTConsumeOptions): Promise<LTSubscription>;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Durable streams on JetStream. A spec becomes a file-backed stream or an
4
- * explicit-ack durable consumer; ensuring either is safe on every boot, and an
5
- * existing consumer keeps its position while its subjects follow the spec.
4
+ * explicit-ack durable consumer; ensuring either is safe on every boot and
5
+ * from several lines at once. An existing consumer keeps its position while
6
+ * its subjects match the spec; one whose subjects changed is made again, since
7
+ * a position in another protocol's messages means nothing to this one.
6
8
  */
7
9
  Object.defineProperty(exports, "__esModule", { value: true });
8
10
  exports.NatsStreams = void 0;
@@ -11,11 +13,15 @@ exports.consumerConfig = consumerConfig;
11
13
  exports.ensureStream = ensureStream;
12
14
  exports.describeStream = describeStream;
13
15
  exports.ensureConsumer = ensureConsumer;
16
+ exports.describeConsumer = describeConsumer;
14
17
  exports.payloadOf = payloadOf;
15
18
  const nats_1 = require("nats");
16
19
  const constants_1 = require("../constants");
17
20
  const DEFAULT_ACK_WAIT_MS = 30_000;
18
21
  const DEFAULT_NAK_DELAY_MS = 1_000;
22
+ /** Consumer events after which the consumer delivers nothing more: its stream or itself is gone, or the server fell silent. */
23
+ const CONSUMER_LOST = new Set(['consumer_deleted', 'consumer_not_found', 'stream_not_found', 'heartbeats_missed']);
24
+ const sameSubjects = (a = [], b = []) => [...a].sort().join('|') === [...b].sort().join('|');
19
25
  function streamConfig(spec) {
20
26
  return { name: spec.name, subjects: spec.subjects, max_age: (0, nats_1.nanos)(spec.maxAgeMs), storage: nats_1.StorageType.File };
21
27
  }
@@ -28,7 +34,11 @@ function consumerConfig(spec) {
28
34
  filter_subjects: spec.filterSubjects,
29
35
  };
30
36
  }
31
- /** Create the stream, or update an existing one to the spec. */
37
+ /**
38
+ * Create the stream, or update an existing one to the spec. Two lines may
39
+ * ensure the same stream at once: the create that loses the race finds the
40
+ * stream in use and updates it instead.
41
+ */
32
42
  async function ensureStream(jsm, spec) {
33
43
  const config = streamConfig(spec);
34
44
  try {
@@ -37,8 +47,14 @@ async function ensureStream(jsm, spec) {
37
47
  catch (err) {
38
48
  if (!/stream not found/i.test(err?.message ?? ''))
39
49
  throw err;
40
- await jsm.streams.add(config);
41
- return;
50
+ try {
51
+ await jsm.streams.add(config);
52
+ return;
53
+ }
54
+ catch (added) {
55
+ if (!/already in use/i.test(added?.message ?? ''))
56
+ throw added;
57
+ }
42
58
  }
43
59
  await jsm.streams.update(spec.name, config);
44
60
  }
@@ -54,7 +70,12 @@ async function describeStream(jsm, name) {
54
70
  throw err;
55
71
  }
56
72
  }
57
- /** Create the consumer, or move an existing one to the spec's subjects without losing its place. */
73
+ /**
74
+ * Create the consumer, or keep an existing one whose subjects match the spec,
75
+ * position and all. One whose subjects differ is deleted and made again at
76
+ * the stream's newest message, since its old position was in another
77
+ * protocol's messages.
78
+ */
58
79
  async function ensureConsumer(jsm, stream, spec) {
59
80
  let existing;
60
81
  try {
@@ -66,10 +87,22 @@ async function ensureConsumer(jsm, stream, spec) {
66
87
  await jsm.consumers.add(stream, consumerConfig(spec));
67
88
  return;
68
89
  }
69
- const want = [...spec.filterSubjects].sort();
70
- const have = [...(existing.config.filter_subjects ?? [])].sort();
71
- if (want.join('|') !== have.join('|'))
72
- await jsm.consumers.update(stream, spec.name, { filter_subjects: spec.filterSubjects });
90
+ if (sameSubjects(spec.filterSubjects, existing.config.filter_subjects))
91
+ return;
92
+ await jsm.consumers.delete(stream, spec.name);
93
+ await jsm.consumers.add(stream, consumerConfig(spec));
94
+ }
95
+ /** The consumer as JetStream holds it, or null when there is none. */
96
+ async function describeConsumer(jsm, stream, name) {
97
+ try {
98
+ const info = await jsm.consumers.info(stream, name);
99
+ return { name, filterSubjects: info.config.filter_subjects ?? (info.config.filter_subject ? [info.config.filter_subject] : []) };
100
+ }
101
+ catch (err) {
102
+ if (/consumer not found|stream not found/i.test(err?.message ?? ''))
103
+ return null;
104
+ throw err;
105
+ }
73
106
  }
74
107
  function payloadOf(m) {
75
108
  return Buffer.from(m.data).toString('utf8');
@@ -88,6 +121,9 @@ class NatsStreams {
88
121
  describeStream(name) {
89
122
  return describeStream(this.jsm, name);
90
123
  }
124
+ describeConsumer(stream, name) {
125
+ return describeConsumer(this.jsm, stream, name);
126
+ }
91
127
  async append(subject, payload) {
92
128
  await this.js.publish(subject, payload);
93
129
  }
@@ -95,6 +131,15 @@ class NatsStreams {
95
131
  async consume(stream, consumer, handler, opts = {}) {
96
132
  const nakDelayMs = opts.nakDelayMs ?? DEFAULT_NAK_DELAY_MS;
97
133
  const messages = await (await this.js.consumers.get(stream, consumer)).consume();
134
+ // The consumer's own status: once its stream or itself is gone, or the server fell silent, the reader is told.
135
+ void (async () => {
136
+ for await (const status of await messages.status()) {
137
+ if (!CONSUMER_LOST.has(String(status.type)))
138
+ continue;
139
+ opts.onLost?.(String(status.type));
140
+ return;
141
+ }
142
+ })().catch(() => { });
98
143
  void (async () => {
99
144
  for await (const m of messages) {
100
145
  const delivery = await handler({ subject: m.subject, payload: payloadOf(m), deliveries: m.info.deliveryCount })
@@ -164,20 +164,32 @@ class Dispatcher {
164
164
  row.dispatch = state_1.DISPATCH_STATE.ACCEPTED;
165
165
  for (const job of jobs)
166
166
  state.rememberSent(a.machineId, job.jobId, a.rowId);
167
+ // The machine may say a job is ready before the claim below returns: the set it is taken out of is there first, and a ready that came earlier still is already out of it.
168
+ const preparing = a.receivedOnAccept ? jobs.filter((job, i) => replies[i]?.status === protocol_1.REPLY_STATUS.ACCEPTED && replies[i]?.preparing).map((job) => `${a.cmdId}${job.suffix}`) : [];
169
+ if (row && preparing.length) {
170
+ row.awaitingReady = new Set(preparing.filter((cmdId) => !row.readyEarly?.has(cmdId)));
171
+ row.readyEarly = undefined;
172
+ }
167
173
  if (reconciled)
168
174
  log.info(log_1.GATEWAY_LOG.DISPATCH_RECONCILED, { row: a.rowId, machine: a.machineId, jobs: silent.map((j) => j.jobId) });
169
175
  log.info(log_1.GATEWAY_LOG.DISPATCHED, { row: a.rowId, machine: a.machineId, reason: replies.map((r) => r?.reason ?? 'held').join('; ') });
170
- this.check(a.rowId, 'claim', await lt.claim(a.machineId, a.rowId));
176
+ const claiming = lt.claim(a.machineId, a.rowId);
177
+ if (row)
178
+ row.claiming = claiming;
179
+ this.check(a.rowId, 'claim', await claiming);
180
+ if (row)
181
+ row.claiming = undefined;
171
182
  if (!a.receivedOnAccept)
172
183
  return;
173
- const preparing = jobs.filter((job, i) => replies[i]?.status === protocol_1.REPLY_STATUS.ACCEPTED && replies[i]?.preparing).map((job) => `${a.cmdId}${job.suffix}`);
174
- if (!preparing.length) {
184
+ // A ready that came while the claim was out has received the row already.
185
+ const live = state.get(a.rowId);
186
+ if (!live || live.ended)
187
+ return;
188
+ if (!preparing.length || !live.awaitingReady?.size) {
175
189
  await this.received(a);
176
190
  return;
177
191
  }
178
- if (row)
179
- row.awaitingReady = new Set(preparing);
180
- log.info(log_1.GATEWAY_LOG.DISPATCH_PREPARING, { row: a.rowId, machine: a.machineId, jobs: preparing });
192
+ log.info(log_1.GATEWAY_LOG.DISPATCH_PREPARING, { row: a.rowId, machine: a.machineId, jobs: [...live.awaitingReady] });
181
193
  return;
182
194
  }
183
195
  // The handoff may have ended meanwhile: a machine that ran the job anyway reports the arrival.
@@ -57,7 +57,12 @@ export declare class Executor {
57
57
  * carrying the units out of it.
58
58
  */
59
59
  private lateReply;
60
- /** On arrival dispatch, a row that waited for the machine to prepare is received once every job it sent is ready. */
60
+ /**
61
+ * On arrival dispatch, a row that waited for the machine to prepare is
62
+ * received once every job it sent is ready. A ready that comes before the
63
+ * dispatch has recorded what it waits for is kept for it; one that comes
64
+ * while the dispatch's claim is still out waits for that claim.
65
+ */
61
66
  private readyForArrival;
62
67
  /** Add the item; when the row then holds every key the action waits for, resolve it. */
63
68
  private accumulate;
@@ -155,14 +155,31 @@ class Executor {
155
155
  received: false, errorCode: contracts_1.HANDOFF_ERROR.DISPATCH_FAILED, detail: `${m} could not prepare the job: ${a.reason}`, ...(a.code ? { code: a.code } : {}),
156
156
  }));
157
157
  }
158
- /** On arrival dispatch, a row that waited for the machine to prepare is received once every job it sent is ready. */
158
+ /**
159
+ * On arrival dispatch, a row that waited for the machine to prepare is
160
+ * received once every job it sent is ready. A ready that comes before the
161
+ * dispatch has recorded what it waits for is kept for it; one that comes
162
+ * while the dispatch's claim is still out waits for that claim.
163
+ */
159
164
  async readyForArrival(into, m, cmdId) {
160
165
  const { lt, state } = this.d;
161
- if (into.ended || !into.awaitingReady?.has(cmdId))
166
+ if (into.ended)
167
+ return [];
168
+ if (!into.awaitingReady) {
169
+ if (into.dispatch !== state_1.DISPATCH_STATE.ACCEPTED && into.dispatch !== state_1.DISPATCH_STATE.PENDING)
170
+ return [];
171
+ (into.readyEarly ??= new Set()).add(cmdId);
172
+ return [{ verb: 'none', detail: `ready before its dispatch settled; kept` }];
173
+ }
174
+ if (!into.awaitingReady.has(cmdId))
162
175
  return [];
163
176
  into.awaitingReady.delete(cmdId);
164
177
  if (into.awaitingReady.size)
165
178
  return [];
179
+ if (into.claiming)
180
+ await into.claiming;
181
+ if (into.ended)
182
+ return [];
166
183
  const units = into.units.map((u) => u.unitId);
167
184
  const resolved = await lt.resolve(m, into.id, { received: true, receiver: m, units });
168
185
  state.close(into.id);
@@ -32,6 +32,7 @@ export declare const GATEWAY_LOG: {
32
32
  readonly LEADING: "machine_gateway.line.leading";
33
33
  readonly STANDBY: "machine_gateway.line.standby";
34
34
  readonly LEADERSHIP_LOST: "machine_gateway.line.leadership_lost";
35
+ readonly WIRE_LOST: "machine_gateway.line.wire_lost";
35
36
  readonly START_FAILED: "machine_gateway.line.start_failed";
36
37
  };
37
38
  export type GatewayLogEvent = typeof GATEWAY_LOG[keyof typeof GATEWAY_LOG];
@@ -37,6 +37,7 @@ exports.GATEWAY_LOG = {
37
37
  LEADING: 'machine_gateway.line.leading',
38
38
  STANDBY: 'machine_gateway.line.standby',
39
39
  LEADERSHIP_LOST: 'machine_gateway.line.leadership_lost',
40
+ WIRE_LOST: 'machine_gateway.line.wire_lost',
40
41
  START_FAILED: 'machine_gateway.line.start_failed',
41
42
  };
42
43
  exports.consoleLog = {
@@ -131,6 +131,23 @@ function heldUnder(state, machineId, unitId, senderJobId) {
131
131
  const held = state.heldJob(machineId, unitId);
132
132
  return !!held && (!senderJobId || (0, jobs_1.jobOwns)(senderJobId, held));
133
133
  }
134
+ /**
135
+ * Units a new row sends to a machine that already holds them from an earlier
136
+ * attempt (a job that failed to prepare, then a retry) need no second scan:
137
+ * the row is dispatched now, with the arrivals the gateway kept for them.
138
+ */
139
+ function arrivedAlready(state, row, dispatchTtlMs) {
140
+ const m = row.toMachine;
141
+ if (!m || !row.units.length || !row.units.every((u) => state.heldJob(m, u.unitId)))
142
+ return [];
143
+ const arrivals = row.units.map((u) => {
144
+ const before = state.closedFor(u.unitId, (r) => r.toMachine === m && !!r.arrivals?.[u.unitId]);
145
+ return [u.unitId, before?.arrivals?.[u.unitId] ?? { unitId: u.unitId, carrierId: u.carrierId ?? null }];
146
+ });
147
+ row.arrivals = Object.fromEntries(arrivals);
148
+ row.dueAt = Date.now();
149
+ return [(0, pacing_1.dispatchAction)(row, m, dispatchTtlMs)];
150
+ }
134
151
  function planHandoff(state, line, event, facets, dispatchTtlMs) {
135
152
  const id = event.escalationId;
136
153
  if (event.verb === VERB.CREATED || event.verb === VERB.CLAIMED) {
@@ -152,9 +169,10 @@ function planHandoff(state, line, event, facets, dispatchTtlMs) {
152
169
  }
153
170
  if (state.dispatchOnArrival) {
154
171
  const refused = (0, pacing_1.refuseUnfit)(state, line, row);
155
- if (!refused.length)
156
- row.dispatch = state_1.DISPATCH_STATE.ARRIVING;
157
- return refused;
172
+ if (refused.length)
173
+ return refused;
174
+ row.dispatch = state_1.DISPATCH_STATE.ARRIVING;
175
+ return arrivedAlready(state, row, dispatchTtlMs);
158
176
  }
159
177
  const refused = !!(0, pacing_1.softwareRefusal)(state, line, row.toMachine) || !!(0, pacing_1.jobRefusal)(state, row);
160
178
  if (state.holdDispatch || (!refused && (!(0, pacing_1.hasRoom)(state, line, row) || !(0, registration_1.reachable)(state, line, row.toMachine)))) {
@@ -37,6 +37,10 @@ export interface HandoffRow extends HandoffFacets {
37
37
  arrivals?: Record<string, Record<string, any>>;
38
38
  /** Dispatch commands accepted as preparing; on arrival dispatch the row is received once each is ready. */
39
39
  awaitingReady?: Set<string>;
40
+ /** Jobs the machine said were ready before the dispatch recorded what it waits for. */
41
+ readyEarly?: Set<string>;
42
+ /** The claim the dispatch has out; a ready that completes the row waits for it. */
43
+ claiming?: Promise<unknown>;
40
44
  /** Lifecycle item keys already on the row (lifecycle.ts). */
41
45
  noted?: string[];
42
46
  /** Parked with a limit on its items, which lifecycle notes must never use up. */
@@ -80,7 +80,7 @@ class GatewayState {
80
80
  this.openRows.set(row.id, existing
81
81
  ? {
82
82
  ...row, dispatch: existing.dispatch, trace: (0, trace_1.mergeTrace)(row.trace, existing.trace), arrivals: existing.arrivals,
83
- dueAt: existing.dueAt, noted: existing.noted ?? row.noted, awaitingReady: existing.awaitingReady,
83
+ dueAt: existing.dueAt, noted: existing.noted ?? row.noted, awaitingReady: existing.awaitingReady, readyEarly: existing.readyEarly, claiming: existing.claiming,
84
84
  }
85
85
  : row);
86
86
  }
@@ -30,6 +30,8 @@ export declare class LineLeadership {
30
30
  private leadOnce;
31
31
  /** Lead while the lock is held; the error that ended it. */
32
32
  private holdLock;
33
+ /** The leader gives its turn up without stopping: `lost` runs, the lock goes, and the line contends again after the pause. */
34
+ relinquish(reason: string): void;
33
35
  /** A leader unlocks; a replica still waiting drops its connection, which ends the wait. */
34
36
  stop(): Promise<void>;
35
37
  }
@@ -62,7 +62,7 @@ class LineLeadership {
62
62
  async holdLock(client, lead) {
63
63
  const ended = new Promise((resolve) => {
64
64
  client.once('error', resolve);
65
- this.endTurn = () => resolve(new Error('leadership stopped'));
65
+ this.endTurn = (err) => resolve(err ?? new Error('leadership stopped'));
66
66
  });
67
67
  try {
68
68
  await client.query(LOCK_SQL, [this.key]);
@@ -76,6 +76,12 @@ class LineLeadership {
76
76
  return err;
77
77
  }
78
78
  }
79
+ /** The leader gives its turn up without stopping: `lost` runs, the lock goes, and the line contends again after the pause. */
80
+ relinquish(reason) {
81
+ if (!this.leading)
82
+ return;
83
+ this.endTurn?.(new Error(reason));
84
+ }
79
85
  /** A leader unlocks; a replica still waiting drops its connection, which ends the wait. */
80
86
  async stop() {
81
87
  this.stopped = true;
@@ -19,7 +19,7 @@ export type LineMessaging = Pick<typeof messagingRegistry, 'streams' | 'pubsub'>
19
19
  * server of the site's own, which the bus connects to itself. `siteCodecs` are
20
20
  * the codecs of every line on the site, so the streams keep all their subjects.
21
21
  */
22
- export declare function createMachineBus(config: MachineLineConfig, line: LineDef, codec?: LineCodec, messaging?: LineMessaging, siteCodecs?: LineCodec[]): MachineBus;
22
+ export declare function createMachineBus(config: MachineLineConfig, line: LineDef, codec?: LineCodec, messaging?: LineMessaging, siteCodecs?: LineCodec[], onLost?: (reason: string) => void): MachineBus;
23
23
  /** Long Tail's escalation events for the gateway; `in-process` needs the running instance's callback adapter. */
24
24
  export declare function createEscalationFeed(config: MachineLineConfig, line: LineDef, callbacks?: CallbackEventAdapter): EscalationFeed;
25
25
  /** One MQTT link per simulated machine; machines speak MQTT in every networked mode. */
@@ -36,10 +36,10 @@ function defaultCodec(config, line) {
36
36
  * server of the site's own, which the bus connects to itself. `siteCodecs` are
37
37
  * the codecs of every line on the site, so the streams keep all their subjects.
38
38
  */
39
- function createMachineBus(config, line, codec = defaultCodec(config, line), messaging = messaging_1.messagingRegistry, siteCodecs = []) {
39
+ function createMachineBus(config, line, codec = defaultCodec(config, line), messaging = messaging_1.messagingRegistry, siteCodecs = [], onLost) {
40
40
  switch (config.transport) {
41
41
  case config_1.MACHINE_TRANSPORT.NATS: {
42
- const where = { mqtt: mqttOf(config), controllerId: (0, line_1.controllerId)(line), siteId: line.siteId, lineId: line.lineId, codec, siteCodecs };
42
+ const where = { mqtt: mqttOf(config), controllerId: (0, line_1.controllerId)(line), siteId: line.siteId, lineId: line.lineId, codec, siteCodecs, onLost };
43
43
  if (config.siteNatsUrl) {
44
44
  return new nats_bus_1.NatsMachineBus({ natsUrl: config.siteNatsUrl, user: config.siteNatsUser, password: config.siteNatsPassword, ...where });
45
45
  }
@@ -103,8 +103,14 @@ class LineRun {
103
103
  return id;
104
104
  };
105
105
  const { config, line, codec } = this;
106
+ const where = { site: line.siteId, line: line.lineId };
107
+ // A wire that stops delivering ends this turn: the gateway stops, the line contends again and ensures its streams anew.
108
+ const onLost = (reason) => {
109
+ this.log.warn(log_1.GATEWAY_LOG.WIRE_LOST, { ...where, reason });
110
+ this.leadership.relinquish(`wire lost: ${reason}`);
111
+ };
106
112
  this.gateway = new gateway_1.MachineGateway({
107
- bus: (0, select_1.createMachineBus)(config, line, codec, undefined, this.siteCodecs()),
113
+ bus: (0, select_1.createMachineBus)(config, line, codec, undefined, this.siteCodecs(), onLost),
108
114
  codec,
109
115
  rows: this.opts.rows,
110
116
  feed: (0, select_1.createEscalationFeed)(config, line, this.opts.callbacks),
@@ -121,7 +127,7 @@ class LineRun {
121
127
  });
122
128
  await this.gateway.start();
123
129
  this.ready = true;
124
- this.log.info(log_1.GATEWAY_LOG.LEADING, { site: line.siteId, line: line.lineId });
130
+ this.log.info(log_1.GATEWAY_LOG.LEADING, where);
125
131
  }
126
132
  }
127
133
  class MachineSurface {
@@ -47,15 +47,19 @@ export interface LTStreamMessage extends LTMessage {
47
47
  export interface LTConsumeOptions {
48
48
  /** Delay before a nak'd message is delivered again. */
49
49
  nakDelayMs?: number;
50
+ /** Told once when the consumer can deliver nothing more: its stream or itself is gone, or the server fell silent. */
51
+ onLost?: (reason: string) => void;
50
52
  }
51
53
  /** Durable streams: messages kept, delivered to named consumers in order, one at a time, until settled. */
52
54
  export interface LTStreams {
53
55
  /** Create the stream, or bring an existing one's subjects and age up to the spec. */
54
56
  ensureStream(spec: StreamSpec): Promise<void>;
55
- /** Create the consumer, or bring an existing one's filter up to the spec; its position is kept. */
57
+ /** Create the consumer, or keep an existing one whose subjects match the spec; one whose subjects changed is made again. */
56
58
  ensureConsumer(stream: string, spec: ConsumerSpec): Promise<void>;
57
59
  /** The stream as it is now, or null when there is none. */
58
60
  describeStream(name: string): Promise<StreamSpec | null>;
61
+ /** The consumer as it is now, or null when there is none. */
62
+ describeConsumer(stream: string, name: string): Promise<ConsumerSpec | null>;
59
63
  /** Append a message; resolves once the stream holds it. */
60
64
  append(subject: Subject, payload: string): Promise<void>;
61
65
  /** Deliver the consumer's messages to `handler` one at a time; a thrown handler counts as a nak. */
@@ -1,2 +1,2 @@
1
- import{j as o}from"./vendor-query-DvWWuNIB.js";import{c as n}from"./tasks-Dab4hExW.js";import{z as m,a9 as c}from"./index-CkMHS-hG.js";import{u}from"./mcp-CmcUXYce.js";import{P as d}from"./PageHeaderWithStats-BEQYYBJv.js";import"./vendor-react-_9U4mKFr.js";import"./vendor-icons-fxBvvHBi.js";function S(){var e;m();const{data:t}=n({limit:1}),{data:a}=c({status:"pending",limit:1}),{data:s}=u(),l=((e=s==null?void 0:s.servers)==null?void 0:e.filter(i=>i.status==="connected").length)??0,r=s?`${l}/${s.total}`:"—";return o.jsx("div",{children:o.jsx(d,{title:"Admin",stats:[{label:"Tasks",value:(t==null?void 0:t.total)??"—"},{label:"Pending Escalations",value:(a==null?void 0:a.total)??"—",dotClass:"bg-status-pending"},{label:"MCP Servers",value:r},{label:"System",value:"Healthy",dotClass:"bg-status-success"}]})})}export{S as AdminDashboard};
2
- //# sourceMappingURL=AdminDashboard-Bm7VG65H.js.map
1
+ import{j as o}from"./vendor-query-DvWWuNIB.js";import{c as n}from"./tasks-ClJ-mbj9.js";import{z as m,a9 as c}from"./index-pzbGpihI.js";import{u}from"./mcp-_0kFRcyT.js";import{P as d}from"./PageHeaderWithStats-BEQYYBJv.js";import"./vendor-react-_9U4mKFr.js";import"./vendor-icons-fxBvvHBi.js";function S(){var e;m();const{data:t}=n({limit:1}),{data:a}=c({status:"pending",limit:1}),{data:s}=u(),l=((e=s==null?void 0:s.servers)==null?void 0:e.filter(i=>i.status==="connected").length)??0,r=s?`${l}/${s.total}`:"—";return o.jsx("div",{children:o.jsx(d,{title:"Admin",stats:[{label:"Tasks",value:(t==null?void 0:t.total)??"—"},{label:"Pending Escalations",value:(a==null?void 0:a.total)??"—",dotClass:"bg-status-pending"},{label:"MCP Servers",value:r},{label:"System",value:"Healthy",dotClass:"bg-status-success"}]})})}export{S as AdminDashboard};
2
+ //# sourceMappingURL=AdminDashboard-DRE0hSDS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminDashboard-Bm7VG65H.js","sources":["../../src/pages/admin/AdminDashboard.tsx"],"sourcesContent":["import { useTasks } from '../../api/tasks';\nimport { useEscalations } from '../../api/escalations';\nimport { useEscalationListEvents } from '../../hooks/useEventHooks';\nimport { useMcpServers } from '../../api/mcp';\nimport { PageHeaderWithStats } from '../../components/common/layout/PageHeaderWithStats';\n\nexport function AdminDashboard() {\n useEscalationListEvents();\n const { data: taskData } = useTasks({ limit: 1 });\n const { data: pendingEsc } = useEscalations({ status: 'pending', limit: 1 });\n const { data: mcpData } = useMcpServers();\n\n const connectedServers =\n mcpData?.servers?.filter((s) => s.status === 'connected').length ?? 0;\n const mcpLabel = mcpData ? `${connectedServers}/${mcpData.total}` : '—';\n\n return (\n <div>\n <PageHeaderWithStats\n title=\"Admin\"\n stats={[\n { label: 'Tasks', value: taskData?.total ?? '—' },\n { label: 'Pending Escalations', value: pendingEsc?.total ?? '—', dotClass: 'bg-status-pending' },\n { label: 'MCP Servers', value: mcpLabel },\n { label: 'System', value: 'Healthy', dotClass: 'bg-status-success' },\n ]}\n />\n </div>\n );\n}\n"],"names":["AdminDashboard","useEscalationListEvents","taskData","useTasks","pendingEsc","useEscalations","mcpData","useMcpServers","connectedServers","_a","s","mcpLabel","jsx","PageHeaderWithStats"],"mappings":"oSAMO,SAASA,GAAiB,OAC/BC,EAAA,EACA,KAAM,CAAE,KAAMC,CAAA,EAAaC,EAAS,CAAE,MAAO,EAAG,EAC1C,CAAE,KAAMC,CAAA,EAAeC,EAAe,CAAE,OAAQ,UAAW,MAAO,EAAG,EACrE,CAAE,KAAMC,CAAA,EAAYC,EAAA,EAEpBC,IACJC,EAAAH,GAAA,YAAAA,EAAS,UAAT,YAAAG,EAAkB,OAAQC,GAAMA,EAAE,SAAW,aAAa,SAAU,EAChEC,EAAWL,EAAU,GAAGE,CAAgB,IAAIF,EAAQ,KAAK,GAAK,IAEpE,aACG,MAAA,CACC,SAAAM,EAAAA,IAACC,EAAA,CACC,MAAM,QACN,MAAO,CACL,CAAE,MAAO,QAAS,OAAOX,GAAA,YAAAA,EAAU,QAAS,GAAA,EAC5C,CAAE,MAAO,sBAAuB,OAAOE,GAAA,YAAAA,EAAY,QAAS,IAAK,SAAU,mBAAA,EAC3E,CAAE,MAAO,cAAe,MAAOO,CAAA,EAC/B,CAAE,MAAO,SAAU,MAAO,UAAW,SAAU,mBAAA,CAAoB,CACrE,CAAA,EAEJ,CAEJ"}
1
+ {"version":3,"file":"AdminDashboard-DRE0hSDS.js","sources":["../../src/pages/admin/AdminDashboard.tsx"],"sourcesContent":["import { useTasks } from '../../api/tasks';\nimport { useEscalations } from '../../api/escalations';\nimport { useEscalationListEvents } from '../../hooks/useEventHooks';\nimport { useMcpServers } from '../../api/mcp';\nimport { PageHeaderWithStats } from '../../components/common/layout/PageHeaderWithStats';\n\nexport function AdminDashboard() {\n useEscalationListEvents();\n const { data: taskData } = useTasks({ limit: 1 });\n const { data: pendingEsc } = useEscalations({ status: 'pending', limit: 1 });\n const { data: mcpData } = useMcpServers();\n\n const connectedServers =\n mcpData?.servers?.filter((s) => s.status === 'connected').length ?? 0;\n const mcpLabel = mcpData ? `${connectedServers}/${mcpData.total}` : '—';\n\n return (\n <div>\n <PageHeaderWithStats\n title=\"Admin\"\n stats={[\n { label: 'Tasks', value: taskData?.total ?? '—' },\n { label: 'Pending Escalations', value: pendingEsc?.total ?? '—', dotClass: 'bg-status-pending' },\n { label: 'MCP Servers', value: mcpLabel },\n { label: 'System', value: 'Healthy', dotClass: 'bg-status-success' },\n ]}\n />\n </div>\n );\n}\n"],"names":["AdminDashboard","useEscalationListEvents","taskData","useTasks","pendingEsc","useEscalations","mcpData","useMcpServers","connectedServers","_a","s","mcpLabel","jsx","PageHeaderWithStats"],"mappings":"oSAMO,SAASA,GAAiB,OAC/BC,EAAA,EACA,KAAM,CAAE,KAAMC,CAAA,EAAaC,EAAS,CAAE,MAAO,EAAG,EAC1C,CAAE,KAAMC,CAAA,EAAeC,EAAe,CAAE,OAAQ,UAAW,MAAO,EAAG,EACrE,CAAE,KAAMC,CAAA,EAAYC,EAAA,EAEpBC,IACJC,EAAAH,GAAA,YAAAA,EAAS,UAAT,YAAAG,EAAkB,OAAQC,GAAMA,EAAE,SAAW,aAAa,SAAU,EAChEC,EAAWL,EAAU,GAAGE,CAAgB,IAAIF,EAAQ,KAAK,GAAK,IAEpE,aACG,MAAA,CACC,SAAAM,EAAAA,IAACC,EAAA,CACC,MAAM,QACN,MAAO,CACL,CAAE,MAAO,QAAS,OAAOX,GAAA,YAAAA,EAAU,QAAS,GAAA,EAC5C,CAAE,MAAO,sBAAuB,OAAOE,GAAA,YAAAA,EAAY,QAAS,IAAK,SAAU,mBAAA,EAC3E,CAAE,MAAO,cAAe,MAAOO,CAAA,EAC/B,CAAE,MAAO,SAAU,MAAO,UAAW,SAAU,mBAAA,CAAoB,CACrE,CAAA,EAEJ,CAEJ"}