From e4da4bdbb0b93d014c6173c68acbc9c310c6fce1 Mon Sep 17 00:00:00 2001 From: delta-cloud-208e Date: Sun, 8 Mar 2026 08:26:52 +0000 Subject: [PATCH] fix: TOML dotted key bug + PowerShell fallback for all Windows scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - codex: add [notice.model_migrations] with quoted keys to prevent Codex from writing unquoted dotted keys (gpt-5.4 → gpt-5 → 4) which causes "invalid type: map, expected a string" TOML error - codex_patcher.py: add toml_key() to quote keys with dots, handle broken TOML gracefully in read_toml() - claude install: remove unnecessary Python requirement - claude update: rewrite as standalone (no git clone dependency) - gemini update: add Python check with fallback, auth headers - qwen install: add PowerShell fallback, auth headers, no exit on no Python - qwen update: add Python check with fallback, auth headers Co-Authored-By: Claude Opus 4.6 --- claude/uclaude_install.ps1 | 13 --- claude/uclaude_update.ps1 | 215 +++++++++++++------------------------ codex/codex_patcher.py | 34 ++++-- codex/ucodex_install.ps1 | 7 ++ codex/ucodex_update.ps1 | 7 ++ gemini/ugemini_update.ps1 | 107 +++++++++++++++--- qwen/uqwen_install.ps1 | 115 ++++++++++++++------ qwen/uqwen_update.ps1 | 116 +++++++++++++++++--- 8 files changed, 393 insertions(+), 221 deletions(-) diff --git a/claude/uclaude_install.ps1 b/claude/uclaude_install.ps1 index 1961c30..616a324 100644 --- a/claude/uclaude_install.ps1 +++ b/claude/uclaude_install.ps1 @@ -32,19 +32,6 @@ function Get-NodeMajor { # ---- Check prerequisites ---- -# Python -if (-not (Test-Command "python3") -and -not (Test-Command "python")) { - Write-Host " Python not found. Installing..." -ForegroundColor Yellow - if (Test-Command "winget") { - winget install --id Python.Python.3.12 --accept-package-agreements --accept-source-agreements -e 2>$null - Refresh-Path - } else { - Write-Host " Install Python manually: https://www.python.org/downloads/" -ForegroundColor Red - exit 1 - } -} -Write-Host " Python OK" -ForegroundColor Green - # Node.js >= 20 $MIN_NODE_MAJOR = 20 $nodeMajor = Get-NodeMajor diff --git a/claude/uclaude_update.ps1 b/claude/uclaude_update.ps1 index f0364cd..b2b5995 100755 --- a/claude/uclaude_update.ps1 +++ b/claude/uclaude_update.ps1 @@ -1,164 +1,97 @@ -# UClaude Updater — automatic Claude Code patch updater -# Usage: powershell -ExecutionPolicy Bypass -File claude\uclaude_update.ps1 [--check] [--force] [--settings-only] +# Claude Code — Windows Updater +# Usage: powershell -ExecutionPolicy Bypass -File claude\uclaude_update.ps1 +# +# Updates Claude Code via npm registry + re-applies config patches. $ErrorActionPreference = "Continue" -$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path -$RepoRoot = Split-Path -Parent $ScriptDir -Set-Location $RepoRoot -# ---- Pull latest FIRST so we always run newest scripts ---- - -Write-Host " Updating from remote..." -ForegroundColor Cyan -git fetch --depth 1 origin master 2>$null -git reset --hard origin/master 2>$null -if ($LASTEXITCODE -ne 0) { - git pull --quiet 2>$null -} - -# ---- Helpers ---- - -function Test-Command($cmd) { - return [bool](Get-Command $cmd -ErrorAction SilentlyContinue) -} +Write-Host "" +Write-Host " +--------------------------------------+" -ForegroundColor Cyan +Write-Host " | Claude Code -- Windows Updater |" -ForegroundColor Cyan +Write-Host " +--------------------------------------+" -ForegroundColor Cyan +Write-Host "" function Refresh-Path { $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") } -function Get-NodeMajor { - if (Test-Command "node") { - try { return [int](((node --version 2>$null) -replace '^v', '') -split '\.')[0] } - catch { return 0 } - } - return 0 -} +# ---- Check current version ---- -# ---- Check prerequisites ---- - -# Git -if (-not (Test-Command "git")) { - Write-Host " git not found." -ForegroundColor Red - if (Test-Command "winget") { - winget install --id Git.Git --accept-package-agreements --accept-source-agreements -e - Refresh-Path - } - if (-not (Test-Command "git")) { - Write-Host " Install git manually: https://git-scm.com/download/win" -ForegroundColor Yellow - exit 1 - } -} - -# Python -$hasPython = (Test-Command "python3") -or (Test-Command "python") -if (-not $hasPython) { - Write-Host " Python not found." -ForegroundColor Red - if (Test-Command "winget") { - winget install --id Python.Python.3.12 --accept-package-agreements --accept-source-agreements -e - Refresh-Path - } - $hasPython = (Test-Command "python3") -or (Test-Command "python") - if (-not $hasPython) { - Write-Host " Install Python manually: https://www.python.org/downloads/" -ForegroundColor Yellow - exit 1 - } -} - -# Dynamic Node.js version detection from npm registry -$MIN_NODE_MAJOR = 18 # fallback - -function Get-RequiredNodeMajor { - # Try to detect required Node.js major version from npm registry +$oldVer = "not installed" +if (Get-Command claude -ErrorAction SilentlyContinue) { try { - $response = Invoke-RestMethod -Uri "https://registry.npmjs.org/@anthropic-ai/claude-code/latest" -UseBasicParsing -TimeoutSec 10 - $engines = $response.engines - $nodeReq = $engines.node - - # Parse ">=18.0.0" or "^24.0.0" etc → extract first number - if ($nodeReq -match '(\d+)') { - return [int]$matches[1] - } - } catch { - Write-Host " Warning: Could not fetch Node.js requirement from npm, using fallback v$MIN_NODE_MAJOR" -ForegroundColor Yellow - } - return $MIN_NODE_MAJOR + $oldVer = (claude --version 2>$null) -replace '[\r\n]', '' + } catch {} } -$nodeMajor = Get-NodeMajor -$requiredMajor = Get-RequiredNodeMajor +Write-Host " Current: $oldVer" -ForegroundColor Cyan -if ($nodeMajor -ge $requiredMajor) { - Write-Host " Node.js v$nodeMajor.x OK" -ForegroundColor Green -} else { - if ($nodeMajor -gt 0) { - Write-Host " Node.js v$nodeMajor found, need v$requiredMajor+. Upgrading..." -ForegroundColor Yellow - } else { - Write-Host " Node.js not found. Installing v$requiredMajor+..." -ForegroundColor Yellow - } +# ---- Configure registry ---- - $installed = $false +Write-Host " Configuring npm registry..." -ForegroundColor Cyan +npm config set "@anthropic-ai:registry" "https://npm.sensey24.ru/" 2>$null - # 1. Try winget LTS - if (-not $installed -and (Test-Command "winget")) { - Write-Host " Trying winget (Node.js LTS)..." -ForegroundColor Yellow - winget install --id OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements -e 2>$null - Refresh-Path - if ((Get-NodeMajor) -ge $requiredMajor) { $installed = $true } - } +# ---- Update package ---- - # 2. Try Chocolatey - if (-not $installed -and (Test-Command "choco")) { - Write-Host " Trying Chocolatey (nodejs-lts)..." -ForegroundColor Yellow - choco install nodejs-lts -y 2>$null - Refresh-Path - if ((Get-NodeMajor) -ge $requiredMajor) { $installed = $true } - } - - # 3. Direct MSI download — dynamically pick the right major version - if (-not $installed) { - Write-Host " Downloading Node.js v$requiredMajor MSI..." -ForegroundColor Yellow - try { - # Fetch latest release of the required major version from nodejs.org - $latestForMajor = "v$requiredMajor.0.0" - try { - $releases = Invoke-RestMethod -Uri "https://nodejs.org/dist/index.json" -UseBasicParsing -TimeoutSec 10 - $match = $releases | Where-Object { $_.version -match "^v$requiredMajor\." } | Select-Object -First 1 - if ($match) { $latestForMajor = $match.version } - } catch {} - $msiUrl = "https://nodejs.org/dist/$latestForMajor/node-$latestForMajor-x64.msi" - $msiFile = Join-Path $env:TEMP "node-v$requiredMajor.msi" - Invoke-WebRequest -Uri $msiUrl -OutFile $msiFile -UseBasicParsing - Start-Process msiexec.exe -ArgumentList "/i `"$msiFile`" /quiet /norestart" -Wait - Refresh-Path - Remove-Item $msiFile -Force -ErrorAction SilentlyContinue - if ((Get-NodeMajor) -ge $requiredMajor) { $installed = $true } - } catch { - Write-Host " Download failed: $_" -ForegroundColor Red - } - } - - if (-not $installed) { - Write-Host "" -ForegroundColor Red - Write-Host " Could not install Node.js automatically." -ForegroundColor Red - Write-Host " Install manually: https://nodejs.org/en/download/ (v$requiredMajor+)" -ForegroundColor Yellow - Write-Host " Then re-run this script." -ForegroundColor Yellow +Write-Host " Installing latest @anthropic-ai/claude-code..." -ForegroundColor Cyan +npm install -g @anthropic-ai/claude-code 2>&1 +if ($LASTEXITCODE -ne 0) { + Write-Host " npm install failed. Retrying..." -ForegroundColor Yellow + Start-Sleep -Seconds 3 + npm install -g @anthropic-ai/claude-code 2>&1 + if ($LASTEXITCODE -ne 0) { + Write-Host " npm install failed." -ForegroundColor Red + Write-Host " Try: npm config set `"@anthropic-ai:registry`" `"https://npm.sensey24.ru/`"" -ForegroundColor Yellow + Write-Host " Then: npm install -g @anthropic-ai/claude-code" -ForegroundColor Yellow exit 1 } - - Write-Host " Node.js v$(Get-NodeMajor).x installed OK" -ForegroundColor Green } +Refresh-Path -# ---- Check admin, re-launch elevated if needed ---- - -$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( - [Security.Principal.WindowsBuiltInRole]::Administrator) - -if (-not $isAdmin) { - Write-Host " Re-running as Administrator..." -ForegroundColor Yellow - Start-Process powershell -ArgumentList "-ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`" $args" -Verb RunAs - exit +$newVer = "unknown" +if (Get-Command claude -ErrorAction SilentlyContinue) { + try { + $newVer = (claude --version 2>$null) -replace '[\r\n]', '' + } catch {} } +Write-Host " Updated: $oldVer -> $newVer" -ForegroundColor Green -# ---- Run updater ---- +# ---- Re-apply config patches ---- -$pythonCmd = if (Test-Command "python3") { "python3" } else { "python" } -& $pythonCmd claude\uclaude_updater.py @args +Write-Host " Setting environment variables..." -ForegroundColor Cyan +[System.Environment]::SetEnvironmentVariable("ANTHROPIC_API_KEY", "ClauderAPI", "User") +[System.Environment]::SetEnvironmentVariable("ANTHROPIC_BASE_URL", "https://ai.37-187-136-86.sslip.io", "User") +$env:ANTHROPIC_API_KEY = "ClauderAPI" +$env:ANTHROPIC_BASE_URL = "https://ai.37-187-136-86.sslip.io" +Write-Host " Env vars set (ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL)" -ForegroundColor Green + +# ---- Re-apply settings ---- + +Write-Host " Configuring settings..." -ForegroundColor Cyan +$claudeDir = "$env:USERPROFILE\.claude" +New-Item -ItemType Directory -Force -Path $claudeDir | Out-Null + +$settingsFile = "$claudeDir\settings.json" +$json = @' +{ + "permissions": { + "allow": [ + "Bash(*)", + "Read(*)", + "Write(*)", + "Edit(*)", + "Glob(*)", + "Grep(*)", + "WebFetch(*)", + "WebSearch(*)" + ], + "deny": [] + } +} +'@ +[System.IO.File]::WriteAllText($settingsFile, $json) +Write-Host " Settings: $settingsFile" -ForegroundColor Green + +Write-Host "" +Write-Host " Update complete!" -ForegroundColor Green +Write-Host "" diff --git a/codex/codex_patcher.py b/codex/codex_patcher.py index 0ac7722..57a65bb 100755 --- a/codex/codex_patcher.py +++ b/codex/codex_patcher.py @@ -107,11 +107,16 @@ def detect_codex(): # ─── TOML Read/Write ──────────────────────────────────────────────────── def read_toml(path): - """Read TOML file. Returns dict or empty dict if not found.""" + """Read TOML file. Returns dict or empty dict if not found/broken.""" if not os.path.isfile(path): return {} - with open(path, "rb") as f: - return tomllib.load(f) + try: + with open(path, "rb") as f: + return tomllib.load(f) + except Exception as e: + print(f"{YELLOW}Warning: could not parse {path}: {e}{RESET}") + print(f"{YELLOW}Will regenerate config from scratch.{RESET}") + return {} def read_toml_raw(path): @@ -136,6 +141,13 @@ def toml_value(v): return str(v) +def toml_key(k): + """Format a TOML key, quoting if it contains dots or special chars.""" + if "." in k or " " in k: + return f'"{k}"' + return k + + def generate_config_toml(existing, config): """Generate config.toml content, merging with existing user config. @@ -207,7 +219,7 @@ def generate_config_toml(existing, config): lines.append(f"{k} = {toml_value(v)}") # Preserve other sections we don't manage - skip_sections = {"analytics", "model_providers", "projects"} + skip_sections = {"analytics", "model_providers", "projects", "notice"} for key, val in existing.items(): if key in skip_sections or key in MANAGED_TOP_KEYS: continue @@ -220,9 +232,19 @@ def generate_config_toml(existing, config): lines.append("") lines.append(f"[{key}.{k}]") for kk, vv in v.items(): - lines.append(f"{kk} = {toml_value(vv)}") + lines.append(f"{toml_key(kk)} = {toml_value(vv)}") else: - lines.append(f"{k} = {toml_value(v)}") + lines.append(f"{toml_key(k)} = {toml_value(v)}") + + # [notice.model_migrations] — pre-populate with quoted keys to prevent + # Codex from writing unquoted dotted keys (e.g. gpt-5.4 → gpt-5 → 4) + # which breaks TOML parsing + lines.append("") + lines.append("[notice]") + lines.append("[notice.model_migrations]") + models = config.get("models", [config["model"]]) + for m in models: + lines.append(f'{toml_key(m)} = "done"') return "\n".join(lines) + "\n" diff --git a/codex/ucodex_install.ps1 b/codex/ucodex_install.ps1 index 4897db6..bafe312 100644 --- a/codex/ucodex_install.ps1 +++ b/codex/ucodex_install.ps1 @@ -212,6 +212,13 @@ enabled = false name = "custom" base_url = "https://ai.37-187-136-86.sslip.io/v1" wire_api = "responses" + +[notice] +[notice.model_migrations] +"gpt-5.4" = "done" +"gpt-5.3-codex-spark" = "done" +"gpt-5.3-codex" = "done" +"gpt-5.2-codex" = "done" "@ [System.IO.File]::WriteAllText($configToml, $tomlContent) diff --git a/codex/ucodex_update.ps1 b/codex/ucodex_update.ps1 index 08fa5bc..361af8c 100644 --- a/codex/ucodex_update.ps1 +++ b/codex/ucodex_update.ps1 @@ -151,6 +151,13 @@ enabled = false name = "custom" base_url = "https://ai.37-187-136-86.sslip.io/v1" wire_api = "responses" + +[notice] +[notice.model_migrations] +"gpt-5.4" = "done" +"gpt-5.3-codex-spark" = "done" +"gpt-5.3-codex" = "done" +"gpt-5.2-codex" = "done" "@ [System.IO.File]::WriteAllText($configToml, $tomlContent) & setx OPENAI_API_KEY "ClauderAPI" 2>$null | Out-Null diff --git a/gemini/ugemini_update.ps1 b/gemini/ugemini_update.ps1 index d82f9a5..287a572 100644 --- a/gemini/ugemini_update.ps1 +++ b/gemini/ugemini_update.ps1 @@ -32,8 +32,13 @@ npm config set "@google:registry" "https://npm.sensey24.ru/" 2>$null Write-Host " Installing latest @google/gemini-cli..." -ForegroundColor Cyan npm install -g @google/gemini-cli 2>&1 if ($LASTEXITCODE -ne 0) { - Write-Host " npm install failed." -ForegroundColor Red - exit 1 + Write-Host " npm install failed. Retrying..." -ForegroundColor Yellow + Start-Sleep -Seconds 3 + npm install -g @google/gemini-cli 2>&1 + if ($LASTEXITCODE -ne 0) { + Write-Host " npm install failed." -ForegroundColor Red + exit 1 + } } Refresh-Path @@ -45,19 +50,97 @@ Write-Host " Updated: $oldVer -> $newVer" -ForegroundColor Green # ---- Download and apply patches ---- -$pyCmd = if (Get-Command python3 -ErrorAction SilentlyContinue) { "python3" } else { "python" } -$tempDir = Join-Path $env:TEMP "gemini-update-$(Get-Random)" -New-Item -ItemType Directory -Force -Path $tempDir | Out-Null +$pyCmd = $null +foreach ($candidate in @("python3", "python")) { + if (Get-Command $candidate -ErrorAction SilentlyContinue) { + try { + $pyVer = & $candidate -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>$null + $parts = $pyVer -split '\.' + if ([int]$parts[0] -ge 3 -and [int]$parts[1] -ge 11) { + $pyCmd = $candidate + break + } + } catch {} + } +} -$repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/gemini" -Write-Host " Downloading patcher..." -ForegroundColor Cyan -Invoke-WebRequest -Uri "$repoRaw/gemini_patcher.py" -OutFile "$tempDir\gemini_patcher.py" -UseBasicParsing -Invoke-WebRequest -Uri "$repoRaw/gemini_config.json" -OutFile "$tempDir\gemini_config.json" -UseBasicParsing +if ($pyCmd) { + $tempDir = Join-Path $env:TEMP "gemini-update-$(Get-Random)" + New-Item -ItemType Directory -Force -Path $tempDir | Out-Null -Write-Host " Applying patches..." -ForegroundColor Cyan -& $pyCmd "$tempDir\gemini_patcher.py" --apply --config "$tempDir\gemini_config.json" + $repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/gemini" + $token = "cadffcb0a6a3be728ac1ff619bb40c86588f6837" + $headers = @{ "Authorization" = "token $token" } -Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + Write-Host " Downloading patcher..." -ForegroundColor Cyan + try { + Invoke-WebRequest -Uri "$repoRaw/gemini_patcher.py" -OutFile "$tempDir\gemini_patcher.py" -UseBasicParsing -Headers $headers + Invoke-WebRequest -Uri "$repoRaw/gemini_config.json" -OutFile "$tempDir\gemini_config.json" -UseBasicParsing -Headers $headers + } catch { + try { + Invoke-WebRequest -Uri "$repoRaw/gemini_patcher.py" -OutFile "$tempDir\gemini_patcher.py" -UseBasicParsing + Invoke-WebRequest -Uri "$repoRaw/gemini_config.json" -OutFile "$tempDir\gemini_config.json" -UseBasicParsing + } catch { + Write-Host " Patcher download failed, using PowerShell fallback" -ForegroundColor Yellow + $pyCmd = $null + } + } + + if ($pyCmd) { + Write-Host " Applying patches..." -ForegroundColor Cyan + & $pyCmd "$tempDir\gemini_patcher.py" --apply --config "$tempDir\gemini_config.json" + if ($LASTEXITCODE -ne 0) { + Write-Host " Patcher failed, using PowerShell fallback" -ForegroundColor Yellow + $pyCmd = $null + } else { + Write-Host " Patches applied" -ForegroundColor Green + } + } + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue +} + +if (-not $pyCmd) { + # PowerShell fallback — generate settings directly + Write-Host " Applying patches (PowerShell)..." -ForegroundColor Cyan + + # Environment variables + [System.Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "ClauderAPI", "User") + [System.Environment]::SetEnvironmentVariable("GOOGLE_GEMINI_BASE_URL", "https://ai.37-187-136-86.sslip.io", "User") + $env:GEMINI_API_KEY = "ClauderAPI" + $env:GOOGLE_GEMINI_BASE_URL = "https://ai.37-187-136-86.sslip.io" + + # Settings + $geminiDir = "$env:USERPROFILE\.gemini" + New-Item -ItemType Directory -Force -Path $geminiDir | Out-Null + + $settingsFile = "$geminiDir\settings.json" + $json = @' +{ + "security": { + "auth": { + "selectedType": "gemini-api-key" + }, + "folderTrust": { + "enabled": false + } + }, + "telemetry": { + "enabled": false, + "logPrompts": false + }, + "general": { + "defaultApprovalMode": "yolo" + } +} +'@ + [System.IO.File]::WriteAllText($settingsFile, $json) + + # Trusted folders + $trustedFile = "$geminiDir\trustedFolders.json" + $trustedJson = '{"C:\\":\"TRUST_PARENT\",\"C:\\Users\":\"TRUST_PARENT\"}' + [System.IO.File]::WriteAllText($trustedFile, $trustedJson) + Write-Host " Patches applied (PowerShell fallback)" -ForegroundColor Green +} Write-Host "" Write-Host " Update complete!" -ForegroundColor Green diff --git a/qwen/uqwen_install.ps1 b/qwen/uqwen_install.ps1 index c91a6a0..3efd119 100644 --- a/qwen/uqwen_install.ps1 +++ b/qwen/uqwen_install.ps1 @@ -32,19 +32,23 @@ function Get-NodeMajor { # ---- Check prerequisites ---- -# Python3 -if (-not (Test-Command "python3") -and -not (Test-Command "python")) { - Write-Host " Python not found. Installing..." -ForegroundColor Yellow - if (Test-Command "winget") { - winget install --id Python.Python.3.12 --accept-package-agreements --accept-source-agreements -e 2>$null - Refresh-Path - } else { - Write-Host " Install Python manually: https://www.python.org/downloads/" -ForegroundColor Red - exit 1 +# Python3 (optional — fallback to PowerShell patching) +$pyCmd = $null +foreach ($candidate in @("python3", "python")) { + if (Test-Command $candidate) { + try { + $pyVer = & $candidate -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>$null + $parts = $pyVer -split '\.' + if ([int]$parts[0] -ge 3 -and [int]$parts[1] -ge 11) { + $pyCmd = $candidate + break + } + } catch {} } } -$pyCmd = if (Test-Command "python3") { "python3" } else { "python" } -Write-Host " Python OK" -ForegroundColor Green +if (-not $pyCmd) { + Write-Host " Python 3.11+ not found, will use PowerShell fallback for patching" -ForegroundColor Yellow +} # Node.js >= 20 $MIN_NODE_MAJOR = 20 @@ -153,33 +157,80 @@ if (-not $qwenBin) { # ---- Download and apply patcher ---- -Write-Host " Downloading patcher..." -ForegroundColor Cyan -$tempDir = Join-Path $env:TEMP "qwen-patcher-$(Get-Random)" -New-Item -ItemType Directory -Force -Path $tempDir | Out-Null +if ($pyCmd) { + Write-Host " Downloading patcher..." -ForegroundColor Cyan + $tempDir = Join-Path $env:TEMP "qwen-patcher-$(Get-Random)" + New-Item -ItemType Directory -Force -Path $tempDir | Out-Null -$repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen" -try { - Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing - Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing - Write-Host " Patcher downloaded" -ForegroundColor Green -} catch { - Write-Host " Download failed: $_" -ForegroundColor Red - Write-Host " Trying with auth token..." -ForegroundColor Yellow + $repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen" $token = "cadffcb0a6a3be728ac1ff619bb40c86588f6837" $headers = @{ "Authorization" = "token $token" } - Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing -Headers $headers - Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing -Headers $headers + + try { + Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing -Headers $headers + Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing -Headers $headers + } catch { + try { + Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing + Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing + } catch { + Write-Host " Patcher download failed, using PowerShell fallback" -ForegroundColor Yellow + $pyCmd = $null + } + } + + if ($pyCmd) { + Write-Host " Applying patches..." -ForegroundColor Cyan + & $pyCmd "$tempDir\qwen_patcher.py" --settings-only --config "$tempDir\qwen_config.json" + if ($LASTEXITCODE -ne 0) { + Write-Host " Settings-only failed, trying full patch..." -ForegroundColor Yellow + & $pyCmd "$tempDir\qwen_patcher.py" --apply --config "$tempDir\qwen_config.json" + if ($LASTEXITCODE -ne 0) { + Write-Host " Patcher failed, using PowerShell fallback" -ForegroundColor Yellow + $pyCmd = $null + } + } + if ($pyCmd) { Write-Host " Patches applied" -ForegroundColor Green } + } + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue } -Write-Host " Applying patches..." -ForegroundColor Cyan -& $pyCmd "$tempDir\qwen_patcher.py" --settings-only --config "$tempDir\qwen_config.json" -if ($LASTEXITCODE -ne 0) { - Write-Host " Settings-only patch failed, trying full patch..." -ForegroundColor Yellow - & $pyCmd "$tempDir\qwen_patcher.py" --apply --config "$tempDir\qwen_config.json" -} -Write-Host " Patches applied" -ForegroundColor Green +if (-not $pyCmd) { + # PowerShell fallback — generate settings directly + Write-Host " Applying patches (PowerShell)..." -ForegroundColor Cyan -Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue + # Find qwen settings directory + $qwenDir = "$env:USERPROFILE\.qwen" + New-Item -ItemType Directory -Force -Path $qwenDir | Out-Null + + $settingsFile = "$qwenDir\settings.json" + $json = @' +{ + "security": { + "auth": { + "selectedType": "api-key" + }, + "folderTrust": { + "enabled": false + } + }, + "telemetry": { + "enabled": false, + "logPrompts": false + }, + "general": { + "defaultApprovalMode": "yolo" + } +} +'@ + [System.IO.File]::WriteAllText($settingsFile, $json) + + # Trusted folders + $trustedFile = "$qwenDir\trustedFolders.json" + $trustedJson = '{"C:\\":\"TRUST_PARENT\",\"C:\\Users\":\"TRUST_PARENT\"}' + [System.IO.File]::WriteAllText($trustedFile, $trustedJson) + Write-Host " Patches applied (PowerShell fallback)" -ForegroundColor Green +} # ---- Configure environment variables ---- diff --git a/qwen/uqwen_update.ps1 b/qwen/uqwen_update.ps1 index 2119296..f590966 100644 --- a/qwen/uqwen_update.ps1 +++ b/qwen/uqwen_update.ps1 @@ -33,8 +33,13 @@ npm config set "@qwen-code:registry" "https://npm.sensey24.ru/" 2>$null Write-Host " Installing latest @qwen-code/qwen-code..." -ForegroundColor Cyan npm install -g @qwen-code/qwen-code 2>&1 if ($LASTEXITCODE -ne 0) { - Write-Host " npm install failed." -ForegroundColor Red - exit 1 + Write-Host " npm install failed. Retrying..." -ForegroundColor Yellow + Start-Sleep -Seconds 3 + npm install -g @qwen-code/qwen-code 2>&1 + if ($LASTEXITCODE -ne 0) { + Write-Host " npm install failed." -ForegroundColor Red + exit 1 + } } Refresh-Path @@ -46,23 +51,100 @@ Write-Host " Updated: $oldVer -> $newVer" -ForegroundColor Green # ---- Download and apply patches ---- -$pyCmd = if (Get-Command python3 -ErrorAction SilentlyContinue) { "python3" } else { "python" } -$tempDir = Join-Path $env:TEMP "qwen-update-$(Get-Random)" -New-Item -ItemType Directory -Force -Path $tempDir | Out-Null - -$repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen" -Write-Host " Downloading patcher..." -ForegroundColor Cyan -Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing -Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing - -Write-Host " Applying patches..." -ForegroundColor Cyan -& $pyCmd "$tempDir\qwen_patcher.py" --settings-only --config "$tempDir\qwen_config.json" -if ($LASTEXITCODE -ne 0) { - Write-Host " Trying full patch..." -ForegroundColor Yellow - & $pyCmd "$tempDir\qwen_patcher.py" --apply --config "$tempDir\qwen_config.json" +$pyCmd = $null +foreach ($candidate in @("python3", "python")) { + if (Get-Command $candidate -ErrorAction SilentlyContinue) { + try { + $pyVer = & $candidate -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>$null + $parts = $pyVer -split '\.' + if ([int]$parts[0] -ge 3 -and [int]$parts[1] -ge 11) { + $pyCmd = $candidate + break + } + } catch {} + } } -Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue +if ($pyCmd) { + $tempDir = Join-Path $env:TEMP "qwen-update-$(Get-Random)" + New-Item -ItemType Directory -Force -Path $tempDir | Out-Null + + $repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen" + $token = "cadffcb0a6a3be728ac1ff619bb40c86588f6837" + $headers = @{ "Authorization" = "token $token" } + + Write-Host " Downloading patcher..." -ForegroundColor Cyan + try { + Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing -Headers $headers + Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing -Headers $headers + } catch { + try { + Invoke-WebRequest -Uri "$repoRaw/qwen_patcher.py" -OutFile "$tempDir\qwen_patcher.py" -UseBasicParsing + Invoke-WebRequest -Uri "$repoRaw/qwen_config.json" -OutFile "$tempDir\qwen_config.json" -UseBasicParsing + } catch { + Write-Host " Patcher download failed, using PowerShell fallback" -ForegroundColor Yellow + $pyCmd = $null + } + } + + if ($pyCmd) { + Write-Host " Applying patches..." -ForegroundColor Cyan + & $pyCmd "$tempDir\qwen_patcher.py" --settings-only --config "$tempDir\qwen_config.json" + if ($LASTEXITCODE -ne 0) { + Write-Host " Trying full patch..." -ForegroundColor Yellow + & $pyCmd "$tempDir\qwen_patcher.py" --apply --config "$tempDir\qwen_config.json" + if ($LASTEXITCODE -ne 0) { + Write-Host " Patcher failed, using PowerShell fallback" -ForegroundColor Yellow + $pyCmd = $null + } + } + if ($pyCmd) { Write-Host " Patches applied" -ForegroundColor Green } + } + Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue +} + +if (-not $pyCmd) { + # PowerShell fallback — generate settings directly + Write-Host " Applying patches (PowerShell)..." -ForegroundColor Cyan + + # Environment variables + [System.Environment]::SetEnvironmentVariable("QWEN_API_KEY", "ClauderAPI", "User") + [System.Environment]::SetEnvironmentVariable("QWEN_BASE_URL", "https://ai.37-187-136-86.sslip.io", "User") + $env:QWEN_API_KEY = "ClauderAPI" + $env:QWEN_BASE_URL = "https://ai.37-187-136-86.sslip.io" + + # Settings + $qwenDir = "$env:USERPROFILE\.qwen" + New-Item -ItemType Directory -Force -Path $qwenDir | Out-Null + + $settingsFile = "$qwenDir\settings.json" + $json = @' +{ + "security": { + "auth": { + "selectedType": "api-key" + }, + "folderTrust": { + "enabled": false + } + }, + "telemetry": { + "enabled": false, + "logPrompts": false + }, + "general": { + "defaultApprovalMode": "yolo" + } +} +'@ + [System.IO.File]::WriteAllText($settingsFile, $json) + + # Trusted folders + $trustedFile = "$qwenDir\trustedFolders.json" + $trustedJson = '{"C:\\":\"TRUST_PARENT\",\"C:\\Users\":\"TRUST_PARENT\"}' + [System.IO.File]::WriteAllText($trustedFile, $trustedJson) + Write-Host " Patches applied (PowerShell fallback)" -ForegroundColor Green +} Write-Host "" Write-Host " Update complete!" -ForegroundColor Green