@echo off
chcp 65001 >nul
setlocal EnableExtensions
title DreamN — автонастройка API-ключа

rem ============================================================
rem  DreamN — автонастройка ключа из заказа FunPay  ·  v2.0
rem
rem  Прописывает ключ и модели в: Claude Code, Codex,
rem  Cline / Roo Code / Kilo Code (VS Code, VSCodium, Cursor),
rem  OpenCode и ZCode (reasoning + vision + показ размышлений).
rem  Для Cursor дополнительно печатает ручные шаги.
rem
rem  Надёжность:
rem   · ключ передаётся в PowerShell через переменную окружения
rem     (спецсимволы при вставке не ломают команду);
rem   · все JSON пишутся UTF-8 без BOM (иначе клиенты на Node
rem     не могут их прочитать);
rem   · TLS 1.2 включается принудительно (старые Windows);
rem   · существующие конфиги объединяются, а не затираются,
rem     и сохраняются в .bak;
rem   · модели ПЕРЕД записью проверяются живым запросом:
rem     gpt-5.6-sol / claude-opus-5 / gpt-6-astra могут быть
rem     временно недоступны — скрипт сам выберет рабочую модель;
rem   · image-модели (qwen-image-*, wan*, z-image-*) в конфиги
rem     чат-клиентов не пишутся;
rem   · в конце — самопроверка всех записанных конфигов.
rem
rem  При смене домена поменять только GW ниже.
rem  DREAMN_SKIP_SETX=1 отключает setx (только для тестов).
rem ============================================================
set "GW=https://ai.dreamn-api-market.ru"
set "DREAMN_GW=%GW%"
set "DREAMN_T=%TEMP%\dreamn_setup"
if not exist "%DREAMN_T%" mkdir "%DREAMN_T%" >nul 2>nul
del /q "%DREAMN_T%\*.txt" >nul 2>nul

where powershell >nul 2>nul
if errorlevel 1 (
    echo.
    echo   [!!] Не найден PowerShell — автонастройка невозможна.
    echo        Настройте клиенты вручную: Base URL %GW%/v1,
    echo        API Key — ваш ключ sk-... Инструкция: dreamn-api-market.ru
    echo.
    pause
    exit /b 1
)

echo.
echo   ==============================================
echo     DreamN — автонастройка API-ключа · v2.0
echo   ==============================================
echo.
echo   Ключ приходит в чат заказа FunPay после оплаты
echo   и начинается с "sk-".
echo.
echo   Будут настроены: Claude Code, Codex, Cline,
echo   Roo Code, Kilo Code, OpenCode, ZCode.
echo   Для Cursor покажем ручные шаги — 30 секунд.
echo.

set "APIKEY="
set /p APIKEY=Вставьте API-ключ из заказа: 
if not defined APIKEY (
    echo.
    echo   [!!] Ключ не введён. Запустите скрипт ещё раз.
    pause
    exit /b 1
)

