mirror of
https://github.com/openai/codex.git
synced 2026-09-17 12:23:33 +00:00
## Why Linux voice needs system ALSA plugins and enough buffering to accommodate PipeWire graph cycles without losing capture samples. Voice startup failures also need actionable diagnostics without exposing native error details. ## What changed - Build and bundle GNU voice helpers and runtimes with primary Linux musl release archives, and sign the archives. Keep Python wheels free of these libraries to preserve `manylinux_2_17` compatibility. - Discover ALSA plugins in fixed system directories and increase Linux capture and playback buffering to support larger PipeWire graph cycles. - Report voice failures by stage, preserve negotiation timeout classification, and discard native error sources. Suppress the misleading `requested` closure message after failure cleanup. - Add explicit Windows MSVC, pkgconf, and CMake toolchain configuration and preserve host architecture in native build environments. ## Testing Add coverage for Linux release assembly, ALSA plugin discovery, PipeWire capture and playback, classified startup failures, failure cleanup rendering, and Windows build environment handling. GitOrigin-RevId: d805eace96a669ce3a4489f12e2db6f68f9f7f53
243 lines
6.7 KiB
Bash
243 lines
6.7 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: build-codex-package-archive.sh \
|
|
--target <rust-target> \
|
|
--bundle <primary|app-server> \
|
|
--entrypoint-dir <dir> \
|
|
--archive-dir <dir> \
|
|
[--bwrap-bin <path>] \
|
|
[--code-mode-host-bin <path>] \
|
|
[--rg-bin <path>] \
|
|
[--zsh-bin <path>] \
|
|
[--zsh-manifest <path>] \
|
|
[--codex-command-runner-bin <path>] \
|
|
[--codex-windows-sandbox-setup-bin <path>] \
|
|
[--voice-release-dir <path> --release-version <release-version>] \
|
|
[--target-suffixed-entrypoint]
|
|
EOF
|
|
}
|
|
|
|
target=""
|
|
bundle=""
|
|
entrypoint_dir=""
|
|
archive_dir=""
|
|
target_suffixed_entrypoint="false"
|
|
resource_args=()
|
|
bwrap_bin_provided="false"
|
|
code_mode_host_bin_provided="false"
|
|
command_runner_bin_provided="false"
|
|
sandbox_setup_bin_provided="false"
|
|
voice_release_dir=""
|
|
release_version=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--target)
|
|
target="${2:?--target requires a value}"
|
|
shift 2
|
|
;;
|
|
--bundle)
|
|
bundle="${2:?--bundle requires a value}"
|
|
shift 2
|
|
;;
|
|
--entrypoint-dir)
|
|
entrypoint_dir="${2:?--entrypoint-dir requires a value}"
|
|
shift 2
|
|
;;
|
|
--archive-dir)
|
|
archive_dir="${2:?--archive-dir requires a value}"
|
|
shift 2
|
|
;;
|
|
--bwrap-bin)
|
|
resource_args+=(--bwrap-bin "${2:?--bwrap-bin requires a value}")
|
|
bwrap_bin_provided="true"
|
|
shift 2
|
|
;;
|
|
--code-mode-host-bin)
|
|
resource_args+=(--code-mode-host-bin "${2:?--code-mode-host-bin requires a value}")
|
|
code_mode_host_bin_provided="true"
|
|
shift 2
|
|
;;
|
|
--rg-bin)
|
|
resource_args+=(--rg-bin "${2:?--rg-bin requires a value}")
|
|
shift 2
|
|
;;
|
|
--zsh-bin)
|
|
resource_args+=(--zsh-bin "${2:?--zsh-bin requires a value}")
|
|
shift 2
|
|
;;
|
|
--zsh-manifest)
|
|
resource_args+=(--zsh-manifest "${2:?--zsh-manifest requires a value}")
|
|
shift 2
|
|
;;
|
|
--codex-command-runner-bin)
|
|
resource_args+=(
|
|
--codex-command-runner-bin
|
|
"${2:?--codex-command-runner-bin requires a value}"
|
|
)
|
|
command_runner_bin_provided="true"
|
|
shift 2
|
|
;;
|
|
--codex-windows-sandbox-setup-bin)
|
|
resource_args+=(
|
|
--codex-windows-sandbox-setup-bin
|
|
"${2:?--codex-windows-sandbox-setup-bin requires a value}"
|
|
)
|
|
sandbox_setup_bin_provided="true"
|
|
shift 2
|
|
;;
|
|
--target-suffixed-entrypoint)
|
|
target_suffixed_entrypoint="true"
|
|
shift
|
|
;;
|
|
--voice-release-dir)
|
|
voice_release_dir="${2:?--voice-release-dir requires a value}"
|
|
shift 2
|
|
;;
|
|
--release-version)
|
|
release_version="${2:?--release-version requires a value}"
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unexpected argument: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$target" || -z "$bundle" || -z "$entrypoint_dir" || -z "$archive_dir" ]]; then
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
if [[ ( -n "$voice_release_dir" || -n "$release_version" ) && ( -z "$voice_release_dir" || -z "$release_version" || "$bundle" != "primary" || ( "$target" != *-apple-darwin && "$target" != *-unknown-linux-musl ) ) ]]; then
|
|
echo "Voice resources require a primary macOS or Linux release package version" >&2
|
|
exit 1
|
|
fi
|
|
|
|
case "$bundle" in
|
|
primary)
|
|
variant="codex"
|
|
entrypoint="codex"
|
|
archive_stem="codex-package"
|
|
;;
|
|
app-server)
|
|
variant="codex-app-server"
|
|
entrypoint="codex-app-server"
|
|
archive_stem="codex-app-server-package"
|
|
;;
|
|
*)
|
|
echo "No Codex package variant for bundle: $bundle" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
exe_suffix=""
|
|
case "$target" in
|
|
*windows*)
|
|
exe_suffix=".exe"
|
|
;;
|
|
esac
|
|
|
|
code_mode_host_bin="${entrypoint_dir%/}/codex-code-mode-host${exe_suffix}"
|
|
if [[ "$code_mode_host_bin_provided" == "false" && -f "$code_mode_host_bin" ]]; then
|
|
resource_args+=(--code-mode-host-bin "$code_mode_host_bin")
|
|
fi
|
|
|
|
entrypoint_name="$entrypoint"
|
|
if [[ "$target_suffixed_entrypoint" == "true" ]]; then
|
|
entrypoint_name="${entrypoint_name}-${target}"
|
|
fi
|
|
|
|
case "$target" in
|
|
*linux*)
|
|
bwrap_bin="${entrypoint_dir%/}/bwrap"
|
|
if [[ "$bwrap_bin_provided" == "false" && -f "$bwrap_bin" ]]; then
|
|
resource_args+=(--bwrap-bin "$bwrap_bin")
|
|
fi
|
|
;;
|
|
*windows*)
|
|
command_runner_bin="${entrypoint_dir%/}/codex-command-runner.exe"
|
|
sandbox_setup_bin="${entrypoint_dir%/}/codex-windows-sandbox-setup.exe"
|
|
if [[ "$command_runner_bin_provided" == "false" && -f "$command_runner_bin" ]]; then
|
|
resource_args+=(--codex-command-runner-bin "$command_runner_bin")
|
|
fi
|
|
if [[ "$sandbox_setup_bin_provided" == "false" && -f "$sandbox_setup_bin" ]]; then
|
|
resource_args+=(--codex-windows-sandbox-setup-bin "$sandbox_setup_bin")
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
repo_root="${GITHUB_WORKSPACE:-}"
|
|
if [[ -z "$repo_root" ]]; then
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
fi
|
|
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
python_bin="python3"
|
|
else
|
|
python_bin="python"
|
|
fi
|
|
|
|
if ! command -v zstd >/dev/null 2>&1 && [[ -x "${repo_root}/.github/workflows/zstd" ]]; then
|
|
export PATH="${repo_root}/.github/workflows:${PATH}"
|
|
fi
|
|
|
|
mkdir -p "$archive_dir"
|
|
package_dir="${RUNNER_TEMP:-/tmp}/${archive_stem}-${target}"
|
|
gzip_archive_path="${archive_dir}/${archive_stem}-${target}.tar.gz"
|
|
zstd_archive_path="${archive_dir}/${archive_stem}-${target}.tar.zst"
|
|
rm -rf "$package_dir"
|
|
|
|
python_args=(
|
|
"${repo_root}/scripts/build_codex_package.py"
|
|
--target "$target"
|
|
--variant "$variant"
|
|
--entrypoint-bin "${entrypoint_dir%/}/${entrypoint_name}${exe_suffix}"
|
|
--cargo-profile release
|
|
--package-dir "$package_dir"
|
|
)
|
|
if [[ -z "$voice_release_dir" ]]; then
|
|
python_args+=(--archive-output "$gzip_archive_path" --archive-output "$zstd_archive_path")
|
|
fi
|
|
if ((${#resource_args[@]} > 0)); then
|
|
python_args+=("${resource_args[@]}")
|
|
fi
|
|
python_args+=(--force)
|
|
|
|
"$python_bin" "${python_args[@]}"
|
|
|
|
if [[ -n "$voice_release_dir" ]]; then
|
|
voice_target="$target"
|
|
if [[ "$target" == *-unknown-linux-musl ]]; then
|
|
voice_target="${target%-musl}-gnu"
|
|
fi
|
|
voice_package="${RUNNER_TEMP:-/tmp}/${archive_stem}-voice-${target}"
|
|
rm -rf "$voice_package"
|
|
"$python_bin" "${repo_root}/third_party/voice/assemble_package.py" \
|
|
--package "$package_dir" \
|
|
--helper "${voice_release_dir%/}/codex-voice-host" \
|
|
--runtime "${voice_release_dir%/}/runtime" \
|
|
--voice-target "$voice_target" \
|
|
--build-commit "$(git -C "$repo_root" rev-parse HEAD)" \
|
|
--release-version "$release_version" \
|
|
--output "$voice_package"
|
|
PYTHONPATH="${repo_root}/scripts" "$python_bin" - \
|
|
"$voice_package" "$gzip_archive_path" "$zstd_archive_path" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
from codex_package.archive import write_archive
|
|
|
|
package = Path(sys.argv[1])
|
|
for archive in sys.argv[2:]:
|
|
write_archive(package, Path(archive), force=True)
|
|
PY
|
|
fi
|