# ============================================================ # Router One · Codex CLI 一键接入 / one-click setup (Windows) # Docs: https://router.one/docs/guides/cli-setup # # 用法 / Usage (PowerShell): # $env:ROUTER_ONE_API_KEY = "sk-your-api-key"; irm https://router.one/install/codex.ps1 | iex # ============================================================ $ErrorActionPreference = "Stop" function Write-RouterOk([string]$Message) { Write-Host "[OK] $Message" -ForegroundColor Green } function Write-RouterWarn([string]$Message) { Write-Host "[!] $Message" -ForegroundColor Yellow } function Write-RouterErr([string]$Message) { Write-Host "[X] $Message" -ForegroundColor Red } function Write-RouterInfo([string]$Message) { Write-Host "> $Message" -ForegroundColor DarkGray } # PS 5.1 Set-Content -Encoding UTF8 writes a BOM, which breaks JSON/TOML # parsers downstream — always write config files BOM-less. function Write-RouterFile([string]$FilePath, [string]$Content) { $Utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($FilePath, $Content, $Utf8NoBom) } Write-Host "" Write-Host "Router One · Codex CLI 一键接入" -ForegroundColor Cyan Write-Host "" $ApiKey = $env:ROUTER_ONE_API_KEY if ([string]::IsNullOrWhiteSpace($ApiKey)) { $ApiKey = Read-Host "请输入你的 Router One API Key / Enter your API key (sk-...)" } $ApiKey = "$ApiKey".Trim() if ([string]::IsNullOrWhiteSpace($ApiKey)) { Write-RouterErr "缺少 API Key / missing API key" Write-RouterInfo "先在 https://router.one/dashboard/api-keys 创建 API Key" return } if ($ApiKey -eq "sk-your-api-key") { Write-RouterErr "请把 sk-your-api-key 替换成你的真实 API Key / replace the placeholder with your real key" return } if (-not $ApiKey.StartsWith("sk-")) { Write-RouterWarn "API Key 一般以 sk- 开头,请确认复制完整 / keys usually start with sk-" } # ---- 1. Codex CLI ------------------------------------------ $CodexCommand = Get-Command codex -ErrorAction SilentlyContinue if ($CodexCommand) { Write-RouterOk "检测到 Codex CLI / found Codex CLI: $($CodexCommand.Source)" } else { $NpmCommand = Get-Command npm -ErrorAction SilentlyContinue if ($NpmCommand) { Write-RouterInfo "未检测到 Codex CLI,通过 npm 安装 / installing @openai/codex via npm..." npm install -g @openai/codex } if (-not (Get-Command codex -ErrorAction SilentlyContinue)) { Write-RouterInfo "通过官方安装器安装(无需 Node.js)/ installing via the official installer..." try { irm https://chatgpt.com/codex/install.ps1 | iex } catch { Write-RouterWarn "官方安装器执行失败 / official installer failed" } $UserPath = [System.Environment]::GetEnvironmentVariable("Path", "User") $MachinePath = [System.Environment]::GetEnvironmentVariable("Path", "Machine") $env:Path = "$MachinePath;$UserPath;$env:Path" } if (Get-Command codex -ErrorAction SilentlyContinue) { Write-RouterOk "Codex CLI 安装完成 / installed" } else { Write-RouterWarn "未能确认 codex 命令可用:安装可能未完成,或需重开 PowerShell 后生效 / could not confirm codex on PATH — reopen PowerShell if needed" } } # ---- 2. ~/.codex/config.toml ------------------------------- $CodexDir = Join-Path $env:USERPROFILE ".codex" $ConfigPath = Join-Path $CodexDir "config.toml" New-Item -ItemType Directory -Force -Path $CodexDir | Out-Null $ConfigToml = @' model = "gpt-5.6-sol" model_provider = "router" model_reasoning_effort = "high" model_verbosity = "high" web_search = "live" [model_providers.router] base_url = "https://api.router.one/v1" env_key = "ROUTER_ONE_API_KEY" env_key_instructions = "Create an API key at https://router.one/dashboard/api-keys and set the ROUTER_ONE_API_KEY environment variable." name = "Router One" wire_api = "responses" '@ if (Test-Path $ConfigPath) { $Stamp = Get-Date -Format "yyyyMMddHHmmss" Copy-Item $ConfigPath "$ConfigPath.bak.$Stamp" Write-RouterWarn "已有 config.toml,原文件备份到 / existing config backed up: $ConfigPath.bak.$Stamp" } Write-RouterFile $ConfigPath ($ConfigToml + "`n") Write-RouterOk "已写入 $ConfigPath (provider=router, env_key=ROUTER_ONE_API_KEY)" # ---- 3. 持久化 API Key / persist the key ------------------- [System.Environment]::SetEnvironmentVariable("ROUTER_ONE_API_KEY", $ApiKey, "User") $env:ROUTER_ONE_API_KEY = $ApiKey Write-RouterOk "已把 ROUTER_ONE_API_KEY 写入用户环境变量(当前会话已生效)/ saved to user environment variables" # ---- 4. Verify --------------------------------------------- Write-RouterInfo "发送一次 1 token 测试请求验证网关连通 / verifying gateway..." try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 } catch {} $VerifyBody = '{"model":"auto","max_tokens":1,"messages":[{"role":"user","content":"ping"}]}' $VerifyFailed = $false try { Invoke-RestMethod -Method Post -Uri "https://api.router.one/v1/chat/completions" ` -Headers @{ Authorization = "Bearer $ApiKey" } ` -ContentType "application/json" -Body $VerifyBody -TimeoutSec 60 | Out-Null Write-RouterOk "网关连通,API Key 有效 / gateway reachable, key valid" } catch { $StatusCode = 0 if ($_.Exception.Response) { try { $StatusCode = [int]$_.Exception.Response.StatusCode } catch { $StatusCode = 0 } } if ($StatusCode -eq 401) { Write-RouterErr "API Key 无效 (401)。配置已写入,但请到 https://router.one/dashboard/api-keys 检查或重新生成 Key。" $VerifyFailed = $true } elseif ($StatusCode -eq 402) { Write-RouterWarn "API Key 有效但余额不足 (402)。请先充值 / top up first: https://router.one/dashboard" } elseif ($StatusCode -eq 0) { Write-RouterWarn "网络请求失败,跳过验证(配置已写入)/ network error, skipped verification" } else { Write-RouterWarn "验证请求返回 HTTP $StatusCode (配置已写入)。排查见 / troubleshooting: https://router.one/docs/guides/cli-setup" } } Write-Host "" if ($VerifyFailed) { Write-RouterErr "配置完成,但 API Key 验证未通过 / setup finished but key verification failed" } else { Write-RouterOk "全部完成!运行 codex 开始使用 / all set — run: codex" } Write-RouterInfo "文档 / docs: https://router.one/docs/guides/cli-setup"