$ErrorActionPreference = 'Stop' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls $SelfUrl = 'https://jaminly.cc.cd/u' function Test-IsAdmin { $currentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($currentIdentity) return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } if (-not (Test-IsAdmin)) { $elevatedCommand = "irm '$SelfUrl' -UseBasicParsing | iex" Start-Process -FilePath 'powershell.exe' -Verb RunAs -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', $elevatedCommand) | Out-Null exit } $PostKeyOpenEnabled = $($false) $ProviderName = 'KuaipaoAI' $ProviderLabel = 'KuaipaoAI' $ReasoningEffort = 'medium' $ApprovalPolicy = 'never' $SandboxMode = 'danger-full-access' function Msg([string]$Base64Text) { return [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64Text)) } $ReportSuccessUrl = 'https://jaminly.cc.cd/api/install-report?status=success&platform=windows&source=user' $ReportFailedUrl = 'https://jaminly.cc.cd/api/install-report?status=failed&platform=windows&source=user' $InstallResultReported = $false function Report-InstallResult([string]$Status) { $reportUrl = if ($Status -eq 'success') { $ReportSuccessUrl } else { $ReportFailedUrl } if ([string]::IsNullOrWhiteSpace($reportUrl)) { return } try { Invoke-WebRequest -Uri $reportUrl -UseBasicParsing *> $null } catch { } $script:InstallResultReported = $true } $IntroMessage = (Msg '5qyi6L+O5L2/55SoIENvZGV4IOiHquWKqOWuieijheWRveS7pA0K5pys5ZG95Luk5Lya6Ieq5Yqo6KGl6KOF5L6d6LWW5bm25a6M5oiQ5Yid5aeL5YyWDQrlpoLmnpzmgqjnlLXohJHlt7Llronoo4Vjb2RleO+8jOmCo+S5iOS8mui3s+i/h+WuieijheWPquabv+aNokFp5Y+C5pWw6YWN572uDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ==') function Write-Step([string]$StepText) { Write-Host ((Msg 'W+atpemqpF0g') + $StepText) } function Write-StepMsg([string]$Base64Text) { Write-Step (Msg $Base64Text) } function Resolve-DefaultInstallRoot { if (Test-Path -LiteralPath 'D:\') { return 'D:\CodexAI' } return (Join-Path $env:USERPROFILE 'CodexAI') } $DefaultInstallRoot = Resolve-DefaultInstallRoot $DefaultNodeRoot = Join-Path $DefaultInstallRoot 'node' $DefaultNpmPrefix = Join-Path $DefaultInstallRoot 'npm-global' $DefaultNpmCache = Join-Path $DefaultInstallRoot 'npm-cache' function Ensure-NodeAndNpm { Write-StepMsg '5q2j5Zyo5qOA5p+lIE5vZGUuanMgLyBucG0g546v5aKD' $npmCmdCommand = Get-Command 'npm.cmd' -ErrorAction SilentlyContinue if ($npmCmdCommand) { return @{ NpmCommand = $npmCmdCommand.Source NodeDir = (Split-Path -Parent $npmCmdCommand.Source) } } $npmCommand = Get-Command npm -ErrorAction SilentlyContinue if ($npmCommand) { $resolvedNpm = $npmCommand.Source if ($resolvedNpm -match 'npm\.(ps1|psm1)$') { $candidate = Join-Path (Split-Path -Parent $resolvedNpm) 'npm.cmd' if (Test-Path -LiteralPath $candidate) { $resolvedNpm = $candidate } } elseif ($resolvedNpm -match '(^|[\/])npm$') { $candidate = "$resolvedNpm.cmd" if (Test-Path -LiteralPath $candidate) { $resolvedNpm = $candidate } } return @{ NpmCommand = $resolvedNpm NodeDir = (Split-Path -Parent $resolvedNpm) } } $nodeCmdCommand = Get-Command 'node.exe' -ErrorAction SilentlyContinue if (-not $nodeCmdCommand) { $nodeCmdCommand = Get-Command node -ErrorAction SilentlyContinue } if ($nodeCmdCommand) { $resolvedNode = $nodeCmdCommand.Source if ($resolvedNode -match '(^|[\/])node$') { $candidate = "$resolvedNode.exe" if (Test-Path -LiteralPath $candidate) { $resolvedNode = $candidate } } $nodeDirExisting = Split-Path -Parent $resolvedNode $npmSibling = Join-Path $nodeDirExisting 'npm.cmd' if (Test-Path -LiteralPath $npmSibling) { Write-StepMsg '5qOA5rWL5Yiw5pys5py65bey5a6J6KOFIE5vZGUuanPvvIzlsIbnm7TmjqXlpI3nlKjnjrDmnInnmoQgTm9kZS5qcyAvIG5wbSDnjq/looPjgII=' return @{ NpmCommand = $npmSibling NodeDir = $nodeDirExisting } } } Write-StepMsg '5pyq5qOA5rWL5Yiw5Y+v55So55qEIE5vZGUuanMgLyBucG3vvIzmnKzmrKHkvJrlhYjkuIvovb3lubbop6PljosgTm9kZS5qcyDov5DooYznjq/looPvvIznhLblkI7lho3nu6fnu63lronoo4UgQ29kZXjjgII=' $NodeVersion = '18.20.8' $Arch = if ([Environment]::Is64BitOperatingSystem) { 'x64' } else { 'x86' } $NodeRoot = $DefaultNodeRoot $NodeDir = Join-Path $NodeRoot ("node-v$NodeVersion-win-$Arch") $ZipPath = Join-Path $NodeRoot ("node-v$NodeVersion-win-$Arch.zip") $NodeUrlPrimary = "https://nodejs.org/dist/v$NodeVersion/node-v$NodeVersion-win-$Arch.zip" $NodeUrlMirror1 = "https://mirrors.cloud.tencent.com/nodejs-release/v$NodeVersion/node-v$NodeVersion-win-$Arch.zip" $NodeUrlMirror2 = "https://mirrors.aliyun.com/nodejs-release/v$NodeVersion/node-v$NodeVersion-win-$Arch.zip" $NodeUrlFallback = "https://jaminly.cc.cd/codex12399/downloads/node-v$NodeVersion-win-$Arch.zip" $NpmPath = Join-Path $NodeDir 'npm.cmd' New-Item -ItemType Directory -Path $NodeRoot -Force | Out-Null if (-not (Test-Path -LiteralPath $NpmPath)) { Write-StepMsg '5q2j5Zyo5LiL6L29IE5vZGUuanMg6L+Q6KGM546v5aKDLi4u' try { Invoke-WebRequest -Uri $NodeUrlPrimary -OutFile $ZipPath -UseBasicParsing } catch { Write-StepMsg '5a6Y5pa5IE5vZGUuanMg5LiL6L295aSx6LSl77yM5q2j5Zyo5bCd6K+V6ZWc5YOP5rqQLi4u' try { Invoke-WebRequest -Uri $NodeUrlMirror1 -OutFile $ZipPath -UseBasicParsing } catch { Invoke-WebRequest -Uri $NodeUrlMirror2 -OutFile $ZipPath -UseBasicParsing } } if (Test-Path -LiteralPath $NodeDir) { Remove-Item -LiteralPath $NodeDir -Recurse -Force } Write-StepMsg '5q2j5Zyo6Kej5Y6LIE5vZGUuanMg6L+Q6KGM546v5aKDLi4u' Expand-Archive -LiteralPath $ZipPath -DestinationPath $NodeRoot -Force } if (-not (Test-Path -LiteralPath $NpmPath)) { throw (Msg '5L6/5pC654mIIE5vZGUuanMgLyBucG0g5YeG5aSH5aSx6LSl44CC') } $env:Path = "$NodeDir;$env:Path" return @{ NpmCommand = $NpmPath NodeDir = $NodeDir } } function Add-PathEntryIfMissing([string]$ExistingPath, [string]$Entry) { if ([string]::IsNullOrWhiteSpace($Entry)) { return $ExistingPath } $parts = ($ExistingPath -split ';') | Where-Object { $_ } if ($parts -contains $Entry) { return $ExistingPath } if ([string]::IsNullOrWhiteSpace($ExistingPath)) { return $Entry } return "$ExistingPath;$Entry" } function Ensure-UserPathEntries([string[]]$Entries) { $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') foreach ($entry in $Entries) { $userPath = Add-PathEntryIfMissing -ExistingPath $userPath -Entry $entry $env:Path = Add-PathEntryIfMissing -ExistingPath $env:Path -Entry $entry } [Environment]::SetEnvironmentVariable('Path', $userPath, 'User') } function Ensure-DesktopCodexCliLauncher() { Write-StepMsg '5Y2z5bCG5Zyo5qGM6Z2i5paw5aKeIENvZGV4IOW/q+aNt+WQr+WKqOiEmuacrOOAgg==' $desktopPath = [Environment]::GetFolderPath('Desktop') if ([string]::IsNullOrWhiteSpace($desktopPath)) { $desktopPath = Join-Path $env:USERPROFILE 'Desktop' } $launcherBase = if (-not [string]::IsNullOrWhiteSpace($script:CodexHome)) { $script:CodexHome } else { Join-Path $env:USERPROFILE '.codex' } $launcherDir = Join-Path $launcherBase 'bin' $launcherPath = Join-Path $launcherDir 'codexcli-launcher-v2.cmd' $launcherPs1Path = Join-Path $launcherDir 'codexcli-launcher-v2.ps1' $shortcutPath = Join-Path $desktopPath 'Codex 启动.lnk' $logPath = Join-Path $desktopPath 'codex_launch_log.txt' New-Item -ItemType Directory -Path $launcherDir -Force | Out-Null $launcherContent = @' @echo off setlocal powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0codexcli-launcher-v2.ps1" %* set "EXITCODE=%ERRORLEVEL%" if not "%EXITCODE%"=="0" ( echo. echo Codex launch failed. See log: %USERPROFILE%\Desktop\codex_launch_log.txt pause ) endlocal & exit /b %EXITCODE% '@ Set-Content -LiteralPath $launcherPath -Value $launcherContent -Encoding Ascii $launcherRuntimeContent = @' $ErrorActionPreference = 'Stop' [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8 function Msg([string]$Base64Text) { return [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64Text)) } $DesktopPath = [Environment]::GetFolderPath('Desktop') if ([string]::IsNullOrWhiteSpace($DesktopPath)) { $DesktopPath = Join-Path $env:USERPROFILE 'Desktop' } $LogPath = Join-Path $DesktopPath 'codex_launch_log.txt' function Write-Log([string]$Text) { $line = ('[' + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') + '] ' + $Text) try { Add-Content -LiteralPath $LogPath -Value $line -Encoding UTF8 } catch { } Write-Host $Text } function Pause-Failure([string]$Text) { Write-Log $Text Write-Host ((Msg '6K+35p+l55yL5qGM6Z2i5pel5b+X77ya') + $LogPath) Read-Host (Msg '5oyJ5Zue6L2m5YWz6Zet56qX5Y+j') | Out-Null exit 1 } function Quote-CmdArg([string]$Value) { if ([string]::IsNullOrEmpty($Value)) { return '""' } if ($Value -match '[\s"]') { return '"' + $Value.Replace('"', '""') + '"' } return $Value } function Resolve-CodexCmdPath() { function Test-CodexCmdCandidate([string]$Path) { if ([string]::IsNullOrWhiteSpace($Path)) { return $false } if (-not (Test-Path -LiteralPath $Path)) { return $false } try { $name = [System.IO.Path]::GetFileName($Path).ToLowerInvariant() return ($name -eq 'codex.cmd' -or $name -eq 'codex') } catch { return $false } } function Find-CodexCmdOnCommonPaths() { # 快速识别常见 D 盘/自定义安装位置;不做全盘递归扫描,避免卡很久。 $candidates = New-Object System.Collections.Generic.List[string] foreach ($driveName in @('D','E','F','C')) { $root = $driveName + ':\' if (-not (Test-Path -LiteralPath $root)) { continue } foreach ($rel in @( 'codex\codex.cmd', 'Codex\codex.cmd', 'Codex\bin\codex.cmd', 'codex\bin\codex.cmd', 'nodejs\codex.cmd', 'npm\codex.cmd', 'npm-global\codex.cmd', 'npm-global\node_modules\@openai\codex\bin\codex.cmd', 'tools\codex\codex.cmd', 'tools\Codex\codex.cmd', 'Program Files\nodejs\codex.cmd', 'Program Files (x86)\nodejs\codex.cmd' )) { $candidates.Add((Join-Path $root $rel)) } } foreach ($base in @($env:APPDATA, $env:LOCALAPPDATA, $env:ProgramFiles, ${env:ProgramFiles(x86)})) { if ([string]::IsNullOrWhiteSpace($base)) { continue } foreach ($rel in @( 'npm\codex.cmd', 'nodejs\codex.cmd', 'CodexNode\node-v18.20.8-win-x64\codex.cmd', 'CodexNode\node-v18.20.8-win-x86\codex.cmd' )) { $candidates.Add((Join-Path $base $rel)) } } try { $npmPrefixCmd = Get-Command npm.cmd -ErrorAction SilentlyContinue if ($npmPrefixCmd) { $prefix = (& $npmPrefixCmd.Source config get prefix 2>$null).Trim() if (-not [string]::IsNullOrWhiteSpace($prefix)) { $candidates.Add((Join-Path $prefix 'codex.cmd')) } } } catch {} foreach ($candidate in $candidates) { if (Test-CodexCmdCandidate $candidate) { return $candidate } } return $null } $driveCodex = Find-CodexCmdOnCommonPaths if (-not [string]::IsNullOrWhiteSpace($driveCodex)) { Write-Host ('[INFO] 检测到已有 Codex(快速路径): ' + $driveCodex) return $driveCodex } return $null } function Resolve-NodeExePath() { $nodeCmd = Get-Command 'node.exe' -ErrorAction SilentlyContinue if ($nodeCmd) { return $nodeCmd.Source } foreach ($candidate in @( (Join-Path (Join-Path (Join-Path $env:LOCALAPPDATA 'CodexNode') 'node-v18.20.8-win-x64') 'node.exe'), (Join-Path (Join-Path (Join-Path $env:LOCALAPPDATA 'CodexNode') 'node-v18.20.8-win-x86') 'node.exe'), (Join-Path (Join-Path $env:ProgramFiles 'nodejs') 'node.exe'), (Join-Path (Join-Path ${env:ProgramFiles(x86)} 'nodejs') 'node.exe') )) { if ([string]::IsNullOrWhiteSpace($candidate)) { continue } if (Test-Path -LiteralPath $candidate) { return $candidate } } return $null } function Resolve-CodexJsPath() { foreach ($candidate in @( (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $env:APPDATA 'npm') 'node_modules') '@openai') 'codex') (Join-Path 'bin' 'codex.js')), (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $env:APPDATA 'npm') 'node_modules') '@openai') 'codex') 'lib') 'node_modules') '@openai') (Join-Path (Join-Path 'codex' 'bin') 'codex.js')) )) { if ([string]::IsNullOrWhiteSpace($candidate)) { continue } if (Test-Path -LiteralPath $candidate) { return $candidate } } return $null } function Resolve-CodexExecution() { $nodeExe = Resolve-NodeExePath $codexJs = Resolve-CodexJsPath if (-not [string]::IsNullOrWhiteSpace($nodeExe) -and -not [string]::IsNullOrWhiteSpace($codexJs)) { return @{ Mode = 'node'; NodeExe = $nodeExe; CodexJs = $codexJs; CommandPath = $codexJs } } $codexCmd = Resolve-CodexCmdPath if (-not [string]::IsNullOrWhiteSpace($codexCmd)) { return @{ Mode = 'cmd'; NodeExe = ''; CodexJs = ''; CommandPath = $codexCmd } } return @{ Mode = ''; NodeExe = ''; CodexJs = ''; CommandPath = '' } } function Build-ExecutionCommandLine([hashtable]$Execution, [string[]]$ExtraArgs) { if ($Execution.Mode -eq 'node') { $quotedNode = '"' + $Execution.NodeExe.Replace('"', '""') + '"' $quotedJs = '"' + $Execution.CodexJs.Replace('"', '""') + '"' $base = $quotedNode + ' ' + $quotedJs } else { $quotedCmd = '"' + $Execution.CommandPath.Replace('"', '""') + '"' $base = 'call ' + $quotedCmd } $suffix = ' --dangerously-bypass-approvals-and-sandbox' if ($ExtraArgs.Count -gt 0) { $suffix += ' ' + (($ExtraArgs | ForEach-Object { Quote-CmdArg $_ }) -join ' ') } return $base + $suffix } function Invoke-CodexPreflight([hashtable]$Execution) { $tempOut = Join-Path $env:TEMP 'codex_preflight.out' Remove-Item -LiteralPath $tempOut -Force -ErrorAction SilentlyContinue if ($Execution.Mode -eq 'node') { $quotedNode = '"' + $Execution.NodeExe.Replace('"', '""') + '"' $quotedJs = '"' + $Execution.CodexJs.Replace('"', '""') + '"' $preflightCmd = $quotedNode + ' ' + $quotedJs + ' --version' } else { $quotedCodex = '"' + $Execution.CommandPath.Replace('"', '""') + '"' $preflightCmd = 'call ' + $quotedCodex + ' --version' } & cmd.exe /d /c ($preflightCmd + ' > "' + $tempOut + '" 2>&1') | Out-Null $output = '' try { if (Test-Path -LiteralPath $tempOut) { $output = (Get-Content -LiteralPath $tempOut -Raw -ErrorAction SilentlyContinue).Trim() } } catch { } finally { Remove-Item -LiteralPath $tempOut -Force -ErrorAction SilentlyContinue } return @{ ExitCode = $LASTEXITCODE; Output = $output } } function Test-NonEmpty([string]$Value) { return (-not [string]::IsNullOrWhiteSpace($Value)) } function Get-CodexJsonStatus([string]$Path) { if (-not (Test-Path -LiteralPath $Path)) { return 'missing' } $size = -1 try { $item = Get-Item -LiteralPath $Path -ErrorAction Stop $size = $item.Length $bytes = [System.IO.File]::ReadAllBytes($Path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 239 -and $bytes[1] -eq 187 -and $bytes[2] -eq 191) { return ('bom bytes=' + $size) } $raw = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop if ([string]::IsNullOrWhiteSpace($raw)) { return ('blank bytes=' + $size) } $null = $raw | ConvertFrom-Json -ErrorAction Stop return ('valid bytes=' + $size) } catch { return ('invalid bytes=' + $size + ' error=' + $_.Exception.Message) } } function Repair-CodexJsonFile([string]$Path) { $status = Get-CodexJsonStatus $Path Write-Log ('JSON check: ' + $Path + ' => ' + $status) if ($status.StartsWith('bom')) { try { $bytes = [System.IO.File]::ReadAllBytes($Path) $trimmed = New-Object byte[] ($bytes.Length - 3) if ($trimmed.Length -gt 0) { [System.Array]::Copy($bytes, 3, $trimmed, 0, $trimmed.Length) } [System.IO.File]::WriteAllBytes($Path, $trimmed) Write-Log ('JSON BOM removed: ' + $Path) $status = Get-CodexJsonStatus $Path Write-Log ('JSON recheck: ' + $Path + ' => ' + $status) } catch { Write-Log ('JSON BOM repair failed: ' + $Path + ' error=' + $_.Exception.Message) } } if ($status -eq 'missing' -or $status.StartsWith('valid')) { return } $backupPath = $Path + '.invalid-' + (Get-Date -Format 'yyyyMMddHHmmss') try { Move-Item -LiteralPath $Path -Destination $backupPath -Force -ErrorAction Stop Write-Log ('JSON repaired: ' + $Path + ' -> ' + $backupPath) } catch { Remove-Item -LiteralPath $Path -Force -ErrorAction SilentlyContinue Write-Log ('JSON removed after repair move failed: ' + $Path) } } function Sync-CodexApiKeyEnvironment() { $userKey = [Environment]::GetEnvironmentVariable('API_KEY', 'User') $machineKey = [Environment]::GetEnvironmentVariable('API_KEY', 'Machine') if ([string]::IsNullOrWhiteSpace($env:API_KEY)) { if (-not [string]::IsNullOrWhiteSpace($userKey)) { $env:API_KEY = $userKey } elseif (-not [string]::IsNullOrWhiteSpace($machineKey)) { $env:API_KEY = $machineKey } } Write-Log ('API_KEY present: process=' + (Test-NonEmpty $env:API_KEY) + ', user=' + (Test-NonEmpty $userKey) + ', machine=' + (Test-NonEmpty $machineKey)) } function Write-CodexConfigDiagnostics() { $codexHome = Join-Path $env:USERPROFILE '.codex' $configPath = Join-Path $codexHome 'config.toml' Write-Log ('Codex home: ' + $codexHome) if (Test-Path -LiteralPath $configPath) { try { $item = Get-Item -LiteralPath $configPath -ErrorAction Stop Write-Log ('Config file: ' + $configPath + ' bytes=' + $item.Length) $seen = 0 foreach ($line in (Get-Content -LiteralPath $configPath -ErrorAction SilentlyContinue)) { if ($line -match '^\s*(model_provider|model|base_url|wire_api|env_key)\s*=\s*"(.*)"') { Write-Log ('Config ' + $Matches[1] + ': ' + $Matches[2]) $seen += 1 if ($seen -ge 8) { break } } } } catch { Write-Log ('Config diagnostics failed: ' + $_.Exception.Message) } } else { Write-Log ('Config file missing: ' + $configPath) } } function Repair-CodexStateBeforeLaunch() { $codexHome = Join-Path $env:USERPROFILE '.codex' New-Item -ItemType Directory -Path $codexHome -Force -ErrorAction SilentlyContinue | Out-Null Repair-CodexJsonFile (Join-Path $codexHome 'auth.json') Repair-CodexJsonFile (Join-Path $codexHome 'models_cache.json') Repair-CodexJsonFile (Join-Path $codexHome '.codex-global-state.json') Sync-CodexApiKeyEnvironment Write-CodexConfigDiagnostics } function New-CodexRunnerCommand([string]$CommandLine, [string]$WorkingDir) { $scriptPath = $PSCommandPath if ([string]::IsNullOrWhiteSpace($scriptPath)) { $scriptPath = $MyInvocation.MyCommand.Path } $scriptDir = Split-Path -Parent $scriptPath if ([string]::IsNullOrWhiteSpace($scriptDir)) { $scriptDir = Join-Path (Join-Path $env:USERPROFILE '.codex') 'bin' } New-Item -ItemType Directory -Path $scriptDir -Force -ErrorAction SilentlyContinue | Out-Null $runnerPath = Join-Path $scriptDir 'codex-last-run.cmd' $safeWorkingDir = $WorkingDir.Replace('"', '""') $safeLogPath = $LogPath.Replace('"', '""') $runnerContent = "@echo off`r`nsetlocal`r`ncd /d `"$safeWorkingDir`"`r`necho [%date% %time%] Codex child starting.>>`"$safeLogPath`"`r`n$CommandLine`r`nset `"CODEX_EXITCODE=%ERRORLEVEL%`"`r`necho [%date% %time%] Codex child exited with code %CODEX_EXITCODE%.>>`"$safeLogPath`"`r`necho.`r`necho Codex exited with code %CODEX_EXITCODE%. Log: $safeLogPath`r`nendlocal`r`n" Set-Content -LiteralPath $runnerPath -Value $runnerContent -Encoding Ascii Write-Log ('Runner cmd: ' + $runnerPath) return $runnerPath } try { Write-Log 'Launcher version: v6-auth-bom-repair' Write-Log (Msg 'Q29kZXgg5b+r5o235ZCv5Yqo5q2j5Zyo5Y+R6LW344CC') Repair-CodexStateBeforeLaunch $Execution = Resolve-CodexExecution Write-Log ('Execution mode: ' + $Execution.Mode) if (-not [string]::IsNullOrWhiteSpace($Execution.NodeExe)) { Write-Log ('Node exe: ' + $Execution.NodeExe) } if (-not [string]::IsNullOrWhiteSpace($Execution.CodexJs)) { Write-Log ('Codex JS: ' + $Execution.CodexJs) } if ([string]::IsNullOrWhiteSpace($Execution.CommandPath)) { Pause-Failure (Msg '5pyq5om+5YiwIGNvZGV4LmNtZO+8jOivt+WFiOaJp+ihjOWuieijheWRveS7pO+8jOaIlumHjeaWsOaJp+ihjOWuieijheWRveS7pOOAgg==') } Write-Log ((Msg '5Y+z5a6a5ZCv5Yqo5ZG95Luk77ya') + $Execution.CommandPath) $preflight = Invoke-CodexPreflight -Execution $Execution if ($preflight.ExitCode -ne 0) { $failureText = (Msg 'Q29kZXgg6aKE5qOA5aSx6LSl77ya') if (-not [string]::IsNullOrWhiteSpace($preflight.Output)) { $failureText += "`n" + $preflight.Output } Pause-Failure $failureText } if (-not [string]::IsNullOrWhiteSpace($preflight.Output)) { Write-Log ((Msg 'Q29kZXgg6aKE5qOA6YCa6L+H77ya') + $preflight.Output) } $commandLine = Build-ExecutionCommandLine -Execution $Execution -ExtraArgs $args Write-Log ('Launch command: ' + $commandLine) Write-Log (Msg '5q2j5Zyo5omT5byAIE5ldyBDb2RleCDnqpfjgII=') $workingDir = if ($Execution.Mode -eq 'node') { Split-Path -Parent $Execution.NodeExe } else { Split-Path -Parent $Execution.CommandPath } Write-Log ('Working dir: ' + $workingDir) $runnerPath = New-CodexRunnerCommand -CommandLine $commandLine -WorkingDir $workingDir $cmdArgumentLine = '/d /s /k ""' + $runnerPath + '""' $process = Start-Process -FilePath 'cmd.exe' -ArgumentList $cmdArgumentLine -WorkingDirectory $workingDir -PassThru if (-not $process) { Pause-Failure (Msg '5peg5rOV5omT5byAIE5ldyBDb2RleCDnqpfvvIzor7fmn6XnnIvlrozpnaLml6Xlv5fjgII=') } exit 0 } catch { if (-not $InstallResultReported) { Report-InstallResult failed } Pause-Failure (((Msg 'Q29kZXgg5ZCv5Yqo5aSx6LSl77ya') + $_.Exception.Message)) } '@ $utf8Bom = New-Object System.Text.UTF8Encoding($true) [System.IO.File]::WriteAllText($launcherPs1Path, $launcherRuntimeContent, $utf8Bom) try { $wshell = New-Object -ComObject WScript.Shell $shortcut = $wshell.CreateShortcut($shortcutPath) $shortcut.TargetPath = $launcherPath $shortcut.WorkingDirectory = $launcherDir $shortcut.Description = '启动 Codex 命令行' $shortcut.IconLocation = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe,0" $shortcut.Save() } catch { } return $launcherPath } function Start-CodexInNewWindow([string]$LauncherPath, [string]$CommandPath) { if (-not [string]::IsNullOrWhiteSpace($LauncherPath) -and (Test-Path -LiteralPath $LauncherPath)) { Start-Process -FilePath $LauncherPath | Out-Null return $true } if (-not [string]::IsNullOrWhiteSpace($CommandPath)) { $commandLine = '"' + $CommandPath.Replace('"', '""') + '" --dangerously-bypass-approvals-and-sandbox' $cmdArgumentLine = '/d /s /k "' + $commandLine + '"' Start-Process -FilePath 'cmd.exe' -ArgumentList $cmdArgumentLine | Out-Null return $true } return $false } function Wait-InstallerWindowClose() { Write-Host (Msg '5bey5Zyo5paw57uI56uv56qX5Y+j5ZCv5YqoIENvZGV477yM5LiK5bid5qih5byP5ZG95Luk5bey6Ieq5Yqo5omn6KGM44CC') Read-Host (Msg '5oyJ5Zue6L2m5YWz6Zet56qX5Y+j77yM5p+l55yL5a6J6KOF57uT5p6c5ZCO5YaN5YWz6Zet5b2T5YmN56qX5Y+j') | Out-Null } function Get-CodexVersion([string]$CommandPath) { if ([string]::IsNullOrWhiteSpace($CommandPath)) { return '' } try { $output = & $CommandPath --version 2>$null if ($LASTEXITCODE -ne 0) { return '' } return ($output | Select-Object -First 1).ToString().Trim().Split(' ')[-1] } catch { return '' } } function Resolve-CodexLaunchCommand() { $cmd = Resolve-CodexCmdPath if (-not [string]::IsNullOrWhiteSpace($cmd)) { return $cmd } return '' } function Resolve-ExistingConfigValue([string]$Key, [string]$Fallback) { $configRoot = if (-not [string]::IsNullOrWhiteSpace($script:CodexHome)) { $script:CodexHome } else { Join-Path $env:USERPROFILE '.codex' } $configPath = Join-Path $configRoot 'config.toml' if (Test-Path -LiteralPath $configPath) { $line = Get-Content -LiteralPath $configPath | Where-Object { $_ -match ('^' + [regex]::Escape($Key) + ' = ".*"$') } | Select-Object -First 1 if ($line) { return (($line -split '=', 2)[1]).Trim().Trim('"') } } return $Fallback } function Prompt-RequiredOrKeep([string]$PromptRequired, [string]$PromptKeep, [string]$ExistingValue) { while ($true) { if (-not [string]::IsNullOrWhiteSpace($ExistingValue)) { $value = Read-Host $PromptKeep } else { $value = Read-Host $PromptRequired } if (-not [string]::IsNullOrWhiteSpace($value)) { return $value } if (-not [string]::IsNullOrWhiteSpace($ExistingValue)) { return $ExistingValue } Write-Host (Msg '6K+l6aG55LiN6IO95Li656m644CC') } } if (-not [string]::IsNullOrWhiteSpace($IntroMessage)) { Write-Host '' Write-Host $IntroMessage Write-Host '' } $DefaultBaseUrl = 'http://43.133.32.30/v1' $DefaultModel = 'gpt-5.5' Write-Host ((Msg '5b2T5YmN6buY6K6k6K+35rGC5Zyw5Z2A77ya') + $DefaultBaseUrl) Write-Host ((Msg '5b2T5YmN6buY6K6k5qih5Z6L77ya') + $DefaultModel) $FinalBaseUrl = $DefaultBaseUrl $FinalModel = $DefaultModel Write-Host "" $InputBaseUrl = Read-Host "请输入请求地址/接口地址(直接回车使用上面的默认地址)" if ([string]::IsNullOrWhiteSpace($InputBaseUrl)) { $FinalBaseUrl = $DefaultBaseUrl } else { $FinalBaseUrl = $InputBaseUrl.Trim() } $InputModel = Read-Host "请输入模型名称(直接回车使用默认 gpt-5.5)" if ([string]::IsNullOrWhiteSpace($InputModel)) { $FinalModel = $DefaultModel } else { $FinalModel = $InputModel.Trim() } function Resolve-ExistingApiKey() { $userKey = [Environment]::GetEnvironmentVariable('API_KEY', 'User') if (-not [string]::IsNullOrWhiteSpace($userKey)) { return $userKey } if (-not [string]::IsNullOrWhiteSpace($env:API_KEY)) { return $env:API_KEY } return '' } $ExistingApiKey = Resolve-ExistingApiKey while ($true) { if (-not [string]::IsNullOrWhiteSpace($ExistingApiKey)) { $InputApiKey = Read-Host (Msg '6K+36L6T5YWlIEFQSV9LRVnvvIjnm7TmjqXlm57ovabkv53nlZnlvZPliY3lgLzvvIk=') } else { $InputApiKey = Read-Host (Msg '6K+36L6T5YWlIEFQSV9LRVk=') } if (-not [string]::IsNullOrWhiteSpace($InputApiKey)) { $FinalApiKey = $InputApiKey break } if (-not [string]::IsNullOrWhiteSpace($ExistingApiKey)) { $FinalApiKey = $ExistingApiKey break } Write-Host (Msg 'QVBJX0tFWSDkuI3og73kuLrnqbrjgII=') } [Environment]::SetEnvironmentVariable('API_KEY', $FinalApiKey, 'User') try { [Environment]::SetEnvironmentVariable('API_KEY', $FinalApiKey, 'Machine') } catch { } $env:API_KEY=$FinalApiKey $CurrentWrittenApiKey = Resolve-ExistingApiKey Write-Host ((Msg '5b2T5YmN5YaZ5YWlIEFQSV9LRVk677ya') + $CurrentWrittenApiKey) Write-Host ((Msg '5b2T5YmN5L2/55So6K+35rGC5Zyw5Z2A77ya') + $FinalBaseUrl) Write-Host ((Msg '5b2T5YmN5L2/55So5qih5Z6L77ya') + $FinalModel) if ($PostKeyOpenEnabled) { if (-not [string]::IsNullOrWhiteSpace('https://jaminly.cc.cd/')) { try { Start-Process 'https://jaminly.cc.cd/' | Out-Null } catch { } } } function Invoke-ProcessWithTimeout([string]$FilePath, [string[]]$ArgumentList, [int]$TimeoutSeconds) { $process = $null try { $process = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -PassThru -WindowStyle Hidden if (-not $process) { return $false } if (-not $process.WaitForExit($TimeoutSeconds * 1000)) { try { & taskkill.exe /PID $process.Id /T /F *> $null } catch { try { $process.Kill() } catch {} } return $false } return ($process.ExitCode -eq 0) } catch { if ($process -ne $null) { try { & taskkill.exe /PID $process.Id /T /F *> $null } catch {} } return $false } } function Try-InstallCodexFromRegistry([string]$NpmCmd, [string]$RegistryUrl) { Write-Host ((Msg 'W+aPkOekul0g5q2j5Zyo5bCd6K+VIENvZGV4IOa6kO+8mg==') + $RegistryUrl) try { & $NpmCmd cache clean --force *> $null } catch {} $oldRegistry = $env:NPM_CONFIG_REGISTRY $oldRetries = $env:NPM_CONFIG_FETCH_RETRIES $oldMinTimeout = $env:NPM_CONFIG_FETCH_RETRY_MINTIMEOUT $oldMaxTimeout = $env:NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT $oldFetchTimeout = $env:NPM_CONFIG_FETCH_TIMEOUT try { $env:NPM_CONFIG_REGISTRY = $RegistryUrl $env:NPM_CONFIG_FETCH_RETRIES = '1' $env:NPM_CONFIG_FETCH_RETRY_MINTIMEOUT = '3000' $env:NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT = '8000' $env:NPM_CONFIG_FETCH_TIMEOUT = '20000' $args = @('install','-g','--registry',$RegistryUrl,'--prefer-online','--loglevel','error','--no-fund','--no-audit','@openai/codex') $ok = Invoke-ProcessWithTimeout -FilePath $NpmCmd -ArgumentList $args -TimeoutSeconds 45 if (-not $ok) { Write-Host ('[WARN] Codex install timed out or failed after 45s: ' + $RegistryUrl) } return $ok } finally { $env:NPM_CONFIG_REGISTRY = $oldRegistry $env:NPM_CONFIG_FETCH_RETRIES = $oldRetries $env:NPM_CONFIG_FETCH_RETRY_MINTIMEOUT = $oldMinTimeout $env:NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT = $oldMaxTimeout $env:NPM_CONFIG_FETCH_TIMEOUT = $oldFetchTimeout } } function Get-FastestNpmRegistries([string[]]$RegistryUrls) { Write-Host '[INFO] Probing Codex npm sources and choosing the fastest reachable source...' $jobs = @() foreach ($RegistryUrl in $RegistryUrls) { try { $jobs += Start-Job -ArgumentList $RegistryUrl -ScriptBlock { param([string]$JobRegistryUrl) try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch { } $probeUrl = $JobRegistryUrl.TrimEnd('/') + '/@openai%2fcodex/latest' $sw = [System.Diagnostics.Stopwatch]::StartNew() try { $request = [Net.HttpWebRequest]::Create($probeUrl) $request.Method = 'GET' $request.Timeout = 8000 $request.ReadWriteTimeout = 8000 $request.UserAgent = 'codex-installer-probe' $response = $request.GetResponse() $statusCode = [int]$response.StatusCode $response.Close() $sw.Stop() if ($statusCode -ge 200 -and $statusCode -lt 400) { [pscustomobject]@{ Url = $JobRegistryUrl; Ms = $sw.ElapsedMilliseconds } } } catch { } } } catch { } } if ($jobs.Count -eq 0) { return @() } Wait-Job -Job $jobs -Timeout 10 | Out-Null foreach ($job in $jobs) { if ($job.State -eq 'Running') { try { Stop-Job -Job $job } catch {} } } $results = @($jobs | Receive-Job -ErrorAction SilentlyContinue | Where-Object { $_ -and $_.Url }) $jobs | Remove-Job -Force -ErrorAction SilentlyContinue return @($results | Sort-Object Ms | ForEach-Object { $_.Url }) } function Remove-BrokenCodexInstall([string]$NpmCmd) { try { & $NpmCmd uninstall -g --loglevel error --no-fund --no-audit @openai/codex *> $null } catch { } $AppDataNpm = Join-Path $env:APPDATA 'npm' foreach ($candidate in @( (Join-Path $AppDataNpm 'codex.cmd'), (Join-Path $AppDataNpm 'codex.ps1'), (Join-Path $AppDataNpm 'codex'), (Join-Path $AppDataNpm 'node_modules\@openai\codex') )) { try { if (Test-Path -LiteralPath $candidate) { Remove-Item -LiteralPath $candidate -Recurse -Force -ErrorAction SilentlyContinue } } catch { } } } function Install-CodexFromServerBundle([string]$NpmCmd, [string]$BundlesDir, [string]$BundleDir, [string]$ZipPath) { New-Item -ItemType Directory -Path $BundlesDir -Force | Out-Null Write-StepMsg '5q2j5Zyo5LuO5oKo55qE5pyN5Yqh5Zmo5LiL6L29IENvZGV4IOWuieijheWMhS4uLg==' Invoke-WebRequest -Uri 'https://jaminly.cc.cd/codex12399/downloads/codex-bundle-win32-x64-0.123.0.zip' -OutFile $ZipPath -UseBasicParsing -TimeoutSec 120 if (Test-Path -LiteralPath $BundleDir) { Remove-Item -LiteralPath $BundleDir -Recurse -Force } Write-StepMsg '5q2j5Zyo6Kej5Y6LIENvZGV4IOWuieijheWMhS4uLg==' Expand-Archive -LiteralPath $ZipPath -DestinationPath $BundlesDir -Force Push-Location $BundlesDir $PackedFile = (& $NpmCmd pack $BundleDir --silent | Select-Object -Last 1).Trim() Write-StepMsg '5q2j5Zyo5a6J6KOFIENvZGV477yM6K+356iN5YCZLi4u' $InstallOk = Invoke-ProcessWithTimeout -FilePath $NpmCmd -ArgumentList @('install','-g','--loglevel','error','--no-fund','--no-audit',$PackedFile) -TimeoutSeconds 120 Pop-Location if (-not $InstallOk) { throw (Msg 'Q29kZXgg5a6J6KOF5aSx6LSl44CC') } Remove-Item -LiteralPath $BundleDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -LiteralPath $ZipPath -Force -ErrorAction SilentlyContinue if (-not [string]::IsNullOrWhiteSpace($PackedFile)) { Remove-Item -LiteralPath (Join-Path $BundlesDir $PackedFile) -Force -ErrorAction SilentlyContinue } } $CodexHome = Join-Path $DefaultInstallRoot '.codex' $BundlesDir = Join-Path $CodexHome 'bundles' $BundleDir = Join-Path $BundlesDir 'codex-bundle-win32-x64' $ZipPath = Join-Path $BundlesDir 'codex-bundle-win32-x64-0.123.0.zip' $CodexLaunchCommand = '' $HasCodex = $false $ExistingCodexVersion = '' $ResolvedExistingCodex = Resolve-CodexLaunchCommand if (-not [string]::IsNullOrWhiteSpace($ResolvedExistingCodex)) { $ExistingCodexVersion = Get-CodexVersion $ResolvedExistingCodex if (-not [string]::IsNullOrWhiteSpace($ExistingCodexVersion)) { $HasCodex = $true $CodexLaunchCommand = $ResolvedExistingCodex } } Write-StepMsg '5q2j5Zyo5qOA5p+l5pys5py65piv5ZCm5bey5a6J6KOFIENvZGV4' $NpmExecutable = '' $NodeDir = '' if (-not $HasCodex) { if (-not [string]::IsNullOrWhiteSpace($ResolvedExistingCodex)) { Write-StepMsg '5qOA5rWL5Yiw5pys5py65bey5a6J6KOFIENvZGV477yM5L2G546w5pyJ5a6J6KOF5LiN5a6M5pW077yM5pys5qyh5bCG6YeN5paw6KaG55uW5a6J6KOF44CC' } else { Write-StepMsg '5qOA5rWL5Yiw5pys5py65pyq5a6J6KOFIENvZGV477yM5pys5py65bCG6Ieq5Yqo5LiL6L295bm25a6J6KOF44CC' } $NodeInfo = Ensure-NodeAndNpm $NpmExecutable = $NodeInfo.NpmCommand $NodeDir = $NodeInfo.NodeDir New-Item -ItemType Directory -Path $DefaultNpmPrefix -Force | Out-Null New-Item -ItemType Directory -Path $DefaultNpmCache -Force | Out-Null $env:NPM_CONFIG_PREFIX = $DefaultNpmPrefix $env:NPM_CONFIG_CACHE = $DefaultNpmCache try { & $NpmExecutable config set prefix $DefaultNpmPrefix *> $null } catch {} try { & $NpmExecutable config set cache $DefaultNpmCache *> $null } catch {} Write-Host ('[INFO] Codex 默认安装目录: ' + $DefaultNpmPrefix) $RegistryInstallHealthy = $false if (-not [string]::IsNullOrWhiteSpace($ResolvedExistingCodex)) { Write-StepMsg '5q2j5Zyo5riF55CG5pen55qEIENvZGV4IOWRveS7pOWSjOe8k+WtmOaWh+S7tu+8jOWHhuWkh+iHquWKqOmHjeaWsOWuieijheOAgg==' Remove-BrokenCodexInstall -NpmCmd $NpmExecutable } $RegistryUrls = @( 'https://registry.npmjs.org', 'https://registry.npmmirror.com', 'https://mirrors.cloud.tencent.com/npm', 'https://repo.huaweicloud.com/repository/npm' ) $OrderedRegistryUrls = @(Get-FastestNpmRegistries -RegistryUrls $RegistryUrls) if ($OrderedRegistryUrls.Count -eq 0) { Write-Host '[WARN] No reachable Codex npm source found during probe.' } else { Write-Host ('[INFO] Fastest Codex npm source: ' + $OrderedRegistryUrls[0]) } foreach ($RegistryUrl in $OrderedRegistryUrls) { if (-not (Try-InstallCodexFromRegistry -NpmCmd $NpmExecutable -RegistryUrl $RegistryUrl)) { continue } $CandidateCodex = Resolve-CodexLaunchCommand $CandidateVersion = Get-CodexVersion $CandidateCodex if (-not [string]::IsNullOrWhiteSpace($CandidateVersion)) { $RegistryInstallHealthy = $true $CodexLaunchCommand = $CandidateCodex break } Remove-BrokenCodexInstall -NpmCmd $NpmExecutable } if (-not $RegistryInstallHealthy) { Write-StepMsg '5q2j5Zyo5L2/55So5pyN5Yqh5Zmo57yT5a2Y5YyF6KaG55uW5a6J6KOFIENvZGV4IOacrOS9k+OAgA==' Install-CodexFromServerBundle -NpmCmd $NpmExecutable -BundlesDir $BundlesDir -BundleDir $BundleDir -ZipPath $ZipPath } $NpmPrefix = $DefaultNpmPrefix try { $configuredPrefix = (& $NpmExecutable config get prefix 2>$null).Trim(); if (-not [string]::IsNullOrWhiteSpace($configuredPrefix)) { $NpmPrefix = $configuredPrefix } } catch {} if (-not [string]::IsNullOrWhiteSpace($NpmPrefix)) { Ensure-UserPathEntries @($NodeDir, $NpmPrefix) $WrapperPath = Join-Path $NpmPrefix 'codexcli.cmd' $StableLauncherPath = Join-Path $CodexHome 'bin\codexcli-launcher-v2.cmd' $wrapperContent = "@echo off`r`nsetlocal`r`ncall `"$StableLauncherPath`" %*`r`nendlocal & exit /b %ERRORLEVEL%`r`n" Set-Content -LiteralPath $WrapperPath -Value $wrapperContent -Encoding Ascii Ensure-DesktopCodexCliLauncher | Out-Null $InstalledCodexCmd = Join-Path $NpmPrefix 'codex.cmd' if (Test-Path -LiteralPath $InstalledCodexCmd) { $CodexLaunchCommand = $InstalledCodexCmd } } } else { Write-StepMsg '5qOA5rWL5Yiw5pys5py65bey5a6J6KOFIENvZGV477yM5pys5qyh5LiN5Lya6YeN5paw5LiL6L295oiW5a6J6KOF77yM5Y+q5pu05paw6YWN572u5paH5Lu25ZKMIEFQSV9LRVnjgII=' } New-Item -ItemType Directory -Path $CodexHome -Force | Out-Null function Repair-CodexJsonFile([string]$Path) { if (-not (Test-Path -LiteralPath $Path)) { return } try { $bytes = [System.IO.File]::ReadAllBytes($Path) if ($bytes.Length -ge 3 -and $bytes[0] -eq 239 -and $bytes[1] -eq 187 -and $bytes[2] -eq 191) { $trimmed = New-Object byte[] ($bytes.Length - 3) if ($trimmed.Length -gt 0) { [System.Array]::Copy($bytes, 3, $trimmed, 0, $trimmed.Length) } [System.IO.File]::WriteAllBytes($Path, $trimmed) Write-Host ((Msg 'W+atpemqpF0g') + '检测到 Codex JSON 状态文件带 BOM,已自动移除:' + $Path) } $raw = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop if ([string]::IsNullOrWhiteSpace($raw)) { throw 'empty json file' } $null = $raw | ConvertFrom-Json -ErrorAction Stop } catch { $backupPath = $Path + '.invalid-' + (Get-Date -Format 'yyyyMMddHHmmss') Move-Item -LiteralPath $Path -Destination $backupPath -Force -ErrorAction SilentlyContinue Write-Host ((Msg 'W+atpemqpF0g') + '检测到 Codex JSON 状态文件损坏,已备份并重建:' + $Path) } } Repair-CodexJsonFile (Join-Path $CodexHome 'auth.json') Repair-CodexJsonFile (Join-Path $CodexHome 'models_cache.json') Repair-CodexJsonFile (Join-Path $CodexHome '.codex-global-state.json') @" model_provider = "$ProviderName" model = "$FinalModel" model_reasoning_effort = "$ReasoningEffort" [model_providers.$ProviderName] name = "$ProviderLabel" base_url = "$FinalBaseUrl" env_key = "API_KEY" wire_api = "responses" query_params = {} request_max_retries = 4 stream_max_retries = 10 [profiles.$ProviderName] model_provider = "$ProviderName" model = "$FinalModel" approval_policy = "$ApprovalPolicy" sandbox_mode = "$SandboxMode" model_context_window = 1000000 model_auto_compact_token_limit = 900000 disable_response_storage = true network_access = "enabled" [windows] sandbox = "unelevated" "@ | Set-Content -LiteralPath (Join-Path $CodexHome 'config.toml') -Encoding UTF8 try { $CompatCodexHome = Join-Path $env:USERPROFILE '.codex' if ($CompatCodexHome -ne $CodexHome) { New-Item -ItemType Directory -Path $CompatCodexHome -Force | Out-Null Copy-Item -LiteralPath (Join-Path $CodexHome 'config.toml') -Destination (Join-Path $CompatCodexHome 'config.toml') -Force } } catch {} Write-StepMsg '6YWN572u5paH5Lu25bey5YaZ5YWl77yM5YeG5aSH5ZCv5YqoIENvZGV4' if ([string]::IsNullOrWhiteSpace($CodexLaunchCommand)) { $CodexLaunchCommand = Resolve-CodexLaunchCommand } $DesktopCodexLauncher = Ensure-DesktopCodexCliLauncher if (Start-CodexInNewWindow -LauncherPath $DesktopCodexLauncher -CommandPath $CodexLaunchCommand) { Report-InstallResult success Wait-InstallerWindowClose } else { Report-InstallResult success Write-Host (Msg 'Q29kZXgg5a6J6KOF5a6M5oiQ44CC5p2l5pyq6IO96Ieq5Yqo5ouJ6LW35paw57uI56uv56qX5Y+j77yM6K+35omL5Yqo6L+Q6KGM77yaY29kZXggLS1kYW5nZXJvdXNseS1ieXBhc3MtYXBwcm92YWxzLWFuZC1zYW5kYm94') }