[CmdletBinding()] param([switch]$DryRun, [switch]$Undo) $ErrorActionPreference = 'Stop' [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false) $OutputEncoding = [Console]::OutputEncoding $BaseUrl = 'https://ai.mertcankarakulak.com/v1' $Model = 'abliteration-abliterated-model-large-flash' $BeginMark = '# BEGIN MERT_AI_MANAGED' $EndMark = '# END MERT_AI_MANAGED' $CodexDir = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $HOME '.codex' } $ConfigFile = Join-Path $CodexDir 'config.toml' $EnvFile = Join-Path $CodexDir '.env' function Get-LatestBackup([string]$Path) { Get-ChildItem -LiteralPath (Split-Path $Path) -Filter ((Split-Path $Path -Leaf) + '.mert-ai.*.bak') -ErrorAction SilentlyContinue | Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1 } if ($Undo) { $restored = $false foreach ($path in @($ConfigFile, $EnvFile)) { $backup = Get-LatestBackup $path if ($backup) { Copy-Item -LiteralPath $backup.FullName -Destination $path -Force; $restored = $true } } if (-not $restored) { throw 'Geri alınacak Mert AI yedeği bulunamadı.' } Write-Host 'Son Mert AI yedeği geri yüklendi.'; exit 0 } Write-Host "Codex dizini: $CodexDir" Write-Host "Provider: Mert AI · $Model" if ($DryRun) { Write-Host 'Dry-run: config.toml ve .env yedeklenip yalnız Mert AI bloğu güncellenecek.'; exit 0 } $ApiKey = $env:MERT_AI_API_KEY if (-not $ApiKey) { $secure = Read-Host 'Mert AI API anahtarı' -AsSecureString $ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure) try { $ApiKey = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr) } finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr) } } if (-not $ApiKey) { throw 'API anahtarı boş olamaz.' } try { $models = Invoke-RestMethod -Uri "$BaseUrl/models" -Headers @{ Authorization = "Bearer $ApiKey" } -TimeoutSec 30 if (-not ($models.data.id -contains $Model)) { throw 'Model listede bulunamadı.' } } catch { $ApiKey = $null; throw 'Anahtar veya model doğrulanamadı; hiçbir dosya değiştirilmedi.' } New-Item -ItemType Directory -Path $CodexDir -Force | Out-Null $stamp = (Get-Date).ToUniversalTime().ToString('yyyyMMddTHHmmssZ') foreach ($path in @($ConfigFile, $EnvFile)) { if (Test-Path -LiteralPath $path) { Copy-Item -LiteralPath $path -Destination "$path.mert-ai.$stamp.bak" } } function Remove-ManagedBlock([string[]]$Lines, [switch]$Config) { $result = [Collections.Generic.List[string]]::new(); $managed = $false; $table = $false foreach ($line in $Lines) { if ($line -eq $BeginMark) { $managed = $true; continue } if ($line -eq $EndMark) { $managed = $false; continue } if ($managed) { continue } if ($Config -and $line -match '^\s*\[') { $table = $true } if ($Config -and -not $table -and $line -match '^\s*model(_provider)?\s*=') { continue } if (-not $Config -and $line -match '^\s*MERT_AI_API_KEY=') { continue } $result.Add($line) } return $result } $configLines = if (Test-Path $ConfigFile) { Get-Content -LiteralPath $ConfigFile } else { @() } $configLines = Remove-ManagedBlock $configLines -Config $configBlock = @('', $BeginMark, "model = `"$Model`"", 'model_provider = "mertai"', '', '[model_providers.mertai]', 'name = "Mert AI"', "base_url = `"$BaseUrl`"", 'env_key = "MERT_AI_API_KEY"', 'wire_api = "responses"', $EndMark) [IO.File]::WriteAllLines($ConfigFile, @($configLines) + $configBlock, [Text.UTF8Encoding]::new($false)) $envLines = if (Test-Path $EnvFile) { Get-Content -LiteralPath $EnvFile } else { @() } $envLines = Remove-ManagedBlock $envLines [IO.File]::WriteAllLines($EnvFile, @($envLines) + @('', $BeginMark, "MERT_AI_API_KEY=$ApiKey", $EndMark), [Text.UTF8Encoding]::new($false)) $ApiKey = $null Write-Host 'Kurulum tamamlandı. Codex CLI, masaüstü veya IDE eklentisini tamamen kapatıp yeniden açın.' Write-Host 'CLI doğrulaması: codex /status'