Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ Bun-native TypeScript with no separate server compile step.
- `tests/` — Bun tests in domain directories that mirror `src/`
(`tests/<domain>/*.test.ts`; `providers/` and `adapters/` have one more
level for the larger vendors). The explicit map is
`scripts/test-layout/layout.json`, with regex seeds and migration state in
`scripts/test-layout/layout.json` plus its `explicitShards` sibling maps, with regex seeds and migration state in
`scripts/test-layout/seeds.json`; `tests/test-layout.test.ts` enforces that every file resolves to a
domain and sits in it, and only the two layout guards live at the root.
Shared helpers in `tests/helpers/`, fixtures in `tests/fixtures/`, broader
scenarios in `tests/e2e-style/`. Source-oracle tests resolve the repository
through `tests/helpers/repo-root.ts` (`repoRoot()`, `repoPath()`,
`helperPath()`, `fixturePath()`), never `import.meta.dir + "/.."`. A new
test file lands in its domain directory and needs an entry in both
`layout.json` `explicit` and `tests/fixtures/test-layout-expected.json`
`layout.json` `explicit` (or its domain shard) and a `tests/fixtures/test-layout-expected*.json` shard
(`tests/test-layout-tooling.test.ts` names the missing one); the regex
seeds in `seeds.json` place a conventionally named file until then.
History: `devlog/_fin/260905_test_modularization_and_windows/`.
Expand Down Expand Up @@ -268,7 +268,7 @@ fails `file-size ratchet: repository` for your branch and for every branch cut f
Two branches can each stay under a cap alone and sum over it together; that is what
happened in #4908, #5011 and #5018. The remedy is always a move, never a number: put the
new case in a sibling file, byte for byte, and register it in **both**
`scripts/test-layout/layout.json` and `tests/fixtures/test-layout-expected.json`.
`scripts/test-layout/layout.json` (or its domain shard) and a `tests/fixtures/test-layout-expected*.json` shard.
`d3ca5522db` is the original precedent.