echo.
echo   [1/8] Проверяю ключ и получаю список моделей...
rem Ключ нормализуется в PowerShell (пробелы/кавычки при вставке), ответ — в %DREAMN_T%
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop';[Net.ServicePointManager]::SecurityProtocol=[Net.ServicePointManager]::SecurityProtocol -bor 3072;$T=$env:DREAMN_T;$k=($env:APIKEY -replace '\s','').Trim([char]34).Trim();if(-not $k){Write-Host '       [!!] Ключ пустой — введите его целиком.';exit 2};if(-not $k.StartsWith('sk-')){Write-Host '       [?] Ключ обычно начинается с sk- — проверяю как есть.'};try{$r=Invoke-RestMethod -Uri ($env:DREAMN_GW+'/v1/models') -Headers @{Authorization=('Bearer '+$k)} -TimeoutSec 25}catch{$c=0;if($_.Exception.Response){$c=[int]$_.Exception.Response.StatusCode};if($c -eq 401 -or $c -eq 403){Write-Host '       [!!] Сервер отклонил ключ: проверьте, что скопировали его целиком из чата заказа.'}else{Write-Host ('       [!!] Не удалось связаться с сервером: '+$_.Exception.Message);Write-Host '       Проверьте интернет или повторите попытку позже.'};exit 3};$names=@($r.data|ForEach-Object{''+$_.id}|Where-Object{$_});if(-not $names.Count){Write-Host '       [!!] Ключ не вернул ни одной модели — напишите в чат заказа.';exit 4};$hidden=@('qwen-image-max','qwen-image-3.0','qwen-image-3.0-pro','qwen-image-edit-max','qwen-image-edit-plus','wan2.7-image','z-image-turbo');$chat=@($names|Where-Object{$hidden -notcontains $_});if(-not $chat.Count){$chat=$names};$io=[System.IO.File];$io::WriteAllText((Join-Path $T 'key.txt'),$k);$io::WriteAllText((Join-Path $T 'models.txt'),($names -join ','));$io::WriteAllText((Join-Path $T 'chatmodels.txt'),($chat -join ','));Write-Host ('       [OK] Ключ работает, моделей доступно: '+$names.Count);Write-Host ('       '+($names -join ', '));exit 0"
if errorlevel 1 (
    echo.
    echo   [!!] Без работающего ключа продолжать нет смысла.
    echo        Уточните ключ в чате заказа FunPay и запустите скрипт заново.
    pause
    exit /b 1
)
set /p APIKEY=<"%DREAMN_T%\key.txt"
set /p MODELS=<"%DREAMN_T%\models.txt"
set /p CHATMODELS=<"%DREAMN_T%\chatmodels.txt"
set "DREAMN_CHATMODELS=%CHATMODELS%"

