@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
|
@@ -23,7 +23,7 @@ export class FleetConfigService {
|
|
|
23
23
|
this.preflight = options.preflight ?? (async () => emptyReport());
|
|
24
24
|
this.beforeMutation = options.beforeMutation;
|
|
25
25
|
}
|
|
26
|
-
read() {
|
|
26
|
+
read(includeDefinitions = false) {
|
|
27
27
|
const sources = readSources(this.path);
|
|
28
28
|
try {
|
|
29
29
|
loadConfig(this.path, { yamlMode: 'strict' });
|
|
@@ -31,7 +31,7 @@ export class FleetConfigService {
|
|
|
31
31
|
catch (error) {
|
|
32
32
|
throw safeError(error, sourceSensitiveValues(sources));
|
|
33
33
|
}
|
|
34
|
-
const raw = modelFrom(sources);
|
|
34
|
+
const raw = modelFrom(sources, includeDefinitions);
|
|
35
35
|
const redacted = redactModel(raw);
|
|
36
36
|
return {
|
|
37
37
|
path: basename(this.path), exists: true, firstRun: false,
|
|
@@ -41,7 +41,7 @@ export class FleetConfigService {
|
|
|
41
41
|
async preview(baseRevision, input) {
|
|
42
42
|
const current = readSources(this.path);
|
|
43
43
|
assertRevision(baseRevision, current);
|
|
44
|
-
const currentModel = modelFrom(current);
|
|
44
|
+
const currentModel = modelFrom(current, !!input && typeof input === 'object' && 'roles' in input);
|
|
45
45
|
const next = restoreRedactions(assertModel(input), currentModel, new Set(redactModel(currentModel).paths));
|
|
46
46
|
const proposal = renderProposal(current, next);
|
|
47
47
|
const staged = stageProposal(this.path, current, proposal);
|
|
@@ -63,7 +63,7 @@ export class FleetConfigService {
|
|
|
63
63
|
return withFileLock(`${splitRootFor(this.path)}.web-edit.lock`, async () => {
|
|
64
64
|
const current = readSources(this.path);
|
|
65
65
|
assertRevision(baseRevision, current);
|
|
66
|
-
const currentModel = modelFrom(current);
|
|
66
|
+
const currentModel = modelFrom(current, !!input && typeof input === 'object' && 'roles' in input);
|
|
67
67
|
const next = restoreRedactions(assertModel(input), currentModel, new Set(redactModel(currentModel).paths));
|
|
68
68
|
const proposal = renderProposal(current, next);
|
|
69
69
|
const changed = changedDocuments(current, proposal);
|
|
@@ -105,6 +105,8 @@ export class FleetConfigService {
|
|
|
105
105
|
rmSync(target, { force: true });
|
|
106
106
|
else {
|
|
107
107
|
assertWritableTarget(target, current.documents.has(rel));
|
|
108
|
+
mkdirSync(dirname(target), { recursive: true, mode: 0o700 });
|
|
109
|
+
trustedDirectory(dirname(target));
|
|
108
110
|
replaceFileAtomically(target, contents, 0o600);
|
|
109
111
|
chmodSync(target, 0o600);
|
|
110
112
|
}
|
|
@@ -184,7 +186,7 @@ function readSources(manifest) {
|
|
|
184
186
|
}
|
|
185
187
|
return { manifest, root, documents };
|
|
186
188
|
}
|
|
187
|
-
function modelFrom(sources) {
|
|
189
|
+
function modelFrom(sources, includeDefinitions = false) {
|
|
188
190
|
const manifestKey = basename(sources.manifest);
|
|
189
191
|
const manifest = parseFleetDocument(sources.manifest, sources.documents.get(manifestKey), 'strict').value;
|
|
190
192
|
const agents = {};
|
|
@@ -199,15 +201,24 @@ function modelFrom(sources) {
|
|
|
199
201
|
const id = basename(rel, extname(rel));
|
|
200
202
|
agent_templates[id] = parseFleetDocument(absoluteFor(sources.manifest, rel), source, 'strict').value;
|
|
201
203
|
}
|
|
202
|
-
|
|
204
|
+
const model = { manifest, agents, agent_templates };
|
|
205
|
+
if (includeDefinitions)
|
|
206
|
+
for (const kind of ['roles', 'brains', 'room_templates']) {
|
|
207
|
+
model[kind] = {};
|
|
208
|
+
for (const [rel, source] of sources.documents)
|
|
209
|
+
if (rel.startsWith(kind + '/') && ['.yaml', '.yml'].includes(extname(rel))) {
|
|
210
|
+
model[kind][basename(rel, extname(rel))] = parseFleetDocument(absoluteFor(sources.manifest, rel), source, 'strict').value;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return model;
|
|
203
214
|
}
|
|
204
215
|
function assertModel(value) {
|
|
205
216
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
206
217
|
throw new FleetError('invalid_request', 'model must be an object');
|
|
207
218
|
const input = value;
|
|
208
|
-
if (Object.keys(input).sort().join(',')
|
|
209
|
-
throw new FleetError('invalid_request', 'model
|
|
210
|
-
for (const key of
|
|
219
|
+
if (!['agent_templates,agents,manifest', 'agent_templates,agents,brains,manifest,roles,room_templates'].includes(Object.keys(input).sort().join(',')))
|
|
220
|
+
throw new FleetError('invalid_request', 'model requires manifest, agents, agent_templates and optionally all definition collections');
|
|
221
|
+
for (const key of Object.keys(input))
|
|
211
222
|
if (!input[key] || typeof input[key] !== 'object' || Array.isArray(input[key]))
|
|
212
223
|
throw new FleetError('invalid_request', `${key} must be an object`);
|
|
213
224
|
for (const [id, doc] of Object.entries(input.agents)) {
|
|
@@ -222,6 +233,14 @@ function assertModel(value) {
|
|
|
222
233
|
if (!doc || typeof doc !== 'object' || Array.isArray(doc))
|
|
223
234
|
throw new FleetError('invalid_request', `Agent Template '${id}' must be an object`);
|
|
224
235
|
}
|
|
236
|
+
for (const kind of ['roles', 'brains', 'room_templates']) {
|
|
237
|
+
for (const [id, doc] of Object.entries((input[kind] ?? {}))) {
|
|
238
|
+
if (!ROLE_NAME_RE.test(id))
|
|
239
|
+
throw new FleetError('invalid_request', `invalid definition ID '${id}'`);
|
|
240
|
+
if (!doc || typeof doc !== 'object' || Array.isArray(doc))
|
|
241
|
+
throw new FleetError('invalid_request', `definition '${id}' must be an object`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
225
244
|
return structuredClone(input);
|
|
226
245
|
}
|
|
227
246
|
function renderProposal(current, model) {
|
|
@@ -240,9 +259,21 @@ function renderProposal(current, model) {
|
|
|
240
259
|
next.set(oldRel ?? join('agent_templates', `${id}.yaml`), oldRel
|
|
241
260
|
? render(current.documents.get(oldRel), doc) : stringify(doc));
|
|
242
261
|
}
|
|
243
|
-
for (const [
|
|
244
|
-
if (
|
|
245
|
-
|
|
262
|
+
for (const kind of ['roles', 'brains', 'room_templates']) {
|
|
263
|
+
if (model[kind] === undefined) {
|
|
264
|
+
for (const [rel, source] of current.documents)
|
|
265
|
+
if (rel.startsWith(kind + '/'))
|
|
266
|
+
next.set(rel, source);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
for (const [rel, source] of current.documents)
|
|
270
|
+
if (rel.startsWith(kind + '/') && !['.yaml', '.yml'].includes(extname(rel)))
|
|
271
|
+
next.set(rel, source);
|
|
272
|
+
for (const [id, doc] of Object.entries(model[kind])) {
|
|
273
|
+
const oldRel = [...current.documents.keys()].find(rel => rel.startsWith(kind + '/') && ['.yaml', '.yml'].includes(extname(rel)) && basename(rel, extname(rel)) === id);
|
|
274
|
+
next.set(oldRel ?? join(kind, `${id}.yaml`), oldRel ? render(current.documents.get(oldRel), doc) : stringify(doc));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
246
277
|
return next;
|
|
247
278
|
}
|
|
248
279
|
function render(source, model) {
|
|
@@ -395,9 +426,9 @@ function sourceDiff(before, after, label, secrets) {
|
|
|
395
426
|
...left.slice(left.length - tail, left.length - tail + trailing).map(x => ` ${x}`), ''].join('\n');
|
|
396
427
|
}
|
|
397
428
|
function proposalDiff(current, proposal) {
|
|
398
|
-
const secrets = sensitiveValues(modelFrom(current));
|
|
429
|
+
const secrets = sensitiveValues(modelFrom(current, true));
|
|
399
430
|
try {
|
|
400
|
-
secrets.push(...sensitiveValues(modelFrom({ ...current, documents: proposal })));
|
|
431
|
+
secrets.push(...sensitiveValues(modelFrom({ ...current, documents: proposal }, true)));
|
|
401
432
|
}
|
|
402
433
|
catch { /* validation reports later */ }
|
|
403
434
|
return [...new Set([...current.documents.keys(), ...proposal.keys()])].sort().map(rel => sourceDiff(current.documents.get(rel) ?? '', proposal.get(rel) ?? '', rel, secrets)).filter(Boolean).join('\n');
|
|
@@ -405,7 +436,7 @@ function proposalDiff(current, proposal) {
|
|
|
405
436
|
function splitLines(source) { return source.replace(/\n$/, '').split('\n'); }
|
|
406
437
|
function restartImpact(before, after) {
|
|
407
438
|
const roles = [...new Set([...Object.keys(before.agents), ...Object.keys(after.agents)])]
|
|
408
|
-
.filter(id => JSON.stringify(before.agents[id]) !== JSON.stringify(after.agents[id])).sort();
|
|
439
|
+
.filter(id => JSON.stringify(before.agents[id]) !== JSON.stringify(after.agents[id]) || JSON.stringify(before.roles) !== JSON.stringify(after.roles) || JSON.stringify(before.brains) !== JSON.stringify(after.brains)).sort();
|
|
409
440
|
const watchdogScheduler = JSON.stringify(before.manifest.watchdogs) !== JSON.stringify(after.manifest.watchdogs);
|
|
410
441
|
const scheduledLoops = JSON.stringify(before.manifest.loops) !== JSON.stringify(after.manifest.loops);
|
|
411
442
|
const required = roles.length > 0 || watchdogScheduler || scheduledLoops;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type IncomingMessage } from 'node:http';
|
|
2
|
+
import type { WebAuth } from './auth.js';
|
|
3
|
+
/** Each entry exposes one dedicated backend listener. Endpoint dispatch stays upstream. */
|
|
4
|
+
export interface ServiceTarget {
|
|
5
|
+
prefix: string;
|
|
6
|
+
origin: string;
|
|
7
|
+
upstreamPrefix?: string;
|
|
8
|
+
/** Server-side service credentials; never taken from browser headers. */
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
/** Dedicated credential-authenticated services reject direct browser context. */
|
|
11
|
+
stripBrowserContext?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface GatewayOptions {
|
|
14
|
+
/** Backend mode is for a separate loopback machine-client listener; browsers are rejected. */
|
|
15
|
+
auth: WebAuth | 'backend';
|
|
16
|
+
fleetOrigin: string;
|
|
17
|
+
services: ServiceTarget[];
|
|
18
|
+
}
|
|
19
|
+
/** Raw transport deliberately runs outside Fastify's JSON parser and body limits. */
|
|
20
|
+
export declare function createPrefixGateway(options: GatewayOptions): {
|
|
21
|
+
server: import("http").Server<typeof IncomingMessage, typeof import("http").ServerResponse>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { createServer, request as httpRequest } from 'node:http';
|
|
2
|
+
import { request as httpsRequest } from 'node:https';
|
|
3
|
+
const hopHeaders = new Set(['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailer', 'transfer-encoding', 'upgrade']);
|
|
4
|
+
function headersFor(message) {
|
|
5
|
+
const denied = new Set([...hopHeaders, ...(message.headers.connection ?? '').split(',').map(x => x.trim().toLowerCase())]);
|
|
6
|
+
return Object.fromEntries(Object.entries(message.headers).filter(([key]) => !denied.has(key)));
|
|
7
|
+
}
|
|
8
|
+
/** Raw transport deliberately runs outside Fastify's JSON parser and body limits. */
|
|
9
|
+
export function createPrefixGateway(options) {
|
|
10
|
+
const auth = options.auth === 'backend' ? undefined : options.auth;
|
|
11
|
+
const services = options.services.map(target => {
|
|
12
|
+
if (!/^\/[a-z][a-z0-9-]*$/.test(target.prefix) || target.prefix === '/fleet')
|
|
13
|
+
throw new Error('invalid service prefix');
|
|
14
|
+
const origin = new URL(target.origin);
|
|
15
|
+
if (target.upstreamPrefix && !/^\/(?:[A-Za-z0-9_-]+\/)*[A-Za-z0-9_-]*$/.test(target.upstreamPrefix))
|
|
16
|
+
throw new Error('invalid upstream service prefix');
|
|
17
|
+
if (!['http:', 'https:'].includes(origin.protocol) || origin.pathname !== '/' || origin.search || origin.hash || origin.username || origin.password)
|
|
18
|
+
throw new Error('service target must be an HTTP origin');
|
|
19
|
+
return { ...target, origin: origin.origin };
|
|
20
|
+
});
|
|
21
|
+
if (new Set(services.map(x => x.prefix)).size !== services.length)
|
|
22
|
+
throw new Error('duplicate service prefix');
|
|
23
|
+
const select = (req) => {
|
|
24
|
+
const raw = req.url ?? '/';
|
|
25
|
+
if (!raw.startsWith('/') || raw.startsWith('//'))
|
|
26
|
+
throw new Error('invalid request target');
|
|
27
|
+
const path = raw.split('?')[0];
|
|
28
|
+
const service = services.find(x => path === x.prefix || path.startsWith(x.prefix + '/'));
|
|
29
|
+
const fleet = path === '/fleet/api' || path.startsWith('/fleet/api/');
|
|
30
|
+
return { service, page: !service && !fleet && !path.startsWith('/api/'), origin: service?.origin ?? options.fleetOrigin,
|
|
31
|
+
path: service ? (service.upstreamPrefix || '') + (raw.slice(service.prefix.length) || '/').replace(/^\?/, '/?') : fleet ? raw.slice('/fleet'.length) : raw };
|
|
32
|
+
};
|
|
33
|
+
const prepare = (req, upgrade = false) => {
|
|
34
|
+
const route = select(req);
|
|
35
|
+
const request = { headers: req.headers, method: req.method, url: route.path };
|
|
36
|
+
if (!auth && (req.headers.origin || req.headers['sec-fetch-site'] || !route.service))
|
|
37
|
+
throw new Error('machine-client listener rejects browser requests');
|
|
38
|
+
auth?.validateBoundary(request, upgrade, route.page);
|
|
39
|
+
const session = route.service && auth ? auth.authenticate(request, !upgrade && !['GET', 'HEAD', 'OPTIONS'].includes(req.method ?? 'GET')) : undefined;
|
|
40
|
+
const headers = headersFor(req);
|
|
41
|
+
// Forward only the explicit browser context, never an attacker-selected forwarding chain.
|
|
42
|
+
for (const key of Object.keys(headers))
|
|
43
|
+
if (key.startsWith('x-forwarded-') || key === 'forwarded')
|
|
44
|
+
delete headers[key];
|
|
45
|
+
if (route.service) {
|
|
46
|
+
if (auth)
|
|
47
|
+
for (const name of ['cookie', 'authorization', 'x-csrf-token', 'x-ours-api-token'])
|
|
48
|
+
delete headers[name];
|
|
49
|
+
if (route.service.stripBrowserContext) {
|
|
50
|
+
for (const name of ['origin', 'sec-fetch-site', 'sec-fetch-mode', 'sec-fetch-dest', 'sec-fetch-user'])
|
|
51
|
+
delete headers[name];
|
|
52
|
+
}
|
|
53
|
+
Object.assign(headers, route.service.headers);
|
|
54
|
+
headers.host = new URL(route.origin).host;
|
|
55
|
+
}
|
|
56
|
+
if (upgrade) {
|
|
57
|
+
headers.connection = 'Upgrade';
|
|
58
|
+
headers.upgrade = 'websocket';
|
|
59
|
+
}
|
|
60
|
+
return { ...route, headers, session };
|
|
61
|
+
};
|
|
62
|
+
const track = (req, session, close) => {
|
|
63
|
+
if (!session)
|
|
64
|
+
return () => { };
|
|
65
|
+
const unbind = auth.bindTransport(session.id, close);
|
|
66
|
+
const timer = setInterval(() => { try {
|
|
67
|
+
auth.authenticate({ headers: req.headers });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
close();
|
|
71
|
+
} }, 30_000);
|
|
72
|
+
timer.unref();
|
|
73
|
+
return () => { clearInterval(timer); unbind(); };
|
|
74
|
+
};
|
|
75
|
+
const server = createServer((req, res) => {
|
|
76
|
+
let route;
|
|
77
|
+
try {
|
|
78
|
+
route = prepare(req);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const code = error.code;
|
|
82
|
+
res.writeHead(code === 'unauthorized' ? 401 : 403, { 'content-type': 'application/json', 'cache-control': 'no-store' });
|
|
83
|
+
res.end(JSON.stringify({ error: { code: code ?? 'forbidden', message: error.message } }));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (req.url === '/') {
|
|
87
|
+
res.writeHead(302, { location: '/fleet' });
|
|
88
|
+
res.end();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const upstream = (route.origin.startsWith('https:') ? httpsRequest : httpRequest)(route.origin, {
|
|
92
|
+
method: req.method, path: route.path, headers: route.headers,
|
|
93
|
+
}, response => {
|
|
94
|
+
const headers = headersFor(response);
|
|
95
|
+
if (route.service)
|
|
96
|
+
delete headers['set-cookie'];
|
|
97
|
+
res.writeHead(response.statusCode ?? 502, headers);
|
|
98
|
+
response.on('error', () => res.destroy());
|
|
99
|
+
response.on('aborted', () => res.destroy());
|
|
100
|
+
response.on('close', () => { if (!response.complete)
|
|
101
|
+
res.destroy(); });
|
|
102
|
+
response.pipe(res);
|
|
103
|
+
res.on('close', () => response.destroy());
|
|
104
|
+
});
|
|
105
|
+
upstream.on('error', () => {
|
|
106
|
+
if (!res.headersSent)
|
|
107
|
+
res.writeHead(502, { 'content-type': 'application/json' });
|
|
108
|
+
res.end(JSON.stringify({ error: { code: 'upstream_unavailable', message: 'Service is unavailable' } }));
|
|
109
|
+
});
|
|
110
|
+
const untrack = track(req, route.session, () => { upstream.destroy(); res.destroy(); });
|
|
111
|
+
res.on('close', untrack);
|
|
112
|
+
req.on('aborted', () => upstream.destroy());
|
|
113
|
+
res.on('close', () => upstream.destroy());
|
|
114
|
+
req.pipe(upstream);
|
|
115
|
+
});
|
|
116
|
+
const sockets = new Set();
|
|
117
|
+
server.on('connection', socket => { sockets.add(socket); socket.on('close', () => sockets.delete(socket)); });
|
|
118
|
+
server.on('upgrade', (req, socket, head) => {
|
|
119
|
+
let route;
|
|
120
|
+
try {
|
|
121
|
+
route = prepare(req, true);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
socket.end('HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const upstream = (route.origin.startsWith('https:') ? httpsRequest : httpRequest)(route.origin, {
|
|
128
|
+
method: req.method, path: route.path, headers: route.headers,
|
|
129
|
+
});
|
|
130
|
+
upstream.on('upgrade', (response, peer, upstreamHead) => {
|
|
131
|
+
const headers = headersFor(response);
|
|
132
|
+
headers.connection = 'Upgrade';
|
|
133
|
+
headers.upgrade = 'websocket';
|
|
134
|
+
delete headers['set-cookie'];
|
|
135
|
+
socket.write(`HTTP/1.1 101 Switching Protocols\r\n${Object.entries(headers).flatMap(([k, v]) => (Array.isArray(v) ? v : [v]).map(value => `${k}: ${value}\r\n`)).join('')}\r\n`);
|
|
136
|
+
if (head.length)
|
|
137
|
+
peer.write(head);
|
|
138
|
+
if (upstreamHead.length)
|
|
139
|
+
socket.write(upstreamHead);
|
|
140
|
+
const untrack = track(req, route.session, () => { peer.destroy(); socket.destroy(); });
|
|
141
|
+
socket.on('close', untrack);
|
|
142
|
+
peer.pipe(socket);
|
|
143
|
+
socket.pipe(peer);
|
|
144
|
+
peer.on('error', () => socket.destroy());
|
|
145
|
+
socket.on('error', () => peer.destroy());
|
|
146
|
+
socket.on('close', () => peer.destroy());
|
|
147
|
+
peer.on('close', () => socket.destroy());
|
|
148
|
+
});
|
|
149
|
+
upstream.on('response', response => { socket.end(`HTTP/1.1 ${response.statusCode ?? 502} Rejected\r\nConnection: close\r\n\r\n`); response.destroy(); });
|
|
150
|
+
upstream.on('error', () => socket.destroy());
|
|
151
|
+
socket.on('close', () => upstream.destroy());
|
|
152
|
+
upstream.end();
|
|
153
|
+
});
|
|
154
|
+
return { server, async close() { for (const socket of sockets)
|
|
155
|
+
socket.destroy(); await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())); } };
|
|
156
|
+
}
|
package/dist/web/runtime.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { type WebServer } from './server.js';
|
|
|
2
2
|
import { type WebAccessConfig } from './access.js';
|
|
3
3
|
export interface StartWebOptions {
|
|
4
4
|
configPath?: string;
|
|
5
|
+
/** Separate console state for an independently launched gateway. */
|
|
6
|
+
webStateDir?: string;
|
|
7
|
+
control?: boolean;
|
|
8
|
+
staticRoot?: string;
|
|
5
9
|
port?: number;
|
|
6
10
|
open?: boolean;
|
|
7
11
|
binPath: string;
|
package/dist/web/runtime.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import { replaceFileAtomically } from '../atomic-file.js';
|
|
2
|
+
import { validateAccountOrigin } from '../account-origin.js';
|
|
3
|
+
import { startWorkspaceTunnel } from './workspace-tunnel.js';
|
|
4
|
+
import { createPrefixGateway } from './prefix-gateway.js';
|
|
5
|
+
import { readClientProfile } from '../client-profile.js';
|
|
6
|
+
import { readPrivateFile } from '@ours.network/sdk/connector';
|
|
7
|
+
import { LayoutBindingGrants } from '../rooms-tasks/layout-binding-grants.js';
|
|
8
|
+
import { RoomLayoutService } from '../rooms-tasks/layout-service.js';
|
|
1
9
|
import { spawn } from 'node:child_process';
|
|
2
|
-
import {
|
|
10
|
+
import { FleetNotificationProducer } from '../notifications/fleet-producer.js';
|
|
11
|
+
import { producerConfig } from '../notifications/outbox.js';
|
|
12
|
+
import { SubscriptionService } from '../subscriptions/service.js';
|
|
13
|
+
import { existsSync, realpathSync, readFileSync } from 'node:fs';
|
|
3
14
|
import { resolve } from 'node:path';
|
|
4
15
|
import { loadConfig } from '../config.js';
|
|
5
16
|
import { RoleRepository } from '../application/role-repository.js';
|
|
@@ -13,7 +24,7 @@ import { FleetError } from '../application/errors.js';
|
|
|
13
24
|
import { controlRequest, controlSocketPath } from '../session/control.js';
|
|
14
25
|
import { pickBackend } from '../supervisor/index.js';
|
|
15
26
|
import { realExec } from '../exec.js';
|
|
16
|
-
import { home, stateRoot } from '../paths.js';
|
|
27
|
+
import { home, stateRoot, agentsRoot, tmpRoot } from '../paths.js';
|
|
17
28
|
import { AuditSink } from './audit.js';
|
|
18
29
|
import { FleetEventBus } from './events.js';
|
|
19
30
|
import { buildWebServer } from './server.js';
|
|
@@ -21,8 +32,11 @@ import { FleetConfigService } from './fleet-config-service.js';
|
|
|
21
32
|
import { mergeTopology } from './topology-model.js';
|
|
22
33
|
import { TopologyDraftStore } from './topology-draft-store.js';
|
|
23
34
|
import { TopologyPromoteService } from './topology-promote.js';
|
|
35
|
+
import { RoomLayoutDefinitions } from '../application/room-layout-definitions.js';
|
|
36
|
+
import { PresetProvenance } from '../application/preset-provenance.js';
|
|
24
37
|
import { doctor } from '../doctor.js';
|
|
25
38
|
import { acquireWebServerLock } from './lock.js';
|
|
39
|
+
import { WorkspaceDeviceStore } from './workspace-devices.js';
|
|
26
40
|
import { TrustedDeviceStore } from './device-store.js';
|
|
27
41
|
import { WebAuth } from './auth.js';
|
|
28
42
|
import { startWebControlServer } from './control.js';
|
|
@@ -47,19 +61,31 @@ function cachedConfigProvider(configPath) {
|
|
|
47
61
|
};
|
|
48
62
|
}
|
|
49
63
|
export async function startWebConsole(options) {
|
|
50
|
-
const
|
|
64
|
+
const notificationConfig = producerConfig();
|
|
65
|
+
let requestedPort = options.port ?? 49_271;
|
|
51
66
|
if (!Number.isInteger(requestedPort) || requestedPort < 0 || requestedPort > 65_535)
|
|
52
67
|
throw new FleetError('invalid_request', 'port must be between 0 and 65535');
|
|
53
|
-
const
|
|
54
|
-
const
|
|
68
|
+
const webDir = options.webStateDir ?? resolve(stateRoot(), 'web');
|
|
69
|
+
const lock = acquireWebServerLock(webDir);
|
|
55
70
|
const bind = options.bind ?? '127.0.0.1';
|
|
56
71
|
const publicOrigin = options.publicOrigin ? validatePublicOrigin(options.publicOrigin) : undefined;
|
|
72
|
+
const workspaceGateway = Boolean(publicOrigin && existsSync(resolve(stateRoot(), 'workspace', 'binding.json')));
|
|
57
73
|
if (!isLoopback(bind) && !publicOrigin) {
|
|
58
74
|
lock.release();
|
|
59
75
|
throw new FleetError('forbidden', 'a non-loopback bind requires an explicit --public-origin');
|
|
60
76
|
}
|
|
61
77
|
const access = options.access ?? new WebAccessStore(webDir).read();
|
|
62
|
-
const
|
|
78
|
+
const bindingFile = resolve(stateRoot(), 'workspace', 'binding.json');
|
|
79
|
+
let appOrigin = 'https://app.ours.network';
|
|
80
|
+
try {
|
|
81
|
+
if (existsSync(bindingFile))
|
|
82
|
+
appOrigin = validateAccountOrigin(JSON.parse(readFileSync(bindingFile, 'utf8')).appOrigin ?? appOrigin);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
lock.release();
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
const auth = new WebAuth(publicOrigin?.origin ?? `http://127.0.0.1:${requestedPort}`, publicOrigin?.host ?? `127.0.0.1:${requestedPort}`, Date.now, new TrustedDeviceStore(webDir), access, new WorkspaceDeviceStore(webDir), appOrigin);
|
|
63
89
|
const backend = pickBackend();
|
|
64
90
|
const repository = new RoleRepository({
|
|
65
91
|
configPath: options.configPath,
|
|
@@ -159,8 +185,17 @@ export async function startWebConsole(options) {
|
|
|
159
185
|
try {
|
|
160
186
|
server = await buildWebServer({
|
|
161
187
|
query, repository, logs, commands, creation, removal, audit, events, watchdogs, configuration,
|
|
162
|
-
taskRooms: new TaskRoomApplicationService(options.configPath),
|
|
188
|
+
taskRooms: new TaskRoomApplicationService(options.configPath, { binPath: () => options.binPath }),
|
|
189
|
+
roomLayouts: new RoomLayoutDefinitions(options.configPath),
|
|
190
|
+
layoutBindings: new LayoutBindingGrants(new RoomLayoutService(options.configPath).supervisor()),
|
|
191
|
+
presetProvenance: new PresetProvenance(options.configPath),
|
|
163
192
|
topology: readTopology, topologyDrafts, topologyPromote,
|
|
193
|
+
subscriptions: new SubscriptionService({
|
|
194
|
+
agents: async () => (await query.list(true)).map(({ role, status }) => ({
|
|
195
|
+
roleId: role.id, stateDir: repository.stateDir(role), running: status.supervisor.liveness === 'running',
|
|
196
|
+
})),
|
|
197
|
+
onChange: () => events.publish('subscription.changed', {}),
|
|
198
|
+
}),
|
|
164
199
|
async session(roleId) {
|
|
165
200
|
const role = await repository.get(roleId);
|
|
166
201
|
if (!role)
|
|
@@ -174,7 +209,7 @@ export async function startWebConsole(options) {
|
|
|
174
209
|
}
|
|
175
210
|
throw new FleetError('capability_unavailable', 'role session backend is unavailable');
|
|
176
211
|
},
|
|
177
|
-
}, { origin: `http://127.0.0.1:${requestedPort}`, host: `127.0.0.1:${requestedPort}` }, { auth });
|
|
212
|
+
}, { origin: `http://127.0.0.1:${requestedPort}`, host: `127.0.0.1:${requestedPort}` }, { auth, staticRoot: options.staticRoot });
|
|
178
213
|
}
|
|
179
214
|
catch (error) {
|
|
180
215
|
lock.release();
|
|
@@ -182,7 +217,7 @@ export async function startWebConsole(options) {
|
|
|
182
217
|
}
|
|
183
218
|
let address;
|
|
184
219
|
try {
|
|
185
|
-
address = await server.app.listen({ host: bind, port: requestedPort });
|
|
220
|
+
address = await server.app.listen({ host: workspaceGateway ? '127.0.0.1' : bind, port: workspaceGateway ? 0 : requestedPort });
|
|
186
221
|
}
|
|
187
222
|
catch (error) {
|
|
188
223
|
await server.close();
|
|
@@ -193,27 +228,59 @@ export async function startWebConsole(options) {
|
|
|
193
228
|
const localHost = `127.0.0.1:${actual.port}`;
|
|
194
229
|
const browserOrigin = publicOrigin?.origin ?? `http://${localHost}`;
|
|
195
230
|
const browserHost = publicOrigin?.host ?? localHost;
|
|
231
|
+
let gateway;
|
|
232
|
+
if (workspaceGateway)
|
|
233
|
+
try {
|
|
234
|
+
const profile = readClientProfile(), provider = new URL(profile.serverUrl), credential = readPrivateFile(profile.credentialPath, 4096).toString('utf8').trim();
|
|
235
|
+
const basePath = provider.pathname.replace(/\/$/, '');
|
|
236
|
+
const services = ['daemon', 'cowork', 'messenger'].map(name => ({ prefix: '/' + name, origin: provider.origin, upstreamPrefix: basePath + '/' + name, stripBrowserContext: true, headers: { 'X-Ours-Api-Token': credential, ...(name === 'messenger' ? { Origin: provider.origin, 'X-Ours-Messenger-CSRF': '1' } : name === 'cowork' ? { Origin: provider.origin } : {}) } }));
|
|
237
|
+
gateway = createPrefixGateway({ auth: server.auth, fleetOrigin: address, services });
|
|
238
|
+
const listen = (port) => new Promise((resolve, reject) => { gateway.server.once('error', reject); gateway.server.listen(port, bind, () => { gateway.server.off('error', reject); resolve(); }); });
|
|
239
|
+
try {
|
|
240
|
+
await listen(requestedPort);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
const selection = resolve(webDir, 'port-selection.json');
|
|
244
|
+
if (error.code !== 'EADDRINUSE' || !existsSync(selection) || JSON.parse(readPrivateFile(selection, 4096).toString()).expiresAt <= Date.now())
|
|
245
|
+
throw error;
|
|
246
|
+
await listen(0);
|
|
247
|
+
}
|
|
248
|
+
const bound = gateway.server.address();
|
|
249
|
+
if (!bound || typeof bound === 'string')
|
|
250
|
+
throw Error('Workspace listener did not bind');
|
|
251
|
+
requestedPort = bound.port;
|
|
252
|
+
replaceFileAtomically(resolve(webDir, 'workspace-port.json'), JSON.stringify({ port: requestedPort }) + '\n', 0o600);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
await gateway?.close().catch(() => { });
|
|
256
|
+
await server.close();
|
|
257
|
+
lock.release();
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
196
260
|
server.auth.setBoundary(browserOrigin, browserHost, publicOrigin ? {
|
|
197
261
|
// nginx's safe default uses the loopback upstream as Host. The declared
|
|
198
262
|
// browser Origin remains mandatory for auth/mutations and WebSocket hello,
|
|
199
263
|
// so operators do not need a fragile Host-rewrite incantation.
|
|
200
|
-
hosts: [localHost, `localhost:${actual.port}`],
|
|
264
|
+
hosts: [localHost, `localhost:${actual.port}`, ...(workspaceGateway ? [`127.0.0.1:${requestedPort}`, `localhost:${requestedPort}`] : [])],
|
|
201
265
|
} : {
|
|
202
266
|
hosts: [`localhost:${actual.port}`], origins: [`http://localhost:${actual.port}`],
|
|
203
267
|
});
|
|
204
268
|
let control;
|
|
205
269
|
try {
|
|
206
|
-
control
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
270
|
+
if (options.control !== false)
|
|
271
|
+
control = await startWebControlServer({
|
|
272
|
+
dir: webDir,
|
|
273
|
+
onOpen() {
|
|
274
|
+
const url = access.mode === 'pairing'
|
|
275
|
+
? `${browserOrigin}/#bootstrap=${server.auth.mintBootstrap()}` : `${browserOrigin}/`;
|
|
276
|
+
openBrowser(url);
|
|
277
|
+
},
|
|
278
|
+
onLinkDevice() { return { version: 1, origin: browserOrigin, ...server.auth.workspaceEnrollment() }; },
|
|
279
|
+
onRevokeAll() { server.auth.revokeAllTrustedDevices(); },
|
|
280
|
+
});
|
|
215
281
|
}
|
|
216
282
|
catch (error) {
|
|
283
|
+
await gateway?.close();
|
|
217
284
|
await server.close();
|
|
218
285
|
lock.release();
|
|
219
286
|
throw error;
|
|
@@ -221,11 +288,30 @@ export async function startWebConsole(options) {
|
|
|
221
288
|
if (options.open !== false)
|
|
222
289
|
openBrowser(access.mode === 'pairing'
|
|
223
290
|
? `${browserOrigin}/#bootstrap=${server.auth.bootstrapSecret}` : `${browserOrigin}/`);
|
|
291
|
+
let stopTunnel;
|
|
292
|
+
try {
|
|
293
|
+
stopTunnel = startWorkspaceTunnel(browserOrigin);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
try {
|
|
297
|
+
await control?.close();
|
|
298
|
+
await gateway?.close();
|
|
299
|
+
await server.close();
|
|
300
|
+
}
|
|
301
|
+
finally {
|
|
302
|
+
lock.release();
|
|
303
|
+
}
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
const notifications = notificationConfig ? new FleetNotificationProducer([agentsRoot(), tmpRoot()], resolve(webDir, 'notification-outboxes'), notificationConfig, options.log) : undefined;
|
|
224
307
|
return {
|
|
225
308
|
...server, address: browserOrigin,
|
|
226
309
|
async close() {
|
|
227
310
|
try {
|
|
228
|
-
await
|
|
311
|
+
await stopTunnel();
|
|
312
|
+
await notifications?.close();
|
|
313
|
+
await control?.close();
|
|
314
|
+
await gateway?.close();
|
|
229
315
|
await server.close();
|
|
230
316
|
}
|
|
231
317
|
finally {
|
package/dist/web/server.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SupervisorOursTools } from '../application/supervisor-ours-tools.js';
|
|
1
2
|
import { type FastifyInstance } from 'fastify';
|
|
2
3
|
import type { FleetQueryService } from '../application/fleet-query-service.js';
|
|
3
4
|
import type { RoleRepository } from '../application/role-repository.js';
|
|
@@ -15,7 +16,12 @@ import type { TopologyDraftStore } from './topology-draft-store.js';
|
|
|
15
16
|
import type { TopologyPromoteService } from './topology-promote.js';
|
|
16
17
|
import type { RoleRemovalService } from '../application/role-removal-service.js';
|
|
17
18
|
import type { TaskRoomApplicationService } from '../application/task-room-service.js';
|
|
19
|
+
import type { RoomLayoutDefinitions } from '../application/room-layout-definitions.js';
|
|
20
|
+
import type { PresetProvenance } from '../application/preset-provenance.js';
|
|
21
|
+
import type { SubscriptionService } from '../subscriptions/service.js';
|
|
22
|
+
import type { LayoutBindingGrants } from '../rooms-tasks/layout-binding-grants.js';
|
|
18
23
|
export interface WebServices {
|
|
24
|
+
layoutBindings?: Pick<LayoutBindingGrants, 'control'>;
|
|
19
25
|
query: FleetQueryService;
|
|
20
26
|
repository: RoleRepository;
|
|
21
27
|
session(roleId: string): Promise<RoleSessionControl>;
|
|
@@ -31,6 +37,10 @@ export interface WebServices {
|
|
|
31
37
|
topologyPromote?: TopologyPromoteService;
|
|
32
38
|
removal?: RoleRemovalService;
|
|
33
39
|
taskRooms?: TaskRoomApplicationService;
|
|
40
|
+
roomLayouts?: RoomLayoutDefinitions;
|
|
41
|
+
presetProvenance?: PresetProvenance;
|
|
42
|
+
oursTools?: Pick<SupervisorOursTools, 'list' | 'call'>;
|
|
43
|
+
subscriptions?: SubscriptionService;
|
|
34
44
|
}
|
|
35
45
|
export interface WebServer {
|
|
36
46
|
app: FastifyInstance;
|
|
@@ -44,4 +54,5 @@ export declare function buildWebServer(services: WebServices, boundary: {
|
|
|
44
54
|
host: string;
|
|
45
55
|
}, options?: {
|
|
46
56
|
auth?: WebAuth;
|
|
57
|
+
staticRoot?: string;
|
|
47
58
|
}): Promise<WebServer>;
|