Skip to content

Commit 8d7c111

Browse files
committed
Add Codex CLI issue 14860 fix package
0 parents  commit 8d7c111

8 files changed

Lines changed: 324 additions & 0 deletions

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.DS_Store
2+
*.o
3+
*.so
4+
*.dylib
5+
*.dll
6+
*.exe
7+
codex
8+
codex.bak-*
9+
target/
10+
.cargo-target/
11+
.cargo-home/
12+
.rustup-home/
13+
source/
14+
vendor/
15+
*.log
16+

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Codex CLI 0.131.0 issue #14860 fix package
2+
3+
This repository contains a small, source-based patch package for Codex CLI
4+
0.131.0. It does not ship or replace Codex with any third-party binary.
5+
6+
The patch follows the Nopiskl issue #14860 approach:
7+
8+
- set `reqwest::ClientBuilder::tcp_user_timeout` to 120 seconds in the default
9+
Codex HTTP client
10+
- keep the installed CLI version at `codex-cli 0.131.0`
11+
- provide a CentOS 7 compatibility shim for the final link step when older
12+
system headers/libc do not expose symbols needed by transitive native code
13+
14+
## Contents
15+
16+
- `patches/codex-cli-0.131.0-issue14860-tcp-user-timeout.patch`
17+
- The source patch for `codex-rs/login/src/auth/default_client.rs`.
18+
- `src/centos7_compat.c`
19+
- Link-time compatibility symbols used on CentOS 7: `memfd_create`,
20+
`le16toh`, and `be16toh`.
21+
- `scripts/build_codex_0_131_0_with_issue14860_fix.sh`
22+
- Applies the patch if needed and builds `codex-cli` from an official
23+
`rust-v0.131.0` source checkout.
24+
- `scripts/install_patched_codex.sh`
25+
- Backs up the currently installed Codex vendor binary and installs the
26+
locally built replacement.
27+
- `docs/centos7-build-notes.md`
28+
- Notes from the CentOS 7 build and install flow.
29+
30+
## Prerequisites
31+
32+
Use an official Codex `rust-v0.131.0` source checkout. This package assumes the
33+
checkout layout contains `codex-rs/`.
34+
35+
On CentOS 7, install the system build dependencies:
36+
37+
```bash
38+
yum install -y openssl-devel perl-IPC-Cmd cmake
39+
```
40+
41+
Use a local Rust/Cargo installation for the source tree instead of modifying
42+
global shell configuration. The tested build used Rust 1.93.0 with:
43+
44+
```bash
45+
RUSTUP_HOME=/path/to/codex-rust-v0.131.0-src/.rustup-home
46+
CARGO_HOME=/path/to/codex-rust-v0.131.0-src/.cargo-home
47+
```
48+
49+
## Build
50+
51+
From this repository:
52+
53+
```bash
54+
SOURCE_ROOT=/path/to/codex-rust-v0.131.0-src \
55+
RUSTUP_HOME=/path/to/codex-rust-v0.131.0-src/.rustup-home \
56+
CARGO_HOME=/path/to/codex-rust-v0.131.0-src/.cargo-home \
57+
CARGO_TARGET_DIR=/path/to/codex-rust-v0.131.0-src/.cargo-target \
58+
scripts/build_codex_0_131_0_with_issue14860_fix.sh
59+
```
60+
61+
Expected verification:
62+
63+
```bash
64+
/path/to/codex-rust-v0.131.0-src/.cargo-target/release/codex --version
65+
# codex-cli 0.131.0
66+
```
67+
68+
## Install
69+
70+
The install script must run as a user that can write the installed Codex vendor
71+
binary path.
72+
73+
```bash
74+
SOURCE_ROOT=/path/to/codex-rust-v0.131.0-src \
75+
INSTALL_PATH=/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex/codex \
76+
scripts/install_patched_codex.sh
77+
```
78+
79+
The script creates a timestamped backup beside the original binary before
80+
installing the patched binary with mode `755`.
81+
82+
## Verified local result
83+
84+
The local patched binary verified as:
85+
86+
```text
87+
codex-cli 0.131.0
88+
```
89+
90+
`codex app-server --help` also returned successfully.

