173 lines
8.6 KiB
PowerShell
173 lines
8.6 KiB
PowerShell
# =============================================================
|
|
# Claude на чужих мозгах — установщик (Windows)
|
|
# Что делает: проверяет Claude и Ollama, создаёт псевдонимы
|
|
# моделей, кладёт два конфига (Ollama Cloud + Z.ai) в приложение
|
|
# Claude и перезапускает его.
|
|
# Запуск одной командой (Windows, PowerShell):
|
|
# irm {URL}/setup.ps1 | iex
|
|
# Откат:
|
|
# $env:SETUP_MODE='restore'; irm {URL}/setup.ps1 | iex
|
|
# =============================================================
|
|
param([string]$Mode = "install")
|
|
if ($env:SETUP_MODE) { $Mode = $env:SETUP_MODE; $env:SETUP_MODE = $null }
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$C3P = Join-Path $env:LOCALAPPDATA "Claude-3p"
|
|
$LIB = Join-Path $C3P "configLibrary"
|
|
$ID_OLLAMA = "a11a0000-0000-4000-8000-0000000000aa"
|
|
$ID_ZAI = "a11a0000-0000-4000-8000-0000000000bb"
|
|
$ID_DEFAULT = "a11a0000-0000-4000-8000-0000000000dd"
|
|
|
|
function Say($t) { Write-Host "`n$t" -ForegroundColor White }
|
|
function Ok($t) { Write-Host " [ok] $t" -ForegroundColor Green }
|
|
function Warn($t) { Write-Host " [!] $t" -ForegroundColor Yellow }
|
|
|
|
function Read-Meta {
|
|
$metaPath = Join-Path $LIB "_meta.json"
|
|
if (Test-Path $metaPath) { Get-Content $metaPath -Raw | ConvertFrom-Json }
|
|
else { [pscustomobject]@{ appliedId = ""; entries = @() } }
|
|
}
|
|
function Write-Meta($meta) {
|
|
$meta | ConvertTo-Json -Depth 5 | Set-Content (Join-Path $LIB "_meta.json") -Encoding UTF8
|
|
}
|
|
function Ensure-Entry($meta, $id, $name) {
|
|
$e = $meta.entries | Where-Object { $_.id -eq $id }
|
|
if ($e) { $e.name = $name }
|
|
else { $meta.entries = @($meta.entries) + [pscustomobject]@{ id = $id; name = $name } }
|
|
return $meta
|
|
}
|
|
function Restart-Claude {
|
|
Say "Перезапускаю приложение Claude..."
|
|
Get-Process -Name "Claude*" -ErrorAction SilentlyContinue | Stop-Process -Force
|
|
Start-Sleep 3
|
|
Start-Process "claude://" -ErrorAction SilentlyContinue
|
|
if (-not $?) {
|
|
$exe = @("$env:LOCALAPPDATA\AnthropicClaude","$env:LOCALAPPDATA\Programs") | ForEach-Object { Get-ChildItem $_ -Recurse -Filter "claude.exe" -ErrorAction SilentlyContinue } | Select-Object -First 1
|
|
if ($exe) { Start-Process $exe.FullName } else { Warn "Открой Claude вручную." }
|
|
}
|
|
Ok "Готово. Открой выбор модели в чате: там GLM-5.3, Kimi K3 и Flash."
|
|
}
|
|
|
|
# ---------- ОТКАТ ----------
|
|
if ($Mode -eq "restore") {
|
|
Say "Откат на родной Claude..."
|
|
if (-not (Test-Path (Join-Path $LIB "_meta.json"))) { Ok "Конфигов нет, откатывать нечего."; exit }
|
|
$meta = Read-Meta
|
|
$def = $meta.entries | Where-Object { $_.name -eq "Default" } | Select-Object -First 1
|
|
if (-not $def) {
|
|
"{}" | Set-Content (Join-Path $LIB "$ID_DEFAULT.json") -Encoding UTF8
|
|
$meta = Ensure-Entry $meta $ID_DEFAULT "Default"
|
|
$def = $meta.entries | Where-Object { $_.id -eq $ID_DEFAULT }
|
|
}
|
|
$meta.appliedId = $def.id
|
|
Write-Meta $meta
|
|
Ok "Применён пустой конфиг Default: приложение вернётся к родному входу."
|
|
Restart-Claude
|
|
Write-Host "`nЕсли что-то осталось сломанным, полный сброс (сотрёт чаты стороннего режима):"
|
|
Write-Host " удали папки $env:LOCALAPPDATA\Claude-3p и $env:LOCALAPPDATA\Claude Nest-3p"
|
|
exit
|
|
}
|
|
|
|
# ---------- 1. Claude ----------
|
|
Say "[1/5] Проверяю приложение Claude..."
|
|
$claudeExe = @("$env:LOCALAPPDATA\AnthropicClaude","$env:LOCALAPPDATA\Programs") | ForEach-Object { Get-ChildItem $_ -Recurse -Filter "claude.exe" -ErrorAction SilentlyContinue } | Select-Object -First 1
|
|
if ($claudeExe) { Ok "Claude установлен." }
|
|
else {
|
|
Warn "Claude не найден. Открываю страницу загрузки..."
|
|
Start-Process "https://claude.com/download"
|
|
Write-Host " Установи Claude, запусти его один раз, войди в аккаунт, затем запусти скрипт снова."
|
|
exit
|
|
}
|
|
|
|
# ---------- 2. Ollama ----------
|
|
Say "[2/5] Проверяю программу Ollama..."
|
|
$haveOllama = [bool](Get-Command ollama -ErrorAction SilentlyContinue)
|
|
if ($haveOllama) { Ok "Ollama установлена." }
|
|
else {
|
|
$ans = Read-Host " Ollama не найдена. Скачать? Нужна для маршрута Ollama Cloud [Y/n]"
|
|
if ($ans -ne "n" -and $ans -ne "N") {
|
|
Start-Process "https://ollama.com/download/OllamaSetup.exe"
|
|
Write-Host " Установи Ollama, запусти, войди в аккаунт (Sign in), затем запусти скрипт снова."
|
|
exit
|
|
} else { Warn "Пропускаю Ollama: поставлю только конфиг Z.ai." }
|
|
}
|
|
|
|
# ---------- 3. Псевдонимы ----------
|
|
if ($haveOllama) {
|
|
Say "[3/5] Создаю псевдонимы облачных моделей (нужен вход в аккаунт Ollama)..."
|
|
$pairs = @(
|
|
@("glm-5.3:cloud", "claude-sonnet-4-6"),
|
|
@("kimi-k3:cloud", "claude-opus-4-6"),
|
|
@("glm-5.3-flash:cloud", "claude-haiku-4-5")
|
|
)
|
|
foreach ($p in $pairs) {
|
|
& ollama pull $p[0] 2>$null
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Warn "Не получилось скачать $($p[0]). Скорее всего, нет входа в аккаунт."
|
|
Write-Host " Открой окно Ollama -> Settings -> Sign in, затем запусти скрипт снова."
|
|
exit 1
|
|
}
|
|
& ollama cp $p[0] $p[1] | Out-Null
|
|
Ok "$($p[1]) -> $($p[0])"
|
|
}
|
|
} else { Say "[3/5] Ollama нет, псевдонимы пропускаю." }
|
|
|
|
# ---------- 4. Конфиги ----------
|
|
Say "[4/5] Кладу конфиги в приложение Claude..."
|
|
New-Item -ItemType Directory -Force -Path $LIB | Out-Null
|
|
$devSettings = Join-Path $C3P "developer_settings.json"
|
|
if (-not (Test-Path $devSettings)) { '{"allowDevTools": true}' | Set-Content $devSettings -Encoding UTF8 }
|
|
|
|
@'
|
|
{
|
|
"inferenceProvider": "gateway",
|
|
"inferenceGatewayBaseUrl": "http://localhost:11434",
|
|
"inferenceGatewayApiKey": "ollama",
|
|
"inferenceGatewayAuthScheme": "bearer",
|
|
"inferenceCredentialKind": "static",
|
|
"modelDiscoveryEnabled": false,
|
|
"inferenceModels": [
|
|
{ "name": "claude-sonnet-4-6", "labelOverride": "GLM-5.3 (Ollama Cloud)", "anthropicFamilyTier": "sonnet", "isFamilyDefault": true },
|
|
{ "name": "claude-opus-4-6", "labelOverride": "Kimi K3 (Ollama Cloud)", "anthropicFamilyTier": "opus", "isFamilyDefault": true },
|
|
{ "name": "claude-haiku-4-5", "labelOverride": "GLM-5.3 Flash (Ollama Cloud)", "anthropicFamilyTier": "haiku", "isFamilyDefault": true }
|
|
]
|
|
}
|
|
'@ | Set-Content (Join-Path $LIB "$ID_OLLAMA.json") -Encoding UTF8
|
|
|
|
@'
|
|
{
|
|
"inferenceProvider": "gateway",
|
|
"inferenceGatewayBaseUrl": "https://api.z.ai/api/anthropic",
|
|
"inferenceGatewayApiKey": "ВСТАВЬ_СЮДА_СВОЙ_КЛЮЧ_ZAI",
|
|
"inferenceGatewayAuthScheme": "bearer",
|
|
"inferenceCredentialKind": "static",
|
|
"modelDiscoveryEnabled": false,
|
|
"inferenceModels": [
|
|
{ "name": "claude-sonnet-4-6", "labelOverride": "GLM-5.3 (Z.ai Coding Plan)", "anthropicFamilyTier": "sonnet", "isFamilyDefault": true },
|
|
{ "name": "claude-haiku-4-5", "labelOverride": "GLM-5.3 Flash (Z.ai, vision)", "anthropicFamilyTier": "haiku", "isFamilyDefault": true }
|
|
]
|
|
}
|
|
'@ | Set-Content (Join-Path $LIB "$ID_ZAI.json") -Encoding UTF8
|
|
|
|
$meta = Read-Meta
|
|
if (-not ($meta.entries | Where-Object { $_.name -eq "Default" })) {
|
|
"{}" | Set-Content (Join-Path $LIB "$ID_DEFAULT.json") -Encoding UTF8
|
|
$meta = Ensure-Entry $meta $ID_DEFAULT "Default"
|
|
}
|
|
$meta = Ensure-Entry $meta $ID_OLLAMA "ollama-cloud"
|
|
$meta = Ensure-Entry $meta $ID_ZAI "zai-glm"
|
|
if ($haveOllama) { $meta.appliedId = $ID_OLLAMA }
|
|
elseif (-not $meta.appliedId) { $meta.appliedId = $ID_DEFAULT }
|
|
Write-Meta $meta
|
|
Ok "Конфиги на месте."
|
|
|
|
# ---------- 5. Рестарт ----------
|
|
if ($Mode -eq "no-restart") { Warn "Перезапуск Claude пропущен." } else { Restart-Claude }
|
|
|
|
Write-Host ""
|
|
Write-Host "Что дальше:"
|
|
Write-Host " · Модель выбирается в чате, рядом с полем ввода."
|
|
Write-Host " · Конфиг Z.ai лежит рядом (панель Developer -> Configure Third-Party Inference):"
|
|
Write-Host " выбери zai-glm, вставь свой ключ в Gateway API key, Apply Changes, перезапуск."
|
|
Write-Host " · Вернуть родной Claude: powershell -File setup-windows.ps1 restore"
|