anygate 0.5.2 → 0.5.4

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.
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  BACKENDS,
4
4
  MAX_MODEL_CATALOG,
5
- VERSION,
6
5
  addCustomEndpointProvider,
7
6
  addProviderFromTemplate,
7
+ aggregateAnalytics,
8
8
  buildAntigravityAuthUrl,
9
9
  buildDedupedModelRows,
10
10
  checkForUpdates,
@@ -65,12 +65,12 @@ import {
65
65
  summarizeServerProviders,
66
66
  validateCustomEndpointUrl,
67
67
  writeSecureLogLine
68
- } from "./chunk-6GVUN4JO.js";
68
+ } from "./chunk-E2MV3GDX.js";
69
69
  import {
70
70
  getTemplateById,
71
71
  listAddableTemplates,
72
72
  listVisibleOAuthTemplates
73
- } from "./chunk-YYSUTRMV.js";
73
+ } from "./chunk-VKROC37K.js";
74
74
 
75
75
  // src/ui/command.ts
76
76
  import { createServer } from "http";
@@ -89,37 +89,41 @@ import { join } from "path";
89
89
  var isWindows = process.platform === "win32";
90
90
  var isMac = process.platform === "darwin";
91
91
  var SUPPORTED_APPS = [
92
- { id: "claude", name: "Claude Code CLI", type: "cli", detectId: "claude", gatewayCommand: "claude" },
93
- { id: "codex", name: "Codex CLI", type: "cli", detectId: "codex", gatewayCommand: "codex" },
94
- { id: "gemini", name: "Gemini CLI", type: "cli", detectId: "gemini", gatewayCommand: "gemini" },
95
- { id: "agy", name: "Antigravity CLI", type: "cli", detectId: "agy", gatewayCommand: "agy" },
92
+ { id: "claude", name: "Claude Code CLI", type: "cli", detectId: "claude", gatewayCommand: "claude", installHint: "npm install -g @anthropic-ai/claude-code" },
93
+ { id: "codex", name: "Codex CLI", type: "cli", detectId: "codex", gatewayCommand: "codex", installHint: "npm install -g @openai/codex" },
94
+ { id: "gemini", name: "Gemini CLI", type: "cli", detectId: "gemini", gatewayCommand: "gemini", installHint: "npm install -g @google/gemini-cli" },
95
+ { id: "agy", name: "Antigravity CLI", type: "cli", detectId: "agy", gatewayCommand: "agy", installHint: "npm install -g @google/antigravity-cli" },
96
96
  {
97
97
  id: "antigravity",
98
98
  name: "Antigravity (App)",
99
99
  type: "app",
100
100
  detectId: "antigravity",
101
- gatewayCommand: "antigravity"
101
+ gatewayCommand: "antigravity",
102
+ installUrl: "https://antigravity.dev/download"
102
103
  },
103
104
  {
104
105
  id: "antigravity-ide",
105
106
  name: "Antigravity IDE (App)",
106
107
  type: "app",
107
108
  detectId: "antigravity-ide",
108
- gatewayCommand: "antigravity-ide"
109
+ gatewayCommand: "antigravity-ide",
110
+ installUrl: "https://antigravity.dev/ide"
109
111
  },
110
112
  {
111
113
  id: "claude-app",
112
114
  name: "Claude Code Desktop",
113
115
  type: "app",
114
116
  detectId: "claude-app",
115
- gatewayCommand: "claude-app"
117
+ gatewayCommand: "claude-app",
118
+ installUrl: "https://claude.com/download"
116
119
  },
117
120
  {
118
121
  id: "codex-app",
119
122
  name: "ChatGPT Desktop (Codex)",
120
123
  type: "app",
121
124
  detectId: "codex-app",
122
- gatewayCommand: "codex-app"
125
+ gatewayCommand: "codex-app",
126
+ installUrl: "https://openai.com/chatgpt/desktop"
123
127
  }
124
128
  ];
125
129
  function fallbackPathsForApp(id, platform = process.platform) {
@@ -332,7 +336,9 @@ function getSupportedApps() {
332
336
  path,
333
337
  pathSource,
334
338
  gatewayCommand: app.gatewayCommand,
335
- launchCommand: installed ? getGatewayLaunchCommand(app.id) : null
339
+ launchCommand: installed ? getGatewayLaunchCommand(app.id) : null,
340
+ installHint: app.installHint,
341
+ installUrl: app.installUrl
336
342
  };
337
343
  });
338
344
  }
@@ -608,6 +614,8 @@ function handleUiApiRequest(req, res, opts = {}) {
608
614
  handleStartServer(req, res, opts);
609
615
  } else if (url === "/api/server/stop" && req.method === "POST") {
610
616
  handleStopServer(res, opts);
617
+ } else if (url.startsWith("/api/analytics") && req.method === "GET") {
618
+ handleGetAnalytics(res, req);
611
619
  } else {
612
620
  sendJson(res, 404, { error: "Not found" });
613
621
  }
@@ -634,6 +642,16 @@ async function handlePostConfig(req, res) {
634
642
  sendJson(res, 400, { error: String(err) });
635
643
  }
636
644
  }
