@hotmeshio/long-tail 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/README.md +9 -2
  2. package/build/api/settings.d.ts +4 -1
  3. package/build/api/settings.js +7 -1
  4. package/build/index.d.ts +4 -0
  5. package/build/index.js +35 -8
  6. package/build/lib/db/config-lock.d.ts +10 -0
  7. package/build/lib/db/config-lock.js +28 -0
  8. package/build/lib/db/schemas/041_machine_lines.sql +26 -0
  9. package/build/lib/events/browser-view.js +8 -2
  10. package/build/lib/events/nats.d.ts +11 -0
  11. package/build/lib/events/nats.js +33 -2
  12. package/build/lib/events/publish.d.ts +33 -0
  13. package/build/lib/events/publish.js +52 -1
  14. package/build/lib/machines/index.d.ts +1 -0
  15. package/build/lib/machines/index.js +1 -0
  16. package/build/lib/machines/line.d.ts +4 -1
  17. package/build/lib/machines/line.js +18 -1
  18. package/build/lib/machines/protocol/codec.d.ts +24 -0
  19. package/build/lib/machines/protocol/codec.js +10 -0
  20. package/build/lib/machines/protocol/constants.d.ts +1 -1
  21. package/build/lib/machines/protocol/constants.js +1 -1
  22. package/build/lib/machines/protocol/contract.js +12 -3
  23. package/build/lib/machines/site/edge-account.d.ts +11 -0
  24. package/build/lib/machines/site/edge-account.js +24 -0
  25. package/build/lib/machines/site/mosquitto-conf.d.ts +5 -4
  26. package/build/lib/machines/site/mosquitto-conf.js +31 -16
  27. package/build/lib/machines/site/site-conf.d.ts +16 -6
  28. package/build/lib/machines/site/site-conf.js +39 -13
  29. package/build/lib/machines/transport/callback-feed.d.ts +1 -0
  30. package/build/lib/machines/transport/callback-feed.js +4 -1
  31. package/build/lib/machines/transport/delivery.d.ts +3 -4
  32. package/build/lib/machines/transport/delivery.js +3 -8
  33. package/build/lib/machines/transport/index.d.ts +2 -0
  34. package/build/lib/machines/transport/index.js +2 -0
  35. package/build/lib/machines/transport/memory.d.ts +2 -0
  36. package/build/lib/machines/transport/memory.js +6 -0
  37. package/build/lib/machines/transport/mqtt-bus.d.ts +2 -0
  38. package/build/lib/machines/transport/mqtt-bus.js +4 -0
  39. package/build/lib/machines/transport/nats-bus.d.ts +8 -13
  40. package/build/lib/machines/transport/nats-bus.js +26 -43
  41. package/build/lib/machines/transport/nats-feed.d.ts +1 -0
  42. package/build/lib/machines/transport/nats-feed.js +6 -3
  43. package/build/lib/machines/transport/pubsub-feed.d.ts +18 -0
  44. package/build/lib/machines/transport/pubsub-feed.js +42 -0
  45. package/build/lib/machines/transport/stream-bus.d.ts +42 -0
  46. package/build/lib/machines/transport/stream-bus.js +61 -0
  47. package/build/lib/machines/transport/streams.d.ts +10 -14
  48. package/build/lib/machines/transport/streams.js +18 -61
  49. package/build/lib/messaging/config.d.ts +25 -0
  50. package/build/lib/messaging/config.js +55 -0
  51. package/build/lib/messaging/constants.d.ts +26 -0
  52. package/build/lib/messaging/constants.js +26 -0
  53. package/build/lib/messaging/index.d.ts +24 -0
  54. package/build/lib/messaging/index.js +65 -0
  55. package/build/lib/messaging/memory.d.ts +16 -0
  56. package/build/lib/messaging/memory.js +147 -0
  57. package/build/lib/messaging/nats/permissions.d.ts +13 -0
  58. package/build/lib/messaging/nats/permissions.js +22 -0
  59. package/build/lib/messaging/nats/provider.d.ts +30 -0
  60. package/build/lib/messaging/nats/provider.js +77 -0
  61. package/build/lib/messaging/nats/render-conf.d.ts +68 -0
  62. package/build/lib/messaging/nats/render-conf.js +58 -0
  63. package/build/lib/messaging/nats/streams.d.ts +26 -0
  64. package/build/lib/messaging/nats/streams.js +97 -0
  65. package/build/lib/messaging/subjects.d.ts +8 -0
  66. package/build/lib/messaging/subjects.js +25 -0
  67. package/build/modules/machines.d.ts +8 -0
  68. package/build/modules/machines.js +16 -0
  69. package/build/routes/index.js +2 -0
  70. package/build/routes/machines.d.ts +2 -0
  71. package/build/routes/machines.js +220 -0
  72. package/build/scripts/bambu-boat.d.ts +17 -0
  73. package/build/scripts/bambu-boat.js +134 -0
  74. package/build/scripts/bambu-print.d.ts +18 -0
  75. package/build/scripts/bambu-print.js +114 -0
  76. package/build/services/machines/commands.d.ts +5 -5
  77. package/build/services/machines/commands.js +3 -2
  78. package/build/services/machines/config.d.ts +8 -1
  79. package/build/services/machines/config.js +17 -7
  80. package/build/services/machines/contracts.d.ts +29 -2
  81. package/build/services/machines/contracts.js +12 -3
  82. package/build/services/machines/gateway/actions.d.ts +2 -1
  83. package/build/services/machines/gateway/admission.d.ts +15 -3
  84. package/build/services/machines/gateway/admission.js +29 -14
  85. package/build/services/machines/gateway/dispatcher.d.ts +19 -3
  86. package/build/services/machines/gateway/dispatcher.js +61 -13
  87. package/build/services/machines/gateway/executor.d.ts +18 -4
  88. package/build/services/machines/gateway/executor.js +99 -34
  89. package/build/services/machines/gateway/gateway.d.ts +22 -1
  90. package/build/services/machines/gateway/gateway.js +83 -28
  91. package/build/services/machines/gateway/index.d.ts +3 -0
  92. package/build/services/machines/gateway/index.js +3 -0
  93. package/build/services/machines/gateway/inspect.d.ts +17 -0
  94. package/build/services/machines/gateway/inspect.js +68 -0
  95. package/build/services/machines/gateway/lifecycle.d.ts +21 -0
  96. package/build/services/machines/gateway/lifecycle.js +89 -0
  97. package/build/services/machines/gateway/log.d.ts +8 -0
  98. package/build/services/machines/gateway/log.js +18 -0
  99. package/build/services/machines/gateway/pacing.d.ts +14 -0
  100. package/build/services/machines/gateway/pacing.js +27 -2
  101. package/build/services/machines/gateway/plan-escalation.js +21 -7
  102. package/build/services/machines/gateway/plan-machine.d.ts +5 -4
  103. package/build/services/machines/gateway/plan-machine.js +70 -19
  104. package/build/services/machines/gateway/project.d.ts +9 -0
  105. package/build/services/machines/gateway/project.js +55 -0
  106. package/build/services/machines/gateway/receipts.d.ts +3 -0
  107. package/build/services/machines/gateway/receipts.js +3 -1
  108. package/build/services/machines/gateway/reconcile.d.ts +2 -0
  109. package/build/services/machines/gateway/reconcile.js +16 -3
  110. package/build/services/machines/gateway/registration.js +1 -1
  111. package/build/services/machines/gateway/reply-waiter.d.ts +6 -3
  112. package/build/services/machines/gateway/reply-waiter.js +37 -16
  113. package/build/services/machines/gateway/state.d.ts +50 -4
  114. package/build/services/machines/gateway/state.js +77 -10
  115. package/build/services/machines/gateway/wire.d.ts +58 -0
  116. package/build/services/machines/gateway/wire.js +171 -0
  117. package/build/services/machines/index.d.ts +3 -0
  118. package/build/services/machines/index.js +2 -0
  119. package/build/services/machines/leadership.d.ts +17 -4
  120. package/build/services/machines/leadership.js +43 -18
  121. package/build/services/machines/line-index.d.ts +16 -0
  122. package/build/services/machines/line-index.js +39 -0
  123. package/build/services/machines/registry-sql.d.ts +31 -0
  124. package/build/services/machines/registry-sql.js +110 -0
  125. package/build/services/machines/registry-sync.d.ts +31 -0
  126. package/build/services/machines/registry-sync.js +81 -0
  127. package/build/services/machines/registry.d.ts +77 -0
  128. package/build/services/machines/registry.js +158 -0
  129. package/build/services/machines/rows.js +26 -2
  130. package/build/services/machines/select.d.ts +9 -2
  131. package/build/services/machines/select.js +20 -7
  132. package/build/services/machines/surface.d.ts +45 -5
  133. package/build/services/machines/surface.js +102 -16
  134. package/build/services/machines/testing/fake-long-tail.d.ts +1 -0
  135. package/build/services/machines/testing/fake-long-tail.js +6 -3
  136. package/build/start/adapters.js +11 -2
  137. package/build/start/apply-report.d.ts +1 -1
  138. package/build/start/apply-report.js +3 -25
  139. package/build/start/index.js +23 -5
  140. package/build/system/index.js +13 -0
  141. package/build/system/mcp-servers/admin/schemas.d.ts +22 -22
  142. package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -7
  143. package/build/system/mcp-servers/machines-schemas.d.ts +35 -0
  144. package/build/system/mcp-servers/machines-schemas.js +35 -0
  145. package/build/system/mcp-servers/machines.d.ts +20 -0
  146. package/build/system/mcp-servers/machines.js +154 -0
  147. package/build/system/seed/tool-manifests-machines.d.ts +2 -0
  148. package/build/system/seed/tool-manifests-machines.js +88 -0
  149. package/build/tsconfig.tsbuildinfo +1 -1
  150. package/build/types/events.d.ts +6 -1
  151. package/build/types/index.d.ts +2 -0
  152. package/build/types/machines-view.d.ts +159 -0
  153. package/build/types/machines-view.js +7 -0
  154. package/build/types/machines.d.ts +6 -1
  155. package/build/types/messaging.d.ts +72 -0
  156. package/build/types/messaging.js +11 -0
  157. package/build/types/startup.d.ts +26 -1
  158. package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js → AdminDashboard-Bm7VG65H.js} +2 -2
  159. package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js.map → AdminDashboard-Bm7VG65H.js.map} +1 -1
  160. package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js → AgentConfigPage-aJF7Sdbc.js} +6 -6
  161. package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js.map → AgentConfigPage-aJF7Sdbc.js.map} +1 -1
  162. package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js → AgentDetailPage-GwwghhxT.js} +3 -3
  163. package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js.map → AgentDetailPage-GwwghhxT.js.map} +1 -1
  164. package/dashboard/dist/assets/AgentsPage-DVvCzZyg.js +2 -0
  165. package/dashboard/dist/assets/{AgentsPage-C9UuUKhr.js.map → AgentsPage-DVvCzZyg.js.map} +1 -1
  166. package/dashboard/dist/assets/AvailableEscalationsPage-Cxmcji_K.js +2 -0
  167. package/dashboard/dist/assets/{AvailableEscalationsPage-DrvfXz70.js.map → AvailableEscalationsPage-Cxmcji_K.js.map} +1 -1
  168. package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js → BotPicker-CofRxk4L.js} +2 -2
  169. package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js.map → BotPicker-CofRxk4L.js.map} +1 -1
  170. package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js → BulkAssignModal-BARWuz4L.js} +2 -2
  171. package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js.map → BulkAssignModal-BARWuz4L.js.map} +1 -1
  172. package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js → CapabilitiesPage-BJAWVNEx.js} +2 -2
  173. package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js.map → CapabilitiesPage-BJAWVNEx.js.map} +1 -1
  174. package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js → CollapsibleSection-CtgoaG75.js} +2 -2
  175. package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js.map → CollapsibleSection-CtgoaG75.js.map} +1 -1
  176. package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js → ConfirmDeleteModal-BYXXBWs6.js} +2 -2
  177. package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js.map → ConfirmDeleteModal-BYXXBWs6.js.map} +1 -1
  178. package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js → ConnectedAppsPage-D0JkzWa7.js} +2 -2
  179. package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js.map → ConnectedAppsPage-D0JkzWa7.js.map} +1 -1
  180. package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js → CountdownTimer-BcFxdZYN.js} +2 -2
  181. package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js.map → CountdownTimer-BcFxdZYN.js.map} +1 -1
  182. package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js → CredentialsPage-DPSY20rV.js} +2 -2
  183. package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js.map → CredentialsPage-DPSY20rV.js.map} +1 -1
  184. package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js → CronLabel-Dg_Oew_Y.js} +2 -2
  185. package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js.map → CronLabel-Dg_Oew_Y.js.map} +1 -1
  186. package/dashboard/dist/assets/{DropZone-u1JGfR9G.js → DropZone-Cl_Flb16.js} +2 -2
  187. package/dashboard/dist/assets/{DropZone-u1JGfR9G.js.map → DropZone-Cl_Flb16.js.map} +1 -1
  188. package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js → ElapsedCell-Dm3G5fK2.js} +2 -2
  189. package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js.map → ElapsedCell-Dm3G5fK2.js.map} +1 -1
  190. package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js → EntityTimelinePanel-CrEEP04e.js} +2 -2
  191. package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js.map → EntityTimelinePanel-CrEEP04e.js.map} +1 -1
  192. package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js → EscalationListSchemaPage-wOInXcjs.js} +3 -3
  193. package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js.map → EscalationListSchemaPage-wOInXcjs.js.map} +1 -1
  194. package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js → EscalationSchemaPage-CrIj_g9d.js} +3 -3
  195. package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js.map → EscalationSchemaPage-CrIj_g9d.js.map} +1 -1
  196. package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js → EscalationTimeline-CeAsl5IT.js} +2 -2
  197. package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js.map → EscalationTimeline-CeAsl5IT.js.map} +1 -1
  198. package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js → EscalationTitleSelect-D8qpCYiy.js} +2 -2
  199. package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js.map → EscalationTitleSelect-D8qpCYiy.js.map} +1 -1
  200. package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js → EscalationsOverview-CvaqVPsr.js} +2 -2
  201. package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js.map → EscalationsOverview-CvaqVPsr.js.map} +1 -1
  202. package/dashboard/dist/assets/{EventTable-V4RF_n58.js → EventTable-Be0JuEl6.js} +2 -2
  203. package/dashboard/dist/assets/{EventTable-V4RF_n58.js.map → EventTable-Be0JuEl6.js.map} +1 -1
  204. package/dashboard/dist/assets/FilterBar-BVyAjIgv.js +2 -0
  205. package/dashboard/dist/assets/FilterBar-BVyAjIgv.js.map +1 -0
  206. package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js → GraphInvokePage-D_QigJeD.js} +2 -2
  207. package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js.map → GraphInvokePage-D_QigJeD.js.map} +1 -1
  208. package/dashboard/dist/assets/{HomePage-EjcNxlKx.js → HomePage-C1haeuNy.js} +2 -2
  209. package/dashboard/dist/assets/{HomePage-EjcNxlKx.js.map → HomePage-C1haeuNy.js.map} +1 -1
  210. package/dashboard/dist/assets/LinePage-CWD5pv1g.js +5 -0
  211. package/dashboard/dist/assets/LinePage-CWD5pv1g.js.map +1 -0
  212. package/dashboard/dist/assets/LinesPage-NqChsKcO.js +3 -0
  213. package/dashboard/dist/assets/LinesPage-NqChsKcO.js.map +1 -0
  214. package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js → ListToolbar-BZCNrTh6.js} +2 -2
  215. package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js.map → ListToolbar-BZCNrTh6.js.map} +1 -1
  216. package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js → McpOverview-yJTYnh1z.js} +2 -2
  217. package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js.map → McpOverview-yJTYnh1z.js.map} +1 -1
  218. package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js → McpQueryDetailPage-ChuLpJ4u.js} +3 -3
  219. package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js.map → McpQueryDetailPage-ChuLpJ4u.js.map} +1 -1
  220. package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js → McpQueryPage-9S-v9soF.js} +2 -2
  221. package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js.map → McpQueryPage-9S-v9soF.js.map} +1 -1
  222. package/dashboard/dist/assets/McpRunDetailPage-BhrcfxD5.js +2 -0
  223. package/dashboard/dist/assets/{McpRunDetailPage-80fQn9iX.js.map → McpRunDetailPage-BhrcfxD5.js.map} +1 -1
  224. package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js → McpRunsPage-C5_i8_Zx.js} +2 -2
  225. package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js.map → McpRunsPage-C5_i8_Zx.js.map} +1 -1
  226. package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js → NamespacePill-OTZD2hzt.js} +2 -2
  227. package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js.map → NamespacePill-OTZD2hzt.js.map} +1 -1
  228. package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js → OperationsPage-C03CeU5P.js} +2 -2
  229. package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js.map → OperationsPage-C03CeU5P.js.map} +1 -1
  230. package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js → OperatorDashboard-BzC134Jt.js} +2 -2
  231. package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js.map → OperatorDashboard-BzC134Jt.js.map} +1 -1
  232. package/dashboard/dist/assets/{PageHeader-BSWIspNB.js → PageHeader-Hx8APPwE.js} +2 -2
  233. package/dashboard/dist/assets/{PageHeader-BSWIspNB.js.map → PageHeader-Hx8APPwE.js.map} +1 -1
  234. package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js → PageHeaderWithStats-BEQYYBJv.js} +2 -2
  235. package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js.map → PageHeaderWithStats-BEQYYBJv.js.map} +1 -1
  236. package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js → PersonaDetailPage-D0mY9L6j.js} +2 -2
  237. package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js.map → PersonaDetailPage-D0mY9L6j.js.map} +1 -1
  238. package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js → PersonasPage-FFlm5Eug.js} +2 -2
  239. package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js.map → PersonasPage-FFlm5Eug.js.map} +1 -1
  240. package/dashboard/dist/assets/{PortalPage-CucNZn_w.js → PortalPage-Cpc25uO-.js} +2 -2
  241. package/dashboard/dist/assets/{PortalPage-CucNZn_w.js.map → PortalPage-Cpc25uO-.js.map} +1 -1
  242. package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js → ProcessDetailPage-Di2J7KwY.js} +2 -2
  243. package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js.map → ProcessDetailPage-Di2J7KwY.js.map} +1 -1
  244. package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js → ProcessesListPage-BEXwU3Z0.js} +2 -2
  245. package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js.map → ProcessesListPage-BEXwU3Z0.js.map} +1 -1
  246. package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js → ResolverForm-2ks-3jXC.js} +6 -6
  247. package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js.map → ResolverForm-2ks-3jXC.js.map} +1 -1
  248. package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js → RoleDetailPage-DqoOk0xc.js} +3 -3
  249. package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js.map → RoleDetailPage-DqoOk0xc.js.map} +1 -1
  250. package/dashboard/dist/assets/{RolePill-CoETDpjF.js → RolePill-R5_ctGFy.js} +2 -2
  251. package/dashboard/dist/assets/{RolePill-CoETDpjF.js.map → RolePill-R5_ctGFy.js.map} +1 -1
  252. package/dashboard/dist/assets/{RolesPage-DBKxeam4.js → RolesPage-CPmo8Srr.js} +2 -2
  253. package/dashboard/dist/assets/{RolesPage-DBKxeam4.js.map → RolesPage-CPmo8Srr.js.map} +1 -1
  254. package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js → RosterWidget-D2yovCKw.js} +2 -2
  255. package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js.map → RosterWidget-D2yovCKw.js.map} +1 -1
  256. package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js → RunAsSelector-CMv96On6.js} +2 -2
  257. package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js.map → RunAsSelector-CMv96On6.js.map} +1 -1
  258. package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js → ScanCodesPage-CA6cTT-M.js} +2 -2
  259. package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js.map → ScanCodesPage-CA6cTT-M.js.map} +1 -1
  260. package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js → ScanSchemeDetailPage-DnctN5-H.js} +2 -2
  261. package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js.map → ScanSchemeDetailPage-DnctN5-H.js.map} +1 -1
  262. package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js → ScanStationPage-Bk8RwkKL.js} +2 -2
  263. package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js.map → ScanStationPage-Bk8RwkKL.js.map} +1 -1
  264. package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js → ScopeBadge-BXZ084nD.js} +2 -2
  265. package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js.map → ScopeBadge-BXZ084nD.js.map} +1 -1
  266. package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js → StickyPagination-B0FSuUgs.js} +2 -2
  267. package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js.map → StickyPagination-B0FSuUgs.js.map} +1 -1
  268. package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js → StreamMessageDetail-BwZEvMpP.js} +2 -2
  269. package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js.map → StreamMessageDetail-BwZEvMpP.js.map} +1 -1
  270. package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js → SwimlaneTimeline-BDVQEaMw.js} +2 -2
  271. package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js.map → SwimlaneTimeline-BDVQEaMw.js.map} +1 -1
  272. package/dashboard/dist/assets/{TagInput-S7UuVT_M.js → TagInput-DjPUDp2M.js} +2 -2
  273. package/dashboard/dist/assets/{TagInput-S7UuVT_M.js.map → TagInput-DjPUDp2M.js.map} +1 -1
  274. package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js → TaskDetailPage-BOlv3iGB.js} +2 -2
  275. package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js.map → TaskDetailPage-BOlv3iGB.js.map} +1 -1
  276. package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js → TaskQueuePill-D-4Ynf3K.js} +2 -2
  277. package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js.map → TaskQueuePill-D-4Ynf3K.js.map} +1 -1
  278. package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js → TasksListPage-e2teY0bD.js} +2 -2
  279. package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js.map → TasksListPage-e2teY0bD.js.map} +1 -1
  280. package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js → TimeAgo-Cvkpf_b3.js} +2 -2
  281. package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js.map → TimeAgo-Cvkpf_b3.js.map} +1 -1
  282. package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js → TimestampCell-B3btAV0N.js} +2 -2
  283. package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js.map → TimestampCell-B3btAV0N.js.map} +1 -1
  284. package/dashboard/dist/assets/{ToolPill-D40uLM_v.js → ToolPill-GsKQ80CO.js} +2 -2
  285. package/dashboard/dist/assets/{ToolPill-D40uLM_v.js.map → ToolPill-GsKQ80CO.js.map} +1 -1
  286. package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js → ToolTestPanel-B03nebR7.js} +2 -2
  287. package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js.map → ToolTestPanel-B03nebR7.js.map} +1 -1
  288. package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js → TopicDetailPage-DBRWne3O.js} +3 -3
  289. package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js.map → TopicDetailPage-DBRWne3O.js.map} +1 -1
  290. package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js → TopicsPage-CVe2M9HD.js} +2 -2
  291. package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js.map → TopicsPage-CVe2M9HD.js.map} +1 -1
  292. package/dashboard/dist/assets/{UserName-DQFjuoib.js → UserName-B_q_qp6V.js} +2 -2
  293. package/dashboard/dist/assets/{UserName-DQFjuoib.js.map → UserName-B_q_qp6V.js.map} +1 -1
  294. package/dashboard/dist/assets/WorkflowExecutionPage-Bh_dr9tM.js +2 -0
  295. package/dashboard/dist/assets/{WorkflowExecutionPage-Di08wCbs.js.map → WorkflowExecutionPage-Bh_dr9tM.js.map} +1 -1
  296. package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js → WorkflowPill-D7244fKp.js} +2 -2
  297. package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js.map → WorkflowPill-D7244fKp.js.map} +1 -1
  298. package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js → WorkflowsDashboard-DA6Mj7qH.js} +2 -2
  299. package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js.map → WorkflowsDashboard-DA6Mj7qH.js.map} +1 -1
  300. package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js → WorkflowsOverview-B1kBLj-a.js} +2 -2
  301. package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js.map → WorkflowsOverview-B1kBLj-a.js.map} +1 -1
  302. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js → YamlWorkflowDetailPage-6GJM8QIX.js} +8 -8
  303. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js.map → YamlWorkflowDetailPage-6GJM8QIX.js.map} +1 -1
  304. package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js → YamlWorkflowsPage-Bu811C7f.js} +2 -2
  305. package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js.map → YamlWorkflowsPage-Bu811C7f.js.map} +1 -1
  306. package/dashboard/dist/assets/{agents-PuftRTB2.js → agents-MPk_GnYz.js} +2 -2
  307. package/dashboard/dist/assets/{agents-PuftRTB2.js.map → agents-MPk_GnYz.js.map} +1 -1
  308. package/dashboard/dist/assets/{bots-BmEiPAWY.js → bots-2RihE2Tc.js} +2 -2
  309. package/dashboard/dist/assets/{bots-BmEiPAWY.js.map → bots-2RihE2Tc.js.map} +1 -1
  310. package/dashboard/dist/assets/{capabilities-CRii4Soa.js → capabilities-CC4iwJ1P.js} +2 -2
  311. package/dashboard/dist/assets/{capabilities-CRii4Soa.js.map → capabilities-CC4iwJ1P.js.map} +1 -1
  312. package/dashboard/dist/assets/{controlplane-DO_czaYo.js → controlplane-Bmkic8BH.js} +2 -2
  313. package/dashboard/dist/assets/{controlplane-DO_czaYo.js.map → controlplane-Bmkic8BH.js.map} +1 -1
  314. package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js → escalation-columns-B0lhUUrQ.js} +2 -2
  315. package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js.map → escalation-columns-B0lhUUrQ.js.map} +1 -1
  316. package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js → escalation-items-7WFpPo46.js} +2 -2
  317. package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js.map → escalation-items-7WFpPo46.js.map} +1 -1
  318. package/dashboard/dist/assets/index-B9uv-euR.css +1 -0
  319. package/dashboard/dist/assets/{index-DhSCCpqM.js → index-B_XV1rwu.js} +2 -2
  320. package/dashboard/dist/assets/{index-DhSCCpqM.js.map → index-B_XV1rwu.js.map} +1 -1
  321. package/dashboard/dist/assets/{index-Cx8xb-oU.js → index-C2CLfGwL.js} +2 -2
  322. package/dashboard/dist/assets/{index-Cx8xb-oU.js.map → index-C2CLfGwL.js.map} +1 -1
  323. package/dashboard/dist/assets/{index-Cga5IW3D.js → index-C3AeFihz.js} +2 -2
  324. package/dashboard/dist/assets/{index-Cga5IW3D.js.map → index-C3AeFihz.js.map} +1 -1
  325. package/dashboard/dist/assets/{index-DiaRlFYI.js → index-CBri8fYM.js} +2 -2
  326. package/dashboard/dist/assets/{index-DiaRlFYI.js.map → index-CBri8fYM.js.map} +1 -1
  327. package/dashboard/dist/assets/{index-CL_1VpGb.js → index-CRWsB7ZC.js} +2 -2
  328. package/dashboard/dist/assets/{index-CL_1VpGb.js.map → index-CRWsB7ZC.js.map} +1 -1
  329. package/dashboard/dist/assets/{index-XntldBd0.js → index-CTOv3G7a.js} +2 -2
  330. package/dashboard/dist/assets/{index-XntldBd0.js.map → index-CTOv3G7a.js.map} +1 -1
  331. package/dashboard/dist/assets/{index-CfP2nKRc.js → index-CcArGkzI.js} +3 -3
  332. package/dashboard/dist/assets/{index-CfP2nKRc.js.map → index-CcArGkzI.js.map} +1 -1
  333. package/dashboard/dist/assets/{index-Dz6R8-Dw.js → index-CkMHS-hG.js} +25 -25
  334. package/dashboard/dist/assets/index-CkMHS-hG.js.map +1 -0
  335. package/dashboard/dist/assets/index-CmsmwCyv.js +2 -0
  336. package/dashboard/dist/assets/{index-4YaDUcKd.js.map → index-CmsmwCyv.js.map} +1 -1
  337. package/dashboard/dist/assets/{index-2SM2_onB.js → index-CvJsvqIc.js} +2 -2
  338. package/dashboard/dist/assets/{index-2SM2_onB.js.map → index-CvJsvqIc.js.map} +1 -1
  339. package/dashboard/dist/assets/{index-Rwqrflm-.js → index-D-ilRyfy.js} +2 -2
  340. package/dashboard/dist/assets/{index-Rwqrflm-.js.map → index-D-ilRyfy.js.map} +1 -1
  341. package/dashboard/dist/assets/{index-CZ7A3AcD.js → index-DSUtfDXx.js} +2 -2
  342. package/dashboard/dist/assets/{index-CZ7A3AcD.js.map → index-DSUtfDXx.js.map} +1 -1
  343. package/dashboard/dist/assets/{index-jL2K6us4.js → index-Da6ycKyf.js} +2 -2
  344. package/dashboard/dist/assets/{index-jL2K6us4.js.map → index-Da6ycKyf.js.map} +1 -1
  345. package/dashboard/dist/assets/{knowledge-CeUqGPuo.js → knowledge-Bpbg20DC.js} +2 -2
  346. package/dashboard/dist/assets/{knowledge-CeUqGPuo.js.map → knowledge-Bpbg20DC.js.map} +1 -1
  347. package/dashboard/dist/assets/machines-BqOZZU-3.js +2 -0
  348. package/dashboard/dist/assets/machines-BqOZZU-3.js.map +1 -0
  349. package/dashboard/dist/assets/{mcp-Cx96NTeD.js → mcp-CmcUXYce.js} +2 -2
  350. package/dashboard/dist/assets/{mcp-Cx96NTeD.js.map → mcp-CmcUXYce.js.map} +1 -1
  351. package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js → mcp-query-C8buQxN9.js} +2 -2
  352. package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js.map → mcp-query-C8buQxN9.js.map} +1 -1
  353. package/dashboard/dist/assets/{personas--4kjwyOw.js → personas-C2n5oDmY.js} +2 -2
  354. package/dashboard/dist/assets/{personas--4kjwyOw.js.map → personas-C2n5oDmY.js.map} +1 -1
  355. package/dashboard/dist/assets/{pipelines-PgkwvG7f.js → pipelines-RKpSkFz7.js} +2 -2
  356. package/dashboard/dist/assets/{pipelines-PgkwvG7f.js.map → pipelines-RKpSkFz7.js.map} +1 -1
  357. package/dashboard/dist/assets/{tasks-CcYxdBa3.js → tasks-Dab4hExW.js} +2 -2
  358. package/dashboard/dist/assets/{tasks-CcYxdBa3.js.map → tasks-Dab4hExW.js.map} +1 -1
  359. package/dashboard/dist/assets/{topics-_lik7cNY.js → topics-FTMNP7r3.js} +2 -2
  360. package/dashboard/dist/assets/{topics-_lik7cNY.js.map → topics-FTMNP7r3.js.map} +1 -1
  361. package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js → useDebouncedValue-B_1u1YIk.js} +2 -2
  362. package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js.map → useDebouncedValue-B_1u1YIk.js.map} +1 -1
  363. package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js → useNamespace-HUeAI7Qb.js} +2 -2
  364. package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js.map → useNamespace-HUeAI7Qb.js.map} +1 -1
  365. package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js → useYamlActivityEvents-Cax54qHH.js} +2 -2
  366. package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js.map → useYamlActivityEvents-Cax54qHH.js.map} +1 -1
  367. package/dashboard/dist/assets/{validate-FlXCBBT6.js → validate-DxOaV7QS.js} +2 -2
  368. package/dashboard/dist/assets/{validate-FlXCBBT6.js.map → validate-DxOaV7QS.js.map} +1 -1
  369. package/dashboard/dist/assets/{vendor-icons-DUYcKTjP.js → vendor-icons-fxBvvHBi.js} +187 -182
  370. package/dashboard/dist/assets/vendor-icons-fxBvvHBi.js.map +1 -0
  371. package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js → yaml-workflows-BgY1XHJx.js} +2 -2
  372. package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js.map → yaml-workflows-BgY1XHJx.js.map} +1 -1
  373. package/dashboard/dist/index.html +3 -3
  374. package/docs/architecture.md +1 -0
  375. package/docs/code-owned-configuration.md +6 -0
  376. package/docs/dashboard.md +1 -0
  377. package/docs/events.md +83 -4
  378. package/docs/machines.md +129 -23
  379. package/docs/mcp.md +19 -0
  380. package/package.json +3 -1
  381. package/build/lib/machines/transport/nats-durable.d.ts +0 -11
  382. package/build/lib/machines/transport/nats-durable.js +0 -28
  383. package/dashboard/dist/assets/AgentsPage-C9UuUKhr.js +0 -2
  384. package/dashboard/dist/assets/AvailableEscalationsPage-DrvfXz70.js +0 -2
  385. package/dashboard/dist/assets/FilterBar-BygWrnB1.js +0 -2
  386. package/dashboard/dist/assets/FilterBar-BygWrnB1.js.map +0 -1
  387. package/dashboard/dist/assets/McpRunDetailPage-80fQn9iX.js +0 -2
  388. package/dashboard/dist/assets/WorkflowExecutionPage-Di08wCbs.js +0 -2
  389. package/dashboard/dist/assets/index-4YaDUcKd.js +0 -2
  390. package/dashboard/dist/assets/index-CnU7Jjz3.css +0 -1
  391. package/dashboard/dist/assets/index-Dz6R8-Dw.js.map +0 -1
  392. package/dashboard/dist/assets/vendor-icons-DUYcKTjP.js.map +0 -1
