Skip to content

wip: Codex native dispatcher fleet-pane slice - #2

Closed
lukemaj wants to merge 5 commits into
mainfrom
feat/1-agent-fleet
Closed

lukemaj wants to merge 5 commits into
mainfrom
feat/1-agent-fleet

Conversation

@lukemaj

@lukemaj lukemaj commented Sep 24, 2026 •

Copy link
Copy Markdown

Production Codex fleet slice for #1: one externally launched Codex dispatcher appears in T3, streams its work, and receives messages in its native session.

Problem: agents work across separate harnesses and machines with no shared surface. Users need one place to see an externally launched dispatcher, inspect its live work, and message it without moving orchestration into the UI or forking its session.

What changed since the helper-only scaffold (b33d069):

  • apps/server fleet/CodexNativeWs (new): production WebSocket client over the vendored app-server protocol framing. initialize with experimentalApi true, initialized notify, FIFO request/response matching, notification fan-out. Close only closes our socket.
  • apps/server fleet/FleetService (new): per-connection scoped service. Reads CodexSettings.nativeEndpoint per codex instance from ServerSettings, dials lazily, discovers via paged thread/loaded/list (bare string ids) plus per-thread thread/read (turns nested in thread.turns), attaches loaded sessions metadata-only (excludeTurns true, no settings), forwards item/turn/status notifications with per-item delta accumulation, tracks running turns, sends via steer with expectedTurnId (stale turn refused, no resend) or guarded idle turn/start. notLoaded is never attached, read, or messaged. Endpoint URLs never leave the server.
  • packages/contracts: fleet list/read/send/subscribe RPC methods, FleetError, history and stream-event schemas; auth scopes (read for list/read/subscribe, operate for send); client subscription tag registered.
  • apps/server ws.ts: fleet.* handlers wired into the authenticated WsRpcGroup with the FleetService layer.
  • packages/client-runtime: fleet RPC atoms per environment; runtime keeps truthful offline rows, single-agent upserts, endpoint notices, and upsert-in-place history/live merge.
  • apps/web: clickable Fleet section in the agents panel fed by every connected environment; row selection opens live transcript plus composer (active steer vs ownership-gated idle follow-up, uncertain/refused states surfaced). nativeEndpoint control renders through the existing schema-driven provider settings form.
  • apps/server fleet/FleetSessions: rewritten around recorded shapes (string-id pages with cursor, thread.turns nesting, explicit notLoaded refusal even with no loaded flag, delta accumulation without first-ID-wins loss, refused-before-send decisions).

Proof:

  • ./node_modules/.bin/vp test run apps/server/src/fleet/FleetSessions.test.ts packages/client-runtime/src/state/fleetRuntime.test.ts: 2 files, 60 tests pass.
  • New: CodexNativeWs.test.ts (6 tests, real protocol framing over in-memory sockets) and FleetService.test.ts (7 tests, real settings layers plus real WS transport against a recorded-shape peer): all pass. Full fleet set: 65 tests pass. contracts rpc.test, auth RpcAuthorization, serverSettings suites pass.
  • Scoped tsc clean: contracts, server, client-runtime, web. Scoped lint clean on changed files (ChatView warnings pre-existing).

Known limits:

Built with Muse Spark via OpenCode.

@lukemaj
lukemaj marked this pull request as draft September 24, 2026 16:35
…client

Dial CodexSettings.nativeEndpoint with the vendored app-server protocol
over a real WebSocket (initialize experimentalApi, FIFO JSON-RPC), discover
via paged thread/loaded/list plus per-thread thread/read, attach loaded
sessions metadata-only, steer active turns with expectedTurnId, and expose
everything through authenticated fleet.* RPCs with per-connection scoped
subscriptions. Disconnect never touches the native backend.

Muse Spark on OpenCode
…mposer

Aggregate per-environment native sessions under stable identity in the
agents panel. Rows open the live transcript with history merged over
streaming deltas; the composer steers active turns and gates idle
follow-ups on confirmed ownership. Offline environments keep truthful
rows; endpoint URLs never cross the wire.

Muse Spark on OpenCode
Cover string-id paged loaded lists, nested thread.turns history, explicit
notLoaded refusal, delta accumulation without first-ID-wins loss, stale
turn refusal, guarded idle follow-ups, uncertain delivery without resend,
and FleetService over the real socket framing against recorded settings.

Muse Spark on OpenCode
@lukemaj

lukemaj commented Sep 25, 2026

Copy link
Copy Markdown
Author

Superseded along with #1 by the T3-spawns-agents direction (#5, #10). Closing.

@lukemaj lukemaj closed this Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant