Skip to content

Fix codex_app_server provider against a real Codex app-server (busy-loop wedge, sandbox shape, auth flag) - #558

Open
scks1 wants to merge 1 commit into
algorithmicsuperintelligence:mainfrom
scks1:fix/codex-app-server-real-server-compat
Open

scks1 wants to merge 1 commit into
algorithmicsuperintelligence:mainfrom
scks1:fix/codex-app-server-real-server-compat

Conversation

@scks1

@scks1 scks1 commented Oct 29, 2026

Copy link
Copy Markdown

Summary

The codex_app_server provider fails against a real codex app-server in three independent ways. All three were found by running the provider against the real server (Codex 0.160.1, ChatGPT subscription auth) and each is verified against the server's own generated JSON schema or a live protocol session. The in-process fake server in the test suite models none of the three real-server behaviors, which is why the existing tests all pass while the provider is broken in production.

The three defects

1. request() wedges in a 100%-CPU busy loop on the first interleaved notification.
_AppServerSession.request() parked any non-matching message in self._pending, and next_message() drains _pending before reading the message queue. A real app-server emits notifications (e.g. configWarning, account/updated) before responses, so the first interleaved notification was returned by next_message() forever; the actual response was never read from the queue and the request deadline was never consulted (the _pending path has no deadline check). Fix: stash non-matching messages in a local list during the request and restore them to the front of _pending, in order, in a finally block when the response arrives.

2. thread/start sends the obsolete sandbox map form, rejected with -32600.
The provider sent "sandbox": {"mode": "read-only", "networkAccess": false}. In current app-server versions, ThreadStartParams.sandbox is the SandboxMode string enum ("read-only" | "workspace-write" | "danger-full-access") — confirmed in the generated JSON schema of both Codex 0.160.1 and 0.164.0-alpha.9. Fix: send "sandbox": "read-only". Note the existing test test_thread_is_non_interactive_and_read_only asserted the broken map shape; this PR corrects that assertion.

3. A valid ChatGPT login is misread as logged-out.
_ensure_authenticated() raised CodexAuthError whenever account/read returned requiresOpenaiAuth: true. Current servers return requiresOpenaiAuth: true together with a valid ChatGPT account — the flag describes the auth mode, not a missing login. Fix: only a missing account fails the boundary; the existing account-type check (type == "chatgpt") is unchanged.

Tests

The fake server gains two behaviors a real server has and it lacked:

  • notify_first scenario: pushes an unsolicited notification ahead of the account/read and thread/start responses.
  • chatgpt_requires_auth_flag scenario: account/read returns a valid ChatGPT account with requiresOpenaiAuth: True.

New/corrected tests cover all three defects. Each fails against the unfixed code: the auth-flag and sandbox tests fail immediately; the notification test runs generate() in a thread and fails on a join-timeout assertion, so the wedged code fails the test instead of hanging the suite.

Results (Python 3.12, unittest):

  • tests/test_codex_app_server_llm.py: 26 tests, OK.
  • Plus test_llm_ensemble, test_llm_config_optional_params, test_reasoning_effort_config, test_valid_configs: 49 tests total, OK.

Live re-verification (2026-10-29)

Against both installed servers (Codex 0.164.0-alpha.9 on PATH and 0.160.1), a patched-provider session now completes initialize → account/read (auth check passes) → thread/start (accepted, thread id issued) → turn/start, with server notifications flowing — i.e. all three fixed behaviors hold against the real protocol. The turn itself then errored server-side (responseStreamDisconnected: Connection refused) because this machine's Codex config routes the model provider through a local gateway (127.0.0.1:17321) that is not running in the test environment; that failure is downstream of, and unrelated to, the three fixes, and is identical for both server versions. End-to-end generation with these fixes was previously verified live on the same setup (exact-token smoke test, Codex 0.160.1).

Three defects that only appear against a real `codex app-server`
(the in-process fake server models none of them):

1. request() parked non-matching messages in _pending, which
   next_message() drains before reading the queue — so the first
   interleaved notification (a real server emits e.g. configWarning /
   account/updated before responses) was returned forever in a
   100%-CPU busy loop and the actual response was never read. Stash
   non-matching messages locally during the request and restore them
   to the front of _pending, in order, when the response arrives.

2. thread/start sent sandbox as a {"mode": ..., "networkAccess": ...}
   map. ThreadStartParams.sandbox is a SandboxMode string enum in
   current app-server versions (verified against the server's
   generated JSON schema for Codex 0.160.1 and 0.164.0-alpha.9); the
   map form is rejected with -32600. Send "read-only". The existing
   test asserted the broken map shape and is corrected.

3. _ensure_authenticated() treated requiresOpenaiAuth as a
   logged-out signal. Current servers return requiresOpenaiAuth=true
   together with a valid ChatGPT account — the flag describes the
   auth mode. Only a missing account fails the boundary now (the
   account type check below is unchanged).

Tests: the fake server gains a notify_first scenario (unsolicited
notifications ahead of account/read and thread/start responses) and a
chatgpt_requires_auth_flag account/read variant. New tests cover all
three defects; each fails against the unfixed code (the notification
test via a join-timeout assertion, so the wedged code fails instead
of hanging the suite).
@scks1

scks1 commented Oct 29, 2026

Copy link
Copy Markdown
Author

Adding the disclosure that should have been in the original submission:

Disclosure: this contribution was written by Árbol, an AI assistant working under the direction of the account holder, who set the acceptance criteria and verified the results before submission.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

1 similar comment
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants