openmausbot 0.1.69 → 0.1.71

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.
Files changed (66) hide show
  1. package/dist/assets/{index-BmHupgVJ.js → index-CJtyBonr.js} +1 -1
  2. package/dist/assets/index-CYLdYtYp.css +1 -0
  3. package/dist/assets/index-Di4ovwu5.js +289 -0
  4. package/dist/index.html +2 -2
  5. package/dist-server/container-mcp.js +6 -2
  6. package/dist-server/drivers/agents-proxy.js +305 -16
  7. package/dist-server/drivers/pi-mcp-extension.ts +1 -1
  8. package/dist-server/index.js +3141 -1124
  9. package/dist-server/local-computer-proxy.js +2 -0
  10. package/dist-server/local-computer.js +2 -1
  11. package/dist-server/mcp-gate.js +543 -0
  12. package/dist-server/mcp-server.js +38 -0
  13. package/dist-server/openmausbot.js +772 -260
  14. package/dist-server/pair-cli.js +772 -260
  15. package/dist-server/prepare-cloudflared.js +20 -3
  16. package/dist-server/proxy-paths.js +1 -0
  17. package/dist-server/server/agent-tool-policy.js +29 -0
  18. package/dist-server/server/bot-package.js +55 -2
  19. package/dist-server/server/browser-live.js +12 -7
  20. package/dist-server/server/config.js +40 -4
  21. package/dist-server/server/delegations.js +132 -74
  22. package/dist-server/server/drivers/acp/core.js +2 -0
  23. package/dist-server/server/drivers/acp/cursor.js +1 -1
  24. package/dist-server/server/drivers/acp/grok.js +5 -1
  25. package/dist-server/server/drivers/agents-proxy.js +324 -16
  26. package/dist-server/server/drivers/boxagent.js +1 -1
  27. package/dist-server/server/drivers/claude-login-auth.js +102 -9
  28. package/dist-server/server/drivers/claude.js +298 -21
  29. package/dist-server/server/drivers/codex.js +13 -4
  30. package/dist-server/server/drivers/pi.js +1 -1
  31. package/dist-server/server/engine-install.js +137 -0
  32. package/dist-server/server/env-path.js +12 -0
  33. package/dist-server/server/harness/bus.js +1 -1
  34. package/dist-server/server/harness/registry.js +31 -6
  35. package/dist-server/server/index.js +860 -215
  36. package/dist-server/server/local-computer.js +1 -1
  37. package/dist-server/server/mcp-gate-config.js +56 -0
  38. package/dist-server/server/mcp-gate.js +227 -0
  39. package/dist-server/server/mcp-trim.js +182 -0
  40. package/dist-server/server/memory-journal.js +440 -0
  41. package/dist-server/server/memory-store.js +308 -0
  42. package/dist-server/server/message-db.js +90 -3
  43. package/dist-server/server/package-export.js +25 -0
  44. package/dist-server/server/peer-approval.js +1 -1
  45. package/dist-server/server/peer-provenance.js +6 -2
  46. package/dist-server/server/proxy-paths.js +1 -0
  47. package/dist-server/server/redact.js +15 -0
  48. package/dist-server/server/resume-recovery.js +46 -0
  49. package/dist-server/server/routines.js +116 -55
  50. package/dist-server/server/screen-frame-gate.js +9 -6
  51. package/dist-server/server/skill-library.js +5 -5
  52. package/dist-server/server/steer-queue.js +20 -1
  53. package/dist-server/server/store.js +29 -7
  54. package/dist-server/server/system-prompt.js +14 -1
  55. package/dist-server/server/team-backup.js +53 -4
  56. package/dist-server/server/tool-summary.js +39 -0
  57. package/dist-server/server/tts/speech-text.js +3 -1
  58. package/dist-server/server/turn-context.js +18 -0
  59. package/dist-server/server/workspace.js +321 -22
  60. package/dist-server/shared/approval-mode.js +1 -1
  61. package/dist-server/shared/team-backup.js +14 -2
  62. package/dist-server/vps-container-mcp.js +6 -2
  63. package/package.json +1 -1
  64. package/skills/create-verification-skill/SKILL.md +2 -3
  65. package/dist/assets/index-COp5lMnv.js +0 -279
  66. package/dist/assets/index-Jk7TIeyW.css +0 -1
