# @excitedjs/agent-runtime-codex

The built-in **Codex** Dreamux plugin, always loaded by
[Dreamux](https://github.com/excitedjs/dreamux). Its default export is the neutral provider
factory for `npm:@excitedjs/agent-runtime-codex`. `createCodexPlugin()` is the
named plugin factory: Dreamux always loads it to contribute `builtin:codex`.
Named bare-provider constructors retain their own options.

The provider it contributes implements the public `AgentRuntimeProvider`
contract from
[`@excitedjs/dreamux-types`](../../dreamux-types) against the Codex
`app-server`: process supervision, the WebSocket RPC client, the `initialize`
handshake, thread start/resume, the per-runtime turn manager, teammate
completion delivery, bounded native transcript pagination, and Codex doctor
diagnostics.

## Boundary

This package depends only on the neutral `@excitedjs/dreamux-types` contracts
and shared `@excitedjs/dreamux-utils`; it never imports `@excitedjs/dreamux`
core. Everything host-specific — per-dispatcher paths, the volatile
rendezvous-socket root, the durable state sink, the process `PATH` seeded from
the host package bins, and bundled-skill installation — is supplied by the
Dreamux host through the neutral `AgentRuntimeCreateContext` and provider
factory options. The package owns only Codex-engine mechanics and its own
`~/.codex` home/config paths.

The host resolves `builtin:codex` to this package and wraps it with a
core-owned adapter that maps its private dispatcher objects onto the neutral
contract; see
`.agents/tasks/architecture/npm-package-split/requirement.md (npm-package-split-and-channel-targets)`.

## Logger

The package logs through the required `DreamuxLogger` in the neutral runtime
create context. The provider binds that logger, skill sources, and extra CLI
arguments when it constructs the runtime. Each successful thread start/resume
constructs a TurnManager bound to that thread id; socket allocation remains
per process start. Optional process/client factories remain available for
embedders.

## Ultrathink

Include `ultrathink` as a whole word in a submission to request the current
model's highest supported reasoning effort. Matching is case-insensitive and
includes quoted text in that submission; a word it is only part of, such as
`ultrathinking`, does not match. The submission text is passed through
unchanged, and the turn carries one added text item holding the same sentence
Claude Code injects for this keyword. It does not scan history or tools.

The next ordinary submission explicitly restores the original effort. Busy
submissions use the same rule without waiting for completion; Codex owns input
merging and when the setting takes effect. This does not guarantee immediate
escalation or keep a merged native turn elevated after ordinary input.

On cold resume, ordinary effort comes from the effective Codex configuration,
or the resumed model's default when unset. A temporary effort saved by Codex
does not become the ordinary baseline. No global config or other thread is
modified. The feature uses stock `turn/start` parameters without a proxy.

## Standalone use

External callers can construct the bare provider directly, without going
through the plugin:

```ts
import { createCodexAgentRuntimeProvider } from '@excitedjs/agent-runtime-codex';
```

The provider accepts `restartBackoffBaseMs` and `restartBackoffMaxMs` options.
It constructs the native process and WebSocket client directly. Each runtime
start allocates a fresh socket from the neutral path capability; restart never
reuses a construction-time socket allocation.

## Portable Structured Output

The neutral `AgentRuntimeTextInput.outputSchema` contract accepts ordinary
optional object properties. Codex strict structured output requires every
declared property to appear in `required`, so this package privately compiles a
narrow portable subset before `turn/start`:

- one closed root object (`additionalProperties: false`);
- nested closed objects and single-schema arrays;
- `string`, `number`, `integer`, `boolean`, `null`, and nullable
  `[T, "null"]`;
- `description`, primitive-value `enum`, and numeric `minimum` / `maximum`.

Every wire property is required. An originally optional non-nullable property is
made nullable for Codex, then a `null` placeholder is removed from the completed
JSON before Dreamux observes the result. Required nullable values remain
present as `null`.

Open objects, optional fields that already accept `null`, tuples, non-null
unions, composition/reference keywords, unknown keywords, and other unsupported
constraints fail before `turn/start` with
`UnsupportedAgentRuntimeFeatureError(feature = "outputSchema")`. The adapter
does not drop constraints or fall back to unconstrained text.

Concurrent submissions may fold into one active Codex turn only when both are
structured with the same compiled wire schema and restoration plan, or both are
unstructured. Structured/unstructured mixing and incompatible schemas fail
before another `turn/start`.

The resident turn collector keeps its notification subscription until disposal,
connection failure or runtime stop. It retains native items until their terminal
has been converted, including items for turns with no host submission, and then
releases them. Each observed terminal selects its result synchronously, without
waiting for input association. The result remains available until the native
admissions in flight at observation have retired, so a positive acknowledgement
can still bind the same result after a later connection failure or stop.

The public runtime boundary returns one `RuntimeSubmission` handle per accepted
send; submissions folded into the active native turn settle with the same
immutable `RuntimeCompletion`, and queued submissions settle with distinct
completions in native order. Every normally completed or observed-failed native
terminal also publishes once through `context.results`, including unbound turns.
The sink and all bound settlements receive the same frozen object. The existing
terminal callback order determines publication; codec restoration and assistant
extraction apply equally to bound and unbound terminals. Scoped fatal errors and
codec failures produce failed results. Interrupted terminals keep bound partial-output
settlements but publish no new result. Connection-level protocol failure and
teardown do not invent native results. Codex
`turnId` values remain private correlation keys in this package; Dreamux core
observes only the object's terminal outcome. Unscoped protocol failure fails
accepted inputs without an observed answer; stop settles those inputs as stopped. An already
selected result remains the answer for late positive admissions. A negative or
ambiguous acknowledgement returns no submission and creates no requested reply.
Runtime stop converges accepted inputs after the supervised process group is
proven absent.

## Native transcripts

Codex `thread/start` and `thread/resume` return the native `thread.path`. This
package validates and canonicalizes that rollout path under Codex's
`sessions`/`archived_sessions` roots, verifies its session metadata, and
persists it with the runtime checkpoint before admission can be reported.
Cold reads can rediscover active, archived, `.jsonl`, or `.jsonl.zst`
representations and follow native `history_base` lineage without starting a
runtime.

`readTranscript` projects completed native turns into provider-neutral
message/tool blocks. It owns opaque append-stable cursors, rewrite and query
mismatch detection, bounded scanning, payload redaction/truncation, and the
fixed host output budget. If a compressed or lineage transcript cannot be read
within the native scan bound, it fails with `scan_unsupported` rather than
performing an unbounded scan. Native Turn/rollout IDs and filesystem paths never
appear in transcript pages.

All accepted native `turn/start` aliases folded into that object remain in its
canonical active slot until their responses and native terminal output have
converged. A source is reserved while admission is in flight, committed after
acceptance or an ambiguous request failure, and released only after a proven
pre-request failure. Concurrent uses of one reserved source share one admission
outcome. `failed` is therefore safe to retry; `ambiguous` may have crossed the
app-server boundary and must not be retried automatically. Runtime stop publishes
its fence and starts client/process teardown before joining startup or restart,
then drains all input admissions before resolving.

See
[Provider Runtime](../../../.agents/domains/provider-runtime.md#codex-portable-output-schema)
for the complete current lifecycle and failure contract.


The result observer is optional for old-host compatibility: native per-input
values still resolve when `context.results` is absent. When present, this provider
must publish each normal/failed terminal in finalization order with the same C
returned to every answered input, including late admissions against an already
finalized native record. Current Core always supplies it. Old provider/new Core
keeps bound answers and requested replies, without certification of background
report coverage or ordering; loading successfully is not conformity. There is no
capability negotiation or fallback queue.
