Skip to content

Commit 6e373c8

Browse files
authored
fix(codex): bundle codex-code-mode-host next to the codex binary
The codex 0.140.0 -> 0.144.0 bump (#3567) introduced a new runtime dependency: codex resolves codex-code-mode-host as a sibling of its own executable and routes all command execution through it for code-mode models (gpt-5.6 family advertises tool_mode: code_mode_only). We only shipped codex and rg into .vite/build/codex-acp, so Codex sessions could chat but every command/edit failed with the host binary missing. Download the host from the same codex release, stage it next to codex, and make the packaged-app verification fail the release when any codex sibling binary is missing. Generated-By: PostHog Code Task-Id: 541351db-2923-49df-8b67-45e277f5dce8
1 parent 46f300a commit 6e373c8

3 files changed

Lines changed: 58 additions & 58 deletions

File tree

.github/workflows/code-release.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,10 @@ jobs:
199199
echo "OK: $bin"
200200
done
201201
202-
# The native codex CLI must ship as a sibling of codex-acp, or the
203-
# app-server harness silently falls back to codex-acp in production.
204-
for f in codex rg; do
202+
# codex resolves codex-code-mode-host and rg as siblings of its own
203+
# executable; shipping codex without them breaks command execution
204+
# at runtime (code-mode models route all commands through the host).
205+
for f in codex codex-code-mode-host rg; do
205206
if [[ ! -f "$RESOURCES/app.asar.unpacked/.vite/build/codex-acp/$f" ]]; then
206207
echo "FAIL: codex-acp/$f missing in bundled binaries"
207208
exit 1

apps/code/scripts/download-binaries.mjs

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,56 @@ import { extract } from "tar";
1919
const __dirname = dirname(fileURLToPath(import.meta.url));
2020
const DEST_DIR = join(__dirname, "..", "resources", "codex-acp");
2121

22+
const CODEX_VERSION = "0.144.0";
23+
24+
function nativeTarget() {
25+
const { platform, arch } = process;
26+
const targets = {
27+
darwin: { arm64: "aarch64-apple-darwin", x64: "x86_64-apple-darwin" },
28+
linux: {
29+
arm64: "aarch64-unknown-linux-musl",
30+
x64: "x86_64-unknown-linux-musl",
31+
},
32+
win32: {
33+
arm64: "aarch64-pc-windows-msvc",
34+
x64: "x86_64-pc-windows-msvc",
35+
},
36+
};
37+
const target = targets[platform]?.[arch];
38+
if (!target) throw new Error(`Unsupported platform: ${platform}/${arch}`);
39+
return target;
40+
}
41+
42+
function codexReleaseUrl(binary, version, target) {
43+
const suffix = target.includes("windows") ? ".exe.zip" : ".tar.gz";
44+
return `https://github.com/openai/codex/releases/download/rust-v${version}/${binary}-${target}${suffix}`;
45+
}
46+
47+
// Codex release archives contain a target-suffixed binary
48+
// (e.g. `codex-aarch64-apple-darwin`); rename it after extract.
49+
const codexArchiveBinaryName = (binary) => (target) =>
50+
process.platform === "win32"
51+
? `${binary}-${target}.exe`
52+
: `${binary}-${target}`;
53+
2254
const BINARIES = [
2355
{
2456
name: "codex",
25-
version: "0.144.0",
26-
getUrl: (version, target) => {
27-
if (target.includes("windows")) {
28-
return `https://github.com/openai/codex/releases/download/rust-v${version}/codex-${target}.exe.zip`;
29-
}
30-
return `https://github.com/openai/codex/releases/download/rust-v${version}/codex-${target}.tar.gz`;
31-
},
32-
getTarget: () => {
33-
const { platform, arch } = process;
34-
const targets = {
35-
darwin: { arm64: "aarch64-apple-darwin", x64: "x86_64-apple-darwin" },
36-
linux: {
37-
arm64: "aarch64-unknown-linux-musl",
38-
x64: "x86_64-unknown-linux-musl",
39-
},
40-
win32: {
41-
arm64: "aarch64-pc-windows-msvc",
42-
x64: "x86_64-pc-windows-msvc",
43-
},
44-
};
45-
const platformTargets = targets[platform];
46-
if (!platformTargets)
47-
throw new Error(`Unsupported platform: ${platform}`);
48-
const target = platformTargets[arch];
49-
if (!target) throw new Error(`Unsupported arch: ${arch}`);
50-
return target;
51-
},
52-
// The codex release archive contains a target-suffixed binary
53-
// (e.g. `codex-aarch64-apple-darwin`); rename it to `codex` after extract.
54-
archiveBinaryName: (target) =>
55-
process.platform === "win32" ? `codex-${target}.exe` : `codex-${target}`,
57+
version: CODEX_VERSION,
58+
getUrl: (version, target) => codexReleaseUrl("codex", version, target),
59+
getTarget: nativeTarget,
60+
archiveBinaryName: codexArchiveBinaryName("codex"),
61+
},
62+
{
63+
// codex resolves this host as a sibling of its own executable and routes
64+
// all command execution through it for code-mode models (gpt-5.6+). It is
65+
// released per codex version, so it must stay in lockstep with `codex`.
66+
name: "codex-code-mode-host",
67+
version: CODEX_VERSION,
68+
getUrl: (version, target) =>
69+
codexReleaseUrl("codex-code-mode-host", version, target),
70+
getTarget: nativeTarget,
71+
archiveBinaryName: codexArchiveBinaryName("codex-code-mode-host"),
5672
},
5773
{
5874
name: "rg",
@@ -61,26 +77,7 @@ const BINARIES = [
6177
const ext = target.includes("windows") ? "zip" : "tar.gz";
6278
return `https://github.com/microsoft/ripgrep-prebuilt/releases/download/v${version}/ripgrep-v${version}-${target}.${ext}`;
6379
},
64-
getTarget: () => {
65-
const { platform, arch } = process;
66-
const targets = {
67-
darwin: { arm64: "aarch64-apple-darwin", x64: "x86_64-apple-darwin" },
68-
linux: {
69-
arm64: "aarch64-unknown-linux-musl",
70-
x64: "x86_64-unknown-linux-musl",
71-
},
72-
win32: {
73-
arm64: "aarch64-pc-windows-msvc",
74-
x64: "x86_64-pc-windows-msvc",
75-
},
76-
};
77-
const platformTargets = targets[platform];
78-
if (!platformTargets)
79-
throw new Error(`Unsupported platform: ${platform}`);
80-
const target = platformTargets[arch];
81-
if (!target) throw new Error(`Unsupported arch: ${arch}`);
82-
return target;
83-
},
80+
getTarget: nativeTarget,
8481
},
8582
];
8683

apps/code/vite-main-plugins.mts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,10 +592,12 @@ export function copyCodexAcpBinaries(): Plugin {
592592
const sourceDir = join(__dirname, "resources/codex-acp");
593593
const binaries = [
594594
{ name: "codex", winName: "codex.exe" },
595-
// The native codex CLI must ship next to codex-acp: the app-server
596-
// sub-adapter resolves it as a sibling and silently falls back to
597-
// codex-acp when it's missing.
598-
{ name: "codex", winName: "codex.exe" },
595+
// codex resolves the code-mode host as a sibling of its own executable;
596+
// code-mode models (gpt-5.6+) cannot run commands without it.
597+
{
598+
name: "codex-code-mode-host",
599+
winName: "codex-code-mode-host.exe",
600+
},
599601
{ name: "rg", winName: "rg.exe" },
600602
];
601603

0 commit comments

Comments
 (0)