codex

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 1, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package codex implements agent.Adapter against OpenAI's `codex` CLI (the `codex exec` non-interactive subcommand). It mirrors agent/goose for the Launch/stream scaffold and agent/claude for the NativeSchema:true contract; the agent package itself stays import-free of harness specifics.

Capabilities().NativeSchema is TRUE: `codex exec --output-schema <FILE>` API-constrains the model's final response (OpenAI Responses structured output), so the agent_message text is pure conforming JSON. The adapter writes the step's output_schema to a container temp file (via the same sh -c command), passes --output-schema, and strict-json.Unmarshals the LAST agent_message text into a map; the engine re-validates it against output_schema (engine ValidateOutputMap). Layer 2 (free-text parsing) is never reached — codex is the first non-Claude NativeSchema:true adapter (conformance Bucket 14).

Gate independence is structural: every Launch runs a bare `codex exec` with --ephemeral and never a resume/fork subcommand; ValidateConfig rejects the corresponding with-keys.

Index

Constants

View Source
const AdapterRef = "openai/codex"

AdapterRef must match the workflow `uses:` literal byte-for-byte.

Variables

View Source
var DefaultEnvAllowlist = []string{"OPENAI_API_KEY", "CODEX_HOME"}

DefaultEnvAllowlist — env names the codex adapter forwards into each `codex exec`. Single source of truth for the CLI --agent-env default and resume's implicit allowlist. OPENAI_API_KEY overlaps goose's allowlist → defaultAgentEnv dedups (see cli/agent_registry.go). CODEX_HOME points codex at its auth.json/config dir (the ChatGPT-OAuth provisioning path). The adapter forces no env (--ephemeral handles session persistence).

Functions

This section is empty.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter is the agent.Adapter implementation for OpenAI codex. One Adapter per CLI invocation; multiple Launch calls per Adapter; all state read-only after construction (no session state crosses Launch boundaries).

func New

func New(opts ...Option) (*Adapter, error)

New constructs an Adapter.

func (*Adapter) Capabilities

func (*Adapter) Capabilities() agent.Caps

Capabilities returns Caps{NativeSchema: true} — codex's --output-schema constrains generation API-side; layer 2 is never reached.

func (*Adapter) Launch

func (a *Adapter) Launch(ctx context.Context, handle container.Handle, inv agent.AgentInvocation) (<-chan agent.AgentEvent, <-chan agent.AgentOutcome, error)

Launch runs `codex exec --json ...` inside handle via the streaming Backend.Exec. codex's --json emits JSONL flushed live; Launch scans it and emits ONE AgentEvent per line, records the LAST agent_message text (last-wins), captures the terminal usage + any error/turn.failed message, then sends exactly one AgentOutcome.

STREAMING GRANULARITY (accepted limitation): codex exec --json is EVENT-granular, not token-granular — each agent_message arrives as ONE complete item.completed line (no item.updated/text deltas). So events (tool calls, reasoning) render live, but the answer TEXT does NOT stream character-by-character like goose/claude. Token deltas exist only on codex's mcp-server/app-server JSON-RPC interface, which the stdin-less container.Cmd seam cannot drive. See the spec §1 streaming note.

γ contract: returns IMMEDIATELY with both channels open; events closes BEFORE outcome (defer LIFO); never reuses a session.

func (*Adapter) Ref

func (*Adapter) Ref() string

Ref returns the agent-runtime identifier this adapter satisfies.

func (*Adapter) RequiredEnv

func (*Adapter) RequiredEnv() []string

RequiredEnv implements agent.CredentialNamer. Returns the CREDENTIAL env var name codex authenticates with. OPENAI_API_KEY is defined in DefaultEnvAllowlist; CODEX_HOME is a config directory (not a credential) and is intentionally excluded.

func (*Adapter) ValidateConfig

func (a *Adapter) ValidateConfig(with ir.RawConfig) error

ValidateConfig enforces codex's with-schema (session-reject → unknown-key → required-prompt → per-key types+enums). Deterministic (sorted keys); runs twice per node (run-start walk + defensive dispatch) → idempotent. No provider-conditional auth gate: codex auth (ChatGPT-OAuth or OPENAI_API_KEY) cannot be statically probed — a missing credential surfaces as a loud turn.failed at Launch.

func (*Adapter) Version

func (a *Adapter) Version(ctx context.Context, handle container.Handle) (string, error)

Version runs `codex --version` inside handle and parses the leading semver. Recorded in run.started.Runtimes; re-resolved on resume; drift hard-errors.

type ErrRuntimeNotFound

type ErrRuntimeNotFound struct {
	Ref       string
	Container string
	Cause     error
}

ErrRuntimeNotFound — Version failed.

func (*ErrRuntimeNotFound) Error

func (e *ErrRuntimeNotFound) Error() string

func (*ErrRuntimeNotFound) Unwrap

func (e *ErrRuntimeNotFound) Unwrap() error

type ErrSessionReuseAttempted

type ErrSessionReuseAttempted struct{ Key string }

ErrSessionReuseAttempted — a with-key that would re-use a codex session, breaking gate independence (spec §5.5). Defense-in-depth: the adapter always runs bare `codex exec`, never a resume/fork subcommand.

func (*ErrSessionReuseAttempted) Error

func (e *ErrSessionReuseAttempted) Error() string

type ErrStreamParse

type ErrStreamParse struct {
	Line  []byte
	Cause error
}

ErrStreamParse backs the parse unit tests; Launch tolerates a stray non-JSON line.

func (*ErrStreamParse) Error

func (e *ErrStreamParse) Error() string

func (*ErrStreamParse) Unwrap

func (e *ErrStreamParse) Unwrap() error

type ErrUnexpectedExit

type ErrUnexpectedExit struct {
	ExitCode int
	Output   string
}

ErrUnexpectedExit is sent (bare) when codex exited with no usable result. Output is the captured stdout/diag tail. The engine default branch maps it to retryable_failure.

func (*ErrUnexpectedExit) Error

func (e *ErrUnexpectedExit) Error() string

type Option

type Option func(*Adapter)

Option configures the Adapter at construction time (functional-options).

func WithBackend

func WithBackend(b container.Backend) Option

WithBackend supplies the container.Backend used by Version and Launch.

func WithEnv

func WithEnv(env map[string]string) Option

WithEnv supplies the env-var allowlist forwarded into each `codex exec` exec environment. Copied into agent.SecretEnv (redacts under fmt verbs; json:"-" so secrets never reach the state log). Empty map permitted.

func WithPricing

func WithPricing(t pricing.Table) Option

WithPricing injects the pricing.Table used to derive a USD cost from token usage. Tests pass a self-contained fixture table; production leaves it unset so New defaults it to pricing.Default() (embedded rates ⊕ $AWF_PRICING_FILE).

Jump to

Keyboard shortcuts

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