From 30401f396306bdec1fb28f8f8177871678fcc212 Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Fri, 12 Jun 2026 00:03:53 +0000 Subject: [PATCH] build: package and launch code mode host --- .../scripts/build-codex-package-archive.sh | 17 ++++++ .github/workflows/rust-release-windows.yml | 14 +++-- .github/workflows/rust-release.yml | 52 +++++++++------- BUILD.bazel | 2 + codex-rs/cli/BUILD.bazel | 10 +++- defs.bzl | 60 +++++++++++++++++++ justfile | 6 +- runfile_env_binary_launcher.bat.tpl | 51 ++++++++++++++++ runfile_env_binary_launcher.sh.tpl | 57 ++++++++++++++++++ scripts/codex_package/README.md | 4 +- scripts/codex_package/cargo.py | 13 +++- scripts/codex_package/cli.py | 14 +++++ scripts/codex_package/layout.py | 8 +++ scripts/codex_package/targets.py | 1 + scripts/codex_package/test_cargo.py | 21 +++++++ scripts/codex_package/v8.py | 7 ++- scripts/install/install.ps1 | 1 + scripts/install/install.sh | 6 +- workspace_root_test_launcher.bat.tpl | 4 +- 19 files changed, 309 insertions(+), 39 deletions(-) create mode 100644 runfile_env_binary_launcher.bat.tpl create mode 100644 runfile_env_binary_launcher.sh.tpl diff --git a/.github/scripts/build-codex-package-archive.sh b/.github/scripts/build-codex-package-archive.sh index 80da4cf20c..5559562566 100644 --- a/.github/scripts/build-codex-package-archive.sh +++ b/.github/scripts/build-codex-package-archive.sh @@ -8,6 +8,7 @@ Usage: build-codex-package-archive.sh \ --bundle \ --entrypoint-dir \ --archive-dir \ + [--code-mode-host-bin ] \ [--bwrap-bin ] \ [--codex-command-runner-bin ] \ [--codex-windows-sandbox-setup-bin ] \ @@ -19,6 +20,7 @@ target="" bundle="" entrypoint_dir="" archive_dir="" +code_mode_host_bin="" target_suffixed_entrypoint="false" resource_args=() bwrap_bin_provided="false" @@ -43,6 +45,10 @@ while [[ $# -gt 0 ]]; do archive_dir="${2:?--archive-dir requires a value}" shift 2 ;; + --code-mode-host-bin) + code_mode_host_bin="${2:?--code-mode-host-bin requires a value}" + shift 2 + ;; --bwrap-bin) resource_args+=(--bwrap-bin "${2:?--bwrap-bin requires a value}") bwrap_bin_provided="true" @@ -110,8 +116,18 @@ case "$target" in esac entrypoint_name="$entrypoint" +code_mode_host_name="codex-code-mode-host" if [[ "$target_suffixed_entrypoint" == "true" ]]; then entrypoint_name="${entrypoint_name}-${target}" + code_mode_host_name="${code_mode_host_name}-${target}" +fi + +if [[ -z "$code_mode_host_bin" ]]; then + code_mode_host_bin="${entrypoint_dir%/}/${code_mode_host_name}${exe_suffix}" +fi +if [[ ! -f "$code_mode_host_bin" ]]; then + echo "Code-mode host binary ${code_mode_host_bin} not found" >&2 + exit 1 fi case "$target" in @@ -159,6 +175,7 @@ python_args=( --target "$target" --variant "$variant" --entrypoint-bin "${entrypoint_dir%/}/${entrypoint_name}${exe_suffix}" + --code-mode-host-bin "$code_mode_host_bin" --cargo-profile release --package-dir "$package_dir" --archive-output "$gzip_archive_path" diff --git a/.github/workflows/rust-release-windows.yml b/.github/workflows/rust-release-windows.yml index 49e627c1be..fd9549e006 100644 --- a/.github/workflows/rust-release-windows.yml +++ b/.github/workflows/rust-release-windows.yml @@ -41,14 +41,14 @@ jobs: - runner: windows-x64 target: x86_64-pc-windows-msvc bundle: helpers - binaries: "codex-windows-sandbox-setup codex-command-runner" + binaries: "codex-windows-sandbox-setup codex-command-runner codex-code-mode-host" runs_on: group: ${{ github.event.repository.name }}-runners labels: ${{ github.event.repository.name }}-windows-x64 - runner: windows-arm64 target: aarch64-pc-windows-msvc bundle: helpers - binaries: "codex-windows-sandbox-setup codex-command-runner" + binaries: "codex-windows-sandbox-setup codex-command-runner codex-code-mode-host" runs_on: group: ${{ github.event.repository.name }}-runners labels: ${{ github.event.repository.name }}-windows-arm64 @@ -158,7 +158,7 @@ jobs: run: working-directory: codex-rs env: - WINDOWS_BINARIES: "codex codex-responses-api-proxy codex-windows-sandbox-setup codex-command-runner codex-app-server" + WINDOWS_BINARIES: "codex codex-responses-api-proxy codex-windows-sandbox-setup codex-command-runner codex-code-mode-host codex-app-server" strategy: fail-fast: false @@ -340,16 +340,18 @@ jobs: bundle_dir="$(mktemp -d)" runner_src="$dest/codex-command-runner-${{ matrix.target }}.exe" setup_src="$dest/codex-windows-sandbox-setup-${{ matrix.target }}.exe" - if [[ -f "$runner_src" && -f "$setup_src" ]]; then + code_mode_host_src="$dest/codex-code-mode-host-${{ matrix.target }}.exe" + if [[ -f "$runner_src" && -f "$setup_src" && -f "$code_mode_host_src" ]]; then cp "$dest/$base" "$bundle_dir/$base" cp "$runner_src" "$bundle_dir/codex-command-runner.exe" cp "$setup_src" "$bundle_dir/codex-windows-sandbox-setup.exe" + cp "$code_mode_host_src" "$bundle_dir/codex-code-mode-host.exe" # Use an absolute path so bundle zips land in the real dist # dir even when 7z runs from a temp directory. (cd "$bundle_dir" && 7z a "$repo_root/$dest/${base}.zip" .) else - echo "warning: missing sandbox binaries; falling back to single-binary zip" - echo "warning: expected $runner_src and $setup_src" + echo "warning: missing bundled binaries; falling back to single-binary zip" + echo "warning: expected $runner_src, $setup_src, and $code_mode_host_src" (cd "$dest" && 7z a "${base}.zip" "$base") fi rm -rf "$bundle_dir" diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index a2646e3eae..9d4f325e55 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -80,50 +80,50 @@ jobs: target: aarch64-apple-darwin bundle: primary artifact_name: aarch64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" build_dmg: "true" - runner: macos-15-xlarge target: aarch64-apple-darwin bundle: app-server artifact_name: aarch64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" build_dmg: "false" - runner: macos-15-xlarge target: x86_64-apple-darwin bundle: primary artifact_name: x86_64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" build_dmg: "true" - runner: macos-15-xlarge target: x86_64-apple-darwin bundle: app-server artifact_name: x86_64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" build_dmg: "false" # Release artifacts intentionally ship MUSL-linked Linux binaries. - runner: ${{ github.event.repository.name }}-linux-x64-xl target: x86_64-unknown-linux-musl bundle: primary artifact_name: x86_64-unknown-linux-musl - binaries: "codex codex-responses-api-proxy bwrap" + binaries: "codex codex-responses-api-proxy codex-code-mode-host bwrap" build_dmg: "false" - runner: ${{ github.event.repository.name }}-linux-x64-xl target: x86_64-unknown-linux-musl bundle: app-server artifact_name: x86_64-unknown-linux-musl-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" build_dmg: "false" - runner: ${{ github.event.repository.name }}-linux-arm64 target: aarch64-unknown-linux-musl bundle: primary artifact_name: aarch64-unknown-linux-musl - binaries: "codex codex-responses-api-proxy bwrap" + binaries: "codex codex-responses-api-proxy codex-code-mode-host bwrap" build_dmg: "false" - runner: ${{ github.event.repository.name }}-linux-arm64 target: aarch64-unknown-linux-musl bundle: app-server artifact_name: aarch64-unknown-linux-musl-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" build_dmg: "false" steps: @@ -208,6 +208,7 @@ jobs: - name: Configure rusty_v8 artifact overrides and verify checksums uses: ./.github/actions/setup-rusty-v8 with: + sandbox: "true" target: ${{ matrix.target }} - if: ${{ contains(matrix.target, 'linux') }} @@ -344,9 +345,15 @@ jobs: rm -rf "$bundle_root" mkdir -p "$bundle_root/codex-resources" cp "$dest/codex-${{ matrix.target }}" "$bundle_root/codex" + cp "$dest/codex-code-mode-host-${{ matrix.target }}" \ + "$bundle_root/codex-code-mode-host" cp "$dest/bwrap-${{ matrix.target }}" "$bundle_root/codex-resources/bwrap" - chmod 0755 "$bundle_root/codex" "$bundle_root/codex-resources/bwrap" - tar -C "$bundle_root" -cf - codex codex-resources/bwrap | + chmod 0755 \ + "$bundle_root/codex" \ + "$bundle_root/codex-code-mode-host" \ + "$bundle_root/codex-resources/bwrap" + tar -C "$bundle_root" -cf - \ + codex codex-code-mode-host codex-resources/bwrap | zstd -T0 -19 -o "$dest/codex-${{ matrix.target }}-bundle.tar.zst" fi @@ -484,19 +491,19 @@ jobs: - target: aarch64-apple-darwin bundle: primary artifact_name: aarch64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" - target: aarch64-apple-darwin bundle: app-server artifact_name: aarch64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" - target: x86_64-apple-darwin bundle: primary artifact_name: x86_64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" - target: x86_64-apple-darwin bundle: app-server artifact_name: x86_64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -602,22 +609,22 @@ jobs: - target: aarch64-apple-darwin bundle: primary artifact_name: aarch64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" build_dmg: "true" - target: aarch64-apple-darwin bundle: app-server artifact_name: aarch64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" build_dmg: "false" - target: x86_64-apple-darwin bundle: primary artifact_name: x86_64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" build_dmg: "true" - target: x86_64-apple-darwin bundle: app-server artifact_name: x86_64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" build_dmg: "false" steps: @@ -889,22 +896,22 @@ jobs: - target: aarch64-apple-darwin bundle: primary artifact_name: aarch64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" verify_dmg: "true" - target: aarch64-apple-darwin bundle: app-server artifact_name: aarch64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" verify_dmg: "false" - target: x86_64-apple-darwin bundle: primary artifact_name: x86_64-apple-darwin - binaries: "codex codex-responses-api-proxy" + binaries: "codex codex-responses-api-proxy codex-code-mode-host" verify_dmg: "true" - target: x86_64-apple-darwin bundle: app-server artifact_name: x86_64-apple-darwin-app-server - binaries: "codex-app-server" + binaries: "codex-app-server codex-code-mode-host" verify_dmg: "false" steps: @@ -992,6 +999,7 @@ jobs: mkdir -p "$package_dir" tar -xzf "${packaged_dir}/${package_stem}-${target}.tar.gz" -C "$package_dir" verify_signed_binary "${package_dir}/bin/${package_entrypoint}" + verify_signed_binary "${package_dir}/bin/codex-code-mode-host" if [[ "${{ matrix.verify_dmg }}" != "true" ]]; then exit 0 diff --git a/BUILD.bazel b/BUILD.bazel index a82126e6f1..3f5d4f3f33 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -71,6 +71,8 @@ alias( exports_files([ "AGENTS.md", + "runfile_env_binary_launcher.bat.tpl", + "runfile_env_binary_launcher.sh.tpl", "workspace_root_test_launcher.bat.tpl", "workspace_root_test_launcher.sh.tpl", ]) diff --git a/codex-rs/cli/BUILD.bazel b/codex-rs/cli/BUILD.bazel index 97c868845b..c7671f92a5 100644 --- a/codex-rs/cli/BUILD.bazel +++ b/codex-rs/cli/BUILD.bazel @@ -1,4 +1,4 @@ -load("//:defs.bzl", "MACOS_WEBRTC_RUSTC_LINK_FLAGS", "codex_rust_crate") +load("//:defs.bzl", "MACOS_WEBRTC_RUSTC_LINK_FLAGS", "codex_rust_crate", "runfile_env_binary") load("//bazel/platforms:release_binaries.bzl", "multiplatform_binaries") codex_rust_crate( @@ -13,3 +13,11 @@ codex_rust_crate( multiplatform_binaries( name = "codex", ) + +runfile_env_binary( + name = "codex-with-code-mode", + binary = ":codex", + runfile_env = { + "//codex-rs/code-mode-host:codex-code-mode-host": "CODEX_CODE_MODE_HOST_PATH", + }, +) diff --git a/defs.bzl b/defs.bzl index 851ea676c8..4dfb8e4ca9 100644 --- a/defs.bzl +++ b/defs.bzl @@ -125,6 +125,66 @@ def _windows_workspace_root_setup(ctx): return """set "INSTA_WORKSPACE_ROOT=%workspace_root%" cd /d "%workspace_root%" || exit /b 1""" +def _runfile_env_binary_impl(ctx): + is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) + launcher = ctx.actions.declare_file(ctx.label.name + ".bat" if is_windows else ctx.label.name) + binary = ctx.executable.binary + launcher_template = ctx.file._windows_launcher_template if is_windows else ctx.file._bash_launcher_template + runfile_env_exports = _windows_runfile_env_exports(ctx) if is_windows else _bash_runfile_env_exports(ctx) + ctx.actions.expand_template( + template = launcher_template, + output = launcher, + is_executable = True, + substitutions = { + "__BINARY__": binary.short_path, + "__RUNFILE_ENV_EXPORTS__": runfile_env_exports, + "__WORKSPACE_NAME__": ctx.workspace_name, + }, + ) + + runfiles = ctx.runfiles(files = [binary]).merge(ctx.attr.binary[DefaultInfo].default_runfiles) + for runfile_dep in ctx.attr.runfile_env: + executable = runfile_dep[DefaultInfo].files_to_run.executable + if executable == None: + fail("{} does not provide an executable for runfile_env".format(runfile_dep.label)) + runfiles = runfiles.merge(ctx.runfiles(files = [executable])) + runfiles = runfiles.merge(runfile_dep[DefaultInfo].default_runfiles) + + return [DefaultInfo( + executable = launcher, + files = depset([launcher]), + runfiles = runfiles, + )] + +runfile_env_binary = rule( + implementation = _runfile_env_binary_impl, + executable = True, + toolchains = ["@bazel_tools//tools/test:default_test_toolchain_type"], + attrs = { + "binary": attr.label( + cfg = "target", + executable = True, + mandatory = True, + ), + "runfile_env": attr.label_keyed_string_dict( + cfg = "target", + ), + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + providers = [platform_common.ConstraintValueInfo], + ), + "_bash_launcher_template": attr.label( + allow_single_file = True, + default = "//:runfile_env_binary_launcher.sh.tpl", + ), + "_windows_launcher_template": attr.label( + allow_single_file = True, + default = "//:runfile_env_binary_launcher.bat.tpl", + ), + }, + doc = "Runs a binary with environment variables resolved from executable runfiles.", +) + workspace_root_test = rule( implementation = _workspace_root_test_impl, test = True, diff --git a/justfile b/justfile index fa32a19e7d..153fc7bd97 100644 --- a/justfile +++ b/justfile @@ -96,16 +96,18 @@ bench-smoke: just bench -- --test # Build and run Codex from source using Bazel. +# The launcher target also builds the code-mode host and injects its runfile +# path, so Bazel can rebuild either binary incrementally. # On Unix, use `[no-cd]` and `--run_under="cd $PWD &&"` to ensure Bazel runs # the command in the current working directory. [no-cd] [unix] bazel-codex *args: - bazel run //codex-rs/cli:codex --run_under="cd $PWD &&" -- "$@" + bazel run //codex-rs/cli:codex-with-code-mode --run_under="cd $PWD &&" -- "$@" [windows] bazel-codex *args: - bazel run //codex-rs/cli:codex --run_under='cd /d "{{ invocation_directory_native() }}" &&' -- @($args | Select-Object -Skip 1) + bazel run //codex-rs/cli:codex-with-code-mode --run_under='cd /d "{{ invocation_directory_native() }}" &&' -- @($args | Select-Object -Skip 1) [no-cd] bazel-lock-update: diff --git a/runfile_env_binary_launcher.bat.tpl b/runfile_env_binary_launcher.bat.tpl new file mode 100644 index 0000000000..2d322e5677 --- /dev/null +++ b/runfile_env_binary_launcher.bat.tpl @@ -0,0 +1,51 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +call :resolve_runfile binary "__BINARY__" +if errorlevel 1 exit /b 1 + +__RUNFILE_ENV_EXPORTS__ + +"%binary%" %* +exit /b %ERRORLEVEL% + +:resolve_runfile +setlocal EnableExtensions EnableDelayedExpansion +set "logical_path=%~2" +set "native_logical_path=%logical_path:/=\%" +set "workspace_name=__WORKSPACE_NAME__" + +for %%R in ("%RUNFILES_DIR%" "%TEST_SRCDIR%" "%~f0.runfiles") do ( + set "runfiles_root=%%~R" + if defined runfiles_root ( + for %%P in ("!native_logical_path!" "%TEST_WORKSPACE%\!native_logical_path!" "!workspace_name!\!native_logical_path!" "_main\!native_logical_path!") do ( + if exist "!runfiles_root!\%%~P" ( + endlocal & set "%~1=!runfiles_root!\%%~P" & exit /b 0 + ) + ) + ) +) + +set "manifest=%RUNFILES_MANIFEST_FILE%" +if not defined manifest if exist "%~f0.runfiles_manifest" set "manifest=%~f0.runfiles_manifest" +if not defined manifest if exist "%~f0.exe.runfiles_manifest" set "manifest=%~f0.exe.runfiles_manifest" + +if defined manifest if exist "%manifest%" ( + for /f "usebackq tokens=1,* delims= " %%A in ("%manifest%") do ( + if "%%A"=="%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + if "%%A"=="%TEST_WORKSPACE%/%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + if "%%A"=="%workspace_name%/%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + if "%%A"=="_main/%logical_path%" ( + endlocal & set "%~1=%%B" & exit /b 0 + ) + ) +) + +>&2 echo failed to resolve runfile: %logical_path% +endlocal & exit /b 1 diff --git a/runfile_env_binary_launcher.sh.tpl b/runfile_env_binary_launcher.sh.tpl new file mode 100644 index 0000000000..105118f7f9 --- /dev/null +++ b/runfile_env_binary_launcher.sh.tpl @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +resolve_runfile() { + local logical_path="$1" + local launcher_runfiles="$0.runfiles" + local workspace_name="__WORKSPACE_NAME__" + local runfiles_root + + for runfiles_root in "${RUNFILES_DIR:-}" "${TEST_SRCDIR:-}" "${launcher_runfiles}"; do + if [[ -z "${runfiles_root}" ]]; then + continue + fi + for candidate in \ + "${runfiles_root}/${logical_path}" \ + "${runfiles_root}/${TEST_WORKSPACE:-}/${logical_path}" \ + "${runfiles_root}/${workspace_name}/${logical_path}" \ + "${runfiles_root}/_main/${logical_path}"; do + if [[ -e "${candidate}" ]]; then + printf '%s\n' "${candidate}" + return 0 + fi + done + done + + local manifest="${RUNFILES_MANIFEST_FILE:-}" + if [[ -z "${manifest}" ]]; then + if [[ -f "$0.runfiles_manifest" ]]; then + manifest="$0.runfiles_manifest" + elif [[ -f "$0.exe.runfiles_manifest" ]]; then + manifest="$0.exe.runfiles_manifest" + fi + fi + + if [[ -n "${manifest}" && -f "${manifest}" ]]; then + local resolved + resolved="$(awk -v path="${logical_path}" '$1 == path || substr($1, length($1) - length(path), length(path) + 1) == "/" path { $1 = ""; sub(/^ /, ""); print; exit }' "${manifest}")" + if [[ -n "${resolved}" ]]; then + printf '%s\n' "${resolved}" + return 0 + fi + fi + + echo "failed to resolve runfile: ${logical_path}" >&2 + return 1 +} + +binary="$(resolve_runfile "__BINARY__")" +RUNFILE_ENV_ARGS=() + +__RUNFILE_ENV_EXPORTS__ + +if (( ${#RUNFILE_ENV_ARGS[@]} > 0 )); then + exec env "${RUNFILE_ENV_ARGS[@]}" "${binary}" "$@" +else + exec "${binary}" "$@" +fi diff --git a/scripts/codex_package/README.md b/scripts/codex_package/README.md index 323a3ce5ba..3fe93441d4 100644 --- a/scripts/codex_package/README.md +++ b/scripts/codex_package/README.md @@ -10,7 +10,8 @@ The builder creates a canonical Codex package directory: . ├── codex-package.json ├── bin -│ └── [.exe] +│ ├── [.exe] +│ └── codex-code-mode-host[.exe] ├── codex-resources │ ├── bwrap # Linux only │ ├── zsh/bin/zsh # supported Unix targets only @@ -40,6 +41,7 @@ grouped `cargo build` command per package when they are needed and no prebuilt override was provided: - all targets: the selected entrypoint, unless `--entrypoint-bin` is provided +- all targets: `codex-code-mode-host`, unless `--code-mode-host-bin` is provided - Linux targets: `bwrap`, unless `--bwrap-bin` is provided - Windows targets: `codex-command-runner` and `codex-windows-sandbox-setup`, unless the corresponding prebuilt helper flags are provided diff --git a/scripts/codex_package/cargo.py b/scripts/codex_package/cargo.py index 208d85d174..f2dbe6c774 100644 --- a/scripts/codex_package/cargo.py +++ b/scripts/codex_package/cargo.py @@ -17,6 +17,7 @@ CODEX_RS_ROOT = REPO_ROOT / "codex-rs" @dataclass(frozen=True) class SourceBuildOutputs: entrypoint_bin: Path + code_mode_host_bin: Path bwrap_bin: Path | None codex_command_runner_bin: Path | None codex_windows_sandbox_setup_bin: Path | None @@ -29,6 +30,7 @@ def build_source_binaries( cargo: str, profile: str, entrypoint_bin: Path | None, + code_mode_host_bin: Path | None, bwrap_bin: Path | None, codex_command_runner_bin: Path | None, codex_windows_sandbox_setup_bin: Path | None, @@ -43,6 +45,7 @@ def build_source_binaries( spec, variant, build_entrypoint=entrypoint_bin is None, + build_code_mode_host=code_mode_host_bin is None, build_bwrap=spec.is_linux and bwrap_bin is None, build_codex_command_runner=spec.is_windows and codex_command_runner_bin is None, build_codex_windows_sandbox_setup=spec.is_windows @@ -61,7 +64,7 @@ def build_source_binaries( cmd.extend(["--bin", binary]) cargo_env = None - if entrypoint_bin is None: + if entrypoint_bin is None or code_mode_host_bin is None: codex_v8_env = resolve_codex_v8_cargo_env(spec) if codex_v8_env: cargo_env = {**os.environ, **codex_v8_env} @@ -80,6 +83,10 @@ def build_source_binaries( entrypoint_bin, output_dir / variant.entrypoint_name(spec), ), + code_mode_host_bin=resolve_output_path( + code_mode_host_bin, + output_dir / f"codex-code-mode-host{spec.exe_suffix}", + ), bwrap_bin=resolve_output_path( bwrap_bin, output_dir / "bwrap" if spec.is_linux else None, @@ -102,6 +109,7 @@ def source_binaries_for_target( variant: PackageVariant, *, build_entrypoint: bool, + build_code_mode_host: bool, build_bwrap: bool, build_codex_command_runner: bool, build_codex_windows_sandbox_setup: bool, @@ -109,6 +117,8 @@ def source_binaries_for_target( binaries = [] if build_entrypoint: binaries.append(variant.cargo_bin) + if build_code_mode_host: + binaries.append("codex-code-mode-host") if build_bwrap: binaries.append("bwrap") if build_codex_command_runner: @@ -174,6 +184,7 @@ def cargo_profile_dirname(profile: str) -> str: def validate_source_outputs(outputs: SourceBuildOutputs) -> None: for path in [ outputs.entrypoint_bin, + outputs.code_mode_host_bin, outputs.bwrap_bin, outputs.codex_command_runner_bin, outputs.codex_windows_sandbox_setup_bin, diff --git a/scripts/codex_package/cli.py b/scripts/codex_package/cli.py index b7d919e4ff..d3c6fafe33 100644 --- a/scripts/codex_package/cli.py +++ b/scripts/codex_package/cli.py @@ -82,6 +82,14 @@ def parse_args() -> argparse.Namespace: "variant. If omitted, the entrypoint is built with Cargo." ), ) + parser.add_argument( + "--code-mode-host-bin", + type=Path, + help=( + "Optional prebuilt codex-code-mode-host executable. If omitted, " + "codex-code-mode-host is built with Cargo." + ), + ) parser.add_argument( "--bwrap-bin", type=Path, @@ -140,6 +148,11 @@ def main() -> int: "prebuilt entrypoint executable", "--entrypoint-bin", ), + code_mode_host_bin=resolve_optional_input_path( + args.code_mode_host_bin, + "prebuilt code-mode host executable", + "--code-mode-host-bin", + ), bwrap_bin=resolve_optional_input_path( args.bwrap_bin, "prebuilt Linux bwrap executable", @@ -159,6 +172,7 @@ def main() -> int: version = read_workspace_version() inputs = PackageInputs( entrypoint_bin=source_outputs.entrypoint_bin, + code_mode_host_bin=source_outputs.code_mode_host_bin, rg_bin=resolve_rg_bin(spec, args.rg_bin), zsh_bin=resolve_zsh_bin(spec), bwrap_bin=source_outputs.bwrap_bin, diff --git a/scripts/codex_package/layout.py b/scripts/codex_package/layout.py index 63598672ea..131de5f5bc 100644 --- a/scripts/codex_package/layout.py +++ b/scripts/codex_package/layout.py @@ -51,6 +51,11 @@ def build_package_dir( bin_dir / entrypoint_name, is_windows=spec.is_windows, ) + copy_executable( + inputs.code_mode_host_bin, + bin_dir / f"codex-code-mode-host{spec.exe_suffix}", + is_windows=spec.is_windows, + ) copy_executable(inputs.rg_bin, path_dir / spec.rg_name, is_windows=spec.is_windows) if inputs.zsh_bin is not None: @@ -83,6 +88,7 @@ def build_package_dir( "target": spec.target, "variant": variant.name, "entrypoint": f"bin/{entrypoint_name}", + "codeModeHost": f"bin/codex-code-mode-host{spec.exe_suffix}", "resourcesDir": "codex-resources", "pathDir": "codex-path", } @@ -118,6 +124,7 @@ def validate_package_dir( "target": spec.target, "variant": variant.name, "entrypoint": f"bin/{variant.entrypoint_name(spec)}", + "codeModeHost": f"bin/codex-code-mode-host{spec.exe_suffix}", "resourcesDir": "codex-resources", "pathDir": "codex-path", } @@ -130,6 +137,7 @@ def validate_package_dir( required_files = [ Path("bin") / variant.entrypoint_name(spec), + Path("bin") / f"codex-code-mode-host{spec.exe_suffix}", Path("codex-path") / spec.rg_name, ] executable_files = list(required_files) diff --git a/scripts/codex_package/targets.py b/scripts/codex_package/targets.py index 8307a3e630..016202cf5f 100644 --- a/scripts/codex_package/targets.py +++ b/scripts/codex_package/targets.py @@ -39,6 +39,7 @@ class PackageVariant: @dataclass(frozen=True) class PackageInputs: entrypoint_bin: Path + code_mode_host_bin: Path rg_bin: Path zsh_bin: Path | None bwrap_bin: Path | None diff --git a/scripts/codex_package/test_cargo.py b/scripts/codex_package/test_cargo.py index 6185f8b8b3..6f2df7a3ff 100644 --- a/scripts/codex_package/test_cargo.py +++ b/scripts/codex_package/test_cargo.py @@ -20,6 +20,7 @@ class SourceBinariesForTargetTest(unittest.TestCase): TARGET_SPECS["aarch64-apple-darwin"], PACKAGE_VARIANTS["codex"], build_entrypoint=False, + build_code_mode_host=False, build_bwrap=False, build_codex_command_runner=False, build_codex_windows_sandbox_setup=False, @@ -35,6 +36,7 @@ class SourceBinariesForTargetTest(unittest.TestCase): TARGET_SPECS["x86_64-unknown-linux-musl"], PACKAGE_VARIANTS["codex"], build_entrypoint=False, + build_code_mode_host=False, build_bwrap=False, build_codex_command_runner=False, build_codex_windows_sandbox_setup=False, @@ -50,6 +52,7 @@ class SourceBinariesForTargetTest(unittest.TestCase): TARGET_SPECS["x86_64-pc-windows-msvc"], PACKAGE_VARIANTS["codex"], build_entrypoint=False, + build_code_mode_host=False, build_bwrap=False, build_codex_command_runner=False, build_codex_windows_sandbox_setup=False, @@ -63,6 +66,7 @@ class SourceBinariesForTargetTest(unittest.TestCase): TARGET_SPECS["x86_64-pc-windows-msvc"], PACKAGE_VARIANTS["codex"], build_entrypoint=False, + build_code_mode_host=False, build_bwrap=False, build_codex_command_runner=True, build_codex_windows_sandbox_setup=True, @@ -70,10 +74,25 @@ class SourceBinariesForTargetTest(unittest.TestCase): ["codex-command-runner", "codex-windows-sandbox-setup"], ) + def test_missing_code_mode_host_is_built(self) -> None: + self.assertEqual( + source_binaries_for_target( + TARGET_SPECS["x86_64-unknown-linux-musl"], + PACKAGE_VARIANTS["codex"], + build_entrypoint=False, + build_code_mode_host=True, + build_bwrap=False, + build_codex_command_runner=False, + build_codex_windows_sandbox_setup=False, + ), + ["codex-code-mode-host"], + ) + def test_build_uses_prebuilt_windows_helpers_without_running_cargo(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: root = Path(temp_dir) entrypoint = touch_file(root / "codex.exe") + code_mode_host = touch_file(root / "codex-code-mode-host.exe") command_runner = touch_file(root / "codex-command-runner.exe") sandbox_setup = touch_file(root / "codex-windows-sandbox-setup.exe") @@ -83,12 +102,14 @@ class SourceBinariesForTargetTest(unittest.TestCase): cargo=str(root / "cargo-that-should-not-run"), profile="release", entrypoint_bin=entrypoint, + code_mode_host_bin=code_mode_host, bwrap_bin=None, codex_command_runner_bin=command_runner, codex_windows_sandbox_setup_bin=sandbox_setup, ) self.assertEqual(outputs.entrypoint_bin, entrypoint) + self.assertEqual(outputs.code_mode_host_bin, code_mode_host) self.assertEqual(outputs.codex_command_runner_bin, command_runner) self.assertEqual(outputs.codex_windows_sandbox_setup_bin, sandbox_setup) diff --git a/scripts/codex_package/v8.py b/scripts/codex_package/v8.py index 4033e6822f..16c9a740a9 100644 --- a/scripts/codex_package/v8.py +++ b/scripts/codex_package/v8.py @@ -16,6 +16,7 @@ from .targets import TargetSpec DOWNLOAD_TIMEOUT_SECS = 120 +ARTIFACT_PROFILE = "ptrcomp_sandbox_release" @dataclass(frozen=True) @@ -70,9 +71,9 @@ def fetch_codex_v8_artifacts( ) target = spec.target cache_dir = (cache_root or default_cache_root()) / f"rusty-v8-{version}-{target}" - archive = cache_dir / f"librusty_v8_release_{target}.a.gz" - binding = cache_dir / f"src_binding_release_{target}.rs" - checksums = cache_dir / f"rusty_v8_release_{target}.sha256" + archive = cache_dir / f"librusty_v8_{ARTIFACT_PROFILE}_{target}.a.gz" + binding = cache_dir / f"src_binding_{ARTIFACT_PROFILE}_{target}.rs" + checksums = cache_dir / f"rusty_v8_{ARTIFACT_PROFILE}_{target}.sha256" download_file(f"{release_url}/{checksums.name}", checksums) expected_checksums = load_checksums(checksums, {archive.name, binding.name}) diff --git a/scripts/install/install.ps1 b/scripts/install/install.ps1 index 6973d482e2..31aef584f3 100644 --- a/scripts/install/install.ps1 +++ b/scripts/install/install.ps1 @@ -537,6 +537,7 @@ function Test-PackageContentsAreComplete { $expectedFiles = @( "codex-package.json", "bin\codex.exe", + "bin\codex-code-mode-host.exe", "codex-path\rg.exe", "codex-resources\codex-command-runner.exe", "codex-resources\codex-windows-sandbox-setup.exe" diff --git a/scripts/install/install.sh b/scripts/install/install.sh index 23980b0c5e..f5304090b6 100755 --- a/scripts/install/install.sh +++ b/scripts/install/install.sh @@ -677,7 +677,10 @@ install_package_release() { rm -rf "$stage_release" mkdir -p "$stage_release" tar -xzf "$archive_path" -C "$stage_release" - chmod 0755 "$stage_release/bin/codex" "$stage_release/codex-path/rg" + chmod 0755 \ + "$stage_release/bin/codex" \ + "$stage_release/bin/codex-code-mode-host" \ + "$stage_release/codex-path/rg" if [ -f "$stage_release/codex-resources/bwrap" ]; then chmod 0755 "$stage_release/codex-resources/bwrap" fi @@ -730,6 +733,7 @@ release_dir_is_complete() { package) [ -f "$release_dir/codex-package.json" ] && [ -x "$release_dir/bin/codex" ] && + [ -x "$release_dir/bin/codex-code-mode-host" ] && [ -x "$release_dir/codex" ] && [ -x "$release_dir/codex-path/rg" ] || return 1 diff --git a/workspace_root_test_launcher.bat.tpl b/workspace_root_test_launcher.bat.tpl index 3613b91d76..00bd6804d8 100644 --- a/workspace_root_test_launcher.bat.tpl +++ b/workspace_root_test_launcher.bat.tpl @@ -7,11 +7,11 @@ if errorlevel 1 exit /b 1 for %%I in ("%workspace_root_marker%") do set "workspace_root_marker_dir=%%~dpI" for %%I in ("%workspace_root_marker_dir%..\..") do set "workspace_root=%%~fI" +__RUNFILE_ENV_EXPORTS__ + call :resolve_runfile test_bin "__TEST_BIN__" if errorlevel 1 exit /b 1 -__RUNFILE_ENV_EXPORTS__ - __WORKSPACE_ROOT_SETUP__ set "TOTAL_SHARDS=%RULES_RUST_TEST_TOTAL_SHARDS%"