Fix Codex startup approvals and companion upgrades

This commit is contained in:
Codex
2026-09-05 04:18:41 +00:00
parent 85326d845d
commit b16a9c0ed2
5 changed files with 192 additions and 41 deletions
@@ -1,6 +1,6 @@
--- ---
name: codex-app-server-upgrade name: codex-app-server-upgrade
description: Safely check, update, or self-upgrade the host Codex app-server and Codex CLI binary for this project. Use when asked to upgrade Codex, run app-server update checks, restart Codex after an update, or let Codex invoke its own app-server upgrade through the project script. description: Safely check, update, or self-upgrade the host Codex app-server, Codex CLI binary, and its code-mode host for this project. Use when asked to upgrade Codex, repair or update its code-mode host, run app-server update checks, restart Codex after an update, or let Codex invoke its own app-server upgrade through the project script.
--- ---
# Codex App Server Upgrade # Codex App Server Upgrade
@@ -19,6 +19,14 @@ If the current directory is not the project root, find the nearest repository co
## Commands ## Commands
Start with automatic approval review when needed:
```bash
scripts/start-codex-app-server start --approve-for-me
```
For a durable setting across restarts and upgrades, set `CODEX_APPROVE_FOR_ME=1` in `.env`.
Check status: Check status:
```bash ```bash
@@ -41,7 +49,9 @@ scripts/start-codex-app-server check-updates -y
## Self-Upgrade Behavior ## Self-Upgrade Behavior
When the app-server is running, `check-updates -y` downloads and validates the new Codex binary first, then starts a detached worker to stop the app-server process group, replace the binary, and start the app-server again. This is the correct path even when Codex itself initiated the command. When the app-server is running, `check-updates -y` downloads and validates matching Codex, code-mode host, and Linux `bwrap` binaries from the same release first. It then starts a detached worker to stop the app-server process group, replace all downloaded components, and start the app-server again. Release archives may contain target-suffixed executable names; the installer normalizes them to their stable installed paths.
If Codex is already current but its sibling `codex-code-mode-host` binary is missing, `check-updates` downloads and installs the checked companion binary. On Linux it also repairs the bundled `bwrap` helper when needed.
Expect the current Codex connection or tool call to be interrupted after the handoff. After a short delay, verify the outcome with: Expect the current Codex connection or tool call to be interrupted after the handoff. After a short delay, verify the outcome with:
@@ -57,7 +67,7 @@ sed -n '1,160p' run/codex-app-server-upgrade.log
## Safety Rules ## Safety Rules
- Do not manually `kill`, `mv`, or overwrite the Codex binary for this workflow. - Do not manually `kill`, `mv`, or overwrite the Codex or code-mode host binaries for this workflow.
- Do not assume `/usr/local/bin/codex`, a specific home directory, or any machine-specific path. - Do not assume `/usr/local/bin/codex`, a specific home directory, or any machine-specific path.
- Use `CODEX_BIN=/absolute/path/to/codex` only when the user or environment explicitly requires a non-default binary. - Use `CODEX_BIN=/absolute/path/to/codex` only when the user or environment explicitly requires a non-default binary.
- If the script reports that it cannot replace the binary without write permission, stop and report that non-interactive privileges or a writable `CODEX_BIN` are required. - If the script reports that it cannot replace the binary without write permission, stop and report that non-interactive privileges or a writable `CODEX_BIN` are required.
@@ -1,4 +1,4 @@
interface: interface:
display_name: "Codex App Server Upgrade" display_name: "Codex App Server Upgrade"
short_description: "Safely self-upgrade Codex app-server." short_description: "Safely upgrade Codex and its code-mode host."
default_prompt: "Safely check for and apply a Codex app-server upgrade using the project script." default_prompt: "Use $codex-app-server-upgrade to safely update Codex and its code-mode host."
+2
View File
@@ -18,6 +18,8 @@ DB_DIR=./data
# Leave empty to use Codex defaults. # Leave empty to use Codex defaults.
DEFAULT_MODEL= DEFAULT_MODEL=
DEFAULT_SANDBOX=workspace-write DEFAULT_SANDBOX=workspace-write
# Set to 1 to route approval requests through Codex automatic review.
CODEX_APPROVE_FOR_ME=0
POLL_TIMEOUT_SECONDS=30 POLL_TIMEOUT_SECONDS=30
# Container should usually match the host user so SQLite files remain writable. # Container should usually match the host user so SQLite files remain writable.
+1 -1
View File
@@ -11,7 +11,7 @@ Docker Compose runs only the Go Telegram bot. Codex runs on the host through `co
scripts/start-codex-app-server start scripts/start-codex-app-server start
``` ```
The script supports `start`, `stop`, `status`, `check-updates [-y]`, and the alias `check-upgrade [-y]`. `start` launches Codex detached, writes `run/codex-app-server.pid`, logs to `run/codex-app-server.log`, and is idempotent if the socket is already live. `check-updates` compares the local `codex` binary with the latest OpenAI Codex GitHub release. With `-y`, it downloads and validates the matching platform archive before stopping a running app-server. If the app-server is running, the final stop/replace/start step is handed to a detached worker so the upgrade can complete even when invoked from Codex itself. If the upgraded server fails to start, the worker restores the previous binary and starts it again. The script supports `start [--approve-for-me]`, `stop`, `status`, `check-updates [-y]`, and the alias `check-upgrade [-y]`. `start` launches Codex detached, writes `run/codex-app-server.pid`, logs to `run/codex-app-server.log`, and is idempotent if the socket is already live. `--approve-for-me` routes approval requests through Codex automatic review using the `workspace-write` sandbox. Set `CODEX_APPROVE_FOR_ME=1` in `.env` to retain that setting across restarts and upgrades. `check-updates` compares the local `codex` binary with the latest OpenAI Codex GitHub release. With `-y`, it downloads and validates the matching platform archives for Codex, the code-mode host, and Linux `bwrap` before stopping a running app-server. If the app-server is running, the final stop/replace/start step is handed to a detached worker so the upgrade can complete even when invoked from Codex itself. If the upgraded server fails to start, the worker restores the previous components and starts it again.
3. Add at least one Telegram user and workspace: 3. Add at least one Telegram user and workspace:
+174 -35
View File
@@ -28,6 +28,7 @@ read_env_value() {
HOST_CODEX_SOCKET="${HOST_CODEX_SOCKET:-$(read_env_value HOST_CODEX_SOCKET)}" HOST_CODEX_SOCKET="${HOST_CODEX_SOCKET:-$(read_env_value HOST_CODEX_SOCKET)}"
HOST_CODEX_SOCKET="${HOST_CODEX_SOCKET:-$RUN_DIR/codex.sock}" HOST_CODEX_SOCKET="${HOST_CODEX_SOCKET:-$RUN_DIR/codex.sock}"
CODEX_APPROVE_FOR_ME="${CODEX_APPROVE_FOR_ME:-$(read_env_value CODEX_APPROVE_FOR_ME)}"
mkdir -p "$RUN_DIR" mkdir -p "$RUN_DIR"
chmod 700 "$RUN_DIR" chmod 700 "$RUN_DIR"
@@ -37,15 +38,17 @@ usage() {
Usage: $0 <start|stop|status|check-updates|check-upgrade> [options] Usage: $0 <start|stop|status|check-updates|check-upgrade> [options]
Commands: Commands:
start Start codex app-server if it is not already running. start [--approve-for-me]
Start codex app-server if it is not already running.
stop Stop codex app-server and remove stale runtime files. stop Stop codex app-server and remove stale runtime files.
status Print whether codex app-server is running. status Print whether codex app-server is running.
check-updates [-y] Check GitHub releases and optionally install the latest Codex binary. check-updates [-y] Check GitHub releases and optionally install Codex and its companion binaries.
check-upgrade [-y] Alias for check-updates. check-upgrade [-y] Alias for check-updates.
Environment: Environment:
CODEX_BIN Codex executable to replace. Defaults to the codex found on PATH. CODEX_BIN Codex executable to replace. Defaults to the codex found on PATH.
CODEX_RELEASE_REPO GitHub repo for releases. Defaults to openai/codex. CODEX_RELEASE_REPO GitHub repo for releases. Defaults to openai/codex.
CODEX_APPROVE_FOR_ME Enable automatic approval review when starting Codex (1/true/yes).
USAGE USAGE
} }
@@ -114,7 +117,13 @@ codex_bin() {
} }
start_server() { start_server() {
local old_pid pid start_codex_bin local old_pid pid start_codex_bin approve_for_me
approve_for_me="${1:-$CODEX_APPROVE_FOR_ME}"
case "$approve_for_me" in
1|true|yes|on) approve_for_me=1 ;;
0|false|no|off|"") approve_for_me=0 ;;
*) echo "invalid CODEX_APPROVE_FOR_ME value: $approve_for_me" >&2; return 2 ;;
esac
old_pid="$(pid_from_file)" old_pid="$(pid_from_file)"
if [[ -n "$old_pid" ]] && kill -0 "$old_pid" 2>/dev/null; then if [[ -n "$old_pid" ]] && kill -0 "$old_pid" 2>/dev/null; then
if [[ -S "$HOST_CODEX_SOCKET" ]]; then if [[ -S "$HOST_CODEX_SOCKET" ]]; then
@@ -145,8 +154,12 @@ start_server() {
tail -f /dev/null > "$1" & tail -f /dev/null > "$1" &
writer=$! writer=$!
trap "kill $writer 2>/dev/null || true" EXIT trap "kill $writer 2>/dev/null || true" EXIT
"$4" app-server --listen "$2" < "$1" codex_args=(app-server --listen "$2")
' codex-app-server "$STDIN_FIFO" "unix://$HOST_CODEX_SOCKET" "$PID_FILE" "$start_codex_bin" >> "$LOG_FILE" 2>&1 if [[ "$5" == "1" ]]; then
codex_args=(--approve-for-me "${codex_args[@]}")
fi
"$4" "${codex_args[@]}" < "$1"
' codex-app-server "$STDIN_FIFO" "unix://$HOST_CODEX_SOCKET" "$PID_FILE" "$start_codex_bin" "$approve_for_me" >> "$LOG_FILE" 2>&1
for _ in $(seq 1 50); do for _ in $(seq 1 50); do
[[ -f "$PID_FILE" ]] && break [[ -f "$PID_FILE" ]] && break
@@ -312,6 +325,7 @@ target, path = sys.argv[1], sys.argv[2]
needs_bwrap = "linux" in target needs_bwrap = "linux" in target
codex_asset_name = f"codex-{target}.tar.gz" codex_asset_name = f"codex-{target}.tar.gz"
bwrap_asset_name = f"bwrap-{target}.tar.gz" if needs_bwrap else None bwrap_asset_name = f"bwrap-{target}.tar.gz" if needs_bwrap else None
code_mode_host_asset_name = f"codex-code-mode-host-{target}.tar.gz"
with open(path, "r", encoding="utf-8") as f: with open(path, "r", encoding="utf-8") as f:
release = json.load(f) release = json.load(f)
tag = release.get("tag_name", "") tag = release.get("tag_name", "")
@@ -323,7 +337,11 @@ elif version.startswith("v"):
assets = {asset.get("name"): asset for asset in release.get("assets", [])} assets = {asset.get("name"): asset for asset in release.get("assets", [])}
codex_asset = assets.get(codex_asset_name) codex_asset = assets.get(codex_asset_name)
bwrap_asset = assets.get(bwrap_asset_name) if needs_bwrap else None bwrap_asset = assets.get(bwrap_asset_name) if needs_bwrap else None
required_assets = [(codex_asset_name, codex_asset)] code_mode_host_asset = assets.get(code_mode_host_asset_name)
required_assets = [
(codex_asset_name, codex_asset),
(code_mode_host_asset_name, code_mode_host_asset),
]
if needs_bwrap: if needs_bwrap:
required_assets.append((bwrap_asset_name, bwrap_asset)) required_assets.append((bwrap_asset_name, bwrap_asset))
missing = [name for name, asset in required_assets if asset is None] missing = [name for name, asset in required_assets if asset is None]
@@ -338,6 +356,8 @@ if bwrap_asset is not None:
else: else:
print("") print("")
print("") print("")
print(code_mode_host_asset.get("browser_download_url", ""))
print(code_mode_host_asset.get("digest", ""))
print(version) print(version)
print(tag) print(tag)
PY PY
@@ -399,6 +419,32 @@ extract_bwrap_binary() {
printf '%s\n' "$found" printf '%s\n' "$found"
} }
extract_code_mode_host_binary() {
local archive="$1" dest="$2" found
local -a matches=()
mkdir -p "$dest/code-mode-host-extract"
tar -xzf "$archive" -C "$dest/code-mode-host-extract"
mapfile -d '' -t matches < <(
find "$dest/code-mode-host-extract" -type f \
\( -name codex-code-mode-host -o -name 'codex-code-mode-host-*' \) -print0
)
if [[ "${#matches[@]}" -eq 0 ]]; then
echo "downloaded archive does not contain a code-mode host executable" >&2
return 1
fi
if [[ "${#matches[@]}" -ne 1 ]]; then
echo "downloaded archive contains multiple code-mode host executables" >&2
return 1
fi
found="${matches[0]}"
chmod +x "$found"
if ! "$found" --help >/dev/null 2>&1; then
echo "downloaded code-mode host executable failed validation" >&2
return 1
fi
printf '%s\n' "$found"
}
bundled_bwrap_path() { bundled_bwrap_path() {
local bin="$1" local bin="$1"
printf '%s/codex-resources/bwrap\n' "$(dirname "$bin")" printf '%s/codex-resources/bwrap\n' "$(dirname "$bin")"
@@ -414,6 +460,17 @@ bwrap_required_for_target() {
[[ "$1" == *linux* ]] [[ "$1" == *linux* ]]
} }
code_mode_host_path() {
local bin="$1"
printf '%s/codex-code-mode-host\n' "$(dirname "$bin")"
}
code_mode_host_installed() {
local bin="$1" host
host="$(code_mode_host_path "$bin")"
[[ -x "$host" && ! -L "$host" ]]
}
run_install() { run_install() {
if [[ "${#INSTALL_PREFIX[@]}" -gt 0 ]]; then if [[ "${#INSTALL_PREFIX[@]}" -gt 0 ]]; then
"${INSTALL_PREFIX[@]}" "$@" "${INSTALL_PREFIX[@]}" "$@"
@@ -456,8 +513,27 @@ install_bundled_bwrap() {
run_install mv -f "$tmp_new" "$bundled" run_install mv -f "$tmp_new" "$bundled"
} }
install_code_mode_host() {
local candidate="$1" bin="$2" backup="$3" host host_dir tmp_new host_backup host_missing
host="$(code_mode_host_path "$bin")"
host_dir="$(dirname "$host")"
tmp_new="$host.new.$$"
host_backup="$backup.code-mode-host"
host_missing="$backup.code-mode-host.missing"
run_install mkdir -p "$host_dir"
if [[ -e "$host" ]]; then
run_install cp -p "$host" "$host_backup"
else
run_install touch "$host_missing"
fi
run_install install -m 0755 "$candidate" "$tmp_new"
run_install mv -f "$tmp_new" "$host"
}
install_candidate() { install_candidate() {
local candidate="$1" bwrap_candidate="$2" bin="$3" backup="$4" tmp_new="$bin.new.$$" local candidate="$1" bwrap_candidate="$2" code_mode_host_candidate="$3" bin="$4" backup="$5" tmp_new
tmp_new="$bin.new.$$"
choose_install_prefix "$bin" choose_install_prefix "$bin"
run_install cp -p "$bin" "$backup" run_install cp -p "$bin" "$backup"
run_install install -m 0755 "$candidate" "$tmp_new" run_install install -m 0755 "$candidate" "$tmp_new"
@@ -465,10 +541,11 @@ install_candidate() {
if [[ -n "$bwrap_candidate" ]]; then if [[ -n "$bwrap_candidate" ]]; then
install_bundled_bwrap "$bwrap_candidate" "$bin" "$backup" install_bundled_bwrap "$bwrap_candidate" "$bin" "$backup"
fi fi
install_code_mode_host "$code_mode_host_candidate" "$bin" "$backup"
} }
restore_backup() { restore_backup() {
local bin="$1" backup="$2" tmp_failed="$bin.failed.$$" bundled bwrap_backup bwrap_missing local bin="$1" backup="$2" tmp_failed="$bin.failed.$$" bundled bwrap_backup bwrap_missing host host_backup host_missing
if [[ ! -e "$backup" ]]; then if [[ ! -e "$backup" ]]; then
echo "backup missing; cannot restore $bin" >&2 echo "backup missing; cannot restore $bin" >&2
return 1 return 1
@@ -489,6 +566,17 @@ restore_backup() {
run_install rm -f "$bundled" run_install rm -f "$bundled"
run_install rm -f "$bwrap_missing" run_install rm -f "$bwrap_missing"
fi fi
host="$(code_mode_host_path "$bin")"
host_backup="$backup.code-mode-host"
host_missing="$backup.code-mode-host.missing"
if [[ -e "$host_backup" ]]; then
run_install mkdir -p "$(dirname "$host")"
run_install mv -f "$host_backup" "$host"
elif [[ -e "$host_missing" ]]; then
run_install rm -f "$host"
run_install rm -f "$host_missing"
fi
} }
confirm_upgrade() { confirm_upgrade() {
@@ -506,14 +594,15 @@ confirm_upgrade() {
} }
apply_upgrade() { apply_upgrade() {
local candidate="$1" bwrap_candidate="$2" bin="$3" backup="$4" local_version="$5" latest_version="$6" was_running=0 local candidate="$1" bwrap_candidate="$2" code_mode_host_candidate="$3" bin="$4" backup="$5" local_version="$6" latest_version="$7" was_running=0
if is_running; then if is_running; then
was_running=1 was_running=1
stop_server stop_server
fi fi
if ! install_candidate "$candidate" "$bwrap_candidate" "$bin" "$backup"; then if ! install_candidate "$candidate" "$bwrap_candidate" "$code_mode_host_candidate" "$bin" "$backup"; then
echo "failed to install Codex update" >&2 echo "failed to install Codex update" >&2
restore_backup "$bin" "$backup" || true
if [[ "$was_running" == "1" ]]; then if [[ "$was_running" == "1" ]]; then
start_server || true start_server || true
fi fi
@@ -534,12 +623,12 @@ apply_upgrade() {
} }
handoff_upgrade() { handoff_upgrade() {
local candidate="$1" bwrap_candidate="$2" bin="$3" backup="$4" update_dir="$5" local_version="$6" latest_version="$7" local candidate="$1" bwrap_candidate="$2" code_mode_host_candidate="$3" bin="$4" backup="$5" update_dir="$6" local_version="$7" latest_version="$8"
: > "$UPGRADE_LOG_FILE" : > "$UPGRADE_LOG_FILE"
setsid -f bash -c ' setsid -f bash -c '
sleep 1 sleep 1
"$0" __apply-upgrade "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$0" __apply-upgrade "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8"
' "$0" "$candidate" "$bwrap_candidate" "$bin" "$backup" "$update_dir" "$local_version" "$latest_version" >> "$UPGRADE_LOG_FILE" 2>&1 ' "$0" "$candidate" "$bwrap_candidate" "$code_mode_host_candidate" "$bin" "$backup" "$update_dir" "$local_version" "$latest_version" >> "$UPGRADE_LOG_FILE" 2>&1
echo "Codex upgrade handoff started; app-server will restart if replacement succeeds. log=$UPGRADE_LOG_FILE" echo "Codex upgrade handoff started; app-server will restart if replacement succeeds. log=$UPGRADE_LOG_FILE"
} }
@@ -559,8 +648,8 @@ check_updates() {
require_cmd python3 require_cmd python3
require_cmd ps require_cmd ps
local bin local_version target json latest_version latest_tag codex_download_url codex_digest bwrap_download_url bwrap_digest local bin local_version target json latest_version latest_tag codex_download_url codex_digest bwrap_download_url bwrap_digest code_mode_host_download_url code_mode_host_digest
local codex_archive bwrap_archive tmp candidate bwrap_candidate candidate_version backup local codex_archive bwrap_archive code_mode_host_archive tmp candidate bwrap_candidate code_mode_host_candidate candidate_version backup missing_bwrap missing_code_mode_host
bin="$(codex_bin)" bin="$(codex_bin)"
if [[ -z "$bin" ]]; then if [[ -z "$bin" ]]; then
echo "codex executable not found; set CODEX_BIN" >&2 echo "codex executable not found; set CODEX_BIN" >&2
@@ -585,8 +674,10 @@ check_updates() {
codex_digest="${release_info[1]:-}" codex_digest="${release_info[1]:-}"
bwrap_download_url="${release_info[2]:-}" bwrap_download_url="${release_info[2]:-}"
bwrap_digest="${release_info[3]:-}" bwrap_digest="${release_info[3]:-}"
latest_version="${release_info[4]:-}" code_mode_host_download_url="${release_info[4]:-}"
latest_tag="${release_info[5]:-}" code_mode_host_digest="${release_info[5]:-}"
latest_version="${release_info[6]:-}"
latest_tag="${release_info[7]:-}"
if [[ -z "$latest_version" || -z "$codex_download_url" ]]; then if [[ -z "$latest_version" || -z "$codex_download_url" ]]; then
rm -rf "$tmp" rm -rf "$tmp"
echo "could not determine latest Codex release for $target" >&2 echo "could not determine latest Codex release for $target" >&2
@@ -597,28 +688,59 @@ check_updates() {
echo "could not determine latest bundled bwrap release for $target" >&2 echo "could not determine latest bundled bwrap release for $target" >&2
return 1 return 1
fi fi
if [[ -z "$code_mode_host_download_url" ]]; then
rm -rf "$tmp"
echo "could not determine latest code-mode host release for $target" >&2
return 1
fi
if ! version_gt "$latest_version" "$local_version"; then if ! version_gt "$latest_version" "$local_version"; then
if ! bwrap_required_for_target "$target" || bundled_bwrap_installed "$bin"; then missing_bwrap=0
missing_code_mode_host=0
if bwrap_required_for_target "$target" && ! bundled_bwrap_installed "$bin"; then
missing_bwrap=1
fi
if ! code_mode_host_installed "$bin"; then
missing_code_mode_host=1
fi
if [[ "$missing_bwrap" == "0" && "$missing_code_mode_host" == "0" ]]; then
rm -rf "$tmp" rm -rf "$tmp"
echo "Codex is already current: $local_version (latest $latest_version)" echo "Codex is already current: $local_version (latest $latest_version)"
return 0 return 0
fi fi
echo "Codex is already current: $local_version (latest $latest_version); installing missing bundled bwrap" echo "Codex is already current: $local_version (latest $latest_version); installing missing companion binaries"
bwrap_archive="$tmp/bwrap-$target.tar.gz" bwrap_candidate=""
curl -fL "$bwrap_download_url" -o "$bwrap_archive" code_mode_host_candidate=""
verify_digest "$bwrap_archive" "$bwrap_digest" if [[ "$missing_bwrap" == "1" ]]; then
bwrap_candidate="$(extract_bwrap_binary "$bwrap_archive" "$tmp")" bwrap_archive="$tmp/bwrap-$target.tar.gz"
curl -fL "$bwrap_download_url" -o "$bwrap_archive"
verify_digest "$bwrap_archive" "$bwrap_digest"
bwrap_candidate="$(extract_bwrap_binary "$bwrap_archive" "$tmp")"
fi
if [[ "$missing_code_mode_host" == "1" ]]; then
code_mode_host_archive="$tmp/codex-code-mode-host-$target.tar.gz"
curl -fL "$code_mode_host_download_url" -o "$code_mode_host_archive"
verify_digest "$code_mode_host_archive" "$code_mode_host_digest"
code_mode_host_candidate="$(extract_code_mode_host_binary "$code_mode_host_archive" "$tmp")"
fi
backup="$bin.bak.$(date -u +%Y%m%d%H%M%S)" backup="$bin.bak.$(date -u +%Y%m%d%H%M%S)"
choose_install_prefix "$bin" choose_install_prefix "$bin"
if install_bundled_bwrap "$bwrap_candidate" "$bin" "$backup"; then if [[ -n "$bwrap_candidate" ]]; then
install_bundled_bwrap "$bwrap_candidate" "$bin" "$backup"
run_install rm -f "$backup.bwrap.missing" run_install rm -f "$backup.bwrap.missing"
rm -rf "$tmp" fi
echo "Bundled bwrap installed: $(bundled_bwrap_path "$bin")" if [[ -n "$code_mode_host_candidate" ]]; then
return 0 install_code_mode_host "$code_mode_host_candidate" "$bin" "$backup"
run_install rm -f "$backup.code-mode-host.missing"
fi fi
rm -rf "$tmp" rm -rf "$tmp"
return 1 if [[ "$missing_bwrap" == "1" ]]; then
echo "Bundled bwrap installed: $(bundled_bwrap_path "$bin")"
fi
if [[ "$missing_code_mode_host" == "1" ]]; then
echo "Code-mode host installed: $(code_mode_host_path "$bin")"
fi
return 0
fi fi
echo "Codex update available: $local_version -> $latest_version ($latest_tag)" echo "Codex update available: $local_version -> $latest_version ($latest_tag)"
confirm_upgrade "$local_version" "$latest_version" "$bin" confirm_upgrade "$local_version" "$latest_version" "$bin"
@@ -635,6 +757,10 @@ check_updates() {
else else
bwrap_candidate="" bwrap_candidate=""
fi fi
code_mode_host_archive="$tmp/codex-code-mode-host-$target.tar.gz"
curl -fL "$code_mode_host_download_url" -o "$code_mode_host_archive"
verify_digest "$code_mode_host_archive" "$code_mode_host_digest"
code_mode_host_candidate="$(extract_code_mode_host_binary "$code_mode_host_archive" "$tmp")"
candidate_version="$(codex_version_from "$candidate")" candidate_version="$(codex_version_from "$candidate")"
if [[ "$candidate_version" != "$latest_version" ]]; then if [[ "$candidate_version" != "$latest_version" ]]; then
rm -rf "$tmp" rm -rf "$tmp"
@@ -646,11 +772,11 @@ check_updates() {
choose_install_prefix "$bin" choose_install_prefix "$bin"
if is_running; then if is_running; then
handoff_upgrade "$candidate" "$bwrap_candidate" "$bin" "$backup" "$tmp" "$local_version" "$latest_version" handoff_upgrade "$candidate" "$bwrap_candidate" "$code_mode_host_candidate" "$bin" "$backup" "$tmp" "$local_version" "$latest_version"
return 0 return 0
fi fi
if apply_upgrade "$candidate" "$bwrap_candidate" "$bin" "$backup" "$local_version" "$latest_version"; then if apply_upgrade "$candidate" "$bwrap_candidate" "$code_mode_host_candidate" "$bin" "$backup" "$local_version" "$latest_version"; then
rm -rf "$tmp" rm -rf "$tmp"
return 0 return 0
fi fi
@@ -659,7 +785,7 @@ check_updates() {
} }
apply_upgrade_worker() { apply_upgrade_worker() {
local candidate="$1" bwrap_candidate="$2" bin="$3" backup="$4" update_dir="$5" local_version="$6" latest_version="$7" rc=0 local candidate="$1" bwrap_candidate="$2" code_mode_host_candidate="$3" bin="$4" backup="$5" update_dir="$6" local_version="$7" latest_version="$8" rc=0
if [[ ! -x "$candidate" ]]; then if [[ ! -x "$candidate" ]]; then
echo "upgrade candidate is missing or not executable: $candidate" >&2 echo "upgrade candidate is missing or not executable: $candidate" >&2
rm -rf "$update_dir" rm -rf "$update_dir"
@@ -670,7 +796,12 @@ apply_upgrade_worker() {
rm -rf "$update_dir" rm -rf "$update_dir"
return 1 return 1
fi fi
if ! apply_upgrade "$candidate" "$bwrap_candidate" "$bin" "$backup" "$local_version" "$latest_version"; then if [[ ! -x "$code_mode_host_candidate" ]]; then
echo "code-mode host candidate is missing or not executable: $code_mode_host_candidate" >&2
rm -rf "$update_dir"
return 1
fi
if ! apply_upgrade "$candidate" "$bwrap_candidate" "$code_mode_host_candidate" "$bin" "$backup" "$local_version" "$latest_version"; then
rc=1 rc=1
fi fi
rm -rf "$update_dir" rm -rf "$update_dir"
@@ -681,8 +812,16 @@ cmd="${1:-help}"
case "$cmd" in case "$cmd" in
start) start)
shift || true shift || true
if [[ $# -ne 0 ]]; then usage; exit 2; fi start_approve_for_me="$CODEX_APPROVE_FOR_ME"
start_server while [[ $# -gt 0 ]]; do
case "$1" in
--approve-for-me) start_approve_for_me=1 ;;
-h|--help) usage; exit 0 ;;
*) echo "unknown start option: $1" >&2; usage; exit 2 ;;
esac
shift
done
start_server "$start_approve_for_me"
;; ;;
stop) stop)
shift || true shift || true
@@ -700,7 +839,7 @@ case "$cmd" in
;; ;;
__apply-upgrade) __apply-upgrade)
shift || true shift || true
if [[ $# -ne 7 ]]; then echo "invalid upgrade worker arguments" >&2; exit 2; fi if [[ $# -ne 8 ]]; then echo "invalid upgrade worker arguments" >&2; exit 2; fi
apply_upgrade_worker "$@" apply_upgrade_worker "$@"
;; ;;
-h|--help|help) -h|--help|help)