Codex OAuth native compact design contract
August 14, 2026 · View on GitHub
Status
This fork remains one npm package. Its Host entry owns the codex-oauth route,
OAuth lifecycle, authenticated transport, replay guard, and probe. Its
./compaction entry mounts inside the codex-native agent preset's isolated
compaction realm, where it replaces compaction-basic and owns /compact,
automatic step-pressure compaction, and context-overflow recovery.
Manual mode and automatic mode share the same provider-native transaction.
Manual success additionally flushes under Scheme A. Automatic pressure starts
at 80% of the routed model context window, retains at least 16% verbatim, and
allows one additional convergence attempt; provider-confirmed overflow forces
one balanced native reduction and one request retry. Non-codex-oauth routes
are ignored without a text-summary fallback.
Verified protocol
A real-account smoke established:
- legacy V1
responses/compactreturned HTTP 404 on the current ChatGPT backend; - current V2 succeeded through normal Codex Responses with one trailing
{ "type": "compaction_trigger" }item; - the returned opaque compaction item survived JSON encode/decode;
- a continuation recovered a nonce whose plaintext source item was not replayed.
V2 is therefore the production path for this fork. V1 may remain a tested, fail-closed compatibility path but is not an automatic fallback.
Image input contract
For a routed model whose catalog declares image input, the Host adapter reads
only DSH durable attachment references through the optional attachments
service and emits pi-ai image blocks. The Responses converter lowers these to
input_image items with canonical data:image/...;base64,... URLs and
detail: "auto". This covers user uploads, deferred read_image context, and
images nested in tool results. Attachment reads are deduplicated within one
request and receive its abort signal. Missing storage, unreadable bytes,
in-history system images, and models without image capability fail before
provider traffic.
The agent-scoped engine uses the same converter before manual, pressure, and
overflow compaction. Before persistence, every V2-retained input_image data URL
is externalized back to its verified durable attachment ref; inline image bytes
are forbidden in checkpoint JSON. Replay re-reads that ref and reconstructs the
exact provider data URL, while the opaque compaction item remains untouched.
Retention budgets charge client text while preserving images attached to
retained messages. Replay reduction and pressure use Codex's fixed model-visible
resized-image estimate rather than base64 wire length.
Only PNG, JPEG, WebP, and GIF bytes admitted by the DSH attachment service are
supported. The plugin does not fetch remote image URLs and does not use an OAuth
Files API or file_id. Base64 payloads are request/checkpoint data and must
never enter logs or diagnostics.
Package architecture
one npm package: dsh-llm-codex-auth-native-compact-image
├─ Host entry: provider, OAuth, transport, adapter, replay guard, probe
└─ Agent entry: isolated ctx.compaction, /compact, pressure/overflow listeners
DshCredentialStore
└─ owns OPENAI_CODEX_OAUTH persistence and serialized refresh
CodexOAuthTransport
├─ resolves auth through pi-ai Models
├─ derives ChatGPT account id internally
├─ attaches bearer/account headers
├─ restricts production traffic to chatgpt.com/backend-api
├─ sends normal model Responses requests
└─ sends native V2 compaction_trigger requests
CodexAdapter
├─ validates native checkpoint provider/model/account identity
├─ injects opaque items before generic pi-ai conversion
└─ handles normal DSH ↔ pi-ai message conversion
Native compaction module
├─ manual + automatic CompactionEngine and standalone /compact
├─ agent/pre-step pressure and agent/request-error overflow recovery
├─ native-aware opaque replay-token pressure correction
├─ global foreign-provider replay guard
└─ internal probe API retained only for transport regression tests
OAuth tokens, refresh tokens, raw account ids, authorization headers, and cookies MUST stay inside the OAuth store/transport. The compaction engine and checkpoint receive only provider output plus non-secret metadata.
Transport contract
interface CodexOAuthTransport {
describe(): {
provider: 'codex-oauth'
remoteCompaction: 'v2' | 'v1' | 'unsupported'
defaultModel?: string
}
compact(request: {
model: string
input: JsonValue[]
instructions?: string
signal: AbortSignal
}): Promise<{
protocol: 'responses.compaction-trigger.v2' | 'responses.compact.v1'
model: string
transportIdentity: string
items: JsonValue[]
usage?: JsonValue
}>
}
transportIdentity is a one-way compatibility fingerprint. It MUST contain no
raw account id, email, or credential material.
Production requests accept no configurable absolute URL. Explicit test
construction may inject a loopback HTTP base. Platform API endpoints and API-key,
environment-key, browser-cookie, local-summary, or compaction-basic fallbacks
are forbidden.
Durable checkpoint
interface OpenAiNativeCheckpointV1 {
kind: 'openai-codex-native-compaction'
version: 1
provider: 'codex-oauth'
model: string
transportIdentity: string
protocol: 'responses.compaction-trigger.v2' | 'responses.compact.v1'
items: JsonValue[]
}
The carrier is embedded in the compact replacement message source so it is available in normal adapter input without process-memory lookup. It must preserve complete JSON structure, ordering, and unknown fields across JSONL persistence, restart, fork, and export/import.
Replay
Before generic DSH-to-pi-ai conversion, CodexAdapter must:
- recognize and validate checkpoint kind/version;
- require provider, model, and transport-identity compatibility;
- replace the synthetic checkpoint carrier with native continuation items at the same logical position;
- never send marker text;
- fail before network with
NATIVE_COMPACT_REPLAY_INCOMPATIBLEfor every incompatible or unsupported checkpoint.
A global llm/stream guard must prevent another adapter from receiving native
checkpoint data.
Manual and automatic engine
Every path acquires the durable compaction lock, selects a tool-pairing-balanced
region, builds exact provider-native input, calls the shared transport with the
live abort signal, validates lossless-JSON continuation items, rejects a
checkpoint whose Codex-compatible model-visible estimate would not reduce the
selected replay region, and appends the normal lifecycle bracket plus adjacent
replacement. Retained user/developer/system messages use the ordinary
4-bytes/token JSON proxy. Compaction ciphertext mirrors codex-rs
estimate_reasoning_length: decoded base64 bytes minus fixed framing, then the
same 4-byte conversion. Raw wire JSON must not be priced at 2 chars/token because
that over-counts opaque ciphertext by roughly 2.7x and rejects valid reductions. Manual /compact reserves idle maintenance admission and flushes
before reporting success.
Automatic pressure runs from agent/pre-step inside the open turn. It resolves
the adapter-owned context window, applies the configured 80%/16% policy, and
uses a native-aware measurement that adds back opaque replay cost hidden from
the generic marker-text token meter. agent/request-error handles only the
standard context-window-exceeded code, performs one forced native reduction,
and retries only after surface generation advances. Foreign routes call no
transport and receive no text-summary fallback.
The agent entry fails startup if another ctx.compaction provider is registered
inside the same isolated realm. The shipped compaction-basic and
command-compact rows are therefore removed from codex-native; this is also
why a Host-global command alone cannot work—agent-scoped command definitions
shadow global definitions.
Persistence failure semantics — plugin-only Scheme A
This fork intentionally uses the existing DSH compaction seam without changing DSH core:
- transport failure writes no replacement;
- after a replacement is appended, a persistence flush failure reports the
stable
persistenceclass; - the current process surface may already contain the replacement;
- restart follows the actually persisted append-only log;
- the plugin performs no rollback because the public Session API has none.
This matches dsh-compaction-basic; strict staged atomic commit is outside this
plugin's contract.
Activation gates
Manual and automatic modes are accepted only while these invariants continue to pass:
- engine source/runtime receives no OAuth material;
- endpoint isolation rejects every Platform API target before I/O;
- refresh serialization, account header, cancellation, and error redaction match ordinary Codex requests;
- unknown/nested opaque fixtures survive compact → JSONL → restart → replay;
- transport failure leaves no replacement and every bracket/lock closes under the Scheme A persistence semantics above;
- provider/model/identity/version incompatibility fails before network;
- manual compact passes restart, fork, export/import, and repeated-compaction;
- logs, events, checkpoints, errors, and snapshots contain no secrets/raw id;
- failures never invoke Platform compact, text summary, or compaction-basic;
- an explicit real-account test performs compact and post-restart continuation;
- pressure compaction runs only inside an open turn and writes a native source;
- overflow retries only after a successful surface replacement;
- foreign providers perform no native transport call and never invoke a text-summary fallback;
- repeated native checkpoints are measured using opaque replay cost rather than marker text alone.