From 3a0d9bca64a62fd3483ba3689d799bb768698a02 Mon Sep 17 00:00:00 2001 From: iceweasel-oai Date: Tue, 16 Dec 2025 16:14:33 -0800 Subject: [PATCH] include new windows binaries in npm package. (#8140) The Windows Elevated Sandbox uses two new binaries: codex-windows-sandbox-setup.exe codex-command-runner.exe This PR includes them when installing native deps and packaging for npm --- .github/dotslash-config.json | 24 +++++++++++++ codex-cli/scripts/build_npm_package.py | 17 +++++++-- codex-cli/scripts/install_native_deps.py | 44 ++++++++++++++++-------- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/.github/dotslash-config.json b/.github/dotslash-config.json index 5e28cdf207..00e9032cf1 100644 --- a/.github/dotslash-config.json +++ b/.github/dotslash-config.json @@ -55,6 +55,30 @@ "path": "codex-responses-api-proxy.exe" } } + }, + "codex-command-runner": { + "platforms": { + "windows-x86_64": { + "regex": "^codex-command-runner-x86_64-pc-windows-msvc\\.exe\\.zst$", + "path": "codex-command-runner.exe" + }, + "windows-aarch64": { + "regex": "^codex-command-runner-aarch64-pc-windows-msvc\\.exe\\.zst$", + "path": "codex-command-runner.exe" + } + } + }, + "codex-windows-sandbox-setup": { + "platforms": { + "windows-x86_64": { + "regex": "^codex-windows-sandbox-setup-x86_64-pc-windows-msvc\\.exe\\.zst$", + "path": "codex-windows-sandbox-setup.exe" + }, + "windows-aarch64": { + "regex": "^codex-windows-sandbox-setup-aarch64-pc-windows-msvc\\.exe\\.zst$", + "path": "codex-windows-sandbox-setup.exe" + } + } } } } diff --git a/codex-cli/scripts/build_npm_package.py b/codex-cli/scripts/build_npm_package.py index ef96bef2ee..bf0eb5f469 100755 --- a/codex-cli/scripts/build_npm_package.py +++ b/codex-cli/scripts/build_npm_package.py @@ -20,9 +20,14 @@ PACKAGE_NATIVE_COMPONENTS: dict[str, list[str]] = { "codex-responses-api-proxy": ["codex-responses-api-proxy"], "codex-sdk": ["codex"], } +WINDOWS_ONLY_COMPONENTS: dict[str, list[str]] = { + "codex": ["codex-windows-sandbox-setup", "codex-command-runner"], +} COMPONENT_DEST_DIR: dict[str, str] = { "codex": "codex", "codex-responses-api-proxy": "codex-responses-api-proxy", + "codex-windows-sandbox-setup": "codex", + "codex-command-runner": "codex", "rg": "path", } @@ -103,7 +108,7 @@ def main() -> int: "pointing to a directory containing pre-installed binaries." ) - copy_native_binaries(vendor_src, staging_dir, native_components) + copy_native_binaries(vendor_src, staging_dir, package, native_components) if release_version: staging_dir_str = str(staging_dir) @@ -232,7 +237,12 @@ def stage_codex_sdk_sources(staging_dir: Path) -> None: shutil.copy2(license_src, staging_dir / "LICENSE") -def copy_native_binaries(vendor_src: Path, staging_dir: Path, components: list[str]) -> None: +def copy_native_binaries( + vendor_src: Path, + staging_dir: Path, + package: str, + components: list[str], +) -> None: vendor_src = vendor_src.resolve() if not vendor_src.exists(): raise RuntimeError(f"Vendor source directory not found: {vendor_src}") @@ -250,6 +260,9 @@ def copy_native_binaries(vendor_src: Path, staging_dir: Path, components: list[s if not target_dir.is_dir(): continue + if "windows" in target_dir.name: + components_set.update(WINDOWS_ONLY_COMPONENTS.get(package, [])) + dest_target_dir = vendor_dest / target_dir.name dest_target_dir.mkdir(parents=True, exist_ok=True) diff --git a/codex-cli/scripts/install_native_deps.py b/codex-cli/scripts/install_native_deps.py index 8d3909c9e1..f2c3987b2d 100755 --- a/codex-cli/scripts/install_native_deps.py +++ b/codex-cli/scripts/install_native_deps.py @@ -36,8 +36,11 @@ class BinaryComponent: artifact_prefix: str # matches the artifact filename prefix (e.g. codex-.zst) dest_dir: str # directory under vendor// where the binary is installed binary_basename: str # executable name inside dest_dir (before optional .exe) + targets: tuple[str, ...] | None = None # limit installation to specific targets +WINDOWS_TARGETS = tuple(target for target in BINARY_TARGETS if "windows" in target) + BINARY_COMPONENTS = { "codex": BinaryComponent( artifact_prefix="codex", @@ -49,6 +52,18 @@ BINARY_COMPONENTS = { dest_dir="codex-responses-api-proxy", binary_basename="codex-responses-api-proxy", ), + "codex-windows-sandbox-setup": BinaryComponent( + artifact_prefix="codex-windows-sandbox-setup", + dest_dir="codex", + binary_basename="codex-windows-sandbox-setup", + targets=WINDOWS_TARGETS, + ), + "codex-command-runner": BinaryComponent( + artifact_prefix="codex-command-runner", + dest_dir="codex", + binary_basename="codex-command-runner", + targets=WINDOWS_TARGETS, + ), } RG_TARGET_PLATFORM_PAIRS: list[tuple[str, str]] = [ @@ -79,7 +94,8 @@ def parse_args() -> argparse.Namespace: choices=tuple(list(BINARY_COMPONENTS) + ["rg"]), help=( "Limit installation to the specified components." - " May be repeated. Defaults to 'codex' and 'rg'." + " May be repeated. Defaults to codex, codex-windows-sandbox-setup," + " codex-command-runner, and rg." ), ) parser.add_argument( @@ -101,7 +117,12 @@ def main() -> int: vendor_dir = codex_cli_root / VENDOR_DIR_NAME vendor_dir.mkdir(parents=True, exist_ok=True) - components = args.components or ["codex", "rg"] + components = args.components or [ + "codex", + "codex-windows-sandbox-setup", + "codex-command-runner", + "rg", + ] workflow_url = (args.workflow_url or DEFAULT_WORKFLOW_URL).strip() if not workflow_url: @@ -116,8 +137,7 @@ def main() -> int: install_binary_components( artifacts_dir, vendor_dir, - BINARY_TARGETS, - [name for name in components if name in BINARY_COMPONENTS], + [BINARY_COMPONENTS[name] for name in components if name in BINARY_COMPONENTS], ) if "rg" in components: @@ -206,23 +226,19 @@ def _download_artifacts(workflow_id: str, dest_dir: Path) -> None: def install_binary_components( artifacts_dir: Path, vendor_dir: Path, - targets: Iterable[str], - component_names: Sequence[str], + selected_components: Sequence[BinaryComponent], ) -> None: - selected_components = [BINARY_COMPONENTS[name] for name in component_names if name in BINARY_COMPONENTS] if not selected_components: return - targets = list(targets) - if not targets: - return - for component in selected_components: + component_targets = list(component.targets or BINARY_TARGETS) + print( f"Installing {component.binary_basename} binaries for targets: " - + ", ".join(targets) + + ", ".join(component_targets) ) - max_workers = min(len(targets), max(1, (os.cpu_count() or 1))) + max_workers = min(len(component_targets), max(1, (os.cpu_count() or 1))) with ThreadPoolExecutor(max_workers=max_workers) as executor: futures = { executor.submit( @@ -232,7 +248,7 @@ def install_binary_components( target, component, ): target - for target in targets + for target in component_targets } for future in as_completed(futures): installed_path = future.result()