A moved test is not automatically the same test. One case moved out of
Expand Down
129 changes: 128 additions & 1 deletion docs-site/src/content/docs/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,133 @@ removes the private overlay files and leaves native Codex intact. Windows keeps
script wrappers; uninstall restores the saved launcher. See the
[CLI lifecycle reference](/reference/cli/lifecycle/#ocx-codex-shim-installstatusuninstallremove).

## Experimental Windows desktop compatibility

**Codex Set → Desktop compatibility** provides local controls for a bounded compatibility
trial while retaining the native Codex login. This is an experimental relay, not a guarantee
that every Codex build or exhausted-account state can recover its composer.

1. Inspect status, prepare the encrypted certificate and review its fingerprint before
registering trust. Windows may ask for confirmation. Trust applies to the current Windows
user and allows the local relay to handle `chatgpt.com` traffic.
2. Start observation. Save drafts, close Codex, then use **Open Codex** in this panel to launch
the packaged app with the managed connection. The panel never forcibly closes an existing app.
3. Only after eligible exhaustion is observed, **Run 3-minute trial** offers a separate account-wide
consent. It adjusts two UI flags across the signed-in account, not just the selected model.
Actual usage, credits, spending restrictions and server limits remain unchanged. A produced
response alone does not establish that the composer recovered.

An original response showing available usage or a protected state ends the trial immediately.
Available credits or active Luna Reserve also leave the response unchanged and end the trial,
even when ordinary usage is exhausted. This preserves the app's existing entitlement state.
If eligible exhaustion appears again, another explicit trial is required; the earlier consent
does not silently reactivate correction.

**Return to observation** disarms correction. The three-minute limit bounds response correction,
not the time until Codex refreshes its display. Expiry and returning to observation request a
fresh usage response; the app may retain its previous display until that response arrives.
The panel shows this limitation before trial consent and while awaiting the original response;
it cannot confirm the app's cache refresh. **Stop service** closes its connections and leaves
the certificate for reuse; active connections may be interrupted. For renewal or trust removal,
stop the service and close Codex first. Renewal prepares a new untrusted certificate; review the
new fingerprint before registering it. An uncertain action is not automatically retried.
Certificates are restricted to TLS server authentication. If status shows `renewal-required`,
stop the service and close Codex, then renew the older certificate before starting again.
The native API URL must match the proxy's actual listener address and port. IPv4 and IPv6
loopback addresses are not interchangeable here; ambiguous `localhost` aliases are refused.
Codex's automatic MCP connection refresh and configuration formatting do not invalidate
observation. Model, authentication, profile and routing changes still require a fresh
observation context; the service does not silently adopt those changes during a trial.

The service preserves its PAC address and local connection ports for reuse after a restart.
With the same trusted certificate, an already configured app can reconnect through its cached
PAC; restarting the service never resumes a correction trial. If a saved port cannot be bound
or connection metadata is invalid, startup refuses rather than silently assigning another
address. The first successful start owns `codex-desktop-compatibility/connection.json` under
the OpenCodex home. Do not delete that file as a routine restart fix: a different address
requires launching the app with a fresh managed connection.

Current support is limited to the assessed Windows build `26.924.2738.0`, native file-based
login. HTTP/HTTPS proxies and authenticated SOCKS5 proxies are supported through the shared
outbound policy; NO_PROXY can explicitly select a direct route. Failed proxy connections do not
fall back to direct egress. OpenCodex managed client mode is not yet supported by these controls.
For this desktop relay, HTTP(S) `ALL_PROXY` also applies when `HTTPS_PROXY` is unset. An invalid
`HTTPS_PROXY` refuses the operation instead of falling back to `ALL_PROXY`.
Unknown app builds refuse correction; the integration does not patch application files or
switch to login-free mode.
The native root config and its selected profile must route `openai_base_url` to this process's
actual local data listener. A different provider, destination or unsupported override refuses
observation startup. This check does not determine a conversation's selected model or prove
that project-local overrides are absent. If routing or the installed app build changes during
a trial, correction is refused before the next usage response; periodic checks also return
an idle trial to observation. Original responses and other app traffic continue to relay.
Native login-file replacement or token rotation also invalidates the trial, even when the
same account returns. Stop and start observation to bind the current login before another
explicit trial; old responses cannot authorize the replacement session.
Changes to the root Codex config (except its MCP server table and formatting), provider configuration, model aliases, routing profiles,
fallback, compaction or memory-model routes also invalidate the observation context. Restoring the previous
settings does not restore its consent: stop and start observation, then confirm a new trial
when eligible. This detects changes to those configured routes, not which model a conversation
actually selects; an unchanged mixed-provider configuration is not proof of provider isolation.

After certificate preparation and a successful manual start, enable **Resume observation when
OpenCodex starts** in the same panel. The optional OpenCodex configuration
`"desktopCompatibility": { "startOnProxyStart": true }` resumes **observation only** when the model
proxy starts. Omission or `false` disables this automatic start. It reuses the saved endpoints
and trusted certificate, never launches Codex or enrolls trust, and never resumes an Apply trial.
Automatic observation waits for startup configuration sync to finish. Failed sync or a wait
longer than two minutes leaves observation off; inspect its status and start it manually after
resolving the startup problem. The model proxy continues to follow its own readiness policy.
If prerequisites are missing, observation stays off and the model proxy continues running.
Saving this preference does not start or stop the current service. Use its separate service
controls for immediate changes. If a save cannot be confirmed, refresh its status before retrying.

A running service does not establish that Codex is connected through it. A normal app launch or
an app updater can omit the managed connection argument. Save drafts, close Codex, then use
**Open Codex** in this panel to restore that connection. This control never closes the app for you.
After a Codex update, an unassessed app version refuses correction until its compatibility is
reviewed; reinstalling the certificate does not make an unassessed build supported.

On Windows, an explicit OpenCodex full-app restart preserves an already active loopback
compatibility PAC argument only when the current OpenCodex process owns the serving compatibility
runtime. A stale or foreign endpoint is refused before stopping Codex; replacement of the runtime
during restart also prevents managed relaunch. The app launches through Windows package activation. It checks the
package identity and routing argument after launch; unreadable or conflicting main-app routing arguments cause
a refusal before the restart. This does not enable a compatibility mode, install a certificate,
or watch and restart the app automatically. Normal launches without that routing argument keep
their existing behavior.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

### Transport coverage and recovery evidence

The compatibility panel reports identity-checked JSON/SSE usage responses and currently
bound streams separately from open connections. These are lifetime relay observations,
including requests made by diagnostic clients. They do not identify the sending native
process, prove that the app updated its authoritative cache, or prove composer recovery.
No request body, token, account ID or source IP is added to this diagnostic status.

[Issue #6196](https://github.com/lidge-jun/opencodex/issues/6196) reports a macOS build whose
authoritative gate requests originate in the bundled Rust app-server and bypass Chromium
PAC settings. A healthy PAC, certificate or synthetic request cannot establish coverage
of that transport. This Windows experiment is not a fix for that macOS design blocker.

Before adding another platform or transport, document and validate this sequence:

1. Identify the actual process and transport that sends each authoritative gate request.
2. Prove that an app-origin request reaches the intended relay, separately from test clients.
3. Verify the response schema and the app's cache/update path for the exact installed build.
4. On natural account exhaustion, verify original-composer submission, independent-provider
completion, and preservation of sign-in, Chat, existing threads and remote connections.
5. Verify shutdown, ordinary launch, restart and update behavior; do not infer one from another.

The present policy handles only `/backend-api/wham/usage` and its `/stream` endpoint.
Conversation initialization and other endpoints, including their `blocked_features` and
`limits_progress`, pass unchanged. Their presence is not permission to clear them: they may
represent unrelated restrictions. The Windows build's renderer-to-Electron fetch path does
not establish the network path of a different OS/build or every app-server RPC. App-server
routing requires its own reviewed design; changing model-provider URLs alone is not proof
that account, login or remote-control traffic follows the same route. No automatic app-server
wrapper, global proxy change or login rewrite is installed by these controls.

## Routed models during Codex reserve mode

Codex Pool can optionally protect stored pool accounts at a selected 5-hour or weekly usage
Expand All @@ -1019,7 +1146,7 @@ When the ChatGPT 5-hour quota is exhausted, Codex may offer a reserve fallback m
**every other entry unselectable — including opencodex routed models**, even though those
run on independent providers and credentials and consume none of the exhausted quota.

**This is a Codex client behavior and the proxy cannot change it.** The reserve state
**This is a Codex client behavior that ordinary model-proxy routing cannot change.** The reserve state
arrives from the ChatGPT backend on the client's own authenticated connection, not through
the proxy. The desktop app polls `backend-api/wham/usage` and treats reserve as active when
the response carries `rate_limit_upsell.banner_type = "luna_reserve"`, the primary
Expand Down
Loading
Loading