@ours.network/fleet 1.2.0-nightly.9 → 2.0.1
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 +280 -68
- package/dist/account-origin.d.ts +5 -0
- package/dist/account-origin.js +31 -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 +22 -0
- package/dist/agent-ours/mcp-endpoint.js +101 -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 +27 -1
- package/dist/agent-ours/service.js +107 -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 +31 -0
- package/dist/application/conversation-history.js +339 -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 +43 -0
- package/dist/application/resource-observer.js +323 -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 +3 -1
- package/dist/application/role-repository.js +89 -54
- 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 +63 -17
- package/dist/application/session-control.js +221 -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 +5 -1
- package/dist/briefing.js +138 -31
- package/dist/build-info.json +10 -5
- package/dist/capabilities.d.ts +9 -1
- package/dist/capabilities.js +13 -0
- package/dist/cli.js +391 -38
- 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 +402 -20
- 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 +13 -0
- package/dist/fleet-command-audit.js +31 -9
- 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 +31 -0
- package/dist/notifications/fleet-producer.js +351 -0
- package/dist/notifications/outbox.d.ts +59 -0
- package/dist/notifications/outbox.js +199 -0
- package/dist/notifications/target-cleanup.d.ts +16 -0
- package/dist/notifications/target-cleanup.js +75 -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 +5 -0
- package/dist/paths.js +5 -0
- package/dist/preset-migration.js +55 -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 +4 -0
- package/dist/rooms-tasks/archived-absence.js +11 -0
- package/dist/rooms-tasks/cli.js +182 -5
- package/dist/rooms-tasks/close.d.ts +5 -2
- package/dist/rooms-tasks/close.js +224 -36
- 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 +66 -10
- 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-review.d.ts +113 -0
- package/dist/rooms-tasks/task-review.js +561 -0
- 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 +51 -5
- package/dist/rooms-tasks/task-state.js +358 -50
- package/dist/rooms-tasks/task-tools.d.ts +35 -0
- package/dist/rooms-tasks/task-tools.js +134 -0
- package/dist/rooms-tasks/types.d.ts +78 -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 +23 -4
- package/dist/runner.js +409 -61
- 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 +219 -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 +213 -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 +20 -1
- package/dist/startup-readiness.js +66 -3
- 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 +18 -37
- 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 +130 -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 +26 -0
- package/dist/web/conversation-stream.js +239 -0
- package/dist/web/events.d.ts +2 -0
- package/dist/web/events.js +9 -0
- package/dist/web/fleet-config-service.d.ts +7 -1
- package/dist/web/fleet-config-service.js +61 -16
- package/dist/web/prefix-gateway.d.ts +32 -0
- package/dist/web/prefix-gateway.js +248 -0
- package/dist/web/resource-views.d.ts +138 -0
- package/dist/web/resource-views.js +519 -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 +893 -71
- 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 +605 -0
- package/dist/workspace-replacement.d.ts +66 -0
- package/dist/workspace-replacement.js +238 -0
- package/docs/acp-files.md +146 -0
- package/docs/conversation-stream.md +216 -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-progress-review.md +143 -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 +25 -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 +6 -3
- 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 +21 -13
- package/presets/fleet/roles/Critic.yaml +24 -0
- package/presets/fleet/roles/Developer.yaml +32 -0
- package/presets/fleet/roles/Engineer.yaml +72 -0
- package/presets/fleet/roles/LocalCoordinator.yaml +17 -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
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { ConversationObservation } from './conversation-observation.js';
|
|
2
|
+
import { appendTaskCreated } from './task-notice.js';
|
|
1
3
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
4
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
5
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
6
|
+
import { boundedJson } from './conversation-normalizer.js';
|
|
4
7
|
import { ConversationEventStore } from './conversation-store.js';
|
|
5
8
|
import { SessionEvents } from './events.js';
|
|
9
|
+
import { memberAuthority, memberBindings, pendingInventory, takeBatch, refuseAtRelease, RELEASE_GUARD_REFUSED, } from './prompt-batch.js';
|
|
6
10
|
import { CodexAppServerTransport } from './codex-app-server-transport.js';
|
|
7
11
|
import { CODEX_APP_SERVER_CANCEL_DEADLINE_EXCEEDED, SessionControlError, sessionBackendCapabilities, turnResult, } from './types.js';
|
|
8
12
|
const PERMISSION_TIMEOUT_MS = 10 * 60_000;
|
|
@@ -12,7 +16,6 @@ const INTERRUPT_TERMINATE_GRACE_MS = 5_000;
|
|
|
12
16
|
const TERMINAL_RECONCILE_QUIET_MS = 2_000;
|
|
13
17
|
const TERMINAL_RECONCILE_REQUEST_TIMEOUT_MS = 5_000;
|
|
14
18
|
const SCHEDULED_REDACTION = '[scheduled-loop content redacted]';
|
|
15
|
-
const COMMENTARY_REDACTION = '[assistant commentary redacted]';
|
|
16
19
|
const OWNER_ADMIN_CONTEXT_KEY = 'ours-fleet://prompt-provenance?source=owner_admin_console';
|
|
17
20
|
const OWNER_CHANNEL_CONTEXT_KEY = 'ours-fleet://prompt-provenance?source=owner_channel';
|
|
18
21
|
const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
@@ -24,6 +27,7 @@ function sourceFor(origin) {
|
|
|
24
27
|
case 'owner': return { source: 'owner_channel', persistBody: false };
|
|
25
28
|
case 'fleet-monitor': return { source: 'fleet_monitor', persistBody: false };
|
|
26
29
|
case 'scheduled-loop': return { source: 'scheduled_loop', persistBody: false };
|
|
30
|
+
case 'self-reminder': return { source: 'fleet_monitor', persistBody: false };
|
|
27
31
|
case 'local-console':
|
|
28
32
|
default: return { source: 'local_console', persistBody: true };
|
|
29
33
|
}
|
|
@@ -74,6 +78,31 @@ export function nativePromptAdditionalContext(origin) {
|
|
|
74
78
|
};
|
|
75
79
|
return undefined;
|
|
76
80
|
}
|
|
81
|
+
const PROMPT_BATCH_CONTEXT_KEY = 'ours-fleet://prompt-batch';
|
|
82
|
+
/**
|
|
83
|
+
* Application context for a turn that carries several admitted prompts.
|
|
84
|
+
*
|
|
85
|
+
* The single-prompt context says "the accompanying user text", which would
|
|
86
|
+
* cover every member. A shared turn therefore carries this one entry instead:
|
|
87
|
+
* each member is its own user text item, in order, and its route and exact
|
|
88
|
+
* bytes are stated here by the server. Text imitating this wording is still
|
|
89
|
+
* only user text; it cannot add an application-context entry.
|
|
90
|
+
*/
|
|
91
|
+
export function nativeBatchAdditionalContext(members) {
|
|
92
|
+
if (members.length === 1)
|
|
93
|
+
return nativePromptAdditionalContext(members[0].origin);
|
|
94
|
+
const bindings = memberBindings(members, origin => sourceFor(origin).source);
|
|
95
|
+
return {
|
|
96
|
+
[PROMPT_BATCH_CONTEXT_KEY]: {
|
|
97
|
+
kind: 'application',
|
|
98
|
+
value: `Fleet queued prompt batch: ${members.length} separately admitted prompts in submission order, `
|
|
99
|
+
+ 'one user text item each. Server-generated provenance per item, describing only that item: '
|
|
100
|
+
+ bindings.map(binding => `item ${binding.index} of ${binding.of} `
|
|
101
|
+
+ `(source=${binding.source}, bytes=${binding.bytes}, sha256=${binding.sha256}): `
|
|
102
|
+
+ `${memberAuthority(binding.source)}`).join('; ') + '.',
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
77
106
|
function toolItem(item) {
|
|
78
107
|
switch (item.type) {
|
|
79
108
|
case 'commandExecution': return {
|
|
@@ -121,7 +150,13 @@ export class CodexAppServerSession {
|
|
|
121
150
|
lastError;
|
|
122
151
|
exit = null;
|
|
123
152
|
queueDepth = 0;
|
|
153
|
+
deferredRecovered = [];
|
|
154
|
+
observation = new ConversationObservation(() => this.captureObservation());
|
|
124
155
|
promptTail = Promise.resolve();
|
|
156
|
+
/** Admitted prompts not yet handed to the app-server, in admission order. */
|
|
157
|
+
pendingPrompts = [];
|
|
158
|
+
/** Admitted prompt → the turn that carries it, while that turn is open. */
|
|
159
|
+
sharedTurns = new Map();
|
|
125
160
|
activeTurn;
|
|
126
161
|
controllerCount = 0;
|
|
127
162
|
controllerGrace;
|
|
@@ -139,6 +174,9 @@ export class CodexAppServerSession {
|
|
|
139
174
|
roleId: options.name, log: line => options.log(`[${options.name}] ${line}`),
|
|
140
175
|
});
|
|
141
176
|
this.conversationStartCursor = this.conversation.lastCursor();
|
|
177
|
+
// A durable append can precede its inventory mutation. Capture only after
|
|
178
|
+
// the synchronous owner checkpoint, never the state at append notification.
|
|
179
|
+
this.conversation.subscribe(() => this.observation.scheduleCapture());
|
|
142
180
|
// Use Fleet's provider-neutral resume marker so runner recovery rotates the
|
|
143
181
|
// exact native thread id after a poisoned fast resume.
|
|
144
182
|
this.threadFile = join(options.stateDir, '.session-id');
|
|
@@ -172,6 +210,9 @@ export class CodexAppServerSession {
|
|
|
172
210
|
alive: this.isAlive(),
|
|
173
211
|
readiness: this.readiness,
|
|
174
212
|
sessionId: this.threadId,
|
|
213
|
+
// A shared turn is a human console turn if any member is: inbox traffic must not cut it short.
|
|
214
|
+
...(this.activeTurn?.origin ? { activePromptSource: this.activeTurn.console
|
|
215
|
+
? 'owner-admin-console' : this.activeTurn.origin.kind } : {}),
|
|
175
216
|
lastError: this.lastError,
|
|
176
217
|
pendingPermissionId: this.pendingPermissions.keys().next().value,
|
|
177
218
|
runtimeModel: this.runtimeModel,
|
|
@@ -184,6 +225,9 @@ export class CodexAppServerSession {
|
|
|
184
225
|
};
|
|
185
226
|
}
|
|
186
227
|
async queuePrompt(text, options = {}) {
|
|
228
|
+
// A guarded prompt must reach the model only through the release fence.
|
|
229
|
+
if (options.releaseGuard)
|
|
230
|
+
options = { ...options, interrupt: false, steer: false };
|
|
187
231
|
if (this.closing || !this.threadId || !this.transport.isAlive())
|
|
188
232
|
throw new SessionControlError('offline', this.lastError ?? 'Codex app-server session is offline');
|
|
189
233
|
let delivery;
|
|
@@ -200,15 +244,18 @@ export class CodexAppServerSession {
|
|
|
200
244
|
}
|
|
201
245
|
const promptId = randomUUID();
|
|
202
246
|
const queuedBehind = this.queueDepth;
|
|
203
|
-
this.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
247
|
+
const run = this.observation.checkpoint(() => {
|
|
248
|
+
this.admit(promptId, text, queuedBehind, options);
|
|
249
|
+
this.queueDepth++;
|
|
250
|
+
return this.enqueue(promptId, text, options.origin, options.releaseGuard);
|
|
251
|
+
});
|
|
207
252
|
const completion = run.then(result => {
|
|
208
253
|
this.queueDepth = Math.max(0, this.queueDepth - 1);
|
|
254
|
+
this.observation.publish();
|
|
209
255
|
return result;
|
|
210
256
|
}, error => {
|
|
211
257
|
this.queueDepth = Math.max(0, this.queueDepth - 1);
|
|
258
|
+
this.observation.publish();
|
|
212
259
|
return turnResult(false, 'failed', error instanceof Error ? error.message : String(error));
|
|
213
260
|
});
|
|
214
261
|
return {
|
|
@@ -216,6 +263,53 @@ export class CodexAppServerSession {
|
|
|
216
263
|
delivery: delivery ?? (queuedBehind ? 'queued' : 'started'),
|
|
217
264
|
};
|
|
218
265
|
}
|
|
266
|
+
/** The turn whose events and result answer this admitted prompt; itself unless a release shared it. */
|
|
267
|
+
sharedTurnId(promptId) {
|
|
268
|
+
return this.sharedTurns.get(promptId);
|
|
269
|
+
}
|
|
270
|
+
/** Each prompt keeps its own step in the chain; the step it reaches releases a whole snapshot. */
|
|
271
|
+
enqueue(promptId, text, origin, releaseGuard) {
|
|
272
|
+
const entry = {
|
|
273
|
+
promptId, text, origin, ...sourceFor(origin), admittedAt: new Date().toISOString(),
|
|
274
|
+
// The one text the native session runs as an operation instead of a turn.
|
|
275
|
+
command: text.trim() === '/compact',
|
|
276
|
+
...(releaseGuard ? { releaseGuard } : {}),
|
|
277
|
+
};
|
|
278
|
+
this.pendingPrompts.push(entry);
|
|
279
|
+
const run = this.promptTail.then(() => this.release(entry));
|
|
280
|
+
this.promptTail = run.then(() => undefined, () => undefined);
|
|
281
|
+
return run;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The turn boundary: the first waiting prompt to get here synchronously
|
|
285
|
+
* takes every pending prompt delivered with it into one turn. A prompt
|
|
286
|
+
* admitted afterwards stays pending for the next boundary, and a step whose
|
|
287
|
+
* prompt was already taken reports that turn's result.
|
|
288
|
+
*/
|
|
289
|
+
release(entry) {
|
|
290
|
+
if (entry.released)
|
|
291
|
+
return entry.released;
|
|
292
|
+
const refused = refuseAtRelease(this.pendingPrompts, entry, Boolean(this.threadId && this.transport.isAlive()));
|
|
293
|
+
if (refused) {
|
|
294
|
+
this.conversation.appendSafe({
|
|
295
|
+
kind: 'turn.completed', sessionGeneration: this.sessionGeneration,
|
|
296
|
+
promptId: entry.promptId, turnId: entry.promptId,
|
|
297
|
+
payload: { outcome: 'cancelled', stopReason: RELEASE_GUARD_REFUSED },
|
|
298
|
+
});
|
|
299
|
+
entry.released = Promise.resolve(refused);
|
|
300
|
+
return entry.released;
|
|
301
|
+
}
|
|
302
|
+
const members = takeBatch(this.pendingPrompts, entry);
|
|
303
|
+
for (const member of members)
|
|
304
|
+
this.sharedTurns.set(member.promptId, members[0].promptId);
|
|
305
|
+
const run = this.runPrompt(members).finally(() => {
|
|
306
|
+
for (const member of members)
|
|
307
|
+
this.sharedTurns.delete(member.promptId);
|
|
308
|
+
});
|
|
309
|
+
for (const member of members)
|
|
310
|
+
member.released = run;
|
|
311
|
+
return run;
|
|
312
|
+
}
|
|
219
313
|
async submitPrompt(text, options = {}) {
|
|
220
314
|
try {
|
|
221
315
|
return await (await this.queuePrompt(text, options)).completion;
|
|
@@ -226,10 +320,20 @@ export class CodexAppServerSession {
|
|
|
226
320
|
throw error;
|
|
227
321
|
}
|
|
228
322
|
}
|
|
323
|
+
liveVoiceSupported = true;
|
|
324
|
+
async interruptPrompt(generation, promptId) {
|
|
325
|
+
if (generation !== this.sessionGeneration)
|
|
326
|
+
throw new Error('session_changed: Agent session changed.');
|
|
327
|
+
if (!this.activeTurn?.promptIds.includes(promptId))
|
|
328
|
+
return { state: 'settled' };
|
|
329
|
+
return this.interrupt('local-console');
|
|
330
|
+
}
|
|
229
331
|
async interrupt(source = 'local-console') {
|
|
230
332
|
const active = this.activeTurn;
|
|
231
|
-
if (!active || !this.threadId
|
|
333
|
+
if (!active || !this.threadId)
|
|
232
334
|
return { state: 'settled' };
|
|
335
|
+
if (!active.nativeTurnId)
|
|
336
|
+
throw new SessionControlError('backend', 'The operation is still pending without a native turn ID. Cancellation is not confirmed; inspect or restart the agent if it does not progress.');
|
|
233
337
|
active.cancellationSource ??= source;
|
|
234
338
|
this.events.emit('state', { turnId: active.promptId, status: 'running', origin: active.origin });
|
|
235
339
|
this.conversation.appendSafe({
|
|
@@ -334,7 +438,12 @@ export class CodexAppServerSession {
|
|
|
334
438
|
});
|
|
335
439
|
this.conversation.close();
|
|
336
440
|
await this.transport.close();
|
|
441
|
+
this.observation.publish();
|
|
442
|
+
}
|
|
443
|
+
taskNoticeBinding() {
|
|
444
|
+
return this.activeTurn && this.threadId ? { sessionGeneration: this.sessionGeneration, acpSessionId: this.threadId, promptId: this.activeTurn.promptId } : undefined;
|
|
337
445
|
}
|
|
446
|
+
recordTaskCreated(binding, notice) { appendTaskCreated(this.conversation, binding, notice); }
|
|
338
447
|
conversationPage(request = {}) {
|
|
339
448
|
const floor = Number(this.conversationStartCursor ?? 0);
|
|
340
449
|
const requested = Number(request.after ?? 0);
|
|
@@ -349,11 +458,42 @@ export class CodexAppServerSession {
|
|
|
349
458
|
}
|
|
350
459
|
return { ...page, events: visible, snapshot: this.conversationSnapshot() };
|
|
351
460
|
}
|
|
461
|
+
subscribeConversationFailure(listener) {
|
|
462
|
+
return this.conversation.subscribeFailure(listener);
|
|
463
|
+
}
|
|
464
|
+
conversationReplayAvailable(expectedGeneration) {
|
|
465
|
+
return expectedGeneration === this.sessionGeneration && this.conversation.generationDurable(expectedGeneration);
|
|
466
|
+
}
|
|
467
|
+
replayConversation(request) {
|
|
468
|
+
if (request.expectedGeneration !== this.sessionGeneration)
|
|
469
|
+
throw new Error('session generation changed');
|
|
470
|
+
return this.conversation.replay(request);
|
|
471
|
+
}
|
|
472
|
+
observeConversation(listener) {
|
|
473
|
+
return this.observation.observe(listener);
|
|
474
|
+
}
|
|
475
|
+
captureObservation() {
|
|
476
|
+
const snapshot = this.snapshot();
|
|
477
|
+
return {
|
|
478
|
+
...this.conversationSnapshot(),
|
|
479
|
+
...pendingInventory(this.pendingPrompts),
|
|
480
|
+
ledgerBarrier: Number(this.conversation.lastCursor() ?? 0),
|
|
481
|
+
alive: snapshot.alive,
|
|
482
|
+
readiness: snapshot.alive ? snapshot.readiness : 'offline',
|
|
483
|
+
activePromptIds: [...(this.activeTurn?.promptIds ?? [])],
|
|
484
|
+
pendingPermissions: [...this.pendingPermissions].flatMap(([permissionId, pending]) => pending.presented ? [{ permissionId, ...pending.presented }] : []),
|
|
485
|
+
commands: [{ name: 'compact', description: textBlock('Compact session context') }],
|
|
486
|
+
runtimeModel: snapshot.runtimeModel,
|
|
487
|
+
reasoningEffort: snapshot.reasoningEffort,
|
|
488
|
+
permissionMode: snapshot.permissionMode,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
352
491
|
conversationSnapshot() {
|
|
353
492
|
return {
|
|
354
493
|
sessionGeneration: this.sessionGeneration,
|
|
355
494
|
readiness: this.isAlive() ? this.readiness : 'offline',
|
|
356
495
|
queueDepth: this.queueDepth,
|
|
496
|
+
...pendingInventory(this.pendingPrompts),
|
|
357
497
|
pendingPermissionIds: [...this.pendingPermissions.keys()],
|
|
358
498
|
...(this.conversation.degraded ? { historyDegraded: true } : {}),
|
|
359
499
|
};
|
|
@@ -367,11 +507,16 @@ export class CodexAppServerSession {
|
|
|
367
507
|
const existing = this.conversation.receiptFor(command.commandId, bodyDigest);
|
|
368
508
|
if (existing)
|
|
369
509
|
return existing;
|
|
510
|
+
if (command.expectedSessionGeneration !== undefined && command.expectedSessionGeneration !== this.conversationSnapshot().sessionGeneration)
|
|
511
|
+
throw new Error('session_changed: Agent session changed. Record a new voice message.');
|
|
512
|
+
if (command.requireIdle && (this.queueDepth > 0 || this.conversationSnapshot().readiness !== 'idle'))
|
|
513
|
+
throw new Error('voice_busy: Agent is already working. Wait for the current turn.');
|
|
370
514
|
const queued = await this.queuePrompt(command.text, {
|
|
371
515
|
origin: { kind: 'owner-admin-console', commandId: command.commandId },
|
|
372
516
|
actor: { browserSession: command.actorBrowserSession },
|
|
373
517
|
});
|
|
374
518
|
const receipt = {
|
|
519
|
+
sessionGeneration: this.sessionGeneration,
|
|
375
520
|
commandId: command.commandId, promptId: queued.promptId,
|
|
376
521
|
state: queued.queuedBehind ? 'queued' : 'starting', queuedBehind: queued.queuedBehind,
|
|
377
522
|
acceptedAt: new Date().toISOString(), eventCursor: this.conversation.lastCursor() ?? '0',
|
|
@@ -387,6 +532,8 @@ export class CodexAppServerSession {
|
|
|
387
532
|
this.transport.notify('initialized');
|
|
388
533
|
const persisted = this.options.mode === 'resume' && existsSync(this.threadFile)
|
|
389
534
|
? readFileSync(this.threadFile, 'utf8').trim() : '';
|
|
535
|
+
if (this.options.requireResume && !persisted)
|
|
536
|
+
throw new Error('TASK_CONTEXT_RESUME_UNAVAILABLE');
|
|
390
537
|
const common = {
|
|
391
538
|
cwd: this.options.cwd,
|
|
392
539
|
approvalPolicy: this.options.approvalPolicy,
|
|
@@ -406,6 +553,8 @@ export class CodexAppServerSession {
|
|
|
406
553
|
this.threadId = string(thread?.id);
|
|
407
554
|
if (!this.threadId)
|
|
408
555
|
throw new Error('Codex app-server did not return a thread id');
|
|
556
|
+
if (this.options.requireResume && this.threadId !== persisted)
|
|
557
|
+
throw new Error('TASK_CONTEXT_RESUME_MISMATCH');
|
|
409
558
|
writeFileSync(this.threadFile, this.threadId + '\n', { mode: 0o600 });
|
|
410
559
|
const model = string(response.model) ?? this.options.model ?? undefined;
|
|
411
560
|
if (model)
|
|
@@ -415,10 +564,15 @@ export class CodexAppServerSession {
|
|
|
415
564
|
this.reasoningEffort = { value: effort };
|
|
416
565
|
this.readiness = 'idle';
|
|
417
566
|
this.events.emit('state', { status: 'idle', text: `Codex thread ${this.threadId}` });
|
|
567
|
+
this.conversation.appendSafe({
|
|
568
|
+
kind: 'capabilities.updated', sessionGeneration: this.sessionGeneration,
|
|
569
|
+
payload: { commands: [{ name: 'compact', description: textBlock('Compact session context') }] },
|
|
570
|
+
});
|
|
418
571
|
this.conversation.appendSafe({
|
|
419
572
|
kind: 'session.state', sessionGeneration: this.sessionGeneration,
|
|
420
573
|
payload: { status: 'idle' },
|
|
421
574
|
});
|
|
575
|
+
this.observation.publish();
|
|
422
576
|
}
|
|
423
577
|
recoverOpenPrompts() {
|
|
424
578
|
for (const open of this.conversation.openPrompts()) {
|
|
@@ -433,15 +587,27 @@ export class CodexAppServerSession {
|
|
|
433
587
|
});
|
|
434
588
|
continue;
|
|
435
589
|
}
|
|
436
|
-
this.queueDepth++;
|
|
437
590
|
const origin = open.commandId
|
|
438
591
|
? { kind: 'owner-admin-console', commandId: open.commandId }
|
|
439
592
|
: undefined;
|
|
440
|
-
const
|
|
441
|
-
this.
|
|
442
|
-
|
|
593
|
+
const recovered = { promptId: open.promptId, text: open.text, ...(origin ? { origin } : {}) };
|
|
594
|
+
if (this.options.deferRecoveredPrompts)
|
|
595
|
+
this.deferredRecovered.push(recovered);
|
|
596
|
+
else
|
|
597
|
+
this.dispatchRecovered(recovered);
|
|
443
598
|
}
|
|
444
599
|
}
|
|
600
|
+
/** Dispatch recovered prompts once the caller's control plane is listening. */
|
|
601
|
+
activateRecoveredPrompts() {
|
|
602
|
+
for (const recovered of this.deferredRecovered.splice(0))
|
|
603
|
+
this.dispatchRecovered(recovered);
|
|
604
|
+
}
|
|
605
|
+
dispatchRecovered({ promptId, text, origin }) {
|
|
606
|
+
this.queueDepth++;
|
|
607
|
+
const run = this.enqueue(promptId, text, origin);
|
|
608
|
+
this.observation.publish();
|
|
609
|
+
void run.finally(() => { this.queueDepth = Math.max(0, this.queueDepth - 1); this.observation.publish(); });
|
|
610
|
+
}
|
|
445
611
|
admit(promptId, text, queuedBehind, options) {
|
|
446
612
|
const { source, persistBody } = sourceFor(options.origin);
|
|
447
613
|
const bytes = Buffer.byteLength(text);
|
|
@@ -470,30 +636,44 @@ export class CodexAppServerSession {
|
|
|
470
636
|
else
|
|
471
637
|
this.conversation.appendSafe(draft);
|
|
472
638
|
}
|
|
473
|
-
async runPrompt(
|
|
639
|
+
async runPrompt(members) {
|
|
640
|
+
const { text, promptId, origin } = members[0];
|
|
474
641
|
if (!this.threadId || !this.transport.isAlive())
|
|
475
642
|
return turnResult(false, 'failed', this.lastError ?? 'Codex app-server session is offline');
|
|
476
643
|
let settle;
|
|
477
644
|
const settled = new Promise(resolveResult => { settle = resolveResult; });
|
|
478
|
-
const active = {
|
|
645
|
+
const active = {
|
|
646
|
+
promptId, origin, output: '', settled, settle,
|
|
647
|
+
promptIds: members.map(member => member.promptId),
|
|
648
|
+
console: members.some(member => member.origin?.kind === 'owner-admin-console'),
|
|
649
|
+
};
|
|
479
650
|
this.activeTurn = active;
|
|
480
651
|
this.finalAnswerObserved = false;
|
|
481
652
|
this.activeItems.clear();
|
|
482
653
|
this.readiness = 'running';
|
|
654
|
+
this.observation.publish();
|
|
483
655
|
this.events.emit('state', { turnId: promptId, status: 'running', origin });
|
|
484
|
-
this.conversation.appendSafe({
|
|
656
|
+
members.forEach((member, index) => this.conversation.appendSafe({
|
|
485
657
|
kind: 'prompt.started', sessionGeneration: this.sessionGeneration,
|
|
486
|
-
promptId, turnId: promptId, source: sourceFor(origin).source,
|
|
487
|
-
|
|
658
|
+
promptId: member.promptId, turnId: promptId, source: sourceFor(member.origin).source,
|
|
659
|
+
payload: members.length > 1 ? { batch: { turnId: promptId, index, size: members.length } } : {},
|
|
660
|
+
}));
|
|
488
661
|
try {
|
|
662
|
+
if (text.trim() === '/compact') {
|
|
663
|
+
// The acknowledgement is not completion. Standard turn notifications
|
|
664
|
+
// settle the same queued prompt and durable browser receipt.
|
|
665
|
+
await this.transport.request('thread/compact/start', { threadId: this.threadId });
|
|
666
|
+
return await settled;
|
|
667
|
+
}
|
|
489
668
|
const response = await this.transport.request('turn/start', {
|
|
490
669
|
threadId: this.threadId,
|
|
491
|
-
|
|
670
|
+
// One unchanged user text item per admitted prompt, in admission order.
|
|
671
|
+
input: members.map(member => ({ type: 'text', text: member.text, text_elements: [] })),
|
|
492
672
|
approvalPolicy: this.options.approvalPolicy,
|
|
493
673
|
model: this.options.model ?? null,
|
|
494
674
|
effort: this.options.effort ?? null,
|
|
495
|
-
...(
|
|
496
|
-
? { additionalContext:
|
|
675
|
+
...(nativeBatchAdditionalContext(members)
|
|
676
|
+
? { additionalContext: nativeBatchAdditionalContext(members) } : {}),
|
|
497
677
|
});
|
|
498
678
|
const turn = isObject(response.turn) ? response.turn : undefined;
|
|
499
679
|
active.nativeTurnId ??= string(turn?.id);
|
|
@@ -699,7 +879,7 @@ export class CodexAppServerSession {
|
|
|
699
879
|
promptId: this.activeTurn?.promptId, turnId: this.activeTurn?.promptId,
|
|
700
880
|
messageId: id, source: 'agent',
|
|
701
881
|
payload: {
|
|
702
|
-
role: 'assistant', content: textBlock(delta, scheduled ? SCHEDULED_REDACTION :
|
|
882
|
+
role: 'assistant', content: textBlock(delta, scheduled ? SCHEDULED_REDACTION : undefined),
|
|
703
883
|
},
|
|
704
884
|
});
|
|
705
885
|
}
|
|
@@ -746,6 +926,10 @@ export class CodexAppServerSession {
|
|
|
746
926
|
toolCallId: scheduled ? 'scheduled-loop-tool' : id, snapshot,
|
|
747
927
|
title: scheduled ? 'scheduled-loop tool' : tool.title, status: tool.status,
|
|
748
928
|
kind: string(item.type),
|
|
929
|
+
...(!scheduled && item.arguments !== undefined ? { rawInput: boundedJson(item.arguments) } : {}),
|
|
930
|
+
...(!scheduled && item.type === 'commandExecution' ? { rawInput: boundedJson({ command: item.command, cwd: item.cwd }), ...(item.aggregatedOutput !== undefined ? { rawOutput: boundedJson({ output: item.aggregatedOutput, exitCode: item.exitCode }) } : {}) } : {}),
|
|
931
|
+
...(!scheduled && item.type === 'fileChange' && item.changes !== undefined ? { rawOutput: boundedJson(item.changes) } : {}),
|
|
932
|
+
...(!scheduled && (item.result !== undefined || item.error !== undefined) ? { rawOutput: boundedJson({ result: item.result, error: item.error }) } : {}),
|
|
749
933
|
},
|
|
750
934
|
});
|
|
751
935
|
}
|
|
@@ -768,14 +952,17 @@ export class CodexAppServerSession {
|
|
|
768
952
|
cancellationSource: active.cancellationSource,
|
|
769
953
|
});
|
|
770
954
|
this.events.emit('state', { status: this.readiness });
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
955
|
+
// Every member closes with the shared outcome, so none is left waiting.
|
|
956
|
+
for (const member of active.promptIds)
|
|
957
|
+
this.conversation.appendSafe({
|
|
958
|
+
kind: 'turn.completed', sessionGeneration: this.sessionGeneration,
|
|
959
|
+
promptId: member, turnId: active.promptId,
|
|
960
|
+
payload: {
|
|
961
|
+
outcome, ...(detail ? { stopReason: detail } : {}),
|
|
962
|
+
...(active.cancellationSource ? { cancellationSource: active.cancellationSource } : {}),
|
|
963
|
+
},
|
|
964
|
+
});
|
|
965
|
+
this.observation.publish();
|
|
779
966
|
active.settle(result);
|
|
780
967
|
}
|
|
781
968
|
/**
|
|
@@ -939,7 +1126,6 @@ export class CodexAppServerSession {
|
|
|
939
1126
|
this.resolvePermission(permissionId, pending, 'denied', 'automatic', 'deny_once', unattended ? 'permissions.unattended=deny' : 'permissions.approval=deny', unattended ? 'no controller is attached' : 'the role denies permission requests');
|
|
940
1127
|
return;
|
|
941
1128
|
}
|
|
942
|
-
this.pendingPermissions.set(permissionId, pending);
|
|
943
1129
|
this.readiness = 'awaiting_permission';
|
|
944
1130
|
const timeoutMs = this.options.permissionTimeoutMs ?? PERMISSION_TIMEOUT_MS;
|
|
945
1131
|
const expiresAt = new Date(Date.now() + timeoutMs).toISOString();
|
|
@@ -949,19 +1135,23 @@ export class CodexAppServerSession {
|
|
|
949
1135
|
?? (method === 'item/fileChange/requestApproval' ? 'Apply file changes'
|
|
950
1136
|
: method === 'item/permissions/requestApproval' ? 'Grant additional permissions'
|
|
951
1137
|
: 'Run command');
|
|
1138
|
+
const presented = { toolCallId, title, options, expiresAt };
|
|
1139
|
+
pending.presented = presented;
|
|
1140
|
+
this.pendingPermissions.set(permissionId, pending);
|
|
952
1141
|
this.events.emit('permission', {
|
|
953
1142
|
turnId: this.activeTurn?.promptId, origin: this.activeTurn?.origin,
|
|
954
|
-
permissionId,
|
|
1143
|
+
permissionId, ...presented, status: 'pending',
|
|
955
1144
|
});
|
|
956
1145
|
this.conversation.appendSafe({
|
|
957
1146
|
kind: 'permission.requested', sessionGeneration: this.sessionGeneration,
|
|
958
1147
|
permissionId, promptId: this.activeTurn?.promptId, turnId: this.activeTurn?.promptId,
|
|
959
|
-
toolCallId, payload:
|
|
1148
|
+
toolCallId, payload: presented,
|
|
960
1149
|
});
|
|
961
1150
|
pending.expiry = setTimeout(() => {
|
|
962
1151
|
this.autoResolvePermission(permissionId, pending, undefined, `no decision arrived within ${Math.round(timeoutMs / 1000)}s`);
|
|
963
1152
|
}, timeoutMs);
|
|
964
1153
|
pending.expiry.unref?.();
|
|
1154
|
+
this.observation.publish();
|
|
965
1155
|
}
|
|
966
1156
|
serverRequestResolved(params) {
|
|
967
1157
|
const requestId = typeof params.requestId === 'string' || typeof params.requestId === 'number'
|
|
@@ -987,6 +1177,8 @@ export class CodexAppServerSession {
|
|
|
987
1177
|
this.resolvePermission(permissionId, pending, 'denied', 'automatic', 'deny_once', policy, reason);
|
|
988
1178
|
}
|
|
989
1179
|
resolvePermission(permissionId, pending, decision, decisionSource, optionId, policy, reason) {
|
|
1180
|
+
if (!this.pendingPermissions.size && this.readiness === 'awaiting_permission')
|
|
1181
|
+
this.readiness = 'running';
|
|
990
1182
|
this.events.emit('permission', {
|
|
991
1183
|
turnId: this.activeTurn?.promptId, origin: this.activeTurn?.origin,
|
|
992
1184
|
permissionId, toolCallId: pending.toolCallId, status: 'completed', decision,
|
|
@@ -999,8 +1191,7 @@ export class CodexAppServerSession {
|
|
|
999
1191
|
payload: { decision, decisionSource, ...(optionId ? { optionId } : {}),
|
|
1000
1192
|
...(policy ? { policy } : {}), ...(reason ? { reason } : {}) },
|
|
1001
1193
|
});
|
|
1002
|
-
|
|
1003
|
-
this.readiness = 'running';
|
|
1194
|
+
this.observation.publish();
|
|
1004
1195
|
this.scheduleTerminalReconciliation();
|
|
1005
1196
|
}
|
|
1006
1197
|
currentEvent(event) {
|
|
@@ -1048,10 +1239,12 @@ export class CodexAppServerSession {
|
|
|
1048
1239
|
if (this.activeTurn)
|
|
1049
1240
|
this.finishTurn('failed', this.lastError);
|
|
1050
1241
|
}
|
|
1242
|
+
this.observation.publish();
|
|
1051
1243
|
}
|
|
1052
1244
|
fail(error) {
|
|
1053
1245
|
this.lastError = error instanceof Error ? error.message : String(error);
|
|
1054
1246
|
this.readiness = 'failed';
|
|
1055
1247
|
this.events.emit('error', { text: this.lastError });
|
|
1248
|
+
this.observation.publish();
|
|
1056
1249
|
}
|
|
1057
1250
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { LayoutControlRequest } from '../rooms-tasks/layout-control.js';
|
|
2
|
+
import type { SupervisorCorrespondence, AgentHistoryQuery } from '../agent-ours/correspondence.js';
|
|
1
3
|
import { type Socket } from 'node:net';
|
|
4
|
+
import { type PassiveConversationFollowRequest } from './conversation-replay.js';
|
|
2
5
|
import type { AgentSession, ControlFailureKind, SessionEvent, SessionSnapshot } from './types.js';
|
|
3
6
|
import type { OwnerChannelHandle, OwnerChannelManagementRequest } from '../owner-channel/channel.js';
|
|
4
7
|
import type { ScheduledLoopManagerHandle } from '../loops/manager.js';
|
|
@@ -9,8 +12,13 @@ export interface ControlRequest {
|
|
|
9
12
|
version: 1 | 2 | 3;
|
|
10
13
|
id: string;
|
|
11
14
|
token: string;
|
|
12
|
-
command: 'status' | 'snapshot' | 'submit_prompt' | 'respond_permission' | 'interrupt' | 'follow' | 'events_since' | 'owner_channel_manage' | 'loop_status' | 'loop_run_now' | 'loop_disable' | 'loop_enable' | 'reload_config' | 'conversation_page' | 'conversation_follow' | 'submit_prompt_v2' | 'interrupt_v2' | 'respond_permission_v2' | 'fleet_spawn' | 'fleet_audit_begin' | 'fleet_audit_present' | 'fleet_audit_finish';
|
|
15
|
+
command: 'status' | 'snapshot' | 'submit_prompt' | 'respond_permission' | 'interrupt' | 'follow' | 'events_since' | 'owner_channel_manage' | 'loop_status' | 'loop_run_now' | 'loop_disable' | 'loop_enable' | 'reload_config' | 'conversation_page' | 'conversation_follow' | 'submit_prompt_v2' | 'submit_voice_prompt' | 'interrupt_v2' | 'interrupt_voice_v2' | 'layout_control' | 'agent_contacts' | 'agent_history' | 'respond_permission_v2' | 'fleet_spawn' | 'fleet_audit_begin' | 'fleet_audit_present' | 'fleet_audit_finish';
|
|
16
|
+
layout?: LayoutControlRequest;
|
|
17
|
+
agentHistory?: AgentHistoryQuery;
|
|
13
18
|
text?: string;
|
|
19
|
+
expectedSessionGeneration?: string;
|
|
20
|
+
requireIdle?: boolean;
|
|
21
|
+
promptId?: string;
|
|
14
22
|
permissionId?: string;
|
|
15
23
|
optionId?: string;
|
|
16
24
|
since?: number;
|
|
@@ -19,7 +27,8 @@ export interface ControlRequest {
|
|
|
19
27
|
ownerChannel?: OwnerChannelManagementRequest;
|
|
20
28
|
loop?: string;
|
|
21
29
|
/** Conversation cursor: replay strictly after this durable seq. */
|
|
22
|
-
after?: string;
|
|
30
|
+
after?: string | number;
|
|
31
|
+
expectedGeneration?: string;
|
|
23
32
|
limit?: number;
|
|
24
33
|
/** Idempotency key for v3 mutations. */
|
|
25
34
|
commandId?: string;
|
|
@@ -112,9 +121,13 @@ export declare class RoleControlServer {
|
|
|
112
121
|
private readonly sockets;
|
|
113
122
|
/** Interrupt idempotency: same command id returns the first receipt. */
|
|
114
123
|
private readonly interruptCommands;
|
|
124
|
+
private correspondence?;
|
|
125
|
+
setCorrespondence(value: SupervisorCorrespondence): void;
|
|
115
126
|
private ownerChannel?;
|
|
116
127
|
private loopManager?;
|
|
117
128
|
private reloadConfig?;
|
|
129
|
+
private layoutControl?;
|
|
130
|
+
setLayoutControl(handler: (request: LayoutControlRequest) => Promise<unknown>): void;
|
|
118
131
|
private fleetSpawner?;
|
|
119
132
|
private fleetAuditor?;
|
|
120
133
|
constructor(stateDir: string, session: AgentSession, log: (line: string) => void);
|
|
@@ -130,6 +143,7 @@ export declare class RoleControlServer {
|
|
|
130
143
|
private handle;
|
|
131
144
|
/** Version and capability gate shared by every conversation v3 command. */
|
|
132
145
|
private requireConversation;
|
|
146
|
+
private observationFeatures;
|
|
133
147
|
private write;
|
|
134
148
|
}
|
|
135
149
|
/**
|
|
@@ -149,7 +163,7 @@ export declare function followControl(stateDir: string, onMessage: (message: Rec
|
|
|
149
163
|
* `{ version, conversationEvent }`. Closing the socket detaches the
|
|
150
164
|
* controller-presence this connection contributed.
|
|
151
165
|
*/
|
|
152
|
-
export declare function followConversation(stateDir: string, after: string | undefined, onMessage: (message: Record<string, unknown>) => void): Promise<{
|
|
166
|
+
export declare function followConversation(stateDir: string, after: string | undefined | PassiveConversationFollowRequest, onMessage: (message: Record<string, unknown>) => void): Promise<{
|
|
153
167
|
socket: Socket;
|
|
154
168
|
close(): void;
|
|
155
169
|
}>;
|