@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,23 @@
|
|
|
1
|
+
import type { ResolvedRole } from '../config.js';
|
|
2
|
+
import { AgentOursRuntime } from './runtime.js';
|
|
3
|
+
export declare const privateRuntimeRoot: () => string;
|
|
4
|
+
export interface ManagedAgentService {
|
|
5
|
+
runtime: AgentOursRuntime;
|
|
6
|
+
descriptor: string;
|
|
7
|
+
privatePaths: string[];
|
|
8
|
+
close(terminal: boolean): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/** Only trusted launch orchestration may write this descriptor, never the child. */
|
|
11
|
+
export declare function storeRoomSecret(role: ResolvedRole): void;
|
|
12
|
+
export declare function storeTemporaryLaunch(role: ResolvedRole, action: string): void;
|
|
13
|
+
export declare function prepareManagedAgent(role: ResolvedRole, stateDir: string, temporary: boolean): Promise<ManagedAgentService>;
|
|
14
|
+
/** Explicit trusted inventory migration: read and pin existing permanent CID, never bind. */
|
|
15
|
+
export declare function preparePermanentAssignment(role: ResolvedRole): Promise<'verified' | 'unverified'>;
|
|
16
|
+
export declare function readRoomReadiness(roomCid: string, name: string): {
|
|
17
|
+
room: string;
|
|
18
|
+
invite: string;
|
|
19
|
+
cid: string;
|
|
20
|
+
generation: number;
|
|
21
|
+
} | undefined;
|
|
22
|
+
/** Explicit logical-instance termination, independent of harness/bridge transport. */
|
|
23
|
+
export declare function releaseManagedAgent(role: ResolvedRole): Promise<void>;
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { socketPath as privateSocketPath } from '../socket-path.js';
|
|
2
|
+
import { randomBytes, randomUUID } from 'node:crypto';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { attachOursClient } from '@ours.network/sdk/client';
|
|
6
|
+
import { ApplicationIdentityStore } from '@ours.network/mcp/application-identities';
|
|
7
|
+
import { readClientProfile } from '../client-profile.js';
|
|
8
|
+
import { stateRoot } from '../paths.js';
|
|
9
|
+
import { createCoworkAdapter } from '../rooms-tasks/cowork-adapter.js';
|
|
10
|
+
import { RuntimeController } from './controller.js';
|
|
11
|
+
import { atomicPrivateWrite, binderKey } from './state.js';
|
|
12
|
+
import { AgentOursRuntime } from './runtime.js';
|
|
13
|
+
import { startMcpEndpoint } from './mcp-endpoint.js';
|
|
14
|
+
export const privateRuntimeRoot = () => join(stateRoot(), 'private-ours');
|
|
15
|
+
function roomSecretPath(role) {
|
|
16
|
+
const startup = role.roomMemberStartup;
|
|
17
|
+
return join(privateRuntimeRoot(), 'room-inputs', binderKey(startup.room_identity_cid, JSON.stringify([role.name, startup.invite_id])) + '.json');
|
|
18
|
+
}
|
|
19
|
+
function matchesRoomSecret(secret, role) {
|
|
20
|
+
const startup = role.roomMemberStartup;
|
|
21
|
+
return secret.room_id === startup.room_id && secret.room_identity_cid === startup.room_identity_cid
|
|
22
|
+
&& secret.invite_id === startup.invite_id && secret.identity_name === role.identity
|
|
23
|
+
&& secret.role === startup.role;
|
|
24
|
+
}
|
|
25
|
+
/** Only trusted launch orchestration may write this descriptor, never the child. */
|
|
26
|
+
export function storeRoomSecret(role) {
|
|
27
|
+
const startup = role.roomMemberStartup;
|
|
28
|
+
if (!startup?.invite)
|
|
29
|
+
return;
|
|
30
|
+
if (startup.identity_name !== role.identity)
|
|
31
|
+
throw Error('ROOM_SECRET_MISMATCH');
|
|
32
|
+
const root = join(privateRuntimeRoot(), 'room-inputs');
|
|
33
|
+
mkdirSync(root, { recursive: true, mode: 0o700 });
|
|
34
|
+
// Failed attempts retain private evidence. A new invite must never overwrite
|
|
35
|
+
// or consume a previous attempt's descriptor.
|
|
36
|
+
const path = roomSecretPath(role);
|
|
37
|
+
if (existsSync(path)) {
|
|
38
|
+
const old = JSON.parse(readFileSync(path, 'utf8'));
|
|
39
|
+
if (!matchesRoomSecret(old, role) || old.invite !== startup.invite)
|
|
40
|
+
throw Error('ROOM_SECRET_COLLISION');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
atomicPrivateWrite(path, startup);
|
|
44
|
+
}
|
|
45
|
+
export function storeTemporaryLaunch(role, action) {
|
|
46
|
+
const root = join(privateRuntimeRoot(), 'launches');
|
|
47
|
+
mkdirSync(root, { recursive: true, mode: 0o700 });
|
|
48
|
+
atomicPrivateWrite(join(root, binderKey('temporary', role.name) + '.json'), {
|
|
49
|
+
role: role.name,
|
|
50
|
+
identity: role.identity,
|
|
51
|
+
action,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export async function prepareManagedAgent(role, stateDir, temporary) {
|
|
55
|
+
if (role.owner_channel?.identity === role.identity)
|
|
56
|
+
throw Error('OWNER_AGENT_IDENTITY_COLLISION');
|
|
57
|
+
const profile = readClientProfile({ ...process.env, ...role.env });
|
|
58
|
+
if (!profile)
|
|
59
|
+
throw Error('MANAGED_OURS_REQUIRES_EXPLICIT_DAEMON_PROFILE');
|
|
60
|
+
const root = privateRuntimeRoot(), key = binderKey(profile.expectedInstanceId, role.identity), dir = join(root, key);
|
|
61
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
62
|
+
const instancePath = join(dir, 'instance.json');
|
|
63
|
+
const launch = temporary
|
|
64
|
+
? JSON.parse(readFileSync(join(root, 'launches', binderKey('temporary', role.name) + '.json'), 'utf8'))
|
|
65
|
+
: undefined;
|
|
66
|
+
if (launch &&
|
|
67
|
+
(launch.role !== role.name ||
|
|
68
|
+
launch.identity !== role.identity ||
|
|
69
|
+
typeof launch.action !== 'string'))
|
|
70
|
+
throw Error('INVALID_TEMP_LAUNCH');
|
|
71
|
+
let instance;
|
|
72
|
+
if (existsSync(instancePath)) {
|
|
73
|
+
const old = JSON.parse(readFileSync(instancePath, 'utf8'));
|
|
74
|
+
if (old.role !== role.name || old.temporary !== temporary)
|
|
75
|
+
throw Error('IDENTITY_ASSIGNED_TO_OTHER_ROLE');
|
|
76
|
+
instance = old.instance;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
instance = randomUUID();
|
|
80
|
+
try {
|
|
81
|
+
writeFileSync(instancePath, JSON.stringify({ instance, role: role.name, temporary }), {
|
|
82
|
+
flag: 'wx',
|
|
83
|
+
mode: 0o600,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (error.code !== 'EEXIST')
|
|
88
|
+
throw error;
|
|
89
|
+
const old = JSON.parse(readFileSync(instancePath, 'utf8'));
|
|
90
|
+
if (old.role !== role.name || old.temporary !== temporary)
|
|
91
|
+
throw Error('IDENTITY_ASSIGNED_TO_OTHER_ROLE');
|
|
92
|
+
instance = old.instance;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const controller = await RuntimeController.acquire(root, profile.expectedInstanceId, role.identity, instance);
|
|
96
|
+
let closeClient;
|
|
97
|
+
let partialEndpoint;
|
|
98
|
+
try {
|
|
99
|
+
let prior = controller.journal.read();
|
|
100
|
+
if (prior?.phase === 'RELEASED') {
|
|
101
|
+
if (temporary && launch.action === prior.action)
|
|
102
|
+
throw Error('TERMINAL_TEMP_REQUIRES_NEW_LAUNCH');
|
|
103
|
+
instance = controller.successor();
|
|
104
|
+
atomicPrivateWrite(instancePath, { instance, role: role.name, temporary });
|
|
105
|
+
if (temporary && existsSync(join(dir, 'identity-pin.json')))
|
|
106
|
+
unlinkSync(join(dir, 'identity-pin.json'));
|
|
107
|
+
prior = undefined;
|
|
108
|
+
}
|
|
109
|
+
const generation = prior ? controller.resumeGeneration() : 1;
|
|
110
|
+
const tokenPath = join(dir, 'owner.json');
|
|
111
|
+
let token;
|
|
112
|
+
if (existsSync(tokenPath)) {
|
|
113
|
+
const owner = JSON.parse(readFileSync(tokenPath, 'utf8'));
|
|
114
|
+
if (owner.instance !== instance || typeof owner.token !== 'string')
|
|
115
|
+
throw Error('OWNER_RECORD_MISMATCH');
|
|
116
|
+
token = owner.token;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
if (prior)
|
|
120
|
+
throw Error('OWNER_RECORD_MISSING');
|
|
121
|
+
token = randomBytes(32).toString('hex');
|
|
122
|
+
atomicPrivateWrite(tokenPath, { instance, token });
|
|
123
|
+
}
|
|
124
|
+
const client = await attachOursClient({
|
|
125
|
+
endpoint: profile.endpoint,
|
|
126
|
+
expectedInstanceId: profile.expectedInstanceId,
|
|
127
|
+
credentialPath: profile.credentialPath,
|
|
128
|
+
sessionMode: 'external',
|
|
129
|
+
leaseToken: token,
|
|
130
|
+
requiredCapabilities: ['external-sessions-v1', 'root-first-identities-v1'],
|
|
131
|
+
});
|
|
132
|
+
closeClient = () => client.close();
|
|
133
|
+
const pinPath = join(dir, 'identity-pin.json');
|
|
134
|
+
const pin = existsSync(pinPath) ? JSON.parse(readFileSync(pinPath, 'utf8')) : undefined;
|
|
135
|
+
if (pin &&
|
|
136
|
+
(pin.daemon !== profile.expectedInstanceId ||
|
|
137
|
+
pin.name !== role.identity ||
|
|
138
|
+
typeof pin.cid !== 'string'))
|
|
139
|
+
throw Error('INVALID_IDENTITY_PIN');
|
|
140
|
+
const runtime = new AgentOursRuntime({
|
|
141
|
+
instance,
|
|
142
|
+
generation,
|
|
143
|
+
daemon: profile.expectedInstanceId,
|
|
144
|
+
name: role.identity,
|
|
145
|
+
lifetime: temporary ? 'temporary' : 'permanent',
|
|
146
|
+
action: launch?.action ?? prior?.action ?? randomUUID(),
|
|
147
|
+
expectedCid: pin?.cid,
|
|
148
|
+
allowCreate: true,
|
|
149
|
+
bio: role.bio ?? '',
|
|
150
|
+
}, {
|
|
151
|
+
client,
|
|
152
|
+
journal: controller.journal,
|
|
153
|
+
assertFence: controller.assertFence,
|
|
154
|
+
now: Date.now,
|
|
155
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
156
|
+
});
|
|
157
|
+
let room;
|
|
158
|
+
if (role.roomMemberStartup) {
|
|
159
|
+
const startup = role.roomMemberStartup;
|
|
160
|
+
const legacyPath = join(root, 'room-inputs', binderKey(startup.room_identity_cid, role.name) + '.json');
|
|
161
|
+
const currentPath = roomSecretPath(role);
|
|
162
|
+
const path = existsSync(currentPath) ? currentPath : legacyPath;
|
|
163
|
+
const cowork = createCoworkAdapter();
|
|
164
|
+
room = {
|
|
165
|
+
id: startup.room_id,
|
|
166
|
+
cid: startup.room_identity_cid,
|
|
167
|
+
seat: startup.invite_id,
|
|
168
|
+
action: startup.invite_id,
|
|
169
|
+
redeem: async (attached) => {
|
|
170
|
+
const secret = JSON.parse(readFileSync(path, 'utf8'));
|
|
171
|
+
if (!matchesRoomSecret(secret, role))
|
|
172
|
+
throw Error('ROOM_SECRET_MISMATCH');
|
|
173
|
+
return attached.addContact({ invite: secret.invite });
|
|
174
|
+
},
|
|
175
|
+
observe: async (agentCid) => {
|
|
176
|
+
const [contacts, observed] = await Promise.all([
|
|
177
|
+
client.listContacts(),
|
|
178
|
+
cowork.getRoom(startup.room_id),
|
|
179
|
+
]);
|
|
180
|
+
if (!observed || observed.identity_cid !== startup.room_identity_cid)
|
|
181
|
+
return 'mismatch';
|
|
182
|
+
const seat = observed.seats.find((s) => s.invite_id === startup.invite_id);
|
|
183
|
+
if (seat && (seat.identity_cid !== agentCid || seat.role !== startup.role))
|
|
184
|
+
return 'mismatch';
|
|
185
|
+
return seat?.seat_state === 'active' &&
|
|
186
|
+
contacts.contacts.some((c) => c.container_id === startup.room_identity_cid)
|
|
187
|
+
? 'established'
|
|
188
|
+
: 'pending';
|
|
189
|
+
},
|
|
190
|
+
discardSecret: async () => {
|
|
191
|
+
if (existsSync(path))
|
|
192
|
+
unlinkSync(path);
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
await runtime.prepare(room);
|
|
197
|
+
if (role.roomMemberStartup) {
|
|
198
|
+
const startup = role.roomMemberStartup;
|
|
199
|
+
atomicPrivateWrite(join(root, 'room-inputs', binderKey(startup.room_identity_cid, role.name) + '.ready.json'), { room: startup.room_id, invite: startup.invite_id, cid: runtime.snapshot.cid, generation });
|
|
200
|
+
}
|
|
201
|
+
if (!pin)
|
|
202
|
+
atomicPrivateWrite(pinPath, {
|
|
203
|
+
daemon: profile.expectedInstanceId,
|
|
204
|
+
name: role.identity,
|
|
205
|
+
cid: runtime.snapshot.cid,
|
|
206
|
+
});
|
|
207
|
+
const identities = new ApplicationIdentityStore({ instanceId: profile.expectedInstanceId }, { path: join(dir, 'application.json') });
|
|
208
|
+
await identities.add(role.identity);
|
|
209
|
+
const bridgeDir = join(stateDir, '.ours-bridge');
|
|
210
|
+
mkdirSync(bridgeDir, { recursive: true, mode: 0o700 });
|
|
211
|
+
const capability = randomBytes(32).toString('hex'), socket = privateSocketPath(join(bridgeDir, `g${generation}.sock`));
|
|
212
|
+
const endpoint = await startMcpEndpoint({
|
|
213
|
+
socket,
|
|
214
|
+
capability,
|
|
215
|
+
generation,
|
|
216
|
+
runtime,
|
|
217
|
+
client,
|
|
218
|
+
identities,
|
|
219
|
+
remoteDaemonFiles: true,
|
|
220
|
+
});
|
|
221
|
+
partialEndpoint = endpoint;
|
|
222
|
+
const descriptor = join(bridgeDir, 'descriptor.json');
|
|
223
|
+
atomicPrivateWrite(descriptor, { socket, capability, generation, role: role.name, identity: role.identity, cid: runtime.snapshot.cid });
|
|
224
|
+
return {
|
|
225
|
+
runtime,
|
|
226
|
+
descriptor,
|
|
227
|
+
privatePaths: [root, profile.configPath, profile.credentialPath],
|
|
228
|
+
close: async (terminal) => {
|
|
229
|
+
try {
|
|
230
|
+
await endpoint.close();
|
|
231
|
+
if (terminal)
|
|
232
|
+
await runtime.terminal();
|
|
233
|
+
else
|
|
234
|
+
await runtime.suspend();
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
try {
|
|
238
|
+
await client.close();
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
controller.unlock();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
try {
|
|
249
|
+
await partialEndpoint?.close();
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
try {
|
|
253
|
+
await closeClient?.();
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
controller.unlock();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/** Explicit trusted inventory migration: read and pin existing permanent CID, never bind. */
|
|
263
|
+
export async function preparePermanentAssignment(role) {
|
|
264
|
+
const profile = readClientProfile({ ...process.env, ...role.env });
|
|
265
|
+
if (!profile)
|
|
266
|
+
throw Error('MANAGED_OURS_REQUIRES_EXPLICIT_DAEMON_PROFILE');
|
|
267
|
+
const client = await attachOursClient({
|
|
268
|
+
endpoint: profile.endpoint,
|
|
269
|
+
expectedInstanceId: profile.expectedInstanceId,
|
|
270
|
+
credentialPath: profile.credentialPath,
|
|
271
|
+
sessionMode: 'external',
|
|
272
|
+
leaseToken: randomUUID(),
|
|
273
|
+
requiredCapabilities: ['external-sessions-v1', 'root-first-identities-v1'],
|
|
274
|
+
env: {},
|
|
275
|
+
});
|
|
276
|
+
try {
|
|
277
|
+
const rows = await client.listIdentities(), row = rows.find((r) => r.name === role.identity);
|
|
278
|
+
if (!row)
|
|
279
|
+
return 'unverified';
|
|
280
|
+
if (!('cid' in row) || row.kind !== 'role' || row.temp)
|
|
281
|
+
throw Error('PERMANENT_ASSIGNMENT_NOT_A_ROLE');
|
|
282
|
+
const dir = join(privateRuntimeRoot(), binderKey(profile.expectedInstanceId, role.identity));
|
|
283
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
284
|
+
const path = join(dir, 'identity-pin.json');
|
|
285
|
+
if (existsSync(path)) {
|
|
286
|
+
const old = JSON.parse(readFileSync(path, 'utf8'));
|
|
287
|
+
if (old.cid !== row.cid ||
|
|
288
|
+
old.daemon !== profile.expectedInstanceId ||
|
|
289
|
+
old.name !== role.identity)
|
|
290
|
+
throw Error('PERMANENT_ASSIGNMENT_PIN_MISMATCH');
|
|
291
|
+
}
|
|
292
|
+
else
|
|
293
|
+
atomicPrivateWrite(path, {
|
|
294
|
+
daemon: profile.expectedInstanceId,
|
|
295
|
+
name: role.identity,
|
|
296
|
+
cid: row.cid,
|
|
297
|
+
});
|
|
298
|
+
return 'verified';
|
|
299
|
+
}
|
|
300
|
+
finally {
|
|
301
|
+
try {
|
|
302
|
+
await client.releaseLease();
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
await client.close();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
export function readRoomReadiness(roomCid, name) {
|
|
310
|
+
try {
|
|
311
|
+
return JSON.parse(readFileSync(join(privateRuntimeRoot(), 'room-inputs', binderKey(roomCid, name) + '.ready.json'), 'utf8'));
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
if (error.code === 'ENOENT')
|
|
315
|
+
return;
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/** Explicit logical-instance termination, independent of harness/bridge transport. */
|
|
320
|
+
export async function releaseManagedAgent(role) {
|
|
321
|
+
const profile = readClientProfile({ ...process.env, ...role.env });
|
|
322
|
+
if (!profile)
|
|
323
|
+
throw Error('MANAGED_OURS_REQUIRES_EXPLICIT_DAEMON_PROFILE');
|
|
324
|
+
const root = privateRuntimeRoot(), dir = join(root, binderKey(profile.expectedInstanceId, role.identity));
|
|
325
|
+
if (!existsSync(join(dir, 'instance.json')))
|
|
326
|
+
return;
|
|
327
|
+
const instance = JSON.parse(readFileSync(join(dir, 'instance.json'), 'utf8'));
|
|
328
|
+
if (instance.role !== role.name)
|
|
329
|
+
throw Error('IDENTITY_ASSIGNED_TO_OTHER_ROLE');
|
|
330
|
+
const controller = await RuntimeController.acquire(root, profile.expectedInstanceId, role.identity, instance.instance);
|
|
331
|
+
try {
|
|
332
|
+
const state = controller.journal.read();
|
|
333
|
+
if (!state || state.phase === 'RELEASED')
|
|
334
|
+
return;
|
|
335
|
+
const owner = JSON.parse(readFileSync(join(dir, 'owner.json'), 'utf8'));
|
|
336
|
+
if (owner.instance !== state.instance)
|
|
337
|
+
throw Error('OWNER_RECORD_MISMATCH');
|
|
338
|
+
const client = await attachOursClient({
|
|
339
|
+
endpoint: profile.endpoint,
|
|
340
|
+
expectedInstanceId: profile.expectedInstanceId,
|
|
341
|
+
credentialPath: profile.credentialPath,
|
|
342
|
+
sessionMode: 'external',
|
|
343
|
+
leaseToken: owner.token,
|
|
344
|
+
requiredCapabilities: ['external-sessions-v1', 'root-first-identities-v1'],
|
|
345
|
+
});
|
|
346
|
+
try {
|
|
347
|
+
const runtime = new AgentOursRuntime({
|
|
348
|
+
instance: state.instance,
|
|
349
|
+
generation: state.generation,
|
|
350
|
+
daemon: state.daemon,
|
|
351
|
+
name: state.name,
|
|
352
|
+
lifetime: state.lifetime,
|
|
353
|
+
action: state.action,
|
|
354
|
+
allowCreate: false,
|
|
355
|
+
bio: '',
|
|
356
|
+
}, {
|
|
357
|
+
client,
|
|
358
|
+
journal: controller.journal,
|
|
359
|
+
assertFence: controller.assertFence,
|
|
360
|
+
now: Date.now,
|
|
361
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
362
|
+
});
|
|
363
|
+
await runtime.terminal();
|
|
364
|
+
}
|
|
365
|
+
finally {
|
|
366
|
+
await client.close();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
controller.unlock();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type Phase = 'PREPARING' | 'OWNED' | 'ROOM_PENDING' | 'READY' | 'SERVING' | 'RECOVERING' | 'QUIESCING' | 'TERMINAL_INTENT' | 'RELEASED' | 'FAILED' | 'CLEANUP_PENDING';
|
|
2
|
+
export interface RuntimeState {
|
|
3
|
+
version: 1;
|
|
4
|
+
instance: string;
|
|
5
|
+
generation: number;
|
|
6
|
+
daemon: string;
|
|
7
|
+
name: string;
|
|
8
|
+
cid?: string;
|
|
9
|
+
lifetime: 'permanent' | 'temporary';
|
|
10
|
+
action: string;
|
|
11
|
+
phase: Phase;
|
|
12
|
+
revision: number;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
admissionIntent?: {
|
|
15
|
+
id: string;
|
|
16
|
+
cid: string;
|
|
17
|
+
seat: string;
|
|
18
|
+
action: string;
|
|
19
|
+
agentCid: string;
|
|
20
|
+
};
|
|
21
|
+
releaseAck?: {
|
|
22
|
+
released: string[];
|
|
23
|
+
closed: string[];
|
|
24
|
+
attempted: number;
|
|
25
|
+
notified: number;
|
|
26
|
+
failed: number;
|
|
27
|
+
};
|
|
28
|
+
room?: {
|
|
29
|
+
id: string;
|
|
30
|
+
cid: string;
|
|
31
|
+
seat: string;
|
|
32
|
+
agentCid: string;
|
|
33
|
+
action: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare function atomicPrivateWrite(path: string, value: unknown): void;
|
|
37
|
+
export declare function binderKey(daemon: string, identity: string): string;
|
|
38
|
+
/** Supervisor-owned durable state; retained across harness reconnects. */
|
|
39
|
+
export declare class RuntimeJournal {
|
|
40
|
+
readonly privateDir: string;
|
|
41
|
+
readonly path: string;
|
|
42
|
+
constructor(privateDir: string);
|
|
43
|
+
read(): RuntimeState | undefined;
|
|
44
|
+
commit(next: RuntimeState, expectedRevision?: number): void;
|
|
45
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { closeSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const phases = [
|
|
5
|
+
'PREPARING',
|
|
6
|
+
'OWNED',
|
|
7
|
+
'ROOM_PENDING',
|
|
8
|
+
'READY',
|
|
9
|
+
'SERVING',
|
|
10
|
+
'RECOVERING',
|
|
11
|
+
'QUIESCING',
|
|
12
|
+
'TERMINAL_INTENT',
|
|
13
|
+
'RELEASED',
|
|
14
|
+
'FAILED',
|
|
15
|
+
'CLEANUP_PENDING',
|
|
16
|
+
];
|
|
17
|
+
export function atomicPrivateWrite(path, value) {
|
|
18
|
+
const tmp = `${path}.${randomUUID()}.tmp`;
|
|
19
|
+
const fd = openSync(tmp, 'wx', 0o600);
|
|
20
|
+
try {
|
|
21
|
+
writeFileSync(fd, JSON.stringify(value) + '\n');
|
|
22
|
+
fsyncSync(fd);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
closeSync(fd);
|
|
26
|
+
}
|
|
27
|
+
renameSync(tmp, path);
|
|
28
|
+
const parent = openSync(join(path, '..'), 'r');
|
|
29
|
+
try {
|
|
30
|
+
fsyncSync(parent);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
closeSync(parent);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function binderKey(daemon, identity) {
|
|
37
|
+
return createHash('sha256')
|
|
38
|
+
.update(JSON.stringify([daemon, identity]))
|
|
39
|
+
.digest('hex');
|
|
40
|
+
}
|
|
41
|
+
/** Supervisor-owned durable state; retained across harness reconnects. */
|
|
42
|
+
export class RuntimeJournal {
|
|
43
|
+
privateDir;
|
|
44
|
+
path;
|
|
45
|
+
constructor(privateDir) {
|
|
46
|
+
this.privateDir = privateDir;
|
|
47
|
+
mkdirSync(privateDir, { recursive: true, mode: 0o700 });
|
|
48
|
+
this.path = join(privateDir, 'state.json');
|
|
49
|
+
}
|
|
50
|
+
read() {
|
|
51
|
+
let raw;
|
|
52
|
+
try {
|
|
53
|
+
raw = readFileSync(this.path, 'utf8');
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (error.code === 'ENOENT')
|
|
57
|
+
return;
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
const s = JSON.parse(raw);
|
|
61
|
+
if (s.version !== 1 ||
|
|
62
|
+
!s.instance ||
|
|
63
|
+
!s.daemon ||
|
|
64
|
+
!s.name ||
|
|
65
|
+
!s.action ||
|
|
66
|
+
!phases.includes(s.phase) ||
|
|
67
|
+
!Number.isSafeInteger(s.generation) ||
|
|
68
|
+
s.generation < 1 ||
|
|
69
|
+
!Number.isSafeInteger(s.revision) ||
|
|
70
|
+
!['permanent', 'temporary'].includes(s.lifetime))
|
|
71
|
+
throw Error('CORRUPT_RUNTIME_JOURNAL');
|
|
72
|
+
return s;
|
|
73
|
+
}
|
|
74
|
+
commit(next, expectedRevision) {
|
|
75
|
+
const current = this.read();
|
|
76
|
+
if (current?.revision !== expectedRevision)
|
|
77
|
+
throw Error('STALE_RUNTIME_REVISION');
|
|
78
|
+
if (current &&
|
|
79
|
+
(current.instance !== next.instance ||
|
|
80
|
+
current.daemon !== next.daemon ||
|
|
81
|
+
current.name !== next.name ||
|
|
82
|
+
current.lifetime !== next.lifetime ||
|
|
83
|
+
next.generation < current.generation))
|
|
84
|
+
throw Error('RUNTIME_IDENTITY_MISMATCH');
|
|
85
|
+
if (current &&
|
|
86
|
+
['TERMINAL_INTENT', 'CLEANUP_PENDING', 'RELEASED'].includes(current.phase) &&
|
|
87
|
+
!['TERMINAL_INTENT', 'CLEANUP_PENDING', 'RELEASED'].includes(next.phase))
|
|
88
|
+
throw Error('RETIRED_RUNTIME');
|
|
89
|
+
atomicPrivateWrite(this.path, {
|
|
90
|
+
...next,
|
|
91
|
+
revision: (expectedRevision ?? 0) + 1,
|
|
92
|
+
updatedAt: new Date().toISOString(),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Socket } from 'node:net';
|
|
2
|
+
export declare const MAX_FRAME_BYTES: number;
|
|
3
|
+
export declare const MAX_CHUNK_BYTES: number;
|
|
4
|
+
/** One bounded framed channel. No request replay after disconnect. */
|
|
5
|
+
export declare class Wire {
|
|
6
|
+
readonly socket: Socket;
|
|
7
|
+
private buffer;
|
|
8
|
+
private ended;
|
|
9
|
+
onFrame: (frame: unknown) => void;
|
|
10
|
+
onClose: () => void;
|
|
11
|
+
constructor(socket: Socket);
|
|
12
|
+
send(frame: unknown): Promise<void>;
|
|
13
|
+
close(): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const MAX_FRAME_BYTES = 1024 * 1024;
|
|
2
|
+
export const MAX_CHUNK_BYTES = 64 * 1024;
|
|
3
|
+
/** One bounded framed channel. No request replay after disconnect. */
|
|
4
|
+
export class Wire {
|
|
5
|
+
socket;
|
|
6
|
+
buffer = Buffer.alloc(0);
|
|
7
|
+
ended = false;
|
|
8
|
+
onFrame = () => { };
|
|
9
|
+
onClose = () => { };
|
|
10
|
+
constructor(socket) {
|
|
11
|
+
this.socket = socket;
|
|
12
|
+
socket.on('data', (chunk) => {
|
|
13
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
14
|
+
for (;;) {
|
|
15
|
+
const end = this.buffer.indexOf(10);
|
|
16
|
+
if (end < 0) {
|
|
17
|
+
if (this.buffer.length > MAX_FRAME_BYTES)
|
|
18
|
+
socket.destroy();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (end > MAX_FRAME_BYTES) {
|
|
22
|
+
socket.destroy();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const line = this.buffer.subarray(0, end);
|
|
26
|
+
this.buffer = this.buffer.subarray(end + 1);
|
|
27
|
+
try {
|
|
28
|
+
this.onFrame(JSON.parse(line.toString('utf8')));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
socket.destroy();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
socket.on('error', () => socket.destroy());
|
|
37
|
+
socket.on('close', () => {
|
|
38
|
+
if (!this.ended) {
|
|
39
|
+
this.ended = true;
|
|
40
|
+
this.onClose();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async send(frame) {
|
|
45
|
+
if (this.ended || this.socket.destroyed)
|
|
46
|
+
throw Error('BRIDGE_DISCONNECTED');
|
|
47
|
+
const bytes = Buffer.from(JSON.stringify(frame) + '\n');
|
|
48
|
+
if (bytes.length > MAX_FRAME_BYTES)
|
|
49
|
+
throw Error('FRAME_TOO_LARGE');
|
|
50
|
+
await new Promise((resolve, reject) => this.socket.write(bytes, (error) => (error ? reject(error) : resolve())));
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
this.socket.destroy();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ConversationEventV1 } from '../session/conversation-types.js';
|
|
2
|
+
import type { ConversationPageView } from './session-control.js';
|
|
3
|
+
/** Whether a ledger event belongs in the conversation: the live generation, or history of the resumed ACP session. */
|
|
4
|
+
export declare function conversationEventVisible(event: ConversationEventV1, sessionGeneration: string, resumedSessionId?: string): boolean;
|
|
5
|
+
export interface ConversationTailPage extends ConversationPageView {
|
|
6
|
+
/** Pass as `before` to read the next older page. */
|
|
7
|
+
olderCursor?: string;
|
|
8
|
+
hasOlder: boolean;
|
|
9
|
+
/** Latest page only: older events the view still needs, the current session's latest capabilities and still-pending permission requests. */
|
|
10
|
+
context: ConversationEventV1[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The newest `limit` visible events before `before` (or the newest overall),
|
|
14
|
+
* read backwards from the ledger so opening a long session costs one page.
|
|
15
|
+
* `nextCursor` is the newest ledger position seen, for forward `after` paging.
|
|
16
|
+
*/
|
|
17
|
+
export declare function conversationTailPage(stateDir: string, request: {
|
|
18
|
+
before?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}, snapshot: ConversationPageView['snapshot'], resumedSessionId?: string): Promise<ConversationTailPage>;
|
|
21
|
+
/** Read the existing ACP session ledger without opening its writer/recovery store. */
|
|
22
|
+
export declare function resumedConversationPage(stateDir: string, request: {
|
|
23
|
+
after?: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
}, live: ConversationPageView, expectedSessionId: string): Promise<ConversationPageView>;
|