openmausbot 0.1.63 → 0.1.65

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.
@@ -2265,7 +2265,7 @@ function displayText(value, multiline = false) {
2265
2265
  }
2266
2266
  function plainText(question, hidden, context) {
2267
2267
  const { input, output, signal } = context;
2268
- return new Promise((resolve9, reject) => {
2268
+ return new Promise((resolve10, reject) => {
2269
2269
  input.setRawMode?.(hidden);
2270
2270
  const rl = createInterface({ input, terminal: hidden });
2271
2271
  let finished = false;
@@ -2276,7 +2276,7 @@ function plainText(question, hidden, context) {
2276
2276
  rl.close();
2277
2277
  output.write("\n");
2278
2278
  if (error51) reject(error51);
2279
- else resolve9(answer ?? "");
2279
+ else resolve10(answer ?? "");
2280
2280
  };
2281
2281
  const cancel = () => finish(void 0, signal.reason ?? new SetupCancelled());
2282
2282
  signal.addEventListener("abort", cancel, { once: true });
@@ -17758,6 +17758,7 @@ function saveConfig(patch) {
17758
17758
  }
17759
17759
  if (checkedPatch.vps !== void 0) disk.vps = normalizeVpsConfig(checkedPatch.vps);
17760
17760
  if (checkedPatch.language !== void 0) disk.language = checkedPatch.language;
17761
+ if (checkedPatch.customDomain !== void 0) disk.customDomain = checkedPatch.customDomain;
17761
17762
  if (checkedPatch.defaultModelSelection !== void 0) {
17762
17763
  disk.defaultModelSelection = checkedPatch.defaultModelSelection;
17763
17764
  }
@@ -17948,6 +17949,8 @@ var init_config = __esm({
17948
17949
  effort: external_exports.enum(EFFORT_LEVELS).optional()
17949
17950
  });
17950
17951
  appConfigSchema = external_exports.object({
17952
+ /** Verified by the dedicated domain endpoint, never a generic config patch. */
17953
+ customDomain: external_exports.string().optional(),
17951
17954
  defaultModelSelection: defaultModelSelectionSchema.optional(),
17952
17955
  /** CLI-only launch preferences. Never enable remote access implicitly. */
17953
17956
  cliStartup: external_exports.object({
@@ -17991,7 +17994,7 @@ var init_config = __esm({
17991
17994
  storedAppConfigSchema = appConfigSchema.extend({
17992
17995
  browserProfiles: storedBrowserProfilesSchema.optional()
17993
17996
  });
17994
- appConfigPatchSchema = appConfigSchema.omit({ instances: true, mcpServers: true, cliStartup: true });
17997
+ appConfigPatchSchema = appConfigSchema.omit({ instances: true, mcpServers: true, cliStartup: true, customDomain: true });
17995
17998
  jsonObjectSchema = external_exports.record(external_exports.string(), external_exports.json());
17996
17999
  DATA_DIR = process.env.OMB_DATA_DIR ?? join3(homedir2(), ".openmausbot");
17997
18000
  LEGACY_DATA_DIR = join3(homedir2(), ".opengrokbot");
@@ -18614,12 +18617,12 @@ function describeSpawnFailure(err, cli) {
18614
18617
  function killCliTree(child, timeoutMs = 5e3) {
18615
18618
  const pid = child.pid;
18616
18619
  if (!pid || child.exitCode !== null || child.signalCode !== null) return Promise.resolve(true);
18617
- return new Promise((resolve9) => {
18620
+ return new Promise((resolve10) => {
18618
18621
  let timer;
18619
18622
  const done = (stopped) => {
18620
18623
  clearTimeout(timer);
18621
18624
  child.off("close", closed);
18622
- resolve9(stopped);
18625
+ resolve10(stopped);
18623
18626
  };
18624
18627
  const closed = () => done(true);
18625
18628
  child.once("close", closed);
@@ -18766,6 +18769,10 @@ var init_registry = __esm({
18766
18769
  const instance = this.get(instanceId);
18767
18770
  return instance?.startAuthentication ? instance.startAuthentication() : null;
18768
18771
  }
18772
+ async getAuthentication(instanceId, flowId) {
18773
+ const instance = this.get(instanceId);
18774
+ return instance?.getAuthentication ? instance.getAuthentication(flowId) : null;
18775
+ }
18769
18776
  async completeAuthentication(instanceId, flowId, callbackUrl) {
18770
18777
  const instance = this.get(instanceId);
18771
18778
  if (!instance?.completeAuthentication) return false;
@@ -18838,6 +18845,7 @@ var init_registry = __esm({
18838
18845
  },
18839
18846
  access: driver?.metadata.access ?? "subscription",
18840
18847
  install: driver?.install,
18848
+ authentication: inst.startAuthentication ? { method: inst.getAuthentication ? "device-code" : "browser" } : void 0,
18841
18849
  cli: this.cliByInstance.get(inst.instanceId),
18842
18850
  cliDefault: cliDefaultOf(driver),
18843
18851
  // every copy of the driver's default binary on the augmented PATH —
@@ -19543,7 +19551,7 @@ function createAcpDriver(support11) {
19543
19551
  }
19544
19552
  appendNative(threadId, { dir: "out", source: SOURCE, msg: nativeLogMessage(obj) });
19545
19553
  };
19546
- const request = (method, params, timeoutMs) => new Promise((resolve9, reject) => {
19554
+ const request = (method, params, timeoutMs) => new Promise((resolve10, reject) => {
19547
19555
  const id = nextId++;
19548
19556
  let timer = null;
19549
19557
  if (timeoutMs) {
@@ -19553,7 +19561,7 @@ function createAcpDriver(support11) {
19553
19561
  }, timeoutMs);
19554
19562
  timer.unref?.();
19555
19563
  }
19556
- rpcPending.set(id, { resolve: resolve9, reject, timer });
19564
+ rpcPending.set(id, { resolve: resolve10, reject, timer });
19557
19565
  send({ jsonrpc: "2.0", id, method, params });
19558
19566
  });
19559
19567
  const stop = () => killCliTree(child);
@@ -19989,12 +19997,12 @@ ${turn.text}` : turn.text;
19989
19997
  const snapshot = async () => {
19990
19998
  const env = childEnv();
19991
19999
  if (support11.snapshot) return support11.snapshot(env, config2, instanceId);
19992
- const version2 = await new Promise((resolve9) => {
20000
+ const version2 = await new Promise((resolve10) => {
19993
20001
  execCli(
19994
20002
  config2.cli,
19995
20003
  ["--version"],
19996
20004
  { timeout: 8e3, env },
19997
- (err, stdout2) => resolve9(err ? null : stdout2.trim())
20005
+ (err, stdout2) => resolve10(err ? null : stdout2.trim())
19998
20006
  );
19999
20007
  });
20000
20008
  if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
@@ -20384,14 +20392,14 @@ var init_antigravity_acp = __esm({
20384
20392
  this.child.stderr.setEncoding("utf8");
20385
20393
  this.child.stderr.on("data", (chunk) => this.consumeDiagnostics(chunk));
20386
20394
  this.child.once("error", (error51) => this.failAll(error51));
20387
- this.exited = new Promise((resolve9) => {
20395
+ this.exited = new Promise((resolve10) => {
20388
20396
  this.child.once("close", (code, signal) => {
20389
20397
  this.noteStartupDiagnostic(this.diagnosticBuffer);
20390
20398
  this.diagnosticBuffer = "";
20391
20399
  if (!this.closed) this.failAll(new Error(
20392
20400
  `Antigravity ACP exited ${code ?? signal ?? "unexpectedly"}.${this.nativeStartupHint ? ` ${this.nativeStartupHint}` : ""}`
20393
20401
  ));
20394
- resolve9();
20402
+ resolve10();
20395
20403
  });
20396
20404
  });
20397
20405
  }
@@ -20497,8 +20505,8 @@ var init_antigravity_acp = __esm({
20497
20505
  async closeAndWait(timeoutMs = 5e3) {
20498
20506
  this.close();
20499
20507
  let timer;
20500
- const timedOut = new Promise((resolve9) => {
20501
- timer = setTimeout(() => resolve9(false), timeoutMs);
20508
+ const timedOut = new Promise((resolve10) => {
20509
+ timer = setTimeout(() => resolve10(false), timeoutMs);
20502
20510
  timer.unref?.();
20503
20511
  });
20504
20512
  try {
@@ -21007,7 +21015,7 @@ var init_antigravity_runtime = __esm({
21007
21015
  FREE_SPACE_MARGIN = 256 * 1024 * 1024;
21008
21016
  DOWNLOAD_TIMEOUT_MS = 45 * 6e4;
21009
21017
  STAGING_PREFIX = ".install-";
21010
- wait = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
21018
+ wait = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
21011
21019
  INSTALL_RECORD = ".install-complete.json";
21012
21020
  AntigravitySetupError = class extends Error {
21013
21021
  status = 409;
@@ -21429,13 +21437,13 @@ function computeBackoff(attempt, random = Math.random) {
21429
21437
  function interruptibleDelay(ms, signal) {
21430
21438
  let timer = null;
21431
21439
  let onCancel = null;
21432
- const promise2 = new Promise((resolve9) => {
21433
- timer = setTimeout(() => resolve9("elapsed"), Math.max(1, ms));
21440
+ const promise2 = new Promise((resolve10) => {
21441
+ timer = setTimeout(() => resolve10("elapsed"), Math.max(1, ms));
21434
21442
  timer.unref?.();
21435
- if (signal?.aborted) return resolve9("cancelled");
21443
+ if (signal?.aborted) return resolve10("cancelled");
21436
21444
  onCancel = () => {
21437
21445
  clearTimeout(timer);
21438
- resolve9("cancelled");
21446
+ resolve10("cancelled");
21439
21447
  };
21440
21448
  signal?.addEventListener("abort", onCancel, { once: true });
21441
21449
  });
@@ -21489,15 +21497,15 @@ import { createServer as createNetServer } from "node:net";
21489
21497
  import { homedir as homedir6, tmpdir as tmpdir2 } from "node:os";
21490
21498
  import { join as join13, dirname as dirname6 } from "node:path";
21491
21499
  function claudeSignedIn(cli, env, run3 = execCli) {
21492
- return new Promise((resolve9) => {
21500
+ return new Promise((resolve10) => {
21493
21501
  run3(cli, ["auth", "status", "--json"], { timeout: 8e3, env }, (_error, stdout2) => {
21494
21502
  try {
21495
21503
  const status = JSON.parse(stdout2);
21496
- resolve9(
21504
+ resolve10(
21497
21505
  typeof status === "object" && status !== null && "loggedIn" in status && status.loggedIn === true
21498
21506
  );
21499
21507
  } catch {
21500
- resolve9(false);
21508
+ resolve10(false);
21501
21509
  }
21502
21510
  });
21503
21511
  });
@@ -21673,9 +21681,9 @@ async function createPermissionBroker(opts) {
21673
21681
  unlinkSync3(candidate);
21674
21682
  } catch {
21675
21683
  }
21676
- let outcome = await new Promise((resolve9) => {
21677
- attempt.once("listening", () => resolve9("listening"));
21678
- attempt.once("error", (error51) => resolve9(error51));
21684
+ let outcome = await new Promise((resolve10) => {
21685
+ attempt.once("listening", () => resolve10("listening"));
21686
+ attempt.once("error", (error51) => resolve10(error51));
21679
21687
  attempt.listen(candidate);
21680
21688
  });
21681
21689
  if (outcome === "listening" && process.platform !== "win32") {
@@ -21912,19 +21920,19 @@ var init_claude = __esm({
21912
21920
  };
21913
21921
  const writeUser = (s, threadId, promptMsg) => {
21914
21922
  if (!s.child.stdin.writable || s.child.stdin.destroyed) return Promise.resolve(false);
21915
- return new Promise((resolve9) => {
21923
+ return new Promise((resolve10) => {
21916
21924
  try {
21917
21925
  s.child.stdin.write(JSON.stringify(promptMsg) + "\n", (error51) => {
21918
- if (error51) return resolve9(false);
21926
+ if (error51) return resolve10(false);
21919
21927
  appendNative(threadId, {
21920
21928
  dir: "out",
21921
21929
  source: "claude.sdk.message",
21922
21930
  msg: diagnosticClaudeUserMessage(promptMsg)
21923
21931
  });
21924
- resolve9(true);
21932
+ resolve10(true);
21925
21933
  });
21926
21934
  } catch {
21927
- resolve9(false);
21935
+ resolve10(false);
21928
21936
  }
21929
21937
  });
21930
21938
  };
@@ -22410,19 +22418,19 @@ var init_claude = __esm({
22410
22418
  };
22411
22419
  const snapshot = async () => {
22412
22420
  const env = claudeEnvironment(void 0, { ...process.env, ...input.environment });
22413
- const version2 = await new Promise((resolve9) => {
22421
+ const version2 = await new Promise((resolve10) => {
22414
22422
  execCli(
22415
22423
  config2.cli,
22416
22424
  ["--version"],
22417
22425
  { timeout: 8e3, env },
22418
- (err, stdout2) => resolve9(err ? null : stdout2.trim())
22426
+ (err, stdout2) => resolve10(err ? null : stdout2.trim())
22419
22427
  );
22420
22428
  });
22421
22429
  if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
22422
22430
  const authenticated = await claudeSignedIn(config2.cli, env);
22423
22431
  return { state: "available", version: version2, authenticated, billing: "subscription" };
22424
22432
  };
22425
- const generateReview = (prompt, signal) => new Promise((resolve9, reject) => {
22433
+ const generateReview = (prompt, signal) => new Promise((resolve10, reject) => {
22426
22434
  const child = spawnCli(
22427
22435
  config2.cli,
22428
22436
  ["-p", "--model", "claude-haiku-4-5", "--output-format", "text"],
@@ -22440,7 +22448,7 @@ var init_claude = __esm({
22440
22448
  clearTimeout(timer);
22441
22449
  signal?.removeEventListener("abort", onAbort);
22442
22450
  if (error51) reject(error51);
22443
- else resolve9(stdout2.trim());
22451
+ else resolve10(stdout2.trim());
22444
22452
  };
22445
22453
  const onAbort = () => {
22446
22454
  killCliTree(child);
@@ -22551,7 +22559,7 @@ function decodeCodexSelection(id) {
22551
22559
  return { model: id, modelProvider: MODEL_ID2.test(id) ? OFFICIAL_CODEX_PROVIDER : null };
22552
22560
  }
22553
22561
  function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
22554
- return new Promise((resolve9) => {
22562
+ return new Promise((resolve10) => {
22555
22563
  const child = spawnCli(cli, ["app-server"], {
22556
22564
  cwd: homedir7(),
22557
22565
  env,
@@ -22568,7 +22576,7 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
22568
22576
  settled = true;
22569
22577
  clearTimeout(timer);
22570
22578
  killCliTree(child);
22571
- resolve9(catalog);
22579
+ resolve10(catalog);
22572
22580
  };
22573
22581
  const request = (method, params, kind) => {
22574
22582
  const id = nextId++;
@@ -22936,9 +22944,227 @@ var init_codex_instructions = __esm({
22936
22944
  }
22937
22945
  });
22938
22946
 
22947
+ // server/drivers/codex-device-auth.ts
22948
+ import { randomUUID as randomUUID8 } from "node:crypto";
22949
+ import { realpathSync } from "node:fs";
22950
+ import { homedir as homedir8 } from "node:os";
22951
+ import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute3, join as join16, resolve as resolve6 } from "node:path";
22952
+ import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
22953
+ function canonicalPath(path3) {
22954
+ try {
22955
+ return realpathSync(path3);
22956
+ } catch {
22957
+ const parent = dirname7(path3);
22958
+ return parent === path3 ? path3 : join16(canonicalPath(parent), basename4(path3));
22959
+ }
22960
+ }
22961
+ function codexDevicePrompt(output) {
22962
+ const clean = stripVTControlCharacters3(output);
22963
+ const lines = clean.split(/\r?\n/).slice(0, -1).map((line) => line.trim());
22964
+ if (!lines.some((line) => /^https:\/\/auth\.openai\.com\/codex\/device\/?$/.test(line))) return null;
22965
+ const userCode = lines.find((line) => /^[A-Z0-9]{4,8}-[A-Z0-9]{4,8}$/.test(line));
22966
+ return userCode ? { authorizationUrl: DEVICE_URL, userCode } : null;
22967
+ }
22968
+ function loginFailure(output) {
22969
+ if (/(unexpected argument|unrecognized (argument|option)|unknown option).*device-auth/i.test(output)) {
22970
+ return "This server's Codex CLI needs updating for browser sign-in. Run npm install -g @openai/codex@latest on the server, then try again.";
22971
+ }
22972
+ if (/device.{0,40}(disabled|not enabled|not allowed)|enable.{0,40}device/i.test(output)) {
22973
+ return "Enable device-code login in your ChatGPT security settings or ask your workspace admin to allow it, then try again.";
22974
+ }
22975
+ if (/expired|expiration|timed out/i.test(output)) {
22976
+ return "The ChatGPT sign-in code expired. Start sign-in again for a new code.";
22977
+ }
22978
+ return "ChatGPT sign-in did not finish. Check the server's connection and that device-code login is enabled in ChatGPT, then try again.";
22979
+ }
22980
+ var DEVICE_URL, MAX_OUTPUT, authenticatingHomes, CodexDeviceAuthController;
22981
+ var init_codex_device_auth = __esm({
22982
+ "server/drivers/codex-device-auth.ts"() {
22983
+ "use strict";
22984
+ init_procs();
22985
+ DEVICE_URL = "https://auth.openai.com/codex/device";
22986
+ MAX_OUTPUT = 16384;
22987
+ authenticatingHomes = /* @__PURE__ */ new Set();
22988
+ CodexDeviceAuthController = class {
22989
+ flow = null;
22990
+ disposed = false;
22991
+ options;
22992
+ constructor(options) {
22993
+ this.options = options;
22994
+ }
22995
+ async start() {
22996
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing in.");
22997
+ if (this.flow?.status.phase === "waiting") {
22998
+ if (this.flow.ready) return { ...this.flow.status, phase: "waiting" };
22999
+ throw new Error("A ChatGPT sign-in is already starting. Please wait for the code.");
23000
+ }
23001
+ await this.flow?.stopping;
23002
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing in.");
23003
+ const env = this.options.environment();
23004
+ const home = env.HOME || env.USERPROFILE || homedir8();
23005
+ if (!isAbsolute3(home) || env.CODEX_HOME && !isAbsolute3(env.CODEX_HOME)) {
23006
+ throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing in.");
23007
+ }
23008
+ const homeKey = canonicalPath(resolve6(env.CODEX_HOME || join16(home, ".codex")));
23009
+ if (authenticatingHomes.has(homeKey)) {
23010
+ throw new Error("A ChatGPT sign-in is already running for this server account. Finish or cancel it before starting another.");
23011
+ }
23012
+ authenticatingHomes.add(homeKey);
23013
+ return new Promise((resolveStart, reject) => {
23014
+ const flow = {
23015
+ status: {
23016
+ phase: "waiting",
23017
+ flowId: randomUUID8(),
23018
+ authorizationUrl: null,
23019
+ expiresAt: new Date(Date.now() + (this.options.lifetimeMs ?? 15 * 6e4)).toISOString()
23020
+ },
23021
+ child: null,
23022
+ ready: false,
23023
+ resolve: resolveStart,
23024
+ reject,
23025
+ homeKey,
23026
+ startupTimer: setTimeout(() => this.finish(flow, "failed", "Codex did not provide a sign-in code in time. Check the server connection and update Codex, then try again."), this.options.startupTimeoutMs ?? 3e4),
23027
+ expiryTimer: setTimeout(() => this.finish(flow, "expired", "The ChatGPT sign-in code expired. Start sign-in again."), this.options.lifetimeMs ?? 15 * 6e4)
23028
+ };
23029
+ flow.startupTimer.unref();
23030
+ flow.expiryTimer.unref();
23031
+ this.flow = flow;
23032
+ this.run(flow, ["login", "status"], env, home, (code, output) => {
23033
+ if (code === 0 && /^logged in.*chatgpt\b/im.test(output)) {
23034
+ this.finish(flow, "succeeded");
23035
+ } else if (code === 0 && /^logged in\b/im.test(output)) {
23036
+ this.finish(flow, "failed", "Codex already has a different sign-in method on this server. Ask the server administrator to review it before changing accounts.");
23037
+ } else if (code !== 0 && /^not logged in\b/im.test(output)) {
23038
+ this.run(flow, ["login", "--device-auth"], env, home, (loginCode, loginOutput) => {
23039
+ if (loginCode !== 0 || !flow.ready) {
23040
+ this.finish(flow, "failed", loginFailure(loginOutput));
23041
+ return;
23042
+ }
23043
+ flow.startupTimer = setTimeout(() => this.finish(flow, "failed", "Codex finished sign-in but could not confirm the account. Refresh Settings and try again."), this.options.startupTimeoutMs ?? 3e4);
23044
+ flow.startupTimer.unref();
23045
+ this.run(flow, ["login", "status"], env, home, (statusCode, statusOutput) => {
23046
+ this.finish(
23047
+ flow,
23048
+ statusCode === 0 && /^logged in.*chatgpt\b/im.test(statusOutput) ? "succeeded" : "failed",
23049
+ "Codex finished sign-in but did not confirm a ChatGPT account. Refresh Settings and try again."
23050
+ );
23051
+ });
23052
+ }, true);
23053
+ } else this.finish(flow, "failed", "Codex could not confirm the existing sign-in on this server. Update Codex and check its login status before trying again.");
23054
+ });
23055
+ });
23056
+ }
23057
+ async get(flowId) {
23058
+ if (!flowId || this.flow?.status.flowId !== flowId) throw new Error("This sign-in is no longer available. Start sign-in again.");
23059
+ return { ...this.flow.status };
23060
+ }
23061
+ async cancel() {
23062
+ if (this.flow?.status.phase === "waiting") this.finish(this.flow, "cancelled", "ChatGPT sign-in cancelled.");
23063
+ await this.flow?.stopping;
23064
+ if (this.flow?.terminationFailed) throw new Error(this.flow.status.message);
23065
+ }
23066
+ async dispose() {
23067
+ this.disposed = true;
23068
+ await this.cancel();
23069
+ this.flow = null;
23070
+ }
23071
+ run(flow, args, env, cwd, done, parsePrompt = false) {
23072
+ if (flow.status.phase !== "waiting") return;
23073
+ let child;
23074
+ try {
23075
+ child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
23076
+ } catch {
23077
+ this.finish(flow, "failed", "Codex could not start on this server. Install or update the configured Codex CLI, then try again.");
23078
+ return;
23079
+ }
23080
+ flow.child = child;
23081
+ child.stdin.end();
23082
+ let output = "";
23083
+ const receive = (chunk) => {
23084
+ if (flow.status.phase !== "waiting") return;
23085
+ if (output.length + chunk.length > MAX_OUTPUT) {
23086
+ this.finish(flow, "failed", "Codex returned an unexpected sign-in response. Update the server's Codex CLI and try again.");
23087
+ return;
23088
+ }
23089
+ output += chunk.toString("utf8");
23090
+ const prompt = parsePrompt && !flow.ready ? codexDevicePrompt(output) : null;
23091
+ if (prompt) {
23092
+ flow.status = { ...flow.status, ...prompt };
23093
+ flow.ready = true;
23094
+ clearTimeout(flow.startupTimer);
23095
+ flow.resolve({ ...flow.status, phase: "waiting" });
23096
+ }
23097
+ };
23098
+ child.stdout.on("data", receive);
23099
+ child.stderr.on("data", receive);
23100
+ child.once("error", (error51) => {
23101
+ const message2 = error51.code === "ENOENT" ? "Codex is not installed on this server. Run npm install -g @openai/codex@latest on the server, then try again." : "Codex could not start on this server. Check the configured CLI path and its executable permissions.";
23102
+ this.finish(flow, "failed", message2);
23103
+ });
23104
+ child.once("close", (code) => {
23105
+ if (flow.child === child) flow.child = null;
23106
+ if (flow.status.phase === "waiting") done(code, stripVTControlCharacters3(output));
23107
+ output = "";
23108
+ });
23109
+ }
23110
+ finish(flow, phase, message2) {
23111
+ if (flow.status.phase !== "waiting") return;
23112
+ clearTimeout(flow.startupTimer);
23113
+ clearTimeout(flow.expiryTimer);
23114
+ flow.status = {
23115
+ phase,
23116
+ flowId: flow.status.flowId,
23117
+ authorizationUrl: null,
23118
+ expiresAt: null,
23119
+ ...phase !== "succeeded" && message2 ? { message: message2 } : {}
23120
+ };
23121
+ if (!flow.ready) {
23122
+ if (phase === "succeeded") flow.resolve({ ...flow.status, phase });
23123
+ else flow.reject(new Error(message2 ?? "ChatGPT sign-in did not finish."));
23124
+ }
23125
+ flow.stopping = this.stopChild(flow).catch(() => false).then((stopped) => {
23126
+ const release = () => authenticatingHomes.delete(flow.homeKey);
23127
+ if (stopped) {
23128
+ release();
23129
+ return;
23130
+ }
23131
+ flow.terminationFailed = true;
23132
+ flow.status = { ...flow.status, phase: "failed", message: "Codex could not be stopped on this server. Ask the server administrator to stop the login process before trying again." };
23133
+ const child = flow.child;
23134
+ if (!child || child.exitCode !== null || child.signalCode !== null) release();
23135
+ else child.once("close", release);
23136
+ });
23137
+ if (phase === "succeeded") void this.options.onAuthenticated?.().catch(() => {
23138
+ });
23139
+ }
23140
+ async stopChild(flow) {
23141
+ const child = flow.child;
23142
+ if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500)) return true;
23143
+ if (process.platform !== "win32" && child.pid) {
23144
+ try {
23145
+ process.kill(-child.pid, "SIGKILL");
23146
+ } catch {
23147
+ child.kill("SIGKILL");
23148
+ }
23149
+ } else child.kill("SIGKILL");
23150
+ await new Promise((resolveStop) => {
23151
+ if (child.exitCode !== null || child.signalCode !== null) return resolveStop();
23152
+ const timer = setTimeout(resolveStop, 1500);
23153
+ timer.unref();
23154
+ child.once("close", () => {
23155
+ clearTimeout(timer);
23156
+ resolveStop();
23157
+ });
23158
+ });
23159
+ return child.exitCode !== null || child.signalCode !== null;
23160
+ }
23161
+ };
23162
+ }
23163
+ });
23164
+
22939
23165
  // server/drivers/codex.ts
22940
23166
  import { existsSync as existsSync6 } from "node:fs";
22941
- import { homedir as homedir8 } from "node:os";
23167
+ import { homedir as homedir9 } from "node:os";
22942
23168
  function codexPredatesAstra(version2) {
22943
23169
  const value = version2.trim();
22944
23170
  const match = /\bcodex-cli\s+v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9a-z.-]+)?(?![\d.])\b/i.exec(value) ?? /^v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9a-z.-]+)?$/i.exec(value);
@@ -23207,6 +23433,7 @@ var init_codex = __esm({
23207
23433
  init_retry();
23208
23434
  init_native();
23209
23435
  init_codex_instructions();
23436
+ init_codex_device_auth();
23210
23437
  init_codex_catalog();
23211
23438
  DRIVER_KIND3 = "codex";
23212
23439
  ASTRA_MODEL_ID = "gpt-6-astra";
@@ -23260,6 +23487,11 @@ var init_codex = __esm({
23260
23487
  }
23261
23488
  };
23262
23489
  await refreshModels();
23490
+ const authentication = new CodexDeviceAuthController({
23491
+ cli: config2.cli,
23492
+ environment: childEnv,
23493
+ onAuthenticated: refreshModels
23494
+ });
23263
23495
  const listeners = /* @__PURE__ */ new Set();
23264
23496
  const active = /* @__PURE__ */ new Map();
23265
23497
  const emit = (event) => {
@@ -23335,7 +23567,7 @@ var init_codex = __esm({
23335
23567
  );
23336
23568
  }
23337
23569
  const child = spawnCli(config2.cli, appServerArgs, {
23338
- cwd: turn.cwd ?? homedir8(),
23570
+ cwd: turn.cwd ?? homedir9(),
23339
23571
  env,
23340
23572
  stdio: ["pipe", "pipe", "pipe"]
23341
23573
  });
@@ -23363,7 +23595,7 @@ var init_codex = __esm({
23363
23595
  msg: codexNativeLogMessage(obj)
23364
23596
  });
23365
23597
  };
23366
- const request = (method, params, timeoutMs = 6e4) => new Promise((resolve9, reject) => {
23598
+ const request = (method, params, timeoutMs = 6e4) => new Promise((resolve10, reject) => {
23367
23599
  const id = nextId++;
23368
23600
  if (method === "config/read") sensitiveResponseIds.add(id);
23369
23601
  const timer = setTimeout(() => {
@@ -23373,7 +23605,7 @@ var init_codex = __esm({
23373
23605
  rpcPending.set(id, {
23374
23606
  resolve: (v) => {
23375
23607
  clearTimeout(timer);
23376
- resolve9(v);
23608
+ resolve10(v);
23377
23609
  },
23378
23610
  reject: (e) => {
23379
23611
  clearTimeout(timer);
@@ -23641,7 +23873,7 @@ var init_codex = __esm({
23641
23873
  let effectiveConfig;
23642
23874
  try {
23643
23875
  const configured = await request("config/read", {
23644
- cwd: turn.cwd ?? homedir8(),
23876
+ cwd: turn.cwd ?? homedir9(),
23645
23877
  includeLayers: false
23646
23878
  });
23647
23879
  effectiveConfig = configured?.config;
@@ -23685,7 +23917,7 @@ var init_codex = __esm({
23685
23917
  const selection = decodeCodexSelection(turn.model);
23686
23918
  const startThread = () => request("thread/start", {
23687
23919
  developerInstructions,
23688
- cwd: turn.cwd ?? homedir8(),
23920
+ cwd: turn.cwd ?? homedir9(),
23689
23921
  model: selection.model,
23690
23922
  ...selection.modelProvider ? { modelProvider: selection.modelProvider } : {},
23691
23923
  ...approvalParams.thread,
@@ -23752,8 +23984,8 @@ var init_codex = __esm({
23752
23984
  void settle(false, "shutdown_timeout");
23753
23985
  return;
23754
23986
  }
23755
- await new Promise((resolve9) => {
23756
- const timer = setTimeout(resolve9, Math.max(1, Math.round(delayMs * retryScale)));
23987
+ await new Promise((resolve10) => {
23988
+ const timer = setTimeout(resolve10, Math.max(1, Math.round(delayMs * retryScale)));
23757
23989
  timer.unref?.();
23758
23990
  });
23759
23991
  if (!stopRequested) {
@@ -23781,21 +24013,21 @@ var init_codex = __esm({
23781
24013
  };
23782
24014
  const snapshot = async () => {
23783
24015
  const env = childEnv();
23784
- const version2 = await new Promise((resolve9) => {
24016
+ const version2 = await new Promise((resolve10) => {
23785
24017
  execCli(
23786
24018
  config2.cli,
23787
24019
  ["--version"],
23788
24020
  { timeout: 8e3, env },
23789
- (err, stdout2) => resolve9(err ? null : stdout2.trim())
24021
+ (err, stdout2) => resolve10(err ? null : stdout2.trim())
23790
24022
  );
23791
24023
  });
23792
24024
  if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
23793
- const authenticated = await new Promise((resolve9) => {
24025
+ const authenticated = await new Promise((resolve10) => {
23794
24026
  execCli(
23795
24027
  config2.cli,
23796
24028
  ["login", "status"],
23797
24029
  { timeout: 8e3, env },
23798
- (err, stdout2, stderr) => resolve9(!err && /^logged in\b/im.test(`${stdout2}
24030
+ (err, stdout2, stderr) => resolve10(!err && /^logged in\b/im.test(`${stdout2}
23799
24031
  ${stderr ?? ""}`))
23800
24032
  );
23801
24033
  });
@@ -23816,6 +24048,9 @@ ${stderr ?? ""}`))
23816
24048
  return models;
23817
24049
  },
23818
24050
  refreshModels,
24051
+ startAuthentication: () => authentication.start(),
24052
+ getAuthentication: (flowId) => authentication.get(flowId),
24053
+ cancelAuthentication: () => authentication.cancel(),
23819
24054
  snapshot,
23820
24055
  adapter: {
23821
24056
  provider: DRIVER_KIND3,
@@ -23853,6 +24088,7 @@ ${stderr ?? ""}`))
23853
24088
  }
23854
24089
  },
23855
24090
  dispose: async () => {
24091
+ await authentication.dispose();
23856
24092
  await Promise.all([...active.values()].map(({ stop }) => stop()));
23857
24093
  listeners.clear();
23858
24094
  }
@@ -24139,11 +24375,11 @@ var init_grok = __esm({
24139
24375
 
24140
24376
  // server/drivers/acp/grok.ts
24141
24377
  import { existsSync as existsSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
24142
- import { homedir as homedir9 } from "node:os";
24143
- import { join as join16 } from "node:path";
24378
+ import { homedir as homedir10 } from "node:os";
24379
+ import { join as join17 } from "node:path";
24144
24380
  function grokHome(env) {
24145
24381
  if (env.GROK_HOME) return env.GROK_HOME;
24146
- return join16(env.HOME || env.USERPROFILE || homedir9(), ".grok");
24382
+ return join17(env.HOME || env.USERPROFILE || homedir10(), ".grok");
24147
24383
  }
24148
24384
  function unquote2(raw) {
24149
24385
  const value = raw.trim();
@@ -24153,7 +24389,7 @@ function unquote2(raw) {
24153
24389
  return value;
24154
24390
  }
24155
24391
  function readGrokModelCatalog(env = process.env) {
24156
- const path3 = join16(grokHome(env), "config.toml");
24392
+ const path3 = join17(grokHome(env), "config.toml");
24157
24393
  let text2 = "";
24158
24394
  try {
24159
24395
  text2 = readFileSync9(path3, "utf8");
@@ -24226,7 +24462,7 @@ function ensureGrokInjectSlug(modelId, env = process.env) {
24226
24462
  if (!inject) return modelId;
24227
24463
  const host = localHost(inject.host);
24228
24464
  if (!host) return modelId;
24229
- const path3 = join16(grokHome(env), "config.toml");
24465
+ const path3 = join17(grokHome(env), "config.toml");
24230
24466
  let text2 = "";
24231
24467
  try {
24232
24468
  text2 = readFileSync9(path3, "utf8");
@@ -24361,7 +24597,7 @@ var init_grok2 = __esm({
24361
24597
  // an unauthenticated CLI is a user action, not something to paper over.
24362
24598
  pickAuthMethod: (methods) => methods.some((m) => m.id === "cached_token") ? "cached_token" : null,
24363
24599
  authFailure: "fail",
24364
- isAuthenticated: () => existsSync7(join16(homedir9(), ".grok", "auth.json")),
24600
+ isAuthenticated: () => existsSync7(join17(homedir10(), ".grok", "auth.json")),
24365
24601
  // `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
24366
24602
  // reach the agent-stdio system prompt (verified against 1.0.0), so the
24367
24603
  // persona is prepended codex-style.
@@ -24375,11 +24611,11 @@ ${turn.text}` : turn.text
24375
24611
 
24376
24612
  // server/drivers/acp/gemini.ts
24377
24613
  import { existsSync as existsSync8, readFileSync as readFileSync10 } from "node:fs";
24378
- import { homedir as homedir10 } from "node:os";
24379
- import { join as join17 } from "node:path";
24614
+ import { homedir as homedir11 } from "node:os";
24615
+ import { join as join18 } from "node:path";
24380
24616
  function liveOauthCredential() {
24381
24617
  try {
24382
- const creds = JSON.parse(readFileSync10(join17(homedir10(), ".gemini", "oauth_creds.json"), "utf8"));
24618
+ const creds = JSON.parse(readFileSync10(join18(homedir11(), ".gemini", "oauth_creds.json"), "utf8"));
24383
24619
  if (typeof creds.access_token !== "string" || creds.access_token.trim().length === 0) return false;
24384
24620
  const hasRefresh = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
24385
24621
  if (creds.expiry_date !== void 0) {
@@ -24392,7 +24628,7 @@ function liveOauthCredential() {
24392
24628
  }
24393
24629
  }
24394
24630
  function geminiIsAuthenticated(env) {
24395
- return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync8(join17(homedir10(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
24631
+ return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync8(join18(homedir11(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
24396
24632
  }
24397
24633
  var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
24398
24634
  var init_gemini = __esm({
@@ -24435,16 +24671,16 @@ ${turn.text}` : turn.text
24435
24671
 
24436
24672
  // server/drivers/acp/kimi.ts
24437
24673
  import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "node:fs";
24438
- import { homedir as homedir11 } from "node:os";
24439
- import { join as join18 } from "node:path";
24674
+ import { homedir as homedir12 } from "node:os";
24675
+ import { join as join19 } from "node:path";
24440
24676
  function isLocalInjectAlias(slug) {
24441
24677
  return LOCAL_PROVIDER_PREFIXES.some((prefix) => slug.startsWith(prefix));
24442
24678
  }
24443
24679
  function kimiDataRoot(env) {
24444
- return env.KIMI_CODE_HOME || join18(env.HOME || env.USERPROFILE || homedir11(), ".kimi-code");
24680
+ return env.KIMI_CODE_HOME || join19(env.HOME || env.USERPROFILE || homedir12(), ".kimi-code");
24445
24681
  }
24446
24682
  function credentialsPath(env) {
24447
- return join18(kimiDataRoot(env), "credentials", "kimi-code.json");
24683
+ return join19(kimiDataRoot(env), "credentials", "kimi-code.json");
24448
24684
  }
24449
24685
  function quoteToml2(value) {
24450
24686
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
@@ -24732,7 +24968,7 @@ function ensureKimiInjectAlias(modelId, env = process.env) {
24732
24968
  const alias = `${inject.host}/${inject.model.replace(/\//g, "-")}`;
24733
24969
  const dataRoot = kimiDataRoot(env);
24734
24970
  mkdirSync5(dataRoot, { recursive: true });
24735
- const path3 = join18(dataRoot, "config.toml");
24971
+ const path3 = join19(dataRoot, "config.toml");
24736
24972
  let text2 = "";
24737
24973
  try {
24738
24974
  text2 = readFileSync11(path3, "utf8");
@@ -24797,7 +25033,7 @@ function readKimiModelCatalog(env) {
24797
25033
  const dataRoot = kimiDataRoot(env);
24798
25034
  let text2 = "";
24799
25035
  try {
24800
- text2 = readFileSync11(join18(dataRoot, "config.toml"), "utf8");
25036
+ text2 = readFileSync11(join19(dataRoot, "config.toml"), "utf8");
24801
25037
  } catch {
24802
25038
  return STATIC_KIMI_MODELS;
24803
25039
  }
@@ -24917,18 +25153,18 @@ ${turn.text}` : turn.text
24917
25153
 
24918
25154
  // server/drivers/acp/droid.ts
24919
25155
  import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
24920
- import { homedir as homedir12 } from "node:os";
24921
- import { join as join19 } from "node:path";
25156
+ import { homedir as homedir13 } from "node:os";
25157
+ import { join as join20 } from "node:path";
24922
25158
  function authFilePaths(env) {
24923
- const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir12();
24924
- return AUTH_FILES.map((name) => join19(home, ".factory", name));
25159
+ const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir13();
25160
+ return AUTH_FILES.map((name) => join20(home, ".factory", name));
24925
25161
  }
24926
25162
  function droidInjectId(host, model) {
24927
25163
  const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
24928
25164
  return `${INJECT_ID_PREFIX}${safe}`;
24929
25165
  }
24930
25166
  function factoryHome(env) {
24931
- return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE || homedir12();
25167
+ return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE || homedir13();
24932
25168
  }
24933
25169
  function ensureDroidInjectModel(modelId, env = process.env) {
24934
25170
  const inject = decodeInjectId(modelId);
@@ -24936,9 +25172,9 @@ function ensureDroidInjectModel(modelId, env = process.env) {
24936
25172
  const host = localHost(inject.host);
24937
25173
  if (!host) return modelId;
24938
25174
  const id = droidInjectId(inject.host, inject.model);
24939
- const dir = join19(factoryHome(env), ".factory");
25175
+ const dir = join20(factoryHome(env), ".factory");
24940
25176
  mkdirSync6(dir, { recursive: true });
24941
- const path3 = join19(dir, "settings.json");
25177
+ const path3 = join20(dir, "settings.json");
24942
25178
  let settings2 = {};
24943
25179
  try {
24944
25180
  settings2 = JSON.parse(readFileSync12(path3, "utf8"));
@@ -24978,7 +25214,7 @@ function applyDroidLocalAuthEnv(env, modelId) {
24978
25214
  env.FACTORY_API_KEY = "openmausbot-local";
24979
25215
  }
24980
25216
  function readSettings(env) {
24981
- return JSON.parse(readFileSync12(join19(factoryHome(env), ".factory", "settings.json"), "utf8"));
25217
+ return JSON.parse(readFileSync12(join20(factoryHome(env), ".factory", "settings.json"), "utf8"));
24982
25218
  }
24983
25219
  async function resolveModels(env) {
24984
25220
  let catalog = MODELS3;
@@ -25247,10 +25483,10 @@ function decodeCursorAuthText(text2) {
25247
25483
  return null;
25248
25484
  }
25249
25485
  function execText(run3, cli, args, env) {
25250
- return new Promise((resolve9) => {
25486
+ return new Promise((resolve10) => {
25251
25487
  run3(cli, args, { timeout: EXEC_TIMEOUT_MS, env }, (err, stdout2) => {
25252
- if (err) return resolve9(null);
25253
- resolve9(String(stdout2 ?? ""));
25488
+ if (err) return resolve10(null);
25489
+ resolve10(String(stdout2 ?? ""));
25254
25490
  });
25255
25491
  });
25256
25492
  }
@@ -25369,8 +25605,8 @@ ${turn.text}` : turn.text
25369
25605
 
25370
25606
  // server/drivers/acp/opencode-go.ts
25371
25607
  import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "node:fs";
25372
- import { homedir as homedir13 } from "node:os";
25373
- import { join as join20 } from "node:path";
25608
+ import { homedir as homedir14 } from "node:os";
25609
+ import { join as join21 } from "node:path";
25374
25610
  function labelForModel(id) {
25375
25611
  return id.split(/[-_.]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
25376
25612
  }
@@ -25444,7 +25680,7 @@ function parseOpenCodeModelsOutput(stdout2) {
25444
25680
  return { default: (preferred ?? options[0]).id, options };
25445
25681
  }
25446
25682
  function runOpenCodeModels(cli, environment, verbose) {
25447
- return new Promise((resolve9, reject) => {
25683
+ return new Promise((resolve10, reject) => {
25448
25684
  execCli(
25449
25685
  cli,
25450
25686
  ["models", ...verbose ? ["--verbose"] : []],
@@ -25454,7 +25690,7 @@ function runOpenCodeModels(cli, environment, verbose) {
25454
25690
  reject(new Error(stderr?.trim() || error51.message, { cause: error51 }));
25455
25691
  return;
25456
25692
  }
25457
- resolve9(stdout2);
25693
+ resolve10(stdout2);
25458
25694
  }
25459
25695
  );
25460
25696
  });
@@ -25470,8 +25706,8 @@ async function discoverOpenCodeModels(environment, cli = "opencode") {
25470
25706
  }
25471
25707
  }
25472
25708
  function opencodeConfigDir(env) {
25473
- const home = env.HOME || env.USERPROFILE || homedir13();
25474
- return join20(env.XDG_CONFIG_HOME || join20(home, ".config"), "opencode");
25709
+ const home = env.HOME || env.USERPROFILE || homedir14();
25710
+ return join21(env.XDG_CONFIG_HOME || join21(home, ".config"), "opencode");
25475
25711
  }
25476
25712
  function ensureOpenCodeInjectModel(modelId, env = process.env) {
25477
25713
  const inject = decodeInjectId(modelId);
@@ -25481,7 +25717,7 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
25481
25717
  const native = `${inject.host}/${inject.model}`;
25482
25718
  const dir = opencodeConfigDir(env);
25483
25719
  mkdirSync7(dir, { recursive: true });
25484
- const path3 = join20(dir, "opencode.json");
25720
+ const path3 = join21(dir, "opencode.json");
25485
25721
  let config2 = { $schema: "https://opencode.ai/config.json" };
25486
25722
  if (existsSync11(path3)) {
25487
25723
  try {
@@ -25517,12 +25753,12 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
25517
25753
  return native;
25518
25754
  }
25519
25755
  function storedAuthPaths(env) {
25520
- const home = env.HOME || env.USERPROFILE || homedir13();
25756
+ const home = env.HOME || env.USERPROFILE || homedir14();
25521
25757
  const roots = [
25522
- env.XDG_DATA_HOME || join20(home, ".local", "share"),
25523
- process.platform === "darwin" ? join20(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join20(home, "AppData", "Local") : ""
25758
+ env.XDG_DATA_HOME || join21(home, ".local", "share"),
25759
+ process.platform === "darwin" ? join21(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join21(home, "AppData", "Local") : ""
25524
25760
  ].filter(Boolean);
25525
- return [...new Set(roots)].map((root) => join20(root, "opencode", "auth.json"));
25761
+ return [...new Set(roots)].map((root) => join21(root, "opencode", "auth.json"));
25526
25762
  }
25527
25763
  function usableAuthEntry(parsed) {
25528
25764
  return Object.values(parsed).some((auth) => {
@@ -25653,10 +25889,10 @@ ${turn.text}` : turn.text
25653
25889
 
25654
25890
  // server/drivers/acp/qwen.ts
25655
25891
  import { chmodSync as chmodSync3, existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "node:fs";
25656
- import { homedir as homedir14 } from "node:os";
25657
- import { join as join21 } from "node:path";
25892
+ import { homedir as homedir15 } from "node:os";
25893
+ import { join as join22 } from "node:path";
25658
25894
  function qwenHome(env) {
25659
- return join21(env.HOME || env.USERPROFILE || homedir14(), ".qwen");
25895
+ return join22(env.HOME || env.USERPROFILE || homedir15(), ".qwen");
25660
25896
  }
25661
25897
  function envKeyFor(hostId) {
25662
25898
  return `OPENMAUSBOT_QWEN_${hostId.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
@@ -25668,7 +25904,7 @@ function ensureQwenInjectModel(modelId, env = process.env) {
25668
25904
  if (!host) return modelId;
25669
25905
  const dir = qwenHome(env);
25670
25906
  mkdirSync8(dir, { recursive: true });
25671
- const path3 = join21(dir, "settings.json");
25907
+ const path3 = join22(dir, "settings.json");
25672
25908
  let settings2 = {};
25673
25909
  if (existsSync12(path3)) {
25674
25910
  try {
@@ -32634,8 +32870,8 @@ var init_browser = __esm({
32634
32870
  // server/drivers/acp/hermes.ts
32635
32871
  import { spawn as spawn4 } from "node:child_process";
32636
32872
  import { mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "node:fs";
32637
- import { homedir as homedir15 } from "node:os";
32638
- import { join as join22 } from "node:path";
32873
+ import { homedir as homedir16 } from "node:os";
32874
+ import { join as join23 } from "node:path";
32639
32875
  function bindHermesScreenshotCompat(env, modelId) {
32640
32876
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT];
32641
32877
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL];
@@ -32645,7 +32881,7 @@ function bindHermesScreenshotCompat(env, modelId) {
32645
32881
  env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL] = inject.model;
32646
32882
  }
32647
32883
  function hermesHome(env) {
32648
- return env.HERMES_HOME || join22(env.HOME || env.USERPROFILE || homedir15(), ".hermes");
32884
+ return env.HERMES_HOME || join23(env.HOME || env.USERPROFILE || homedir16(), ".hermes");
32649
32885
  }
32650
32886
  function quoteYaml(value) {
32651
32887
  if (/^[\w./:+-]+$/.test(value)) return value;
@@ -32687,7 +32923,7 @@ function ensureHermesInjectProvider(modelId, env = process.env) {
32687
32923
  if (!host) return modelId;
32688
32924
  const dir = hermesHome(env);
32689
32925
  mkdirSync9(dir, { recursive: true });
32690
- const path3 = join22(dir, "config.yaml");
32926
+ const path3 = join23(dir, "config.yaml");
32691
32927
  let text2 = "";
32692
32928
  try {
32693
32929
  text2 = readFileSync15(path3, "utf8");
@@ -32758,13 +32994,13 @@ function hermesConfiguredModel(env = process.env) {
32758
32994
  const dir = hermesHome(env);
32759
32995
  let secrets = "";
32760
32996
  try {
32761
- secrets = readFileSync15(join22(dir, ".env"), "utf8");
32997
+ secrets = readFileSync15(join23(dir, ".env"), "utf8");
32762
32998
  } catch {
32763
32999
  }
32764
33000
  const hasHostedProviderKey = HERMES_HOSTED_PROVIDER_KEYS.some((name) => nonEmptyDotenvValue(secrets, name));
32765
33001
  let configuredDefault = null;
32766
33002
  try {
32767
- configuredDefault = hermesConfigDefault(readFileSync15(join22(dir, "config.yaml"), "utf8"));
33003
+ configuredDefault = hermesConfigDefault(readFileSync15(join23(dir, "config.yaml"), "utf8"));
32768
33004
  } catch {
32769
33005
  }
32770
33006
  const configuredProvider = configuredDefault?.provider.toLowerCase() ?? "";
@@ -32780,12 +33016,12 @@ function hermesConfiguredModel(env = process.env) {
32780
33016
  };
32781
33017
  }
32782
33018
  async function fetchHermesAcpModels(cli, env) {
32783
- return await new Promise((resolve9) => {
33019
+ return await new Promise((resolve10) => {
32784
33020
  let child;
32785
33021
  try {
32786
33022
  child = spawn4(cli, ["acp"], { stdio: ["pipe", "pipe", "ignore"], env });
32787
33023
  } catch {
32788
- return resolve9([]);
33024
+ return resolve10([]);
32789
33025
  }
32790
33026
  let settled = false;
32791
33027
  let timer;
@@ -32806,7 +33042,7 @@ async function fetchHermesAcpModels(cli, env) {
32806
33042
  }
32807
33043
  } catch {
32808
33044
  }
32809
- resolve9(out);
33045
+ resolve10(out);
32810
33046
  };
32811
33047
  timer = setTimeout(() => done([]), 5e3);
32812
33048
  child.once("error", () => done([]));
@@ -32849,7 +33085,7 @@ async function fetchHermesAcpModels(cli, env) {
32849
33085
  }
32850
33086
  if (msg?.id === initId) {
32851
33087
  if (!msg.result) return done([]);
32852
- sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE || homedir15(), mcpServers: [] });
33088
+ sessionId = send("session/new", { cwd: env.HOME || env.USERPROFILE || homedir16(), mcpServers: [] });
32853
33089
  } else if (sessionId && msg?.id === sessionId) {
32854
33090
  const list = Array.isArray(msg.result?.models?.availableModels) ? msg.result.models.availableModels : [];
32855
33091
  done(
@@ -33085,8 +33321,8 @@ var init_openai_compat = __esm({
33085
33321
 
33086
33322
  // server/drivers/pi.ts
33087
33323
  import { chmodSync as chmodSync4, existsSync as existsSync13, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, readFileSync as readFileSync16, rmSync as rmSync2, writeFileSync as writeFileSync10 } from "node:fs";
33088
- import { homedir as homedir16, tmpdir as tmpdir3 } from "node:os";
33089
- import { join as join23 } from "node:path";
33324
+ import { homedir as homedir17, tmpdir as tmpdir3 } from "node:os";
33325
+ import { join as join24 } from "node:path";
33090
33326
  function readPiPromptImages(turn) {
33091
33327
  return (turn.images ?? []).map((image) => ({
33092
33328
  type: "image",
@@ -33193,7 +33429,7 @@ async function applyPiLocalCatalog(catalog, env = process.env, fetchImpl = fetch
33193
33429
  return preferPiInjectRows(await mergeLocalInject(catalog, env, fetchImpl));
33194
33430
  }
33195
33431
  function piAgentDir(env) {
33196
- return join23(env.HOME || env.USERPROFILE || homedir16(), ".pi", "agent");
33432
+ return join24(env.HOME || env.USERPROFILE || homedir17(), ".pi", "agent");
33197
33433
  }
33198
33434
  function ensurePiInjectModel(modelId, env = process.env) {
33199
33435
  const split = splitPiModel(modelId);
@@ -33204,7 +33440,7 @@ function ensurePiInjectModel(modelId, env = process.env) {
33204
33440
  if (!host) return split;
33205
33441
  const dir = piAgentDir(env);
33206
33442
  mkdirSync10(dir, { recursive: true });
33207
- const path3 = join23(dir, "models.json");
33443
+ const path3 = join24(dir, "models.json");
33208
33444
  let root = { providers: {} };
33209
33445
  if (existsSync13(path3)) {
33210
33446
  try {
@@ -33258,7 +33494,7 @@ function ensurePiInjectModel(modelId, env = process.env) {
33258
33494
  return split;
33259
33495
  }
33260
33496
  function readPiDefaultModel(env) {
33261
- const home = env.HOME || env.USERPROFILE || homedir16();
33497
+ const home = env.HOME || env.USERPROFILE || homedir17();
33262
33498
  try {
33263
33499
  const s = JSON.parse(readFileSync16(`${home}/.pi/agent/settings.json`, "utf8"));
33264
33500
  return s.defaultProvider && s.defaultModel ? `${s.defaultProvider}/${s.defaultModel}` : "";
@@ -33268,7 +33504,7 @@ function readPiDefaultModel(env) {
33268
33504
  }
33269
33505
  async function fetchPiModels(cli, env) {
33270
33506
  const child = spawnCli(cli, PI_ARGS, { stdio: ["pipe", "pipe", "pipe"], env });
33271
- return new Promise((resolve9) => {
33507
+ return new Promise((resolve10) => {
33272
33508
  let buf = "";
33273
33509
  let done = false;
33274
33510
  const fallbackDefault = readPiDefaultModel(env);
@@ -33279,7 +33515,7 @@ async function fetchPiModels(cli, env) {
33279
33515
  killCliTree(child);
33280
33516
  } catch {
33281
33517
  }
33282
- resolve9(catalog);
33518
+ resolve10(catalog);
33283
33519
  };
33284
33520
  const timer = setTimeout(() => finish({ default: "", options: [] }), 15e3);
33285
33521
  timer.unref?.();
@@ -33406,9 +33642,9 @@ var init_pi = __esm({
33406
33642
  const mcpServers = buildMcpServers(turn);
33407
33643
  let mcpTempDir = null;
33408
33644
  if (mcpServers) {
33409
- mcpTempDir = mkdtempSync2(join23(tmpdir3(), "omb-pi-mcp-"));
33645
+ mcpTempDir = mkdtempSync2(join24(tmpdir3(), "omb-pi-mcp-"));
33410
33646
  try {
33411
- writeFileSync10(join23(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
33647
+ writeFileSync10(join24(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
33412
33648
  } catch (err) {
33413
33649
  try {
33414
33650
  rmSync2(mcpTempDir, { recursive: true, force: true });
@@ -33426,7 +33662,7 @@ var init_pi = __esm({
33426
33662
  env: piEnvironment({
33427
33663
  ...process.env,
33428
33664
  ...input.environment,
33429
- ...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join23(mcpTempDir, "mcp.json") } : {}
33665
+ ...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join24(mcpTempDir, "mcp.json") } : {}
33430
33666
  })
33431
33667
  });
33432
33668
  } catch (err) {
@@ -33449,13 +33685,13 @@ var init_pi = __esm({
33449
33685
  }
33450
33686
  responseWaiters.clear();
33451
33687
  };
33452
- const awaitResponse = (command, timeoutMs = 2e4) => new Promise((resolve9, reject) => {
33688
+ const awaitResponse = (command, timeoutMs = 2e4) => new Promise((resolve10, reject) => {
33453
33689
  const timer = setTimeout(() => {
33454
33690
  responseWaiters.delete(command);
33455
33691
  reject(new Error(`pi ${command} timed out`));
33456
33692
  }, timeoutMs);
33457
33693
  timer.unref?.();
33458
- responseWaiters.set(command, { resolve: resolve9, reject, timer });
33694
+ responseWaiters.set(command, { resolve: resolve10, reject, timer });
33459
33695
  });
33460
33696
  child.stdin.on("error", () => rejectWaiters(new Error("pi stdin closed")));
33461
33697
  const send = (obj) => {
@@ -33663,7 +33899,7 @@ ${turn.text}` : turn.text;
33663
33899
  return { turnId };
33664
33900
  };
33665
33901
  const snapshot = async () => {
33666
- const version2 = await new Promise((resolve9) => {
33902
+ const version2 = await new Promise((resolve10) => {
33667
33903
  const child = spawnCli(config2.cli, ["--version"], {
33668
33904
  stdio: ["ignore", "pipe", "pipe"],
33669
33905
  env: piEnvironment({ ...process.env, ...input.environment })
@@ -33676,16 +33912,16 @@ ${turn.text}` : turn.text;
33676
33912
  killCliTree(child);
33677
33913
  } catch {
33678
33914
  }
33679
- resolve9(null);
33915
+ resolve10(null);
33680
33916
  }, 8e3);
33681
33917
  timer.unref?.();
33682
33918
  child.on("error", () => {
33683
33919
  clearTimeout(timer);
33684
- resolve9(null);
33920
+ resolve10(null);
33685
33921
  });
33686
33922
  child.on("close", () => {
33687
33923
  clearTimeout(timer);
33688
- resolve9(out.trim() || null);
33924
+ resolve10(out.trim() || null);
33689
33925
  });
33690
33926
  });
33691
33927
  if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
@@ -33764,15 +34000,15 @@ ${turn.text}` : turn.text;
33764
34000
 
33765
34001
  // server/drivers/minimax.ts
33766
34002
  import { readFileSync as readFileSync17 } from "node:fs";
33767
- import { homedir as homedir17 } from "node:os";
33768
- import { join as join24 } from "node:path";
34003
+ import { homedir as homedir18 } from "node:os";
34004
+ import { join as join25 } from "node:path";
33769
34005
  function normalizedApiUrl(value) {
33770
34006
  const root = value.trim().replace(/\/+$/, "");
33771
34007
  return root.endsWith("/v1") ? root : `${root}/v1`;
33772
34008
  }
33773
- function loadLocalMiniMaxConfig(home = homedir17()) {
34009
+ function loadLocalMiniMaxConfig(home = homedir18()) {
33774
34010
  try {
33775
- const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join24(home, ".mmx", "config.json"), "utf8")));
34011
+ const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join25(home, ".mmx", "config.json"), "utf8")));
33776
34012
  const configuredUrl = raw.base_url?.trim() ? raw.base_url : raw.region === "cn" ? CN_URL : DEFAULT_URL2;
33777
34013
  return {
33778
34014
  apiKey: raw.api_key?.trim() ?? "",
@@ -34040,8 +34276,8 @@ __export(cli_setup_exports, {
34040
34276
  });
34041
34277
  import { spawn as spawn5 } from "node:child_process";
34042
34278
  import { readFileSync as readFileSync18 } from "node:fs";
34043
- import { join as join25, resolve as resolve6 } from "node:path";
34044
- import { randomUUID as randomUUID8 } from "node:crypto";
34279
+ import { join as join26, resolve as resolve7 } from "node:path";
34280
+ import { randomUUID as randomUUID9 } from "node:crypto";
34045
34281
  async function inspect(id, entry) {
34046
34282
  const registry2 = new ProviderRegistry(BUILT_IN_DRIVERS);
34047
34283
  try {
@@ -34073,11 +34309,11 @@ async function runSetupCli(cli, args, environment = {}) {
34073
34309
  resetPathCache();
34074
34310
  }
34075
34311
  function assertDataDir(dataDir) {
34076
- if (resolve6(dataDir) !== resolve6(DATA_DIR)) throw new Error("Setup data directory mismatch. Restart the CLI with --data-dir.");
34312
+ if (resolve7(dataDir) !== resolve7(DATA_DIR)) throw new Error("Setup data directory mismatch. Restart the CLI with --data-dir.");
34077
34313
  }
34078
34314
  function checkStoredConfig(dataDir) {
34079
34315
  try {
34080
- parseStoredConfig(JSON.parse(readFileSync18(join25(dataDir, "config.json"), "utf8")));
34316
+ parseStoredConfig(JSON.parse(readFileSync18(join26(dataDir, "config.json"), "utf8")));
34081
34317
  } catch (error51) {
34082
34318
  if (error51.code === "ENOENT") return;
34083
34319
  throw new Error("Existing config.json could not be read or validated. Setup has not changed it; repair it before continuing.");
@@ -34188,7 +34424,7 @@ async function runSetup(options, io = defaultSetupIo(), deps = dependencies) {
34188
34424
  try {
34189
34425
  if (native) {
34190
34426
  id = prior?.[0] ?? native.id;
34191
- if (!prior && runtime[id] && runtime[id].driver !== native.driver) id = `${native.id}-${randomUUID8().slice(0, 8)}`;
34427
+ if (!prior && runtime[id] && runtime[id].driver !== native.driver) id = `${native.id}-${randomUUID9().slice(0, 8)}`;
34192
34428
  entry = { ...cfg.instances?.[id] ?? { driver: native.driver }, enabled: true };
34193
34429
  const models = await connectNative(native, id, entry, io, deps);
34194
34430
  const saved = cfg.defaultModelSelection;
@@ -34243,7 +34479,7 @@ async function runSetup(options, io = defaultSetupIo(), deps = dependencies) {
34243
34479
  if (routingProvider) await deps.verify(url2, key, model, routingProvider);
34244
34480
  else await deps.verify(url2, key, model);
34245
34481
  io.log("Test reply received.");
34246
- id = reuse && prior ? prior[0] : `api-${randomUUID8().slice(0, 8)}`;
34482
+ id = reuse && prior ? prior[0] : `api-${randomUUID9().slice(0, 8)}`;
34247
34483
  entry = reuse && prior ? { ...cfg.instances[id], config: { ...rawObject(cfg.instances[id].config), model } } : { driver: "openai-compat", displayName: label, config: { url: url2, key, model, provider: routingProvider ?? "" } };
34248
34484
  if (!reuse) io.log("The key will be stored in your private config.json (plaintext, owner-only permissions on Unix). Never share this file.");
34249
34485
  }
@@ -34353,7 +34589,7 @@ var init_browser_engine_release = __esm({
34353
34589
  });
34354
34590
 
34355
34591
  // server/browser-bundle-release.ts
34356
- import { join as join26 } from "node:path";
34592
+ import { join as join27 } from "node:path";
34357
34593
  function browserBundleSpec(target) {
34358
34594
  if (!Object.hasOwn(CHROME_ASSETS, target)) throw new Error(`Unsupported desktop browser target: ${target}`);
34359
34595
  const pinned = CHROME_ASSETS[target];
@@ -34389,10 +34625,10 @@ function browserBundlePaths(bundleDirectory, target) {
34389
34625
  const spec = browserBundleSpec(target);
34390
34626
  return {
34391
34627
  directory: bundleDirectory,
34392
- manifest: join26(bundleDirectory, "manifest.json"),
34393
- engine: join26(bundleDirectory, spec.engine.executable),
34394
- chrome: join26(bundleDirectory, spec.chrome.executable),
34395
- licenses: join26(bundleDirectory, "licenses")
34628
+ manifest: join27(bundleDirectory, "manifest.json"),
34629
+ engine: join27(bundleDirectory, spec.engine.executable),
34630
+ chrome: join27(bundleDirectory, spec.chrome.executable),
34631
+ licenses: join27(bundleDirectory, "licenses")
34396
34632
  };
34397
34633
  }
34398
34634
  var CHROME_VERSION, CHROME_ASSETS;
@@ -34429,10 +34665,10 @@ __export(browser_engine_exports, {
34429
34665
  resolveAgentBrowserBinary: () => resolveAgentBrowserBinary
34430
34666
  });
34431
34667
  import { spawn as spawn6 } from "node:child_process";
34432
- import { createHash as createHash6, randomBytes as randomBytes2, randomUUID as randomUUID9 } from "node:crypto";
34668
+ import { createHash as createHash6, randomBytes as randomBytes2, randomUUID as randomUUID10 } from "node:crypto";
34433
34669
  import { chmodSync as chmodSync5, existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync4, rmSync as rmSync3, statSync as statSync3, writeFileSync as writeFileSync11 } from "node:fs";
34434
34670
  import { tmpdir as tmpdir4 } from "node:os";
34435
- import { delimiter as delimiter5, join as join27, resolve as resolve7 } from "node:path";
34671
+ import { delimiter as delimiter5, join as join28, resolve as resolve8 } from "node:path";
34436
34672
  function executableName(platform = process.platform) {
34437
34673
  return platform === "win32" ? "agent-browser.exe" : "agent-browser";
34438
34674
  }
@@ -34441,14 +34677,14 @@ function isMusl(platform = process.platform, exists = existsSync14) {
34441
34677
  }
34442
34678
  function pinnedBinaryPath(dataDir = DATA_DIR, platform = process.platform, arch = process.arch) {
34443
34679
  const version2 = agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform, arch));
34444
- return join27(dataDir, ENGINE_DIR, version2, executableName(platform));
34680
+ return join28(dataDir, ENGINE_DIR, version2, executableName(platform));
34445
34681
  }
34446
34682
  function onPath(env, platform, exists) {
34447
34683
  const pathValue = platform === "win32" ? Object.entries(env).findLast(([key]) => key.toUpperCase() === "PATH")?.[1] : env.PATH;
34448
34684
  for (const part of (pathValue ?? "").split(delimiter5)) {
34449
34685
  const dir = part.trim().replace(/^"|"$/gu, "");
34450
34686
  if (!dir) continue;
34451
- const candidate = resolve7(dir, executableName(platform));
34687
+ const candidate = resolve8(dir, executableName(platform));
34452
34688
  if (exists(candidate)) return candidate;
34453
34689
  }
34454
34690
  return null;
@@ -34457,7 +34693,7 @@ function packagedBrowser(options) {
34457
34693
  const resources = (options.env ?? process.env).OMB_RESOURCES_PATH;
34458
34694
  if (!resources) return null;
34459
34695
  try {
34460
- return browserBundlePaths(join27(resolve7(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
34696
+ return browserBundlePaths(join28(resolve8(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
34461
34697
  } catch {
34462
34698
  return null;
34463
34699
  }
@@ -34470,7 +34706,7 @@ function resolveAgentBrowserBinary(options = {}) {
34470
34706
  const platform = options.platform ?? process.platform;
34471
34707
  const exists = options.exists ?? existsSync14;
34472
34708
  const override = env.OMB_AGENT_BROWSER_PATH?.trim();
34473
- if (override) return resolve7(override) && exists(resolve7(override)) ? resolve7(override) : null;
34709
+ if (override) return resolve8(override) && exists(resolve8(override)) ? resolve8(override) : null;
34474
34710
  const bundle = packagedBrowser(options);
34475
34711
  if (bundle && exists(bundle.directory)) return completePackage(bundle, exists) ? bundle.engine : null;
34476
34712
  const pinned = pinnedBinaryPath(options.dataDir, platform, options.arch);
@@ -34482,7 +34718,7 @@ async function installAgentBrowserBinary(options = {}) {
34482
34718
  const asset = options.asset ?? resolveAgentBrowserReleaseAsset(platform, options.arch ?? process.arch, options.musl ?? isMusl(platform));
34483
34719
  if (!asset) throw new Error(`agent-browser publishes no build for ${platform}-${options.arch ?? process.arch}.`);
34484
34720
  const destination = pinnedBinaryPath(options.dataDir, platform, options.arch);
34485
- const directory = join27(destination, "..");
34721
+ const directory = join28(destination, "..");
34486
34722
  mkdirSync11(directory, { recursive: true, mode: 448 });
34487
34723
  const url2 = agentBrowserReleaseUrl(asset);
34488
34724
  options.log?.(`downloading agent-browser ${agentBrowserReleaseVersion(asset)} (${Math.round(asset.bytes / 1024 / 1024)} MB, digest pinned)`);
@@ -34508,7 +34744,7 @@ async function installAgentBrowserBinary(options = {}) {
34508
34744
  }
34509
34745
  function ensureChrome(binaryPath, options = {}) {
34510
34746
  const bundle = packagedBrowser(options);
34511
- if (!options.withDeps && bundle && resolve7(binaryPath) === bundle.engine && completePackage(bundle, existsSync14)) {
34747
+ if (!options.withDeps && bundle && resolve8(binaryPath) === bundle.engine && completePackage(bundle, existsSync14)) {
34512
34748
  options.log?.("agent-browser: the bundled browser is ready; no download needed");
34513
34749
  return Promise.resolve();
34514
34750
  }
@@ -34534,7 +34770,7 @@ function ensureChrome(binaryPath, options = {}) {
34534
34770
  });
34535
34771
  }
34536
34772
  function browserEngineEncryptionKey(dataDir = DATA_DIR) {
34537
- const file2 = join27(dataDir, KEY_FILE);
34773
+ const file2 = join28(dataDir, KEY_FILE);
34538
34774
  try {
34539
34775
  const existing = readFileSync19(file2, "utf8").trim();
34540
34776
  if (/^[0-9a-f]{64}$/u.test(existing)) return existing;
@@ -34582,13 +34818,13 @@ function agentBrowserIntegration(input) {
34582
34818
  if (sourceEnv[name]) env[name] = sourceEnv[name];
34583
34819
  }
34584
34820
  const bundle = packagedBrowser({ env: sourceEnv });
34585
- if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve7(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync14)) {
34821
+ if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve8(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync14)) {
34586
34822
  env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
34587
34823
  }
34588
34824
  return { command: input.binaryPath, args: ["mcp", "--tools", "core", "--no-webmcp"], env };
34589
34825
  }
34590
34826
  function agentBrowserFrame(input) {
34591
- const file2 = join27(tmpdir4(), `openmausbot-browser-${randomUUID9()}.png`);
34827
+ const file2 = join28(tmpdir4(), `openmausbot-browser-${randomUUID10()}.png`);
34592
34828
  return new Promise((settle, fail) => {
34593
34829
  const child = spawn6(input.binaryPath, ["screenshot", file2], {
34594
34830
  env: { ...process.env, ...input.env },
@@ -34624,7 +34860,7 @@ function agentBrowserFrame(input) {
34624
34860
  });
34625
34861
  }
34626
34862
  function browserSessionId(botId, partitionId) {
34627
- if (partitionId === "guest") return `guest-${randomUUID9()}`;
34863
+ if (partitionId === "guest") return `guest-${randomUUID10()}`;
34628
34864
  const raw = partitionId || `bot-${botId}`;
34629
34865
  return raw.replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 96);
34630
34866
  }
@@ -34692,8 +34928,8 @@ var init_browser_engine = __esm({
34692
34928
  var import_qrcode_terminal = __toESM(require_main(), 1);
34693
34929
  import { spawn as spawn7 } from "node:child_process";
34694
34930
  import { closeSync as closeSync3, existsSync as existsSync15, mkdirSync as mkdirSync12, openSync as openSync3, readFileSync as readFileSync20 } from "node:fs";
34695
- import { homedir as homedir18 } from "node:os";
34696
- import { dirname as dirname7, join as join28, resolve as resolve8 } from "node:path";
34931
+ import { homedir as homedir19 } from "node:os";
34932
+ import { dirname as dirname8, join as join29, resolve as resolve9 } from "node:path";
34697
34933
  import { createInterface as createInterface2 } from "node:readline/promises";
34698
34934
  import { fileURLToPath as fileURLToPath3 } from "node:url";
34699
34935
 
@@ -34747,14 +34983,14 @@ function explainTailscaleFailure(reason) {
34747
34983
  }
34748
34984
  }
34749
34985
  function run(cli, args, timeoutMs) {
34750
- return new Promise((resolve9) => {
34986
+ return new Promise((resolve10) => {
34751
34987
  execFile(
34752
34988
  cli,
34753
34989
  args,
34754
34990
  { timeout: timeoutMs, killSignal: "SIGKILL", maxBuffer: 16 * 1024 * 1024, env: { ...process.env, PATH: searchPath() } },
34755
34991
  (error51, stdout2, stderr) => {
34756
34992
  const code = error51 && "code" in error51 && typeof error51.code === "number" ? error51.code : error51 ? null : 0;
34757
- resolve9({ ok: !error51, stdout: String(stdout2 ?? ""), stderr: String(stderr ?? ""), code });
34993
+ resolve10({ ok: !error51, stdout: String(stdout2 ?? ""), stderr: String(stderr ?? ""), code });
34758
34994
  }
34759
34995
  );
34760
34996
  });
@@ -35518,13 +35754,13 @@ function writePrivateToken(runtimeRoot2, token, { fileSystem, processId, identif
35518
35754
  }
35519
35755
  async function waitForExit(child, milliseconds) {
35520
35756
  if (child.exitCode !== null || child.signalCode !== null) return;
35521
- await new Promise((resolve9) => {
35757
+ await new Promise((resolve10) => {
35522
35758
  let settled = false;
35523
35759
  const finish = () => {
35524
35760
  if (settled) return;
35525
35761
  settled = true;
35526
35762
  clearTimeout(timer);
35527
- resolve9();
35763
+ resolve10();
35528
35764
  };
35529
35765
  child.once("exit", finish);
35530
35766
  const timer = setTimeout(finish, milliseconds);
@@ -35688,8 +35924,8 @@ function createManagedCompanionTunnel({
35688
35924
  child = spawned;
35689
35925
  const cancellationController = new AbortController();
35690
35926
  let resolveCancellation;
35691
- const cancellation = new Promise((resolve9) => {
35692
- resolveCancellation = resolve9;
35927
+ const cancellation = new Promise((resolve10) => {
35928
+ resolveCancellation = resolve10;
35693
35929
  });
35694
35930
  let cancelled = false;
35695
35931
  attemptHandle = {
@@ -35705,8 +35941,8 @@ function createManagedCompanionTunnel({
35705
35941
  let terminated = false;
35706
35942
  let expectedStop = false;
35707
35943
  let resolveExit;
35708
- const exit = new Promise((resolve9) => {
35709
- resolveExit = resolve9;
35944
+ const exit = new Promise((resolve10) => {
35945
+ resolveExit = resolve10;
35710
35946
  });
35711
35947
  const onTerminated = () => {
35712
35948
  if (terminated) return;
@@ -35740,8 +35976,8 @@ function createManagedCompanionTunnel({
35740
35976
  }
35741
35977
  if (Date.now() >= deadline) break;
35742
35978
  await Promise.race([
35743
- new Promise((resolve9) => {
35744
- const timer = setTimeout(resolve9, verifyIntervalMs);
35979
+ new Promise((resolve10) => {
35980
+ const timer = setTimeout(resolve10, verifyIntervalMs);
35745
35981
  timer.unref?.();
35746
35982
  }),
35747
35983
  exit,
@@ -36559,7 +36795,7 @@ function describeTunnelState(state, address) {
36559
36795
  }
36560
36796
 
36561
36797
  // server/cli.ts
36562
- var HERE2 = dirname7(fileURLToPath3(import.meta.url));
36798
+ var HERE2 = dirname8(fileURLToPath3(import.meta.url));
36563
36799
  var COMMANDS = ["setup", "start", "serve", "pair", "sessions", "status", "login", "logout", "browser", "help", "--help", "-h"];
36564
36800
  function parseArgs(argv, env = process.env) {
36565
36801
  const implicitStart = !argv.length || argv[0].startsWith("--") && argv[0] !== "--help";
@@ -36570,7 +36806,7 @@ function parseArgs(argv, env = process.env) {
36570
36806
  const options = {
36571
36807
  command: command === "--help" || command === "-h" ? "help" : command,
36572
36808
  port: Number(env.OMB_PORT || 8799),
36573
- dataDir: env.OMB_DATA_DIR || join28(homedir18(), ".openmausbot"),
36809
+ dataDir: env.OMB_DATA_DIR || join29(homedir19(), ".openmausbot"),
36574
36810
  tailscale: false,
36575
36811
  tunnel: false,
36576
36812
  client: false,
@@ -36588,7 +36824,7 @@ function parseArgs(argv, env = process.env) {
36588
36824
  };
36589
36825
  try {
36590
36826
  if (arg === "--port") options.port = Number(value());
36591
- else if (arg === "--data-dir") options.dataDir = resolve8(value());
36827
+ else if (arg === "--data-dir") options.dataDir = resolve9(value());
36592
36828
  else if (arg === "--label") options.label = value();
36593
36829
  else if (arg === "--public-url") options.publicUrl = value().replace(/\/+$/, "");
36594
36830
  else if (arg === "--tailscale") options.tailscale = true;
@@ -36674,7 +36910,7 @@ function defaultIo() {
36674
36910
  }
36675
36911
  function serverVersion(here = HERE2) {
36676
36912
  try {
36677
- const parsed = JSON.parse(readFileSync20(resolve8(here, "..", "package.json"), "utf8"));
36913
+ const parsed = JSON.parse(readFileSync20(resolve9(here, "..", "package.json"), "utf8"));
36678
36914
  const version2 = typeof parsed === "object" && parsed !== null ? Reflect.get(parsed, "version") : void 0;
36679
36915
  return typeof version2 === "string" && version2 ? version2 : "0.0.0";
36680
36916
  } catch {
@@ -36699,7 +36935,7 @@ async function isWorkspaceRunning(options) {
36699
36935
  try {
36700
36936
  const { status, body } = await api(options.port, "/api/health");
36701
36937
  if (status !== 200 || body?.app !== "openmausbot") return false;
36702
- const expected = readFileSync20(join28(options.dataDir, "environment-id"), "utf8").trim();
36938
+ const expected = readFileSync20(join29(options.dataDir, "environment-id"), "utf8").trim();
36703
36939
  const descriptor = await api(options.port, "/.well-known/openmausbot/environment");
36704
36940
  return /^[0-9a-f-]{36}$/i.test(expected) && descriptor.status === 200 && descriptor.body?.environmentId === expected;
36705
36941
  } catch {
@@ -36996,16 +37232,16 @@ async function runBrowser(options, io = defaultIo()) {
36996
37232
  return 0;
36997
37233
  }
36998
37234
  function serverEntry(here = HERE2) {
36999
- const bundled = join28(here, "index.js");
37000
- const root = resolve8(here, "..");
37235
+ const bundled = join29(here, "index.js");
37236
+ const root = resolve9(here, "..");
37001
37237
  if (existsSync15(bundled)) {
37002
- const staticDir2 = [join28(root, "dist"), join28(here, "..", "ui")].find((d) => existsSync15(join28(d, "index.html"))) ?? null;
37003
- const skillsDir = existsSync15(join28(root, "skills")) ? join28(root, "skills") : null;
37238
+ const staticDir2 = [join29(root, "dist"), join29(here, "..", "ui")].find((d) => existsSync15(join29(d, "index.html"))) ?? null;
37239
+ const skillsDir = existsSync15(join29(root, "skills")) ? join29(root, "skills") : null;
37004
37240
  return { command: process.execPath, args: [bundled], staticDir: staticDir2, skillsDir };
37005
37241
  }
37006
- const source = join28(here, "index.ts");
37007
- const staticDir = existsSync15(join28(root, "dist", "index.html")) ? join28(root, "dist") : null;
37008
- return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync15(join28(root, "skills")) ? join28(root, "skills") : null };
37242
+ const source = join29(here, "index.ts");
37243
+ const staticDir = existsSync15(join29(root, "dist", "index.html")) ? join29(root, "dist") : null;
37244
+ return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync15(join29(root, "skills")) ? join29(root, "skills") : null };
37009
37245
  }
37010
37246
  async function planTunnel(options, log) {
37011
37247
  const account = createTunnelAccount({ dataDir: options.dataDir, version: serverVersion() });
@@ -37084,9 +37320,9 @@ async function runServe(options, log = console.log) {
37084
37320
  let child;
37085
37321
  try {
37086
37322
  if (options.guided) {
37087
- const logsDir = join28(options.dataDir, "logs");
37323
+ const logsDir = join29(options.dataDir, "logs");
37088
37324
  mkdirSync12(logsDir, { recursive: true, mode: 448 });
37089
- logPath = join28(logsDir, `server-${Date.now()}-${process.pid}.log`);
37325
+ logPath = join29(logsDir, `server-${Date.now()}-${process.pid}.log`);
37090
37326
  logFd = openSync3(logPath, "wx", 384);
37091
37327
  log("\nStarting your workspace\u2026");
37092
37328
  }
@@ -37263,7 +37499,7 @@ async function runOnboardingCommand(options, io = defaultIo(), startServer = run
37263
37499
  }
37264
37500
  if (options.command === "setup") {
37265
37501
  io.log("\nAll set. Start with: openmausbot (or npx openmausbot without a global install).");
37266
- if (options.dataDir !== join28(homedir18(), ".openmausbot") || options.port !== 8799) {
37502
+ if (options.dataDir !== join29(homedir19(), ".openmausbot") || options.port !== 8799) {
37267
37503
  io.log(`Use the same --data-dir (${options.dataDir}) and --port (${options.port}) options when starting.`);
37268
37504
  }
37269
37505
  return 0;