@@ -1181,7 +1181,7 @@ var init_dist = __esm({
1181
1181
  MODIFIER_RE = new RegExp("\\p{M}+", "gu");
1182
1182
  NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
1183
1183
  getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
1184
- const LIMIT = truncationOptions.limit ?? Infinity;
1184
+ const LIMIT2 = truncationOptions.limit ?? Infinity;
1185
1185
  const ELLIPSIS = truncationOptions.ellipsis ?? "";
1186
1186
  const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
1187
1187
  const ANSI_WIDTH = 0;
@@ -1205,7 +1205,7 @@ var init_dist = __esm({
1205
1205
  let lengthExtra = 0;
1206
1206
  let truncationEnabled = false;
1207
1207
  let truncationIndex = length;
1208
- let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
1208
+ let truncationLimit = Math.max(0, LIMIT2 - ELLIPSIS_WIDTH);
1209
1209
  let unmatchedStart = 0;
1210
1210
  let unmatchedEnd = 0;
1211
1211
  let width = 0;
@@ -1226,7 +1226,7 @@ var init_dist = __esm({
1226
1226
  if (width + widthExtra > truncationLimit) {
1227
1227
  truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
1228
1228
  }
1229
- if (width + widthExtra > LIMIT) {
1229
+ if (width + widthExtra > LIMIT2) {
1230
1230
  truncationEnabled = true;
1231
1231
  break outer;
1232
1232
  }
@@ -1247,7 +1247,7 @@ var init_dist = __esm({
1247
1247
  if (width + widthExtra > truncationLimit) {
1248
1248
  truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
1249
1249
  }
1250
- if (width + widthExtra > LIMIT) {
1250
+ if (width + widthExtra > LIMIT2) {
1251
1251
  truncationEnabled = true;
1252
1252
  break outer;
1253
1253
  }
@@ -1264,7 +1264,7 @@ var init_dist = __esm({
1264
1264
  width: truncationEnabled ? truncationLimit : width,
1265
1265
  index: truncationEnabled ? truncationIndex : length,
1266
1266
  truncated: truncationEnabled,
1267
- ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
1267
+ ellipsed: truncationEnabled && LIMIT2 >= ELLIPSIS_WIDTH
1268
1268
  };
1269
1269
  };
1270
1270
  dist_default = getStringTruncatedWidth;
@@ -17964,8 +17964,9 @@ var init_config = __esm({
17964
17964
  });
17965
17965
  });
17966
17966
  featureConfigSchema = external_exports.object({
17967
- /** Experimental desktop workflow recorder. Hidden unless explicitly enabled. */
17968
- skillRecorder: external_exports.boolean().optional(),
17967
+ /** Bots may draft skills (skill_manage, /learn) for your review. Off unless
17968
+ * explicitly enabled. */
17969
+ skillAuthoring: external_exports.boolean().optional(),
17969
17970
  /** Show each tool run in the transcript. Off unless explicitly enabled. */
17970
17971
  showToolCalls: external_exports.boolean().optional(),
17971
17972
  /** Experimental built-in browser. Off until explicitly enabled; each bot
@@ -18475,6 +18476,11 @@ function windowsKnownDirs() {
18475
18476
  join7(home, "go", "bin")
18476
18477
  ];
18477
18478
  }
18479
+ function registerPathDir(dir) {
18480
+ if (registeredDirs.includes(dir)) return;
18481
+ registeredDirs.unshift(dir);
18482
+ resetPathCache();
18483
+ }
18478
18484
  function resetPathCache() {
18479
18485
  cached2 = null;
18480
18486
  probed = false;
@@ -18482,6 +18488,7 @@ function resetPathCache() {
18482
18488
  function augmentedPath() {
18483
18489
  if (cached2 === null) {
18484
18490
  cached2 = mergePaths([
18491
+ ...registeredDirs.filter((d) => existsSync5(d)),
18485
18492
  ...process.env.OMB_EXTRA_PATH ? process.env.OMB_EXTRA_PATH.split(delimiter3) : [],
18486
18493
  ...process.env.PATH ? process.env.PATH.split(delimiter3) : [],
18487
18494
  // Keep the last successful login-shell result while a rescan starts a
@@ -18646,13 +18653,14 @@ function resolveCliSpawn(cli, args) {
18646
18653
  }
18647
18654
  return resolveWord(cli, args);
18648
18655
  }
18649
- var cached2, probed, loginShellPath;
18656
+ var cached2, probed, loginShellPath, registeredDirs;
18650
18657
  var init_env_path = __esm({
18651
18658
  "server/env-path.ts"() {
18652
18659
  "use strict";
18653
18660
  cached2 = null;
18654
18661
  probed = false;
18655
18662
  loginShellPath = null;
18663
+ registeredDirs = [];
18656
18664
  }
18657
18665
  });
18658
18666
 
@@ -18766,7 +18774,124 @@ var init_procs = __esm({
18766
18774
  }
18767
18775
  });
18768
18776
 
18777
+ // server/engine-install.ts
18778
+ import { existsSync as existsSync6, mkdirSync as mkdirSync6 } from "node:fs";
18779
+ import { join as join9 } from "node:path";
18780
+ import { stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
18781
+ function enginesPrefix(baseDir = DATA_DIR) {
18782
+ return join9(baseDir, "tools", "npm");
18783
+ }
18784
+ function enginesBinDir(baseDir = DATA_DIR, platform = process.platform) {
18785
+ return platform === "win32" ? enginesPrefix(baseDir) : join9(enginesPrefix(baseDir), "bin");
18786
+ }
18787
+ function npmPackageOf(install) {
18788
+ const line = install?.command?.linux ?? install?.command?.darwin ?? install?.command?.win32;
18789
+ const match = line ? /^npm install -g ((?:@[\w.-]+\/)?[\w.-]+)$/.exec(line.trim()) : null;
18790
+ return match ? match[1] : null;
18791
+ }
18792
+ function npmAvailable() {
18793
+ return findCliCandidates("npm").length > 0;
18794
+ }
18795
+ function serverInstallFor(install, npmPresent = npmAvailable()) {
18796
+ if (!install || install.managed) return null;
18797
+ const pkg = npmPackageOf(install);
18798
+ return pkg && npmPresent ? { package: pkg } : null;
18799
+ }
18800
+ function installNpmEngine(pkg, options = {}) {
18801
+ const key = `${options.baseDir ?? DATA_DIR} ${pkg}`;
18802
+ const existing = running.get(key);
18803
+ if (existing) return existing;
18804
+ const run3 = installOnce(pkg, options).finally(() => running.delete(key));
18805
+ running.set(key, run3);
18806
+ return run3;
18807
+ }
18808
+ async function installOnce(pkg, options) {
18809
+ const prefix = enginesPrefix(options.baseDir);
18810
+ mkdirSync6(prefix, { recursive: true });
18811
+ const env = {
18812
+ ...options.env ?? process.env,
18813
+ PATH: options.path ?? augmentedPath(),
18814
+ NO_COLOR: "1",
18815
+ npm_config_update_notifier: "false",
18816
+ npm_config_fund: "false",
18817
+ npm_config_audit: "false"
18818
+ };
18819
+ stripWorkspaceCredentialEnv(env);
18820
+ const args = ["install", "-g", "--prefix", prefix, "--loglevel=error", `--allow-scripts=${pkg}`, `${pkg}@latest`];
18821
+ const result = await runNpm(args, env, prefix, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
18822
+ if (result.code !== 0) {
18823
+ throw new Error(`npm could not install ${pkg} on this server.${tail(result.output)}`);
18824
+ }
18825
+ registerPathDir(enginesBinDir(options.baseDir));
18826
+ resetPathCache();
18827
+ if (options.cli) {
18828
+ const binDir = enginesBinDir(options.baseDir);
18829
+ if (!findCliCandidates(options.cli).some((path3) => path3.startsWith(binDir))) {
18830
+ throw new Error(`${pkg} installed, but it did not provide a \`${options.cli}\` command. Check the package name in this engine's install descriptor.`);
18831
+ }
18832
+ }
18833
+ }
18834
+ function tail(output) {
18835
+ const clean = stripVTControlCharacters3(output).trim();
18836
+ if (!clean) return "";
18837
+ const lines = clean.split(/\r?\n/).filter((line) => line.trim()).slice(-6);
18838
+ return `
18839
+ ${lines.join("\n").slice(-600)}`;
18840
+ }
18841
+ function runNpm(args, env, cwd, timeoutMs) {
18842
+ return new Promise((resolveRun, rejectRun) => {
18843
+ let child;
18844
+ try {
18845
+ child = spawnCli("npm", args, { env, cwd, stdio: ["pipe", "pipe", "pipe"] });
18846
+ } catch {
18847
+ rejectRun(new Error("npm could not start on this server. Install Node.js with npm for the user running OpenMausBot, then try again."));
18848
+ return;
18849
+ }
18850
+ child.stdin.end();
18851
+ let output = "";
18852
+ const receive = (chunk) => {
18853
+ if (output.length < MAX_OUTPUT) output += chunk.toString("utf8").slice(0, MAX_OUTPUT - output.length);
18854
+ };
18855
+ child.stdout.on("data", receive);
18856
+ child.stderr.on("data", receive);
18857
+ let timedOut = false;
18858
+ const timer = setTimeout(() => {
18859
+ timedOut = true;
18860
+ void killCliTree(child);
18861
+ }, timeoutMs);
18862
+ timer.unref();
18863
+ child.once("error", (error51) => {
18864
+ clearTimeout(timer);
18865
+ 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."));
18866
+ });
18867
+ child.once("close", (code) => {
18868
+ clearTimeout(timer);
18869
+ if (timedOut) {
18870
+ rejectRun(new Error("The install took too long and was stopped. Check the server's network connection and try again."));
18871
+ return;
18872
+ }
18873
+ resolveRun({ code, output });
18874
+ });
18875
+ });
18876
+ }
18877
+ var MAX_OUTPUT, DEFAULT_TIMEOUT_MS, running;
18878
+ var init_engine_install = __esm({
18879
+ "server/engine-install.ts"() {
18880
+ "use strict";
18881
+ init_config();
18882
+ init_env_path();
18883
+ init_procs();
18884
+ MAX_OUTPUT = 64 * 1024;
18885
+ DEFAULT_TIMEOUT_MS = 10 * 6e4;
18886
+ running = /* @__PURE__ */ new Map();
18887
+ }
18888
+ });
18889
+
18769
18890
  // server/harness/registry.ts
18891
+ function withServerInstall(install, npmPresent) {
18892
+ const server = install ? serverInstallFor(install, npmPresent) : null;
18893
+ return server ? { ...install, server } : install;
18894
+ }
18770
18895
  function cliDefaultOf(driver) {
18771
18896
  if (!driver) return void 0;
18772
18897
  try {
@@ -18785,13 +18910,21 @@ var init_registry = __esm({
18785
18910
  "server/harness/registry.ts"() {
18786
18911
  "use strict";
18787
18912
  init_env_path();
18913
+ init_engine_install();
18788
18914
  ProviderRegistry = class {
18789
18915
  byId = /* @__PURE__ */ new Map();
18790
18916
  /** decoded per-instance `cli` overrides, for describe() — drivers spawn
18791
18917
  * from their own config; this map only reports what was configured */
18792
18918
  cliByInstance = /* @__PURE__ */ new Map();
18793
18919
  driversByKind;
18794
- constructor(drivers) {
18920
+ /** Where Settings-driven npm installs go; the data directory by default. */
18921
+ enginesBaseDir;
18922
+ /** Whether npm is on this machine; injectable because the PATH scan also
18923
+ * looks in standard install locations, which tests cannot empty. */
18924
+ npmPresent;
18925
+ constructor(drivers, options = {}) {
18926
+ this.enginesBaseDir = options.enginesBaseDir;
18927
+ this.npmPresent = options.npmAvailable ?? npmAvailable;
18795
18928
  this.driversByKind = new Map(drivers.map((d) => [d.driverKind, d]));
18796
18929
  }
18797
18930
  async load(configs) {
@@ -18866,10 +18999,20 @@ var init_registry = __esm({
18866
18999
  await instance.refreshModels?.();
18867
19000
  return true;
18868
19001
  }
19002
+ /** A driver's own installer (a managed download) first; otherwise the
19003
+ * app's npm prefix, when the driver's install one-liner is an npm package
19004
+ * and npm is on PATH. False means Settings has nothing to offer here. */
18869
19005
  async installRuntime(instanceId) {
18870
- const instance = this.get(instanceId);
18871
- if (!instance?.installRuntime) return false;
18872
- await instance.installRuntime();
19006
+ const entry = this.byId.get(instanceId);
19007
+ if (!entry) return false;
19008
+ if (entry.live?.installRuntime) {
19009
+ await entry.live.installRuntime();
19010
+ return true;
19011
+ }
19012
+ const driver = this.driversByKind.get(entry.shadow?.driverKind ?? entry.live.driverKind);
19013
+ const server = serverInstallFor(driver?.install, this.npmPresent());
19014
+ if (!server) return false;
19015
+ await installNpmEngine(server.package, { baseDir: this.enginesBaseDir, cli: cliDefaultOf(driver) });
18873
19016
  return true;
18874
19017
  }
18875
19018
  async startAuthentication(instanceId) {
@@ -18904,6 +19047,7 @@ var init_registry = __esm({
18904
19047
  candidatesByName.set(name, found);
18905
19048
  return found;
18906
19049
  };
19050
+ const npmPresent = this.npmPresent();
18907
19051
  return Promise.all(
18908
19052
  this.entries().map(async (entry) => {
18909
19053
  const driver = this.driversByKind.get(entry.shadow?.driverKind ?? entry.live.driverKind);
@@ -18917,7 +19061,7 @@ var init_registry = __esm({
18917
19061
  capabilities: { computerMcp: false, agentsMcp: false, localComputerMcp: false },
18918
19062
  // an unknown driver has no driver record, hence no install path
18919
19063
  access: driver?.metadata.access ?? "subscription",
18920
- install: driver?.install,
19064
+ install: withServerInstall(driver?.install, npmPresent),
18921
19065
  cli: entry.shadow.cli,
18922
19066
  cliDefault: cliDefaultOf(driver),
18923
19067
  // a shadow is exactly the "your CLI is broken, pick another"
@@ -18951,7 +19095,7 @@ var init_registry = __esm({
18951
19095
  approvalReview: inst.reviewPermission !== void 0
18952
19096
  },
18953
19097
  access: driver?.metadata.access ?? "subscription",
18954
- install: driver?.install,
19098
+ install: withServerInstall(driver?.install, npmPresent),
18955
19099
  authentication: inst.startAuthentication ? {
18956
19100
  method: inst.getAuthentication && inst.completeAuthentication ? "paste-code" : inst.getAuthentication ? "device-code" : "browser",
18957
19101
  // a link and a callback URL (managed engines)
@@ -18986,7 +19130,7 @@ var init_registry = __esm({
18986
19130
  // server/drivers/local-inject.ts
18987
19131
  import { readFileSync as readFileSync5 } from "node:fs";
18988
19132
  import { homedir as homedir6 } from "node:os";
18989
- import { join as join9 } from "node:path";
19133
+ import { join as join10 } from "node:path";
18990
19134
  function contextWindowsFromPs(extra) {
18991
19135
  const out = /* @__PURE__ */ new Map();
18992
19136
  const rec = extra && typeof extra === "object" ? extra : null;
@@ -19071,7 +19215,7 @@ function firstUnslothToken(row) {
19071
19215
  function readUnslothKey(env) {
19072
19216
  const home = env.HOME || env.USERPROFILE || homedir6();
19073
19217
  try {
19074
- const raw = JSON.parse(readFileSync5(join9(home, ".unsloth", "studio", "auth", "agent_api_key.json"), "utf8"));
19218
+ const raw = JSON.parse(readFileSync5(join10(home, ".unsloth", "studio", "auth", "agent_api_key.json"), "utf8"));
19075
19219
  if (raw.servers && typeof raw.servers === "object") {
19076
19220
  const servers = raw.servers;
19077
19221
  for (const url2 of ["http://127.0.0.1:8888", "http://localhost:8888"]) {
@@ -19130,12 +19274,12 @@ function loadedIdsFromPayloads(_host, catalog, extra) {
19130
19274
  };
19131
19275
  if (extra && typeof extra === "object") {
19132
19276
  const rec = extra;
19133
- const running = Array.isArray(rec.models) ? rec.models : Array.isArray(rec.data) ? rec.data : [];
19134
- const hasLoadedFlags = running.some(
19277
+ const running2 = Array.isArray(rec.models) ? rec.models : Array.isArray(rec.data) ? rec.data : [];
19278
+ const hasLoadedFlags = running2.some(
19135
19279
  (row) => row && typeof row === "object" && ("loaded" in row || "state" in row)
19136
19280
  );
19137
19281
  if (!hasLoadedFlags && typeof rec.default_model === "string") add(rec.default_model);
19138
- for (const row of running) {
19282
+ for (const row of running2) {
19139
19283
  if (typeof row === "string") {
19140
19284
  if (!hasLoadedFlags) add(row);
19141
19285
  continue;
@@ -19272,12 +19416,12 @@ var init_local_inject = __esm({
19272
19416
  });
19273
19417
 
19274
19418
  // server/proxy-paths.ts
19275
- import { existsSync as existsSync6 } from "node:fs";
19276
- import { dirname as dirname4, join as join10 } from "node:path";
19419
+ import { existsSync as existsSync7 } from "node:fs";
19420
+ import { dirname as dirname4, join as join11 } from "node:path";
19277
19421
  import { fileURLToPath as fileURLToPath2 } from "node:url";
19278
19422
  function resolveProxy(relative2) {
19279
- const source = join10(SERVER_ROOT, `${relative2}.ts`);
19280
- return existsSync6(source) ? source : join10(SERVER_ROOT, `${relative2}.js`);
19423
+ const source = join11(SERVER_ROOT, `${relative2}.ts`);
19424
+ return existsSync7(source) ? source : join11(SERVER_ROOT, `${relative2}.js`);
19281
19425
  }
19282
19426
  var SERVER_ROOT, SPAWNED_PROXIES;
19283
19427
  var init_proxy_paths = __esm({
@@ -19294,6 +19438,7 @@ var init_proxy_paths = __esm({
19294
19438
  agents: resolveProxy("drivers/agents-proxy"),
19295
19439
  dweb: resolveProxy("drivers/dweb-proxy"),
19296
19440
  connectors: resolveProxy("connector-proxy"),
19441
+ mcpGate: resolveProxy("mcp-gate"),
19297
19442
  phone: resolveProxy("drivers/phone-proxy"),
19298
19443
  // Loaded by the external `pi` process via `-e`, not by this server — but
19299
19444
  // resolved through the same single source of truth so the packaged layout
@@ -19305,7 +19450,7 @@ var init_proxy_paths = __esm({
19305
19450
 
19306
19451
  // server/container-computer.ts
19307
19452
  import { execFile as execFile4 } from "node:child_process";
19308
- import { join as join11, resolve as resolve3 } from "node:path";
19453
+ import { join as join12, resolve as resolve3 } from "node:path";
19309
19454
  import { promisify } from "node:util";
19310
19455
  function computerProxyEnv(computer) {
19311
19456
  return {
@@ -19329,7 +19474,7 @@ var init_container_computer = __esm({
19329
19474
  IMAGE_REPOSITORY = "localhost/openmausbot/cua-local-vm";
19330
19475
  IMAGE_LAYER_VERSION = "5";
19331
19476
  IMAGE = `${IMAGE_REPOSITORY}:driver-${CUA_DRIVER_VERSION}-v${IMAGE_LAYER_VERSION}`;
19332
- VM_WORKSPACE_DIR = join11(DATA_DIR, "vm-home");
19477
+ VM_WORKSPACE_DIR = join12(DATA_DIR, "vm-home");
19333
19478
  MEMORY_BYTES = 4 * 1024 * 1024 * 1024;
19334
19479
  SHM_BYTES = 512 * 1024 * 1024;
19335
19480
  containerMcpPath = SPAWNED_PROXIES.containerMcp;
@@ -19363,6 +19508,9 @@ ${close}`);
19363
19508
  for (const re of KEY_PREFIXES) out = out.replace(re, (m) => mask(m));
19364
19509
  out = out.replace(BEARER, (_m, lead, tok) => `${lead}${mask(tok)}`);
19365
19510
  out = out.replace(KEY_VALUE, (_m, key, sep, quote, value) => `${key}${sep}${quote}${mask(value)}${quote}`);
19511
+ out = out.replace(KEY_SUFFIX_ASSIGNMENT, (_m, key, sep, quote, value) => `${key}${sep}${quote}${mask(value)}${quote}`);
19512
+ out = out.replace(SECRET_FLAG, (_m, flag, quote, value) => `${flag}${quote}${mask(value)}${quote}`);
19513
+ out = out.replace(URL_USERINFO, (_m, lead, secret, at) => `${lead}${mask(secret)}${at}`);
19366
19514
  return out;
19367
19515
  }
19368
19516
  function redactSecrets(input, depth = 0) {
@@ -19387,7 +19535,7 @@ function redactSecrets(input, depth = 0) {
19387
19535
  }
19388
19536
  return out;
19389
19537
  }
19390
- var SECRET_KEY_PARTS, REDACTION_MARKER, mask, KEY_PREFIXES, BEARER, PEM_BLOCK, KEY_VALUE;
19538
+ var SECRET_KEY_PARTS, REDACTION_MARKER, mask, KEY_PREFIXES, BEARER, PEM_BLOCK, KEY_VALUE, KEY_SUFFIX_ASSIGNMENT, SECRET_FLAG, URL_USERINFO;
19391
19539
  var init_redact = __esm({
19392
19540
  "server/redact.ts"() {
19393
19541
  "use strict";
@@ -19397,6 +19545,12 @@ var init_redact = __esm({
19397
19545
  KEY_PREFIXES = [
19398
19546
  /\bsk-(?:ant-|proj-|live-|test-)?[A-Za-z0-9_-]{16,}/g,
19399
19547
  // anthropic / openai / stripe
19548
+ /\bxai-[A-Za-z0-9_-]{20,}/g,
19549
+ // xai (grok)
19550
+ /\bgsk_[A-Za-z0-9]{40,}/g,
19551
+ // groq
19552
+ /\bhf_[A-Za-z0-9]{30,}/g,
19553
+ // hugging face
19400
19554
  /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}/g,
19401
19555
  // github classic
19402
19556
  /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
@@ -19415,16 +19569,19 @@ var init_redact = __esm({
19415
19569
  BEARER = /(\bBearer\s+)([A-Za-z0-9._~+/=-]{12,})/g;
19416
19570
  PEM_BLOCK = /(-----BEGIN [A-Z ]*PRIVATE KEY-----)([\s\S]*?)(-----END [A-Z ]*PRIVATE KEY-----)/g;
19417
19571
  KEY_VALUE = /\b((?:[A-Za-z0-9_-]*_)?(?:api[_-]?key|apikey|secret|token|password|passwd|authorization|auth[_-]?token|access[_-]?key|private[_-]?key)s?)(["']?\s*[=:]\s*)(["']?)([A-Za-z0-9._~+/=-]{8,})\3/gi;
19572
+ KEY_SUFFIX_ASSIGNMENT = /\b([A-Za-z][A-Za-z0-9_-]*[_-]key)s?(=)(["']?)([A-Za-z0-9._~+/=-]+)\3/gi;
19573
+ SECRET_FLAG = /(--(?:token|password|passwd|api-key|apikey|secret|access-key|auth-token)(?:=|\s+))(["']?)(?!-)([A-Za-z0-9._~+/=-]+)\2/gi;
19574
+ URL_USERINFO = /(\b[a-z][a-z0-9+.-]*:\/\/[^\s/:@'"]+:)([^\s/@'"«»]+)(@)/gi;
19418
19575
  }
19419
19576
  });
19420
19577
 
19421
19578
  // server/drivers/native.ts
19422
19579
  import { appendFileSync } from "node:fs";
19423
- import { join as join12 } from "node:path";
19580
+ import { join as join13 } from "node:path";
19424
19581
  function appendNative(threadId, entry) {
19425
19582
  try {
19426
19583
  appendFileSync(
19427
- join12(NATIVE_DIR, `${threadId}.ndjson`),
19584
+ join13(NATIVE_DIR, `${threadId}.ndjson`),
19428
19585
  JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...entry, msg: redactSecrets(entry.msg) }) + "\n",
19429
19586
  { mode: 384 }
19430
19587
  );
@@ -19439,6 +19596,36 @@ var init_native = __esm({
19439
19596
  }
19440
19597
  });
19441
19598
 
19599
+ // server/tool-summary.ts
19600
+ function fieldsOf(input) {
19601
+ if (input === null || typeof input !== "object" || Array.isArray(input)) return void 0;
19602
+ return input;
19603
+ }
19604
+ function commandSummary(input) {
19605
+ const command = fieldsOf(input)?.command;
19606
+ if (typeof command !== "string") return void 0;
19607
+ return cut(command.replace(/\s*[\r\n]+\s*/g, " "), LIMIT);
19608
+ }
19609
+ function askInputSummary(input) {
19610
+ const fields = fieldsOf(input);
19611
+ if (!fields) return void 0;
19612
+ if (typeof fields.question === "string") return cut(fields.question, QUESTION_LIMIT);
19613
+ if (typeof fields.command === "string") return cut(fields.command, LIMIT);
19614
+ if (typeof fields.url === "string") return cut(fields.url, LIMIT);
19615
+ const text2 = JSON.stringify(fields);
19616
+ return text2 === "{}" ? void 0 : cut(text2, LIMIT);
19617
+ }
19618
+ var QUESTION_LIMIT, LIMIT, cut;
19619
+ var init_tool_summary = __esm({
19620
+ "server/tool-summary.ts"() {
19621
+ "use strict";
19622
+ init_redact();
19623
+ QUESTION_LIMIT = 300;
19624
+ LIMIT = 200;
19625
+ cut = (text2, limit) => redactSecretsInText(text2).trim().slice(0, limit);
19626
+ }
19627
+ });
19628
+
19442
19629
  // server/drivers/acp/core.ts
19443
19630
  import { homedir as homedir7 } from "node:os";
19444
19631
  import { lstat, mkdir, readFile, realpath, stat, writeFile } from "node:fs/promises";
@@ -19883,7 +20070,8 @@ function createAcpDriver(support11) {
19883
20070
  type: "item.started",
19884
20071
  itemType: "tool",
19885
20072
  itemId: u4.toolCallId,
19886
- title: String(u4.rawInput?.command ?? u4.title ?? "tool").slice(0, 80)
20073
+ title: String(u4.rawInput?.command ?? u4.title ?? "tool").slice(0, 80),
20074
+ summary: commandSummary(u4.rawInput)
19887
20075
  });
19888
20076
  break;
19889
20077
  }
@@ -20193,6 +20381,7 @@ var init_core3 = __esm({
20193
20381
  init_env_path();
20194
20382
  init_approval_mode();
20195
20383
  init_native();
20384
+ init_tool_summary();
20196
20385
  init_proxy_paths();
20197
20386
  COMPUTER_PROXY_PATH = SPAWNED_PROXIES.computer;
20198
20387
  envOr = (key, fallback) => Number(process.env[key] ?? fallback);
@@ -20210,7 +20399,7 @@ import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypt
20210
20399
  import { mkdir as mkdir2, mkdtemp, readFile as readFile2, rm, stat as stat2 } from "node:fs/promises";
20211
20400
  import { request as httpRequest } from "node:http";
20212
20401
  import { tmpdir as tmpdir2 } from "node:os";
20213
- import { delimiter as delimiter4, join as join13, resolve as resolve5 } from "node:path";
20402
+ import { delimiter as delimiter4, join as join14, resolve as resolve5 } from "node:path";
20214
20403
  function quoteBrowserArgument(value) {
20215
20404
  return `'${value.replaceAll("'", `'"'"'`)}'`;
20216
20405
  }
@@ -20245,11 +20434,11 @@ function authorizationUrlFromLine(line) {
20245
20434
  }
20246
20435
  }
20247
20436
  function antigravityProfileDirectory(instanceId, baseDir = DATA_DIR) {
20248
- return join13(baseDir, "providers", "antigravity", createHash3("sha256").update(instanceId).digest("hex"));
20437
+ return join14(baseDir, "providers", "antigravity", createHash3("sha256").update(instanceId).digest("hex"));
20249
20438
  }
20250
20439
  async function prepareAntigravityProfile(input) {
20251
20440
  const directory = resolve5(input.profileDirectory ?? antigravityProfileDirectory(input.instanceId, input.baseDir));
20252
- const acpDirectory = join13(directory, "antigravity-acp");
20441
+ const acpDirectory = join14(directory, "antigravity-acp");
20253
20442
  await mkdir2(acpDirectory, { recursive: true, mode: 448 });
20254
20443
  if (process.platform !== "win32") {
20255
20444
  const { chmod: chmod2 } = await import("node:fs/promises");
@@ -20257,7 +20446,7 @@ async function prepareAntigravityProfile(input) {
20257
20446
  await chmod2(acpDirectory, 448);
20258
20447
  }
20259
20448
  writeFileAtomic(
20260
- join13(acpDirectory, "settings.json"),
20449
+ join14(acpDirectory, "settings.json"),
20261
20450
  `${JSON.stringify({ auth: { type: "oauth-personal" } })}
20262
20451
  `,
20263
20452
  { mode: 384 }
@@ -20280,7 +20469,7 @@ async function prepareAntigravityProfile(input) {
20280
20469
  PYTHONUNBUFFERED: "1",
20281
20470
  ELECTRON_RUN_AS_NODE: "1"
20282
20471
  });
20283
- return { directory, tokenPath: join13(acpDirectory, "acp_token.json"), environment };
20472
+ return { directory, tokenPath: join14(acpDirectory, "acp_token.json"), environment };
20284
20473
  }
20285
20474
  async function antigravityProfileAuthenticated(profile) {
20286
20475
  try {
@@ -20409,7 +20598,7 @@ function isValidAntigravityInitializeResult(initialized, expectedVersion) {
20409
20598
  return true;
20410
20599
  }
20411
20600
  async function validateAntigravityRuntime(runtime, expectedVersion) {
20412
- const profileDirectory = await mkdtemp(join13(tmpdir2(), "openmaus-antigravity-verify-"));
20601
+ const profileDirectory = await mkdtemp(join14(tmpdir2(), "openmaus-antigravity-verify-"));
20413
20602
  let client;
20414
20603
  let failed = false;
20415
20604
  let failure;
@@ -20798,7 +20987,7 @@ import {
20798
20987
  writeFile as writeFile2
20799
20988
  } from "node:fs/promises";
20800
20989
  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";
20990
+ import { delimiter as delimiter5, dirname as dirname6, isAbsolute as isAbsolute2, join as join15, resolve as resolve6 } from "node:path";
20802
20991
  import { Transform } from "node:stream";
20803
20992
  import { pipeline } from "node:stream/promises";
20804
20993
  import { createInflateRaw } from "node:zlib";
@@ -20819,7 +21008,7 @@ async function retryOnWindowsFileLock(step, options = {}) {
20819
21008
  }
20820
21009
  }
20821
21010
  function runtimeRoot(baseDir = DATA_DIR) {
20822
- return join14(baseDir, "tools", "antigravity-acp", `${process.platform}-${process.arch}`);
21011
+ return join15(baseDir, "tools", "antigravity-acp", `${process.platform}-${process.arch}`);
20823
21012
  }
20824
21013
  function executableNames(platform = process.platform) {
20825
21014
  return platform === "win32" ? { executable: "agy_acp_server.exe", harness: "localharness_external.exe" } : { executable: "agy_acp_server.par", harness: "localharness_external" };
@@ -20836,10 +21025,10 @@ async function executableFile(path3, bytes) {
20836
21025
  }
20837
21026
  async function completedRelease(directory, asset) {
20838
21027
  try {
20839
- const record3 = JSON.parse(await readFile3(join14(directory, INSTALL_RECORD), "utf8"));
21028
+ const record3 = JSON.parse(await readFile3(join15(directory, INSTALL_RECORD), "utf8"));
20840
21029
  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);
21030
+ const executablePath = join15(directory, asset.executable.name);
21031
+ const harnessPath = join15(directory, asset.harness.name);
20843
21032
  if (!await executableFile(executablePath, asset.executable.bytes)) return null;
20844
21033
  if (!await executableFile(harnessPath, asset.harness.bytes)) return null;
20845
21034
  return { executablePath, harnessPath, source: "managed", version: asset.version };
@@ -20855,7 +21044,7 @@ function pathCandidates(binary2, env) {
20855
21044
  async function externalRuntime(candidate, source) {
20856
21045
  const names = executableNames();
20857
21046
  const executablePath = resolve6(candidate);
20858
- const harnessPath = join14(dirname6(executablePath), names.harness);
21047
+ const harnessPath = join15(dirname6(executablePath), names.harness);
20859
21048
  if (!await executableFile(executablePath) || !await executableFile(harnessPath)) return null;
20860
21049
  return { executablePath, harnessPath, source, version: null };
20861
21050
  }
@@ -20875,7 +21064,7 @@ async function resolveAntigravityRuntime(binaryPath, env = process.env, baseDir
20875
21064
  }
20876
21065
  const asset = resolveAntigravityReleaseAsset();
20877
21066
  if (asset) {
20878
- const managed = await completedRelease(join14(runtimeRoot(baseDir), "versions", asset.sha256), asset);
21067
+ const managed = await completedRelease(join15(runtimeRoot(baseDir), "versions", asset.sha256), asset);
20879
21068
  if (managed) return managed;
20880
21069
  }
20881
21070
  const names = executableNames();
@@ -20895,25 +21084,25 @@ async function pinnedZipEntries(path3) {
20895
21084
  try {
20896
21085
  const info = await handle.stat();
20897
21086
  const tailBytes = Math.min(info.size, MAX_EOCD_BYTES);
20898
- const tail = Buffer.alloc(tailBytes);
21087
+ const tail2 = Buffer.alloc(tailBytes);
20899
21088
  const tailOffset = info.size - tailBytes;
20900
- if ((await handle.read(tail, 0, tailBytes, tailOffset)).bytesRead !== tailBytes) {
21089
+ if ((await handle.read(tail2, 0, tailBytes, tailOffset)).bytesRead !== tailBytes) {
20901
21090
  throw new Error("The verified archive was truncated.");
20902
21091
  }
20903
21092
  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) {
21093
+ for (let cursor4 = tail2.length - 22; cursor4 >= 0; cursor4 -= 1) {
21094
+ if (tail2.readUInt32LE(cursor4) === EOCD_SIGNATURE && cursor4 + 22 + tail2.readUInt16LE(cursor4 + 20) === tail2.length) {
20906
21095
  eocd = cursor4;
20907
21096
  break;
20908
21097
  }
20909
21098
  }
20910
21099
  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);
21100
+ const disk = tail2.readUInt16LE(eocd + 4);
21101
+ const directoryDisk = tail2.readUInt16LE(eocd + 6);
21102
+ const diskEntries = tail2.readUInt16LE(eocd + 8);
21103
+ const entryCount = tail2.readUInt16LE(eocd + 10);
21104
+ const directoryBytes = tail2.readUInt32LE(eocd + 12);
21105
+ const directoryOffset = tail2.readUInt32LE(eocd + 16);
20917
21106
  const eocdOffset = tailOffset + eocd;
20918
21107
  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
21108
  const directory = Buffer.alloc(directoryBytes);
@@ -20997,19 +21186,19 @@ async function extractPinnedArchive(archivePath, outputDirectory, asset) {
20997
21186
  start: dataOffset,
20998
21187
  end: dataOffset + entry.compressedBytes - 1
20999
21188
  });
21000
- const destination = createWriteStream(join14(outputDirectory, entry.name), { flags: "wx", mode: 448 });
21189
+ const destination = createWriteStream(join15(outputDirectory, entry.name), { flags: "wx", mode: 448 });
21001
21190
  if (entry.compression === 8) await pipeline(source, createInflateRaw(), counter, destination);
21002
21191
  else await pipeline(source, counter, destination);
21003
21192
  if (bytes !== expectedBytes) throw new Error("An extracted file was truncated.");
21004
21193
  }
21005
21194
  if (seen.size !== 2) throw new Error("The archive is missing an expected file.");
21006
21195
  }
21007
- async function installOnce(options) {
21196
+ async function installOnce2(options) {
21008
21197
  const asset = options.asset === void 0 ? resolveAntigravityReleaseAsset() : options.asset;
21009
21198
  if (!asset) throw new Error(`Google does not publish an Antigravity runtime for ${process.platform}-${process.arch}.`);
21010
21199
  const root = runtimeRoot(options.baseDir);
21011
- const versions = join14(root, "versions");
21012
- const destination = join14(versions, asset.sha256);
21200
+ const versions = join15(root, "versions");
21201
+ const destination = join15(versions, asset.sha256);
21013
21202
  await mkdir3(versions, { recursive: true, mode: 448 });
21014
21203
  const existing = await completedRelease(destination, asset);
21015
21204
  if (existing) {
@@ -21025,11 +21214,11 @@ async function installOnce(options) {
21025
21214
  } catch (error51) {
21026
21215
  if (error51 instanceof Error && error51.message.includes("Antigravity needs")) throw error51;
21027
21216
  }
21028
- const staging = await mkdtemp2(join14(versions, `${STAGING_PREFIX}${randomUUID7()}-`));
21217
+ const staging = await mkdtemp2(join15(versions, `${STAGING_PREFIX}${randomUUID7()}-`));
21029
21218
  let failed = false;
21030
21219
  try {
21031
- const archivePath = join14(staging, "download.zip");
21032
- const runtimeDirectory = join14(staging, "runtime");
21220
+ const archivePath = join15(staging, "download.zip");
21221
+ const runtimeDirectory = join15(staging, "runtime");
21033
21222
  await mkdir3(runtimeDirectory, { mode: 448 });
21034
21223
  const controller = new AbortController();
21035
21224
  const timeout = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS2);
@@ -21075,12 +21264,12 @@ async function installOnce(options) {
21075
21264
  }
21076
21265
  await extractPinnedArchive(archivePath, runtimeDirectory, asset);
21077
21266
  if (process.platform !== "win32") {
21078
- await chmod(join14(runtimeDirectory, asset.executable.name), 493);
21079
- await chmod(join14(runtimeDirectory, asset.harness.name), 493);
21267
+ await chmod(join15(runtimeDirectory, asset.executable.name), 493);
21268
+ await chmod(join15(runtimeDirectory, asset.harness.name), 493);
21080
21269
  }
21081
21270
  const candidate = {
21082
- executablePath: join14(runtimeDirectory, asset.executable.name),
21083
- harnessPath: join14(runtimeDirectory, asset.harness.name),
21271
+ executablePath: join15(runtimeDirectory, asset.executable.name),
21272
+ harnessPath: join15(runtimeDirectory, asset.harness.name),
21084
21273
  source: "managed",
21085
21274
  version: asset.version
21086
21275
  };
@@ -21091,7 +21280,7 @@ async function installOnce(options) {
21091
21280
  executable: asset.executable,
21092
21281
  harness: asset.harness
21093
21282
  };
21094
- await writeFile2(join14(runtimeDirectory, INSTALL_RECORD), `${JSON.stringify(record3)}
21283
+ await writeFile2(join15(runtimeDirectory, INSTALL_RECORD), `${JSON.stringify(record3)}
21095
21284
  `, { flag: "wx", mode: 384 });
21096
21285
  try {
21097
21286
  await retryOnWindowsFileLock(() => rename(runtimeDirectory, destination));
@@ -21118,9 +21307,9 @@ function installAntigravityRuntime(options = {}) {
21118
21307
  const key = runtimeRoot(options.baseDir);
21119
21308
  const existing = installs.get(key);
21120
21309
  if (existing) return existing;
21121
- const running = installOnce(options).finally(() => installs.delete(key));
21122
- installs.set(key, running);
21123
- return running;
21310
+ const running2 = installOnce2(options).finally(() => installs.delete(key));
21311
+ installs.set(key, running2);
21312
+ return running2;
21124
21313
  }
21125
21314
  function antigravityManagedInstallAvailable() {
21126
21315
  return resolveAntigravityReleaseAsset() !== null;
@@ -21337,7 +21526,7 @@ var init_boxagent = __esm({
21337
21526
  const listeners = /* @__PURE__ */ new Set();
21338
21527
  const active = /* @__PURE__ */ new Map();
21339
21528
  const emit = (event) => {
21340
- for (const l of [...listeners]) l(event);
21529
+ for (const l of Array.from(listeners)) l(event);
21341
21530
  };
21342
21531
  const base2 = (threadId, turnId) => ({
21343
21532
  eventId: newEventId(),
@@ -21527,18 +21716,39 @@ var init_boxagent = __esm({
21527
21716
  }
21528
21717
  });
21529
21718
 
21719
+ // server/resume-recovery.ts
21720
+ function classifyResumeFailure(state) {
21721
+ if (state.producedOutput || state.promptSubmitted) return "after-accept";
21722
+ if (state.attempted && state.rejected) return "before-accept";
21723
+ return "unknown";
21724
+ }
21725
+ function mayReplay(failure) {
21726
+ return failure === "before-accept";
21727
+ }
21728
+ function recoveryPromptFor(input) {
21729
+ if (!mayReplay(input.failure)) return { text: input.currentText, replayed: false };
21730
+ const replay = input.recoveryText?.trim();
21731
+ if (!replay || replay === input.currentText.trim()) return { text: input.currentText, replayed: false };
21732
+ return { text: replay, replayed: true };
21733
+ }
21734
+ var init_resume_recovery = __esm({
21735
+ "server/resume-recovery.ts"() {
21736
+ "use strict";
21737
+ }
21738
+ });
21739
+
21530
21740
  // server/drivers/claude-login-auth.ts
21531
21741
  import { randomUUID as randomUUID8 } from "node:crypto";
21532
21742
  import { realpathSync } from "node:fs";
21533
21743
  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";
21744
+ import { basename as basename4, dirname as dirname7, isAbsolute as isAbsolute3, join as join16, resolve as resolve7 } from "node:path";
21745
+ import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
21536
21746
  function canonicalPath(path3) {
21537
21747
  try {
21538
21748
  return realpathSync(path3);
21539
21749
  } catch {
21540
21750
  const parent = dirname7(path3);
21541
- return parent === path3 ? path3 : join15(canonicalPath(parent), basename4(path3));
21751
+ return parent === path3 ? path3 : join16(canonicalPath(parent), basename4(path3));
21542
21752
  }
21543
21753
  }
21544
21754
  function claudeSignInLink(value) {
@@ -21553,7 +21763,7 @@ function claudeSignInLink(value) {
21553
21763
  }
21554
21764
  }
21555
21765
  function claudeLoginPrompt(output) {
21556
- const lines = stripVTControlCharacters3(output).split(/\r?\n/).slice(0, -1);
21766
+ const lines = stripVTControlCharacters4(output).split(/\r?\n/).slice(0, -1);
21557
21767
  for (const line of lines) {
21558
21768
  const match = /(https:\/\/\S+)/.exec(line.trim());
21559
21769
  const link = match ? claudeSignInLink(match[1].replace(/[),.;]+$/, "")) : null;
@@ -21565,17 +21775,18 @@ function claudeLoginCode(value) {
21565
21775
  const code = value.trim();
21566
21776
  return /^[A-Za-z0-9_\-#.:]{8,1024}$/.test(code) ? code : null;
21567
21777
  }
21568
- var MAX_OUTPUT, SIGN_IN_HOSTS, authenticatingHomes, NOT_AVAILABLE, ClaudeLoginController;
21778
+ var MAX_OUTPUT2, SIGN_IN_HOSTS, authenticatingHomes, NOT_AVAILABLE, ClaudeLoginController;
21569
21779
  var init_claude_login_auth = __esm({
21570
21780
  "server/drivers/claude-login-auth.ts"() {
21571
21781
  "use strict";
21572
21782
  init_procs();
21573
- MAX_OUTPUT = 32768;
21783
+ MAX_OUTPUT2 = 32768;
21574
21784
  SIGN_IN_HOSTS = ["claude.com", "claude.ai", "console.anthropic.com", "platform.claude.com"];
21575
21785
  authenticatingHomes = /* @__PURE__ */ new Set();
21576
21786
  NOT_AVAILABLE = "This sign-in is no longer available. Start sign-in again.";
21577
21787
  ClaudeLoginController = class {
21578
21788
  flow = null;
21789
+ logoutChild = null;
21579
21790
  disposed = false;
21580
21791
  options;
21581
21792
  constructor(options) {
@@ -21594,7 +21805,7 @@ var init_claude_login_auth = __esm({
21594
21805
  if (!isAbsolute3(home) || env.CLAUDE_CONFIG_DIR && !isAbsolute3(env.CLAUDE_CONFIG_DIR)) {
21595
21806
  throw new Error("Use an absolute HOME and CLAUDE_CONFIG_DIR path for this server's Claude provider before signing in.");
21596
21807
  }
21597
- const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join15(home, ".claude")));
21808
+ const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join16(home, ".claude")));
21598
21809
  if (authenticatingHomes.has(homeKey)) {
21599
21810
  throw new Error("A Claude sign-in is already running for this server account. Finish or cancel it before starting another.");
21600
21811
  }
@@ -21667,43 +21878,121 @@ var init_claude_login_auth = __esm({
21667
21878
  if (this.flow?.status.phase === "waiting") this.finish(this.flow, "cancelled", "Claude sign-in cancelled.");
21668
21879
  await this.flow?.stopping;
21669
21880
  if (this.flow?.terminationFailed) throw new Error(this.flow.status.message);
21881
+ if (this.logoutChild && !await this.stopChild(this.logoutChild)) {
21882
+ throw new Error("Claude Code could not be stopped on this server. Ask the server administrator to stop the account command before trying again.");
21883
+ }
21670
21884
  }
21671
21885
  async dispose() {
21672
21886
  this.disposed = true;
21673
21887
  await this.cancel();
21674
21888
  this.flow = null;
21675
21889
  }
21890
+ /** Remove the sign-in Claude Code stores for this server account (its
21891
+ * configuration directory) so a different subscription can sign in. A
21892
+ * sign-in in progress is never pulled away underneath the browser
21893
+ * completing it, and the CLI's own status is the verdict, as for sign-in. */
21894
+ async signOut() {
21895
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
21896
+ if (this.flow?.status.phase === "waiting") throw new Error("Finish or cancel the Claude sign-in in progress before signing out.");
21897
+ await this.flow?.stopping;
21898
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
21899
+ const env = this.options.environment();
21900
+ const home = env.HOME || env.USERPROFILE || homedir8();
21901
+ if (!isAbsolute3(home) || env.CLAUDE_CONFIG_DIR && !isAbsolute3(env.CLAUDE_CONFIG_DIR)) {
21902
+ throw new Error("Use an absolute HOME and CLAUDE_CONFIG_DIR path for this server's Claude provider before signing out.");
21903
+ }
21904
+ const homeKey = canonicalPath(resolve7(env.CLAUDE_CONFIG_DIR || join16(home, ".claude")));
21905
+ if (authenticatingHomes.has(homeKey)) {
21906
+ throw new Error("A Claude sign-in is running for this server account. Finish or cancel it before signing out.");
21907
+ }
21908
+ authenticatingHomes.add(homeKey);
21909
+ try {
21910
+ await this.logout(env);
21911
+ if (this.disposed) throw new Error("This provider was removed. Refresh Settings before signing out.");
21912
+ const status = await this.authStatus(env);
21913
+ 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.");
21914
+ 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.");
21915
+ } finally {
21916
+ const child = this.logoutChild;
21917
+ if (child && child.exitCode === null && child.signalCode === null) {
21918
+ child.once("close", () => authenticatingHomes.delete(homeKey));
21919
+ } else authenticatingHomes.delete(homeKey);
21920
+ }
21921
+ }
21922
+ /** `claude auth logout`, bounded and non-interactive. Its output stays
21923
+ * here; the status command afterwards decides whether it worked. */
21924
+ logout(env) {
21925
+ return new Promise((resolveDone, rejectDone) => {
21926
+ if (this.disposed) {
21927
+ rejectDone(new Error("This provider was removed. Refresh Settings before signing out."));
21928
+ return;
21929
+ }
21930
+ let child;
21931
+ try {
21932
+ child = spawnCli(this.options.cli, ["auth", "logout"], { env: { ...env, NO_COLOR: "1" }, stdio: ["pipe", "pipe", "pipe"] });
21933
+ } catch {
21934
+ rejectDone(new Error("Claude Code could not start on this server. Install or update the configured Claude CLI, then try again."));
21935
+ return;
21936
+ }
21937
+ this.logoutChild = child;
21938
+ child.stdin.end();
21939
+ child.stdout.on("data", () => {
21940
+ });
21941
+ child.stderr.on("data", () => {
21942
+ });
21943
+ const timer = setTimeout(() => {
21944
+ void this.stopChild(child).catch(() => false).then((stopped) => {
21945
+ 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."));
21946
+ });
21947
+ }, this.options.startupTimeoutMs ?? 3e4);
21948
+ timer.unref();
21949
+ child.once("error", (error51) => {
21950
+ clearTimeout(timer);
21951
+ 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."));
21952
+ });
21953
+ child.once("close", () => {
21954
+ clearTimeout(timer);
21955
+ if (this.logoutChild === child) this.logoutChild = null;
21956
+ resolveDone();
21957
+ });
21958
+ });
21959
+ }
21676
21960
  signedIn(env) {
21961
+ return this.authStatus(env).then((status) => status === "in");
21962
+ }
21963
+ /** `claude auth status --json`: signed in, signed out, or not answered. */
21964
+ authStatus(env) {
21677
21965
  return new Promise((resolveStatus) => {
21678
21966
  let child;
21679
21967
  try {
21680
21968
  child = spawnCli(this.options.cli, ["auth", "status", "--json"], { env: { ...env, NO_COLOR: "1" }, stdio: ["ignore", "pipe", "pipe"] });
21681
21969
  } catch {
21682
- resolveStatus(false);
21970
+ resolveStatus("unknown");
21683
21971
  return;
21684
21972
  }
21685
21973
  let stdout2 = "";
21686
21974
  child.stdout.on("data", (chunk) => {
21687
- if (stdout2.length < MAX_OUTPUT) stdout2 += chunk.toString("utf8");
21975
+ if (stdout2.length < MAX_OUTPUT2) stdout2 += chunk.toString("utf8");
21688
21976
  });
21689
21977
  child.stderr.on("data", () => {
21690
21978
  });
21691
21979
  const timer = setTimeout(() => {
21692
21980
  child.kill("SIGKILL");
21693
- resolveStatus(false);
21981
+ resolveStatus("unknown");
21694
21982
  }, 8e3);
21695
21983
  timer.unref();
21696
21984
  child.once("error", () => {
21697
21985
  clearTimeout(timer);
21698
- resolveStatus(false);
21986
+ resolveStatus("unknown");
21699
21987
  });
21700
- child.once("close", () => {
21988
+ child.once("close", (code) => {
21701
21989
  clearTimeout(timer);
21702
21990
  try {
21703
21991
  const status = JSON.parse(stdout2);
21704
- resolveStatus(typeof status === "object" && status !== null && Reflect.get(status, "loggedIn") === true);
21992
+ const loggedIn = typeof status === "object" && status !== null ? Reflect.get(status, "loggedIn") : void 0;
21993
+ resolveStatus(code === 0 && loggedIn === true ? "in" : code === 1 && loggedIn === false ? "out" : "unknown");
21705
21994
  } catch {
21706
- resolveStatus(false);
21995
+ resolveStatus("unknown");
21707
21996
  }
21708
21997
  });
21709
21998
  });
@@ -21724,7 +22013,7 @@ var init_claude_login_auth = __esm({
21724
22013
  flow.child = child;
21725
22014
  const receive = (chunk) => {
21726
22015
  if (flow.status.phase !== "waiting") return;
21727
- if (flow.output.length + chunk.length > MAX_OUTPUT) {
22016
+ if (flow.output.length + chunk.length > MAX_OUTPUT2) {
21728
22017
  this.finish(flow, "failed", "Claude Code returned an unexpected sign-in response. Update the server's Claude CLI and try again.");
21729
22018
  return;
21730
22019
  }
@@ -21746,7 +22035,7 @@ var init_claude_login_auth = __esm({
21746
22035
  child.once("close", (code) => {
21747
22036
  if (flow.child === child) flow.child = null;
21748
22037
  if (flow.status.phase !== "waiting") return;
21749
- const output = stripVTControlCharacters3(flow.output);
22038
+ const output = stripVTControlCharacters4(flow.output);
21750
22039
  flow.output = "";
21751
22040
  void this.signedIn(flow.env).then((signedIn) => {
21752
22041
  if (flow.status.phase !== "waiting") return;
@@ -21779,7 +22068,7 @@ var init_claude_login_auth = __esm({
21779
22068
  else flow.completion.reject(new Error(message2 ?? "Claude sign-in did not finish."));
21780
22069
  flow.completion = void 0;
21781
22070
  }
21782
- flow.stopping = this.stopChild(flow).catch(() => false).then((stopped) => {
22071
+ flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
21783
22072
  const release = () => authenticatingHomes.delete(flow.homeKey);
21784
22073
  if (stopped) {
21785
22074
  release();
@@ -21794,8 +22083,7 @@ var init_claude_login_auth = __esm({
21794
22083
  if (phase === "succeeded") void this.options.onAuthenticated?.().catch(() => {
21795
22084
  });
21796
22085
  }
21797
- async stopChild(flow) {
21798
- const child = flow.child;
22086
+ async stopChild(child) {
21799
22087
  if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500)) return true;
21800
22088
  if (process.platform !== "win32" && child.pid) {
21801
22089
  try {
@@ -21819,6 +22107,53 @@ var init_claude_login_auth = __esm({
21819
22107
  }
21820
22108
  });
21821
22109
 
22110
+ // server/mcp-trim.ts
22111
+ var DEFAULT_RESULT_BUDGET;
22112
+ var init_mcp_trim = __esm({
22113
+ "server/mcp-trim.ts"() {
22114
+ "use strict";
22115
+ DEFAULT_RESULT_BUDGET = 8e3;
22116
+ }
22117
+ });
22118
+
22119
+ // server/mcp-gate-config.ts
22120
+ import { join as join17 } from "node:path";
22121
+ function resultBudget(env = process.env) {
22122
+ const raw = env.OMB_MCP_RESULT_BUDGET;
22123
+ if (raw === void 0 || raw === "") return DEFAULT_RESULT_BUDGET;
22124
+ const parsed = Number(raw);
22125
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : DEFAULT_RESULT_BUDGET;
22126
+ }
22127
+ function spillDir(threadId) {
22128
+ return join17(DATA_DIR, "tool-results", threadId.replace(/[^A-Za-z0-9_-]/g, "-").slice(0, 80) || "thread");
22129
+ }
22130
+ function gateServer(input) {
22131
+ const { name, server, budget } = input;
22132
+ if (budget <= 0) return null;
22133
+ if (!server || typeof server !== "object" || Array.isArray(server)) return null;
22134
+ const spec = server;
22135
+ if (typeof spec.command !== "string" || !spec.command) return null;
22136
+ return {
22137
+ command: input.execPath ?? process.execPath,
22138
+ args: [SPAWNED_PROXIES.mcpGate],
22139
+ env: {
22140
+ ...input.nodeEnv,
22141
+ OMB_GATE_NAME: name,
22142
+ OMB_GATE_UPSTREAM: JSON.stringify({ command: spec.command, args: spec.args ?? [], env: spec.env ?? {} }),
22143
+ OMB_GATE_SPILL_DIR: spillDir(input.threadId),
22144
+ OMB_GATE_BUDGET: String(budget)
22145
+ }
22146
+ };
22147
+ }
22148
+ var init_mcp_gate_config = __esm({
22149
+ "server/mcp-gate-config.ts"() {
22150
+ "use strict";
22151
+ init_config();
22152
+ init_mcp_trim();
22153
+ init_proxy_paths();
22154
+ }
22155
+ });
22156
+
21822
22157
  // server/drivers/retry.ts
21823
22158
  function classifyError(err) {
21824
22159
  const text2 = messageOf(err);
@@ -21907,7 +22242,7 @@ import { createHash as createHash5, randomBytes as randomBytes2 } from "node:cry
21907
22242
  import { chmodSync as chmodSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, rmSync as rmSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
21908
22243
  import { createServer as createNetServer } from "node:net";
21909
22244
  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";
22245
+ import { join as join18, dirname as dirname8, isAbsolute as isAbsolute4, normalize } from "node:path";
21911
22246
  function claudeAuthStatus(cli, env, run3 = execCli) {
21912
22247
  return new Promise((resolve13) => {
21913
22248
  run3(cli, ["auth", "status", "--json"], { timeout: 8e3, maxBuffer: 65536, env }, (_error, stdout2) => {
@@ -21933,8 +22268,8 @@ function claudeAuthStatus(cli, env, run3 = execCli) {
21933
22268
  }
21934
22269
  function resolveClaudeConfigDir(configDir, env = process.env) {
21935
22270
  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;
22271
+ const configured = configDir?.trim() || env.CLAUDE_CONFIG_DIR?.trim() || join18(home, ".claude");
22272
+ const expanded = configured === "~" ? home : configured.startsWith("~/") ? join18(home, configured.slice(2)) : configured;
21938
22273
  if (!isAbsolute4(expanded) || /[\p{Cc}\p{Cf}]/u.test(expanded)) {
21939
22274
  throw new Error("claude: configDir must be an absolute path or start with ~/");
21940
22275
  }
@@ -21963,6 +22298,57 @@ function claudeEnvironment(model, source = process.env, configDir, instanceEnvir
21963
22298
  if (!applied.injected) delete env.ANTHROPIC_API_KEY;
21964
22299
  return env;
21965
22300
  }
22301
+ function inheritsUserConfig(env) {
22302
+ return env.OMB_CLAUDE_INHERIT_USER_CONFIG === "1";
22303
+ }
22304
+ function projectMcpServers(cwd) {
22305
+ let parsed;
22306
+ try {
22307
+ parsed = JSON.parse(readFileSync6(join18(cwd, ".mcp.json"), "utf8"));
22308
+ } catch {
22309
+ return {};
22310
+ }
22311
+ const servers = parsed?.mcpServers;
22312
+ if (!servers || typeof servers !== "object" || Array.isArray(servers)) return {};
22313
+ const out = {};
22314
+ for (const [name, server] of Object.entries(servers)) {
22315
+ if (server && typeof server === "object" && !Array.isArray(server)) out[name] = server;
22316
+ }
22317
+ return out;
22318
+ }
22319
+ function autoCompactWindow(env) {
22320
+ const raw = (env.OMB_CLAUDE_AUTOCOMPACT ?? "").trim().toLowerCase();
22321
+ if (raw === "off") return null;
22322
+ if (raw === "auto") return "auto";
22323
+ const parsed = raw ? Number(raw) : DEFAULT_AUTOCOMPACT_TOKENS;
22324
+ if (!Number.isFinite(parsed) || parsed <= 0) return String(DEFAULT_AUTOCOMPACT_TOKENS);
22325
+ return String(Math.min(1e6, Math.max(1e5, Math.floor(parsed))));
22326
+ }
22327
+ function parseClaudeCliVersion(stdout2) {
22328
+ const match = /(\d+)\.(\d+)\.(\d+)/.exec(stdout2 ?? "");
22329
+ if (!match) return null;
22330
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
22331
+ }
22332
+ function versionAtLeast(installed, floor) {
22333
+ for (let i2 = 0; i2 < 3; i2 += 1) {
22334
+ if (installed[i2] !== floor[i2]) return installed[i2] > floor[i2];
22335
+ }
22336
+ return true;
22337
+ }
22338
+ function claudeCliSupports(version2, flag) {
22339
+ return version2 === null || versionAtLeast(version2, CLAUDE_FLAG_FLOORS[flag]);
22340
+ }
22341
+ function claudeCliUpdate(version2, cli) {
22342
+ const parsed = parseClaudeCliVersion(version2);
22343
+ if (!parsed || versionAtLeast(parsed, CLAUDE_CONTEXT_CONTROL_MIN_VERSION)) return void 0;
22344
+ const floor = CLAUDE_CONTEXT_CONTROL_MIN_VERSION.join(".");
22345
+ const missing = Object.keys(CLAUDE_FLAG_FLOORS).filter((flag) => !claudeCliSupports(parsed, flag));
22346
+ return {
22347
+ title: "Update Claude Code for context controls",
22348
+ message: `Claude Code ${parsed.join(".")} predates ${floor}, so bots run without ${missing.join(", ")}: no compaction window picked by OpenMausBot` + (missing.includes("--setting-sources") ? ", and bots still see this machine's own Claude Code setup" : "") + ". Update it, then refresh Engines.",
22349
+ command: cli === "claude" ? "claude update" : `${cli} update`
22350
+ };
22351
+ }
21966
22352
  async function resolveClaudeTurnModel(model, env) {
21967
22353
  if (!model || decodeInjectId(model) || STATIC_CLAUDE_MODELS.options.some((option) => option.id === model)) {
21968
22354
  return model;
@@ -21986,7 +22372,7 @@ function extrasFromUnknown(value) {
21986
22372
  function readClaudeModelCatalog(env = process.env) {
21987
22373
  let settings2 = {};
21988
22374
  try {
21989
- settings2 = JSON.parse(readFileSync6(join16(resolveClaudeConfigDir(void 0, env), "settings.json"), "utf8"));
22375
+ settings2 = JSON.parse(readFileSync6(join18(resolveClaudeConfigDir(void 0, env), "settings.json"), "utf8"));
21990
22376
  } catch {
21991
22377
  return STATIC_CLAUDE_MODELS;
21992
22378
  }
@@ -22020,12 +22406,7 @@ function systemEndedReply(kind) {
22020
22406
  return kind === "question" ? { behavior: "answer", message: "OpenMausBot: the turn is ending \u2014 wrap up." } : { behavior: "deny", message: "OpenMausBot: the turn ended" };
22021
22407
  }
22022
22408
  function askSummary(ask) {
22023
- const input = ask.input ?? {};
22024
- if (typeof input.question === "string") return input.question.slice(0, 300);
22025
- if (typeof input.command === "string") return input.command.slice(0, 200);
22026
- if (typeof input.url === "string") return input.url.slice(0, 200);
22027
- const text2 = JSON.stringify(input);
22028
- return text2 === "{}" ? ask.tool ?? "tool" : text2.slice(0, 200);
22409
+ return askInputSummary(ask.input) ?? ask.tool ?? "tool";
22029
22410
  }
22030
22411
  function permissionSocketPath(threadId) {
22031
22412
  const prefix = threadId.replace(/[^\w-]/g, "").slice(0, 4);
@@ -22036,7 +22417,7 @@ function brokerSocketCandidates(threadId) {
22036
22417
  const base2 = permissionSocketPath(threadId);
22037
22418
  if (process.platform !== "win32") {
22038
22419
  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`)];
22420
+ return [base2, join18(tmpdir3(), `omb-perm-${scope}.sock`)];
22040
22421
  }
22041
22422
  return [
22042
22423
  base2,
@@ -22159,7 +22540,7 @@ async function createPermissionBroker(opts) {
22159
22540
  }
22160
22541
  if (!server) throw new Error("claude: permission broker could not bind a local socket");
22161
22542
  const drain = () => {
22162
- for (const p of [...pending.values()]) {
22543
+ for (const p of Array.from(pending.values())) {
22163
22544
  const { behavior, message: message2 } = systemEndedReply(p.ask.kind);
22164
22545
  p.finish(behavior, message2, "system");
22165
22546
  }
@@ -22234,6 +22615,17 @@ function firstText(content) {
22234
22615
  }
22235
22616
  return "";
22236
22617
  }
22618
+ function withVolatileNote(text2, volatile) {
22619
+ const body = volatile.trim() ? `This part of your instructions changed since this session started. It replaces the earlier copy:
22620
+
22621
+ ${volatile.trim()}` : "The notes that were in your instructions when this session started have been cleared.";
22622
+ const note = `<system-reminder>
22623
+ ${body}
22624
+ </system-reminder>`;
22625
+ return text2 ? `${note}
22626
+
22627
+ ${text2}` : note;
22628
+ }
22237
22629
  function claudeUserMessage(text2, images) {
22238
22630
  if (!images?.length) return { type: "user", message: { role: "user", content: text2 } };
22239
22631
  const content = images.map((image) => ({
@@ -22265,16 +22657,19 @@ function diagnosticClaudeUserMessage(message2) {
22265
22657
  }
22266
22658
  };
22267
22659
  }
22268
- var CLAUDE_ACCOUNT_ENV_KEYS, DRIVER_KIND2, STATIC_CLAUDE_MODELS, CLAUDE_MODEL_ID, PROXY_PATH, PERM_PROXY_PATH, DWEB_PROXY_PATH, NODE_ENV_FLAG, DENY_TIMEOUT_NOTE, QUESTION_TIMEOUT_NOTE, DUPLICATE_ASK_ID_NOTE, ClaudeDriver;
22660
+ var CLAUDE_ACCOUNT_ENV_KEYS, DEFAULT_AUTOCOMPACT_TOKENS, CLAUDE_FLAG_FLOORS, CLAUDE_CONTEXT_CONTROL_MIN_VERSION, DRIVER_KIND2, STATIC_CLAUDE_MODELS, CLAUDE_MODEL_ID, PROXY_PATH, PERM_PROXY_PATH, DWEB_PROXY_PATH, NODE_ENV_FLAG, DENY_TIMEOUT_NOTE, QUESTION_TIMEOUT_NOTE, DUPLICATE_ASK_ID_NOTE, ClaudeDriver;
22269
22661
  var init_claude = __esm({
22270
22662
  "server/drivers/claude.ts"() {
22271
22663
  "use strict";
22272
22664
  init_config();
22273
22665
  init_env_path();
22274
22666
  init_procs();
22667
+ init_resume_recovery();
22275
22668
  init_claude_login_auth();
22276
22669
  init_container_computer();
22670
+ init_mcp_gate_config();
22277
22671
  init_contracts();
22672
+ init_tool_summary();
22278
22673
  init_retry();
22279
22674
  init_local_inject();
22280
22675
  init_native();
@@ -22293,6 +22688,13 @@ var init_claude = __esm({
22293
22688
  "CLAUDE_CODE_USE_VERTEX",
22294
22689
  "CLAUDE_CODE_USE_FOUNDRY"
22295
22690
  ];
22691
+ DEFAULT_AUTOCOMPACT_TOKENS = 2e5;
22692
+ CLAUDE_FLAG_FLOORS = {
22693
+ "--strict-mcp-config": [1, 0, 60],
22694
+ "--setting-sources": [1, 0, 122],
22695
+ "--autocompact": [2, 1, 122]
22696
+ };
22697
+ CLAUDE_CONTEXT_CONTROL_MIN_VERSION = CLAUDE_FLAG_FLOORS["--autocompact"];
22296
22698
  DRIVER_KIND2 = "claudeAgent";
22297
22699
  STATIC_CLAUDE_MODELS = {
22298
22700
  default: "claude-sonnet-5",
@@ -22343,6 +22745,7 @@ var init_claude = __esm({
22343
22745
  }
22344
22746
  };
22345
22747
  await refreshModels();
22748
+ let cliVersion = null;
22346
22749
  const listeners = /* @__PURE__ */ new Set();
22347
22750
  const active = /* @__PURE__ */ new Map();
22348
22751
  const sessions = /* @__PURE__ */ new Map();
@@ -22393,7 +22796,7 @@ var init_claude = __esm({
22393
22796
  });
22394
22797
  };
22395
22798
  const emit = (event) => {
22396
- for (const l of [...listeners]) l(event);
22799
+ for (const l of Array.from(listeners)) l(event);
22397
22800
  };
22398
22801
  const base2 = (threadId, turnId) => ({
22399
22802
  eventId: newEventId(),
@@ -22439,6 +22842,15 @@ var init_claude = __esm({
22439
22842
  args.push("--disallowedTools", config2.disallowedTools.join(","));
22440
22843
  }
22441
22844
  const turnEnvironment = environment();
22845
+ const isolated = !inheritsUserConfig(turnEnvironment);
22846
+ if (isolated) {
22847
+ if (claudeCliSupports(cliVersion, "--strict-mcp-config")) args.push("--strict-mcp-config");
22848
+ if (claudeCliSupports(cliVersion, "--setting-sources")) args.push("--setting-sources", "project");
22849
+ }
22850
+ const compactWindow = autoCompactWindow(turnEnvironment);
22851
+ if (compactWindow && claudeCliSupports(cliVersion, "--autocompact")) {
22852
+ args.push("--autocompact", compactWindow);
22853
+ }
22442
22854
  const turnModel = await resolveClaudeTurnModel(turn.model, turnEnvironment);
22443
22855
  const injected = applyClaudeInject({ ...turnEnvironment }, turnModel);
22444
22856
  if (injected.model) args.push("--model", injected.model);
@@ -22489,9 +22901,23 @@ var init_claude = __esm({
22489
22901
  };
22490
22902
  allowed.push("mcp__dweb");
22491
22903
  }
22904
+ const botOwned = /* @__PURE__ */ new Set();
22492
22905
  for (const [name, server] of Object.entries(turn.integrations?.custom ?? {})) {
22493
22906
  if (name in mcpServers) continue;
22494
22907
  mcpServers[name] = { ...server };
22908
+ botOwned.add(name);
22909
+ }
22910
+ if (isolated && turn.cwd) {
22911
+ for (const [name, server] of Object.entries(projectMcpServers(turn.cwd))) {
22912
+ if (name in mcpServers) continue;
22913
+ mcpServers[name] = server;
22914
+ botOwned.add(name);
22915
+ }
22916
+ }
22917
+ const budget = resultBudget(turnEnvironment);
22918
+ for (const name of botOwned) {
22919
+ const gated = gateServer({ name, server: mcpServers[name], threadId, budget, nodeEnv: NODE_ENV_FLAG });
22920
+ if (gated) mcpServers[name] = gated;
22495
22921
  }
22496
22922
  let broker;
22497
22923
  const socketPath = permissionSocketPath(threadId);
@@ -22502,7 +22928,7 @@ var init_claude = __esm({
22502
22928
  allowed.push("mcp__ogb");
22503
22929
  let mcpConfigPath = null;
22504
22930
  if (Object.keys(mcpServers).length) {
22505
- mcpConfigPath = join16(mkdtempSync2(join16(tmpdir3(), "omb-mcp-")), "mcp.json");
22931
+ mcpConfigPath = join18(mkdtempSync2(join18(tmpdir3(), "omb-mcp-")), "mcp.json");
22506
22932
  args.push("--mcp-config", mcpConfigPath);
22507
22933
  args.push("--allowedTools", allowed.join(","));
22508
22934
  }
@@ -22513,7 +22939,9 @@ var init_claude = __esm({
22513
22939
  const keyArgs = args.filter((a2, i2) => !privateFileFlags.has(a2) && !privateFileFlags.has(args[i2 - 1] ?? ""));
22514
22940
  const argsKey = JSON.stringify({
22515
22941
  args: keyArgs,
22516
- system: turn.system ?? null,
22942
+ // the volatile half is deliberately absent: it must not respawn a
22943
+ // healthy session (see Session.volatile)
22944
+ system: turn.systemStable ?? turn.system ?? null,
22517
22945
  mcpServers,
22518
22946
  cwd,
22519
22947
  model: injected.model ?? null,
@@ -22529,7 +22957,10 @@ var init_claude = __esm({
22529
22957
  killCliTree(live.child);
22530
22958
  }, turnId, broker: live.broker });
22531
22959
  emit({ ...base2(threadId, turnId), type: "turn.started" });
22532
- const written = await writeUser(live, threadId, promptMsg);
22960
+ const volatile = turn.systemVolatile ?? "";
22961
+ const message2 = volatile === live.volatile ? promptMsg : claudeUserMessage(withVolatileNote(turn.text, volatile), turn.images);
22962
+ live.volatile = volatile;
22963
+ const written = await writeUser(live, threadId, message2);
22533
22964
  if (!written) {
22534
22965
  active.delete(threadId);
22535
22966
  live.turn = null;
@@ -22570,7 +23001,7 @@ var init_claude = __esm({
22570
23001
  };
22571
23002
  try {
22572
23003
  if (turn.system) {
22573
- systemPromptPath = join16(mkdtempSync2(join16(tmpdir3(), "omb-system-")), "prompt.txt");
23004
+ systemPromptPath = join18(mkdtempSync2(join18(tmpdir3(), "omb-system-")), "prompt.txt");
22574
23005
  writeFileSync5(systemPromptPath, turn.system, { mode: 384 });
22575
23006
  args.push("--append-system-prompt-file", systemPromptPath);
22576
23007
  }
@@ -22636,7 +23067,9 @@ var init_claude = __esm({
22636
23067
  mcpConfigPath,
22637
23068
  systemPromptPath,
22638
23069
  argsKey,
23070
+ volatile: turn.systemVolatile ?? "",
22639
23071
  sessionId: sessionId ?? newSessionId,
23072
+ sawInit: false,
22640
23073
  turn: { turnId, settled: false, sawStreamDelta: false },
22641
23074
  idleTimer: null,
22642
23075
  closing: false,
@@ -22676,6 +23109,7 @@ var init_claude = __esm({
22676
23109
  switch (o.type) {
22677
23110
  case "system":
22678
23111
  if (o.subtype === "init") {
23112
+ session.sawInit = true;
22679
23113
  if (typeof o.session_id === "string") session.sessionId = o.session_id;
22680
23114
  emit({ ...base2(threadId, currentTurnId()), type: "session.started", sessionId: o.session_id, model: o.model });
22681
23115
  } else if (o.subtype === "thinking_tokens") {
@@ -22712,7 +23146,14 @@ var init_claude = __esm({
22712
23146
  }
22713
23147
  for (const b of Array.isArray(msg.content) ? msg.content : []) {
22714
23148
  if (b.type === "tool_use") {
22715
- emit({ ...base2(threadId, currentTurnId()), type: "item.started", itemType: "tool", itemId: b.id, title: b.name });
23149
+ emit({
23150
+ ...base2(threadId, currentTurnId()),
23151
+ type: "item.started",
23152
+ itemType: "tool",
23153
+ itemId: b.id,
23154
+ title: b.name,
23155
+ summary: commandSummary(b.input)
23156
+ });
22716
23157
  }
22717
23158
  }
22718
23159
  if (msg.usage) {
@@ -22835,6 +23276,56 @@ var init_claude = __esm({
22835
23276
  })();
22836
23277
  return;
22837
23278
  }
23279
+ const resumeFailure = classifyResumeFailure({
23280
+ attempted: Boolean(sessionId),
23281
+ rejected: !session.sawInit,
23282
+ promptSubmitted: session.sawInit,
23283
+ producedOutput: session.turn.sawStreamDelta
23284
+ });
23285
+ if (mayReplay(resumeFailure) && !retry.cancelled) {
23286
+ const recovery = recoveryPromptFor({
23287
+ recoveryText: turn.recoveryText,
23288
+ currentText: turn.text,
23289
+ failure: resumeFailure
23290
+ });
23291
+ session.broker?.close();
23292
+ session.broker = void 0;
23293
+ if (session.mcpConfigPath) {
23294
+ try {
23295
+ rmSync2(dirname8(session.mcpConfigPath), { recursive: true, force: true });
23296
+ } catch {
23297
+ }
23298
+ session.mcpConfigPath = null;
23299
+ }
23300
+ if (session.systemPromptPath) {
23301
+ removePrivateTempDir(session.systemPromptPath);
23302
+ session.systemPromptPath = null;
23303
+ }
23304
+ sessions.delete(threadId);
23305
+ session.turn = null;
23306
+ active.delete(threadId);
23307
+ emit({
23308
+ ...base2(threadId, turnId),
23309
+ type: "turn.retrying",
23310
+ attempt: retry.attempt + 1,
23311
+ delayMs: 0,
23312
+ reason: "resume_rejected"
23313
+ });
23314
+ void (async () => {
23315
+ try {
23316
+ await sendTurn({ ...turn, resumeCursor: void 0, recoveryText: void 0, text: recovery.text });
23317
+ } catch (e) {
23318
+ retryState.delete(threadId);
23319
+ emit({
23320
+ ...base2(threadId, turnId),
23321
+ type: "runtime.error",
23322
+ message: e instanceof Error ? e.message : String(e)
23323
+ });
23324
+ emit({ ...base2(threadId, turnId), type: "turn.completed", ok: false, stopReason: "exit_before_result", cost: null });
23325
+ }
23326
+ })();
23327
+ return;
23328
+ }
22838
23329
  retryState.delete(threadId);
22839
23330
  emit({
22840
23331
  ...base2(threadId, currentTurnId()),
@@ -22887,8 +23378,10 @@ var init_claude = __esm({
22887
23378
  );
22888
23379
  });
22889
23380
  if (!version2) return { state: "unavailable", reason: `\`${config2.cli}\` CLI not found` };
23381
+ cliVersion = parseClaudeCliVersion(version2);
22890
23382
  const auth = await claudeAuthStatus(config2.cli, env);
22891
- return { state: "available", version: version2, ...auth, billing: "subscription" };
23383
+ const update = claudeCliUpdate(version2, config2.cli);
23384
+ return { state: "available", version: version2, ...auth, ...update ? { update } : {}, billing: "subscription" };
22892
23385
  };
22893
23386
  const generateReview = (prompt, signal) => new Promise((resolve13, reject) => {
22894
23387
  const child = spawnCli(
@@ -22956,6 +23449,7 @@ var init_claude = __esm({
22956
23449
  getAuthentication: (flowId) => login.get(flowId),
22957
23450
  completeAuthentication: (flowId, code) => login.complete(flowId, code),
22958
23451
  cancelAuthentication: () => login.cancel(),
23452
+ signOut: () => login.signOut(),
22959
23453
  adapter: {
22960
23454
  provider: DRIVER_KIND2,
22961
23455
  capabilities: {
@@ -22987,7 +23481,7 @@ var init_claude = __esm({
22987
23481
  hasSession: (threadId) => active.has(threadId),
22988
23482
  stopAll: async () => {
22989
23483
  for (const { stop } of active.values()) stop();
22990
- for (const threadId of [...sessions.keys()]) closeSession(threadId, "stopAll");
23484
+ for (const threadId of Array.from(sessions.keys())) closeSession(threadId, "stopAll");
22991
23485
  },
22992
23486
  onEvent: (listener) => {
22993
23487
  listeners.add(listener);
@@ -22997,9 +23491,13 @@ var init_claude = __esm({
22997
23491
  generateText: (prompt) => generateReview(prompt),
22998
23492
  reviewPermission: generateReview,
22999
23493
  dispose: async () => {
23000
- for (const { stop } of active.values()) stop();
23001
- for (const threadId of [...sessions.keys()]) closeSession(threadId, "dispose");
23002
- listeners.clear();
23494
+ try {
23495
+ await login.dispose();
23496
+ } finally {
23497
+ for (const { stop } of active.values()) stop();
23498
+ for (const threadId of Array.from(sessions.keys())) closeSession(threadId, "dispose");
23499
+ listeners.clear();
23500
+ }
23003
23501
  }
23004
23502
  };
23005
23503
  }
@@ -23010,7 +23508,7 @@ var init_claude = __esm({
23010
23508
  // server/drivers/codex-catalog.ts
23011
23509
  import { readdirSync as readdirSync2, readFileSync as readFileSync7 } from "node:fs";
23012
23510
  import { homedir as homedir10 } from "node:os";
23013
- import { basename as basename5, join as join17 } from "node:path";
23511
+ import { basename as basename5, join as join19 } from "node:path";
23014
23512
  function encodeCodexSelection(provider, model) {
23015
23513
  return `${provider}${SEP}${model}`;
23016
23514
  }
@@ -23126,7 +23624,7 @@ function readCodexAppServerModelCatalog(cli, env, timeoutMs = 8e3) {
23126
23624
  }
23127
23625
  function codexHome(env) {
23128
23626
  if (env.CODEX_HOME) return env.CODEX_HOME;
23129
- return join17(env.HOME || env.USERPROFILE || homedir10(), ".codex");
23627
+ return join19(env.HOME || env.USERPROFILE || homedir10(), ".codex");
23130
23628
  }
23131
23629
  function unquote(raw) {
23132
23630
  let value = raw.trim();
@@ -23212,11 +23710,11 @@ function niceLabel(model, provider, known, named) {
23212
23710
  }
23213
23711
  function collectCatalogNames(home) {
23214
23712
  const named = /* @__PURE__ */ new Map();
23215
- for (const file2 of listDir(join17(home, "model-catalogs"))) {
23713
+ for (const file2 of listDir(join19(home, "model-catalogs"))) {
23216
23714
  if (!file2.endsWith(".json")) continue;
23217
23715
  const provider = basename5(file2, ".json").replace(/-models$/, "");
23218
23716
  if (!PROVIDER_ID.test(provider)) continue;
23219
- const raw = readText(join17(home, "model-catalogs", file2));
23717
+ const raw = readText(join19(home, "model-catalogs", file2));
23220
23718
  if (!raw) continue;
23221
23719
  let parsed;
23222
23720
  try {
@@ -23268,7 +23766,7 @@ async function probeProviderModels(provider, env, fetchImpl) {
23268
23766
  async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli) {
23269
23767
  const official = (cli ? await readCodexAppServerModelCatalog(cli, env) : null) ?? STATIC_CODEX_MODELS;
23270
23768
  const home = codexHome(env);
23271
- const mainText = readText(join17(home, "config.toml"));
23769
+ const mainText = readText(join19(home, "config.toml"));
23272
23770
  if (!mainText) return mergeLocalInject(official, env, fetchImpl);
23273
23771
  const main2 = parseCodexToml(mainText);
23274
23772
  const known = new Map(main2.providers.map((provider) => [provider.id, provider]));
@@ -23283,7 +23781,7 @@ async function readCodexModelCatalog(env = process.env, fetchImpl = fetch, cli)
23283
23781
  remember(main2.modelProvider, main2.model);
23284
23782
  for (const file2 of listDir(home)) {
23285
23783
  if (!file2.endsWith(".config.toml")) continue;
23286
- const profile = parseCodexToml(readText(join17(home, file2)) ?? "");
23784
+ const profile = parseCodexToml(readText(join19(home, file2)) ?? "");
23287
23785
  for (const provider of profile.providers) {
23288
23786
  if (!known.has(provider.id)) known.set(provider.id, provider);
23289
23787
  }
@@ -23349,8 +23847,8 @@ var init_codex_catalog = __esm({
23349
23847
 
23350
23848
  // server/drivers/codex-instructions.ts
23351
23849
  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";
23850
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync8 } from "node:fs";
23851
+ import { join as join20 } from "node:path";
23354
23852
  function codexDeveloperInstructions(config2, botInstructions) {
23355
23853
  if (!config2 || typeof config2 !== "object" || Array.isArray(config2)) {
23356
23854
  throw new Error("Codex returned no effective configuration; cannot safely update bot instructions.");
@@ -23364,8 +23862,8 @@ function codexDeveloperInstructions(config2, botInstructions) {
23364
23862
  ${configured}` : botInstructions;
23365
23863
  }
23366
23864
  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`);
23865
+ const directory = join20(DATA_DIR, "codex-instructions");
23866
+ const path3 = join20(directory, `${digest(JSON.stringify([key, nativeThreadId]))}.sha256`);
23369
23867
  const fingerprint = digest(instructions);
23370
23868
  let previous;
23371
23869
  try {
@@ -23394,7 +23892,7 @@ async function syncCodexInstructions(key, nativeThreadId, instructions, resumed,
23394
23892
  }
23395
23893
  }
23396
23894
  if (!resumed || previous !== fingerprint) {
23397
- mkdirSync6(directory, { recursive: true });
23895
+ mkdirSync7(directory, { recursive: true });
23398
23896
  writeFileAtomic(path3, fingerprint, { mode: 384 });
23399
23897
  }
23400
23898
  }
@@ -23412,18 +23910,18 @@ var init_codex_instructions = __esm({
23412
23910
  import { randomUUID as randomUUID9 } from "node:crypto";
23413
23911
  import { realpathSync as realpathSync2 } from "node:fs";
23414
23912
  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";
23913
+ import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute5, join as join21, resolve as resolve8 } from "node:path";
23914
+ import { stripVTControlCharacters as stripVTControlCharacters5 } from "node:util";
23417
23915
  function canonicalPath2(path3) {
23418
23916
  try {
23419
23917
  return realpathSync2(path3);
23420
23918
  } catch {
23421
23919
  const parent = dirname9(path3);
23422
- return parent === path3 ? path3 : join19(canonicalPath2(parent), basename6(path3));
23920
+ return parent === path3 ? path3 : join21(canonicalPath2(parent), basename6(path3));
23423
23921
  }
23424
23922
  }
23425
23923
  function codexDevicePrompt(output) {
23426
- const clean = stripVTControlCharacters4(output);
23924
+ const clean = stripVTControlCharacters5(output);
23427
23925
  const lines = clean.split(/\r?\n/).slice(0, -1).map((line) => line.trim());
23428
23926
  if (!lines.some((line) => /^https:\/\/auth\.openai\.com\/codex\/device\/?$/.test(line))) return null;
23429
23927
  const userCode = lines.find((line) => /^[A-Z0-9]{4,8}-[A-Z0-9]{4,8}$/.test(line));
@@ -23441,13 +23939,13 @@ function loginFailure(output) {
23441
23939
  }
23442
23940
  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
23941
  }
23444
- var DEVICE_URL, MAX_OUTPUT2, authenticatingHomes2, CodexDeviceAuthController;
23942
+ var DEVICE_URL, MAX_OUTPUT3, authenticatingHomes2, CodexDeviceAuthController;
23445
23943
  var init_codex_device_auth = __esm({
23446
23944
  "server/drivers/codex-device-auth.ts"() {
23447
23945
  "use strict";
23448
23946
  init_procs();
23449
23947
  DEVICE_URL = "https://auth.openai.com/codex/device";
23450
- MAX_OUTPUT2 = 16384;
23948
+ MAX_OUTPUT3 = 16384;
23451
23949
  authenticatingHomes2 = /* @__PURE__ */ new Set();
23452
23950
  CodexDeviceAuthController = class {
23453
23951
  flow = null;
@@ -23470,7 +23968,7 @@ var init_codex_device_auth = __esm({
23470
23968
  if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
23471
23969
  throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing in.");
23472
23970
  }
23473
- const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join19(home, ".codex")));
23971
+ const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join21(home, ".codex")));
23474
23972
  if (authenticatingHomes2.has(homeKey)) {
23475
23973
  throw new Error("A ChatGPT sign-in is already running for this server account. Finish or cancel it before starting another.");
23476
23974
  }
@@ -23549,7 +24047,7 @@ var init_codex_device_auth = __esm({
23549
24047
  if (!isAbsolute5(home) || env.CODEX_HOME && !isAbsolute5(env.CODEX_HOME)) {
23550
24048
  throw new Error("Use an absolute HOME and CODEX_HOME path for this server's Codex provider before signing out.");
23551
24049
  }
23552
- const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join19(home, ".codex")));
24050
+ const homeKey = canonicalPath2(resolve8(env.CODEX_HOME || join21(home, ".codex")));
23553
24051
  if (authenticatingHomes2.has(homeKey)) {
23554
24052
  throw new Error("A ChatGPT sign-in is running for this server account. Finish or cancel it before signing out.");
23555
24053
  }
@@ -23592,7 +24090,7 @@ var init_codex_device_auth = __esm({
23592
24090
  child.stdin.end();
23593
24091
  let output = "";
23594
24092
  const receive = (chunk) => {
23595
- if (output.length < MAX_OUTPUT2) output += chunk.toString("utf8").slice(0, MAX_OUTPUT2 - output.length);
24093
+ if (output.length < MAX_OUTPUT3) output += chunk.toString("utf8").slice(0, MAX_OUTPUT3 - output.length);
23596
24094
  };
23597
24095
  child.stdout.on("data", receive);
23598
24096
  child.stderr.on("data", receive);
@@ -23609,7 +24107,7 @@ var init_codex_device_auth = __esm({
23609
24107
  child.once("close", (code) => {
23610
24108
  clearTimeout(timer);
23611
24109
  if (this.command === child) this.command = null;
23612
- resolveExec({ code, output: stripVTControlCharacters4(output) });
24110
+ resolveExec({ code, output: stripVTControlCharacters5(output) });
23613
24111
  });
23614
24112
  });
23615
24113
  }
@@ -23627,7 +24125,7 @@ var init_codex_device_auth = __esm({
23627
24125
  let output = "";
23628
24126
  const receive = (chunk) => {
23629
24127
  if (flow.status.phase !== "waiting") return;
23630
- if (output.length + chunk.length > MAX_OUTPUT2) {
24128
+ if (output.length + chunk.length > MAX_OUTPUT3) {
23631
24129
  this.finish(flow, "failed", "Codex returned an unexpected sign-in response. Update the server's Codex CLI and try again.");
23632
24130
  return;
23633
24131
  }
@@ -23648,7 +24146,7 @@ var init_codex_device_auth = __esm({
23648
24146
  });
23649
24147
  child.once("close", (code) => {
23650
24148
  if (flow.child === child) flow.child = null;
23651
- if (flow.status.phase === "waiting") done(code, stripVTControlCharacters4(output));
24149
+ if (flow.status.phase === "waiting") done(code, stripVTControlCharacters5(output));
23652
24150
  output = "";
23653
24151
  });
23654
24152
  }
@@ -23708,11 +24206,11 @@ var init_codex_device_auth = __esm({
23708
24206
 
23709
24207
  // server/drivers/codex-identity.ts
23710
24208
  import { homedir as homedir12 } from "node:os";
23711
- import { isAbsolute as isAbsolute6, join as join20, resolve as resolve9 } from "node:path";
24209
+ import { isAbsolute as isAbsolute6, join as join22, resolve as resolve9 } from "node:path";
23712
24210
  function codexHome2(env) {
23713
24211
  if (env.CODEX_HOME) return isAbsolute6(env.CODEX_HOME) ? resolve9(env.CODEX_HOME) : null;
23714
24212
  const home = env.HOME || env.USERPROFILE || homedir12();
23715
- return isAbsolute6(home) ? join20(home, ".codex") : null;
24213
+ return isAbsolute6(home) ? join22(home, ".codex") : null;
23716
24214
  }
23717
24215
  async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
23718
24216
  const cwd = env.HOME || env.USERPROFILE || homedir12();
@@ -23774,7 +24272,7 @@ async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
23774
24272
  child.stdout.on("data", (chunk) => {
23775
24273
  if (finishing) return;
23776
24274
  outputBytes += Buffer.byteLength(chunk);
23777
- if (outputBytes > MAX_OUTPUT3) {
24275
+ if (outputBytes > MAX_OUTPUT4) {
23778
24276
  void finish(null);
23779
24277
  return;
23780
24278
  }
@@ -23809,18 +24307,18 @@ async function codexAccountEmail(cli, env, timeoutMs = 3e3) {
23809
24307
  send({ id: 1, method: "initialize", params: { clientInfo: { name: "openmausbot", version: "1" } } });
23810
24308
  });
23811
24309
  }
23812
- var MAX_OUTPUT3, EMAIL;
24310
+ var MAX_OUTPUT4, EMAIL;
23813
24311
  var init_codex_identity = __esm({
23814
24312
  "server/drivers/codex-identity.ts"() {
23815
24313
  "use strict";
23816
24314
  init_procs();
23817
- MAX_OUTPUT3 = 16384;
24315
+ MAX_OUTPUT4 = 16384;
23818
24316
  EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
23819
24317
  }
23820
24318
  });
23821
24319
 
23822
24320
  // server/drivers/codex.ts
23823
- import { existsSync as existsSync7 } from "node:fs";
24321
+ import { existsSync as existsSync8 } from "node:fs";
23824
24322
  import { homedir as homedir13 } from "node:os";
23825
24323
  function codexPredatesAstra(version2) {
23826
24324
  const value = version2.trim();
@@ -23837,7 +24335,7 @@ function codexPredatesAstra(version2) {
23837
24335
  function codexUpdateCommand(cli, platform = process.platform) {
23838
24336
  if (cli === "codex") return "codex update";
23839
24337
  const trimmed = cli.trim();
23840
- const tokens = trimmed.includes(" ") && existsSync7(trimmed) ? [trimmed] : splitCliString(trimmed);
24338
+ const tokens = trimmed.includes(" ") && existsSync8(trimmed) ? [trimmed] : splitCliString(trimmed);
23841
24339
  const quote = platform === "win32" ? (token) => `'${token.replaceAll("'", "''")}'` : (token) => `'${token.replaceAll("'", `'\\''`)}'`;
23842
24340
  const command = (tokens.length > 0 ? tokens : [trimmed]).map(quote).join(" ");
23843
24341
  return platform === "win32" ? `& ${command} update` : `${command} update`;
@@ -24089,6 +24587,7 @@ var init_codex = __esm({
24089
24587
  init_env_path();
24090
24588
  init_retry();
24091
24589
  init_native();
24590
+ init_tool_summary();
24092
24591
  init_codex_instructions();
24093
24592
  init_codex_device_auth();
24094
24593
  init_codex_identity();
@@ -24153,7 +24652,7 @@ var init_codex = __esm({
24153
24652
  const listeners = /* @__PURE__ */ new Set();
24154
24653
  const active = /* @__PURE__ */ new Map();
24155
24654
  const emit = (event) => {
24156
- for (const l of [...listeners]) l(event);
24655
+ for (const l of Array.from(listeners)) l(event);
24157
24656
  };
24158
24657
  const base2 = (threadId, turnId) => ({
24159
24658
  eventId: newEventId(),
@@ -24281,7 +24780,7 @@ var init_codex = __esm({
24281
24780
  const settle = async (ok, stopReason) => {
24282
24781
  if (state.settled) return;
24283
24782
  state.settled = true;
24284
- for (const finish of [...asks.values()]) finish("deny", "OpenMausBot: the turn ended", "system");
24783
+ for (const finish of Array.from(asks.values())) finish("deny", "OpenMausBot: the turn ended", "system");
24285
24784
  for (const p of rpcPending.values()) p.reject(new Error("turn settled"));
24286
24785
  rpcPending.clear();
24287
24786
  const complete = () => {
@@ -24392,7 +24891,16 @@ var init_codex = __esm({
24392
24891
  case "item/started": {
24393
24892
  const item = p.item ?? {};
24394
24893
  const title = item.type === "commandExecution" ? String(item.command ?? "shell") : item.type === "fileChange" ? "edit" : item.type === "mcpToolCall" ? item.tool ?? item.name ?? "mcp" : item.type === "webSearch" ? "web_search" : null;
24395
- if (title) emit({ ...base2(threadId, turnId), type: "item.started", itemType: "tool", itemId: item.id, title });
24894
+ if (title) {
24895
+ emit({
24896
+ ...base2(threadId, turnId),
24897
+ type: "item.started",
24898
+ itemType: "tool",
24899
+ itemId: item.id,
24900
+ title,
24901
+ summary: item.type === "commandExecution" ? commandSummary({ command: item.command }) : void 0
24902
+ });
24903
+ }
24396
24904
  break;
24397
24905
  }
24398
24906
  case "item/completed": {
@@ -25035,12 +25543,12 @@ var init_grok = __esm({
25035
25543
  });
25036
25544
 
25037
25545
  // server/drivers/acp/grok.ts
25038
- import { existsSync as existsSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
25546
+ import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
25039
25547
  import { homedir as homedir14 } from "node:os";
25040
- import { join as join21 } from "node:path";
25548
+ import { join as join23 } from "node:path";
25041
25549
  function grokHome(env) {
25042
25550
  if (env.GROK_HOME) return env.GROK_HOME;
25043
- return join21(env.HOME || env.USERPROFILE || homedir14(), ".grok");
25551
+ return join23(env.HOME || env.USERPROFILE || homedir14(), ".grok");
25044
25552
  }
25045
25553
  function unquote2(raw) {
25046
25554
  const value = raw.trim();
@@ -25050,7 +25558,7 @@ function unquote2(raw) {
25050
25558
  return value;
25051
25559
  }
25052
25560
  function readGrokModelCatalog(env = process.env) {
25053
- const path3 = join21(grokHome(env), "config.toml");
25561
+ const path3 = join23(grokHome(env), "config.toml");
25054
25562
  let text2 = "";
25055
25563
  try {
25056
25564
  text2 = readFileSync9(path3, "utf8");
@@ -25123,7 +25631,7 @@ function ensureGrokInjectSlug(modelId, env = process.env) {
25123
25631
  if (!inject) return modelId;
25124
25632
  const host = localHost(inject.host);
25125
25633
  if (!host) return modelId;
25126
- const path3 = join21(grokHome(env), "config.toml");
25634
+ const path3 = join23(grokHome(env), "config.toml");
25127
25635
  let text2 = "";
25128
25636
  try {
25129
25637
  text2 = readFileSync9(path3, "utf8");
@@ -25227,9 +25735,13 @@ var init_grok2 = __esm({
25227
25735
  // and BEFORE `stdio` (`grok agent -m slug stdio`). Putting -m first is
25228
25736
  // accepted as a TUI option and then ignored, so ACP session/new keeps
25229
25737
  // [models].default (grok-4.6) and oMLX never sees a request.
25738
+ // Auto selects Grok's native classifier; if its feature gate is disabled,
25739
+ // residual requests still ask. Never replace it with bypassPermissions.
25740
+ // Verified: grok 1.0.3 --help and xai-org/grok-build@37949780,
25741
+ // crates/codegen/xai-grok-pager-bin/src/main.rs:1259-1273.
25230
25742
  spawnArgs: (config2, turn) => [
25231
25743
  "--permission-mode",
25232
- config2.fullAuto ? "bypassPermissions" : "default",
25744
+ config2.fullAuto ? "bypassPermissions" : turn.approvalMode === "auto" ? "auto" : "default",
25233
25745
  "agent",
25234
25746
  ...turn.model ? ["-m", turn.model] : [],
25235
25747
  // long form on purpose: `--effort` is documented as an alias, and an
@@ -25258,7 +25770,7 @@ var init_grok2 = __esm({
25258
25770
  // an unauthenticated CLI is a user action, not something to paper over.
25259
25771
  pickAuthMethod: (methods) => methods.some((m) => m.id === "cached_token") ? "cached_token" : null,
25260
25772
  authFailure: "fail",
25261
- isAuthenticated: () => existsSync8(join21(homedir14(), ".grok", "auth.json")),
25773
+ isAuthenticated: () => existsSync9(join23(homedir14(), ".grok", "auth.json")),
25262
25774
  // `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
25263
25775
  // reach the agent-stdio system prompt (verified against 1.0.0), so the
25264
25776
  // persona is prepended codex-style.
@@ -25271,12 +25783,12 @@ ${turn.text}` : turn.text
25271
25783
  });
25272
25784
 
25273
25785
  // server/drivers/acp/gemini.ts
25274
- import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
25786
+ import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
25275
25787
  import { homedir as homedir15 } from "node:os";
25276
- import { join as join22 } from "node:path";
25788
+ import { join as join24 } from "node:path";
25277
25789
  function liveOauthCredential() {
25278
25790
  try {
25279
- const creds = JSON.parse(readFileSync10(join22(homedir15(), ".gemini", "oauth_creds.json"), "utf8"));
25791
+ const creds = JSON.parse(readFileSync10(join24(homedir15(), ".gemini", "oauth_creds.json"), "utf8"));
25280
25792
  if (typeof creds.access_token !== "string" || creds.access_token.trim().length === 0) return false;
25281
25793
  const hasRefresh = typeof creds.refresh_token === "string" && creds.refresh_token.trim().length > 0;
25282
25794
  if (creds.expiry_date !== void 0) {
@@ -25289,7 +25801,7 @@ function liveOauthCredential() {
25289
25801
  }
25290
25802
  }
25291
25803
  function geminiIsAuthenticated(env) {
25292
- return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync9(join22(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
25804
+ return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync10(join24(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
25293
25805
  }
25294
25806
  var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
25295
25807
  var init_gemini = __esm({
@@ -25331,17 +25843,17 @@ ${turn.text}` : turn.text
25331
25843
  });
25332
25844
 
25333
25845
  // server/drivers/acp/kimi.ts
25334
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
25846
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
25335
25847
  import { homedir as homedir16 } from "node:os";
25336
- import { join as join23 } from "node:path";
25848
+ import { join as join25 } from "node:path";
25337
25849
  function isLocalInjectAlias(slug) {
25338
25850
  return LOCAL_PROVIDER_PREFIXES.some((prefix) => slug.startsWith(prefix));
25339
25851
  }
25340
25852
  function kimiDataRoot(env) {
25341
- return env.KIMI_CODE_HOME || join23(env.HOME || env.USERPROFILE || homedir16(), ".kimi-code");
25853
+ return env.KIMI_CODE_HOME || join25(env.HOME || env.USERPROFILE || homedir16(), ".kimi-code");
25342
25854
  }
25343
25855
  function credentialsPath(env) {
25344
- return join23(kimiDataRoot(env), "credentials", "kimi-code.json");
25856
+ return join25(kimiDataRoot(env), "credentials", "kimi-code.json");
25345
25857
  }
25346
25858
  function quoteToml2(value) {
25347
25859
  return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
@@ -25628,8 +26140,8 @@ function ensureKimiInjectAlias(modelId, env = process.env) {
25628
26140
  if (!host) return modelId;
25629
26141
  const alias = `${inject.host}/${inject.model.replace(/\//g, "-")}`;
25630
26142
  const dataRoot = kimiDataRoot(env);
25631
- mkdirSync7(dataRoot, { recursive: true });
25632
- const path3 = join23(dataRoot, "config.toml");
26143
+ mkdirSync8(dataRoot, { recursive: true });
26144
+ const path3 = join25(dataRoot, "config.toml");
25633
26145
  let text2 = "";
25634
26146
  try {
25635
26147
  text2 = readFileSync11(path3, "utf8");
@@ -25694,7 +26206,7 @@ function readKimiModelCatalog(env) {
25694
26206
  const dataRoot = kimiDataRoot(env);
25695
26207
  let text2 = "";
25696
26208
  try {
25697
- text2 = readFileSync11(join23(dataRoot, "config.toml"), "utf8");
26209
+ text2 = readFileSync11(join25(dataRoot, "config.toml"), "utf8");
25698
26210
  } catch {
25699
26211
  return STATIC_KIMI_MODELS;
25700
26212
  }
@@ -25803,7 +26315,7 @@ var init_kimi = __esm({
25803
26315
  authFailure: "continue",
25804
26316
  // Match the child CLI's own data-root precedence. A custom instance HOME or
25805
26317
  // KIMI_CODE_HOME must not be checked against the server user's home instead.
25806
- isAuthenticated: (env) => existsSync10(credentialsPath(env)),
26318
+ isAuthenticated: (env) => existsSync11(credentialsPath(env)),
25807
26319
  buildPromptText: (turn) => turn.system ? `${turn.system}
25808
26320
 
25809
26321
  ${turn.text}` : turn.text
@@ -25813,12 +26325,12 @@ ${turn.text}` : turn.text
25813
26325
  });
25814
26326
 
25815
26327
  // server/drivers/acp/droid.ts
25816
- import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
26328
+ import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
25817
26329
  import { homedir as homedir17 } from "node:os";
25818
- import { join as join24 } from "node:path";
26330
+ import { join as join26 } from "node:path";
25819
26331
  function authFilePaths(env) {
25820
26332
  const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir17();
25821
- return AUTH_FILES.map((name) => join24(home, ".factory", name));
26333
+ return AUTH_FILES.map((name) => join26(home, ".factory", name));
25822
26334
  }
25823
26335
  function droidInjectId(host, model) {
25824
26336
  const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
@@ -25833,14 +26345,14 @@ function ensureDroidInjectModel(modelId, env = process.env) {
25833
26345
  const host = localHost(inject.host);
25834
26346
  if (!host) return modelId;
25835
26347
  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");
26348
+ const dir = join26(factoryHome(env), ".factory");
26349
+ mkdirSync9(dir, { recursive: true });
26350
+ const path3 = join26(dir, "settings.json");
25839
26351
  let settings2 = {};
25840
26352
  try {
25841
26353
  settings2 = JSON.parse(readFileSync12(path3, "utf8"));
25842
26354
  } catch (error51) {
25843
- if (existsSync11(path3)) throw error51;
26355
+ if (existsSync12(path3)) throw error51;
25844
26356
  }
25845
26357
  const custom2 = Array.isArray(settings2.customModels) ? [...settings2.customModels] : [];
25846
26358
  const match = custom2.find(
@@ -25871,11 +26383,11 @@ function ensureDroidInjectModel(modelId, env = process.env) {
25871
26383
  function applyDroidLocalAuthEnv(env, modelId) {
25872
26384
  if (!decodeInjectId(modelId)) return;
25873
26385
  if (env.FACTORY_API_KEY?.trim()) return;
25874
- if (authFilePaths(env).some(existsSync11)) return;
26386
+ if (authFilePaths(env).some(existsSync12)) return;
25875
26387
  env.FACTORY_API_KEY = "openmausbot-local";
25876
26388
  }
25877
26389
  function readSettings(env) {
25878
- return JSON.parse(readFileSync12(join24(factoryHome(env), ".factory", "settings.json"), "utf8"));
26390
+ return JSON.parse(readFileSync12(join26(factoryHome(env), ".factory", "settings.json"), "utf8"));
25879
26391
  }
25880
26392
  async function resolveModels(env) {
25881
26393
  let catalog = MODELS3;
@@ -25962,7 +26474,7 @@ var init_droid = __esm({
25962
26474
  // The signed-in CLI is the primary source; FACTORY_API_KEY is the fallback
25963
26475
  // droid itself advertises, and it is checked last so an ambient key can
25964
26476
  // never be what makes an otherwise logged-out instance look ready.
25965
- isAuthenticated: (env) => authFilePaths(env).some(existsSync11) || Boolean(env.FACTORY_API_KEY),
26477
+ isAuthenticated: (env) => authFilePaths(env).some(existsSync12) || Boolean(env.FACTORY_API_KEY),
25966
26478
  resolveModels,
25967
26479
  resolveTurnModel: (model, env) => model ? ensureDroidInjectModel(model, env) : model,
25968
26480
  applyTurnEnv: (env, { requestedModel }) => {
@@ -26086,7 +26598,7 @@ function decodeCursorModelText(text2) {
26086
26598
  for (const raw of text2.split(/\r?\n/)) {
26087
26599
  const line = raw.trim();
26088
26600
  if (!line || line.startsWith("#") || /^available\s+models?\b/i.test(line) || /^models?\b/i.test(line)) continue;
26089
- const stripped = line.replace(/^[\s*•\-]+\s*/, "");
26601
+ const stripped = line.replace(/^[\s*•-]+\s*/, "");
26090
26602
  const parts = stripped.split(/\s+[—–|:]\s+|\s+-\s+|\s{2,}/);
26091
26603
  const id = (parts[0] ?? "").trim();
26092
26604
  const rawLabel = parts.slice(1).join(" ").trim();
@@ -26265,9 +26777,9 @@ ${turn.text}` : turn.text
26265
26777
  });
26266
26778
 
26267
26779
  // server/drivers/acp/opencode-go.ts
26268
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
26780
+ import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
26269
26781
  import { homedir as homedir18 } from "node:os";
26270
- import { join as join25 } from "node:path";
26782
+ import { join as join27 } from "node:path";
26271
26783
  function labelForModel(id) {
26272
26784
  return id.split(/[-_.]+/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
26273
26785
  }
@@ -26368,7 +26880,7 @@ async function discoverOpenCodeModels(environment, cli = "opencode") {
26368
26880
  }
26369
26881
  function opencodeConfigDir(env) {
26370
26882
  const home = env.HOME || env.USERPROFILE || homedir18();
26371
- return join25(env.XDG_CONFIG_HOME || join25(home, ".config"), "opencode");
26883
+ return join27(env.XDG_CONFIG_HOME || join27(home, ".config"), "opencode");
26372
26884
  }
26373
26885
  function ensureOpenCodeInjectModel(modelId, env = process.env) {
26374
26886
  const inject = decodeInjectId(modelId);
@@ -26377,10 +26889,10 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
26377
26889
  if (!host) return modelId;
26378
26890
  const native = `${inject.host}/${inject.model}`;
26379
26891
  const dir = opencodeConfigDir(env);
26380
- mkdirSync9(dir, { recursive: true });
26381
- const path3 = join25(dir, "opencode.json");
26892
+ mkdirSync10(dir, { recursive: true });
26893
+ const path3 = join27(dir, "opencode.json");
26382
26894
  let config2 = { $schema: "https://opencode.ai/config.json" };
26383
- if (existsSync12(path3)) {
26895
+ if (existsSync13(path3)) {
26384
26896
  try {
26385
26897
  config2 = JSON.parse(readFileSync13(path3, "utf8"));
26386
26898
  } catch {
@@ -26416,10 +26928,10 @@ function ensureOpenCodeInjectModel(modelId, env = process.env) {
26416
26928
  function storedAuthPaths(env) {
26417
26929
  const home = env.HOME || env.USERPROFILE || homedir18();
26418
26930
  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") : ""
26931
+ env.XDG_DATA_HOME || join27(home, ".local", "share"),
26932
+ process.platform === "darwin" ? join27(home, "Library", "Application Support") : process.platform === "win32" ? env.LOCALAPPDATA || join27(home, "AppData", "Local") : ""
26421
26933
  ].filter(Boolean);
26422
- return [...new Set(roots)].map((root) => join25(root, "opencode", "auth.json"));
26934
+ return [...new Set(roots)].map((root) => join27(root, "opencode", "auth.json"));
26423
26935
  }
26424
26936
  function usableAuthEntry(parsed) {
26425
26937
  return Object.values(parsed).some((auth) => {
@@ -26549,13 +27061,13 @@ ${turn.text}` : turn.text
26549
27061
  });
26550
27062
 
26551
27063
  // 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";
27064
+ import { chmodSync as chmodSync4, existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
26553
27065
  import { createHash as createHash7 } from "node:crypto";
26554
27066
  import { homedir as homedir19 } from "node:os";
26555
- import { join as join26 } from "node:path";
27067
+ import { join as join28 } from "node:path";
26556
27068
  function qwenHome(env) {
26557
27069
  const home = process.platform === "win32" ? env.USERPROFILE || env.HOME || homedir19() : env.HOME || env.USERPROFILE || homedir19();
26558
- return join26(home, ".qwen");
27070
+ return join28(home, ".qwen");
26559
27071
  }
26560
27072
  function isRecord(value) {
26561
27073
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -26567,7 +27079,7 @@ function qwenModelLabel(id, name) {
26567
27079
  function readQwenRoutes(env) {
26568
27080
  let settings2;
26569
27081
  try {
26570
- settings2 = JSON.parse(readFileSync14(join26(qwenHome(env), "settings.json"), "utf8"));
27082
+ settings2 = JSON.parse(readFileSync14(join28(qwenHome(env), "settings.json"), "utf8"));
26571
27083
  } catch {
26572
27084
  return [];
26573
27085
  }
@@ -26650,10 +27162,10 @@ function ensureQwenInjectModel(modelId, env = process.env) {
26650
27162
  const host = localHost(inject.host);
26651
27163
  if (!host) return modelId;
26652
27164
  const dir = qwenHome(env);
26653
- mkdirSync10(dir, { recursive: true });
26654
- const path3 = join26(dir, "settings.json");
27165
+ mkdirSync11(dir, { recursive: true });
27166
+ const path3 = join28(dir, "settings.json");
26655
27167
  let settings2 = {};
26656
- if (existsSync13(path3)) {
27168
+ if (existsSync14(path3)) {
26657
27169
  try {
26658
27170
  settings2 = JSON.parse(readFileSync14(path3, "utf8"));
26659
27171
  } catch {
@@ -33650,9 +34162,9 @@ var init_browser = __esm({
33650
34162
 
33651
34163
  // server/drivers/acp/hermes.ts
33652
34164
  import { spawn as spawn5 } from "node:child_process";
33653
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
34165
+ import { mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
33654
34166
  import { homedir as homedir20 } from "node:os";
33655
- import { join as join27 } from "node:path";
34167
+ import { join as join29 } from "node:path";
33656
34168
  function bindHermesScreenshotCompat(env, modelId) {
33657
34169
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT];
33658
34170
  delete env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL];
@@ -33662,7 +34174,7 @@ function bindHermesScreenshotCompat(env, modelId) {
33662
34174
  env[HERMES_OPENMAUS_SCREENSHOT_COMPAT_MODEL] = inject.model;
33663
34175
  }
33664
34176
  function hermesHome(env) {
33665
- return env.HERMES_HOME || join27(env.HOME || env.USERPROFILE || homedir20(), ".hermes");
34177
+ return env.HERMES_HOME || join29(env.HOME || env.USERPROFILE || homedir20(), ".hermes");
33666
34178
  }
33667
34179
  function quoteYaml(value) {
33668
34180
  if (/^[\w./:+-]+$/.test(value)) return value;
@@ -33703,8 +34215,8 @@ function ensureHermesInjectProvider(modelId, env = process.env) {
33703
34215
  const host = localHost(inject.host);
33704
34216
  if (!host) return modelId;
33705
34217
  const dir = hermesHome(env);
33706
- mkdirSync11(dir, { recursive: true });
33707
- const path3 = join27(dir, "config.yaml");
34218
+ mkdirSync12(dir, { recursive: true });
34219
+ const path3 = join29(dir, "config.yaml");
33708
34220
  let text2 = "";
33709
34221
  try {
33710
34222
  text2 = readFileSync15(path3, "utf8");
@@ -33775,13 +34287,13 @@ function hermesConfiguredModel(env = process.env) {
33775
34287
  const dir = hermesHome(env);
33776
34288
  let secrets = "";
33777
34289
  try {
33778
- secrets = readFileSync15(join27(dir, ".env"), "utf8");
34290
+ secrets = readFileSync15(join29(dir, ".env"), "utf8");
33779
34291
  } catch {
33780
34292
  }
33781
34293
  const hasHostedProviderKey = HERMES_HOSTED_PROVIDER_KEYS.some((name) => nonEmptyDotenvValue(secrets, name));
33782
34294
  let configuredDefault = null;
33783
34295
  try {
33784
- configuredDefault = hermesConfigDefault(readFileSync15(join27(dir, "config.yaml"), "utf8"));
34296
+ configuredDefault = hermesConfigDefault(readFileSync15(join29(dir, "config.yaml"), "utf8"));
33785
34297
  } catch {
33786
34298
  }
33787
34299
  const configuredProvider = configuredDefault?.provider.toLowerCase() ?? "";
@@ -34101,9 +34613,9 @@ var init_openai_compat = __esm({
34101
34613
  });
34102
34614
 
34103
34615
  // 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";
34616
+ 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
34617
  import { homedir as homedir21, tmpdir as tmpdir4 } from "node:os";
34106
- import { join as join28 } from "node:path";
34618
+ import { join as join30 } from "node:path";
34107
34619
  function readPiPromptImages(turn) {
34108
34620
  return (turn.images ?? []).map((image) => ({
34109
34621
  type: "image",
@@ -34210,7 +34722,7 @@ async function applyPiLocalCatalog(catalog, env = process.env, fetchImpl = fetch
34210
34722
  return preferPiInjectRows(await mergeLocalInject(catalog, env, fetchImpl));
34211
34723
  }
34212
34724
  function piAgentDir(env) {
34213
- return join28(env.HOME || env.USERPROFILE || homedir21(), ".pi", "agent");
34725
+ return join30(env.HOME || env.USERPROFILE || homedir21(), ".pi", "agent");
34214
34726
  }
34215
34727
  function ensurePiInjectModel(modelId, env = process.env) {
34216
34728
  const split = splitPiModel(modelId);
@@ -34220,10 +34732,10 @@ function ensurePiInjectModel(modelId, env = process.env) {
34220
34732
  const host = localHost(inject.host);
34221
34733
  if (!host) return split;
34222
34734
  const dir = piAgentDir(env);
34223
- mkdirSync12(dir, { recursive: true });
34224
- const path3 = join28(dir, "models.json");
34735
+ mkdirSync13(dir, { recursive: true });
34736
+ const path3 = join30(dir, "models.json");
34225
34737
  let root = { providers: {} };
34226
- if (existsSync14(path3)) {
34738
+ if (existsSync15(path3)) {
34227
34739
  try {
34228
34740
  const parsed = JSON.parse(readFileSync16(path3, "utf8"));
34229
34741
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
@@ -34395,7 +34907,7 @@ var init_pi = __esm({
34395
34907
  const listeners = /* @__PURE__ */ new Set();
34396
34908
  const active = /* @__PURE__ */ new Map();
34397
34909
  const emit = (event) => {
34398
- for (const l of [...listeners]) l(event);
34910
+ for (const l of Array.from(listeners)) l(event);
34399
34911
  };
34400
34912
  const base2 = (threadId, turnId) => ({
34401
34913
  eventId: newEventId(),
@@ -34423,9 +34935,9 @@ var init_pi = __esm({
34423
34935
  const mcpServers = buildMcpServers(turn);
34424
34936
  let mcpTempDir = null;
34425
34937
  if (mcpServers) {
34426
- mcpTempDir = mkdtempSync3(join28(tmpdir4(), "omb-pi-mcp-"));
34938
+ mcpTempDir = mkdtempSync3(join30(tmpdir4(), "omb-pi-mcp-"));
34427
34939
  try {
34428
- writeFileSync12(join28(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
34940
+ writeFileSync12(join30(mcpTempDir, "mcp.json"), JSON.stringify({ mcpServers }), { mode: 384 });
34429
34941
  } catch (err) {
34430
34942
  try {
34431
34943
  rmSync3(mcpTempDir, { recursive: true, force: true });
@@ -34443,7 +34955,7 @@ var init_pi = __esm({
34443
34955
  env: piEnvironment({
34444
34956
  ...process.env,
34445
34957
  ...input.environment,
34446
- ...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join28(mcpTempDir, "mcp.json") } : {}
34958
+ ...mcpServers && mcpTempDir ? { OMB_MCP_CONFIG: join30(mcpTempDir, "mcp.json") } : {}
34447
34959
  })
34448
34960
  });
34449
34961
  } catch (err) {
@@ -34782,14 +35294,14 @@ ${turn.text}` : turn.text;
34782
35294
  // server/drivers/minimax.ts
34783
35295
  import { readFileSync as readFileSync17 } from "node:fs";
34784
35296
  import { homedir as homedir22 } from "node:os";
34785
- import { join as join29 } from "node:path";
35297
+ import { join as join31 } from "node:path";
34786
35298
  function normalizedApiUrl(value) {
34787
35299
  const root = value.trim().replace(/\/+$/, "");
34788
35300
  return root.endsWith("/v1") ? root : `${root}/v1`;
34789
35301
  }
34790
35302
  function loadLocalMiniMaxConfig(home = homedir22()) {
34791
35303
  try {
34792
- const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join29(home, ".mmx", "config.json"), "utf8")));
35304
+ const raw = localConfigSchema.parse(JSON.parse(readFileSync17(join31(home, ".mmx", "config.json"), "utf8")));
34793
35305
  const configuredUrl = raw.base_url?.trim() ? raw.base_url : raw.region === "cn" ? CN_URL : DEFAULT_URL2;
34794
35306
  return {
34795
35307
  apiKey: raw.api_key?.trim() ?? "",
@@ -35057,7 +35569,7 @@ __export(cli_setup_exports, {
35057
35569
  });
35058
35570
  import { spawn as spawn6 } from "node:child_process";
35059
35571
  import { readFileSync as readFileSync18 } from "node:fs";
35060
- import { join as join30, resolve as resolve10 } from "node:path";
35572
+ import { join as join32, resolve as resolve10 } from "node:path";
35061
35573
  import { randomUUID as randomUUID10 } from "node:crypto";
35062
35574
  async function inspect(id, entry) {
35063
35575
  const registry2 = new ProviderRegistry(BUILT_IN_DRIVERS);
@@ -35094,7 +35606,7 @@ function assertDataDir(dataDir) {
35094
35606
  }
35095
35607
  function checkStoredConfig(dataDir) {
35096
35608
  try {
35097
- parseStoredConfig(JSON.parse(readFileSync18(join30(dataDir, "config.json"), "utf8")));
35609
+ parseStoredConfig(JSON.parse(readFileSync18(join32(dataDir, "config.json"), "utf8")));
35098
35610
  } catch (error51) {
35099
35611
  if (error51.code === "ENOENT") return;
35100
35612
  throw new Error("Existing config.json could not be read or validated. Setup has not changed it; repair it before continuing.");
@@ -35372,7 +35884,7 @@ var init_browser_engine_release = __esm({
35372
35884
  });
35373
35885
 
35374
35886
  // server/browser-bundle-release.ts
35375
- import { join as join31 } from "node:path";
35887
+ import { join as join33 } from "node:path";
35376
35888
  function browserBundleSpec(target) {
35377
35889
  if (!Object.hasOwn(CHROME_ASSETS, target)) throw new Error(`Unsupported desktop browser target: ${target}`);
35378
35890
  const pinned = CHROME_ASSETS[target];
@@ -35408,10 +35920,10 @@ function browserBundlePaths(bundleDirectory, target) {
35408
35920
  const spec = browserBundleSpec(target);
35409
35921
  return {
35410
35922
  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")
35923
+ manifest: join33(bundleDirectory, "manifest.json"),
35924
+ engine: join33(bundleDirectory, spec.engine.executable),
35925
+ chrome: join33(bundleDirectory, spec.chrome.executable),
35926
+ licenses: join33(bundleDirectory, "licenses")
35415
35927
  };
35416
35928
  }
35417
35929
  var CHROME_VERSION, CHROME_ASSETS;
@@ -35466,9 +35978,9 @@ __export(browser_engine_exports, {
35466
35978
  });
35467
35979
  import { spawn as spawn7 } from "node:child_process";
35468
35980
  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";
35981
+ 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
35982
  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";
35983
+ import { delimiter as delimiter6, dirname as dirname10, join as join34, resolve as resolve11 } from "node:path";
35472
35984
  function browserRestoreKey(session) {
35473
35985
  if (!/^[A-Za-z0-9_-]{1,96}$/.test(session)) throw new Error("Invalid browser session.");
35474
35986
  return `omb-${createHash8("sha256").update(session).digest("hex")}`;
@@ -35477,15 +35989,15 @@ function browserSessionsDirectory(env) {
35477
35989
  const namespace = env.AGENT_BROWSER_NAMESPACE;
35478
35990
  if (namespace && !/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/.test(namespace)) throw new Error("Invalid browser namespace.");
35479
35991
  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");
35992
+ const stateRoot = namespace ? join34(home, ".agent-browser", "namespaces", namespace, "state") : join34(home, ".agent-browser");
35993
+ return join34(stateRoot, "sessions");
35482
35994
  }
35483
35995
  function managedBrowserConfigPath(env) {
35484
- return join32(browserSessionsDirectory(env), "..", "omb-managed-config.json");
35996
+ return join34(browserSessionsDirectory(env), "..", "omb-managed-config.json");
35485
35997
  }
35486
35998
  function ensureManagedBrowserConfig(env) {
35487
35999
  const path3 = managedBrowserConfigPath(env);
35488
- mkdirSync13(dirname10(path3), { recursive: true, mode: 448 });
36000
+ mkdirSync14(dirname10(path3), { recursive: true, mode: 448 });
35489
36001
  try {
35490
36002
  writeFileSync13(path3, "{}\n", { flag: "wx", mode: 384 });
35491
36003
  } catch (error51) {
@@ -35568,12 +36080,12 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
35568
36080
  ensureManagedBrowserConfig(env);
35569
36081
  if (options.persistent === false) return;
35570
36082
  const directory = browserSessionsDirectory(env);
35571
- const key = join32(directory, session);
36083
+ const key = join34(directory, session);
35572
36084
  let pending = preparedBrowserSessions.get(key);
35573
36085
  if (!pending) {
35574
36086
  pending = (async () => {
35575
- const targetBase = join32(directory, `${restoreKey}-${session}`);
35576
- const hasTarget = () => existsSync15(`${targetBase}.json.enc`) || existsSync15(`${targetBase}.json`);
36087
+ const targetBase = join34(directory, `${restoreKey}-${session}`);
36088
+ const hasTarget = () => existsSync16(`${targetBase}.json.enc`) || existsSync16(`${targetBase}.json`);
35577
36089
  if (hasTarget()) return;
35578
36090
  check2();
35579
36091
  if (!await closeBrowserSession(binaryPath, { ...env, AGENT_BROWSER_RESTORE: session }, options.timeoutMs)) {
@@ -35582,7 +36094,7 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
35582
36094
  check2();
35583
36095
  if (hasTarget()) return;
35584
36096
  const candidates = [".json.enc", ".json"].flatMap((suffix) => {
35585
- const path3 = join32(directory, `${session}-${session}${suffix}`);
36097
+ const path3 = join34(directory, `${session}-${session}${suffix}`);
35586
36098
  try {
35587
36099
  const stat4 = statSync3(path3);
35588
36100
  if (!stat4.isFile()) throw new Error("Saved browser state is not a file.");
@@ -35612,12 +36124,12 @@ async function prepareBrowserSessionState(binaryPath, session, options = {}) {
35612
36124
  function executableName(platform = process.platform) {
35613
36125
  return platform === "win32" ? "agent-browser.exe" : "agent-browser";
35614
36126
  }
35615
- function isMusl(platform = process.platform, exists = existsSync15) {
36127
+ function isMusl(platform = process.platform, exists = existsSync16) {
35616
36128
  return platform === "linux" && (exists("/lib/ld-musl-x86_64.so.1") || exists("/lib/ld-musl-aarch64.so.1"));
35617
36129
  }
35618
36130
  function pinnedBinaryPath(dataDir = DATA_DIR, platform = process.platform, arch = process.arch) {
35619
36131
  const version2 = agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform, arch));
35620
- return join32(dataDir, ENGINE_DIR, version2, executableName(platform));
36132
+ return join34(dataDir, ENGINE_DIR, version2, executableName(platform));
35621
36133
  }
35622
36134
  function onPath(env, platform, exists) {
35623
36135
  const pathValue = platform === "win32" ? Object.entries(env).findLast(([key]) => key.toUpperCase() === "PATH")?.[1] : env.PATH;
@@ -35633,7 +36145,7 @@ function packagedBrowser(options) {
35633
36145
  const resources = (options.env ?? process.env).OMB_RESOURCES_PATH;
35634
36146
  if (!resources) return null;
35635
36147
  try {
35636
- return browserBundlePaths(join32(resolve11(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
36148
+ return browserBundlePaths(join34(resolve11(resources), "browser-engine"), `${options.platform ?? process.platform}-${options.arch ?? process.arch}`);
35637
36149
  } catch {
35638
36150
  return null;
35639
36151
  }
@@ -35644,7 +36156,7 @@ function completePackage(bundle, exists) {
35644
36156
  function resolveAgentBrowserBinary(options = {}) {
35645
36157
  const env = options.env ?? process.env;
35646
36158
  const platform = options.platform ?? process.platform;
35647
- const exists = options.exists ?? existsSync15;
36159
+ const exists = options.exists ?? existsSync16;
35648
36160
  const override = env.OMB_AGENT_BROWSER_PATH?.trim();
35649
36161
  if (override) return resolve11(override) && exists(resolve11(override)) ? resolve11(override) : null;
35650
36162
  const bundle = packagedBrowser(options);
@@ -35658,8 +36170,8 @@ async function installAgentBrowserBinary(options = {}) {
35658
36170
  const asset = options.asset ?? resolveAgentBrowserReleaseAsset(platform, options.arch ?? process.arch, options.musl ?? isMusl(platform));
35659
36171
  if (!asset) throw new Error(`agent-browser publishes no build for ${platform}-${options.arch ?? process.arch}.`);
35660
36172
  const destination = pinnedBinaryPath(options.dataDir, platform, options.arch);
35661
- const directory = join32(destination, "..");
35662
- mkdirSync13(directory, { recursive: true, mode: 448 });
36173
+ const directory = join34(destination, "..");
36174
+ mkdirSync14(directory, { recursive: true, mode: 448 });
35663
36175
  const url2 = agentBrowserReleaseUrl(asset);
35664
36176
  options.log?.(`downloading agent-browser ${agentBrowserReleaseVersion(asset)} (${Math.round(asset.bytes / 1024 / 1024)} MB, digest pinned)`);
35665
36177
  const controller = new AbortController();
@@ -35684,7 +36196,7 @@ async function installAgentBrowserBinary(options = {}) {
35684
36196
  }
35685
36197
  function ensureChrome(binaryPath, options = {}) {
35686
36198
  const bundle = packagedBrowser(options);
35687
- if (!options.withDeps && bundle && resolve11(binaryPath) === bundle.engine && completePackage(bundle, existsSync15)) {
36199
+ if (!options.withDeps && bundle && resolve11(binaryPath) === bundle.engine && completePackage(bundle, existsSync16)) {
35688
36200
  options.log?.("agent-browser: the bundled browser is ready; no download needed");
35689
36201
  return Promise.resolve();
35690
36202
  }
@@ -35710,14 +36222,14 @@ function ensureChrome(binaryPath, options = {}) {
35710
36222
  });
35711
36223
  }
35712
36224
  function browserEngineEncryptionKey(dataDir = DATA_DIR) {
35713
- const file2 = join32(dataDir, KEY_FILE);
36225
+ const file2 = join34(dataDir, KEY_FILE);
35714
36226
  try {
35715
36227
  const existing = readFileSync19(file2, "utf8").trim();
35716
36228
  if (/^[0-9a-f]{64}$/u.test(existing)) return existing;
35717
36229
  } catch {
35718
36230
  }
35719
36231
  const key = randomBytes3(32).toString("hex");
35720
- mkdirSync13(dataDir, { recursive: true });
36232
+ mkdirSync14(dataDir, { recursive: true });
35721
36233
  writeFileAtomic(file2, `${key}
35722
36234
  `, { mode: 384 });
35723
36235
  return key;
@@ -35731,7 +36243,7 @@ function browserEngineStatus(options = {}) {
35731
36243
  const version2 = managed ? agentBrowserReleaseVersion(resolveAgentBrowserReleaseAsset(platform2, options.arch)) : AGENT_BROWSER_VERSION;
35732
36244
  return { kind: "ready", binaryPath, version: version2 };
35733
36245
  }
35734
- if (bundle && (options.exists ?? existsSync15)(bundle.directory)) {
36246
+ if (bundle && (options.exists ?? existsSync16)(bundle.directory)) {
35735
36247
  return { kind: "unavailable", reason: "The desktop browser bundle is incomplete. Reinstall or update OpenMausBot to repair it.", installable: false };
35736
36248
  }
35737
36249
  const platform = options.platform ?? process.platform;
@@ -35764,13 +36276,13 @@ function agentBrowserIntegration(input) {
35764
36276
  if (sourceEnv[name]) env[name] = sourceEnv[name];
35765
36277
  }
35766
36278
  const bundle = packagedBrowser({ env: sourceEnv });
35767
- if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve11(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync15)) {
36279
+ if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve11(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync16)) {
35768
36280
  env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
35769
36281
  }
35770
36282
  return { command: input.binaryPath, args: ["mcp", "--tools", "core", "--no-webmcp"], env };
35771
36283
  }
35772
36284
  function agentBrowserFrame(input) {
35773
- const file2 = join32(tmpdir5(), `openmausbot-browser-${randomUUID11()}.png`);
36285
+ const file2 = join34(tmpdir5(), `openmausbot-browser-${randomUUID11()}.png`);
35774
36286
  return new Promise((settle, fail) => {
35775
36287
  const child = spawn7(input.binaryPath, ["screenshot", file2], {
35776
36288
  env: browserRuntimeEnv(input.env),
@@ -35840,8 +36352,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
35840
36352
  }
35841
36353
  };
35842
36354
  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");
36355
+ for (const base2 of bases) for (const suffix of [".json", ".json.enc", ".json.previous", ".json.enc.previous"]) remove(join34(directory, base2 + suffix));
36356
+ const pendingDirectory = join34(directory, ".tmp");
35845
36357
  let pendingFiles = [];
35846
36358
  try {
35847
36359
  pendingFiles = readdirSync3(pendingDirectory);
@@ -35849,8 +36361,8 @@ async function clearBrowserSessionState(binaryPath, session, options = {}) {
35849
36361
  if (error51.code !== "ENOENT") throw error51;
35850
36362
  }
35851
36363
  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));
36364
+ for (const name of pendingFiles) if (candidates.some((candidate) => candidate.test(name))) remove(join34(pendingDirectory, name));
36365
+ preparedBrowserSessions.delete(join34(directory, session));
35854
36366
  return true;
35855
36367
  } catch {
35856
36368
  return false;
@@ -35877,9 +36389,9 @@ var init_browser_engine = __esm({
35877
36389
  // server/cli.ts
35878
36390
  var import_qrcode_terminal = __toESM(require_main(), 1);
35879
36391
  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";
36392
+ import { closeSync as closeSync3, existsSync as existsSync17, mkdirSync as mkdirSync15, openSync as openSync3, readFileSync as readFileSync20 } from "node:fs";
35881
36393
  import { homedir as homedir24 } from "node:os";
35882
- import { dirname as dirname11, join as join33, resolve as resolve12 } from "node:path";
36394
+ import { dirname as dirname11, join as join35, resolve as resolve12 } from "node:path";
35883
36395
  import { createInterface as createInterface2 } from "node:readline/promises";
35884
36396
  import { fileURLToPath as fileURLToPath3 } from "node:url";
35885
36397
 
@@ -38124,7 +38636,7 @@ function parseArgs(argv, env = process.env) {
38124
38636
  const options = {
38125
38637
  command: command === "--help" || command === "-h" ? "help" : command,
38126
38638
  port: Number(env.OMB_PORT || 8799),
38127
- dataDir: env.OMB_DATA_DIR || join33(homedir24(), ".openmausbot"),
38639
+ dataDir: env.OMB_DATA_DIR || join35(homedir24(), ".openmausbot"),
38128
38640
  tailscale: false,
38129
38641
  tunnel: false,
38130
38642
  client: false,
@@ -38279,7 +38791,7 @@ async function isWorkspaceRunning(options) {
38279
38791
  try {
38280
38792
  const { status, body } = await api(options.port, "/api/health");
38281
38793
  if (status !== 200 || body?.app !== "openmausbot") return false;
38282
- const expected = readFileSync20(join33(options.dataDir, "environment-id"), "utf8").trim();
38794
+ const expected = readFileSync20(join35(options.dataDir, "environment-id"), "utf8").trim();
38283
38795
  const descriptor = await api(options.port, "/.well-known/openmausbot/environment");
38284
38796
  return /^[0-9a-f-]{36}$/i.test(expected) && descriptor.status === 200 && descriptor.body?.environmentId === expected;
38285
38797
  } catch {
@@ -38479,9 +38991,9 @@ async function runStatus(options, io = defaultIo()) {
38479
38991
  return code;
38480
38992
  }
38481
38993
  async function runAccess(options, io = defaultIo()) {
38482
- const file2 = join33(options.dataDir, "config.json");
38994
+ const file2 = join35(options.dataDir, "config.json");
38483
38995
  let raw = {};
38484
- if (existsSync16(file2)) {
38996
+ if (existsSync17(file2)) {
38485
38997
  try {
38486
38998
  const parsed = JSON.parse(readFileSync20(file2, "utf8"));
38487
38999
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("not an object");
@@ -38497,7 +39009,7 @@ async function runAccess(options, io = defaultIo()) {
38497
39009
  const members = list(Reflect.get(current, "members"));
38498
39010
  const overridden = process.env.OMB_SIGNIN_EMAILS !== void 0 || process.env.OMB_SIGNIN_MEMBER_EMAILS !== void 0;
38499
39011
  const write = (next) => {
38500
- mkdirSync14(options.dataDir, { recursive: true, mode: 448 });
39012
+ mkdirSync15(options.dataDir, { recursive: true, mode: 448 });
38501
39013
  writeFileAtomic(file2, `${JSON.stringify({ ...raw, signIn: next }, null, 2)}
38502
39014
  `, { mode: 384 });
38503
39015
  };
@@ -38631,16 +39143,16 @@ async function runBrowser(options, io = defaultIo()) {
38631
39143
  return 0;
38632
39144
  }
38633
39145
  function serverEntry(here = HERE2) {
38634
- const bundled = join33(here, "index.js");
39146
+ const bundled = join35(here, "index.js");
38635
39147
  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;
39148
+ if (existsSync17(bundled)) {
39149
+ const staticDir2 = [join35(root, "dist"), join35(here, "..", "ui")].find((d) => existsSync17(join35(d, "index.html"))) ?? null;
39150
+ const skillsDir = existsSync17(join35(root, "skills")) ? join35(root, "skills") : null;
38639
39151
  return { command: process.execPath, args: [bundled], staticDir: staticDir2, skillsDir };
38640
39152
  }
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 };
39153
+ const source = join35(here, "index.ts");
39154
+ const staticDir = existsSync17(join35(root, "dist", "index.html")) ? join35(root, "dist") : null;
39155
+ return { command: process.execPath, args: ["--experimental-strip-types", source], staticDir, skillsDir: existsSync17(join35(root, "skills")) ? join35(root, "skills") : null };
38644
39156
  }
38645
39157
  async function planTunnel(options, log) {
38646
39158
  let access2 = null;
@@ -38740,9 +39252,9 @@ async function runServe(options, log = console.log) {
38740
39252
  let child;
38741
39253
  try {
38742
39254
  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`);
39255
+ const logsDir = join35(options.dataDir, "logs");
39256
+ mkdirSync15(logsDir, { recursive: true, mode: 448 });
39257
+ logPath = join35(logsDir, `server-${Date.now()}-${process.pid}.log`);
38746
39258
  logFd = openSync3(logPath, "wx", 384);
38747
39259
  log("\nStarting your workspace\u2026");
38748
39260
  }
@@ -38934,7 +39446,7 @@ async function runOnboardingCommand(options, io = defaultIo(), startServer = run
38934
39446
  }
38935
39447
  if (options.command === "setup") {
38936
39448
  io.log("\nAll set. Start with: openmausbot (or npx openmausbot without a global install).");
38937
- if (options.dataDir !== join33(homedir24(), ".openmausbot") || options.port !== 8799) {
39449
+ if (options.dataDir !== join35(homedir24(), ".openmausbot") || options.port !== 8799) {
38938
39450
  io.log(`Use the same --data-dir (${options.dataDir}) and --port (${options.port}) options when starting.`);
38939
39451
  }
38940
39452
  return 0;