echo.
echo   [2/8] Живой тест моделей — выбираю рабочую, займёт 10-40 секунд...
rem Параллельные пробные запросы к каждой модели-кандидату; итог — main.txt / claude.txt / notes.txt
powershell -NoProfile -ExecutionPolicy Bypass -Command "$T=$env:DREAMN_T;$GW=$env:DREAMN_GW;$io=[System.IO.File];$chat=@(($io::ReadAllText((Join-Path $T 'chatmodels.txt')).Trim()) -split ',');$prio=@('qwen3.8-max','qwen3.8-max-0902','glm-5.3','kimi-k3','deepseek-v4-pro-0813','deepseek-v4.1-flash');$cands=@($prio|Where-Object{$chat -contains $_});foreach($m in @('claude-opus-5','gpt-5.6-sol','gpt-6-astra')){if(($chat -contains $m) -and ($cands -notcontains $m)){$cands+=$m}};if(-not $cands.Count){$cands=@($chat|Select-Object -First 5)};if($cands.Count -gt 10){$cands=@($cands|Select-Object -First 10)};$sb={param($gw,$key,$model)[Net.ServicePointManager]::SecurityProtocol=[Net.ServicePointManager]::SecurityProtocol -bor 3072;$body=@{model=$model;max_tokens=8;stream=$false;messages=@(@{role='user';content='ping'})}|ConvertTo-Json -Depth 5 -Compress;$sw=[Diagnostics.Stopwatch]::StartNew();try{$r=Invoke-WebRequest -Uri ($gw+'/v1/chat/completions') -Method Post -Headers @{Authorization=('Bearer '+$key)} -ContentType 'application/json; charset=utf-8' -Body $body -TimeoutSec 80 -UseBasicParsing;$sw.Stop();if($r.Content.Contains([char]34+'error'+[char]34)){return ($model+'|fail|ошибка в ответе')};return ($model+'|ok|'+$sw.ElapsedMilliseconds)}catch{$sw.Stop();return ($model+'|fail|нет ответа')}};$jobs=@();foreach($m in $cands){$jobs+=Start-Job -ScriptBlock $sb -ArgumentList $GW,$env:APIKEY,$m};$null=Wait-Job $jobs -Timeout 100;$res=@{};foreach($j in $jobs){$o=Receive-Job $j -ErrorAction SilentlyContinue;Remove-Job $j -Force;if($o){$p=(''+$o) -split '\|',3;$res[$p[0]]=@{ok=($p[1] -eq 'ok');info=$p[2]}}};$missing=@($cands|Where-Object{-not $res.ContainsKey($_)});if($missing.Count){Write-Host ('       Повторная проверка: '+($missing -join ', '))};foreach($m in $missing){$body=@{model=$m;max_tokens=8;stream=$false;messages=@(@{role='user';content='ping'})}|ConvertTo-Json -Depth 5 -Compress;$sw=[Diagnostics.Stopwatch]::StartNew();try{$r=Invoke-WebRequest -Uri ($GW+'/v1/chat/completions') -Method Post -Headers @{Authorization=('Bearer '+$env:APIKEY)} -ContentType 'application/json; charset=utf-8' -Body $body -TimeoutSec 30 -UseBasicParsing;$sw.Stop();if($r.Content.Contains([char]34+'error'+[char]34)){$res[$m]=@{ok=$false;info='ошибка в ответе'}}else{$res[$m]=@{ok=$true;info=''+$sw.ElapsedMilliseconds}}}catch{$res[$m]=@{ok=$false;info='нет ответа'}}};$main='';$claude='';foreach($m in $cands){if($res.ContainsKey($m) -and $res[$m].ok){if(-not $main){$main=$m};if($m -eq 'claude-opus-5'){$claude=$m}}};if(-not $main){$main=$chat[0]};if(-not $claude){$claude=$main};foreach($m in $cands){if($res.ContainsKey($m)){if($res[$m].ok){Write-Host ('       [OK] '+$m+' — отвечает, '+[math]::Round([double]$res[$m].info/1000,1)+' с')}else{Write-Host ('       [--] '+$m+' — временно не отвечает')}}else{Write-Host ('       [??] '+$m+' — проверка не завершилась')}};$io::WriteAllText((Join-Path $T 'main.txt'),$main);$io::WriteAllText((Join-Path $T 'claude.txt'),$claude);$notes=New-Object System.Collections.Generic.List[string];$bad=@('gpt-5.6-sol','claude-opus-5','gpt-6-astra'|Where-Object{$chat -contains $_ -and ((-not $res.ContainsKey($_)) -or (-not $res[$_].ok))});if($bad.Count){$notes.Add('     ВАЖНО: '+($bad -join ', ')+' — временно недоступны');$notes.Add('     на стороне провайдера. Баланс ключа не сгорает:');$notes.Add('     конфиги настроены на рабочую модель '+$main+'.');$notes.Add('     Когда их вернут — просто выберите их в клиенте.')};if(-not ($res.ContainsKey($main) -and $res[$main].ok)){$notes.Add('     Ни одна модель не ответила на тест. Конфиги записаны,');$notes.Add('     но проверьте интернет или напишите в чат заказа.')};if($notes.Count){$io::WriteAllText((Join-Path $T 'notes.txt'),(($notes -join [Environment]::NewLine)+[Environment]::NewLine))}else{Remove-Item (Join-Path $T 'notes.txt') -Force -ErrorAction SilentlyContinue};Write-Host ('       Основная модель для конфигов: '+$main);exit 0"
if errorlevel 1 echo   [??] Тест моделей не завершился — беру первую доступную модель.
if exist "%DREAMN_T%\main.txt" (set /p MODEL=<"%DREAMN_T%\main.txt") else (for /f "delims=," %%a in ("%CHATMODELS%") do set "MODEL=%%a")
if exist "%DREAMN_T%\claude.txt" (set /p CLAUDEMODEL=<"%DREAMN_T%\claude.txt") else (set "CLAUDEMODEL=%MODEL%")
set "DREAMN_MODEL=%MODEL%"
set "DREAMN_CLAUDE_MODEL=%CLAUDEMODEL%"

