@hotmeshio/long-tail 0.27.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 (339) 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.js +9 -4
  5. package/build/lib/db/config-lock.d.ts +10 -0
  6. package/build/lib/db/config-lock.js +28 -0
  7. package/build/lib/db/schemas/041_machine_lines.sql +26 -0
  8. package/build/lib/events/browser-view.js +8 -2
  9. package/build/lib/events/publish.d.ts +33 -0
  10. package/build/lib/events/publish.js +52 -1
  11. package/build/lib/machines/line.d.ts +4 -1
  12. package/build/lib/machines/line.js +18 -1
  13. package/build/lib/machines/protocol/codec.d.ts +8 -0
  14. package/build/lib/machines/protocol/codec.js +9 -0
  15. package/build/lib/machines/protocol/constants.d.ts +1 -1
  16. package/build/lib/machines/protocol/constants.js +1 -1
  17. package/build/lib/machines/protocol/contract.js +2 -2
  18. package/build/lib/machines/site/mosquitto-conf.d.ts +5 -4
  19. package/build/lib/machines/site/mosquitto-conf.js +31 -16
  20. package/build/lib/machines/site/site-conf.d.ts +9 -2
  21. package/build/lib/machines/site/site-conf.js +27 -8
  22. package/build/lib/machines/transport/callback-feed.d.ts +1 -0
  23. package/build/lib/machines/transport/callback-feed.js +4 -1
  24. package/build/lib/machines/transport/memory.d.ts +2 -0
  25. package/build/lib/machines/transport/memory.js +6 -0
  26. package/build/lib/machines/transport/mqtt-bus.d.ts +2 -0
  27. package/build/lib/machines/transport/mqtt-bus.js +4 -0
  28. package/build/lib/machines/transport/nats-bus.d.ts +1 -0
  29. package/build/lib/machines/transport/nats-bus.js +3 -0
  30. package/build/lib/machines/transport/nats-feed.d.ts +1 -0
  31. package/build/lib/machines/transport/nats-feed.js +4 -1
  32. package/build/lib/machines/transport/pubsub-feed.d.ts +1 -0
  33. package/build/lib/machines/transport/pubsub-feed.js +4 -1
  34. package/build/lib/machines/transport/stream-bus.d.ts +2 -0
  35. package/build/lib/machines/transport/stream-bus.js +5 -1
  36. package/build/modules/machines.d.ts +8 -0
  37. package/build/modules/machines.js +16 -0
  38. package/build/routes/index.js +2 -0
  39. package/build/routes/machines.d.ts +2 -0
  40. package/build/routes/machines.js +220 -0
  41. package/build/services/machines/commands.d.ts +5 -5
  42. package/build/services/machines/commands.js +3 -2
  43. package/build/services/machines/config.d.ts +2 -1
  44. package/build/services/machines/config.js +1 -1
  45. package/build/services/machines/contracts.d.ts +10 -0
  46. package/build/services/machines/gateway/actions.d.ts +1 -0
  47. package/build/services/machines/gateway/admission.d.ts +15 -3
  48. package/build/services/machines/gateway/admission.js +29 -14
  49. package/build/services/machines/gateway/dispatcher.d.ts +3 -0
  50. package/build/services/machines/gateway/dispatcher.js +12 -4
  51. package/build/services/machines/gateway/executor.d.ts +11 -2
  52. package/build/services/machines/gateway/executor.js +68 -29
  53. package/build/services/machines/gateway/gateway.d.ts +16 -1
  54. package/build/services/machines/gateway/gateway.js +55 -23
  55. package/build/services/machines/gateway/index.d.ts +3 -0
  56. package/build/services/machines/gateway/index.js +3 -0
  57. package/build/services/machines/gateway/inspect.d.ts +17 -0
  58. package/build/services/machines/gateway/inspect.js +68 -0
  59. package/build/services/machines/gateway/log.d.ts +8 -0
  60. package/build/services/machines/gateway/log.js +18 -0
  61. package/build/services/machines/gateway/pacing.js +1 -0
  62. package/build/services/machines/gateway/plan-escalation.js +8 -3
  63. package/build/services/machines/gateway/plan-machine.js +16 -6
  64. package/build/services/machines/gateway/project.d.ts +9 -0
  65. package/build/services/machines/gateway/project.js +55 -0
  66. package/build/services/machines/gateway/receipts.d.ts +3 -0
  67. package/build/services/machines/gateway/receipts.js +3 -1
  68. package/build/services/machines/gateway/reconcile.js +3 -3
  69. package/build/services/machines/gateway/registration.js +1 -1
  70. package/build/services/machines/gateway/reply-waiter.d.ts +6 -3
  71. package/build/services/machines/gateway/reply-waiter.js +37 -16
  72. package/build/services/machines/gateway/state.d.ts +29 -3
  73. package/build/services/machines/gateway/state.js +61 -7
  74. package/build/services/machines/gateway/wire.d.ts +58 -0
  75. package/build/services/machines/gateway/wire.js +171 -0
  76. package/build/services/machines/index.d.ts +3 -0
  77. package/build/services/machines/index.js +2 -0
  78. package/build/services/machines/line-index.d.ts +16 -0
  79. package/build/services/machines/line-index.js +39 -0
  80. package/build/services/machines/registry-sql.d.ts +31 -0
  81. package/build/services/machines/registry-sql.js +110 -0
  82. package/build/services/machines/registry-sync.d.ts +31 -0
  83. package/build/services/machines/registry-sync.js +81 -0
  84. package/build/services/machines/registry.d.ts +77 -0
  85. package/build/services/machines/registry.js +158 -0
  86. package/build/services/machines/rows.js +10 -1
  87. package/build/services/machines/surface.d.ts +45 -5
  88. package/build/services/machines/surface.js +95 -15
  89. package/build/start/apply-report.d.ts +1 -1
  90. package/build/start/apply-report.js +3 -25
  91. package/build/start/index.js +16 -4
  92. package/build/system/index.js +13 -0
  93. package/build/system/mcp-servers/admin/schemas.d.ts +22 -22
  94. package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -7
  95. package/build/system/mcp-servers/machines-schemas.d.ts +35 -0
  96. package/build/system/mcp-servers/machines-schemas.js +35 -0
  97. package/build/system/mcp-servers/machines.d.ts +20 -0
  98. package/build/system/mcp-servers/machines.js +154 -0
  99. package/build/system/seed/tool-manifests-machines.d.ts +2 -0
  100. package/build/system/seed/tool-manifests-machines.js +88 -0
  101. package/build/tsconfig.tsbuildinfo +1 -1
  102. package/build/types/events.d.ts +6 -1
  103. package/build/types/index.d.ts +1 -0
  104. package/build/types/machines-view.d.ts +159 -0
  105. package/build/types/machines-view.js +7 -0
  106. package/build/types/machines.d.ts +4 -0
  107. package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js → AdminDashboard-Bm7VG65H.js} +2 -2
  108. package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js.map → AdminDashboard-Bm7VG65H.js.map} +1 -1
  109. package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js → AgentConfigPage-aJF7Sdbc.js} +6 -6
  110. package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js.map → AgentConfigPage-aJF7Sdbc.js.map} +1 -1
  111. package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js → AgentDetailPage-GwwghhxT.js} +3 -3
  112. package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js.map → AgentDetailPage-GwwghhxT.js.map} +1 -1
  113. package/dashboard/dist/assets/AgentsPage-DVvCzZyg.js +2 -0
  114. package/dashboard/dist/assets/{AgentsPage-C9UuUKhr.js.map → AgentsPage-DVvCzZyg.js.map} +1 -1
  115. package/dashboard/dist/assets/AvailableEscalationsPage-Cxmcji_K.js +2 -0
  116. package/dashboard/dist/assets/{AvailableEscalationsPage-DrvfXz70.js.map → AvailableEscalationsPage-Cxmcji_K.js.map} +1 -1
  117. package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js → BotPicker-CofRxk4L.js} +2 -2
  118. package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js.map → BotPicker-CofRxk4L.js.map} +1 -1
  119. package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js → BulkAssignModal-BARWuz4L.js} +2 -2
  120. package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js.map → BulkAssignModal-BARWuz4L.js.map} +1 -1
  121. package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js → CapabilitiesPage-BJAWVNEx.js} +2 -2
  122. package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js.map → CapabilitiesPage-BJAWVNEx.js.map} +1 -1
  123. package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js → CollapsibleSection-CtgoaG75.js} +2 -2
  124. package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js.map → CollapsibleSection-CtgoaG75.js.map} +1 -1
  125. package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js → ConfirmDeleteModal-BYXXBWs6.js} +2 -2
  126. package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js.map → ConfirmDeleteModal-BYXXBWs6.js.map} +1 -1
  127. package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js → ConnectedAppsPage-D0JkzWa7.js} +2 -2
  128. package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js.map → ConnectedAppsPage-D0JkzWa7.js.map} +1 -1
  129. package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js → CountdownTimer-BcFxdZYN.js} +2 -2
  130. package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js.map → CountdownTimer-BcFxdZYN.js.map} +1 -1
  131. package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js → CredentialsPage-DPSY20rV.js} +2 -2
  132. package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js.map → CredentialsPage-DPSY20rV.js.map} +1 -1
  133. package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js → CronLabel-Dg_Oew_Y.js} +2 -2
  134. package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js.map → CronLabel-Dg_Oew_Y.js.map} +1 -1
  135. package/dashboard/dist/assets/{DropZone-u1JGfR9G.js → DropZone-Cl_Flb16.js} +2 -2
  136. package/dashboard/dist/assets/{DropZone-u1JGfR9G.js.map → DropZone-Cl_Flb16.js.map} +1 -1
  137. package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js → ElapsedCell-Dm3G5fK2.js} +2 -2
  138. package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js.map → ElapsedCell-Dm3G5fK2.js.map} +1 -1
  139. package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js → EntityTimelinePanel-CrEEP04e.js} +2 -2
  140. package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js.map → EntityTimelinePanel-CrEEP04e.js.map} +1 -1
  141. package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js → EscalationListSchemaPage-wOInXcjs.js} +3 -3
  142. package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js.map → EscalationListSchemaPage-wOInXcjs.js.map} +1 -1
  143. package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js → EscalationSchemaPage-CrIj_g9d.js} +3 -3
  144. package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js.map → EscalationSchemaPage-CrIj_g9d.js.map} +1 -1
  145. package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js → EscalationTimeline-CeAsl5IT.js} +2 -2
  146. package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js.map → EscalationTimeline-CeAsl5IT.js.map} +1 -1
  147. package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js → EscalationTitleSelect-D8qpCYiy.js} +2 -2
  148. package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js.map → EscalationTitleSelect-D8qpCYiy.js.map} +1 -1
  149. package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js → EscalationsOverview-CvaqVPsr.js} +2 -2
  150. package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js.map → EscalationsOverview-CvaqVPsr.js.map} +1 -1
  151. package/dashboard/dist/assets/{EventTable-V4RF_n58.js → EventTable-Be0JuEl6.js} +2 -2
  152. package/dashboard/dist/assets/{EventTable-V4RF_n58.js.map → EventTable-Be0JuEl6.js.map} +1 -1
  153. package/dashboard/dist/assets/FilterBar-BVyAjIgv.js +2 -0
  154. package/dashboard/dist/assets/FilterBar-BVyAjIgv.js.map +1 -0
  155. package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js → GraphInvokePage-D_QigJeD.js} +2 -2
  156. package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js.map → GraphInvokePage-D_QigJeD.js.map} +1 -1
  157. package/dashboard/dist/assets/{HomePage-EjcNxlKx.js → HomePage-C1haeuNy.js} +2 -2
  158. package/dashboard/dist/assets/{HomePage-EjcNxlKx.js.map → HomePage-C1haeuNy.js.map} +1 -1
  159. package/dashboard/dist/assets/LinePage-CWD5pv1g.js +5 -0
  160. package/dashboard/dist/assets/LinePage-CWD5pv1g.js.map +1 -0
  161. package/dashboard/dist/assets/LinesPage-NqChsKcO.js +3 -0
  162. package/dashboard/dist/assets/LinesPage-NqChsKcO.js.map +1 -0
  163. package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js → ListToolbar-BZCNrTh6.js} +2 -2
  164. package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js.map → ListToolbar-BZCNrTh6.js.map} +1 -1
  165. package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js → McpOverview-yJTYnh1z.js} +2 -2
  166. package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js.map → McpOverview-yJTYnh1z.js.map} +1 -1
  167. package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js → McpQueryDetailPage-ChuLpJ4u.js} +3 -3
  168. package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js.map → McpQueryDetailPage-ChuLpJ4u.js.map} +1 -1
  169. package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js → McpQueryPage-9S-v9soF.js} +2 -2
  170. package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js.map → McpQueryPage-9S-v9soF.js.map} +1 -1
  171. package/dashboard/dist/assets/McpRunDetailPage-BhrcfxD5.js +2 -0
  172. package/dashboard/dist/assets/{McpRunDetailPage-80fQn9iX.js.map → McpRunDetailPage-BhrcfxD5.js.map} +1 -1
  173. package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js → McpRunsPage-C5_i8_Zx.js} +2 -2
  174. package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js.map → McpRunsPage-C5_i8_Zx.js.map} +1 -1
  175. package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js → NamespacePill-OTZD2hzt.js} +2 -2
  176. package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js.map → NamespacePill-OTZD2hzt.js.map} +1 -1
  177. package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js → OperationsPage-C03CeU5P.js} +2 -2
  178. package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js.map → OperationsPage-C03CeU5P.js.map} +1 -1
  179. package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js → OperatorDashboard-BzC134Jt.js} +2 -2
  180. package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js.map → OperatorDashboard-BzC134Jt.js.map} +1 -1
  181. package/dashboard/dist/assets/{PageHeader-BSWIspNB.js → PageHeader-Hx8APPwE.js} +2 -2
  182. package/dashboard/dist/assets/{PageHeader-BSWIspNB.js.map → PageHeader-Hx8APPwE.js.map} +1 -1
  183. package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js → PageHeaderWithStats-BEQYYBJv.js} +2 -2
  184. package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js.map → PageHeaderWithStats-BEQYYBJv.js.map} +1 -1
  185. package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js → PersonaDetailPage-D0mY9L6j.js} +2 -2
  186. package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js.map → PersonaDetailPage-D0mY9L6j.js.map} +1 -1
  187. package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js → PersonasPage-FFlm5Eug.js} +2 -2
  188. package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js.map → PersonasPage-FFlm5Eug.js.map} +1 -1
  189. package/dashboard/dist/assets/{PortalPage-CucNZn_w.js → PortalPage-Cpc25uO-.js} +2 -2
  190. package/dashboard/dist/assets/{PortalPage-CucNZn_w.js.map → PortalPage-Cpc25uO-.js.map} +1 -1
  191. package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js → ProcessDetailPage-Di2J7KwY.js} +2 -2
  192. package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js.map → ProcessDetailPage-Di2J7KwY.js.map} +1 -1
  193. package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js → ProcessesListPage-BEXwU3Z0.js} +2 -2
  194. package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js.map → ProcessesListPage-BEXwU3Z0.js.map} +1 -1
  195. package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js → ResolverForm-2ks-3jXC.js} +6 -6
  196. package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js.map → ResolverForm-2ks-3jXC.js.map} +1 -1
  197. package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js → RoleDetailPage-DqoOk0xc.js} +3 -3
  198. package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js.map → RoleDetailPage-DqoOk0xc.js.map} +1 -1
  199. package/dashboard/dist/assets/{RolePill-CoETDpjF.js → RolePill-R5_ctGFy.js} +2 -2
  200. package/dashboard/dist/assets/{RolePill-CoETDpjF.js.map → RolePill-R5_ctGFy.js.map} +1 -1
  201. package/dashboard/dist/assets/{RolesPage-DBKxeam4.js → RolesPage-CPmo8Srr.js} +2 -2
  202. package/dashboard/dist/assets/{RolesPage-DBKxeam4.js.map → RolesPage-CPmo8Srr.js.map} +1 -1
  203. package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js → RosterWidget-D2yovCKw.js} +2 -2
  204. package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js.map → RosterWidget-D2yovCKw.js.map} +1 -1
  205. package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js → RunAsSelector-CMv96On6.js} +2 -2
  206. package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js.map → RunAsSelector-CMv96On6.js.map} +1 -1
  207. package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js → ScanCodesPage-CA6cTT-M.js} +2 -2
  208. package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js.map → ScanCodesPage-CA6cTT-M.js.map} +1 -1
  209. package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js → ScanSchemeDetailPage-DnctN5-H.js} +2 -2
  210. package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js.map → ScanSchemeDetailPage-DnctN5-H.js.map} +1 -1
  211. package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js → ScanStationPage-Bk8RwkKL.js} +2 -2
  212. package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js.map → ScanStationPage-Bk8RwkKL.js.map} +1 -1
  213. package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js → ScopeBadge-BXZ084nD.js} +2 -2
  214. package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js.map → ScopeBadge-BXZ084nD.js.map} +1 -1
  215. package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js → StickyPagination-B0FSuUgs.js} +2 -2
  216. package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js.map → StickyPagination-B0FSuUgs.js.map} +1 -1
  217. package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js → StreamMessageDetail-BwZEvMpP.js} +2 -2
  218. package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js.map → StreamMessageDetail-BwZEvMpP.js.map} +1 -1
  219. package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js → SwimlaneTimeline-BDVQEaMw.js} +2 -2
  220. package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js.map → SwimlaneTimeline-BDVQEaMw.js.map} +1 -1
  221. package/dashboard/dist/assets/{TagInput-S7UuVT_M.js → TagInput-DjPUDp2M.js} +2 -2
  222. package/dashboard/dist/assets/{TagInput-S7UuVT_M.js.map → TagInput-DjPUDp2M.js.map} +1 -1
  223. package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js → TaskDetailPage-BOlv3iGB.js} +2 -2
  224. package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js.map → TaskDetailPage-BOlv3iGB.js.map} +1 -1
  225. package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js → TaskQueuePill-D-4Ynf3K.js} +2 -2
  226. package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js.map → TaskQueuePill-D-4Ynf3K.js.map} +1 -1
  227. package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js → TasksListPage-e2teY0bD.js} +2 -2
  228. package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js.map → TasksListPage-e2teY0bD.js.map} +1 -1
  229. package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js → TimeAgo-Cvkpf_b3.js} +2 -2
  230. package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js.map → TimeAgo-Cvkpf_b3.js.map} +1 -1
  231. package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js → TimestampCell-B3btAV0N.js} +2 -2
  232. package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js.map → TimestampCell-B3btAV0N.js.map} +1 -1
  233. package/dashboard/dist/assets/{ToolPill-D40uLM_v.js → ToolPill-GsKQ80CO.js} +2 -2
  234. package/dashboard/dist/assets/{ToolPill-D40uLM_v.js.map → ToolPill-GsKQ80CO.js.map} +1 -1
  235. package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js → ToolTestPanel-B03nebR7.js} +2 -2
  236. package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js.map → ToolTestPanel-B03nebR7.js.map} +1 -1
  237. package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js → TopicDetailPage-DBRWne3O.js} +3 -3
  238. package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js.map → TopicDetailPage-DBRWne3O.js.map} +1 -1
  239. package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js → TopicsPage-CVe2M9HD.js} +2 -2
  240. package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js.map → TopicsPage-CVe2M9HD.js.map} +1 -1
  241. package/dashboard/dist/assets/{UserName-DQFjuoib.js → UserName-B_q_qp6V.js} +2 -2
  242. package/dashboard/dist/assets/{UserName-DQFjuoib.js.map → UserName-B_q_qp6V.js.map} +1 -1
  243. package/dashboard/dist/assets/WorkflowExecutionPage-Bh_dr9tM.js +2 -0
  244. package/dashboard/dist/assets/{WorkflowExecutionPage-Di08wCbs.js.map → WorkflowExecutionPage-Bh_dr9tM.js.map} +1 -1
  245. package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js → WorkflowPill-D7244fKp.js} +2 -2
  246. package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js.map → WorkflowPill-D7244fKp.js.map} +1 -1
  247. package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js → WorkflowsDashboard-DA6Mj7qH.js} +2 -2
  248. package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js.map → WorkflowsDashboard-DA6Mj7qH.js.map} +1 -1
  249. package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js → WorkflowsOverview-B1kBLj-a.js} +2 -2
  250. package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js.map → WorkflowsOverview-B1kBLj-a.js.map} +1 -1
  251. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js → YamlWorkflowDetailPage-6GJM8QIX.js} +8 -8
  252. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js.map → YamlWorkflowDetailPage-6GJM8QIX.js.map} +1 -1
  253. package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js → YamlWorkflowsPage-Bu811C7f.js} +2 -2
  254. package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js.map → YamlWorkflowsPage-Bu811C7f.js.map} +1 -1
  255. package/dashboard/dist/assets/{agents-PuftRTB2.js → agents-MPk_GnYz.js} +2 -2
  256. package/dashboard/dist/assets/{agents-PuftRTB2.js.map → agents-MPk_GnYz.js.map} +1 -1
  257. package/dashboard/dist/assets/{bots-BmEiPAWY.js → bots-2RihE2Tc.js} +2 -2
  258. package/dashboard/dist/assets/{bots-BmEiPAWY.js.map → bots-2RihE2Tc.js.map} +1 -1
  259. package/dashboard/dist/assets/{capabilities-CRii4Soa.js → capabilities-CC4iwJ1P.js} +2 -2
  260. package/dashboard/dist/assets/{capabilities-CRii4Soa.js.map → capabilities-CC4iwJ1P.js.map} +1 -1
  261. package/dashboard/dist/assets/{controlplane-DO_czaYo.js → controlplane-Bmkic8BH.js} +2 -2
  262. package/dashboard/dist/assets/{controlplane-DO_czaYo.js.map → controlplane-Bmkic8BH.js.map} +1 -1
  263. package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js → escalation-columns-B0lhUUrQ.js} +2 -2
  264. package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js.map → escalation-columns-B0lhUUrQ.js.map} +1 -1
  265. package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js → escalation-items-7WFpPo46.js} +2 -2
  266. package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js.map → escalation-items-7WFpPo46.js.map} +1 -1
  267. package/dashboard/dist/assets/index-B9uv-euR.css +1 -0
  268. package/dashboard/dist/assets/{index-DhSCCpqM.js → index-B_XV1rwu.js} +2 -2
  269. package/dashboard/dist/assets/{index-DhSCCpqM.js.map → index-B_XV1rwu.js.map} +1 -1
  270. package/dashboard/dist/assets/{index-Cx8xb-oU.js → index-C2CLfGwL.js} +2 -2
  271. package/dashboard/dist/assets/{index-Cx8xb-oU.js.map → index-C2CLfGwL.js.map} +1 -1
  272. package/dashboard/dist/assets/{index-Cga5IW3D.js → index-C3AeFihz.js} +2 -2
  273. package/dashboard/dist/assets/{index-Cga5IW3D.js.map → index-C3AeFihz.js.map} +1 -1
  274. package/dashboard/dist/assets/{index-DiaRlFYI.js → index-CBri8fYM.js} +2 -2
  275. package/dashboard/dist/assets/{index-DiaRlFYI.js.map → index-CBri8fYM.js.map} +1 -1
  276. package/dashboard/dist/assets/{index-CL_1VpGb.js → index-CRWsB7ZC.js} +2 -2
  277. package/dashboard/dist/assets/{index-CL_1VpGb.js.map → index-CRWsB7ZC.js.map} +1 -1
  278. package/dashboard/dist/assets/{index-XntldBd0.js → index-CTOv3G7a.js} +2 -2
  279. package/dashboard/dist/assets/{index-XntldBd0.js.map → index-CTOv3G7a.js.map} +1 -1
  280. package/dashboard/dist/assets/{index-CfP2nKRc.js → index-CcArGkzI.js} +3 -3
  281. package/dashboard/dist/assets/{index-CfP2nKRc.js.map → index-CcArGkzI.js.map} +1 -1
  282. package/dashboard/dist/assets/{index-Dz6R8-Dw.js → index-CkMHS-hG.js} +25 -25
  283. package/dashboard/dist/assets/index-CkMHS-hG.js.map +1 -0
  284. package/dashboard/dist/assets/index-CmsmwCyv.js +2 -0
  285. package/dashboard/dist/assets/{index-4YaDUcKd.js.map → index-CmsmwCyv.js.map} +1 -1
  286. package/dashboard/dist/assets/{index-2SM2_onB.js → index-CvJsvqIc.js} +2 -2
  287. package/dashboard/dist/assets/{index-2SM2_onB.js.map → index-CvJsvqIc.js.map} +1 -1
  288. package/dashboard/dist/assets/{index-Rwqrflm-.js → index-D-ilRyfy.js} +2 -2
  289. package/dashboard/dist/assets/{index-Rwqrflm-.js.map → index-D-ilRyfy.js.map} +1 -1
  290. package/dashboard/dist/assets/{index-CZ7A3AcD.js → index-DSUtfDXx.js} +2 -2
  291. package/dashboard/dist/assets/{index-CZ7A3AcD.js.map → index-DSUtfDXx.js.map} +1 -1
  292. package/dashboard/dist/assets/{index-jL2K6us4.js → index-Da6ycKyf.js} +2 -2
  293. package/dashboard/dist/assets/{index-jL2K6us4.js.map → index-Da6ycKyf.js.map} +1 -1
  294. package/dashboard/dist/assets/{knowledge-CeUqGPuo.js → knowledge-Bpbg20DC.js} +2 -2
  295. package/dashboard/dist/assets/{knowledge-CeUqGPuo.js.map → knowledge-Bpbg20DC.js.map} +1 -1
  296. package/dashboard/dist/assets/machines-BqOZZU-3.js +2 -0
  297. package/dashboard/dist/assets/machines-BqOZZU-3.js.map +1 -0
  298. package/dashboard/dist/assets/{mcp-Cx96NTeD.js → mcp-CmcUXYce.js} +2 -2
  299. package/dashboard/dist/assets/{mcp-Cx96NTeD.js.map → mcp-CmcUXYce.js.map} +1 -1
  300. package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js → mcp-query-C8buQxN9.js} +2 -2
  301. package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js.map → mcp-query-C8buQxN9.js.map} +1 -1
  302. package/dashboard/dist/assets/{personas--4kjwyOw.js → personas-C2n5oDmY.js} +2 -2
  303. package/dashboard/dist/assets/{personas--4kjwyOw.js.map → personas-C2n5oDmY.js.map} +1 -1
  304. package/dashboard/dist/assets/{pipelines-PgkwvG7f.js → pipelines-RKpSkFz7.js} +2 -2
  305. package/dashboard/dist/assets/{pipelines-PgkwvG7f.js.map → pipelines-RKpSkFz7.js.map} +1 -1
  306. package/dashboard/dist/assets/{tasks-CcYxdBa3.js → tasks-Dab4hExW.js} +2 -2
  307. package/dashboard/dist/assets/{tasks-CcYxdBa3.js.map → tasks-Dab4hExW.js.map} +1 -1
  308. package/dashboard/dist/assets/{topics-_lik7cNY.js → topics-FTMNP7r3.js} +2 -2
  309. package/dashboard/dist/assets/{topics-_lik7cNY.js.map → topics-FTMNP7r3.js.map} +1 -1
  310. package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js → useDebouncedValue-B_1u1YIk.js} +2 -2
  311. package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js.map → useDebouncedValue-B_1u1YIk.js.map} +1 -1
  312. package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js → useNamespace-HUeAI7Qb.js} +2 -2
  313. package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js.map → useNamespace-HUeAI7Qb.js.map} +1 -1
  314. package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js → useYamlActivityEvents-Cax54qHH.js} +2 -2
  315. package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js.map → useYamlActivityEvents-Cax54qHH.js.map} +1 -1
  316. package/dashboard/dist/assets/{validate-FlXCBBT6.js → validate-DxOaV7QS.js} +2 -2
  317. package/dashboard/dist/assets/{validate-FlXCBBT6.js.map → validate-DxOaV7QS.js.map} +1 -1
  318. package/dashboard/dist/assets/{vendor-icons-DUYcKTjP.js → vendor-icons-fxBvvHBi.js} +187 -182
  319. package/dashboard/dist/assets/vendor-icons-fxBvvHBi.js.map +1 -0
  320. package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js → yaml-workflows-BgY1XHJx.js} +2 -2
  321. package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js.map → yaml-workflows-BgY1XHJx.js.map} +1 -1
  322. package/dashboard/dist/index.html +3 -3
  323. package/docs/architecture.md +1 -0
  324. package/docs/code-owned-configuration.md +6 -0
  325. package/docs/dashboard.md +1 -0
  326. package/docs/events.md +34 -1
  327. package/docs/machines.md +93 -16
  328. package/docs/mcp.md +19 -0
  329. package/package.json +1 -1
  330. package/dashboard/dist/assets/AgentsPage-C9UuUKhr.js +0 -2
  331. package/dashboard/dist/assets/AvailableEscalationsPage-DrvfXz70.js +0 -2
  332. package/dashboard/dist/assets/FilterBar-BygWrnB1.js +0 -2
  333. package/dashboard/dist/assets/FilterBar-BygWrnB1.js.map +0 -1
  334. package/dashboard/dist/assets/McpRunDetailPage-80fQn9iX.js +0 -2
  335. package/dashboard/dist/assets/WorkflowExecutionPage-Di08wCbs.js +0 -2
  336. package/dashboard/dist/assets/index-4YaDUcKd.js +0 -2
  337. package/dashboard/dist/assets/index-CnU7Jjz3.css +0 -1
  338. package/dashboard/dist/assets/index-Dz6R8-Dw.js.map +0 -1
  339. package/dashboard/dist/assets/vendor-icons-DUYcKTjP.js.map +0 -1
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /**
3
+ * The line registry's statements. Every write is one statement: the
4
+ * version advances in the same UPDATE that changes the row, and a version
5
+ * check rides the WHERE so a stale writer gets zero rows back.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.LIST_SITES = exports.LINE_ORDER = exports.HEALTH_ROW_TYPES = exports.LIST_CODE_LINES = exports.LIST_ENABLED_LINES = exports.DELETE_LINE = exports.GET_LINE = exports.APPLY_CODE_LINE = exports.SEED_CODE_LINE = exports.UPSERT_API_LINE = exports.LINE_SOURCE = void 0;
9
+ exports.listLinesSql = listLinesSql;
10
+ const contracts_1 = require("./contracts");
11
+ exports.LINE_SOURCE = { CODE: 'code', API: 'api' };
12
+ const COLUMNS = 'site_id, line_id, definition, source, version, enabled, search_text, created_at, updated_at';
13
+ /** An API write: insert, or replace and advance the version; $5 non-null requires that version. */
14
+ exports.UPSERT_API_LINE = `
15
+ INSERT INTO lt_machine_lines (site_id, line_id, definition, source, search_text)
16
+ VALUES ($1, $2, $3::jsonb, '${exports.LINE_SOURCE.API}', $4)
17
+ ON CONFLICT (site_id, line_id) DO UPDATE
18
+ SET definition = EXCLUDED.definition,
19
+ source = '${exports.LINE_SOURCE.API}',
20
+ search_text = EXCLUDED.search_text,
21
+ enabled = true,
22
+ version = lt_machine_lines.version + 1,
23
+ updated_at = NOW()
24
+ WHERE $5::int IS NULL OR lt_machine_lines.version = $5::int
25
+ RETURNING ${COLUMNS}`;
26
+ /** A db-owned code line: first writer wins, an existing row is left as it is. */
27
+ exports.SEED_CODE_LINE = `
28
+ INSERT INTO lt_machine_lines (site_id, line_id, definition, source, search_text)
29
+ VALUES ($1, $2, $3::jsonb, '${exports.LINE_SOURCE.CODE}', $4)
30
+ ON CONFLICT (site_id, line_id) DO NOTHING
31
+ RETURNING ${COLUMNS}`;
32
+ /** A code-owned code line: written only when the definition or the owner differs, one version per change. */
33
+ exports.APPLY_CODE_LINE = `
34
+ INSERT INTO lt_machine_lines (site_id, line_id, definition, source, search_text)
35
+ VALUES ($1, $2, $3::jsonb, '${exports.LINE_SOURCE.CODE}', $4)
36
+ ON CONFLICT (site_id, line_id) DO UPDATE
37
+ SET definition = EXCLUDED.definition,
38
+ source = '${exports.LINE_SOURCE.CODE}',
39
+ search_text = EXCLUDED.search_text,
40
+ enabled = true,
41
+ version = lt_machine_lines.version + 1,
42
+ updated_at = NOW()
43
+ WHERE lt_machine_lines.definition IS DISTINCT FROM EXCLUDED.definition
44
+ OR lt_machine_lines.source <> '${exports.LINE_SOURCE.CODE}'
45
+ OR NOT lt_machine_lines.enabled
46
+ RETURNING ${COLUMNS}`;
47
+ exports.GET_LINE = `SELECT ${COLUMNS} FROM lt_machine_lines WHERE site_id = $1 AND line_id = $2`;
48
+ exports.DELETE_LINE = `DELETE FROM lt_machine_lines WHERE site_id = $1 AND line_id = $2 RETURNING ${COLUMNS}`;
49
+ exports.LIST_ENABLED_LINES = `SELECT ${COLUMNS} FROM lt_machine_lines WHERE enabled ORDER BY site_id, line_id`;
50
+ exports.LIST_CODE_LINES = `SELECT site_id, line_id FROM lt_machine_lines WHERE source = '${exports.LINE_SOURCE.CODE}'`;
51
+ /** The kinds of pending rows the index counts, in the order the health CTE projects them. */
52
+ exports.HEALTH_ROW_TYPES = [
53
+ contracts_1.ROW_TYPE.MACHINE_OFFLINE, contracts_1.ROW_TYPE.MACHINE_QUIET, contracts_1.ROW_TYPE.ALARM,
54
+ contracts_1.ROW_TYPE.HANDOFF_ERROR, contracts_1.ROW_TYPE.CONTRACT_VIOLATION, contracts_1.ROW_TYPE.MACHINE_REGISTRATION,
55
+ contracts_1.ROW_TYPE.HANDOFF, contracts_1.ROW_TYPE.MACHINE_COMMAND,
56
+ ];
57
+ const PENDING = 'pending';
58
+ /** Pending rows per line, counted by kind: $1 is the list of row types. */
59
+ const HEALTH_CTE = `
60
+ health AS (
61
+ SELECT metadata->>'siteId' AS site_id, metadata->>'lineId' AS line_id,
62
+ COUNT(*) FILTER (WHERE type = '${contracts_1.ROW_TYPE.MACHINE_OFFLINE}')::int AS offline,
63
+ COUNT(*) FILTER (WHERE type = '${contracts_1.ROW_TYPE.MACHINE_QUIET}')::int AS quiet,
64
+ COUNT(*) FILTER (WHERE type = '${contracts_1.ROW_TYPE.ALARM}')::int AS alarms,
65
+ COUNT(*) FILTER (WHERE type IN ('${contracts_1.ROW_TYPE.HANDOFF_ERROR}', '${contracts_1.ROW_TYPE.CONTRACT_VIOLATION}', '${contracts_1.ROW_TYPE.MACHINE_REGISTRATION}'))::int AS people,
66
+ COUNT(*) FILTER (WHERE type = '${contracts_1.ROW_TYPE.HANDOFF}')::int AS handoff,
67
+ COUNT(*) FILTER (WHERE type = '${contracts_1.ROW_TYPE.MACHINE_COMMAND}')::int AS command
68
+ FROM public.lt_escalations
69
+ WHERE status = '${PENDING}' AND type = ANY($1::text[]) AND metadata ? 'siteId' AND metadata ? 'lineId'
70
+ GROUP BY 1, 2
71
+ ),
72
+ lines AS (
73
+ SELECT l.${COLUMNS.split(', ').join(', l.')},
74
+ COALESCE(h.offline, 0) AS offline, COALESCE(h.quiet, 0) AS quiet, COALESCE(h.alarms, 0) AS alarms,
75
+ COALESCE(h.people, 0) AS people, COALESCE(h.handoff, 0) AS handoff, COALESCE(h.command, 0) AS command,
76
+ (COALESCE(h.offline, 0) + COALESCE(h.alarms, 0) + COALESCE(h.people, 0)) > 0 AS attention
77
+ FROM lt_machine_lines l
78
+ LEFT JOIN health h ON h.site_id = l.site_id AND h.line_id = l.line_id
79
+ WHERE l.enabled
80
+ )`;
81
+ /** The index's order, by name; attention first within each. */
82
+ exports.LINE_ORDER = {
83
+ attention: 'attention DESC, (offline + alarms + people) DESC, site_id, line_id',
84
+ site: 'site_id, line_id',
85
+ updated: 'updated_at DESC, site_id, line_id',
86
+ };
87
+ /**
88
+ * One page of the index: $1 row types, $2 search pattern or null, $3 site
89
+ * or null, $4 attention or null, $5 limit, $6 offset, $7 line or null. The
90
+ * total rides every row as a window count.
91
+ */
92
+ function listLinesSql(order) {
93
+ return `
94
+ WITH ${HEALTH_CTE}
95
+ SELECT *, COUNT(*) OVER() AS total
96
+ FROM lines
97
+ WHERE ($2::text IS NULL OR search_text ILIKE $2 ESCAPE '\\')
98
+ AND ($3::text IS NULL OR site_id = $3)
99
+ AND ($4::boolean IS NULL OR attention = $4)
100
+ AND ($7::text IS NULL OR line_id = $7)
101
+ ORDER BY ${order}
102
+ LIMIT $5 OFFSET $6`;
103
+ }
104
+ /** Every site, with its lines and how many need attention: $1 row types. */
105
+ exports.LIST_SITES = `
106
+ WITH ${HEALTH_CTE}
107
+ SELECT site_id, COUNT(*)::int AS lines, COUNT(*) FILTER (WHERE attention)::int AS attention
108
+ FROM lines
109
+ GROUP BY site_id
110
+ ORDER BY site_id`;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Keeps the running surface in step with the line registry. A declaration
3
+ * through the API writes the registry, applies the line's roles, runs the
4
+ * line on this replica and tells every other replica, which reads the row
5
+ * again and follows. Boot applies the code lines the same way, then starts
6
+ * the surface with everything the registry holds.
7
+ */
8
+ import type { CallbackEventAdapter } from '../../lib/events/callback';
9
+ import type { LineDef } from '../../lib/machines/line';
10
+ import { type LineApplyReport, type LineRecord } from './registry';
11
+ import type { LineSurface } from './surface';
12
+ export declare const LINE_ACTION: {
13
+ readonly DECLARED: "declared";
14
+ readonly RETIRED: "retired";
15
+ };
16
+ /** Declare a line through the API on this replica, then tell the others. */
17
+ export declare function declareLine(surface: LineSurface, def: LineDef, expectedVersion?: number): Promise<LineRecord>;
18
+ /** Retire a line on this replica and in the registry, then tell the others. Roles and bot accounts stay. */
19
+ export declare function retireLine(surface: LineSurface, siteId: string, lineId: string): Promise<LineRecord | null>;
20
+ /** Boot: apply code lines under the configSource rules, then every enabled line the registry holds. */
21
+ export declare function syncDeclaredLines(lines: LineDef[], codeOwned: boolean): Promise<{
22
+ report: LineApplyReport;
23
+ lines: LineDef[];
24
+ }>;
25
+ /**
26
+ * Follow registry changes other replicas publish. The event only names the
27
+ * line: the registry row is read again and decides, so a stray or stale
28
+ * event cannot stop a line the registry still holds. The surface ignores a
29
+ * line it already runs unchanged.
30
+ */
31
+ export declare function watchLineRegistry(surface: LineSurface, callbacks: CallbackEventAdapter): () => void;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * Keeps the running surface in step with the line registry. A declaration
4
+ * through the API writes the registry, applies the line's roles, runs the
5
+ * line on this replica and tells every other replica, which reads the row
6
+ * again and follows. Boot applies the code lines the same way, then starts
7
+ * the surface with everything the registry holds.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.LINE_ACTION = void 0;
11
+ exports.declareLine = declareLine;
12
+ exports.retireLine = retireLine;
13
+ exports.syncDeclaredLines = syncDeclaredLines;
14
+ exports.watchLineRegistry = watchLineRegistry;
15
+ const publish_1 = require("../../lib/events/publish");
16
+ const config_lock_1 = require("../../lib/db/config-lock");
17
+ const logger_1 = require("../../lib/logger");
18
+ const topics_1 = require("../../lib/machines/protocol/topics");
19
+ const seed_1 = require("../role/seed");
20
+ const registry_1 = require("./registry");
21
+ const roles_1 = require("./roles");
22
+ const LINE_EVENTS = 'machine.line.>';
23
+ const LOG = '[lt-machines]';
24
+ exports.LINE_ACTION = { DECLARED: 'declared', RETIRED: 'retired' };
25
+ /** The line's station, exit and operator roles, where the host declared none. */
26
+ async function applyLineRoles(line) {
27
+ await (0, config_lock_1.withConfigLock)(async () => {
28
+ for (const cfg of (0, roles_1.machineRoleConfigs)(line))
29
+ await (0, seed_1.applyRoleConfig)(cfg, false);
30
+ });
31
+ }
32
+ /** Declare a line through the API on this replica, then tell the others. */
33
+ async function declareLine(surface, def, expectedVersion) {
34
+ const record = await (0, registry_1.declareApiLine)(def, expectedVersion);
35
+ await applyLineRoles(record.definition);
36
+ await surface.declare(record.definition);
37
+ await (0, publish_1.publishMachineLineEvent)({ siteId: record.siteId, lineId: record.lineId, source: record.source, version: record.version, action: exports.LINE_ACTION.DECLARED });
38
+ return record;
39
+ }
40
+ /** Retire a line on this replica and in the registry, then tell the others. Roles and bot accounts stay. */
41
+ async function retireLine(surface, siteId, lineId) {
42
+ const record = await (0, registry_1.deleteLine)(siteId, lineId);
43
+ if (!record)
44
+ return null;
45
+ await surface.retire(siteId, lineId);
46
+ await (0, publish_1.publishMachineLineEvent)({ siteId, lineId, source: record.source, version: record.version, action: exports.LINE_ACTION.RETIRED });
47
+ return record;
48
+ }
49
+ /** Boot: apply code lines under the configSource rules, then every enabled line the registry holds. */
50
+ async function syncDeclaredLines(lines, codeOwned) {
51
+ const report = await (0, config_lock_1.withConfigLock)(() => (0, registry_1.applyDeclaredLines)(lines, codeOwned));
52
+ const enabled = await (0, registry_1.listEnabledLines)();
53
+ return { report, lines: enabled.map((r) => r.definition) };
54
+ }
55
+ /**
56
+ * Follow registry changes other replicas publish. The event only names the
57
+ * line: the registry row is read again and decides, so a stray or stale
58
+ * event cannot stop a line the registry still holds. The surface ignores a
59
+ * line it already runs unchanged.
60
+ */
61
+ function watchLineRegistry(surface, callbacks) {
62
+ return callbacks.on(LINE_EVENTS, (event) => {
63
+ const data = (event.data ?? {});
64
+ if (!(0, topics_1.isTopicLevel)(data.siteId) || !(0, topics_1.isTopicLevel)(data.lineId))
65
+ return;
66
+ const { siteId, lineId } = data;
67
+ void follow(surface, siteId, lineId).catch((err) => {
68
+ logger_1.loggerRegistry.warn(`${LOG} following ${siteId}/${lineId} failed: ${err instanceof Error ? err.message : String(err)}`);
69
+ });
70
+ });
71
+ }
72
+ async function follow(surface, siteId, lineId) {
73
+ const record = await (0, registry_1.getLine)(siteId, lineId);
74
+ if (!record || !record.enabled) {
75
+ await surface.retire(siteId, lineId);
76
+ return;
77
+ }
78
+ const outcome = await surface.declare(record.definition);
79
+ if (outcome !== 'unchanged')
80
+ logger_1.loggerRegistry.info(`${LOG} line ${siteId}/${lineId} ${outcome} from the registry (v${record.version})`);
81
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The line registry: every line this deployment controls, in Postgres, so
3
+ * every replica contends for the same lines and the Lines index reads one
4
+ * list. Lines come from code (start({ machines })) and from the API; the
5
+ * configSource rules decide who wins at boot, the version says what changed.
6
+ */
7
+ import { type LineDef } from '../../lib/machines/line';
8
+ import type { LineHealth, LineSource, SiteSummary } from '../../types/machines-view';
9
+ import { LINE_ORDER, LINE_SOURCE } from './registry-sql';
10
+ export { LINE_SOURCE };
11
+ /** A registry row. */
12
+ export interface LineRecord {
13
+ siteId: string;
14
+ lineId: string;
15
+ definition: LineDef;
16
+ source: LineSource;
17
+ version: number;
18
+ enabled: boolean;
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ }
22
+ /** A registry row with its pending rows counted. */
23
+ export interface LineRecordWithHealth extends LineRecord {
24
+ health: LineHealth;
25
+ }
26
+ export interface LineListQuery {
27
+ q?: string;
28
+ site?: string;
29
+ /** One line by id, with `site`. */
30
+ line?: string;
31
+ attention?: boolean;
32
+ sort?: keyof typeof LINE_ORDER;
33
+ limit?: number;
34
+ offset?: number;
35
+ }
36
+ export interface LineListPage {
37
+ lines: LineRecordWithHealth[];
38
+ total: number;
39
+ limit: number;
40
+ offset: number;
41
+ }
42
+ /** What boot did with each code line, and the code lines it no longer declares. */
43
+ export interface LineApplyReport {
44
+ applied: string[];
45
+ unchanged: string[];
46
+ dbOwned: string[];
47
+ orphans: string[];
48
+ }
49
+ /** A write that named a version the row no longer has. */
50
+ export declare class LineVersionConflict extends Error {
51
+ readonly siteId: string;
52
+ readonly lineId: string;
53
+ readonly expected: number;
54
+ constructor(siteId: string, lineId: string, expected: number);
55
+ }
56
+ export declare const DEFAULT_LINE_PAGE = 50;
57
+ export declare const MAX_LINE_PAGE = 200;
58
+ /** The index's search text: everything a person might type to find the line. */
59
+ export declare function searchTextOf(line: LineDef): string;
60
+ /** Declare a line through the API: insert, or replace and advance its version. */
61
+ export declare function declareApiLine(def: LineDef, expectedVersion?: number): Promise<LineRecord>;
62
+ /**
63
+ * Apply one code line. Db-owned: insert if absent, otherwise leave the row
64
+ * and log drift. Code-owned: write when the definition differs, once.
65
+ */
66
+ export declare function applyCodeLine(def: LineDef, codeOwned: boolean): Promise<'applied' | 'unchanged' | 'db-owned'>;
67
+ /** Boot: apply every code line and report, naming code lines the registry still holds that code no longer declares. */
68
+ export declare function applyDeclaredLines(lines: LineDef[], codeOwned: boolean): Promise<LineApplyReport>;
69
+ export declare function getLine(siteId: string, lineId: string): Promise<LineRecord | null>;
70
+ export declare function deleteLine(siteId: string, lineId: string): Promise<LineRecord | null>;
71
+ /** Every enabled line, code and API alike: what a replica contends for. */
72
+ export declare function listEnabledLines(): Promise<LineRecord[]>;
73
+ /** One page of the index, searched and filtered in SQL, with each line's pending rows counted. */
74
+ export declare function listLines(query?: LineListQuery): Promise<LineListPage>;
75
+ /** One line with its pending rows counted, or null. */
76
+ export declare function getLineWithHealth(siteId: string, lineId: string): Promise<LineRecordWithHealth | null>;
77
+ export declare function listSites(): Promise<SiteSummary[]>;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ /**
3
+ * The line registry: every line this deployment controls, in Postgres, so
4
+ * every replica contends for the same lines and the Lines index reads one
5
+ * list. Lines come from code (start({ machines })) and from the API; the
6
+ * configSource rules decide who wins at boot, the version says what changed.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MAX_LINE_PAGE = exports.DEFAULT_LINE_PAGE = exports.LineVersionConflict = exports.LINE_SOURCE = void 0;
10
+ exports.searchTextOf = searchTextOf;
11
+ exports.declareApiLine = declareApiLine;
12
+ exports.applyCodeLine = applyCodeLine;
13
+ exports.applyDeclaredLines = applyDeclaredLines;
14
+ exports.getLine = getLine;
15
+ exports.deleteLine = deleteLine;
16
+ exports.listEnabledLines = listEnabledLines;
17
+ exports.listLines = listLines;
18
+ exports.getLineWithHealth = getLineWithHealth;
19
+ exports.listSites = listSites;
20
+ const node_util_1 = require("node:util");
21
+ const db_1 = require("../../lib/db");
22
+ const logger_1 = require("../../lib/logger");
23
+ const line_1 = require("../../lib/machines/line");
24
+ const registry_sql_1 = require("./registry-sql");
25
+ Object.defineProperty(exports, "LINE_SOURCE", { enumerable: true, get: function () { return registry_sql_1.LINE_SOURCE; } });
26
+ /** A write that named a version the row no longer has. */
27
+ class LineVersionConflict extends Error {
28
+ constructor(siteId, lineId, expected) {
29
+ super(`line ${siteId}/${lineId} is not at version ${expected}`);
30
+ this.siteId = siteId;
31
+ this.lineId = lineId;
32
+ this.expected = expected;
33
+ this.name = 'LineVersionConflict';
34
+ }
35
+ }
36
+ exports.LineVersionConflict = LineVersionConflict;
37
+ exports.DEFAULT_LINE_PAGE = 50;
38
+ exports.MAX_LINE_PAGE = 200;
39
+ const LOG = '[lt-machines]';
40
+ /** The index's search text: everything a person might type to find the line. */
41
+ function searchTextOf(line) {
42
+ const words = [line.siteId, line.lineId];
43
+ for (const m of line.machines)
44
+ words.push(m.machineId, m.process, (0, line_1.machineRole)(m), m.address ?? '');
45
+ return [...new Set(words.filter(Boolean).map((w) => w.toLowerCase()))].join(' ');
46
+ }
47
+ function toRecord(row) {
48
+ return {
49
+ siteId: row.site_id, lineId: row.line_id, definition: row.definition, source: row.source,
50
+ version: row.version, enabled: row.enabled,
51
+ createdAt: new Date(row.created_at).toISOString(), updatedAt: new Date(row.updated_at).toISOString(),
52
+ };
53
+ }
54
+ function toHealth(row) {
55
+ const machines = Array.isArray(row.definition?.machines) ? row.definition.machines.length : 0;
56
+ return {
57
+ machines, offline: row.offline, quiet: row.quiet, alarms: row.alarms, people: row.people,
58
+ handoff: row.handoff, command: row.command, attention: row.attention === true,
59
+ };
60
+ }
61
+ function keyOf(siteId, lineId) {
62
+ return `${siteId}/${lineId}`;
63
+ }
64
+ /** A LIKE pattern that matches the text anywhere, with the person's wildcards taken literally. */
65
+ function likePattern(q) {
66
+ return `%${q.trim().toLowerCase().replace(/[\\%_]/g, (c) => `\\${c}`)}%`;
67
+ }
68
+ /** Declare a line through the API: insert, or replace and advance its version. */
69
+ async function declareApiLine(def, expectedVersion) {
70
+ const line = (0, line_1.validateLine)(def);
71
+ const { rows } = await (0, db_1.getPool)().query(registry_sql_1.UPSERT_API_LINE, [
72
+ line.siteId, line.lineId, JSON.stringify(line), searchTextOf(line), expectedVersion ?? null,
73
+ ]);
74
+ if (!rows.length)
75
+ throw new LineVersionConflict(line.siteId, line.lineId, expectedVersion);
76
+ return toRecord(rows[0]);
77
+ }
78
+ /**
79
+ * Apply one code line. Db-owned: insert if absent, otherwise leave the row
80
+ * and log drift. Code-owned: write when the definition differs, once.
81
+ */
82
+ async function applyCodeLine(def, codeOwned) {
83
+ const line = (0, line_1.validateLine)(def);
84
+ const params = [line.siteId, line.lineId, JSON.stringify(line), searchTextOf(line)];
85
+ const { rows } = await (0, db_1.getPool)().query(codeOwned ? registry_sql_1.APPLY_CODE_LINE : registry_sql_1.SEED_CODE_LINE, params);
86
+ if (rows.length)
87
+ return 'applied';
88
+ if (codeOwned)
89
+ return 'unchanged';
90
+ const existing = await getLine(line.siteId, line.lineId);
91
+ if (existing && !(0, node_util_1.isDeepStrictEqual)(existing.definition, line)) {
92
+ logger_1.loggerRegistry.warn(`${LOG} line ${keyOf(line.siteId, line.lineId)} differs from its declaration; the registry row stands (db-owned)`);
93
+ }
94
+ return 'db-owned';
95
+ }
96
+ /** Boot: apply every code line and report, naming code lines the registry still holds that code no longer declares. */
97
+ async function applyDeclaredLines(lines, codeOwned) {
98
+ const report = { applied: [], unchanged: [], dbOwned: [], orphans: [] };
99
+ const declared = new Set();
100
+ for (const line of lines) {
101
+ const key = keyOf(line.siteId, line.lineId);
102
+ declared.add(key);
103
+ const outcome = await applyCodeLine(line, codeOwned);
104
+ if (outcome === 'applied')
105
+ report.applied.push(key);
106
+ else if (outcome === 'unchanged')
107
+ report.unchanged.push(key);
108
+ else
109
+ report.dbOwned.push(key);
110
+ }
111
+ const { rows } = await (0, db_1.getPool)().query(registry_sql_1.LIST_CODE_LINES);
112
+ report.orphans = rows.map((r) => keyOf(r.site_id, r.line_id)).filter((k) => !declared.has(k));
113
+ const counts = `applied ${report.applied.length}, unchanged ${report.unchanged.length}, db-owned ${report.dbOwned.length}`;
114
+ if (report.orphans.length)
115
+ logger_1.loggerRegistry.warn(`${LOG} lines: ${counts}, declared in code before and not now: [${report.orphans.join(', ')}]`);
116
+ else
117
+ logger_1.loggerRegistry.info(`${LOG} lines: ${counts}`);
118
+ return report;
119
+ }
120
+ async function getLine(siteId, lineId) {
121
+ const { rows } = await (0, db_1.getPool)().query(registry_sql_1.GET_LINE, [siteId, lineId]);
122
+ return rows.length ? toRecord(rows[0]) : null;
123
+ }
124
+ async function deleteLine(siteId, lineId) {
125
+ const { rows } = await (0, db_1.getPool)().query(registry_sql_1.DELETE_LINE, [siteId, lineId]);
126
+ return rows.length ? toRecord(rows[0]) : null;
127
+ }
128
+ /** Every enabled line, code and API alike: what a replica contends for. */
129
+ async function listEnabledLines() {
130
+ const { rows } = await (0, db_1.getPool)().query(registry_sql_1.LIST_ENABLED_LINES);
131
+ return rows.map(toRecord);
132
+ }
133
+ /** One page of the index, searched and filtered in SQL, with each line's pending rows counted. */
134
+ async function listLines(query = {}) {
135
+ const limit = Math.min(Math.max(1, Math.floor(query.limit ?? exports.DEFAULT_LINE_PAGE)), exports.MAX_LINE_PAGE);
136
+ const offset = Math.max(0, Math.floor(query.offset ?? 0));
137
+ const order = registry_sql_1.LINE_ORDER[query.sort ?? 'attention'];
138
+ if (!order)
139
+ throw new Error(`sort must be one of ${Object.keys(registry_sql_1.LINE_ORDER).join(', ')}`);
140
+ const { rows } = await (0, db_1.getPool)().query((0, registry_sql_1.listLinesSql)(order), [
141
+ [...registry_sql_1.HEALTH_ROW_TYPES], query.q?.trim() ? likePattern(query.q) : null, query.site || null,
142
+ query.attention ?? null, limit, offset, query.line || null,
143
+ ]);
144
+ return {
145
+ lines: rows.map((r) => ({ ...toRecord(r), health: toHealth(r) })),
146
+ total: rows.length ? Number(rows[0].total) : 0,
147
+ limit, offset,
148
+ };
149
+ }
150
+ /** One line with its pending rows counted, or null. */
151
+ async function getLineWithHealth(siteId, lineId) {
152
+ const page = await listLines({ site: siteId, line: lineId, limit: 1 });
153
+ return page.lines[0] ?? null;
154
+ }
155
+ async function listSites() {
156
+ const { rows } = await (0, db_1.getPool)().query(registry_sql_1.LIST_SITES, [[...registry_sql_1.HEALTH_ROW_TYPES]]);
157
+ return rows.map((r) => ({ siteId: r.site_id, lines: r.lines, attention: r.attention }));
158
+ }
@@ -15,6 +15,13 @@ const str = (v) => (v === undefined || v === null || v === '' ? null : String(v)
15
15
  function paramsOf(v) {
16
16
  return v && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
17
17
  }
18
+ /** Named references with string values; other values are dropped, and an empty set is no refs. */
19
+ function refsOf(v) {
20
+ if (!v || typeof v !== 'object' || Array.isArray(v))
21
+ return undefined;
22
+ const refs = Object.fromEntries(Object.entries(v).filter((e) => typeof e[1] === 'string'));
23
+ return Object.keys(refs).length ? refs : undefined;
24
+ }
18
25
  function artifactOf(v) {
19
26
  if (!v || typeof v.url !== 'string' || !v.url || typeof v.sha256 !== 'string' || !v.sha256)
20
27
  return undefined;
@@ -36,9 +43,10 @@ function unitsOf(v) {
36
43
  const artifact = artifactOf(u.artifact);
37
44
  const artifacts = artifactsOf(u.artifacts);
38
45
  const parameters = paramsOf(u.parameters);
46
+ const refs = refsOf(u.refs);
39
47
  return {
40
48
  unitId: String(u.unitId), carrierId: str(u.carrierId),
41
- ...(artifact ? { artifact } : {}), ...(artifacts ? { artifacts } : {}), ...(parameters ? { parameters } : {}),
49
+ ...(artifact ? { artifact } : {}), ...(artifacts ? { artifacts } : {}), ...(parameters ? { parameters } : {}), ...(refs ? { refs } : {}),
42
50
  };
43
51
  });
44
52
  }
@@ -63,6 +71,7 @@ function readHandoffFacets(md = {}) {
63
71
  artifactSha256: str(md.artifactSha256),
64
72
  attempt: Number(md.attempt ?? 1),
65
73
  ...(paramsOf(md.parameters) ? { parameters: paramsOf(md.parameters) } : {}),
74
+ ...(refsOf(md.refs) ? { refs: refsOf(md.refs) } : {}),
66
75
  };
67
76
  }