package/README.md CHANGED
@@ -63,6 +63,12 @@ The `reviewer` role owns a versioned form schema. The platform renders it as the
63
63
 
64
64
  Two surfaces, one model. A `proxyActivity` targets a machine: call it, get a result. `conditional` targets the external world — a reviewer, an operator, a factory cell. It suspends the workflow and writes a single escalation row carrying everything needed to route the work: the `role` that should act, its `type` and `priority`, and any `metadata` to display or filter on. People work that row through an RBAC-scoped surface — find it, claim it, resolve it — from the dashboard, the API, or MCP, and resolving it resumes the workflow exactly where it paused.
65
65
 
66
+ Three kinds of resolver answer the same row:
67
+
68
+ - **People**, on the [dashboard](https://github.com/hotmeshio/long-tail/blob/main/docs/dashboard.md): the role's versioned form is their UI.
69
+ - **Systems and agents**, over the [API](https://github.com/hotmeshio/long-tail/blob/main/docs/api/http/escalations.md) and MCP: the same find, claim and resolve verbs, as a service account.
70
+ - **Machines**, over [MQTT](https://github.com/hotmeshio/long-tail/blob/main/docs/machines.md): a line's gateway claims and resolves as each machine, and the protocol lands on the row as data; the dashboard's Lines view watches the wire, and lines are declared in code or through the API.
71
+
66
72
  Activities are plain functions:
67
73
 
68
74
  ```typescript
@@ -76,7 +82,7 @@ export async function analyzeContent(content: string) {
76
82
 
77
83
  The non-deterministic queue has qualities the deterministic one never needed:
78
84
 
79
- - **RBAC is intrinsic.** The queue is a role; permission lives in the queue itself. Any member answers — a person in the dashboard, a service account through the API — and the workflow is indifferent to which.
85
+ - **RBAC is intrinsic.** The queue is a role; permission lives in the queue itself. Any member answers — a person in the dashboard, a service account through the API, a machine over MQTT — and the workflow is indifferent to which.
80
86
  - **The form is data.** A versioned JSON Schema on the role renders the resolver's UI — fields, validation, conditionals, layout — with zero frontend code. Assign an escalation to one named user with self scope and you have a just-in-time form: one person, one item, one auditable edition.
81
87
  - **Claims are locks.** A claim is a TTL window with an extend prompt before it lapses and a resolve guard behind it — the platform rejects a submission against an expired claim atomically, in the same statement that settles the row. Stale work cannot land.
82
88
  - **Cancel is home.** Cancellation is a first-class settlement, not an exception. When the pressure no longer applies, the waiting flow sees `null` and reconciles to a modeled resting state. Handled is broader than resolved — timeout, cancel, and hop-onward are all endings the loop was built to reach.
@@ -170,6 +176,7 @@ const lt = await start({
170
176
  telemetry: { honeycomb: { apiKey: process.env.HNY } },
171
177
  logging: { pino: { level: 'info' } },
172
178
  maintenance: true,
179
+ machines: { lines: [Machines.loadLine('/etc/line.json')] }, // rows resolved over MQTT; the dashboard gains a Lines view
173
180
  });
174
181
  ```
175
182
 
@@ -246,7 +253,7 @@ All modes share PostgreSQL and scale independently. See [Cloud Deployment](https
246
253
  | [Schema Enforcement](https://github.com/hotmeshio/long-tail/blob/main/docs/schema-enforcement.md) | form_schema as an enforced API contract on every resolve surface |
247
254
  | [Code-Owned Configuration](https://github.com/hotmeshio/long-tail/blob/main/docs/code-owned-configuration.md) | `configSource` — declared config compared and applied at every boot |
248
255
  | [Faceted Routing](https://github.com/hotmeshio/long-tail/blob/main/docs/faceted-routing.md) | Query and atomically claim the queue by facets; dispatcher pattern |
249
- | [Machines](https://github.com/hotmeshio/long-tail/blob/main/docs/machines.md) | `start({ machines })`: machines resolve escalation rows over MQTT, as people do with forms |
256
+ | [Machines](https://github.com/hotmeshio/long-tail/blob/main/docs/machines.md) | `start({ machines })`: machines resolve escalation rows over MQTT, as people do with forms; the Lines view, the line registry API and the machines MCP server |
250
257
  | [SDK](https://github.com/hotmeshio/long-tail/blob/main/docs/sdk.md) | Embedded usage, `createClient`, event subscriptions |
251
258
  | [Architecture](https://github.com/hotmeshio/long-tail/blob/main/docs/architecture.md) | Project structure, conventions, discovery |
252
259
  | [Cloud](https://github.com/hotmeshio/long-tail/blob/main/docs/cloud.md) | AWS ECS, GCP Cloud Run, Docker |
@@ -8,6 +8,9 @@ import type { LTApiResult } from '../types/sdk';
8
8
  * environment block (long-tail + HotMesh versions, Node env/version).
9
9
  *
10
10
  * @param req — the incoming HTTP request, used to derive NATS WS URL from headers when proxying
11
- * @returns `{ status: 200, data: { telemetry, escalation, events, auth, ai, features, search, branding, display, environment } }`
11
+ * `machines` is present only when `start({ machines })` runs a surface; it carries the
12
+ * number of lines this replica runs and nothing else, since the settings are public.
13
+ *
14
+ * @returns `{ status: 200, data: { telemetry, escalation, events, auth, ai, features, search, branding, display, environment, machines? } }`
12
15
  */
13
16
  export declare function getSettings(req?: IncomingMessage): Promise<LTApiResult>;
@@ -12,6 +12,7 @@ const search_1 = require("../modules/search");
12
12
  const branding_1 = require("../modules/branding");
13
13
  const oauth_server_1 = require("../modules/oauth-server");
14
14
  const display_1 = require("../modules/display");
15
+ const machines_1 = require("../modules/machines");
15
16
  const version_1 = require("../modules/version");
16
17
  const sso_1 = require("../modules/sso");
17
18
  const defaults_1 = require("../modules/defaults");
@@ -43,7 +44,10 @@ function resolveNatsWsUrl(adapter, req) {
43
44
  * environment block (long-tail + HotMesh versions, Node env/version).
44
45
  *
45
46
  * @param req — the incoming HTTP request, used to derive NATS WS URL from headers when proxying
46
- * @returns `{ status: 200, data: { telemetry, escalation, events, auth, ai, features, search, branding, display, environment } }`
47
+ * `machines` is present only when `start({ machines })` runs a surface; it carries the
48
+ * number of lines this replica runs and nothing else, since the settings are public.
49
+ *
50
+ * @returns `{ status: 200, data: { telemetry, escalation, events, auth, ai, features, search, branding, display, environment, machines? } }`
47
51
  */
48
52
  async function getSettings(req) {
49
53
  try {
@@ -55,6 +59,7 @@ async function getSettings(req) {
55
59
  // connect via NATS instead of Socket.IO.
56
60
  const forceNats = config_1.config.EVENT_TRANSPORT === 'nats';
57
61
  const transport = forceNats && natsAdapter ? 'nats' : hasSocketIO ? 'socketio' : natsAdapter ? 'nats' : 'none';
62
+ const machines = (0, machines_1.getMachineSurface)();
58
63
  return {
59
64
  status: 200,
60
65
  data: {
@@ -97,6 +102,7 @@ async function getSettings(req) {
97
102
  nodeVersion: process.version,
98
103
  eventTransport: transport,
99
104
  },
105
+ ...(machines ? { machines: { declared: machines.describeLines().length } } : {}),
100
106
  },
101
107
  };
102
108
  }
package/build/index.d.ts CHANGED
@@ -21,6 +21,10 @@ export { NatsEventAdapter } from './lib/events/nats';
21
21
  export { InMemoryEventAdapter } from './lib/events/memory';
22
22
  export { SocketIOEventAdapter, type SocketIOAuthenticator } from './lib/events/socketio';
23
23
  export { publishMilestoneEvent, publishTaskEvent, publishEscalationEvent, publishActivityEvent, publishWorkflowEvent, publishAgentEvent, publishKnowledgeEvent } from './lib/events/publish';
24
+ export { messagingRegistry, MemoryMessagingProvider, DELIVERY } from './lib/messaging';
25
+ export { NatsMessagingProvider } from './lib/messaging/nats/provider';
26
+ export { renderNatsConf, type NatsConfOptions, type EdgeAccount, type NatsUser } from './lib/messaging/nats/render-conf';
27
+ export { jsPermissions } from './lib/messaging/nats/permissions';
24
28
  export { telemetryRegistry } from './lib/telemetry';
25
29
  export { HoneycombTelemetryAdapter } from './lib/telemetry/honeycomb';
26
30
  export { loggerRegistry } from './lib/logger';
package/build/index.js CHANGED
@@ -15,9 +15,6 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
- };
21
18
  var __importStar = (this && this.__importStar) || (function () {
22
19
  var ownKeys = function(o) {
23
20
  ownKeys = Object.getOwnPropertyNames || function (o) {
@@ -35,12 +32,16 @@ var __importStar = (this && this.__importStar) || (function () {
35
32
  return result;
36
33
  };
37
34
  })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.McpClient = exports.McpService = exports.BuiltInMcpAdapter = exports.mcpRegistry = exports.defaultMaintenanceConfig = exports.maintenanceRegistry = exports.PinoLoggerAdapter = exports.loggerRegistry = exports.HoneycombTelemetryAdapter = exports.telemetryRegistry = exports.publishKnowledgeEvent = exports.publishAgentEvent = exports.publishWorkflowEvent = exports.publishActivityEvent = exports.publishEscalationEvent = exports.publishTaskEvent = exports.publishMilestoneEvent = exports.SocketIOEventAdapter = exports.InMemoryEventAdapter = exports.NatsEventAdapter = exports.eventRegistry = exports.ltConfig = exports.seedConfigTopics = exports.seedSystemTopics = exports.TopicService = exports.displayGtin = exports.normalizeGtin = exports.isValidGtin = exports.assertValidScanIdentityRule = exports.assertValidScanSteps = exports.assertValidScanScheme = exports.UserService = exports.ConfigService = exports.EscalationService = exports.TaskService = exports.setAuthAdapter = exports.signToken = exports.requireAdmin = exports.requireAuth = exports.createAuthMiddleware = exports.JwtAuthAdapter = exports.conditionalAccumulator = exports.conditionLT = exports.conditional = exports.executeLT = exports.createLTActivityInterceptor = exports.createLTInterceptor = exports.registerLT = exports.midnightTheme = exports.start = void 0;
40
- exports.LTExpressAdapter = exports.Machines = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = exports.getActivityIdentity = exports.McpEscalationStrategy = exports.DefaultEscalationStrategy = exports.escalationStrategyRegistry = exports.McpVisionServer = exports.McpTranslationServer = exports.McpServer = void 0;
39
+ exports.PinoLoggerAdapter = exports.loggerRegistry = exports.HoneycombTelemetryAdapter = exports.telemetryRegistry = exports.jsPermissions = exports.renderNatsConf = exports.NatsMessagingProvider = exports.DELIVERY = exports.MemoryMessagingProvider = exports.messagingRegistry = exports.publishKnowledgeEvent = exports.publishAgentEvent = exports.publishWorkflowEvent = exports.publishActivityEvent = exports.publishEscalationEvent = exports.publishTaskEvent = exports.publishMilestoneEvent = exports.SocketIOEventAdapter = exports.InMemoryEventAdapter = exports.NatsEventAdapter = exports.eventRegistry = exports.ltConfig = exports.seedConfigTopics = exports.seedSystemTopics = exports.TopicService = exports.displayGtin = exports.normalizeGtin = exports.isValidGtin = exports.assertValidScanIdentityRule = exports.assertValidScanSteps = exports.assertValidScanScheme = exports.UserService = exports.ConfigService = exports.EscalationService = exports.TaskService = exports.setAuthAdapter = exports.signToken = exports.requireAdmin = exports.requireAuth = exports.createAuthMiddleware = exports.JwtAuthAdapter = exports.conditionalAccumulator = exports.conditionLT = exports.conditional = exports.executeLT = exports.createLTActivityInterceptor = exports.createLTInterceptor = exports.registerLT = exports.midnightTheme = exports.start = void 0;
40
+ exports.LTExpressAdapter = exports.Machines = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = exports.getActivityIdentity = exports.McpEscalationStrategy = exports.DefaultEscalationStrategy = exports.escalationStrategyRegistry = exports.McpVisionServer = exports.McpTranslationServer = exports.McpServer = exports.McpClient = exports.McpService = exports.BuiltInMcpAdapter = exports.mcpRegistry = exports.defaultMaintenanceConfig = exports.maintenanceRegistry = void 0;
41
41
  const config_1 = require("./modules/config");
42
42
  const logger_1 = require("./lib/logger");
43
43
  const midnight_1 = require("./themes/midnight");
44
+ const path = __importStar(require("path"));
44
45
  const start_1 = require("./start");
45
46
  const line_1 = require("./lib/machines/line");
46
47
  // ─── Package Exports ─────────────────────────────────────────────────────────
@@ -100,6 +101,16 @@ Object.defineProperty(exports, "publishActivityEvent", { enumerable: true, get:
100
101
  Object.defineProperty(exports, "publishWorkflowEvent", { enumerable: true, get: function () { return publish_1.publishWorkflowEvent; } });
101
102
  Object.defineProperty(exports, "publishAgentEvent", { enumerable: true, get: function () { return publish_1.publishAgentEvent; } });
102
103
  Object.defineProperty(exports, "publishKnowledgeEvent", { enumerable: true, get: function () { return publish_1.publishKnowledgeEvent; } });
104
+ var messaging_1 = require("./lib/messaging");
105
+ Object.defineProperty(exports, "messagingRegistry", { enumerable: true, get: function () { return messaging_1.messagingRegistry; } });
106
+ Object.defineProperty(exports, "MemoryMessagingProvider", { enumerable: true, get: function () { return messaging_1.MemoryMessagingProvider; } });
107
+ Object.defineProperty(exports, "DELIVERY", { enumerable: true, get: function () { return messaging_1.DELIVERY; } });
108
+ var provider_1 = require("./lib/messaging/nats/provider");
109
+ Object.defineProperty(exports, "NatsMessagingProvider", { enumerable: true, get: function () { return provider_1.NatsMessagingProvider; } });
110
+ var render_conf_1 = require("./lib/messaging/nats/render-conf");
111
+ Object.defineProperty(exports, "renderNatsConf", { enumerable: true, get: function () { return render_conf_1.renderNatsConf; } });
112
+ var permissions_1 = require("./lib/messaging/nats/permissions");
113
+ Object.defineProperty(exports, "jsPermissions", { enumerable: true, get: function () { return permissions_1.jsPermissions; } });
103
114
  var telemetry_1 = require("./lib/telemetry");
104
115
  Object.defineProperty(exports, "telemetryRegistry", { enumerable: true, get: function () { return telemetry_1.telemetryRegistry; } });
105
116
  var honeycomb_1 = require("./lib/telemetry/honeycomb");
@@ -257,7 +268,7 @@ async function main() {
257
268
  // Machines resolve rows over MQTT when a line and a transport are configured
258
269
  // (docker-compose.machines.yml sets both).
259
270
  machines: process.env.MACHINE_TRANSPORT && process.env.MACHINE_LINE_CONFIG
260
- ? { lines: [(0, line_1.loadLine)(process.env.MACHINE_LINE_CONFIG)] }
271
+ ? machinesFromEnv(process.env.MACHINE_LINE_CONFIG, process.env.MACHINE_CODEC_MODULE)
261
272
  : undefined,
262
273
  branding: {
263
274
  ...(process.env.WHITE_LABEL ? { appName: process.env.WHITE_LABEL } : {}),
@@ -266,11 +277,27 @@ async function main() {
266
277
  themes: [midnight_1.midnightTheme],
267
278
  },
268
279
  telemetry: honeycombKey ? { honeycomb: { apiKey: honeycombKey } } : undefined,
269
- events: config_1.config.EVENT_TRANSPORT === 'nats'
270
- ? { nats: { url: config_1.config.NATS_URL, wsUrl: config_1.config.NATS_WS_URL || undefined, token: config_1.config.NATS_TOKEN || undefined } }
280
+ // Messaging from LT_MESSAGING / LT_NATS_* when set; otherwise the older EVENT_TRANSPORT=nats with NATS_*.
281
+ messaging: !process.env.LT_MESSAGING && config_1.config.EVENT_TRANSPORT === 'nats'
282
+ ? { nats: { url: config_1.config.NATS_URL, token: config_1.config.NATS_TOKEN || undefined, ws: { url: config_1.config.NATS_WS_URL || undefined } } }
271
283
  : undefined,
272
284
  });
273
285
  }
286
+ /**
287
+ * The configured lines (MACHINE_LINE_CONFIG, one path or several), spoken to by
288
+ * the generic codec, or for one line by the codec MACHINE_CODEC_MODULE names (its `createCodec(line)`).
289
+ */
290
+ function machinesFromEnv(lineConfig, codecModule) {
291
+ const lines = (0, line_1.loadLines)(lineConfig);
292
+ if (!codecModule)
293
+ return { lines };
294
+ if (lines.length > 1)
295
+ throw new Error('MACHINE_CODEC_MODULE speaks for one line; MACHINE_LINE_CONFIG names several');
296
+ const { createCodec } = require(path.resolve(codecModule));
297
+ if (typeof createCodec !== 'function')
298
+ throw new Error(`MACHINE_CODEC_MODULE=${codecModule} exports no createCodec(line)`);
299
+ return { lines, codec: createCodec(lines[0]) };
300
+ }
274
301
  // Run server when executed directly
275
302
  if (require.main === module) {
276
303
  require('dotenv').config();
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Serializes multi-statement config writes (role-list replaces, escalation
3
+ * target replaces, line declarations) across concurrently booting containers
4
+ * and live API writes. Single-statement upserts are individually race-safe;
5
+ * the lock exists for the replace transactions and keeps boot reports
6
+ * coherent. Distinct from the migration lock so a slow migration on one
7
+ * container never blocks another's config pass behind two locks at once.
8
+ */
9
+ export declare const CONFIG_APPLY_LOCK_ID = 8675310;
10
+ export declare function withConfigLock<T>(fn: () => Promise<T>): Promise<T>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONFIG_APPLY_LOCK_ID = void 0;
4
+ exports.withConfigLock = withConfigLock;
5
+ const index_1 = require("./index");
6
+ /**
7
+ * Serializes multi-statement config writes (role-list replaces, escalation
8
+ * target replaces, line declarations) across concurrently booting containers
9
+ * and live API writes. Single-statement upserts are individually race-safe;
10
+ * the lock exists for the replace transactions and keeps boot reports
11
+ * coherent. Distinct from the migration lock so a slow migration on one
12
+ * container never blocks another's config pass behind two locks at once.
13
+ */
14
+ exports.CONFIG_APPLY_LOCK_ID = 8675310;
15
+ async function withConfigLock(fn) {
16
+ const pool = (0, index_1.getPool)();
17
+ const client = await pool.connect();
18
+ try {
19
+ await client.query(`SELECT pg_advisory_lock(${exports.CONFIG_APPLY_LOCK_ID})`);
20
+ return await fn();
21
+ }
22
+ finally {
23
+ await client
24
+ .query(`SELECT pg_advisory_unlock(${exports.CONFIG_APPLY_LOCK_ID})`)
25
+ .catch(() => { });
26
+ client.release();
27
+ }
28
+ }
@@ -0,0 +1,26 @@
1
+ -- Migration 041: The machine line registry
2
+ --
3
+ -- One row per line a deployment controls: the line definition as the
4
+ -- gateway reads it (site, line, machines in route order), who declared it,
5
+ -- and a version that advances on every change. Lines declared in code
6
+ -- (start({ machines })) are applied here at boot under the configSource
7
+ -- rules; lines declared through PUT /api/machines/lines live here alone.
8
+ -- Every replica reads the registry to know which lines to contend for, and
9
+ -- the Lines index reads it with the pending rows that say how each line is.
10
+ -- search_text is the service's lowercase projection of site, line, machine
11
+ -- ids, processes, roles and addresses, for the index's search.
12
+
13
+ CREATE TABLE IF NOT EXISTS lt_machine_lines (
14
+ site_id TEXT NOT NULL,
15
+ line_id TEXT NOT NULL,
16
+ definition JSONB NOT NULL,
17
+ source TEXT NOT NULL CHECK (source IN ('code', 'api')),
18
+ version INT NOT NULL DEFAULT 1,
19
+ enabled BOOLEAN NOT NULL DEFAULT true,
20
+ search_text TEXT NOT NULL,
21
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
22
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
23
+ PRIMARY KEY (site_id, line_id)
24
+ );
25
+
26
+ CREATE INDEX IF NOT EXISTS lt_machine_lines_site_idx ON lt_machine_lines (site_id, line_id);
@@ -41,13 +41,15 @@ exports.holderView = holderView;
41
41
  /**
42
42
  * What a browser receives of an event. Builders receive events whole. Anyone
43
43
  * else receives enough to route and refresh: escalation events keep their
44
- * routing fields, and every other event arrives without `data` and
45
- * `milestones`. Full records are read through the scoped API, by id.
44
+ * routing fields, machine wire events keep everything but the raw payload,
45
+ * and every other event arrives without `data` and `milestones`. Full
46
+ * records are read through the scoped API, by id.
46
47
  *
47
48
  * Server-side consumers (agent triggers, callbacks) are unaffected: this view
48
49
  * applies only where events leave for a browser.
49
50
  */
50
51
  const ESCALATION_SUBJECT = 'system.escalation.';
52
+ const MACHINE_WIRE_SUBJECT = 'machine.wire.';
51
53
  const ACTIVE_ACCOUNT = 'active';
52
54
  /** Escalation event fields a browser needs to route a refresh and follow a claim. */
53
55
  exports.BROWSER_ESCALATION_FIELDS = [
@@ -69,6 +71,10 @@ function eventForViewer(event, viewer) {
69
71
  }
70
72
  return { ...rest, data: kept };
71
73
  }
74
+ if (typeof event.type === 'string' && event.type.startsWith(MACHINE_WIRE_SUBJECT) && data) {
75
+ const { payload: _payload, ...wire } = data;
76
+ return { ...rest, data: wire };
77
+ }
72
78
  return rest;
73
79
  }
74
80
  /**
@@ -1,4 +1,7 @@
1
1
  import type { LTEvent, LTEventAdapter } from '../../types';
2
+ import type { LTMessagingProvider } from '../../types/messaging';
3
+ /** The part of Long Tail's messaging the adapter uses. */
4
+ export type EventMessaging = Pick<LTMessagingProvider, 'connected' | 'pubsub'>;
2
5
  /**
3
6
  * NATS event adapter — publish AND subscribe.
4
7
  *
@@ -11,6 +14,9 @@ import type { LTEvent, LTEventAdapter } from '../../types';
11
14
  * An `_originId` field prevents the publishing container from
12
15
  * re-dispatching its own events.
13
16
  *
17
+ * Given `messaging` (Long Tail's messaging, `start({ messaging })`), it publishes
18
+ * and bridges over that connection; otherwise it opens a connection of its own.
19
+ *
14
20
  * Usage:
15
21
  * ```typescript
16
22
  * import { eventRegistry, NatsEventAdapter } from '@hotmeshio/long-tail';
@@ -22,6 +28,8 @@ import type { LTEvent, LTEventAdapter } from '../../types';
22
28
  export declare class NatsEventAdapter implements LTEventAdapter {
23
29
  private nc;
24
30
  private sub;
31
+ private readonly messaging;
32
+ private bridge;
25
33
  private url;
26
34
  private _wsUrl;
27
35
  private _wsProxyTarget;
@@ -36,6 +44,7 @@ export declare class NatsEventAdapter implements LTEventAdapter {
36
44
  wsProxy?: string;
37
45
  subjectPrefix?: string;
38
46
  token?: string;
47
+ messaging?: EventMessaging;
39
48
  });
40
49
  /**
41
50
  * Public NATS WebSocket URL for browser connections.
@@ -59,6 +68,8 @@ export declare class NatsEventAdapter implements LTEventAdapter {
59
68
  */
60
69
  setCallbackBridge(adapter: LTEventAdapter): void;
61
70
  connect(): Promise<void>;
71
+ /** An event from another container, handed to the local callback adapter. */
72
+ private bridgeIn;
62
73
  publish(event: LTEvent): Promise<void>;
63
74
  disconnect(): Promise<void>;
64
75
  }
@@ -18,6 +18,9 @@ const sc = (0, nats_1.StringCodec)();
18
18
  * An `_originId` field prevents the publishing container from
19
19
  * re-dispatching its own events.
20
20
  *
21
+ * Given `messaging` (Long Tail's messaging, `start({ messaging })`), it publishes
22
+ * and bridges over that connection; otherwise it opens a connection of its own.
23
+ *
21
24
  * Usage:
22
25
  * ```typescript
23
26
  * import { eventRegistry, NatsEventAdapter } from '@hotmeshio/long-tail';
@@ -30,9 +33,11 @@ class NatsEventAdapter {
30
33
  constructor(options) {
31
34
  this.nc = null;
32
35
  this.sub = null;
36
+ this.bridge = null;
33
37
  this._wsProxyBasePath = '';
34
38
  this.originId = (0, crypto_1.randomUUID)();
35
39
  this.callbackAdapter = null;
40
+ this.messaging = options?.messaging ?? null;
36
41
  this.url = options?.url || config_1.config.NATS_URL;
37
42
  this._wsUrl = options?.wsUrl || config_1.config.NATS_WS_URL || null;
38
43
  this._wsProxyTarget = options?.wsProxy || null;
@@ -75,6 +80,11 @@ class NatsEventAdapter {
75
80
  this.callbackAdapter = adapter;
76
81
  }
77
82
  async connect() {
83
+ if (this.messaging) {
84
+ if (this.callbackAdapter)
85
+ this.bridge = this.messaging.pubsub.subscribe(`${this.subjectPrefix}.>`, (m) => this.bridgeIn(m));
86
+ return;
87
+ }
78
88
  this.nc = await (0, nats_1.connect)({
79
89
  servers: this.url,
80
90
  token: this.token,
@@ -102,15 +112,36 @@ class NatsEventAdapter {
102
112
  })();
103
113
  }
104
114
  }
115
+ /** An event from another container, handed to the local callback adapter. */
116
+ bridgeIn(m) {
117
+ try {
118
+ const event = JSON.parse(m.payload);
119
+ if (event._originId === this.originId)
120
+ return;
121
+ this.callbackAdapter?.publish(event);
122
+ }
123
+ catch {
124
+ // Malformed message, skip
125
+ }
126
+ }
105
127
  async publish(event) {
106
- if (!this.nc)
107
- return;
108
128
  const subject = `${this.subjectPrefix}.${event.type}`;
109
129
  const enriched = { ...event, _originId: this.originId };
130
+ if (this.messaging) {
131
+ if (this.messaging.connected)
132
+ await this.messaging.pubsub.publish(subject, JSON.stringify(enriched));
133
+ return;
134
+ }
135
+ if (!this.nc)
136
+ return;
110
137
  this.nc.publish(subject, sc.encode(JSON.stringify(enriched)));
111
138
  logger_1.loggerRegistry.info(`[lt-events:nats] published: ${subject} (origin=${this.originId.slice(0, 8)})`);
112
139
  }
113
140
  async disconnect() {
141
+ if (this.bridge) {
142
+ await this.bridge.close();
143
+ this.bridge = null;
144
+ }
114
145
  if (this.sub) {
115
146
  this.sub.unsubscribe();
116
147
  this.sub = null;
@@ -1,4 +1,5 @@
1
1
  import type { LTMilestone } from '../../types';
2
+ import type { WireEvent } from '../../types/machines-view';
2
3
  /**
3
4
  * Publish a milestone event. Called from handleCompletion (workflow
4
5
  * interceptor), ltCompleteTask (orchestrator activity), and the
@@ -124,3 +125,35 @@ export declare function publishWorkflowEvent(params: {
124
125
  status: string;
125
126
  data?: Record<string, any>;
126
127
  }): Promise<void>;
128
+ /** The subject family of every message a line's gateway reads or sends. */
129
+ export declare const MACHINE_WIRE_TYPE = "machine.wire";
130
+ /** The subject family of the gateway log. */
131
+ export declare const MACHINE_LOG_TYPE = "machine.log";
132
+ /** The machine token of a wire event from an address no station claims. */
133
+ export declare const MACHINE_UNKNOWN_TOKEN = "unknown";
134
+ /**
135
+ * Publish one wire record from a line's gateway.
136
+ * Subject: machine.wire.{site}.{line}.{machineId|unknown}.{in|out}
137
+ */
138
+ export declare function publishMachineWireEvent(event: WireEvent): Promise<void>;
139
+ /** The log event as one subject token: `machine_gateway.dispatch.accepted` becomes `dispatch-accepted`. */
140
+ export declare function machineLogToken(event: string): string;
141
+ /**
142
+ * Publish one gateway log entry.
143
+ * Subject: machine.log.{site}.{line}.{event}
144
+ */
145
+ export declare function publishMachineLogEvent(params: {
146
+ siteId: string;
147
+ lineId: string;
148
+ level: 'info' | 'warn' | 'error';
149
+ event: string;
150
+ context?: Record<string, unknown>;
151
+ }): Promise<void>;
152
+ /** A line declared or retired in the registry; every replica reads the row again and follows. */
153
+ export declare function publishMachineLineEvent(params: {
154
+ siteId: string;
155
+ lineId: string;
156
+ source: 'code' | 'api';
157
+ version: number;
158
+ action: 'declared' | 'retired';
159
+ }): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ANNOUNCEMENT_TOPIC = void 0;
3
+ exports.MACHINE_UNKNOWN_TOKEN = exports.MACHINE_LOG_TYPE = exports.MACHINE_WIRE_TYPE = exports.ANNOUNCEMENT_TOPIC = void 0;
4
4
  exports.publishMilestoneEvent = publishMilestoneEvent;
5
5
  exports.publishTaskEvent = publishTaskEvent;
6
6
  exports.publishEscalationEvent = publishEscalationEvent;
@@ -10,6 +10,10 @@ exports.publishKnowledgeEvent = publishKnowledgeEvent;
10
10
  exports.publishFileEvent = publishFileEvent;
11
11
  exports.publishAgentEvent = publishAgentEvent;
12
12
  exports.publishWorkflowEvent = publishWorkflowEvent;
13
+ exports.publishMachineWireEvent = publishMachineWireEvent;
14
+ exports.machineLogToken = machineLogToken;
15
+ exports.publishMachineLogEvent = publishMachineLogEvent;
16
+ exports.publishMachineLineEvent = publishMachineLineEvent;
13
17
  const index_1 = require("./index");
14
18
  const matching_1 = require("./matching");
15
19
  const logger_1 = require("../logger");
@@ -202,3 +206,50 @@ function publishWorkflowEvent(params) {
202
206
  timestamp: new Date().toISOString(),
203
207
  });
204
208
  }
209
+ /** The subject family of every message a line's gateway reads or sends. */
210
+ exports.MACHINE_WIRE_TYPE = 'machine.wire';
211
+ /** The subject family of the gateway log. */
212
+ exports.MACHINE_LOG_TYPE = 'machine.log';
213
+ /** The machine token of a wire event from an address no station claims. */
214
+ exports.MACHINE_UNKNOWN_TOKEN = 'unknown';
215
+ const MACHINE_SOURCE = 'machine-gateway';
216
+ /**
217
+ * Publish one wire record from a line's gateway.
218
+ * Subject: machine.wire.{site}.{line}.{machineId|unknown}.{in|out}
219
+ */
220
+ function publishMachineWireEvent(event) {
221
+ const machine = event.machineId ? (0, matching_1.sanitizeSubjectToken)(event.machineId) : exports.MACHINE_UNKNOWN_TOKEN;
222
+ return fireAndForget({
223
+ type: `${exports.MACHINE_WIRE_TYPE}.${(0, matching_1.sanitizeSubjectToken)(event.siteId)}.${(0, matching_1.sanitizeSubjectToken)(event.lineId)}.${machine}.${event.direction}`,
224
+ source: MACHINE_SOURCE,
225
+ data: event,
226
+ timestamp: event.at,
227
+ });
228
+ }
229
+ const GATEWAY_LOG_PREFIX = 'machine_gateway.';
230
+ /** The log event as one subject token: `machine_gateway.dispatch.accepted` becomes `dispatch-accepted`. */
231
+ function machineLogToken(event) {
232
+ return (0, matching_1.sanitizeSubjectToken)(event.startsWith(GATEWAY_LOG_PREFIX) ? event.slice(GATEWAY_LOG_PREFIX.length) : event);
233
+ }
234
+ /**
235
+ * Publish one gateway log entry.
236
+ * Subject: machine.log.{site}.{line}.{event}
237
+ */
238
+ function publishMachineLogEvent(params) {
239
+ return fireAndForget({
240
+ type: `${exports.MACHINE_LOG_TYPE}.${(0, matching_1.sanitizeSubjectToken)(params.siteId)}.${(0, matching_1.sanitizeSubjectToken)(params.lineId)}.${machineLogToken(params.event)}`,
241
+ source: MACHINE_SOURCE,
242
+ data: { level: params.level, event: params.event, siteId: params.siteId, lineId: params.lineId, ...(params.context ?? {}) },
243
+ timestamp: new Date().toISOString(),
244
+ });
245
+ }
246
+ const MACHINE_LINE_TYPE = 'machine.line';
247
+ /** A line declared or retired in the registry; every replica reads the row again and follows. */
248
+ function publishMachineLineEvent(params) {
249
+ return fireAndForget({
250
+ type: `${MACHINE_LINE_TYPE}.${(0, matching_1.sanitizeSubjectToken)(params.siteId)}.${(0, matching_1.sanitizeSubjectToken)(params.lineId)}.${params.action}`,
251
+ source: MACHINE_SOURCE,
252
+ data: { ...params },
253
+ timestamp: new Date().toISOString(),
254
+ });
255
+ }
@@ -2,4 +2,5 @@ export * from './protocol';
2
2
  export * from './transport';
3
3
  export * from './line';
4
4
  export * from './site/site-conf';
5
+ export * from './site/edge-account';
5
6
  export * from './site/mosquitto-conf';
@@ -18,4 +18,5 @@ __exportStar(require("./protocol"), exports);
18
18
  __exportStar(require("./transport"), exports);
19
19
  __exportStar(require("./line"), exports);
20
20
  __exportStar(require("./site/site-conf"), exports);
21
+ __exportStar(require("./site/edge-account"), exports);
21
22
  __exportStar(require("./site/mosquitto-conf"), exports);
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * The line: site, line and the machines on it, in route order, read from a
3
- * JSON file (MACHINE_LINE_CONFIG) or passed in by the host.
3
+ * JSON file or passed in by the host. MACHINE_LINE_CONFIG names one file, or
4
+ * several separated by commas.
4
5
  */
5
6
  import type { LineDef, MachineDef, MachineIdent, MaterialDef, MeasurementDef } from '../../types/machines';
6
7
  export type { LineDef, MachineDef, MaterialDef, MeasurementDef };
@@ -22,6 +23,8 @@ export type CarrierRole = typeof CARRIER_ROLE[keyof typeof CARRIER_ROLE];
22
23
  export declare function validateLine(line: LineDef): LineDef;
23
24
  /** The line at `path` (JSON), or `fallback` when no path is given. */
24
25
  export declare function loadLine(path: string | undefined, fallback?: LineDef): LineDef;
26
+ /** Every line in `paths`, a comma-separated list of JSON files (MACHINE_LINE_CONFIG); each site and line once. */
27
+ export declare function loadLines(paths: string | undefined, fallback?: LineDef): LineDef[];
25
28
  export declare function identOf(line: LineDef, machineId: string): MachineIdent;
26
29
  export declare function machineById(line: LineDef, machineId: string): MachineDef;
27
30
  /** The broker identity of each machine whose address the line declares, {site}-{line}-{address}. */
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  /**
3
3
  * The line: site, line and the machines on it, in route order, read from a
4
- * JSON file (MACHINE_LINE_CONFIG) or passed in by the host.
4
+ * JSON file or passed in by the host. MACHINE_LINE_CONFIG names one file, or
5
+ * several separated by commas.
5
6
  */
6
7
  Object.defineProperty(exports, "__esModule", { value: true });
7
8
  exports.DEFAULT_OPERATOR_ROLE = exports.DEFAULT_EXIT_ROLE = exports.CARRIER_ROLE = exports.ADDRESSING = void 0;
8
9
  exports.learnsAddress = learnsAddress;
9
10
  exports.validateLine = validateLine;
10
11
  exports.loadLine = loadLine;
12
+ exports.loadLines = loadLines;
11
13
  exports.identOf = identOf;
12
14
  exports.machineById = machineById;
13
15
  exports.clientIds = clientIds;
@@ -68,6 +70,21 @@ function loadLine(path, fallback) {
68
70
  }
69
71
  return validateLine(JSON.parse((0, fs_1.readFileSync)(path, 'utf8')));
70
72
  }
73
+ /** Every line in `paths`, a comma-separated list of JSON files (MACHINE_LINE_CONFIG); each site and line once. */
74
+ function loadLines(paths, fallback) {
75
+ const list = (paths ?? '').split(',').map((p) => p.trim()).filter(Boolean);
76
+ if (!list.length)
77
+ return [loadLine(undefined, fallback)];
78
+ const lines = list.map((p) => loadLine(p));
79
+ const seen = new Set();
80
+ for (const line of lines) {
81
+ const key = `${line.siteId}/${line.lineId}`;
82
+ if (seen.has(key))
83
+ throw new Error(`line ${key} is declared twice in MACHINE_LINE_CONFIG`);
84
+ seen.add(key);
85
+ }
86
+ return lines;
87
+ }
71
88
  function identOf(line, machineId) {
72
89
  const address = line.machines.find((m) => m.machineId === machineId)?.address;
73
90
  return { siteId: line.siteId, lineId: line.lineId, machineId, ...(address ? { address } : {}) };
@@ -16,6 +16,10 @@ export interface MachineCommand {
16
16
  cmdId: string;
17
17
  op: string;
18
18
  args: Record<string, unknown>;
19
+ /** How many times this gateway has sent this cmdId, this time included. */
20
+ attempt?: number;
21
+ /** The command may have reached the machine before: sent earlier, or its row predates this gateway's takeover. */
22
+ retry?: boolean;
19
23
  }
20
24
  /** MQTT filters under each machine's topic, e.g. `job` or `alarm/+`. */
21
25
  export interface CodecChannels {
@@ -55,6 +59,24 @@ export interface LineCodec {
55
59
  * to a person. Otherwise (the default) known fields are acted on and the violations are logged.
56
60
  */
57
61
  readonly strict?: boolean;
62
+ /**
63
+ * The machines keep no retained state and report only what changes: the gateway asks each one for
64
+ * a snapshot when it takes the line, so it knows every machine's job before acting on a change.
65
+ */
66
+ readonly snapshotOnStart?: boolean;
67
+ /**
68
+ * Active alarms stay retained on the broker until they clear, as in the line protocol. A takeover's
69
+ * retained read is then every active alarm, and an alarm row whose alarm is missing from it cleared
70
+ * while no gateway listened. Otherwise a machine's snapshot lists its active alarms, and an alarm it
71
+ * no longer lists has cleared.
72
+ */
73
+ readonly retainedAlarms?: boolean;
74
+ /**
75
+ * Commands of the machines' own, beyond the line protocol's control ops, that a machine-command row
76
+ * may ask for. Each is sent through `encode` and the row resolves with the reply. Every entry is a
77
+ * non-empty string; the gateway refuses a codec whose entries are not.
78
+ */
79
+ readonly rowOps?: readonly string[];
58
80
  /** One wire message as zero or more line-protocol messages; empty when the topic is not a machine's. */
59
81
  decode(topic: string, payload: string, retained?: boolean): Inspection[];
60
82
  /** The command as wire messages; none when the machines have no such command, and the gateway then sends nothing. */
@@ -65,6 +87,8 @@ export interface LineCodec {
65
87
  */
66
88
  receipt?(ident: MachineIdent, messageIds: string[]): WireMessage[];
67
89
  }
90
+ /** The codec's own row ops, each a non-empty string; anything else is a misconfigured codec and throws. */
91
+ export declare function declaredRowOps(codec: Pick<LineCodec, 'rowOps'>): readonly string[];
68
92
  export declare const DISPATCH_ON: {
69
93
  readonly CREATED: "created";
70
94
  readonly ARRIVAL: "arrival";