echo.
echo   [3/8] Claude Code...
rem ~/.claude/settings.json: секция env, старые значения сохраняются, конфликтующий ANTHROPIC_API_KEY удаляется
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop';$io=[System.IO.File];$utf8=New-Object System.Text.UTF8Encoding($false);$p=Join-Path $env:USERPROFILE '.claude\settings.json';New-Item -ItemType Directory -Force -Path (Split-Path $p)|Out-Null;if(Test-Path $p){Copy-Item $p ($p+'.bak') -Force};$d=@{};if(Test-Path $p){try{$j=$io::ReadAllText($p)|ConvertFrom-Json;foreach($pr in $j.PSObject.Properties){$d[$pr.Name]=$pr.Value}}catch{Write-Host '       [?] Старый settings.json не читается — собираю новый, старый сохранён в .bak'}};$e=@{};if($d.ContainsKey('env') -and $d['env']){foreach($pr in $d['env'].PSObject.Properties){$e[$pr.Name]=$pr.Value}};$e.Remove('ANTHROPIC_API_KEY');$d.Remove('apiKeyHelper');$e['ANTHROPIC_BASE_URL']=$env:DREAMN_GW;$e['ANTHROPIC_AUTH_TOKEN']=$env:APIKEY;foreach($n in @('ANTHROPIC_MODEL','ANTHROPIC_SMALL_FAST_MODEL','ANTHROPIC_DEFAULT_OPUS_MODEL','ANTHROPIC_DEFAULT_SONNET_MODEL','ANTHROPIC_DEFAULT_HAIKU_MODEL')){$e[$n]=$env:DREAMN_CLAUDE_MODEL};$d['env']=$e;$io::WriteAllText($p,($d|ConvertTo-Json -Depth 20),$utf8);Write-Host ('       [OK] settings.json обновлён, модель '+$env:DREAMN_CLAUDE_MODEL);exit 0"
if errorlevel 1 echo   [!!] Claude Code: не удалось записать конфиг — см. проверку в конце.

