feat: add Windows PowerShell installers for Codex and Qwen, fix BOM issue

- codex/ucodex_install.ps1: downloads Rust binary from GitHub + patches config
- qwen/uqwen_install.ps1: npm install + patcher + env vars
- gemini/ugemini_install.ps1: fix UTF-8 BOM in settings.json (Set-Content → WriteAllText)
- README.md: add Windows CMD/PowerShell configure instructions for Gemini, Codex, Qwen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
delta-cloud-208e
2026-03-08 07:24:19 +00:00
parent c84c2668ce
commit f50c0dfced
4 changed files with 710 additions and 17 deletions

View File

@@ -122,7 +122,7 @@ npm install -g @google/gemini-cli
> Node.js required. Install from https://nodejs.org/ if not present.
Then configure:
Then configure (Linux / macOS):
```bash
echo 'export GEMINI_API_KEY="ClauderAPI"' >> ~/.bashrc
echo 'export GOOGLE_GEMINI_BASE_URL="https://ai.37-187-136-86.sslip.io"' >> ~/.bashrc
@@ -136,46 +136,64 @@ cat > ~/.gemini/settings.json << 'EOF'
EOF
```
Then configure (Windows — run in **PowerShell**, not CMD):
```powershell
[System.Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "ClauderAPI", "User")
[System.Environment]::SetEnvironmentVariable("GOOGLE_GEMINI_BASE_URL", "https://ai.37-187-136-86.sslip.io", "User")
$d = "$env:USERPROFILE\.gemini"; New-Item -ItemType Directory -Force -Path $d | Out-Null
[System.IO.File]::WriteAllText("$d\settings.json", '{"security":{"auth":{"selectedType":"gemini-api-key"}},"telemetry":{"enabled":false,"logPrompts":false}}')
```
Or use CMD:
```cmd
setx GEMINI_API_KEY "ClauderAPI"
setx GOOGLE_GEMINI_BASE_URL "https://ai.37-187-136-86.sslip.io"
mkdir "%USERPROFILE%\.gemini" 2>nul
echo {"security":{"auth":{"selectedType":"gemini-api-key"}},"telemetry":{"enabled":false,"logPrompts":false}} > "%USERPROFILE%\.gemini\settings.json"
```
Verify: `gemini -p "Hello"`
**Alternative — Automatic installer (installs Node.js, CLI, patches, settings):**
Linux / macOS:
```bash
curl -fsSL -H "Authorization: token cadffcb0a6a3be728ac1ff619bb40c86588f6837" \
https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/gemini/ugemini_install.sh \
-o /tmp/ugemini.sh && sudo bash /tmp/ugemini.sh
```
See [gemini/README.md](gemini/README.md) for Windows instructions and details.
Windows (PowerShell as Administrator):
```powershell
git clone --depth 1 https://x-token:cadffcb0a6a3be728ac1ff619bb40c86588f6837@git.sensey24.ru/aibot777/unlimitedcoding.git
cd unlimitedcoding
powershell -ExecutionPolicy Bypass -File gemini\ugemini_install.ps1
```
See [gemini/README.md](gemini/README.md) for details.
### Codex CLI — Install
> Codex CLI is a compiled Rust binary (not npm). Install via GitHub releases.
**Step 1 — Clone repo and install binary:**
**Linux / macOS:**
```bash
git clone --depth 1 https://x-token:cadffcb0a6a3be728ac1ff619bb40c86588f6837@git.sensey24.ru/aibot777/unlimitedcoding.git
cd unlimitedcoding/codex
cp codex_config.example.json codex_config.json
# Edit codex_config.json — set your base_url and api_key
```
**Step 2 — Install + patch:**
```bash
sudo bash ucodex_install.sh
```
Or manually:
```bash
sudo bash update-codex.sh # Install/update binary
sudo python3 codex_patcher.py --apply # Apply config patches
**Windows (PowerShell as Administrator):**
```powershell
git clone --depth 1 https://x-token:cadffcb0a6a3be728ac1ff619bb40c86588f6837@git.sensey24.ru/aibot777/unlimitedcoding.git
cd unlimitedcoding
powershell -ExecutionPolicy Bypass -File codex\ucodex_install.ps1
```
**Step 3 — Verify:** `codex exec "Hello"`
Verify: `codex exec "Hello"`
**Update:**
**Update (Linux):**
```bash
cd unlimitedcoding/codex
git pull
@@ -209,14 +227,22 @@ python3 qwen_patcher.py --settings-only
Verify: `qwen -p "Hello"`
**Alternative — Automatic installer (installs Node.js, CLI, patches, settings):**
**Alternative — Automatic installer:**
Linux / macOS:
```bash
curl -fsSL -H "Authorization: token cadffcb0a6a3be728ac1ff619bb40c86588f6837" \
https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/qwen/uqwen_install.sh \
-o /tmp/uqwen.sh && sudo bash /tmp/uqwen.sh
```
Windows (PowerShell as Administrator):
```powershell
git clone --depth 1 https://x-token:cadffcb0a6a3be728ac1ff619bb40c86588f6837@git.sensey24.ru/aibot777/unlimitedcoding.git
cd unlimitedcoding
powershell -ExecutionPolicy Bypass -File qwen\uqwen_install.ps1
```
See [qwen/README.md](qwen/README.md) for details, models, and troubleshooting.
### Manual install from release