docs/centos7-build-notes.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# CentOS 7 build notes
2+
3+
## Goal
4+
5+
Build Codex CLI 0.131.0 from official `rust-v0.131.0` source with only the
6+
issue #14860 timeout patch, then install the resulting binary over the local
7+
Codex vendor binary after creating a backup.
8+
9+
## System dependencies
10+
11+
The successful CentOS 7 build required:
12+
13+
```bash
14+
yum install -y openssl-devel perl-IPC-Cmd cmake
15+
```
16+
17+
The temporary vendored OpenSSL Cargo changes were not needed and should be
18+
removed before the final build.
19+
20+
## Source patch
21+
22+
`codex-rs/login/src/auth/default_client.rs` was changed to:
23+
24+
- import `std::time::Duration`
25+
- define `DEFAULT_TCP_USER_TIMEOUT` as 120 seconds
26+
- call `builder.tcp_user_timeout(DEFAULT_TCP_USER_TIMEOUT)` in
27+
`try_build_reqwest_client()`
28+
29+
## Link compatibility
30+
31+
On the local CentOS 7 system the final `codex-cli` link failed with missing
32+
symbols:
33+
34+
- `le16toh`
35+
- `be16toh`
36+
- `memfd_create`
37+
38+
These came from transitive native code (`tree-sitter` and V8) and old system
39+
headers/libc. The build script compiles `src/centos7_compat.c` and passes the
40+
resulting object as a final `rustc` link argument.
41+
42+
## Local verification
43+
44+
The patched local install was verified with:
45+
46+
```bash
47+
codex --version
48+
codex app-server --help
49+
```
50+
51+
Expected version output:
52+
53+
```text
54+
codex-cli 0.131.0
55+
```
56+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
diff --git a/codex-rs/login/src/auth/default_client.rs b/codex-rs/login/src/auth/default_client.rs
2+
index ee51edf..23450c1 100644
3+
--- a/codex-rs/login/src/auth/default_client.rs
4+
+++ b/codex-rs/login/src/auth/default_client.rs
5+
@@ -16,6 +16,7 @@ use reqwest::header::USER_AGENT;
6+
use std::sync::LazyLock;
7+
use std::sync::Mutex;
8+
use std::sync::RwLock;
9+
+use std::time::Duration;
10+
11+
/// Set this to add a suffix to the User-Agent string.
12+
///
13+
@@ -36,6 +37,7 @@ pub static USER_AGENT_SUFFIX: LazyLock<Mutex<Option<String>>> = LazyLock::new(||
14+
pub const DEFAULT_ORIGINATOR: &str = "codex_cli_rs";
15+
pub const CODEX_INTERNAL_ORIGINATOR_OVERRIDE_ENV_VAR: &str = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
16+
pub const RESIDENCY_HEADER_NAME: &str = "x-openai-internal-codex-residency";
17+
+const DEFAULT_TCP_USER_TIMEOUT: Duration = Duration::from_secs(120);
18+
19+
pub use codex_config::ResidencyRequirement;
20+
21+
@@ -221,6 +223,9 @@ pub fn build_reqwest_client() -> reqwest::Client {
22+
/// this method directly.
23+
pub fn try_build_reqwest_client() -> Result<reqwest::Client, BuildCustomCaTransportError> {
24+
let mut builder = reqwest::Client::builder().default_headers(default_headers());
25+
+ // reqwest defaults tcp_user_timeout to 30s on Linux-family targets, which is too short
26+
+ // for long-running unary requests such as remote compaction.
27+
+ builder = builder.tcp_user_timeout(DEFAULT_TCP_USER_TIMEOUT);
28+
if is_sandboxed() {
29+
builder = builder.no_proxy();
30+
}
31+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
SOURCE_ROOT="${SOURCE_ROOT:-${REPO_DIR}/../codex-rust-v0.131.0-src}"
6+
CODEX_RS="${SOURCE_ROOT}/codex-rs"
7+
RUSTUP_HOME="${RUSTUP_HOME:-${SOURCE_ROOT}/.rustup-home}"
8+
CARGO_HOME="${CARGO_HOME:-${SOURCE_ROOT}/.cargo-home}"
9+
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-${SOURCE_ROOT}/.cargo-target}"
10+
CARGO_BIN="${CARGO_BIN:-${CARGO_HOME}/bin/cargo}"
11+
COMPAT_SRC="${REPO_DIR}/src/centos7_compat.c"
12+
COMPAT_DIR="${CODEX_RS}/target_compat"
13+
COMPAT_OBJ="${COMPAT_DIR}/centos7_compat.o"
14+
PATCH_FILE="${REPO_DIR}/patches/codex-cli-0.131.0-issue14860-tcp-user-timeout.patch"
15+
16+
if [[ ! -d "${CODEX_RS}" ]]; then
17+
echo "missing codex-rs directory: ${CODEX_RS}" >&2
18+
exit 1
19+
fi
20+
21+
if [[ ! -x "${CARGO_BIN}" ]]; then
22+
echo "missing cargo binary: ${CARGO_BIN}" >&2
23+
exit 1
24+
fi
25+
26+
cd "${SOURCE_ROOT}"
27+
28+
if ! grep -q "DEFAULT_TCP_USER_TIMEOUT" codex-rs/login/src/auth/default_client.rs; then
29+
patch -p1 < "${PATCH_FILE}"
30+
fi
31+
32+
mkdir -p "${COMPAT_DIR}"
33+
cp "${COMPAT_SRC}" "${COMPAT_DIR}/centos7_compat.c"
34+
cc -fPIC -c "${COMPAT_DIR}/centos7_compat.c" -o "${COMPAT_OBJ}"
35+
36+
cd "${CODEX_RS}"
37+
38+
env \
39+
RUSTUP_HOME="${RUSTUP_HOME}" \
40+
CARGO_HOME="${CARGO_HOME}" \
41+
CARGO_TARGET_DIR="${CARGO_TARGET_DIR}" \
42+
CFLAGS="${CFLAGS:--fno-builtin-memcmp}" \
43+
CARGO_PROFILE_RELEASE_LTO="${CARGO_PROFILE_RELEASE_LTO:-false}" \
44+
CARGO_PROFILE_RELEASE_CODEGEN_UNITS="${CARGO_PROFILE_RELEASE_CODEGEN_UNITS:-16}" \
45+
"${CARGO_BIN}" rustc -p codex-cli --release --bin codex -- \
46+
-C "link-arg=${COMPAT_OBJ}"
47+
48+
"${CARGO_TARGET_DIR}/release/codex" --version

scripts/install_patched_codex.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
SOURCE_ROOT="${SOURCE_ROOT:-${REPO_DIR}/../codex-rust-v0.131.0-src}"
6+
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-${SOURCE_ROOT}/.cargo-target}"
7+
BUILT_CODEX="${BUILT_CODEX:-${CARGO_TARGET_DIR}/release/codex}"
8+
INSTALL_PATH="${INSTALL_PATH:-/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex/codex}"
9+
10+
if [[ ! -x "${BUILT_CODEX}" ]]; then
11+
echo "missing built codex binary: ${BUILT_CODEX}" >&2
12+
exit 1
13+
fi
14+
15+
if [[ ! -f "${INSTALL_PATH}" ]]; then
16+
echo "missing installed codex binary: ${INSTALL_PATH}" >&2
17+
exit 1
18+
fi
19+
20+
timestamp="$(date +%Y%m%d-%H%M%S)"
21+
backup_path="${INSTALL_PATH}.bak-${timestamp}"
22+
23+
cp -a "${INSTALL_PATH}" "${backup_path}"
24+
install -m 755 "${BUILT_CODEX}" "${INSTALL_PATH}"
25+
26+
echo "backup: ${backup_path}"
27+
echo "installed: ${INSTALL_PATH}"
28+
"${INSTALL_PATH}" --version

src/centos7_compat.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include <stdint.h>
2+
#include <sys/syscall.h>
3+
#include <unistd.h>
4+
5+
#ifndef SYS_memfd_create
6+
#ifdef __NR_memfd_create
7+
#define SYS_memfd_create __NR_memfd_create
8+
#elif defined(__x86_64__)
9+
#define SYS_memfd_create 319
10+
#else
11+
#error "SYS_memfd_create is not defined for this target"
12+
#endif
13+
#endif
14+
15+
uint16_t le16toh(uint16_t value) {
16+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
17+
return value;
18+
#else
19+
return __builtin_bswap16(value);
20+
#endif
21+
}
22+
23+
uint16_t be16toh(uint16_t value) {
24+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
25+
return __builtin_bswap16(value);
26+
#else
27+
return value;
28+
#endif
29+
}
30+
31+
int memfd_create(const char *name, unsigned int flags) {
32+
return (int)syscall(SYS_memfd_create, name, flags);
33+
}
34+

0 commit comments

Comments
 (0)