@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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { MAX_CHUNK_BYTES } from './wire.js';
|
|
3
|
+
/** Call-scoped callbacks carry no daemon credentials or upload receipts. */
|
|
4
|
+
export class FileCallbacks {
|
|
5
|
+
wire;
|
|
6
|
+
pending = new Map();
|
|
7
|
+
constructor(wire) {
|
|
8
|
+
this.wire = wire;
|
|
9
|
+
}
|
|
10
|
+
receive(frame) {
|
|
11
|
+
if (frame?.kind !== 'fs-result' || typeof frame.id !== 'string')
|
|
12
|
+
throw Error('INVALID_FILE_RESPONSE');
|
|
13
|
+
const p = this.pending.get(frame.id);
|
|
14
|
+
if (!p)
|
|
15
|
+
throw Error('UNSOLICITED_FILE_RESPONSE');
|
|
16
|
+
this.pending.delete(frame.id);
|
|
17
|
+
clearTimeout(p.timer);
|
|
18
|
+
if (frame.error)
|
|
19
|
+
p.reject(Error('AGENT_FILE_OPERATION_FAILED'));
|
|
20
|
+
else
|
|
21
|
+
p.resolve(frame.value);
|
|
22
|
+
}
|
|
23
|
+
close() {
|
|
24
|
+
for (const p of this.pending.values()) {
|
|
25
|
+
clearTimeout(p.timer);
|
|
26
|
+
p.reject(Error('FILE_BRIDGE_DISCONNECTED'));
|
|
27
|
+
}
|
|
28
|
+
this.pending.clear();
|
|
29
|
+
}
|
|
30
|
+
async rpc(call, op, args, signal) {
|
|
31
|
+
signal.throwIfAborted();
|
|
32
|
+
if (this.pending.size >= 64)
|
|
33
|
+
throw Error('FILE_CALLBACK_LIMIT');
|
|
34
|
+
const id = randomUUID();
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const finish = (f) => (value) => {
|
|
37
|
+
signal.removeEventListener('abort', abort);
|
|
38
|
+
f(value);
|
|
39
|
+
};
|
|
40
|
+
const fail = (reason) => {
|
|
41
|
+
const p = this.pending.get(id);
|
|
42
|
+
if (!p)
|
|
43
|
+
return;
|
|
44
|
+
this.pending.delete(id);
|
|
45
|
+
clearTimeout(p.timer);
|
|
46
|
+
finish(reject)(reason);
|
|
47
|
+
};
|
|
48
|
+
const abort = () => fail(Error('FILE_CALLBACK_ABORTED'));
|
|
49
|
+
const timer = setTimeout(() => fail(Error('FILE_CALLBACK_TIMEOUT')), 30_000);
|
|
50
|
+
timer.unref();
|
|
51
|
+
this.pending.set(id, { resolve: finish(resolve), reject: finish(reject), timer });
|
|
52
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
53
|
+
void this.wire
|
|
54
|
+
.send({ kind: 'fs', id, call, op, args })
|
|
55
|
+
.catch(() => fail(Error('FILE_BRIDGE_DISCONNECTED')));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async canRead(path, extra) {
|
|
59
|
+
return (await this.rpc(String(extra.requestId), 'probe', { path }, extra.signal)) === true;
|
|
60
|
+
}
|
|
61
|
+
async read(path, extra) {
|
|
62
|
+
const call = String(extra.requestId), handle = randomUUID();
|
|
63
|
+
const meta = await this.rpc(call, 'read-open', { path, handle }, extra.signal);
|
|
64
|
+
if (!meta ||
|
|
65
|
+
typeof meta.filename !== 'string' ||
|
|
66
|
+
!Number.isSafeInteger(meta.size) ||
|
|
67
|
+
meta.size < 0)
|
|
68
|
+
throw Error('INVALID_FILE_METADATA');
|
|
69
|
+
const close = async () => {
|
|
70
|
+
await this.rpc(call, 'close', { handle }, new AbortController().signal).catch(() => { });
|
|
71
|
+
};
|
|
72
|
+
const body = new ReadableStream({
|
|
73
|
+
pull: async (controller) => {
|
|
74
|
+
try {
|
|
75
|
+
const chunk = await this.rpc(call, 'read', { handle }, extra.signal);
|
|
76
|
+
if (chunk === null) {
|
|
77
|
+
controller.close();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (typeof chunk !== 'string' || chunk.length > Math.ceil(MAX_CHUNK_BYTES / 3) * 4)
|
|
81
|
+
throw Error('INVALID_FILE_CHUNK');
|
|
82
|
+
const bytes = Buffer.from(chunk, 'base64');
|
|
83
|
+
if (bytes.length > MAX_CHUNK_BYTES)
|
|
84
|
+
throw Error('FILE_CHUNK_TOO_LARGE');
|
|
85
|
+
controller.enqueue(bytes);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
controller.error(error);
|
|
89
|
+
await close();
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
cancel: close,
|
|
93
|
+
});
|
|
94
|
+
return { filename: meta.filename, size: meta.size, body, close };
|
|
95
|
+
}
|
|
96
|
+
async write(path, body, extra) {
|
|
97
|
+
const call = String(extra.requestId), handle = randomUUID();
|
|
98
|
+
const reader = body.getReader();
|
|
99
|
+
try {
|
|
100
|
+
const resolved = await this.rpc(call, 'write-open', { path, handle }, extra.signal);
|
|
101
|
+
if (typeof resolved !== 'string')
|
|
102
|
+
throw Error('INVALID_FILE_PATH');
|
|
103
|
+
let size = 0;
|
|
104
|
+
for (;;) {
|
|
105
|
+
extra.signal.throwIfAborted();
|
|
106
|
+
const chunk = await reader.read();
|
|
107
|
+
if (chunk.done)
|
|
108
|
+
break;
|
|
109
|
+
for (let offset = 0; offset < chunk.value.length; offset += MAX_CHUNK_BYTES) {
|
|
110
|
+
const bytes = chunk.value.subarray(offset, offset + MAX_CHUNK_BYTES);
|
|
111
|
+
size += bytes.length;
|
|
112
|
+
await this.rpc(call, 'write', { handle, data: Buffer.from(bytes).toString('base64') }, extra.signal);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
await this.rpc(call, 'close', { handle }, extra.signal);
|
|
116
|
+
return { path: resolved, size };
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
await reader.cancel().catch(() => { });
|
|
120
|
+
await this.rpc(call, 'close', { handle }, new AbortController().signal).catch(() => { });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AcpMcpServer } from '../harness/types.js';
|
|
2
|
+
import type { ResolvedRole } from '../config.js';
|
|
3
|
+
export interface ManagedHarnessOurs {
|
|
4
|
+
server: AcpMcpServer;
|
|
5
|
+
native: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
/** Do not pass the supervisor's ours connection credentials to harness children. */
|
|
8
|
+
export declare function managedChildEnvironment(input: NodeJS.ProcessEnv): Record<string, string>;
|
|
9
|
+
/** Replace ours only; retain the user's ordinary harness configuration and plugins. */
|
|
10
|
+
export declare function prepareManagedHarness(role: ResolvedRole, stateDir: string, cwd: string, descriptor: string, env: Record<string, string>): {
|
|
11
|
+
ours: ManagedHarnessOurs;
|
|
12
|
+
env: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
export declare function managedClaudeMeta(base: Record<string, unknown> | undefined): Record<string, unknown>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
/** Do not pass the supervisor's ours connection credentials to harness children. */
|
|
4
|
+
export function managedChildEnvironment(input) {
|
|
5
|
+
const out = {};
|
|
6
|
+
for (const [key, value] of Object.entries(input)) {
|
|
7
|
+
if (value === undefined || (/^OURS_/i.test(key) && !key.startsWith('OURS_FLEET_')))
|
|
8
|
+
continue;
|
|
9
|
+
out[key] = value;
|
|
10
|
+
}
|
|
11
|
+
out.FLEET_OURS_MANAGED = '1';
|
|
12
|
+
return out;
|
|
13
|
+
}
|
|
14
|
+
/** Replace ours only; retain the user's ordinary harness configuration and plugins. */
|
|
15
|
+
export function prepareManagedHarness(role, stateDir, cwd, descriptor, env) {
|
|
16
|
+
const bridge = fileURLToPath(new URL('./bridge.js', import.meta.url));
|
|
17
|
+
const server = {
|
|
18
|
+
name: 'ours',
|
|
19
|
+
command: process.execPath,
|
|
20
|
+
args: [bridge],
|
|
21
|
+
env: [{ name: 'FLEET_OURS_BRIDGE_DESCRIPTOR', value: descriptor }],
|
|
22
|
+
};
|
|
23
|
+
// Portable allow covers bound identity messaging, not all tools on the server.
|
|
24
|
+
const tools = role.harness === 'codex' && role.permissions?.approval === 'allow'
|
|
25
|
+
? Object.fromEntries([
|
|
26
|
+
'current_identity', 'get_messages', 'list_history', 'list_contacts', 'send_message',
|
|
27
|
+
].map(name => [name, { approval_mode: 'approve' }]))
|
|
28
|
+
: undefined;
|
|
29
|
+
const native = {
|
|
30
|
+
mcp_servers: {
|
|
31
|
+
ours: {
|
|
32
|
+
command: process.execPath,
|
|
33
|
+
args: [bridge],
|
|
34
|
+
env: { FLEET_OURS_BRIDGE_DESCRIPTOR: descriptor },
|
|
35
|
+
...(tools ? { tools } : {}),
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
plugins: { 'ours@ours-codex-marketplace': { enabled: false } },
|
|
39
|
+
};
|
|
40
|
+
const child = managedChildEnvironment({ ...process.env, ...env });
|
|
41
|
+
if (role.harness === 'codex') {
|
|
42
|
+
const config = child.CODEX_CONFIG ? JSON.parse(child.CODEX_CONFIG) : {};
|
|
43
|
+
child.CODEX_CONFIG = JSON.stringify({
|
|
44
|
+
...config,
|
|
45
|
+
mcp_servers: { ...config.mcp_servers, ...native.mcp_servers },
|
|
46
|
+
plugins: { ...config.plugins, ...native.plugins },
|
|
47
|
+
});
|
|
48
|
+
// codex-acp otherwise prefers a same-name connector from the user's config.
|
|
49
|
+
child.DISABLE_MCP_CONFIG_FILTERING = 'true';
|
|
50
|
+
}
|
|
51
|
+
return { ours: { server, native }, env: child };
|
|
52
|
+
}
|
|
53
|
+
export function managedClaudeMeta(base) {
|
|
54
|
+
const meta = base ?? {}, claude = (meta.claudeCode ?? {});
|
|
55
|
+
const options = (claude.options ?? {});
|
|
56
|
+
const settings = typeof options.settings === 'string'
|
|
57
|
+
? JSON.parse(readFileSync(options.settings, 'utf8'))
|
|
58
|
+
: (options.settings ?? {});
|
|
59
|
+
return {
|
|
60
|
+
...meta,
|
|
61
|
+
claudeCode: {
|
|
62
|
+
...claude,
|
|
63
|
+
options: {
|
|
64
|
+
...options,
|
|
65
|
+
settings: {
|
|
66
|
+
...settings,
|
|
67
|
+
enabledPlugins: { ...settings.enabledPlugins, 'ours@ours.network': false },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ApplicationIdentityStore } from '@ours.network/mcp/application-identities';
|
|
2
|
+
import type { OursClient } from '@ours.network/sdk/client';
|
|
3
|
+
import type { AgentOursRuntime } from './runtime.js';
|
|
4
|
+
export interface EndpointOptions {
|
|
5
|
+
socket: string;
|
|
6
|
+
capability: string;
|
|
7
|
+
generation: number;
|
|
8
|
+
runtime: AgentOursRuntime;
|
|
9
|
+
client: OursClient;
|
|
10
|
+
identities: ApplicationIdentityStore;
|
|
11
|
+
remoteDaemonFiles: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function startMcpEndpoint(options: EndpointOptions): Promise<{
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createServer } from 'node:net';
|
|
2
|
+
import { chmod, unlink } from 'node:fs/promises';
|
|
3
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
4
|
+
import { createManagedOursMcpServer } from '@ours.network/mcp/server';
|
|
5
|
+
import { JSONRPCMessageSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
import { FileCallbacks } from './file-rpc.js';
|
|
7
|
+
import { Wire } from './wire.js';
|
|
8
|
+
export async function startMcpEndpoint(options) {
|
|
9
|
+
const sockets = new Set();
|
|
10
|
+
const server = createServer((socket) => {
|
|
11
|
+
if (sockets.size >= 4) {
|
|
12
|
+
socket.destroy();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const wire = new Wire(socket);
|
|
16
|
+
sockets.add(wire);
|
|
17
|
+
const files = new FileCallbacks(wire);
|
|
18
|
+
let authenticated = false;
|
|
19
|
+
let inFlight = 0;
|
|
20
|
+
const ids = new Set();
|
|
21
|
+
const deadline = setTimeout(() => wire.close(), 5000);
|
|
22
|
+
deadline.unref();
|
|
23
|
+
const transport = {
|
|
24
|
+
start: async () => { },
|
|
25
|
+
send: async (message) => {
|
|
26
|
+
if ('id' in message &&
|
|
27
|
+
message.id !== undefined &&
|
|
28
|
+
('result' in message || 'error' in message))
|
|
29
|
+
ids.delete(message.id);
|
|
30
|
+
await wire.send({ kind: 'mcp', value: message });
|
|
31
|
+
},
|
|
32
|
+
close: async () => wire.close(),
|
|
33
|
+
};
|
|
34
|
+
const mcp = createManagedOursMcpServer(options.client, 'managed-v1', options.identities, {
|
|
35
|
+
remoteDaemonFiles: options.remoteDaemonFiles,
|
|
36
|
+
fileContext: files,
|
|
37
|
+
admit: async () => {
|
|
38
|
+
if (!authenticated || inFlight >= 32)
|
|
39
|
+
throw Error('MCP_ADMISSION_LIMIT');
|
|
40
|
+
inFlight++;
|
|
41
|
+
try {
|
|
42
|
+
const release = await options.runtime.admit();
|
|
43
|
+
return () => {
|
|
44
|
+
inFlight--;
|
|
45
|
+
release();
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
inFlight--;
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
wire.onClose = () => {
|
|
55
|
+
clearTimeout(deadline);
|
|
56
|
+
sockets.delete(wire);
|
|
57
|
+
files.close();
|
|
58
|
+
transport.onclose?.();
|
|
59
|
+
};
|
|
60
|
+
wire.onFrame = (frame) => {
|
|
61
|
+
if (!authenticated) {
|
|
62
|
+
const actual = typeof frame?.capability === 'string' ? Buffer.from(frame.capability) : Buffer.alloc(0);
|
|
63
|
+
const expected = Buffer.from(options.capability);
|
|
64
|
+
if (frame?.kind !== 'hello' ||
|
|
65
|
+
frame.generation !== options.generation ||
|
|
66
|
+
actual.length !== expected.length ||
|
|
67
|
+
!timingSafeEqual(actual, expected))
|
|
68
|
+
throw Error('UNAUTHORIZED_BRIDGE');
|
|
69
|
+
authenticated = true;
|
|
70
|
+
clearTimeout(deadline);
|
|
71
|
+
void mcp
|
|
72
|
+
.connect(transport)
|
|
73
|
+
.then(() => wire.send({ kind: 'ready' }))
|
|
74
|
+
.catch(() => wire.close());
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (frame?.kind === 'fs-result') {
|
|
78
|
+
files.receive(frame);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (frame?.kind !== 'mcp')
|
|
82
|
+
throw Error('UNKNOWN_BRIDGE_OPERATION');
|
|
83
|
+
const message = JSONRPCMessageSchema.parse(frame.value);
|
|
84
|
+
if ('method' in message && 'id' in message) {
|
|
85
|
+
if (ids.has(message.id) || ids.size >= 64)
|
|
86
|
+
throw Error('MCP_REQUEST_LIMIT');
|
|
87
|
+
ids.add(message.id);
|
|
88
|
+
}
|
|
89
|
+
transport.onmessage?.(message);
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
await new Promise((resolve, reject) => {
|
|
93
|
+
server.once('error', reject);
|
|
94
|
+
server.listen(options.socket, () => {
|
|
95
|
+
server.removeListener('error', reject);
|
|
96
|
+
resolve();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
await chmod(options.socket, 0o600);
|
|
100
|
+
return {
|
|
101
|
+
close: async () => {
|
|
102
|
+
for (const socket of sockets)
|
|
103
|
+
socket.close();
|
|
104
|
+
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
|
|
105
|
+
await unlink(options.socket).catch((error) => {
|
|
106
|
+
if (error.code !== 'ENOENT')
|
|
107
|
+
throw error;
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AgentHistoryQuery } from './correspondence.js';
|
|
2
|
+
import type { OursClient } from '@ours.network/sdk/client';
|
|
3
|
+
import { RuntimeJournal, type RuntimeState } from './state.js';
|
|
4
|
+
export interface AssignedIdentity {
|
|
5
|
+
instance: string;
|
|
6
|
+
generation: number;
|
|
7
|
+
daemon: string;
|
|
8
|
+
name: string;
|
|
9
|
+
lifetime: 'permanent' | 'temporary';
|
|
10
|
+
action: string;
|
|
11
|
+
expectedCid?: string;
|
|
12
|
+
allowCreate: boolean;
|
|
13
|
+
bio: string;
|
|
14
|
+
}
|
|
15
|
+
export interface RoomAdmission {
|
|
16
|
+
id: string;
|
|
17
|
+
cid: string;
|
|
18
|
+
seat: string;
|
|
19
|
+
action: string;
|
|
20
|
+
/** The secret stays in trusted storage and is never returned to the child. */
|
|
21
|
+
redeem(client: OursClient): Promise<{
|
|
22
|
+
cid: string;
|
|
23
|
+
}>;
|
|
24
|
+
observe(agentCid: string): Promise<'pending' | 'established' | 'mismatch'>;
|
|
25
|
+
discardSecret(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface RuntimeDependencies {
|
|
28
|
+
journal: RuntimeJournal;
|
|
29
|
+
/** Client is already attached to the pinned daemon with its durable external owner. */
|
|
30
|
+
client: OursClient;
|
|
31
|
+
/** Checked before every operation; tied to the cross-process controller lock. */
|
|
32
|
+
assertFence(): void;
|
|
33
|
+
sleep(ms: number): Promise<void>;
|
|
34
|
+
now(): number;
|
|
35
|
+
}
|
|
36
|
+
/** A bridge never owns this object or its client; EOF never releases its lease. */
|
|
37
|
+
export declare class AgentOursRuntime {
|
|
38
|
+
readonly assignment: AssignedIdentity;
|
|
39
|
+
private readonly deps;
|
|
40
|
+
private inFlight;
|
|
41
|
+
private drain?;
|
|
42
|
+
private accepting;
|
|
43
|
+
private state;
|
|
44
|
+
constructor(assignment: AssignedIdentity, deps: RuntimeDependencies);
|
|
45
|
+
get snapshot(): Readonly<RuntimeState>;
|
|
46
|
+
private transition;
|
|
47
|
+
private verify;
|
|
48
|
+
prepare(room?: RoomAdmission, timeoutMs?: number): Promise<void>;
|
|
49
|
+
/** Admission covers SDK calls, response rendering and agent filesystem callbacks. */
|
|
50
|
+
admit(): Promise<() => void>;
|
|
51
|
+
/** Trusted supervisor-only admission for a later room; keeps the live harness
|
|
52
|
+
* and original startup assignment. Not exposed as an agent lifecycle tool. */
|
|
53
|
+
joinAdditionalRoom(invite: string, expectedRoomCid: string): Promise<void>;
|
|
54
|
+
readContacts(): Promise<unknown>;
|
|
55
|
+
readHistory(request: AgentHistoryQuery): Promise<unknown>;
|
|
56
|
+
startHarness<T>(start: () => Promise<T>): Promise<T>;
|
|
57
|
+
suspend(): Promise<void>;
|
|
58
|
+
terminal(): Promise<void>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/** A bridge never owns this object or its client; EOF never releases its lease. */
|
|
2
|
+
export class AgentOursRuntime {
|
|
3
|
+
assignment;
|
|
4
|
+
deps;
|
|
5
|
+
inFlight = 0;
|
|
6
|
+
drain;
|
|
7
|
+
accepting = false;
|
|
8
|
+
state;
|
|
9
|
+
constructor(assignment, deps) {
|
|
10
|
+
this.assignment = assignment;
|
|
11
|
+
this.deps = deps;
|
|
12
|
+
const existing = deps.journal.read();
|
|
13
|
+
if (existing) {
|
|
14
|
+
if (existing.instance !== assignment.instance ||
|
|
15
|
+
existing.daemon !== assignment.daemon ||
|
|
16
|
+
existing.name !== assignment.name ||
|
|
17
|
+
existing.lifetime !== assignment.lifetime ||
|
|
18
|
+
existing.generation !== assignment.generation ||
|
|
19
|
+
existing.action !== assignment.action ||
|
|
20
|
+
(assignment.expectedCid !== undefined &&
|
|
21
|
+
existing.cid !== undefined &&
|
|
22
|
+
existing.cid !== assignment.expectedCid))
|
|
23
|
+
throw Error('RUNTIME_ASSIGNMENT_MISMATCH');
|
|
24
|
+
this.state = existing;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Deliberately serialize only the public ownership facts, never credentials.
|
|
28
|
+
const { instance, generation, daemon, name, lifetime, action } = assignment;
|
|
29
|
+
this.state = {
|
|
30
|
+
version: 1,
|
|
31
|
+
instance,
|
|
32
|
+
generation,
|
|
33
|
+
daemon,
|
|
34
|
+
name,
|
|
35
|
+
lifetime,
|
|
36
|
+
action,
|
|
37
|
+
phase: 'PREPARING',
|
|
38
|
+
revision: 0,
|
|
39
|
+
updatedAt: '',
|
|
40
|
+
};
|
|
41
|
+
deps.assertFence();
|
|
42
|
+
deps.journal.commit(this.state);
|
|
43
|
+
this.state = deps.journal.read();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
get snapshot() {
|
|
47
|
+
return structuredClone(this.state);
|
|
48
|
+
}
|
|
49
|
+
transition(phase, patch = {}) {
|
|
50
|
+
this.deps.assertFence();
|
|
51
|
+
this.deps.journal.commit({ ...this.state, ...patch, phase }, this.state.revision);
|
|
52
|
+
this.state = this.deps.journal.read();
|
|
53
|
+
}
|
|
54
|
+
async verify() {
|
|
55
|
+
this.deps.assertFence();
|
|
56
|
+
if (this.assignment.expectedCid && this.state.cid !== this.assignment.expectedCid)
|
|
57
|
+
throw Error('PINNED_CID_MISMATCH');
|
|
58
|
+
const actual = await this.deps.client.currentIdentity();
|
|
59
|
+
if (actual.cid !== this.state.cid ||
|
|
60
|
+
actual.name !== this.state.name ||
|
|
61
|
+
actual.temporary !== (this.state.lifetime === 'temporary') ||
|
|
62
|
+
actual.isRoot)
|
|
63
|
+
throw Error('IDENTITY_PROOF_MISMATCH');
|
|
64
|
+
this.deps.assertFence();
|
|
65
|
+
}
|
|
66
|
+
async prepare(room, timeoutMs = 30_000) {
|
|
67
|
+
if (['TERMINAL_INTENT', 'CLEANUP_PENDING', 'RELEASED', 'FAILED', 'QUIESCING'].includes(this.state.phase))
|
|
68
|
+
throw Error('RUNTIME_NOT_RESUMABLE');
|
|
69
|
+
this.deps.assertFence();
|
|
70
|
+
if (!this.state.cid) {
|
|
71
|
+
// An existing PREPARING journal is an uncertain create, never evidence of absence.
|
|
72
|
+
if (this.state.phase === 'RECOVERING')
|
|
73
|
+
throw Error('UNCERTAIN_PROVISIONING');
|
|
74
|
+
const rows = await this.deps.client.listIdentities();
|
|
75
|
+
const row = rows.find((r) => r.name === this.state.name);
|
|
76
|
+
if (row) {
|
|
77
|
+
if (!('cid' in row) ||
|
|
78
|
+
this.state.lifetime === 'temporary' ||
|
|
79
|
+
!this.assignment.expectedCid ||
|
|
80
|
+
row.cid !== this.assignment.expectedCid ||
|
|
81
|
+
row.kind === 'root' ||
|
|
82
|
+
row.temp)
|
|
83
|
+
throw Error('IDENTITY_COLLISION');
|
|
84
|
+
this.transition('RECOVERING');
|
|
85
|
+
await this.deps.client.chooseIdentity({ name: this.state.name, force: false });
|
|
86
|
+
this.transition('OWNED', { cid: row.cid });
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
if (!this.assignment.allowCreate || this.assignment.expectedCid)
|
|
90
|
+
throw Error('IDENTITY_ABSENT');
|
|
91
|
+
// Persist uncertainty before the non-idempotent call. Crash recovery requires owner proof.
|
|
92
|
+
this.transition('RECOVERING');
|
|
93
|
+
const args = {
|
|
94
|
+
name: this.state.name,
|
|
95
|
+
bio: this.assignment.bio,
|
|
96
|
+
exposeLocal: false,
|
|
97
|
+
localAutoAccept: true,
|
|
98
|
+
};
|
|
99
|
+
const created = this.state.lifetime === 'temporary'
|
|
100
|
+
? await this.deps.client.createTemporaryIdentity(args)
|
|
101
|
+
: await this.deps.client.createIdentity(args);
|
|
102
|
+
if (created.hierarchy !== 'role')
|
|
103
|
+
throw Error('ROOT_PROVISIONING_FORBIDDEN');
|
|
104
|
+
this.transition('OWNED', { cid: created.info.cid });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
await this.verify();
|
|
108
|
+
if (!room && (this.state.room || this.state.admissionIntent))
|
|
109
|
+
throw Error('ROOM_DESCRIPTOR_REQUIRED');
|
|
110
|
+
if (room) {
|
|
111
|
+
if (this.state.room &&
|
|
112
|
+
(this.state.room.id !== room.id ||
|
|
113
|
+
this.state.room.cid !== room.cid ||
|
|
114
|
+
this.state.room.seat !== room.seat ||
|
|
115
|
+
this.state.room.agentCid !== this.state.cid ||
|
|
116
|
+
this.state.room.action !== room.action))
|
|
117
|
+
throw Error('ROOM_ASSIGNMENT_MISMATCH');
|
|
118
|
+
const intent = this.state.admissionIntent;
|
|
119
|
+
if (intent &&
|
|
120
|
+
(intent.id !== room.id ||
|
|
121
|
+
intent.cid !== room.cid ||
|
|
122
|
+
intent.seat !== room.seat ||
|
|
123
|
+
intent.action !== room.action ||
|
|
124
|
+
intent.agentCid !== this.state.cid))
|
|
125
|
+
throw Error('ROOM_INTENT_MISMATCH');
|
|
126
|
+
if (!this.state.room && !intent) {
|
|
127
|
+
// A permanent identity may already occupy its seat after a clean supervisor stop.
|
|
128
|
+
const existing = await room.observe(this.state.cid);
|
|
129
|
+
if (existing === 'mismatch') {
|
|
130
|
+
this.transition('FAILED');
|
|
131
|
+
throw Error('WRONG_ROOM_SEAT');
|
|
132
|
+
}
|
|
133
|
+
this.transition('ROOM_PENDING', {
|
|
134
|
+
admissionIntent: {
|
|
135
|
+
id: room.id,
|
|
136
|
+
cid: room.cid,
|
|
137
|
+
seat: room.seat,
|
|
138
|
+
action: room.action,
|
|
139
|
+
agentCid: this.state.cid,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
if (existing !== 'established') {
|
|
143
|
+
const result = await room.redeem(this.deps.client);
|
|
144
|
+
if (result.cid !== room.cid) {
|
|
145
|
+
this.transition('FAILED');
|
|
146
|
+
throw Error('WRONG_ROOM_CID');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const deadline = this.deps.now() + timeoutMs;
|
|
151
|
+
for (;;) {
|
|
152
|
+
this.deps.assertFence();
|
|
153
|
+
const observation = await room.observe(this.state.cid);
|
|
154
|
+
if (observation === 'mismatch') {
|
|
155
|
+
this.transition('FAILED');
|
|
156
|
+
throw Error('WRONG_ROOM_SEAT');
|
|
157
|
+
}
|
|
158
|
+
if (observation === 'established')
|
|
159
|
+
break;
|
|
160
|
+
if (this.deps.now() >= deadline)
|
|
161
|
+
throw Error('ROOM_PENDING');
|
|
162
|
+
await this.deps.sleep(Math.min(250, deadline - this.deps.now()));
|
|
163
|
+
}
|
|
164
|
+
this.transition('READY', {
|
|
165
|
+
room: {
|
|
166
|
+
id: room.id,
|
|
167
|
+
cid: room.cid,
|
|
168
|
+
seat: room.seat,
|
|
169
|
+
agentCid: this.state.cid,
|
|
170
|
+
action: room.action,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
await room.discardSecret();
|
|
174
|
+
}
|
|
175
|
+
else
|
|
176
|
+
this.transition('READY');
|
|
177
|
+
this.accepting = true;
|
|
178
|
+
}
|
|
179
|
+
/** Admission covers SDK calls, response rendering and agent filesystem callbacks. */
|
|
180
|
+
async admit() {
|
|
181
|
+
this.deps.assertFence();
|
|
182
|
+
if (!this.accepting || !['READY', 'SERVING'].includes(this.state.phase))
|
|
183
|
+
throw Error('RUNTIME_NOT_READY');
|
|
184
|
+
this.inFlight++;
|
|
185
|
+
let released = false;
|
|
186
|
+
const release = () => {
|
|
187
|
+
if (released)
|
|
188
|
+
return;
|
|
189
|
+
released = true;
|
|
190
|
+
if (--this.inFlight === 0)
|
|
191
|
+
this.drain?.();
|
|
192
|
+
};
|
|
193
|
+
try {
|
|
194
|
+
await this.verify();
|
|
195
|
+
if (!this.accepting)
|
|
196
|
+
throw Error('RUNTIME_QUIESCING');
|
|
197
|
+
return release;
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
release();
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/** Trusted supervisor-only admission for a later room; keeps the live harness
|
|
205
|
+
* and original startup assignment. Not exposed as an agent lifecycle tool. */
|
|
206
|
+
async joinAdditionalRoom(invite, expectedRoomCid) {
|
|
207
|
+
const release = await this.admit();
|
|
208
|
+
try {
|
|
209
|
+
const contact = await this.deps.client.addContact({ invite });
|
|
210
|
+
if (contact.cid !== expectedRoomCid)
|
|
211
|
+
throw Error('ADDITIONAL_ROOM_CID_MISMATCH');
|
|
212
|
+
await this.verify();
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
release();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async readContacts() {
|
|
219
|
+
const release = await this.admit();
|
|
220
|
+
try {
|
|
221
|
+
const data = await this.deps.client.listContacts();
|
|
222
|
+
await this.verify();
|
|
223
|
+
return { identity: { name: this.state.name, cid: this.state.cid, generation: this.state.generation }, ...data };
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
release();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async readHistory(request) {
|
|
230
|
+
const release = await this.admit();
|
|
231
|
+
try {
|
|
232
|
+
const data = await this.deps.client.listHistory(request);
|
|
233
|
+
await this.verify();
|
|
234
|
+
return { identity: { name: this.state.name, cid: this.state.cid, generation: this.state.generation }, ...data };
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
release();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async startHarness(start) {
|
|
241
|
+
if (!this.accepting || this.state.phase !== 'READY')
|
|
242
|
+
throw Error('RUNTIME_NOT_READY');
|
|
243
|
+
await this.verify();
|
|
244
|
+
this.transition('SERVING');
|
|
245
|
+
return start();
|
|
246
|
+
}
|
|
247
|
+
async suspend() {
|
|
248
|
+
this.accepting = false;
|
|
249
|
+
if (this.inFlight)
|
|
250
|
+
await new Promise((resolve) => {
|
|
251
|
+
this.drain = resolve;
|
|
252
|
+
});
|
|
253
|
+
this.transition('RECOVERING');
|
|
254
|
+
}
|
|
255
|
+
async terminal() {
|
|
256
|
+
this.accepting = false;
|
|
257
|
+
if (this.state.phase === 'RELEASED')
|
|
258
|
+
return;
|
|
259
|
+
if (!['TERMINAL_INTENT', 'CLEANUP_PENDING'].includes(this.state.phase))
|
|
260
|
+
this.transition('QUIESCING');
|
|
261
|
+
if (this.inFlight)
|
|
262
|
+
await new Promise((resolve) => {
|
|
263
|
+
this.drain = resolve;
|
|
264
|
+
});
|
|
265
|
+
this.transition('TERMINAL_INTENT');
|
|
266
|
+
try {
|
|
267
|
+
this.deps.assertFence();
|
|
268
|
+
const ack = await this.deps.client.releaseLease();
|
|
269
|
+
if (!ack ||
|
|
270
|
+
!Array.isArray(ack.released) ||
|
|
271
|
+
!Array.isArray(ack.closed) ||
|
|
272
|
+
[...ack.released, ...ack.closed].some((name) => typeof name !== 'string') ||
|
|
273
|
+
[ack.attempted, ack.notified, ack.failed].some((n) => !Number.isSafeInteger(n) || n < 0) ||
|
|
274
|
+
ack.notified + ack.failed !== ack.attempted)
|
|
275
|
+
throw Error('INVALID_RELEASE_ACK');
|
|
276
|
+
this.transition('RELEASED', { releaseAck: ack });
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
this.transition('CLEANUP_PENDING');
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|