openmausbot 0.1.69 → 0.1.70

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.
@@ -18475,6 +18475,11 @@ function windowsKnownDirs() {
18475
18475
  join7(home, "go", "bin")
18476
18476
  ];
18477
18477
  }
18478
+ function registerPathDir(dir) {
18479
+ if (registeredDirs.includes(dir)) return;
18480
+ registeredDirs.unshift(dir);
18481
+ resetPathCache();
18482
+ }
18478
18483
  function resetPathCache() {
18479
18484
  cached2 = null;
18480
18485
  probed = false;
@@ -18482,6 +18487,7 @@ function resetPathCache() {
18482
18487
  function augmentedPath() {
18483
18488
  if (cached2 === null) {
18484
18489
  cached2 = mergePaths([
18490
+ ...registeredDirs.filter((d) => existsSync5(d)),
18485
18491
  ...process.env.OMB_EXTRA_PATH ? process.env.OMB_EXTRA_PATH.split(delimiter3) : [],
18486
18492
  ...process.env.PATH ? process.env.PATH.split(delimiter3) : [],
18487
18493
  // Keep the last successful login-shell result while a rescan starts a
@@ -18646,13 +18652,14 @@ function resolveCliSpawn(cli, args) {
18646
18652
  }
18647
18653
  return resolveWord(cli, args);
18648
18654
  }
18649
- var cached2, probed, loginShellPath;
18655
+ var cached2, probed, loginShellPath, registeredDirs;
18650
18656
  var init_env_path = __esm({
18651
18657
  "server/env-path.ts"() {
18652
18658
  "use strict";
18653
18659
  cached2 = null;
18654
18660
  probed = false;
18655
18661
  loginShellPath = null;
18662
+ registeredDirs = [];
18656
18663
  }
18657
18664
  });
18658
18665
 
@@ -18766,7 +18773,124 @@ var init_procs = __esm({
18766
18773
  }
18767
18774
  });
18768
18775
 
18776
+ // server/engine-install.ts
18777
+ import { existsSync as existsSync6, mkdirSync as mkdirSync6 } from "node:fs";
18778
+ import { join as join9 } from "node:path";
18779
+ import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
18780
+ function enginesPrefix(baseDir = DATA_DIR) {
18781
+ return join9(baseDir, "tools", "npm");
18782
+ }
18783
+ function enginesBinDir(baseDir = DATA_DIR, platform = process.platform) {
18784
+ return platform === "win32" ? enginesPrefix(baseDir) : join9(enginesPrefix(baseDir), "bin");
18785
+ }
18786
+ function npmPackageOf(install) {
18787
+ const line = install?.command?.linux ?? install?.command?.darwin ?? install?.command?.win32;
18788
+ const match = line ? /^npm install -g ((?:@[\w.-]+\/)?[\w.-]+)$/.exec(line.trim()) : null;
18789
+ return match ? match[1] : null;
18790
+ }
18791
+ function npmAvailable() {
18792
+ return findCliCandidates("npm").length > 0;
18793
+ }
18794
+ function serverInstallFor(install, npmPresent = npmAvailable()) {
18795
+ if (!install || install.managed) return null;
18796
+ const pkg = npmPackageOf(install);
18797
+ return pkg && npmPresent ? { package: pkg } : null;
18798
+ }
18799
+ function installNpmEngine(pkg, options = {}) {
18800
+ const key = `${options.baseDir ?? DATA_DIR} ${pkg}`;
18801
+ const existing = running.get(key);
18802
+ if (existing) return existing;
18803
+ const run3 = installOnce(pkg, options).finally(() => running.delete(key));
18804
+ running.set(key, run3);
18805
+ return run3;
18806
+ }
18807
+ async function installOnce(pkg, options) {
18808
+ const prefix = enginesPrefix(options.baseDir);
18809
+ mkdirSync6(prefix, { recursive: true });
18810
+ const env = {
18811
+ ...options.env ?? process.env,
18812
+ PATH: options.path ?? augmentedPath(),
18813
+ NO_COLOR: "1",
18814
+ npm_config_update_notifier: "false",
18815
+ npm_config_fund: "false",
18816
+ npm_config_audit: "false"
18817
+ };
18818
+ stripWorkspaceCredentialEnv(env);
18819
+ const args = ["install", "-g", "--prefix", prefix, "--loglevel=error", `--allow-scripts=${pkg}`, `${pkg}@latest`];
18820
+ const result = await runNpm(args, env, prefix, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
18821
+ if (result.code !== 0) {
18822
+ throw new Error(`npm could not install ${pkg} on this server.${tail(result.output)}`);
18823
+ }
18824
+ registerPathDir(enginesBinDir(options.baseDir));
18825
+ resetPathCache();
18826
+ if (options.cli) {
18827
+ const binDir = enginesBinDir(options.baseDir);
18828
+ if (!findCliCandidates(options.cli).some((path3) => path3.startsWith(binDir))) {
18829
+ throw new Error(`${pkg} installed, but it did not provide a \`${options.cli}\` command. Check the package name in this engine's install descriptor.`);
18830
+ }
18831
+ }
18832
+ }
18833
+ function tail(output) {
18834
+ const clean = stripVTControlCharacters3(output).trim();
18835
+ if (!clean) return "";
18836
+ const lines = clean.split(/\r?\n/).filter((line) => line.trim()).slice(-6);
18837
+ return `
18838
+ ${lines.join("\n").slice(-600)}`;
18839
+ }
18840
+ function runNpm(args, env, cwd, timeoutMs) {
18841
+ return new Promise((resolveRun, rejectRun) => {
18842
+ let child;
18843
+ try {
18844
+ child = spawnCli("npm", args, { env, cwd, stdio: ["pipe", "pipe", "pipe"] });
18845
+ } catch {
18846
+ rejectRun(new Error("npm could not start on this server. Install Node.js with npm for the user running OpenMausBot, then try again."));
18847
+ return;
18848
+ }
18849
+ child.stdin.end();
18850
+ let output = "";
18851
+ const receive = (chunk) => {
18852
+ if (output.length < MAX_OUTPUT) output += chunk.toString("utf8").slice(0, MAX_OUTPUT - output.length);
18853
+ };
18854
+ child.stdout.on("data", receive);
18855
+ child.stderr.on("data", receive);
18856
+ let timedOut = false;
18857
+ const timer = setTimeout(() => {
18858
+ timedOut = true;
18859
+ void killCliTree(child);
18860
+ }, timeoutMs);
18861
+ timer.unref();
18862
+ child.once("error", (error51) => {
18863
+ clearTimeout(timer);
18864
+ rejectRun(new Error(error51.code === "ENOENT" ? "npm is not installed on this server. Install Node.js with npm for the user running OpenMausBot, then try again." : "npm could not start on this server. Check that Node.js is installed for the user running OpenMausBot."));
18865
+ });
18866
+ child.once("close", (code) => {
18867
+ clearTimeout(timer);
18868
+ if (timedOut) {
18869
+ rejectRun(new Error("The install took too long and was stopped. Check the server's network connection and try again."));
18870
+ return;
18871
+ }
18872
+ resolveRun({ code, output });
18873
+ });
18874
+ });
18875
+ }
18876
+ var MAX_OUTPUT, DEFAULT_TIMEOUT_MS, running;
18877
+ var init_engine_install = __esm({
18878
+ "server/engine-install.ts"() {
18879
+ "use strict";
18880
+ init_config();
18881
+ init_env_path();
18882
+ init_procs();
18883
+ MAX_OUTPUT = 64 * 1024;
18884
+ DEFAULT_TIMEOUT_MS = 10 * 6e4;
18885
+ running = /* @__PURE__ */ new Map();
18886
+ }
18887
+ });
18888
+
18769
18889
  // server/harness/registry.ts
18890
+ function withServerInstall(install, npmPresent) {
18891
+ const server = install ? serverInstallFor(install, npmPresent) : null;
18892
+ return server ? { ...install, server } : install;
18893
+ }
18770
18894
  function cliDefaultOf(driver) {
18771
18895
  if (!driver) return void 0;
18772
18896
  try {
@@ -18785,13 +18909,21 @@ var init_registry = __esm({
18785
18909
  "server/harness/registry.ts"() {
18786
18910
  "use strict";
18787
18911
  init_env_path();
18912
+ init_engine_install();
18788
18913
  ProviderRegistry = class {
18789
18914
  byId = /* @__PURE__ */ new Map();
18790
18915
  /** decoded per-instance `cli` overrides, for describe() — drivers spawn
18791
18916
  * from their own config; this map only reports what was configured */
18792
18917
  cliByInstance = /* @__PURE__ */ new Map();
18793
18918
  driversByKind;
18794
- constructor(drivers) {
18919
+ /** Where Settings-driven npm installs go; the data directory by default. */
18920
+ enginesBaseDir;
18921
+ /** Whether npm is on this machine; injectable because the PATH scan also
18922
+ * looks in standard install locations, which tests cannot empty. */
18923
+ npmPresent;
18924
+ constructor(drivers, options = {}) {
18925
+ this.enginesBaseDir = options.enginesBaseDir;
18926
+ this.npmPresent = options.npmAvailable ?? npmAvailable;
18795
18927
  this.driversByKind = new Map(drivers.map((d) => [d.driverKind, d]));
18796
18928
  }
18797
18929
  async load(configs) {
@@ -18866,10 +18998,20 @@ var init_registry = __esm({
18866
18998
  await instance.refreshModels?.();
18867
18999
  return true;
18868
19000
  }
19001
+ /** A driver's own installer (a managed download) first; otherwise the
19002
+ * app's npm prefix, when the driver's install one-liner is an npm package
19003
+ * and npm is on PATH. False means Settings has nothing to offer here. */
18869
19004
  async installRuntime(instanceId) {
18870
- const instance = this.get(instanceId);
18871
- if (!instance?.installRuntime) return false;
18872
- await instance.installRuntime();
19005
+ const entry = this.byId.get(instanceId);
19006
+ if (!entry) return false;
19007
+ if (entry.live?.installRuntime) {
19008
+ await entry.live.installRuntime();
19009
+ return true;
19010
+ }
19011
+ const driver = this.driversByKind.get(entry.shadow?.driverKind ?? entry.live.driverKind);
19012
+ const server = serverInstallFor(driver?.install, this.npmPresent());
19013
+ if (!server) return false;
19014
+ await installNpmEngine(server.package, { baseDir: this.enginesBaseDir, cli: cliDefaultOf(driver) });
18873
19015
  return true;
18874
19016
  }
18875
19017
  async startAuthentication(instanceId) {
@@ -18904,6 +19046,7 @@ var init_registry = __esm({
18904
19046
  candidatesByName.set(name, found);
18905
19047
  return found;
18906
19048
  };
19049
+ const npmPresent = this.npmPresent();
18907
19050
  return Promise.all(
18908
19051
  this.entries().map(async (entry) => {
18909
19052
  const driver = this.driversByKind.get(entry.shadow?.driverKind ?? entry.live.driverKind);
@@ -18917,7 +19060,7 @@ var init_registry = __esm({
18917
19060
  capabilities: { computerMcp: false, agentsMcp: false, localComputerMcp: false },
18918
19061
  // an unknown driver has no driver record, hence no install path
18919
19062
  access: driver?.metadata.access ?? "subscription",
18920
- install: driver?.install,
19063
+ install: withServerInstall(driver?.install, npmPresent),
18921
19064
  cli: entry.shadow.cli,
18922
19065
  cliDefault: cliDefaultOf(driver),
18923
19066
  // a shadow is exactly the "your CLI is broken, pick another"
@@ -18951,7 +19094,7 @@ var init_registry = __esm({
18951
19094
  approvalReview: inst.reviewPermission !== void 0
18952
19095
  },
18953
19096
  access: driver?.metadata.access ?? "subscription",
18954
- install: driver?.install,
19097
+ install: withServerInstall(driver?.install, npmPresent),
18955
19098
  authentication: inst.startAuthentication ? {
18956
19099
  method: inst.getAuthentication && inst.completeAuthentication ? "paste-code" : inst.getAuthentication ? "device-code" : "browser",
18957
19100
  // a link and a callback URL (managed engines)
@@ -18986,7 +19129,7 @@ var init_registry = __esm({
18986
19129
  // server/drivers/local-inject.ts
18987
19130
  import { readFileSync as readFileSync5 } from "node:fs";
18988
19131
  import { homedir as homedir6 } from "node:os";
18989
- import { join as join9 } from "node:path";
19132
+ import { join as join10 } from "node:path";
18990
19133
  function contextWindowsFromPs(extra) {
18991
19134
  const out = /* @__PURE__ */ new Map();
18992
19135
  const rec = extra && typeof extra === "object" ? extra : null;
@@ -19071,7 +19214,7 @@ function firstUnslothToken(row) {
19071
19214
  function readUnslothKey(env) {
19072
19215
  const home = env.HOME || env.USERPROFILE || homedir6();
19073
19216
  try {
19074
- const raw = JSON.parse(readFileSync5(join9(home, ".unsloth", "studio", "auth", "agent_api_key.json"), "utf8"));
19217
+ const raw = JSON.parse(readFileSync5(join10(home, ".unsloth", "studio", "auth", "agent_api_key.json"), "utf8"));
19075
19218
  if (raw.servers && typeof raw.servers === "object") {
19076
19219
  const servers = raw.servers;
19077
19220
  for (const url2 of ["http://127.0.0.1:8888", "http://localhost:8888"]) {
@@ -19130,12 +19273,12 @@ function loadedIdsFromPayloads(_host, catalog, extra) {
19130
19273
  };
19131
19274
  if (extra && typeof extra === "object") {
19132
19275
  const rec = extra;
19133
- const running = Array.isArray(rec.models) ? rec.models : Array.isArray(rec.data) ? rec.data : [];
19134
- const hasLoadedFlags = running.some(
19276
+ const running2 = Array.isArray(rec.models) ? rec.models : Array.isArray(rec.data) ? rec.data : [];
19277
+ const hasLoadedFlags = running2.some(
19135
19278
  (row) => row && typeof row === "object" && ("loaded" in row || "state" in row)
19136
19279
  );
19137
19280
  if (!hasLoadedFlags && typeof rec.default_model === "string") add(rec.default_model);
19138
- for (const row of running) {
19281
+ for (const row of running2) {
19139
19282
  if (typeof row === "string") {
19140
19283
  if (!hasLoadedFlags) add(row);
19141
19284
  continue;
@@ -19272,12 +19415,12 @@ var init_local_inject = __esm({
19272
19415
  });
19273
19416
 
19274
19417
  // server/proxy-paths.ts
19275
- import { existsSync as existsSync6 } from "node:fs";
19276
- import { dirname as dirname4, join as join10 } from "node:path";
19418
+ import { existsSync as existsSync7 } from "node:fs";
19419
+ import { dirname as dirname4, join as join11 } from "node:path";
19277
19420
  import { fileURLToPath as fileURLToPath2 } from "node:url";
19278
19421
  function resolveProxy(relative2) {
19279
- const source = join10(SERVER_ROOT, `${relative2}.ts`);
19280
- return existsSync6(source) ? source : join10(SERVER_ROOT, `${relative2}.js`);
19422
+ const source = join11(SERVER_ROOT, `${relative2}.ts`);
19423
+ return existsSync7(source) ? source : join11(SERVER_ROOT, `${relative2}.js`);
19281
19424
  }
19282
19425
  var SERVER_ROOT, SPAWNED_PROXIES;
19283
19426
  var init_proxy_paths = __esm({
@@ -19305,7 +19448,7 @@ var init_proxy_paths = __esm({
19305
19448
 
19306
19449
  // server/container-computer.ts
19307
19450
  import { execFile as execFile4 } from "node:child_process";
19308
- import { join as join11, resolve as resolve3 } from "node:path";
19451
+ import { join as join12, resolve as resolve3 } from "node:path";
19309
19452
  import { promisify } from "node:util";
19310
19453
  function computerProxyEnv(computer) {
19311
19454
  return {
@@ -19329,7 +19472,7 @@ var init_container_computer = __esm({
19329
19472
  IMAGE_REPOSITORY = "localhost/openmausbot/cua-local-vm";
19330
19473
  IMAGE_LAYER_VERSION = "5";
19331
19474
  IMAGE = `${IMAGE_REPOSITORY}:driver-${CUA_DRIVER_VERSION}-v${IMAGE_LAYER_VERSION}`;
19332
- VM_WORKSPACE_DIR = join11(DATA_DIR, "vm-home");
19475
+ VM_WORKSPACE_DIR = join12(DATA_DIR, "vm-home");
19333
19476
  MEMORY_BYTES = 4 * 1024 * 1024 * 1024;
19334
19477
  SHM_BYTES = 512 * 1024 * 1024;
19335
19478
  containerMcpPath = SPAWNED_PROXIES.containerMcp;
@@ -19420,11 +19563,11 @@ var init_redact = __esm({
19420
19563
 
19421
19564
  // server/drivers/native.ts
19422
19565
  import { appendFileSync } from "node:fs";
19423
- import { join as join12 } from "node:path";
19566
+ import { join as join13 } from "node:path";
19424
19567
  function appendNative(threadId, entry) {
19425
19568
  try {
19426
19569
  appendFileSync(
19427
- join12(NATIVE_DIR, `${threadId}.ndjson`),
19570
+ join13(NATIVE_DIR, `${threadId}.ndjson`),
19428
19571
  JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...entry, msg: redactSecrets(entry.msg) }) + "\n",
19429
19572
  { mode: 384 }
19430
19573
  );
@@ -20210,7 +20353,7 @@ import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypt
20210
20353
  import { mkdir as mkdir2, mkdtemp, readFile as readFile2, rm, stat as stat2 } from "node:fs/promises";
20211
20354
  import { request as httpRequest } from "node:http";
20212
20355
  import { tmpdir as tmpdir2 } from "node:os";
20213
- import { delimiter as delimiter4, join as join13, resolve as resolve5 } from "node:path";
20356
+ import { delimiter as delimiter4, join as join14, resolve as resolve5 } from "node:path";
20214
20357
  function quoteBrowserArgument(value) {
20215
20358
  return `'${value.replaceAll("'", `'"'"'`)}'`;
20216
20359
  }
@@ -20245,11 +20388,11 @@ function authorizationUrlFromLine(line) {
20245
20388
  }
20246
20389
  }
20247
20390
  function antigravityProfileDirectory(instanceId, baseDir = DATA_DIR) {
20248
- return join13(baseDir, "providers", "antigravity", createHash3("sha256").update(instanceId).digest("hex"));
20391
+ return join14(baseDir, "providers", "antigravity", createHash3("sha256").update(instanceId).digest("hex"));
20249
20392
  }
20250
20393
  async function prepareAntigravityProfile(input) {
20251
20394
  const directory = resolve5(input.profileDirectory ?? antigravityProfileDirectory(input.instanceId, input.baseDir));
20252
- const acpDirectory = join13(directory, "antigravity-acp");
20395
+ const acpDirectory = join14(directory, "antigravity-acp");
20253
20396
  await mkdir2(acpDirectory, { recursive: true, mode: 448 });
20254
20397
  if (process.platform !== "win32") {
20255
20398
  const { chmod: chmod2 } = await import("node:fs/promises");
@@ -20257,7 +20400,7 @@ async function prepareAntigravityProfile(input) {
20257
20400
  await chmod2(acpDirectory, 448);
20258
20401
  }
20259
20402
  writeFileAtomic(
20260
- join13(acpDirectory, "settings.json"),
20403
+ join14(acpDirectory, "settings.json"),
20261
20404
  `${JSON.stringify({ auth: { type: "oauth-personal" } })}
20262
20405
  `,
20263
20406
  { mode: 384 }
@@ -20280,7 +20423,7 @@ async function prepareAntigravityProfile(input) {
20280
20423
  PYTHONUNBUFFERED: "1",
20281
20424
  ELECTRON_RUN_AS_NODE: "1"
20282
20425
  });
20283
- return { directory, tokenPath: join13(acpDirectory, "acp_token.json"), environment };
20426
+ return { directory, tokenPath: join14(acpDirectory, "acp_token.json"), environment };
20284
20427
  }
20285
20428
  async function antigravityProfileAuthenticated(profile) {
20286
20429
  try {
@@ -20409,7 +20552,7 @@ function isValidAntigravityInitializeResult(initialized, expectedVersion) {
20409
20552
  return true;
20410
20553
  }
20411
20554
  async function validateAntigravityRuntime(runtime, expectedVersion) {
20412
- const profileDirectory = await mkdtemp(join13(tmpdir2(), "openmaus-antigravity-verify-"));
20555
+ const profileDirectory = await mkdtemp(join14(tmpdir2(), "openmaus-antigravity-verify-"));
20413
20556
  let client;
20414
20557
  let failed = false;
20415
20558
  let failure;
@@ -20798,7 +20941,7 @@ import {
20798
20941
  writeFile as writeFile2
20799
20942
  } from "node:fs/promises";
20800
20943
  import { constants } from "node:fs";
20801
- import { delimiter as delimiter5, dirname as dirname6, isAbsolute as isAbsolute2, join as join14, resolve as resolve6 } from "node:path";
20944
+ import { delimiter as delimiter5, dirname as dirname6, isAbsolute as isAbsolute2, join as join15, resolve as resolve6 } from "node:path";
20802
20945
  import { Transform } from "node:stream";
20803
20946
  import { pipeline } from "node:stream/promises";
20804
20947
  import { createInflateRaw } from "node:zlib";
@@ -20819,7 +20962,7 @@ async function retryOnWindowsFileLock(step, options = {}) {
20819
20962
  }
20820
20963
  }
20821
20964
  function runtimeRoot(baseDir = DATA_DIR) {
20822
- return join14(baseDir, "tools", "antigravity-acp", `${process.platform}-${process.arch}`);
20965
+ return join15(baseDir, "tools", "antigravity-acp", `${process.platform}-${process.arch}`);
20823
20966
  }
20824
20967
  function executableNames(platform = process.platform) {
20825
20968
  return platform === "win32" ? { executable: "agy_acp_server.exe", harness: "localharness_external.exe" } : { executable: "agy_acp_server.par", harness: "localharness_external" };
@@ -20836,10 +20979,10 @@ async function executableFile(path3, bytes) {
20836
20979
  }
20837
20980
  async function completedRelease(directory, asset) {
20838
20981
  try {
20839
- const record3 = JSON.parse(await readFile3(join14(directory, INSTALL_RECORD), "utf8"));
20982
+ const record3 = JSON.parse(await readFile3(join15(directory, INSTALL_RECORD), "utf8"));
20840
20983
  if (record3.sha256 !== asset.sha256 || record3.version !== asset.version || record3.executable.name !== asset.executable.name || record3.executable.bytes !== asset.executable.bytes || record3.harness.name !== asset.harness.name || record3.harness.bytes !== asset.harness.bytes) return null;
20841
- const executablePath = join14(directory, asset.executable.name);
20842
- const harnessPath = join14(directory, asset.harness.name);
20984
+ const executablePath = join15(directory, asset.executable.name);
20985
+ const harnessPath = join15(directory, asset.harness.name);
20843
20986
  if (!await executableFile(executablePath, asset.executable.bytes)) return null;
20844
20987
  if (!await executableFile(harnessPath, asset.harness.bytes)) return null;
20845
20988
  return { executablePath, harnessPath, source: "managed", version: asset.version };
@@ -20855,7 +20998,7 @@ function pathCandidates(binary2, env) {
20855
20998
  async function externalRuntime(candidate, source) {
20856
20999
  const names = executableNames();
20857
21000
  const executablePath = resolve6(candidate);
20858
- const harnessPath = join14(dirname6(executablePath), names.harness);
21001
+ const harnessPath = join15(dirname6(executablePath), names.harness);
20859
21002
  if (!await executableFile(executablePath) || !await executableFile(harnessPath)) return null;
20860
21003
  return { executablePath, harnessPath, source, version: null };
20861
21004
  }
@@ -20875,7 +21018,7 @@ async function resolveAntigravityRuntime(binaryPath, env = process.env, baseDir
20875
21018
  }
20876
21019
  const asset = resolveAntigravityReleaseAsset();
20877
21020
  if (asset) {
20878
- const managed = await completedRelease(join14(runtimeRoot(baseDir), "versions", asset.sha256), asset);
21021
+ const managed = await completedRelease(join15(runtimeRoot(baseDir), "versions", asset.sha256), asset);
20879
21022
  if (managed) return managed;
20880
21023
  }
20881
21024
  const names = executableNames();
@@ -20895,25 +21038,25 @@ async function pinnedZipEntries(path3) {
20895
21038
  try {
20896
21039
  const info = await handle.stat();
20897
21040
  const tailBytes = Math.min(info.size, MAX_EOCD_BYTES);
20898
- const tail = Buffer.alloc(tailBytes);
21041
+ const tail2 = Buffer.alloc(tailBytes);
20899
21042
  const tailOffset = info.size - tailBytes;
20900
- if ((await handle.read(tail, 0, tailBytes, tailOffset)).bytesRead !== tailBytes) {
21043
+ if ((await handle.read(tail2, 0, tailBytes, tailOffset)).bytesRead !== tailBytes) {
20901
21044
  throw new Error("The verified archive was truncated.");
20902
21045
  }
20903
21046
  let eocd = -1;
20904
- for (let cursor4 = tail.length - 22; cursor4 >= 0; cursor4 -= 1) {
20905
- if (tail.readUInt32LE(cursor4) === EOCD_SIGNATURE && cursor4 + 22 + tail.readUInt16LE(cursor4 + 20) === tail.length) {
21047
+ for (let cursor4 = tail2.length - 22; cursor4 >= 0; cursor4 -= 1) {
21048
+ if (tail2.readUInt32LE(cursor4) === EOCD_SIGNATURE && cursor4 + 22 + tail2.readUInt16LE(cursor4 + 20) === tail2.length) {
20906
21049
  eocd = cursor4;
20907
21050
  break;
20908
21051
  }
20909
21052
  }
20910
21053
  if (eocd < 0) throw new Error("The verified archive has no valid ZIP directory.");
20911
- const disk = tail.readUInt16LE(eocd + 4);
20912
- const directoryDisk = tail.readUInt16LE(eocd + 6);
20913
- const diskEntries = tail.readUInt16LE(eocd + 8);
20914
- const entryCount = tail.readUInt16LE(eocd + 10);
20915
- const directoryBytes = tail.readUInt32LE(eocd + 12);
20916
- const directoryOffset = tail.readUInt32LE(eocd + 16);
21054
+ const disk = tail2.readUInt16LE(eocd + 4);
21055
+ const directoryDisk = tail2.readUInt16LE(eocd + 6);
21056
+ const diskEntries = tail2.readUInt16LE(eocd + 8);
21057
+ const entryCount = tail2.readUInt16LE(eocd + 10);
21058
+ const directoryBytes = tail2.readUInt32LE(eocd + 12);
21059
+ const directoryOffset = tail2.readUInt32LE(eocd + 16);
20917
21060
  const eocdOffset = tailOffset + eocd;
20918
21061
  if (disk !== 0 || directoryDisk !== 0 || diskEntries !== entryCount || entryCount !== 2 || directoryBytes === 4294967295 || directoryOffset === 4294967295 || directoryOffset + directoryBytes > eocdOffset) throw new Error("The verified archive uses an unsupported ZIP layout.");
20919
21062
  const directory = Buffer.alloc(directoryBytes);
@@ -20997,19 +21140,19 @@ async function extractPinnedArchive(archivePath, outputDirectory, asset) {
20997
21140
  start: dataOffset,
20998
21141
  end: dataOffset + entry.compressedBytes - 1
20999
21142
  });
21000
- const destination = createWriteStream(join14(outputDirectory, entry.name), { flags: "wx", mode: 448 });
21143
+ const destination = createWriteStream(join15(outputDirectory, entry.name), { flags: "wx", mode: 448 });
21001
21144
  if (entry.compression === 8) await pipeline(source, createInflateRaw(), counter, destination);
21002
21145
  else await pipeline(source, counter, destination);
21003
21146
  if (bytes !== expectedBytes) throw new Error("An extracted file was truncated.");
21004
21147
  }
21005
21148
  if (seen.size !== 2) throw new Error("The archive is missing an expected file.");
21006
21149
  }
21007
- async function installOnce(options) {
21150
+ async function installOnce2(options) {
21008
21151
  const asset = options.asset === void 0 ? resolveAntigravityReleaseAsset() : options.asset;
21009
21152
  if (!asset) throw new Error(`Google does not publish an Antigravity runtime for ${process.platform}-${process.arch}.`);
21010
21153
  const root = runtimeRoot(options.baseDir);
21011
- const versions = join14(root, "versions");
21012
- const destination = join14(versions, asset.sha256);
21154
+ const versions = join15(root, "versions");
21155
+ const destination = join15(versions, asset.sha256);
21013
21156
  await mkdir3(versions, { recursive: true, mode: 448 });
21014
21157
  const existing = await completedRelease(destination, asset);
21015
21158
  if (existing) {
@@ -21025,11 +21168,11 @@ async function installOnce(options) {
21025
21168
  } catch (error51) {
21026
21169
  if (error51 instanceof Error && error51.message.includes("Antigravity needs")) throw error51;
21027
21170
  }
21028
- const staging = await mkdtemp2(join14(versions, `${STAGING_PREFIX}${randomUUID7()}-`));
21171
+ const staging = await mkdtemp2(join15(versions, `${STAGING_PREFIX}${randomUUID7()}-`));
21029
21172
  let failed = false;
21030
21173
  try {
21031
- const archivePath = join14(staging, "download.zip");
21032
- const runtimeDirectory = join14(staging, "runtime");
21174
+ const archivePath = join15(staging, "download.zip");
21175
+ const runtimeDirectory = join15(staging, "runtime");
21033
21176
  await mkdir3(runtimeDirectory, { mode: 448 });
21034
21177
  const controller = new AbortController();
21035
21178
  const timeout = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS2);
@@ -21075,12 +21218,12 @@ async function installOnce(options) {
21075
21218
  }
21076
21219
  await extractPinnedArchive(archivePath, runtimeDirectory, asset);
21077
21220
  if (process.platform !== "win32") {
21078
- await chmod(join14(runtimeDirectory, asset.executable.name), 493);
21079
- await chmod(join14(runtimeDirectory, asset.harness.name), 493);
21221
+ await chmod(join15(runtimeDirectory, asset.executable.name), 493);
21222
+ await chmod(join15(runtimeDirectory, asset.harness.name), 493);
21080
21223
  }
21081
21224
  const candidate = {
21082
- executablePath: join14(runtimeDirectory, asset.executable.name),
21083
- harnessPath: join14(runtimeDirectory, asset.harness.name),
21225
+ executablePath: join15(runtimeDirectory, asset.executable.name),
21226
+ harnessPath: join15(runtimeDirectory, asset.harness.name),
21084
21227
  source: "managed",
21085
21228
  version: asset.version
21086
21229
  };
@@ -21091,7 +21234,7 @@ async function installOnce(options) {
21091
21234
  executable: asset.executable,
21092
21235
  harness: asset.harness
21093
21236
  };
21094
- await writeFile2(join14(runtimeDirectory, INSTALL_RECORD), `${JSON.stringify(record3)}
21237
+ await writeFile2(join15(runtimeDirectory, INSTALL_RECORD), `${JSON.stringify(record3)}
21095
21238
  `, { flag: "wx", mode: 384 });
21096
21239
  try {
21097
21240
  await retryOnWindowsFileLock(() => rename(runtimeDirectory, destination));
@@ -21118,9 +21261,9 @@ function installAntigravityRuntime(options = {}) {
21118
21261
  const key = runtimeRoot(options.baseDir);
21119
21262
  const existing = installs.get(key);
21120
21263
  if (existing) return existing;
21121
- const running = installOnce(options).finally(() => installs.delete(key));
21122
- installs.set(key, running);
21123
- return running;
21264
+ const running2 = installOnce2(options).finally(() => installs.delete(key));
21265
+ installs.set(key, running2);
21266
+ return running2;
21124
21267
  }
21125
21268
  function antigravityManagedInstallAvailable() {
21126
21269
  return resolveAntigravityReleaseAsset() !== null;
@@ -21531,14 +21674,14 @@ var init_boxagent = __esm({
21531
21674
  import { randomUUID as randomUUID8 } from "node:crypto";
21532
21675
  import { realpathSync } from "node:fs";
21533
21676
  import { homedir as homedir8 } from "node:os";
21534
- import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute3, join as join15, resolve as resolve7 } from "node:path";
21535
- import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
21677
+ import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute3, join as join16, resolve as resolve7 } from "node:path";
21678
+ import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
21536
21679
  function canonicalPath(path3) {
21537
21680
  try {
21538
21681
  return realpathSync(path3);
21539
21682
  } catch {
21540
21683
  const parent = dirname7(path3);
21541
- return parent === path3 ? path3 : join15(canonicalPath(parent), basename4(path3));
21684
+ return parent === path3 ? path3 : join16(canonicalPath(parent), basename4(path3));
21542
21685
  }
21543
21686
  }
21544
21687
  function claudeSignInLink(value) {
@@ -21553,7 +21696,7 @@ function claudeSignInLink(value) {
21553
21696
  }
21554
21697
  }
21555
21698
  function claudeLoginPrompt(output) {
21556
- const lines = stripVTControlCharacters3(output).split(/\r?\n/).slice(0, -1);
21699
+ const lines = stripVTControlCharacters4(output).split(/\r?\n/).slice(0, -1);
21557
21700
  for (const line of lines) {
21558
21701
  const match = /(https:\/\/\S+)/.exec(line.trim());
21559
21702
  const link = match ? claudeSignInLink(match[1].replace(/[),.;]+$/, "")) : null;
@@ -21565,17 +21708,18 @@ function claudeLoginCode(value) {
21565
21708
  const code = value.trim();
21566
21709
  return /^[A-Za-z0-9_\-#.:]{8,1024}$/.test(code) ? code : null;
21567
21710
  }
21568
- var MAX_OUTPUT, SIGN_IN_HOSTS, authenticatingHomes, NOT_AVAILABLE, ClaudeLoginController;
21711
+ var MAX_OUTPUT2, SIGN_IN_HOSTS, authenticatingHomes, NOT_AVAILABLE, ClaudeLoginController;
21569
21712
  var init_claude_login_auth = __esm({
21570
21713
  "server/drivers/claude-login-auth.ts"() {
21571
21714
  "use strict";
21572
21715
  init_procs();
21573
- MAX_OUTPUT = 32768;
21716
+ MAX_OUTPUT2 = 32768;
21574
21717
  SIGN_IN_HOSTS = ["claude.com", "claude.ai", "console.anthropic.com", "platform.claude.com"];
21575
21718
  authenticatingHomes = /* @__PURE__ */ new Set();
21576
21719
  NOT_AVAILABLE = "This sign-in is no longer available. Start sign-in again.";
21577
21720
  ClaudeLoginController = class {
21578
21721
  flow = null;
21722
+ logoutChild = null;
21579
21723
  disposed = false;
21580
21724
  options;
21581
21725
  constructor(options) {
@@ -21594,7 +21738,7 @@ var init_claude_login_auth = __esm({
21594
21738
  if (!isAbsolute3(home) || env.CLAUDE_CONFIG_DIR && !isAbsolute3(env.CLAUDE_CONFIG_DIR)) {
21595
21739
  throw new Error("Use an absolute HOME and CLAUDE_CONFIG_DIR path for this server's Claude provider before signing in.");
21596
21740
  }
21597
- const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join15(home, ".claude")));
21741
+ const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join16(home, ".claude")));
21598
21742
  if (authenticatingHomes.has(homeKey)) {
21599
21743
  throw new Error("A Claude sign-in is already running for this server account. Finish or cancel it before starting another.");
21600
21744
  }
@@ -21667,43 +21811,121 @@ var init_claude_login_auth = __esm({
21667
21811
  if (this.flow?.status.phase === "waiting") this.finish(this.flow, "cancelled", "Claude sign-in cancelled.");
21668
21812
  await this.flow?.stopping;
21669
21813
  if (this.flow?.terminationFailed) throw new Error(this.flow.status.message);
21814
+ if (this.logoutChild && !await this.stopChild(this.logoutChild)) {
21815
+ throw new Error("Claude Code could not be stopped on this server. Ask the server administrator to stop the account command before trying again.");
21816
+ }
21670
21817
  }
21671
21818
  async dispose() {
21672
21819
  this.disposed = true;
21673
21820
  await this.cancel();
21674
21821
  this.flow = null;
21675
21822
  }
21823
+ /** Remove the sign-in Claude Code stores for this server account (its
21824
+ * configuration directory) so a different subscription can sign in. A
21825
+ * sign-in in progress is never pulled away underneath the browser
21826
+ * completing it, and the CLI's own status is the verdict, as for sign-in. */
21827
+ async signOut() {
21828
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
21829
+ if (this.flow?.status.phase === "waiting") throw new Error("Finish or cancel the Claude sign-in in progress before signing out.");
21830
+ await this.flow?.stopping;
21831
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
21832
+ const env = this.options.environment();
21833
+ const home = env.HOME || env.USERPROFILE || homedir8();
21834
+ if (!isAbsolute3(home) || env.CLAUDE_CONFIG_DIR && !isAbsolute3(env.CLAUDE_CONFIG_DIR)) {
21835
+ throw new Error("Use an absolute HOME and CLAUDE_CONFIG_DIR path for this server's Claude provider before signing out.");
21836
+ }
21837
+ const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join16(home, ".claude")));
21838
+ if (authenticatingHomes.has(homeKey)) {
21839
+ throw new Error("A Claude sign-in is running for this server account. Finish or cancel it before signing out.");
21840
+ }
21841
+ authenticatingHomes.add(homeKey);
21842
+ try {
21843
+ await this.logout(env);
21844
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
21845
+ const status = await this.authStatus(env);
21846
+ if (status === "in") throw new Error("Claude Code still reports a sign-in on this server. Update Claude Code and check its auth status before trying again.");
21847
+ if (status === "unknown") throw new Error("Claude Code could not confirm the sign-out on this server. Update Claude Code and check its auth status before trying again.");
21848
+ } finally {
21849
+ const child = this.logoutChild;
21850
+ if (child && child.exitCode === null && child.signalCode === null) {
21851
+ child.once("close", () => authenticatingHomes.delete(homeKey));
21852
+ } else authenticatingHomes.delete(homeKey);
21853
+ }
21854
+ }
21855
+ /** `claude auth logout`, bounded and non-interactive. Its output stays
21856
+ * here; the status command afterwards decides whether it worked. */
21857
+ logout(env) {
21858
+ return new Promise((resolveDone, rejectDone) => {
21859
+ if (this.disposed) {
21860
+ rejectDone(new Error("This provider was removed. Refresh Settings before signing out."));
21861
+ return;
21862
+ }
21863
+ let child;
21864
+ try {
21865
+ child = spawnCli(this.options.cli, ["auth", "logout"], { env: { ...env, NO_COLOR: "1" }, stdio: ["pipe", "pipe", "pipe"] });
21866
+ } catch {
21867
+ rejectDone(new Error("Claude Code could not start on this server. Install or update the configured Claude CLI, then try again."));
21868
+ return;
21869
+ }
21870
+ this.logoutChild = child;
21871
+ child.stdin.end();
21872
+ child.stdout.on("data", () => {
21873
+ });
21874
+ child.stderr.on("data", () => {
21875
+ });
21876
+ const timer = setTimeout(() => {
21877
+ void this.stopChild(child).catch(() => false).then((stopped) => {
21878
+ if (!stopped) rejectDone(new Error("Claude Code could not be stopped on this server. Ask the server administrator to stop the account command before trying again."));
21879
+ });
21880
+ }, this.options.startupTimeoutMs ?? 3e4);
21881
+ timer.unref();
21882
+ child.once("error", (error51) => {
21883
+ clearTimeout(timer);
21884
+ rejectDone(new Error(error51.code === "ENOENT" ? "Claude Code is not installed on this server. Install it on the server, then try again." : "Claude Code could not start on this server. Check the configured CLI path and its executable permissions."));
21885
+ });
21886
+ child.once("close", () => {
21887
+ clearTimeout(timer);
21888
+ if (this.logoutChild === child) this.logoutChild = null;
21889
+ resolveDone();
21890
+ });
21891
+ });
21892
+ }
21676
21893
  signedIn(env) {
21894
+ return this.authStatus(env).then((status) => status === "in");
21895
+ }
21896
+ /** `claude auth status --json`: signed in, signed out, or not answered. */
21897
+ authStatus(env) {
21677
21898
  return new Promise((resolveStatus) => {
21678
21899
  let child;
21679
21900
  try {
21680
21901
  child = spawnCli(this.options.cli, ["auth", "status", "--json"], { env: { ...env, NO_COLOR: "1" }, stdio: ["ignore", "pipe", "pipe"] });
21681
21902
  } catch {
21682
- resolveStatus(false);
21903
+ resolveStatus("unknown");
21683
21904
  return;
21684
21905
  }
21685
21906
  let stdout2 = "";
21686
21907
  child.stdout.on("data", (chunk) => {
21687
- if (stdout2.length < MAX_OUTPUT) stdout2 += chunk.toString("utf8");
21908
+ if (stdout2.length < MAX_OUTPUT2) stdout2 += chunk.toString("utf8");
21688
21909
  });
21689
21910
  child.stderr.on("data", () => {
21690
21911
  });
21691
21912
  const timer = setTimeout(() => {
21692
21913
  child.kill("SIGKILL");
21693
- resolveStatus(false);
21914
+ resolveStatus("unknown");
21694
21915
  }, 8e3);
21695
21916
  timer.unref();
21696
21917
  child.once("error", () => {
21697
21918
  clearTimeout(timer);
21698
- resolveStatus(false);
21919
+ resolveStatus("unknown");
21699
21920
  });
21700
- child.once("close", () => {
21921
+ child.once("close", (code) => {
21701
21922
  clearTimeout(timer);
21702
21923
  try {
21703
21924
  const status = JSON.parse(stdout2);
21704
- resolveStatus(typeof status === "object" && status !== null && Reflect.get(status, "loggedIn") === true);
21925
+ const loggedIn = typeof status === "object" && status !== null ? Reflect.get(status, "loggedIn") : void 0;
21926
+ resolveStatus(code === 0 && loggedIn === true ? "in" : code === 1 && loggedIn === false ? "out" : "unknown");
21705
21927
  } catch {
21706
- resolveStatus(false);
21928
+ resolveStatus("unknown");
21707
21929
  }
21708
21930
  });
21709
21931
  });
@@ -21724,7 +21946,7 @@ var init_claude_login_auth = __esm({
21724
21946
  flow.child = child;
21725
21947
  const receive = (chunk) => {
21726
21948
  if (flow.status.phase !== "waiting") return;
21727
- if (flow.output.length + chunk.length > MAX_OUTPUT) {
21949
+ if (flow.output.length + chunk.length > MAX_OUTPUT2) {
21728
21950
  this.finish(flow, "failed", "Claude Code returned an unexpected sign-in response. Update the server's Claude CLI and try again.");
21729
21951
  return;
21730
21952
  }
@@ -21746,7 +21968,7 @@ var init_claude_login_auth = __esm({
21746
21968
  child.once("close", (code) => {
21747
21969
  if (flow.child === child) flow.child = null;
21748
21970
  if (flow.status.phase !== "waiting") return;
21749
- const output = stripVTControlCharacters3(flow.output);
21971
+ const output = stripVTControlCharacters4(flow.output);
21750
21972
  flow.output = "";
21751
21973
  void this.signedIn(flow.env).then((signedIn) => {
21752
21974
  if (flow.status.phase !== "waiting") return;
@@ -21779,7 +22001,7 @@ var init_claude_login_auth = __esm({
21779
22001
  else flow.completion.reject(new Error(message2 ?? "Claude sign-in did not finish."));
21780
22002
  flow.completion = void 0;
21781
22003
  }
21782
- flow.stopping = this.stopChild(flow).catch(() => false).then((stopped) => {
22004
+ flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
21783
22005
  const release = () => authenticatingHomes.delete(flow.homeKey);
21784
22006
  if (stopped) {
21785
22007
  release();
@@ -21794,8 +22016,7 @@ var init_claude_login_auth = __esm({
21794
22016
  if (phase === "succeeded") void this.options.onAuthenticated?.().catch(() => {
21795
22017
  });
21796
22018
  }
21797
- async stopChild(flow) {
21798
- const child = flow.child;
22019
+ async stopChild(child) {
21799
22020
  if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500)) return true;
21800
22021
  if (process.platform !== "win32" && child.pid) {
21801
22022
  try {
@@ -21907,7 +22128,7 @@ import { createHash as createHash5, randomBytes as randomBytes2 } from "node:cry
21907
22128
  import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, rmSync as rmSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
21908
22129
  import { createServer as createNetServer } from "node:net";
21909
22130
  import { homedir as homedir9, tmpdir as tmpdir3 } from "node:os";
21910
- import { join as join16, dirname as dirname8, isAbsolute as isAbsolute4, normalize } from "node:path";
22131
+ import { join as join17, dirname as dirname8, isAbsolute as isAbsolute4, normalize } from "node:path";
21911
22132
  function claudeAuthStatus(cli, env, run3 = execCli) {
21912
22133
  return new Promise((resolve13) => {
21913
22134
  run3(cli, ["auth", "status", "--json"], { timeout: 8e3, maxBuffer: 65536, env }, (_error, stdout2) => {
@@ -21933,8 +22154,8 @@ function claudeAuthStatus(cli, env, run3 = execCli) {
21933
22154
  }
21934
22155
  function resolveClaudeConfigDir(configDir, env = process.env) {
21935
22156
  const home = env.HOME || env.USERPROFILE || homedir9();
21936
- const configured = configDir?.trim() || env.CLAUDE_CONFIG_DIR?.trim() || join16(home, ".claude");
21937
- const expanded = configured === "~" ? home : configured.startsWith("~/") ? join16(home, configured.slice(2)) : configured;
22157
+ const configured = configDir?.trim() || env.CLAUDE_CONFIG_DIR?.trim() || join17(home, ".claude");
22158
+ const expanded = configured === "~" ? home : configured.startsWith("~/") ? join17(home, configured.slice(2)) : configured;
21938
22159
  if (!isAbsolute4(expanded) || /[\p{Cc}\p{Cf}]/u.test(expanded)) {
21939
22160
  throw new Error("claude: configDir must be an absolute path or start with ~/");
21940
22161
  }
@@ -21986,7 +22207,7 @@ function extrasFromUnknown(value) {
21986
22207
  function readClaudeModelCatalog(env = process.env) {
21987
22208
  let settings2 = {};
21988
22209
  try {
21989
- settings2 = JSON.parse(readFileSync6(join16(resolveClaudeConfigDir(void 0, env), "settings.json"), "utf8"));
22210
+ settings2 = JSON.parse(readFileSync6(join17(resolveClaudeConfigDir(void 0, env), "settings.json"), "utf8"));
21990
22211
  } catch {
21991
22212
  return STATIC_CLAUDE_MODELS;
21992
22213
  }
@@ -22036,7 +22257,7 @@ function brokerSocketCandidates(threadId) {
22036
22257
  const base2 = permissionSocketPath(threadId);
22037
22258
  if (process.platform !== "win32") {
22038
22259
  const scope = createHash5("sha256").update(`${DATA_DIR}\0${process.pid}\0${threadId}`).digest("hex").slice(0, 16);
22039
- return [base2, join16(tmpdir3(), `omb-perm-${scope}.sock`)];
22260
+ return [base2, join17(tmpdir3(), `omb-perm-${scope}.sock`)];
22040
22261
  }
22041
22262
  return [
22042
22263
  base2,
@@ -22502,7 +22723,7 @@ var init_claude = __esm({
22502
22723
  allowed.push("mcp__ogb");
22503
22724
  let mcpConfigPath = null;
22504
22725
  if (Object.keys(mcpServers).length) {
22505
- mcpConfigPath = join16(mkdtempSync2(join16(tmpdir3(), "omb-mcp-")), "mcp.json");
22726
+ mcpConfigPath = join17(mkdtempSync2(join17(tmpdir3(), "omb-mcp-")), "mcp.json");
22506
22727
  args.push("--mcp-config", mcpConfigPath);
22507
22728
  args.push("--allowedTools", allowed.join(","));
22508
22729
  }
@@ -22570,7 +22791,7 @@ var init_claude = __esm({
22570
22791
  };
22571
22792
  try {
22572
22793
  if (turn.system) {
22573
- systemPromptPath = join16(mkdtempSync2(join16(tmpdir3(), "omb-system-")), "prompt.txt");
22794
+ systemPromptPath = join17(mkdtempSync2(join17(tmpdir3(), "omb-system-")), "prompt.txt");
22574
22795
  writeFileSync5(systemPromptPath, turn.system, { mode: 384 });
22575
22796
  args.push("--append-system-prompt-file", systemPromptPath);
22576
22797
  }
@@ -22956,6 +23177,7 @@ var init_claude = __esm({
22956
23177
  getAuthentication: (flowId) => login.get(flowId),
22957
23178
  completeAuthentication: (flowId, code) => login.complete(flowId, code),
22958
23179
  cancelAuthentication: () => login.cancel(),
23180
+ signOut: () => login.signOut(),
22959
23181
  adapter: {
22960
23182
  provider: DRIVER_KIND2,
22961
23183
  capabilities: {
@@ -22997,9 +23219,13 @@ var init_claude = __esm({
22997
23219
  generateText: (prompt) => generateReview(prompt),
22998
23220
  reviewPermission: generateReview,
22999
23221
  dispose: async () => {
23000
- for (const { stop } of active.values()) stop();
23001
- for (const threadId of [...sessions.keys()]) closeSession(threadId, "dispose");
23002
- listeners.clear();
23222
+ try {
23223
+ await login.dispose();
23224
+ } finally {
23225
+ for (const { stop } of active.values()) stop();
23226
+ for (const threadId of [...sessions.keys()]) closeSession(threadId, "dispose");
23227
+ listeners.clear();
23228
+ }
23003
23229
  }
23004
23230
  };
23005
23231
  }
@@ -23010,7 +23236,7 @@ var init_claude = __esm({
23010
23236
  // server/drivers/codex-catalog.ts
23011
23237
  import { readdirSync as readdirSync2, readFileSync as readFileSync7 } from "node:fs";
23012
23238
  import { homedir as homedir10 } from "node:os";
23013
- import { basename as basename5, join as join17 } from "node:path";
23239
+ import { basename as basename5, join as join18 } from "node:path";
23014
23240
  function encodeCodexSelection(provider, model) {
23015
23241
  return `${provider}${SEP}${model}`;
23016
23242
  }
@@ -23126,7 +23352,7 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
23126
23352
  }
23127
23353
  function codexHome(env) {
23128
23354
  if (env.CODEX_HOME) return env.CODEX_HOME;
23129
- return join17(env.HOME || env.USERPROFILE || homedir10(), ".codex");
23355
+ return join18(env.HOME || env.USERPROFILE || homedir10(), ".codex");
23130
23356
  }
23131
23357
  function unquote(raw) {
23132
23358
  let value = raw.trim();
@@ -23212,11 +23438,11 @@ function niceLabel(model, provider, known, named) {
23212
23438
  }
23213
23439
  function collectCatalogNames(home) {
23214
23440
  const named = /* @__PURE__ */ new Map();
23215
- for (const file2 of listDir(join17(home, "model-catalogs"))) {
23441
+ for (const file2 of listDir(join18(home, "model-catalogs"))) {
23216
23442
  if (!file2.endsWith(".json")) continue;
23217
23443
  const provider = basename5(file2, ".json").replace(/-models$/, "");
23218
23444
  if (!PROVIDER_ID.test(provider)) continue;
23219
- const raw = readText(join17(home, "model-catalogs", file2));
23445
+ const raw = readText(join18(home, "model-catalogs", file2));
23220
23446
  if (!raw) continue;
23221
23447
  let parsed;
23222
23448
  try {
@@ -23268,7 +23494,7 @@ async function probeProviderModels(provider, env, fetchImpl) {
23268
23494
  async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli) {
23269
23495
  const official = (cli ? await readCodexAppServerModelCatalog(cli, env) : null) ?? STATIC_CODEX_MODELS;
23270
23496
  const home = codexHome(env);
23271
- const mainText = readText(join17(home, "config.toml"));
23497
+ const mainText = readText(join18(home, "config.toml"));
23272
23498
  if (!mainText) return mergeLocalInject(official, env, fetchImpl);
23273
23499
  const main2 = parseCodexToml(mainText);
23274
23500
  const known = new Map(main2.providers.map((provider) => [provider.id, provider]));
@@ -23283,7 +23509,7 @@ async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli)
23283
23509
  remember(main2.modelProvider, main2.model);
23284
23510
  for (const file2 of listDir(home)) {
23285
23511
  if (!file2.endsWith(".config.toml")) continue;
23286
- const profile = parseCodexToml(readText(join17(home, file2)) ?? "");
23512
+ const profile = parseCodexToml(readText(join18(home, file2)) ?? "");
23287
23513
  for (const provider of profile.providers) {
23288
23514
  if (!known.has(provider.id)) known.set(provider.id, provider);
23289
23515
  }
@@ -23349,8 +23575,8 @@ var init_codex_catalog = __esm({
23349
23575
 
23350
23576
  // server/drivers/codex-instructions.ts
23351
23577
  import { createHash as createHash6 } from "node:crypto";
23352
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync8 } from "node:fs";
23353
- import { join as join18 } from "node:path";
23578
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync8 } from "node:fs";
23579
+ import { join as join19 } from "node:path";
23354
23580
  function codexDeveloperInstructions(config2, botInstructions) {
23355
23581
  if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
23356
23582
  throw new Error("Codex returned no effective configuration; cannot safely update bot instructions.");
@@ -23364,8 +23590,8 @@ function codexDeveloperInstructions(config2, botInstructions) {
23364
23590
  ${configured}` : botInstructions;
23365
23591
  }
23366
23592
  async function syncCodexInstructions(key, nativeThreadId, instructions, resumed, request) {
23367
- const directory = join18(DATA_DIR, "codex-instructions");
23368
- const path3 = join18(directory, `${digest(JSON.stringify([key, nativeThreadId]))}.sha256`);
23593
+ const directory = join19(DATA_DIR, "codex-instructions");
23594
+ const path3 = join19(directory, `${digest(JSON.stringify([key, nativeThreadId]))}.sha256`);
23369
23595
  const fingerprint = digest(instructions);
23370
23596
  let previous;
23371
23597
  try {
@@ -23394,7 +23620,7 @@ async function syncCodexInstructions(key, nativeThreadId, instructions, resumed,
23394
23620
  }
23395
23621
  }
23396
23622
  if (!resumed || previous !== fingerprint) {
23397
- mkdirSync6(directory, { recursive: true });
23623
+ mkdirSync7(directory, { recursive: true });
23398
23624
  writeFileAtomic(path3, fingerprint, { mode: 384 });
23399
23625
  }
23400
23626
  }
@@ -23412,18 +23638,18 @@ var init_codex_instructions = __esm({
23412
23638
  import { randomUUID as randomUUID9 } from "node:crypto";
23413
23639
  import { realpathSync as realpathSync2 } from "node:fs";
23414
23640
  import { homedir as homedir11 } from "node:os";
23415
- import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute5, join as join19, resolve as resolve8 } from "node:path";
23416
- import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
23641
+ import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute5, join as join20, resolve as resolve8 } from "node:path";
23642
+ import { stripVTControlCharacters as stripVTControlCharacters5 } from "node:util";
23417
23643
  function canonicalPath2(path3) {
23418
23644
  try {
23419
23645
  return realpathSync2(path3);
23420
23646
  } catch {
23421
23647
  const parent = dirname9(path3);
23422
- return parent === path3 ? path3 : join19(canonicalPath2(parent), basename6(path3));
23648
+ return parent === path3 ? path3 : join20(canonicalPath2(parent), basename6(path3));
23423
23649
  }
23424
23650
  }
23425
23651
  function codexDevicePrompt(output) {
23426
- const clean = stripVTControlCharacters4(output);
23652
+ const clean = stripVTControlCharacters5(output);
23427
23653
  const lines = clean.split(/\r?\n/).slice(0, -1).map((line) => line.trim());
23428
23654
  if (!lines.some((line) => /^https:\/\/auth\.openai\.com\/codex\/device\/?$/.test(line))) return null;
23429
23655
  const userCode = lines.find((line) => /^[A-Z0-9]{4,8}-[A-Z0-9]{4,8}$/.test(line));
@@ -23441,13 +23667,13 @@ function loginFailure(output) {
23441
23667
  }
23442
23668
  return "ChatGPT sign-in did not finish. Check the server's connection and that device-code login is enabled in ChatGPT, then try again.";
23443
23669
  }
23444
- var DEVICE_URL, MAX_OUTPUT2, authenticatingHomes2, CodexDeviceAuthController;
23670
+ var DEVICE_URL, MAX_OUTPUT3, authenticatingHomes2, CodexDeviceAuthController;
23445
23671
  var init_codex_device_auth = __esm({
23446
23672
  "server/drivers/codex-device-auth.ts"() {
23447
23673
  "use strict";
23448
23674
  init_procs();
23449
23675
  DEVICE_URL = "https://auth.openai.com/codex/device";
23450
- MAX_OUTPUT2 = 16384;
23676
+ MAX_OUTPUT3 = 16384;
23451
23677
  authenticatingHomes2 = /* @__PURE__ */ new Set();
23452
23678
  CodexDeviceAuthController = class {
23453
23679
  flow = null;
@@ -23470,7 +23696,7 @@ var init_codex_device_auth = __esm({
23470
23696
  if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
23471
23697
  throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing in.");
23472
23698
  }
23473
- const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join19(home, ".codex")));
23699
+ const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join20(home, ".codex")));
23474
23700
  if (authenticatingHomes2.has(homeKey)) {
23475
23701
  throw new Error("A ChatGPT sign-in is already running for this server account. Finish or cancel it before starting another.");
23476
23702
  }
@@ -23549,7 +23775,7 @@ var init_codex_device_auth = __esm({
23549
23775
  if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
23550
23776
  throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing out.");
23551
23777
  }
23552
- const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join19(home, ".codex")));
23778
+ const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join20(home, ".codex")));
23553
23779
  if (authenticatingHomes2.has(homeKey)) {
23554
23780
  throw new Error("A ChatGPT sign-in is running for this server account. Finish or cancel it before signing out.");
23555
23781
  }
@@ -23592,7 +23818,7 @@ var init_codex_device_auth = __esm({
23592
23818
  child.stdin.end();
23593
23819
  let output = "";
23594
23820
  const receive = (chunk) => {
23595
- if (output.length < MAX_OUTPUT2) output += chunk.toString("utf8").slice(0, MAX_OUTPUT2 - output.length);
23821
+ if (output.length < MAX_OUTPUT3) output += chunk.toString("utf8").slice(0, MAX_OUTPUT3 - output.length);
23596
23822
  };
23597
23823
  child.stdout.on("data", receive);
23598
23824
  child.stderr.on("data", receive);
@@ -23609,7 +23835,7 @@ var init_codex_device_auth = __esm({
23609
23835
  child.once("close", (code) => {
23610
23836
  clearTimeout(timer);
23611
23837
  if (this.command === child) this.command = null;
23612
- resolveExec({ code, output: stripVTControlCharacters4(output) });
23838
+ resolveExec({ code, output: stripVTControlCharacters5(output) });
23613
23839
  });
23614
23840
  });
23615
23841
  }
@@ -23627,7 +23853,7 @@ var init_codex_device_auth = __esm({
23627
23853
  let output = "";
23628
23854
  const receive = (chunk) => {
23629
23855
  if (flow.status.phase !== "waiting") return;
23630
- if (output.length + chunk.length > MAX_OUTPUT2) {
23856
+ if (output.length + chunk.length > MAX_OUTPUT3) {
23631
23857
  this.finish(flow, "failed", "Codex returned an unexpected sign-in response. Update the server's Codex CLI and try again.");
23632
23858
  return;
23633
23859
  }
@@ -23648,7 +23874,7 @@ var init_codex_device_auth = __esm({
23648
23874
  });
23649
23875
  child.once("close", (code) => {
23650
23876
  if (flow.child === child) flow.child = null;
23651
- if (flow.status.phase === "waiting") done(code, stripVTControlCharacters4(output));
23877
+ if (flow.status.phase === "waiting") done(code, stripVTControlCharacters5(output));
23652
23878
  output = "";
23653
23879
  });
23654
23880
  }
@@ -23708,11 +23934,11 @@ var init_codex_device_auth = __esm({
23708
23934
 
23709
23935
  // server/drivers/codex-identity.ts
23710
23936
  import { homedir as homedir12 } from "node:os";
23711
- import { isAbsolute as isAbsolute6, join as join20, resolve as resolve9 } from "node:path";
23937
+ import { isAbsolute as isAbsolute6, join as join21, resolve as resolve9 } from "node:path";
23712
23938
  function codexHome2(env) {
23713
23939
  if (env.CODEX_HOME) return isAbsolute6(env.CODEX_HOME) ? resolve9(env.CODEX_HOME) : null;
23714
23940
  const home = env.HOME || env.USERPROFILE || homedir12();
23715
- return isAbsolute6(home) ? join20(home, ".codex") : null;
23941
+ return isAbsolute6(home) ? join21(home, ".codex") : null;
23716
23942
  }
23717
23943
  async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
23718
23944
  const cwd = env.HOME || env.USERPROFILE || homedir12();
@@ -23774,7 +24000,7 @@ async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
23774
24000
  child.stdout.on("data", (chunk) => {
23775
24001
  if (finishing) return;
23776
24002
  outputBytes += Buffer.byteLength(chunk);
23777
- if (outputBytes > MAX_OUTPUT3) {
24003
+ if (outputBytes > MAX_OUTPUT4) {
23778
24004
  void finish(null);
23779
24005
  return;
23780
24006
  }
@@ -23809,18 +24035,18 @@ async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
23809
24035
  send({ id: 1, method: "initialize", params: { clientInfo: { name: "openmausbot", version: "1" } } });
23810
24036
  });
23811
24037
  }
23812
- var MAX_OUTPUT3, EMAIL;
24038
+ var MAX_OUTPUT4, EMAIL;
23813
24039
  var init_codex_identity = __esm({
23814
24040
  "server/drivers/codex-identity.ts"() {
23815
24041
  "use strict";
23816
24042
  init_procs();
23817
- MAX_OUTPUT3 = 16384;
24043
+ MAX_OUTPUT4 = 16384;
23818
24044
  EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
23819
24045
  }
23820
24046
  });
23821
24047
 
23822
24048
  // server/drivers/codex.ts
23823
- import { existsSync as existsSync7 } from "node:fs";
24049
+ import { existsSync as existsSync8 } from "node:fs";
23824
24050
  import { homedir as homedir13 } from "node:os";
23825
24051
  function codexPredatesAstra(version2) {
23826
24052
  const value = version2.trim();
@@ -23837,7 +24063,7 @@ function codexPredatesAstra(version2) {
23837
24063
  function codexUpdateCommand(cli, platform = process.platform) {
23838
24064
  if (cli === "codex") return "codex update";
23839
24065
  const trimmed = cli.trim();
23840
- const tokens = trimmed.includes(" ") && existsSync7(trimmed) ? [trimmed] : splitCliString(trimmed);
24066
+ const tokens = trimmed.includes(" ") && existsSync8(trimmed) ? [trimmed] : splitCliString(trimmed);
23841
24067
  const quote = platform === "win32" ? (token) => `'${token.replaceAll("'", "''")}'` : (token) => `'${token.replaceAll("'", `'\\''`)}'`;
23842
24068
  const command = (tokens.length > 0 ? tokens : [trimmed]).map(quote).join(" ");
23843
24069
  return platform === "win32" ? `& ${command} update` : `${command} update`;
@@ -25035,12 +25261,12 @@ var init_grok = __esm({
25035
25261
  });
25036
25262
 
25037
25263
  // server/drivers/acp/grok.ts
25038
- import { existsSync as existsSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
25264
+ import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
25039
25265
  import { homedir as homedir14 } from "node:os";
25040
- import { join as join21 } from "node:path";
25266
+ import { join as join22 } from "node:path";
25041
25267
  function grokHome(env) {
25042
25268
  if (env.GROK_HOME) return env.GROK_HOME;
25043
- return join21(env.HOME || env.USERPROFILE || homedir14(), ".grok");
25269
+ return join22(env.HOME || env.USERPROFILE || homedir14(), ".grok");
25044
25270
  }
25045
25271
  function unquote2(raw) {
25046
25272
  const value = raw.trim();
@@ -25050,7 +25276,7 @@ function unquote2(raw) {
25050
25276
  return value;
25051
25277
  }
25052
25278
  function readGrokModelCatalog(env = process.env) {
25053
- const path3 = join21(grokHome(env), "config.toml");
25279
+ const path3 = join22(grokHome(env), "config.toml");
25054
25280
  let text2 = "";
25055
25281
  try {
25056
25282
  text2 = readFileSync9(path3, "utf8");
@@ -25123,7 +25349,7 @@ function ensureGrokInjectSlug(modelId, env = process.env) {
25123
25349
  if (!inject) return modelId;
25124
25350
  const host = localHost(inject.host);
25125
25351
  if (!host) return modelId;
25126
- const path3 = join21(grokHome(env), "config.toml");
25352
+ const path3 = join22(grokHome(env), "config.toml");
25127
25353
  let text2 = "";
25128
25354
  try {
25129
25355
  text2 = readFileSync9(path3, "utf8");
@@ -25258,7 +25484,7 @@ var init_grok2 = __esm({
25258
25484
  // an unauthenticated CLI is a user action, not something to paper over.
25259
25485
  pickAuthMethod: (methods) => methods.some((m) => m.id === "cached_token") ? "cached_token" : null,
25260
25486
  authFailure: "fail",
25261
- isAuthenticated: () => existsSync8(join21(homedir14(), ".grok", "auth.json")),
25487
+ isAuthenticated: () => existsSync9(join22(homedir14(), ".grok", "auth.json")),
25262
25488
  // `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
25263
25489
  // reach the agent-stdio system prompt (verified against 1.0.0), so the
25264
25490
  // persona is prepended codex-style.
@@ -25271,12 +25497,12 @@ ${turn.text}` : turn.text
25271
25497
  });
25272
25498
 
25273
25499
  // server/drivers/acp/gemini.ts
25274
- import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
25500
+ import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
25275
25501
  import { homedir as homedir15 } from "node:os";
25276
- import { join as join22 } from "node:path";
25502
+ import { join as join23 } from "node:path";
25277
25503
  function liveOauthCredential() {
25278
25504
  try {
25279
- const creds = JSON.parse(readFileSync10(join22(homedir15(), ".gemini", "oauth_creds.json"), "utf8"));
25505
+ const creds = JSON.parse(readFileSync10(join23(homedir15(), ".gemini", "oauth_creds.json"), "utf8"));
25280
25506
  if (typeof creds.access_token !== "string" || creds.access_token.trim().length === 0) return false;
25281
25507
  const hasRefresh = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
25282
25508
  if (creds.expiry_date !== void 0) {
@@ -25289,7 +25515,7 @@ function liveOauthCredential() {
25289
25515
  }
25290
25516
  }
25291
25517
  function geminiIsAuthenticated(env) {
25292
- return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync9(join22(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
25518
+ return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync10(join23(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
25293
25519
  }
25294
25520
  var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
25295
25521
  var init_gemini = __esm({
@@ -25331,17 +25557,17 @@ ${turn.text}` : turn.text
25331
25557
  });
25332
25558
 
25333
25559
  // server/drivers/acp/kimi.ts
25334
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
25560
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
25335
25561
  import { homedir as homedir16 } from "node:os";
25336
- import { join as join23 } from "node:path";
25562
+ import { join as join24 } from "node:path";
25337
25563
  function isLocalInjectAlias(slug) {
25338
25564
  return LOCAL_PROVIDER_PREFIXES.some((prefix) => slug.startsWith(prefix));
25339
25565
  }
25340
25566
  function kimiDataRoot(env) {
25341
- return env.KIMI_CODE_HOME || join23(env.HOME || env.USERPROFILE || homedir16(), ".kimi-code");
25567
+ return env.KIMI_CODE_HOME || join24(env.HOME || env.USERPROFILE || homedir16(), ".kimi-code");
25342
25568
  }
25343
25569
  function credentialsPath(env) {
25344
- return join23(kimiDataRoot(env), "credentials", "kimi-code.json");
25570
+ return join24(kimiDataRoot(env), "credentials", "kimi-code.json");
25345
25571
  }
25346
25572
  function quoteToml2(value) {
25347
25573
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
@@ -25628,8 +25854,8 @@ function ensureKimiInjectAlias(modelId, env = process.env) {
25628
25854
  if (!host) return modelId;
25629
25855
  const alias = `${inject.host}/${inject.model.replace(/\//g, "-")}`;
25630
25856
  const dataRoot = kimiDataRoot(env);
25631
- mkdirSync7(dataRoot, { recursive: true });
25632
- const path3 = join23(dataRoot, "config.toml");
25857
+ mkdirSync8(dataRoot, { recursive: true });
25858
+ const path3 = join24(dataRoot, "config.toml");
25633
25859
  let text2 = "";
25634
25860
  try {
25635
25861
  text2 = readFileSync11(path3, "utf8");
@@ -25694,7 +25920,7 @@ function readKimiModelCatalog(env) {
25694
25920
  const dataRoot = kimiDataRoot(env);
25695
25921
  let text2 = "";
25696
25922
  try {
25697
- text2 = readFileSync11(join23(dataRoot, "config.toml"), "utf8");
25923
+ text2 = readFileSync11(join24(dataRoot, "config.toml"), "utf8");
25698
25924
  } catch {
25699
25925
  return STATIC_KIMI_MODELS;
25700
25926
  }
@@ -25803,7 +26029,7 @@ var init_kimi = __esm({
25803
26029
  authFailure: "continue",
25804
26030
  // Match the child CLI's own data-root precedence. A custom instance HOME or
25805
26031
  // KIMI_CODE_HOME must not be checked against the server user's home instead.
25806
- isAuthenticated: (env) => existsSync10(credentialsPath(env)),
26032
+ isAuthenticated: (env) => existsSync11(credentialsPath(env)),
25807
26033
  buildPromptText: (turn) => turn.system ? `${turn.system}
25808
26034
 
25809
26035
  ${turn.text}` : turn.text
@@ -25813,12 +26039,12 @@ ${turn.text}` : turn.text
25813
26039
  });
25814
26040
 
25815
26041
  // server/drivers/acp/droid.ts
25816
- import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
26042
+ import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
25817
26043
  import { homedir as homedir17 } from "node:os";
25818
- import { join as join24 } from "node:path";
26044
+ import { join as join25 } from "node:path";
25819
26045
  function authFilePaths(env) {
25820
26046
  const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir17();
25821
- return AUTH_FILES.map((name) => join24(home, ".factory", name));
26047
+ return AUTH_FILES.map((name) => join25(home, ".factory", name));
25822
26048
  }
25823
26049
  function droidInjectId(host, model) {
25824
26050
  const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
@@ -25833,14 +26059,14 @@ function ensureDroidInjectModel(modelId, env = process.env) {
25833
26059
  const host = localHost(inject.host);
25834
26060
  if (!host) return modelId;
25835
26061
  const id = droidInjectId(inject.host, inject.model);
25836
- const dir = join24(factoryHome(env), ".factory");
25837
- mkdirSync8(dir, { recursive: true });
25838
- const path3 = join24(dir, "settings.json");
26062
+ const dir = join25(factoryHome(env), ".factory");
26063
+ mkdirSync9(dir, { recursive: true });
26064
+ const path3 = join25(dir, "settings.json");
25839
26065
  let settings2 = {};
25840
26066
  try {
25841
26067
  settings2 = JSON.parse(readFileSync12(path3, "utf8"));
25842
26068
  } catch (error51) {
25843
- if (existsSync11(path3)) throw error51;
26069
+ if (existsSync12(path3)) throw error51;
25844
26070
  }
25845
26071
  const custom2 = Array.isArray(settings2.customModels) ? [...settings2.customModels] : [];
25846
26072
  const match = custom2.find(
@@ -25871,11 +26097,11 @@ function ensureDroidInjectModel(modelId, env = process.env) {
25871
26097
  function applyDroidLocalAuthEnv(env, modelId) {
25872
26098
  if (!decodeInjectId(modelId)) return;
25873
26099
  if (env.FACTORY_API_KEY?.trim()) return;
25874
- if (authFilePaths(env).some(existsSync11)) return;
26100
+ if (authFilePaths(env).some(existsSync12)) return;
25875
26101
  env.FACTORY_API_KEY = "openmausbot-local";
25876
26102
  }
25877
26103
  function readSettings(env) {
25878
- return JSON.parse(readFileSync12(join24(factoryHome(env), ".factory", "settings.json"), "utf8"));
26104
+ return JSON.parse(readFileSync12(join25(factoryHome(env), ".factory", "settings.json"), "utf8"));
25879
26105
  }
25880
26106
  async function resolveModels(env) {
25881
26107
  let catalog = MODELS3;
@@ -25962,7 +26188,7 @@ var init_droid = __esm({
25962
26188
  // The signed-in CLI is the primary source; FACTORY_API_KEY is the fallback
25963
26189
  // droid itself advertises, and it is checked last so an ambient key can
25964
26190
  // never be what makes an otherwise logged-out instance look ready.
25965
- isAuthenticated: (env) => authFilePaths(env).some(existsSync11) || Boolean(env.FACTORY_API_KEY),
26191
+ isAuthenticated: (env) => authFilePaths(env).some(existsSync12) || Boolean(env.FACTORY_API_KEY),
25966
26192
  resolveModels,
25967
26193
  resolveTurnModel: (model, env) => model ? ensureDroidInjectModel(model, env) : model,
25968
26194
  applyTurnEnv: (env, { requestedModel }) => {
@@ -26265,9 +26491,9 @@ ${turn.text}` : turn.text
26265
26491
  });
26266
26492
 
26267
26493
  // server/drivers/acp/opencode-go.ts
26268
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
26494
+ import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
26269
26495
  import { homedir as homedir18 } from "node:os";
26270
- import { join as join25 } from "node:path";
26496
+ import { join as join26 } from "node:path";
26271
26497
  function labelForModel(id) {
26272
26498
  return id.split(/[-_.]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
26273
26499
  }
@@ -26368,7 +26594,7 @@ async function discoverOpenCodeModels(environment, cli = "opencode") {
26368
26594
  }
26369
26595
  function opencodeConfigDir(env) {
26370
26596
  const home = env.HOME || env.USERPROFILE || homedir18();
26371
- return join25(env.XDG_CONFIG_HOME || join25(home, ".config"), "opencode");
26597
+ return join26(env.XDG_CONFIG_HOME || join26(home, ".config"), "opencode");
26372
26598
  }
26373
26599
  function ensureOpenCodeInjectModel(modelId, env = process.env) {
26374
26600
  const inject = decodeInjectId(modelId);
@@ -26377,10 +26603,10 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
26377
26603
  if (!host) return modelId;
26378
26604
  const native = `${inject.host}/${inject.model}`;
26379
26605
  const dir = opencodeConfigDir(env);
26380
- mkdirSync9(dir, { recursive: true });
26381
- const path3 = join25(dir, "opencode.json");
26606
+ mkdirSync10(dir, { recursive: true });
26607
+ const path3 = join26(dir, "opencode.json");
26382
26608
  let config2 = { $schema: "https://opencode.ai/config.json" };
26383
- if (existsSync12(path3)) {
26609
+ if (existsSync13(path3)) {
26384
26610
  try {
26385
26611
  config2 = JSON.parse(readFileSync13(path3, "utf8"));
26386
26612
  } catch {
@@ -26416,10 +26642,10 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
26416
26642
  function storedAuthPaths(env) {
26417
26643
  const home = env.HOME || env.USERPROFILE || homedir18();
26418
26644
  const roots = [
26419
- env.XDG_DATA_HOME || join25(home, ".local", "share"),
26420
- process.platform === "darwin" ? join25(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join25(home, "AppData", "Local") : ""
26645
+ env.XDG_DATA_HOME || join26(home, ".local", "share"),
26646
+ process.platform === "darwin" ? join26(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join26(home, "AppData", "Local") : ""
26421
26647
  ].filter(Boolean);
26422
- return [...new Set(roots)].map((root) => join25(root, "opencode", "auth.json"));
26648
+ return [...new Set(roots)].map((root) => join26(root, "opencode", "auth.json"));
26423
26649
  }
26424
26650
  function usableAuthEntry(parsed) {
26425
26651
  return Object.values(parsed).some((auth) => {
@@ -26549,13 +26775,13 @@ ${turn.text}` : turn.text
26549
26775
  });
26550
26776
 
26551
26777
  // server/drivers/acp/qwen.ts
26552
- import { chmodSync as chmodSync4, existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
26778
+ import { chmodSync as chmodSync4, existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
26553
26779
  import { createHash as createHash7 } from "node:crypto";
26554
26780
  import { homedir as homedir19 } from "node:os";
26555
- import { join as join26 } from "node:path";
26781
+ import { join as join27 } from "node:path";
26556
26782
  function qwenHome(env) {
26557
26783
  const home = process.platform === "win32" ? env.USERPROFILE || env.HOME || homedir19() : env.HOME || env.USERPROFILE || homedir19();
26558
- return join26(home, ".qwen");
26784
+ return join27(home, ".qwen");
26559
26785
  }
26560
26786
  function isRecord(value) {
26561
26787
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -26567,7 +26793,7 @@ function qwenModelLabel(id, name) {
26567
26793
  function readQwenRoutes(env) {
26568
26794
  let settings2;
26569
26795
  try {
26570
- settings2 = JSON.parse(readFileSync14(join26(qwenHome(env), "settings.json"), "utf8"));
26796
+ settings2 = JSON.parse(readFileSync14(join27(qwenHome(env), "settings.json"), "utf8"));
26571
26797
  } catch {
26572
26798
  return [];
26573
26799
  }
@@ -26650,10 +26876,10 @@ function ensureQwenInjectModel(modelId, env = process.env) {
26650
26876
  const host = localHost(inject.host);
26651
26877
  if (!host) return modelId;
26652
26878
  const dir = qwenHome(env);
26653
- mkdirSync10(dir, { recursive: true });
26654
- const path3 = join26(dir, "settings.json");
26879
+ mkdirSync11(dir, { recursive: true });
26880
+ const path3 = join27(dir, "settings.json");
26655
26881
  let settings2 = {};
26656
- if (existsSync13(path3)) {
26882
+ if (existsSync14(path3)) {
26657
26883
  try {
26658
26884
  settings2 = JSON.parse(readFileSync14(path3, "utf8"));
26659
26885
  } catch {
@@ -33650,9 +33876,9 @@ var init_browser = __esm({
33650
33876
 
33651
33877
  // server/drivers/acp/hermes.ts
33652
33878
  import { spawn as spawn5 } from "node:child_process";
33653
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
33879
+ import { mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
33654
33880
  import { homedir as homedir20 } from "node:os";
33655
- import { join as join27 } from "node:path";
33881
+ import { join as join28 } from "node:path";
33656
33882
  function bindHermesScreenshotCompat(env, modelId) {
33657
33883
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT];
33658
33884
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL];
@@ -33662,7 +33888,7 @@ function bindHermesScreenshotCompat(env, modelId) {
33662
33888
  env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL] = inject.model;
33663
33889
  }
33664
33890
  function hermesHome(env) {
33665
- return env.HERMES_HOME || join27(env.HOME || env.USERPROFILE || homedir20(), ".hermes");
33891
+ return env.HERMES_HOME || join28(env.HOME || env.USERPROFILE || homedir20(), ".hermes");
33666
33892
  }
33667
33893
  function quoteYaml(value) {
33668
33894
  if (/^[\w./:+-]+$/.test(value)) return value;
@@ -33703,8 +33929,8 @@ function ensureHermesInjectProvider(modelId, env = process.env) {
33703
33929
  const host = localHost(inject.host);
33704
33930
  if (!host) return modelId;
33705
33931
  const dir = hermesHome(env);
33706
- mkdirSync11(dir, { recursive: true });
33707
- const path3 = join27(dir, "config.yaml");
33932
+ mkdirSync12(dir, { recursive: true });
33933
+ const path3 = join28(dir, "config.yaml");
33708
33934
  let text2 = "";
33709
33935
  try {
33710
33936
  text2 = readFileSync15(path3, "utf8");
@@ -33775,13 +34001,13 @@ function hermesConfiguredModel(env = process.env) {
33775
34001
  const dir = hermesHome(env);
33776
34002
  let secrets = "";
33777
34003
  try {
33778
- secrets = readFileSync15(join27(dir, ".env"), "utf8");
34004
+ secrets = readFileSync15(join28(dir, ".env"), "utf8");
33779
34005
  } catch {
33780
34006
  }
33781
34007
  const hasHostedProviderKey = HERMES_HOSTED_PROVIDER_KEYS.some((name) => nonEmptyDotenvValue(secrets, name));
33782
34008
  let configuredDefault = null;
33783
34009
  try {
33784
- configuredDefault = hermesConfigDefault(readFileSync15(join27(dir, "config.yaml"), "utf8"));
34010
+ configuredDefault = hermesConfigDefault(readFileSync15(join28(dir, "config.yaml"), "utf8"));
33785
34011
  } catch {
33786
34012
  }
33787
34013
  const configuredProvider = configuredDefault?.provider.toLowerCase() ?? "";
@@ -34101,9 +34327,9 @@ var init_openai_compat = __esm({
34101
34327
  });
34102
34328
 
34103
34329
  // server/drivers/pi.ts
34104
- import { chmodSync as chmodSync5, existsSync as existsSync14, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
34330
+ import { chmodSync as chmodSync5, existsSync as existsSync15, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
34105
34331
  import { homedir as homedir21, tmpdir as tmpdir4 } from "node:os";
34106
- import { join as join28 } from "node:path";
34332
+ import { join as join29 } from "node:path";
34107
34333
  function readPiPromptImages(turn) {
34108
34334
  return (turn.images ?? []).map((image) => ({
34109
34335
  type: "image",
@@ -34210,7 +34436,7 @@ async function applyPiLocalCatalog(catalog, env = process.env, fetchImpl = fetch
34210
34436
  return preferPiInjectRows(await mergeLocalInject(catalog, env, fetchImpl));
34211
34437
  }
34212
34438
  function piAgentDir(env) {
34213
- return join28(env.HOME || env.USERPROFILE || homedir21(), ".pi", "agent");
34439
+ return join29(env.HOME || env.USERPROFILE || homedir21(), ".pi", "agent");
34214
34440
  }
34215
34441
  function ensurePiInjectModel(modelId, env = process.env) {
34216
34442
  const split = splitPiModel(modelId);
@@ -34220,10 +34446,10 @@ function ensurePiInjectModel(modelId, env = process.env) {
34220
34446
  const host = localHost(inject.host);
34221
34447
  if (!host) return split;
34222
34448
  const dir = piAgentDir(env);
34223
- mkdirSync12(dir, { recursive: true });
34224
- const path3 = join28(dir, "models.json");
34449
+ mkdirSync13(dir, { recursive: true });
34450
+ const path3 = join29(dir, "models.json");
34225
34451
  let root = { providers: {} };
34226
- if (existsSync14(path3)) {
34452
+ if (existsSync15(path3)) {
34227
34453
  try {
34228
34454
  const parsed = JSON.parse(readFileSync16(path3, "utf8"));
34229
34455
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
@@ -34423,9 +34649,9 @@ var init_pi = __esm({
34423
34649
  const mcpServers = buildMcpServers(turn);
34424
34650
  let mcpTempDir = null;
34425
34651
  if (mcpServers) {
34426
- mcpTempDir = mkdtempSync3(join28(tmpdir4(), "omb-pi-mcp-"));
34652
+ mcpTempDir = mkdtempSync3(join29(tmpdir4(), "omb-pi-mcp-"));
34427
34653
  try {
34428
- writeFileSync12(join28(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
34654
+ writeFileSync12(join29(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
34429
34655
  } catch (err) {
34430
34656
  try {
34431
34657
  rmSync3(mcpTempDir, { recursive: true, force: true });
@@ -34443,7 +34669,7 @@ var init_pi = __esm({
34443
34669
  env: piEnvironment({
34444
34670
  ...process.env,
34445
34671
  ...input.environment,
34446
- ...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join28(mcpTempDir, "mcp.json") } : {}
34672
+ ...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join29(mcpTempDir, "mcp.json") } : {}
34447
34673
  })
34448
34674
  });
34449
34675
  } catch (err) {
@@ -34782,14 +35008,14 @@ ${turn.text}` : turn.text;
34782
35008
  // server/drivers/minimax.ts
34783
35009
  import { readFileSync as readFileSync17 } from "node:fs";
34784
35010
  import { homedir as homedir22 } from "node:os";
34785
- import { join as join29 } from "node:path";
35011
+ import { join as join30 } from "node:path";
34786
35012
  function normalizedApiUrl(value) {
34787
35013
  const root = value.trim().replace(/\/+$/, "");
34788
35014
  return root.endsWith("/v1") ? root : `${root}/v1`;
34789
35015
  }
34790
35016
  function loadLocalMiniMaxConfig(home = homedir22()) {
34791
35017
  try {
34792
- const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join29(home, ".mmx", "config.json"), "utf8")));
35018
+ const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join30(home, ".mmx", "config.json"), "utf8")));
34793
35019
  const configuredUrl = raw.base_url?.trim() ? raw.base_url : raw.region === "cn" ? CN_URL : DEFAULT_URL2;
34794
35020
  return {
34795
35021
  apiKey: raw.api_key?.trim() ?? "",
@@ -35057,7 +35283,7 @@ __export(cli_setup_exports, {
35057
35283
  });
35058
35284
  import { spawn as spawn6 } from "node:child_process";
35059
35285
  import { readFileSync as readFileSync18 } from "node:fs";
35060
- import { join as join30, resolve as resolve10 } from "node:path";
35286
+ import { join as join31, resolve as resolve10 } from "node:path";
35061
35287
  import { randomUUID as randomUUID10 } from "node:crypto";
35062
35288
  async function inspect(id, entry) {
35063
35289
  const registry2 = new ProviderRegistry(BUILT_IN_DRIVERS);
@@ -35094,7 +35320,7 @@ function assertDataDir(dataDir) {
35094
35320
  }
35095
35321
  function checkStoredConfig(dataDir) {
35096
35322
  try {
35097
- parseStoredConfig(JSON.parse(readFileSync18(join30(dataDir, "config.json"), "utf8")));
35323
+ parseStoredConfig(JSON.parse(readFileSync18(join31(dataDir, "config.json"), "utf8")));
35098
35324
  } catch (error51) {
35099
35325
  if (error51.code === "ENOENT") return;
35100
35326
  throw new Error("Existing config.json could not be read or validated. Setup has not changed it; repair it before continuing.");
@@ -35372,7 +35598,7 @@ var init_browser_engine_release = __esm({
35372
35598
  });
35373
35599
 
35374
35600
  // server/browser-bundle-release.ts
35375
- import { join as join31 } from "node:path";
35601
+ import { join as join32 } from "node:path";
35376
35602
  function browserBundleSpec(target) {
35377
35603
  if (!Object.hasOwn(CHROME_ASSETS, target)) throw new Error(`Unsupported desktop browser target: ${target}`);
35378
35604
  const pinned = CHROME_ASSETS[target];
@@ -35408,10 +35634,10 @@ function browserBundlePaths(bundleDirectory, target) {
35408
35634
  const spec = browserBundleSpec(target);
35409
35635
  return {
35410
35636
  directory: bundleDirectory,
35411
- manifest: join31(bundleDirectory, "manifest.json"),
35412
- engine: join31(bundleDirectory, spec.engine.executable),
35413
- chrome: join31(bundleDirectory, spec.chrome.executable),
35414
- licenses: join31(bundleDirectory, "licenses")
35637
+ manifest: join32(bundleDirectory, "manifest.json"),
35638
+ engine: join32(bundleDirectory, spec.engine.executable),
35639
+ chrome: join32(bundleDirectory, spec.chrome.executable),
35640
+ licenses: join32(bundleDirectory, "licenses")
35415
35641
  };
35416
35642
  }
35417
35643
  var CHROME_VERSION, CHROME_ASSETS;
@@ -35466,9 +35692,9 @@ __export(browser_engine_exports, {
35466
35692
  });
35467
35693
  import { spawn as spawn7 } from "node:child_process";
35468
35694
  import { createHash as createHash8, randomBytes as randomBytes3, randomUUID as randomUUID11 } from "node:crypto";
35469
- import { chmodSync as chmodSync6, constants as constants2, copyFileSync, existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync19, readdirSync as readdirSync3, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "node:fs";
35695
+ import { chmodSync as chmodSync6, constants as constants2, copyFileSync, existsSync as existsSync16, mkdirSync as mkdirSync14, readFileSync as readFileSync19, readdirSync as readdirSync3, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "node:fs";
35470
35696
  import { homedir as homedir23, tmpdir as tmpdir5 } from "node:os";
35471
- import { delimiter as delimiter6, dirname as dirname10, join as join32, resolve as resolve11 } from "node:path";
35697
+ import { delimiter as delimiter6, dirname as dirname10, join as join33, resolve as resolve11 } from "node:path";
35472
35698
  function browserRestoreKey(session) {
35473
35699
  if (!/^[A-Za-z0-9_-]{1,96}$/.test(session)) throw new Error("Invalid browser session.");
35474
35700
  return `omb-${createHash8("sha256").update(session).digest("hex")}`;
@@ -35477,15 +35703,15 @@ function browserSessionsDirectory(env) {
35477
35703
  const namespace = env.AGENT_BROWSER_NAMESPACE;
35478
35704
  if (namespace && !/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/.test(namespace)) throw new Error("Invalid browser namespace.");
35479
35705
  const home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir23();
35480
- const stateRoot = namespace ? join32(home, ".agent-browser", "namespaces", namespace, "state") : join32(home, ".agent-browser");
35481
- return join32(stateRoot, "sessions");
35706
+ const stateRoot = namespace ? join33(home, ".agent-browser", "namespaces", namespace, "state") : join33(home, ".agent-browser");
35707
+ return join33(stateRoot, "sessions");
35482
35708
  }
35483
35709
  function managedBrowserConfigPath(env) {
35484
- return join32(browserSessionsDirectory(env), "..", "omb-managed-config.json");
35710
+ return join33(browserSessionsDirectory(env), "..", "omb-managed-config.json");
35485
35711
  }
35486
35712
  function ensureManagedBrowserConfig(env) {
35487
35713
  const path3 = managedBrowserConfigPath(env);
35488
- mkdirSync13(dirname10(path3), { recursive: true, mode: 448 });
35714
+ mkdirSync14(dirname10(path3), { recursive: true, mode: 448 });
35489
35715
  try {
35490
35716
  writeFileSync13(path3, "{}\n", { flag: "wx", mode: 384 });
35491
35717
  } catch (error51) {
@@ -35568,12 +35794,12 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
35568
35794
  ensureManagedBrowserConfig(env);
35569
35795
  if (options.persistent === false) return;
35570
35796
  const directory = browserSessionsDirectory(env);
35571
- const key = join32(directory, session);
35797
+ const key = join33(directory, session);
35572
35798
  let pending = preparedBrowserSessions.get(key);
35573
35799
  if (!pending) {
35574
35800
  pending = (async () => {
35575
- const targetBase = join32(directory, `${restoreKey}-${session}`);
35576
- const hasTarget = () => existsSync15(`${targetBase}.json.enc`) || existsSync15(`${targetBase}.json`);
35801
+ const targetBase = join33(directory, `${restoreKey}-${session}`);
35802
+ const hasTarget = () => existsSync16(`${targetBase}.json.enc`) || existsSync16(`${targetBase}.json`);
35577
35803
  if (hasTarget()) return;
35578
35804
  check2();
35579
35805
  if (!await closeBrowserSession(binaryPath, { ...env, AGENT_BROWSER_RESTORE: session }, options.timeoutMs)) {
@@ -35582,7 +35808,7 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
35582
35808
  check2();
35583
35809
  if (hasTarget()) return;
35584
35810
  const candidates = [".json.enc", ".json"].flatMap((suffix) => {
35585
- const path3 = join32(directory, `${session}-${session}${suffix}`);
35811
+ const path3 = join33(directory, `${session}-${session}${suffix}`);
35586
35812
  try {
35587
35813
  const stat4 = statSync3(path3);
35588
35814
  if (!stat4.isFile()) throw new Error("Saved browser state is not a file.");
@@ -35612,12 +35838,12 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
35612
35838
  function executableName(platform = process.platform) {
35613
35839
  return platform === "win32" ? "agent-browser.exe" : "agent-browser";
35614
35840
  }
35615
- function isMusl(platform = process.platform, exists = existsSync15) {
35841
+ function isMusl(platform = process.platform, exists = existsSync16) {
35616
35842
  return platform === "linux" && (exists("/lib/ld-musl-x86_64.so.1") || exists("/lib/ld-musl-aarch64.so.1"));
35617
35843
  }
35618
35844
  function pinnedBinaryPath(dataDir = DATA_DIR, platform = process.platform, arch = process.arch) {
35619
35845
  const version2 = agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform, arch));
35620
- return join32(dataDir, ENGINE_DIR, version2, executableName(platform));
35846
+ return join33(dataDir, ENGINE_DIR, version2, executableName(platform));
35621
35847
  }
35622
35848
  function onPath(env, platform, exists) {
35623
35849
  const pathValue = platform === "win32" ? Object.entries(env).findLast(([key]) => key.toUpperCase() === "PATH")?.[1] : env.PATH;
@@ -35633,7 +35859,7 @@ function packagedBrowser(options) {
35633
35859
  const resources = (options.env ?? process.env).OMB_RESOURCES_PATH;
35634
35860
  if (!resources) return null;
35635
35861
  try {
35636
- return browserBundlePaths(join32(resolve11(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
35862
+ return browserBundlePaths(join33(resolve11(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
35637
35863
  } catch {
35638
35864
  return null;
35639
35865
  }
@@ -35644,7 +35870,7 @@ function completePackage(bundle, exists) {
35644
35870
  function resolveAgentBrowserBinary(options = {}) {
35645
35871
  const env = options.env ?? process.env;
35646
35872
  const platform = options.platform ?? process.platform;
35647
- const exists = options.exists ?? existsSync15;
35873
+ const exists = options.exists ?? existsSync16;
35648
35874
  const override = env.OMB_AGENT_BROWSER_PATH?.trim();
35649
35875
  if (override) return resolve11(override) && exists(resolve11(override)) ? resolve11(override) : null;
35650
35876
  const bundle = packagedBrowser(options);
@@ -35658,8 +35884,8 @@ async function installAgentBrowserBinary(options = {}) {
35658
35884
  const asset = options.asset ?? resolveAgentBrowserReleaseAsset(platform, options.arch ?? process.arch, options.musl ?? isMusl(platform));
35659
35885
  if (!asset) throw new Error(`agent-browser publishes no build for ${platform}-${options.arch ?? process.arch}.`);
35660
35886
  const destination = pinnedBinaryPath(options.dataDir, platform, options.arch);
35661
- const directory = join32(destination, "..");
35662
- mkdirSync13(directory, { recursive: true, mode: 448 });
35887
+ const directory = join33(destination, "..");
35888
+ mkdirSync14(directory, { recursive: true, mode: 448 });
35663
35889
  const url2 = agentBrowserReleaseUrl(asset);
35664
35890
  options.log?.(`downloading agent-browser ${agentBrowserReleaseVersion(asset)} (${Math.round(asset.bytes / 1024 / 1024)} MB, digest pinned)`);
35665
35891
  const controller = new AbortController();
@@ -35684,7 +35910,7 @@ async function installAgentBrowserBinary(options = {}) {
35684
35910
  }
35685
35911
  function ensureChrome(binaryPath, options = {}) {
35686
35912
  const bundle = packagedBrowser(options);
35687
- if (!options.withDeps && bundle && resolve11(binaryPath) === bundle.engine && completePackage(bundle, existsSync15)) {
35913
+ if (!options.withDeps && bundle && resolve11(binaryPath) === bundle.engine && completePackage(bundle, existsSync16)) {
35688
35914
  options.log?.("agent-browser: the bundled browser is ready; no download needed");
35689
35915
  return Promise.resolve();
35690
35916
  }
@@ -35710,14 +35936,14 @@ function ensureChrome(binaryPath, options = {}) {
35710
35936
  });
35711
35937
  }
35712
35938
  function browserEngineEncryptionKey(dataDir = DATA_DIR) {
35713
- const file2 = join32(dataDir, KEY_FILE);
35939
+ const file2 = join33(dataDir, KEY_FILE);
35714
35940
  try {
35715
35941
  const existing = readFileSync19(file2, "utf8").trim();
35716
35942
  if (/^[0-9a-f]{64}$/u.test(existing)) return existing;
35717
35943
  } catch {
35718
35944
  }
35719
35945
  const key = randomBytes3(32).toString("hex");
35720
- mkdirSync13(dataDir, { recursive: true });
35946
+ mkdirSync14(dataDir, { recursive: true });
35721
35947
  writeFileAtomic(file2, `${key}
35722
35948
  `, { mode: 384 });
35723
35949
  return key;
@@ -35731,7 +35957,7 @@ function browserEngineStatus(options = {}) {
35731
35957
  const version2 = managed ? agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform2, options.arch)) : AGENT_BROWSER_VERSION;
35732
35958
  return { kind: "ready", binaryPath, version: version2 };
35733
35959
  }
35734
- if (bundle && (options.exists ?? existsSync15)(bundle.directory)) {
35960
+ if (bundle && (options.exists ?? existsSync16)(bundle.directory)) {
35735
35961
  return { kind: "unavailable", reason: "The desktop browser bundle is incomplete. Reinstall or update OpenMausBot to repair it.", installable: false };
35736
35962
  }
35737
35963
  const platform = options.platform ?? process.platform;
@@ -35764,13 +35990,13 @@ function agentBrowserIntegration(input) {
35764
35990
  if (sourceEnv[name]) env[name] = sourceEnv[name];
35765
35991
  }
35766
35992
  const bundle = packagedBrowser({ env: sourceEnv });
35767
- if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve11(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync15)) {
35993
+ if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve11(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync16)) {
35768
35994
  env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
35769
35995
  }
35770
35996
  return { command: input.binaryPath, args: ["mcp", "--tools", "core", "--no-webmcp"], env };
35771
35997
  }
35772
35998
  function agentBrowserFrame(input) {
35773
- const file2 = join32(tmpdir5(), `openmausbot-browser-${randomUUID11()}.png`);
35999
+ const file2 = join33(tmpdir5(), `openmausbot-browser-${randomUUID11()}.png`);
35774
36000
  return new Promise((settle, fail) => {
35775
36001
  const child = spawn7(input.binaryPath, ["screenshot", file2], {
35776
36002
  env: browserRuntimeEnv(input.env),
@@ -35840,8 +36066,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
35840
36066
  }
35841
36067
  };
35842
36068
  try {
35843
- for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(join32(directory, base2 + suffix));
35844
- const pendingDirectory = join32(directory, ".tmp");
36069
+ for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(join33(directory, base2 + suffix));
36070
+ const pendingDirectory = join33(directory, ".tmp");
35845
36071
  let pendingFiles = [];
35846
36072
  try {
35847
36073
  pendingFiles = readdirSync3(pendingDirectory);
@@ -35849,8 +36075,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
35849
36075
  if (error51.code !== "ENOENT") throw error51;
35850
36076
  }
35851
36077
  const candidates = bases.map((base2) => new RegExp(`^${base2}-candidate-[0-9]+\\.json(?:\\.enc)?$`));
35852
- for (const name of pendingFiles) if (candidates.some((candidate) => candidate.test(name))) remove(join32(pendingDirectory, name));
35853
- preparedBrowserSessions.delete(join32(directory, session));
36078
+ for (const name of pendingFiles) if (candidates.some((candidate) => candidate.test(name))) remove(join33(pendingDirectory, name));
36079
+ preparedBrowserSessions.delete(join33(directory, session));
35854
36080
  return true;
35855
36081
  } catch {
35856
36082
  return false;
@@ -35877,9 +36103,9 @@ var init_browser_engine = __esm({
35877
36103
  // server/cli.ts
35878
36104
  var import_qrcode_terminal = __toESM(require_main(), 1);
35879
36105
  import { spawn as spawn8 } from "node:child_process";
35880
- import { closeSync as closeSync3, existsSync as existsSync16, mkdirSync as mkdirSync14, openSync as openSync3, readFileSync as readFileSync20 } from "node:fs";
36106
+ import { closeSync as closeSync3, existsSync as existsSync17, mkdirSync as mkdirSync15, openSync as openSync3, readFileSync as readFileSync20 } from "node:fs";
35881
36107
  import { homedir as homedir24 } from "node:os";
35882
- import { dirname as dirname11, join as join33, resolve as resolve12 } from "node:path";
36108
+ import { dirname as dirname11, join as join34, resolve as resolve12 } from "node:path";
35883
36109
  import { createInterface as createInterface2 } from "node:readline/promises";
35884
36110
  import { fileURLToPath as fileURLToPath3 } from "node:url";
35885
36111
 
@@ -38124,7 +38350,7 @@ function parseArgs(argv, env = process.env) {
38124
38350
  const options = {
38125
38351
  command: command === "--help" || command === "-h" ? "help" : command,
38126
38352
  port: Number(env.OMB_PORT || 8799),
38127
- dataDir: env.OMB_DATA_DIR || join33(homedir24(), ".openmausbot"),
38353
+ dataDir: env.OMB_DATA_DIR || join34(homedir24(), ".openmausbot"),
38128
38354
  tailscale: false,
38129
38355
  tunnel: false,
38130
38356
  client: false,
@@ -38279,7 +38505,7 @@ async function isWorkspaceRunning(options) {
38279
38505
  try {
38280
38506
  const { status, body } = await api(options.port, "/api/health");
38281
38507
  if (status !== 200 || body?.app !== "openmausbot") return false;
38282
- const expected = readFileSync20(join33(options.dataDir, "environment-id"), "utf8").trim();
38508
+ const expected = readFileSync20(join34(options.dataDir, "environment-id"), "utf8").trim();
38283
38509
  const descriptor = await api(options.port, "/.well-known/openmausbot/environment");
38284
38510
  return /^[0-9a-f-]{36}$/i.test(expected) && descriptor.status === 200 && descriptor.body?.environmentId === expected;
38285
38511
  } catch {
@@ -38479,9 +38705,9 @@ async function runStatus(options, io = defaultIo()) {
38479
38705
  return code;
38480
38706
  }
38481
38707
  async function runAccess(options, io = defaultIo()) {
38482
- const file2 = join33(options.dataDir, "config.json");
38708
+ const file2 = join34(options.dataDir, "config.json");
38483
38709
  let raw = {};
38484
- if (existsSync16(file2)) {
38710
+ if (existsSync17(file2)) {
38485
38711
  try {
38486
38712
  const parsed = JSON.parse(readFileSync20(file2, "utf8"));
38487
38713
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("not an object");
@@ -38497,7 +38723,7 @@ async function runAccess(options, io = defaultIo()) {
38497
38723
  const members = list(Reflect.get(current, "members"));
38498
38724
  const overridden = process.env.OMB_SIGNIN_EMAILS !== void 0 || process.env.OMB_SIGNIN_MEMBER_EMAILS !== void 0;
38499
38725
  const write = (next) => {
38500
- mkdirSync14(options.dataDir, { recursive: true, mode: 448 });
38726
+ mkdirSync15(options.dataDir, { recursive: true, mode: 448 });
38501
38727
  writeFileAtomic(file2, `${JSON.stringify({ ...raw, signIn: next }, null, 2)}
38502
38728
  `, { mode: 384 });
38503
38729
  };
@@ -38631,16 +38857,16 @@ async function runBrowser(options, io = defaultIo()) {
38631
38857
  return 0;
38632
38858
  }
38633
38859
  function serverEntry(here = HERE2) {
38634
- const bundled = join33(here, "index.js");
38860
+ const bundled = join34(here, "index.js");
38635
38861
  const root = resolve12(here, "..");
38636
- if (existsSync16(bundled)) {
38637
- const staticDir2 = [join33(root, "dist"), join33(here, "..", "ui")].find((d) => existsSync16(join33(d, "index.html"))) ?? null;
38638
- const skillsDir = existsSync16(join33(root, "skills")) ? join33(root, "skills") : null;
38862
+ if (existsSync17(bundled)) {
38863
+ const staticDir2 = [join34(root, "dist"), join34(here, "..", "ui")].find((d) => existsSync17(join34(d, "index.html"))) ?? null;
38864
+ const skillsDir = existsSync17(join34(root, "skills")) ? join34(root, "skills") : null;
38639
38865
  return { command: process.execPath, args: [bundled], staticDir: staticDir2, skillsDir };
38640
38866
  }
38641
- const source = join33(here, "index.ts");
38642
- const staticDir = existsSync16(join33(root, "dist", "index.html")) ? join33(root, "dist") : null;
38643
- return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync16(join33(root, "skills")) ? join33(root, "skills") : null };
38867
+ const source = join34(here, "index.ts");
38868
+ const staticDir = existsSync17(join34(root, "dist", "index.html")) ? join34(root, "dist") : null;
38869
+ return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync17(join34(root, "skills")) ? join34(root, "skills") : null };
38644
38870
  }
38645
38871
  async function planTunnel(options, log) {
38646
38872
  let access2 = null;
@@ -38740,9 +38966,9 @@ async function runServe(options, log = console.log) {
38740
38966
  let child;
38741
38967
  try {
38742
38968
  if (options.guided) {
38743
- const logsDir = join33(options.dataDir, "logs");
38744
- mkdirSync14(logsDir, { recursive: true, mode: 448 });
38745
- logPath = join33(logsDir, `server-${Date.now()}-${process.pid}.log`);
38969
+ const logsDir = join34(options.dataDir, "logs");
38970
+ mkdirSync15(logsDir, { recursive: true, mode: 448 });
38971
+ logPath = join34(logsDir, `server-${Date.now()}-${process.pid}.log`);
38746
38972
  logFd = openSync3(logPath, "wx", 384);
38747
38973
  log("\nStarting your workspace\u2026");
38748
38974
  }
@@ -38934,7 +39160,7 @@ async function runOnboardingCommand(options, io = defaultIo(), startServer = run
38934
39160
  }
38935
39161
  if (options.command === "setup") {
38936
39162
  io.log("\nAll set. Start with: openmausbot (or npx openmausbot without a global install).");
38937
- if (options.dataDir !== join33(homedir24(), ".openmausbot") || options.port !== 8799) {
39163
+ if (options.dataDir !== join34(homedir24(), ".openmausbot") || options.port !== 8799) {
38938
39164
  io.log(`Use the same --data-dir (${options.dataDir}) and --port (${options.port}) options when starting.`);
38939
39165
  }
38940
39166
  return 0;