68
77
  exports.standardRows = {
@@ -3,13 +3,17 @@
3
3
  * controls, one replica leads (an advisory lock), makes sure the line's bot
4
4
  * accounts exist, and runs the gateway: escalation events in, machine
5
5
  * messages in, verbs performed in process as each machine. Workflows never
6
- * see any of it; their rows are resolved the way a form resolves them.
6
+ * see any of it; their rows are resolved the way a form resolves them. The
7
+ * surface also describes its lines for the dashboard: every replica lists
8
+ * them, and the leader of a line projects it.
7
9
  */
8
10
  import type { CallbackEventAdapter } from '../../lib/events/callback';
9
- import type { LineDef } from '../../lib/machines/line';
11
+ import { type LineDef } from '../../lib/machines/line';
12
+ import { type LineCodec } from '../../lib/machines/protocol';
13
+ import type { InboundMessage } from '../../lib/machines/transport';
14
+ import type { InspectResult, LineSummary, LineView } from '../../types/machines-view';
10
15
  import { type MachineLineConfig } from './config';
11
16
  import { type GatewayLog } from './gateway/log';
12
- import type { LineCodec } from '../../lib/machines/protocol';
13
17
  import type { HandoffRowAdapter } from './rows';
14
18
  type Env = Record<string, string | undefined>;
15
19
  export interface MachineSurfaceOptions {
@@ -21,13 +25,49 @@ export interface MachineSurfaceOptions {
21
25
  codec?: LineCodec;
22
26
  rows?: HandoffRowAdapter;
23
27
  }
28
+ /** A message to dry-run against a line. */
29
+ export type WireProbe = Pick<InboundMessage, 'topic' | 'payload' | 'retained'>;
30
+ /** What settings and the API read of the surface. */
31
+ export interface LineSurface {
32
+ /** Every declared line, on every replica. */
33
+ describeLines(): LineSummary[];
34
+ /** The line as its leader sees it; null when this replica is not leading it, or the line is not declared. */
35
+ describeLine(siteId: string, lineId: string): LineView | null;
36
+ /** A dry run of one message; null when this replica is not leading the line. */
37
+ inspect(siteId: string, lineId: string, probe: WireProbe): InspectResult | null;
38
+ /** The declared line, or undefined. */
39
+ findLine(siteId: string, lineId: string): LineDef | undefined;
40
+ /** The ops a machine-command row on this line may ask for. */
41
+ commandOps(siteId: string, lineId: string): string[];
42
+ /** Run a line on this replica: started, replaced when its definition changed, or unchanged. */
43
+ declare(line: LineDef): Promise<DeclareOutcome>;
44
+ /** Stop running a line on this replica; false when it was not running. */
45
+ retire(siteId: string, lineId: string): Promise<boolean>;
46
+ }
47
+ export type DeclareOutcome = 'started' | 'replaced' | 'unchanged';
24
48
  /** Inside Long Tail the gateway reads escalation events in process. */
25
49
  export declare function surfaceConfig(env: Env): MachineLineConfig;
26
- export declare class MachineSurface {
50
+ /** The line as every replica can describe it: its machines, roles, declared addresses and the codec's own ops. */
51
+ export declare function summarizeLine(line: LineDef, codec: Pick<LineCodec, 'rowOps'>): LineSummary;
52
+ /** The ops a machine-command row may ask for: the control ops, a snapshot, and the codec's own. */
53
+ export declare function commandOpsOf(codec: Pick<LineCodec, 'rowOps'>): string[];
54
+ export declare class MachineSurface implements LineSurface {
55
+ private readonly config;
56
+ private readonly opts;
57
+ private readonly log;
27
58
  private readonly runs;
28
59
  private constructor();
29
- /** Validate the configuration, then contend for every line in the background. */
60
+ /** Validate the configuration, then contend for every line in the background. The registry may add lines later. */
30
61
  static start(opts: MachineSurfaceOptions): MachineSurface;
31
62
  stop(): Promise<void>;
63
+ declare(line: LineDef): Promise<DeclareOutcome>;
64
+ retire(siteId: string, lineId: string): Promise<boolean>;
65
+ describeLines(): LineSummary[];
66
+ describeLine(siteId: string, lineId: string): LineView | null;
67
+ inspect(siteId: string, lineId: string, probe: WireProbe): InspectResult | null;
68
+ findLine(siteId: string, lineId: string): LineDef | undefined;
69
+ commandOps(siteId: string, lineId: string): string[];
70
+ private begin;
71
+ private run;
32
72
  }
33
73
  export {};