codex

package
v1.167.0-beta.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package codex implements agentproxy.Facade for the codex CLI's app-server JSON-RPC protocol (github.com/openai/codex, codex-rs/app-server).

Package codex: raw event passthrough (v1.5) — the prefer-source_raw half of the translator strategy translate.go's doc comment reserved a seam for.

When the hosted session's agent runtime is codex itself (Facade.AgentKind), every canonical event the OHR adapter emitted carries the exact native app-server frame it was mapped from (HostedAgentEvent.SourceRaw — one JSON-RPC message as read off the codex app-server transport in the sandbox, requested via StreamSession's IncludeRaw). Forwarding that frame to the TUI beats reconstructing an approximation from canonical's ~15-event common denominator: canonical carries no file diffs, no command output, no reasoning deltas, no item metadata — the native frame carries all of it.

"Verbatim" has exactly one deliberate exception: identifier rewriting. The in-sandbox adapter drove its own thread/start and turn/start against the VM's app-server, so the raw params reference the VM's thread and turn ids — but this proxy's client was told the thread id is Facade.SessionID (thread/start's synthesized reply) and each turn's id is the harness run id (turn/start's synthesized reply). A frame forwarded with the VM's ids would describe a thread and turn the client has never heard of, so threadId/turnId (and turn.id) are rewritten to the proxy's ids. Native item ids are kept: the proxy never promises item ids in any reply, so the raw frames' own item lifecycle (started → deltas → completed, all sharing the native id) is self-consistent as-is.

The fallback is per event, as the v1.5 plan specifies: an event with no usable raw frame (adapter-synthesized events like a TurnError-mapped run.failed; a server that doesn't retain bytes; a non-codex session) takes translate.go's canonical reconstruction instead. The two paths keep their item-id families from colliding naturally: a turn whose run.started was forwarded raw never sets turnState.itemStarted, so finishTurn's synthesized agentMessage item/completed — the only canonical notification that could duplicate a raw item — stays suppressed for that turn.

This file also holds the inbound halves, which come in two shapes because the client sends two kinds of message.

Notifications and turns (v2): rawTurnStartFrame packages the TUI's turn/start params as SendInput's source_raw, so the in-sandbox adapter drives the turn from the client's actual params (input items, model, effort, approval policy) instead of a synthesized single-text turn.

Requests (M1): relayRequest forwards a client *request* — one that blocks waiting for an answer — to the agent and returns its reply. turn/start is deliberately not one of these: it already has a canonical meaning (SendInput) and a run to attribute events to, so relaying it around that would start a turn no one is tracking. Everything else this facade can't answer itself goes through, which is what makes turn/interrupt real and lets new codex methods work without a doctl release.

The direction is inverted but the id discipline is symmetric. Outbound rewrites VM ids to proxy ids. Inbound ships the proxy-side ids as-is and the adapter rewrites them to the VM's own — it is the only component that knows those. JSON-RPC request ids never cross a hop at all: each side mints its own and answers on the id it was given.

Package codex: --replay support, feeding a session's durable event history into the first thread this facade bootstraps.

Package codex: canonical-event-to-codex-notification translation.

This file is the "translator-strategy seam" the original implementation plan called for: the logic that decides what a canonical event means in codex terms lives here, not scattered inline in runEventLoop/drainStream's own dispatch loop (facade.go). As of v1.5 the seam carries two strategies: translateEvent first offers each event to tryRawPassthrough (raw.go), which forwards the event's native codex frame when one is available, and only reconstructs from canonical — everything below — when it isn't.

This is deliberately not a Go interface with multiple implementations: the raw strategy is one conditional at the top of translateEvent plus its own self-contained file, exactly the shape the v1 comment here reserved. The canonical reconstruction is not legacy — it is the permanent fallback (adapter-synthesized events carry no raw bytes; non-codex sessions never forward raw at all) and the only path that can ever serve cross-agent use.

Index

Constants

View Source
const TestedVersion = "0.142.5"

TestedVersion is the codex-cli version this facade's protocol handling was captured against (hosted-agents' docs/design/codex-app-server-protocol-capture.md: stdio send-message-v2 capture plus a live codex --remote / app-server pairing over WebSocket). Re-run that capture and update this pin on every codex upgrade — the WS/app-server transport is officially experimental and can change without notice.

Variables

This section is empty.

Functions

This section is empty.

Types

type Facade

type Facade struct {
	// SessionID is the hosted session this facade bridges to. thread/start's
	// synthesized thread id is exactly this value — simplest possible way to
	// satisfy "a synthesized thread whose id embeds the session id" while
	// matching what the real capture showed too (thread.id == thread.sessionId
	// there as well).
	SessionID string

	// Sessions is the harness bridge: turn/start calls SendInput on it, and
	// the background streaming goroutine reads StreamSession's SSE events to
	// translate into codex notifications. The bootstrap methods (initialize,
	// thread/start, etc.) don't touch it.
	Sessions do.HostedAgentsService

	// AgentKind is the hosted session's agent runtime, from GetSession at
	// proxy startup. Raw passthrough (v1.5) is gated on it: an event's
	// native SourceRaw bytes are only forwarded when the session's agent
	// speaks this facade's protocol (AGENT_KIND_CODEX_CLI) — cross-agent
	// sessions (e.g. codex TUI driving an OpenCode session) always take the
	// canonical-reconstruction path, where raw bytes would be the wrong
	// protocol entirely. Empty (older CLI paths, tests that don't care)
	// disables raw passthrough.
	AgentKind godo.HostedAgentKind

	// Replay, when true, feeds this session's full durable event history
	// into the first thread this facade bootstraps before that thread would
	// otherwise appear to start with no prior conversation — see
	// replaySessionHistory. Set once at construction from the --replay CLI
	// flag; never toggled per-connection.
	Replay bool
	// contains filtered or unexported fields
}

Facade implements agentproxy.Facade for codex --remote.

func (*Facade) AfterReply

func (f *Facade) AfterReply(ctx context.Context, method string)

AfterReply implements agentproxy.AfterReply: once handleConn has written a successful thread/start or thread/resume result, start the deferred replaySessionHistory goroutine if maybeReplay armed one.

func (*Facade) Dispatch

func (f *Facade) Dispatch(ctx context.Context, method string, params json.RawMessage) (any, error)

Dispatch implements agentproxy.Facade.

func (*Facade) SetNotifier

func (f *Facade) SetNotifier(n agentproxy.Notifier)

SetNotifier implements agentproxy.NotifierAware.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL