anygate 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/command.ts","../src/apps/shared/native-launcher.ts","../src/ui/api.ts","../src/ui/server-control.ts","../src/services/doctor.ts"],"sourcesContent":["import { createServer } from 'node:http'\nimport {\n readFileSync,\n readdirSync,\n writeFileSync,\n unlinkSync,\n existsSync,\n mkdirSync,\n} from 'node:fs'\nimport { join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { dirname } from 'node:path'\nimport pc from 'picocolors'\nimport * as p from '@clack/prompts'\nimport { getAppHome } from '../config/paths.js'\nimport { handleUiApiRequest, type UiServerLifecycleEvent } from './api.js'\nimport { getUiDebugLogPath, makeTraceLogger } from '../apps/shared/trace-log.js'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n// Served SPA is produced by `vite build` (src/ui/app → dist/ui/dist). Version is injected\n// at build time via the __APP_VERSION__ define, so no runtime substitution needed.\nconst PUBLIC_DIR = join(__dirname, 'ui', 'dist')\nconst LOCK_FILE = join(getAppHome(), 'ui.lock')\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.png': 'image/png',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.json': 'application/json; charset=utf-8',\n '.woff2': 'font/woff2',\n}\n\nfunction ext(path: string): string {\n const i = path.lastIndexOf('.')\n return i >= 0 ? path.slice(i) : ''\n}\n\nfunction buildStaticCache(): Map<string, { content: Buffer; mime: string }> {\n const cache = new Map<string, { content: Buffer; mime: string }>()\n try {\n const walk = (dir: string, prefix: string): void => {\n for (const name of readdirSync(dir)) {\n const full = join(dir, name)\n const key = `${prefix}/${name}`\n try {\n readdirSync(full) // directory — recurse\n walk(full, key)\n } catch {\n const mime = MIME[ext(name)]\n if (!mime) continue\n const raw = readFileSync(full)\n cache.set(key, { content: raw, mime })\n }\n }\n }\n walk(PUBLIC_DIR, '')\n const index = cache.get('/index.html')\n if (index) cache.set('/__spa_fallback__', index)\n } catch {}\n return cache\n}\n\nfunction removeLock(): void {\n try {\n unlinkSync(LOCK_FILE)\n } catch {}\n}\n\n/** Shape of `ui.lock` — where a previously started UI said it was listening. */\nexport interface UiLockInfo {\n pid: number\n port: number\n}\n\nexport function parseUiLock(raw: string): UiLockInfo | null {\n try {\n const { pid, port } = JSON.parse(raw) as { pid?: unknown; port?: unknown }\n if (!Number.isInteger(pid) || !Number.isInteger(port)) return null\n if ((port as number) < 1 || (port as number) > 65535) return null\n return { pid: pid as number, port: port as number }\n } catch {\n return null\n }\n}\n\n/** How long a recorded port gets to identify itself before we call the lock stale. */\nconst PROBE_TIMEOUT_MS = 1500\n\n/**\n * Ask whatever is listening on `port` whether it is an anygate UI.\n *\n * A PID check cannot answer this on any platform. `ui.lock` outlives a hard kill\n * — terminal window closed, taskkill, reboot — and the OS is then free to hand\n * that PID to an unrelated program, which Windows reliably does. \"The PID\n * exists\" is true in that case while the port is dead, so `anygate ui` refused\n * to start and pointed at a URL nothing was serving. The recorded port is\n * ephemeral too, so another service may legitimately hold it by now. Only the\n * server's own `/api/ping` marker tells a live UI apart from either impostor.\n */\nexport async function probeUiServer(\n port: number,\n fetchImpl: typeof fetch = fetch\n): Promise<boolean> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS)\n try {\n const res = await fetchImpl(`http://127.0.0.1:${port}/api/ping`, { signal: controller.signal })\n if (!res.ok) return false\n const body = (await res.json()) as { app?: unknown }\n return body?.app === 'anygate'\n } catch {\n return false\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Resolve the lock file to a URL only when a live anygate UI answers there. Any\n * other outcome — no lock, unreadable lock, silent or unrecognized port — clears\n * the lock so this run starts a fresh server instead of stalling on a dead one.\n */\nexport async function checkExistingServer(fetchImpl: typeof fetch = fetch): Promise<string | null> {\n if (!existsSync(LOCK_FILE)) return null\n let lock: UiLockInfo | null = null\n try {\n lock = parseUiLock(readFileSync(LOCK_FILE, 'utf8'))\n } catch {\n lock = null\n }\n if (lock && (await probeUiServer(lock.port, fetchImpl))) {\n return `http://127.0.0.1:${lock.port}`\n }\n removeLock()\n return null\n}\n\nexport function isUiApiRoute(url: string): boolean {\n return url.startsWith('/api/') || url.startsWith('/auth/callback')\n}\n\nexport function formatUiServerLifecycleMessage(event: UiServerLifecycleEvent): string {\n if (event.type === 'stopped') return '◇ Server Gateway stopped'\n const mode = event.listenMode === 'network' ? 'Network' : 'Local'\n const modelLabel = event.modelCount === 1 ? 'model' : 'models'\n return `◆ Server Gateway started · ${mode} mode · ${event.modelCount} ${modelLabel} exposed`\n}\n\nexport async function resolveUiShutdownDecision(\n signal: NodeJS.Signals,\n promptClose: () => Promise<boolean | symbol> = () =>\n p.confirm({\n message: 'anygate UI is still running. Close it?',\n initialValue: true,\n })\n): Promise<'close' | 'keep'> {\n if (signal !== 'SIGINT') return 'close'\n const shouldClose = await promptClose()\n if (p.isCancel(shouldClose)) return 'close'\n return shouldClose ? 'close' : 'keep'\n}\n\nexport async function runUiCommand(opts: { trace?: boolean } = {}): Promise<number> {\n const existing = await checkExistingServer()\n if (existing) {\n console.log(\n `\\n ${pc.bold('anygate UI')} already running at ${pc.cyan(existing)}\\n ${pc.dim('Press Ctrl+C in that terminal to stop it')}\\n`\n )\n // Reopen the tab: someone typing `anygate ui` wants the dashboard in front\n // of them, and printing a URL to an already-running instance left them with\n // nothing to click.\n try {\n const { default: open } = await import('open')\n await open(existing)\n } catch {\n // Browser couldn't open — URL already printed above\n }\n return 0\n }\n\n if (opts.trace) {\n process.env.ANYGATE_TRACE = '1'\n }\n\n const staticCache = buildStaticCache()\n const traceLogPath = opts.trace ? getUiDebugLogPath() : undefined\n const trace = traceLogPath ? makeTraceLogger(traceLogPath) : undefined\n trace?.('ui server starting')\n\n const server = createServer((req, res) => {\n const url = req.url ?? '/'\n\n res.setHeader('X-Content-Type-Options', 'nosniff')\n\n if (isUiApiRoute(url)) {\n handleUiApiRequest(req, res, {\n trace: opts.trace,\n traceLogPath,\n onServerLifecycle: event => {\n console.log(`\\n ${formatUiServerLifecycleMessage(event)}\\n`)\n },\n })\n return\n }\n\n const key = url === '/' ? '/index.html' : url.split('?')[0]\n trace?.(`static ${req.method ?? 'GET'} ${url} -> ${key}`)\n const cached = staticCache.get(key)\n if (cached) {\n res.writeHead(200, { 'Content-Type': cached.mime })\n res.end(cached.content)\n return\n }\n\n // SPA fallback: serve index.html for any non-asset route (client-side hash routing).\n if (!ext(key) && staticCache.has('/__spa_fallback__')) {\n const fb = staticCache.get('/__spa_fallback__')!\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(fb.content)\n return\n }\n res.writeHead(404)\n res.end('Not found')\n })\n\n await new Promise<void>((resolve, reject) => {\n server.listen(0, '127.0.0.1', () => resolve())\n server.once('error', reject)\n })\n\n const addr = server.address()\n if (!addr || typeof addr === 'string') {\n console.error('Failed to bind server')\n return 1\n }\n\n const port = addr.port\n const url = `http://127.0.0.1:${port}`\n\n mkdirSync(getAppHome(), { recursive: true })\n writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid, port }))\n\n // Covers every exit this process can still observe, including an uncaught\n // throw — the signal handlers below only fire for Ctrl+C and SIGTERM. A hard\n // kill or reboot still orphans the lock, which is what probeUiServer is for.\n process.on('exit', removeLock)\n\n const cleanup = () => {\n removeLock()\n server.close()\n process.exit(0)\n }\n let handlingSignal = false\n const handleSignal = async (signal: NodeJS.Signals) => {\n if (handlingSignal) return\n handlingSignal = true\n const decision = await resolveUiShutdownDecision(signal)\n if (decision === 'keep') {\n handlingSignal = false\n return\n }\n cleanup()\n }\n process.on('SIGINT', () => {\n void handleSignal('SIGINT')\n })\n process.on('SIGTERM', () => {\n void handleSignal('SIGTERM')\n })\n\n console.log(\n `\\n ${pc.bold('anygate UI')} ${pc.cyan(url)}\\n ${pc.dim('Press Ctrl+C to stop')}\\n`\n )\n if (traceLogPath) {\n console.log(` ${pc.dim(`Trace log: ${traceLogPath}`)}\\n`)\n trace?.(`ui server listening ${url}`)\n }\n\n try {\n const { default: open } = await import('open')\n await open(url)\n trace?.(`browser open ${url}`)\n } catch {\n trace?.(`browser open failed ${url}`)\n // Browser couldn't open — URL already printed above\n }\n\n await new Promise<void>(() => {}) // keep alive until signal\n return 0\n}\n","import { chmodSync, existsSync, mkdtempSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { getAppPathOverride } from '../../../src/storage/config.js'\nimport { findBinaryOnPath } from '../shared/binary-lookup.js'\nimport { findClaudeApp } from '../claude/desktop-launch.js'\nimport { findCodexApp } from '../codex/app-launch.js'\n\nconst isWindows = process.platform === 'win32'\nconst isMac = process.platform === 'darwin'\n\nexport interface AppInfo {\n id: string\n name: string\n type: 'cli' | 'app'\n installed: boolean\n path: string | null\n pathSource: 'auto' | 'override' | null\n gatewayCommand: string\n launchCommand: string | null\n /** Shell command to install this app (CLIs). Absent for desktop apps. */\n installHint?: string\n /** Vendor download page for desktop apps. Absent for CLIs. */\n installUrl?: string\n}\n\nexport interface GatewayLaunchOptions {\n providerId?: string\n modelId?: string\n /** Launch with all routable models from `providerId` (emits --all-models). */\n allModels?: boolean\n favorites?: boolean\n /** Launch the full favorites catalog (emits bare --favorites) instead of resolving to the first favorite. */\n favoritesCatalog?: boolean\n cwd?: string\n trace?: boolean\n}\n\ninterface SupportedAppDefinition {\n id: string\n name: string\n type: 'cli' | 'app'\n detectId: string\n gatewayCommand: string\n /** Shell command to install this app (CLIs). */\n installHint?: string\n /** Vendor download page for desktop apps. */\n installUrl?: string\n}\n\nconst SUPPORTED_APPS: SupportedAppDefinition[] = [\n {\n id: 'claude',\n name: 'Claude Code CLI',\n type: 'cli',\n detectId: 'claude',\n gatewayCommand: 'claude',\n installHint: 'npm install -g @anthropic-ai/claude-code',\n },\n {\n id: 'codex',\n name: 'Codex CLI',\n type: 'cli',\n detectId: 'codex',\n gatewayCommand: 'codex',\n installHint: 'npm install -g @openai/codex',\n },\n {\n id: 'gemini',\n name: 'Gemini CLI',\n type: 'cli',\n detectId: 'gemini',\n gatewayCommand: 'gemini',\n installHint: 'npm install -g @google/gemini-cli',\n },\n {\n id: 'agy',\n name: 'Antigravity CLI',\n type: 'cli',\n detectId: 'agy',\n gatewayCommand: 'agy',\n installHint: 'npm install -g @google/antigravity-cli',\n },\n {\n id: 'antigravity',\n name: 'Antigravity (App)',\n type: 'app',\n detectId: 'antigravity',\n gatewayCommand: 'antigravity',\n installUrl: 'https://antigravity.dev/download',\n },\n {\n id: 'antigravity-ide',\n name: 'Antigravity IDE (App)',\n type: 'app',\n detectId: 'antigravity-ide',\n gatewayCommand: 'antigravity-ide',\n installUrl: 'https://antigravity.dev/ide',\n },\n {\n id: 'claude-app',\n name: 'Claude Code Desktop',\n type: 'app',\n detectId: 'claude-app',\n gatewayCommand: 'claude-app',\n installUrl: 'https://claude.com/download',\n },\n {\n id: 'codex-app',\n name: 'ChatGPT Desktop (Codex)',\n type: 'app',\n detectId: 'codex-app',\n gatewayCommand: 'codex-app',\n installUrl: 'https://openai.com/chatgpt/desktop',\n },\n]\n\nexport function fallbackPathsForApp(\n id: string,\n platform: NodeJS.Platform = process.platform\n): string[] {\n const windows = platform === 'win32'\n const mac = platform === 'darwin'\n const appData = process.env['APPDATA'] ?? homedir()\n const localAppData = process.env['LOCALAPPDATA'] ?? join(homedir(), 'AppData', 'Local')\n\n switch (id) {\n case 'claude':\n return windows\n ? [join(appData, 'npm', 'claude.cmd'), join(appData, 'npm', 'claude')]\n : [\n join(homedir(), '.local', 'bin', 'claude'),\n join(homedir(), '.npm', 'bin', 'claude'),\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ]\n case 'codex':\n return windows\n ? [join(appData, 'npm', 'codex.cmd'), join(appData, 'npm', 'codex')]\n : [\n join(homedir(), '.local', 'bin', 'codex'),\n join(homedir(), '.npm', 'bin', 'codex'),\n '/usr/local/bin/codex',\n '/opt/homebrew/bin/codex',\n ]\n case 'gemini':\n return windows\n ? [join(appData, 'npm', 'gemini.cmd'), join(appData, 'npm', 'gemini')]\n : [\n join(homedir(), '.local', 'bin', 'gemini'),\n join(homedir(), '.npm', 'bin', 'gemini'),\n '/usr/local/bin/gemini',\n '/opt/homebrew/bin/gemini',\n ]\n case 'agy':\n return windows\n ? [\n join(appData, 'npm', 'agy.cmd'),\n join(appData, 'npm', 'agy'),\n join(localAppData, 'Antigravity', 'agy.exe'),\n ]\n : [\n join(homedir(), '.local', 'bin', 'agy'),\n join(homedir(), '.npm', 'bin', 'agy'),\n '/usr/local/bin/agy',\n '/opt/homebrew/bin/agy',\n ]\n case 'antigravity-ide':\n if (mac) {\n return [\n '/Applications/Antigravity IDE.app/Contents/Resources/app/bin/antigravity-ide',\n join(\n homedir(),\n 'Applications',\n 'Antigravity IDE.app',\n 'Contents',\n 'Resources',\n 'app',\n 'bin',\n 'antigravity-ide'\n ),\n ]\n }\n if (windows) {\n return [\n join(localAppData, 'Programs', 'Antigravity IDE', 'Antigravity IDE.exe'),\n join(localAppData, 'Programs', 'antigravity-ide', 'Antigravity IDE.exe'),\n join(localAppData, 'Programs', 'Antigravity', 'Antigravity IDE.exe'),\n ]\n }\n return ['/opt/antigravity-ide/Antigravity-IDE']\n case 'antigravity':\n if (mac) {\n return [\n '/Applications/Antigravity.app/Contents/MacOS/Antigravity',\n join(homedir(), 'Applications', 'Antigravity.app', 'Contents', 'MacOS', 'Antigravity'),\n ]\n }\n if (windows) {\n return [join(localAppData, 'Programs', 'Antigravity', 'Antigravity.exe')]\n }\n return ['/opt/antigravity/antigravity', '/usr/local/bin/antigravity', '/usr/bin/antigravity']\n case 'claude-app':\n if (mac) {\n return [\n '/Applications/Claude.app/Contents/MacOS/Claude',\n join(homedir(), 'Applications', 'Claude.app', 'Contents', 'MacOS', 'Claude'),\n ]\n }\n return windows ? [join(localAppData, 'Programs', 'claude', 'Claude.exe')] : []\n case 'codex-app':\n if (mac) {\n // OpenAI merged the Codex desktop app into the ChatGPT desktop app\n // (2026-07-09) — it's now named \"ChatGPT.app\" on disk. Codex.app is\n // kept as a fallback for installs that haven't updated yet.\n return [\n '/Applications/ChatGPT.app',\n join(homedir(), 'Applications', 'ChatGPT.app'),\n '/Applications/Codex.app',\n join(homedir(), 'Applications', 'Codex.app'),\n ]\n }\n // Windows exe/folder naming after the rename is unverified against a\n // real install (see src/codex/app-launch.ts) — best-effort guess\n // mirroring the confirmed macOS convention, with Codex.exe kept as\n // a fallback for installs that haven't updated yet.\n return windows\n ? [\n join(localAppData, 'Programs', 'ChatGPT', 'ChatGPT.exe'),\n join(localAppData, 'Programs', 'OpenAI ChatGPT', 'ChatGPT.exe'),\n join(localAppData, 'openai-chatgpt-electron', 'ChatGPT.exe'),\n join(localAppData, 'Programs', 'Codex', 'Codex.exe'),\n join(localAppData, 'Programs', 'OpenAI Codex', 'Codex.exe'),\n join(localAppData, 'openai-codex-electron', 'Codex.exe'),\n ]\n : []\n default:\n return []\n }\n}\n\nconst FALLBACKS: Record<string, string[]> = Object.fromEntries(\n SUPPORTED_APPS.map(app => [app.detectId, fallbackPathsForApp(app.detectId)])\n)\n\nexport function getSupportedApp(id: string): SupportedAppDefinition | undefined {\n return SUPPORTED_APPS.find(app => app.id === id)\n}\n\n// Check if a specific binary/app is installed\nexport function detectApp(id: string): {\n installed: boolean\n path: string | null\n pathSource: 'auto' | 'override' | null\n} {\n // A manual override wins only while it still exists. A stale one must NOT be\n // treated as \"not installed\": Microsoft Store (MSIX) installs live under\n // version-stamped paths (…\\WindowsApps\\Claude_1.24012.1.0_x64__…\\app\\claude.exe),\n // so every Store auto-update invalidates a previously-valid override. Reporting\n // the app as missing left users permanently stuck, because re-browsing to the new\n // path only re-armed the same trap on the next update. Fall through to\n // auto-detection instead, which resolves the version-independent AppsFolder moniker.\n const override = getAppPathOverride(id)\n if (override && existsSync(override)) {\n return { installed: true, path: override, pathSource: 'override' }\n }\n\n const resolvedPath = findBinaryOnPath(id, FALLBACKS[id] ?? [], { verifyWhichResult: true })\n if (resolvedPath) {\n return { installed: true, path: resolvedPath, pathSource: 'auto' }\n }\n\n // Microsoft Store (MSIX) installs live under version-stamped WindowsApps\n // paths the static fallback lists can't cover — the app-launch finders\n // handle them via Get-StartApps (returning a shell:AppsFolder moniker).\n const appFinder = id === 'claude-app' ? findClaudeApp : id === 'codex-app' ? findCodexApp : null\n if (appFinder) {\n const appPath = appFinder()\n if (appPath) return { installed: true, path: appPath, pathSource: 'auto' }\n }\n\n return { installed: false, path: null, pathSource: null }\n}\n\n// Generate the shell command to open a new native terminal running the chosen tool/args\nexport function getTerminalLaunchCommand(\n binPath: string,\n args: string[],\n opts: { cwd?: string; displayCommand?: string } = {}\n): string {\n const fullCmd = [binPath, ...args]\n .map(arg => {\n // Whitelist: alphanumeric, dash, underscore, dot, slash (for paths).\n // Anything else is rejected outright rather than escaped — the values\n // here (anygate binary path, provider/model ids) are always simple\n // identifiers, and there is no single escaping scheme that is safe for\n // all three downstream shells (macOS sh, Linux sh, Windows cmd.exe).\n if (!/^[a-zA-Z0-9\\-_./:]+$/.test(arg)) {\n throw new Error(`Unsafe launch argument: ${JSON.stringify(arg)}`)\n }\n return arg\n })\n .join(' ')\n const cwdPrefix = opts.cwd ? `cd ${quoteShellArg(opts.cwd)} && ` : ''\n const runCmd = `${cwdPrefix}${fullCmd}`\n\n if (isMac) {\n const dir = mkdtempSync(join(tmpdir(), 'anygate-launch-'))\n const scriptPath = join(dir, 'launch.command')\n const displayCommand = opts.displayCommand ?? [binPath, ...args].join(' ')\n writeFileSync(\n scriptPath,\n [\n '#!/bin/sh',\n 'trap \\'rm -f \"$0\"; rmdir \"$(dirname \"$0\")\" 2>/dev/null\\' EXIT',\n 'clear',\n opts.cwd ? `cd ${quoteShellArg(opts.cwd)} || exit 1` : '',\n `printf '%s\\\\n\\\\n' ${quoteShellArg(`$ ${displayCommand}`)}`,\n fullCmd,\n 'status=$?',\n 'printf \"\\\\nanygate session exited with code %s. Press Return to close this window. \" \"$status\"',\n 'read _',\n 'exit \"$status\"',\n '',\n ].join('\\n'),\n { encoding: 'utf8', mode: 0o700 }\n )\n chmodSync(scriptPath, 0o700)\n return `open -a Terminal ${quoteShellArg(scriptPath)}`\n }\n\n if (isWindows) {\n // Windows Start command: launches in cmd.exe in a new window.\n // First parameter to start is the window title; /d sets the working\n // directory — cwd must NOT be passed as a `cd '...'` prefix because\n // cmd.exe does not understand the POSIX single-quoting used by\n // quoteShellArg (\"The filename, directory name, or volume label\n // syntax is incorrect\").\n const dirFlag = opts.cwd ? `/d \"${opts.cwd}\" ` : ''\n return `start \"anygate Terminal\" ${dirFlag}cmd.exe /k \"${fullCmd}\"`\n }\n\n // Linux: probe terminal emulators (fallback to generic execution)\n // Write runCmd to a script file rather than embedding it inline — runCmd may\n // itself contain single-quoted segments (from quoteShellArg), which breaks\n // nested single-quoting if interpolated directly into `sh -c '...'`.\n const dir = mkdtempSync(join(tmpdir(), 'anygate-launch-'))\n const scriptPath = join(dir, 'launch.sh')\n writeFileSync(scriptPath, ['#!/bin/sh', runCmd, 'exec sh', ''].join('\\n'), {\n encoding: 'utf8',\n mode: 0o700,\n })\n chmodSync(scriptPath, 0o700)\n const scriptArg = quoteShellArg(scriptPath)\n return `x-terminal-emulator -e sh ${scriptArg} || gnome-terminal -- sh ${scriptArg} || xterm -e sh ${scriptArg}`\n}\n\nfunction quoteShellArg(value: string): string {\n if (/^[a-zA-Z0-9\\-_./]+$/.test(value)) return value\n return `'${value.replace(/'/g, \"'\\\\''\")}'`\n}\n\nfunction gatewayCliPath(): string {\n return 'anygate'\n}\n\nexport function getGatewayLaunchCommand(appId: string, options: GatewayLaunchOptions = {}): string {\n const app = getSupportedApp(appId)\n if (!app) throw new Error(`Unsupported app: ${appId}`)\n\n const args = [app.gatewayCommand]\n if (options.trace) {\n args.push('--trace')\n }\n if (options.favoritesCatalog) {\n args.push('--favorites')\n } else if (options.allModels && options.providerId) {\n args.push('--provider', options.providerId, '--all-models')\n } else if (options.providerId && options.modelId) {\n args.push('--provider', options.providerId, '--model', options.modelId)\n } else if (options.providerId || options.modelId) {\n throw new Error('Both providerId and modelId are required for an explicit anygate launch.')\n }\n\n return getTerminalLaunchCommand(gatewayCliPath(), args, {\n cwd: options.cwd,\n displayCommand: ['anygate', ...args].join(' '),\n })\n}\n\n// Get lists of all supported apps and status\nexport function getSupportedApps(): AppInfo[] {\n return SUPPORTED_APPS.map(app => {\n const { installed, path, pathSource } = detectApp(app.detectId)\n return {\n id: app.id,\n name: app.name,\n type: app.type,\n installed,\n path,\n pathSource,\n gatewayCommand: app.gatewayCommand,\n launchCommand: installed ? getGatewayLaunchCommand(app.id) : null,\n installHint: app.installHint,\n installUrl: app.installUrl,\n }\n })\n}\n","import {\n getSupportedApps,\n getSupportedApp,\n getGatewayLaunchCommand,\n detectApp,\n} from '../apps/shared/native-launcher.ts'\nimport { exec } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst execAsync = promisify(exec)\nimport { existsSync, statSync } from 'node:fs'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { randomUUID } from 'node:crypto'\nimport {\n loadPreferences,\n recordLaunchFolder,\n savePreferences,\n setAppPathOverride,\n loadLaunchPresets,\n saveLaunchPresets,\n} from '../storage/config.js'\nimport { fetchProviderCatalog } from '../registry/provider-catalog.js'\nimport { favoriteProviderDisplayName } from '../apps/claude/favorites-provider-display.ts'\nimport { saveProviderCredential, resolveProviderCredential } from '../config/env.js'\nimport { readBody, sendJson } from '../shared/http.ts'\nimport { VERSION } from '../config/constants.js'\nimport { loadRegistry } from '../registry/storage/io.js'\nimport { refreshProviderModels, refreshAllProviderModels } from '../registry/sync/refresh-models.js'\nimport {\n listAddableTemplates,\n listVisibleOAuthTemplates,\n PROVIDER_TEMPLATES,\n getTemplateById,\n} from '../registry/templates/provider-templates.js'\nimport {\n addProviderFromTemplate,\n type AddTemplateResult,\n} from '../registry/templates/add-template.js'\nimport {\n addCustomEndpointProvider,\n type CustomEndpointKind,\n} from '../registry/storage/custom-endpoint.js'\nimport { validateCustomEndpointUrl } from '../registry/validation/url-security.js'\nimport { saveNativeOAuthCredential } from '../registry/provider-auth.js'\nimport { removeProviderFromRegistry } from '../registry/storage/crud.js'\nimport { requestXaiDeviceCode, pollXaiDeviceCodeToken } from '../auth/xai.js'\nimport {\n requestOpenAiDeviceCode,\n pollOpenAiDeviceCodeToken,\n openAiDeviceCodeUrl,\n buildOpenAiBrowserAuthUrl,\n exchangeOpenAiBrowserToken,\n ISSUER,\n} from '../auth/openai.js'\nimport { requestGithubDeviceCode, pollGithubDeviceCodeToken } from '../auth/github.js'\nimport { guiCallbackRedirectUri } from '../auth/claude-code.js'\nimport { buildAntigravityAuthUrl, completeAntigravityExchange } from '../auth/antigravity-oauth.js'\nimport { startCallbackServer } from '../auth/callback-server.js'\n\nimport { providerOptionsFromCatalog } from '../gateway/server/server.js'\nimport {\n getServerStatus,\n startGatewayServer,\n stopGatewayServer,\n type ServerStartRequest,\n} from './server-control.js'\nimport { writeSecureLogLine } from '../apps/shared/trace-log.js'\nimport { freeStatusLabel } from '../apps/shared/free-models.ts'\nimport { checkForUpdates } from '../apps/shared/update-check.ts'\nimport { aggregateAnalytics, type RangeId } from '../storage/analytics.js'\nimport { collectDoctorReport } from '../services/doctor.js'\nimport { subscribeToAppEvents, emitAppEvent, type AppEvent } from '../services/event-bus.js'\nimport type { LaunchPreset } from '../types/index.js'\nimport { resolveInputTypes, resolveReasoning } from '../registry/models-dev.js'\n\nconst MODELS_TIMEOUT_MS = 30_000\n\nexport type UiServerLifecycleEvent =\n { type: 'started'; listenMode: 'local' | 'network'; modelCount: number } | { type: 'stopped' }\n\nexport interface UiApiOptions {\n trace?: boolean\n traceLogPath?: string\n onServerLifecycle?: (event: UiServerLifecycleEvent) => void\n}\n\n// ── OAuth device-code session store ──────────────────────────────────────────\n// Keyed by random session ID returned to the client. Sessions auto-purge on\n// first terminal status read so the map doesn't grow unboundedly.\n\ntype OAuthSessionStatus = 'pending' | 'done' | 'error'\n\ninterface OAuthSession {\n status: OAuthSessionStatus\n url: string\n userCode?: string // device code flows only\n providerId: string\n error?: string\n // PKCE flows only — never sent to client:\n codeVerifier?: string\n oauthState?: string\n codeResolver?: (code: string) => void\n errorRejecter?: (err: string) => void\n}\n\nconst oauthSessions = new Map<string, OAuthSession>()\n\nasync function fetchModelsWithTimeout(opts?: Parameters<typeof fetchProviderCatalog>[0]) {\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('timeout')), MODELS_TIMEOUT_MS)\n )\n return Promise.race([fetchProviderCatalog(opts), timeout])\n}\n\n/** Shared 500/504 mapping for the two provider-catalog-fetching routes below. */\nfunction sendCatalogFetchError(res: ServerResponse, err: unknown, label: string): void {\n const isTimeout = String(err).includes('timeout')\n sendJson(res, isTimeout ? 504 : 500, { error: isTimeout ? `${label} timed out` : String(err) })\n}\n\nfunction isLoopbackOrigin(origin: string | undefined): boolean {\n if (!origin) return false\n try {\n const hostname = new URL(origin).hostname\n return hostname === '127.0.0.1' || hostname === 'localhost' || hostname === '::1'\n } catch {\n return false\n }\n}\n\nfunction sendCors(req: IncomingMessage, res: ServerResponse): void {\n const origin = req.headers.origin\n const originValue = Array.isArray(origin) ? origin[0] : origin\n if (isLoopbackOrigin(originValue)) {\n res.setHeader('Access-Control-Allow-Origin', originValue!)\n }\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type')\n}\n\nfunction traceUi(opts: UiApiOptions | undefined, message: string): void {\n if (!opts?.trace || !opts.traceLogPath) return\n writeSecureLogLine(opts.traceLogPath, `${new Date().toISOString()} ${message}`)\n}\n\nfunction notifyServerLifecycle(opts: UiApiOptions, event: UiServerLifecycleEvent): void {\n // Push to live dashboards before the terminal callback, so a throwing\n // console handler can't suppress the UI update.\n emitAppEvent(\n event.type === 'started'\n ? {\n type: 'server',\n running: true,\n listenMode: event.listenMode,\n modelCount: event.modelCount,\n }\n : { type: 'server', running: false }\n )\n try {\n opts.onServerLifecycle?.(event)\n } catch {\n // Terminal output must not affect the gateway lifecycle or API response.\n }\n}\n\nexport function handleUiApiRequest(\n req: IncomingMessage,\n res: ServerResponse,\n opts: UiApiOptions = {}\n): void {\n sendCors(req, res)\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n const url = req.url ?? ''\n traceUi(opts, `${req.method ?? 'GET'} ${url}`)\n\n if (url === '/api/config' && req.method === 'GET') {\n handleGetConfig(res)\n } else if (url === '/api/update-status' && req.method === 'GET') {\n handleGetUpdateStatus(res)\n } else if (url === '/api/config' && req.method === 'POST') {\n handlePostConfig(req, res)\n } else if (url === '/api/models' && req.method === 'GET') {\n handleGetModels(res)\n } else if (url === '/api/models/test' && req.method === 'POST') {\n handleTestModel(req, res)\n } else if (url === '/api/keys' && req.method === 'POST') {\n handlePostKeys(req, res)\n } else if (url === '/api/providers/refresh' && req.method === 'POST') {\n handleProviderRefresh(req, res)\n } else if (url === '/api/providers/refresh-all' && req.method === 'POST') {\n handleRefreshAll(res)\n } else if (url === '/api/providers/templates' && req.method === 'GET') {\n handleGetTemplates(res)\n } else if (url === '/api/providers/add' && req.method === 'POST') {\n handleAddProvider(req, res)\n } else if (url === '/api/providers/add-custom' && req.method === 'POST') {\n handleAddCustomProvider(req, res)\n } else if (url === '/api/providers/delete' && req.method === 'POST') {\n handleDeleteProvider(req, res)\n // Both spellings are served: `oauth/*` is what every shipped client calls\n // (the Svelte app and the legacy public/app.js), while `auth/*` is the\n // name introduced by the b88a876 rename. Keeping both means the rename\n // can finish without stranding any client.\n } else if (\n (url === '/api/providers/oauth/start' || url === '/api/providers/auth/start') &&\n req.method === 'POST'\n ) {\n handleOAuthStart(req, res)\n } else if (\n (url.startsWith('/api/providers/oauth/status') ||\n url.startsWith('/api/providers/auth/status')) &&\n req.method === 'GET'\n ) {\n handleOAuthStatus(req, res)\n } else if (url.startsWith('/auth/callback') && req.method === 'GET') {\n handleOAuthCallback(req, res)\n } else if (url === '/api/apps' && req.method === 'GET') {\n handleGetApps(res)\n } else if (url === '/api/apps/path' && req.method === 'POST') {\n handleSetAppPath(req, res)\n } else if (url === '/api/apps/launch' && req.method === 'POST') {\n handleLaunchApp(req, res, opts)\n } else if (url === '/api/apps/browse-folder' && req.method === 'POST') {\n handleBrowseFolder(res)\n } else if (url === '/api/server/status' && req.method === 'GET') {\n handleGetServerStatus(res)\n } else if (url === '/api/server/providers' && req.method === 'GET') {\n handleGetServerProviders(res)\n } else if (url === '/api/server/start' && req.method === 'POST') {\n handleStartServer(req, res, opts)\n } else if (url === '/api/server/stop' && req.method === 'POST') {\n handleStopServer(res, opts)\n } else if (url === '/api/events' && req.method === 'GET') {\n handleEventStream(req, res)\n } else if (url === '/api/presets' && req.method === 'GET') {\n handleGetPresets(res)\n } else if (url === '/api/presets' && req.method === 'POST') {\n handleSavePresets(req, res)\n } else if (url === '/api/ping' && req.method === 'GET') {\n handleGetPing(res)\n } else if (url === '/api/health' && req.method === 'GET') {\n handleGetHealth(res)\n } else if (url.startsWith('/api/analytics') && req.method === 'GET') {\n handleGetAnalytics(res, req)\n } else {\n sendJson(res, 404, { error: 'Not found' })\n }\n}\n\n/** Interval between SSE keepalive comments. Keeps proxies from idling us out. */\nconst SSE_KEEPALIVE_MS = 25_000\n\n/**\n * `GET /api/events` — Server-Sent Events stream of live app activity.\n *\n * Replaces the dashboard's 5s status polling: the client opens one stream and\n * receives usage/server/provider events as they happen. EventSource reconnects\n * on its own, so a dropped connection needs no client-side retry logic.\n */\nfunction handleEventStream(req: IncomingMessage, res: ServerResponse): void {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n // Defeats proxy buffering that would otherwise delay events.\n 'X-Accel-Buffering': 'no',\n })\n\n const send = (event: AppEvent): void => {\n // `writable` guards the race where the client disconnects between the\n // event firing and this write.\n if (!res.writableEnded) res.write(`data: ${JSON.stringify(event)}\\n\\n`)\n }\n\n res.write(': connected\\n\\n')\n\n const unsubscribe = subscribeToAppEvents(send)\n const keepalive = setInterval(() => {\n if (!res.writableEnded) res.write(': keepalive\\n\\n')\n }, SSE_KEEPALIVE_MS)\n if (typeof keepalive.unref === 'function') keepalive.unref()\n\n const cleanup = (): void => {\n clearInterval(keepalive)\n unsubscribe()\n }\n req.on('close', cleanup)\n req.on('error', cleanup)\n res.on('close', cleanup)\n}\n\n/**\n * Coerce one untrusted preset object into a `LaunchPreset`, or null if it lacks\n * the required identity fields. Unknown keys are dropped so a malformed client\n * can't write arbitrary data into the shared config file.\n */\nfunction sanitizePreset(raw: unknown): LaunchPreset | null {\n if (!raw || typeof raw !== 'object') return null\n const p = raw as Record<string, unknown>\n const str = (v: unknown): string | undefined =>\n typeof v === 'string' && v.trim() ? v.trim() : undefined\n const id = str(p['id'])\n const appId = str(p['appId'])\n if (!id || !appId) return null\n const flags = Array.isArray(p['flags'])\n ? p['flags'].filter((f): f is string => typeof f === 'string')\n : undefined\n const preset: LaunchPreset = { id, appId }\n const providerId = str(p['providerId'])\n const modelId = str(p['modelId'])\n const folder = str(p['folder'])\n const label = str(p['label'])\n if (providerId) preset.providerId = providerId\n if (modelId) preset.modelId = modelId\n if (folder) preset.folder = folder\n if (label) preset.label = label\n if (flags?.length) preset.flags = flags\n return preset\n}\n\nfunction handleGetPresets(res: ServerResponse): void {\n try {\n sendJson(res, 200, { presets: loadLaunchPresets() })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleSavePresets(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req)) as { presets?: unknown }\n if (!Array.isArray(body.presets)) {\n sendJson(res, 400, { error: 'presets must be an array' })\n return\n }\n const seen = new Map<string, LaunchPreset>()\n for (const raw of body.presets) {\n const preset = sanitizePreset(raw)\n // Last write wins per id, so a duplicated id can't create two rows.\n if (preset) seen.set(preset.id, preset)\n }\n sendJson(res, 200, { ok: true, presets: saveLaunchPresets([...seen.values()]) })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\n/**\n * `GET /api/ping` — liveness identity probe. Deliberately does no disk,\n * keychain, or network work so `anygate ui` can call it on startup to decide\n * whether the port recorded in `ui.lock` still belongs to a live UI. The `app`\n * marker is what makes the answer attributable: a PID can be recycled and an\n * ephemeral port can be reassigned, so only a reply in this shape proves an\n * anygate UI is on the other end. See `probeUiServer` in ./command.ts.\n */\nfunction handleGetPing(res: ServerResponse): void {\n sendJson(res, 200, { app: 'anygate', version: VERSION, pid: process.pid })\n}\n\n/**\n * `GET /api/health` — real system diagnostics, shared with `anygate doctor`.\n *\n * Shape matches the UI's `HealthReport` contract. `providerReachability` is\n * deliberately omitted: it would require a network round-trip per provider, and\n * reporting an empty array here would read as \"all providers unreachable\".\n * Live provider checks live behind their own explicit endpoint instead.\n */\nasync function handleGetHealth(res: ServerResponse): Promise<void> {\n try {\n const gatewayRunning = (await getServerStatus()).running\n const report = await collectDoctorReport({ gatewayRunning })\n sendJson(res, 200, {\n ok: report.ok,\n checks: report.checks,\n nodeVersion: report.nodeVersion,\n keychain: report.keychain,\n conflictingEnvVars: report.conflictingEnvVars,\n gatewayPort: report.gatewayPort,\n // Busy-but-ours counts as available to the UI: nothing is blocking a start.\n port17645Available: report.gatewayPortAvailable || report.gatewayPortOwnedByAnygate,\n gatewayPortOwnedByAnygate: report.gatewayPortOwnedByAnygate,\n })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleGetUpdateStatus(res: ServerResponse): Promise<void> {\n sendJson(res, 200, await checkForUpdates())\n}\n\nfunction handleGetConfig(res: ServerResponse): void {\n const prefs = loadPreferences()\n sendJson(res, 200, {\n favoriteModels: prefs.favoriteModels ?? [],\n antigravityCliFavoriteModels: prefs.antigravityCliFavoriteModels ?? [],\n })\n}\n\nasync function handlePostConfig(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req))\n const update: Parameters<typeof savePreferences>[0] = {}\n if (Array.isArray(body.favoriteModels)) update.favoriteModels = body.favoriteModels\n if (Array.isArray(body.antigravityCliFavoriteModels))\n update.antigravityCliFavoriteModels = body.antigravityCliFavoriteModels\n if (Object.keys(update).length > 0) savePreferences(update)\n sendJson(res, 200, { ok: true })\n } catch (err) {\n sendJson(res, 400, { error: String(err) })\n }\n}\n\n// Some providers (e.g. Mistral) report the same model id twice in the\n// catalog. Svelte 5 throws `each_key_duplicate` on duplicate #each keys,\n// which blanks the whole Models page — dedupe per provider before sending.\nfunction dedupModelsById<T extends { id: string }>(models: T[]): T[] {\n const seen = new Set<string>()\n const out: T[] = []\n for (const m of models) {\n if (seen.has(m.id)) continue\n seen.add(m.id)\n out.push(m)\n }\n return out\n}\n\nasync function handleGetModels(res: ServerResponse): Promise<void> {\n try {\n const catalog = await fetchModelsWithTimeout()\n const registry = loadRegistry()\n const rawCountById = new Map(\n registry.providers.map(p => [p.id, p.modelsCache?.models.length ?? 0])\n )\n const providers = catalog.map(p => ({\n id: p.id,\n name: p.name,\n favoriteName: favoriteProviderDisplayName(p),\n hasKey: Boolean(p.apiKey),\n freeAccess:\n !p.apiKey &&\n (() => {\n const t = registry.providers.find(rp => rp.id === p.id)?.templateId ?? p.id\n return getTemplateById(t)?.anonymousFreeModels === true\n })(),\n authType: p.authType ?? 'api',\n modelCount: rawCountById.get(p.id) ?? p.models.length,\n signupUrl: getTemplateById(p.id)?.signupUrl ?? null,\n models: dedupModelsById(p.models).map(m => ({\n id: m.id,\n name: m.name,\n isFree: m.isFree ?? false,\n freeStatus: m.freeStatus,\n freeLabel: freeStatusLabel(m.freeStatus),\n contextWindow: m.contextWindow,\n cost: m.cost,\n providerId: p.id,\n inputTypes: resolveInputTypes(m.family, p.id, m.id),\n reasoning:\n m.reasoning ?? resolveReasoning(p.id, m.id),\n })),\n }))\n\n // OAuth providers with 0 models are excluded by materializeOne (no models = not materialized).\n // Surface them anyway so their card appears and the user can click Refresh Models.\n const materializedIds = new Set(catalog.map(p => p.id))\n for (const rp of registry.providers) {\n if (rp.authType !== 'oauth' || !rp.enabled || materializedIds.has(rp.id)) continue\n const credential = await resolveProviderCredential(rp.id, rp.authRef).catch(() => null)\n if (!credential) continue\n providers.push({\n id: rp.id,\n name: rp.name,\n favoriteName: favoriteProviderDisplayName({\n id: rp.id,\n name: rp.name,\n authType: rp.authType,\n }),\n hasKey: true,\n freeAccess: false,\n authType: 'oauth',\n modelCount: 0,\n signupUrl: getTemplateById(rp.templateId)?.signupUrl ?? null,\n models: [],\n })\n }\n\n sendJson(res, 200, { providers })\n } catch (err) {\n sendCatalogFetchError(res, err, 'Model fetch')\n }\n}\n\n// ── Model Tester (live latency / benchmark) ──────────────────────────────\n// Runs a real request against a provider+model's upstream endpoint from the\n// server (browser can't reach providers directly: CORS + secret keys). Measures\n// connect / TTFT / total latency and reports a short response sample.\nconst TEST_TIMEOUT_MS = 30_000\nconst TEST_DEFAULT_PROMPT = 'Reply with a single word: pong'\nconst TEST_MAX_SAMPLE = 400\n\ninterface TestModelRow {\n providerId: string\n modelId: string\n prompt?: string\n}\n\nasync function handleTestModel(req: IncomingMessage, res: ServerResponse): Promise<void> {\n let body: TestModelRow\n try {\n body = JSON.parse(await readBody(req))\n } catch {\n sendJson(res, 400, { error: 'Invalid JSON body' })\n return\n }\n const { providerId, modelId, prompt } = body\n if (!providerId || typeof providerId !== 'string') {\n sendJson(res, 400, { error: 'providerId required' })\n return\n }\n if (!modelId || typeof modelId !== 'string') {\n sendJson(res, 400, { error: 'modelId required' })\n return\n }\n\n try {\n const catalog = await fetchModelsWithTimeout()\n const provider = catalog.find(p => p.id === providerId)\n if (!provider) {\n sendJson(res, 200, {\n ok: false,\n providerId,\n modelId,\n format: 'unknown',\n connectMs: null,\n ttftMs: null,\n totalMs: null,\n tokens: 0,\n tokensPerSec: null,\n streamStability: 'n/a',\n sample: '',\n error: `Provider \"${providerId}\" not found in catalog`,\n errorHint: 'Connect or enable the provider in Providers & Keys first.',\n })\n return\n }\n const model = provider.models.find(m => m.id === modelId)\n if (!model) {\n sendJson(res, 200, {\n ok: false,\n providerId,\n modelId,\n format: 'unknown',\n connectMs: null,\n ttftMs: null,\n totalMs: null,\n tokens: 0,\n tokensPerSec: null,\n streamStability: 'n/a',\n sample: '',\n error: `Model \"${modelId}\" not found on provider \"${providerId}\"`,\n errorHint: 'Pick a model that belongs to the selected provider.',\n })\n return\n }\n\n // Resolve credential via authRef (covers API keys + OAuth) like the other flows.\n const registry = loadRegistry()\n const registryProvider = registry.providers.find(p => p.id === providerId)\n let apiKey: string | null = provider.apiKey ?? null\n if (registryProvider?.authRef) {\n apiKey = await resolveProviderCredential(providerId, registryProvider.authRef)\n }\n\n const format =\n model.modelFormat === 'anthropic' || model.modelFormat === 'openai'\n ? model.modelFormat\n : 'unsupported'\n\n const upstreamModelId = model.upstreamModelId || model.id\n const userPrompt = typeof prompt === 'string' && prompt.trim() ? prompt : TEST_DEFAULT_PROMPT\n\n // Build upstream URL + headers per format.\n let upstreamUrl: string\n const headers: Record<string, string> = { 'Content-Type': 'application/json' }\n let requestBody: unknown\n\n if (model.modelFormat === 'anthropic') {\n const base = (model.baseUrl || '').replace(/\\/v1\\/?$/, '')\n if (!base) {\n sendJson(res, 200, failNoEndpoint(providerId, modelId, format))\n return\n }\n upstreamUrl = `${base.replace(/\\/$/, '')}/v1/messages`\n headers['x-api-key'] = apiKey ?? ''\n headers['anthropic-version'] = '2023-06-01'\n requestBody = {\n model: upstreamModelId,\n max_tokens: 256,\n stream: true,\n messages: [{ role: 'user', content: userPrompt }],\n }\n } else if (model.modelFormat === 'openai') {\n const completionsUrl =\n model.completionsUrl ||\n (model.apiBaseUrl ? `${model.apiBaseUrl.replace(/\\/$/, '')}/chat/completions` : '')\n if (!completionsUrl) {\n sendJson(res, 200, failNoEndpoint(providerId, modelId, format))\n return\n }\n upstreamUrl = completionsUrl\n headers['Authorization'] = `Bearer ${apiKey ?? ''}`\n requestBody = {\n model: upstreamModelId,\n stream: true,\n messages: [{ role: 'user', content: userPrompt }],\n }\n } else {\n sendJson(res, 200, {\n ok: false,\n providerId,\n modelId,\n format: 'unsupported',\n connectMs: null,\n ttftMs: null,\n totalMs: null,\n tokens: 0,\n tokensPerSec: null,\n streamStability: 'n/a',\n sample: '',\n error: `Model format \"${model.modelFormat}\" is not directly testable from the UI`,\n errorHint:\n \"This provider routes through anygate's SDK adapter. Use the CLI or Server gateway to exercise it.\",\n })\n return\n }\n\n // Static provider headers (e.g. plan/auth tracking) — never override auth.\n for (const [k, v] of Object.entries(provider.headers ?? {})) {\n if (!(k.toLowerCase() in headers)) headers[k] = v\n }\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), TEST_TIMEOUT_MS)\n const t0 = performance.now()\n let connectMs: number | null = null\n let ttftMs: number | null = null\n let totalMs: number | null = null\n let tokens = 0\n const gaps: number[] = []\n let lastChunkT: number | null = null\n let sample = ''\n\n try {\n const upstream = await fetch(upstreamUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n signal: controller.signal,\n })\n\n // connectMs = time to first response headers (socket + TLS + handshake done).\n connectMs = Math.round(performance.now() - t0)\n\n if (!upstream.ok || !upstream.body) {\n const snippet = upstream.body ? (await upstream.text()).slice(0, 240) : ''\n clearTimeout(timeout)\n sendJson(res, 200, {\n ok: false,\n providerId,\n modelId,\n format,\n connectMs,\n ttftMs: null,\n totalMs: Math.round(performance.now() - t0),\n tokens: 0,\n tokensPerSec: null,\n streamStability: 'n/a',\n sample: snippet,\n error: `Upstream responded ${upstream.status} ${upstream.statusText}`,\n errorHint:\n upstream.status === 401\n ? 'API key missing or rejected — add/refresh the key in Providers & Keys.'\n : upstream.status === 404\n ? 'Endpoint not found — the provider base URL may be wrong.'\n : 'Check the provider key and base URL.',\n })\n return\n }\n\n const reader = upstream.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n const chunk = decoder.decode(value, { stream: true })\n if (!chunk) continue\n\n const now = performance.now()\n const delta = now - t0\n if (ttftMs === null) ttftMs = Math.round(delta)\n if (lastChunkT !== null) gaps.push(now - lastChunkT)\n lastChunkT = now\n\n buffer += chunk\n // Count streamed units + extract a readable sample from SSE / JSON.\n if (model.modelFormat === 'anthropic') {\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const trimmed = line.trim()\n if (!trimmed.startsWith('data:')) continue\n const data = trimmed.slice(5).trim()\n if (data === '[DONE]') continue\n try {\n const evt = JSON.parse(data)\n if (evt.type === 'content_block_delta' && evt.delta?.type === 'text_delta') {\n tokens++\n if (sample.length < TEST_MAX_SAMPLE) sample += evt.delta.text\n }\n } catch {\n /* ignore non-JSON SSE noise */\n }\n }\n } else {\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n for (const line of lines) {\n const trimmed = line.trim()\n if (!trimmed.startsWith('data:')) continue\n const data = trimmed.slice(5).trim()\n if (data === '[DONE]') continue\n try {\n const evt = JSON.parse(data)\n const piece = evt.choices?.[0]?.delta?.content\n if (typeof piece === 'string' && piece) {\n tokens++\n if (sample.length < TEST_MAX_SAMPLE) sample += piece\n }\n } catch {\n /* ignore */\n }\n }\n }\n }\n\n totalMs = Math.round(performance.now() - t0)\n clearTimeout(timeout)\n\n const tokensPerSec =\n tokens > 0 && ttftMs !== null\n ? Math.round((tokens / (totalMs - ttftMs + 1)) * 1000 * 10) / 10\n : null\n const streamStability = computeStability(gaps)\n\n sendJson(res, 200, {\n ok: true,\n providerId,\n modelId,\n format,\n connectMs,\n ttftMs,\n totalMs,\n tokens,\n tokensPerSec,\n streamStability,\n sample: sample.trim(),\n })\n } catch (fetchErr) {\n clearTimeout(timeout)\n const aborted = fetchErr instanceof Error && fetchErr.name === 'AbortError'\n sendJson(res, 200, {\n ok: false,\n providerId,\n modelId,\n format,\n connectMs,\n ttftMs,\n totalMs: Math.round(performance.now() - t0),\n tokens,\n tokensPerSec: null,\n streamStability: gaps.length ? computeStability(gaps) : 'n/a',\n sample,\n error: aborted ? `Request timed out after ${TEST_TIMEOUT_MS / 1000}s` : String(fetchErr),\n errorHint: aborted\n ? 'The endpoint did not respond in time — it may be slow, down, or the URL is unreachable.'\n : 'Network-level failure reaching the provider endpoint.',\n })\n }\n } catch (err) {\n sendJson(res, 500, {\n ok: false,\n providerId,\n modelId,\n format: 'unknown',\n connectMs: null,\n ttftMs: null,\n totalMs: null,\n tokens: 0,\n tokensPerSec: null,\n streamStability: 'n/a',\n sample: '',\n error: String(err),\n })\n }\n}\n\nfunction failNoEndpoint(providerId: string, modelId: string, format: string) {\n return {\n ok: false,\n providerId,\n modelId,\n format,\n connectMs: null,\n ttftMs: null,\n totalMs: null,\n tokens: 0,\n tokensPerSec: null,\n streamStability: 'n/a' as const,\n sample: '',\n error: 'No usable upstream endpoint for this model',\n errorHint:\n 'The provider is missing a base URL / completions URL. Re-add or refresh it in Providers & Keys.',\n }\n}\n\nfunction computeStability(gaps: number[]): 'steady' | 'intermittent' {\n if (gaps.length < 3) return 'steady'\n const mean = gaps.reduce((a, b) => a + b, 0) / gaps.length\n if (mean === 0) return 'steady'\n const variance = gaps.reduce((a, b) => a + (b - mean) ** 2, 0) / gaps.length\n const cv = Math.sqrt(variance) / mean\n return cv > 1.2 ? 'intermittent' : 'steady'\n}\n\nasync function handlePostKeys(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req))\n const { providerId, key } = body\n if (!providerId || typeof providerId !== 'string') {\n sendJson(res, 400, { error: 'providerId required' })\n return\n }\n if (!key || typeof key !== 'string' || key.trim().length === 0) {\n sendJson(res, 400, { error: 'key must be a non-empty string' })\n return\n }\n const authRef = `keyring:provider:${providerId}`\n const saved = await saveProviderCredential(authRef, key.trim())\n if (saved) {\n sendJson(res, 200, { ok: true })\n } else {\n sendJson(res, 500, { error: 'Keychain unavailable — key not saved' })\n }\n } catch (err) {\n sendJson(res, 400, { error: String(err) })\n }\n}\n\nconst CUSTOM_TEMPLATES = [\n {\n id: '__custom_openai__',\n name: 'Custom OpenAI-compatible',\n signupUrl: null,\n authType: 'api',\n custom: true,\n },\n {\n id: '__custom_anthropic__',\n name: 'Custom Anthropic-compatible',\n signupUrl: null,\n authType: 'api',\n custom: true,\n },\n] as const\n\nfunction handleGetTemplates(res: ServerResponse): void {\n const registry = loadRegistry()\n const configured = new Set(registry.providers.map(p => p.id))\n\n // Only offer providers the user has not configured yet. listSupportedTemplates()\n // returns the whole catalog, so using it here listed providers that were already\n // set up (with a working key) alongside genuinely new ones. listAddableTemplates\n // applies the same exclusion the CLI's add flow uses, including the zen/go\n // aliasing for opencode-cloud.\n const apiTemplates = listAddableTemplates(configured).map(t => ({\n id: t.id,\n name: t.name,\n signupUrl: t.signupUrl ?? null,\n signupNote: t.signupNote ?? null,\n authType: t.authType,\n anonymousFreeModels: t.anonymousFreeModels ?? false,\n urlPrompt: t.urlPrompt ?? null,\n defaultBaseUrl: t.defaultBaseUrl ?? null,\n apiKeyOptional: t.apiKeyOptional ?? false,\n custom: false,\n }))\n\n const oauthTemplates = listVisibleOAuthTemplates(configured).map(t => ({\n id: t.id,\n name: t.name,\n signupUrl: t.signupUrl ?? null,\n authType: t.authType,\n subscriptionRisk: t.subscriptionRisk ?? false,\n custom: false,\n }))\n\n sendJson(res, 200, { templates: [...apiTemplates, ...oauthTemplates, ...CUSTOM_TEMPLATES] })\n}\n\nasync function handleAddCustomProvider(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req)) as {\n kind?: string\n displayName?: string\n baseUrl?: string\n apiKey?: string\n headers?: Record<string, string>\n }\n const { kind, displayName, baseUrl, apiKey = '', headers } = body\n if (kind !== 'openai' && kind !== 'anthropic') {\n sendJson(res, 400, { error: 'kind must be \"openai\" or \"anthropic\"' })\n return\n }\n if (!displayName?.trim()) {\n sendJson(res, 400, { error: 'displayName required' })\n return\n }\n if (!baseUrl?.trim()) {\n sendJson(res, 400, { error: 'baseUrl required' })\n return\n }\n const result = await addCustomEndpointProvider({\n kind: kind as CustomEndpointKind,\n displayName: displayName.trim(),\n baseUrl: baseUrl.trim(),\n apiKey: apiKey.trim(),\n allowInsecureLocal: true,\n headers: headers && Object.keys(headers).length > 0 ? headers : undefined,\n })\n if (result.added) {\n sendJson(res, 200, { ok: true, name: displayName.trim(), count: result.modelCount ?? 0 })\n } else {\n sendJson(res, 200, { ok: false, error: result.error, hint: result.hint })\n }\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleAddProvider(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req))\n const { templateId, key, baseUrl } = body\n if (!templateId || typeof templateId !== 'string') {\n sendJson(res, 400, { error: 'templateId required' })\n return\n }\n const { getTemplateById } = await import('../registry/templates/provider-templates.js')\n const template = getTemplateById(templateId)\n if (!template) {\n sendJson(res, 404, { error: `Template '${templateId}' not found` })\n return\n }\n if (template.authType === 'oauth') {\n if (templateId === 'claude-code') {\n sendJson(res, 400, {\n error: 'Claude Code OAuth must be completed in the terminal: anygate providers auth claude-code',\n })\n return\n }\n\n const host = (req.headers.host as string | undefined) ?? '127.0.0.1'\n const sessionId = randomUUID()\n\n if (templateId === 'xai-oauth') {\n const device = await requestXaiDeviceCode()\n const url = device.verification_uri_complete ?? device.verification_uri\n const session: OAuthSession = {\n status: 'pending',\n url,\n userCode: device.user_code,\n providerId: templateId,\n }\n oauthSessions.set(sessionId, session)\n\n pollXaiDeviceCodeToken(device)\n .then(async tokens => {\n await saveNativeOAuthCredential(templateId, tokens)\n await refreshOAuthProviderModels(templateId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { oauth: true, sessionId, url, userCode: device.user_code })\n return\n }\n\n if (templateId === 'github-copilot') {\n const device = await requestGithubDeviceCode()\n const url = device.verification_uri\n const session: OAuthSession = {\n status: 'pending',\n url,\n userCode: device.user_code,\n providerId: templateId,\n }\n oauthSessions.set(sessionId, session)\n\n pollGithubDeviceCodeToken(device)\n .then(async tokens => {\n await saveNativeOAuthCredential(templateId, tokens)\n await refreshOAuthProviderModels(templateId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { oauth: true, sessionId, url, userCode: device.user_code })\n return\n }\n\n if (templateId === 'antigravity') {\n const redirectUri = guiCallbackRedirectUri(host)\n const pkce = await buildAntigravityAuthUrl(redirectUri)\n const { authUrl, codeVerifier, oauthState } = pkce\n const session: OAuthSession = {\n status: 'pending',\n url: authUrl,\n providerId: templateId,\n codeVerifier,\n oauthState,\n }\n oauthSessions.set(sessionId, session)\n\n const codePromise = new Promise<string>((resolve, reject) => {\n session.codeResolver = resolve\n session.errorRejecter = (err: string) => reject(err)\n setTimeout(() => reject(new Error('OAuth timeout — sign-in not completed')), 10 * 60 * 1000)\n })\n oauthSessions.set(sessionId, session)\n\n codePromise\n .then(async code => {\n const result = await completeAntigravityExchange(code, codeVerifier, redirectUri)\n const tokens = result.tokens\n const accountId = result.userInfo.email\n const providerData: Record<string, unknown> = {}\n if (result.projectId) providerData.projectId = result.projectId\n if (result.tierId) providerData.tier = result.tierId\n\n await saveNativeOAuthCredential(templateId, tokens, accountId, providerData)\n await refreshOAuthProviderModels(templateId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { oauth: true, sessionId, authUrl, pkce: true })\n return\n }\n\n // OpenAI (ChatGPT) browser-based OAuth flow (authorization code + PKCE)\n // This uses the standard browser-based OAuth flow instead of device code polling,\n // so users don't need to enable device code authorization in ChatGPT Security Settings.\n if (templateId === 'openai-oauth') {\n const redirectUri = `${ISSUER}/deviceauth/callback`\n const { authUrl, codeVerifier, oauthState } = await buildOpenAiBrowserAuthUrl(redirectUri)\n\n // Start callback server to receive the OAuth redirect\n const server = await startCallbackServer()\n\n let session: OAuthSession | undefined\n\n try {\n session = {\n status: 'pending',\n url: authUrl,\n providerId: templateId,\n codeVerifier,\n oauthState,\n }\n oauthSessions.set(sessionId, session)\n\n // Open the browser (ignored - we wait for callback server instead)\n ;(open(authUrl) as any)?.catch(() => {})\n\n // Wait for the callback with authorization code\n const { code } = await server.waitForCallback()\n\n if (!code) {\n throw new Error('No authorization code received from callback')\n }\n\n // Exchange authorization code for tokens\n const { tokens, accountId } = await exchangeOpenAiBrowserToken(code, codeVerifier)\n\n // Save credentials and refresh models\n await saveNativeOAuthCredential(templateId, tokens, accountId)\n await refreshOAuthProviderModels(templateId)\n oauthSessions.set(sessionId, { ...session!, status: 'done' })\n } catch (err) {\n oauthSessions.set(sessionId, { ...session ?? {} as OAuthSession, status: 'error', error: String(err) })\n } finally {\n server.close()\n }\n\n sendJson(res, 200, { oauth: true, sessionId, url: authUrl, pkce: true })\n return\n }\n\n const device = await requestOpenAiDeviceCode()\n const url = openAiDeviceCodeUrl()\n const session: OAuthSession = { status: 'pending', url, userCode: device.user_code, providerId: templateId }\n oauthSessions.set(sessionId, session)\n\n pollOpenAiDeviceCodeToken(device)\n .then(async ({ tokens, accountId }) => {\n await saveNativeOAuthCredential(templateId, tokens, accountId)\n await refreshOAuthProviderModels(templateId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { oauth: true, sessionId, url, userCode: device.user_code })\n return\n }\n const rawKey = typeof key === 'string' ? key.trim() : ''\n if (!rawKey && !template.anonymousFreeModels && !template.apiKeyOptional) {\n sendJson(res, 400, { error: 'key must be a non-empty string' })\n return\n }\n // Keyless self-hosted providers (Ollama, LM Studio) are stored with no\n // credential at all. This used to persist template.id as a stand-in key to\n // survive materializeOne's blank-key guard; that guard now honours\n // apiKeyOptional, so the fake credential is unnecessary and misleading.\n const keyText = rawKey\n\n let baseUrlOverride: string | undefined\n if (template.urlPrompt) {\n // Fall back to the template default so a user on the standard port can\n // submit without retyping the URL the form already shows.\n baseUrlOverride =\n (typeof baseUrl === 'string' ? baseUrl.trim() : '') || (template.defaultBaseUrl ?? '')\n if (!baseUrlOverride) {\n sendJson(res, 400, { error: 'baseUrl required' })\n return\n }\n const usesHttp = /^http:\\/\\//i.test(baseUrlOverride)\n const valid = await validateCustomEndpointUrl(baseUrlOverride, {\n allowInsecureLocal: usesHttp,\n })\n if (!valid.ok) {\n sendJson(res, 400, { error: valid.error ?? 'Invalid URL', hint: valid.hint })\n return\n }\n }\n\n const result: AddTemplateResult = await addProviderFromTemplate(template, keyText, {\n baseUrl: baseUrlOverride,\n })\n if (result.added) {\n sendJson(res, 200, { ok: true, name: template.name, count: result.modelCount ?? 0 })\n } else {\n sendJson(res, 200, { ok: false, error: result.error, hint: result.hint })\n }\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleRefreshAll(res: ServerResponse): Promise<void> {\n try {\n const result = await refreshAllProviderModels(async provider => {\n if (!provider.authRef) return null\n return resolveProviderCredential(provider.id, provider.authRef)\n })\n // Return per-provider summary: id, name, ok, count\n const summary = result.refreshed.map(r => {\n // OAuth providers can't refresh model lists via the standard API endpoint —\n // the token is for user sessions, not model discovery. This is expected, not broken.\n const isOAuthExpected = !r.ok && !r.skipped && r.reason?.includes('OAuth token')\n return {\n id: r.id,\n name: r.name,\n ok: r.ok || isOAuthExpected,\n count: r.modelCount ?? r.previousModelCount ?? 0,\n skipped: r.skipped ?? isOAuthExpected,\n oauthWarning: isOAuthExpected,\n reason: r.reason,\n }\n })\n sendJson(res, 200, {\n ok: true,\n providers: summary,\n total: summary.reduce((n, p) => n + p.count, 0),\n })\n } catch (err) {\n sendJson(res, 500, { ok: false, error: String(err) })\n }\n}\n\nasync function handleProviderRefresh(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req))\n const { providerId } = body\n if (!providerId || typeof providerId !== 'string') {\n sendJson(res, 400, { error: 'providerId required' })\n return\n }\n const registry = loadRegistry()\n const registryProvider = registry.providers.find(p => p.id === providerId)\n if (!registryProvider) {\n sendJson(res, 200, { ok: false, error: 'Provider not found in registry' })\n return\n }\n // Resolve credential via authRef (covers both API keys and OAuth tokens)\n const apiKey = await resolveProviderCredential(providerId, registryProvider.authRef)\n // Use the same refresh path as `anygate providers refresh-models` so counts match CLI\n const result = await refreshProviderModels(providerId, apiKey, registry)\n if (result.ok) {\n sendJson(res, 200, { ok: true, count: result.modelCount ?? result.previousModelCount ?? 0 })\n } else {\n sendJson(res, 200, { ok: false, error: result.reason ?? 'Refresh failed' })\n }\n } catch (err) {\n sendJson(res, 200, { ok: false, error: String(err) })\n }\n}\n\nasync function handleDeleteProvider(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req)) as { providerId?: string }\n const { providerId } = body\n if (!providerId || typeof providerId !== 'string') {\n sendJson(res, 400, { error: 'providerId required' })\n return\n }\n const result = await removeProviderFromRegistry(providerId)\n if (result.removed) {\n sendJson(res, 200, { ok: true, name: result.name })\n } else {\n sendJson(res, 200, { ok: false, error: result.error ?? 'Provider not found' })\n }\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nconst DEVICE_CODE_PROVIDER_IDS = new Set(['xai-oauth', 'openai-oauth', 'github-copilot'])\nconst PKCE_PROVIDER_IDS = new Set(['claude-code', 'antigravity'])\nconst NATIVE_OAUTH_PROVIDER_IDS = new Set([...DEVICE_CODE_PROVIDER_IDS, ...PKCE_PROVIDER_IDS])\n\nasync function refreshOAuthProviderModels(providerId: string): Promise<void> {\n const registry = loadRegistry()\n const entry = registry.providers.find(p => p.id === providerId)\n if (!entry) return\n const apiKey = await resolveProviderCredential(providerId, entry.authRef)\n await refreshProviderModels(providerId, apiKey, registry)\n}\n\nasync function handleOAuthStart(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req)) as { providerId?: string }\n const { providerId } = body\n if (!providerId || !NATIVE_OAUTH_PROVIDER_IDS.has(providerId)) {\n sendJson(res, 400, {\n error: `providerId must be one of: ${[...NATIVE_OAUTH_PROVIDER_IDS].join(', ')}`,\n })\n return\n }\n\n const sessionId = randomUUID()\n\n if (providerId === 'xai-oauth') {\n let session: OAuthSession = { status: 'error', url: '', providerId }\n oauthSessions.set(sessionId, session)\n\n try {\n const device = await requestXaiDeviceCode()\n const url = device.verification_uri_complete ?? device.verification_uri\n session = { status: 'pending', url, userCode: device.user_code, providerId }\n oauthSessions.set(sessionId, session)\n\n pollXaiDeviceCodeToken(device)\n .then(async tokens => {\n await saveNativeOAuthCredential(providerId, tokens)\n await refreshOAuthProviderModels(providerId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { sessionId, url, userCode: device.user_code })\n } catch (err) {\n oauthSessions.set(sessionId, { ...session, error: String(err) })\n sendJson(res, 500, { error: String(err) })\n }\n return\n }\n\n if (providerId === 'github-copilot') {\n let session: OAuthSession = { status: 'error', url: '', providerId }\n oauthSessions.set(sessionId, session)\n\n try {\n const device = await requestGithubDeviceCode()\n const url = device.verification_uri\n session = { status: 'pending', url, userCode: device.user_code, providerId }\n oauthSessions.set(sessionId, session)\n\n pollGithubDeviceCodeToken(device)\n .then(async tokens => {\n await saveNativeOAuthCredential(providerId, tokens)\n await refreshOAuthProviderModels(providerId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { sessionId, url, userCode: device.user_code })\n } catch (err) {\n oauthSessions.set(sessionId, { ...session, error: String(err) })\n sendJson(res, 500, { error: String(err) })\n }\n return\n }\n\n if (PKCE_PROVIDER_IDS.has(providerId)) {\n if (providerId === 'claude-code') {\n sendJson(res, 400, {\n error:\n 'Claude Code OAuth must be completed in the terminal: anygate providers auth claude-code',\n })\n return\n }\n\n let session: OAuthSession = { status: 'error', url: '', providerId }\n oauthSessions.set(sessionId, session)\n\n try {\n // PKCE / browser-redirect flow (claude-code, future: antigravity).\n const host = (req.headers.host as string | undefined) ?? '127.0.0.1'\n const redirectUri = guiCallbackRedirectUri(host)\n\n let pkce: Awaited<ReturnType<typeof buildAntigravityAuthUrl>>\n if (providerId === 'antigravity') {\n pkce = await buildAntigravityAuthUrl(redirectUri)\n } else {\n sendJson(res, 400, { error: `PKCE flow for \"${providerId}\" not yet implemented` })\n return\n }\n\n const { authUrl, codeVerifier, oauthState } = pkce\n session = { status: 'pending', url: authUrl, providerId, codeVerifier, oauthState }\n oauthSessions.set(sessionId, session)\n\n // The callback route will call session.codeResolver when the code arrives.\n const codePromise = new Promise<string>((resolve, reject) => {\n session.codeResolver = resolve\n session.errorRejecter = (err: string) => reject(new Error(err))\n setTimeout(() => reject(new Error('OAuth timeout — sign-in not completed')), 10 * 60 * 1000)\n })\n oauthSessions.set(sessionId, session) // re-set with resolvers attached\n\n codePromise\n .then(async code => {\n let providerData: Record<string, unknown> = {}\n let accountId: string | undefined\n let tokens: import('../auth/types.js').OAuthTokenResponse\n\n if (providerId === 'antigravity') {\n const result = await completeAntigravityExchange(code, codeVerifier, redirectUri)\n tokens = result.tokens\n accountId = result.userInfo.email\n if (result.projectId) providerData.projectId = result.projectId\n if (result.tierId) providerData.tier = result.tierId\n } else {\n throw new Error(`Unknown PKCE provider: ${providerId}`)\n }\n\n await saveNativeOAuthCredential(providerId, tokens, accountId, providerData)\n\n await refreshOAuthProviderModels(providerId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { sessionId, authUrl, pkce: true })\n } catch (err) {\n oauthSessions.set(sessionId, { ...session, error: String(err) })\n sendJson(res, 500, { error: String(err) })\n }\n return\n }\n\n // openai-oauth\n let session: OAuthSession = { status: 'error', url: '', providerId }\n oauthSessions.set(sessionId, session)\n\n try {\n const device = await requestOpenAiDeviceCode()\n const url = openAiDeviceCodeUrl()\n session = { status: 'pending', url, userCode: device.user_code, providerId }\n oauthSessions.set(sessionId, session)\n\n pollOpenAiDeviceCodeToken(device)\n .then(async ({ tokens, accountId }) => {\n await saveNativeOAuthCredential(providerId, tokens, accountId)\n await refreshOAuthProviderModels(providerId)\n oauthSessions.set(sessionId, { ...session, status: 'done' })\n })\n .catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) })\n })\n\n sendJson(res, 200, { sessionId, url, userCode: device.user_code })\n } catch (err) {\n oauthSessions.set(sessionId, { ...session, error: String(err) })\n sendJson(res, 500, { error: String(err) })\n }\n } catch (err) {\n // Safety net for any unexpected error in provider validation etc.\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nfunction handleOAuthStatus(req: IncomingMessage, res: ServerResponse): void {\n const searchParams = new URL(req.url ?? '', 'http://localhost').searchParams\n const sessionId = searchParams.get('sessionId') ?? ''\n const session = oauthSessions.get(sessionId)\n if (!session) {\n sendJson(res, 404, { error: 'Session not found or expired' })\n return\n }\n sendJson(res, 200, { status: session.status, error: session.error })\n if (session.status !== 'pending') oauthSessions.delete(sessionId)\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n}\n\nfunction callbackPage(type: 'success' | 'error', message: string): string {\n const icon = type === 'success' ? '&#10003;' : '&#10007;'\n const color = type === 'success' ? '#22c55e' : '#ef4444'\n const title = type === 'success' ? 'Authentication successful' : 'Authentication failed'\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>${title}</title></head>\n<body style=\"font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0\">\n<div style=\"text-align:center;padding:2rem;background:#fff;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.1);max-width:400px\">\n<div style=\"color:${color};font-size:2.5rem\">${icon}</div>\n<h1 style=\"margin:.5rem 0\">${title}</h1>\n<p style=\"color:#666\">${escapeHtml(message)}</p>\n</div></body></html>`\n}\n\nfunction handleOAuthCallback(req: IncomingMessage, res: ServerResponse): void {\n const sp = new URL(req.url ?? '', 'http://localhost').searchParams\n const code = sp.get('code') ?? ''\n const state = sp.get('state') ?? ''\n const error = sp.get('error') ?? ''\n\n let matchedSession: OAuthSession | undefined\n for (const session of oauthSessions.values()) {\n if (session.oauthState === state) {\n matchedSession = session\n break\n }\n }\n\n if (!matchedSession) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(callbackPage('error', 'Unknown or expired OAuth session. Please try signing in again.'))\n return\n }\n\n if (error) {\n matchedSession.errorRejecter?.(error)\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(callbackPage('error', `Authorization denied: ${error}`))\n return\n }\n\n if (!code) {\n matchedSession.errorRejecter?.('No authorization code received')\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(callbackPage('error', 'No authorization code received. Please try again.'))\n return\n }\n\n matchedSession.codeResolver?.(code)\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(callbackPage('success', 'You can close this tab and return to anygate.'))\n}\n\nfunction handleGetApps(res: ServerResponse): void {\n try {\n const apps = getSupportedApps()\n sendJson(res, 200, { apps, recentLaunchFolders: loadPreferences().recentLaunchFolders ?? [] })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nconst AGY_APP_IDS = new Set(['antigravity', 'agy', 'antigravity-ide'])\n\nasync function handleLaunchApp(\n req: IncomingMessage,\n res: ServerResponse,\n opts: UiApiOptions\n): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req))\n const { appId, favorites, favoritesCatalog, allModels, cwd } = body\n let { providerId, modelId } = body as { providerId?: string; modelId?: string }\n if (!appId) {\n sendJson(res, 400, { error: 'Missing appId' })\n return\n }\n if (!getSupportedApp(appId)) {\n sendJson(res, 400, { error: `Unknown app: ${appId}` })\n return\n }\n\n const { installed, path } = detectApp(appId)\n if (!installed || !path) {\n sendJson(res, 400, { error: `App ${appId} is not installed on this system.` })\n return\n }\n\n // allModels (provider catalog mode): requires providerId, no modelId needed\n if (allModels && !providerId) {\n sendJson(res, 400, { error: 'providerId is required when allModels is true.' })\n return\n }\n if (!allModels && !favorites && (providerId || modelId) && (!providerId || !modelId)) {\n sendJson(res, 400, {\n error: 'Both providerId and modelId are required to launch a specific anygate model.',\n })\n return\n }\n\n const fullCatalog = Boolean(favoritesCatalog)\n if (fullCatalog) {\n providerId = undefined\n modelId = undefined\n } else if (allModels) {\n modelId = undefined\n } else if (favorites && !providerId && !modelId) {\n const prefs = loadPreferences()\n const favList = AGY_APP_IDS.has(appId)\n ? (prefs.antigravityCliFavoriteModels ?? [])\n : (prefs.favoriteModels ?? [])\n if (favList.length > 0) {\n providerId = favList[0]!.providerId\n modelId = favList[0]!.modelId\n }\n }\n\n const launchFolder = typeof cwd === 'string' && cwd.trim() ? cwd.trim() : undefined\n if (launchFolder) {\n try {\n if (!statSync(launchFolder).isDirectory()) {\n sendJson(res, 400, { error: 'Launch folder must be a directory.' })\n return\n }\n } catch {\n sendJson(res, 400, { error: 'Launch folder does not exist.' })\n return\n }\n recordLaunchFolder(launchFolder)\n }\n\n const launchCmd = getGatewayLaunchCommand(appId, {\n providerId,\n modelId,\n allModels: Boolean(allModels) && Boolean(providerId),\n favoritesCatalog: fullCatalog,\n cwd: launchFolder,\n trace: opts.trace,\n })\n traceUi(\n opts,\n `launch app=${appId} provider=${providerId ?? ''} model=${modelId ?? ''} allModels=${Boolean(allModels)} favorites=${Boolean(favorites)} catalog=${fullCatalog} cwd=${launchFolder ?? ''} command=${launchCmd}`\n )\n\n // Execute command asynchronously to open the terminal window detached\n exec(launchCmd, err => {\n if (err) {\n traceUi(opts, `launch error app=${appId} error=${err.message}`)\n console.error('Failed to spawn native terminal window:', err)\n }\n })\n\n sendJson(res, 200, { ok: true, command: launchCmd })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleSetAppPath(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req))\n const { appId, path } = body\n if (!appId || typeof appId !== 'string') {\n sendJson(res, 400, { error: 'Missing appId' })\n return\n }\n\n if (path !== null && (typeof path !== 'string' || !path.trim())) {\n sendJson(res, 400, {\n error: 'path must be a non-empty string, or null to clear the override.',\n })\n return\n }\n\n const trimmed = typeof path === 'string' ? path.trim() : null\n if (trimmed && !existsSync(trimmed)) {\n sendJson(res, 400, { error: 'That path does not exist.' })\n return\n }\n\n setAppPathOverride(appId, trimmed)\n sendJson(res, 200, { ok: true, apps: getSupportedApps() })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleGetServerStatus(res: ServerResponse): Promise<void> {\n try {\n sendJson(res, 200, await getServerStatus())\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleGetServerProviders(res: ServerResponse): Promise<void> {\n try {\n const catalog = await fetchModelsWithTimeout({ agent: 'server' })\n sendJson(res, 200, { providers: providerOptionsFromCatalog(catalog) })\n } catch (err) {\n sendCatalogFetchError(res, err, 'Provider fetch')\n }\n}\n\nasync function handleStartServer(\n req: IncomingMessage,\n res: ServerResponse,\n opts: UiApiOptions\n): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req)) as Partial<ServerStartRequest>\n if (typeof body.favoritesOnly !== 'boolean') {\n sendJson(res, 400, { error: 'favoritesOnly must be a boolean' })\n return\n }\n if (typeof body.maskGatewayIds !== 'boolean') {\n sendJson(res, 400, { error: 'maskGatewayIds must be a boolean' })\n return\n }\n if (body.listenMode !== 'local' && body.listenMode !== 'network') {\n sendJson(res, 400, { error: 'listenMode must be \"local\" or \"network\"' })\n return\n }\n const request: ServerStartRequest = {\n favoritesOnly: body.favoritesOnly,\n freeModelsOnly: Boolean(body.freeModelsOnly),\n exposedProviders: Array.isArray(body.exposedProviders) ? body.exposedProviders : null,\n maskGatewayIds: body.maskGatewayIds,\n listenMode: body.listenMode,\n passwordMode: body.passwordMode === 'saved' ? 'saved' : 'new',\n password: typeof body.password === 'string' ? body.password : undefined,\n savePassword: Boolean(body.savePassword),\n }\n const result = await startGatewayServer(request)\n if (result.ok) {\n notifyServerLifecycle(opts, {\n type: 'started',\n listenMode: request.listenMode,\n modelCount: result.status.models?.length ?? 0,\n })\n }\n sendJson(res, 200, result)\n } catch (err) {\n sendJson(res, 500, { ok: false, error: String(err) })\n }\n}\n\nasync function handleStopServer(res: ServerResponse, opts: UiApiOptions): Promise<void> {\n try {\n const result = await stopGatewayServer()\n if (result.stopped) notifyServerLifecycle(opts, { type: 'stopped' })\n sendJson(res, 200, result)\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\n/**\n * GET /api/analytics?range=all|30d|7d\n * Aggregates the local-only usage log into the DashboardAnalytics shape the UI\n * already consumes (see ui/src/lib/api/analytics.ts). Defaults to 'all'.\n */\nfunction handleGetAnalytics(res: ServerResponse, req: IncomingMessage): void {\n try {\n const sp = new URL(req.url ?? '', 'http://localhost').searchParams\n const rangeParam = sp.get('range')\n const range: RangeId =\n rangeParam === '7d' || rangeParam === '30d' || rangeParam === 'all' ? rangeParam : 'all'\n sendJson(res, 200, aggregateAnalytics(range))\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n\nasync function handleBrowseFolder(res: ServerResponse): Promise<void> {\n try {\n let resultPath = ''\n const isMac = process.platform === 'darwin'\n const isWindows = process.platform === 'win32'\n\n if (isMac) {\n const script = 'POSIX path of (choose folder with prompt \"Select launch folder:\")'\n try {\n const { stdout } = await execAsync(`osascript -e '${script}'`)\n resultPath = stdout.trim()\n } catch (err: any) {\n if (\n err.code === 1 ||\n String(err.stderr).includes('-128') ||\n String(err.stdout).includes('-128')\n ) {\n sendJson(res, 200, { ok: true, canceled: true })\n return\n }\n throw err\n }\n } else if (isWindows) {\n // The try/catch + exit 1 is load-bearing: without it PowerShell reports\n // dialog failures (e.g. \"not running in UserInteractive mode\" when the\n // UI server was started from a non-interactive session like SSH) as\n // non-terminating errors and still exits 0 with empty stdout, which\n // looks identical to the user canceling.\n //\n // The owner form must be Show()n (invisible: opacity 0, 1x1, no\n // border/taskbar) — WinForms only applies TopMost to the native handle\n // when the form is actually shown, and without a shown TopMost owner\n // the dialog opens at the bottom of the z-order, behind the browser,\n // with no taskbar button: it exists but the user never sees it.\n const psCommand = [\n 'try {',\n ' Add-Type -AssemblyName System.Windows.Forms',\n ' $f = New-Object System.Windows.Forms.FolderBrowserDialog',\n ' $f.Description = \"Select launch folder\"',\n ' $owner = New-Object System.Windows.Forms.Form',\n ' $owner.TopMost = $true',\n ' $owner.ShowInTaskbar = $false',\n ' $owner.FormBorderStyle = \"None\"',\n ' $owner.Opacity = 0',\n ' $owner.Width = 1',\n ' $owner.Height = 1',\n ' $owner.StartPosition = \"CenterScreen\"',\n ' $owner.Show()',\n ' $owner.Activate()',\n ' if ($f.ShowDialog($owner) -eq \"OK\") { $f.SelectedPath }',\n ' $owner.Close()',\n '} catch {',\n ' [Console]::Error.WriteLine($_.Exception.Message)',\n ' exit 1',\n '}',\n ].join('\\n')\n try {\n // -Sta is required: System.Windows.Forms dialogs throw\n // ThreadStateException under PowerShell's default MTA apartment state.\n // -EncodedCommand sidesteps cmd.exe quoting: -Command \"...\" mangled\n // the script (its newlines were never actually stripped).\n const encoded = Buffer.from(psCommand, 'utf16le').toString('base64')\n const { stdout } = await execAsync(`powershell -NoProfile -Sta -EncodedCommand ${encoded}`)\n resultPath = stdout.trim()\n } catch (err) {\n sendJson(res, 500, {\n error: `Failed to open folder picker: ${err instanceof Error ? err.message : String(err)}`,\n })\n return\n }\n } else {\n try {\n const { stdout } = await execAsync(\n 'zenity --file-selection --directory --title=\"Select launch folder\"'\n )\n resultPath = stdout.trim()\n } catch {\n try {\n const { stdout } = await execAsync('kdialog --getexistingdirectory .')\n resultPath = stdout.trim()\n } catch {\n sendJson(res, 500, { error: 'No GUI folder picker available on this platform' })\n return\n }\n }\n }\n\n if (!resultPath) {\n sendJson(res, 200, { ok: true, canceled: true })\n return\n }\n\n sendJson(res, 200, { ok: true, path: resultPath })\n } catch (err) {\n sendJson(res, 500, { error: String(err) })\n }\n}\n","// In-process lifecycle for the `anygate server` gateway, launched from the web UI.\n// Runs inside the same Node process as `anygate ui` — no child process, no PID file.\n// Stops automatically when the UI process exits, same as closing a terminal running\n// `anygate server` with Ctrl+C.\n\nimport { BACKENDS, MAX_MODEL_CATALOG } from '../config/constants.js'\nimport {\n getSavedServerPassword,\n getServerExposedProviders,\n getServerFavoritesOnly,\n getServerFreeModelsOnly,\n getServerListenMode,\n getServerMaskGatewayIds,\n loadPreferences,\n setSavedServerPassword,\n setServerExposedProviders,\n setServerFavoritesOnly,\n setServerFreeModelsOnly,\n setServerListenMode,\n setServerMaskGatewayIds,\n} from '../storage/config.js'\nimport type { FavoriteModel } from '../types/index.js'\nimport { startServer, type ServerHandle } from '../gateway/server/router.js'\nimport {\n buildDedupedModelRows,\n createGatewayModelCatalog,\n gatewayProviderLabel,\n type GatewayModelOptions,\n type ServerModelInfo,\n} from '../gateway/server/models.js'\nimport {\n filterServerModelsByFavorites,\n filterServerModelsByFreeStatus,\n filterServerModelsByProviders,\n summarizeServerProviders,\n} from '../gateway/server/catalog-filter.js'\nimport {\n getLocalIps,\n loadServerModels,\n resolveServerUpstreamApiKey,\n} from '../gateway/server/server.js'\n\nexport type ServerListenMode = 'local' | 'network'\n\nexport interface ServerStartRequest {\n favoritesOnly: boolean\n freeModelsOnly: boolean\n exposedProviders: string[] | null\n maskGatewayIds: boolean\n listenMode: ServerListenMode\n /** Only relevant when listenMode is 'network'. */\n passwordMode?: 'saved' | 'new'\n password?: string\n savePassword?: boolean\n}\n\ntype RunningConfig = Omit<ServerStartRequest, 'passwordMode' | 'password' | 'savePassword'>\n\ninterface RunningState {\n handle: ServerHandle\n config: RunningConfig\n serverPassword: string | null\n /** Derived once from `models` at start time — the exposed model set never changes while running. */\n providerSummary: string\n modelRows: ServerModelRow[]\n}\n\nexport interface ServerModelRow {\n providerLabel: string\n name: string\n anthropicId: string\n openaiId: string\n}\n\nexport interface ServerSavedConfig {\n favoritesOnly: boolean\n freeModelsOnly: boolean\n exposedProviders: string[] | null\n maskGatewayIds: boolean\n listenMode: ServerListenMode\n hasSavedPassword: boolean\n}\n\nexport interface ServerNetworkUrl {\n name: string\n anthropicUrl: string\n openaiUrl: string\n}\n\nexport interface ServerStatusPayload {\n running: boolean\n saved: ServerSavedConfig\n listenMode?: ServerListenMode\n anthropicUrl?: string\n openaiUrl?: string\n networkUrls?: ServerNetworkUrl[]\n apiKey?: string\n exposedProviders?: string[] | null\n favoritesOnly?: boolean\n freeModelsOnly?: boolean\n maskGatewayIds?: boolean\n providerSummary?: string\n models?: ServerModelRow[]\n}\n\nlet running: RunningState | null = null\nlet startInFlight: Promise<\n { ok: true; status: ServerStatusPayload } | { ok: false; error: string }\n> | null = null\n\n// The OS keychain read behind getSavedServerPassword() is a blocking native call, and this\n// flag is polled every few seconds from the UI — cache it briefly so the poll loop doesn't\n// hit the keychain on every tick. Refreshed immediately below whenever we save a password.\nconst SAVED_PASSWORD_CACHE_TTL_MS = 30_000\nlet hasSavedPasswordCache: { value: boolean; expiresAt: number } | null = null\n\nasync function hasSavedPasswordCached(): Promise<boolean> {\n const now = Date.now()\n if (hasSavedPasswordCache && hasSavedPasswordCache.expiresAt > now)\n return hasSavedPasswordCache.value\n const value = Boolean(await getSavedServerPassword())\n hasSavedPasswordCache = { value, expiresAt: now + SAVED_PASSWORD_CACHE_TTL_MS }\n return value\n}\n\nfunction buildModelRows(\n models: ServerModelInfo[],\n gateway?: GatewayModelOptions\n): ServerModelRow[] {\n const groups = new Map<string, ServerModelInfo[]>()\n for (const model of models) {\n const label = gatewayProviderLabel(model)\n const list = groups.get(label)\n if (list) list.push(model)\n else groups.set(label, [model])\n }\n\n const rows: ServerModelRow[] = []\n for (const [providerLabel, groupModels] of groups) {\n for (const row of buildDedupedModelRows(groupModels, gateway))\n rows.push({ providerLabel, ...row })\n }\n return rows.sort(\n (a, b) => a.providerLabel.localeCompare(b.providerLabel) || a.name.localeCompare(b.name)\n )\n}\n\nasync function buildSavedConfig(): Promise<ServerSavedConfig> {\n return {\n favoritesOnly: getServerFavoritesOnly(),\n freeModelsOnly: getServerFreeModelsOnly(),\n exposedProviders: getServerExposedProviders(),\n maskGatewayIds: getServerMaskGatewayIds(),\n listenMode: getServerListenMode(),\n hasSavedPassword: await hasSavedPasswordCached(),\n }\n}\n\nexport async function getServerStatus(): Promise<ServerStatusPayload> {\n const saved = await buildSavedConfig()\n if (!running) return { running: false, saved }\n\n const { handle, config, serverPassword, providerSummary, modelRows } = running\n\n const payload: ServerStatusPayload = {\n running: true,\n saved,\n listenMode: config.listenMode,\n anthropicUrl: `http://127.0.0.1:${handle.port}/anthropic`,\n openaiUrl: `http://127.0.0.1:${handle.port}/openai/v1`,\n exposedProviders: config.exposedProviders,\n favoritesOnly: config.favoritesOnly,\n freeModelsOnly: config.freeModelsOnly,\n maskGatewayIds: config.maskGatewayIds,\n providerSummary,\n models: modelRows,\n }\n\n if (config.listenMode === 'network') {\n payload.networkUrls = getLocalIps().map(\n ({ name, address }: { name: string; address: string }) => ({\n name,\n anthropicUrl: `http://${address}:${handle.port}/anthropic`,\n openaiUrl: `http://${address}:${handle.port}/openai/v1`,\n })\n )\n payload.apiKey = serverPassword ?? undefined\n } else {\n payload.apiKey = 'any non-empty value'\n }\n\n return payload\n}\n\nexport function startGatewayServer(\n req: ServerStartRequest\n): Promise<{ ok: true; status: ServerStatusPayload } | { ok: false; error: string }> {\n if (running)\n return Promise.resolve({ ok: false, error: 'Server is already running. Stop it first.' })\n // Two near-simultaneous start requests would otherwise both pass the `running`\n // check above and race through the async setup below — serialize on the\n // in-flight promise instead of just the (only-set-at-the-end) `running` flag.\n if (startInFlight) return startInFlight\n startInFlight = doStartGatewayServer(req).finally(() => {\n startInFlight = null\n })\n return startInFlight\n}\n\nasync function doStartGatewayServer(\n req: ServerStartRequest\n): Promise<{ ok: true; status: ServerStatusPayload } | { ok: false; error: string }> {\n if (req.listenMode !== 'local' && req.listenMode !== 'network') {\n return { ok: false, error: 'Invalid listen mode.' }\n }\n\n const apiKey = await resolveServerUpstreamApiKey()\n if (!apiKey) {\n return {\n ok: false,\n error: 'No providers configured. Add a provider in Providers & Keys first.',\n }\n }\n\n let serverPassword: string | null = null\n if (req.listenMode === 'network') {\n if (req.passwordMode === 'saved') {\n const saved = await getSavedServerPassword()\n if (!saved) return { ok: false, error: 'No saved password found — enter a new password.' }\n serverPassword = saved\n } else {\n const trimmed = (req.password ?? '').trim()\n if (!trimmed) return { ok: false, error: 'A server password is required for network mode.' }\n serverPassword = trimmed\n if (req.savePassword) {\n await setSavedServerPassword(trimmed)\n hasSavedPasswordCache = { value: true, expiresAt: Date.now() + SAVED_PASSWORD_CACHE_TTL_MS }\n }\n }\n }\n\n let models: ServerModelInfo[]\n try {\n models = await loadServerModels()\n } catch (err) {\n return {\n ok: false,\n error: `Failed to load models: ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n\n if (req.exposedProviders) models = filterServerModelsByProviders(models, req.exposedProviders)\n\n if (req.favoritesOnly) {\n const favorites: FavoriteModel[] = loadPreferences().favoriteModels ?? []\n if (favorites.length === 0) {\n return {\n ok: false,\n error: 'No favorite models configured. Add favorites in the Favorites tab first.',\n }\n }\n models = filterServerModelsByFavorites(models, favorites).slice(0, MAX_MODEL_CATALOG)\n if (models.length === 0) {\n return { ok: false, error: 'No favorite models matched the current provider filter.' }\n }\n }\n\n if (req.freeModelsOnly) {\n models = filterServerModelsByFreeStatus(models)\n if (models.length === 0) {\n return { ok: false, error: 'No free models matched the current server filters.' }\n }\n }\n\n if (models.length === 0) {\n return {\n ok: false,\n error: 'No models to expose. Add providers or adjust the exposed-provider filter.',\n }\n }\n\n // Persist wizard choices so the terminal `anygate server` quick-start path and this\n // panel stay in sync, matching the CLI wizard's own save-as-you-go behavior.\n setServerFavoritesOnly(req.favoritesOnly)\n setServerFreeModelsOnly(req.freeModelsOnly)\n // Always persist, including the \"all providers\" case: `null` must clear a\n // previously saved subset, otherwise switching back to All leaves the old\n // selection stored and the panel restores it on next load.\n // getServerExposedProviders() reads an empty list back as null.\n setServerExposedProviders(req.exposedProviders ?? [])\n setServerMaskGatewayIds(req.maskGatewayIds)\n setServerListenMode(req.listenMode)\n\n const host = req.listenMode === 'network' ? '0.0.0.0' : '127.0.0.1'\n const gateway = req.maskGatewayIds ? { maskGatewayIds: true as const } : undefined\n\n let handle: ServerHandle\n try {\n handle = await startServer({\n host,\n port: 17645,\n apiKey,\n serverPassword,\n catalog: createGatewayModelCatalog(models, gateway),\n backends: BACKENDS,\n gateway,\n })\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code\n const message =\n code === 'EADDRINUSE'\n ? 'Port 17645 is already in use — stop the other anygate server instance first.'\n : `Failed to start server: ${err instanceof Error ? err.message : String(err)}`\n return { ok: false, error: message }\n }\n\n running = {\n handle,\n serverPassword,\n config: {\n favoritesOnly: req.favoritesOnly,\n freeModelsOnly: req.freeModelsOnly,\n exposedProviders: req.exposedProviders,\n maskGatewayIds: req.maskGatewayIds,\n listenMode: req.listenMode,\n },\n providerSummary: summarizeServerProviders(models),\n modelRows: buildModelRows(models, gateway),\n }\n\n return { ok: true, status: await getServerStatus() }\n}\n\nexport async function stopGatewayServer(): Promise<{ ok: true; stopped: boolean }> {\n if (running) {\n await running.handle.close()\n running = null\n return { ok: true, stopped: true }\n }\n return { ok: true, stopped: false }\n}\n","import pc from 'picocolors'\nimport { createServer } from 'node:net'\nimport { GATEWAY_PORT } from '../config/constants.js'\nimport {\n detectConflicts,\n isSecretServiceAvailable,\n readFromCredentialStore,\n} from '../config/env.js'\nimport { gateIntro, gateOutro, printPanel } from '../apps/shared/ui.js'\n\ninterface CheckResult {\n /** Stable machine-readable key so the UI can render per-check without parsing labels. */\n id: DoctorCheckId\n label: string\n ok: boolean\n detail: string\n /** A failed critical check flips the overall exit code to 1. */\n critical: boolean\n}\n\nexport type DoctorCheckId = 'node' | 'keychain' | 'opencode-key' | 'env-conflicts' | 'gateway-port'\n\nexport interface DoctorReport {\n /** False when any critical check failed. */\n ok: boolean\n checks: CheckResult[]\n nodeVersion: string\n keychain: { available: boolean; note: string }\n /** Names only — values are secrets and must never leave the process. */\n conflictingEnvVars: string[]\n gatewayPort: number\n gatewayPortAvailable: boolean\n /** True when the gateway port is busy because *our* gateway is running. */\n gatewayPortOwnedByAnygate: boolean\n}\n\nfunction nodeMajor(): number {\n const raw = process.versions.node.split('.')[0] ?? '0'\n return Number.parseInt(raw, 10) || 0\n}\n\nfunction checkPortFree(port: number): Promise<boolean> {\n return new Promise(resolve => {\n const server = createServer()\n server.once('error', () => resolve(false))\n server.listen(port, () => {\n server.close(() => resolve(true))\n })\n const timer = setTimeout(() => resolve(true), 1500)\n if (typeof timer.unref === 'function') timer.unref()\n })\n}\n\nfunction line(ok: boolean, label: string, detail = ''): string {\n const mark = ok ? pc.green('✓') : pc.red('✗')\n const text = detail ? `${label} ${pc.dim(`— ${detail}`)}` : label\n return ` ${mark} ${text}`\n}\n\n/**\n * Run every diagnostic and return structured results. Contains no terminal\n * output so it can back both `anygate doctor` and `GET /api/health`.\n *\n * @param opts.gatewayRunning Whether anygate's own gateway currently holds\n * GATEWAY_PORT. A busy port is only a problem when we aren't the owner, so the\n * caller passes what it knows rather than this module guessing.\n */\nexport async function collectDoctorReport(\n opts: { gatewayRunning?: boolean } = {}\n): Promise<DoctorReport> {\n const checks: CheckResult[] = []\n\n const major = nodeMajor()\n checks.push({\n id: 'node',\n label: 'Node.js version',\n ok: major >= 18,\n detail: `v${process.versions.node} (requires ≥ 18)`,\n critical: true,\n })\n\n let keyringOk = false\n let keyringDetail = ''\n const platform = process.platform\n if (platform === 'darwin') {\n keyringOk = true\n keyringDetail = 'macOS Keychain Service'\n } else if (platform === 'win32') {\n keyringOk = true\n keyringDetail = 'Windows Credential Manager'\n } else if (platform === 'linux') {\n keyringOk = await isSecretServiceAvailable()\n keyringDetail = keyringOk\n ? 'Secret Service (GNOME Keyring / KWallet)'\n : 'Secret Service daemon unreachable'\n } else {\n keyringDetail = `Unsupported platform (${platform})`\n }\n\n checks.push({\n id: 'keychain',\n label: 'Secure credential storage',\n ok: keyringOk,\n detail: keyringDetail,\n critical: false,\n })\n\n const storedKey = await readFromCredentialStore()\n checks.push({\n id: 'opencode-key',\n label: 'OpenCode API key',\n ok: Boolean(storedKey || process.env['OPENCODE_API_KEY']),\n detail: storedKey\n ? 'Configured in secure store'\n : process.env['OPENCODE_API_KEY']\n ? 'Configured via process environment'\n : 'Not set (run `anygate --setup`)',\n critical: false,\n })\n\n const conflicts = detectConflicts()\n const conflictNames = conflicts.map(c => c.name)\n checks.push({\n id: 'env-conflicts',\n label: 'Environment variable conflicts',\n ok: conflicts.length === 0,\n detail:\n conflicts.length === 0\n ? 'Clean'\n : `Found ${conflicts.length} conflicting var(s): ${conflictNames.join(', ')}`,\n critical: false,\n })\n\n const portFree = await checkPortFree(GATEWAY_PORT)\n // Our own running gateway holding the port is the expected healthy state,\n // not a conflict — only an unrelated process squatting on it is a problem.\n const ownedByUs = !portFree && Boolean(opts.gatewayRunning)\n checks.push({\n id: 'gateway-port',\n label: `Local gateway port (${GATEWAY_PORT})`,\n ok: portFree || ownedByUs,\n detail: portFree\n ? 'Available'\n : ownedByUs\n ? 'In use by the anygate gateway'\n : 'In use by another process',\n critical: false,\n })\n\n return {\n ok: !checks.some(c => c.critical && !c.ok),\n checks,\n nodeVersion: process.versions.node,\n keychain: { available: keyringOk, note: keyringDetail },\n conflictingEnvVars: conflictNames,\n gatewayPort: GATEWAY_PORT,\n gatewayPortAvailable: portFree,\n gatewayPortOwnedByAnygate: ownedByUs,\n }\n}\n\nexport async function runDoctorCommand(_dryRun: boolean): Promise<number> {\n gateIntro('Doctor')\n\n const report = await collectDoctorReport()\n\n const lines = report.checks.map(c => line(c.ok, c.label, c.detail))\n printPanel('System Diagnostic', lines)\n\n if (!report.ok) {\n gateOutro('One or more critical checks failed.')\n return 1\n }\n\n gateOutro('All checks completed successfully.')\n return 0\n}\n"],"mappings":"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","names":["createServer","writeFileSync","existsSync","join","pc","dir","scriptPath","existsSync","p","getTemplateById","device","url","session","result","existsSync","isMac","isWindows","join","existsSync","pc","open","createServer","url","writeFileSync"]}
@@ -11,10 +11,11 @@ import {
11
11
  OPENCODE_CACHE_PATH,
12
12
  RATE_LIMIT_MAX_REQUESTS,
13
13
  RATE_LIMIT_WINDOW_MS,
14
+ REQUEST_TIMEOUT_MS,
14
15
  VERSION,
15
16
  VERTEX_ANTHROPIC_NPM,
16
17
  classifyModelFormat
17
- } from "./chunk-S5WL3M5G.js";
18
+ } from "./chunk-RNW2MGKL.js";
18
19
  import "./chunk-UT3JLF3M.js";
19
20
  export {
20
21
  BACKENDS,
@@ -28,8 +29,9 @@ export {
28
29
  OPENCODE_CACHE_PATH,
29
30
  RATE_LIMIT_MAX_REQUESTS,
30
31
  RATE_LIMIT_WINDOW_MS,
32
+ REQUEST_TIMEOUT_MS,
31
33
  VERSION,
32
34
  VERTEX_ANTHROPIC_NPM,
33
35
  classifyModelFormat
34
36
  };
35
- //# sourceMappingURL=constants-U356SKNS.js.map
37
+ //# sourceMappingURL=constants-7DBGCJ34.js.map
@@ -9,7 +9,5 @@
9
9
  "modelsEndpoint": "/v1/models",
10
10
  "signupUrl": "https://claude.ai",
11
11
  "modelSource": "api-list",
12
- "hidden": true,
13
- "subscriptionRisk": true,
14
12
  "npm": "@ai-sdk/anthropic"
15
- }
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "id": "openai",
3
+ "name": "OpenAI",
4
+ "description": "OpenAI API key",
5
+ "addable": true,
6
+ "supported": true,
7
+ "authType": "apiKey",
8
+ "apiBaseUrl": "https://api.openai.com/v1",
9
+ "modelsEndpoint": "/models",
10
+ "signupUrl": "https://platform.openai.com/account/api-keys",
11
+ "modelSource": "api-list",
12
+ "npm": "@ai-sdk/openai"
13
+ }