@ours.network/fleet 1.2.0-nightly.3 → 1.2.0-nightly.31
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 +158 -28
- package/dist/account-origin.d.ts +2 -0
- package/dist/account-origin.js +6 -0
- package/dist/agent-ours/bridge.d.ts +3 -0
- package/dist/agent-ours/bridge.js +178 -0
- package/dist/agent-ours/controller.d.ts +14 -0
- package/dist/agent-ours/controller.js +60 -0
- package/dist/agent-ours/correspondence.d.ts +10 -0
- package/dist/agent-ours/correspondence.js +1 -0
- package/dist/agent-ours/file-rpc.d.ts +23 -0
- package/dist/agent-ours/file-rpc.js +123 -0
- package/dist/agent-ours/harness.d.ts +14 -0
- package/dist/agent-ours/harness.js +72 -0
- package/dist/agent-ours/mcp-endpoint.d.ts +15 -0
- package/dist/agent-ours/mcp-endpoint.js +111 -0
- package/dist/agent-ours/runtime.d.ts +59 -0
- package/dist/agent-ours/runtime.js +283 -0
- package/dist/agent-ours/service.d.ts +23 -0
- package/dist/agent-ours/service.js +372 -0
- package/dist/agent-ours/state.d.ts +45 -0
- package/dist/agent-ours/state.js +95 -0
- package/dist/agent-ours/wire.d.ts +14 -0
- package/dist/agent-ours/wire.js +55 -0
- package/dist/application/conversation-history.d.ts +25 -0
- package/dist/application/conversation-history.js +189 -0
- package/dist/application/fleet-query-service.d.ts +1 -1
- package/dist/application/fleet-query-service.js +2 -2
- package/dist/application/legacy-supervisor-identity.d.ts +7 -0
- package/dist/application/legacy-supervisor-identity.js +43 -0
- package/dist/application/model-catalog.d.ts +1 -1
- package/dist/application/model-catalog.js +5 -2
- package/dist/application/preset-provenance.d.ts +19 -0
- package/dist/application/preset-provenance.js +59 -0
- package/dist/application/room-layout-definitions.d.ts +45 -0
- package/dist/application/room-layout-definitions.js +130 -0
- package/dist/application/session-control.d.ts +18 -0
- package/dist/application/session-control.js +54 -3
- package/dist/application/supervisor-ours-tools.d.ts +159 -0
- package/dist/application/supervisor-ours-tools.js +113 -0
- package/dist/application/task-layouts.d.ts +91 -0
- package/dist/application/task-layouts.js +249 -0
- package/dist/application/task-room-service.d.ts +99 -3
- package/dist/application/task-room-service.js +296 -31
- package/dist/atomic-file.d.ts +5 -0
- package/dist/atomic-file.js +62 -1
- package/dist/briefing.js +10 -59
- package/dist/build-info.json +6 -4
- package/dist/capabilities.d.ts +3 -1
- package/dist/capabilities.js +4 -0
- package/dist/cli.js +131 -5
- package/dist/client-profile.d.ts +5 -16
- package/dist/client-profile.js +4 -112
- package/dist/config.d.ts +4 -0
- package/dist/config.js +7 -0
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +5 -16
- package/dist/daemon-recovery.d.ts +1 -8
- package/dist/daemon-recovery.js +8 -113
- package/dist/docs.d.ts +3 -3
- package/dist/docs.js +43 -23
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.js +46 -59
- package/dist/erased-resources.d.ts +9 -0
- package/dist/erased-resources.js +87 -0
- package/dist/fleet-command-audit.d.ts +1 -0
- package/dist/fleet-command-audit.js +12 -7
- package/dist/harness/agent-session.d.ts +2 -0
- package/dist/harness/claude-code-session.js +4 -2
- package/dist/harness/codex-app-server-proxy.d.ts +4 -1
- package/dist/harness/codex-app-server-proxy.js +41 -5
- package/dist/harness/codex-session.js +9 -2
- package/dist/harness/codex.d.ts +3 -2
- package/dist/harness/codex.js +4 -3
- package/dist/harness/hermes-session.js +7 -1
- package/dist/init-wizard.js +20 -9
- package/dist/isolation/policy.js +2 -0
- package/dist/isolation/types.d.ts +5 -0
- package/dist/monitor.d.ts +1 -34
- package/dist/monitor.js +24 -151
- package/dist/notifications/fleet-producer.d.ts +18 -0
- package/dist/notifications/fleet-producer.js +129 -0
- package/dist/notifications/outbox.d.ts +31 -0
- package/dist/notifications/outbox.js +104 -0
- package/dist/owner-channel/channel.d.ts +3 -0
- package/dist/owner-channel/channel.js +34 -6
- package/dist/owner-channel/commands.d.ts +4 -0
- package/dist/owner-channel/commands.js +8 -0
- package/dist/owner-channel/lifecycle-outbox.js +4 -3
- package/dist/owner-channel/ours-client.js +2 -17
- package/dist/preset-migration.js +15 -0
- package/dist/rooms-tasks/add-member.d.ts +48 -0
- package/dist/rooms-tasks/add-member.js +83 -0
- package/dist/rooms-tasks/archived-absence.d.ts +8 -0
- package/dist/rooms-tasks/archived-absence.js +48 -0
- package/dist/rooms-tasks/cli.js +34 -5
- package/dist/rooms-tasks/close.d.ts +5 -2
- package/dist/rooms-tasks/close.js +208 -28
- package/dist/rooms-tasks/config.js +3 -1
- package/dist/rooms-tasks/cowork-adapter.d.ts +6 -4
- package/dist/rooms-tasks/cowork-adapter.js +11 -117
- package/dist/rooms-tasks/cowork-http.d.ts +3 -0
- package/dist/rooms-tasks/cowork-http.js +70 -0
- package/dist/rooms-tasks/deletion.d.ts +1 -1
- package/dist/rooms-tasks/deletion.js +74 -5
- package/dist/rooms-tasks/erasure.d.ts +6 -0
- package/dist/rooms-tasks/erasure.js +169 -0
- package/dist/rooms-tasks/external-worker.d.ts +1 -1
- package/dist/rooms-tasks/external-worker.js +3 -4
- package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
- package/dist/rooms-tasks/layout-binding-client.js +56 -0
- package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
- package/dist/rooms-tasks/layout-binding-grants.js +128 -0
- package/dist/rooms-tasks/layout-cli.d.ts +4 -0
- package/dist/rooms-tasks/layout-cli.js +107 -0
- package/dist/rooms-tasks/layout-config.d.ts +11 -0
- package/dist/rooms-tasks/layout-config.js +89 -0
- package/dist/rooms-tasks/layout-control.d.ts +21 -0
- package/dist/rooms-tasks/layout-control.js +52 -0
- package/dist/rooms-tasks/layout-service.d.ts +42 -0
- package/dist/rooms-tasks/layout-service.js +185 -0
- package/dist/rooms-tasks/layout.d.ts +114 -0
- package/dist/rooms-tasks/layout.js +250 -0
- package/dist/rooms-tasks/live-readiness.d.ts +18 -0
- package/dist/rooms-tasks/live-readiness.js +85 -0
- package/dist/rooms-tasks/member-startup.d.ts +1 -0
- package/dist/rooms-tasks/member-startup.js +2 -0
- package/dist/rooms-tasks/provision.d.ts +14 -0
- package/dist/rooms-tasks/provision.js +182 -48
- package/dist/rooms-tasks/room-state.d.ts +4 -2
- package/dist/rooms-tasks/room-state.js +53 -8
- package/dist/rooms-tasks/task-state.d.ts +42 -7
- package/dist/rooms-tasks/task-state.js +153 -23
- package/dist/rooms-tasks/types.d.ts +28 -0
- package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
- package/dist/rooms-tasks/workspace-artifacts.js +93 -0
- package/dist/rooms-tasks/workspace.d.ts +26 -0
- package/dist/rooms-tasks/workspace.js +195 -0
- package/dist/runner.d.ts +23 -3
- package/dist/runner.js +581 -494
- package/dist/session/acp.d.ts +3 -0
- package/dist/session/acp.js +14 -0
- package/dist/session/arbiter.d.ts +3 -0
- package/dist/session/arbiter.js +20 -2
- package/dist/session/codex-app-server-transport.js +1 -1
- package/dist/session/codex-app-server.d.ts +3 -0
- package/dist/session/codex-app-server.js +25 -1
- package/dist/session/control.d.ts +10 -1
- package/dist/session/control.js +37 -2
- package/dist/session/conversation-normalizer.d.ts +2 -1
- package/dist/session/conversation-normalizer.js +1 -1
- package/dist/session/conversation-types.d.ts +5 -3
- package/dist/session/task-notice.d.ts +14 -0
- package/dist/session/task-notice.js +13 -0
- package/dist/session/types.d.ts +3 -0
- package/dist/socket-path.d.ts +2 -0
- package/dist/socket-path.js +22 -0
- package/dist/spawn.js +19 -16
- package/dist/startup-readiness.d.ts +13 -0
- package/dist/startup-readiness.js +38 -0
- package/dist/subscriptions/cli.d.ts +78 -0
- package/dist/subscriptions/cli.js +186 -0
- package/dist/subscriptions/launch.d.ts +37 -0
- package/dist/subscriptions/launch.js +93 -0
- package/dist/subscriptions/login.d.ts +75 -0
- package/dist/subscriptions/login.js +182 -0
- package/dist/subscriptions/observed.d.ts +7 -0
- package/dist/subscriptions/observed.js +44 -0
- package/dist/subscriptions/probe.d.ts +10 -0
- package/dist/subscriptions/probe.js +73 -0
- package/dist/subscriptions/service.d.ts +102 -0
- package/dist/subscriptions/service.js +364 -0
- package/dist/subscriptions/store.d.ts +71 -0
- package/dist/subscriptions/store.js +140 -0
- package/dist/supervisor/launchd.js +2 -1
- package/dist/supervisor/systemd.js +9 -23
- package/dist/temp-idle.d.ts +17 -0
- package/dist/temp-idle.js +42 -0
- package/dist/temp-lifecycle.d.ts +6 -1
- package/dist/temp-lifecycle.js +29 -13
- package/dist/temp-supervisor-recovery.d.ts +3 -0
- package/dist/temp-supervisor-recovery.js +46 -0
- package/dist/watchdog/briefing.js +3 -16
- package/dist/watchdog/run.js +19 -5
- package/dist/web/agent-attachments.d.ts +29 -0
- package/dist/web/agent-attachments.js +162 -0
- package/dist/web/auth.d.ts +28 -2
- package/dist/web/auth.js +81 -8
- package/dist/web/available-port.d.ts +2 -0
- package/dist/web/available-port.js +23 -0
- package/dist/web/control.d.ts +3 -2
- package/dist/web/control.js +11 -7
- package/dist/web/fleet-config-service.d.ts +4 -1
- package/dist/web/fleet-config-service.js +46 -15
- package/dist/web/prefix-gateway.d.ts +23 -0
- package/dist/web/prefix-gateway.js +156 -0
- package/dist/web/runtime.d.ts +4 -0
- package/dist/web/runtime.js +106 -20
- package/dist/web/server.d.ts +11 -0
- package/dist/web/server.js +445 -31
- package/dist/web/service.d.ts +11 -2
- package/dist/web/service.js +30 -4
- package/dist/web/workspace-devices.d.ts +29 -0
- package/dist/web/workspace-devices.js +84 -0
- package/dist/web/workspace-tunnel.d.ts +1 -0
- package/dist/web/workspace-tunnel.js +32 -0
- package/dist/web-app/assets/FleetApp-D58F4xje.css +1 -0
- package/dist/web-app/assets/FleetApp-DP5cBY0o.js +302 -0
- package/dist/web-app/assets/FleetApp-DP5cBY0o.js.map +1 -0
- package/dist/web-app/assets/abnfDiagram-VCTEODGH-BvJIz7wN.js +2 -0
- package/dist/web-app/assets/abnfDiagram-VCTEODGH-BvJIz7wN.js.map +1 -0
- package/dist/web-app/assets/arc-AT_BEfpe.js +2 -0
- package/dist/web-app/assets/arc-AT_BEfpe.js.map +1 -0
- package/dist/web-app/assets/architectureDiagram-5GKGNRK7-vSgJa9Xb.js +37 -0
- package/dist/web-app/assets/architectureDiagram-5GKGNRK7-vSgJa9Xb.js.map +1 -0
- package/dist/web-app/assets/blockDiagram-I7D4REHJ-DCFk_4Kv.js +130 -0
- package/dist/web-app/assets/blockDiagram-I7D4REHJ-DCFk_4Kv.js.map +1 -0
- package/dist/web-app/assets/browser-CMIwJ_8L.js +9 -0
- package/dist/web-app/assets/browser-CMIwJ_8L.js.map +1 -0
- package/dist/web-app/assets/c4Diagram-7LVT6UL2-8J_dVUtF.js +39 -0
- package/dist/web-app/assets/c4Diagram-7LVT6UL2-8J_dVUtF.js.map +1 -0
- package/dist/web-app/assets/channel-BHCBlfND.js +2 -0
- package/dist/web-app/assets/channel-BHCBlfND.js.map +1 -0
- package/dist/web-app/assets/chunk-2Q5K7J3B-31RX-jnL.js +2 -0
- package/dist/web-app/assets/chunk-2Q5K7J3B-31RX-jnL.js.map +1 -0
- package/dist/web-app/assets/chunk-5VM5RSS4-CFF8_ZJH.js +16 -0
- package/dist/web-app/assets/chunk-5VM5RSS4-CFF8_ZJH.js.map +1 -0
- package/dist/web-app/assets/chunk-F27PBJKO-Dx1l5wLI.js +2 -0
- package/dist/web-app/assets/chunk-F27PBJKO-Dx1l5wLI.js.map +1 -0
- package/dist/web-app/assets/chunk-IMKFNOWR-Ba2_9bl_.js +232 -0
- package/dist/web-app/assets/chunk-IMKFNOWR-Ba2_9bl_.js.map +1 -0
- package/dist/web-app/assets/chunk-JWPE2WC7-_mnRB2OH.js +2 -0
- package/dist/web-app/assets/chunk-JWPE2WC7-_mnRB2OH.js.map +1 -0
- package/dist/web-app/assets/chunk-POPQ4Y6H-B8jQTxQO.js +2 -0
- package/dist/web-app/assets/chunk-POPQ4Y6H-B8jQTxQO.js.map +1 -0
- package/dist/web-app/assets/chunk-SVP7TREG-BO_Jnb_c.js +89 -0
- package/dist/web-app/assets/chunk-SVP7TREG-BO_Jnb_c.js.map +1 -0
- package/dist/web-app/assets/chunk-TICWLB2K-ZYZ9hFu5.js +207 -0
- package/dist/web-app/assets/chunk-TICWLB2K-ZYZ9hFu5.js.map +1 -0
- package/dist/web-app/assets/chunk-XXDRQBXY-ByUAYXI3.js +2 -0
- package/dist/web-app/assets/chunk-XXDRQBXY-ByUAYXI3.js.map +1 -0
- package/dist/web-app/assets/classDiagram-ZZMXUADV-Ddx7RAuT.js +2 -0
- package/dist/web-app/assets/classDiagram-ZZMXUADV-Ddx7RAuT.js.map +1 -0
- package/dist/web-app/assets/classDiagram-v2-VYDZK3BY-Ddx7RAuT.js +2 -0
- package/dist/web-app/assets/classDiagram-v2-VYDZK3BY-Ddx7RAuT.js.map +1 -0
- package/dist/web-app/assets/cose-bilkent-JH36ORCC-BuOGJgHG.js +2 -0
- package/dist/web-app/assets/cose-bilkent-JH36ORCC-BuOGJgHG.js.map +1 -0
- package/dist/web-app/assets/cynefin-OW5HDTMX-DLksGPh8.js +179 -0
- package/dist/web-app/assets/cynefin-OW5HDTMX-DLksGPh8.js.map +1 -0
- package/dist/web-app/assets/cynefinDiagram-5FMLGOSQ-nJQb5qZR.js +63 -0
- package/dist/web-app/assets/cynefinDiagram-5FMLGOSQ-nJQb5qZR.js.map +1 -0
- package/dist/web-app/assets/cytoscape.esm-CtNdOvlO.js +332 -0
- package/dist/web-app/assets/cytoscape.esm-CtNdOvlO.js.map +1 -0
- package/dist/web-app/assets/dagre-GXQ25YYZ-CCF5O_UD.js +5 -0
- package/dist/web-app/assets/dagre-GXQ25YYZ-CCF5O_UD.js.map +1 -0
- package/dist/web-app/assets/defaultLocale-DX6XiGOO.js +2 -0
- package/dist/web-app/assets/defaultLocale-DX6XiGOO.js.map +1 -0
- package/dist/web-app/assets/diagram-S7CK7UJ4-C88au4NC.js +31 -0
- package/dist/web-app/assets/diagram-S7CK7UJ4-C88au4NC.js.map +1 -0
- package/dist/web-app/assets/diagram-UQ7AKVKN-B4QnPs7U.js +42 -0
- package/dist/web-app/assets/diagram-UQ7AKVKN-B4QnPs7U.js.map +1 -0
- package/dist/web-app/assets/diagram-VSXAHHWV-DeANdVWA.js +4 -0
- package/dist/web-app/assets/diagram-VSXAHHWV-DeANdVWA.js.map +1 -0
- package/dist/web-app/assets/diagram-VX7I27RA-YzlB_2AY.js +25 -0
- package/dist/web-app/assets/diagram-VX7I27RA-YzlB_2AY.js.map +1 -0
- package/dist/web-app/assets/diagram-Z3DM3KII-YY9NFaz_.js +25 -0
- package/dist/web-app/assets/diagram-Z3DM3KII-YY9NFaz_.js.map +1 -0
- package/dist/web-app/assets/ebnfDiagram-PWID7BFC-Cqu9kHUC.js +2 -0
- package/dist/web-app/assets/ebnfDiagram-PWID7BFC-Cqu9kHUC.js.map +1 -0
- package/dist/web-app/assets/erDiagram-RLTQ6QDP-IHi93MdG.js +100 -0
- package/dist/web-app/assets/erDiagram-RLTQ6QDP-IHi93MdG.js.map +1 -0
- package/dist/web-app/assets/flowDiagram-HODETNUW-19bm7W5P.js +169 -0
- package/dist/web-app/assets/flowDiagram-HODETNUW-19bm7W5P.js.map +1 -0
- package/dist/web-app/assets/ganttDiagram-EL5Y4UJY-BvCqvyiB.js +293 -0
- package/dist/web-app/assets/ganttDiagram-EL5Y4UJY-BvCqvyiB.js.map +1 -0
- package/dist/web-app/assets/gitGraphDiagram-WWUBYQGX-G4Ubl8Fs.js +107 -0
- package/dist/web-app/assets/gitGraphDiagram-WWUBYQGX-G4Ubl8Fs.js.map +1 -0
- package/dist/web-app/assets/index-C4BdeFB9.css +1 -0
- package/dist/web-app/assets/index-Dtn3ZY6J.js +430 -0
- package/dist/web-app/assets/index-Dtn3ZY6J.js.map +1 -0
- package/dist/web-app/assets/infoDiagram-27XIBGKW-B6rtfbuC.js +3 -0
- package/dist/web-app/assets/infoDiagram-27XIBGKW-B6rtfbuC.js.map +1 -0
- package/dist/web-app/assets/init-Gi6I4Gst.js +2 -0
- package/dist/web-app/assets/init-Gi6I4Gst.js.map +1 -0
- package/dist/web-app/assets/ishikawaDiagram-5VMMS53U-Lp8q1D21.js +71 -0
- package/dist/web-app/assets/ishikawaDiagram-5VMMS53U-Lp8q1D21.js.map +1 -0
- package/dist/web-app/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist/web-app/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist/web-app/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/web-app/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/web-app/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist/web-app/assets/journeyDiagram-3NMN7TZE-Av03B9l3.js +140 -0
- package/dist/web-app/assets/journeyDiagram-3NMN7TZE-Av03B9l3.js.map +1 -0
- package/dist/web-app/assets/kanban-definition-UXKFOSKX-Ddd3_ejb.js +90 -0
- package/dist/web-app/assets/kanban-definition-UXKFOSKX-Ddd3_ejb.js.map +1 -0
- package/dist/web-app/assets/katex-HP8lGamR.js +258 -0
- package/dist/web-app/assets/katex-HP8lGamR.js.map +1 -0
- package/dist/web-app/assets/layout-CNjBeOlp.js +2 -0
- package/dist/web-app/assets/layout-CNjBeOlp.js.map +1 -0
- package/dist/web-app/assets/linear-DDONU9Ir.js +2 -0
- package/dist/web-app/assets/linear-DDONU9Ir.js.map +1 -0
- package/dist/web-app/assets/mermaid.core-B9X3C61k.js +313 -0
- package/dist/web-app/assets/mermaid.core-B9X3C61k.js.map +1 -0
- package/dist/web-app/assets/mindmap-definition-YA3MSWOX-I2UME2Ce.js +97 -0
- package/dist/web-app/assets/mindmap-definition-YA3MSWOX-I2UME2Ce.js.map +1 -0
- package/dist/web-app/assets/ordinal-Cboi1Yqb.js +2 -0
- package/dist/web-app/assets/ordinal-Cboi1Yqb.js.map +1 -0
- package/dist/web-app/assets/pegDiagram-XKGWAZYB-BER8lNbi.js +2 -0
- package/dist/web-app/assets/pegDiagram-XKGWAZYB-BER8lNbi.js.map +1 -0
- package/dist/web-app/assets/pieDiagram-E7YTZNPT-FVWVg8rH.js +40 -0
- package/dist/web-app/assets/pieDiagram-E7YTZNPT-FVWVg8rH.js.map +1 -0
- package/dist/web-app/assets/quadrantDiagram-AXDQQJYC-YlvT1u77.js +8 -0
- package/dist/web-app/assets/quadrantDiagram-AXDQQJYC-YlvT1u77.js.map +1 -0
- package/dist/web-app/assets/railroadDiagram-O6MQD6OU-CvxT6dMW.js +2 -0
- package/dist/web-app/assets/railroadDiagram-O6MQD6OU-CvxT6dMW.js.map +1 -0
- package/dist/web-app/assets/requirementDiagram-BXWQKSXE-Caav4EkP.js +85 -0
- package/dist/web-app/assets/requirementDiagram-BXWQKSXE-Caav4EkP.js.map +1 -0
- package/dist/web-app/assets/sankeyDiagram-P5KCCOFB-B5Uw70Gn.js +41 -0
- package/dist/web-app/assets/sankeyDiagram-P5KCCOFB-B5Uw70Gn.js.map +1 -0
- package/dist/web-app/assets/sequenceDiagram-WJ2MYXX4-D2SLKVJl.js +163 -0
- package/dist/web-app/assets/sequenceDiagram-WJ2MYXX4-D2SLKVJl.js.map +1 -0
- package/dist/web-app/assets/sizeCapture-INFHLROL-BVaBfbwa.js +2 -0
- package/dist/web-app/assets/sizeCapture-INFHLROL-BVaBfbwa.js.map +1 -0
- package/dist/web-app/assets/stateDiagram-D77RDMKH-BlV9y2tf.js +2 -0
- package/dist/web-app/assets/stateDiagram-D77RDMKH-BlV9y2tf.js.map +1 -0
- package/dist/web-app/assets/stateDiagram-v2-MP3YSRHH-BU4Tu2pp.js +2 -0
- package/dist/web-app/assets/stateDiagram-v2-MP3YSRHH-BU4Tu2pp.js.map +1 -0
- package/dist/web-app/assets/swimlanes-42K2YHIH-Pv3Wv8c7.js +2 -0
- package/dist/web-app/assets/swimlanes-42K2YHIH-Pv3Wv8c7.js.map +1 -0
- package/dist/web-app/assets/swimlanesDiagram-VR7AAH4N-BNKjOvPH.js +9 -0
- package/dist/web-app/assets/swimlanesDiagram-VR7AAH4N-BNKjOvPH.js.map +1 -0
- package/dist/web-app/assets/timeline-definition-24CTP7MA-C9TOilaR.js +121 -0
- package/dist/web-app/assets/timeline-definition-24CTP7MA-C9TOilaR.js.map +1 -0
- package/dist/web-app/assets/vennDiagram-4TSXK5OY-DeSDprN4.js +35 -0
- package/dist/web-app/assets/vennDiagram-4TSXK5OY-DeSDprN4.js.map +1 -0
- package/dist/web-app/assets/wardleyDiagram-VM6X3IG4-SulZn-nm.js +79 -0
- package/dist/web-app/assets/wardleyDiagram-VM6X3IG4-SulZn-nm.js.map +1 -0
- package/dist/web-app/assets/xychartDiagram-S5SC5T6Z-CC6MrQ0h.js +8 -0
- package/dist/web-app/assets/xychartDiagram-S5SC5T6Z-CC6MrQ0h.js.map +1 -0
- package/dist/web-app/fleet-index.html +19 -0
- package/dist/web-app/fleet.webmanifest +37 -0
- package/dist/web-app/icons/apple-touch-icon.png +0 -0
- package/dist/web-app/icons/favicon-16.png +0 -0
- package/dist/web-app/icons/favicon-32.png +0 -0
- package/dist/web-app/icons/icon-192-maskable.png +0 -0
- package/dist/web-app/icons/icon-192.png +0 -0
- package/dist/web-app/icons/icon-512-maskable.png +0 -0
- package/dist/web-app/icons/icon-512.png +0 -0
- package/dist/web-app/index.html +9 -7
- package/dist/web-app/manifest.webmanifest +10 -8
- package/dist/web-app/sw.js +210 -40
- package/dist/web-app/version.json +1 -0
- package/dist/web-app/workspace-install.sh +148 -0
- package/dist/workspace-enrollment.d.ts +28 -0
- package/dist/workspace-enrollment.js +129 -0
- package/docs/room-layouts.md +227 -0
- package/docs/task-workspaces.md +130 -0
- package/examples/room-layouts/fresh.yaml +27 -0
- package/examples/room-layouts/scoped.yaml +21 -0
- package/examples/room-layouts/shared.yaml +19 -0
- package/package.json +14 -17
- package/presets/README.md +78 -0
- package/presets/brain-catalog.json +8 -2
- package/presets/fleet/agent_templates/Engineer.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
- package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
- package/presets/fleet/roles/Coordinator.yaml +22 -0
- package/presets/fleet/roles/Engineer.yaml +40 -0
- package/presets/fleet/room_layouts/engineering.yaml +25 -0
- package/presets/fleet/room_layouts/pair.yaml +24 -0
- package/presets/fleet/room_layouts/single.yaml +17 -0
- package/presets/fleet/room_layouts/team.yaml +30 -0
- package/presets/fleet/room_templates/engineering.yaml +19 -0
- package/presets/manifest.json +2 -2
- package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
- package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
- package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
- package/dist/web-app/icons/ours-fleet.svg +0 -4
- package/dist/web-app/offline.html +0 -18
package/dist/init-wizard.js
CHANGED
|
@@ -7,13 +7,19 @@ import { packagedPresetRoot } from './preset-bootstrap.js';
|
|
|
7
7
|
import { listTemplates } from './rooms-tasks/templates.js';
|
|
8
8
|
const WORK_KINDS = ['development', 'review', 'coordination'];
|
|
9
9
|
const ROLE_WORK = {
|
|
10
|
-
Developer: 'development', Critic: 'review',
|
|
10
|
+
Developer: 'development', Engineer: 'development', Critic: 'review',
|
|
11
11
|
LocalCoordinator: 'coordination', Coordinator: 'coordination', FleetCoordinator: 'coordination',
|
|
12
12
|
};
|
|
13
13
|
const REASONING_EFFORT = {
|
|
14
14
|
quick: 'low', balanced: 'medium', thorough: 'high',
|
|
15
15
|
};
|
|
16
16
|
const MODEL_LABELS = {
|
|
17
|
+
'gpt-6.1-sol': 'GPT-6.1 Sol',
|
|
18
|
+
'gpt-6-sol': 'GPT-6 Sol',
|
|
19
|
+
'gpt-6-luna': 'GPT-6 Luna',
|
|
20
|
+
'claude-fable-5-1': 'Claude Fable 5.1',
|
|
21
|
+
'claude-opus-5-5': 'Claude Opus 5.5',
|
|
22
|
+
'claude-haiku-4-5-20251001': 'Claude Haiku 4.5',
|
|
17
23
|
'gpt-6-astra': 'GPT-6 Astra',
|
|
18
24
|
'gpt-5.6-sol': 'GPT-5.6 Sol',
|
|
19
25
|
'gpt-5.6-terra': 'GPT-5.6 Terra',
|
|
@@ -33,10 +39,10 @@ export function validateCatalog(value, path = 'supported model catalog') {
|
|
|
33
39
|
for (const model of value.models) {
|
|
34
40
|
if (!['codex', 'claude-code'].includes(model.harness) || model.session !== 'acp'
|
|
35
41
|
|| typeof model.model !== 'string' || !MODEL_LABELS[model.model]
|
|
36
|
-
|| !Array.isArray(model.efforts)
|
|
42
|
+
|| !Array.isArray(model.efforts)
|
|
37
43
|
|| new Set(model.efforts).size !== model.efforts.length
|
|
38
44
|
|| model.efforts.some(effort => !['low', 'medium', 'high', 'xhigh', 'max', 'ultra'].includes(effort))
|
|
39
|
-
|| !['low', 'medium', 'high'].every(effort => model.efforts.includes(effort)))
|
|
45
|
+
|| (model.efforts.length > 0 && !['low', 'medium', 'high'].every(effort => model.efforts.includes(effort))))
|
|
40
46
|
throw new Error(`unsupported model state in ${path}`);
|
|
41
47
|
const tuple = `${model.harness}\0${model.session}\0${model.model}`;
|
|
42
48
|
if (tuples.has(tuple))
|
|
@@ -90,7 +96,9 @@ export async function askInitQuestions(prompter, configuration) {
|
|
|
90
96
|
return undefined;
|
|
91
97
|
if (subscriptions.length === 0)
|
|
92
98
|
throw new Error('Select at least one subscription.');
|
|
93
|
-
|
|
99
|
+
// The wizard assigns low/medium/high; no-effort models remain available as named presets.
|
|
100
|
+
const available = catalog().models.filter(model => subscriptions.includes(subscriptionFor(model))
|
|
101
|
+
&& model.efforts.length > 0);
|
|
94
102
|
if (!available.length)
|
|
95
103
|
throw new Error('None of the selected subscriptions has a supported model.');
|
|
96
104
|
prompter.note([
|
|
@@ -163,6 +171,7 @@ export function formatSetupSummary(answers, configuration) {
|
|
|
163
171
|
' One-agent work: one Developer',
|
|
164
172
|
' Reviewed pair: Developer + independent Critic',
|
|
165
173
|
' Team: LocalCoordinator + Developer + Critic',
|
|
174
|
+
' Gated engineering: Engineer (gate pipeline) + independent Critic',
|
|
166
175
|
' FleetCoordinator: coordination model',
|
|
167
176
|
'',
|
|
168
177
|
'After the final Yes, Fleet performs host service setup before publishing the complete configuration.',
|
|
@@ -221,7 +230,7 @@ export function generateSetup(answers) {
|
|
|
221
230
|
if (tuples.size !== 1)
|
|
222
231
|
throw new Error('one-model assignment requires the same exact model for development, review, and coordination');
|
|
223
232
|
}
|
|
224
|
-
for (const role of ['Coordinator', 'LocalCoordinator', 'Developer', 'Critic']) {
|
|
233
|
+
for (const role of ['Coordinator', 'LocalCoordinator', 'Developer', 'Engineer', 'Critic']) {
|
|
225
234
|
files.set(`roles/${role}.yaml`, preset(`roles/${role}.yaml`));
|
|
226
235
|
if (role === 'Coordinator')
|
|
227
236
|
continue;
|
|
@@ -236,8 +245,10 @@ export function generateSetup(answers) {
|
|
|
236
245
|
}
|
|
237
246
|
files.set('agents/FleetCoordinator.yaml', preset('agents/FleetCoordinator.yaml')
|
|
238
247
|
.replace('brain: { ref: claude-default }', 'brain: { ref: coordination }'));
|
|
239
|
-
for (const name of ['single', 'pair', 'team'])
|
|
248
|
+
for (const name of ['single', 'pair', 'team', 'engineering']) {
|
|
240
249
|
files.set(`room_templates/${name}.yaml`, preset(`room_templates/${name}.yaml`));
|
|
250
|
+
files.set(`room_layouts/${name}.yaml`, preset(`room_layouts/${name}.yaml`));
|
|
251
|
+
}
|
|
241
252
|
return { files, answers };
|
|
242
253
|
}
|
|
243
254
|
/** Run the mutation boundary only after the complete questionnaire is accepted. */
|
|
@@ -385,7 +396,7 @@ function writeStaged(stageManifest, setup) {
|
|
|
385
396
|
replaceFileAtomically(target, contents, 0o600);
|
|
386
397
|
fsyncPath(target);
|
|
387
398
|
}
|
|
388
|
-
for (const kind of ['agents', 'agent_templates', 'roles', 'brains', 'room_templates'])
|
|
399
|
+
for (const kind of ['agents', 'agent_templates', 'roles', 'brains', 'room_templates', 'room_layouts'])
|
|
389
400
|
fsyncPath(join(stageRoot, kind));
|
|
390
401
|
fsyncPath(stageRoot);
|
|
391
402
|
fsyncPath(dirname(stageManifest));
|
|
@@ -394,8 +405,8 @@ function validateStaged(stageManifest) {
|
|
|
394
405
|
const config = loadConfig(stageManifest, { yamlMode: 'strict' });
|
|
395
406
|
const templates = listTemplates(config.roomTemplates ?? {});
|
|
396
407
|
const names = new Set(templates.map(template => template.name));
|
|
397
|
-
if (!['pair', 'single', 'team'].every(name => names.has(name)))
|
|
398
|
-
throw new Error('generated setup did not resolve the default single, pair, and
|
|
408
|
+
if (!['pair', 'single', 'team', 'engineering'].every(name => names.has(name)))
|
|
409
|
+
throw new Error('generated setup did not resolve the default single, pair, team, and engineering experiences');
|
|
399
410
|
for (const template of templates)
|
|
400
411
|
for (const member of template.members)
|
|
401
412
|
if (!config.agentTemplates?.[member.agent_template])
|
package/dist/isolation/policy.js
CHANGED
|
@@ -168,6 +168,8 @@ export function resolveIsolation(cfg, ctx) {
|
|
|
168
168
|
}
|
|
169
169
|
for (const dir of ctx.additionalWriteDirs ?? [])
|
|
170
170
|
addRw(dir);
|
|
171
|
+
if (ctx.subscriptionHome)
|
|
172
|
+
addRw(ctx.subscriptionHome);
|
|
171
173
|
// The selected harness/session command may live outside the system allowlist
|
|
172
174
|
// (for example Node and a bundled ACP adapter under ~/.local). The runner
|
|
173
175
|
// resolves its exact executable/package closure; keep every such bind RO.
|
|
@@ -63,6 +63,11 @@ export interface WrapContext {
|
|
|
63
63
|
* them for itself or for its peers.
|
|
64
64
|
*/
|
|
65
65
|
harnessSharedPaths?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* The pinned subscription profile home (CLAUDE_CONFIG_DIR / CODEX_HOME), mounted
|
|
68
|
+
* read-write so the CLI can refresh that profile's login. Absent for the default.
|
|
69
|
+
*/
|
|
70
|
+
subscriptionHome?: string;
|
|
66
71
|
/** Exact launcher/interpreter/module closure required by the selected command. */
|
|
67
72
|
runtimeReadPaths?: string[];
|
|
68
73
|
brokerEndpoint?: string;
|
package/dist/monitor.d.ts
CHANGED
|
@@ -88,33 +88,6 @@ export interface MonitorDeps {
|
|
|
88
88
|
* turns they trigger keep dying.
|
|
89
89
|
*/
|
|
90
90
|
export type StatusCause = 'connectivity' | 'delivery' | 'modal' | 'offline' | 'turns-failing' | 'safe-boundary' | 'auth';
|
|
91
|
-
/** Best-effort daemon config (issue #17): the fields the MCP client reads. */
|
|
92
|
-
interface DaemonConfig {
|
|
93
|
-
apiToken?: string;
|
|
94
|
-
port?: number;
|
|
95
|
-
stateDir?: string;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Read the daemon config the way the MCP client does — best-effort. Any missing,
|
|
99
|
-
* malformed, or unreadable config yields `{}` so token resolution falls through
|
|
100
|
-
* (issue #17). Only the well-typed fields we consume are surfaced.
|
|
101
|
-
*/
|
|
102
|
-
export declare function readDaemonConfig(env: NodeJS.ProcessEnv): DaemonConfig;
|
|
103
|
-
/**
|
|
104
|
-
* Resolve the daemon API token exactly like the MCP client (issue #17), a 3-step
|
|
105
|
-
* chain: `OURS_API_TOKEN` (trimmed) → config `apiToken` (trimmed) → the 0600 owner
|
|
106
|
-
* token at `<stateDir>/daemon-token`. Never generates a token; a failed read of
|
|
107
|
-
* any source (missing/unreadable) silently falls through to the next.
|
|
108
|
-
*/
|
|
109
|
-
export declare function resolveApiToken(env: NodeJS.ProcessEnv, file?: DaemonConfig): string | undefined;
|
|
110
|
-
export interface DaemonEndpoint {
|
|
111
|
-
origin: string;
|
|
112
|
-
port: number;
|
|
113
|
-
configPath: string;
|
|
114
|
-
stateDir: string;
|
|
115
|
-
url(name: string): string;
|
|
116
|
-
headers: Record<string, string>;
|
|
117
|
-
}
|
|
118
91
|
export type IdentityPresence = {
|
|
119
92
|
state: 'present';
|
|
120
93
|
temporary: boolean;
|
|
@@ -125,16 +98,12 @@ export type IdentityPresence = {
|
|
|
125
98
|
state: 'unknown';
|
|
126
99
|
detail: string;
|
|
127
100
|
};
|
|
128
|
-
/** Resolve the daemon endpoint + auth header from env → config → defaults. */
|
|
129
|
-
export declare function resolveEndpoint(env: NodeJS.ProcessEnv, includeToken?: boolean): DaemonEndpoint;
|
|
130
101
|
/**
|
|
131
102
|
* Ask the daemon's authoritative identity index. The notifications endpoint is
|
|
132
103
|
* intentionally unsuitable for lifecycle: it serves an empty 200 page for a
|
|
133
104
|
* valid but missing identity, which made a closed temp identity look healthy.
|
|
134
105
|
*/
|
|
135
106
|
export declare function probeIdentityPresence(name: string, fetch: FetchLike, env: NodeJS.ProcessEnv, deps?: IdentityProbeDeps): Promise<IdentityPresence>;
|
|
136
|
-
/** Actionable, secret-free description of every token source for this profile. */
|
|
137
|
-
export declare function authResolutionHint(ep: DaemonEndpoint): string;
|
|
138
107
|
/** Keep only the events whose type the role asked to wake on. */
|
|
139
108
|
export declare function filterEvents(events: NotifyEvent[], wakeSources: string[]): NotifyEvent[];
|
|
140
109
|
/**
|
|
@@ -196,8 +165,7 @@ export declare class Monitor {
|
|
|
196
165
|
private readonly identity;
|
|
197
166
|
private readonly cfg;
|
|
198
167
|
private readonly deps;
|
|
199
|
-
private readonly
|
|
200
|
-
private readonly profile?;
|
|
168
|
+
private readonly profile;
|
|
201
169
|
private readonly profileKey;
|
|
202
170
|
private readonly monitorLeaseToken;
|
|
203
171
|
private profileClientPromise?;
|
|
@@ -263,4 +231,3 @@ export declare class Monitor {
|
|
|
263
231
|
private writeStatus;
|
|
264
232
|
}
|
|
265
233
|
export declare function createMonitor(o: MonitorOpts): Monitor;
|
|
266
|
-
export {};
|
package/dist/monitor.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { join } from 'node:path';
|
|
5
4
|
import { attachOursClient } from '@ours.network/sdk/client';
|
|
6
5
|
import { clientProfileKey, readClientProfile, } from './client-profile.js';
|
|
@@ -42,124 +41,28 @@ const TURN_OBSERVE_INTERVAL_MS = 1_500;
|
|
|
42
41
|
const DEFAULT_TURN_FAIL_THRESHOLD = 3; // fallback when the resolved config omits it
|
|
43
42
|
class AuthError extends Error {
|
|
44
43
|
}
|
|
45
|
-
/** Path to the daemon config the MCP client uses: OURS_CONFIG ?? real ~/.ours/config.json. */
|
|
46
|
-
const daemonConfigPath = (env) => env.OURS_CONFIG ?? join(homedir(), '.ours', 'config.json');
|
|
47
|
-
/** Preserve the daemon's legacy env integer semantics: parseInt, invalid → absent. */
|
|
48
|
-
function envInt(env, name) {
|
|
49
|
-
const raw = env[name];
|
|
50
|
-
if (raw === undefined)
|
|
51
|
-
return undefined;
|
|
52
|
-
const n = parseInt(raw, 10);
|
|
53
|
-
return Number.isNaN(n) ? undefined : n;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Read the daemon config the way the MCP client does — best-effort. Any missing,
|
|
57
|
-
* malformed, or unreadable config yields `{}` so token resolution falls through
|
|
58
|
-
* (issue #17). Only the well-typed fields we consume are surfaced.
|
|
59
|
-
*/
|
|
60
|
-
export function readDaemonConfig(env) {
|
|
61
|
-
try {
|
|
62
|
-
const p = JSON.parse(readFileSync(daemonConfigPath(env), 'utf8'));
|
|
63
|
-
const o = {};
|
|
64
|
-
if (typeof p.apiToken === 'string' && p.apiToken.trim())
|
|
65
|
-
o.apiToken = p.apiToken.trim();
|
|
66
|
-
if (typeof p.port === 'number' && Number.isFinite(p.port))
|
|
67
|
-
o.port = p.port;
|
|
68
|
-
if (typeof p.stateDir === 'string')
|
|
69
|
-
o.stateDir = p.stateDir;
|
|
70
|
-
return o;
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
return {};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Resolve the daemon API token exactly like the MCP client (issue #17), a 3-step
|
|
78
|
-
* chain: `OURS_API_TOKEN` (trimmed) → config `apiToken` (trimmed) → the 0600 owner
|
|
79
|
-
* token at `<stateDir>/daemon-token`. Never generates a token; a failed read of
|
|
80
|
-
* any source (missing/unreadable) silently falls through to the next.
|
|
81
|
-
*/
|
|
82
|
-
export function resolveApiToken(env, file = readDaemonConfig(env)) {
|
|
83
|
-
const e = env.OURS_API_TOKEN?.trim();
|
|
84
|
-
if (e)
|
|
85
|
-
return e;
|
|
86
|
-
if (file.apiToken)
|
|
87
|
-
return file.apiToken;
|
|
88
|
-
const sd = env.OURS_STATE_DIR ?? file.stateDir ?? join(homedir(), '.ours');
|
|
89
|
-
try {
|
|
90
|
-
const t = readFileSync(join(sd, 'daemon-token'), 'utf8').trim();
|
|
91
|
-
if (t)
|
|
92
|
-
return t;
|
|
93
|
-
}
|
|
94
|
-
catch { /* missing/unreadable (e.g. cross-user 0600) → fall through */ }
|
|
95
|
-
return undefined;
|
|
96
|
-
}
|
|
97
|
-
/** Resolve the daemon endpoint + auth header from env → config → defaults. */
|
|
98
|
-
export function resolveEndpoint(env, includeToken = true) {
|
|
99
|
-
const file = readDaemonConfig(env);
|
|
100
|
-
const port = envInt(env, 'OURS_PORT') ?? file.port ?? DEFAULT_PORT;
|
|
101
|
-
const configPath = daemonConfigPath(env);
|
|
102
|
-
const stateDir = env.OURS_STATE_DIR ?? file.stateDir ?? join(homedir(), '.ours');
|
|
103
|
-
const token = includeToken ? resolveApiToken(env, file) : undefined;
|
|
104
|
-
const origin = `http://127.0.0.1:${port}`;
|
|
105
|
-
return {
|
|
106
|
-
origin,
|
|
107
|
-
port,
|
|
108
|
-
configPath,
|
|
109
|
-
stateDir,
|
|
110
|
-
url: (name) => `${origin}/identities/${encodeURIComponent(name)}/notifications`,
|
|
111
|
-
headers: token ? { 'x-ours-api-token': token } : {},
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
44
|
/**
|
|
115
45
|
* Ask the daemon's authoritative identity index. The notifications endpoint is
|
|
116
46
|
* intentionally unsuitable for lifecycle: it serves an empty 200 page for a
|
|
117
47
|
* valid but missing identity, which made a closed temp identity look healthy.
|
|
118
48
|
*/
|
|
119
49
|
export async function probeIdentityPresence(name, fetch, env, deps = {}) {
|
|
120
|
-
|
|
121
|
-
if (profile) {
|
|
122
|
-
let client;
|
|
123
|
-
try {
|
|
124
|
-
client = await (deps.attachClient?.({
|
|
125
|
-
endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
|
|
126
|
-
credentialPath: profile.credentialPath,
|
|
127
|
-
sessionMode: 'external', leaseToken: randomUUID(), env: {},
|
|
128
|
-
}) ?? attachOursClient({
|
|
129
|
-
endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
|
|
130
|
-
credentialPath: profile.credentialPath,
|
|
131
|
-
sessionMode: 'external', leaseToken: randomUUID(), env: {},
|
|
132
|
-
}));
|
|
133
|
-
return classifyIdentityPresence(name, await client.identities());
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
return { state: 'unknown', detail: 'selected identity index is unavailable' };
|
|
137
|
-
}
|
|
138
|
-
finally {
|
|
139
|
-
await client?.close().catch(() => undefined);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const ep = resolveEndpoint(env);
|
|
143
|
-
let response;
|
|
50
|
+
let client;
|
|
144
51
|
try {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (!response.ok)
|
|
151
|
-
return {
|
|
152
|
-
state: 'unknown',
|
|
153
|
-
detail: response.status === 401
|
|
154
|
-
? `daemon rejected the API token (401) — ${authResolutionHint(ep)}`
|
|
155
|
-
: `identity index returned HTTP ${response.status}`,
|
|
52
|
+
const profile = readClientProfile(env);
|
|
53
|
+
const options = {
|
|
54
|
+
endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
|
|
55
|
+
credentialPath: profile.credentialPath,
|
|
56
|
+
sessionMode: 'external', leaseToken: randomUUID(), env: {},
|
|
156
57
|
};
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return classifyIdentityPresence(name, body.identities);
|
|
58
|
+
client = await (deps.attachClient?.(options) ?? attachOursClient(options));
|
|
59
|
+
return classifyIdentityPresence(name, await client.identities());
|
|
160
60
|
}
|
|
161
|
-
catch
|
|
162
|
-
return { state: 'unknown', detail:
|
|
61
|
+
catch {
|
|
62
|
+
return { state: 'unknown', detail: 'gateway identity index unavailable; check the shared client profile and issued credential' };
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await client?.close().catch(() => undefined);
|
|
163
66
|
}
|
|
164
67
|
}
|
|
165
68
|
function classifyIdentityPresence(name, identities) {
|
|
@@ -186,12 +89,6 @@ function classifyIdentityPresence(name, identities) {
|
|
|
186
89
|
stale: found.stale === true,
|
|
187
90
|
};
|
|
188
91
|
}
|
|
189
|
-
/** Actionable, secret-free description of every token source for this profile. */
|
|
190
|
-
export function authResolutionHint(ep) {
|
|
191
|
-
const tokenPath = join(ep.stateDir, 'daemon-token');
|
|
192
|
-
return `set OURS_API_TOKEN, set apiToken in ${JSON.stringify(ep.configPath)}, or ensure ` +
|
|
193
|
-
`${JSON.stringify(tokenPath)} is readable by the fleet supervisor`;
|
|
194
|
-
}
|
|
195
92
|
/** Keep only the events whose type the role asked to wake on. */
|
|
196
93
|
export function filterEvents(events, wakeSources) {
|
|
197
94
|
const set = new Set(wakeSources);
|
|
@@ -414,7 +311,6 @@ export class Monitor {
|
|
|
414
311
|
identity;
|
|
415
312
|
cfg;
|
|
416
313
|
deps;
|
|
417
|
-
ep;
|
|
418
314
|
profile;
|
|
419
315
|
profileKey;
|
|
420
316
|
monitorLeaseToken = `ours-fleet-monitor-${process.pid}-${randomUUID()}`;
|
|
@@ -441,8 +337,7 @@ export class Monitor {
|
|
|
441
337
|
this.cfg = o.cfg;
|
|
442
338
|
this.deps = o.deps;
|
|
443
339
|
this.profile = readClientProfile(o.deps.env);
|
|
444
|
-
this.
|
|
445
|
-
this.profileKey = this.profile ? clientProfileKey(this.profile) : this.ep.origin;
|
|
340
|
+
this.profileKey = clientProfileKey(this.profile);
|
|
446
341
|
this.statusPath = join(o.agentDir, '.monitor-status');
|
|
447
342
|
this.cursorPath = join(o.agentDir, '.notify-cursor');
|
|
448
343
|
this.statePath = join(o.agentDir, '.monitor-state.json');
|
|
@@ -470,14 +365,8 @@ export class Monitor {
|
|
|
470
365
|
}
|
|
471
366
|
catch (e) {
|
|
472
367
|
if (e instanceof AuthError) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
this.degrade('auth', e.message);
|
|
476
|
-
}
|
|
477
|
-
else {
|
|
478
|
-
this.fatal = true;
|
|
479
|
-
this.degrade('auth', e.message, 'failed');
|
|
480
|
-
}
|
|
368
|
+
this.cursor = null;
|
|
369
|
+
this.degrade('auth', e.message);
|
|
481
370
|
}
|
|
482
371
|
else {
|
|
483
372
|
this.cursor = null;
|
|
@@ -510,11 +399,6 @@ export class Monitor {
|
|
|
510
399
|
catch (e) {
|
|
511
400
|
if (this.stopped)
|
|
512
401
|
return;
|
|
513
|
-
if (e instanceof AuthError && !this.profile) {
|
|
514
|
-
this.fatal = true;
|
|
515
|
-
this.degrade('auth', e.message, 'failed');
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
402
|
backoff = Math.min(backoff + BACKOFF_STEP_MS, BACKOFF_MAX_MS);
|
|
519
403
|
if (e instanceof AuthError)
|
|
520
404
|
this.degrade('auth', e.message);
|
|
@@ -630,23 +514,19 @@ export class Monitor {
|
|
|
630
514
|
this.currentAbort = ctrl;
|
|
631
515
|
let timedOut = false;
|
|
632
516
|
const timer = this.deps.timers.set(() => { timedOut = true; ctrl.abort(); }, timeoutMs);
|
|
633
|
-
let resp;
|
|
634
517
|
try {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
return { cursor: page.cursor, events: page.events };
|
|
643
|
-
}
|
|
644
|
-
resp = await this.deps.fetch(`${this.ep.url(this.identity)}?since=${since}`, { headers: this.ep.headers, signal: ctrl.signal });
|
|
518
|
+
const client = await this.profileClient();
|
|
519
|
+
const page = await client.readNotificationPage(this.identity, {
|
|
520
|
+
since: since === 'tip' ? 'tip' : Number.parseInt(since, 10),
|
|
521
|
+
signal: ctrl.signal,
|
|
522
|
+
requestTimeoutMs: timeoutMs,
|
|
523
|
+
});
|
|
524
|
+
return { cursor: page.cursor, events: page.events };
|
|
645
525
|
}
|
|
646
526
|
catch (error) {
|
|
647
527
|
if (timedOut && timeoutKind === 'stall')
|
|
648
528
|
throw new Error(`notification stream stalled for ${Math.round(timeoutMs / 1000)}s`);
|
|
649
|
-
if (
|
|
529
|
+
if (/(?:HTTP\s*401|unauthori[sz]ed|API token)/i.test(msg(error)))
|
|
650
530
|
throw new AuthError(`daemon rejected the API token (401) — verify the credential file `
|
|
651
531
|
+ `${JSON.stringify(this.profile.credentialPath)} selected by `
|
|
652
532
|
+ `${JSON.stringify(this.profile.configPath)}`);
|
|
@@ -656,15 +536,8 @@ export class Monitor {
|
|
|
656
536
|
this.deps.timers.clear(timer);
|
|
657
537
|
this.currentAbort = null;
|
|
658
538
|
}
|
|
659
|
-
if (resp.status === 401)
|
|
660
|
-
throw new AuthError(`daemon rejected the API token (401) — ${authResolutionHint(this.ep)}`);
|
|
661
|
-
if (!resp.ok)
|
|
662
|
-
throw new Error(`daemon returned HTTP ${resp.status}`);
|
|
663
|
-
return resp.json();
|
|
664
539
|
}
|
|
665
540
|
profileClient() {
|
|
666
|
-
if (!this.profile)
|
|
667
|
-
throw new Error('explicit client profile is not selected');
|
|
668
541
|
if (!this.profileClientPromise) {
|
|
669
542
|
const { endpoint, expectedInstanceId, credentialPath } = this.profile;
|
|
670
543
|
const options = {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ProducerConfig } from './outbox.js';
|
|
2
|
+
/** Read durable supervisor ledgers without restarting agents or attaching a
|
|
3
|
+
* conversation controller. Each tick reads at most 256 KiB per role, from its
|
|
4
|
+
* checkpoint; it never loads a complete transcript or requests model history. */
|
|
5
|
+
export declare class FleetNotificationProducer {
|
|
6
|
+
private readonly roots;
|
|
7
|
+
private readonly stateDir;
|
|
8
|
+
private readonly config;
|
|
9
|
+
private readonly warn;
|
|
10
|
+
private readonly queues;
|
|
11
|
+
private readonly timer;
|
|
12
|
+
private readonly existing;
|
|
13
|
+
constructor(roots: string[], stateDir: string, config: ProducerConfig, warn?: (line: string) => void);
|
|
14
|
+
private names;
|
|
15
|
+
poll(): void;
|
|
16
|
+
drain(): Promise<void>;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { closeSync, existsSync, lstatSync, openSync, readSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { NotificationOutbox } from './outbox.js';
|
|
5
|
+
/** Read durable supervisor ledgers without restarting agents or attaching a
|
|
6
|
+
* conversation controller. Each tick reads at most 256 KiB per role, from its
|
|
7
|
+
* checkpoint; it never loads a complete transcript or requests model history. */
|
|
8
|
+
export class FleetNotificationProducer {
|
|
9
|
+
roots;
|
|
10
|
+
stateDir;
|
|
11
|
+
config;
|
|
12
|
+
warn;
|
|
13
|
+
queues = new Map();
|
|
14
|
+
timer;
|
|
15
|
+
existing = new Set();
|
|
16
|
+
constructor(roots, stateDir, config, warn = () => { }) {
|
|
17
|
+
this.roots = roots;
|
|
18
|
+
this.stateDir = stateDir;
|
|
19
|
+
this.config = config;
|
|
20
|
+
this.warn = warn;
|
|
21
|
+
for (const root of roots)
|
|
22
|
+
for (const name of this.names(root))
|
|
23
|
+
this.existing.add(join(root, name));
|
|
24
|
+
this.poll();
|
|
25
|
+
this.timer = setInterval(() => this.poll(), 1000);
|
|
26
|
+
this.timer.unref();
|
|
27
|
+
}
|
|
28
|
+
names(root) {
|
|
29
|
+
try {
|
|
30
|
+
return readdirSync(root, { withFileTypes: true }).filter(d => d.isDirectory() && /^[a-zA-Z0-9_-]+$/.test(d.name)).map(d => d.name);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
poll() {
|
|
37
|
+
for (const root of this.roots)
|
|
38
|
+
for (const roleId of this.names(root)) {
|
|
39
|
+
const roleDir = join(root, roleId), dir = join(roleDir, '.conversation');
|
|
40
|
+
try {
|
|
41
|
+
if (!existsSync(dir) || lstatSync(dir).isSymbolicLink())
|
|
42
|
+
continue;
|
|
43
|
+
const segments = readdirSync(dir).filter(n => /^events-\d{6}\.jsonl$/.test(n) && !lstatSync(join(dir, n)).isSymbolicLink()).sort();
|
|
44
|
+
if (!segments.length)
|
|
45
|
+
continue;
|
|
46
|
+
let outbox = this.queues.get(roleDir);
|
|
47
|
+
if (!outbox) {
|
|
48
|
+
const key = createHash('sha256').update(roleDir).digest('hex');
|
|
49
|
+
outbox = new NotificationOutbox(join(this.stateDir, key + '.json'), this.config, async (value, eventId) => ({ eventId, title: `${roleId}: agent completed`, body: 'Your agent finished responding. Open the chat to view the result.',
|
|
50
|
+
url: `/fleet/chats?chat=${encodeURIComponent(roleId)}&detail=1`, ...value }), this.warn);
|
|
51
|
+
if (!outbox.checkpoint) {
|
|
52
|
+
const segment = this.existing.has(roleDir) ? segments.at(-1) : segments[0];
|
|
53
|
+
outbox.saveCheckpoint({ segment, offset: this.existing.has(roleDir) ? statSync(join(dir, segment)).size : 0, prompts: [] });
|
|
54
|
+
}
|
|
55
|
+
this.queues.set(roleDir, outbox);
|
|
56
|
+
}
|
|
57
|
+
const saved = outbox.checkpoint;
|
|
58
|
+
const current = { ...saved, prompts: [...saved.prompts], messages: { ...saved.messages } };
|
|
59
|
+
let index = segments.indexOf(current.segment);
|
|
60
|
+
if (index < 0) {
|
|
61
|
+
this.warn('Notification ledger segment unavailable; checkpoint retained');
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const file = join(dir, current.segment), size = statSync(file).size;
|
|
65
|
+
if (size < current.offset) {
|
|
66
|
+
this.warn('Notification ledger truncated; checkpoint retained');
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (size === current.offset && index < segments.length - 1) {
|
|
70
|
+
current.segment = segments[++index];
|
|
71
|
+
current.offset = 0;
|
|
72
|
+
}
|
|
73
|
+
const fd = openSync(join(dir, current.segment), 'r'), buffer = Buffer.alloc(256 * 1024);
|
|
74
|
+
let count;
|
|
75
|
+
try {
|
|
76
|
+
count = readSync(fd, buffer, 0, buffer.length, current.offset);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
closeSync(fd);
|
|
80
|
+
}
|
|
81
|
+
let position = 0;
|
|
82
|
+
while (position < count) {
|
|
83
|
+
const end = buffer.indexOf(10, position);
|
|
84
|
+
if (end < 0 || end >= count) {
|
|
85
|
+
// Oversized model/media events are irrelevant to prompt/completion
|
|
86
|
+
// correlation. Skip in bounded chunks; retain partial small lines.
|
|
87
|
+
if (current.discarding || (position === 0 && count === buffer.length)) {
|
|
88
|
+
current.offset += count - position;
|
|
89
|
+
current.discarding = true;
|
|
90
|
+
this.warn('Notification observer skipping oversized ledger record');
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (current.discarding) {
|
|
95
|
+
current.offset += end - position + 1;
|
|
96
|
+
position = end + 1;
|
|
97
|
+
current.discarding = false;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const event = JSON.parse(buffer.subarray(position, end).toString('utf8'));
|
|
101
|
+
if (event.schemaVersion !== 1 || event.roleId !== roleId)
|
|
102
|
+
throw new Error('invalid ledger event');
|
|
103
|
+
const prompt = `${event.sessionGeneration}:${event.promptId}`;
|
|
104
|
+
if (event.kind === 'prompt.admitted' && event.promptId && ['browser', 'owner_admin_console', 'owner_channel'].includes(event.source ?? '')) {
|
|
105
|
+
if (!current.prompts.includes(prompt))
|
|
106
|
+
current.prompts.push(prompt);
|
|
107
|
+
}
|
|
108
|
+
if (['message.chunk', 'message.replace'].includes(event.kind) && event.promptId && event.messageId && current.prompts.includes(prompt))
|
|
109
|
+
current.messages[prompt] = event.messageId;
|
|
110
|
+
if (event.kind === 'turn.completed' && event.promptId && current.prompts.includes(prompt)) {
|
|
111
|
+
if (!outbox.enqueue(`${roleId}:${event.sessionGeneration}:${event.seq}`, { url: `/fleet/chats?chat=${encodeURIComponent(roleId)}&detail=1#fleet-message-${encodeURIComponent(current.messages[prompt] ?? event.promptId)}` }))
|
|
112
|
+
break;
|
|
113
|
+
current.prompts = current.prompts.filter(p => p !== prompt);
|
|
114
|
+
delete current.messages[prompt];
|
|
115
|
+
}
|
|
116
|
+
current.offset += end - position + 1;
|
|
117
|
+
position = end + 1;
|
|
118
|
+
}
|
|
119
|
+
if (current.segment !== saved.segment || current.offset !== saved.offset)
|
|
120
|
+
outbox.saveCheckpoint(current);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
this.warn('Notification ledger admission pending; checkpoint will replay');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async drain() { await Promise.all([...this.queues.values()].map(q => q.drain())); }
|
|
128
|
+
async close() { clearInterval(this.timer); await Promise.all([...this.queues.values()].map(q => q.close())); }
|
|
129
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface NotificationInput {
|
|
2
|
+
eventId: string;
|
|
3
|
+
title: string;
|
|
4
|
+
body: string;
|
|
5
|
+
url: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ProducerConfig {
|
|
8
|
+
origin: string;
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function producerConfig(env?: NodeJS.ProcessEnv): ProducerConfig | undefined;
|
|
12
|
+
/** Durable producer queue. Service dedupe makes crash-after-acceptance replay safe. */
|
|
13
|
+
export declare class NotificationOutbox {
|
|
14
|
+
private readonly file;
|
|
15
|
+
private readonly config;
|
|
16
|
+
private readonly project;
|
|
17
|
+
private readonly warn;
|
|
18
|
+
private entries;
|
|
19
|
+
cursor?: number;
|
|
20
|
+
checkpoint?: unknown;
|
|
21
|
+
private running?;
|
|
22
|
+
private timer;
|
|
23
|
+
constructor(file: string, config: ProducerConfig, project: (value: unknown, id: string) => Promise<NotificationInput>, warn?: (message: string) => void);
|
|
24
|
+
private persist;
|
|
25
|
+
advance(cursor: number): void;
|
|
26
|
+
saveCheckpoint(checkpoint: unknown): void;
|
|
27
|
+
enqueue(id: string, value: unknown, cursor?: number | undefined): boolean;
|
|
28
|
+
drain(): Promise<void>;
|
|
29
|
+
private drainOnce;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
}
|