645
+ function dedupModelsById(models) {
646
+ const seen = /* @__PURE__ */ new Set();
647
+ const out = [];
648
+ for (const m of models) {
649
+ if (seen.has(m.id)) continue;
650
+ seen.add(m.id);
651
+ out.push(m);
652
+ }
653
+ return out;
654
+ }
637
655
  async function handleGetModels(res) {
638
656
  try {
639
657
  const catalog = await fetchModelsWithTimeout();
@@ -650,7 +668,8 @@ async function handleGetModels(res) {
650
668
  })(),
651
669
  authType: p2.authType ?? "api",
652
670
  modelCount: rawCountById.get(p2.id) ?? p2.models.length,
653
- models: p2.models.map((m) => ({
671
+ signupUrl: getTemplateById(p2.id)?.signupUrl ?? null,
672
+ models: dedupModelsById(p2.models).map((m) => ({
654
673
  id: m.id,
655
674
  name: m.name,
656
675
  isFree: m.isFree ?? false,
@@ -673,6 +692,7 @@ async function handleGetModels(res) {
673
692
  freeAccess: false,
674
693
  authType: "oauth",
675
694
  modelCount: 0,
695
+ signupUrl: getTemplateById(rp.templateId)?.signupUrl ?? null,
676
696
  models: []
677
697
  });
678
698
  }
@@ -773,7 +793,7 @@ async function handleAddProvider(req, res) {
773
793
  sendJson(res, 400, { error: "templateId required" });
774
794
  return;
775
795
  }
776
- const { listSupportedTemplates } = await import("./provider-templates-75KU6VA6.js");
796
+ const { listSupportedTemplates } = await import("./provider-templates-TWR5XSYI.js");
777
797
  const template = listSupportedTemplates().find((t) => t.id === templateId);
778
798
  if (!template) {
779
799
  sendJson(res, 404, { error: `Template '${templateId}' not found` });
@@ -1210,6 +1230,16 @@ async function handleStopServer(res, opts) {
1210
1230
  sendJson(res, 500, { error: String(err) });
1211
1231
  }
1212
1232
  }
1233
+ function handleGetAnalytics(res, req) {
1234
+ try {
1235
+ const sp = new URL(req.url ?? "", "http://localhost").searchParams;
1236
+ const rangeParam = sp.get("range");
1237
+ const range = rangeParam === "7d" || rangeParam === "30d" || rangeParam === "all" ? rangeParam : "all";
1238
+ sendJson(res, 200, aggregateAnalytics(range));
1239
+ } catch (err) {
1240
+ sendJson(res, 500, { error: String(err) });
1241
+ }
1242
+ }
1213
1243
  async function handleBrowseFolder(res) {
1214
1244
  try {
1215
1245
  let resultPath = "";
@@ -1284,7 +1314,7 @@ async function handleBrowseFolder(res) {
1284
1314
 
1285
1315
  // src/ui/command.ts
1286
1316
  var __dirname = dirname(fileURLToPath(import.meta.url));
1287
- var PUBLIC_DIR = join2(__dirname, "ui", "public");
1317
+ var PUBLIC_DIR = join2(__dirname, "ui", "dist");
1288
1318
  var LOCK_FILE = join2(getAppHome(), "ui.lock");
1289
1319
  var MIME = {
1290
1320
  ".html": "text/html; charset=utf-8",
@@ -1292,7 +1322,9 @@ var MIME = {
1292
1322
  ".css": "text/css; charset=utf-8",
1293
1323
  ".png": "image/png",
1294
1324
  ".webp": "image/webp",
1295
- ".svg": "image/svg+xml"
1325
+ ".svg": "image/svg+xml",
1326
+ ".json": "application/json; charset=utf-8",
1327
+ ".woff2": "font/woff2"
1296
1328
  };
1297
1329
  function ext(path) {
1298
1330
  const i = path.lastIndexOf(".");
@@ -1301,13 +1333,24 @@ function ext(path) {
1301
1333
  function buildStaticCache() {
1302
1334
  const cache = /* @__PURE__ */ new Map();
1303
1335
  try {
1304
- for (const name of readdirSync(PUBLIC_DIR)) {
1305
- const mime = MIME[ext(name)];
1306
- if (!mime) continue;
1307
- const raw = readFileSync(join2(PUBLIC_DIR, name));
1308
- const content = name === "index.html" ? Buffer.from(raw.toString("utf8").replace("{{VERSION}}", VERSION)) : raw;
1309
- cache.set(`/${name}`, { content, mime });
1310
- }
1336
+ const walk = (dir, prefix) => {
1337
+ for (const name of readdirSync(dir)) {
1338
+ const full = join2(dir, name);
1339
+ const key = `${prefix}/${name}`;
1340
+ try {
1341
+ readdirSync(full);
1342
+ walk(full, key);
1343
+ } catch {
1344
+ const mime = MIME[ext(name)];
1345
+ if (!mime) continue;
1346
+ const raw = readFileSync(full);
1347
+ cache.set(key, { content: raw, mime });
1348
+ }
1349
+ }
1350
+ };
1351
+ walk(PUBLIC_DIR, "");
1352
+ const index = cache.get("/index.html");
1353
+ if (index) cache.set("/__spa_fallback__", index);
1311
1354
  } catch {
1312
1355
  }
1313
1356
  return cache;
@@ -1385,6 +1428,12 @@ async function runUiCommand(opts = {}) {
1385
1428
  res.end(cached.content);
1386
1429
  return;
1387
1430
  }
1431
+ if (!ext(key) && staticCache.has("/__spa_fallback__")) {
1432
+ const fb = staticCache.get("/__spa_fallback__");
1433
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
1434
+ res.end(fb.content);
1435
+ return;
1436
+ }
1388
1437
  res.writeHead(404);
1389
1438
  res.end("Not found");
1390
1439
  });
@@ -1449,4 +1498,4 @@ export {
1449
1498
  resolveUiShutdownDecision,
1450
1499
  runUiCommand
1451
1500
  };
1452
- //# sourceMappingURL=command-OQI56XYG.js.map
1501
+ //# sourceMappingURL=command-GJYPBC6E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/command.ts","../src/agents/shared/native-launcher.ts","../src/ui/api.ts","../src/ui/server-control.ts"],"sourcesContent":["import { createServer } from 'node:http';\nimport { readFileSync, readdirSync, writeFileSync, unlinkSync, existsSync, mkdirSync } 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 '../core/paths.js';\nimport { handleUiApiRequest, type UiServerLifecycleEvent } from './api.js';\nimport { getUiDebugLogPath, makeTraceLogger } from '../agents/shared/trace-log.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// Served SPA is produced by `vite build` (ui/ → src/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 { unlinkSync(LOCK_FILE); } catch {}\n}\n\nfunction checkExistingServer(): string | null {\n if (!existsSync(LOCK_FILE)) return null;\n try {\n const { pid, port } = JSON.parse(readFileSync(LOCK_FILE, 'utf8'));\n process.kill(pid, 0);\n return `http://127.0.0.1:${port}`;\n } catch {\n removeLock();\n return null;\n }\n}\n\nexport function isUiApiRoute(url: string): boolean {\n return url.startsWith('/api/') || url.startsWith('/oauth/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> = () => 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 = checkExistingServer();\n if (existing) {\n console.log(`\\n ${pc.bold('anygate UI')} already running at ${pc.cyan(existing)}\\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 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', () => { void handleSignal('SIGINT'); });\n process.on('SIGTERM', () => { void handleSignal('SIGTERM'); });\n\n console.log(`\\n ${pc.bold('anygate UI')} ${pc.cyan(url)}\\n ${pc.dim('Press Ctrl+C to stop')}\\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\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/core/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 favorites?: 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 { id: 'claude', name: 'Claude Code CLI', type: 'cli', detectId: 'claude', gatewayCommand: 'claude', installHint: 'npm install -g @anthropic-ai/claude-code' },\n { id: 'codex', name: 'Codex CLI', type: 'cli', detectId: 'codex', gatewayCommand: 'codex', installHint: 'npm install -g @openai/codex' },\n { id: 'gemini', name: 'Gemini CLI', type: 'cli', detectId: 'gemini', gatewayCommand: 'gemini', installHint: 'npm install -g @google/gemini-cli' },\n { id: 'agy', name: 'Antigravity CLI', type: 'cli', detectId: 'agy', gatewayCommand: 'agy', installHint: 'npm install -g @google/antigravity-cli' },\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(id: string, platform: NodeJS.Platform = process.platform): 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 ? [\n join(appData, 'npm', 'claude.cmd'),\n join(appData, 'npm', 'claude'),\n ]\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 ? [\n join(appData, 'npm', 'codex.cmd'),\n join(appData, 'npm', 'codex'),\n ]\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 ? [\n join(appData, 'npm', 'gemini.cmd'),\n join(appData, 'npm', 'gemini'),\n ]\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(homedir(), 'Applications', 'Antigravity IDE.app', 'Contents', 'Resources', 'app', 'bin', 'antigravity-ide'),\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 [\n join(localAppData, 'Programs', 'Antigravity', 'Antigravity.exe'),\n ];\n }\n return [\n '/opt/antigravity/antigravity',\n '/usr/local/bin/antigravity',\n '/usr/bin/antigravity',\n ];\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\n ? [join(localAppData, 'Programs', 'claude', 'Claude.exe')]\n : [];\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): { installed: boolean; path: string | null; pathSource: 'auto' | 'override' | null } {\n const override = getAppPathOverride(id);\n if (override) {\n return existsSync(override)\n ? { installed: true, path: override, pathSource: 'override' }\n : { installed: false, 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(scriptPath, [\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'), { encoding: 'utf8', mode: 0o700 });\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, [\n '#!/bin/sh',\n runCmd,\n 'exec sh',\n '',\n ].join('\\n'), { encoding: 'utf8', mode: 0o700 });\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.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 { getSupportedApps, getSupportedApp, getGatewayLaunchCommand, detectApp } from '../agents/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 { loadPreferences, recordLaunchFolder, savePreferences, setAppPathOverride } from '../core/config.js';\nimport { fetchProviderCatalog } from '../providers/provider-catalog.ts';\nimport { favoriteProviderDisplayName } from '../agents/claude/favorites-provider-display.ts';\nimport { saveProviderCredential, resolveProviderCredential } from '../core/env.js';\nimport { readBody, sendJson } from '../core/http-utils.ts';\nimport { loadRegistry } from '../registry/io.js';\nimport { refreshProviderModels, refreshAllProviderModels } from '../registry/refresh-models.js';\nimport { listAddableTemplates, listVisibleOAuthTemplates, PROVIDER_TEMPLATES, getTemplateById } from '../providers/provider-templates.ts';\nimport { addProviderFromTemplate, type AddTemplateResult } from '../registry/add-template.js';\nimport { addCustomEndpointProvider, type CustomEndpointKind } from '../registry/custom-endpoint.js';\nimport { validateCustomEndpointUrl } from '../registry/url-security.js';\nimport { saveNativeOAuthCredential } from '../registry/provider-auth.js';\nimport { removeProviderFromRegistry } from '../registry/crud.js';\nimport { requestXaiDeviceCode, pollXaiDeviceCodeToken } from '../oauth/xai.js';\nimport { requestOpenAiDeviceCode, pollOpenAiDeviceCodeToken, openAiDeviceCodeUrl } from '../oauth/openai.js';\nimport { requestGithubDeviceCode, pollGithubDeviceCodeToken } from '../oauth/github.js';\nimport {\n guiCallbackRedirectUri,\n} from '../oauth/claude-code.js';\nimport {\n buildAntigravityAuthUrl,\n completeAntigravityExchange,\n} from '../oauth/antigravity-oauth.js';\n\nimport { providerOptionsFromCatalog } from '../gateway/server.ts';\nimport { getServerStatus, startGatewayServer, stopGatewayServer, type ServerStartRequest } from './server-control.js';\nimport { writeSecureLogLine } from '../agents/shared/trace-log.js';\nimport { freeStatusLabel } from '../agents/shared/free-models.ts';\nimport { checkForUpdates } from '../agents/shared/update-check.ts';\nimport { aggregateAnalytics, type RangeId } from '../core/analytics-log.js';\n\nconst MODELS_TIMEOUT_MS = 30_000;\n\nexport type UiServerLifecycleEvent =\n | { type: 'started'; listenMode: 'local' | 'network'; modelCount: number }\n | { 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 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(req: IncomingMessage, res: ServerResponse, opts: UiApiOptions = {}): void {\n sendCors(req, res);\n if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; }\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/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 } else if (url === '/api/providers/oauth/start' && req.method === 'POST') {\n handleOAuthStart(req, res);\n } else if (url.startsWith('/api/providers/oauth/status') && req.method === 'GET') {\n handleOAuthStatus(req, res);\n } else if (url.startsWith('/oauth/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.startsWith('/api/analytics') && req.method === 'GET') {\n handleGetAnalytics(res, req);\n } else {\n sendJson(res, 404, { error: 'Not found' });\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)) 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(registry.providers.map(p => [p.id, p.modelsCache?.models.length ?? 0]));\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: !p.apiKey && (() => {\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 })),\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({ id: rp.id, name: rp.name, authType: rp.authType }),\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\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' }); return;\n }\n if (!key || typeof key !== 'string' || key.trim().length === 0) {\n sendJson(res, 400, { error: 'key must be a non-empty string' }); 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 { id: '__custom_openai__', name: 'Custom OpenAI-compatible', signupUrl: null, authType: 'api', custom: true },\n { id: '__custom_anthropic__', name: 'Custom Anthropic-compatible', signupUrl: null, authType: 'api', custom: true },\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 const apiTemplates = listAddableTemplates(configured).map(t => ({\n id: t.id,\n name: t.name,\n signupUrl: t.signupUrl ?? 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)\n .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; displayName?: string; baseUrl?: string; apiKey?: string; 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\"' }); return;\n }\n if (!displayName?.trim()) {\n sendJson(res, 400, { error: 'displayName required' }); return;\n }\n if (!baseUrl?.trim()) {\n sendJson(res, 400, { error: 'baseUrl required' }); 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' }); return;\n }\n const { listSupportedTemplates } = await import('../providers/provider-templates.js');\n const template = listSupportedTemplates().find(t => t.id === templateId);\n if (!template) {\n sendJson(res, 404, { error: `Template '${templateId}' not found` }); 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' }); return;\n }\n const keyText = template.apiKeyOptional && !rawKey && !template.anonymousFreeModels ? template.id : rawKey;\n\n let baseUrlOverride: string | undefined;\n if (template.urlPrompt) {\n baseUrlOverride = typeof baseUrl === 'string' ? baseUrl.trim() : '';\n if (!baseUrlOverride) {\n sendJson(res, 400, { error: 'baseUrl required' }); return;\n }\n const usesHttp = /^http:\\/\\//i.test(baseUrlOverride);\n const valid = await validateCustomEndpointUrl(baseUrlOverride, { allowInsecureLocal: usesHttp });\n if (!valid.ok) {\n sendJson(res, 400, { error: valid.error ?? 'Invalid URL', hint: valid.hint }); return;\n }\n }\n\n const result: AddTemplateResult = await addProviderFromTemplate(template, keyText, { baseUrl: baseUrlOverride });\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, { ok: true, providers: summary, total: summary.reduce((n, p) => n + p.count, 0) });\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' }); 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' }); 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' }); 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, { error: `providerId must be one of: ${[...NATIVE_OAUTH_PROVIDER_IDS].join(', ')}` }); return;\n }\n\n const sessionId = randomUUID();\n\n if (providerId === 'xai-oauth') {\n const device = await requestXaiDeviceCode();\n const url = device.verification_uri_complete ?? device.verification_uri;\n const session: OAuthSession = { status: 'pending', url, userCode: device.user_code, providerId };\n oauthSessions.set(sessionId, session);\n\n pollXaiDeviceCodeToken(device).then(async tokens => {\n await saveNativeOAuthCredential(providerId, tokens);\n await refreshOAuthProviderModels(providerId);\n oauthSessions.set(sessionId, { ...session, status: 'done' });\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 return;\n }\n\n if (providerId === 'github-copilot') {\n const device = await requestGithubDeviceCode();\n const url = device.verification_uri;\n const session: OAuthSession = { status: 'pending', url, userCode: device.user_code, providerId };\n oauthSessions.set(sessionId, session);\n\n pollGithubDeviceCodeToken(device).then(async tokens => {\n await saveNativeOAuthCredential(providerId, tokens);\n await refreshOAuthProviderModels(providerId);\n oauthSessions.set(sessionId, { ...session, status: 'done' });\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 return;\n }\n\n if (PKCE_PROVIDER_IDS.has(providerId)) {\n if (providerId === '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 // 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` }); return;\n }\n\n const { authUrl, codeVerifier, oauthState } = pkce;\n const session: OAuthSession = {\n status: 'pending',\n url: authUrl,\n providerId,\n codeVerifier,\n oauthState,\n };\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.then(async (code) => {\n let providerData: Record<string, unknown> = {};\n let accountId: string | undefined;\n let tokens: import('../oauth/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 }).catch(err => {\n oauthSessions.set(sessionId, { ...session, status: 'error', error: String(err) });\n });\n\n sendJson(res, 200, { sessionId, authUrl, pkce: true });\n return;\n }\n\n // openai-oauth\n const device = await requestOpenAiDeviceCode();\n const url = openAiDeviceCodeUrl();\n const session: OAuthSession = { status: 'pending', url, userCode: device.user_code, providerId };\n oauthSessions.set(sessionId, session);\n\n pollOpenAiDeviceCodeToken(device).then(async ({ tokens, accountId }) => {\n await saveNativeOAuthCredential(providerId, tokens, accountId);\n await refreshOAuthProviderModels(providerId);\n oauthSessions.set(sessionId, { ...session, status: 'done' });\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 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) { sendJson(res, 404, { error: 'Session not found or expired' }); return; }\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.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').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) { matchedSession = session; break; }\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(req: IncomingMessage, res: ServerResponse, opts: UiApiOptions): Promise<void> {\n try {\n const body = JSON.parse(await readBody(req));\n const { appId, favorites, 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 if (!favorites && (providerId || modelId) && (!providerId || !modelId)) {\n sendJson(res, 400, { error: 'Both providerId and modelId are required to launch a specific anygate model.' });\n return;\n }\n\n // Resolve the first favorite so the terminal can skip its interactive picker.\n // Without this the launch command has no --provider/--model and the terminal\n // shows the full provider wizard even though the user already chose \"Favorites\".\n 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 cwd: launchFolder,\n trace: opts.trace,\n });\n traceUi(\n opts,\n `launch app=${appId} provider=${providerId ?? ''} model=${modelId ?? ''} favorites=${Boolean(favorites)} resolved-from-favorites=${Boolean(favorites && providerId)} 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, { error: 'path must be a non-empty string, or null to clear the override.' });\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(req: IncomingMessage, res: ServerResponse, opts: UiApiOptions): 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' }); return;\n }\n if (typeof body.maskGatewayIds !== 'boolean') {\n sendJson(res, 400, { error: 'maskGatewayIds must be a boolean' }); return;\n }\n if (body.listenMode !== 'local' && body.listenMode !== 'network') {\n sendJson(res, 400, { error: 'listenMode must be \"local\" or \"network\"' }); 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 (err.code === 1 || String(err.stderr).includes('-128') || String(err.stdout).includes('-128')) {\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, { error: `Failed to open folder picker: ${err instanceof Error ? err.message : String(err)}` });\n return;\n }\n } else {\n try {\n const { stdout } = await execAsync('zenity --file-selection --directory --title=\"Select launch folder\"');\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 '../core/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 '../core/config.js';\nimport type { FavoriteModel } from '../core/types.js';\nimport { startServer, type ServerHandle } from '../gateway/router.ts';\nimport {\n buildDedupedModelRows,\n createGatewayModelCatalog,\n gatewayProviderLabel,\n type GatewayModelOptions,\n type ServerModelInfo,\n} from '../gateway/models.js';\nimport {\n filterServerModelsByFavorites,\n filterServerModelsByFreeStatus,\n filterServerModelsByProviders,\n summarizeServerProviders,\n} from '../gateway/catalog-filter.js';\nimport { getLocalIps, loadServerModels, resolveServerUpstreamApiKey } from '../gateway/server.ts';\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<{ ok: true; status: ServerStatusPayload } | { ok: false; error: string }> | 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) 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(models: ServerModelInfo[], gateway?: GatewayModelOptions): 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)) rows.push({ providerLabel, ...row });\n }\n return rows.sort((a, b) => a.providerLabel.localeCompare(b.providerLabel) || a.name.localeCompare(b.name));\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(({ 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 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) 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(() => { startInFlight = null; });\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 { ok: false, error: 'No providers configured. Add a provider in Providers & Keys first.' };\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 { ok: false, error: `Failed to load models: ${err instanceof Error ? err.message : String(err)}` };\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 { ok: false, error: 'No favorite models configured. Add favorites in the Favorites tab first.' };\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 { ok: false, error: 'No models to expose. Add providers or adjust the exposed-provider filter.' };\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 if (req.exposedProviders) 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 = 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"],"mappings":"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","names":["writeFileSync","existsSync","join","dir","scriptPath","existsSync","p","device","url","session","existsSync","isMac","isWindows","join","existsSync","url","writeFileSync"]}
@@ -6,7 +6,7 @@ import {
6
6
  listAddableTemplates,
7
7
  listSupportedTemplates,
8
8
  listVisibleOAuthTemplates
9
- } from "./chunk-YYSUTRMV.js";
9
+ } from "./chunk-VKROC37K.js";
10
10
  export {
11
11
  PROVIDER_TEMPLATES,
12
12
  filterTemplates,
@@ -15,4 +15,4 @@ export {
15
15
  listSupportedTemplates,
16
16
  listVisibleOAuthTemplates
17
17
  };
18
- //# sourceMappingURL=provider-templates-75KU6VA6.js.map
18
+ //# sourceMappingURL=provider-templates-TWR5XSYI.js.map
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--radius-xs:.125rem;--radius-sm:.25rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.fixed{position:fixed}.static{position:static}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.table{display:table}.flex-shrink{flex-shrink:1}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.border{border-style:var(--tw-border-style);border-width:1px}.text-end{text-align:end}.text-start{text-align:start}.lowercase{text-transform:lowercase}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}}:root{--bg:oklch(18% .006 70);--sidebar-bg:oklch(15.5% .006 70);--surface:oklch(21% .006 70);--surface-2:oklch(25% .006 70);--surface-hover:oklch(27% .007 70);--border:oklch(30% .006 70);--border-bright:oklch(42% .008 70);--border-glow:oklch(75% .16 65/.3);--glass-bg:oklch(100% 0 0/.04);--glass-bg-strong:oklch(100% 0 0/.07);--glass-border:oklch(100% 0 0/.08);--glass-blur:12px;--accent:oklch(75% .16 65);--accent-dim:oklch(62% .13 60);--accent-muted:oklch(75% .16 65/.12);--accent-glow:oklch(75% .16 65/.15);--accent-2:oklch(72% .14 55);--text-1:oklch(96% .005 80);--text-2:oklch(72% .01 75);--text-3:oklch(52% .01 75);--success:oklch(74% .16 150);--success-bg:oklch(74% .16 150/.1);--error:oklch(66% .2 25);--error-bg:oklch(66% .2 25/.1);--warning:oklch(80% .16 85);--ease:cubic-bezier(.16, 1, .3, 1);--dur-xs:.1s;--dur-sm:.16s;--dur-md:.24s;--dur-lg:.38s;--sidebar-w:248px;--radius:12px;--radius-sm:9px;--radius-xs:6px;--font-body:"Inter", system-ui, -apple-system, sans-serif;--font-display:"Outfit", "Inter", system-ui, sans-serif}html[data-theme=light]{--bg:oklch(96% .004 75);--sidebar-bg:oklch(93% .005 75);--surface:oklch(100% 0 0);--surface-2:oklch(95% .004 75);--surface-hover:oklch(92% .005 75);--border:oklch(86% .006 75);--border-bright:oklch(72% .008 75);--glass-bg:oklch(20% .02 70/.04);--glass-bg-strong:oklch(20% .02 70/.06);--glass-border:oklch(20% .02 70/.08);--text-1:oklch(22% .02 60);--text-2:oklch(42% .015 60);--text-3:oklch(58% .012 60)}*,:before,:after{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth}body{font-family:var(--font-body);color:var(--text-1);background:radial-gradient(ellipse 120% 80% at 50% -20%,oklch(26% .008 70/.6) 0%,transparent 55%),var(--bg);-webkit-font-smoothing:antialiased;min-height:100dvh;font-size:15px;line-height:1.6}a{color:inherit;text-decoration:none}:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--radius-xs)}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}.glass{background:var(--glass-bg);border:1px solid var(--glass-border);-webkit-backdrop-filter:blur(var(--glass-blur))}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}.sidebar.svelte-6dohdz{background:var(--sidebar-bg);border-right:1px solid var(--border);display:flex;flex-direction:column;padding:18px 14px;position:sticky;top:0;height:100dvh;overflow-y:auto;overflow-x:hidden}.sidebar.svelte-6dohdz:after{content:"";position:absolute;top:0;right:0;width:1px;height:100%;background:linear-gradient(to bottom,var(--accent-dim),transparent 60%);opacity:.4}.brand.svelte-6dohdz{display:flex;align-items:center;gap:11px;padding:4px 6px 14px}.monogram.svelte-6dohdz{width:34px;height:34px;border-radius:9px;display:grid;place-items:center;font-family:var(--font-display);font-weight:800;font-size:19px;color:var(--accent);background:var(--glass-bg-strong);border:1px solid var(--glass-border)}.brand-name.svelte-6dohdz{font-family:var(--font-display);font-weight:700;font-size:16px;color:var(--text-1)}.brand-byline.svelte-6dohdz{font-size:11px;color:var(--text-3)}.version-row.svelte-6dohdz{display:flex;align-items:center;justify-content:space-between;padding:0 6px 14px}.version.svelte-6dohdz{font-size:12px;color:var(--text-3)}.health-dot.svelte-6dohdz{width:8px;height:8px;border-radius:50%;background:var(--success);box-shadow:0 0 8px var(--success)}.nav.svelte-6dohdz{display:flex;flex-direction:column;gap:3px;margin-top:4px}.nav-item.svelte-6dohdz{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--radius-sm);color:var(--text-2);font-size:13.5px;font-weight:500;text-align:left;width:100%;transition:background var(--dur-sm) var(--ease),color var(--dur-sm) var(--ease)}.nav-item.svelte-6dohdz:hover{background:var(--surface-hover);color:var(--text-1)}.nav-item.active.svelte-6dohdz{background:var(--accent-muted);color:var(--accent)}.nav-item.svelte-6dohdz svg:where(.svelte-6dohdz){flex-shrink:0}.badge.svelte-7j44kq{display:inline-flex;align-items:center;padding:2px 9px;border-radius:999px;font-size:11.5px;font-weight:600;line-height:1.5}.neutral.svelte-7j44kq{background:var(--glass-bg-strong);color:var(--text-2);border:1px solid var(--glass-border)}.success.svelte-7j44kq{background:var(--success-bg);color:var(--success)}.error.svelte-7j44kq{background:var(--error-bg);color:var(--error)}.warning.svelte-7j44kq{background:color-mix(in oklch,var(--warning) 14%,transparent);color:var(--warning)}.accent.svelte-7j44kq{background:var(--accent-muted);color:var(--accent)}.btn.svelte-8a1c4v{display:inline-flex;align-items:center;gap:7px;border-radius:var(--radius-sm);font-weight:600;font-size:13.5px;cursor:pointer;border:1px solid transparent;transition:background var(--dur-sm) var(--ease),border-color var(--dur-sm) var(--ease),transform var(--dur-xs) var(--ease),opacity var(--dur-sm);-webkit-user-select:none;user-select:none}.btn.svelte-8a1c4v:active{transform:translateY(1px)}.btn.svelte-8a1c4v:disabled{opacity:.5;cursor:not-allowed}.md.svelte-8a1c4v{padding:9px 15px}.sm.svelte-8a1c4v{padding:6px 11px;font-size:12.5px}.lg.svelte-8a1c4v{padding:12px 20px;font-size:15px}.primary.svelte-8a1c4v{background:var(--accent);color:#211201}.primary.svelte-8a1c4v:hover:not(:disabled){background:var(--accent-dim)}.ghost.svelte-8a1c4v{background:transparent;border-color:var(--border-bright);color:var(--text-1)}.ghost.svelte-8a1c4v:hover:not(:disabled){background:var(--surface-hover)}.subtle.svelte-8a1c4v{background:var(--glass-bg-strong);border-color:var(--glass-border);color:var(--text-1)}.subtle.svelte-8a1c4v:hover:not(:disabled){background:var(--surface-hover)}.danger.svelte-8a1c4v{background:var(--error-bg);border-color:var(--error);color:var(--error)}.danger.svelte-8a1c4v:hover:not(:disabled){background:color-mix(in oklch,var(--error) 18%,transparent)}.card.svelte-it2i29{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);transition:border-color var(--dur-sm) var(--ease),transform var(--dur-sm) var(--ease)}.card.hover.svelte-it2i29:hover{border-color:var(--border-bright);transform:translateY(-1px)}.backdrop.svelte-1cuwqu{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:#05030280;display:flex;justify-content:flex-end;animation:svelte-1cuwqu-fade var(--dur-sm) var(--ease)}.drawer.svelte-1cuwqu{width:420px;max-width:92vw;height:100%;background:var(--surface);border-left:1px solid var(--border);display:flex;flex-direction:column;animation:svelte-1cuwqu-slide var(--dur-md) var(--ease)}.drawer.left.svelte-1cuwqu{margin-right:auto;border-left:none;border-right:1px solid var(--border)}.drawer-head.svelte-1cuwqu{padding:18px 20px;font-family:var(--font-display);font-weight:700;font-size:16px;border-bottom:1px solid var(--border)}.drawer-body.svelte-1cuwqu{padding:20px;overflow-y:auto}@keyframes svelte-1cuwqu-fade{0%{opacity:0}to{opacity:1}}@keyframes svelte-1cuwqu-slide{0%{transform:translate(100%)}to{transform:translate(0)}}.empty.svelte-16dv2jh{display:flex;flex-direction:column;align-items:center;gap:8px;padding:40px 20px;color:var(--text-3);text-align:center}.title.svelte-16dv2jh{font-weight:600;color:var(--text-2);font-size:14px}.sub.svelte-16dv2jh{font-size:13px;max-width:320px;line-height:1.5}.icon-btn.svelte-w50x32{display:inline-grid;place-items:center;width:32px;height:32px;border-radius:var(--radius-sm);background:var(--glass-bg-strong);border:1px solid var(--glass-border);color:var(--text-2);cursor:pointer;transition:background var(--dur-sm) var(--ease),color var(--dur-sm) var(--ease)}.icon-btn.svelte-w50x32:hover:not(:disabled){background:var(--surface-hover);color:var(--text-1)}.icon-btn.svelte-w50x32:disabled{opacity:.4;cursor:not-allowed}.input.svelte-1xuvd1z{width:100%;padding:9px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:13.5px;font-family:var(--font-body);transition:border-color var(--dur-sm) var(--ease),background var(--dur-sm) var(--ease)}.input.svelte-1xuvd1z:focus{outline:none;border-color:var(--accent);background:var(--surface-2)}.input.svelte-1xuvd1z::placeholder{color:var(--text-3)}.backdrop.svelte-1qk8a2o{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:#05030299;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);display:grid;place-items:center;animation:svelte-1qk8a2o-fade var(--dur-sm) var(--ease)}.modal.svelte-1qk8a2o{position:relative;min-width:320px;max-width:520px;width:90vw;border-radius:var(--radius);padding:22px;background:var(--surface)}.modal-head.svelte-1qk8a2o{font-family:var(--font-display);font-size:16px;font-weight:700;margin-bottom:14px;color:var(--text-1)}.modal-x.svelte-1qk8a2o{position:absolute;top:12px;right:14px;background:none;border:none;color:var(--text-3);font-size:22px;line-height:1;cursor:pointer}.modal-x.svelte-1qk8a2o:hover{color:var(--text-1)}@keyframes svelte-1qk8a2o-fade{0%{opacity:0}to{opacity:1}}.select.svelte-13vr5hb{padding:9px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:13.5px;font-family:var(--font-body);cursor:pointer}.select.svelte-13vr5hb:focus{outline:none;border-color:var(--accent)}.spinner-wrap.svelte-18351lc{display:flex;align-items:center;gap:10px;color:var(--text-2);font-size:13px;padding:8px 0}.spinner.svelte-18351lc{display:inline-block;border-radius:50%;border:2px solid var(--border);border-top-color:var(--accent);animation:svelte-18351lc-spin .7s linear infinite}@keyframes svelte-18351lc-spin{to{transform:rotate(360deg)}}.tabs.svelte-9oumej{display:inline-flex;gap:2px;padding:3px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm)}.tab.svelte-9oumej{padding:6px 14px;border-radius:7px;font-size:13px;font-weight:500;color:var(--text-2);background:transparent;border:none;cursor:pointer;transition:background var(--dur-sm) var(--ease),color var(--dur-sm) var(--ease)}.tab.svelte-9oumej:hover{color:var(--text-1)}.tab.active.svelte-9oumej{background:var(--accent-muted);color:var(--accent)}.toggle-wrap.svelte-km5m9b{display:inline-flex;align-items:center;gap:8px;cursor:pointer}.toggle.svelte-km5m9b{width:38px;height:21px;border-radius:999px;background:var(--surface-2);border:1px solid var(--border);position:relative;transition:background var(--dur-sm) var(--ease)}.toggle.on.svelte-km5m9b{background:var(--accent);border-color:var(--accent)}.knob.svelte-km5m9b{position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;background:var(--text-1);transition:transform var(--dur-sm) var(--ease)}.toggle.on.svelte-km5m9b .knob:where(.svelte-km5m9b){transform:translate(17px);background:#211201}.lbl.svelte-km5m9b{font-size:13px;color:var(--text-2)}.topbar.svelte-y7n507{display:flex;align-items:center;justify-content:space-between;padding:14px 26px;border-bottom:1px solid var(--border);background:var(--bg);position:sticky;top:0;z-index:20}.title.svelte-y7n507 h1:where(.svelte-y7n507){font-family:var(--font-display);font-size:19px;font-weight:700;color:var(--text-1)}.actions.svelte-y7n507{display:flex;align-items:center;gap:10px}.cmdk.svelte-y7n507{display:inline-flex;align-items:center;gap:8px;padding:7px 12px;border-radius:var(--radius-sm);background:var(--surface);border:1px solid var(--border);color:var(--text-2);font-size:13px;cursor:pointer;transition:border-color var(--dur-sm) var(--ease),color var(--dur-sm) var(--ease)}.cmdk.svelte-y7n507:hover{border-color:var(--border-bright);color:var(--text-1)}.kbd.svelte-y7n507{font-size:11px;padding:1px 6px;border-radius:4px;background:var(--surface-2);color:var(--text-3);border:1px solid var(--border)}.toaster.svelte-1kymlcg{position:fixed;bottom:20px;right:20px;z-index:80;display:flex;flex-direction:column;gap:8px;max-width:360px}.toast.svelte-1kymlcg{display:flex;align-items:center;gap:9px;padding:11px 15px;border-radius:var(--radius-sm);background:var(--surface);border:1px solid var(--border);box-shadow:0 8px 28px #06030080;font-size:13px;color:var(--text-1);cursor:pointer;animation:svelte-1kymlcg-pop var(--dur-sm) var(--ease)}.dot.svelte-1kymlcg{width:7px;height:7px;border-radius:50%;flex-shrink:0}.success.svelte-1kymlcg .dot:where(.svelte-1kymlcg){background:var(--success)}.error.svelte-1kymlcg .dot:where(.svelte-1kymlcg){background:var(--error)}.info.svelte-1kymlcg .dot:where(.svelte-1kymlcg){background:var(--accent)}@keyframes svelte-1kymlcg-pop{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.backdrop.svelte-wh9uu8{position:fixed;top:0;right:0;bottom:0;left:0;z-index:90;background:#0503028c;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);display:flex;align-items:flex-start;justify-content:center;padding-top:14vh}.palette.svelte-wh9uu8{width:540px;max-width:92vw;border-radius:var(--radius);padding:12px;background:var(--surface)}.q.svelte-wh9uu8{width:100%;padding:12px 14px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:14px}.q.svelte-wh9uu8:focus{outline:none;border-color:var(--accent)}.list.svelte-wh9uu8{margin-top:8px;display:flex;flex-direction:column;gap:2px;max-height:50vh;overflow-y:auto}.opt.svelte-wh9uu8{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:10px 13px;border-radius:var(--radius-sm);background:none;border:none;cursor:pointer;text-align:left}.opt.svelte-wh9uu8:hover{background:var(--surface-hover)}.lbl.svelte-wh9uu8{font-size:14px;font-weight:500;color:var(--text-1)}.hint.svelte-wh9uu8{font-size:12px;color:var(--text-3)}.none.svelte-wh9uu8{padding:14px;color:var(--text-3);font-size:13px;text-align:center}.panel.svelte-lftxrq{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:20px}.row.svelte-lftxrq{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}h3.svelte-lftxrq{font-family:var(--font-display);font-size:16px;font-weight:700;color:var(--text-1)}.note.svelte-lftxrq{font-size:12.5px;color:var(--text-3);background:var(--surface-2);padding:9px 12px;border-radius:var(--radius-sm);margin-bottom:12px}.note.svelte-lftxrq code:where(.svelte-lftxrq){font-family:ui-monospace,monospace;color:var(--accent)}.checks.svelte-lftxrq{display:flex;flex-direction:column;gap:9px}.check.svelte-lftxrq{display:flex;justify-content:space-between;font-size:13px}.k.svelte-lftxrq{color:var(--text-2)}.v.svelte-lftxrq{color:var(--text-1);font-family:ui-monospace,monospace;font-size:12px}.actions.svelte-lftxrq{margin-top:14px}.seg.svelte-1yfbpb7{display:inline-flex;gap:2px;padding:3px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm)}.opt.svelte-1yfbpb7{padding:6px 14px;border-radius:7px;font-size:13px;font-weight:500;color:var(--text-2);background:transparent;border:none;cursor:pointer;transition:background var(--dur-sm) var(--ease),color var(--dur-sm) var(--ease)}.opt.svelte-1yfbpb7:hover{color:var(--text-1)}.opt.active.svelte-1yfbpb7{background:var(--accent-muted);color:var(--accent)}.stat.svelte-14oot77{display:flex;flex-direction:column;gap:3px}.lbl.svelte-14oot77{font-size:12px;color:var(--text-3);letter-spacing:.01em}.num.svelte-14oot77{font-family:var(--font-display);font-size:26px;font-weight:800;color:var(--text-1);line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}.sub.svelte-14oot77{font-size:11.5px;color:var(--text-3)}.grid.svelte-9jn9wt{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}@media(max-width:920px){.grid.svelte-9jn9wt{grid-template-columns:repeat(2,1fr)}}@media(max-width:520px){.grid.svelte-9jn9wt{grid-template-columns:1fr}}.heat.svelte-1ryzkww{overflow-x:auto;padding-bottom:4px}.months.svelte-1ryzkww{display:flex;gap:4px;margin-bottom:6px;min-width:max-content}.month.svelte-1ryzkww{font-size:10.5px;color:var(--text-3);flex:0 0 13px;width:13px;line-height:1;white-space:nowrap;overflow:visible}.month.svelte-1ryzkww:not(.has){visibility:hidden}.weeks.svelte-1ryzkww{display:flex;gap:4px;min-width:max-content}.col.svelte-1ryzkww{display:flex;flex-direction:column;gap:4px}.cell.svelte-1ryzkww{width:13px;height:13px;border-radius:3px;border:1px solid var(--border);transition:transform var(--dur-xs) var(--ease)}.cell.svelte-1ryzkww:not(.empty):hover{transform:scale(1.18);border-color:var(--border-bright)}.cell.empty.svelte-1ryzkww{border-color:transparent;background:transparent}.legend.svelte-1ryzkww{display:flex;align-items:center;gap:5px;margin-top:14px;font-size:11.5px;color:var(--text-3)}.key.svelte-1ryzkww{width:12px;height:12px;border-radius:3px;border:1px solid var(--border)}.chart.svelte-1ozbyr9{display:flex;gap:10px;align-items:stretch}.scroll.svelte-1ozbyr9{flex:1;overflow-x:auto;padding-bottom:2px}.bars.svelte-1ozbyr9{position:relative;display:flex;align-items:stretch;gap:3px;min-width:max-content;height:270px}.gridlines.svelte-1ozbyr9{position:absolute;top:0;right:0;bottom:20px;left:0;display:flex;flex-direction:column;justify-content:space-between;pointer-events:none}.gridline.svelte-1ozbyr9{height:1px;background:var(--border, #ddd);opacity:.5}.bar-col.svelte-1ozbyr9{position:relative;flex:1 0 11px;min-width:9px;display:flex;flex-direction:column}.bar-area.svelte-1ozbyr9{flex:1;display:flex;align-items:flex-end}.bar.svelte-1ozbyr9{width:100%;border-radius:4px 4px 2px 2px;background:linear-gradient(180deg,var(--accent),var(--accent-dim));opacity:.85;transition:opacity var(--dur-sm) var(--ease),transform var(--dur-sm) var(--ease);min-height:2px}.bar-col.svelte-1ozbyr9:hover .bar:where(.svelte-1ozbyr9){opacity:1;transform:scaleY(1.02)}.xlabel.svelte-1ozbyr9{height:16px;flex:none;font-size:10.5px;color:var(--text-3);white-space:nowrap;text-align:center;line-height:16px}.yaxis.svelte-1ozbyr9{display:flex;flex-direction:column;justify-content:space-between;font-size:10.5px;color:var(--text-3);height:270px;padding-bottom:16px;text-align:right;min-width:34px}.list.svelte-1ca0tub{display:flex;flex-direction:column;gap:12px}.row.svelte-1ca0tub{display:grid;grid-template-columns:12px 1fr auto 160px;align-items:center;gap:12px}.dot.svelte-1ca0tub{width:10px;height:10px;border-radius:50%;flex:none}.id.svelte-1ca0tub{min-width:0}.name.svelte-1ca0tub{font-size:13.5px;font-weight:600;color:var(--text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.meta.svelte-1ca0tub{font-size:11.5px;color:var(--text-3);text-transform:capitalize}.nums.svelte-1ca0tub{display:flex;gap:12px;font-family:ui-monospace,monospace;font-size:12px;color:var(--text-2)}.in.svelte-1ca0tub{color:var(--text-2)}.out.svelte-1ca0tub{color:var(--text-3)}.share.svelte-1ca0tub{display:flex;align-items:center;gap:8px}.track.svelte-1ca0tub{flex:1;height:6px;background:var(--surface-2);border-radius:4px;overflow:hidden}.fill.svelte-1ca0tub{height:100%;border-radius:4px}.pct.svelte-1ca0tub{font-size:12px;font-weight:600;color:var(--text-1);min-width:34px;text-align:right}@media(max-width:640px){.row.svelte-1ca0tub{grid-template-columns:12px 1fr auto}.share.svelte-1ca0tub{display:none}}.head.svelte-1thed0a{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;margin-bottom:22px;flex-wrap:wrap}.title.svelte-1thed0a h2:where(.svelte-1thed0a){font-family:var(--font-display);font-size:22px;font-weight:700;color:var(--text-1)}.title-row.svelte-1thed0a{display:flex;align-items:center;gap:10px}.sample.svelte-1thed0a{font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--accent);background:var(--accent-muted);border:1px solid var(--border-glow);padding:2px 8px;border-radius:999px}.title.svelte-1thed0a p:where(.svelte-1thed0a){color:var(--text-3);font-size:13px;margin-top:6px;text-transform:capitalize}.section.svelte-1thed0a,.mt{margin-top:28px}.dash.svelte-1thed0a{display:flow-root}.sec-head.svelte-1thed0a{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:16px}.sec-head.svelte-1thed0a h3:where(.svelte-1thed0a){font-family:var(--font-display);font-size:15px;font-weight:700;color:var(--text-1)}.hint.svelte-1thed0a{font-size:12px;color:var(--text-3)}.cols.svelte-1thed0a{display:grid;grid-template-columns:1fr 1fr;gap:16px}.quick.svelte-1thed0a{display:flex;flex-wrap:wrap;gap:8px}.muted.svelte-1thed0a{color:var(--text-3);font-size:13px}.grid.svelte-1thed0a{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}.stat.svelte-1thed0a{display:flex;flex-direction:column;gap:2px}.num.svelte-1thed0a{font-family:var(--font-display);font-size:28px;font-weight:800;color:var(--text-1)}.lbl.svelte-1thed0a{font-size:12.5px;color:var(--text-3)}.loading.svelte-1thed0a{margin-top:28px;display:flex;justify-content:center}@media(max-width:920px){.cols.svelte-1thed0a{grid-template-columns:1fr}.grid.svelte-1thed0a{grid-template-columns:repeat(2,1fr)}}.logo.svelte-1va9fof{display:inline-grid;place-items:center;border-radius:9px;flex-shrink:0;overflow:hidden;box-shadow:0 2px 8px #06030059}.svg.svelte-1va9fof svg{width:100%;height:100%;color:#fff}.mono.svelte-1va9fof{font-family:var(--font-display);font-weight:800;color:#fff}.card.svelte-1p75598{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;display:flex;flex-direction:column;gap:12px;transition:border-color var(--dur-sm) var(--ease)}.card.svelte-1p75598:hover{border-color:var(--border-bright)}.head.svelte-1p75598{display:flex;align-items:center;gap:12px}.meta.svelte-1p75598{flex:1;min-width:0}.name.svelte-1p75598{font-weight:600;font-size:14.5px;color:var(--text-1)}.sub.svelte-1p75598{font-size:12px;color:var(--text-3)}.id.svelte-1p75598{font-family:var(--font-body);opacity:.8}.models.svelte-1p75598{display:flex;flex-wrap:wrap;gap:6px}.chip.svelte-1p75598{font-size:11.5px;padding:3px 9px;border-radius:7px;background:var(--glass-bg-strong);border:1px solid var(--glass-border);color:var(--text-2);max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chip.more.svelte-1p75598{color:var(--accent)}.chip.empty.svelte-1p75598{color:var(--text-3);font-style:italic}.actions.svelte-1p75598{display:flex;align-items:center;gap:8px}.keylink.svelte-1p75598{font-size:12px;font-weight:600;color:var(--accent);text-decoration:none;white-space:nowrap}.keylink.svelte-1p75598:hover{text-decoration:underline}.lbl.svelte-263z8{display:block;font-size:12.5px;font-weight:600;color:var(--text-2);margin-bottom:6px}.sel.svelte-263z8{width:100%;padding:9px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:13.5px}.row.svelte-263z8{display:flex}.hint-link.svelte-263z8{display:inline-block;margin-top:7px;font-size:12.5px;font-weight:600;color:var(--accent);text-decoration:none}.hint-link.svelte-263z8:hover{text-decoration:underline}.head.svelte-1sgc4qo{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:20px}h2.svelte-1sgc4qo{font-family:var(--font-display);font-size:20px;font-weight:700;color:var(--text-1)}.sub.svelte-1sgc4qo{font-size:13px;color:var(--text-3);margin-top:4px;max-width:460px}.acts.svelte-1sgc4qo{display:flex;gap:8px}.grid.svelte-1sgc4qo{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}.backdrop.svelte-1sgc4qo{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:#05030299;display:grid;place-items:center}.modal.svelte-1sgc4qo{width:420px;max-width:90vw;padding:22px;border-radius:var(--radius);background:var(--surface);display:flex;flex-direction:column;gap:12px}.modal.svelte-1sgc4qo h3:where(.svelte-1sgc4qo){font-family:var(--font-display);font-size:16px}.code.svelte-1sgc4qo{font-size:13px;color:var(--text-2)}.note.svelte-1sgc4qo{font-size:12px;color:var(--text-3)}.group.svelte-xohxs0{display:inline-flex;gap:5px;flex-wrap:wrap}.row.svelte-19h4ccs{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:var(--radius-sm);border:1px solid transparent;transition:background var(--dur-sm) var(--ease),border-color var(--dur-sm) var(--ease)}.row.clickable.svelte-19h4ccs{cursor:pointer}.row.clickable.svelte-19h4ccs:hover{background:var(--surface-hover);border-color:var(--border)}.info.svelte-19h4ccs{flex:1;min-width:0}.name.svelte-19h4ccs{font-weight:500;font-size:13.5px;color:var(--text-1)}.pid.svelte-19h4ccs{color:var(--text-3);font-weight:400;margin-left:6px;font-size:12px}.meta.svelte-19h4ccs{font-size:12px;color:var(--text-3);margin-top:2px}.tags.svelte-19h4ccs{flex-shrink:0}.star.svelte-19h4ccs{background:none;border:none;font-size:17px;color:var(--text-3);cursor:pointer;transition:color var(--dur-sm) var(--ease)}.star.on.svelte-19h4ccs{color:var(--accent)}.open.svelte-19h4ccs{flex-shrink:0;padding:5px 11px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--surface-2);color:var(--text-2);font-size:12px;cursor:pointer;transition:border-color var(--dur-sm) var(--ease),color var(--dur-sm) var(--ease)}.open.svelte-19h4ccs:hover{border-color:var(--border-bright);color:var(--text-1)}.star.svelte-19h4ccs:hover{color:var(--accent)}.filters.svelte-1y45iff{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}.q.svelte-1y45iff{flex:1;min-width:180px;padding:9px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:13.5px}.q.svelte-1y45iff:focus{outline:none;border-color:var(--accent)}.s.svelte-1y45iff{padding:9px 11px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:13px;cursor:pointer}.s.svelte-1y45iff:focus{outline:none;border-color:var(--accent)}.stack.svelte-1efx48s{display:flex;flex-direction:column;gap:16px}.grid.svelte-1efx48s{display:grid;grid-template-columns:1fr 1fr;gap:14px}.h.svelte-1efx48s{font-size:11.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-3);margin-bottom:4px}.v.svelte-1efx48s{font-size:13.5px;color:var(--text-1)}.v.mono.svelte-1efx48s{font-family:ui-monospace,monospace;font-size:12.5px;background:var(--surface-2);padding:4px 8px;border-radius:6px;display:inline-block;word-break:break-all}.sub.svelte-1efx48s{color:var(--text-3)}.chips.svelte-1efx48s{display:flex;flex-wrap:wrap;gap:5px}.item.svelte-drwign{display:flex;align-items:center;gap:10px;padding:9px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:grab;transition:border-color var(--dur-sm) var(--ease),background var(--dur-sm) var(--ease)}.item.svelte-drwign:hover{border-color:var(--border-bright)}.item.svelte-drwign:active{cursor:grabbing}.handle.svelte-drwign{color:var(--text-3);font-size:13px;letter-spacing:-2px}.idx.svelte-drwign{font-size:12px;color:var(--text-3);width:16px;text-align:center}.meta.svelte-drwign{flex:1;min-width:0}.name.svelte-drwign{font-size:13px;font-weight:500;color:var(--text-1)}.sub.svelte-drwign{font-size:11.5px;color:var(--text-3)}.x.svelte-drwign{background:none;border:none;color:var(--text-3);font-size:18px;cursor:pointer;line-height:1}.x.svelte-drwign:hover{color:var(--error)}.list.svelte-156gwh2{display:flex;flex-direction:column;gap:7px}.cap.svelte-156gwh2{font-size:12px;color:var(--text-3);text-align:right;margin-top:2px}.meter.svelte-19jc277{font-size:12px;color:var(--text-2)}.top.svelte-19jc277{display:flex;justify-content:space-between;margin-bottom:5px}.n.svelte-19jc277{color:var(--text-3)}.track.svelte-19jc277{height:6px;border-radius:999px;background:var(--surface-2);overflow:hidden}.fill.svelte-19jc277{height:100%;border-radius:999px;background:var(--accent);transition:width var(--dur-md) var(--ease)}.fill.full.svelte-19jc277{background:var(--warning)}.head.svelte-p8xmpw{margin-bottom:18px}h2.svelte-p8xmpw{font-family:var(--font-display);font-size:20px;font-weight:700;color:var(--text-1)}.sub.svelte-p8xmpw{font-size:13px;color:var(--text-3);margin-top:4px}.layout.svelte-p8xmpw{display:grid;grid-template-columns:1fr 360px;gap:18px;align-items:start}.fav-head.svelte-p8xmpw{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}h3.svelte-p8xmpw{font-family:var(--font-display);font-size:15px;font-weight:700}@media(max-width:920px){.layout.svelte-p8xmpw{grid-template-columns:1fr}}.card.svelte-1gp522a{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;display:flex;flex-direction:column;gap:12px}.card.svelte-1gp522a:hover{border-color:var(--border-bright)}.head.svelte-1gp522a{display:flex;align-items:center;gap:12px}.meta.svelte-1gp522a{flex:1}.name.svelte-1gp522a{font-weight:600;font-size:14.5px;color:var(--text-1)}.sub.svelte-1gp522a{font-size:12px;color:var(--text-3)}.path.svelte-1gp522a{font-size:11.5px;color:var(--text-3);background:var(--surface-2);padding:5px 9px;border-radius:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.install.svelte-1gp522a{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.cmd.svelte-1gp522a{font-family:var(--font-mono, ui-monospace, monospace);font-size:11.5px;color:var(--text-2);background:var(--surface-2);border:1px solid var(--border);border-radius:6px;padding:5px 9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}.copy.svelte-1gp522a{font-size:11px;font-weight:600;color:var(--accent);background:none;border:none;cursor:pointer;padding:2px 4px}.copy.svelte-1gp522a:hover{text-decoration:underline}.install-link.svelte-1gp522a{font-size:12.5px;font-weight:600;color:var(--accent);text-decoration:none}.install-link.svelte-1gp522a:hover{text-decoration:underline}.actions.svelte-1gp522a{display:flex;gap:8px;justify-content:flex-end}.head.svelte-ishglm{margin-bottom:18px}h2.svelte-ishglm{font-family:var(--font-display);font-size:20px;font-weight:700;color:var(--text-1)}.sub.svelte-ishglm{font-size:13px;color:var(--text-3);margin-top:4px;max-width:480px}.grid.svelte-ishglm{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}.opts.svelte-ishglm{display:flex;flex-direction:column;gap:10px;align-items:stretch}.lbl.svelte-ishglm{font-size:12.5px;font-weight:600;color:var(--text-2)}.folder.svelte-ishglm{display:flex;gap:8px}.recents.svelte-ishglm{display:flex;flex-direction:column;gap:4px}.recent.svelte-ishglm{text-align:left;font-size:11.5px;color:var(--text-3);background:var(--surface-2);border:1px solid var(--border);border-radius:6px;padding:5px 9px;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.recent.svelte-ishglm:hover{color:var(--text-1)}.row.svelte-ishglm{display:flex}.panel.svelte-swldy1{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:20px}.row.svelte-swldy1{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}h3.svelte-swldy1{font-family:var(--font-display);font-size:16px;font-weight:700;color:var(--text-1)}.desc.svelte-swldy1{font-size:13px;color:var(--text-3);margin-top:4px;max-width:460px}.urls.svelte-swldy1{margin-top:16px;display:flex;flex-direction:column;gap:8px}.url.svelte-swldy1{display:flex;gap:10px;align-items:center}.lbl.svelte-swldy1{font-size:11px;text-transform:uppercase;color:var(--text-3);width:70px;flex-shrink:0}code.svelte-swldy1{font-family:ui-monospace,monospace;font-size:12px;background:var(--surface-2);padding:4px 9px;border-radius:6px;color:var(--accent);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.summary.svelte-swldy1{margin-top:12px;font-size:12.5px;color:var(--text-2);background:var(--surface-2);padding:9px 12px;border-radius:var(--radius-sm)}.opts.svelte-swldy1{margin-top:16px;display:flex;flex-direction:column;gap:12px;align-items:flex-start}.lbl.svelte-swldy1{font-size:12.5px;font-weight:600;color:var(--text-2)}.inp.svelte-swldy1{width:100%;padding:9px 12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-size:13.5px}.inp.svelte-swldy1:focus{outline:none;border-color:var(--accent)}.actions.svelte-swldy1{margin-top:18px}.head.svelte-124gvcr{margin-bottom:18px}h2.svelte-124gvcr{font-family:var(--font-display);font-size:20px;font-weight:700;color:var(--text-1)}.sub.svelte-124gvcr{font-size:13px;color:var(--text-3);margin-top:4px;max-width:480px}.head.svelte-15j4tnx{margin-bottom:18px}h2.svelte-15j4tnx{font-family:var(--font-display);font-size:20px;font-weight:700;color:var(--text-1)}.sub.svelte-15j4tnx{font-size:13px;color:var(--text-3);margin-top:4px}h3.svelte-15j4tnx{font-family:var(--font-display);font-size:15px;font-weight:700;margin-bottom:12px}.cols.svelte-15j4tnx{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}.stack.svelte-15j4tnx{display:flex;flex-direction:column;gap:14px}.line.svelte-15j4tnx{display:flex;justify-content:space-between;align-items:center;font-size:13.5px;color:var(--text-2);gap:12px}.kv.svelte-15j4tnx{display:flex;gap:10px;margin-top:12px;font-size:12px}.kv.svelte-15j4tnx code:where(.svelte-15j4tnx){font-family:ui-monospace,monospace;color:var(--accent);background:var(--surface-2);padding:3px 7px;border-radius:5px}.muted.svelte-15j4tnx{font-size:12.5px;color:var(--text-3);margin-bottom:14px;line-height:1.5}.acts.svelte-15j4tnx{display:flex;gap:8px}.sec-head.svelte-15j4tnx{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}.preset.svelte-15j4tnx{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid var(--border)}.pname.svelte-15j4tnx{font-size:13.5px;font-weight:600;color:var(--text-1);display:block}.psub.svelte-15j4tnx{font-size:11.5px;color:var(--text-3)}.pacts.svelte-15j4tnx{display:flex;gap:6px}.dryrun.svelte-15j4tnx{font-family:ui-monospace,monospace;font-size:11px;color:var(--text-2);background:var(--surface-2);padding:8px 10px;border-radius:6px;white-space:pre-wrap;margin-bottom:10px}.ta.svelte-15j4tnx{width:100%;min-height:160px;padding:10px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-1);font-family:ui-monospace,monospace;font-size:12px;resize:vertical}.ta.svelte-15j4tnx:focus{outline:none;border-color:var(--accent)}.lbl.svelte-15j4tnx{display:block;font-size:12.5px;font-weight:600;color:var(--text-2);margin-bottom:6px}.row.svelte-15j4tnx{display:flex}@media(max-width:920px){.cols.svelte-15j4tnx{grid-template-columns:1fr}}.app-shell.svelte-1n46o8q{display:grid;grid-template-columns:var(--sidebar-w) 1fr;min-height:100dvh}.main.svelte-1n46o8q{display:flex;flex-direction:column;min-width:0}.content.svelte-1n46o8q{padding:26px 30px 60px;max-width:1180px;width:100%}@media(max-width:760px){.app-shell.svelte-1n46o8q{grid-template-columns:1fr}.content.svelte-1n46o8q{padding:18px 16px 50px}}