@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,104 @@
|
|
|
1
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
export function producerConfig(env = process.env) {
|
|
4
|
+
const origin = env.OURS_NOTIFICATIONS_ORIGIN, token = env.OURS_NOTIFICATIONS_PRODUCER_TOKEN;
|
|
5
|
+
if (!origin && !token)
|
|
6
|
+
return;
|
|
7
|
+
if (!origin || !token || token.length < 32)
|
|
8
|
+
throw new Error('notifications producer requires origin and scoped token');
|
|
9
|
+
const url = new URL(origin);
|
|
10
|
+
if (!['http:', 'https:'].includes(url.protocol) || url.origin !== origin || url.username || url.password)
|
|
11
|
+
throw new Error('invalid notification service origin');
|
|
12
|
+
if (url.protocol === 'http:' && !['127.0.0.1', '[::1]', 'localhost'].includes(url.hostname))
|
|
13
|
+
throw new Error('notification credentials require HTTPS or loopback');
|
|
14
|
+
return { origin, token };
|
|
15
|
+
}
|
|
16
|
+
/** Durable producer queue. Service dedupe makes crash-after-acceptance replay safe. */
|
|
17
|
+
export class NotificationOutbox {
|
|
18
|
+
file;
|
|
19
|
+
config;
|
|
20
|
+
project;
|
|
21
|
+
warn;
|
|
22
|
+
entries;
|
|
23
|
+
cursor;
|
|
24
|
+
checkpoint;
|
|
25
|
+
running;
|
|
26
|
+
timer;
|
|
27
|
+
constructor(file, config, project, warn = () => { }) {
|
|
28
|
+
this.file = file;
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.project = project;
|
|
31
|
+
this.warn = warn;
|
|
32
|
+
mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
|
|
33
|
+
const saved = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : { entries: [] };
|
|
34
|
+
this.entries = Array.isArray(saved) ? saved : saved.entries;
|
|
35
|
+
this.cursor = saved.cursor;
|
|
36
|
+
this.checkpoint = saved.checkpoint;
|
|
37
|
+
if (!Array.isArray(this.entries))
|
|
38
|
+
throw new Error('invalid notification outbox');
|
|
39
|
+
this.timer = setInterval(() => { void this.drain(); }, 3000);
|
|
40
|
+
this.timer.unref();
|
|
41
|
+
}
|
|
42
|
+
persist(entries, cursor = this.cursor, checkpoint = this.checkpoint) {
|
|
43
|
+
const tmp = this.file + '.tmp', fd = openSync(tmp, 'w', 0o600);
|
|
44
|
+
try {
|
|
45
|
+
writeFileSync(fd, JSON.stringify({ entries, cursor, checkpoint }));
|
|
46
|
+
fsyncSync(fd);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
closeSync(fd);
|
|
50
|
+
}
|
|
51
|
+
renameSync(tmp, this.file);
|
|
52
|
+
const dir = openSync(dirname(this.file), 'r');
|
|
53
|
+
try {
|
|
54
|
+
fsyncSync(dir);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
closeSync(dir);
|
|
58
|
+
}
|
|
59
|
+
this.entries = entries;
|
|
60
|
+
this.cursor = cursor;
|
|
61
|
+
this.checkpoint = checkpoint;
|
|
62
|
+
}
|
|
63
|
+
advance(cursor) { this.persist(this.entries, cursor); }
|
|
64
|
+
saveCheckpoint(checkpoint) { this.persist(this.entries, this.cursor, checkpoint); }
|
|
65
|
+
enqueue(id, value, cursor = this.cursor) {
|
|
66
|
+
if (this.entries.some(e => e.id === id)) {
|
|
67
|
+
if (cursor !== this.cursor)
|
|
68
|
+
this.advance(cursor);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (this.entries.length >= 2000)
|
|
72
|
+
return false;
|
|
73
|
+
this.persist([...this.entries, { id, value }], cursor);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
drain() {
|
|
77
|
+
return this.running ??= this.drainOnce().finally(() => { this.running = undefined; });
|
|
78
|
+
}
|
|
79
|
+
async drainOnce() {
|
|
80
|
+
for (const entry of [...this.entries].slice(0, 32)) {
|
|
81
|
+
try {
|
|
82
|
+
const value = entry.payload ?? await this.project(entry.value, entry.id);
|
|
83
|
+
// Freeze the canonical projection before any network attempt. A crash
|
|
84
|
+
// after service acceptance must replay the identical dedupe payload.
|
|
85
|
+
if (!entry.payload)
|
|
86
|
+
this.persist(this.entries.map(e => e.id === entry.id ? { ...e, payload: value } : e));
|
|
87
|
+
const response = await fetch(this.config.origin + '/api/v1/send', {
|
|
88
|
+
method: 'POST', redirect: 'error', signal: AbortSignal.timeout(10_000),
|
|
89
|
+
headers: { Authorization: `Bearer ${this.config.token}`, 'Content-Type': 'application/json' },
|
|
90
|
+
body: JSON.stringify(value),
|
|
91
|
+
});
|
|
92
|
+
await response.body?.cancel();
|
|
93
|
+
if (!response.ok)
|
|
94
|
+
throw new Error('notification service rejected event');
|
|
95
|
+
this.persist(this.entries.filter(e => e.id !== entry.id));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
this.warn('Notification producer delivery pending; retrying from durable outbox');
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async close() { clearInterval(this.timer); await this.running; }
|
|
104
|
+
}
|
|
@@ -14,6 +14,8 @@ export interface OwnerChannelOptions {
|
|
|
14
14
|
harness: string;
|
|
15
15
|
config: OwnerChannelConfig;
|
|
16
16
|
session: AgentSession;
|
|
17
|
+
/** Ordinary owner input must not cancel the initial briefing turn. */
|
|
18
|
+
startupPending?: () => boolean;
|
|
17
19
|
stateDir: string;
|
|
18
20
|
env?: Record<string, string>;
|
|
19
21
|
log(line: string): void;
|
|
@@ -269,6 +271,7 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
269
271
|
private attachmentGroups;
|
|
270
272
|
private handleAttachmentGroup;
|
|
271
273
|
private handle;
|
|
274
|
+
private ownerPromptPolicy;
|
|
272
275
|
/**
|
|
273
276
|
* Deterministic command path: the message never becomes an agent prompt.
|
|
274
277
|
* Authorization already happened — the managed-agent relay branch and the
|
|
@@ -883,8 +883,15 @@ export class OwnerChannel {
|
|
|
883
883
|
const recovered = [];
|
|
884
884
|
for (const claim of this.messageRecovery.list()) {
|
|
885
885
|
const item = await this.client.getHistoryItem(claim.wireId);
|
|
886
|
-
if (!item)
|
|
887
|
-
|
|
886
|
+
if (!item) {
|
|
887
|
+
// The daemon has definitively lost this body. Retrying the claim would
|
|
888
|
+
// block every later owner message, including after a supervisor restart.
|
|
889
|
+
// Keep transient lookup errors retryable; only an explicit absence skips.
|
|
890
|
+
this.messageRecovery.pruneHandled(wireId => wireId === claim.wireId);
|
|
891
|
+
this.options.log(`[${this.options.role}] skipped journaled owner message ${claim.wireId} `
|
|
892
|
+
+ `(seq=${claim.seq}): missing from persistent history`);
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
888
895
|
recovered.push(this.historyMessage(item, claim));
|
|
889
896
|
}
|
|
890
897
|
const listed = await this.client.listIncomingMessages();
|
|
@@ -1123,6 +1130,13 @@ export class OwnerChannel {
|
|
|
1123
1130
|
const retrieved = unread.length
|
|
1124
1131
|
? parseRetrievedAttachments(await this.client.getFiles(unread.map(file => file.wireId)), unread)
|
|
1125
1132
|
: [];
|
|
1133
|
+
// getFiles returns daemon-local paths, which need not exist in Fleet's
|
|
1134
|
+
// filesystem (for example with an HTTP daemon in a container). Fetch
|
|
1135
|
+
// through the bound client and keep the daemon's integrity metadata for
|
|
1136
|
+
// admission below; never trust or remap the returned filesystem path.
|
|
1137
|
+
for (const file of retrieved) {
|
|
1138
|
+
file.path = await writeRecoveredAttachment(requestDir, file.wireId, await this.client.fetchFile(file.wireId));
|
|
1139
|
+
}
|
|
1126
1140
|
for (const file of historyRecovered) {
|
|
1127
1141
|
if (!group.recovery)
|
|
1128
1142
|
throw new Error('unexpected read attachment without recovery route');
|
|
@@ -1136,8 +1150,7 @@ export class OwnerChannel {
|
|
|
1136
1150
|
await mkdir(outbox, { recursive: true, mode: 0o700 });
|
|
1137
1151
|
const activityCursor = this.latestEventSeq(this.options.session.eventsSince(0));
|
|
1138
1152
|
const queued = await queueSessionPrompt(this.options.session, this.ownerAttachmentPrompt(sender, originWireId, requestId, admitted, group.caption), {
|
|
1139
|
-
|
|
1140
|
-
...(this.options.config.interrupt ? { interruptSource: 'owner' } : {}),
|
|
1153
|
+
...this.ownerPromptPolicy(),
|
|
1141
1154
|
origin: { kind: 'owner', requestId,
|
|
1142
1155
|
...(group.caption ? { displayText: String(group.caption.text ?? '') } : {}) },
|
|
1143
1156
|
});
|
|
@@ -1263,8 +1276,7 @@ export class OwnerChannel {
|
|
|
1263
1276
|
const activityCursor = this.latestEventSeq(this.options.session.eventsSince(0));
|
|
1264
1277
|
try {
|
|
1265
1278
|
queued = await queueSessionPrompt(this.options.session, this.ownerPrompt(sender, text, wireId), {
|
|
1266
|
-
|
|
1267
|
-
...(this.options.config.interrupt ? { interruptSource: 'owner' } : {}),
|
|
1279
|
+
...this.ownerPromptPolicy(),
|
|
1268
1280
|
origin: { kind: 'owner', requestId, displayText: text },
|
|
1269
1281
|
});
|
|
1270
1282
|
}
|
|
@@ -1309,6 +1321,14 @@ export class OwnerChannel {
|
|
|
1309
1321
|
this.completionTasks.add(task);
|
|
1310
1322
|
return true;
|
|
1311
1323
|
}
|
|
1324
|
+
ownerPromptPolicy() {
|
|
1325
|
+
if (this.options.startupPending?.())
|
|
1326
|
+
return { interrupt: false, steer: true };
|
|
1327
|
+
return {
|
|
1328
|
+
interrupt: this.options.config.interrupt,
|
|
1329
|
+
...(this.options.config.interrupt ? { interruptSource: 'owner' } : {}),
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1312
1332
|
/**
|
|
1313
1333
|
* Deterministic command path: the message never becomes an agent prompt.
|
|
1314
1334
|
* Authorization already happened — the managed-agent relay branch and the
|
|
@@ -1378,6 +1398,7 @@ export class OwnerChannel {
|
|
|
1378
1398
|
await this.fleetOps.provisionTask(task.task_id);
|
|
1379
1399
|
return outcome;
|
|
1380
1400
|
}),
|
|
1401
|
+
observeTaskReadiness: taskId => new TaskRoomApplicationService(this.options.configPath).observeTaskReadiness(taskId),
|
|
1381
1402
|
taskProvisioningOutcome: taskId => new TaskRoomApplicationService(this.options.configPath).taskProvisioningOutcome(taskId),
|
|
1382
1403
|
listTasks: filter => new TaskRoomApplicationService(this.options.configPath).listTasks(filter),
|
|
1383
1404
|
groupedTasks: filter => new TaskRoomApplicationService(this.options.configPath).groupedTasks(filter),
|
|
@@ -1762,6 +1783,13 @@ export class OwnerChannel {
|
|
|
1762
1783
|
const retrieved = unread.length
|
|
1763
1784
|
? parseRetrievedAttachments(await this.client.getFiles(unread.map(file => file.wireId)), unread)
|
|
1764
1785
|
: [];
|
|
1786
|
+
// getFiles returns daemon-local paths, which need not exist in Fleet's
|
|
1787
|
+
// filesystem (for example with an HTTP daemon in a container). Fetch
|
|
1788
|
+
// through the bound client and keep the daemon's integrity metadata for
|
|
1789
|
+
// admission below; never trust or remap the returned filesystem path.
|
|
1790
|
+
for (const file of retrieved) {
|
|
1791
|
+
file.path = await writeRecoveredAttachment(requestDir, file.wireId, await this.client.fetchFile(file.wireId));
|
|
1792
|
+
}
|
|
1765
1793
|
for (const file of historyRecovered) {
|
|
1766
1794
|
if (!group.recovery)
|
|
1767
1795
|
throw new Error('unexpected read attachment without recovery route');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TaskReadinessIssue } from '../rooms-tasks/live-readiness.js';
|
|
1
2
|
import type { InterruptOutcome, SessionEvent, SessionSnapshot } from '../session/types.js';
|
|
2
3
|
import type { RoomOrchestrationRecord, TaskOutcome, TaskRecord, TaskTerminalIntent, TaskListRecord } from '../rooms-tasks/types.js';
|
|
3
4
|
import { type OwnerCommentsState } from './notices.js';
|
|
@@ -58,6 +59,9 @@ export interface OwnerCommandContext {
|
|
|
58
59
|
terminalTask(taskId: string, kind: TaskTerminalIntent['kind'], outcome?: TaskOutcome): Promise<void>;
|
|
59
60
|
createTask(input: Omit<CreateTaskRequest, 'actor'>): Promise<TaskRecord>;
|
|
60
61
|
startTask(taskId: string): Promise<TaskProvisioningOutcome | TaskRecord>;
|
|
62
|
+
observeTaskReadiness?(taskId: string): Promise<{
|
|
63
|
+
state: 'ready';
|
|
64
|
+
} | TaskReadinessIssue>;
|
|
61
65
|
taskProvisioningOutcome?(taskId: string): TaskProvisioningOutcome;
|
|
62
66
|
listTasks(filter?: {
|
|
63
67
|
state?: TaskState | TaskState[];
|
|
@@ -47,6 +47,11 @@ function isKnownOwnerRoomState(message) {
|
|
|
47
47
|
].some(pattern => pattern.test(message));
|
|
48
48
|
}
|
|
49
49
|
function ownerTaskFailure(error) {
|
|
50
|
+
if (error instanceof TaskRoomApplicationError && error.code === 'task_not_ready')
|
|
51
|
+
return {
|
|
52
|
+
kind: 'state', detail: error.message,
|
|
53
|
+
action: 'Ask Fleet Coordinator to inspect room and member status and choose supported recovery.',
|
|
54
|
+
};
|
|
50
55
|
if (error instanceof TaskListError)
|
|
51
56
|
return {
|
|
52
57
|
kind: error.code === 'list_not_found' ? 'not_found'
|
|
@@ -301,6 +306,7 @@ export const ownerCommands = [
|
|
|
301
306
|
const trailingLines = argLines.slice(1).join('\n').trim() || undefined;
|
|
302
307
|
const showTask = async (id) => {
|
|
303
308
|
const { task: t } = ctx.getTask(id);
|
|
309
|
+
const readiness = t.state === 'active' ? await ctx.observeTaskReadiness?.(id) : undefined;
|
|
304
310
|
await ctx.reply(renderMarkdownResult({
|
|
305
311
|
icon: '📋', title: 'Task details',
|
|
306
312
|
fields: [
|
|
@@ -308,6 +314,8 @@ export const ownerCommands = [
|
|
|
308
314
|
{ label: 'Title', value: t.title },
|
|
309
315
|
{ label: 'Status', value: taskStatus(t.state), kind: 'markdown' },
|
|
310
316
|
{ label: 'List', value: t.list_name ?? 'default', kind: 'code' },
|
|
317
|
+
...(readiness ? [{ label: 'Readiness', value: readiness.state },
|
|
318
|
+
...('reason' in readiness ? [{ label: 'Reason', value: readiness.reason }] : [])] : []),
|
|
311
319
|
...(t.blocked ? [{ label: 'Blocked', value: t.blocked.reason }] : []),
|
|
312
320
|
...(t.template ? [{ label: 'Template', value: `${t.template.name}@${t.template.version}`, kind: 'code' }] : []),
|
|
313
321
|
...(t.room_id ? [{ label: 'Room', value: t.room_id, kind: 'code' }] : []),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { redactErasedContent, writePrivacyFilteredLedger } from '../erased-resources.js';
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
3
|
import { chmodSync, existsSync, readFileSync } from 'node:fs';
|
|
3
|
-
import { replaceFileAtomically } from '../atomic-file.js';
|
|
4
4
|
import { lifecycleEventDigestBasis, validateFleetAuditPresentations, } from '../fleet-command-audit.js';
|
|
5
5
|
const DIGEST = /^[a-f0-9]{64}$/u;
|
|
6
6
|
const LIMIT = 5_000;
|
|
@@ -63,7 +63,7 @@ export class FleetLifecycleOutbox {
|
|
|
63
63
|
}
|
|
64
64
|
pending() {
|
|
65
65
|
this.assertHealthy();
|
|
66
|
-
return this.entries.filter(entry => entry.delivery === 'pending').map(entry => structuredClone(entry));
|
|
66
|
+
return redactErasedContent(this.entries).filter(entry => entry.delivery === 'pending').map(entry => structuredClone(entry));
|
|
67
67
|
}
|
|
68
68
|
finish(digest, delivery) {
|
|
69
69
|
this.assertHealthy();
|
|
@@ -82,6 +82,7 @@ export class FleetLifecycleOutbox {
|
|
|
82
82
|
throw new Error(this.corruptReason);
|
|
83
83
|
}
|
|
84
84
|
persist() {
|
|
85
|
-
|
|
85
|
+
this.entries = redactErasedContent(this.entries);
|
|
86
|
+
writePrivacyFilteredLedger(this.path, { version: 1, entries: this.entries });
|
|
86
87
|
}
|
|
87
88
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { extname
|
|
4
|
-
import { readDaemonConfig, resolveEndpoint } from '../monitor.js';
|
|
3
|
+
import { extname } from 'node:path';
|
|
5
4
|
import { readClientProfile } from '../client-profile.js';
|
|
6
5
|
import { OursError, attachOursClient, } from '@ours.network/sdk/client';
|
|
7
6
|
/** Any failure of a daemon operation. Never carries a message body or a token. */
|
|
@@ -131,24 +130,10 @@ export class OursSdkClient {
|
|
|
131
130
|
return;
|
|
132
131
|
const environment = { ...process.env, ...this.env };
|
|
133
132
|
const profile = readClientProfile(environment);
|
|
134
|
-
|
|
135
|
-
// daemon capability before reading the client's protected token delivery file.
|
|
136
|
-
const endpoint = !profile && environment.OURS_DAEMON_ID
|
|
137
|
-
? resolveEndpoint(environment, false) : undefined;
|
|
138
|
-
const token = endpoint ? environment.OURS_API_TOKEN?.trim() || readDaemonConfig(environment).apiToken : undefined;
|
|
139
|
-
const options = profile ? {
|
|
133
|
+
const options = {
|
|
140
134
|
endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
|
|
141
135
|
credentialPath: profile.credentialPath,
|
|
142
136
|
sessionMode: 'external', leaseToken: this.leaseToken, env: {},
|
|
143
|
-
} : endpoint ? {
|
|
144
|
-
endpoint: endpoint.origin, expectedInstanceId: environment.OURS_DAEMON_ID,
|
|
145
|
-
sessionMode: 'external', leaseToken: this.leaseToken,
|
|
146
|
-
...(token ? { token } : { credentialPath: join(endpoint.stateDir, 'daemon-token') }),
|
|
147
|
-
} : {
|
|
148
|
-
env: environment,
|
|
149
|
-
leaseToken: this.leaseToken,
|
|
150
|
-
clientPid: process.pid,
|
|
151
|
-
fetch: notificationDeadlineFetch(this.deps.fetch ?? globalThis.fetch, this.deps.notificationRequestDeadlineMs ?? NOTIFICATION_REQUEST_DEADLINE_MS),
|
|
152
137
|
};
|
|
153
138
|
this.client = await (this.deps.attachClient?.(options) ?? attachOursClient(options));
|
|
154
139
|
this.terminalReleasePending = true;
|
package/dist/preset-migration.js
CHANGED
|
@@ -69,8 +69,11 @@ const V5_GENERATED_ROLE_DEFAULT_FINGERPRINTS = Object.freeze({
|
|
|
69
69
|
});
|
|
70
70
|
const CURRENT_ROLE_DEFAULTS = new Set([
|
|
71
71
|
'roles/Coordinator.yaml', 'roles/LocalCoordinator.yaml', 'roles/Developer.yaml', 'roles/Critic.yaml',
|
|
72
|
+
'roles/Engineer.yaml',
|
|
72
73
|
'agent_templates/LocalCoordinator.yaml', 'agent_templates/Developer.yaml', 'agent_templates/Critic.yaml',
|
|
74
|
+
'agent_templates/Engineer.yaml',
|
|
73
75
|
'room_templates/single.yaml', 'room_templates/pair.yaml', 'room_templates/team.yaml',
|
|
76
|
+
'room_templates/engineering.yaml',
|
|
74
77
|
'agents/FleetCoordinator.yaml',
|
|
75
78
|
]);
|
|
76
79
|
export const legacyStarterMigrationManifest = Object.freeze({
|
|
@@ -258,6 +261,18 @@ export function migratePackagedRoleDefaults(configuration, options = {}, hooks =
|
|
|
258
261
|
unlinkSync(target);
|
|
259
262
|
copyFileSync(join(source, relative), target, constants.COPYFILE_EXCL);
|
|
260
263
|
chmodSync(target, 0o600);
|
|
264
|
+
// New Engineer seats use the existing Developer's selected brain. This
|
|
265
|
+
// preserves wizard/custom provider choices without copying permissions.
|
|
266
|
+
if (relative === 'agent_templates/Engineer.yaml' && classified.additions.includes(path)) {
|
|
267
|
+
const developer = join(root, 'agent_templates/Developer.yaml');
|
|
268
|
+
if (existsSync(developer)) {
|
|
269
|
+
const value = parseFleetDocument(developer, readFileSync(developer, 'utf8'), 'strict').value;
|
|
270
|
+
if (value.brain !== undefined && JSON.stringify(value.brain) !== JSON.stringify({ ref: 'claude-default' })) {
|
|
271
|
+
const bytes = readFileSync(target, 'utf8').replace('brain: { ref: claude-default }', () => `brain: ${JSON.stringify(value.brain)}`);
|
|
272
|
+
writeFileSync(target, bytes, { mode: 0o600 });
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
261
276
|
fsyncPath(target);
|
|
262
277
|
}
|
|
263
278
|
for (const kind of ['roles', 'agent_templates', 'room_templates', 'agents'])
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { FleetConfig } from '../config.js';
|
|
2
|
+
import { TaskStateError } from './task-state.js';
|
|
3
|
+
import { provisionMembers } from './provision.js';
|
|
4
|
+
import type { CoworkAdapter } from './cowork-adapter.js';
|
|
5
|
+
export declare class MemberAdditionRejected extends TaskStateError {
|
|
6
|
+
readonly accepted = false;
|
|
7
|
+
}
|
|
8
|
+
export interface AddMemberRequest {
|
|
9
|
+
requestId: string;
|
|
10
|
+
slot: string;
|
|
11
|
+
role: string;
|
|
12
|
+
brain: string;
|
|
13
|
+
agentTemplate: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function memberAddition(taskId: string, requestId: string): {
|
|
16
|
+
requestId: string;
|
|
17
|
+
taskId: string;
|
|
18
|
+
roleId: string;
|
|
19
|
+
state: "running" | "succeeded" | "attention" | "failed";
|
|
20
|
+
error?: string;
|
|
21
|
+
} | {
|
|
22
|
+
state: string;
|
|
23
|
+
error: string;
|
|
24
|
+
requestId: string;
|
|
25
|
+
taskId: string;
|
|
26
|
+
roleId: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function requestMemberAddition(input: {
|
|
29
|
+
taskId: string;
|
|
30
|
+
request: AddMemberRequest;
|
|
31
|
+
cfg: FleetConfig;
|
|
32
|
+
cowork: CoworkAdapter;
|
|
33
|
+
configPath?: string;
|
|
34
|
+
binPath: string;
|
|
35
|
+
provision?: typeof provisionMembers;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
requestId: string;
|
|
38
|
+
taskId: string;
|
|
39
|
+
roleId: string;
|
|
40
|
+
state: "running" | "succeeded" | "attention" | "failed";
|
|
41
|
+
error?: string;
|
|
42
|
+
} | {
|
|
43
|
+
state: string;
|
|
44
|
+
error: string;
|
|
45
|
+
requestId: string;
|
|
46
|
+
taskId: string;
|
|
47
|
+
roleId: string;
|
|
48
|
+
}>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { replaceFileAtomically, withFileLock } from '../atomic-file.js';
|
|
5
|
+
import { canonicalJson } from '../canonical-json.js';
|
|
6
|
+
import { stateRoot } from '../paths.js';
|
|
7
|
+
import { getTask, TaskStateError } from './task-state.js';
|
|
8
|
+
import { getRoomRecord } from './room-state.js';
|
|
9
|
+
import { prepareExecutionPlan } from './member-overrides.js';
|
|
10
|
+
import { sealTemplateSnapshot } from './templates.js';
|
|
11
|
+
import { provisionMembers } from './provision.js';
|
|
12
|
+
export class MemberAdditionRejected extends TaskStateError {
|
|
13
|
+
accepted = false;
|
|
14
|
+
}
|
|
15
|
+
const running = new Set();
|
|
16
|
+
function pathFor(taskId, requestId) {
|
|
17
|
+
if (!/^[a-z0-9]{10,40}$/.test(taskId) || !/^[a-zA-Z0-9_-]{8,80}$/.test(requestId))
|
|
18
|
+
throw new TaskStateError('Invalid task or request ID');
|
|
19
|
+
return join(stateRoot(), 'member-additions', taskId, requestId + '.json');
|
|
20
|
+
}
|
|
21
|
+
export function memberAddition(taskId, requestId) {
|
|
22
|
+
getTask(taskId);
|
|
23
|
+
const path = pathFor(taskId, requestId);
|
|
24
|
+
if (!existsSync(path))
|
|
25
|
+
throw new TaskStateError('Member request not found');
|
|
26
|
+
const receipt = JSON.parse(readFileSync(path, 'utf8'));
|
|
27
|
+
const { hash, ...view } = receipt;
|
|
28
|
+
return receipt.state === 'running' && !running.has(path) ? { ...view, state: 'attention', error: 'The server stopped observing this launch. Inspect the existing agent before any recovery.' } : view;
|
|
29
|
+
}
|
|
30
|
+
export async function requestMemberAddition(input) {
|
|
31
|
+
const { request: r, taskId } = input;
|
|
32
|
+
if (!r || typeof r.slot !== 'string' || !/^[A-Za-z][A-Za-z0-9_-]{0,31}$/.test(r.slot)
|
|
33
|
+
|| ![r.role, r.brain, r.agentTemplate].every(v => typeof v === 'string' && v.length > 0 && v.length <= 128))
|
|
34
|
+
// No receipt lookup has happened yet: this request ID may already be accepted.
|
|
35
|
+
throw new TaskStateError('Slot, Role, Brain and Agent Template are required');
|
|
36
|
+
const path = pathFor(taskId, r.requestId);
|
|
37
|
+
const hash = createHash('sha256').update(canonicalJson(r)).digest('hex');
|
|
38
|
+
mkdirSync(join(stateRoot(), 'member-additions', taskId), { recursive: true, mode: 0o700 });
|
|
39
|
+
return withFileLock(path + '.lock', async () => {
|
|
40
|
+
if (existsSync(path)) {
|
|
41
|
+
const old = JSON.parse(readFileSync(path, 'utf8'));
|
|
42
|
+
if (old.hash !== hash)
|
|
43
|
+
throw new TaskStateError('Request ID was already used with different settings');
|
|
44
|
+
return memberAddition(taskId, r.requestId);
|
|
45
|
+
}
|
|
46
|
+
const task = getTask(taskId);
|
|
47
|
+
const room = task.room_id && getRoomRecord(task.room_id);
|
|
48
|
+
if (!room || !['active', 'review'].includes(task.state) || task.terminal_intent || task.blocked || room.state !== 'active'
|
|
49
|
+
|| room.task_id !== taskId || room.room_identity_cid !== task.room_identity_cid)
|
|
50
|
+
throw new MemberAdditionRejected('Adding an agent requires an active, unblocked task room');
|
|
51
|
+
const roleId = `${taskId.slice(0, 8)}-${r.slot}-1`;
|
|
52
|
+
if (room.member_seats.some(s => s.role_name === roleId))
|
|
53
|
+
throw new MemberAdditionRejected('This member slot already exists');
|
|
54
|
+
const plan = (() => {
|
|
55
|
+
try {
|
|
56
|
+
return prepareExecutionPlan({ name: 'additional-member', version: 1, description: 'Additional task participant',
|
|
57
|
+
contract: room.template_snapshot?.contract, members: [{ slot: r.slot, role: r.role, count: 1, agent_template: r.agentTemplate }] }, input.cfg, { [r.slot]: { role: r.role, brain: r.brain } });
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new MemberAdditionRejected(error instanceof Error ? error.message : 'Invalid member configuration');
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
const template = sealTemplateSnapshot(plan.snapshot, input.cfg.agentTemplates ?? {}, plan.launchDefinitions);
|
|
64
|
+
const receipt = { taskId, requestId: r.requestId, roleId, hash, state: 'running' };
|
|
65
|
+
const save = () => replaceFileAtomically(path, JSON.stringify(receipt) + '\n', 0o600);
|
|
66
|
+
save();
|
|
67
|
+
running.add(path);
|
|
68
|
+
void (input.provision ?? provisionMembers)({ cfg: input.cfg, cowork: input.cowork, configPath: input.configPath, binPath: input.binPath,
|
|
69
|
+
taskId, roomId: room.room_id, template, goal: task.title, brief: task.brief, append: true }).then(result => {
|
|
70
|
+
const seat = result.member_seats.find(s => s.role_name === roleId);
|
|
71
|
+
receipt.state = seat?.seat_state === 'active' && getTask(taskId).member_roles.some(m => m.name === roleId) ? 'succeeded' : 'attention';
|
|
72
|
+
if (receipt.state === 'attention')
|
|
73
|
+
receipt.error = 'Admission is not confirmed. Inspect the existing launch; no automatic retry was made.';
|
|
74
|
+
}).catch(() => { receipt.state = 'failed'; receipt.error = 'Member launch failed. Inspect the task and agent logs before recovery.'; })
|
|
75
|
+
.finally(() => { try {
|
|
76
|
+
save();
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
running.delete(path);
|
|
80
|
+
} }).catch(() => { running.delete(path); });
|
|
81
|
+
return memberAddition(taskId, r.requestId);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ArchivedMemberAbsence, RoomMemberSeat } from './types.js';
|
|
2
|
+
/** Revalidate live facts; a persisted timestamp is never cleanup authority. */
|
|
3
|
+
export declare function verifyArchivedAbsence(proof: ArchivedMemberAbsence): Promise<void>;
|
|
4
|
+
/** After the verified archive has been consumed by explicit workspace deletion,
|
|
5
|
+
* still fence replacement live state and a recreated daemon identity on every retry.
|
|
6
|
+
*/
|
|
7
|
+
export declare function verifyArchivedMemberStillAbsent(proof: ArchivedMemberAbsence): Promise<void>;
|
|
8
|
+
export declare function proveArchivedAbsence(seat: RoomMemberSeat): Promise<ArchivedMemberAbsence>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { agentDir } from '../paths.js';
|
|
4
|
+
import { tempArchiveForLaunch, tempArchiveForCreationAction, tempSupervisorLiveness } from '../temp-lifecycle.js';
|
|
5
|
+
import { assertMemberIdentityAbsent } from './close.js';
|
|
6
|
+
/** Revalidate live facts; a persisted timestamp is never cleanup authority. */
|
|
7
|
+
export async function verifyArchivedAbsence(proof) {
|
|
8
|
+
const absent = () => {
|
|
9
|
+
if (existsSync(agentDir(proof.name, true)))
|
|
10
|
+
throw new Error('Archived member has replacement live state');
|
|
11
|
+
};
|
|
12
|
+
absent();
|
|
13
|
+
const archive = tempArchiveForLaunch(proof.name, proof.launch_id);
|
|
14
|
+
const action = tempArchiveForCreationAction(proof.name, proof.action_id);
|
|
15
|
+
if (!archive || archive !== proof.archive_path || action?.path !== archive
|
|
16
|
+
|| action.launchId !== proof.launch_id
|
|
17
|
+
|| readFileSync(join(archive, '.identity'), 'utf8').trim() !== proof.name)
|
|
18
|
+
throw new Error('Archived member absence ownership proof mismatch');
|
|
19
|
+
if (await tempSupervisorLiveness(archive) !== 'stopped')
|
|
20
|
+
throw new Error('Archived member supervisor absence is not proven');
|
|
21
|
+
await verifyArchivedMemberStillAbsent(proof);
|
|
22
|
+
}
|
|
23
|
+
/** After the verified archive has been consumed by explicit workspace deletion,
|
|
24
|
+
* still fence replacement live state and a recreated daemon identity on every retry.
|
|
25
|
+
*/
|
|
26
|
+
export async function verifyArchivedMemberStillAbsent(proof) {
|
|
27
|
+
const absent = () => {
|
|
28
|
+
if (existsSync(agentDir(proof.name, true)))
|
|
29
|
+
throw new Error('Archived member has replacement live state');
|
|
30
|
+
};
|
|
31
|
+
absent();
|
|
32
|
+
await assertMemberIdentityAbsent({
|
|
33
|
+
role_name: proof.name, slot: 'archived', cowork_role: 'archived', seat_state: 'removed',
|
|
34
|
+
});
|
|
35
|
+
absent();
|
|
36
|
+
}
|
|
37
|
+
export async function proveArchivedAbsence(seat) {
|
|
38
|
+
if (seat.identity_cid || seat.retirement?.phase !== 'identity_absent'
|
|
39
|
+
|| !seat.launch?.launch_id || !seat.launch.action_id
|
|
40
|
+
|| seat.launch.launch_id !== seat.retirement.launch_id || !seat.retirement.archive_path)
|
|
41
|
+
throw new Error('Missing exact archived member absence evidence');
|
|
42
|
+
const proof = {
|
|
43
|
+
name: seat.role_name, launch_id: seat.launch.launch_id, action_id: seat.launch.action_id,
|
|
44
|
+
archive_path: seat.retirement.archive_path, checked_at: new Date().toISOString(),
|
|
45
|
+
};
|
|
46
|
+
await verifyArchivedAbsence(proof);
|
|
47
|
+
return proof;
|
|
48
|
+
}
|
package/dist/rooms-tasks/cli.js
CHANGED
|
@@ -75,6 +75,11 @@ async function presentDetachedProvisioningOutcome(outcome) {
|
|
|
75
75
|
function taskRoomPublicFailure(error) {
|
|
76
76
|
const f = error.fields;
|
|
77
77
|
switch (error.code) {
|
|
78
|
+
case 'task_not_ready': return {
|
|
79
|
+
legacy: `task readiness ${f.readiness}: ${f.reason}`, kind: 'state',
|
|
80
|
+
detail: `Task ${f.task} readiness is ${f.readiness}: ${f.reason}${f.member ? ` (${f.member})` : ''}.`,
|
|
81
|
+
action: 'Ask Fleet Coordinator to inspect room and member status and choose supported recovery. Do not blindly relaunch agents or reuse invites.',
|
|
82
|
+
};
|
|
78
83
|
case 'task_confirmation_mismatch': return {
|
|
79
84
|
legacy: 'confirmation ID must match task ID', kind: 'usage',
|
|
80
85
|
detail: 'The two task IDs must match.', action: 'Repeat the same task ID twice.',
|
|
@@ -515,10 +520,10 @@ function taskRoomService(configuration) {
|
|
|
515
520
|
function allTemplates(cfg) {
|
|
516
521
|
return cfg.roomTemplates ?? {};
|
|
517
522
|
}
|
|
518
|
-
function coworkFor(cfg) {
|
|
523
|
+
function coworkFor(cfg, options) {
|
|
519
524
|
if (!cfg.rooms)
|
|
520
525
|
throw new ConfigError('rooms: configuration is required before creating or querying rooms');
|
|
521
|
-
return createCoworkAdapter({ configPath: cfg.rooms.cowork?.config });
|
|
526
|
+
return createCoworkAdapter({ configPath: cfg.rooms.cowork?.config, ...options });
|
|
522
527
|
}
|
|
523
528
|
function resolveRoomTemplate(cfg, name) {
|
|
524
529
|
if (!name)
|
|
@@ -827,16 +832,18 @@ export function registerTaskCommands(parent, cOpt) {
|
|
|
827
832
|
dieTaskRoom(e);
|
|
828
833
|
}
|
|
829
834
|
});
|
|
830
|
-
taskCmd.command('show <id>')
|
|
835
|
+
cOpt(taskCmd.command('show <id>'))
|
|
831
836
|
.description('show task details')
|
|
832
837
|
.option('--json', 'JSON output')
|
|
833
838
|
.action(async (id, opts) => {
|
|
834
839
|
try {
|
|
835
|
-
const service = taskRoomService();
|
|
840
|
+
const service = taskRoomService(opts.configuration);
|
|
836
841
|
const { task: t, orchestration: room } = service.getTask(id);
|
|
842
|
+
const readiness = t.state === 'active' ? await service.observeTaskReadiness(id) : undefined;
|
|
837
843
|
if (opts.json) {
|
|
838
844
|
console.log(JSON.stringify({
|
|
839
845
|
schema_version: 1, task: t, orchestration: room ?? null,
|
|
846
|
+
...(readiness ? { readiness } : {}),
|
|
840
847
|
}, null, 2));
|
|
841
848
|
return;
|
|
842
849
|
}
|
|
@@ -846,6 +853,8 @@ export function registerTaskCommands(parent, cOpt) {
|
|
|
846
853
|
{ label: 'ID', value: t.task_id, kind: 'code' },
|
|
847
854
|
{ label: 'Title', value: t.title },
|
|
848
855
|
{ label: 'Status', value: taskStatus(t.state), kind: 'markdown' },
|
|
856
|
+
...(readiness ? [{ label: 'Readiness', value: readiness.state },
|
|
857
|
+
...('reason' in readiness ? [{ label: 'Reason', value: readiness.reason }] : [])] : []),
|
|
849
858
|
...(t.blocked ? [{ label: 'Blocked', value: t.blocked.reason }] : []),
|
|
850
859
|
...(t.template ? [{ label: 'Template', value: `${t.template.name}@${t.template.version}`, kind: 'code' }] : []),
|
|
851
860
|
...(t.room_id ? [{ label: 'Room', value: t.room_id, kind: 'code' }] : []),
|
|
@@ -1152,7 +1161,7 @@ export function registerTaskCommands(parent, cOpt) {
|
|
|
1152
1161
|
const app = taskRoomService(opts.configuration);
|
|
1153
1162
|
for (;;) {
|
|
1154
1163
|
const before = app.taskProvisioningOutcome(id);
|
|
1155
|
-
if (before.kind !== 'in_progress') {
|
|
1164
|
+
if (before.kind !== 'in_progress' || before.next_action) {
|
|
1156
1165
|
await presentDetachedProvisioningOutcome(before);
|
|
1157
1166
|
return;
|
|
1158
1167
|
}
|
|
@@ -1176,6 +1185,26 @@ export function registerTaskCommands(parent, cOpt) {
|
|
|
1176
1185
|
dieTaskRoom(e);
|
|
1177
1186
|
}
|
|
1178
1187
|
});
|
|
1188
|
+
cOpt(taskCmd.command('_layout <id> <operation> [room]', { hidden: true }))
|
|
1189
|
+
.description('internal: run an accepted layout room operation (open, close-room, close)')
|
|
1190
|
+
.option('--json', 'JSON output')
|
|
1191
|
+
.option('--operation-id <id>', 'accepted operation ID; status updates apply only while it is current')
|
|
1192
|
+
.action(async (id, operation, room, opts) => {
|
|
1193
|
+
try {
|
|
1194
|
+
if (!['open', 'close-room', 'close'].includes(operation))
|
|
1195
|
+
throw new Error(`unknown layout operation: ${operation}`);
|
|
1196
|
+
const view = await taskRoomService(opts.configuration).runTaskLayoutOperation({
|
|
1197
|
+
actor: { kind: 'internal_worker', surface: 'cli' }, taskId: id,
|
|
1198
|
+
operation: operation, room, operationId: opts.operationId,
|
|
1199
|
+
});
|
|
1200
|
+
console.log(JSON.stringify({ schema_version: 1, layout: view }, null, 2));
|
|
1201
|
+
}
|
|
1202
|
+
catch (e) {
|
|
1203
|
+
if (opts.json)
|
|
1204
|
+
die(e);
|
|
1205
|
+
dieTaskRoom(e);
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1179
1208
|
cOpt(taskCmd.command('_settle_delete <id>', { hidden: true }))
|
|
1180
1209
|
.description('internal: settle a previously accepted task deletion')
|
|
1181
1210
|
.option('--json', 'JSON output')
|