@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.
- package/README.md +9 -2
- package/build/api/settings.d.ts +4 -1
- package/build/api/settings.js +7 -1
- package/build/index.js +9 -4
- 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/publish.d.ts +33 -0
- package/build/lib/events/publish.js +52 -1
- 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 +8 -0
- package/build/lib/machines/protocol/codec.js +9 -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 +2 -2
- 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 +9 -2
- package/build/lib/machines/site/site-conf.js +27 -8
- 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/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 +1 -0
- package/build/lib/machines/transport/nats-bus.js +3 -0
- package/build/lib/machines/transport/nats-feed.d.ts +1 -0
- package/build/lib/machines/transport/nats-feed.js +4 -1
- package/build/lib/machines/transport/pubsub-feed.d.ts +1 -0
- package/build/lib/machines/transport/pubsub-feed.js +4 -1
- package/build/lib/machines/transport/stream-bus.d.ts +2 -0
- package/build/lib/machines/transport/stream-bus.js +5 -1
- 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/services/machines/commands.d.ts +5 -5
- package/build/services/machines/commands.js +3 -2
- package/build/services/machines/config.d.ts +2 -1
- package/build/services/machines/config.js +1 -1
- package/build/services/machines/contracts.d.ts +10 -0
- package/build/services/machines/gateway/actions.d.ts +1 -0
- 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 +3 -0
- package/build/services/machines/gateway/dispatcher.js +12 -4
- package/build/services/machines/gateway/executor.d.ts +11 -2
- package/build/services/machines/gateway/executor.js +68 -29
- package/build/services/machines/gateway/gateway.d.ts +16 -1
- package/build/services/machines/gateway/gateway.js +55 -23
- 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/log.d.ts +8 -0
- package/build/services/machines/gateway/log.js +18 -0
- package/build/services/machines/gateway/pacing.js +1 -0
- package/build/services/machines/gateway/plan-escalation.js +8 -3
- package/build/services/machines/gateway/plan-machine.js +16 -6
- 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.js +3 -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 +29 -3
- package/build/services/machines/gateway/state.js +61 -7
- 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/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 +10 -1
- package/build/services/machines/surface.d.ts +45 -5
- package/build/services/machines/surface.js +95 -15
- package/build/start/apply-report.d.ts +1 -1
- package/build/start/apply-report.js +3 -25
- package/build/start/index.js +16 -4
- 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 +1 -0
- package/build/types/machines-view.d.ts +159 -0
- package/build/types/machines-view.js +7 -0
- package/build/types/machines.d.ts +4 -0
- 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 +34 -1
- package/docs/machines.md +93 -16
- package/docs/mcp.md +19 -0
- package/package.json +1 -1
- 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
|
@@ -7,19 +7,31 @@
|
|
|
7
7
|
import { type LineDef } from '../../../lib/machines/line';
|
|
8
8
|
import type { Inspection } from '../../../lib/machines/protocol';
|
|
9
9
|
import { type Disposition, type InboundMessage } from '../../../lib/machines/transport';
|
|
10
|
+
import type { WireAction } from '../../../types/machines-view';
|
|
10
11
|
import type { Action } from './actions';
|
|
11
12
|
import { type GatewayLog } from './log';
|
|
12
13
|
import type { GatewayState } from './state';
|
|
13
|
-
/** What handling one decoded message came to. */
|
|
14
|
+
/** What handling one decoded message came to, with what the gateway did for the wire record. */
|
|
14
15
|
export interface Applied {
|
|
15
16
|
disposition: Disposition;
|
|
16
17
|
failed: boolean;
|
|
18
|
+
actions: WireAction[];
|
|
19
|
+
/** The address the message came from, when it was not admitted as a station's. */
|
|
20
|
+
sender?: {
|
|
21
|
+
machineId: string | null;
|
|
22
|
+
address: string | null;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** A message admitted as a station's, with what admitting it did (a binding, say). */
|
|
26
|
+
export interface Admitted {
|
|
27
|
+
seen: Inspection;
|
|
28
|
+
actions: WireAction[];
|
|
17
29
|
}
|
|
18
30
|
export interface AdmissionContext {
|
|
19
31
|
state: GatewayState;
|
|
20
32
|
line: LineDef;
|
|
21
33
|
executor: {
|
|
22
|
-
apply(actions: Action[]): Promise<
|
|
34
|
+
apply(actions: Action[]): Promise<WireAction[]>;
|
|
23
35
|
};
|
|
24
36
|
log: GatewayLog;
|
|
25
37
|
/** Send waiting handoffs that may now go out. */
|
|
@@ -30,6 +42,6 @@ export interface AdmissionContext {
|
|
|
30
42
|
* bound and its waiting work goes out; a contested claim raises one row for a
|
|
31
43
|
* person; either of those, and an address no station claims, is not acted on.
|
|
32
44
|
*/
|
|
33
|
-
export declare function admitSender(ctx: AdmissionContext, topic: string, raw: Inspection): Promise<
|
|
45
|
+
export declare function admitSender(ctx: AdmissionContext, topic: string, raw: Inspection): Promise<Admitted | Applied>;
|
|
34
46
|
/** Under a strict codec a broken message is not acted on: a person sees it on a row, once. */
|
|
35
47
|
export declare function holdViolation(ctx: AdmissionContext, msg: InboundMessage, seen: Inspection): Promise<Applied>;
|
|
@@ -11,8 +11,12 @@ exports.holdViolation = holdViolation;
|
|
|
11
11
|
const contracts_1 = require("../contracts");
|
|
12
12
|
const line_1 = require("../../../lib/machines/line");
|
|
13
13
|
const transport_1 = require("../../../lib/machines/transport");
|
|
14
|
+
const dispatcher_1 = require("./dispatcher");
|
|
14
15
|
const log_1 = require("./log");
|
|
15
16
|
const registration_1 = require("./registration");
|
|
17
|
+
function from(sender) {
|
|
18
|
+
return { machineId: sender.machineId ?? null, address: sender.address };
|
|
19
|
+
}
|
|
16
20
|
/**
|
|
17
21
|
* The station a message is from (registration.ts). A newly claimed station is
|
|
18
22
|
* bound and its waiting work goes out; a contested claim raises one row for a
|
|
@@ -20,47 +24,58 @@ const registration_1 = require("./registration");
|
|
|
20
24
|
*/
|
|
21
25
|
async function admitSender(ctx, topic, raw) {
|
|
22
26
|
const sender = (0, registration_1.resolveSender)(ctx.state, ctx.line, raw);
|
|
27
|
+
const actions = [];
|
|
23
28
|
try {
|
|
24
29
|
if (sender.status === registration_1.SENDER.BOUND) {
|
|
25
|
-
await ctx.executor.apply([{ kind: 'bindAddress', machineId: sender.machineId, address: sender.address }]);
|
|
30
|
+
actions.push(...await ctx.executor.apply([{ kind: 'bindAddress', machineId: sender.machineId, address: sender.address }]));
|
|
26
31
|
await ctx.pace();
|
|
27
32
|
}
|
|
28
33
|
if (sender.seen)
|
|
29
|
-
return sender.seen;
|
|
34
|
+
return { seen: sender.seen, actions };
|
|
30
35
|
if (sender.status === registration_1.SENDER.CONTESTED)
|
|
31
36
|
ctx.state.hearClaim(sender.address, sender.machineId);
|
|
32
37
|
if (sender.status === registration_1.SENDER.CONTESTED && !ctx.state.claimRaised(sender.address, sender.machineId)) {
|
|
33
|
-
await ctx.executor.apply([{ kind: 'createRow', row: (0, registration_1.registrationRow)(ctx.state, ctx.line, sender.address, sender.machineId) }]);
|
|
34
|
-
ctx.state.raiseClaim(sender.address, sender.machineId);
|
|
38
|
+
const [made] = await ctx.executor.apply([{ kind: 'createRow', row: (0, registration_1.registrationRow)(ctx.state, ctx.line, sender.address, sender.machineId) }]);
|
|
39
|
+
ctx.state.raiseClaim(sender.address, sender.machineId, made?.rowId);
|
|
35
40
|
ctx.log.warn(log_1.GATEWAY_LOG.ADDRESS_CONTESTED, { topic, address: sender.address, machine: sender.machineId });
|
|
41
|
+
actions.push({ ...made, detail: `${sender.address} says it is ${sender.machineId}; a person decides` });
|
|
42
|
+
}
|
|
43
|
+
else if (sender.status === registration_1.SENDER.CONTESTED) {
|
|
44
|
+
actions.push({ verb: 'none', detail: `${sender.address} says it is ${sender.machineId}; waiting for a person` });
|
|
45
|
+
}
|
|
46
|
+
if (sender.status === registration_1.SENDER.UNKNOWN) {
|
|
47
|
+
if (ctx.state.firstHeardStranger(sender.address))
|
|
48
|
+
ctx.log.warn(log_1.GATEWAY_LOG.ADDRESS_UNKNOWN, { topic, address: sender.address });
|
|
49
|
+
actions.push({ verb: 'none', detail: `${sender.address} claims no station on this line` });
|
|
36
50
|
}
|
|
37
|
-
|
|
38
|
-
ctx.log.warn(log_1.GATEWAY_LOG.ADDRESS_UNKNOWN, { topic, address: sender.address });
|
|
39
|
-
return { disposition: transport_1.DISPOSITION.ACK, failed: false };
|
|
51
|
+
return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions, sender: from(sender) };
|
|
40
52
|
}
|
|
41
53
|
catch (err) {
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
if (!(err instanceof dispatcher_1.GatewayStopped))
|
|
55
|
+
ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic, error: err.message });
|
|
56
|
+
return { disposition: transport_1.DISPOSITION.NAK, failed: true, actions, sender: from(sender) };
|
|
44
57
|
}
|
|
45
58
|
}
|
|
46
59
|
/** Under a strict codec a broken message is not acted on: a person sees it on a row, once. */
|
|
47
60
|
async function holdViolation(ctx, msg, seen) {
|
|
48
61
|
const { ident, kind } = seen.parsed;
|
|
49
62
|
const key = seen.receiptId ?? seen.body?.id ?? `${msg.topic}:${msg.payload}`;
|
|
63
|
+
const detail = seen.violations.join('; ');
|
|
50
64
|
if (ctx.state.violationRaised(key))
|
|
51
|
-
return { disposition: transport_1.DISPOSITION.ACK, failed: false };
|
|
65
|
+
return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions: [{ verb: 'hold', detail: `${detail} (already shown to a person)` }] };
|
|
52
66
|
try {
|
|
53
|
-
await ctx.executor.apply([{ kind: 'createRow', row: {
|
|
67
|
+
const [made] = await ctx.executor.apply([{ kind: 'createRow', row: {
|
|
54
68
|
type: contracts_1.ROW_TYPE.CONTRACT_VIOLATION, role: (0, line_1.operatorRole)(ctx.line), priority: 2,
|
|
55
69
|
description: `${ident.machineId} sent a ${kind} message that breaks the contract: ${seen.violations.join('; ')}`,
|
|
56
70
|
metadata: { siteId: ident.siteId, lineId: ident.lineId, machineId: ident.machineId, kind, topic: msg.topic, messageId: seen.body?.id ?? null, violations: seen.violations },
|
|
57
71
|
escalation_payload: msg.payload,
|
|
58
72
|
} }]);
|
|
59
73
|
ctx.state.raiseViolation(key);
|
|
60
|
-
return { disposition: transport_1.DISPOSITION.ACK, failed: false };
|
|
74
|
+
return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions: [{ verb: 'hold', rowId: made?.rowId, detail }] };
|
|
61
75
|
}
|
|
62
76
|
catch (err) {
|
|
63
|
-
|
|
64
|
-
|
|
77
|
+
if (!(err instanceof dispatcher_1.GatewayStopped))
|
|
78
|
+
ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic: msg.topic, error: err.message });
|
|
79
|
+
return { disposition: transport_1.DISPOSITION.NAK, failed: true, actions: [] };
|
|
65
80
|
}
|
|
66
81
|
}
|
|
@@ -17,6 +17,7 @@ import { type LineEscalations } from './escalations';
|
|
|
17
17
|
import { type GatewayLog } from './log';
|
|
18
18
|
import type { CommandReply, ReplyWaiter } from './reply-waiter';
|
|
19
19
|
import { type GatewayState } from './state';
|
|
20
|
+
import type { WireRecorder } from './wire';
|
|
20
21
|
export interface DispatcherDeps {
|
|
21
22
|
bus: MachineBus;
|
|
22
23
|
codec: LineCodec;
|
|
@@ -27,6 +28,8 @@ export interface DispatcherDeps {
|
|
|
27
28
|
replyTimeoutMs: number;
|
|
28
29
|
dispatchAttempts: number;
|
|
29
30
|
log: GatewayLog;
|
|
31
|
+
/** Records each command the gateway sends, for the line's wire view. */
|
|
32
|
+
wire?: Pick<WireRecorder, 'command'>;
|
|
30
33
|
}
|
|
31
34
|
type DispatchAction = Extract<Action, {
|
|
32
35
|
kind: 'dispatch';
|
|
@@ -30,6 +30,10 @@ function fromMachine(reply) {
|
|
|
30
30
|
function took(reply) {
|
|
31
31
|
return reply?.status === protocol_1.REPLY_STATUS.ACCEPTED || reply?.status === protocol_1.REPLY_STATUS.COMPLETED;
|
|
32
32
|
}
|
|
33
|
+
/** The reply's structured code for a resolution, when it carried one. */
|
|
34
|
+
function withCode(reply) {
|
|
35
|
+
return reply.code ? { code: reply.code } : {};
|
|
36
|
+
}
|
|
33
37
|
/** Most command ids whose sends are counted; the oldest are forgotten first. */
|
|
34
38
|
const SENT_REMEMBERED = 10_000;
|
|
35
39
|
/** Ends a dispatch or command still running when the gateway stops; the next leader takes it up from the row. */
|
|
@@ -65,9 +69,13 @@ class Dispatcher {
|
|
|
65
69
|
/** False when the codec has no message for the command. `since` is when the command's row was created. */
|
|
66
70
|
async publish(machineId, op, cmdId, args, since) {
|
|
67
71
|
this.live();
|
|
68
|
-
const
|
|
69
|
-
|
|
72
|
+
const ident = (0, registration_1.identFor)(this.d.state, this.d.line, machineId);
|
|
73
|
+
const command = { cmdId, op, args, ...this.countSend(cmdId, since) };
|
|
74
|
+
const wires = this.d.codec.encode(ident, command);
|
|
75
|
+
for (const wire of wires) {
|
|
70
76
|
await this.d.bus.publish(wire.topic, wire.payload);
|
|
77
|
+
this.d.wire?.command(ident, command, wire);
|
|
78
|
+
}
|
|
71
79
|
return wires.length > 0;
|
|
72
80
|
}
|
|
73
81
|
/** Publish and wait for the reply, asking again with the same id; null when none came. */
|
|
@@ -111,7 +119,7 @@ class Dispatcher {
|
|
|
111
119
|
await (0, promises_1.setTimeout)(expiresAt - Date.now() + 1, undefined, { signal: this.stopping.signal }).catch(() => undefined);
|
|
112
120
|
this.live();
|
|
113
121
|
const outcome = reply
|
|
114
|
-
? { accepted: reply.status === protocol_1.REPLY_STATUS.ACCEPTED, machineId: a.machineId, op: a.op, status: reply.status, reason: reply.reason }
|
|
122
|
+
? { accepted: reply.status === protocol_1.REPLY_STATUS.ACCEPTED, machineId: a.machineId, op: a.op, status: reply.status, reason: reply.reason, ...withCode(reply) }
|
|
115
123
|
: { accepted: false, machineId: a.machineId, op: a.op, status: contracts_1.COMMAND_STATUS.NO_REPLY, reason: `no reply after ${this.d.dispatchAttempts} attempts` };
|
|
116
124
|
const context = { row: a.rowId, machine: a.machineId, op: a.op, status: outcome.status, reason: outcome.reason };
|
|
117
125
|
if (outcome.accepted)
|
|
@@ -158,7 +166,7 @@ class Dispatcher {
|
|
|
158
166
|
row.dispatch = state_1.DISPATCH_STATE.REFUSED;
|
|
159
167
|
const unanswered = `${a.machineId} sent no reply after ${this.d.dispatchAttempts} attempts`;
|
|
160
168
|
const resolution = refused
|
|
161
|
-
? { received: false, errorCode: contracts_1.HANDOFF_ERROR.DISPATCH_REFUSED, detail: `${a.machineId} ${refused.status}: ${refused.reason}
|
|
169
|
+
? { received: false, errorCode: contracts_1.HANDOFF_ERROR.DISPATCH_REFUSED, detail: `${a.machineId} ${refused.status}: ${refused.reason}`, ...withCode(refused) }
|
|
162
170
|
: { received: false, errorCode: contracts_1.HANDOFF_ERROR.NO_REPLY, detail: held ? `${unanswered} and does not hold the job` : `${unanswered}; its state is unknown` };
|
|
163
171
|
log.warn(log_1.GATEWAY_LOG.DISPATCH_REFUSED, { row: a.rowId, machine: a.machineId, ...resolution });
|
|
164
172
|
const ended = await lt.resolve(fromMachine(refused ?? null) ? a.machineId : actions_1.CONTROLLER, a.rowId, resolution);
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
* Runs the planner's actions: escalation verbs through LineEscalations,
|
|
3
3
|
* dispatches and commands through the Dispatcher, alarm and machine rows,
|
|
4
4
|
* and the offline debounce. A verb that fails for real throws, so the message that
|
|
5
|
-
* caused it is delivered again.
|
|
5
|
+
* caused it is delivered again. What ran comes back as wire actions, for the
|
|
6
|
+
* record of the message that caused it.
|
|
6
7
|
*/
|
|
7
8
|
import { type LineDef } from '../../../lib/machines/line';
|
|
8
9
|
import { type LineCodec } from '../../../lib/machines/protocol';
|
|
9
10
|
import type { MachineBus } from '../../../lib/machines/transport';
|
|
11
|
+
import type { WireAction } from '../../../types/machines-view';
|
|
10
12
|
import { type Action } from './actions';
|
|
11
13
|
import type { AddressBook } from './address-book';
|
|
12
14
|
import { type LineEscalations } from './escalations';
|
|
13
15
|
import { type GatewayLog } from './log';
|
|
14
16
|
import type { ReplyWaiter } from './reply-waiter';
|
|
15
17
|
import { type GatewayState } from './state';
|
|
18
|
+
import { type WireRecorder } from './wire';
|
|
16
19
|
export interface ExecutorDeps {
|
|
17
20
|
bus: MachineBus;
|
|
18
21
|
lt: LineEscalations;
|
|
@@ -26,19 +29,25 @@ export interface ExecutorDeps {
|
|
|
26
29
|
log: GatewayLog;
|
|
27
30
|
/** Where learned addresses are kept (registration.ts). */
|
|
28
31
|
addresses: AddressBook;
|
|
32
|
+
/** Records each command sent, for the line's wire view. */
|
|
33
|
+
wire?: Pick<WireRecorder, 'command'>;
|
|
29
34
|
}
|
|
30
35
|
export declare class Executor {
|
|
31
36
|
private readonly d;
|
|
32
37
|
private inflight;
|
|
33
38
|
private quietPending;
|
|
34
39
|
private timers;
|
|
40
|
+
private stopped;
|
|
35
41
|
private readonly dispatcher;
|
|
36
42
|
constructor(d: ExecutorDeps);
|
|
37
43
|
/** Dispatches and commands run detached so one slow reply never holds up the feed. */
|
|
38
|
-
apply(actions: Action[]): Promise<
|
|
44
|
+
apply(actions: Action[]): Promise<WireAction[]>;
|
|
39
45
|
/** Resolves when every detached dispatch has finished. */
|
|
40
46
|
idle(): Promise<void>;
|
|
47
|
+
/** Work still running sends nothing more and raises no row; the next leader takes it up from the message or the row. */
|
|
41
48
|
stop(): void;
|
|
49
|
+
/** A row raised after stop() would be raised again by the next leader, so the message is nak'd instead. */
|
|
50
|
+
private live;
|
|
42
51
|
private track;
|
|
43
52
|
private run;
|
|
44
53
|
/**
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Runs the planner's actions: escalation verbs through LineEscalations,
|
|
4
4
|
* dispatches and commands through the Dispatcher, alarm and machine rows,
|
|
5
5
|
* and the offline debounce. A verb that fails for real throws, so the message that
|
|
6
|
-
* caused it is delivered again.
|
|
6
|
+
* caused it is delivered again. What ran comes back as wire actions, for the
|
|
7
|
+
* record of the message that caused it.
|
|
7
8
|
*/
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.Executor = void 0;
|
|
@@ -16,18 +17,28 @@ const log_1 = require("./log");
|
|
|
16
17
|
const dispatcher_1 = require("./dispatcher");
|
|
17
18
|
const plan_shared_1 = require("./plan-shared");
|
|
18
19
|
const state_1 = require("./state");
|
|
20
|
+
const wire_1 = require("./wire");
|
|
19
21
|
const NOT_FOUND = 404;
|
|
20
22
|
const CONFLICT = 409;
|
|
23
|
+
/** A verb's outcome as the wire records it: done, already done, or refused by Long Tail. */
|
|
24
|
+
function outcomeOf(verb, rowId, result) {
|
|
25
|
+
const refused = result.outcome === escalations_1.VERB_OUTCOME.INVALID || result.status === NOT_FOUND || result.status === CONFLICT;
|
|
26
|
+
if (refused)
|
|
27
|
+
return { verb: 'refuse', rowId, detail: `${verb}: ${result.detail ?? result.outcome}` };
|
|
28
|
+
return { verb, rowId, ...(result.outcome === escalations_1.VERB_OUTCOME.ALREADY ? { detail: result.detail ?? 'already ended' } : {}) };
|
|
29
|
+
}
|
|
21
30
|
class Executor {
|
|
22
31
|
constructor(d) {
|
|
23
32
|
this.d = d;
|
|
24
33
|
this.inflight = new Set();
|
|
25
34
|
this.quietPending = new Set();
|
|
26
35
|
this.timers = new Set();
|
|
36
|
+
this.stopped = false;
|
|
27
37
|
this.dispatcher = new dispatcher_1.Dispatcher(d);
|
|
28
38
|
}
|
|
29
39
|
/** Dispatches and commands run detached so one slow reply never holds up the feed. */
|
|
30
40
|
async apply(actions) {
|
|
41
|
+
const done = [];
|
|
31
42
|
for (const action of actions) {
|
|
32
43
|
if (action.kind === 'dispatch')
|
|
33
44
|
this.track(this.dispatcher.dispatch(action));
|
|
@@ -35,22 +46,33 @@ class Executor {
|
|
|
35
46
|
this.track(this.dispatcher.command(action));
|
|
36
47
|
else if (action.kind === 'control')
|
|
37
48
|
this.track(this.dispatcher.control(action));
|
|
38
|
-
else
|
|
39
|
-
await this.run(action);
|
|
49
|
+
else {
|
|
50
|
+
done.push(...await this.run(action));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
done.push((0, wire_1.plannedAction)(action));
|
|
40
54
|
}
|
|
55
|
+
return done;
|
|
41
56
|
}
|
|
42
57
|
/** Resolves when every detached dispatch has finished. */
|
|
43
58
|
async idle() {
|
|
44
59
|
while (this.inflight.size)
|
|
45
60
|
await Promise.all([...this.inflight]);
|
|
46
61
|
}
|
|
62
|
+
/** Work still running sends nothing more and raises no row; the next leader takes it up from the message or the row. */
|
|
47
63
|
stop() {
|
|
64
|
+
this.stopped = true;
|
|
48
65
|
for (const t of this.timers)
|
|
49
66
|
clearTimeout(t);
|
|
50
67
|
this.timers.clear();
|
|
51
68
|
this.dispatcher.stop();
|
|
52
69
|
this.d.replies.cancelAll();
|
|
53
70
|
}
|
|
71
|
+
/** A row raised after stop() would be raised again by the next leader, so the message is nak'd instead. */
|
|
72
|
+
live() {
|
|
73
|
+
if (this.stopped)
|
|
74
|
+
throw new dispatcher_1.GatewayStopped();
|
|
75
|
+
}
|
|
54
76
|
track(work) {
|
|
55
77
|
const tracked = work.catch((err) => {
|
|
56
78
|
if (!(err instanceof dispatcher_1.GatewayStopped))
|
|
@@ -62,37 +84,45 @@ class Executor {
|
|
|
62
84
|
async run(a) {
|
|
63
85
|
const { lt, state, replies } = this.d;
|
|
64
86
|
switch (a.kind) {
|
|
65
|
-
case 'claim':
|
|
66
|
-
|
|
87
|
+
case 'claim': {
|
|
88
|
+
const result = await lt.claim(a.as, a.rowId);
|
|
89
|
+
this.check(a, result);
|
|
90
|
+
return [outcomeOf('claim', a.rowId, result)];
|
|
91
|
+
}
|
|
67
92
|
case 'accumulate':
|
|
68
93
|
return this.accumulate(a);
|
|
69
|
-
case 'resolve':
|
|
70
|
-
|
|
94
|
+
case 'resolve': {
|
|
95
|
+
const result = await lt.resolve(a.as, a.rowId, a.payload);
|
|
96
|
+
this.check(a, result);
|
|
71
97
|
state.close(a.rowId);
|
|
72
|
-
return;
|
|
98
|
+
return [outcomeOf('resolve', a.rowId, result)];
|
|
99
|
+
}
|
|
73
100
|
case 'createAlarmRow':
|
|
74
|
-
return this.createAlarmRow(a);
|
|
101
|
+
return [{ verb: 'create-row', rowId: await this.createAlarmRow(a), detail: `${a.row.type} ${a.alarmId} at ${a.machineId}` }];
|
|
75
102
|
case 'createRow': {
|
|
103
|
+
this.live();
|
|
76
104
|
const { id } = await lt.create(actions_1.CONTROLLER, a.row);
|
|
77
105
|
this.d.log.info(log_1.GATEWAY_LOG.VIOLATION_ROW, { row: id, type: a.row.type });
|
|
78
|
-
return;
|
|
106
|
+
return [{ verb: 'create-row', rowId: id, detail: a.row.type }];
|
|
79
107
|
}
|
|
80
108
|
case 'watchOffline':
|
|
81
|
-
|
|
109
|
+
this.watchOffline(a.machineId);
|
|
110
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
82
111
|
case 'settleReply':
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
return;
|
|
112
|
+
if (replies.settle({ cmdId: a.cmdId, status: a.status, reason: a.reason, ...(a.code ? { code: a.code } : {}) }))
|
|
113
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
114
|
+
return [{ verb: 'ack', detail: `late ${a.status} ${a.cmdId}` }, ...await this.lateReply(a)];
|
|
86
115
|
case 'settleSnapshot':
|
|
87
116
|
replies.settleSnapshot(a.machineId, new Set(a.jobIds));
|
|
88
|
-
return;
|
|
117
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
89
118
|
case 'bindAddress':
|
|
90
119
|
await this.d.addresses.bind(a.machineId, a.address);
|
|
91
120
|
state.bindAddress(a.machineId, a.address);
|
|
92
121
|
this.d.log.info(log_1.GATEWAY_LOG.ADDRESS_BOUND, { machine: a.machineId, address: a.address, ...(a.by ? { approvedBy: a.by } : {}) });
|
|
93
|
-
return;
|
|
122
|
+
return [{ verb: 'ack', detail: `bound ${a.machineId} to ${a.address}` }];
|
|
94
123
|
case 'refuseBinding':
|
|
95
124
|
this.d.log.warn(log_1.GATEWAY_LOG.ADDRESS_REFUSED, { machine: a.machineId, address: a.address, reason: a.reason });
|
|
125
|
+
return [(0, wire_1.plannedAction)(a)];
|
|
96
126
|
}
|
|
97
127
|
}
|
|
98
128
|
/**
|
|
@@ -106,18 +136,20 @@ class Executor {
|
|
|
106
136
|
const into = state.rowForDispatch(a.cmdId);
|
|
107
137
|
const m = into?.toMachine;
|
|
108
138
|
if (!into || !m)
|
|
109
|
-
return;
|
|
139
|
+
return [];
|
|
110
140
|
const context = { row: into.id, machine: m, cmdId: a.cmdId, reason: a.reason };
|
|
111
|
-
if (a.status === protocol_1.REPLY_STATUS.COMPLETED)
|
|
112
|
-
|
|
141
|
+
if (a.status === protocol_1.REPLY_STATUS.COMPLETED) {
|
|
142
|
+
log.info(log_1.GATEWAY_LOG.DISPATCH_READY, context);
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
113
145
|
if (a.status !== protocol_1.REPLY_STATUS.FAILED)
|
|
114
|
-
return;
|
|
146
|
+
return [];
|
|
115
147
|
const row = into.ended ? onwardRow(state, into, m) : into;
|
|
116
148
|
log.warn(log_1.GATEWAY_LOG.DISPATCH_FAILED, { ...context, ...(into.ended ? { onward: row?.id ?? null } : {}) });
|
|
117
149
|
if (!row)
|
|
118
|
-
return;
|
|
119
|
-
|
|
120
|
-
received: false, errorCode: contracts_1.HANDOFF_ERROR.DISPATCH_FAILED, detail: `${m} could not prepare the job: ${a.reason}`,
|
|
150
|
+
return [];
|
|
151
|
+
return this.apply((0, plan_shared_1.failHandoff)(state, row, m, {
|
|
152
|
+
received: false, errorCode: contracts_1.HANDOFF_ERROR.DISPATCH_FAILED, detail: `${m} could not prepare the job: ${a.reason}`, ...(a.code ? { code: a.code } : {}),
|
|
121
153
|
}));
|
|
122
154
|
}
|
|
123
155
|
/** Add the item; when the row then holds every key the action waits for, resolve it. */
|
|
@@ -125,15 +157,18 @@ class Executor {
|
|
|
125
157
|
const { lt, state } = this.d;
|
|
126
158
|
const result = await lt.accumulate(a.as, a.rowId, a.itemKey, a.payload, a.metadata);
|
|
127
159
|
this.check(a, result);
|
|
160
|
+
const added = { ...outcomeOf('accumulate', a.rowId, result), itemKey: a.itemKey };
|
|
128
161
|
if (!a.complete || result.outcome === escalations_1.VERB_OUTCOME.INVALID)
|
|
129
|
-
return;
|
|
162
|
+
return [added];
|
|
130
163
|
const held = new Set(result.itemKeys ?? await lt.itemKeys(a.rowId));
|
|
131
164
|
if (!a.complete.keys.every((k) => held.has(k)))
|
|
132
|
-
return;
|
|
165
|
+
return [added];
|
|
133
166
|
if (a.complete.then)
|
|
134
|
-
return this.apply(a.complete.then);
|
|
135
|
-
|
|
167
|
+
return [added, ...await this.apply(a.complete.then)];
|
|
168
|
+
const resolved = await lt.resolve(a.as, a.rowId, a.complete.payload ?? {});
|
|
169
|
+
this.check(a, resolved);
|
|
136
170
|
state.close(a.rowId);
|
|
171
|
+
return [added, outcomeOf('resolve', a.rowId, resolved)];
|
|
137
172
|
}
|
|
138
173
|
check(a, result) {
|
|
139
174
|
const rowId = a.rowId;
|
|
@@ -148,17 +183,19 @@ class Executor {
|
|
|
148
183
|
}
|
|
149
184
|
}
|
|
150
185
|
async createAlarmRow(a) {
|
|
186
|
+
this.live();
|
|
151
187
|
const { id } = await this.d.lt.create(actions_1.CONTROLLER, { ...a.row, role: (0, line_1.operatorRole)(this.d.line) });
|
|
152
188
|
this.d.log.info(log_1.GATEWAY_LOG.ALARM_ROW, { row: id, machine: a.machineId, alarm: a.alarmId });
|
|
153
189
|
const track = this.d.state.alarms.get(this.d.state.alarmKey(a.machineId, a.alarmId));
|
|
154
190
|
const raisedAt = a.row.metadata?.raisedAt;
|
|
155
191
|
if (track && (!track.raisedAt || !raisedAt || track.raisedAt === raisedAt)) {
|
|
156
192
|
track.rowId = id;
|
|
157
|
-
return;
|
|
193
|
+
return id;
|
|
158
194
|
}
|
|
159
195
|
// Cleared at the machine, or raised again, while the row was being created.
|
|
160
196
|
const note = track ? `${a.machineId} raised ${a.alarmId} again; this one ended` : `cleared at ${a.machineId}`;
|
|
161
197
|
await this.d.lt.resolve(actions_1.CONTROLLER, id, { decision: contracts_1.DECISION.CLEARED, note });
|
|
198
|
+
return id;
|
|
162
199
|
}
|
|
163
200
|
/** Raise a quiet row for each connected machine silent longer than `quietMs`. */
|
|
164
201
|
checkQuiet(machineIds, quietMs) {
|
|
@@ -172,6 +209,7 @@ class Executor {
|
|
|
172
209
|
}
|
|
173
210
|
}
|
|
174
211
|
async raiseQuiet(machineId, silentMs) {
|
|
212
|
+
this.live();
|
|
175
213
|
const { id } = await this.d.lt.create(actions_1.CONTROLLER, {
|
|
176
214
|
type: contracts_1.ROW_TYPE.MACHINE_QUIET, role: (0, line_1.operatorRole)(this.d.line), priority: 2,
|
|
177
215
|
description: `${machineId} is connected but has sent nothing for ${Math.round(silentMs / 1000)} s`,
|
|
@@ -194,11 +232,12 @@ class Executor {
|
|
|
194
232
|
link.watching = false;
|
|
195
233
|
if (link.online || link.rowId)
|
|
196
234
|
return;
|
|
235
|
+
this.live();
|
|
197
236
|
const since = new Date(link.since).toISOString();
|
|
198
237
|
const { id } = await this.d.lt.create(actions_1.CONTROLLER, {
|
|
199
238
|
type: contracts_1.ROW_TYPE.MACHINE_OFFLINE, role: (0, line_1.operatorRole)(this.d.line), priority: 2,
|
|
200
239
|
description: `${machineId} has been offline since ${since}`,
|
|
201
|
-
metadata: { siteId: this.d.line.siteId, lineId: this.d.line.lineId, machineId, offlineSince: since },
|
|
240
|
+
metadata: { siteId: this.d.line.siteId, lineId: this.d.line.lineId, machineId, offlineSince: since, ...(link.reason ? { reason: link.reason } : {}) },
|
|
202
241
|
});
|
|
203
242
|
this.d.log.info(log_1.GATEWAY_LOG.OFFLINE_ROW, { row: id, machine: machineId });
|
|
204
243
|
if (!link.online)
|
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
* reads escalation events (a new handoff row means "dispatch"), reads every
|
|
4
4
|
* machine message on the line (a receipt means "resolve"), and performs the
|
|
5
5
|
* verbs a person would, as the machine. Neither side knows about the other.
|
|
6
|
+
* Every message read or sent is recorded on the wire (wire.ts).
|
|
6
7
|
*/
|
|
7
8
|
import { type HandoffRowAdapter } from '../rows';
|
|
8
9
|
import { type AddressBook } from './address-book';
|
|
9
10
|
import type { LineDef } from '../../../lib/machines/line';
|
|
10
11
|
import { type LineCodec } from '../../../lib/machines/protocol';
|
|
11
|
-
import { type EscalationFeed, type MachineBus } from '../../../lib/machines/transport';
|
|
12
|
+
import { type EscalationFeed, type InboundMessage, type MachineBus } from '../../../lib/machines/transport';
|
|
13
|
+
import type { InspectResult } from '../../../types/machines-view';
|
|
12
14
|
import type { LineEscalations } from './escalations';
|
|
13
15
|
import { type GatewayLog } from './log';
|
|
14
16
|
import { GatewayState } from './state';
|
|
17
|
+
import { type WireSink } from './wire';
|
|
15
18
|
export interface GatewaySettings {
|
|
16
19
|
topicRoot: string;
|
|
17
20
|
replyTimeoutMs: number;
|
|
@@ -27,6 +30,8 @@ export interface GatewaySettings {
|
|
|
27
30
|
lifecycle?: boolean;
|
|
28
31
|
/** With lifecycle notes, progress is noted each time it crosses this many percent; 0 notes none. */
|
|
29
32
|
progressStep?: number;
|
|
33
|
+
/** Record telemetry messages on the wire too; off unless set. */
|
|
34
|
+
wireTelemetry?: boolean;
|
|
30
35
|
}
|
|
31
36
|
export interface GatewayDeps {
|
|
32
37
|
bus: MachineBus;
|
|
@@ -41,6 +46,8 @@ export interface GatewayDeps {
|
|
|
41
46
|
codec?: LineCodec;
|
|
42
47
|
/** Where a line that learns addresses keeps them; in memory by default. */
|
|
43
48
|
addresses?: AddressBook;
|
|
49
|
+
/** Where wire records go; Long Tail's events by default. */
|
|
50
|
+
wire?: WireSink;
|
|
44
51
|
}
|
|
45
52
|
export declare class MachineGateway {
|
|
46
53
|
private readonly deps;
|
|
@@ -52,14 +59,22 @@ export declare class MachineGateway {
|
|
|
52
59
|
private readonly log;
|
|
53
60
|
private readonly addresses;
|
|
54
61
|
private readonly admission;
|
|
62
|
+
private readonly wire;
|
|
55
63
|
private quietTimer?;
|
|
56
64
|
constructor(deps: GatewayDeps);
|
|
57
65
|
start(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Hand the line over cleanly: nothing new is raised or sent, a message
|
|
68
|
+
* still being handled is nak'd for the next leader if it would make a row,
|
|
69
|
+
* receipts for what was applied go out, then the sessions close.
|
|
70
|
+
*/
|
|
58
71
|
stop(): Promise<void>;
|
|
59
72
|
/** Machines that report only changes are asked for their full state once the gateway listens. */
|
|
60
73
|
private askEveryMachine;
|
|
61
74
|
/** Resolves when no dispatch is in flight (tests). */
|
|
62
75
|
idle(): Promise<void>;
|
|
76
|
+
/** A dry run of one message on a copy of the state: nothing is applied (inspect.ts). */
|
|
77
|
+
inspect(msg: Pick<InboundMessage, 'topic' | 'payload' | 'retained'>): InspectResult;
|
|
63
78
|
/**
|
|
64
79
|
* On taking the line: open handoff and command rows (a dispatch or command
|
|
65
80
|
* interrupted by a restart is sent again with the same cmdId), the gateway's
|