@ours.network/fleet 1.2.0-nightly.7 → 1.2.0-nightly.71
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 +279 -68
- package/dist/account-origin.d.ts +2 -0
- package/dist/account-origin.js +6 -0
- package/dist/agent-ours/bridge.js +26 -9
- 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 +12 -0
- package/dist/agent-ours/file-rpc.js +18 -4
- package/dist/agent-ours/harness.js +9 -1
- package/dist/agent-ours/mcp-endpoint.d.ts +19 -0
- package/dist/agent-ours/mcp-endpoint.js +98 -25
- package/dist/agent-ours/runtime.d.ts +9 -1
- package/dist/agent-ours/runtime.js +50 -2
- package/dist/agent-ours/service.d.ts +24 -1
- package/dist/agent-ours/service.js +97 -13
- package/dist/application/codex-models.d.ts +15 -0
- package/dist/application/codex-models.js +56 -0
- package/dist/application/conversation-history.d.ts +34 -0
- package/dist/application/conversation-history.js +280 -0
- package/dist/application/conversation-role-observer.d.ts +62 -0
- package/dist/application/conversation-role-observer.js +206 -0
- package/dist/application/fleet-query-service.d.ts +1 -1
- package/dist/application/fleet-query-service.js +3 -3
- package/dist/application/log-service.js +8 -8
- 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/resource-observer.d.ts +40 -0
- package/dist/application/resource-observer.js +278 -0
- package/dist/application/role-creation-service.js +3 -2
- package/dist/application/role-removal-service.js +17 -3
- package/dist/application/role-repository.d.ts +1 -1
- package/dist/application/role-repository.js +30 -7
- 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 +61 -17
- package/dist/application/session-control.js +207 -23
- package/dist/application/supervisor-ours-tools.js +5 -11
- package/dist/application/task-layouts.d.ts +91 -0
- package/dist/application/task-layouts.js +261 -0
- package/dist/application/task-room-service.d.ts +101 -3
- package/dist/application/task-room-service.js +286 -33
- package/dist/application/types.d.ts +2 -0
- package/dist/atomic-file.d.ts +34 -1
- package/dist/atomic-file.js +161 -18
- package/dist/briefing.d.ts +3 -1
- package/dist/briefing.js +97 -31
- package/dist/build-info.json +9 -4
- package/dist/capabilities.d.ts +9 -1
- package/dist/capabilities.js +13 -0
- package/dist/cli.js +400 -37
- package/dist/client-profile.d.ts +5 -17
- package/dist/client-profile.js +4 -127
- package/dist/config.d.ts +45 -0
- package/dist/config.js +57 -6
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +4 -4
- package/dist/daemon-recovery.d.ts +14 -9
- package/dist/daemon-recovery.js +124 -115
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +207 -19
- package/dist/doctor.d.ts +4 -1
- package/dist/doctor.js +75 -60
- package/dist/erased-resources.d.ts +9 -0
- package/dist/erased-resources.js +87 -0
- package/dist/file-delivery/reader.d.ts +15 -0
- package/dist/file-delivery/reader.js +63 -0
- package/dist/file-delivery/store.d.ts +15 -0
- package/dist/file-delivery/store.js +124 -0
- package/dist/file-delivery/types.d.ts +19 -0
- package/dist/file-delivery/types.js +1 -0
- package/dist/fleet-command-audit.d.ts +7 -0
- package/dist/fleet-command-audit.js +24 -8
- package/dist/harness/agent-session.d.ts +4 -0
- package/dist/harness/claude-code-session.js +1 -1
- package/dist/harness/claude-code.js +21 -11
- package/dist/harness/claude-runtime.d.ts +12 -0
- package/dist/harness/claude-runtime.js +43 -0
- 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-reasoning.d.ts +5 -0
- package/dist/harness/codex-reasoning.js +12 -0
- package/dist/harness/codex-runtime.d.ts +11 -1
- package/dist/harness/codex-runtime.js +31 -4
- package/dist/harness/codex-session.js +2 -2
- package/dist/harness/codex.js +24 -12
- package/dist/init-wizard.d.ts +2 -0
- package/dist/init-wizard.js +38 -19
- package/dist/isolation/policy.js +6 -1
- package/dist/isolation/types.d.ts +5 -0
- package/dist/managed-cli.d.ts +253 -0
- package/dist/managed-cli.js +923 -0
- package/dist/managed-recovery.d.ts +13 -0
- package/dist/managed-recovery.js +31 -0
- package/dist/minimal-setup.d.ts +2 -0
- package/dist/minimal-setup.js +44 -0
- package/dist/monitor.d.ts +9 -34
- package/dist/monitor.js +90 -153
- package/dist/notifications/fleet-producer.d.ts +22 -0
- package/dist/notifications/fleet-producer.js +237 -0
- package/dist/notifications/outbox.d.ts +46 -0
- package/dist/notifications/outbox.js +158 -0
- package/dist/notifications/target-cleanup.d.ts +11 -0
- package/dist/notifications/target-cleanup.js +63 -0
- package/dist/notifications/task-producer.d.ts +20 -0
- package/dist/notifications/task-producer.js +100 -0
- package/dist/ops.d.ts +2 -0
- package/dist/ops.js +20 -3
- package/dist/owner-channel/channel.js +17 -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/paths.d.ts +2 -0
- package/dist/paths.js +2 -0
- package/dist/preset-migration.js +43 -0
- package/dist/process-incarnation.d.ts +23 -0
- package/dist/process-incarnation.js +42 -0
- package/dist/reminders/manager.d.ts +75 -0
- package/dist/reminders/manager.js +278 -0
- package/dist/reminders/runtime.d.ts +27 -0
- package/dist/reminders/runtime.js +32 -0
- package/dist/reminders/schedule.d.ts +37 -0
- package/dist/reminders/schedule.js +104 -0
- package/dist/reminders/store.d.ts +341 -0
- package/dist/reminders/store.js +762 -0
- package/dist/reminders/tools.d.ts +20 -0
- package/dist/reminders/tools.js +114 -0
- package/dist/resolved-plan.js +1 -0
- package/dist/rooms-tasks/add-member.d.ts +48 -0
- package/dist/rooms-tasks/add-member.js +84 -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 +65 -5
- package/dist/rooms-tasks/close.d.ts +6 -2
- package/dist/rooms-tasks/close.js +246 -37
- package/dist/rooms-tasks/config.d.ts +1 -1
- package/dist/rooms-tasks/config.js +11 -4
- package/dist/rooms-tasks/cowork-adapter.d.ts +12 -5
- package/dist/rooms-tasks/cowork-adapter.js +15 -121
- package/dist/rooms-tasks/cowork-http.js +56 -6
- package/dist/rooms-tasks/deletion.d.ts +1 -1
- package/dist/rooms-tasks/deletion.js +84 -5
- package/dist/rooms-tasks/erasure.d.ts +6 -0
- package/dist/rooms-tasks/erasure.js +173 -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-member-retirement.d.ts +10 -0
- package/dist/rooms-tasks/layout-member-retirement.js +90 -0
- package/dist/rooms-tasks/layout-service.d.ts +43 -0
- package/dist/rooms-tasks/layout-service.js +203 -0
- package/dist/rooms-tasks/layout.d.ts +121 -0
- package/dist/rooms-tasks/layout.js +286 -0
- package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
- package/dist/rooms-tasks/legacy-task-member.js +116 -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-ownership.d.ts +5 -0
- package/dist/rooms-tasks/member-ownership.js +40 -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 +3 -0
- package/dist/rooms-tasks/provision.js +101 -49
- package/dist/rooms-tasks/recovery.d.ts +19 -0
- package/dist/rooms-tasks/recovery.js +110 -0
- package/dist/rooms-tasks/room-state.d.ts +4 -2
- package/dist/rooms-tasks/room-state.js +47 -8
- package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
- package/dist/rooms-tasks/task-service-retirement.js +21 -0
- package/dist/rooms-tasks/task-state.d.ts +52 -8
- package/dist/rooms-tasks/task-state.js +251 -26
- package/dist/rooms-tasks/types.d.ts +40 -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 +35 -0
- package/dist/rooms-tasks/workspace.js +325 -0
- package/dist/runner.d.ts +33 -4
- package/dist/runner.js +410 -62
- package/dist/session/acp.d.ts +75 -2
- package/dist/session/acp.js +345 -82
- package/dist/session/arbiter.d.ts +98 -0
- package/dist/session/arbiter.js +272 -3
- package/dist/session/codex-app-server.d.ts +45 -1
- package/dist/session/codex-app-server.js +225 -32
- package/dist/session/control.d.ts +17 -3
- package/dist/session/control.js +213 -23
- package/dist/session/conversation-normalizer.d.ts +2 -1
- package/dist/session/conversation-normalizer.js +1 -1
- package/dist/session/conversation-observation.d.ts +25 -0
- package/dist/session/conversation-observation.js +100 -0
- package/dist/session/conversation-replay.d.ts +50 -0
- package/dist/session/conversation-replay.js +203 -0
- package/dist/session/conversation-store.d.ts +15 -1
- package/dist/session/conversation-store.js +206 -26
- package/dist/session/conversation-types.d.ts +57 -4
- package/dist/session/prompt-batch.d.ts +79 -0
- package/dist/session/prompt-batch.js +120 -0
- package/dist/session/task-notice.d.ts +14 -0
- package/dist/session/task-notice.js +13 -0
- package/dist/session/types.d.ts +42 -1
- package/dist/setup-tunnel-preflight.d.ts +34 -0
- package/dist/setup-tunnel-preflight.js +62 -0
- package/dist/socket-path.d.ts +2 -0
- package/dist/socket-path.js +22 -0
- package/dist/spawn.d.ts +5 -1
- package/dist/spawn.js +40 -4
- package/dist/startup-prompt.d.ts +15 -0
- package/dist/startup-prompt.js +71 -0
- package/dist/startup-readiness.d.ts +32 -0
- package/dist/startup-readiness.js +101 -0
- package/dist/startup-telemetry.d.ts +16 -0
- package/dist/startup-telemetry.js +46 -0
- package/dist/subscriptions/cli.d.ts +91 -0
- package/dist/subscriptions/cli.js +223 -0
- package/dist/subscriptions/launch.d.ts +37 -0
- package/dist/subscriptions/launch.js +93 -0
- package/dist/subscriptions/login.d.ts +77 -0
- package/dist/subscriptions/login.js +215 -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 +143 -0
- package/dist/supervisor/adoption.d.ts +8 -0
- package/dist/supervisor/adoption.js +78 -0
- package/dist/supervisor/catalog.d.ts +62 -0
- package/dist/supervisor/catalog.js +254 -0
- package/dist/supervisor/fleet.d.ts +8 -0
- package/dist/supervisor/fleet.js +89 -0
- package/dist/supervisor/index.js +3 -6
- package/dist/supervisor/launchd.d.ts +1 -1
- package/dist/supervisor/launchd.js +26 -13
- package/dist/supervisor/legacy.d.ts +35 -0
- package/dist/supervisor/legacy.js +524 -0
- package/dist/supervisor/manager.d.ts +15 -0
- package/dist/supervisor/manager.js +270 -0
- package/dist/supervisor/registration-refresh.d.ts +45 -0
- package/dist/supervisor/registration-refresh.js +266 -0
- package/dist/supervisor/scope.d.ts +4 -0
- package/dist/supervisor/scope.js +10 -0
- package/dist/supervisor/systemd.d.ts +2 -2
- package/dist/supervisor/systemd.js +19 -33
- package/dist/task-supervision.d.ts +9 -0
- package/dist/task-supervision.js +145 -0
- package/dist/temp-idle.d.ts +17 -0
- package/dist/temp-idle.js +42 -0
- package/dist/temp-lifecycle.d.ts +23 -8
- package/dist/temp-lifecycle.js +123 -66
- package/dist/temp-supervisor-recovery.d.ts +1 -1
- package/dist/temp-supervisor-recovery.js +2 -2
- package/dist/tunnel-setup-completion.d.ts +7 -0
- package/dist/tunnel-setup-completion.js +13 -0
- package/dist/tunnel-setup-input.d.ts +19 -0
- package/dist/tunnel-setup-input.js +124 -0
- package/dist/watchdog/query.d.ts +3 -1
- package/dist/watchdog/query.js +2 -1
- package/dist/web/agent-attachments.d.ts +29 -0
- package/dist/web/agent-attachments.js +162 -0
- package/dist/web/auth.d.ts +65 -2
- package/dist/web/auth.js +201 -11
- package/dist/web/available-port.d.ts +2 -0
- package/dist/web/available-port.js +23 -0
- package/dist/web/control.d.ts +3 -3
- package/dist/web/control.js +10 -8
- package/dist/web/conversation-stream-codec.d.ts +23 -0
- package/dist/web/conversation-stream-codec.js +110 -0
- package/dist/web/conversation-stream.d.ts +25 -0
- package/dist/web/conversation-stream.js +231 -0
- package/dist/web/events.d.ts +2 -0
- package/dist/web/events.js +9 -0
- 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 +32 -0
- package/dist/web/prefix-gateway.js +248 -0
- package/dist/web/resource-views.d.ts +124 -0
- package/dist/web/resource-views.js +424 -0
- package/dist/web/runtime.d.ts +3 -1
- package/dist/web/runtime.js +132 -34
- package/dist/web/server.d.ts +19 -0
- package/dist/web/server.js +802 -67
- package/dist/web/service.d.ts +11 -2
- package/dist/web/service.js +30 -4
- package/dist/web/workspace-devices.d.ts +107 -0
- package/dist/web/workspace-devices.js +277 -0
- package/dist/web/workspace-tunnel.d.ts +1 -0
- package/dist/web/workspace-tunnel.js +34 -0
- package/dist/workspace-enrollment.d.ts +83 -0
- package/dist/workspace-enrollment.js +580 -0
- package/dist/workspace-replacement.d.ts +66 -0
- package/dist/workspace-replacement.js +220 -0
- package/docs/acp-files.md +146 -0
- package/docs/conversation-stream.md +196 -0
- package/docs/fleet-migration.md +54 -0
- package/docs/live-voice.md +13 -0
- package/docs/room-layouts.md +227 -0
- package/docs/self-reminders.md +374 -0
- package/docs/task-workspaces.md +225 -0
- package/docs/validation/managed-cli-permissions.md +421 -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 +24 -20
- package/presets/README.md +78 -0
- package/presets/brain-catalog.json +8 -2
- package/presets/fleet/agent_templates/Critic.yaml +1 -1
- package/presets/fleet/agent_templates/Developer.yaml +1 -1
- package/presets/fleet/agent_templates/Engineer.yaml +5 -0
- package/presets/fleet/agent_templates/LocalCoordinator.yaml +4 -2
- package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
- 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 +12 -11
- package/presets/fleet/roles/Critic.yaml +13 -0
- package/presets/fleet/roles/Developer.yaml +13 -0
- package/presets/fleet/roles/Engineer.yaml +53 -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/index.html +0 -17
- package/dist/web-app/manifest.webmanifest +0 -15
- package/dist/web-app/offline.html +0 -18
- package/dist/web-app/sw.js +0 -51
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { relative, resolve, sep } from 'node:path';
|
|
2
|
+
import { agentsRoot, tmpRoot, stateRoot } from '../paths.js';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { observeFleetResources } from '../application/resource-observer.js';
|
|
5
|
+
export async function abortableProjection(read, signal) {
|
|
6
|
+
signal.throwIfAborted();
|
|
7
|
+
let onAbort;
|
|
8
|
+
const aborted = new Promise((_, reject) => {
|
|
9
|
+
onAbort = () => reject(signal.reason ?? new Error('resource projection aborted'));
|
|
10
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
11
|
+
});
|
|
12
|
+
try {
|
|
13
|
+
return await Promise.race([read, aborted]);
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
signal.removeEventListener('abort', onAbort);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export const RESOURCE_FRAME_BYTES = 512 * 1024;
|
|
20
|
+
export const RESOURCE_PENDING_BYTES = 8 * 1024 * 1024;
|
|
21
|
+
export const RESOURCE_ASSEMBLY_BYTES = 16 * 1024 * 1024;
|
|
22
|
+
const CHUNK_BYTES = 256 * 1024;
|
|
23
|
+
/** Lazily yield byte chunks so backpressure never queues an entire large record.
|
|
24
|
+
* Base64 prevents splitting a Unicode scalar from corrupting JSON/SSE parsing. */
|
|
25
|
+
export function* resourceFrames(envelope) {
|
|
26
|
+
const bytes = Buffer.from(JSON.stringify(envelope));
|
|
27
|
+
if (bytes.length > RESOURCE_ASSEMBLY_BYTES)
|
|
28
|
+
throw new Error('resource assembly limit exceeded');
|
|
29
|
+
const ordinary = { event: 'resource', data: envelope };
|
|
30
|
+
if (Buffer.byteLength(`event: resource\ndata: ${bytes.toString('utf8')}\n\n`) <= RESOURCE_FRAME_BYTES) {
|
|
31
|
+
yield ordinary;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const id = `${envelope.viewId}:${envelope.subscriptionEpoch}:${envelope.sequence}`;
|
|
35
|
+
const binding = { protocolVersion: 1, id, producerGeneration: envelope.producerGeneration,
|
|
36
|
+
viewId: envelope.viewId, subscriptionEpoch: envelope.subscriptionEpoch, revision: envelope.revision,
|
|
37
|
+
sequence: envelope.sequence };
|
|
38
|
+
yield { event: 'resource-chunk', data: { ...binding, type: 'start', totalBytes: bytes.length, parts: Math.ceil(bytes.length / CHUNK_BYTES) } };
|
|
39
|
+
for (let offset = 0, index = 0; offset < bytes.length; offset += CHUNK_BYTES, index++) {
|
|
40
|
+
yield { event: 'resource-chunk', data: { ...binding, type: 'chunk', index, data: bytes.subarray(offset, offset + CHUNK_BYTES).toString('base64') } };
|
|
41
|
+
}
|
|
42
|
+
yield { event: 'resource-chunk', data: { ...binding, type: 'commit', totalBytes: bytes.length } };
|
|
43
|
+
}
|
|
44
|
+
/** One Fleet HTTP writer. The active record owns the assembly budget;
|
|
45
|
+
* waiting live records share the smaller pending-output budget. */
|
|
46
|
+
export class ResourceOutput {
|
|
47
|
+
response;
|
|
48
|
+
signal;
|
|
49
|
+
failed;
|
|
50
|
+
#pending = [];
|
|
51
|
+
#pendingBytes = 0;
|
|
52
|
+
#active;
|
|
53
|
+
#closed = false;
|
|
54
|
+
#releaseDrain;
|
|
55
|
+
#abort = () => this.close();
|
|
56
|
+
constructor(response, signal, failed) {
|
|
57
|
+
this.response = response;
|
|
58
|
+
this.signal = signal;
|
|
59
|
+
this.failed = failed;
|
|
60
|
+
if (signal.aborted)
|
|
61
|
+
this.close();
|
|
62
|
+
else {
|
|
63
|
+
signal.addEventListener('abort', this.#abort, { once: true });
|
|
64
|
+
response.once('close', this.#abort);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
send(envelope) {
|
|
68
|
+
if (this.#closed)
|
|
69
|
+
return Promise.reject(new Error('resource output closed'));
|
|
70
|
+
const bytes = Buffer.byteLength(JSON.stringify(envelope));
|
|
71
|
+
if (bytes > RESOURCE_ASSEMBLY_BYTES)
|
|
72
|
+
return this.#fail(new Error('resource assembly limit exceeded'));
|
|
73
|
+
if (this.#active && this.#pendingBytes + bytes > RESOURCE_PENDING_BYTES) {
|
|
74
|
+
return this.#fail(new Error('resource pending limit exceeded'));
|
|
75
|
+
}
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const item = { envelope, bytes, resolve, reject };
|
|
78
|
+
if (!this.#active) {
|
|
79
|
+
this.#active = item;
|
|
80
|
+
void this.#pump();
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.#pending.push(item);
|
|
84
|
+
this.#pendingBytes += bytes;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
#fail(error) {
|
|
89
|
+
this.close(error);
|
|
90
|
+
this.failed(error);
|
|
91
|
+
return Promise.reject(error);
|
|
92
|
+
}
|
|
93
|
+
close(error = new Error('resource output closed')) {
|
|
94
|
+
if (this.#closed)
|
|
95
|
+
return;
|
|
96
|
+
this.#closed = true;
|
|
97
|
+
this.signal.removeEventListener('abort', this.#abort);
|
|
98
|
+
this.response.removeListener('close', this.#abort);
|
|
99
|
+
this.#releaseDrain?.();
|
|
100
|
+
this.#active?.reject(error);
|
|
101
|
+
for (const item of this.#pending.splice(0))
|
|
102
|
+
item.reject(error);
|
|
103
|
+
this.#pendingBytes = 0;
|
|
104
|
+
if (!this.response.destroyed && !this.response.writableEnded)
|
|
105
|
+
this.response.end();
|
|
106
|
+
}
|
|
107
|
+
async #pump() {
|
|
108
|
+
try {
|
|
109
|
+
while (this.#active && !this.#closed) {
|
|
110
|
+
const item = this.#active;
|
|
111
|
+
for (const frame of resourceFrames(item.envelope)) {
|
|
112
|
+
if (this.#closed)
|
|
113
|
+
break;
|
|
114
|
+
const writable = this.response.write(`event: ${frame.event}\ndata: ${JSON.stringify(frame.data)}\n\n`);
|
|
115
|
+
if (!writable)
|
|
116
|
+
await this.#drain();
|
|
117
|
+
}
|
|
118
|
+
if (this.#closed)
|
|
119
|
+
break;
|
|
120
|
+
item.resolve();
|
|
121
|
+
this.#active = this.#pending.shift();
|
|
122
|
+
if (this.#active)
|
|
123
|
+
this.#pendingBytes -= this.#active.bytes;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
const failure = error instanceof Error ? error : new Error('resource output failed');
|
|
128
|
+
this.close(failure);
|
|
129
|
+
this.failed(failure);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
#drain() {
|
|
133
|
+
if (this.#closed)
|
|
134
|
+
return Promise.resolve();
|
|
135
|
+
return new Promise(resolve => {
|
|
136
|
+
const release = () => {
|
|
137
|
+
this.response.removeListener('drain', release);
|
|
138
|
+
this.#releaseDrain = undefined;
|
|
139
|
+
resolve();
|
|
140
|
+
};
|
|
141
|
+
this.#releaseDrain = release;
|
|
142
|
+
this.response.once('drain', release);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export function canonicalResourceDescriptor(input) {
|
|
147
|
+
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
148
|
+
throw Error('invalid resource descriptor');
|
|
149
|
+
const value = input;
|
|
150
|
+
if (!/^[A-Za-z0-9_-]{1,128}$/.test(value.viewId) || !['directory', 'roles', 'tasks', 'task-lists', 'configuration', 'previews', 'task-layout', 'creation-action', 'action', 'member-addition', 'login', 'onboarding-health', 'subscriptions'].includes(value.resource)
|
|
151
|
+
|| Object.keys(value).some(key => !['viewId', 'resource', 'includeTemporary', 'includeDefinitions', 'ids', 'state', 'list', 'groupByList', 'includeDeleting', 'entityId', 'receiptId', 'provider'].includes(key)))
|
|
152
|
+
throw Error('invalid resource descriptor');
|
|
153
|
+
for (const key of ['includeTemporary', 'includeDefinitions', 'groupByList', 'includeDeleting'])
|
|
154
|
+
if (value[key] !== undefined && typeof value[key] !== 'boolean')
|
|
155
|
+
throw Error('invalid resource descriptor');
|
|
156
|
+
if (value.ids !== undefined && (!Array.isArray(value.ids) || value.ids.length > 500 || value.ids.some(id => typeof id !== 'string' || !/^[A-Za-z0-9_-]{1,120}$/.test(id))))
|
|
157
|
+
throw Error('invalid resource ids');
|
|
158
|
+
if (value.state !== undefined && !['all', 'backlog', 'provisioning', 'active', 'review', 'done', 'cancelled', 'failed'].includes(value.state))
|
|
159
|
+
throw Error('invalid resource state');
|
|
160
|
+
if (value.list !== undefined && (typeof value.list !== 'string' || value.list.length > 256))
|
|
161
|
+
throw Error('invalid resource list');
|
|
162
|
+
for (const key of ['entityId', 'receiptId'])
|
|
163
|
+
if (value[key] !== undefined && (typeof value[key] !== 'string' || !/^[A-Za-z0-9_-]{1,120}$/.test(value[key])))
|
|
164
|
+
throw Error('invalid resource target');
|
|
165
|
+
if (['task-layout', 'creation-action', 'action', 'member-addition', 'login'].includes(value.resource) && !value.entityId)
|
|
166
|
+
throw Error('resource target required');
|
|
167
|
+
if (value.resource === 'member-addition' && !value.receiptId)
|
|
168
|
+
throw Error('receipt required');
|
|
169
|
+
if (value.resource === 'login' && !['claude', 'codex'].includes(value.provider ?? ''))
|
|
170
|
+
throw Error('provider required');
|
|
171
|
+
return { ...value, ...(value.ids ? { ids: [...new Set(value.ids)] } : {}) };
|
|
172
|
+
}
|
|
173
|
+
export class ResourceBindingError extends Error {
|
|
174
|
+
status;
|
|
175
|
+
constructor(status, message) {
|
|
176
|
+
super(message);
|
|
177
|
+
this.status = status;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Same committed snapshot/ready/bound-read contract as Messenger. No controllers,
|
|
181
|
+
* notification reads or presence are acquired by this delivery owner. */
|
|
182
|
+
export class FleetResourceViews {
|
|
183
|
+
scope;
|
|
184
|
+
project;
|
|
185
|
+
producerGeneration = randomUUID();
|
|
186
|
+
connections = new Map();
|
|
187
|
+
constructor(scope, project) {
|
|
188
|
+
this.scope = scope;
|
|
189
|
+
this.project = project;
|
|
190
|
+
}
|
|
191
|
+
open(response, owner, authorized) {
|
|
192
|
+
const id = randomUUID(), controller = new AbortController();
|
|
193
|
+
let connection;
|
|
194
|
+
let timer;
|
|
195
|
+
const close = () => {
|
|
196
|
+
if (controller.signal.aborted)
|
|
197
|
+
return;
|
|
198
|
+
controller.abort();
|
|
199
|
+
clearInterval(timer);
|
|
200
|
+
this.connections.delete(id);
|
|
201
|
+
if (connection) {
|
|
202
|
+
for (const view of connection.views.values())
|
|
203
|
+
this.retire(view);
|
|
204
|
+
connection.views.clear();
|
|
205
|
+
connection.output.close();
|
|
206
|
+
}
|
|
207
|
+
response.off('close', close);
|
|
208
|
+
};
|
|
209
|
+
const output = new ResourceOutput(response, controller.signal, close);
|
|
210
|
+
const observer = observeFleetResources(this.scope, state => {
|
|
211
|
+
if (!connection || controller.signal.aborted)
|
|
212
|
+
return;
|
|
213
|
+
if (state.health !== 'healthy') {
|
|
214
|
+
const pending = [...connection.views.values()].map(view => {
|
|
215
|
+
view.failed = true;
|
|
216
|
+
view.rejectInitial(Error('resource observation unavailable'));
|
|
217
|
+
view.controller.abort();
|
|
218
|
+
return this.emit(connection, view, 'health', { healthy: false, reason: state.health === 'unsupported' ? 'unsupported' : 'upstream_unavailable' });
|
|
219
|
+
});
|
|
220
|
+
if (!pending.length)
|
|
221
|
+
response.write(`event: resource-service-health\ndata: ${JSON.stringify({ protocolVersion: 1, healthy: false, reason: state.health === 'unsupported' ? 'unsupported' : 'upstream_unavailable' })}\n\n`);
|
|
222
|
+
void Promise.allSettled(pending).then(close);
|
|
223
|
+
}
|
|
224
|
+
else
|
|
225
|
+
for (const view of connection.views.values())
|
|
226
|
+
if (view.source.snapshot().position !== view.scheduledPosition)
|
|
227
|
+
this.schedule(connection, view);
|
|
228
|
+
}, controller.signal);
|
|
229
|
+
connection = { id, owner, controller, output, views: new Map(), epochs: new Map(), observer, tail: Promise.resolve(), close };
|
|
230
|
+
this.connections.set(id, connection);
|
|
231
|
+
response.once('close', close);
|
|
232
|
+
response.write(`event: resource-connection\ndata: ${JSON.stringify({ protocolVersion: 1, connectionId: id, producerGeneration: this.producerGeneration, continuity: 'reset', baselineRequired: true })}\n\n`);
|
|
233
|
+
if (observer.snapshot().health !== 'healthy') {
|
|
234
|
+
response.write(`event: resource-service-health\ndata: ${JSON.stringify({ protocolVersion: 1, healthy: false, reason: observer.snapshot().health === 'unsupported' ? 'unsupported' : 'upstream_unavailable' })}\n\n`);
|
|
235
|
+
close();
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
timer = setInterval(() => {
|
|
239
|
+
if (!authorized()) {
|
|
240
|
+
close();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
for (const view of connection.views.values())
|
|
244
|
+
if (!view.failed && view.covered && view.covered.position === view.source.snapshot().position)
|
|
245
|
+
void this.emit(connection, view, 'coverage', { source: view.covered }).catch(close);
|
|
246
|
+
// Keep the transport live with no subscribed views; never claim source coverage from bytes.
|
|
247
|
+
if (!connection.views.size)
|
|
248
|
+
response.write(': keepalive\n\n');
|
|
249
|
+
}, 2000);
|
|
250
|
+
timer.unref();
|
|
251
|
+
}
|
|
252
|
+
return { connectionId: id, close };
|
|
253
|
+
}
|
|
254
|
+
register(owner, connectionId, viewId, epoch, input) {
|
|
255
|
+
const connection = this.get(owner, connectionId);
|
|
256
|
+
let descriptor;
|
|
257
|
+
try {
|
|
258
|
+
descriptor = canonicalResourceDescriptor(input);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
throw new ResourceBindingError(400, 'invalid resource descriptor');
|
|
262
|
+
}
|
|
263
|
+
if (descriptor.viewId !== viewId || !Number.isSafeInteger(epoch) || epoch < 1)
|
|
264
|
+
throw new ResourceBindingError(400, 'invalid resource epoch');
|
|
265
|
+
if ((connection.epochs.get(viewId) ?? 0) >= epoch)
|
|
266
|
+
throw new ResourceBindingError(409, 'obsolete resource epoch');
|
|
267
|
+
if (connection.observer.snapshot().health !== 'healthy')
|
|
268
|
+
throw new ResourceBindingError(503, 'resource observation unavailable');
|
|
269
|
+
if (!connection.epochs.has(viewId) && connection.epochs.size >= 256)
|
|
270
|
+
throw new ResourceBindingError(503, 'resource epoch capacity exceeded');
|
|
271
|
+
if (!connection.views.has(viewId) && connection.views.size >= 64)
|
|
272
|
+
throw new ResourceBindingError(409, 'resource view capacity exceeded');
|
|
273
|
+
const old = connection.views.get(viewId);
|
|
274
|
+
if (old)
|
|
275
|
+
this.retire(old);
|
|
276
|
+
let resolveInitial, rejectInitial;
|
|
277
|
+
const initial = new Promise((resolve, reject) => { resolveInitial = resolve; rejectInitial = reject; });
|
|
278
|
+
void initial.catch(() => { });
|
|
279
|
+
const controller = new AbortController();
|
|
280
|
+
const source = connection.observer.cursor(path => this.affects(descriptor, path), controller.signal);
|
|
281
|
+
// Independent agents contribute ordered, last-observed statuses. Their
|
|
282
|
+
// ledger commits wake the view but do not revoke its structural capture.
|
|
283
|
+
const captureSource = descriptor.resource === 'directory' || descriptor.resource === 'roles'
|
|
284
|
+
? connection.observer.cursor(path => this.affects(descriptor, path, true), controller.signal)
|
|
285
|
+
: source;
|
|
286
|
+
const view = { source, captureSource, scheduledPosition: -1, descriptor, epoch, baselineId: randomUUID(), controller, revision: 0, sequence: 0, dirty: false, running: false, failed: false, initial, resolveInitial, rejectInitial };
|
|
287
|
+
connection.views.set(viewId, view);
|
|
288
|
+
connection.epochs.set(viewId, epoch);
|
|
289
|
+
this.schedule(connection, view);
|
|
290
|
+
return { subscriptionEpoch: epoch, baselineId: view.baselineId };
|
|
291
|
+
}
|
|
292
|
+
remove(owner, connectionId, viewId, epoch) {
|
|
293
|
+
const connection = this.get(owner, connectionId), view = connection.views.get(viewId);
|
|
294
|
+
if (typeof viewId !== 'string' || !/^[A-Za-z0-9_-]{1,128}$/.test(viewId) || !Number.isSafeInteger(epoch) || epoch < 1)
|
|
295
|
+
throw new ResourceBindingError(400, 'invalid resource epoch');
|
|
296
|
+
if (!connection.epochs.has(viewId) && connection.epochs.size >= 256)
|
|
297
|
+
throw new ResourceBindingError(503, 'resource epoch capacity exceeded');
|
|
298
|
+
// Independent DELETE can arrive before the POST it retires.
|
|
299
|
+
connection.epochs.set(viewId, Math.max(connection.epochs.get(viewId) ?? 0, epoch));
|
|
300
|
+
if (view && epoch >= view.epoch) {
|
|
301
|
+
this.retire(view);
|
|
302
|
+
connection.views.delete(viewId);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async bound(owner, connectionId, viewId, epoch, baselineId) {
|
|
306
|
+
const connection = this.get(owner, connectionId), view = connection.views.get(viewId);
|
|
307
|
+
if (!view || view.epoch !== epoch || view.baselineId !== baselineId)
|
|
308
|
+
throw new ResourceBindingError(409, 'resource binding mismatch');
|
|
309
|
+
const baseline = await view.initial;
|
|
310
|
+
if (!this.current(connection, view) || view.failed)
|
|
311
|
+
throw new ResourceBindingError(409, 'resource binding retired');
|
|
312
|
+
return baseline;
|
|
313
|
+
}
|
|
314
|
+
close() { for (const connection of this.connections.values())
|
|
315
|
+
connection.close(); }
|
|
316
|
+
get(owner, id) {
|
|
317
|
+
const connection = this.connections.get(id);
|
|
318
|
+
if (!connection || connection.owner !== owner)
|
|
319
|
+
throw new ResourceBindingError(409, 'unknown resource connection');
|
|
320
|
+
return connection;
|
|
321
|
+
}
|
|
322
|
+
current(connection, view) { return !connection.controller.signal.aborted && !view.controller.signal.aborted && connection.views.get(view.descriptor.viewId) === view; }
|
|
323
|
+
retire(view) { view.controller.abort(); view.rejectInitial(new ResourceBindingError(409, 'resource binding retired')); }
|
|
324
|
+
emit(connection, view, kind, payload) {
|
|
325
|
+
return connection.output.send({ protocolVersion: 1, producerGeneration: this.producerGeneration, viewId: view.descriptor.viewId, subscriptionEpoch: view.epoch, baselineId: view.baselineId, sequence: ++view.sequence, revision: view.revision, kind, payload });
|
|
326
|
+
}
|
|
327
|
+
affects(descriptor, path, structural = false) {
|
|
328
|
+
// Only classify known activity writes under the configured role roots.
|
|
329
|
+
// Parent/unknown events and every other file retain full invalidation.
|
|
330
|
+
// The canonical web producer atomically replaces hashed checkpoint files.
|
|
331
|
+
// These delivery acknowledgements are not role/task/config membership;
|
|
332
|
+
// retain full wakes without requiring an outbox-quiet capture window.
|
|
333
|
+
if (structural && /^[a-f0-9]{64}\.json$/.test(relative(resolve(stateRoot(), 'web', 'notification-outboxes'), path)))
|
|
334
|
+
return false;
|
|
335
|
+
const roots = this.scope.roots ?? [agentsRoot(), tmpRoot()];
|
|
336
|
+
for (const root of roots) {
|
|
337
|
+
const parts = relative(resolve(root), path).split(sep);
|
|
338
|
+
if (parts[0] === '..')
|
|
339
|
+
continue;
|
|
340
|
+
// Both session backends append diagnostic events as well as durable
|
|
341
|
+
// conversation events; ACP usage updates also persist observed usage.
|
|
342
|
+
// Monitor cursor/state and its presented status are per-agent activity.
|
|
343
|
+
// None changes role membership/configuration. Keep these as full wakes.
|
|
344
|
+
if (structural && parts.length === 2 && ['.session-events.jsonl', '.session-events.jsonl.1', '.subscription-usage.json', '.notify-cursor', '.monitor-state.json', '.monitor-status'].includes(parts[1]))
|
|
345
|
+
return false;
|
|
346
|
+
if (parts.length < 3 || parts[1] !== '.conversation')
|
|
347
|
+
continue;
|
|
348
|
+
if (structural && (descriptor.resource === 'directory' || descriptor.resource === 'roles'))
|
|
349
|
+
return false;
|
|
350
|
+
if (descriptor.resource === 'previews')
|
|
351
|
+
return (descriptor.ids ?? []).includes(parts[0]);
|
|
352
|
+
// Configuration/provenance reads no conversation data. Directory and
|
|
353
|
+
// roles intentionally remain conservative: live status includes activity.
|
|
354
|
+
if (descriptor.resource === 'configuration')
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
schedule(connection, view) {
|
|
360
|
+
if (!this.current(connection, view) || view.failed)
|
|
361
|
+
return;
|
|
362
|
+
view.scheduledPosition = view.source.snapshot().position;
|
|
363
|
+
view.dirty = true;
|
|
364
|
+
if (view.running)
|
|
365
|
+
return;
|
|
366
|
+
view.running = true;
|
|
367
|
+
const task = connection.tail.then(() => this.refresh(connection, view));
|
|
368
|
+
connection.tail = task.catch(() => { });
|
|
369
|
+
void task.finally(() => { view.running = false; if (view.dirty)
|
|
370
|
+
this.schedule(connection, view); }).catch(connection.close);
|
|
371
|
+
}
|
|
372
|
+
async refresh(connection, view) {
|
|
373
|
+
try {
|
|
374
|
+
if (!view.dirty || !this.current(connection, view))
|
|
375
|
+
return;
|
|
376
|
+
view.dirty = false;
|
|
377
|
+
let payload, source;
|
|
378
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
379
|
+
view.controller.signal.throwIfAborted();
|
|
380
|
+
const before = view.captureSource.snapshot();
|
|
381
|
+
const covered = view.source.snapshot();
|
|
382
|
+
payload = await abortableProjection(this.project(view.descriptor, view.controller.signal, connection.owner), view.controller.signal);
|
|
383
|
+
view.controller.signal.throwIfAborted();
|
|
384
|
+
const after = view.captureSource.snapshot();
|
|
385
|
+
if (after.health !== 'healthy')
|
|
386
|
+
throw Error('resource observation unavailable');
|
|
387
|
+
// Certify only the starting wake barrier. Status commits during the
|
|
388
|
+
// asynchronous canonical read stay dirty and are drained in order by
|
|
389
|
+
// the next serialized capture, even if this read happened to see them.
|
|
390
|
+
if (before.position === after.position) {
|
|
391
|
+
source = covered;
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (!source)
|
|
396
|
+
throw Error('resource projection unstable');
|
|
397
|
+
if (!this.current(connection, view))
|
|
398
|
+
return;
|
|
399
|
+
const first = view.payload === undefined, changed = first || JSON.stringify(payload, (key, value) => key === 'observedAt' ? undefined : value) !== JSON.stringify(view.payload, (key, value) => key === 'observedAt' ? undefined : value);
|
|
400
|
+
view.covered = source;
|
|
401
|
+
if (changed) {
|
|
402
|
+
view.revision++;
|
|
403
|
+
await this.emit(connection, view, 'snapshot', payload);
|
|
404
|
+
if (!this.current(connection, view))
|
|
405
|
+
return;
|
|
406
|
+
view.payload = payload;
|
|
407
|
+
}
|
|
408
|
+
if (first) {
|
|
409
|
+
await this.emit(connection, view, 'ready', { baselineId: view.baselineId, source });
|
|
410
|
+
if (this.current(connection, view))
|
|
411
|
+
view.resolveInitial({ payload, source, producerGeneration: this.producerGeneration, revision: view.revision, baselineId: view.baselineId, descriptor: view.descriptor });
|
|
412
|
+
}
|
|
413
|
+
else
|
|
414
|
+
await this.emit(connection, view, 'coverage', { source });
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
if (!this.current(connection, view))
|
|
418
|
+
return;
|
|
419
|
+
view.failed = true;
|
|
420
|
+
view.rejectInitial(error instanceof Error ? error : Error('projection failed'));
|
|
421
|
+
await this.emit(connection, view, 'resync', { reason: 'projection_unavailable' }).catch(connection.close);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
package/dist/web/runtime.d.ts
CHANGED
|
@@ -2,8 +2,10 @@ import { type WebServer } from './server.js';
|
|
|
2
2
|
import { type WebAccessConfig } from './access.js';
|
|
3
3
|
export interface StartWebOptions {
|
|
4
4
|
configPath?: string;
|
|
5
|
+
/** Separate console state for an independently launched gateway. */
|
|
6
|
+
webStateDir?: string;
|
|
7
|
+
control?: boolean;
|
|
5
8
|
port?: number;
|
|
6
|
-
open?: boolean;
|
|
7
9
|
binPath: string;
|
|
8
10
|
log?(line: string): void;
|
|
9
11
|
bind?: string;
|