-
Notifications
You must be signed in to change notification settings - Fork 2.3k
fix: resolve Node outside minimal hook PATH #737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
fscfede-beep
wants to merge
13
commits into
openai:main
Choose a base branch
from
fscfede-beep:fix/portable-node-launcher-105
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
8f09814
fix: resolve Node outside minimal hook PATH
31b8b18
fix: preserve compatible Node toolchain PATH
a17c3da
test: tidy Node launcher regressions
cc0ffad
fix: preserve alternate Codex toolchain paths
ef58bf1
fix: discover Windows Node installs in launcher
fscfede-beep 1338ede
fix: complete portable launcher coverage
fscfede-beep a6855f3
fix: honor custom NVM_DIR in launcher
fscfede-beep 64dcef9
fix: align launcher node with codex toolchain
fscfede-beep a420fc0
test: isolate portable launcher environment
fscfede-beep 0ef6b73
fix: honor custom fnm directory
fscfede-beep 2c6b255
fix: honor custom asdf and mise roots
fscfede-beep 11007e4
test: preserve launcher test encoding
fscfede-beep e116d57
fix: honor Linuxbrew prefix in launcher
fscfede-beep File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,234 @@ | ||
| #!/bin/sh | ||
| set -u | ||
|
|
||
| target=${1:-} | ||
| if [ -z "$target" ]; then | ||
| echo "Codex Companion Node launcher requires a script name." >&2 | ||
| exit 64 | ||
| fi | ||
| shift | ||
|
|
||
| case "$0" in | ||
| */*) script_base=${0%/*} ;; | ||
| *) script_base=. ;; | ||
| esac | ||
| script_dir=$(CDPATH= cd -- "$script_base" && pwd) | ||
|
|
||
| is_supported_node() { | ||
| "$1" -e 'const [major, minor] = process.versions.node.split(".").map(Number); process.exit(major > 18 || (major === 18 && minor >= 18) ? 0 : 1)' >/dev/null 2>&1 | ||
| } | ||
|
|
||
| windows_path_to_posix() { | ||
| value=$1 | ||
| [ -n "$value" ] || return 1 | ||
| if command -v cygpath >/dev/null 2>&1; then | ||
| cygpath -u "$value" | ||
| return | ||
| fi | ||
|
|
||
| normalized= | ||
| remaining=$value | ||
| while [ -n "$remaining" ]; do | ||
| char=${remaining%"${remaining#?}"} | ||
| remaining=${remaining#?} | ||
| case "$char" in | ||
| \\) normalized="${normalized}/" ;; | ||
| *) normalized="${normalized}${char}" ;; | ||
| esac | ||
| done | ||
| case "$normalized" in | ||
| [A-Za-z]:/*) | ||
| drive=${normalized%%:*} | ||
| rest=${normalized#?:} | ||
| printf '/%s%s\n' "$drive" "$rest" | ||
| ;; | ||
| *) printf '%s\n' "$normalized" ;; | ||
| esac | ||
| } | ||
|
|
||
| find_windows_node() { | ||
| root= | ||
| if [ -n "${NVM_SYMLINK:-}" ]; then | ||
| root=$(windows_path_to_posix "$NVM_SYMLINK") || root= | ||
| for candidate in "$root/node.exe" "$root/node"; do | ||
| [ -x "$candidate" ] || continue | ||
| is_supported_node "$candidate" || continue | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| done | ||
| fi | ||
| if [ -n "${VOLTA_HOME:-}" ]; then | ||
| root=$(windows_path_to_posix "$VOLTA_HOME") || root= | ||
| for candidate in "$root/bin/node.exe" "$root/bin/node"; do | ||
| [ -x "$candidate" ] || continue | ||
| is_supported_node "$candidate" || continue | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| done | ||
| fi | ||
| if [ -n "${LOCALAPPDATA:-}" ]; then | ||
| root=$(windows_path_to_posix "$LOCALAPPDATA") || root= | ||
| for candidate in "$root/Volta/bin/node.exe" "$root/Volta/bin/node"; do | ||
| [ -x "$candidate" ] || continue | ||
| is_supported_node "$candidate" || continue | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| done | ||
| fi | ||
| program_files=${PROGRAMFILES:-${PROGRAMW6432:-${ProgramFiles:-}}} | ||
| if [ -n "$program_files" ]; then | ||
| root=$(windows_path_to_posix "$program_files") || root= | ||
| for candidate in "$root/nodejs/node.exe" "$root/nodejs/node"; do | ||
| [ -x "$candidate" ] || continue | ||
| is_supported_node "$candidate" || continue | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| done | ||
| fi | ||
| return 1 | ||
| } | ||
|
|
||
| node_dir_has_codex() { | ||
| candidate=$1 | ||
| case "$candidate" in */*) candidate_dir=${candidate%/*} ;; *) candidate_dir=. ;; esac | ||
| [ -x "$candidate_dir/codex" ] || [ -f "$candidate_dir/codex.cmd" ] || [ -f "$candidate_dir/codex.exe" ] | ||
| } | ||
|
|
||
| find_managed_node() { | ||
| require_codex=$1 | ||
| home=${HOME:-} | ||
| nvm_dir=$(windows_path_to_posix "${NVM_DIR:-$home/.nvm}") || nvm_dir= | ||
| fnm_dir=$(windows_path_to_posix "${FNM_DIR:-$home/.local/share/fnm}") || fnm_dir= | ||
| asdf_dir=$(windows_path_to_posix "${ASDF_DATA_DIR:-$home/.asdf}") || asdf_dir= | ||
| mise_dir=$(windows_path_to_posix "${MISE_DATA_DIR:-$home/.local/share/mise}") || mise_dir= | ||
| homebrew_prefix=$(windows_path_to_posix "${HOMEBREW_PREFIX:-}") || homebrew_prefix= | ||
| homebrew_node= | ||
| [ -n "$homebrew_prefix" ] && homebrew_node="$homebrew_prefix/bin/node" | ||
| for candidate in \ | ||
| "$homebrew_node" /home/linuxbrew/.linuxbrew/bin/node /opt/homebrew/bin/node /usr/local/bin/node /opt/local/bin/node \ | ||
| "$home/.volta/bin/node" \ | ||
| "$nvm_dir"/versions/node/*/bin/node \ | ||
| "$fnm_dir"/node-versions/*/installation/bin/node \ | ||
| "$asdf_dir"/installs/nodejs/*/bin/node \ | ||
| "$mise_dir"/installs/node/*/bin/node; do | ||
| [ -x "$candidate" ] || continue | ||
| is_supported_node "$candidate" || continue | ||
| if [ "$require_codex" = "true" ]; then | ||
| node_dir_has_codex "$candidate" || continue | ||
| fi | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| done | ||
| return 1 | ||
| } | ||
|
|
||
| find_node() { | ||
| if [ -n "${CODEX_COMPANION_NODE:-}" ]; then | ||
| configured_node=$(windows_path_to_posix "$CODEX_COMPANION_NODE") || configured_node=$CODEX_COMPANION_NODE | ||
| if [ -x "$configured_node" ] && is_supported_node "$configured_node"; then | ||
| printf '%s\n' "$configured_node" | ||
| return 0 | ||
| fi | ||
| fi | ||
|
|
||
| path_node= | ||
| if command -v node >/dev/null 2>&1; then | ||
| candidate=$(command -v node) | ||
| if is_supported_node "$candidate"; then | ||
| path_node=$candidate | ||
| if command -v codex >/dev/null 2>&1; then | ||
| printf '%s\n' "$path_node" | ||
| return 0 | ||
| fi | ||
| fi | ||
| fi | ||
|
|
||
| if candidate=$(find_managed_node true); then | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| fi | ||
| if [ -n "$path_node" ]; then | ||
| printf '%s\n' "$path_node" | ||
| return 0 | ||
| fi | ||
| if candidate=$(find_managed_node false); then | ||
| printf '%s\n' "$candidate" | ||
| return 0 | ||
| fi | ||
| find_windows_node && return 0 | ||
| return 1 | ||
| } | ||
|
|
||
| node_bin=$(find_node) || { | ||
| echo "Codex Companion requires Node.js >=18.18. Add a supported node to PATH or set CODEX_COMPANION_NODE to its executable path." >&2 | ||
| exit 127 | ||
| } | ||
|
|
||
| add_supported_node_dir_to_path() { | ||
| candidate=$1 | ||
| [ -x "$candidate" ] || return 0 | ||
| is_supported_node "$candidate" || return 0 | ||
| case "$candidate" in */*) candidate_dir=${candidate%/*} ;; *) candidate_dir=. ;; esac | ||
| case ":${PATH:-}:" in *":$candidate_dir:"*) ;; *) PATH="${PATH:-}${PATH:+:}$candidate_dir" ;; esac | ||
| } | ||
|
|
||
| add_dir_to_path() { | ||
| candidate_dir=$1 | ||
| [ -d "$candidate_dir" ] || return 0 | ||
| case ":${PATH:-}:" in *":$candidate_dir:"*) ;; *) PATH="${PATH:-}${PATH:+:}$candidate_dir" ;; esac | ||
| } | ||
|
|
||
| add_npm_prefix_dirs_to_path() { | ||
| prefix=${NPM_CONFIG_PREFIX:-} | ||
| if [ -z "$prefix" ] && command -v npm >/dev/null 2>&1; then | ||
| prefix=$(npm prefix -g 2>/dev/null) || prefix= | ||
| fi | ||
| [ -n "$prefix" ] || return 0 | ||
| prefix=$(windows_path_to_posix "$prefix") || return 0 | ||
| add_dir_to_path "$prefix/bin" | ||
| add_dir_to_path "$prefix" | ||
| } | ||
|
|
||
| add_windows_node_dirs_to_path() { | ||
| root= | ||
| if [ -n "${NVM_SYMLINK:-}" ]; then | ||
| root=$(windows_path_to_posix "$NVM_SYMLINK") || root= | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/node.exe" | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/node" | ||
| fi | ||
| if [ -n "${VOLTA_HOME:-}" ]; then | ||
| root=$(windows_path_to_posix "$VOLTA_HOME") || root= | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/bin/node.exe" | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/bin/node" | ||
| fi | ||
| if [ -n "${LOCALAPPDATA:-}" ]; then | ||
| root=$(windows_path_to_posix "$LOCALAPPDATA") || root= | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/Volta/bin/node.exe" | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/Volta/bin/node" | ||
| fi | ||
| program_files=${PROGRAMFILES:-${PROGRAMW6432:-${ProgramFiles:-}}} | ||
| if [ -n "$program_files" ]; then | ||
| root=$(windows_path_to_posix "$program_files") || root= | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/nodejs/node.exe" | ||
| [ -n "$root" ] && add_supported_node_dir_to_path "$root/nodejs/node" | ||
| fi | ||
| } | ||
|
|
||
| case "$node_bin" in */*) node_dir=${node_bin%/*} ;; *) node_dir=. ;; esac | ||
| PATH="$node_dir${PATH:+:$PATH}" | ||
|
fscfede-beep marked this conversation as resolved.
|
||
| home=${HOME:-} | ||
| nvm_dir=$(windows_path_to_posix "${NVM_DIR:-$home/.nvm}") || nvm_dir= | ||
| fnm_dir=$(windows_path_to_posix "${FNM_DIR:-$home/.local/share/fnm}") || fnm_dir= | ||
| asdf_dir=$(windows_path_to_posix "${ASDF_DATA_DIR:-$home/.asdf}") || asdf_dir= | ||
| mise_dir=$(windows_path_to_posix "${MISE_DATA_DIR:-$home/.local/share/mise}") || mise_dir= | ||
| homebrew_prefix=$(windows_path_to_posix "${HOMEBREW_PREFIX:-}") || homebrew_prefix= | ||
| homebrew_node= | ||
| [ -n "$homebrew_prefix" ] && homebrew_node="$homebrew_prefix/bin/node" | ||
| for candidate in "$homebrew_node" /home/linuxbrew/.linuxbrew/bin/node /opt/homebrew/bin/node /usr/local/bin/node /opt/local/bin/node "$home/.volta/bin/node" "$nvm_dir"/versions/node/*/bin/node "$fnm_dir"/node-versions/*/installation/bin/node "$asdf_dir"/installs/nodejs/*/bin/node "$mise_dir"/installs/node/*/bin/node; do | ||
| add_supported_node_dir_to_path "$candidate" | ||
| done | ||
| add_windows_node_dirs_to_path | ||
| add_npm_prefix_dirs_to_path | ||
| export PATH | ||
|
|
||
| exec "$node_bin" "$script_dir/$target" "$@" | ||
|
fscfede-beep marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.