From d37772d67c1106b50a2bca56912c2b9920a1c829 Mon Sep 17 00:00:00 2001 From: delta-cloud-208e Date: Sun, 8 Mar 2026 10:51:56 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20wrapper=20scripts=20for=20all=20CLIs=20?= =?UTF-8?q?=E2=80=94=20env=20vars=20work=20immediately=20without=20source?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: `sudo bash install.sh` runs in child process, `export` inside it never reaches the user's current shell. /etc/environment and /etc/profile.d/ only work for NEW sessions. So `codex`/`gemini`/`qwen` fail with "Missing environment variable" right after install. Solution: wrapper scripts that auto-source env file before exec'ing binary. - codex: /usr/local/bin/codex (wrapper) -> /usr/local/bin/.codex-bin (real) - gemini: /usr/local/bin/gemini (wrapper) -> node .../dist/index.js - qwen: /usr/local/bin/qwen (wrapper) -> node .../dist/index.js Works immediately in ANY shell, no manual `source` needed. Co-Authored-By: Claude Opus 4.6 --- codex/ucodex_install.sh | 65 +++++++++++++++++++++------------ codex/ucodex_update.sh | 51 ++++++++++++++++---------- gemini/ugemini_install.sh | 56 ++++++++++++++++++++++------- gemini/ugemini_update.sh | 47 +++++++++++++++++------- qwen/uqwen_install.sh | 76 ++++++++++++++++++++++++++++----------- qwen/uqwen_update.sh | 63 ++++++++++++++++++++++++++------ 6 files changed, 260 insertions(+), 98 deletions(-) diff --git a/codex/ucodex_install.sh b/codex/ucodex_install.sh index aff1c7f..ff1cc89 100755 --- a/codex/ucodex_install.sh +++ b/codex/ucodex_install.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # UnlimitedCoding — Codex CLI Installer # Downloads Codex binary from GitHub + applies config patches +# Uses wrapper script so env vars work immediately in any shell. # # Usage: # curl -fsSL -H "Authorization: token TOKEN" \ @@ -12,6 +13,10 @@ GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" REPO_RAW="https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/codex" GITHUB_API="https://api.github.com/repos/openai/codex/releases/latest" +CODEX_BIN="/usr/local/bin/.codex-bin" +CODEX_WRAPPER="/usr/local/bin/codex" +ENV_FILE="/etc/profile.d/codex-env.sh" + RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' @@ -66,9 +71,16 @@ if [ -z "$LATEST_VER" ]; then fi info "Latest version: $LATEST_VER ($BINARY_SUFFIX)" +# Migrate: if old codex is a real binary (not our wrapper), move it +if [ -f "$CODEX_WRAPPER" ] && file "$CODEX_WRAPPER" | grep -q "ELF"; then + info "Migrating existing binary to $CODEX_BIN..." + mv -f "$CODEX_WRAPPER" "$CODEX_BIN" +fi + +# Get current version (from real binary) OLD_VER="not installed" -if command -v codex &>/dev/null; then - OLD_VER=$(codex --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") +if [ -f "$CODEX_BIN" ]; then + OLD_VER=$("$CODEX_BIN" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") info "Current version: $OLD_VER" fi @@ -90,14 +102,13 @@ else fi pkill -9 -x "codex" 2>/dev/null || true - CODEX_PATH=$(which codex 2>/dev/null || echo "/usr/local/bin/codex") chmod +x "$BINARY_FILE" - mv -f "$BINARY_FILE" "$CODEX_PATH" + mv -f "$BINARY_FILE" "$CODEX_BIN" rm -rf "$TEMP_BIN" hash -r 2>/dev/null || true - NEW_VER=$(codex --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") - log "Binary installed: $OLD_VER → $NEW_VER" + NEW_VER=$("$CODEX_BIN" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") + log "Binary installed: $OLD_VER -> $NEW_VER" fi # ---- Step 2: Download and apply patches ---- @@ -116,14 +127,14 @@ info "Applying patches..." python3 "$INSTALL_DIR/codex_patcher.py" --apply --config "$INSTALL_DIR/codex_config.json" log "Patches applied" -# ---- Step 3: Set env vars system-wide (all users, all sessions) ---- +# ---- Step 3: Set env vars system-wide ---- echo -e "\n${BOLD}Step 3: Setting environment variables...${NC}" API_KEY=$(python3 -c "import json; print(json.load(open('$INSTALL_DIR/codex_config.json'))['api_key'])") BASE_URL=$(python3 -c "import json; print(json.load(open('$INSTALL_DIR/codex_config.json'))['base_url'])") -# Write to /etc/environment (all users, all sessions including cron) +# /etc/environment (all users, all sessions including cron) ETC_ENV="/etc/environment" for kv in "OPENAI_API_KEY=\"$API_KEY\"" "OPENAI_BASE_URL=\"${BASE_URL}/v1\""; do KEY="${kv%%=*}" @@ -133,34 +144,42 @@ for kv in "OPENAI_API_KEY=\"$API_KEY\"" "OPENAI_BASE_URL=\"${BASE_URL}/v1\""; do echo "$kv" >> "$ETC_ENV" fi done -log "Env vars written to $ETC_ENV (all users)" +log "Env vars written to $ETC_ENV" -# Write to /etc/profile.d/ for export in login shells -cat > /etc/profile.d/codex-env.sh << ENVEOF +# /etc/profile.d/ (login shells) +cat > "$ENV_FILE" << ENVEOF export OPENAI_API_KEY="$API_KEY" export OPENAI_BASE_URL="${BASE_URL}/v1" ENVEOF -chmod 644 /etc/profile.d/codex-env.sh -log "Export script created: /etc/profile.d/codex-env.sh" +chmod 644 "$ENV_FILE" +log "Env file: $ENV_FILE" -# Export for current session -export OPENAI_API_KEY="$API_KEY" -export OPENAI_BASE_URL="${BASE_URL}/v1" +# ---- Step 4: Create wrapper (auto-loads env) ---- -# ---- Step 4: Verify ---- +echo -e "\n${BOLD}Step 4: Creating wrapper...${NC}" -echo -e "\n${BOLD}Step 4: Verifying...${NC}" +cat > "$CODEX_WRAPPER" << 'WRAPPER_EOF' +#!/usr/bin/env bash +# Auto-generated wrapper — loads env vars before running codex binary +[ -f /etc/profile.d/codex-env.sh ] && . /etc/profile.d/codex-env.sh +exec /usr/local/bin/.codex-bin "$@" +WRAPPER_EOF +chmod +x "$CODEX_WRAPPER" +log "Wrapper: $CODEX_WRAPPER -> $CODEX_BIN" -if command -v codex &>/dev/null; then +# ---- Step 5: Verify ---- + +echo -e "\n${BOLD}Step 5: Verifying...${NC}" + +if codex --version &>/dev/null; then VER=$(codex --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") - log "Codex CLI v$VER" + log "Codex CLI v$VER (wrapper OK)" else - err "codex binary not found in PATH" + err "codex wrapper not working" exit 1 fi echo "" echo -e "${GREEN}${BOLD}=== Installation complete! ===${NC}" echo -e "Run: ${CYAN}codex${NC} to start" -echo -e "${YELLOW}Note: Env vars are set system-wide. New shells pick them up automatically.${NC}" -echo -e "${YELLOW}For current shell: source /etc/profile.d/codex-env.sh${NC}" +echo -e "${YELLOW}Env vars auto-loaded by wrapper. Works in any shell immediately.${NC}" diff --git a/codex/ucodex_update.sh b/codex/ucodex_update.sh index 29840a8..f1f292c 100644 --- a/codex/ucodex_update.sh +++ b/codex/ucodex_update.sh @@ -1,13 +1,19 @@ #!/usr/bin/env bash # Codex CLI — Updater # Downloads latest binary from GitHub + re-applies config patches. +# Uses wrapper script so env vars work immediately in any shell. # # Usage: sudo bash ucodex_update.sh set -euo pipefail +GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" REPO_RAW="https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/codex" GITHUB_API="https://api.github.com/repos/openai/codex/releases/latest" +CODEX_BIN="/usr/local/bin/.codex-bin" +CODEX_WRAPPER="/usr/local/bin/codex" +ENV_FILE="/etc/profile.d/codex-env.sh" + GREEN="\033[92m" CYAN="\033[96m" YELLOW="\033[93m" @@ -26,11 +32,18 @@ echo " | Codex CLI — Updater |" echo " +--------------------------------------+" echo -e "${RESET}" +# ---- Migrate old direct binary if needed ---- + +if [ -f "$CODEX_WRAPPER" ] && file "$CODEX_WRAPPER" | grep -q "ELF"; then + info "Migrating old binary to $CODEX_BIN..." + mv -f "$CODEX_WRAPPER" "$CODEX_BIN" +fi + # ---- Check current version ---- OLD_VER="not installed" -if command -v codex &>/dev/null; then - OLD_VER=$(codex --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") +if [ -f "$CODEX_BIN" ]; then + OLD_VER=$("$CODEX_BIN" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") info "Current version: $OLD_VER" fi @@ -48,7 +61,6 @@ info "Latest version: $LATEST_VER" if [ "$OLD_VER" = "$LATEST_VER" ]; then log "Already up to date ($LATEST_VER)" else - # ---- Download binary ---- ARCH=$(uname -m) case "$ARCH" in x86_64) BINARY_SUFFIX="x86_64-unknown-linux-musl" ;; @@ -63,7 +75,6 @@ else curl -L -# -o "$TEMP_DIR/codex.tar.gz" "$DOWNLOAD_URL" tar -xzf "$TEMP_DIR/codex.tar.gz" -C "$TEMP_DIR" - # Find binary BINARY_FILE=$(find "$TEMP_DIR" -maxdepth 1 -name 'codex*' -type f ! -name '*.gz' | head -1) if [ -z "$BINARY_FILE" ]; then err "Binary not found in archive" @@ -71,18 +82,14 @@ else exit 1 fi - # Kill running processes pkill -9 -x "codex" 2>/dev/null || true - - # Install - CODEX_PATH=$(which codex 2>/dev/null || echo "/usr/local/bin/codex") chmod +x "$BINARY_FILE" - mv -f "$BINARY_FILE" "$CODEX_PATH" + mv -f "$BINARY_FILE" "$CODEX_BIN" rm -rf "$TEMP_DIR" hash -r 2>/dev/null || true - NEW_VER=$(codex --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") - log "Binary updated: $OLD_VER → $NEW_VER" + NEW_VER=$("$CODEX_BIN" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") + log "Binary updated: $OLD_VER -> $NEW_VER" fi # ---- Download and apply patches ---- @@ -92,14 +99,14 @@ cleanup() { rm -rf "$PATCH_DIR" 2>/dev/null || true; } trap cleanup EXIT info "Downloading patcher..." -GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" "$REPO_RAW/codex_patcher.py" -o "$PATCH_DIR/codex_patcher.py" curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" "$REPO_RAW/codex_config.json" -o "$PATCH_DIR/codex_config.json" info "Applying patches..." python3 "$PATCH_DIR/codex_patcher.py" --apply --config "$PATCH_DIR/codex_config.json" -# Set env vars system-wide (all users, all sessions) +# ---- Set env vars system-wide ---- + API_KEY=$(python3 -c "import json; print(json.load(open('$PATCH_DIR/codex_config.json'))['api_key'])") BASE_URL=$(python3 -c "import json; print(json.load(open('$PATCH_DIR/codex_config.json'))['base_url'])") @@ -113,17 +120,23 @@ for kv in "OPENAI_API_KEY=\"$API_KEY\"" "OPENAI_BASE_URL=\"${BASE_URL}/v1\""; do fi done -cat > /etc/profile.d/codex-env.sh << ENVEOF +cat > "$ENV_FILE" << ENVEOF export OPENAI_API_KEY="$API_KEY" export OPENAI_BASE_URL="${BASE_URL}/v1" ENVEOF -chmod 644 /etc/profile.d/codex-env.sh +chmod 644 "$ENV_FILE" -export OPENAI_API_KEY="$API_KEY" -export OPENAI_BASE_URL="${BASE_URL}/v1" +# ---- Create/update wrapper ---- -info "Env vars set system-wide (/etc/environment + /etc/profile.d/codex-env.sh)" +cat > "$CODEX_WRAPPER" << 'WRAPPER_EOF' +#!/usr/bin/env bash +[ -f /etc/profile.d/codex-env.sh ] && . /etc/profile.d/codex-env.sh +exec /usr/local/bin/.codex-bin "$@" +WRAPPER_EOF +chmod +x "$CODEX_WRAPPER" + +info "Env vars + wrapper updated" log "Update complete!" -echo -e "For current shell: ${CYAN}source /etc/profile.d/codex-env.sh${RESET}" +echo -e "Codex works immediately — no need to source anything." echo "" diff --git a/gemini/ugemini_install.sh b/gemini/ugemini_install.sh index 709ec7c..bcf1b8d 100755 --- a/gemini/ugemini_install.sh +++ b/gemini/ugemini_install.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash # Gemini CLI — One-line installer +# Uses wrapper script so env vars work immediately in any shell. +# # Usage: # curl -fsSL -H "Authorization: token TOKEN" \ # https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/gemini/ugemini_install.sh \ @@ -12,6 +14,9 @@ REGISTRY_URL="https://npm.sensey24.ru/" NPM_SCOPE="@google" NPM_PACKAGE="@google/gemini-cli" +ENV_FILE="/etc/profile.d/gemini-cli.sh" +WRAPPER_PATH="/usr/local/bin/gemini" + GREEN="\033[92m" RED="\033[91m" CYAN="\033[96m" @@ -24,6 +29,34 @@ err() { echo -e "${RED}[!]${RESET} $*" >&2; } info() { echo -e "${CYAN}[i]${RESET} $*"; } warn() { echo -e "${YELLOW}[~]${RESET} $*"; } +create_wrapper() { + # Find real entry point (npm symlink target) + local real_bin + real_bin=$(readlink -f "$WRAPPER_PATH" 2>/dev/null || true) + + if [ -z "$real_bin" ] || [ "$real_bin" = "$WRAPPER_PATH" ]; then + # Try to find it in node_modules + local npm_root + npm_root=$(npm root -g 2>/dev/null || echo "/usr/lib/node_modules") + real_bin="$npm_root/@google/gemini-cli/dist/index.js" + fi + + if [ ! -f "$real_bin" ]; then + warn "Could not find gemini entry point at $real_bin" + return 1 + fi + + # Remove symlink, create wrapper + rm -f "$WRAPPER_PATH" + cat > "$WRAPPER_PATH" << WEOF +#!/usr/bin/env bash +[ -f $ENV_FILE ] && . $ENV_FILE +exec node "$real_bin" "\$@" +WEOF + chmod +x "$WRAPPER_PATH" + log "Wrapper: $WRAPPER_PATH -> $real_bin" +} + echo -e "${BOLD}" echo " +--------------------------------------+" echo " | Gemini CLI — Installer |" @@ -47,14 +80,12 @@ install_pkg() { fi } -# Python3 if ! command -v python3 &>/dev/null; then info "python3 not found, installing..." install_pkg python3 fi log "Python3 $(python3 --version | awk '{print $2}')" -# curl if ! command -v curl &>/dev/null; then info "curl not found, installing..." install_pkg curl @@ -173,7 +204,6 @@ assert d.get('security',{}).get('auth',{}).get('selectedType') == 'gemini-api-ke "general": { "defaultApprovalMode": "yolo" } } SETTINGS_EOF - # Trust common folders TRUSTED_FILE="$GEMINI_DIR/trustedFolders.json" python3 -c " import json, os @@ -190,13 +220,12 @@ else log "Settings already configured" fi -# ---- Set environment variables (system-wide, all users) ---- +# ---- Set environment variables (system-wide) ---- info "Setting environment variables..." API_KEY=$(python3 -c "import json; print(json.load(open('$INSTALL_DIR/gemini_config.json'))['api_key'])") BASE_URL=$(python3 -c "import json; print(json.load(open('$INSTALL_DIR/gemini_config.json'))['base_url'])") -# Write to /etc/environment (all users, all sessions including cron) ETC_ENV="/etc/environment" for kv in "GEMINI_API_KEY=\"$API_KEY\"" "GOOGLE_GEMINI_BASE_URL=\"$BASE_URL\""; do KEY="${kv%%=*}" @@ -206,17 +235,19 @@ for kv in "GEMINI_API_KEY=\"$API_KEY\"" "GOOGLE_GEMINI_BASE_URL=\"$BASE_URL\""; echo "$kv" >> "$ETC_ENV" fi done -log "Env vars written to $ETC_ENV (all users)" +log "Env vars written to $ETC_ENV" -# Write to /etc/profile.d/ for export in login shells -cat > /etc/profile.d/gemini-cli.sh << PROF_EOF +cat > "$ENV_FILE" << PROF_EOF export GEMINI_API_KEY="$API_KEY" export GOOGLE_GEMINI_BASE_URL="$BASE_URL" PROF_EOF -chmod 644 /etc/profile.d/gemini-cli.sh -log "Export script created: /etc/profile.d/gemini-cli.sh" +chmod 644 "$ENV_FILE" +log "Env file: $ENV_FILE" -# Export for current session +# ---- Create wrapper (auto-loads env) ---- + +info "Creating wrapper..." +create_wrapper export GEMINI_API_KEY="$API_KEY" export GOOGLE_GEMINI_BASE_URL="$BASE_URL" @@ -238,13 +269,12 @@ if echo "$RESULT" | grep -qi "OK"; then echo " gemini-2.5-pro, gemini-2.5-flash" echo " gemini-3-flash, gemini-3.1-pro" echo "" - echo " If env vars not active, run: source /etc/profile.d/gemini-cli.sh" + echo " Env vars auto-loaded by wrapper. Works in any shell." echo "" else warn "Patches applied but test prompt failed." echo " Response: $RESULT" echo "" echo " Try manually:" - echo " source /etc/profile.d/gemini-cli.sh" echo " gemini -p 'Hello'" fi diff --git a/gemini/ugemini_update.sh b/gemini/ugemini_update.sh index 6c055db..a8e0cb2 100644 --- a/gemini/ugemini_update.sh +++ b/gemini/ugemini_update.sh @@ -1,16 +1,20 @@ #!/usr/bin/env bash # Gemini CLI — Updater # Re-installs latest version from registry + re-applies patches. +# Uses wrapper script so env vars work immediately in any shell. # # Usage: sudo bash ugemini_update.sh -# Or: curl -fsSL URL -o /tmp/ugemini_update.sh && sudo bash /tmp/ugemini_update.sh set -euo pipefail +GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" REGISTRY_URL="https://npm.sensey24.ru/" NPM_SCOPE="@google" NPM_PACKAGE="@google/gemini-cli" REPO_RAW="https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/gemini" +ENV_FILE="/etc/profile.d/gemini-cli.sh" +WRAPPER_PATH="/usr/local/bin/gemini" + GREEN="\033[92m" CYAN="\033[96m" YELLOW="\033[93m" @@ -23,6 +27,26 @@ info() { echo -e "${CYAN}[i]${RESET} $*"; } warn() { echo -e "${YELLOW}[~]${RESET} $*"; } err() { echo -e "${RED}[!]${RESET} $*" >&2; } +create_wrapper() { + local npm_root + npm_root=$(npm root -g 2>/dev/null || echo "/usr/lib/node_modules") + local real_bin="$npm_root/@google/gemini-cli/dist/index.js" + + if [ ! -f "$real_bin" ]; then + warn "Could not find gemini entry point at $real_bin" + return 1 + fi + + rm -f "$WRAPPER_PATH" + cat > "$WRAPPER_PATH" << WEOF +#!/usr/bin/env bash +[ -f $ENV_FILE ] && . $ENV_FILE +exec node "$real_bin" "\$@" +WEOF + chmod +x "$WRAPPER_PATH" + log "Wrapper: $WRAPPER_PATH -> $real_bin" +} + echo -e "${BOLD}" echo " +--------------------------------------+" echo " | Gemini CLI — Updater |" @@ -54,9 +78,6 @@ else exit 1 fi -NEW_VER=$(gemini --version 2>/dev/null || echo "unknown") -log "Version: $OLD_VER → $NEW_VER" - # ---- Download and apply patches ---- TEMP_DIR=$(mktemp -d) @@ -64,14 +85,14 @@ cleanup() { rm -rf "$TEMP_DIR" 2>/dev/null || true; } trap cleanup EXIT info "Downloading patcher..." -GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" "$REPO_RAW/gemini_patcher.py" -o "$TEMP_DIR/gemini_patcher.py" curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" "$REPO_RAW/gemini_config.json" -o "$TEMP_DIR/gemini_config.json" info "Applying patches..." python3 "$TEMP_DIR/gemini_patcher.py" --apply --config "$TEMP_DIR/gemini_config.json" -# Set env vars system-wide (all users, all sessions) +# ---- Set env vars system-wide ---- + API_KEY=$(python3 -c "import json; print(json.load(open('$TEMP_DIR/gemini_config.json'))['api_key'])") BASE_URL=$(python3 -c "import json; print(json.load(open('$TEMP_DIR/gemini_config.json'))['base_url'])") @@ -85,17 +106,19 @@ for kv in "GEMINI_API_KEY=\"$API_KEY\"" "GOOGLE_GEMINI_BASE_URL=\"$BASE_URL\""; fi done -cat > /etc/profile.d/gemini-cli.sh << PROF_EOF +cat > "$ENV_FILE" << PROF_EOF export GEMINI_API_KEY="$API_KEY" export GOOGLE_GEMINI_BASE_URL="$BASE_URL" PROF_EOF -chmod 644 /etc/profile.d/gemini-cli.sh +chmod 644 "$ENV_FILE" -export GEMINI_API_KEY="$API_KEY" -export GOOGLE_GEMINI_BASE_URL="$BASE_URL" +# ---- Create wrapper (auto-loads env) ---- -info "Env vars set system-wide (/etc/environment + /etc/profile.d/gemini-cli.sh)" +create_wrapper + +NEW_VER=$(gemini --version 2>/dev/null || echo "unknown") +log "Version: $OLD_VER -> $NEW_VER" log "Update complete!" -echo -e "For current shell: ${CYAN}source /etc/profile.d/gemini-cli.sh${RESET}" +echo -e "Gemini works immediately — no need to source anything." echo "" diff --git a/qwen/uqwen_install.sh b/qwen/uqwen_install.sh index 0d41418..4828e0a 100755 --- a/qwen/uqwen_install.sh +++ b/qwen/uqwen_install.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash # Qwen Code — One-line installer +# Uses wrapper script so env vars work immediately in any shell. +# # Usage: # curl -fsSL -H "Authorization: token TOKEN" \ # https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen/uqwen_install.sh \ @@ -12,6 +14,8 @@ REGISTRY_URL="https://npm.sensey24.ru/" NPM_SCOPE="@qwen-code" NPM_PACKAGE="@qwen-code/qwen-code" +ENV_FILE="/etc/profile.d/qwen-code.sh" + GREEN="\033[92m" RED="\033[91m" CYAN="\033[96m" @@ -24,6 +28,44 @@ err() { echo -e "${RED}[!]${RESET} $*" >&2; } info() { echo -e "${CYAN}[i]${RESET} $*"; } warn() { echo -e "${YELLOW}[~]${RESET} $*"; } +create_wrapper() { + local bin_name="$1" + local bin_path + bin_path=$(command -v "$bin_name" 2>/dev/null || echo "/usr/local/bin/$bin_name") + + local npm_root + npm_root=$(npm root -g 2>/dev/null || echo "/usr/lib/node_modules") + + # Try to resolve real entry point + local real_bin + real_bin=$(readlink -f "$bin_path" 2>/dev/null || true) + if [ -z "$real_bin" ] || [ "$real_bin" = "$bin_path" ] || [ ! -f "$real_bin" ]; then + # Search in node_modules + for candidate_pkg in "@qwen-code/qwen-code" "qwen-code"; do + for entry in "dist/index.js" "bin/index.js" "index.js"; do + if [ -f "$npm_root/$candidate_pkg/$entry" ]; then + real_bin="$npm_root/$candidate_pkg/$entry" + break 2 + fi + done + done + fi + + if [ -z "$real_bin" ] || [ ! -f "$real_bin" ]; then + warn "Could not find $bin_name entry point" + return 1 + fi + + rm -f "$bin_path" + cat > "$bin_path" << WEOF +#!/usr/bin/env bash +[ -f $ENV_FILE ] && . $ENV_FILE +exec node "$real_bin" "\$@" +WEOF + chmod +x "$bin_path" + log "Wrapper: $bin_path -> $real_bin" +} + echo -e "${BOLD}" echo " +--------------------------------------+" echo " | Qwen Code — Installer |" @@ -47,14 +89,12 @@ install_pkg() { fi } -# Python3 if ! command -v python3 &>/dev/null; then info "python3 not found, installing..." install_pkg python3 fi log "Python3 $(python3 --version | awk '{print $2}')" -# curl if ! command -v curl &>/dev/null; then info "curl not found, installing..." install_pkg curl @@ -133,7 +173,6 @@ if [ -z "$QWEN_BIN" ]; then err " # then re-run this script to apply patches" exit 1 fi - # Find the binary after install for candidate in qwen qwen-code; do if command -v "$candidate" &>/dev/null; then QWEN_BIN="$candidate" @@ -166,13 +205,12 @@ if [ $PATCH_EXIT -ne 0 ]; then fi log "Patches applied" -# ---- Set environment variables (system-wide, all users) ---- +# ---- Set environment variables (system-wide) ---- info "Setting environment variables..." API_KEY=$(python3 -c "import json; print(json.load(open('$INSTALL_DIR/qwen_config.json'))['api_key'])") BASE_URL=$(python3 -c "import json; print(json.load(open('$INSTALL_DIR/qwen_config.json'))['base_url'])") -# Write to /etc/environment (all users, all sessions including cron) ETC_ENV="/etc/environment" for kv in "QWEN_API_KEY=\"$API_KEY\"" "QWEN_BASE_URL=\"$BASE_URL\""; do KEY="${kv%%=*}" @@ -182,17 +220,22 @@ for kv in "QWEN_API_KEY=\"$API_KEY\"" "QWEN_BASE_URL=\"$BASE_URL\""; do echo "$kv" >> "$ETC_ENV" fi done -log "Env vars written to $ETC_ENV (all users)" +log "Env vars written to $ETC_ENV" -# Write to /etc/profile.d/ for export in login shells -cat > /etc/profile.d/qwen-code.sh << PROF_EOF +cat > "$ENV_FILE" << PROF_EOF export QWEN_API_KEY="$API_KEY" export QWEN_BASE_URL="$BASE_URL" PROF_EOF -chmod 644 /etc/profile.d/qwen-code.sh -log "Export script created: /etc/profile.d/qwen-code.sh" +chmod 644 "$ENV_FILE" +log "Env file: $ENV_FILE" + +# ---- Create wrapper (auto-loads env) ---- + +info "Creating wrapper..." +if [ -n "$QWEN_BIN" ]; then + create_wrapper "$QWEN_BIN" +fi -# Export for current session export QWEN_API_KEY="$API_KEY" export QWEN_BASE_URL="$BASE_URL" @@ -211,22 +254,15 @@ if [ -n "$QWEN_BIN" ]; then echo " $QWEN_BIN # interactive mode" echo " $QWEN_BIN -p \"Your prompt\" # single prompt" echo "" - echo " Models:" - echo " qwen3.5-plus, qwen3-coder-plus" - echo " qwen3-coder-flash, coder-model" - echo "" - echo " If env vars not active, run: source /etc/profile.d/qwen-code.sh" + echo " Env vars auto-loaded by wrapper. Works in any shell." echo "" else warn "Patches applied but test prompt failed." echo " Response: $RESULT" echo "" - echo " Try manually:" - echo " source /etc/profile.d/qwen-code.sh" - echo " $QWEN_BIN -p 'Hello'" + echo " Try manually: $QWEN_BIN -p 'Hello'" fi else warn "Qwen binary not found in PATH after install." echo " Check: npm list -g ${NPM_PACKAGE}" - echo " Then run: source /etc/profile.d/qwen-code.sh && qwen -p 'Hello'" fi diff --git a/qwen/uqwen_update.sh b/qwen/uqwen_update.sh index dad56fc..efd9262 100644 --- a/qwen/uqwen_update.sh +++ b/qwen/uqwen_update.sh @@ -1,15 +1,19 @@ #!/usr/bin/env bash # Qwen Code — Updater # Re-installs latest version from registry + re-applies patches. +# Uses wrapper script so env vars work immediately in any shell. # # Usage: sudo bash uqwen_update.sh set -euo pipefail +GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" REGISTRY_URL="https://npm.sensey24.ru/" NPM_SCOPE="@qwen-code" NPM_PACKAGE="@qwen-code/qwen-code" REPO_RAW="https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen" +ENV_FILE="/etc/profile.d/qwen-code.sh" + GREEN="\033[92m" CYAN="\033[96m" YELLOW="\033[93m" @@ -22,6 +26,42 @@ info() { echo -e "${CYAN}[i]${RESET} $*"; } warn() { echo -e "${YELLOW}[~]${RESET} $*"; } err() { echo -e "${RED}[!]${RESET} $*" >&2; } +create_wrapper() { + local bin_name="$1" + local bin_path + bin_path=$(command -v "$bin_name" 2>/dev/null || echo "/usr/local/bin/$bin_name") + + local npm_root + npm_root=$(npm root -g 2>/dev/null || echo "/usr/lib/node_modules") + + local real_bin + real_bin=$(readlink -f "$bin_path" 2>/dev/null || true) + if [ -z "$real_bin" ] || [ "$real_bin" = "$bin_path" ] || [ ! -f "$real_bin" ]; then + for candidate_pkg in "@qwen-code/qwen-code" "qwen-code"; do + for entry in "dist/index.js" "bin/index.js" "index.js"; do + if [ -f "$npm_root/$candidate_pkg/$entry" ]; then + real_bin="$npm_root/$candidate_pkg/$entry" + break 2 + fi + done + done + fi + + if [ -z "$real_bin" ] || [ ! -f "$real_bin" ]; then + warn "Could not find $bin_name entry point" + return 1 + fi + + rm -f "$bin_path" + cat > "$bin_path" << WEOF +#!/usr/bin/env bash +[ -f $ENV_FILE ] && . $ENV_FILE +exec node "$real_bin" "\$@" +WEOF + chmod +x "$bin_path" + log "Wrapper: $bin_path -> $real_bin" +} + echo -e "${BOLD}" echo " +--------------------------------------+" echo " | Qwen Code — Updater |" @@ -69,9 +109,6 @@ for candidate in qwen qwen-code; do fi done -NEW_VER=$($QWEN_BIN --version 2>/dev/null || echo "unknown") -log "Version: $OLD_VER → $NEW_VER" - # ---- Download and apply patches ---- TEMP_DIR=$(mktemp -d) @@ -79,7 +116,6 @@ cleanup() { rm -rf "$TEMP_DIR" 2>/dev/null || true; } trap cleanup EXIT info "Downloading patcher..." -GITEA_TOKEN="${GITEA_TOKEN:-cadffcb0a6a3be728ac1ff619bb40c86588f6837}" curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" "$REPO_RAW/qwen_patcher.py" -o "$TEMP_DIR/qwen_patcher.py" curl -fsSL -H "Authorization: token ${GITEA_TOKEN}" "$REPO_RAW/qwen_config.json" -o "$TEMP_DIR/qwen_config.json" @@ -92,7 +128,8 @@ if [ $PATCH_EXIT -ne 0 ]; then python3 "$TEMP_DIR/qwen_patcher.py" --apply --config "$TEMP_DIR/qwen_config.json" fi -# Set env vars system-wide (all users, all sessions) +# ---- Set env vars system-wide ---- + API_KEY=$(python3 -c "import json; print(json.load(open('$TEMP_DIR/qwen_config.json'))['api_key'])") BASE_URL=$(python3 -c "import json; print(json.load(open('$TEMP_DIR/qwen_config.json'))['base_url'])") @@ -106,17 +143,21 @@ for kv in "QWEN_API_KEY=\"$API_KEY\"" "QWEN_BASE_URL=\"$BASE_URL\""; do fi done -cat > /etc/profile.d/qwen-code.sh << PROF_EOF +cat > "$ENV_FILE" << PROF_EOF export QWEN_API_KEY="$API_KEY" export QWEN_BASE_URL="$BASE_URL" PROF_EOF -chmod 644 /etc/profile.d/qwen-code.sh +chmod 644 "$ENV_FILE" -export QWEN_API_KEY="$API_KEY" -export QWEN_BASE_URL="$BASE_URL" +# ---- Create wrapper (auto-loads env) ---- -info "Env vars set system-wide (/etc/environment + /etc/profile.d/qwen-code.sh)" +if [ -n "$QWEN_BIN" ]; then + create_wrapper "$QWEN_BIN" +fi + +NEW_VER=$($QWEN_BIN --version 2>/dev/null || echo "unknown") +log "Version: $OLD_VER -> $NEW_VER" log "Update complete!" -echo -e "For current shell: ${CYAN}source /etc/profile.d/qwen-code.sh${RESET}" +echo -e "Qwen works immediately — no need to source anything." echo ""