@jacobbd/relay-ai 0.6.0 → 0.6.1

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,7 +2,7 @@
2
2
  import {
3
3
  getTemplateById,
4
4
  init_provider_templates
5
- } from "./chunk-MVBA7ABV.js";
5
+ } from "./chunk-EJONCU3B.js";
6
6
 
7
7
  // src/constants.ts
8
8
  import { homedir } from "os";
@@ -11,7 +11,7 @@ import { join } from "path";
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "@jacobbd/relay-ai",
14
- version: "0.6.0",
14
+ version: "0.6.1",
15
15
  publishConfig: {
16
16
  access: "public"
17
17
  },
@@ -1784,6 +1784,10 @@ async function getSavedServerPassword() {
1784
1784
  }
1785
1785
  return null;
1786
1786
  }
1787
+ function getEnvServerPassword() {
1788
+ const value = process.env["RELAY_AI_SERVER_PASSWORD"]?.trim();
1789
+ return value || null;
1790
+ }
1787
1791
  async function setSavedServerPassword(password) {
1788
1792
  const keyring = await getServerPasswordKeyring();
1789
1793
  if (keyring) {
@@ -1867,15 +1871,15 @@ import { join as join4 } from "path";
1867
1871
  import { execFileSync } from "child_process";
1868
1872
  import { existsSync as existsSync2 } from "fs";
1869
1873
  function findBinaryOnPath(name, fallbackPaths, options = {}) {
1870
- const isWindows3 = options.isWindows ?? process.platform === "win32";
1874
+ const isWindows2 = options.isWindows ?? process.platform === "win32";
1871
1875
  const exists = options.exists ?? existsSync2;
1872
1876
  const runWhich = options.runWhich ?? ((binary, win) => execFileSync(win ? "where.exe" : "which", [binary], {
1873
1877
  encoding: "utf8",
1874
1878
  stdio: ["pipe", "pipe", "pipe"]
1875
1879
  }));
1876
1880
  try {
1877
- const lines = runWhich(name, isWindows3).trim().split("\n").map((line) => line.trim()).filter(Boolean);
1878
- const path = (isWindows3 ? lines.find((line) => line.toLowerCase().endsWith(".cmd")) : null) ?? lines[0];
1881
+ const lines = runWhich(name, isWindows2).trim().split("\n").map((line) => line.trim()).filter(Boolean);
1882
+ const path = (isWindows2 ? lines.find((line) => line.toLowerCase().endsWith(".cmd")) : null) ?? lines[0];
1879
1883
  if (path && (!options.verifyWhichResult || exists(path))) return path;
1880
1884
  } catch {
1881
1885
  }
@@ -7377,7 +7381,7 @@ async function fetchTemplateModels(template, apiKey, baseUrlOverride, extraHeade
7377
7381
  models: [],
7378
7382
  baseUrl: "",
7379
7383
  error: "This provider needs a base URL.",
7380
- hint: "Use relay-ai providers import from OpenCode for advanced setups."
7384
+ hint: template.urlPrompt ? "Enter the API base URL when adding this provider." : "This template is missing a default base URL \u2014 report a bug."
7381
7385
  };
7382
7386
  }
7383
7387
  if (template.modelSource === "static-seed") {
@@ -8233,7 +8237,7 @@ async function refreshProviderModels(providerId, apiKey, registry = loadRegistry
8233
8237
  }
8234
8238
  const source = resolveModelSource(provider);
8235
8239
  if (source === "manual-only") {
8236
- const hint = provider.templateId === "google-vertex" || provider.id === "google-vertex" || provider.api.npm === "@ai-sdk/google-vertex" ? "Vertex uses gcloud credentials \u2014 re-import from OpenCode or configure env auth." : "Manual-only provider \u2014 model list is not refreshed automatically.";
8240
+ const hint = provider.templateId === "google-vertex" || provider.id === "google-vertex" || provider.api.npm === "@ai-sdk/google-vertex" ? "Vertex uses gcloud credentials \u2014 use relay-ai server --vertex, or refresh after configuring ADC." : "Manual-only provider \u2014 model list is not refreshed automatically.";
8237
8241
  return {
8238
8242
  id: provider.id,
8239
8243
  name: provider.name,
@@ -8464,6 +8468,44 @@ async function ensureOpencodeCloudProviders(hasOpencodeKey) {
8464
8468
  }
8465
8469
  return { seeded, refreshed };
8466
8470
  }
8471
+ async function addOpencodeCloudFromApiKey(apiKey) {
8472
+ const trimmed = apiKey.trim();
8473
+ if (!trimmed) {
8474
+ return { added: false, error: "API key cannot be empty." };
8475
+ }
8476
+ const saved = await saveToCredentialStore(trimmed);
8477
+ if (!saved) {
8478
+ return {
8479
+ added: false,
8480
+ error: "Could not save API key.",
8481
+ hint: "Ensure RELAY_AI_HOME is writable (Docker uses secrets.json when no OS keyring)."
8482
+ };
8483
+ }
8484
+ process.env["OPENCODE_API_KEY"] = trimmed;
8485
+ const zenStub = addZenRegistryStub();
8486
+ const goStub = addGoRegistryStub();
8487
+ if (!zenStub.added && !goStub.added) {
8488
+ return {
8489
+ added: false,
8490
+ error: "OpenCode Zen / Go is already configured.",
8491
+ hint: "Remove zen or go first, or use Refresh on the provider cards."
8492
+ };
8493
+ }
8494
+ const registry = loadRegistry();
8495
+ const refreshResults = [
8496
+ await refreshProviderModels("zen", trimmed, registry),
8497
+ await refreshProviderModels("go", trimmed, registry)
8498
+ ];
8499
+ const modelCount = refreshResults.reduce((total, result) => total + (result.modelCount ?? 0), 0);
8500
+ const failed = refreshResults.filter((result) => !result.ok);
8501
+ return {
8502
+ added: true,
8503
+ modelCount,
8504
+ ...failed.length > 0 ? {
8505
+ hint: `Providers added, but ${failed.length} catalog refresh${failed.length === 1 ? "" : "es"} failed \u2014 try Refresh on the provider card.`
8506
+ } : {}
8507
+ };
8508
+ }
8467
8509
  function toggleProviderEnabled(id) {
8468
8510
  const registry = loadRegistry();
8469
8511
  const provider = registry.providers.find((p8) => p8.id === id);
@@ -9484,7 +9526,7 @@ async function getServerPasswordForQuickMode(mode, passwordOverride) {
9484
9526
  if (mode === "local") return { password: null, wasSaved: false };
9485
9527
  const trimmedOverride = passwordOverride?.trim();
9486
9528
  if (trimmedOverride) return { password: trimmedOverride, wasSaved: false };
9487
- const fromEnv = process.env["RELAY_AI_SERVER_PASSWORD"]?.trim();
9529
+ const fromEnv = getEnvServerPassword();
9488
9530
  if (fromEnv) return { password: fromEnv, wasSaved: false };
9489
9531
  const savedPassword = await getSavedServerPassword();
9490
9532
  if (savedPassword) return { password: savedPassword, wasSaved: true };
@@ -9637,8 +9679,8 @@ async function resolveServerUpstreamApiKey() {
9637
9679
  }));
9638
9680
  if (apiKey) {
9639
9681
  const isMac = process.platform === "darwin";
9640
- const isWindows3 = process.platform === "win32";
9641
- const storeName = isMac ? "macOS Keychain" : isWindows3 ? "Windows Credential Manager" : "Secret Service";
9682
+ const isWindows2 = process.platform === "win32";
9683
+ const storeName = isMac ? "macOS Keychain" : isWindows2 ? "Windows Credential Manager" : "Secret Service";
9642
9684
  p4.log.success(`Found key in ${storeName}`);
9643
9685
  return apiKey;
9644
9686
  }
@@ -9961,97 +10003,6 @@ function buildHttpProxyRoutes(providers, favorites, selected, max = MAX_MODEL_CA
9961
10003
  return { routes, unavailable, unsupported };
9962
10004
  }
9963
10005
 
9964
- // src/opencode-serve.ts
9965
- import { execSync as execSync2, spawn as spawn2 } from "child_process";
9966
- import { existsSync as existsSync11 } from "fs";
9967
- import { homedir as homedir7 } from "os";
9968
- import { join as join11 } from "path";
9969
- var isWindows2 = process.platform === "win32";
9970
- var OPENCODE_FALLBACK_PATHS = isWindows2 ? [
9971
- join11(process.env["APPDATA"] ?? homedir7(), "npm", "opencode.cmd"),
9972
- join11(process.env["APPDATA"] ?? homedir7(), "npm", "opencode"),
9973
- join11(homedir7(), "AppData", "Roaming", "npm", "opencode.cmd")
9974
- ] : [
9975
- join11(homedir7(), ".opencode", "bin", "opencode"),
9976
- join11(homedir7(), ".local", "bin", "opencode"),
9977
- join11(homedir7(), ".npm", "bin", "opencode"),
9978
- "/usr/local/bin/opencode",
9979
- "/opt/homebrew/bin/opencode"
9980
- ];
9981
- function findOpencodeBinary() {
9982
- try {
9983
- const result = execSync2(isWindows2 ? "where.exe opencode" : "which opencode", {
9984
- encoding: "utf8",
9985
- stdio: ["pipe", "pipe", "pipe"]
9986
- });
9987
- const lines = result.trim().split("\n").map((l) => l.trim()).filter(Boolean);
9988
- const path = (isWindows2 ? lines.find((l) => l.toLowerCase().endsWith(".cmd")) : null) ?? lines[0];
9989
- if (path) return path;
9990
- } catch {
9991
- }
9992
- for (const path of OPENCODE_FALLBACK_PATHS) {
9993
- if (existsSync11(path)) return path;
9994
- }
9995
- return null;
9996
- }
9997
- async function fetchRawOpencodeProviders() {
9998
- const binary = findOpencodeBinary();
9999
- if (!binary) return null;
10000
- return new Promise((resolve) => {
10001
- let child = null;
10002
- let settled = false;
10003
- const TIMEOUT_MS = 1e4;
10004
- const finish = (value) => {
10005
- if (settled) return;
10006
- settled = true;
10007
- clearTimeout(timer);
10008
- try {
10009
- child?.kill();
10010
- } catch {
10011
- }
10012
- resolve(value);
10013
- };
10014
- const timer = setTimeout(() => {
10015
- finish(null);
10016
- }, TIMEOUT_MS);
10017
- try {
10018
- child = isWindows2 ? spawn2("cmd.exe", ["/c", binary, "serve", "--port", "0"], { stdio: ["pipe", "pipe", "pipe"] }) : spawn2(binary, ["serve", "--port", "0"], { stdio: ["pipe", "pipe", "pipe"] });
10019
- } catch {
10020
- finish(null);
10021
- return;
10022
- }
10023
- const portRegex = /opencode server listening on http:\/\/127\.0\.0\.1:(\d+)/;
10024
- let portFound = false;
10025
- let stdoutBuf = "";
10026
- const onData = (chunk) => {
10027
- if (portFound) return;
10028
- stdoutBuf += chunk.toString();
10029
- const match = portRegex.exec(stdoutBuf);
10030
- if (!match) return;
10031
- portFound = true;
10032
- const port = match[1];
10033
- fetch(`http://127.0.0.1:${port}/config/providers`).then((res) => res.json()).then((data) => {
10034
- const raw = data.providers;
10035
- if (!Array.isArray(raw)) {
10036
- finish(null);
10037
- return;
10038
- }
10039
- finish(raw);
10040
- }).catch(() => {
10041
- finish(null);
10042
- });
10043
- };
10044
- child.stdout?.on("data", onData);
10045
- child.stderr?.on("data", onData);
10046
- child.on("error", () => {
10047
- finish(null);
10048
- });
10049
- child.on("exit", () => {
10050
- if (!settled) finish(null);
10051
- });
10052
- });
10053
- }
10054
-
10055
10006
  // src/registry/add-template.ts
10056
10007
  async function probeTemplatePackage(template) {
10057
10008
  if (!template.supported) return template.unsupportedReason ?? "Provider is not supported yet.";
@@ -10075,14 +10026,17 @@ function filterAnonymousFreeModels(models, template) {
10075
10026
  })));
10076
10027
  }
10077
10028
  async function addProviderFromTemplate(template, apiKey, opts) {
10078
- const packageError = await probeTemplatePackage(template);
10079
- if (packageError) {
10080
- return { added: false, error: packageError };
10081
- }
10082
10029
  const trimmedKey = apiKey.trim();
10083
10030
  if (!trimmedKey && !template.apiKeyOptional) {
10084
10031
  return { added: false, error: "API key cannot be empty." };
10085
10032
  }
10033
+ if (template.modelSource === "zen-go-api") {
10034
+ return addOpencodeCloudFromApiKey(trimmedKey);
10035
+ }
10036
+ const packageError = await probeTemplatePackage(template);
10037
+ if (packageError) {
10038
+ return { added: false, error: packageError };
10039
+ }
10086
10040
  const registry = loadRegistry();
10087
10041
  const existing = registry.providers.find((p8) => p8.id === template.id);
10088
10042
  if (existing && !opts?.replaceExisting) {
@@ -10159,80 +10113,6 @@ import pc6 from "picocolors";
10159
10113
  import * as p5 from "@clack/prompts";
10160
10114
  import open3 from "open";
10161
10115
  init_provider_templates();
10162
-
10163
- // src/registry/auth-broker.ts
10164
- import { spawn as spawn3 } from "child_process";
10165
- async function runOpencodeAuthBroker(providerId, options = {}) {
10166
- const binary = findOpencodeBinary();
10167
- if (!binary) {
10168
- throw new Error("OpenCode CLI not found. Install from https://opencode.ai or use native device-code auth.");
10169
- }
10170
- const args = ["auth", "login", "--provider", providerId];
10171
- if (options.method) args.push("-m", options.method);
10172
- const exitCode = await new Promise((resolve, reject) => {
10173
- const child = spawn3(binary, args, { stdio: "inherit" });
10174
- child.on("error", reject);
10175
- child.on("exit", (code) => resolve(code ?? 1));
10176
- });
10177
- if (exitCode !== 0) {
10178
- throw new Error(`OpenCode auth login failed (exit ${exitCode})`);
10179
- }
10180
- const authFile = readOpencodeAuthFile();
10181
- const entry = authFile?.entries[providerId];
10182
- if (!isOpencodeOAuth(entry)) {
10183
- throw new Error(`No OAuth token found for "${providerId}" after OpenCode login`);
10184
- }
10185
- return entry;
10186
- }
10187
-
10188
- // src/registry/convert.ts
10189
- function modelToCached(model) {
10190
- return {
10191
- id: model.id,
10192
- name: model.name,
10193
- upstreamModelId: model.upstreamModelId,
10194
- family: model.family,
10195
- brand: model.brand,
10196
- contextWindow: model.contextWindow,
10197
- cost: model.cost,
10198
- isFree: model.isFree,
10199
- freeStatus: model.freeStatus,
10200
- modelFormat: model.modelFormat,
10201
- npm: model.npm,
10202
- apiUrl: model.apiBaseUrl,
10203
- supportedParameters: model.supportedParameters,
10204
- reasoning: model.reasoning,
10205
- interleavedReasoningField: model.interleavedReasoningField,
10206
- useResponsesLite: model.useResponsesLite,
10207
- preferWebSockets: model.preferWebSockets
10208
- };
10209
- }
10210
- function localProviderToRegistry(provider, opts) {
10211
- if (!isValidProviderId(provider.id)) return null;
10212
- if (provider.models.length === 0) return null;
10213
- const first = provider.models[0];
10214
- const apiUrl = (first.apiBaseUrl ?? first.baseUrl)?.trim();
10215
- const authType = opts?.authType ?? "api";
10216
- return {
10217
- id: provider.id,
10218
- templateId: opts?.templateId ?? provider.id,
10219
- name: provider.name,
10220
- enabled: true,
10221
- authRef: opts?.authRef ?? `keyring:provider:${provider.id}`,
10222
- authType,
10223
- api: {
10224
- npm: first.npm,
10225
- ...apiUrl ? { url: apiUrl } : {}
10226
- },
10227
- addedAt: (/* @__PURE__ */ new Date()).toISOString(),
10228
- modelsCache: {
10229
- fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
10230
- models: provider.models.map(modelToCached)
10231
- }
10232
- };
10233
- }
10234
-
10235
- // src/registry/provider-auth.ts
10236
10116
  var OPENAI_DISPLAY = "OpenAI ChatGPT Plus/Pro";
10237
10117
  var PROVIDER_DISPLAY = {
10238
10118
  xai: "xAI Grok (SuperGrok)",
@@ -10366,30 +10246,8 @@ async function upsertOAuthProvider(providerId, cred) {
10366
10246
  const templateId = providerId.replace(/-oauth$/, "") || providerId;
10367
10247
  const registry = loadRegistry();
10368
10248
  const authRef = oauthAuthRef(registryId);
10369
- const template = getTemplateById(templateId);
10249
+ const template = getTemplateById(templateId) ?? getTemplateById(registryId);
10370
10250
  let entry = registry.providers.find((pr) => pr.id === registryId);
10371
- if (!entry) {
10372
- const raw = await fetchRawOpencodeProviders();
10373
- if (raw) {
10374
- const { providers } = buildImportProviderList(raw, { [providerId]: cred });
10375
- const lp = providers.find((pr) => pr.id === registryId || pr.id === providerId);
10376
- if (lp) {
10377
- const converted = localProviderToRegistry(lp, { authType: "oauth", authRef });
10378
- if (converted) {
10379
- entry = {
10380
- ...converted,
10381
- id: registryId,
10382
- templateId,
10383
- name: oauthDisplayName(registryId, converted.name),
10384
- api: {
10385
- ...converted.api,
10386
- ...template?.headers ? { headers: { ...template.headers, ...converted.api.headers } } : {}
10387
- }
10388
- };
10389
- }
10390
- }
10391
- }
10392
- }
10393
10251
  if (!entry) {
10394
10252
  if (!template) {
10395
10253
  throw new Error(`Provider "${providerId}" is not in your registry and has no template`);
@@ -10397,7 +10255,7 @@ async function upsertOAuthProvider(providerId, cred) {
10397
10255
  const displayName = oauthDisplayName(registryId, template.name);
10398
10256
  entry = {
10399
10257
  id: registryId,
10400
- templateId,
10258
+ templateId: template.id,
10401
10259
  name: displayName,
10402
10260
  enabled: true,
10403
10261
  authRef,
@@ -10410,7 +10268,7 @@ async function upsertOAuthProvider(providerId, cred) {
10410
10268
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
10411
10269
  };
10412
10270
  } else {
10413
- entry = { ...entry, authType: "oauth", authRef, templateId };
10271
+ entry = { ...entry, authType: "oauth", authRef, templateId: entry.templateId ?? templateId };
10414
10272
  }
10415
10273
  const idx = registry.providers.findIndex((pr) => pr.id === registryId);
10416
10274
  if (idx >= 0) registry.providers[idx] = entry;
@@ -10421,50 +10279,16 @@ async function upsertOAuthProvider(providerId, cred) {
10421
10279
  async function authenticateProvider(providerId, options = {}) {
10422
10280
  const registryId = toOAuthRegistryId(providerId);
10423
10281
  if (!supportsNativeOAuth(providerId)) {
10424
- if (findOpencodeBinary()) {
10425
- const cred2 = await runOpencodeAuthBroker(providerId, { method: options.brokerMethod });
10426
- let brokerDiagMsg = "";
10427
- const saved2 = await saveProviderCredential(
10428
- oauthAuthRef(registryId),
10429
- oauthCredentialToKeychainJson(cred2),
10430
- (msg) => {
10431
- brokerDiagMsg = msg;
10432
- }
10433
- );
10434
- if (!saved2) {
10435
- p5.log.warn(`Could not save OAuth tokens \u2014 ${brokerDiagMsg || "session may not persist."}`);
10436
- }
10437
- const registryProvider2 = await upsertOAuthProvider(providerId, cred2);
10438
- return { providerId: registryId, credential: cred2, registryProvider: registryProvider2 };
10439
- }
10440
10282
  throw new Error(
10441
- `Native OAuth is only built in for xai and openai. Install OpenCode for other OAuth providers.`
10283
+ `OAuth for "${providerId}" is not built into relay-ai. Add an API-key provider with relay-ai providers add, or run relay-ai providers import if you already configured it in the OpenCode CLI.`
10442
10284
  );
10443
10285
  }
10444
- let method = options.method;
10445
- if (isBrowserRedirectOAuth(providerId)) {
10446
- if (method === "broker") {
10447
- throw new Error(`Via OpenCode is not supported for "${providerId}". Use the built-in OAuth flow.`);
10448
- }
10449
- method = "native";
10450
- }
10451
- if (!method) {
10452
- const hasOpencode = findOpencodeBinary() !== null;
10453
- if (hasOpencode) {
10454
- const choice = await p5.select({
10455
- message: "How would you like to sign in?",
10456
- options: [
10457
- { value: "native", label: "Device code (recommended)", hint: "Works on SSH/VPS \u2014 open URL on any device" },
10458
- { value: "broker", label: "Via OpenCode", hint: "Uses opencode auth login" }
10459
- ]
10460
- });
10461
- if (p5.isCancel(choice)) throw new Error("Cancelled");
10462
- method = choice;
10463
- } else {
10464
- method = "native";
10465
- }
10286
+ if (options.method === "broker") {
10287
+ throw new Error(
10288
+ "OpenCode auth broker is no longer used for providers. Use the built-in OAuth flow, or relay-ai providers import for OpenCode CLI configs."
10289
+ );
10466
10290
  }
10467
- const cred = method === "broker" ? await runOpencodeAuthBroker(providerId, { method: options.brokerMethod }) : isBrowserRedirectOAuth(providerId) ? await runNativeBrowserOAuth(providerId) : await runNativeDeviceCode(providerId);
10291
+ const cred = isBrowserRedirectOAuth(providerId) ? await runNativeBrowserOAuth(providerId) : await runNativeDeviceCode(providerId);
10468
10292
  let nativeDiagMsg = "";
10469
10293
  const saved = await saveProviderCredential(
10470
10294
  oauthAuthRef(registryId),
@@ -10492,25 +10316,23 @@ function providerAuthHelpText() {
10492
10316
 
10493
10317
  ${pc6.bold("Usage:")}
10494
10318
  relay-ai providers auth <id>
10495
- relay-ai providers auth xai-oauth --native
10496
- relay-ai providers auth openai --broker
10319
+ relay-ai providers auth xai-oauth
10320
+ relay-ai providers auth openai-oauth
10497
10321
  relay-ai providers auth github-copilot
10498
10322
 
10499
- ${pc6.bold("Options:")}
10500
- --native Use built-in OAuth flow
10501
- --broker Delegate to OpenCode auth login
10502
-
10503
10323
  ${pc6.bold("Device code (works on SSH/VPS):")}
10504
10324
  xai-oauth SuperGrok / X Premium (device code at x.ai/device)
10505
10325
  openai-oauth ChatGPT Plus/Pro (device code at auth.openai.com/codex/device)
10506
- github-copilot GitHub Copilot Free or paid (device code at github.com/login/device)`;
10326
+ github-copilot GitHub Copilot Free or paid (device code at github.com/login/device)
10327
+
10328
+ ${pc6.dim("OpenCode CLI configs: use")} relay-ai providers import${pc6.dim(" (optional one-time migration).")}`;
10507
10329
  }
10508
10330
 
10509
10331
  // src/codex/app-launch.ts
10510
- import { execSync as execSync3, spawn as spawn4 } from "child_process";
10511
- import { existsSync as existsSync12, readdirSync, statSync as statSync3 } from "fs";
10512
- import { homedir as homedir8 } from "os";
10513
- import { join as join12 } from "path";
10332
+ import { execSync as execSync2, spawn as spawn2 } from "child_process";
10333
+ import { existsSync as existsSync11, readdirSync, statSync as statSync3 } from "fs";
10334
+ import { homedir as homedir7 } from "os";
10335
+ import { join as join11 } from "path";
10514
10336
  import * as p6 from "@clack/prompts";
10515
10337
  var CODEX_BUNDLE_ID = "com.openai.codex";
10516
10338
  var DARWIN_APP_NAMES = ["ChatGPT", "Codex"];
@@ -10521,7 +10343,7 @@ function codexAppSupported() {
10521
10343
  }
10522
10344
  }
10523
10345
  function run(cmd, encoding = "utf8") {
10524
- return execSync3(cmd, { encoding, stdio: ["pipe", "pipe", "pipe"] }).trim();
10346
+ return execSync2(cmd, { encoding, stdio: ["pipe", "pipe", "pipe"] }).trim();
10525
10347
  }
10526
10348
  function runPowerShell(script) {
10527
10349
  return run(`powershell.exe -NoProfile -Command ${JSON.stringify(script)}`);
@@ -10529,33 +10351,33 @@ function runPowerShell(script) {
10529
10351
  function darwinAppCandidates() {
10530
10352
  return DARWIN_APP_NAMES.flatMap((name) => [
10531
10353
  `/Applications/${name}.app`,
10532
- join12(homedir8(), "Applications", `${name}.app`)
10354
+ join11(homedir7(), "Applications", `${name}.app`)
10533
10355
  ]);
10534
10356
  }
10535
10357
  function winLocalAppData() {
10536
- return process.env.LOCALAPPDATA ?? join12(homedir8(), "AppData", "Local");
10358
+ return process.env.LOCALAPPDATA ?? join11(homedir7(), "AppData", "Local");
10537
10359
  }
10538
10360
  function winCodexExeCandidates() {
10539
10361
  const local = winLocalAppData();
10540
10362
  const bases = WIN_APP_NAMES.flatMap((name) => [
10541
- join12(local, "Programs", name),
10542
- join12(local, "Programs", `OpenAI ${name}`),
10543
- join12(local, name),
10544
- join12(local, `OpenAI ${name}`),
10545
- join12(local, "OpenAI", name)
10363
+ join11(local, "Programs", name),
10364
+ join11(local, "Programs", `OpenAI ${name}`),
10365
+ join11(local, name),
10366
+ join11(local, `OpenAI ${name}`),
10367
+ join11(local, "OpenAI", name)
10546
10368
  ]);
10547
- bases.push(join12(local, "openai-codex-electron"), join12(local, "openai-chatgpt-electron"));
10369
+ bases.push(join11(local, "openai-codex-electron"), join11(local, "openai-chatgpt-electron"));
10548
10370
  const out = [];
10549
10371
  for (const base of bases) {
10550
10372
  for (const name of WIN_APP_NAMES) {
10551
- out.push(join12(base, `${name}.exe`));
10373
+ out.push(join11(base, `${name}.exe`));
10552
10374
  }
10553
10375
  try {
10554
- if (existsSync12(base)) {
10376
+ if (existsSync11(base)) {
10555
10377
  for (const dir of readdirSync(base)) {
10556
10378
  if (dir.startsWith("app-")) {
10557
10379
  for (const name of WIN_APP_NAMES) {
10558
- out.push(join12(base, dir, `${name}.exe`));
10380
+ out.push(join11(base, dir, `${name}.exe`));
10559
10381
  }
10560
10382
  }
10561
10383
  }
@@ -10569,7 +10391,7 @@ function mdfindCodexApp() {
10569
10391
  try {
10570
10392
  const out = run(`mdfind "kMDItemCFBundleIdentifier == '${CODEX_BUNDLE_ID}'"`);
10571
10393
  const first = out.split("\n").map((l) => l.trim()).find(Boolean);
10572
- return first && existsSync12(first) ? first : null;
10394
+ return first && existsSync11(first) ? first : null;
10573
10395
  } catch {
10574
10396
  return null;
10575
10397
  }
@@ -10577,14 +10399,14 @@ function mdfindCodexApp() {
10577
10399
  function findCodexApp() {
10578
10400
  if (process.platform === "darwin") {
10579
10401
  for (const path of darwinAppCandidates()) {
10580
- if (existsSync12(path)) return path;
10402
+ if (existsSync11(path)) return path;
10581
10403
  }
10582
10404
  return mdfindCodexApp();
10583
10405
  }
10584
10406
  if (process.platform === "win32") {
10585
10407
  for (const path of winCodexExeCandidates()) {
10586
10408
  try {
10587
- if (existsSync12(path) && statSync3(path).isFile()) return path;
10409
+ if (existsSync11(path) && statSync3(path).isFile()) return path;
10588
10410
  } catch {
10589
10411
  }
10590
10412
  }
@@ -10654,15 +10476,15 @@ async function waitForQuit(timeoutMs) {
10654
10476
  function openCodexAppAt(path) {
10655
10477
  if (process.platform === "darwin") {
10656
10478
  if (path.endsWith(".app")) {
10657
- execSync3(`open ${JSON.stringify(path)}`, { stdio: "inherit" });
10479
+ execSync2(`open ${JSON.stringify(path)}`, { stdio: "inherit" });
10658
10480
  } else {
10659
- execSync3(`open -b ${CODEX_BUNDLE_ID}`, { stdio: "inherit" });
10481
+ execSync2(`open -b ${CODEX_BUNDLE_ID}`, { stdio: "inherit" });
10660
10482
  }
10661
10483
  return;
10662
10484
  }
10663
10485
  if (process.platform === "win32") {
10664
10486
  if (path.startsWith("shell:AppsFolder\\")) {
10665
- spawn4("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
10487
+ spawn2("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
10666
10488
  } else {
10667
10489
  runPowerShell(`Start-Process -FilePath '${path.replace(/'/g, "''")}'`);
10668
10490
  }
@@ -10679,9 +10501,9 @@ function openCodexApp() {
10679
10501
  }
10680
10502
  function darwinQuit() {
10681
10503
  try {
10682
- execSync3(`osascript -e 'tell application "Codex" to quit'`, { stdio: "pipe" });
10504
+ execSync2(`osascript -e 'tell application "Codex" to quit'`, { stdio: "pipe" });
10683
10505
  } catch {
10684
- execSync3(`osascript -e 'tell application id "${CODEX_BUNDLE_ID}" to quit'`, { stdio: "pipe" });
10506
+ execSync2(`osascript -e 'tell application id "${CODEX_BUNDLE_ID}" to quit'`, { stdio: "pipe" });
10685
10507
  }
10686
10508
  }
10687
10509
  function winQuitGraceful() {
@@ -10729,10 +10551,10 @@ function codexAppInstallHint() {
10729
10551
  }
10730
10552
 
10731
10553
  // src/claude-desktop/app-launch.ts
10732
- import { execSync as execSync4, spawn as spawn5 } from "child_process";
10733
- import { existsSync as existsSync13, readdirSync as readdirSync2, statSync as statSync4 } from "fs";
10734
- import { homedir as homedir9 } from "os";
10735
- import { join as join13 } from "path";
10554
+ import { execSync as execSync3, spawn as spawn3 } from "child_process";
10555
+ import { existsSync as existsSync12, readdirSync as readdirSync2, statSync as statSync4 } from "fs";
10556
+ import { homedir as homedir8 } from "os";
10557
+ import { join as join12 } from "path";
10736
10558
  import * as p7 from "@clack/prompts";
10737
10559
  var CLAUDE_BUNDLE_ID = "com.anthropic.claudefordesktop";
10738
10560
  function claudeAppSupported() {
@@ -10741,7 +10563,7 @@ function claudeAppSupported() {
10741
10563
  }
10742
10564
  }
10743
10565
  function run2(cmd, encoding = "utf8") {
10744
- return execSync4(cmd, { encoding, stdio: ["pipe", "pipe", "pipe"] }).trim();
10566
+ return execSync3(cmd, { encoding, stdio: ["pipe", "pipe", "pipe"] }).trim();
10745
10567
  }
10746
10568
  function runPowerShell2(script) {
10747
10569
  return run2(`powershell.exe -NoProfile -Command ${JSON.stringify(script)}`);
@@ -10749,26 +10571,26 @@ function runPowerShell2(script) {
10749
10571
  function darwinAppCandidates2() {
10750
10572
  return [
10751
10573
  "/Applications/Claude.app",
10752
- join13(homedir9(), "Applications", "Claude.app")
10574
+ join12(homedir8(), "Applications", "Claude.app")
10753
10575
  ];
10754
10576
  }
10755
10577
  function winLocalAppData2() {
10756
- return process.env.LOCALAPPDATA ?? join13(homedir9(), "AppData", "Local");
10578
+ return process.env.LOCALAPPDATA ?? join12(homedir8(), "AppData", "Local");
10757
10579
  }
10758
10580
  function winClaudeExeCandidates() {
10759
10581
  const local = winLocalAppData2();
10760
10582
  const bases = [
10761
- join13(local, "Programs", "Claude"),
10762
- join13(local, "Claude")
10583
+ join12(local, "Programs", "Claude"),
10584
+ join12(local, "Claude")
10763
10585
  ];
10764
10586
  const out = [];
10765
10587
  for (const base of bases) {
10766
- out.push(join13(base, "Claude.exe"));
10588
+ out.push(join12(base, "Claude.exe"));
10767
10589
  try {
10768
- if (existsSync13(base)) {
10590
+ if (existsSync12(base)) {
10769
10591
  for (const name of readdirSync2(base)) {
10770
10592
  if (name.startsWith("app-")) {
10771
- out.push(join13(base, name, "Claude.exe"));
10593
+ out.push(join12(base, name, "Claude.exe"));
10772
10594
  }
10773
10595
  }
10774
10596
  }
@@ -10781,7 +10603,7 @@ function mdfindClaudeApp() {
10781
10603
  try {
10782
10604
  const out = run2(`mdfind "kMDItemCFBundleIdentifier == '${CLAUDE_BUNDLE_ID}'"`);
10783
10605
  const first = out.split("\n").map((l) => l.trim()).find(Boolean);
10784
- return first && existsSync13(first) ? first : null;
10606
+ return first && existsSync12(first) ? first : null;
10785
10607
  } catch {
10786
10608
  return null;
10787
10609
  }
@@ -10789,14 +10611,14 @@ function mdfindClaudeApp() {
10789
10611
  function findClaudeApp() {
10790
10612
  if (process.platform === "darwin") {
10791
10613
  for (const path of darwinAppCandidates2()) {
10792
- if (existsSync13(path)) return path;
10614
+ if (existsSync12(path)) return path;
10793
10615
  }
10794
10616
  return mdfindClaudeApp();
10795
10617
  }
10796
10618
  if (process.platform === "win32") {
10797
10619
  for (const path of winClaudeExeCandidates()) {
10798
10620
  try {
10799
- if (existsSync13(path) && statSync4(path).isFile()) return path;
10621
+ if (existsSync12(path) && statSync4(path).isFile()) return path;
10800
10622
  } catch {
10801
10623
  }
10802
10624
  }
@@ -10860,15 +10682,15 @@ async function waitForQuit2(timeoutMs) {
10860
10682
  function openClaudeAppAt(path) {
10861
10683
  if (process.platform === "darwin") {
10862
10684
  if (path.endsWith(".app")) {
10863
- execSync4(`open ${JSON.stringify(path)}`, { stdio: "inherit" });
10685
+ execSync3(`open ${JSON.stringify(path)}`, { stdio: "inherit" });
10864
10686
  } else {
10865
- execSync4(`open -b ${CLAUDE_BUNDLE_ID}`, { stdio: "inherit" });
10687
+ execSync3(`open -b ${CLAUDE_BUNDLE_ID}`, { stdio: "inherit" });
10866
10688
  }
10867
10689
  return;
10868
10690
  }
10869
10691
  if (process.platform === "win32") {
10870
10692
  if (path.startsWith("shell:AppsFolder\\")) {
10871
- spawn5("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
10693
+ spawn3("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
10872
10694
  } else {
10873
10695
  runPowerShell2(`Start-Process -FilePath '${path.replace(/'/g, "''")}'`);
10874
10696
  }
@@ -10885,9 +10707,9 @@ function openClaudeApp() {
10885
10707
  }
10886
10708
  function darwinQuit2() {
10887
10709
  try {
10888
- execSync4(`osascript -e 'tell application "Claude" to quit'`, { stdio: "pipe" });
10710
+ execSync3(`osascript -e 'tell application "Claude" to quit'`, { stdio: "pipe" });
10889
10711
  } catch {
10890
- execSync4(`osascript -e 'tell application id "${CLAUDE_BUNDLE_ID}" to quit'`, { stdio: "pipe" });
10712
+ execSync3(`osascript -e 'tell application id "${CLAUDE_BUNDLE_ID}" to quit'`, { stdio: "pipe" });
10891
10713
  }
10892
10714
  }
10893
10715
  function winQuitGraceful2() {
@@ -10991,6 +10813,7 @@ export {
10991
10813
  recordLaunchFolder,
10992
10814
  recordLaunchSelection,
10993
10815
  getSavedServerPassword,
10816
+ getEnvServerPassword,
10994
10817
  setSavedServerPassword,
10995
10818
  getServerExposedProviders,
10996
10819
  setServerExposedProviders,
@@ -11039,10 +10862,7 @@ export {
11039
10862
  freeStatusLabel,
11040
10863
  refreshModelsDevCacheAsync,
11041
10864
  shouldHideModel,
11042
- findOpencodeBinary,
11043
- fetchRawOpencodeProviders,
11044
10865
  zenRegistryStub,
11045
- localProviderToRegistry,
11046
10866
  isLikelyPlaceholderKey,
11047
10867
  resolveRefreshCredential,
11048
10868
  oauthAuthRef,
@@ -11106,9 +10926,8 @@ export {
11106
10926
  refreshProviderModels,
11107
10927
  refreshAllProviderModels,
11108
10928
  removeProviderFromRegistry,
11109
- addZenRegistryStub,
11110
- addGoRegistryStub,
11111
10929
  ensureOpencodeCloudProviders,
10930
+ addOpencodeCloudFromApiKey,
11112
10931
  toggleProviderEnabled,
11113
10932
  startServer,
11114
10933
  filterServerModelsByProviders,
@@ -11143,4 +10962,4 @@ export {
11143
10962
  supportsClaudeTransparentMode,
11144
10963
  buildHttpProxyRoutes
11145
10964
  };
11146
- //# sourceMappingURL=chunk-SV2Y6OCD.js.map
10965
+ //# sourceMappingURL=chunk-P4S42QJK.js.map