250
codex/ucodex_install.ps1 Normal file
View File

@@ -0,0 +1,250 @@
# Codex CLI — Windows Installer
# Usage: powershell -ExecutionPolicy Bypass -File codex\ucodex_install.ps1
#
# Downloads Codex CLI binary from GitHub, applies config patches.
# Codex is a compiled Rust binary (not npm).
$ErrorActionPreference = "Continue"
Write-Host ""
Write-Host " +--------------------------------------+" -ForegroundColor Cyan
Write-Host " | Codex CLI -- Windows Installer |" -ForegroundColor Cyan
Write-Host " +--------------------------------------+" -ForegroundColor Cyan
Write-Host ""
# ---- Helpers ----
function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
function Refresh-Path {
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" +
[System.Environment]::GetEnvironmentVariable("Path", "User")
}
# ---- Check prerequisites ----
# Python 3.11+ (for tomllib)
$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 {}
}
}
if (-not $pyCmd) {
Write-Host " Python 3.11+ 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
foreach ($candidate in @("python3", "python")) {
if (Test-Command $candidate) { $pyCmd = $candidate; break }
}
}
if (-not $pyCmd) {
Write-Host " Install Python 3.11+ manually: https://www.python.org/downloads/" -ForegroundColor Red
exit 1
}
}
Write-Host " Python OK ($pyCmd)" -ForegroundColor Green
# curl (usually built into Windows 10+)
if (-not (Test-Command "curl.exe") -and -not (Test-Command "curl")) {
Write-Host " curl not found. Using Invoke-WebRequest fallback." -ForegroundColor Yellow
}
# ---- Download Codex binary ----
Write-Host " Checking latest Codex version..." -ForegroundColor Cyan
$githubApi = "https://api.github.com/repos/openai/codex/releases/latest"
try {
$release = Invoke-RestMethod -Uri $githubApi -UseBasicParsing -TimeoutSec 15
$tagName = $release.tag_name
$latestVersion = ($tagName -replace '^rust-v', '')
Write-Host " Latest version: $latestVersion" -ForegroundColor Green
} catch {
Write-Host " Could not fetch latest version from GitHub." -ForegroundColor Red
Write-Host " Check: https://github.com/openai/codex/releases" -ForegroundColor Yellow
exit 1
}
# Check if already installed and up to date
$currentVersion = ""
if (Test-Command "codex") {
try {
$verOut = codex --version 2>$null
$currentVersion = [regex]::Match($verOut, '\d+\.\d+\.\d+').Value
} catch {}
}
if ($currentVersion -eq $latestVersion) {
Write-Host " Codex v$currentVersion already installed and up to date" -ForegroundColor Green
} else {
if ($currentVersion) {
Write-Host " Updating: $currentVersion -> $latestVersion" -ForegroundColor Yellow
} else {
Write-Host " Installing Codex v$latestVersion..." -ForegroundColor Cyan
}
# Determine architecture
$arch = if ([System.Environment]::Is64BitOperatingSystem) { "x86_64" } else { "i686" }
$binarySuffix = "$arch-pc-windows-msvc"
$downloadUrl = "https://github.com/openai/codex/releases/download/rust-v$latestVersion/codex-$binarySuffix.zip"
Write-Host " Downloading: codex-$binarySuffix.zip" -ForegroundColor Cyan
$tempDir = Join-Path $env:TEMP "codex-install-$(Get-Random)"
New-Item -ItemType Directory -Force -Path $tempDir | Out-Null
$zipFile = Join-Path $tempDir "codex.zip"
try {
Invoke-WebRequest -Uri $downloadUrl -OutFile $zipFile -UseBasicParsing
} catch {
Write-Host " Download failed: $_" -ForegroundColor Red
# Try tar.gz fallback
$downloadUrl = "https://github.com/openai/codex/releases/download/rust-v$latestVersion/codex-$binarySuffix.tar.gz"
Write-Host " Trying tar.gz: $downloadUrl" -ForegroundColor Yellow
$tgzFile = Join-Path $tempDir "codex.tar.gz"
try {
Invoke-WebRequest -Uri $downloadUrl -OutFile $tgzFile -UseBasicParsing
tar -xzf $tgzFile -C $tempDir
} catch {
Write-Host " Download failed. Check https://github.com/openai/codex/releases" -ForegroundColor Red
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
exit 1
}
}
# Extract zip if downloaded
if (Test-Path $zipFile) {
Expand-Archive -Path $zipFile -DestinationPath $tempDir -Force
}
# Find codex.exe
$codexExe = Get-ChildItem -Path $tempDir -Recurse -Filter "codex.exe" | Select-Object -First 1
if (-not $codexExe) {
# Try codex without extension
$codexExe = Get-ChildItem -Path $tempDir -Recurse -Filter "codex" | Where-Object { -not $_.PSIsContainer } | Select-Object -First 1
}
if (-not $codexExe) {
Write-Host " codex binary not found in archive" -ForegroundColor Red
Write-Host " Contents:" -ForegroundColor Yellow
Get-ChildItem -Path $tempDir -Recurse | ForEach-Object { Write-Host " $($_.FullName)" }
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
exit 1
}
# Install to user-accessible location
$installDir = "$env:LOCALAPPDATA\Programs\codex"
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
$destPath = Join-Path $installDir "codex.exe"
# Kill running codex processes
Get-Process -Name "codex" -ErrorAction SilentlyContinue | Stop-Process -Force
Copy-Item -Path $codexExe.FullName -Destination $destPath -Force
Write-Host " Installed: $destPath" -ForegroundColor Green
# Add to PATH if not already there
$userPath = [System.Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$installDir*") {
[System.Environment]::SetEnvironmentVariable("Path", "$userPath;$installDir", "User")
$env:Path = "$env:Path;$installDir"
Write-Host " Added to PATH: $installDir" -ForegroundColor Green
}
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
Refresh-Path
# Verify
try {
$newVer = codex --version 2>$null
Write-Host " Codex installed: $newVer" -ForegroundColor Green
} catch {
Write-Host " Binary installed but could not verify version" -ForegroundColor Yellow
}
}
# ---- Download and apply patcher ----
Write-Host " Downloading patcher..." -ForegroundColor Cyan
$patchDir = Join-Path $env:TEMP "codex-patcher-$(Get-Random)"
New-Item -ItemType Directory -Force -Path $patchDir | Out-Null
$repoRaw = "https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/codex"
$token = "cadffcb0a6a3be728ac1ff619bb40c86588f6837"
$headers = @{ "Authorization" = "token $token" }
try {
Invoke-WebRequest -Uri "$repoRaw/codex_patcher.py" -OutFile "$patchDir\codex_patcher.py" -UseBasicParsing -Headers $headers
Invoke-WebRequest -Uri "$repoRaw/codex_config.json" -OutFile "$patchDir\codex_config.json" -UseBasicParsing -Headers $headers
Write-Host " Patcher downloaded" -ForegroundColor Green
} catch {
# Try without auth
try {
Invoke-WebRequest -Uri "$repoRaw/codex_patcher.py" -OutFile "$patchDir\codex_patcher.py" -UseBasicParsing
Invoke-WebRequest -Uri "$repoRaw/codex_config.json" -OutFile "$patchDir\codex_config.json" -UseBasicParsing
Write-Host " Patcher downloaded (no auth)" -ForegroundColor Green
} catch {
Write-Host " Download failed: $_" -ForegroundColor Red
Write-Host " Clone repo manually: git clone https://git.sensey24.ru/aibot777/unlimitedcoding.git" -ForegroundColor Yellow
Remove-Item -Recurse -Force $patchDir -ErrorAction SilentlyContinue
exit 1
}
}
Write-Host " Applying patches..." -ForegroundColor Cyan
& $pyCmd "$patchDir\codex_patcher.py" --apply --config "$patchDir\codex_config.json"
if ($LASTEXITCODE -ne 0) {
Write-Host " Patching returned exit code $LASTEXITCODE" -ForegroundColor Yellow
}
Write-Host " Patches applied" -ForegroundColor Green
Remove-Item -Recurse -Force $patchDir -ErrorAction SilentlyContinue
# ---- Configure environment variables ----
Write-Host " Setting environment variables..." -ForegroundColor Cyan
[System.Environment]::SetEnvironmentVariable("OPENAI_API_KEY", "ClauderAPI", "User")
[System.Environment]::SetEnvironmentVariable("OPENAI_BASE_URL", "https://ai.37-187-136-86.sslip.io/v1", "User")
$env:OPENAI_API_KEY = "ClauderAPI"
$env:OPENAI_BASE_URL = "https://ai.37-187-136-86.sslip.io/v1"
Write-Host " Env vars set (OPENAI_API_KEY, OPENAI_BASE_URL)" -ForegroundColor Green
# ---- Verify ----
Write-Host ""
Write-Host " Verifying..." -ForegroundColor Cyan
Refresh-Path
try {
$result = & codex exec "Reply with just the number 42" 2>&1 | Out-String
if ($result -match "42") {
Write-Host ""
Write-Host " Codex CLI installed and patched!" -ForegroundColor Green
Write-Host ""
Write-Host " Usage:"
Write-Host " codex # interactive mode"
Write-Host " codex exec `"Your prompt`" # single prompt"
Write-Host ""
Write-Host " Models:"
Write-Host " gpt-5.4, gpt-5.3-codex-spark"
Write-Host " gpt-5.3-codex, gpt-5.2-codex"
} else {
Write-Host " Patches applied but test prompt did not return expected result." -ForegroundColor Yellow
Write-Host " Try: codex exec `"Hello`"" -ForegroundColor Yellow
}
} catch {
Write-Host " Could not run test. Try: codex exec `"Hello`"" -ForegroundColor Yellow
}
Write-Host ""

191
gemini/ugemini_install.ps1 Executable file
View File

@@ -0,0 +1,191 @@
# Gemini CLI — Windows Installer
# Usage: powershell -ExecutionPolicy Bypass -File gemini\ugemini_install.ps1
#
# Installs Node.js (if needed), Gemini CLI via npm registry, configures env vars and settings.
$ErrorActionPreference = "Continue"
Write-Host ""
Write-Host " +--------------------------------------+" -ForegroundColor Cyan
Write-Host " | Gemini CLI -- Windows Installer |" -ForegroundColor Cyan
Write-Host " +--------------------------------------+" -ForegroundColor Cyan
Write-Host ""
# ---- Helpers ----
function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
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 prerequisites ----
# Node.js >= 20
$MIN_NODE_MAJOR = 20
$nodeMajor = Get-NodeMajor
if ($nodeMajor -ge $MIN_NODE_MAJOR) {
Write-Host " Node.js v$nodeMajor.x OK" -ForegroundColor Green
} else {
if ($nodeMajor -gt 0) {
Write-Host " Node.js v$nodeMajor found, need v$MIN_NODE_MAJOR+. Upgrading..." -ForegroundColor Yellow
} else {
Write-Host " Node.js not found. Installing..." -ForegroundColor Yellow
}
$installed = $false
# 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 $MIN_NODE_MAJOR) { $installed = $true }
}
# 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 $MIN_NODE_MAJOR) { $installed = $true }
}
# 3. Direct MSI download
if (-not $installed) {
Write-Host " Downloading Node.js v24 MSI..." -ForegroundColor Yellow
try {
$latestForMajor = "v24.0.0"
try {
$releases = Invoke-RestMethod -Uri "https://nodejs.org/dist/index.json" -UseBasicParsing -TimeoutSec 10
$match = $releases | Where-Object { $_.version -match "^v24\." } | 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-v24.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 $MIN_NODE_MAJOR) { $installed = $true }
} catch {
Write-Host " Download failed: $_" -ForegroundColor Red
}
}
if (-not $installed) {
Write-Host ""
Write-Host " Could not install Node.js automatically." -ForegroundColor Red
Write-Host " Install manually: https://nodejs.org/en/download/ (v$MIN_NODE_MAJOR+)" -ForegroundColor Yellow
exit 1
}
Write-Host " Node.js v$(Get-NodeMajor).x installed OK" -ForegroundColor Green
}
# ---- Configure npm registry ----
Write-Host " Configuring npm registry..." -ForegroundColor Cyan
npm config set "@google:registry" "https://npm.sensey24.ru/" 2>$null
# ---- Install Gemini CLI ----
if (-not (Test-Command "gemini")) {
Write-Host " Installing @google/gemini-cli..." -ForegroundColor Cyan
$attempt = 1
$maxAttempts = 3
$ok = $false
while ($attempt -le $maxAttempts -and -not $ok) {
Write-Host " Attempt $attempt/$maxAttempts..." -ForegroundColor Yellow
npm install -g @google/gemini-cli 2>&1
if ($LASTEXITCODE -eq 0) { $ok = $true }
else {
$attempt++
if ($attempt -le $maxAttempts) { Start-Sleep -Seconds 3 }
}
}
if (-not $ok) {
Write-Host ""
Write-Host " npm install failed after $maxAttempts attempts." -ForegroundColor Red
Write-Host " Try: npm config set `"@google:registry`" `"http://npm.sensey24.ru/`"" -ForegroundColor Yellow
Write-Host " Then: npm install -g @google/gemini-cli" -ForegroundColor Yellow
exit 1
}
Refresh-Path
Write-Host " Gemini CLI installed" -ForegroundColor Green
} else {
Write-Host " Gemini CLI already installed" -ForegroundColor Green
}
# ---- Configure environment variables ----
Write-Host " Setting environment variables..." -ForegroundColor Cyan
[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"
Write-Host " Env vars set (GEMINI_API_KEY, GOOGLE_GEMINI_BASE_URL)" -ForegroundColor Green
# ---- Configure settings ----
Write-Host " Configuring settings..." -ForegroundColor Cyan
$geminiDir = "$env:USERPROFILE\.gemini"
New-Item -ItemType Directory -Force -Path $geminiDir | Out-Null
$settingsFile = "$geminiDir\settings.json"
$json = @'
{
"security": {
"auth": {
"selectedType": "gemini-api-key"
}
},
"telemetry": {
"enabled": false,
"logPrompts": false
}
}
'@
[System.IO.File]::WriteAllText($settingsFile, $json)
Write-Host " Settings: $settingsFile" -ForegroundColor Green
# ---- Verify ----
Write-Host ""
Write-Host " Verifying..." -ForegroundColor Cyan
Refresh-Path
try {
$result = & gemini -p "Reply with just OK" 2>&1 | Out-String
if ($result -match "OK") {
Write-Host ""
Write-Host " Gemini CLI installed and patched!" -ForegroundColor Green
Write-Host ""
Write-Host " Usage:"
Write-Host " gemini # interactive mode"
Write-Host " gemini -p `"Your prompt`" # single prompt"
Write-Host ""
Write-Host " Models:"
Write-Host " gemini-2.5-pro, gemini-2.5-flash"
Write-Host " gemini-3-pro-preview, gemini-3-flash-preview"
} else {
Write-Host " Patches applied but test prompt did not return OK." -ForegroundColor Yellow
Write-Host " Try: gemini -p `"Hello`"" -ForegroundColor Yellow
}
} catch {
Write-Host " Could not run test. Try: gemini -p `"Hello`"" -ForegroundColor Yellow
}
Write-Host ""

226
qwen/uqwen_install.ps1 Normal file
View File

@@ -0,0 +1,226 @@
# Qwen Code — Windows Installer
# Usage: powershell -ExecutionPolicy Bypass -File qwen\uqwen_install.ps1
#
# Installs Node.js (if needed), Qwen Code via npm registry, configures env vars and settings.
$ErrorActionPreference = "Continue"
Write-Host ""
Write-Host " +--------------------------------------+" -ForegroundColor Cyan
Write-Host " | Qwen Code -- Windows Installer |" -ForegroundColor Cyan
Write-Host " +--------------------------------------+" -ForegroundColor Cyan
Write-Host ""
# ---- Helpers ----
function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
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 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
}
}
$pyCmd = if (Test-Command "python3") { "python3" } else { "python" }
Write-Host " Python OK" -ForegroundColor Green
# Node.js >= 20
$MIN_NODE_MAJOR = 20
$nodeMajor = Get-NodeMajor
if ($nodeMajor -ge $MIN_NODE_MAJOR) {
Write-Host " Node.js v$nodeMajor.x OK" -ForegroundColor Green
} else {
if ($nodeMajor -gt 0) {
Write-Host " Node.js v$nodeMajor found, need v$MIN_NODE_MAJOR+. Upgrading..." -ForegroundColor Yellow
} else {
Write-Host " Node.js not found. Installing..." -ForegroundColor Yellow
}
$installed = $false
# 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 $MIN_NODE_MAJOR) { $installed = $true }
}
# 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 $MIN_NODE_MAJOR) { $installed = $true }
}
# 3. Direct MSI download
if (-not $installed) {
Write-Host " Downloading Node.js v24 MSI..." -ForegroundColor Yellow
try {
$latestForMajor = "v24.0.0"
try {
$releases = Invoke-RestMethod -Uri "https://nodejs.org/dist/index.json" -UseBasicParsing -TimeoutSec 10
$match = $releases | Where-Object { $_.version -match "^v24\." } | 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-v24.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 $MIN_NODE_MAJOR) { $installed = $true }
} catch {
Write-Host " Download failed: $_" -ForegroundColor Red
}
}
if (-not $installed) {
Write-Host ""
Write-Host " Could not install Node.js automatically." -ForegroundColor Red
Write-Host " Install manually: https://nodejs.org/en/download/ (v$MIN_NODE_MAJOR+)" -ForegroundColor Yellow
exit 1
}
Write-Host " Node.js v$(Get-NodeMajor).x installed OK" -ForegroundColor Green
}
# ---- Configure npm registry ----
Write-Host " Configuring npm registry..." -ForegroundColor Cyan
npm config set "@qwen-code:registry" "https://npm.sensey24.ru/" 2>$null
# ---- Install Qwen Code ----
$qwenBin = $null
foreach ($candidate in @("qwen", "qwen-code")) {
if (Test-Command $candidate) { $qwenBin = $candidate; break }
}
if (-not $qwenBin) {
Write-Host " Installing @qwen-code/qwen-code..." -ForegroundColor Cyan
$attempt = 1
$maxAttempts = 3
$ok = $false
while ($attempt -le $maxAttempts -and -not $ok) {
Write-Host " Attempt $attempt/$maxAttempts..." -ForegroundColor Yellow
npm install -g @qwen-code/qwen-code 2>&1
if ($LASTEXITCODE -eq 0) { $ok = $true }
else {
$attempt++
if ($attempt -le $maxAttempts) { Start-Sleep -Seconds 3 }
}
}
if (-not $ok) {
Write-Host ""
Write-Host " npm install failed after $maxAttempts attempts." -ForegroundColor Red
Write-Host " Try: npm config set `"@qwen-code:registry`" `"http://npm.sensey24.ru/`"" -ForegroundColor Yellow
Write-Host " Then: npm install -g @qwen-code/qwen-code" -ForegroundColor Yellow
exit 1
}
Refresh-Path
foreach ($candidate in @("qwen", "qwen-code")) {
if (Test-Command $candidate) { $qwenBin = $candidate; break }
}
Write-Host " Qwen Code installed" -ForegroundColor Green
} else {
Write-Host " Qwen Code already installed" -ForegroundColor Green
}
# ---- 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
$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
$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
}
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
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
# ---- Configure environment variables ----
Write-Host " Setting environment variables..." -ForegroundColor Cyan
[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"
Write-Host " Env vars set (QWEN_API_KEY, QWEN_BASE_URL)" -ForegroundColor Green
# ---- Verify ----
Write-Host ""
Write-Host " Verifying..." -ForegroundColor Cyan
Refresh-Path
if ($qwenBin) {
try {
$result = & $qwenBin -p "Reply with just OK" 2>&1 | Out-String
if ($result -match "OK") {
Write-Host ""
Write-Host " Qwen Code installed and patched!" -ForegroundColor Green
Write-Host ""
Write-Host " Usage:"
Write-Host " $qwenBin # interactive mode"
Write-Host " $qwenBin -p `"Your prompt`" # single prompt"
Write-Host ""
Write-Host " Models:"
Write-Host " qwen3.5-plus, qwen3-coder-plus"
Write-Host " qwen3-coder-flash, coder-model"
} else {
Write-Host " Patches applied but test prompt did not return OK." -ForegroundColor Yellow
Write-Host " Try: $qwenBin -p `"Hello`"" -ForegroundColor Yellow
}
} catch {
Write-Host " Could not run test. Try: $qwenBin -p `"Hello`"" -ForegroundColor Yellow
}
} else {
Write-Host " Qwen binary not found in PATH." -ForegroundColor Yellow
Write-Host " Check: npm list -g @qwen-code/qwen-code" -ForegroundColor Yellow
Write-Host " Then restart terminal and run: qwen -p `"Hello`"" -ForegroundColor Yellow
}
Write-Host ""