Repository navigation
Conversation
…and the pinned schema Moved from sortie's sortied crate (crates/sortied/src/codexwire, and scripts/gen-codex-protocol): auth, client, protocol (generated from the Codex 0.158.0 app-server schema), rpc. Standalone: its own workspace, Apache-2.0 with a NOTICE for the schema, deny.toml, clippy.toml, an example, and gen-codex-protocol --check for the pin.
orig (the whole auth.json, tokens included) is private now, with orig_len(); Debug shows it as [redacted; N bytes]. Docs: unix only, the copy-back's race window, mkdir_private on an existing directory.
- A closed flag under the pending-map lock: a call after the server's output ended returns Closed at once instead of waiting forever. - A drop guard removes a cancelled call's pending entry; document tokio::time::timeout for timeouts. - Both readers read bytes: a line that isn't UTF-8 is Malformed (stdout) or kept lossily (stderr, StderrTail::read_from), and reading goes on. - ClientError::Encode for params that don't serialise. - Docs: unbounded line length and channel, panics outside a runtime, no proxy variables in ENV_ALLOW, the graceful stop. - Regression tests for each.
tests/corpus: the server's side of a codex 0.158.0 session (initialize, thread/start, a turn that fails without a login), scrubbed, decoded with the generated types. tests/spawn.rs runs spawn_app_server against tests/fake_codex: args, cwd, the env allowlist, both readers past a non-UTF-8 line, kill on drop.
… --check Also: unix only, Malformed and Closed, timeouts.
fmt, clippy, tests and doctests, MSRV, docs, cargo-deny, and scripts/check-codegen, each gated off while the repo is private.
… its URLs; OpenAI is a valid doc ident The generated docs had [AbsolutePathBufGuard::new] (a broken intra-doc link), [UNSTABLE] and a bare URL; the README, now the crate doc, has OpenAI in its prose (clippy::doc_markdown).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The codexwire crate, moved out of sortie's
sortied(talaagent/sortie#4,crates/sortied/src/codexwireandscripts/gen-codex-protocol; originally macalinao/tala-agent#744) into its own repo: a Rust client that drivescodex app-serverover JSON-RPC, the Codex counterpart to ccwire.protocol: serde types generated from the app-server JSON Schema of Codex 0.158.0 (schema/VERSION,CODEX_VERSION)rpc: line framingclient:spawn_app_server(allowlisted env),Client(id matching, ordered notifications and server requests), stderrredactauth: a session's privateauth.json, copied back only when it's safescripts/gen-codex-protocolregenerates offline.--refresh [CODEX]re-dumps the schema and moves the pin.--check [CODEX]fails if a binary isn't the pinned version.scripts/check-codegencatches drift.[workspace], edition 2024, MSRV 1.85 (as in ccwire). Apache-2.0 only, LICENSE plus a NOTICE that credits OpenAI Codex (Apache-2.0) for the schema.deny.toml, and aclippy.tomllike ccwire's. No tala dependency or strings. Example inexamples/initialize.rs.Changes from the sortied copy:
crate::imports and a crate root;impl Error for ClientError; neutral test fixtures (no user paths); the auth temp-file prefix iscodexwire-; tests allowblock_on, which#[tokio::test]expands to.Why we don't use an upstream crate
openai/codex doesn't publish its app-server protocol types, so we keep the generator.
codex-app-server-protocolandcodex-protocolare owned bynamastex888, a third party. They come from a fork (namastexlabs/codex) and stop at 0.63.0 (2025-12-11), about 95 releases behind 0.158.0. They aren't OpenAI's.codex-codes(meawoppl/rust-code-agent-sdks, Apache-2.0) is a separate, hand-written community SDK. It's a peer, not a source of upstream types.codex-rs/app-server-protocolwould be Apache-2.0, pinnable by therust-v0.158.0tag, and serde-ready, but too heavy:codex-protocol,codex-rollout,codex-secrets,codex-shell-command,codex-history, macros…codex-protocolalone brings tokio, ICU, gix-url, quick-xml, schemars, ts-rs, http, a network proxy and an HTTP client, plus landlock and seccompiler on Linux.rmcp =3.2.0(an exact pin) and zstd.Generating from the schema that
codex app-server generate-json-schemadumps is the interface Codex supports for outside clients. It costs serde, serde_json and tokio.Review fixes (074d368..08d0fed)
Must-fix:
Copied's Debug no longer prints the tokens.origis private (orig_len()instead), and a hand-writtenDebugshows it as[redacted; N bytes]. Test:debug_redacts_the_tokens.closedflag lives under the pending-map lock. The reader sets it on exit, andcallreturnsClientError::Closedat once when it is set. Test:a_call_after_the_server_output_ended_fails_at_once(stdout closed, stdin still open).read_until(b'\n')and a line that isn't UTF-8 becomesServerMessage::Malformed, then reading goes on. It stops only on EOF or an I/O error. Stderr gets the same fix through a new publicStderrTail::read_from(reader), which keeps lines lossily (U+FFFD).spawn_app_serveruses it, and a caller can use it for children it spawns itself. Tests:a_line_that_is_not_utf8_is_malformed_and_reading_goes_on,stderr_lines_that_are_not_utf8_are_kept_lossily, and the fake-codex spawn test..github/workflows/ci.ymlis ported from ccwire with the same private gate. It runs fmt, clippy-D warnings, tests and doctests (--locked), MSRV (fromrust-version), docs (-D warnings) and cargo-deny, plus a newcheck-codegenjob (python3 + rustfmt, offline). There is one clippy and one test job because the crate has no features.deny.tomlis now ccwire's (unmaintained = "all", crates.io only, no git), with this crate's extra allowed dependency licenses kept. The crate itself stays Apache-2.0 only.Should-fix:
callcleans up. A drop guard removes its pending entry, so a timeout orselect!leaks nothing, and a late answer is ignored. There is no timeout API: thecalldocs and the README say to wrap calls intokio::time::timeout. Test:a_cancelled_call_forgets_its_request.tests/corpus.rs. It decodestests/corpus/codex-0.158.0-turn-unauthenticated.jsonlwith the generated types. That file is the server's side of a real codex 0.158.0 session (initialize, thread/start, then a turn that fails without a login:errornotifications, items,turn/completed). Paths, host name and ids are scrubbed. Every known item must decode as something other thanUnknown. The test also covers theUnknownfallback, including a known tag with a broken body.tests/spawn.rs. It runsspawn_app_serveragainsttests/fake_codex, a python3 stand-in. It covers the args, the cwd, the env allowlist (env_clear), a typedinitialize, both readers past a non-UTF-8 line, and kill on drop.Nits taken:
no_rundoctest.--checkis documented as a binary-version check, not a codegen check.Client::newdocuments that it panics outside a runtime and that line length and the message channel are unbounded.ClientError::Encodefor params that fail to serialise.ENV_ALLOW's missing proxy variables, the graceful stop (shutdown, thenchild.wait()under a timeout),copy_back's race window, andmkdir_privateon an existing directory. The README notes the crate is Unix only.Unknowndoc say that a known tag whose body doesn't decode also lands inUnknown, soprotocol.rswas regenerated.Not taken:
AppServer::close()(nit 14): it needs a timer in the library, so it is documented instead.Gate
tala-build-lock): fmt, the tests (13+2+1), the doctests andcheck-codegenpassed. Clippy-D warningsandRUSTDOCFLAGS="-D warnings" cargo doc --no-depseach failed with one error in the lib.[AbsolutePathBufGuard::new], a broken intra-doc link;[UNSTABLE];[]) and wraps its bare URL in<...>, andsrc/protocol.rsis regenerated.doc_markdownobjected to "OpenAI" in the README, which is now the crate doc.clippy.tomladds it todoc-valid-idents.scripts/check-codegenpasses. Build, clippy, doc and tests were not run here:tala-build-lockexited 75 (all slots busy) every time, so this head is handed to the gate queue.GPG signing needs a passphrase in this headless run, so these commits are unsigned, like the branch's earlier ones.
Later follow-ups (not in this PR)
codex execcall (crates/tala-agent/src/image_gen.rs) moves onto codexwire's app-server client.auth.jsonrefresh at a time) moves into codexwire (auth), so every consumer shares it..github/workflows/ci.yml). It is gated off while the repo is private and turns on when the repo goes public.