@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.
- package/README.md +9 -2
- package/build/api/settings.d.ts +4 -1
- package/build/api/settings.js +7 -1
- package/build/index.d.ts +4 -0
- package/build/index.js +35 -8
- package/build/lib/db/config-lock.d.ts +10 -0
- package/build/lib/db/config-lock.js +28 -0
- package/build/lib/db/schemas/041_machine_lines.sql +26 -0
- package/build/lib/events/browser-view.js +8 -2
- package/build/lib/events/nats.d.ts +11 -0
- package/build/lib/events/nats.js +33 -2
- package/build/lib/events/publish.d.ts +33 -0
- package/build/lib/events/publish.js +52 -1
- package/build/lib/machines/index.d.ts +1 -0
- package/build/lib/machines/index.js +1 -0
- package/build/lib/machines/line.d.ts +4 -1
- package/build/lib/machines/line.js +18 -1
- package/build/lib/machines/protocol/codec.d.ts +24 -0
- package/build/lib/machines/protocol/codec.js +10 -0
- package/build/lib/machines/protocol/constants.d.ts +1 -1
- package/build/lib/machines/protocol/constants.js +1 -1
- package/build/lib/machines/protocol/contract.js +12 -3
- package/build/lib/machines/site/edge-account.d.ts +11 -0
- package/build/lib/machines/site/edge-account.js +24 -0
- package/build/lib/machines/site/mosquitto-conf.d.ts +5 -4
- package/build/lib/machines/site/mosquitto-conf.js +31 -16
- package/build/lib/machines/site/site-conf.d.ts +16 -6
- package/build/lib/machines/site/site-conf.js +39 -13
- package/build/lib/machines/transport/callback-feed.d.ts +1 -0
- package/build/lib/machines/transport/callback-feed.js +4 -1
- package/build/lib/machines/transport/delivery.d.ts +3 -4
- package/build/lib/machines/transport/delivery.js +3 -8
- package/build/lib/machines/transport/index.d.ts +2 -0
- package/build/lib/machines/transport/index.js +2 -0
- package/build/lib/machines/transport/memory.d.ts +2 -0
- package/build/lib/machines/transport/memory.js +6 -0
- package/build/lib/machines/transport/mqtt-bus.d.ts +2 -0
- package/build/lib/machines/transport/mqtt-bus.js +4 -0
- package/build/lib/machines/transport/nats-bus.d.ts +8 -13
- package/build/lib/machines/transport/nats-bus.js +26 -43
- package/build/lib/machines/transport/nats-feed.d.ts +1 -0
- package/build/lib/machines/transport/nats-feed.js +6 -3
- package/build/lib/machines/transport/pubsub-feed.d.ts +18 -0
- package/build/lib/machines/transport/pubsub-feed.js +42 -0
- package/build/lib/machines/transport/stream-bus.d.ts +42 -0
- package/build/lib/machines/transport/stream-bus.js +61 -0
- package/build/lib/machines/transport/streams.d.ts +10 -14
- package/build/lib/machines/transport/streams.js +18 -61
- package/build/lib/messaging/config.d.ts +25 -0
- package/build/lib/messaging/config.js +55 -0
- package/build/lib/messaging/constants.d.ts +26 -0
- package/build/lib/messaging/constants.js +26 -0
- package/build/lib/messaging/index.d.ts +24 -0
- package/build/lib/messaging/index.js +65 -0
- package/build/lib/messaging/memory.d.ts +16 -0
- package/build/lib/messaging/memory.js +147 -0
- package/build/lib/messaging/nats/permissions.d.ts +13 -0
- package/build/lib/messaging/nats/permissions.js +22 -0
- package/build/lib/messaging/nats/provider.d.ts +30 -0
- package/build/lib/messaging/nats/provider.js +77 -0
- package/build/lib/messaging/nats/render-conf.d.ts +68 -0
- package/build/lib/messaging/nats/render-conf.js +58 -0
- package/build/lib/messaging/nats/streams.d.ts +26 -0
- package/build/lib/messaging/nats/streams.js +97 -0
- package/build/lib/messaging/subjects.d.ts +8 -0
- package/build/lib/messaging/subjects.js +25 -0
- package/build/modules/machines.d.ts +8 -0
- package/build/modules/machines.js +16 -0
- package/build/routes/index.js +2 -0
- package/build/routes/machines.d.ts +2 -0
- package/build/routes/machines.js +220 -0
- package/build/scripts/bambu-boat.d.ts +17 -0
- package/build/scripts/bambu-boat.js +134 -0
- package/build/scripts/bambu-print.d.ts +18 -0
- package/build/scripts/bambu-print.js +114 -0
- package/build/services/machines/commands.d.ts +5 -5
- package/build/services/machines/commands.js +3 -2
- package/build/services/machines/config.d.ts +8 -1
- package/build/services/machines/config.js +17 -7
- package/build/services/machines/contracts.d.ts +29 -2
- package/build/services/machines/contracts.js +12 -3
- package/build/services/machines/gateway/actions.d.ts +2 -1
- package/build/services/machines/gateway/admission.d.ts +15 -3
- package/build/services/machines/gateway/admission.js +29 -14
- package/build/services/machines/gateway/dispatcher.d.ts +19 -3
- package/build/services/machines/gateway/dispatcher.js +61 -13
- package/build/services/machines/gateway/executor.d.ts +18 -4
- package/build/services/machines/gateway/executor.js +99 -34
- package/build/services/machines/gateway/gateway.d.ts +22 -1
- package/build/services/machines/gateway/gateway.js +83 -28
- package/build/services/machines/gateway/index.d.ts +3 -0
- package/build/services/machines/gateway/index.js +3 -0
- package/build/services/machines/gateway/inspect.d.ts +17 -0
- package/build/services/machines/gateway/inspect.js +68 -0
- package/build/services/machines/gateway/lifecycle.d.ts +21 -0
- package/build/services/machines/gateway/lifecycle.js +89 -0
- package/build/services/machines/gateway/log.d.ts +8 -0
- package/build/services/machines/gateway/log.js +18 -0
- package/build/services/machines/gateway/pacing.d.ts +14 -0
- package/build/services/machines/gateway/pacing.js +27 -2
- package/build/services/machines/gateway/plan-escalation.js +21 -7
- package/build/services/machines/gateway/plan-machine.d.ts +5 -4
- package/build/services/machines/gateway/plan-machine.js +70 -19
- package/build/services/machines/gateway/project.d.ts +9 -0
- package/build/services/machines/gateway/project.js +55 -0
- package/build/services/machines/gateway/receipts.d.ts +3 -0
- package/build/services/machines/gateway/receipts.js +3 -1
- package/build/services/machines/gateway/reconcile.d.ts +2 -0
- package/build/services/machines/gateway/reconcile.js +16 -3
- package/build/services/machines/gateway/registration.js +1 -1
- package/build/services/machines/gateway/reply-waiter.d.ts +6 -3
- package/build/services/machines/gateway/reply-waiter.js +37 -16
- package/build/services/machines/gateway/state.d.ts +50 -4
- package/build/services/machines/gateway/state.js +77 -10
- package/build/services/machines/gateway/wire.d.ts +58 -0
- package/build/services/machines/gateway/wire.js +171 -0
- package/build/services/machines/index.d.ts +3 -0
- package/build/services/machines/index.js +2 -0
- package/build/services/machines/leadership.d.ts +17 -4
- package/build/services/machines/leadership.js +43 -18
- package/build/services/machines/line-index.d.ts +16 -0
- package/build/services/machines/line-index.js +39 -0
- package/build/services/machines/registry-sql.d.ts +31 -0
- package/build/services/machines/registry-sql.js +110 -0
- package/build/services/machines/registry-sync.d.ts +31 -0
- package/build/services/machines/registry-sync.js +81 -0
- package/build/services/machines/registry.d.ts +77 -0
- package/build/services/machines/registry.js +158 -0
- package/build/services/machines/rows.js +26 -2
- package/build/services/machines/select.d.ts +9 -2
- package/build/services/machines/select.js +20 -7
- package/build/services/machines/surface.d.ts +45 -5
- package/build/services/machines/surface.js +102 -16
- package/build/services/machines/testing/fake-long-tail.d.ts +1 -0
- package/build/services/machines/testing/fake-long-tail.js +6 -3
- package/build/start/adapters.js +11 -2
- package/build/start/apply-report.d.ts +1 -1
- package/build/start/apply-report.js +3 -25
- package/build/start/index.js +23 -5
- package/build/system/index.js +13 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +22 -22
- package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -7
- package/build/system/mcp-servers/machines-schemas.d.ts +35 -0
- package/build/system/mcp-servers/machines-schemas.js +35 -0
- package/build/system/mcp-servers/machines.d.ts +20 -0
- package/build/system/mcp-servers/machines.js +154 -0
- package/build/system/seed/tool-manifests-machines.d.ts +2 -0
- package/build/system/seed/tool-manifests-machines.js +88 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/events.d.ts +6 -1
- package/build/types/index.d.ts +2 -0
- package/build/types/machines-view.d.ts +159 -0
- package/build/types/machines-view.js +7 -0
- package/build/types/machines.d.ts +6 -1
- package/build/types/messaging.d.ts +72 -0
- package/build/types/messaging.js +11 -0
- package/build/types/startup.d.ts +26 -1
- package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js → AdminDashboard-Bm7VG65H.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js.map → AdminDashboard-Bm7VG65H.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js → AgentConfigPage-aJF7Sdbc.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js.map → AgentConfigPage-aJF7Sdbc.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js → AgentDetailPage-GwwghhxT.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js.map → AgentDetailPage-GwwghhxT.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage-DVvCzZyg.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-C9UuUKhr.js.map → AgentsPage-DVvCzZyg.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-Cxmcji_K.js +2 -0
- package/dashboard/dist/assets/{AvailableEscalationsPage-DrvfXz70.js.map → AvailableEscalationsPage-Cxmcji_K.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js → BotPicker-CofRxk4L.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js.map → BotPicker-CofRxk4L.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js → BulkAssignModal-BARWuz4L.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js.map → BulkAssignModal-BARWuz4L.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js → CapabilitiesPage-BJAWVNEx.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js.map → CapabilitiesPage-BJAWVNEx.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js → CollapsibleSection-CtgoaG75.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js.map → CollapsibleSection-CtgoaG75.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js → ConfirmDeleteModal-BYXXBWs6.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js.map → ConfirmDeleteModal-BYXXBWs6.js.map} +1 -1
- package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js → ConnectedAppsPage-D0JkzWa7.js} +2 -2
- package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js.map → ConnectedAppsPage-D0JkzWa7.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js → CountdownTimer-BcFxdZYN.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js.map → CountdownTimer-BcFxdZYN.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js → CredentialsPage-DPSY20rV.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js.map → CredentialsPage-DPSY20rV.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js → CronLabel-Dg_Oew_Y.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js.map → CronLabel-Dg_Oew_Y.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-u1JGfR9G.js → DropZone-Cl_Flb16.js} +2 -2
- package/dashboard/dist/assets/{DropZone-u1JGfR9G.js.map → DropZone-Cl_Flb16.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js → ElapsedCell-Dm3G5fK2.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js.map → ElapsedCell-Dm3G5fK2.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js → EntityTimelinePanel-CrEEP04e.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js.map → EntityTimelinePanel-CrEEP04e.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js → EscalationListSchemaPage-wOInXcjs.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js.map → EscalationListSchemaPage-wOInXcjs.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js → EscalationSchemaPage-CrIj_g9d.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js.map → EscalationSchemaPage-CrIj_g9d.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js → EscalationTimeline-CeAsl5IT.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js.map → EscalationTimeline-CeAsl5IT.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js → EscalationTitleSelect-D8qpCYiy.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js.map → EscalationTitleSelect-D8qpCYiy.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js → EscalationsOverview-CvaqVPsr.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js.map → EscalationsOverview-CvaqVPsr.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-V4RF_n58.js → EventTable-Be0JuEl6.js} +2 -2
- package/dashboard/dist/assets/{EventTable-V4RF_n58.js.map → EventTable-Be0JuEl6.js.map} +1 -1
- package/dashboard/dist/assets/FilterBar-BVyAjIgv.js +2 -0
- package/dashboard/dist/assets/FilterBar-BVyAjIgv.js.map +1 -0
- package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js → GraphInvokePage-D_QigJeD.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js.map → GraphInvokePage-D_QigJeD.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-EjcNxlKx.js → HomePage-C1haeuNy.js} +2 -2
- package/dashboard/dist/assets/{HomePage-EjcNxlKx.js.map → HomePage-C1haeuNy.js.map} +1 -1
- package/dashboard/dist/assets/LinePage-CWD5pv1g.js +5 -0
- package/dashboard/dist/assets/LinePage-CWD5pv1g.js.map +1 -0
- package/dashboard/dist/assets/LinesPage-NqChsKcO.js +3 -0
- package/dashboard/dist/assets/LinesPage-NqChsKcO.js.map +1 -0
- package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js → ListToolbar-BZCNrTh6.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js.map → ListToolbar-BZCNrTh6.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js → McpOverview-yJTYnh1z.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js.map → McpOverview-yJTYnh1z.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js → McpQueryDetailPage-ChuLpJ4u.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js.map → McpQueryDetailPage-ChuLpJ4u.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js → McpQueryPage-9S-v9soF.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js.map → McpQueryPage-9S-v9soF.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-BhrcfxD5.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-80fQn9iX.js.map → McpRunDetailPage-BhrcfxD5.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js → McpRunsPage-C5_i8_Zx.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js.map → McpRunsPage-C5_i8_Zx.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js → NamespacePill-OTZD2hzt.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js.map → NamespacePill-OTZD2hzt.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js → OperationsPage-C03CeU5P.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js.map → OperationsPage-C03CeU5P.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js → OperatorDashboard-BzC134Jt.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js.map → OperatorDashboard-BzC134Jt.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BSWIspNB.js → PageHeader-Hx8APPwE.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BSWIspNB.js.map → PageHeader-Hx8APPwE.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js → PageHeaderWithStats-BEQYYBJv.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js.map → PageHeaderWithStats-BEQYYBJv.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js → PersonaDetailPage-D0mY9L6j.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js.map → PersonaDetailPage-D0mY9L6j.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js → PersonasPage-FFlm5Eug.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js.map → PersonasPage-FFlm5Eug.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-CucNZn_w.js → PortalPage-Cpc25uO-.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-CucNZn_w.js.map → PortalPage-Cpc25uO-.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js → ProcessDetailPage-Di2J7KwY.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js.map → ProcessDetailPage-Di2J7KwY.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js → ProcessesListPage-BEXwU3Z0.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js.map → ProcessesListPage-BEXwU3Z0.js.map} +1 -1
- package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js → ResolverForm-2ks-3jXC.js} +6 -6
- package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js.map → ResolverForm-2ks-3jXC.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js → RoleDetailPage-DqoOk0xc.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js.map → RoleDetailPage-DqoOk0xc.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-CoETDpjF.js → RolePill-R5_ctGFy.js} +2 -2
- package/dashboard/dist/assets/{RolePill-CoETDpjF.js.map → RolePill-R5_ctGFy.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DBKxeam4.js → RolesPage-CPmo8Srr.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DBKxeam4.js.map → RolesPage-CPmo8Srr.js.map} +1 -1
- package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js → RosterWidget-D2yovCKw.js} +2 -2
- package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js.map → RosterWidget-D2yovCKw.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js → RunAsSelector-CMv96On6.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js.map → RunAsSelector-CMv96On6.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js → ScanCodesPage-CA6cTT-M.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js.map → ScanCodesPage-CA6cTT-M.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js → ScanSchemeDetailPage-DnctN5-H.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js.map → ScanSchemeDetailPage-DnctN5-H.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js → ScanStationPage-Bk8RwkKL.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js.map → ScanStationPage-Bk8RwkKL.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js → ScopeBadge-BXZ084nD.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js.map → ScopeBadge-BXZ084nD.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js → StickyPagination-B0FSuUgs.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js.map → StickyPagination-B0FSuUgs.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js → StreamMessageDetail-BwZEvMpP.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js.map → StreamMessageDetail-BwZEvMpP.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js → SwimlaneTimeline-BDVQEaMw.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js.map → SwimlaneTimeline-BDVQEaMw.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-S7UuVT_M.js → TagInput-DjPUDp2M.js} +2 -2
- package/dashboard/dist/assets/{TagInput-S7UuVT_M.js.map → TagInput-DjPUDp2M.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js → TaskDetailPage-BOlv3iGB.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js.map → TaskDetailPage-BOlv3iGB.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js → TaskQueuePill-D-4Ynf3K.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js.map → TaskQueuePill-D-4Ynf3K.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js → TasksListPage-e2teY0bD.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js.map → TasksListPage-e2teY0bD.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js → TimeAgo-Cvkpf_b3.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js.map → TimeAgo-Cvkpf_b3.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js → TimestampCell-B3btAV0N.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js.map → TimestampCell-B3btAV0N.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-D40uLM_v.js → ToolPill-GsKQ80CO.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-D40uLM_v.js.map → ToolPill-GsKQ80CO.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js → ToolTestPanel-B03nebR7.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js.map → ToolTestPanel-B03nebR7.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js → TopicDetailPage-DBRWne3O.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js.map → TopicDetailPage-DBRWne3O.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js → TopicsPage-CVe2M9HD.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js.map → TopicsPage-CVe2M9HD.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-DQFjuoib.js → UserName-B_q_qp6V.js} +2 -2
- package/dashboard/dist/assets/{UserName-DQFjuoib.js.map → UserName-B_q_qp6V.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-Bh_dr9tM.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-Di08wCbs.js.map → WorkflowExecutionPage-Bh_dr9tM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js → WorkflowPill-D7244fKp.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js.map → WorkflowPill-D7244fKp.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js → WorkflowsDashboard-DA6Mj7qH.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js.map → WorkflowsDashboard-DA6Mj7qH.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js → WorkflowsOverview-B1kBLj-a.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js.map → WorkflowsOverview-B1kBLj-a.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js → YamlWorkflowDetailPage-6GJM8QIX.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js.map → YamlWorkflowDetailPage-6GJM8QIX.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js → YamlWorkflowsPage-Bu811C7f.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js.map → YamlWorkflowsPage-Bu811C7f.js.map} +1 -1
- package/dashboard/dist/assets/{agents-PuftRTB2.js → agents-MPk_GnYz.js} +2 -2
- package/dashboard/dist/assets/{agents-PuftRTB2.js.map → agents-MPk_GnYz.js.map} +1 -1
- package/dashboard/dist/assets/{bots-BmEiPAWY.js → bots-2RihE2Tc.js} +2 -2
- package/dashboard/dist/assets/{bots-BmEiPAWY.js.map → bots-2RihE2Tc.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CRii4Soa.js → capabilities-CC4iwJ1P.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CRii4Soa.js.map → capabilities-CC4iwJ1P.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DO_czaYo.js → controlplane-Bmkic8BH.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DO_czaYo.js.map → controlplane-Bmkic8BH.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js → escalation-columns-B0lhUUrQ.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js.map → escalation-columns-B0lhUUrQ.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js → escalation-items-7WFpPo46.js} +2 -2
- package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js.map → escalation-items-7WFpPo46.js.map} +1 -1
- package/dashboard/dist/assets/index-B9uv-euR.css +1 -0
- package/dashboard/dist/assets/{index-DhSCCpqM.js → index-B_XV1rwu.js} +2 -2
- package/dashboard/dist/assets/{index-DhSCCpqM.js.map → index-B_XV1rwu.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cx8xb-oU.js → index-C2CLfGwL.js} +2 -2
- package/dashboard/dist/assets/{index-Cx8xb-oU.js.map → index-C2CLfGwL.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cga5IW3D.js → index-C3AeFihz.js} +2 -2
- package/dashboard/dist/assets/{index-Cga5IW3D.js.map → index-C3AeFihz.js.map} +1 -1
- package/dashboard/dist/assets/{index-DiaRlFYI.js → index-CBri8fYM.js} +2 -2
- package/dashboard/dist/assets/{index-DiaRlFYI.js.map → index-CBri8fYM.js.map} +1 -1
- package/dashboard/dist/assets/{index-CL_1VpGb.js → index-CRWsB7ZC.js} +2 -2
- package/dashboard/dist/assets/{index-CL_1VpGb.js.map → index-CRWsB7ZC.js.map} +1 -1
- package/dashboard/dist/assets/{index-XntldBd0.js → index-CTOv3G7a.js} +2 -2
- package/dashboard/dist/assets/{index-XntldBd0.js.map → index-CTOv3G7a.js.map} +1 -1
- package/dashboard/dist/assets/{index-CfP2nKRc.js → index-CcArGkzI.js} +3 -3
- package/dashboard/dist/assets/{index-CfP2nKRc.js.map → index-CcArGkzI.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dz6R8-Dw.js → index-CkMHS-hG.js} +25 -25
- package/dashboard/dist/assets/index-CkMHS-hG.js.map +1 -0
- package/dashboard/dist/assets/index-CmsmwCyv.js +2 -0
- package/dashboard/dist/assets/{index-4YaDUcKd.js.map → index-CmsmwCyv.js.map} +1 -1
- package/dashboard/dist/assets/{index-2SM2_onB.js → index-CvJsvqIc.js} +2 -2
- package/dashboard/dist/assets/{index-2SM2_onB.js.map → index-CvJsvqIc.js.map} +1 -1
- package/dashboard/dist/assets/{index-Rwqrflm-.js → index-D-ilRyfy.js} +2 -2
- package/dashboard/dist/assets/{index-Rwqrflm-.js.map → index-D-ilRyfy.js.map} +1 -1
- package/dashboard/dist/assets/{index-CZ7A3AcD.js → index-DSUtfDXx.js} +2 -2
- package/dashboard/dist/assets/{index-CZ7A3AcD.js.map → index-DSUtfDXx.js.map} +1 -1
- package/dashboard/dist/assets/{index-jL2K6us4.js → index-Da6ycKyf.js} +2 -2
- package/dashboard/dist/assets/{index-jL2K6us4.js.map → index-Da6ycKyf.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CeUqGPuo.js → knowledge-Bpbg20DC.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CeUqGPuo.js.map → knowledge-Bpbg20DC.js.map} +1 -1
- package/dashboard/dist/assets/machines-BqOZZU-3.js +2 -0
- package/dashboard/dist/assets/machines-BqOZZU-3.js.map +1 -0
- package/dashboard/dist/assets/{mcp-Cx96NTeD.js → mcp-CmcUXYce.js} +2 -2
- package/dashboard/dist/assets/{mcp-Cx96NTeD.js.map → mcp-CmcUXYce.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js → mcp-query-C8buQxN9.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js.map → mcp-query-C8buQxN9.js.map} +1 -1
- package/dashboard/dist/assets/{personas--4kjwyOw.js → personas-C2n5oDmY.js} +2 -2
- package/dashboard/dist/assets/{personas--4kjwyOw.js.map → personas-C2n5oDmY.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-PgkwvG7f.js → pipelines-RKpSkFz7.js} +2 -2
- package/dashboard/dist/assets/{pipelines-PgkwvG7f.js.map → pipelines-RKpSkFz7.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CcYxdBa3.js → tasks-Dab4hExW.js} +2 -2
- package/dashboard/dist/assets/{tasks-CcYxdBa3.js.map → tasks-Dab4hExW.js.map} +1 -1
- package/dashboard/dist/assets/{topics-_lik7cNY.js → topics-FTMNP7r3.js} +2 -2
- package/dashboard/dist/assets/{topics-_lik7cNY.js.map → topics-FTMNP7r3.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js → useDebouncedValue-B_1u1YIk.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js.map → useDebouncedValue-B_1u1YIk.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js → useNamespace-HUeAI7Qb.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js.map → useNamespace-HUeAI7Qb.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js → useYamlActivityEvents-Cax54qHH.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js.map → useYamlActivityEvents-Cax54qHH.js.map} +1 -1
- package/dashboard/dist/assets/{validate-FlXCBBT6.js → validate-DxOaV7QS.js} +2 -2
- package/dashboard/dist/assets/{validate-FlXCBBT6.js.map → validate-DxOaV7QS.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DUYcKTjP.js → vendor-icons-fxBvvHBi.js} +187 -182
- package/dashboard/dist/assets/vendor-icons-fxBvvHBi.js.map +1 -0
- package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js → yaml-workflows-BgY1XHJx.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js.map → yaml-workflows-BgY1XHJx.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/architecture.md +1 -0
- package/docs/code-owned-configuration.md +6 -0
- package/docs/dashboard.md +1 -0
- package/docs/events.md +83 -4
- package/docs/machines.md +129 -23
- package/docs/mcp.md +19 -0
- package/package.json +3 -1
- package/build/lib/machines/transport/nats-durable.d.ts +0 -11
- package/build/lib/machines/transport/nats-durable.js +0 -28
- package/dashboard/dist/assets/AgentsPage-C9UuUKhr.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-DrvfXz70.js +0 -2
- package/dashboard/dist/assets/FilterBar-BygWrnB1.js +0 -2
- package/dashboard/dist/assets/FilterBar-BygWrnB1.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-80fQn9iX.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-Di08wCbs.js +0 -2
- package/dashboard/dist/assets/index-4YaDUcKd.js +0 -2
- package/dashboard/dist/assets/index-CnU7Jjz3.css +0 -1
- package/dashboard/dist/assets/index-Dz6R8-Dw.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-DUYcKTjP.js.map +0 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The messaging registry: one provider, registered at startup and shared by
|
|
4
|
+
* every part of Long Tail that needs pub/sub or durable streams (events, the
|
|
5
|
+
* machine surface). Asking for messaging that is not configured fails loudly,
|
|
6
|
+
* because a caller that gets nothing back would believe it was handled.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.LT_SUBJECTS = exports.MESSAGING_LOG = exports.START_AT = exports.DELIVERY = exports.isSubject = exports.subjectMatches = exports.MemoryMessagingProvider = exports.messagingRegistry = void 0;
|
|
10
|
+
const logger_1 = require("../logger");
|
|
11
|
+
const constants_1 = require("./constants");
|
|
12
|
+
const NOT_CONFIGURED = 'No messaging provider is configured: set LT_MESSAGING=nats with LT_NATS_URL, or pass start({ messaging })';
|
|
13
|
+
class LTMessagingRegistry {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.current = null;
|
|
16
|
+
}
|
|
17
|
+
/** Register the provider; replaces any registered before. Call before connect(). */
|
|
18
|
+
register(provider) {
|
|
19
|
+
this.current = provider;
|
|
20
|
+
}
|
|
21
|
+
get hasProvider() {
|
|
22
|
+
return this.current !== null;
|
|
23
|
+
}
|
|
24
|
+
get provider() {
|
|
25
|
+
if (!this.current)
|
|
26
|
+
throw new Error(NOT_CONFIGURED);
|
|
27
|
+
return this.current;
|
|
28
|
+
}
|
|
29
|
+
get pubsub() {
|
|
30
|
+
return this.provider.pubsub;
|
|
31
|
+
}
|
|
32
|
+
get streams() {
|
|
33
|
+
const streams = this.provider.streams;
|
|
34
|
+
if (!streams)
|
|
35
|
+
throw new Error(`Messaging provider ${this.provider.name} has no durable streams; enable JetStream on its NATS server`);
|
|
36
|
+
return streams;
|
|
37
|
+
}
|
|
38
|
+
async connect() {
|
|
39
|
+
if (!this.current || this.current.connected)
|
|
40
|
+
return;
|
|
41
|
+
await this.current.connect();
|
|
42
|
+
logger_1.loggerRegistry.info(`${constants_1.MESSAGING_LOG.CONNECTED} provider=${this.current.name} streams=${this.current.streams ? 'yes' : 'no'}`);
|
|
43
|
+
}
|
|
44
|
+
async disconnect() {
|
|
45
|
+
if (!this.current?.connected)
|
|
46
|
+
return;
|
|
47
|
+
await this.current.disconnect();
|
|
48
|
+
logger_1.loggerRegistry.info(`${constants_1.MESSAGING_LOG.DISCONNECTED} provider=${this.current.name}`);
|
|
49
|
+
}
|
|
50
|
+
/** Forget the provider (tests). */
|
|
51
|
+
clear() {
|
|
52
|
+
this.current = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.messagingRegistry = new LTMessagingRegistry();
|
|
56
|
+
var memory_1 = require("./memory");
|
|
57
|
+
Object.defineProperty(exports, "MemoryMessagingProvider", { enumerable: true, get: function () { return memory_1.MemoryMessagingProvider; } });
|
|
58
|
+
var subjects_1 = require("./subjects");
|
|
59
|
+
Object.defineProperty(exports, "subjectMatches", { enumerable: true, get: function () { return subjects_1.subjectMatches; } });
|
|
60
|
+
Object.defineProperty(exports, "isSubject", { enumerable: true, get: function () { return subjects_1.isSubject; } });
|
|
61
|
+
var constants_2 = require("./constants");
|
|
62
|
+
Object.defineProperty(exports, "DELIVERY", { enumerable: true, get: function () { return constants_2.DELIVERY; } });
|
|
63
|
+
Object.defineProperty(exports, "START_AT", { enumerable: true, get: function () { return constants_2.START_AT; } });
|
|
64
|
+
Object.defineProperty(exports, "MESSAGING_LOG", { enumerable: true, get: function () { return constants_2.MESSAGING_LOG; } });
|
|
65
|
+
Object.defineProperty(exports, "LT_SUBJECTS", { enumerable: true, get: function () { return constants_2.LT_SUBJECTS; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messaging in memory, for tests and single-process development. Pub/sub fans
|
|
3
|
+
* out to every matching subscriber. Streams keep each message until it ages
|
|
4
|
+
* out, and deliver to each consumer one at a time in order; a nak'd message
|
|
5
|
+
* comes back after its delay while later messages go on, as JetStream does.
|
|
6
|
+
*/
|
|
7
|
+
import type { LTMessagingProvider, LTPubSub, LTStreams } from '../../types/messaging';
|
|
8
|
+
export declare class MemoryMessagingProvider implements LTMessagingProvider {
|
|
9
|
+
readonly name = "memory";
|
|
10
|
+
readonly pubsub: LTPubSub;
|
|
11
|
+
readonly streams: LTStreams;
|
|
12
|
+
private live;
|
|
13
|
+
get connected(): boolean;
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
disconnect(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Messaging in memory, for tests and single-process development. Pub/sub fans
|
|
4
|
+
* out to every matching subscriber. Streams keep each message until it ages
|
|
5
|
+
* out, and deliver to each consumer one at a time in order; a nak'd message
|
|
6
|
+
* comes back after its delay while later messages go on, as JetStream does.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MemoryMessagingProvider = void 0;
|
|
10
|
+
const constants_1 = require("./constants");
|
|
11
|
+
const subjects_1 = require("./subjects");
|
|
12
|
+
const DEFAULT_NAK_DELAY_MS = 1_000;
|
|
13
|
+
class MemoryPubSub {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.subs = new Set();
|
|
16
|
+
}
|
|
17
|
+
async publish(subject, payload) {
|
|
18
|
+
for (const sub of [...this.subs])
|
|
19
|
+
if ((0, subjects_1.subjectMatches)(sub.filter, subject))
|
|
20
|
+
sub.handler({ subject, payload });
|
|
21
|
+
}
|
|
22
|
+
subscribe(filter, handler) {
|
|
23
|
+
const sub = { filter, handler };
|
|
24
|
+
this.subs.add(sub);
|
|
25
|
+
return { close: async () => { this.subs.delete(sub); } };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
class MemoryStreams {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.streams = new Map();
|
|
31
|
+
}
|
|
32
|
+
async ensureStream(spec) {
|
|
33
|
+
const existing = this.streams.get(spec.name);
|
|
34
|
+
if (existing)
|
|
35
|
+
existing.spec = spec;
|
|
36
|
+
else
|
|
37
|
+
this.streams.set(spec.name, { spec, messages: [], seq: 0, consumers: new Map(), wake: new Set() });
|
|
38
|
+
}
|
|
39
|
+
async ensureConsumer(stream, spec) {
|
|
40
|
+
const s = this.stream(stream);
|
|
41
|
+
const existing = s.consumers.get(spec.name);
|
|
42
|
+
if (existing) {
|
|
43
|
+
existing.spec = { ...existing.spec, filterSubjects: spec.filterSubjects };
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const floor = (spec.startAt ?? constants_1.START_AT.NEW) === constants_1.START_AT.ALL ? 0 : s.seq;
|
|
47
|
+
s.consumers.set(spec.name, { spec, floor, settled: new Set(), deliveries: new Map(), retryAt: new Map() });
|
|
48
|
+
}
|
|
49
|
+
async append(subject, payload) {
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
for (const s of this.streams.values()) {
|
|
52
|
+
if (!s.spec.subjects.some((f) => (0, subjects_1.subjectMatches)(f, subject)))
|
|
53
|
+
continue;
|
|
54
|
+
s.messages.push({ seq: ++s.seq, subject, payload, at: now });
|
|
55
|
+
s.messages = s.messages.filter((m) => now - m.at <= s.spec.maxAgeMs);
|
|
56
|
+
for (const wake of [...s.wake])
|
|
57
|
+
wake();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async consume(stream, consumer, handler, opts = {}) {
|
|
61
|
+
const s = this.stream(stream);
|
|
62
|
+
const c = s.consumers.get(consumer);
|
|
63
|
+
if (!c)
|
|
64
|
+
throw new Error(`stream ${stream} has no consumer ${consumer}; ensure it first`);
|
|
65
|
+
const nakDelayMs = opts.nakDelayMs ?? DEFAULT_NAK_DELAY_MS;
|
|
66
|
+
let open = true;
|
|
67
|
+
let running = false;
|
|
68
|
+
let timer;
|
|
69
|
+
const next = () => {
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
let waitMs;
|
|
72
|
+
for (const m of s.messages) {
|
|
73
|
+
if (m.seq <= c.floor || c.settled.has(m.seq))
|
|
74
|
+
continue;
|
|
75
|
+
if (!c.spec.filterSubjects.some((f) => (0, subjects_1.subjectMatches)(f, m.subject)))
|
|
76
|
+
continue;
|
|
77
|
+
const at = c.retryAt.get(m.seq);
|
|
78
|
+
if (at === undefined || at <= now)
|
|
79
|
+
return { message: m };
|
|
80
|
+
waitMs = Math.min(waitMs ?? Infinity, at - now);
|
|
81
|
+
}
|
|
82
|
+
return { waitMs };
|
|
83
|
+
};
|
|
84
|
+
const pump = async () => {
|
|
85
|
+
if (running || !open)
|
|
86
|
+
return;
|
|
87
|
+
running = true;
|
|
88
|
+
try {
|
|
89
|
+
for (let step = next(); open && step.message; step = next()) {
|
|
90
|
+
const m = step.message;
|
|
91
|
+
const deliveries = (c.deliveries.get(m.seq) ?? 0) + 1;
|
|
92
|
+
c.deliveries.set(m.seq, deliveries);
|
|
93
|
+
const outcome = await handler({ subject: m.subject, payload: m.payload, deliveries }).catch(() => constants_1.DELIVERY.NAK);
|
|
94
|
+
if (outcome === constants_1.DELIVERY.NAK) {
|
|
95
|
+
c.retryAt.set(m.seq, Date.now() + nakDelayMs);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
c.settled.add(m.seq);
|
|
99
|
+
c.retryAt.delete(m.seq);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const { waitMs } = next();
|
|
103
|
+
if (open && waitMs !== undefined) {
|
|
104
|
+
clearTimeout(timer);
|
|
105
|
+
timer = setTimeout(() => void pump(), Math.max(0, waitMs));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
running = false;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const wake = () => void pump();
|
|
113
|
+
s.wake.add(wake);
|
|
114
|
+
void pump();
|
|
115
|
+
return {
|
|
116
|
+
close: async () => {
|
|
117
|
+
open = false;
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
s.wake.delete(wake);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
stream(name) {
|
|
124
|
+
const s = this.streams.get(name);
|
|
125
|
+
if (!s)
|
|
126
|
+
throw new Error(`no stream ${name}; ensure it first`);
|
|
127
|
+
return s;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
class MemoryMessagingProvider {
|
|
131
|
+
constructor() {
|
|
132
|
+
this.name = 'memory';
|
|
133
|
+
this.pubsub = new MemoryPubSub();
|
|
134
|
+
this.streams = new MemoryStreams();
|
|
135
|
+
this.live = false;
|
|
136
|
+
}
|
|
137
|
+
get connected() {
|
|
138
|
+
return this.live;
|
|
139
|
+
}
|
|
140
|
+
async connect() {
|
|
141
|
+
this.live = true;
|
|
142
|
+
}
|
|
143
|
+
async disconnect() {
|
|
144
|
+
this.live = false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.MemoryMessagingProvider = MemoryMessagingProvider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JetStream rights scoped to named streams and one durable consumer: look up,
|
|
3
|
+
* create and update those streams, create, read and acknowledge through that
|
|
4
|
+
* consumer, and nothing else. Deleting or purging a stream is not granted.
|
|
5
|
+
*/
|
|
6
|
+
export interface JsScope {
|
|
7
|
+
streams: string[];
|
|
8
|
+
durable: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function jsPermissions({ streams, durable }: JsScope): {
|
|
11
|
+
publish: string[];
|
|
12
|
+
subscribe: string[];
|
|
13
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* JetStream rights scoped to named streams and one durable consumer: look up,
|
|
4
|
+
* create and update those streams, create, read and acknowledge through that
|
|
5
|
+
* consumer, and nothing else. Deleting or purging a stream is not granted.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.jsPermissions = jsPermissions;
|
|
9
|
+
function jsPermissions({ streams, durable }) {
|
|
10
|
+
const perStream = streams.flatMap((s) => [
|
|
11
|
+
`$JS.API.STREAM.INFO.${s}`,
|
|
12
|
+
`$JS.API.STREAM.CREATE.${s}`,
|
|
13
|
+
`$JS.API.STREAM.UPDATE.${s}`,
|
|
14
|
+
`$JS.API.CONSUMER.INFO.${s}.${durable}`,
|
|
15
|
+
`$JS.API.CONSUMER.CREATE.${s}.${durable}`,
|
|
16
|
+
`$JS.API.CONSUMER.CREATE.${s}.${durable}.>`,
|
|
17
|
+
`$JS.API.CONSUMER.DURABLE.CREATE.${s}.${durable}`,
|
|
18
|
+
`$JS.API.CONSUMER.MSG.NEXT.${s}.${durable}`,
|
|
19
|
+
`$JS.ACK.${s}.${durable}.>`,
|
|
20
|
+
]);
|
|
21
|
+
return { publish: ['$JS.API.INFO', ...perStream], subscribe: ['_INBOX.>'] };
|
|
22
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messaging on NATS. One connection carries pub/sub (core NATS subjects) and,
|
|
3
|
+
* when the server runs JetStream for this account, durable streams. Without
|
|
4
|
+
* JetStream the provider still serves pub/sub and reports no streams.
|
|
5
|
+
*/
|
|
6
|
+
import type { LTMessagingProvider, LTPubSub, LTStreams } from '../../../types/messaging';
|
|
7
|
+
export interface NatsMessagingOptions {
|
|
8
|
+
url: string;
|
|
9
|
+
/** Token auth, or user and password; neither for an open server. */
|
|
10
|
+
token?: string;
|
|
11
|
+
user?: string;
|
|
12
|
+
password?: string;
|
|
13
|
+
/** The connection's name on the server. */
|
|
14
|
+
name?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class NatsMessagingProvider implements LTMessagingProvider {
|
|
17
|
+
private readonly opts;
|
|
18
|
+
readonly name = "nats";
|
|
19
|
+
readonly pubsub: LTPubSub;
|
|
20
|
+
private nc;
|
|
21
|
+
private durable;
|
|
22
|
+
constructor(opts: NatsMessagingOptions);
|
|
23
|
+
get connected(): boolean;
|
|
24
|
+
get streams(): LTStreams | null;
|
|
25
|
+
connect(): Promise<void>;
|
|
26
|
+
disconnect(): Promise<void>;
|
|
27
|
+
/** Streams when the account has JetStream; null otherwise, and pub/sub still serves. */
|
|
28
|
+
private jetStream;
|
|
29
|
+
private connection;
|
|
30
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Messaging on NATS. One connection carries pub/sub (core NATS subjects) and,
|
|
4
|
+
* when the server runs JetStream for this account, durable streams. Without
|
|
5
|
+
* JetStream the provider still serves pub/sub and reports no streams.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.NatsMessagingProvider = void 0;
|
|
9
|
+
const nats_1 = require("nats");
|
|
10
|
+
const logger_1 = require("../../logger");
|
|
11
|
+
const constants_1 = require("../constants");
|
|
12
|
+
const streams_1 = require("./streams");
|
|
13
|
+
class NatsPubSub {
|
|
14
|
+
constructor(nc) {
|
|
15
|
+
this.nc = nc;
|
|
16
|
+
}
|
|
17
|
+
async publish(subject, payload) {
|
|
18
|
+
this.nc().publish(subject, payload);
|
|
19
|
+
}
|
|
20
|
+
subscribe(filter, handler) {
|
|
21
|
+
const sub = this.nc().subscribe(filter, {
|
|
22
|
+
callback: (err, m) => { if (!err)
|
|
23
|
+
handler({ subject: m.subject, payload: (0, streams_1.payloadOf)(m) }); },
|
|
24
|
+
});
|
|
25
|
+
return { close: async () => { sub.unsubscribe(); } };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
class NatsMessagingProvider {
|
|
29
|
+
constructor(opts) {
|
|
30
|
+
this.opts = opts;
|
|
31
|
+
this.name = 'nats';
|
|
32
|
+
this.pubsub = new NatsPubSub(() => this.connection());
|
|
33
|
+
this.nc = null;
|
|
34
|
+
this.durable = null;
|
|
35
|
+
}
|
|
36
|
+
get connected() {
|
|
37
|
+
return !!this.nc && !this.nc.isClosed();
|
|
38
|
+
}
|
|
39
|
+
get streams() {
|
|
40
|
+
return this.durable;
|
|
41
|
+
}
|
|
42
|
+
async connect() {
|
|
43
|
+
if (this.connected)
|
|
44
|
+
return;
|
|
45
|
+
const { url, token, user, password, name } = this.opts;
|
|
46
|
+
this.nc = await (0, nats_1.connect)({ servers: url, token, user, pass: password, name });
|
|
47
|
+
this.durable = await this.jetStream(this.nc);
|
|
48
|
+
}
|
|
49
|
+
async disconnect() {
|
|
50
|
+
if (!this.nc)
|
|
51
|
+
return;
|
|
52
|
+
await this.nc.drain();
|
|
53
|
+
this.nc = null;
|
|
54
|
+
this.durable = null;
|
|
55
|
+
}
|
|
56
|
+
/** Streams when the account has JetStream; null otherwise, and pub/sub still serves. */
|
|
57
|
+
async jetStream(nc) {
|
|
58
|
+
try {
|
|
59
|
+
const jsm = await nc.jetstreamManager();
|
|
60
|
+
await jsm.getAccountInfo();
|
|
61
|
+
return new streams_1.NatsStreams(jsm, nc.jetstream());
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const reason = String(err?.message ?? err?.code ?? err);
|
|
65
|
+
if (!/jetstream not enabled|503|no responders/i.test(reason)) {
|
|
66
|
+
logger_1.loggerRegistry.warn(`${constants_1.MESSAGING_LOG.STREAMS_UNAVAILABLE} provider=${this.name} reason=${reason}`);
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
connection() {
|
|
72
|
+
if (!this.nc)
|
|
73
|
+
throw new Error('NATS messaging is not connected; call connect() first');
|
|
74
|
+
return this.nc;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.NatsMessagingProvider = NatsMessagingProvider;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Long Tail's NATS server, rendered. Accounts keep traffic apart:
|
|
3
|
+
*
|
|
4
|
+
* - LT: Long Tail itself. It owns the durable streams and imports each edge's
|
|
5
|
+
* subjects, which its streams can then keep.
|
|
6
|
+
* - one edge account per line: the site broker's bridge logs in here (MQTT
|
|
7
|
+
* only) and may publish its line's subjects and nothing else. The account
|
|
8
|
+
* exports exactly those subjects, so nothing of Long Tail's is reachable.
|
|
9
|
+
* - SYS: the server's own monitoring.
|
|
10
|
+
*
|
|
11
|
+
* NATS configuration accepts JSON, so accounts are written as JSON.
|
|
12
|
+
*/
|
|
13
|
+
export interface NatsPermissions {
|
|
14
|
+
publish?: string[] | {
|
|
15
|
+
allow?: string[];
|
|
16
|
+
deny?: string[];
|
|
17
|
+
};
|
|
18
|
+
subscribe?: string[] | {
|
|
19
|
+
allow?: string[];
|
|
20
|
+
deny?: string[];
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface NatsUser {
|
|
24
|
+
user: string;
|
|
25
|
+
password?: string;
|
|
26
|
+
permissions?: NatsPermissions;
|
|
27
|
+
allowed_connection_types?: string[];
|
|
28
|
+
}
|
|
29
|
+
/** A line's edge: who logs in for it, and the subjects it may publish (e.g. `line.v1.site-1.line-1.>`). */
|
|
30
|
+
export interface EdgeAccount {
|
|
31
|
+
name: string;
|
|
32
|
+
subjects: string;
|
|
33
|
+
users: NatsUser[];
|
|
34
|
+
}
|
|
35
|
+
export interface NatsConfOptions {
|
|
36
|
+
serverName: string;
|
|
37
|
+
port?: number;
|
|
38
|
+
httpPort?: number;
|
|
39
|
+
jetstream?: {
|
|
40
|
+
storeDir: string;
|
|
41
|
+
};
|
|
42
|
+
/** WebSocket listener for browsers; `noAuthUser` maps a connection without credentials to that LT user. */
|
|
43
|
+
websocket?: {
|
|
44
|
+
port: number;
|
|
45
|
+
noTls?: boolean;
|
|
46
|
+
noAuthUser?: string;
|
|
47
|
+
};
|
|
48
|
+
/** MQTT listener for edge bridges; with `tls`, certificates map to users by their subject. */
|
|
49
|
+
mqtt?: {
|
|
50
|
+
port: number;
|
|
51
|
+
tls?: {
|
|
52
|
+
certFile: string;
|
|
53
|
+
keyFile: string;
|
|
54
|
+
caFile: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
lt: {
|
|
58
|
+
users: NatsUser[];
|
|
59
|
+
};
|
|
60
|
+
edges: EdgeAccount[];
|
|
61
|
+
system?: {
|
|
62
|
+
user: string;
|
|
63
|
+
password: string;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export declare const LT_ACCOUNT = "LT";
|
|
67
|
+
export declare const SYS_ACCOUNT = "SYS";
|
|
68
|
+
export declare function renderNatsConf(opts: NatsConfOptions): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Long Tail's NATS server, rendered. Accounts keep traffic apart:
|
|
4
|
+
*
|
|
5
|
+
* - LT: Long Tail itself. It owns the durable streams and imports each edge's
|
|
6
|
+
* subjects, which its streams can then keep.
|
|
7
|
+
* - one edge account per line: the site broker's bridge logs in here (MQTT
|
|
8
|
+
* only) and may publish its line's subjects and nothing else. The account
|
|
9
|
+
* exports exactly those subjects, so nothing of Long Tail's is reachable.
|
|
10
|
+
* - SYS: the server's own monitoring.
|
|
11
|
+
*
|
|
12
|
+
* NATS configuration accepts JSON, so accounts are written as JSON.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SYS_ACCOUNT = exports.LT_ACCOUNT = void 0;
|
|
16
|
+
exports.renderNatsConf = renderNatsConf;
|
|
17
|
+
exports.LT_ACCOUNT = 'LT';
|
|
18
|
+
exports.SYS_ACCOUNT = 'SYS';
|
|
19
|
+
function accounts(opts) {
|
|
20
|
+
const out = {
|
|
21
|
+
[exports.LT_ACCOUNT]: {
|
|
22
|
+
jetstream: opts.jetstream ? 'enabled' : 'disabled',
|
|
23
|
+
users: opts.lt.users,
|
|
24
|
+
imports: opts.edges.map((e) => ({ stream: { account: e.name, subject: e.subjects } })),
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
for (const edge of opts.edges) {
|
|
28
|
+
// The edge account has JetStream because NATS keeps MQTT session state there.
|
|
29
|
+
out[edge.name] = { jetstream: opts.jetstream ? 'enabled' : 'disabled', users: edge.users, exports: [{ stream: edge.subjects }] };
|
|
30
|
+
}
|
|
31
|
+
if (opts.system)
|
|
32
|
+
out[exports.SYS_ACCOUNT] = { users: [opts.system] };
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
function renderNatsConf(opts) {
|
|
36
|
+
const lines = [
|
|
37
|
+
'# Rendered by Long Tail (lib/messaging/nats/render-conf.ts). Do not edit by hand.',
|
|
38
|
+
`server_name: ${JSON.stringify(opts.serverName)}`,
|
|
39
|
+
`port: ${opts.port ?? 4222}`,
|
|
40
|
+
`http: ${opts.httpPort ?? 8222}`,
|
|
41
|
+
];
|
|
42
|
+
if (opts.jetstream)
|
|
43
|
+
lines.push(`jetstream { store_dir: ${JSON.stringify(opts.jetstream.storeDir)} }`);
|
|
44
|
+
if (opts.websocket) {
|
|
45
|
+
const ws = opts.websocket;
|
|
46
|
+
lines.push(`websocket { port: ${ws.port}${ws.noTls ? ', no_tls: true, same_origin: false' : ''}${ws.noAuthUser ? `, no_auth_user: ${JSON.stringify(ws.noAuthUser)}` : ''} }`);
|
|
47
|
+
}
|
|
48
|
+
if (opts.mqtt) {
|
|
49
|
+
const tls = opts.mqtt.tls;
|
|
50
|
+
lines.push(tls
|
|
51
|
+
? `mqtt { port: ${opts.mqtt.port}, tls { cert_file: ${JSON.stringify(tls.certFile)}, key_file: ${JSON.stringify(tls.keyFile)}, ca_file: ${JSON.stringify(tls.caFile)}, verify_and_map: true, timeout: 5 } }`
|
|
52
|
+
: `mqtt { port: ${opts.mqtt.port} }`);
|
|
53
|
+
}
|
|
54
|
+
lines.push(`accounts: ${JSON.stringify(accounts(opts), null, 2)}`);
|
|
55
|
+
if (opts.system)
|
|
56
|
+
lines.push(`system_account: ${exports.SYS_ACCOUNT}`);
|
|
57
|
+
return `${lines.join('\n')}\n`;
|
|
58
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable streams on JetStream. A spec becomes a file-backed stream or an
|
|
3
|
+
* explicit-ack durable consumer; ensuring either is safe on every boot, and an
|
|
4
|
+
* existing consumer keeps its position while its subjects follow the spec.
|
|
5
|
+
*/
|
|
6
|
+
import { type ConsumerConfig, type JetStreamClient, type JetStreamManager, type StreamConfig } from 'nats';
|
|
7
|
+
import type { ConsumerSpec, Delivery, LTConsumeOptions, LTStreamMessage, LTStreams, LTSubscription, StreamSpec, Subject } from '../../../types/messaging';
|
|
8
|
+
export declare function streamConfig(spec: StreamSpec): Partial<StreamConfig>;
|
|
9
|
+
export declare function consumerConfig(spec: ConsumerSpec): Partial<ConsumerConfig>;
|
|
10
|
+
/** Create the stream, or update an existing one to the spec. */
|
|
11
|
+
export declare function ensureStream(jsm: JetStreamManager, spec: StreamSpec): Promise<void>;
|
|
12
|
+
/** Create the consumer, or move an existing one to the spec's subjects without losing its place. */
|
|
13
|
+
export declare function ensureConsumer(jsm: JetStreamManager, stream: string, spec: ConsumerSpec): Promise<void>;
|
|
14
|
+
export declare function payloadOf(m: {
|
|
15
|
+
data: Uint8Array;
|
|
16
|
+
}): string;
|
|
17
|
+
export declare class NatsStreams implements LTStreams {
|
|
18
|
+
private readonly jsm;
|
|
19
|
+
private readonly js;
|
|
20
|
+
constructor(jsm: JetStreamManager, js: JetStreamClient);
|
|
21
|
+
ensureStream(spec: StreamSpec): Promise<void>;
|
|
22
|
+
ensureConsumer(stream: string, spec: ConsumerSpec): Promise<void>;
|
|
23
|
+
append(subject: Subject, payload: string): Promise<void>;
|
|
24
|
+
/** One message at a time: the next is not taken until the handler settles this one. */
|
|
25
|
+
consume(stream: string, consumer: string, handler: (m: LTStreamMessage) => Promise<Delivery>, opts?: LTConsumeOptions): Promise<LTSubscription>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Durable streams on JetStream. A spec becomes a file-backed stream or an
|
|
4
|
+
* explicit-ack durable consumer; ensuring either is safe on every boot, and an
|
|
5
|
+
* existing consumer keeps its position while its subjects follow the spec.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.NatsStreams = void 0;
|
|
9
|
+
exports.streamConfig = streamConfig;
|
|
10
|
+
exports.consumerConfig = consumerConfig;
|
|
11
|
+
exports.ensureStream = ensureStream;
|
|
12
|
+
exports.ensureConsumer = ensureConsumer;
|
|
13
|
+
exports.payloadOf = payloadOf;
|
|
14
|
+
const nats_1 = require("nats");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
16
|
+
const DEFAULT_ACK_WAIT_MS = 30_000;
|
|
17
|
+
const DEFAULT_NAK_DELAY_MS = 1_000;
|
|
18
|
+
function streamConfig(spec) {
|
|
19
|
+
return { name: spec.name, subjects: spec.subjects, max_age: (0, nats_1.nanos)(spec.maxAgeMs), storage: nats_1.StorageType.File };
|
|
20
|
+
}
|
|
21
|
+
function consumerConfig(spec) {
|
|
22
|
+
return {
|
|
23
|
+
durable_name: spec.name,
|
|
24
|
+
ack_policy: nats_1.AckPolicy.Explicit,
|
|
25
|
+
deliver_policy: (spec.startAt ?? constants_1.START_AT.NEW) === constants_1.START_AT.ALL ? nats_1.DeliverPolicy.All : nats_1.DeliverPolicy.New,
|
|
26
|
+
ack_wait: (0, nats_1.nanos)(spec.ackWaitMs ?? DEFAULT_ACK_WAIT_MS),
|
|
27
|
+
filter_subjects: spec.filterSubjects,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Create the stream, or update an existing one to the spec. */
|
|
31
|
+
async function ensureStream(jsm, spec) {
|
|
32
|
+
const config = streamConfig(spec);
|
|
33
|
+
try {
|
|
34
|
+
await jsm.streams.info(spec.name);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (!/stream not found/i.test(err?.message ?? ''))
|
|
38
|
+
throw err;
|
|
39
|
+
await jsm.streams.add(config);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
await jsm.streams.update(spec.name, config);
|
|
43
|
+
}
|
|
44
|
+
/** Create the consumer, or move an existing one to the spec's subjects without losing its place. */
|
|
45
|
+
async function ensureConsumer(jsm, stream, spec) {
|
|
46
|
+
let existing;
|
|
47
|
+
try {
|
|
48
|
+
existing = await jsm.consumers.info(stream, spec.name);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (!/consumer not found/i.test(err?.message ?? ''))
|
|
52
|
+
throw err;
|
|
53
|
+
await jsm.consumers.add(stream, consumerConfig(spec));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const want = [...spec.filterSubjects].sort();
|
|
57
|
+
const have = [...(existing.config.filter_subjects ?? [])].sort();
|
|
58
|
+
if (want.join('|') !== have.join('|'))
|
|
59
|
+
await jsm.consumers.update(stream, spec.name, { filter_subjects: spec.filterSubjects });
|
|
60
|
+
}
|
|
61
|
+
function payloadOf(m) {
|
|
62
|
+
return Buffer.from(m.data).toString('utf8');
|
|
63
|
+
}
|
|
64
|
+
class NatsStreams {
|
|
65
|
+
constructor(jsm, js) {
|
|
66
|
+
this.jsm = jsm;
|
|
67
|
+
this.js = js;
|
|
68
|
+
}
|
|
69
|
+
ensureStream(spec) {
|
|
70
|
+
return ensureStream(this.jsm, spec);
|
|
71
|
+
}
|
|
72
|
+
ensureConsumer(stream, spec) {
|
|
73
|
+
return ensureConsumer(this.jsm, stream, spec);
|
|
74
|
+
}
|
|
75
|
+
async append(subject, payload) {
|
|
76
|
+
await this.js.publish(subject, payload);
|
|
77
|
+
}
|
|
78
|
+
/** One message at a time: the next is not taken until the handler settles this one. */
|
|
79
|
+
async consume(stream, consumer, handler, opts = {}) {
|
|
80
|
+
const nakDelayMs = opts.nakDelayMs ?? DEFAULT_NAK_DELAY_MS;
|
|
81
|
+
const messages = await (await this.js.consumers.get(stream, consumer)).consume();
|
|
82
|
+
void (async () => {
|
|
83
|
+
for await (const m of messages) {
|
|
84
|
+
const delivery = await handler({ subject: m.subject, payload: payloadOf(m), deliveries: m.info.deliveryCount })
|
|
85
|
+
.catch(() => constants_1.DELIVERY.NAK);
|
|
86
|
+
if (delivery === constants_1.DELIVERY.ACK)
|
|
87
|
+
m.ack();
|
|
88
|
+
else if (delivery === constants_1.DELIVERY.NAK)
|
|
89
|
+
m.nak(nakDelayMs);
|
|
90
|
+
else
|
|
91
|
+
m.term();
|
|
92
|
+
}
|
|
93
|
+
})();
|
|
94
|
+
return { close: async () => { await messages.close(); } };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.NatsStreams = NatsStreams;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subject filters. Subjects are dot-separated tokens; in a filter `*` matches
|
|
3
|
+
* exactly one token and `>` matches one or more trailing tokens.
|
|
4
|
+
*/
|
|
5
|
+
import type { Subject } from '../../types/messaging';
|
|
6
|
+
export declare function subjectMatches(filter: Subject, subject: Subject): boolean;
|
|
7
|
+
/** Whether `subject` is a valid concrete subject: nonempty tokens, no wildcards or whitespace. */
|
|
8
|
+
export declare function isSubject(subject: string): boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Subject filters. Subjects are dot-separated tokens; in a filter `*` matches
|
|
4
|
+
* exactly one token and `>` matches one or more trailing tokens.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.subjectMatches = subjectMatches;
|
|
8
|
+
exports.isSubject = isSubject;
|
|
9
|
+
function subjectMatches(filter, subject) {
|
|
10
|
+
const f = filter.split('.');
|
|
11
|
+
const s = subject.split('.');
|
|
12
|
+
for (let i = 0; i < f.length; i++) {
|
|
13
|
+
if (f[i] === '>')
|
|
14
|
+
return i === f.length - 1 && s.length > i;
|
|
15
|
+
if (i >= s.length)
|
|
16
|
+
return false;
|
|
17
|
+
if (f[i] !== '*' && f[i] !== s[i])
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return f.length === s.length;
|
|
21
|
+
}
|
|
22
|
+
/** Whether `subject` is a valid concrete subject: nonempty tokens, no wildcards or whitespace. */
|
|
23
|
+
function isSubject(subject) {
|
|
24
|
+
return !!subject && subject.split('.').every((t) => !!t && !/[\s*>]/.test(t));
|
|
25
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The running machine surface, for settings and the machines API. Set by
|
|
3
|
+
* start() when the config declares lines; absent otherwise, so a deployment
|
|
4
|
+
* without machines serves no lines and no Lines view.
|
|
5
|
+
*/
|
|
6
|
+
import type { LineSurface } from '../services/machines/surface';
|
|
7
|
+
export declare function registerMachineSurface(next: LineSurface | null): void;
|
|
8
|
+
export declare function getMachineSurface(): LineSurface | null;
|