echo.
echo   [4/8] Codex...
rem ~/.codex/config.toml: чужие провайдеры и настройки сохраняются, блок dreamn заменяется
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop';$io=[System.IO.File];$utf8=New-Object System.Text.UTF8Encoding($false);$q=[char]34;$dir=Join-Path $env:USERPROFILE '.codex';New-Item -ItemType Directory -Force -Path $dir|Out-Null;$p=Join-Path $dir 'config.toml';$keep=New-Object System.Collections.Generic.List[string];if(Test-Path $p){Copy-Item $p ($p+'.bak') -Force;$in=$false;foreach($ln in $io::ReadAllLines($p)){$t=$ln.Trim();if($t.StartsWith('[')){$in=($t -eq '[model_providers.dreamn]');if(-not $in){$keep.Add($ln)};continue};if($in){continue};if($t -match '^model_provider\s*=' -or $t -match '^model\s*='){continue};$keep.Add($ln)}};$out=New-Object System.Collections.Generic.List[string];$out.Add('model_provider = '+$q+'dreamn'+$q);$out.Add('model = '+$q+$env:DREAMN_MODEL+$q);$out.Add('');foreach($ln in $keep){$out.Add($ln)};if($keep.Count -and $keep[$keep.Count-1].Trim()){$out.Add('')};$out.Add('[model_providers.dreamn]');$out.Add('name = '+$q+'DreamN'+$q);$out.Add('base_url = '+$q+$env:DREAMN_GW+'/v1'+$q);$out.Add('env_key = '+$q+'DREAMN_API_KEY'+$q);$out.Add('wire_api = '+$q+'responses'+$q);$io::WriteAllText($p,(($out -join [Environment]::NewLine)+[Environment]::NewLine),$utf8);Write-Host ('       [OK] config.toml записан, модель '+$env:DREAMN_MODEL+', чужие настройки сохранены');exit 0"
if errorlevel 1 echo   [!!] Codex: не удалось записать конфиг — см. проверку в конце.
set "DREAMN_API_KEY=%APIKEY%"
if not defined DREAMN_SKIP_SETX setx DREAMN_API_KEY "%APIKEY%" >nul
if not defined DREAMN_SKIP_SETX echo        [OK] DREAMN_API_KEY установлен для новых терминалов

echo.
echo   [5/8] Cline / Roo Code / Kilo Code — VS Code, VSCodium, Cursor...
rem Во все найденные редакторы пишутся настройки трёх расширений; JSONC-комментарии переживают разбор
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop';$io=[System.IO.File];$utf8=New-Object System.Text.UTF8Encoding($false);$apps=@{'Code'='VS Code';'Code - Insiders'='VS Code Insiders';'VSCodium'='VSCodium';'Cursor'='Cursor'};$done=0;$written=New-Object System.Collections.Generic.List[string];foreach($a in $apps.Keys){$root=Join-Path $env:APPDATA $a;if(-not (Test-Path $root)){continue};$user=Join-Path $root 'User';New-Item -ItemType Directory -Force -Path $user|Out-Null;$p=Join-Path $user 'settings.json';$raw='';if(Test-Path $p){Copy-Item $p ($p+'.bak') -Force;$raw=$io::ReadAllText($p)};$d=@{};$okp=$true;if($raw.Trim()){try{$clean=(($raw -split '\r?\n')|Where-Object{-not $_.Trim().StartsWith('//')}) -join [char]10;$clean=$clean -replace ',(\s*[}\]])','$1';$j=$clean|ConvertFrom-Json;foreach($pr in $j.PSObject.Properties){$d[$pr.Name]=$pr.Value}}catch{$okp=$false}};if(-not $okp){Write-Host ('       [??] '+$apps[$a]+': settings.json не разобрать — не трогаю. Добавьте настройки расширения вручную.');continue};foreach($pre in @('cline','roo-cline','kilocode')){$d[$pre+'.apiProvider']='openai';$d[$pre+'.openAiBaseUrl']=$env:DREAMN_GW+'/v1';$d[$pre+'.openAiApiKey']=$env:APIKEY};$io::WriteAllText($p,($d|ConvertTo-Json -Depth 20),$utf8);$done++;$written.Add($p);Write-Host ('       [OK] '+$apps[$a]+': настройки расширений записаны, старые в .bak')};$io::WriteAllText((Join-Path $env:DREAMN_T 'editors.txt'),(($written -join [char]10)));if(-not $done){Write-Host '       VS Code/Cursor не найдены — шаг пропущен. Установите редактор и запустите скрипт заново.'}else{Write-Host ('       Модель в расширении выберите один раз в интерфейсе: '+$env:DREAMN_MODEL)};exit 0"
if errorlevel 1 echo   [!!] Редакторы: не удалось записать настройки — см. проверку в конце.

echo.
echo   [6/8] OpenCode...
rem ~/.config/opencode/opencode.json: провайдер dreamn со всеми чат-моделями ключа
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop';$io=[System.IO.File];$utf8=New-Object System.Text.UTF8Encoding($false);$dir=Join-Path $env:USERPROFILE '.config\opencode';New-Item -ItemType Directory -Force -Path $dir|Out-Null;$p=Join-Path $dir 'opencode.json';if(Test-Path $p){Copy-Item $p ($p+'.bak') -Force};$d=@{};if(Test-Path $p){try{$j=$io::ReadAllText($p)|ConvertFrom-Json;foreach($pr in $j.PSObject.Properties){$d[$pr.Name]=$pr.Value}}catch{Write-Host '       [?] Старый opencode.json не читается — собираю новый, старый в .bak'}};if(-not $d.ContainsKey('$schema')){$d['$schema']='https://opencode.ai/config.json'};$prov=@{};if($d['provider']){foreach($pr in $d['provider'].PSObject.Properties){$prov[$pr.Name]=$pr.Value}};$models=@{};foreach($n in ($env:DREAMN_CHATMODELS -split ',')){$n=$n.Trim();if(-not $n){continue};$lim=@{context=131072;output=16384};if($n -eq 'kimi-k3'){$lim=@{context=262144;output=16384}};$models[$n]=@{name=$n;reasoning=$true;temperature=$true;tool_call=$true;limit=$lim}};$prov['dreamn']=@{npm='@ai-sdk/openai-compatible';name='DreamN';options=@{baseURL=$env:DREAMN_GW+'/v1';apiKey=$env:APIKEY};models=$models};$d['provider']=$prov;$io::WriteAllText($p,($d|ConvertTo-Json -Depth 20),$utf8);Write-Host ('       [OK] opencode.json обновлён: провайдер DreamN, моделей '+$models.Count);exit 0"
if errorlevel 1 echo   [!!] OpenCode: не удалось записать конфиг — см. проверку в конце.

echo.
echo   [7/8] ZCode...
rem ~/.zcode/v2/config.json: провайдер DreamN — reasoning, vision-модальности, лимиты; setting.json: показ размышлений в стриме
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop';$io=[System.IO.File];$utf8=New-Object System.Text.UTF8Encoding($false);$zc=Join-Path $env:USERPROFILE '.zcode';if(-not (Test-Path $zc)){Write-Host '       ZCode не установлен — шаг пропущен. Установите и запустите автонастройку ещё раз.';exit 0};$v2=Join-Path $zc 'v2';New-Item -ItemType Directory -Force -Path $v2|Out-Null;$pc=Join-Path $v2 'config.json';if(Test-Path $pc){Copy-Item $pc ($pc+'.bak') -Force};$d=@{};if(Test-Path $pc){try{$j=$io::ReadAllText($pc)|ConvertFrom-Json;foreach($pr in $j.PSObject.Properties){$d[$pr.Name]=$pr.Value}}catch{Write-Host '       [?] config.json не читается — создаю заново, старый в .bak'}};$prov=@{};if($d['provider']){foreach($pr in $d['provider'].PSObject.Properties){$prov[$pr.Name]=$pr.Value}};$pkey='';foreach($k in $prov.Keys){$pv=$prov[$k];$b=$null;try{if($pv -is [System.Collections.IDictionary]){$b=$pv['options']['baseURL']}else{$b=$pv.options.baseURL}}catch{};if($b -and (''+$b).StartsWith($env:DREAMN_GW)){$pkey=$k;break}};if(-not $pkey){$pkey=[guid]::NewGuid().ToString()};$models=@{};foreach($n in ($env:DREAMN_CHATMODELS -split ',')){$n=$n.Trim();if(-not $n){continue};$m=@{};$m['limit']=@{context=1000000;output=128000};if($n -eq 'kimi-k3'){$m['limit']=@{context=1000000;output=131072}};$m['modalities']=@{input=@('text','image','video','pdf');output=@('text')};if($n -eq 'glm-5.3' -or $n -eq 'kimi-k3'){$m['reasoning']=@{enabled=$true;variants=@('low','high','max');defaultVariant='low'}};$m['zcode']=@{modalitiesConfigured=$true};$models[$n]=$m};$prov[$pkey]=@{name='DreamN';kind='openai-compatible';options=@{apiKey=$env:APIKEY;baseURL=$env:DREAMN_GW+'/v1';apiKeyRequired=$true};source='custom';models=$models};$d['provider']=$prov;$io::WriteAllText($pc,($d|ConvertTo-Json -Depth 30),$utf8);$pst=Join-Path $v2 'setting.json';$sd=@{};$sok=$true;if(Test-Path $pst){try{$js=$io::ReadAllText($pst)|ConvertFrom-Json;foreach($pr in $js.PSObject.Properties){$sd[$pr.Name]=$pr.Value}}catch{$sok=$false;Copy-Item $pst ($pst+'.bak') -Force}};if($sok){$sd['messageStreamShowReasoning']=$true;$sd['messageStreamShowReasoningMigrationInitialized']=$true;$io::WriteAllText($pst,($sd|ConvertTo-Json -Depth 30),$utf8)};Write-Host ('       [OK] ZCode: провайдер DreamN — '+$models.Count+' моделей, reasoning + vision, показ размышлений включён');exit 0"
if errorlevel 1 echo   [!!] ZCode: не удалось записать конфиг — см. проверку в конце.

echo.
echo   [8/8] Проверяю записанные конфиги...
rem Перечитывает каждый конфиг и сверяет ключевые поля — пользователь сразу видит, что реально записалось
powershell -NoProfile -ExecutionPolicy Bypass -Command "$io=[System.IO.File];$GW=$env:DREAMN_GW;$K=$env:APIKEY;$global:fails=0;function Chk($label,$cond){if($cond){Write-Host ('       [OK] '+$label)}else{Write-Host ('       [!!] '+$label+' — проверьте файл вручную');$global:fails++}};$p=Join-Path $env:USERPROFILE '.claude\settings.json';$o=$false;try{$j=$io::ReadAllText($p)|ConvertFrom-Json;$o=($j.env.ANTHROPIC_BASE_URL -eq $GW) -and ($j.env.ANTHROPIC_AUTH_TOKEN -eq $K) -and (''+$j.env.ANTHROPIC_MODEL)}catch{};Chk 'Claude Code — settings.json' $o;$p=Join-Path $env:USERPROFILE '.codex\config.toml';$t='';try{$t=$io::ReadAllText($p)}catch{};$q=[char]34;$o=$t.Contains('model_provider = '+$q+'dreamn'+$q) -and $t.Contains($GW+'/v1') -and $t.Contains('[model_providers.dreamn]');Chk 'Codex — config.toml' $o;$ue=[Environment]::GetEnvironmentVariable('DREAMN_API_KEY','User');if($env:DREAMN_SKIP_SETX){$ue=$K};Chk 'Codex — переменная DREAMN_API_KEY' ($ue -eq $K);$el=@();try{$el=@(($io::ReadAllText((Join-Path $env:DREAMN_T 'editors.txt'))) -split [char]10|Where-Object{$_})}catch{};foreach($p in $el){$o=$false;try{$j=$io::ReadAllText($p)|ConvertFrom-Json;$o=($j.'cline.openAiBaseUrl' -eq ($GW+'/v1')) -and ($j.'cline.openAiApiKey' -eq $K) -and ($j.'roo-cline.openAiApiKey' -eq $K) -and ($j.'kilocode.openAiApiKey' -eq $K)}catch{};Chk ('Cline/Roo/Kilo — '+$p) $o};$p=Join-Path $env:USERPROFILE '.config\opencode\opencode.json';$o=$false;try{$j=$io::ReadAllText($p)|ConvertFrom-Json;$mp=$j.provider.dreamn;$o=($mp.options.apiKey -eq $K) -and ($mp.options.baseURL -eq ($GW+'/v1')) -and (@($mp.models.PSObject.Properties).Count -ge 1)}catch{};Chk 'OpenCode — opencode.json' $o;$zc=Join-Path $env:USERPROFILE '.zcode';if(Test-Path $zc){$p=Join-Path $zc 'v2\config.json';$o=$false;try{$j=$io::ReadAllText($p)|ConvertFrom-Json;$found=$false;foreach($pr in $j.provider.PSObject.Properties){if(''+$pr.Value.options.baseURL -eq ($GW+'/v1')){$found=($pr.Value.options.apiKey -eq $K) -and (@($pr.Value.models.PSObject.Properties).Count -ge 1)}};$o=$found}catch{};Chk 'ZCode — провайдер DreamN' $o;$p=Join-Path $zc 'v2\setting.json';$o=$false;try{$j=$io::ReadAllText($p)|ConvertFrom-Json;$o=($j.messageStreamShowReasoning -eq $true)}catch{};Chk 'ZCode — показ размышлений в стриме' $o}else{Write-Host '       [--] ZCode не установлен — пропущен'};if($global:fails){Write-Host ('       Проблемных пунктов: '+$global:fails+'. Напишите в чат заказа FunPay — поможем.')}else{Write-Host '       Все записанные конфиги прошли проверку'};exit 0"

echo.
echo   ==============================================
echo     Готово! Перезапустите редакторы и терминал.
echo.
echo     Основная модель:   %MODEL%
echo     Для Claude Code:   %CLAUDEMODEL%
echo     Все модели ключа:
echo     %MODELS%
echo.
if exist "%DREAMN_T%\notes.txt" (
    type "%DREAMN_T%\notes.txt"
    echo.
)
echo     Cursor — вручную, 30 секунд:
echo        1. Settings - Models - OpenAI API Key: вставьте ключ
echo        2. Включите Override OpenAI Base URL
echo        3. Base URL: %GW%/v1
echo        4. Добавьте модель: %MODEL%
echo.
echo     Остаток по ключу — команда "!статус" в чате
echo     заказа FunPay. Вопросы — тоже туда.
echo   ==============================================
echo.
pause
endlocal
