@buildautomaton/cli 0.1.14 → 0.1.16

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.
package/dist/cli.js CHANGED
@@ -972,10 +972,10 @@ var require_suggestSimilar = __commonJS({
972
972
  var require_command = __commonJS({
973
973
  "../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
974
974
  var EventEmitter2 = __require("node:events").EventEmitter;
975
- var childProcess = __require("node:child_process");
976
- var path32 = __require("node:path");
977
- var fs25 = __require("node:fs");
978
- var process2 = __require("node:process");
975
+ var childProcess2 = __require("node:child_process");
976
+ var path34 = __require("node:path");
977
+ var fs31 = __require("node:fs");
978
+ var process8 = __require("node:process");
979
979
  var { Argument: Argument2, humanReadableArgName } = require_argument();
980
980
  var { CommanderError: CommanderError2 } = require_error();
981
981
  var { Help: Help2 } = require_help();
@@ -1021,10 +1021,10 @@ var require_command = __commonJS({
1021
1021
  this._showHelpAfterError = false;
1022
1022
  this._showSuggestionAfterError = true;
1023
1023
  this._outputConfiguration = {
1024
- writeOut: (str) => process2.stdout.write(str),
1025
- writeErr: (str) => process2.stderr.write(str),
1026
- getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : void 0,
1027
- getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : void 0,
1024
+ writeOut: (str) => process8.stdout.write(str),
1025
+ writeErr: (str) => process8.stderr.write(str),
1026
+ getOutHelpWidth: () => process8.stdout.isTTY ? process8.stdout.columns : void 0,
1027
+ getErrHelpWidth: () => process8.stderr.isTTY ? process8.stderr.columns : void 0,
1028
1028
  outputError: (str, write) => write(str)
1029
1029
  };
1030
1030
  this._hidden = false;
@@ -1403,7 +1403,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1403
1403
  if (this._exitCallback) {
1404
1404
  this._exitCallback(new CommanderError2(exitCode, code, message));
1405
1405
  }
1406
- process2.exit(exitCode);
1406
+ process8.exit(exitCode);
1407
1407
  }
1408
1408
  /**
1409
1409
  * Register callback `fn` for the command.
@@ -1801,16 +1801,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
1801
1801
  }
1802
1802
  parseOptions = parseOptions || {};
1803
1803
  if (argv === void 0 && parseOptions.from === void 0) {
1804
- if (process2.versions?.electron) {
1804
+ if (process8.versions?.electron) {
1805
1805
  parseOptions.from = "electron";
1806
1806
  }
1807
- const execArgv = process2.execArgv ?? [];
1807
+ const execArgv = process8.execArgv ?? [];
1808
1808
  if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
1809
1809
  parseOptions.from = "eval";
1810
1810
  }
1811
1811
  }
1812
1812
  if (argv === void 0) {
1813
- argv = process2.argv;
1813
+ argv = process8.argv;
1814
1814
  }
1815
1815
  this.rawArgs = argv.slice();
1816
1816
  let userArgs;
@@ -1821,7 +1821,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1821
1821
  userArgs = argv.slice(2);
1822
1822
  break;
1823
1823
  case "electron":
1824
- if (process2.defaultApp) {
1824
+ if (process8.defaultApp) {
1825
1825
  this._scriptPath = argv[1];
1826
1826
  userArgs = argv.slice(2);
1827
1827
  } else {
@@ -1906,11 +1906,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1906
1906
  let launchWithNode = false;
1907
1907
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1908
1908
  function findFile(baseDir, baseName) {
1909
- const localBin = path32.resolve(baseDir, baseName);
1910
- if (fs25.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path32.extname(baseName))) return void 0;
1909
+ const localBin = path34.resolve(baseDir, baseName);
1910
+ if (fs31.existsSync(localBin)) return localBin;
1911
+ if (sourceExt.includes(path34.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
- (ext) => fs25.existsSync(`${localBin}${ext}`)
1913
+ (ext) => fs31.existsSync(`${localBin}${ext}`)
1914
1914
  );
1915
1915
  if (foundExt) return `${localBin}${foundExt}`;
1916
1916
  return void 0;
@@ -1922,21 +1922,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1922
1922
  if (this._scriptPath) {
1923
1923
  let resolvedScriptPath;
1924
1924
  try {
1925
- resolvedScriptPath = fs25.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs31.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path32.resolve(
1930
- path32.dirname(resolvedScriptPath),
1929
+ executableDir = path34.resolve(
1930
+ path34.dirname(resolvedScriptPath),
1931
1931
  executableDir
1932
1932
  );
1933
1933
  }
1934
1934
  if (executableDir) {
1935
1935
  let localFile = findFile(executableDir, executableFile);
1936
1936
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1937
- const legacyName = path32.basename(
1937
+ const legacyName = path34.basename(
1938
1938
  this._scriptPath,
1939
- path32.extname(this._scriptPath)
1939
+ path34.extname(this._scriptPath)
1940
1940
  );
1941
1941
  if (legacyName !== this._name) {
1942
1942
  localFile = findFile(
@@ -1947,25 +1947,25 @@ Expecting one of '${allowedValues.join("', '")}'`);
1947
1947
  }
1948
1948
  executableFile = localFile || executableFile;
1949
1949
  }
1950
- launchWithNode = sourceExt.includes(path32.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path34.extname(executableFile));
1951
1951
  let proc;
1952
- if (process2.platform !== "win32") {
1952
+ if (process8.platform !== "win32") {
1953
1953
  if (launchWithNode) {
1954
1954
  args.unshift(executableFile);
1955
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1956
- proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
1955
+ args = incrementNodeInspectorPort(process8.execArgv).concat(args);
1956
+ proc = childProcess2.spawn(process8.argv[0], args, { stdio: "inherit" });
1957
1957
  } else {
1958
- proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
1958
+ proc = childProcess2.spawn(executableFile, args, { stdio: "inherit" });
1959
1959
  }
1960
1960
  } else {
1961
1961
  args.unshift(executableFile);
1962
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1963
- proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
1962
+ args = incrementNodeInspectorPort(process8.execArgv).concat(args);
1963
+ proc = childProcess2.spawn(process8.execPath, args, { stdio: "inherit" });
1964
1964
  }
1965
1965
  if (!proc.killed) {
1966
1966
  const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
1967
1967
  signals.forEach((signal) => {
1968
- process2.on(signal, () => {
1968
+ process8.on(signal, () => {
1969
1969
  if (proc.killed === false && proc.exitCode === null) {
1970
1970
  proc.kill(signal);
1971
1971
  }
@@ -1976,7 +1976,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1976
1976
  proc.on("close", (code) => {
1977
1977
  code = code ?? 1;
1978
1978
  if (!exitCallback) {
1979
- process2.exit(code);
1979
+ process8.exit(code);
1980
1980
  } else {
1981
1981
  exitCallback(
1982
1982
  new CommanderError2(
@@ -1999,7 +1999,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1999
1999
  throw new Error(`'${executableFile}' not executable`);
2000
2000
  }
2001
2001
  if (!exitCallback) {
2002
- process2.exit(1);
2002
+ process8.exit(1);
2003
2003
  } else {
2004
2004
  const wrappedError = new CommanderError2(
2005
2005
  1,
@@ -2491,13 +2491,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2491
2491
  */
2492
2492
  _parseOptionsEnv() {
2493
2493
  this.options.forEach((option) => {
2494
- if (option.envVar && option.envVar in process2.env) {
2494
+ if (option.envVar && option.envVar in process8.env) {
2495
2495
  const optionKey = option.attributeName();
2496
2496
  if (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(
2497
2497
  this.getOptionValueSource(optionKey)
2498
2498
  )) {
2499
2499
  if (option.required || option.optional) {
2500
- this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
2500
+ this.emit(`optionEnv:${option.name()}`, process8.env[option.envVar]);
2501
2501
  } else {
2502
2502
  this.emit(`optionEnv:${option.name()}`);
2503
2503
  }
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2787
2787
  * @return {Command}
2788
2788
  */
2789
2789
  nameFromFilename(filename) {
2790
- this._name = path32.basename(filename, path32.extname(filename));
2790
+ this._name = path34.basename(filename, path34.extname(filename));
2791
2791
  return this;
2792
2792
  }
2793
2793
  /**
@@ -2801,9 +2801,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2801
2801
  * @param {string} [path]
2802
2802
  * @return {(string|null|Command)}
2803
2803
  */
2804
- executableDir(path33) {
2805
- if (path33 === void 0) return this._executableDir;
2806
- this._executableDir = path33;
2804
+ executableDir(path35) {
2805
+ if (path35 === void 0) return this._executableDir;
2806
+ this._executableDir = path35;
2807
2807
  return this;
2808
2808
  }
2809
2809
  /**
@@ -2926,7 +2926,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2926
2926
  */
2927
2927
  help(contextOptions) {
2928
2928
  this.outputHelp(contextOptions);
2929
- let exitCode = process2.exitCode || 0;
2929
+ let exitCode = process8.exitCode || 0;
2930
2930
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
2931
2931
  exitCode = 1;
2932
2932
  }
@@ -5236,7 +5236,7 @@ var require_websocket = __commonJS({
5236
5236
  var http = __require("http");
5237
5237
  var net = __require("net");
5238
5238
  var tls = __require("tls");
5239
- var { randomBytes, createHash: createHash2 } = __require("crypto");
5239
+ var { randomBytes: randomBytes3, createHash: createHash3 } = __require("crypto");
5240
5240
  var { Duplex, Readable: Readable2 } = __require("stream");
5241
5241
  var { URL: URL2 } = __require("url");
5242
5242
  var PerMessageDeflate = require_permessage_deflate();
@@ -5766,7 +5766,7 @@ var require_websocket = __commonJS({
5766
5766
  }
5767
5767
  }
5768
5768
  const defaultPort = isSecure ? 443 : 80;
5769
- const key = randomBytes(16).toString("base64");
5769
+ const key = randomBytes3(16).toString("base64");
5770
5770
  const request = isSecure ? https2.request : http.request;
5771
5771
  const protocolSet = /* @__PURE__ */ new Set();
5772
5772
  let perMessageDeflate;
@@ -5896,7 +5896,7 @@ var require_websocket = __commonJS({
5896
5896
  abortHandshake(websocket, socket, "Invalid Upgrade header");
5897
5897
  return;
5898
5898
  }
5899
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
5899
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
5900
5900
  if (res.headers["sec-websocket-accept"] !== digest) {
5901
5901
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
5902
5902
  return;
@@ -6175,7 +6175,7 @@ var require_stream = __commonJS({
6175
6175
  };
6176
6176
  duplex._final = function(callback) {
6177
6177
  if (ws.readyState === ws.CONNECTING) {
6178
- ws.once("open", function open() {
6178
+ ws.once("open", function open2() {
6179
6179
  duplex._final(callback);
6180
6180
  });
6181
6181
  return;
@@ -6196,7 +6196,7 @@ var require_stream = __commonJS({
6196
6196
  };
6197
6197
  duplex._write = function(chunk, encoding, callback) {
6198
6198
  if (ws.readyState === ws.CONNECTING) {
6199
- ws.once("open", function open() {
6199
+ ws.once("open", function open2() {
6200
6200
  duplex._write(chunk, encoding, callback);
6201
6201
  });
6202
6202
  return;
@@ -6263,7 +6263,7 @@ var require_websocket_server = __commonJS({
6263
6263
  var EventEmitter2 = __require("events");
6264
6264
  var http = __require("http");
6265
6265
  var { Duplex } = __require("stream");
6266
- var { createHash: createHash2 } = __require("crypto");
6266
+ var { createHash: createHash3 } = __require("crypto");
6267
6267
  var extension = require_extension();
6268
6268
  var PerMessageDeflate = require_permessage_deflate();
6269
6269
  var subprotocol = require_subprotocol();
@@ -6564,7 +6564,7 @@ var require_websocket_server = __commonJS({
6564
6564
  );
6565
6565
  }
6566
6566
  if (this._state > RUNNING) return abortHandshake(socket, 503);
6567
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
6567
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
6568
6568
  const headers = [
6569
6569
  "HTTP/1.1 101 Switching Protocols",
6570
6570
  "Upgrade: websocket",
@@ -7129,7 +7129,7 @@ var require_has_flag = __commonJS({
7129
7129
  var require_supports_color = __commonJS({
7130
7130
  "../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
7131
7131
  "use strict";
7132
- var os5 = __require("os");
7132
+ var os6 = __require("os");
7133
7133
  var tty = __require("tty");
7134
7134
  var hasFlag = require_has_flag();
7135
7135
  var { env } = process;
@@ -7177,7 +7177,7 @@ var require_supports_color = __commonJS({
7177
7177
  return min;
7178
7178
  }
7179
7179
  if (process.platform === "win32") {
7180
- const osRelease = os5.release().split(".");
7180
+ const osRelease = os6.release().split(".");
7181
7181
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
7182
7182
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
7183
7183
  }
@@ -7423,15 +7423,15 @@ var require_src2 = __commonJS({
7423
7423
  var fs_1 = __require("fs");
7424
7424
  var debug_1 = __importDefault(require_src());
7425
7425
  var log2 = debug_1.default("@kwsites/file-exists");
7426
- function check2(path32, isFile, isDirectory) {
7427
- log2(`checking %s`, path32);
7426
+ function check2(path34, isFile, isDirectory) {
7427
+ log2(`checking %s`, path34);
7428
7428
  try {
7429
- const stat2 = fs_1.statSync(path32);
7430
- if (stat2.isFile() && isFile) {
7429
+ const stat3 = fs_1.statSync(path34);
7430
+ if (stat3.isFile() && isFile) {
7431
7431
  log2(`[OK] path represents a file`);
7432
7432
  return true;
7433
7433
  }
7434
- if (stat2.isDirectory() && isDirectory) {
7434
+ if (stat3.isDirectory() && isDirectory) {
7435
7435
  log2(`[OK] path represents a directory`);
7436
7436
  return true;
7437
7437
  }
@@ -7446,8 +7446,8 @@ var require_src2 = __commonJS({
7446
7446
  throw e;
7447
7447
  }
7448
7448
  }
7449
- function exists2(path32, type = exports.READABLE) {
7450
- return check2(path32, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
7449
+ function exists2(path34, type = exports.READABLE) {
7450
+ return check2(path34, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
7451
7451
  }
7452
7452
  exports.exists = exists2;
7453
7453
  exports.FILE = 1;
@@ -7922,8 +7922,8 @@ var init_parseUtil = __esm({
7922
7922
  init_errors();
7923
7923
  init_en();
7924
7924
  makeIssue = (params) => {
7925
- const { data, path: path32, errorMaps, issueData } = params;
7926
- const fullPath = [...path32, ...issueData.path || []];
7925
+ const { data, path: path34, errorMaps, issueData } = params;
7926
+ const fullPath = [...path34, ...issueData.path || []];
7927
7927
  const fullIssue = {
7928
7928
  ...issueData,
7929
7929
  path: fullPath
@@ -8231,11 +8231,11 @@ var init_types = __esm({
8231
8231
  init_parseUtil();
8232
8232
  init_util2();
8233
8233
  ParseInputLazyPath = class {
8234
- constructor(parent, value, path32, key) {
8234
+ constructor(parent, value, path34, key) {
8235
8235
  this._cachedPath = [];
8236
8236
  this.parent = parent;
8237
8237
  this.data = value;
8238
- this._path = path32;
8238
+ this._path = path34;
8239
8239
  this._key = key;
8240
8240
  }
8241
8241
  get path() {
@@ -11850,10 +11850,10 @@ function assignProp(target, prop, value) {
11850
11850
  configurable: true
11851
11851
  });
11852
11852
  }
11853
- function getElementAtPath(obj, path32) {
11854
- if (!path32)
11853
+ function getElementAtPath(obj, path34) {
11854
+ if (!path34)
11855
11855
  return obj;
11856
- return path32.reduce((acc, key) => acc?.[key], obj);
11856
+ return path34.reduce((acc, key) => acc?.[key], obj);
11857
11857
  }
11858
11858
  function promiseAllObject(promisesObj) {
11859
11859
  const keys = Object.keys(promisesObj);
@@ -12102,11 +12102,11 @@ function aborted(x, startIndex = 0) {
12102
12102
  }
12103
12103
  return false;
12104
12104
  }
12105
- function prefixIssues(path32, issues) {
12105
+ function prefixIssues(path34, issues) {
12106
12106
  return issues.map((iss) => {
12107
12107
  var _a2;
12108
12108
  (_a2 = iss).path ?? (_a2.path = []);
12109
- iss.path.unshift(path32);
12109
+ iss.path.unshift(path34);
12110
12110
  return iss;
12111
12111
  });
12112
12112
  }
@@ -12295,7 +12295,7 @@ function treeifyError(error40, _mapper) {
12295
12295
  return issue2.message;
12296
12296
  };
12297
12297
  const result = { errors: [] };
12298
- const processError = (error41, path32 = []) => {
12298
+ const processError = (error41, path34 = []) => {
12299
12299
  var _a2, _b;
12300
12300
  for (const issue2 of error41.issues) {
12301
12301
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -12305,7 +12305,7 @@ function treeifyError(error40, _mapper) {
12305
12305
  } else if (issue2.code === "invalid_element") {
12306
12306
  processError({ issues: issue2.issues }, issue2.path);
12307
12307
  } else {
12308
- const fullpath = [...path32, ...issue2.path];
12308
+ const fullpath = [...path34, ...issue2.path];
12309
12309
  if (fullpath.length === 0) {
12310
12310
  result.errors.push(mapper(issue2));
12311
12311
  continue;
@@ -12335,9 +12335,9 @@ function treeifyError(error40, _mapper) {
12335
12335
  processError(error40);
12336
12336
  return result;
12337
12337
  }
12338
- function toDotPath(path32) {
12338
+ function toDotPath(path34) {
12339
12339
  const segs = [];
12340
- for (const seg of path32) {
12340
+ for (const seg of path34) {
12341
12341
  if (typeof seg === "number")
12342
12342
  segs.push(`[${seg}]`);
12343
12343
  else if (typeof seg === "symbol")
@@ -24800,8 +24800,8 @@ var init_acp = __esm({
24800
24800
  this.#requestHandler = requestHandler;
24801
24801
  this.#notificationHandler = notificationHandler;
24802
24802
  this.#stream = stream;
24803
- this.#closedPromise = new Promise((resolve16) => {
24804
- this.#abortController.signal.addEventListener("abort", () => resolve16());
24803
+ this.#closedPromise = new Promise((resolve17) => {
24804
+ this.#abortController.signal.addEventListener("abort", () => resolve17());
24805
24805
  });
24806
24806
  this.#receive();
24807
24807
  }
@@ -24950,8 +24950,8 @@ var init_acp = __esm({
24950
24950
  }
24951
24951
  async sendRequest(method, params) {
24952
24952
  const id = this.#nextRequestId++;
24953
- const responsePromise = new Promise((resolve16, reject) => {
24954
- this.#pendingResponses.set(id, { resolve: resolve16, reject });
24953
+ const responsePromise = new Promise((resolve17, reject) => {
24954
+ this.#pendingResponses.set(id, { resolve: resolve17, reject });
24955
24955
  });
24956
24956
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
24957
24957
  return responsePromise;
@@ -25046,10 +25046,6 @@ var init_acp = __esm({
25046
25046
  }
25047
25047
  });
25048
25048
 
25049
- // src/cli.ts
25050
- import * as fs24 from "node:fs";
25051
- import * as path31 from "node:path";
25052
-
25053
25049
  // ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
25054
25050
  var import_index = __toESM(require_commander(), 1);
25055
25051
  var {
@@ -25067,6 +25063,14 @@ var {
25067
25063
  Help
25068
25064
  } = import_index.default;
25069
25065
 
25066
+ // src/cli/defaults.ts
25067
+ var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
25068
+ var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
25069
+
25070
+ // src/cli/run-cli-action.ts
25071
+ import * as fs30 from "node:fs";
25072
+ import * as path33 from "node:path";
25073
+
25070
25074
  // src/config.ts
25071
25075
  import fs from "node:fs";
25072
25076
  import path from "node:path";
@@ -25145,15 +25149,291 @@ function clearConfigForApi(apiUrl) {
25145
25149
  }
25146
25150
  }
25147
25151
 
25148
- // src/files/cwd/bridge-workspace-directory.ts
25152
+ // src/e2e-certificates/certificates.ts
25153
+ import * as fs2 from "node:fs/promises";
25149
25154
  import * as path2 from "node:path";
25155
+
25156
+ // ../e2ee/src/constants.ts
25157
+ var E2EE_ALG = "A1";
25158
+ var E2EE_KEY_BYTES = 32;
25159
+ var E2EE_NONCE_BYTES = 12;
25160
+
25161
+ // ../e2ee/src/types.ts
25162
+ function isE2eeEnvelope(value) {
25163
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
25164
+ const o = value;
25165
+ return typeof o.k === "string" && typeof o.n === "string" && typeof o.c === "string";
25166
+ }
25167
+ function isE2eeKeyRecord(value) {
25168
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
25169
+ const o = value;
25170
+ return typeof o.id === "string" && o.id.length > 0 && typeof o.name === "string" && o.name.length > 0 && o.a === E2EE_ALG && typeof o.k === "string" && o.k.length > 0 && typeof o.createdAt === "string" && o.createdAt.length > 0;
25171
+ }
25172
+
25173
+ // ../e2ee/src/encoding.ts
25174
+ function base64UrlEncode(bytes) {
25175
+ let binary = "";
25176
+ for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
25177
+ const b64 = btoa(binary);
25178
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
25179
+ }
25180
+ function base64UrlDecode(value) {
25181
+ const b64 = value.replace(/-/g, "+").replace(/_/g, "/");
25182
+ const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
25183
+ const binary = atob(padded);
25184
+ const out = new Uint8Array(binary.length);
25185
+ for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
25186
+ return out;
25187
+ }
25188
+
25189
+ // ../e2ee/src/pem.ts
25190
+ var E2EE_PEM_LABEL = "BUILD AUTOMATON E2EE KEY";
25191
+ function pemHeaderValue(headers, name) {
25192
+ return headers[name.toLowerCase()];
25193
+ }
25194
+ function encodePemBase64(bytes) {
25195
+ const raw = base64UrlEncode(bytes).replace(/-/g, "+").replace(/_/g, "/");
25196
+ const padded = raw + "=".repeat((4 - raw.length % 4) % 4);
25197
+ return padded.replace(/.{1,64}/g, "$&\n").trimEnd();
25198
+ }
25199
+ function decodePemBase64(value) {
25200
+ const compact = value.replace(/\s+/g, "");
25201
+ const binary = atob(compact);
25202
+ const out = new Uint8Array(binary.length);
25203
+ for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
25204
+ return out;
25205
+ }
25206
+ function parseE2eeKeyRecordPem(raw, fallbackName) {
25207
+ const lines = raw.trim().split(/\r?\n/);
25208
+ if (lines[0]?.trim() !== `-----BEGIN ${E2EE_PEM_LABEL}-----`) {
25209
+ throw new Error("The E2EE key file is not a BuildAutomaton PEM key.");
25210
+ }
25211
+ const endIndex = lines.findIndex((line) => line.trim() === `-----END ${E2EE_PEM_LABEL}-----`);
25212
+ if (endIndex < 0) throw new Error("The E2EE key PEM is missing its end marker.");
25213
+ const headers = {};
25214
+ const bodyLines = [];
25215
+ let readingBody = false;
25216
+ for (const line of lines.slice(1, endIndex)) {
25217
+ const trimmed2 = line.trim();
25218
+ if (!trimmed2) {
25219
+ readingBody = true;
25220
+ continue;
25221
+ }
25222
+ const headerMatch = /^([A-Za-z0-9-]+):\s*(.*)$/.exec(trimmed2);
25223
+ if (!readingBody && headerMatch) {
25224
+ headers[headerMatch[1].toLowerCase()] = headerMatch[2].trim();
25225
+ continue;
25226
+ }
25227
+ readingBody = true;
25228
+ bodyLines.push(trimmed2);
25229
+ }
25230
+ const keyBytes = decodePemBase64(bodyLines.join(""));
25231
+ if (keyBytes.byteLength !== E2EE_KEY_BYTES) throw new Error("The E2EE key PEM does not contain a 256-bit key.");
25232
+ const key = {
25233
+ id: pemHeaderValue(headers, "Key-Id") ?? "",
25234
+ name: pemHeaderValue(headers, "Name") ?? fallbackName,
25235
+ a: pemHeaderValue(headers, "Algorithm") ?? E2EE_ALG,
25236
+ k: base64UrlEncode(keyBytes),
25237
+ createdAt: pemHeaderValue(headers, "Created-At") ?? (/* @__PURE__ */ new Date()).toISOString()
25238
+ };
25239
+ if (!isE2eeKeyRecord(key)) throw new Error("The E2EE key PEM has invalid metadata.");
25240
+ return {
25241
+ ...key,
25242
+ name: key.name.trim() || fallbackName
25243
+ };
25244
+ }
25245
+ function parseE2eeKeyRecord(raw, fallbackName) {
25246
+ return parseE2eeKeyRecordPem(raw.trim(), fallbackName);
25247
+ }
25248
+ function serializeE2eeKeyRecord(key) {
25249
+ return [
25250
+ `-----BEGIN ${E2EE_PEM_LABEL}-----`,
25251
+ `Key-Id: ${key.id}`,
25252
+ `Name: ${key.name}`,
25253
+ `Algorithm: ${key.a}`,
25254
+ `Created-At: ${key.createdAt}`,
25255
+ "",
25256
+ encodePemBase64(base64UrlDecode(key.k)),
25257
+ `-----END ${E2EE_PEM_LABEL}-----`,
25258
+ ""
25259
+ ].join("\n");
25260
+ }
25261
+
25262
+ // src/lib/e2ee/cli-e2ee-key.ts
25263
+ import { createHash, randomBytes } from "node:crypto";
25264
+ function createE2eeKeyRecord(name) {
25265
+ const raw = randomBytes(E2EE_KEY_BYTES);
25266
+ const digest = createHash("sha256").update(raw).digest();
25267
+ return {
25268
+ id: base64UrlEncode(digest.subarray(0, 16)),
25269
+ name: name.trim() || "BuildAutomaton E2EE key",
25270
+ a: E2EE_ALG,
25271
+ k: base64UrlEncode(raw),
25272
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
25273
+ };
25274
+ }
25275
+
25276
+ // src/lib/e2ee/cli-e2ee-runtime.ts
25277
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes2 } from "node:crypto";
25278
+ function nonceFromCounter(prefix, counter) {
25279
+ const nonce = Buffer.alloc(E2EE_NONCE_BYTES);
25280
+ prefix.copy(nonce, 0);
25281
+ nonce.writeBigUInt64BE(counter, 4);
25282
+ return nonce;
25283
+ }
25284
+ function createCliE2eeRuntime(key) {
25285
+ const rawKey = Buffer.from(base64UrlDecode(key.k));
25286
+ const prefix = randomBytes2(4);
25287
+ let counter = 0n;
25288
+ function nextNonce() {
25289
+ counter += 1n;
25290
+ return nonceFromCounter(prefix, counter);
25291
+ }
25292
+ function encryptObject(messageWithoutSensitiveFields, plaintext) {
25293
+ const nonce = nextNonce();
25294
+ const cipher = createCipheriv("aes-256-gcm", rawKey, nonce);
25295
+ const ciphertext = Buffer.concat([cipher.update(JSON.stringify(plaintext), "utf8"), cipher.final()]);
25296
+ const tag = cipher.getAuthTag();
25297
+ return {
25298
+ k: key.id,
25299
+ n: base64UrlEncode(nonce),
25300
+ c: base64UrlEncode(Buffer.concat([ciphertext, tag]))
25301
+ };
25302
+ }
25303
+ return {
25304
+ keyId: key.id,
25305
+ handshake: { k: key.id, a: key.a },
25306
+ encryptFields(message, fields) {
25307
+ const plaintext = {};
25308
+ const stripped = { ...message };
25309
+ let hasPlaintext = false;
25310
+ for (const field of fields) {
25311
+ if (Object.prototype.hasOwnProperty.call(stripped, field) && stripped[field] !== void 0) {
25312
+ plaintext[field] = stripped[field];
25313
+ delete stripped[field];
25314
+ hasPlaintext = true;
25315
+ }
25316
+ }
25317
+ if (!hasPlaintext) return message;
25318
+ stripped.ee = encryptObject(stripped, plaintext);
25319
+ return stripped;
25320
+ },
25321
+ decryptMessage(message) {
25322
+ const envelope = message.ee;
25323
+ if (!isE2eeEnvelope(envelope)) return message;
25324
+ if (envelope.k !== key.id) throw new Error(`E2EE key mismatch: ${envelope.k}`);
25325
+ const sealed = Buffer.from(base64UrlDecode(envelope.c));
25326
+ if (sealed.length < 16) throw new Error("Invalid E2EE payload.");
25327
+ const ciphertext = sealed.subarray(0, sealed.length - 16);
25328
+ const tag = sealed.subarray(sealed.length - 16);
25329
+ const nonce = Buffer.from(base64UrlDecode(envelope.n));
25330
+ const decipher = createDecipheriv("aes-256-gcm", rawKey, nonce);
25331
+ decipher.setAuthTag(tag);
25332
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
25333
+ const parsed = JSON.parse(decrypted);
25334
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
25335
+ throw new Error("E2EE payload did not decode to an object.");
25336
+ }
25337
+ const merged = { ...message, ...parsed };
25338
+ delete merged.ee;
25339
+ return merged;
25340
+ }
25341
+ };
25342
+ }
25343
+
25344
+ // src/e2e-certificates/certificates.ts
25345
+ var E2E_CERTIFICATE_ALGORITHM = "A1";
25346
+ var CERTIFICATE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".pem", ".key", ".crt"]);
25347
+ function certificateFromKey({
25348
+ raw,
25349
+ name,
25350
+ createdAt
25351
+ }) {
25352
+ try {
25353
+ const key = parseE2eeKeyRecord(raw, name);
25354
+ return {
25355
+ ...key,
25356
+ name: key.name || name,
25357
+ algorithm: E2E_CERTIFICATE_ALGORITHM,
25358
+ pemBundle: serializeE2eeKeyRecord({ ...key, createdAt: key.createdAt || createdAt })
25359
+ };
25360
+ } catch {
25361
+ return void 0;
25362
+ }
25363
+ }
25364
+ function baseNameForCertificate(fileName) {
25365
+ return path2.basename(fileName, path2.extname(fileName)) || "BuildAutomaton E2EE certificate";
25366
+ }
25367
+ async function readCertificateFiles(directory) {
25368
+ let entries;
25369
+ try {
25370
+ entries = await fs2.readdir(directory, { withFileTypes: true });
25371
+ } catch (err) {
25372
+ const nodeErr = err;
25373
+ if (nodeErr.code === "ENOENT") return [];
25374
+ throw err;
25375
+ }
25376
+ const certificates = [];
25377
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
25378
+ if (!entry.isFile() || !CERTIFICATE_FILE_EXTENSIONS.has(path2.extname(entry.name).toLowerCase())) continue;
25379
+ const filePath = path2.join(directory, entry.name);
25380
+ const raw = await fs2.readFile(filePath, "utf8").catch(() => void 0);
25381
+ if (!raw) continue;
25382
+ const stat3 = await fs2.stat(filePath).catch(() => void 0);
25383
+ const certificate = certificateFromKey({
25384
+ raw,
25385
+ name: baseNameForCertificate(entry.name),
25386
+ createdAt: stat3?.mtime?.toISOString() ?? (/* @__PURE__ */ new Date()).toISOString()
25387
+ });
25388
+ if (certificate) {
25389
+ certificates.push(certificate);
25390
+ }
25391
+ }
25392
+ return certificates;
25393
+ }
25394
+ function createCertificate(directory) {
25395
+ const baseName = path2.basename(directory) || "BuildAutomaton E2EE certificate";
25396
+ const key = createE2eeKeyRecord(baseName);
25397
+ return {
25398
+ ...key,
25399
+ algorithm: E2E_CERTIFICATE_ALGORITHM,
25400
+ pemBundle: serializeE2eeKeyRecord(key)
25401
+ };
25402
+ }
25403
+ async function loadOrCreateE2eCertificates(directory) {
25404
+ const resolved = path2.resolve(directory);
25405
+ await fs2.mkdir(resolved, { recursive: true, mode: 448 });
25406
+ const existing = await readCertificateFiles(resolved);
25407
+ if (existing.length > 0) {
25408
+ return {
25409
+ directory: resolved,
25410
+ certificates: existing,
25411
+ activeCertificate: existing[0],
25412
+ generated: false
25413
+ };
25414
+ }
25415
+ const certificate = createCertificate(resolved);
25416
+ const fileName = `buildautomaton-e2ee-key-${certificate.id.slice(0, 12)}.pem`;
25417
+ await fs2.writeFile(path2.join(resolved, fileName), certificate.pemBundle, {
25418
+ mode: 384
25419
+ });
25420
+ return {
25421
+ directory: resolved,
25422
+ certificates: [certificate],
25423
+ activeCertificate: certificate,
25424
+ generated: true
25425
+ };
25426
+ }
25427
+
25428
+ // src/files/cwd/bridge-workspace-directory.ts
25429
+ import * as path3 from "node:path";
25150
25430
  var bridgeWorkspaceDirectory = null;
25151
25431
  function initBridgeWorkspaceDirectory() {
25152
- bridgeWorkspaceDirectory = path2.resolve(process.cwd());
25432
+ bridgeWorkspaceDirectory = path3.resolve(process.cwd());
25153
25433
  }
25154
25434
  function getBridgeWorkspaceDirectory() {
25155
25435
  if (bridgeWorkspaceDirectory == null) {
25156
- bridgeWorkspaceDirectory = path2.resolve(process.cwd());
25436
+ bridgeWorkspaceDirectory = path3.resolve(process.cwd());
25157
25437
  }
25158
25438
  return bridgeWorkspaceDirectory;
25159
25439
  }
@@ -25321,8 +25601,521 @@ function sendWsMessage(ws, payload) {
25321
25601
  }
25322
25602
  }
25323
25603
 
25604
+ // ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
25605
+ import process7 from "node:process";
25606
+ import { Buffer as Buffer2 } from "node:buffer";
25607
+ import path4 from "node:path";
25608
+ import { fileURLToPath } from "node:url";
25609
+ import { promisify as promisify5 } from "node:util";
25610
+ import childProcess from "node:child_process";
25611
+ import fs7, { constants as fsConstants2 } from "node:fs/promises";
25612
+
25613
+ // ../../node_modules/.pnpm/wsl-utils@0.1.0/node_modules/wsl-utils/index.js
25614
+ import process3 from "node:process";
25615
+ import fs6, { constants as fsConstants } from "node:fs/promises";
25616
+
25617
+ // ../../node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js
25618
+ import process2 from "node:process";
25619
+ import os2 from "node:os";
25620
+ import fs5 from "node:fs";
25621
+
25622
+ // ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
25623
+ import fs4 from "node:fs";
25624
+
25625
+ // ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
25626
+ import fs3 from "node:fs";
25627
+ var isDockerCached;
25628
+ function hasDockerEnv() {
25629
+ try {
25630
+ fs3.statSync("/.dockerenv");
25631
+ return true;
25632
+ } catch {
25633
+ return false;
25634
+ }
25635
+ }
25636
+ function hasDockerCGroup() {
25637
+ try {
25638
+ return fs3.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
25639
+ } catch {
25640
+ return false;
25641
+ }
25642
+ }
25643
+ function isDocker() {
25644
+ if (isDockerCached === void 0) {
25645
+ isDockerCached = hasDockerEnv() || hasDockerCGroup();
25646
+ }
25647
+ return isDockerCached;
25648
+ }
25649
+
25650
+ // ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
25651
+ var cachedResult;
25652
+ var hasContainerEnv = () => {
25653
+ try {
25654
+ fs4.statSync("/run/.containerenv");
25655
+ return true;
25656
+ } catch {
25657
+ return false;
25658
+ }
25659
+ };
25660
+ function isInsideContainer() {
25661
+ if (cachedResult === void 0) {
25662
+ cachedResult = hasContainerEnv() || isDocker();
25663
+ }
25664
+ return cachedResult;
25665
+ }
25666
+
25667
+ // ../../node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js
25668
+ var isWsl = () => {
25669
+ if (process2.platform !== "linux") {
25670
+ return false;
25671
+ }
25672
+ if (os2.release().toLowerCase().includes("microsoft")) {
25673
+ if (isInsideContainer()) {
25674
+ return false;
25675
+ }
25676
+ return true;
25677
+ }
25678
+ try {
25679
+ if (fs5.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
25680
+ return !isInsideContainer();
25681
+ }
25682
+ } catch {
25683
+ }
25684
+ if (fs5.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs5.existsSync("/run/WSL")) {
25685
+ return !isInsideContainer();
25686
+ }
25687
+ return false;
25688
+ };
25689
+ var is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
25690
+
25691
+ // ../../node_modules/.pnpm/wsl-utils@0.1.0/node_modules/wsl-utils/index.js
25692
+ var wslDrivesMountPoint = /* @__PURE__ */ (() => {
25693
+ const defaultMountPoint = "/mnt/";
25694
+ let mountPoint;
25695
+ return async function() {
25696
+ if (mountPoint) {
25697
+ return mountPoint;
25698
+ }
25699
+ const configFilePath2 = "/etc/wsl.conf";
25700
+ let isConfigFileExists = false;
25701
+ try {
25702
+ await fs6.access(configFilePath2, fsConstants.F_OK);
25703
+ isConfigFileExists = true;
25704
+ } catch {
25705
+ }
25706
+ if (!isConfigFileExists) {
25707
+ return defaultMountPoint;
25708
+ }
25709
+ const configContent = await fs6.readFile(configFilePath2, { encoding: "utf8" });
25710
+ const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
25711
+ if (!configMountPoint) {
25712
+ return defaultMountPoint;
25713
+ }
25714
+ mountPoint = configMountPoint.groups.mountPoint.trim();
25715
+ mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
25716
+ return mountPoint;
25717
+ };
25718
+ })();
25719
+ var powerShellPathFromWsl = async () => {
25720
+ const mountPoint = await wslDrivesMountPoint();
25721
+ return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
25722
+ };
25723
+ var powerShellPath = async () => {
25724
+ if (is_wsl_default) {
25725
+ return powerShellPathFromWsl();
25726
+ }
25727
+ return `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
25728
+ };
25729
+
25730
+ // ../../node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js
25731
+ function defineLazyProperty(object2, propertyName, valueGetter) {
25732
+ const define = (value) => Object.defineProperty(object2, propertyName, { value, enumerable: true, writable: true });
25733
+ Object.defineProperty(object2, propertyName, {
25734
+ configurable: true,
25735
+ enumerable: true,
25736
+ get() {
25737
+ const result = valueGetter();
25738
+ define(result);
25739
+ return result;
25740
+ },
25741
+ set(value) {
25742
+ define(value);
25743
+ }
25744
+ });
25745
+ return object2;
25746
+ }
25747
+
25748
+ // ../../node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/index.js
25749
+ import { promisify as promisify4 } from "node:util";
25750
+ import process6 from "node:process";
25751
+ import { execFile as execFile4 } from "node:child_process";
25752
+
25753
+ // ../../node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
25754
+ import { promisify } from "node:util";
25755
+ import process4 from "node:process";
25756
+ import { execFile } from "node:child_process";
25757
+ var execFileAsync = promisify(execFile);
25758
+ async function defaultBrowserId() {
25759
+ if (process4.platform !== "darwin") {
25760
+ throw new Error("macOS only");
25761
+ }
25762
+ const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
25763
+ const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
25764
+ const browserId = match?.groups.id ?? "com.apple.Safari";
25765
+ if (browserId === "com.apple.safari") {
25766
+ return "com.apple.Safari";
25767
+ }
25768
+ return browserId;
25769
+ }
25770
+
25771
+ // ../../node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
25772
+ import process5 from "node:process";
25773
+ import { promisify as promisify2 } from "node:util";
25774
+ import { execFile as execFile2, execFileSync } from "node:child_process";
25775
+ var execFileAsync2 = promisify2(execFile2);
25776
+ async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
25777
+ if (process5.platform !== "darwin") {
25778
+ throw new Error("macOS only");
25779
+ }
25780
+ const outputArguments = humanReadableOutput ? [] : ["-ss"];
25781
+ const execOptions = {};
25782
+ if (signal) {
25783
+ execOptions.signal = signal;
25784
+ }
25785
+ const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments], execOptions);
25786
+ return stdout.trim();
25787
+ }
25788
+
25789
+ // ../../node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js
25790
+ async function bundleName(bundleId) {
25791
+ return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
25792
+ tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
25793
+ }
25794
+
25795
+ // ../../node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/windows.js
25796
+ import { promisify as promisify3 } from "node:util";
25797
+ import { execFile as execFile3 } from "node:child_process";
25798
+ var execFileAsync3 = promisify3(execFile3);
25799
+ var windowsBrowserProgIds = {
25800
+ MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
25801
+ // The missing `L` is correct.
25802
+ MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
25803
+ MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
25804
+ AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
25805
+ ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
25806
+ ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
25807
+ ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
25808
+ ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
25809
+ BraveHTML: { name: "Brave", id: "com.brave.Browser" },
25810
+ BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
25811
+ BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
25812
+ BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
25813
+ FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
25814
+ OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
25815
+ VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
25816
+ "IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
25817
+ };
25818
+ var _windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
25819
+ var UnknownBrowserError = class extends Error {
25820
+ };
25821
+ async function defaultBrowser(_execFileAsync = execFileAsync3) {
25822
+ const { stdout } = await _execFileAsync("reg", [
25823
+ "QUERY",
25824
+ " HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
25825
+ "/v",
25826
+ "ProgId"
25827
+ ]);
25828
+ const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
25829
+ if (!match) {
25830
+ throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
25831
+ }
25832
+ const { id } = match.groups;
25833
+ const dotIndex = id.lastIndexOf(".");
25834
+ const hyphenIndex = id.lastIndexOf("-");
25835
+ const baseIdByDot = dotIndex === -1 ? void 0 : id.slice(0, dotIndex);
25836
+ const baseIdByHyphen = hyphenIndex === -1 ? void 0 : id.slice(0, hyphenIndex);
25837
+ return windowsBrowserProgIds[id] ?? windowsBrowserProgIds[baseIdByDot] ?? windowsBrowserProgIds[baseIdByHyphen] ?? { name: id, id };
25838
+ }
25839
+
25840
+ // ../../node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/index.js
25841
+ var execFileAsync4 = promisify4(execFile4);
25842
+ var titleize = (string4) => string4.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
25843
+ async function defaultBrowser2() {
25844
+ if (process6.platform === "darwin") {
25845
+ const id = await defaultBrowserId();
25846
+ const name = await bundleName(id);
25847
+ return { name, id };
25848
+ }
25849
+ if (process6.platform === "linux") {
25850
+ const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
25851
+ const id = stdout.trim();
25852
+ const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
25853
+ return { name, id };
25854
+ }
25855
+ if (process6.platform === "win32") {
25856
+ return defaultBrowser();
25857
+ }
25858
+ throw new Error("Only macOS, Linux, and Windows are supported");
25859
+ }
25860
+
25861
+ // ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
25862
+ var execFile5 = promisify5(childProcess.execFile);
25863
+ var __dirname = path4.dirname(fileURLToPath(import.meta.url));
25864
+ var localXdgOpenPath = path4.join(__dirname, "xdg-open");
25865
+ var { platform, arch } = process7;
25866
+ async function getWindowsDefaultBrowserFromWsl() {
25867
+ const powershellPath = await powerShellPath();
25868
+ const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
25869
+ const encodedCommand = Buffer2.from(rawCommand, "utf16le").toString("base64");
25870
+ const { stdout } = await execFile5(
25871
+ powershellPath,
25872
+ [
25873
+ "-NoProfile",
25874
+ "-NonInteractive",
25875
+ "-ExecutionPolicy",
25876
+ "Bypass",
25877
+ "-EncodedCommand",
25878
+ encodedCommand
25879
+ ],
25880
+ { encoding: "utf8" }
25881
+ );
25882
+ const progId = stdout.trim();
25883
+ const browserMap = {
25884
+ ChromeHTML: "com.google.chrome",
25885
+ BraveHTML: "com.brave.Browser",
25886
+ MSEdgeHTM: "com.microsoft.edge",
25887
+ FirefoxURL: "org.mozilla.firefox"
25888
+ };
25889
+ return browserMap[progId] ? { id: browserMap[progId] } : {};
25890
+ }
25891
+ var pTryEach = async (array2, mapper) => {
25892
+ let latestError;
25893
+ for (const item of array2) {
25894
+ try {
25895
+ return await mapper(item);
25896
+ } catch (error40) {
25897
+ latestError = error40;
25898
+ }
25899
+ }
25900
+ throw latestError;
25901
+ };
25902
+ var baseOpen = async (options) => {
25903
+ options = {
25904
+ wait: false,
25905
+ background: false,
25906
+ newInstance: false,
25907
+ allowNonzeroExitCode: false,
25908
+ ...options
25909
+ };
25910
+ if (Array.isArray(options.app)) {
25911
+ return pTryEach(options.app, (singleApp) => baseOpen({
25912
+ ...options,
25913
+ app: singleApp
25914
+ }));
25915
+ }
25916
+ let { name: app, arguments: appArguments = [] } = options.app ?? {};
25917
+ appArguments = [...appArguments];
25918
+ if (Array.isArray(app)) {
25919
+ return pTryEach(app, (appName) => baseOpen({
25920
+ ...options,
25921
+ app: {
25922
+ name: appName,
25923
+ arguments: appArguments
25924
+ }
25925
+ }));
25926
+ }
25927
+ if (app === "browser" || app === "browserPrivate") {
25928
+ const ids = {
25929
+ "com.google.chrome": "chrome",
25930
+ "google-chrome.desktop": "chrome",
25931
+ "com.brave.Browser": "brave",
25932
+ "org.mozilla.firefox": "firefox",
25933
+ "firefox.desktop": "firefox",
25934
+ "com.microsoft.msedge": "edge",
25935
+ "com.microsoft.edge": "edge",
25936
+ "com.microsoft.edgemac": "edge",
25937
+ "microsoft-edge.desktop": "edge"
25938
+ };
25939
+ const flags = {
25940
+ chrome: "--incognito",
25941
+ brave: "--incognito",
25942
+ firefox: "--private-window",
25943
+ edge: "--inPrivate"
25944
+ };
25945
+ const browser = is_wsl_default ? await getWindowsDefaultBrowserFromWsl() : await defaultBrowser2();
25946
+ if (browser.id in ids) {
25947
+ const browserName = ids[browser.id];
25948
+ if (app === "browserPrivate") {
25949
+ appArguments.push(flags[browserName]);
25950
+ }
25951
+ return baseOpen({
25952
+ ...options,
25953
+ app: {
25954
+ name: apps[browserName],
25955
+ arguments: appArguments
25956
+ }
25957
+ });
25958
+ }
25959
+ throw new Error(`${browser.name} is not supported as a default browser`);
25960
+ }
25961
+ let command;
25962
+ const cliArguments = [];
25963
+ const childProcessOptions = {};
25964
+ if (platform === "darwin") {
25965
+ command = "open";
25966
+ if (options.wait) {
25967
+ cliArguments.push("--wait-apps");
25968
+ }
25969
+ if (options.background) {
25970
+ cliArguments.push("--background");
25971
+ }
25972
+ if (options.newInstance) {
25973
+ cliArguments.push("--new");
25974
+ }
25975
+ if (app) {
25976
+ cliArguments.push("-a", app);
25977
+ }
25978
+ } else if (platform === "win32" || is_wsl_default && !isInsideContainer() && !app) {
25979
+ command = await powerShellPath();
25980
+ cliArguments.push(
25981
+ "-NoProfile",
25982
+ "-NonInteractive",
25983
+ "-ExecutionPolicy",
25984
+ "Bypass",
25985
+ "-EncodedCommand"
25986
+ );
25987
+ if (!is_wsl_default) {
25988
+ childProcessOptions.windowsVerbatimArguments = true;
25989
+ }
25990
+ const encodedArguments = ["Start"];
25991
+ if (options.wait) {
25992
+ encodedArguments.push("-Wait");
25993
+ }
25994
+ if (app) {
25995
+ encodedArguments.push(`"\`"${app}\`""`);
25996
+ if (options.target) {
25997
+ appArguments.push(options.target);
25998
+ }
25999
+ } else if (options.target) {
26000
+ encodedArguments.push(`"${options.target}"`);
26001
+ }
26002
+ if (appArguments.length > 0) {
26003
+ appArguments = appArguments.map((argument) => `"\`"${argument}\`""`);
26004
+ encodedArguments.push("-ArgumentList", appArguments.join(","));
26005
+ }
26006
+ options.target = Buffer2.from(encodedArguments.join(" "), "utf16le").toString("base64");
26007
+ } else {
26008
+ if (app) {
26009
+ command = app;
26010
+ } else {
26011
+ const isBundled = !__dirname || __dirname === "/";
26012
+ let exeLocalXdgOpen = false;
26013
+ try {
26014
+ await fs7.access(localXdgOpenPath, fsConstants2.X_OK);
26015
+ exeLocalXdgOpen = true;
26016
+ } catch {
26017
+ }
26018
+ const useSystemXdgOpen = process7.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
26019
+ command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
26020
+ }
26021
+ if (appArguments.length > 0) {
26022
+ cliArguments.push(...appArguments);
26023
+ }
26024
+ if (!options.wait) {
26025
+ childProcessOptions.stdio = "ignore";
26026
+ childProcessOptions.detached = true;
26027
+ }
26028
+ }
26029
+ if (platform === "darwin" && appArguments.length > 0) {
26030
+ cliArguments.push("--args", ...appArguments);
26031
+ }
26032
+ if (options.target) {
26033
+ cliArguments.push(options.target);
26034
+ }
26035
+ const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
26036
+ if (options.wait) {
26037
+ return new Promise((resolve17, reject) => {
26038
+ subprocess.once("error", reject);
26039
+ subprocess.once("close", (exitCode) => {
26040
+ if (!options.allowNonzeroExitCode && exitCode > 0) {
26041
+ reject(new Error(`Exited with code ${exitCode}`));
26042
+ return;
26043
+ }
26044
+ resolve17(subprocess);
26045
+ });
26046
+ });
26047
+ }
26048
+ subprocess.unref();
26049
+ return subprocess;
26050
+ };
26051
+ var open = (target, options) => {
26052
+ if (typeof target !== "string") {
26053
+ throw new TypeError("Expected a `target`");
26054
+ }
26055
+ return baseOpen({
26056
+ ...options,
26057
+ target
26058
+ });
26059
+ };
26060
+ function detectArchBinary(binary) {
26061
+ if (typeof binary === "string" || Array.isArray(binary)) {
26062
+ return binary;
26063
+ }
26064
+ const { [arch]: archBinary } = binary;
26065
+ if (!archBinary) {
26066
+ throw new Error(`${arch} is not supported`);
26067
+ }
26068
+ return archBinary;
26069
+ }
26070
+ function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
26071
+ if (wsl && is_wsl_default) {
26072
+ return detectArchBinary(wsl);
26073
+ }
26074
+ if (!platformBinary) {
26075
+ throw new Error(`${platform} is not supported`);
26076
+ }
26077
+ return detectArchBinary(platformBinary);
26078
+ }
26079
+ var apps = {};
26080
+ defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
26081
+ darwin: "google chrome",
26082
+ win32: "chrome",
26083
+ linux: ["google-chrome", "google-chrome-stable", "chromium"]
26084
+ }, {
26085
+ wsl: {
26086
+ ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
26087
+ x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
26088
+ }
26089
+ }));
26090
+ defineLazyProperty(apps, "brave", () => detectPlatformBinary({
26091
+ darwin: "brave browser",
26092
+ win32: "brave",
26093
+ linux: ["brave-browser", "brave"]
26094
+ }, {
26095
+ wsl: {
26096
+ ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
26097
+ x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
26098
+ }
26099
+ }));
26100
+ defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
26101
+ darwin: "firefox",
26102
+ win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
26103
+ linux: "firefox"
26104
+ }, {
26105
+ wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
26106
+ }));
26107
+ defineLazyProperty(apps, "edge", () => detectPlatformBinary({
26108
+ darwin: "microsoft edge",
26109
+ win32: "msedge",
26110
+ linux: ["microsoft-edge", "microsoft-edge-dev"]
26111
+ }, {
26112
+ wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
26113
+ }));
26114
+ defineLazyProperty(apps, "browser", () => "browser");
26115
+ defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
26116
+ var open_default = open;
26117
+
25324
26118
  // src/auth/open-browser.ts
25325
- import { execSync } from "node:child_process";
25326
26119
  function isLocalApiUrl(apiUrl) {
25327
26120
  try {
25328
26121
  const u = new URL(apiUrl);
@@ -25332,8 +26125,11 @@ function isLocalApiUrl(apiUrl) {
25332
26125
  return false;
25333
26126
  }
25334
26127
  }
25335
- function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn = log) {
25336
- const appUrl = apiUrl && isLocalApiUrl(apiUrl) ? process.env.BUILDAUTOMATON_APP_URL ?? "http://localhost:3000" : process.env.BUILDAUTOMATON_APP_URL ?? "https://app.buildautomaton.com";
26128
+ function appUrlForApiUrl(apiUrl) {
26129
+ return apiUrl && isLocalApiUrl(apiUrl) ? process.env.BUILDAUTOMATON_APP_URL ?? "http://localhost:3000" : process.env.BUILDAUTOMATON_APP_URL ?? "https://app.buildautomaton.com";
26130
+ }
26131
+ async function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn = log) {
26132
+ const appUrl = appUrlForApiUrl(apiUrl);
25337
26133
  let connectCliUrl = `${appUrl.replace(/\/$/, "")}/bridges/connect?connectionId=${connectionId}`;
25338
26134
  if (initialWorkspaceId) {
25339
26135
  try {
@@ -25346,10 +26142,11 @@ function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiU
25346
26142
  connectCliUrl += `&bridgeName=${encodeURIComponent(preferredBridgeName.trim())}`;
25347
26143
  }
25348
26144
  logFn("Opening browser to link this CLI\u2026");
25349
- logFn("If you\u2019re already signed in with one workspace, the CLI will connect automatically. Otherwise sign in and link to a workspace.");
26145
+ logFn(
26146
+ "If you\u2019re already signed in with one workspace, the CLI will connect automatically. Otherwise sign in and link to a workspace."
26147
+ );
25350
26148
  try {
25351
- const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
25352
- execSync(`${cmd} "${connectCliUrl}"`, { stdio: "ignore" });
26149
+ await open_default(connectCliUrl, { wait: false });
25353
26150
  } catch {
25354
26151
  logFn("Could not open browser. Open this URL manually:");
25355
26152
  logFn(connectCliUrl);
@@ -25540,8 +26337,8 @@ function runPendingAuth(options) {
25540
26337
  let hasOpenedBrowser = false;
25541
26338
  let resolved = false;
25542
26339
  let resolveAuth;
25543
- const authPromise = new Promise((resolve16) => {
25544
- resolveAuth = resolve16;
26340
+ const authPromise = new Promise((resolve17) => {
26341
+ resolveAuth = resolve17;
25545
26342
  });
25546
26343
  let reconnectAttempt = 0;
25547
26344
  const signInQuiet = createEmptyReconnectQuietSlot();
@@ -25604,7 +26401,7 @@ function runPendingAuth(options) {
25604
26401
  }
25605
26402
  if (!hasOpenedBrowser) {
25606
26403
  hasOpenedBrowser = true;
25607
- openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn);
26404
+ void openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn);
25608
26405
  }
25609
26406
  },
25610
26407
  onClose: (code, reason) => {
@@ -25646,7 +26443,7 @@ function runPendingAuth(options) {
25646
26443
  browserFallback = null;
25647
26444
  if (!hasOpenedBrowser) {
25648
26445
  hasOpenedBrowser = true;
25649
- openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn);
26446
+ void openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn);
25650
26447
  }
25651
26448
  }, BROWSER_OPEN_FALLBACK_MS);
25652
26449
  connect();
@@ -25663,7 +26460,7 @@ function runPendingAuth(options) {
25663
26460
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
25664
26461
  const say = log2 ?? logImmediate;
25665
26462
  say("Cleaning up connections\u2026");
25666
- await new Promise((resolve16) => setImmediate(resolve16));
26463
+ await new Promise((resolve17) => setImmediate(resolve17));
25667
26464
  state.closedByUser = true;
25668
26465
  clearReconnectQuietTimer(state.mainQuiet);
25669
26466
  clearReconnectQuietTimer(state.firehoseQuiet);
@@ -25733,27 +26530,27 @@ function localAgentErrorSuggestsAuth(agentType, errorText) {
25733
26530
  }
25734
26531
 
25735
26532
  // src/git/session-git-queue.ts
25736
- import { execFile as execFile2 } from "node:child_process";
25737
- import { readFile, stat } from "node:fs/promises";
25738
- import { promisify as promisify2 } from "node:util";
25739
- import * as path5 from "node:path";
26533
+ import { execFile as execFile7 } from "node:child_process";
26534
+ import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
26535
+ import { promisify as promisify7 } from "node:util";
26536
+ import * as path7 from "node:path";
25740
26537
 
25741
26538
  // src/git/pre-turn-snapshot.ts
25742
- import * as fs3 from "node:fs";
25743
- import * as path4 from "node:path";
25744
- import { execFile } from "node:child_process";
25745
- import { promisify } from "node:util";
26539
+ import * as fs9 from "node:fs";
26540
+ import * as path6 from "node:path";
26541
+ import { execFile as execFile6 } from "node:child_process";
26542
+ import { promisify as promisify6 } from "node:util";
25746
26543
 
25747
26544
  // src/git/discover-repos.ts
25748
- import * as fs2 from "node:fs";
25749
- import * as path3 from "node:path";
26545
+ import * as fs8 from "node:fs";
26546
+ import * as path5 from "node:path";
25750
26547
 
25751
26548
  // ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
25752
26549
  var import_file_exists = __toESM(require_dist(), 1);
25753
26550
  var import_debug = __toESM(require_src(), 1);
25754
26551
  var import_promise_deferred = __toESM(require_dist2(), 1);
25755
26552
  var import_promise_deferred2 = __toESM(require_dist2(), 1);
25756
- import { Buffer as Buffer2 } from "node:buffer";
26553
+ import { Buffer as Buffer22 } from "node:buffer";
25757
26554
  import { spawn } from "child_process";
25758
26555
  import { normalize } from "node:path";
25759
26556
  import { EventEmitter } from "node:events";
@@ -25785,8 +26582,8 @@ function pathspec(...paths) {
25785
26582
  cache.set(key, paths);
25786
26583
  return key;
25787
26584
  }
25788
- function isPathSpec(path32) {
25789
- return path32 instanceof String && cache.has(path32);
26585
+ function isPathSpec(path34) {
26586
+ return path34 instanceof String && cache.has(path34);
25790
26587
  }
25791
26588
  function toPaths(pathSpec) {
25792
26589
  return cache.get(pathSpec) || [];
@@ -25875,8 +26672,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
25875
26672
  function forEachLineWithContent(input, callback) {
25876
26673
  return toLinesWithContent(input, true).map((line) => callback(line));
25877
26674
  }
25878
- function folderExists(path32) {
25879
- return (0, import_file_exists.exists)(path32, import_file_exists.FOLDER);
26675
+ function folderExists(path34) {
26676
+ return (0, import_file_exists.exists)(path34, import_file_exists.FOLDER);
25880
26677
  }
25881
26678
  function append(target, item) {
25882
26679
  if (Array.isArray(target)) {
@@ -25933,7 +26730,7 @@ function prefixedArray(input, prefix) {
25933
26730
  return output;
25934
26731
  }
25935
26732
  function bufferToString(input) {
25936
- return (Array.isArray(input) ? Buffer2.concat(input) : input).toString("utf-8");
26733
+ return (Array.isArray(input) ? Buffer22.concat(input) : input).toString("utf-8");
25937
26734
  }
25938
26735
  function pick(source, properties) {
25939
26736
  const out = {};
@@ -26280,8 +27077,8 @@ function checkIsRepoRootTask() {
26280
27077
  commands,
26281
27078
  format: "utf-8",
26282
27079
  onError,
26283
- parser(path32) {
26284
- return /^\.(git)?$/.test(path32.trim());
27080
+ parser(path34) {
27081
+ return /^\.(git)?$/.test(path34.trim());
26285
27082
  }
26286
27083
  };
26287
27084
  }
@@ -26715,11 +27512,11 @@ function parseGrep(grep) {
26715
27512
  const paths = /* @__PURE__ */ new Set();
26716
27513
  const results = {};
26717
27514
  forEachLineWithContent(grep, (input) => {
26718
- const [path32, line, preview] = input.split(NULL);
26719
- paths.add(path32);
26720
- (results[path32] = results[path32] || []).push({
27515
+ const [path34, line, preview] = input.split(NULL);
27516
+ paths.add(path34);
27517
+ (results[path34] = results[path34] || []).push({
26721
27518
  line: asNumber(line),
26722
- path: path32,
27519
+ path: path34,
26723
27520
  preview
26724
27521
  });
26725
27522
  });
@@ -27484,14 +28281,14 @@ var init_hash_object = __esm2({
27484
28281
  init_task();
27485
28282
  }
27486
28283
  });
27487
- function parseInit(bare, path32, text) {
28284
+ function parseInit(bare, path34, text) {
27488
28285
  const response = String(text).trim();
27489
28286
  let result;
27490
28287
  if (result = initResponseRegex.exec(response)) {
27491
- return new InitSummary(bare, path32, false, result[1]);
28288
+ return new InitSummary(bare, path34, false, result[1]);
27492
28289
  }
27493
28290
  if (result = reInitResponseRegex.exec(response)) {
27494
- return new InitSummary(bare, path32, true, result[1]);
28291
+ return new InitSummary(bare, path34, true, result[1]);
27495
28292
  }
27496
28293
  let gitDir = "";
27497
28294
  const tokens = response.split(" ");
@@ -27502,7 +28299,7 @@ function parseInit(bare, path32, text) {
27502
28299
  break;
27503
28300
  }
27504
28301
  }
27505
- return new InitSummary(bare, path32, /^re/i.test(response), gitDir);
28302
+ return new InitSummary(bare, path34, /^re/i.test(response), gitDir);
27506
28303
  }
27507
28304
  var InitSummary;
27508
28305
  var initResponseRegex;
@@ -27511,9 +28308,9 @@ var init_InitSummary = __esm2({
27511
28308
  "src/lib/responses/InitSummary.ts"() {
27512
28309
  "use strict";
27513
28310
  InitSummary = class {
27514
- constructor(bare, path32, existing, gitDir) {
28311
+ constructor(bare, path34, existing, gitDir) {
27515
28312
  this.bare = bare;
27516
- this.path = path32;
28313
+ this.path = path34;
27517
28314
  this.existing = existing;
27518
28315
  this.gitDir = gitDir;
27519
28316
  }
@@ -27525,7 +28322,7 @@ var init_InitSummary = __esm2({
27525
28322
  function hasBareCommand(command) {
27526
28323
  return command.includes(bareCommand);
27527
28324
  }
27528
- function initTask(bare = false, path32, customArgs) {
28325
+ function initTask(bare = false, path34, customArgs) {
27529
28326
  const commands = ["init", ...customArgs];
27530
28327
  if (bare && !hasBareCommand(commands)) {
27531
28328
  commands.splice(1, 0, bareCommand);
@@ -27534,7 +28331,7 @@ function initTask(bare = false, path32, customArgs) {
27534
28331
  commands,
27535
28332
  format: "utf-8",
27536
28333
  parser(text) {
27537
- return parseInit(commands.includes("--bare"), path32, text);
28334
+ return parseInit(commands.includes("--bare"), path34, text);
27538
28335
  }
27539
28336
  };
27540
28337
  }
@@ -28350,12 +29147,12 @@ var init_FileStatusSummary = __esm2({
28350
29147
  "use strict";
28351
29148
  fromPathRegex = /^(.+)\0(.+)$/;
28352
29149
  FileStatusSummary = class {
28353
- constructor(path32, index, working_dir) {
28354
- this.path = path32;
29150
+ constructor(path34, index, working_dir) {
29151
+ this.path = path34;
28355
29152
  this.index = index;
28356
29153
  this.working_dir = working_dir;
28357
29154
  if (index === "R" || working_dir === "R") {
28358
- const detail = fromPathRegex.exec(path32) || [null, path32, path32];
29155
+ const detail = fromPathRegex.exec(path34) || [null, path34, path34];
28359
29156
  this.from = detail[2] || "";
28360
29157
  this.path = detail[1] || "";
28361
29158
  }
@@ -28386,14 +29183,14 @@ function splitLine(result, lineStr) {
28386
29183
  default:
28387
29184
  return;
28388
29185
  }
28389
- function data(index, workingDir, path32) {
29186
+ function data(index, workingDir, path34) {
28390
29187
  const raw = `${index}${workingDir}`;
28391
29188
  const handler = parsers6.get(raw);
28392
29189
  if (handler) {
28393
- handler(result, path32);
29190
+ handler(result, path34);
28394
29191
  }
28395
29192
  if (raw !== "##" && raw !== "!!") {
28396
- result.files.push(new FileStatusSummary(path32, index, workingDir));
29193
+ result.files.push(new FileStatusSummary(path34, index, workingDir));
28397
29194
  }
28398
29195
  }
28399
29196
  }
@@ -28702,9 +29499,9 @@ var init_simple_git_api = __esm2({
28702
29499
  next
28703
29500
  );
28704
29501
  }
28705
- hashObject(path32, write) {
29502
+ hashObject(path34, write) {
28706
29503
  return this._runTask(
28707
- hashObjectTask(path32, write === true),
29504
+ hashObjectTask(path34, write === true),
28708
29505
  trailingFunctionArgument(arguments)
28709
29506
  );
28710
29507
  }
@@ -29057,8 +29854,8 @@ var init_branch = __esm2({
29057
29854
  }
29058
29855
  });
29059
29856
  function toPath(input) {
29060
- const path32 = input.trim().replace(/^["']|["']$/g, "");
29061
- return path32 && normalize(path32);
29857
+ const path34 = input.trim().replace(/^["']|["']$/g, "");
29858
+ return path34 && normalize(path34);
29062
29859
  }
29063
29860
  var parseCheckIgnore;
29064
29861
  var init_CheckIgnore = __esm2({
@@ -29372,8 +30169,8 @@ __export2(sub_module_exports, {
29372
30169
  subModuleTask: () => subModuleTask,
29373
30170
  updateSubModuleTask: () => updateSubModuleTask
29374
30171
  });
29375
- function addSubModuleTask(repo, path32) {
29376
- return subModuleTask(["add", repo, path32]);
30172
+ function addSubModuleTask(repo, path34) {
30173
+ return subModuleTask(["add", repo, path34]);
29377
30174
  }
29378
30175
  function initSubModuleTask(customArgs) {
29379
30176
  return subModuleTask(["init", ...customArgs]);
@@ -29706,8 +30503,8 @@ var require_git = __commonJS2({
29706
30503
  }
29707
30504
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
29708
30505
  };
29709
- Git2.prototype.submoduleAdd = function(repo, path32, then) {
29710
- return this._runTask(addSubModuleTask2(repo, path32), trailingFunctionArgument2(arguments));
30506
+ Git2.prototype.submoduleAdd = function(repo, path34, then) {
30507
+ return this._runTask(addSubModuleTask2(repo, path34), trailingFunctionArgument2(arguments));
29711
30508
  };
29712
30509
  Git2.prototype.submoduleUpdate = function(args, then) {
29713
30510
  return this._runTask(
@@ -30333,20 +31130,20 @@ async function isGitRepoDirectory(dirPath) {
30333
31130
  // src/git/discover-repos.ts
30334
31131
  async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
30335
31132
  const result = [];
30336
- const cwdResolved = path3.resolve(cwd);
31133
+ const cwdResolved = path5.resolve(cwd);
30337
31134
  if (await isGitRepoDirectory(cwdResolved)) {
30338
31135
  const remoteUrl = await getRemoteOriginUrl(cwdResolved);
30339
31136
  result.push({ absolutePath: cwdResolved, remoteUrl });
30340
31137
  }
30341
31138
  let entries;
30342
31139
  try {
30343
- entries = fs2.readdirSync(cwdResolved, { withFileTypes: true });
31140
+ entries = fs8.readdirSync(cwdResolved, { withFileTypes: true });
30344
31141
  } catch {
30345
31142
  return result;
30346
31143
  }
30347
31144
  for (const ent of entries) {
30348
31145
  if (!ent.isDirectory()) continue;
30349
- const childPath = path3.join(cwdResolved, ent.name);
31146
+ const childPath = path5.join(cwdResolved, ent.name);
30350
31147
  if (await isGitRepoDirectory(childPath)) {
30351
31148
  const remoteUrl = await getRemoteOriginUrl(childPath);
30352
31149
  result.push({ absolutePath: childPath, remoteUrl });
@@ -30355,22 +31152,22 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
30355
31152
  return result;
30356
31153
  }
30357
31154
  async function discoverGitReposUnderRoot(rootAbs) {
30358
- const root = path3.resolve(rootAbs);
31155
+ const root = path5.resolve(rootAbs);
30359
31156
  const roots = [];
30360
31157
  async function walk(dir) {
30361
31158
  if (await isGitRepoDirectory(dir)) {
30362
- roots.push(path3.resolve(dir));
31159
+ roots.push(path5.resolve(dir));
30363
31160
  return;
30364
31161
  }
30365
31162
  let entries;
30366
31163
  try {
30367
- entries = fs2.readdirSync(dir, { withFileTypes: true });
31164
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
30368
31165
  } catch {
30369
31166
  return;
30370
31167
  }
30371
31168
  for (const ent of entries) {
30372
31169
  if (!ent.isDirectory() || ent.name === ".git") continue;
30373
- await walk(path3.join(dir, ent.name));
31170
+ await walk(path5.join(dir, ent.name));
30374
31171
  }
30375
31172
  }
30376
31173
  await walk(root);
@@ -30384,13 +31181,13 @@ async function discoverGitReposUnderRoot(rootAbs) {
30384
31181
  }
30385
31182
 
30386
31183
  // src/git/pre-turn-snapshot.ts
30387
- var execFileAsync = promisify(execFile);
31184
+ var execFileAsync5 = promisify6(execFile6);
30388
31185
  function snapshotsDirForCwd(agentCwd) {
30389
- return path4.join(agentCwd, ".buildautomaton", "snapshots");
31186
+ return path6.join(agentCwd, ".buildautomaton", "snapshots");
30390
31187
  }
30391
31188
  async function gitStashCreate(repoRoot, log2) {
30392
31189
  try {
30393
- const { stdout } = await execFileAsync("git", ["stash", "create"], {
31190
+ const { stdout } = await execFileAsync5("git", ["stash", "create"], {
30394
31191
  cwd: repoRoot,
30395
31192
  maxBuffer: 10 * 1024 * 1024
30396
31193
  });
@@ -30404,7 +31201,7 @@ async function gitStashCreate(repoRoot, log2) {
30404
31201
  }
30405
31202
  async function gitRun(repoRoot, args, log2, label) {
30406
31203
  try {
30407
- await execFileAsync("git", args, { cwd: repoRoot, maxBuffer: 10 * 1024 * 1024 });
31204
+ await execFileAsync5("git", args, { cwd: repoRoot, maxBuffer: 10 * 1024 * 1024 });
30408
31205
  return { ok: true };
30409
31206
  } catch (e) {
30410
31207
  const msg = e instanceof Error ? e.message : String(e);
@@ -30415,7 +31212,7 @@ async function gitRun(repoRoot, args, log2, label) {
30415
31212
  async function resolveSnapshotRepoRoots(options) {
30416
31213
  const { worktreePaths, fallbackCwd, log: log2 } = options;
30417
31214
  if (worktreePaths?.length) {
30418
- const uniq = [...new Set(worktreePaths.map((p) => path4.resolve(p)))];
31215
+ const uniq = [...new Set(worktreePaths.map((p) => path6.resolve(p)))];
30419
31216
  return uniq;
30420
31217
  }
30421
31218
  try {
@@ -30438,7 +31235,7 @@ async function capturePreTurnSnapshot(options) {
30438
31235
  }
30439
31236
  const dir = snapshotsDirForCwd(agentCwd);
30440
31237
  try {
30441
- fs3.mkdirSync(dir, { recursive: true });
31238
+ fs9.mkdirSync(dir, { recursive: true });
30442
31239
  } catch (e) {
30443
31240
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
30444
31241
  }
@@ -30447,9 +31244,9 @@ async function capturePreTurnSnapshot(options) {
30447
31244
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
30448
31245
  repos
30449
31246
  };
30450
- const filePath = path4.join(dir, `${runId}.json`);
31247
+ const filePath = path6.join(dir, `${runId}.json`);
30451
31248
  try {
30452
- fs3.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
31249
+ fs9.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
30453
31250
  } catch (e) {
30454
31251
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
30455
31252
  }
@@ -30462,7 +31259,7 @@ async function capturePreTurnSnapshot(options) {
30462
31259
  async function applyPreTurnSnapshot(filePath, log2) {
30463
31260
  let data;
30464
31261
  try {
30465
- const raw = fs3.readFileSync(filePath, "utf8");
31262
+ const raw = fs9.readFileSync(filePath, "utf8");
30466
31263
  data = JSON.parse(raw);
30467
31264
  } catch (e) {
30468
31265
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
@@ -30485,17 +31282,17 @@ async function applyPreTurnSnapshot(filePath, log2) {
30485
31282
  return { ok: true };
30486
31283
  }
30487
31284
  function snapshotFilePath(agentCwd, runId) {
30488
- return path4.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
31285
+ return path6.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
30489
31286
  }
30490
31287
 
30491
31288
  // src/git/session-git-queue.ts
30492
- var execFileAsync2 = promisify2(execFile2);
31289
+ var execFileAsync6 = promisify7(execFile7);
30493
31290
  var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
30494
31291
  async function readWorkspaceFileAsUtf8(absPath) {
30495
31292
  try {
30496
- const st = await stat(absPath);
31293
+ const st = await stat2(absPath);
30497
31294
  if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
30498
- return await readFile(absPath, "utf8");
31295
+ return await readFile2(absPath, "utf8");
30499
31296
  } catch {
30500
31297
  return void 0;
30501
31298
  }
@@ -30505,7 +31302,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
30505
31302
  const filePath = snapshotFilePath(agentCwd, runId);
30506
31303
  let data;
30507
31304
  try {
30508
- const raw = await readFile(filePath, "utf8");
31305
+ const raw = await readFile2(filePath, "utf8");
30509
31306
  data = JSON.parse(raw);
30510
31307
  } catch (e) {
30511
31308
  log2(
@@ -30522,7 +31319,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
30522
31319
  if (!repo.stashSha) continue;
30523
31320
  let namesRaw;
30524
31321
  try {
30525
- const { stdout } = await execFileAsync2("git", ["diff", "--name-only", repo.stashSha], {
31322
+ const { stdout } = await execFileAsync6("git", ["diff", "--name-only", repo.stashSha], {
30526
31323
  cwd: repo.path,
30527
31324
  maxBuffer: 10 * 1024 * 1024
30528
31325
  });
@@ -30534,11 +31331,11 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
30534
31331
  continue;
30535
31332
  }
30536
31333
  const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
30537
- const slug = path5.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
31334
+ const slug = path7.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
30538
31335
  for (const rel of lines) {
30539
31336
  if (rel.includes("..")) continue;
30540
31337
  try {
30541
- const { stdout: patchContent } = await execFileAsync2(
31338
+ const { stdout: patchContent } = await execFileAsync6(
30542
31339
  "git",
30543
31340
  ["diff", "--no-color", repo.stashSha, "--", rel],
30544
31341
  {
@@ -30548,7 +31345,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
30548
31345
  );
30549
31346
  if (!patchContent.trim()) continue;
30550
31347
  const displayPath = multiRepo ? `${slug}/${rel}` : rel;
30551
- const absFile = path5.join(repo.path, rel);
31348
+ const absFile = path7.join(repo.path, rel);
30552
31349
  const newText = await readWorkspaceFileAsUtf8(absFile);
30553
31350
  sendSessionUpdate({
30554
31351
  type: "session_file_change",
@@ -30610,7 +31407,9 @@ async function sendPromptToAgent(options) {
30610
31407
  ...augmentAuthFields(errStr)
30611
31408
  });
30612
31409
  if (!result.success) {
30613
- log2(`[Agent] ${result.error ?? "Error"}`);
31410
+ log2(
31411
+ `[Agent] Prompt did not run successfully on the agent (no successful start/completion): ${result.error ?? "Unknown error"}`
31412
+ );
30614
31413
  }
30615
31414
  } catch (err) {
30616
31415
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -30628,8 +31427,8 @@ async function sendPromptToAgent(options) {
30628
31427
  }
30629
31428
 
30630
31429
  // src/agents/acp/ensure-acp-client.ts
30631
- import * as fs4 from "node:fs";
30632
- import * as path9 from "node:path";
31430
+ import * as fs10 from "node:fs";
31431
+ import * as path11 from "node:path";
30633
31432
 
30634
31433
  // src/error-message.ts
30635
31434
  function errorMessage(err) {
@@ -30649,16 +31448,16 @@ __export(claude_code_acp_client_exports, {
30649
31448
  createClaudeCodeAcpClient: () => createClaudeCodeAcpClient,
30650
31449
  detectLocalAgentPresence: () => detectLocalAgentPresence
30651
31450
  });
30652
- import { execFile as execFile4 } from "node:child_process";
30653
- import { promisify as promisify4 } from "node:util";
31451
+ import { execFile as execFile9 } from "node:child_process";
31452
+ import { promisify as promisify9 } from "node:util";
30654
31453
 
30655
31454
  // src/agents/acp/clients/detect-command-on-path.ts
30656
- import { execFile as execFile3 } from "node:child_process";
30657
- import { promisify as promisify3 } from "node:util";
30658
- var execFileAsync3 = promisify3(execFile3);
31455
+ import { execFile as execFile8 } from "node:child_process";
31456
+ import { promisify as promisify8 } from "node:util";
31457
+ var execFileAsync7 = promisify8(execFile8);
30659
31458
  async function isCommandOnPath(command, timeoutMs = 4e3) {
30660
31459
  try {
30661
- await execFileAsync3("which", [command], { timeout: timeoutMs });
31460
+ await execFileAsync7("which", [command], { timeout: timeoutMs });
30662
31461
  return true;
30663
31462
  } catch {
30664
31463
  return false;
@@ -30718,21 +31517,21 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
30718
31517
  }
30719
31518
 
30720
31519
  // src/agents/acp/safe-fs-path.ts
30721
- import * as path6 from "node:path";
31520
+ import * as path8 from "node:path";
30722
31521
  function resolveSafePathUnderCwd(cwd, filePath) {
30723
31522
  const trimmed2 = filePath.trim();
30724
31523
  if (!trimmed2) return null;
30725
- const normalizedCwd = path6.resolve(cwd);
30726
- const resolved = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.resolve(normalizedCwd, trimmed2);
30727
- const rel = path6.relative(normalizedCwd, resolved);
30728
- if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
31524
+ const normalizedCwd = path8.resolve(cwd);
31525
+ const resolved = path8.isAbsolute(trimmed2) ? path8.normalize(trimmed2) : path8.resolve(normalizedCwd, trimmed2);
31526
+ const rel = path8.relative(normalizedCwd, resolved);
31527
+ if (rel.startsWith("..") || path8.isAbsolute(rel)) return null;
30729
31528
  return resolved;
30730
31529
  }
30731
31530
  function toDisplayPathRelativeToCwd(cwd, absolutePath) {
30732
- const normalizedCwd = path6.resolve(cwd);
30733
- const rel = path6.relative(normalizedCwd, path6.resolve(absolutePath));
30734
- if (!rel || rel === "") return path6.basename(absolutePath);
30735
- return rel.split(path6.sep).join("/");
31531
+ const normalizedCwd = path8.resolve(cwd);
31532
+ const rel = path8.relative(normalizedCwd, path8.resolve(absolutePath));
31533
+ if (!rel || rel === "") return path8.basename(absolutePath);
31534
+ return rel.split(path8.sep).join("/");
30736
31535
  }
30737
31536
 
30738
31537
  // src/agents/acp/clients/agent-stderr-capture.ts
@@ -30852,7 +31651,7 @@ async function createSdkStdioAcpClient(options) {
30852
31651
  child.once("close", (code, signal) => {
30853
31652
  onAgentSubprocessExit?.({ code, signal });
30854
31653
  });
30855
- return new Promise((resolve16, reject) => {
31654
+ return new Promise((resolve17, reject) => {
30856
31655
  let initSettled = false;
30857
31656
  const settleReject = (err) => {
30858
31657
  if (initSettled) return;
@@ -30866,7 +31665,7 @@ async function createSdkStdioAcpClient(options) {
30866
31665
  const settleResolve = (handle) => {
30867
31666
  if (initSettled) return;
30868
31667
  initSettled = true;
30869
- resolve16(handle);
31668
+ resolve17(handle);
30870
31669
  };
30871
31670
  child.on("error", (err) => {
30872
31671
  settleReject(new Error(formatSpawnError(err, command[0])));
@@ -30902,8 +31701,8 @@ async function createSdkStdioAcpClient(options) {
30902
31701
  });
30903
31702
  } catch {
30904
31703
  }
30905
- return await new Promise((resolve17) => {
30906
- pendingPermissionResolvers.set(requestId, resolve17);
31704
+ return await new Promise((resolve18) => {
31705
+ pendingPermissionResolvers.set(requestId, resolve18);
30907
31706
  });
30908
31707
  },
30909
31708
  async readTextFile(params) {
@@ -31011,9 +31810,9 @@ async function createSdkStdioAcpClient(options) {
31011
31810
  }
31012
31811
  },
31013
31812
  async cancel() {
31014
- for (const [id, resolve17] of [...pendingPermissionResolvers.entries()]) {
31813
+ for (const [id, resolve18] of [...pendingPermissionResolvers.entries()]) {
31015
31814
  pendingPermissionResolvers.delete(id);
31016
- resolve17({ outcome: { outcome: "cancelled" } });
31815
+ resolve18({ outcome: { outcome: "cancelled" } });
31017
31816
  }
31018
31817
  try {
31019
31818
  await connection.cancel({ sessionId });
@@ -31029,10 +31828,10 @@ async function createSdkStdioAcpClient(options) {
31029
31828
  }
31030
31829
  },
31031
31830
  resolveRequest(requestId, result) {
31032
- const resolve17 = pendingPermissionResolvers.get(requestId);
31033
- if (!resolve17) return;
31831
+ const resolve18 = pendingPermissionResolvers.get(requestId);
31832
+ if (!resolve18) return;
31034
31833
  pendingPermissionResolvers.delete(requestId);
31035
- resolve17(result);
31834
+ resolve18(result);
31036
31835
  },
31037
31836
  disconnect() {
31038
31837
  child.kill();
@@ -31053,12 +31852,12 @@ async function createSdkStdioAcpClient(options) {
31053
31852
  }
31054
31853
 
31055
31854
  // src/agents/acp/clients/claude-code-acp-client.ts
31056
- var execFileAsync4 = promisify4(execFile4);
31855
+ var execFileAsync8 = promisify9(execFile9);
31057
31856
  var BACKEND_LOCAL_AGENT_TYPE = "claude-code";
31058
31857
  async function detectLocalAgentPresence() {
31059
31858
  if (await isCommandOnPath("claude")) return true;
31060
31859
  try {
31061
- await execFileAsync4("npx", ["--yes", "@anthropic-ai/claude-code", "--version"], { timeout: 25e3 });
31860
+ await execFileAsync8("npx", ["--yes", "@anthropic-ai/claude-code", "--version"], { timeout: 25e3 });
31062
31861
  return true;
31063
31862
  } catch {
31064
31863
  return false;
@@ -31173,7 +31972,7 @@ async function createCursorAcpClient(options) {
31173
31972
  onRequest,
31174
31973
  onFileChange
31175
31974
  } = options;
31176
- const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
31975
+ const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
31177
31976
  const isWindows = process.platform === "win32";
31178
31977
  const child = spawn3(command[0], command.slice(1), {
31179
31978
  cwd,
@@ -31183,7 +31982,7 @@ async function createCursorAcpClient(options) {
31183
31982
  });
31184
31983
  const stderrCapture = createStderrCapture(child);
31185
31984
  child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
31186
- return new Promise((resolve16, reject) => {
31985
+ return new Promise((resolve17, reject) => {
31187
31986
  child.on("error", (err) => {
31188
31987
  child.kill();
31189
31988
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -31370,7 +32169,7 @@ async function createCursorAcpClient(options) {
31370
32169
  const newResult = await send("session/new", { cwd, mcpServers: [] });
31371
32170
  const sessionId = newResult?.sessionId ?? "";
31372
32171
  if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
31373
- resolve16({
32172
+ resolve17({
31374
32173
  sessionId,
31375
32174
  async sendPrompt(prompt, _options) {
31376
32175
  promptOutputBuffer = "";
@@ -31556,48 +32355,48 @@ function resolveAgentCommand(preferredAgentType) {
31556
32355
  }
31557
32356
 
31558
32357
  // src/agents/acp/session-file-change-path-kind.ts
31559
- import { execFileSync as execFileSync3 } from "node:child_process";
32358
+ import { execFileSync as execFileSync4 } from "node:child_process";
31560
32359
  import { existsSync, statSync } from "node:fs";
31561
32360
 
31562
32361
  // src/git/get-git-repo-root-sync.ts
31563
- import { execFileSync } from "node:child_process";
31564
- import * as path7 from "node:path";
32362
+ import { execFileSync as execFileSync2 } from "node:child_process";
32363
+ import * as path9 from "node:path";
31565
32364
  function getGitRepoRootSync(startDir) {
31566
32365
  try {
31567
- const out = execFileSync("git", ["rev-parse", "--show-toplevel"], {
31568
- cwd: path7.resolve(startDir),
32366
+ const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
32367
+ cwd: path9.resolve(startDir),
31569
32368
  encoding: "utf8",
31570
32369
  stdio: ["ignore", "pipe", "ignore"],
31571
32370
  maxBuffer: 1024 * 1024
31572
32371
  }).trim();
31573
- return out ? path7.resolve(out) : null;
32372
+ return out ? path9.resolve(out) : null;
31574
32373
  } catch {
31575
32374
  return null;
31576
32375
  }
31577
32376
  }
31578
32377
 
31579
32378
  // src/agents/acp/workspace-files.ts
31580
- import { execFileSync as execFileSync2 } from "node:child_process";
32379
+ import { execFileSync as execFileSync3 } from "node:child_process";
31581
32380
  import { readFileSync as readFileSync4 } from "node:fs";
31582
- import * as path8 from "node:path";
32381
+ import * as path10 from "node:path";
31583
32382
  function resolveWorkspaceFilePath(cwd, rawPath) {
31584
32383
  const trimmed2 = rawPath.trim();
31585
32384
  if (!trimmed2) return null;
31586
- const normalizedCwd = path8.resolve(cwd);
32385
+ const normalizedCwd = path10.resolve(cwd);
31587
32386
  let abs = resolveSafePathUnderCwd(cwd, trimmed2);
31588
32387
  if (!abs) {
31589
- const candidate = path8.isAbsolute(trimmed2) ? path8.normalize(trimmed2) : path8.normalize(path8.resolve(normalizedCwd, trimmed2));
32388
+ const candidate = path10.isAbsolute(trimmed2) ? path10.normalize(trimmed2) : path10.normalize(path10.resolve(normalizedCwd, trimmed2));
31590
32389
  const gitRoot2 = getGitRepoRootSync(cwd);
31591
32390
  if (!gitRoot2) return null;
31592
- const rel = path8.relative(gitRoot2, candidate);
31593
- if (rel.startsWith("..") || path8.isAbsolute(rel)) return null;
32391
+ const rel = path10.relative(gitRoot2, candidate);
32392
+ if (rel.startsWith("..") || path10.isAbsolute(rel)) return null;
31594
32393
  abs = candidate;
31595
32394
  }
31596
32395
  const gitRoot = getGitRepoRootSync(cwd);
31597
32396
  if (gitRoot) {
31598
- const relFromRoot = path8.relative(gitRoot, abs);
31599
- if (!relFromRoot.startsWith("..") && !path8.isAbsolute(relFromRoot)) {
31600
- return { abs, display: relFromRoot.split(path8.sep).join("/") };
32397
+ const relFromRoot = path10.relative(gitRoot, abs);
32398
+ if (!relFromRoot.startsWith("..") && !path10.isAbsolute(relFromRoot)) {
32399
+ return { abs, display: relFromRoot.split(path10.sep).join("/") };
31601
32400
  }
31602
32401
  }
31603
32402
  return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
@@ -31606,9 +32405,9 @@ function readUtf8WorkspaceFile(cwd, displayPath) {
31606
32405
  if (!displayPath || displayPath.includes("..")) return "";
31607
32406
  const gitRoot = getGitRepoRootSync(cwd);
31608
32407
  if (gitRoot) {
31609
- const abs2 = path8.resolve(gitRoot, displayPath);
31610
- const rel = path8.relative(gitRoot, abs2);
31611
- if (!rel.startsWith("..") && !path8.isAbsolute(rel)) {
32408
+ const abs2 = path10.resolve(gitRoot, displayPath);
32409
+ const rel = path10.relative(gitRoot, abs2);
32410
+ if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
31612
32411
  try {
31613
32412
  return readFileSync4(abs2, "utf8");
31614
32413
  } catch {
@@ -31627,9 +32426,9 @@ function tryWorkspaceDisplayToAbs(cwd, displayPath) {
31627
32426
  if (!displayPath || displayPath.includes("..")) return null;
31628
32427
  const gitRoot = getGitRepoRootSync(cwd);
31629
32428
  if (gitRoot) {
31630
- const abs = path8.resolve(gitRoot, displayPath);
31631
- const rel = path8.relative(gitRoot, abs);
31632
- if (!rel.startsWith("..") && !path8.isAbsolute(rel)) return abs;
32429
+ const abs = path10.resolve(gitRoot, displayPath);
32430
+ const rel = path10.relative(gitRoot, abs);
32431
+ if (!rel.startsWith("..") && !path10.isAbsolute(rel)) return abs;
31633
32432
  }
31634
32433
  return resolveSafePathUnderCwd(cwd, displayPath);
31635
32434
  }
@@ -31638,7 +32437,7 @@ function readGitHeadBlob(cwd, displayPath) {
31638
32437
  const gitRoot = getGitRepoRootSync(cwd);
31639
32438
  const execCwd = gitRoot ?? cwd;
31640
32439
  try {
31641
- return execFileSync2("git", ["show", `HEAD:${displayPath}`], {
32440
+ return execFileSync3("git", ["show", `HEAD:${displayPath}`], {
31642
32441
  cwd: execCwd,
31643
32442
  encoding: "utf8",
31644
32443
  maxBuffer: 50 * 1024 * 1024
@@ -31654,7 +32453,7 @@ function gitHeadPathObjectType(cwd, displayPath) {
31654
32453
  const gitRoot = getGitRepoRootSync(cwd);
31655
32454
  if (!gitRoot) return null;
31656
32455
  try {
31657
- return execFileSync3("git", ["cat-file", "-t", `HEAD:${displayPath}`], {
32456
+ return execFileSync4("git", ["cat-file", "-t", `HEAD:${displayPath}`], {
31658
32457
  cwd: gitRoot,
31659
32458
  encoding: "utf8"
31660
32459
  }).trim();
@@ -31745,7 +32544,7 @@ function createBridgeOnRequest(opts) {
31745
32544
  }
31746
32545
 
31747
32546
  // src/agents/acp/hooks/extract-acp-file-diffs-from-update/paths-and-text.ts
31748
- import { fileURLToPath } from "node:url";
32547
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
31749
32548
  function readOptionalTextField(v) {
31750
32549
  if (v === null || v === void 0) return "";
31751
32550
  if (typeof v === "string") return v;
@@ -31755,7 +32554,7 @@ function normalizePathField(raw) {
31755
32554
  const t = raw.trim();
31756
32555
  if (t.startsWith("file://")) {
31757
32556
  try {
31758
- return fileURLToPath(t);
32557
+ return fileURLToPath2(t);
31759
32558
  } catch {
31760
32559
  return t;
31761
32560
  }
@@ -32197,10 +32996,10 @@ function buildAcpSessionBridgeHooks(opts) {
32197
32996
  // src/agents/acp/ensure-acp-client.ts
32198
32997
  async function ensureAcpClient(options) {
32199
32998
  const { state, preferredAgentType, mode, cwd, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
32200
- const targetCwd = path9.resolve(
32999
+ const targetCwd = path11.resolve(
32201
33000
  cwd != null && String(cwd).trim() !== "" ? String(cwd).trim() : getBridgeWorkspaceDirectory()
32202
33001
  );
32203
- if (state.acpHandle && state.lastAcpCwd != null && path9.resolve(state.lastAcpCwd) !== path9.resolve(targetCwd)) {
33002
+ if (state.acpHandle && state.lastAcpCwd != null && path11.resolve(state.lastAcpCwd) !== path11.resolve(targetCwd)) {
32204
33003
  try {
32205
33004
  state.acpHandle.disconnect();
32206
33005
  } catch {
@@ -32232,7 +33031,7 @@ async function ensureAcpClient(options) {
32232
33031
  if (!state.acpStartPromise) {
32233
33032
  let statOk = false;
32234
33033
  try {
32235
- const st = fs4.statSync(targetCwd);
33034
+ const st = fs10.statSync(targetCwd);
32236
33035
  statOk = st.isDirectory();
32237
33036
  if (!statOk) {
32238
33037
  state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
@@ -32428,12 +33227,12 @@ async function createAcpManager(options) {
32428
33227
  }
32429
33228
 
32430
33229
  // src/worktrees/session-worktree-manager.ts
32431
- import * as path15 from "node:path";
32432
- import os3 from "node:os";
33230
+ import * as path17 from "node:path";
33231
+ import os4 from "node:os";
32433
33232
 
32434
33233
  // src/worktrees/prepare-new-session-worktrees.ts
32435
- import * as fs6 from "node:fs";
32436
- import * as path11 from "node:path";
33234
+ import * as fs12 from "node:fs";
33235
+ import * as path13 from "node:path";
32437
33236
 
32438
33237
  // src/git/worktree-add.ts
32439
33238
  async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
@@ -32442,12 +33241,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
32442
33241
  }
32443
33242
 
32444
33243
  // src/worktrees/worktree-layout-file.ts
32445
- import * as fs5 from "node:fs";
32446
- import * as path10 from "node:path";
32447
- import os2 from "node:os";
33244
+ import * as fs11 from "node:fs";
33245
+ import * as path12 from "node:path";
33246
+ import os3 from "node:os";
32448
33247
  var LAYOUT_FILENAME = "worktree-launcher-layout.json";
32449
33248
  function defaultWorktreeLayoutPath() {
32450
- return path10.join(os2.homedir(), ".buildautomaton", LAYOUT_FILENAME);
33249
+ return path12.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
32451
33250
  }
32452
33251
  function normalizeLoadedLayout(raw) {
32453
33252
  if (raw && typeof raw === "object" && "launcherCwds" in raw) {
@@ -32459,8 +33258,8 @@ function normalizeLoadedLayout(raw) {
32459
33258
  function loadWorktreeLayout() {
32460
33259
  try {
32461
33260
  const p = defaultWorktreeLayoutPath();
32462
- if (!fs5.existsSync(p)) return { launcherCwds: [] };
32463
- const raw = JSON.parse(fs5.readFileSync(p, "utf8"));
33261
+ if (!fs11.existsSync(p)) return { launcherCwds: [] };
33262
+ const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
32464
33263
  return normalizeLoadedLayout(raw);
32465
33264
  } catch {
32466
33265
  return { launcherCwds: [] };
@@ -32468,18 +33267,18 @@ function loadWorktreeLayout() {
32468
33267
  }
32469
33268
  function saveWorktreeLayout(layout) {
32470
33269
  try {
32471
- const dir = path10.dirname(defaultWorktreeLayoutPath());
32472
- fs5.mkdirSync(dir, { recursive: true });
32473
- fs5.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
33270
+ const dir = path12.dirname(defaultWorktreeLayoutPath());
33271
+ fs11.mkdirSync(dir, { recursive: true });
33272
+ fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
32474
33273
  } catch {
32475
33274
  }
32476
33275
  }
32477
33276
  function baseNameSafe(abs) {
32478
- return path10.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
33277
+ return path12.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
32479
33278
  }
32480
33279
  function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
32481
- const norm = path10.resolve(launcherCwdAbs);
32482
- const existing = layout.launcherCwds.find((e) => path10.resolve(e.absolutePath) === norm);
33280
+ const norm = path12.resolve(launcherCwdAbs);
33281
+ const existing = layout.launcherCwds.find((e) => path12.resolve(e.absolutePath) === norm);
32483
33282
  if (existing) return existing.dirName;
32484
33283
  const base = baseNameSafe(norm);
32485
33284
  const used = new Set(layout.launcherCwds.map((e) => e.dirName));
@@ -32497,9 +33296,9 @@ function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
32497
33296
  // src/worktrees/prepare-new-session-worktrees.ts
32498
33297
  async function prepareNewSessionWorktrees(options) {
32499
33298
  const { rootAbs, launcherCwd, sessionId, layout, log: log2 } = options;
32500
- const launcherResolved = path11.resolve(launcherCwd);
33299
+ const launcherResolved = path13.resolve(launcherCwd);
32501
33300
  const cwdKey = allocateDirNameForLauncherCwd(layout, launcherResolved);
32502
- const agentMirrorRoot = path11.join(rootAbs, cwdKey);
33301
+ const agentMirrorRoot = path13.join(rootAbs, cwdKey);
32503
33302
  const repos = await discoverGitReposUnderRoot(launcherResolved);
32504
33303
  if (repos.length === 0) {
32505
33304
  log2("[worktrees] No Git repositories under launcher working directory; skipping worktree creation.");
@@ -32507,13 +33306,13 @@ async function prepareNewSessionWorktrees(options) {
32507
33306
  }
32508
33307
  const branch = `session-${sessionId}`;
32509
33308
  const worktreePaths = [];
32510
- fs6.mkdirSync(agentMirrorRoot, { recursive: true });
33309
+ fs12.mkdirSync(agentMirrorRoot, { recursive: true });
32511
33310
  for (const repo of repos) {
32512
- let rel = path11.relative(launcherResolved, repo.absolutePath);
32513
- if (rel.startsWith("..") || path11.isAbsolute(rel)) continue;
33311
+ let rel = path13.relative(launcherResolved, repo.absolutePath);
33312
+ if (rel.startsWith("..") || path13.isAbsolute(rel)) continue;
32514
33313
  const relNorm = rel === "" ? "." : rel;
32515
- const wtPath = path11.join(agentMirrorRoot, relNorm, sessionId);
32516
- fs6.mkdirSync(path11.dirname(wtPath), { recursive: true });
33314
+ const wtPath = path13.join(agentMirrorRoot, relNorm, sessionId);
33315
+ fs12.mkdirSync(path13.dirname(wtPath), { recursive: true });
32517
33316
  try {
32518
33317
  await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
32519
33318
  log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
@@ -32550,23 +33349,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
32550
33349
  }
32551
33350
 
32552
33351
  // src/worktrees/remove-session-worktrees.ts
32553
- import * as fs9 from "node:fs";
33352
+ import * as fs15 from "node:fs";
32554
33353
 
32555
33354
  // src/git/worktree-remove.ts
32556
- import * as fs8 from "node:fs";
33355
+ import * as fs14 from "node:fs";
32557
33356
 
32558
33357
  // src/git/resolve-main-repo-from-git-file.ts
32559
- import * as fs7 from "node:fs";
32560
- import * as path12 from "node:path";
33358
+ import * as fs13 from "node:fs";
33359
+ import * as path14 from "node:path";
32561
33360
  function resolveMainRepoFromWorktreeGitFile(wt) {
32562
- const gitDirFile = path12.join(wt, ".git");
32563
- if (!fs7.existsSync(gitDirFile) || !fs7.statSync(gitDirFile).isFile()) return "";
32564
- const first2 = fs7.readFileSync(gitDirFile, "utf8").trim();
33361
+ const gitDirFile = path14.join(wt, ".git");
33362
+ if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
33363
+ const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
32565
33364
  const m = first2.match(/^gitdir:\s*(.+)$/im);
32566
33365
  if (!m) return "";
32567
- const gitWorktreePath = path12.resolve(wt, m[1].trim());
32568
- const gitDir = path12.dirname(path12.dirname(gitWorktreePath));
32569
- return path12.dirname(gitDir);
33366
+ const gitWorktreePath = path14.resolve(wt, m[1].trim());
33367
+ const gitDir = path14.dirname(path14.dirname(gitWorktreePath));
33368
+ return path14.dirname(gitDir);
32570
33369
  }
32571
33370
 
32572
33371
  // src/git/worktree-remove.ts
@@ -32575,7 +33374,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
32575
33374
  if (mainRepo) {
32576
33375
  await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
32577
33376
  } else {
32578
- fs8.rmSync(worktreePath, { recursive: true, force: true });
33377
+ fs14.rmSync(worktreePath, { recursive: true, force: true });
32579
33378
  }
32580
33379
  }
32581
33380
 
@@ -32588,7 +33387,7 @@ async function removeSessionWorktrees(paths, log2) {
32588
33387
  } catch (e) {
32589
33388
  log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
32590
33389
  try {
32591
- fs9.rmSync(wt, { recursive: true, force: true });
33390
+ fs15.rmSync(wt, { recursive: true, force: true });
32592
33391
  } catch {
32593
33392
  }
32594
33393
  }
@@ -32808,7 +33607,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
32808
33607
  }
32809
33608
 
32810
33609
  // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
32811
- import * as path14 from "node:path";
33610
+ import * as path16 from "node:path";
32812
33611
 
32813
33612
  // src/git/working-directory/changes/parse-git-status.ts
32814
33613
  function parseNameStatusLines(lines) {
@@ -32928,8 +33727,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
32928
33727
  }
32929
33728
 
32930
33729
  // src/git/working-directory/changes/list-changed-files-for-repo.ts
32931
- import * as fs11 from "node:fs";
32932
- import * as path13 from "node:path";
33730
+ import * as fs17 from "node:fs";
33731
+ import * as path15 from "node:path";
32933
33732
 
32934
33733
  // src/git/working-directory/changes/count-lines.ts
32935
33734
  import { createReadStream } from "node:fs";
@@ -32953,7 +33752,7 @@ async function countTextFileLines(absFile) {
32953
33752
  }
32954
33753
 
32955
33754
  // src/git/working-directory/changes/hydrate-patch.ts
32956
- import * as fs10 from "node:fs";
33755
+ import * as fs16 from "node:fs";
32957
33756
  var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
32958
33757
  var MAX_HYDRATE_LINES_PER_GAP = 8e3;
32959
33758
  var MAX_HYDRATE_LINES_PER_FILE = 8e4;
@@ -32968,7 +33767,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
32968
33767
  }
32969
33768
  async function readWorktreeFileLines(abs) {
32970
33769
  try {
32971
- const raw = await fs10.promises.readFile(abs, "utf8");
33770
+ const raw = await fs16.promises.readFile(abs, "utf8");
32972
33771
  return raw.split(/\r?\n/);
32973
33772
  } catch {
32974
33773
  return null;
@@ -33103,7 +33902,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33103
33902
  const rows = [];
33104
33903
  for (const pathInRepo of paths) {
33105
33904
  const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
33106
- const abs = path13.join(repoGitCwd, pathInRepo);
33905
+ const abs = path15.join(repoGitCwd, pathInRepo);
33107
33906
  const nums = numByPath.get(pathInRepo);
33108
33907
  let additions = nums?.additions ?? 0;
33109
33908
  let deletions = nums?.deletions ?? 0;
@@ -33116,7 +33915,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33116
33915
  deletions = fromGit.deletions;
33117
33916
  } else {
33118
33917
  try {
33119
- const st = await fs11.promises.stat(abs);
33918
+ const st = await fs17.promises.stat(abs);
33120
33919
  if (st.isFile()) additions = await countTextFileLines(abs);
33121
33920
  else additions = 0;
33122
33921
  } catch {
@@ -33142,7 +33941,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33142
33941
  } else {
33143
33942
  pathInRepo = row.pathRelLauncher;
33144
33943
  }
33145
- const absFile = path13.join(repoGitCwd, pathInRepo);
33944
+ const absFile = path15.join(repoGitCwd, pathInRepo);
33146
33945
  let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
33147
33946
  if (patch) {
33148
33947
  patch = await hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, row.change);
@@ -33158,8 +33957,8 @@ function normRepoRel(p) {
33158
33957
  return x === "" ? "." : x;
33159
33958
  }
33160
33959
  async function getWorkingTreeChangeRepoDetails(options) {
33161
- const launcher = path14.resolve(getBridgeWorkspaceDirectory());
33162
- const mirror = options.agentMirrorRootAbs ? path14.resolve(options.agentMirrorRootAbs) : null;
33960
+ const launcher = path16.resolve(getBridgeWorkspaceDirectory());
33961
+ const mirror = options.agentMirrorRootAbs ? path16.resolve(options.agentMirrorRootAbs) : null;
33163
33962
  const out = [];
33164
33963
  const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
33165
33964
  const basisInput = options.basis ?? { kind: "working" };
@@ -33171,7 +33970,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
33171
33970
  }
33172
33971
  const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
33173
33972
  for (const target of options.commitTargetAbsDirs) {
33174
- const t = path14.resolve(target);
33973
+ const t = path16.resolve(target);
33175
33974
  if (!await isGitRepoDirectory(t)) continue;
33176
33975
  const g = simpleGit(t);
33177
33976
  let branch = "HEAD";
@@ -33184,7 +33983,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
33184
33983
  const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
33185
33984
  let repoRelPath;
33186
33985
  if (mirror) {
33187
- const relNorm = path14.relative(mirror, path14.dirname(t));
33986
+ const relNorm = path16.relative(mirror, path16.dirname(t));
33188
33987
  repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
33189
33988
  } else {
33190
33989
  let top = t;
@@ -33193,8 +33992,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
33193
33992
  } catch {
33194
33993
  top = t;
33195
33994
  }
33196
- const rel = path14.relative(launcher, path14.resolve(top)).replace(/\\/g, "/") || ".";
33197
- repoRelPath = rel.startsWith("..") ? path14.basename(path14.resolve(top)) : rel;
33995
+ const rel = path16.relative(launcher, path16.resolve(top)).replace(/\\/g, "/") || ".";
33996
+ repoRelPath = rel.startsWith("..") ? path16.basename(path16.resolve(top)) : rel;
33198
33997
  }
33199
33998
  const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
33200
33999
  if (filter && norm !== filter) continue;
@@ -33286,7 +34085,7 @@ var SessionWorktreeManager = class {
33286
34085
  }
33287
34086
  if (!opts.isNewSession) {
33288
34087
  const agentCwd = this.sessionAgentCwd.get(sessionId);
33289
- if (agentCwd) return path15.resolve(agentCwd);
34088
+ if (agentCwd) return path17.resolve(agentCwd);
33290
34089
  return void 0;
33291
34090
  }
33292
34091
  const prep = await prepareNewSessionWorktrees({
@@ -33299,7 +34098,7 @@ var SessionWorktreeManager = class {
33299
34098
  if (!prep) return void 0;
33300
34099
  this.sessionPaths.set(sessionId, prep.worktreePaths);
33301
34100
  this.sessionAgentCwd.set(sessionId, prep.agentCwd);
33302
- return path15.resolve(prep.agentCwd);
34101
+ return path17.resolve(prep.agentCwd);
33303
34102
  }
33304
34103
  async renameSessionBranch(sessionId, newBranch) {
33305
34104
  const paths = this.sessionPaths.get(sessionId);
@@ -33320,7 +34119,7 @@ var SessionWorktreeManager = class {
33320
34119
  getAgentCwdForSession(sessionId) {
33321
34120
  if (!sessionId) return null;
33322
34121
  const c = this.sessionAgentCwd.get(sessionId);
33323
- return c ? path15.resolve(c) : null;
34122
+ return c ? path17.resolve(c) : null;
33324
34123
  }
33325
34124
  async removeSessionWorktrees(sessionId) {
33326
34125
  const paths = this.sessionPaths.get(sessionId);
@@ -33368,30 +34167,30 @@ var SessionWorktreeManager = class {
33368
34167
  }
33369
34168
  };
33370
34169
  function defaultWorktreesRootAbs() {
33371
- return path15.join(os3.homedir(), ".buildautomaton", "worktrees");
34170
+ return path17.join(os4.homedir(), ".buildautomaton", "worktrees");
33372
34171
  }
33373
34172
 
33374
34173
  // src/files/watch-file-index.ts
33375
34174
  import { watch } from "node:fs";
33376
- import path22 from "node:path";
34175
+ import path24 from "node:path";
33377
34176
 
33378
34177
  // src/files/index/build-file-index.ts
33379
- import path19 from "node:path";
34178
+ import path21 from "node:path";
33380
34179
 
33381
34180
  // src/runtime/yield-to-event-loop.ts
33382
34181
  function yieldToEventLoop() {
33383
- return new Promise((resolve16) => setImmediate(resolve16));
34182
+ return new Promise((resolve17) => setImmediate(resolve17));
33384
34183
  }
33385
34184
 
33386
34185
  // src/files/index/walk-workspace-tree.ts
33387
- import fs12 from "node:fs";
33388
- import path17 from "node:path";
34186
+ import fs18 from "node:fs";
34187
+ import path19 from "node:path";
33389
34188
 
33390
34189
  // src/files/index/constants.ts
33391
- import path16 from "node:path";
33392
- import os4 from "node:os";
34190
+ import path18 from "node:path";
34191
+ import os5 from "node:os";
33393
34192
  var INDEX_WORK_YIELD_EVERY = 256;
33394
- var INDEX_DIR = path16.join(os4.homedir(), ".buildautomaton");
34193
+ var INDEX_DIR = path18.join(os5.homedir(), ".buildautomaton");
33395
34194
  var INDEX_HASH_LEN = 16;
33396
34195
  var INDEX_VERSION = 2;
33397
34196
  var INDEX_LOG_PREFIX = "[file-index]";
@@ -33400,23 +34199,23 @@ var INDEX_LOG_PREFIX = "[file-index]";
33400
34199
  function walkWorkspaceTreeSync(dir, baseDir, out) {
33401
34200
  let names;
33402
34201
  try {
33403
- names = fs12.readdirSync(dir);
34202
+ names = fs18.readdirSync(dir);
33404
34203
  } catch {
33405
34204
  return;
33406
34205
  }
33407
34206
  for (const name of names) {
33408
34207
  if (name.startsWith(".")) continue;
33409
- const full = path17.join(dir, name);
33410
- let stat2;
34208
+ const full = path19.join(dir, name);
34209
+ let stat3;
33411
34210
  try {
33412
- stat2 = fs12.statSync(full);
34211
+ stat3 = fs18.statSync(full);
33413
34212
  } catch {
33414
34213
  continue;
33415
34214
  }
33416
- const relative5 = path17.relative(baseDir, full).replace(/\\/g, "/");
33417
- if (stat2.isDirectory()) {
34215
+ const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
34216
+ if (stat3.isDirectory()) {
33418
34217
  walkWorkspaceTreeSync(full, baseDir, out);
33419
- } else if (stat2.isFile()) {
34218
+ } else if (stat3.isFile()) {
33420
34219
  out.push(relative5);
33421
34220
  }
33422
34221
  }
@@ -33424,7 +34223,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
33424
34223
  async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
33425
34224
  let names;
33426
34225
  try {
33427
- names = await fs12.promises.readdir(dir);
34226
+ names = await fs18.promises.readdir(dir);
33428
34227
  } catch {
33429
34228
  return;
33430
34229
  }
@@ -33434,17 +34233,17 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
33434
34233
  await yieldToEventLoop();
33435
34234
  }
33436
34235
  state.n++;
33437
- const full = path17.join(dir, name);
33438
- let stat2;
34236
+ const full = path19.join(dir, name);
34237
+ let stat3;
33439
34238
  try {
33440
- stat2 = await fs12.promises.stat(full);
34239
+ stat3 = await fs18.promises.stat(full);
33441
34240
  } catch {
33442
34241
  continue;
33443
34242
  }
33444
- const relative5 = path17.relative(baseDir, full).replace(/\\/g, "/");
33445
- if (stat2.isDirectory()) {
34243
+ const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
34244
+ if (stat3.isDirectory()) {
33446
34245
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
33447
- } else if (stat2.isFile()) {
34246
+ } else if (stat3.isFile()) {
33448
34247
  out.push(relative5);
33449
34248
  }
33450
34249
  }
@@ -33522,22 +34321,22 @@ async function buildTrigramMapForPathsAsync(paths) {
33522
34321
  }
33523
34322
 
33524
34323
  // src/files/index/write-index-file.ts
33525
- import fs13 from "node:fs";
34324
+ import fs19 from "node:fs";
33526
34325
 
33527
34326
  // src/files/index/paths.ts
33528
- import path18 from "node:path";
34327
+ import path20 from "node:path";
33529
34328
  import crypto2 from "node:crypto";
33530
34329
  function getIndexPathForCwd(resolvedCwd) {
33531
34330
  const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
33532
- return path18.join(INDEX_DIR, `.file-index-${hash}.json`);
34331
+ return path20.join(INDEX_DIR, `.file-index-${hash}.json`);
33533
34332
  }
33534
34333
 
33535
34334
  // src/files/index/write-index-file.ts
33536
34335
  function writeIndexFileSync(resolvedCwd, data) {
33537
34336
  const indexPath = getIndexPathForCwd(resolvedCwd);
33538
34337
  try {
33539
- if (!fs13.existsSync(INDEX_DIR)) fs13.mkdirSync(INDEX_DIR, { recursive: true });
33540
- fs13.writeFileSync(indexPath, JSON.stringify(data), "utf8");
34338
+ if (!fs19.existsSync(INDEX_DIR)) fs19.mkdirSync(INDEX_DIR, { recursive: true });
34339
+ fs19.writeFileSync(indexPath, JSON.stringify(data), "utf8");
33541
34340
  } catch (e) {
33542
34341
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
33543
34342
  }
@@ -33545,8 +34344,8 @@ function writeIndexFileSync(resolvedCwd, data) {
33545
34344
  async function writeIndexFileAsync(resolvedCwd, data) {
33546
34345
  const indexPath = getIndexPathForCwd(resolvedCwd);
33547
34346
  try {
33548
- await fs13.promises.mkdir(INDEX_DIR, { recursive: true });
33549
- await fs13.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
34347
+ await fs19.promises.mkdir(INDEX_DIR, { recursive: true });
34348
+ await fs19.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
33550
34349
  } catch (e) {
33551
34350
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
33552
34351
  }
@@ -33560,7 +34359,7 @@ function sortPaths(paths) {
33560
34359
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
33561
34360
  }
33562
34361
  function buildFileIndex(cwd) {
33563
- const resolved = path19.resolve(cwd);
34362
+ const resolved = path21.resolve(cwd);
33564
34363
  const paths = [];
33565
34364
  walkWorkspaceTreeSync(resolved, resolved, paths);
33566
34365
  sortPaths(paths);
@@ -33570,7 +34369,7 @@ function buildFileIndex(cwd) {
33570
34369
  return data;
33571
34370
  }
33572
34371
  async function buildFileIndexAsync(cwd) {
33573
- const resolved = path19.resolve(cwd);
34372
+ const resolved = path21.resolve(cwd);
33574
34373
  const paths = [];
33575
34374
  await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
33576
34375
  await yieldToEventLoop();
@@ -33582,13 +34381,13 @@ async function buildFileIndexAsync(cwd) {
33582
34381
  }
33583
34382
 
33584
34383
  // src/files/index/load-file-index.ts
33585
- import fs14 from "node:fs";
33586
- import path20 from "node:path";
34384
+ import fs20 from "node:fs";
34385
+ import path22 from "node:path";
33587
34386
  function loadFileIndex(cwd) {
33588
- const resolved = path20.resolve(cwd);
34387
+ const resolved = path22.resolve(cwd);
33589
34388
  const indexPath = getIndexPathForCwd(resolved);
33590
34389
  try {
33591
- const raw = fs14.readFileSync(indexPath, "utf8");
34390
+ const raw = fs20.readFileSync(indexPath, "utf8");
33592
34391
  const parsed = JSON.parse(raw);
33593
34392
  if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
33594
34393
  const obj = parsed;
@@ -33607,9 +34406,9 @@ function loadFileIndex(cwd) {
33607
34406
  }
33608
34407
 
33609
34408
  // src/files/index/ensure-file-index.ts
33610
- import path21 from "node:path";
34409
+ import path23 from "node:path";
33611
34410
  async function ensureFileIndexAsync(cwd) {
33612
- const resolved = path21.resolve(cwd);
34411
+ const resolved = path23.resolve(cwd);
33613
34412
  const cached2 = loadFileIndex(resolved);
33614
34413
  if (cached2 !== null) return { data: cached2, fromCache: true };
33615
34414
  const data = await buildFileIndexAsync(resolved);
@@ -33692,7 +34491,7 @@ function createFsWatcher(resolved, schedule) {
33692
34491
  }
33693
34492
  }
33694
34493
  function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
33695
- const resolved = path22.resolve(cwd);
34494
+ const resolved = path24.resolve(cwd);
33696
34495
  void buildFileIndexAsync(resolved).catch((e) => {
33697
34496
  console.error("[file-index] Initial index build failed:", e);
33698
34497
  });
@@ -33720,7 +34519,7 @@ function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
33720
34519
  }
33721
34520
 
33722
34521
  // src/dev-servers/manager/dev-server-manager.ts
33723
- import { rm } from "node:fs/promises";
34522
+ import { rm as rm2 } from "node:fs/promises";
33724
34523
 
33725
34524
  // src/dev-servers/process/send-server-status.ts
33726
34525
  function sendDevServerStatus(getWs, serverId, status, options) {
@@ -33739,15 +34538,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
33739
34538
 
33740
34539
  // src/dev-servers/process/terminate-child-process.ts
33741
34540
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
33742
- const exited = new Promise((resolve16) => {
33743
- proc.once("exit", () => resolve16());
34541
+ const exited = new Promise((resolve17) => {
34542
+ proc.once("exit", () => resolve17());
33744
34543
  });
33745
34544
  log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
33746
34545
  try {
33747
34546
  proc.kill("SIGTERM");
33748
34547
  } catch {
33749
34548
  }
33750
- await Promise.race([exited, new Promise((resolve16) => setTimeout(resolve16, graceMs))]);
34549
+ await Promise.race([exited, new Promise((resolve17) => setTimeout(resolve17, graceMs))]);
33751
34550
  }
33752
34551
  function forceKillChild(proc, log2, shortId, graceMs) {
33753
34552
  log2(
@@ -33761,7 +34560,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
33761
34560
  }
33762
34561
 
33763
34562
  // src/dev-servers/process/wire-dev-server-child-process.ts
33764
- import fs15 from "node:fs";
34563
+ import fs21 from "node:fs";
33765
34564
 
33766
34565
  // src/dev-servers/manager/forward-pipe.ts
33767
34566
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -33797,7 +34596,7 @@ function wireDevServerChildProcess(d) {
33797
34596
  d.setPollInterval(void 0);
33798
34597
  return;
33799
34598
  }
33800
- fs15.readFile(d.mergedLogPath, (err, buf) => {
34599
+ fs21.readFile(d.mergedLogPath, (err, buf) => {
33801
34600
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
33802
34601
  if (buf.length <= d.mergedReadPos.value) return;
33803
34602
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -33835,7 +34634,7 @@ ${errTail}` : ""}`);
33835
34634
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
33836
34635
  };
33837
34636
  if (mergedPath) {
33838
- fs15.readFile(mergedPath, (err, buf) => {
34637
+ fs21.readFile(mergedPath, (err, buf) => {
33839
34638
  if (!err && buf.length > d.mergedReadPos.value) {
33840
34639
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
33841
34640
  if (chunk.length > 0) {
@@ -33937,13 +34736,13 @@ function parseDevServerDefs(servers) {
33937
34736
  }
33938
34737
 
33939
34738
  // src/dev-servers/manager/shell-spawn/utils.ts
33940
- import fs16 from "node:fs";
34739
+ import fs22 from "node:fs";
33941
34740
  function isSpawnEbadf(e) {
33942
34741
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
33943
34742
  }
33944
34743
  function rmDirQuiet(dir) {
33945
34744
  try {
33946
- fs16.rmSync(dir, { recursive: true, force: true });
34745
+ fs22.rmSync(dir, { recursive: true, force: true });
33947
34746
  } catch {
33948
34747
  }
33949
34748
  }
@@ -33951,7 +34750,7 @@ var cachedDevNullReadFd;
33951
34750
  function devNullReadFd() {
33952
34751
  if (cachedDevNullReadFd === void 0) {
33953
34752
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
33954
- cachedDevNullReadFd = fs16.openSync(devPath, "r");
34753
+ cachedDevNullReadFd = fs22.openSync(devPath, "r");
33955
34754
  }
33956
34755
  return cachedDevNullReadFd;
33957
34756
  }
@@ -34025,15 +34824,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
34025
34824
 
34026
34825
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
34027
34826
  import { spawn as spawn6 } from "node:child_process";
34028
- import fs17 from "node:fs";
34827
+ import fs23 from "node:fs";
34029
34828
  import { tmpdir } from "node:os";
34030
- import path23 from "node:path";
34829
+ import path25 from "node:path";
34031
34830
  function trySpawnMergedLogFile(command, env, cwd, signal) {
34032
- const tmpRoot = fs17.mkdtempSync(path23.join(tmpdir(), "ba-devsrv-log-"));
34033
- const logPath = path23.join(tmpRoot, "combined.log");
34831
+ const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir(), "ba-devsrv-log-"));
34832
+ const logPath = path25.join(tmpRoot, "combined.log");
34034
34833
  let logFd;
34035
34834
  try {
34036
- logFd = fs17.openSync(logPath, "a");
34835
+ logFd = fs23.openSync(logPath, "a");
34037
34836
  } catch {
34038
34837
  rmDirQuiet(tmpRoot);
34039
34838
  return null;
@@ -34052,7 +34851,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
34052
34851
  } else {
34053
34852
  proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
34054
34853
  }
34055
- fs17.closeSync(logFd);
34854
+ fs23.closeSync(logFd);
34056
34855
  return {
34057
34856
  proc,
34058
34857
  pipedStdoutStderr: true,
@@ -34061,7 +34860,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
34061
34860
  };
34062
34861
  } catch (e) {
34063
34862
  try {
34064
- fs17.closeSync(logFd);
34863
+ fs23.closeSync(logFd);
34065
34864
  } catch {
34066
34865
  }
34067
34866
  rmDirQuiet(tmpRoot);
@@ -34072,22 +34871,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
34072
34871
 
34073
34872
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
34074
34873
  import { spawn as spawn7 } from "node:child_process";
34075
- import fs18 from "node:fs";
34874
+ import fs24 from "node:fs";
34076
34875
  import { tmpdir as tmpdir2 } from "node:os";
34077
- import path24 from "node:path";
34876
+ import path26 from "node:path";
34078
34877
  function shSingleQuote(s) {
34079
34878
  return `'${s.replace(/'/g, `'\\''`)}'`;
34080
34879
  }
34081
34880
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
34082
- const tmpRoot = fs18.mkdtempSync(path24.join(tmpdir2(), "ba-devsrv-sh-"));
34083
- const logPath = path24.join(tmpRoot, "combined.log");
34084
- const innerPath = path24.join(tmpRoot, "_cmd.sh");
34085
- const runnerPath = path24.join(tmpRoot, "_run.sh");
34881
+ const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
34882
+ const logPath = path26.join(tmpRoot, "combined.log");
34883
+ const innerPath = path26.join(tmpRoot, "_cmd.sh");
34884
+ const runnerPath = path26.join(tmpRoot, "_run.sh");
34086
34885
  try {
34087
- fs18.writeFileSync(innerPath, `#!/bin/sh
34886
+ fs24.writeFileSync(innerPath, `#!/bin/sh
34088
34887
  ${command}
34089
34888
  `);
34090
- fs18.writeFileSync(
34889
+ fs24.writeFileSync(
34091
34890
  runnerPath,
34092
34891
  `#!/bin/sh
34093
34892
  cd ${shSingleQuote(cwd)}
@@ -34113,13 +34912,13 @@ cd ${shSingleQuote(cwd)}
34113
34912
  }
34114
34913
  }
34115
34914
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
34116
- const tmpRoot = fs18.mkdtempSync(path24.join(tmpdir2(), "ba-devsrv-sh-"));
34117
- const logPath = path24.join(tmpRoot, "combined.log");
34118
- const runnerPath = path24.join(tmpRoot, "_run.bat");
34915
+ const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
34916
+ const logPath = path26.join(tmpRoot, "combined.log");
34917
+ const runnerPath = path26.join(tmpRoot, "_run.bat");
34119
34918
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
34120
34919
  const com = process.env.ComSpec || "cmd.exe";
34121
34920
  try {
34122
- fs18.writeFileSync(
34921
+ fs24.writeFileSync(
34123
34922
  runnerPath,
34124
34923
  `@ECHO OFF\r
34125
34924
  CD /D ${q(cwd)}\r
@@ -34229,8 +35028,90 @@ var StreamTail = class {
34229
35028
  }
34230
35029
  };
34231
35030
 
34232
- // src/dev-servers/manager/dev-server-manager.ts
35031
+ // src/dev-servers/manager/dev-server-constants.ts
34233
35032
  var BRIDGE_SHUTDOWN_GRACE_MS = 8e3;
35033
+
35034
+ // src/dev-servers/manager/dev-server-firehose-messages.ts
35035
+ function buildFirehoseSnapshotMessage(params) {
35036
+ const payload = {
35037
+ type: "log_snapshot",
35038
+ serverId: params.serverId,
35039
+ viewerId: params.viewerId,
35040
+ stdoutTail: params.tails.stdout,
35041
+ stderrTail: params.tails.stderr
35042
+ };
35043
+ return params.e2ee ? params.e2ee.encryptFields(payload, ["stdoutTail", "stderrTail"]) : payload;
35044
+ }
35045
+ function buildFirehoseLogChunkMessage(params) {
35046
+ const payload = {
35047
+ type: "log_chunk",
35048
+ serverId: params.serverId,
35049
+ stream: params.stream,
35050
+ text: params.text
35051
+ };
35052
+ return params.e2ee ? params.e2ee.encryptFields(payload, ["text"]) : payload;
35053
+ }
35054
+
35055
+ // src/dev-servers/manager/dev-server-firehose-sink.ts
35056
+ var DevServerFirehoseSink = class {
35057
+ constructor(options) {
35058
+ this.options = options;
35059
+ }
35060
+ logViewerRefCountByServerId = /* @__PURE__ */ new Map();
35061
+ firehoseSend = null;
35062
+ attach(send) {
35063
+ this.firehoseSend = send;
35064
+ }
35065
+ detach() {
35066
+ this.firehoseSend = null;
35067
+ this.logViewerRefCountByServerId.clear();
35068
+ }
35069
+ openLogViewer(serverId, viewerId) {
35070
+ const next = (this.logViewerRefCountByServerId.get(serverId) ?? 0) + 1;
35071
+ this.logViewerRefCountByServerId.set(serverId, next);
35072
+ this.sendSnapshot(serverId, viewerId);
35073
+ }
35074
+ closeLogViewer(serverId) {
35075
+ const n = (this.logViewerRefCountByServerId.get(serverId) ?? 0) - 1;
35076
+ if (n <= 0) this.logViewerRefCountByServerId.delete(serverId);
35077
+ else this.logViewerRefCountByServerId.set(serverId, n);
35078
+ }
35079
+ pushLogChunk(serverId, stream, chunk) {
35080
+ if ((this.logViewerRefCountByServerId.get(serverId) ?? 0) <= 0) return;
35081
+ if (!this.options.isPipedCaptureEnabled(serverId)) return;
35082
+ if (!this.firehoseSend) return;
35083
+ const text = chunk.toString("utf8");
35084
+ setImmediate(() => {
35085
+ if (!this.firehoseSend) return;
35086
+ this.firehoseSend(buildFirehoseLogChunkMessage({ serverId, stream, text, e2ee: this.options.e2ee }));
35087
+ });
35088
+ }
35089
+ sendSnapshot(serverId, viewerId) {
35090
+ const payload = buildFirehoseSnapshotMessage({
35091
+ serverId,
35092
+ viewerId,
35093
+ tails: this.options.getTails(serverId),
35094
+ e2ee: this.options.e2ee
35095
+ });
35096
+ setImmediate(() => {
35097
+ const send = this.firehoseSend;
35098
+ if (!send) return;
35099
+ send(payload);
35100
+ });
35101
+ }
35102
+ };
35103
+
35104
+ // src/dev-servers/manager/cleanup-merged-log-dir.ts
35105
+ import { rm } from "node:fs/promises";
35106
+ function cleanupMergedLogDirForServer(map2, serverId) {
35107
+ const mergedDir = map2.get(serverId);
35108
+ if (!mergedDir) return;
35109
+ map2.delete(serverId);
35110
+ void rm(mergedDir, { recursive: true, force: true }).catch(() => {
35111
+ });
35112
+ }
35113
+
35114
+ // src/dev-servers/manager/dev-server-manager.ts
34234
35115
  var emptyTails = () => ({ stdout: [], stderr: [] });
34235
35116
  var DevServerManager = class {
34236
35117
  defsById = /* @__PURE__ */ new Map();
@@ -34238,66 +35119,36 @@ var DevServerManager = class {
34238
35119
  streamTailsByServerId = /* @__PURE__ */ new Map();
34239
35120
  spawnGenerationByServerId = /* @__PURE__ */ new Map();
34240
35121
  pipedCaptureByServerId = /* @__PURE__ */ new Map();
34241
- logViewerRefCountByServerId = /* @__PURE__ */ new Map();
34242
- firehoseSend = null;
34243
35122
  mergedLogPollByServerId = /* @__PURE__ */ new Map();
34244
35123
  mergedLogCleanupDirByServerId = /* @__PURE__ */ new Map();
34245
35124
  abortControllersByServerId = /* @__PURE__ */ new Map();
34246
35125
  getWs;
34247
35126
  log;
34248
35127
  getBridgeCwd;
35128
+ e2ee;
35129
+ firehoseSink;
34249
35130
  constructor(options) {
34250
35131
  this.getWs = options.getWs;
34251
35132
  this.log = options.log;
34252
35133
  this.getBridgeCwd = options.getBridgeCwd ?? (() => process.cwd());
35134
+ this.e2ee = options.e2ee;
35135
+ this.firehoseSink = new DevServerFirehoseSink({
35136
+ getTails: (serverId) => this.snapshotTails(serverId),
35137
+ isPipedCaptureEnabled: (serverId) => this.pipedCaptureByServerId.get(serverId) === true,
35138
+ e2ee: this.e2ee
35139
+ });
34253
35140
  }
34254
35141
  attachFirehose(send) {
34255
- this.firehoseSend = send;
35142
+ this.firehoseSink.attach(send);
34256
35143
  }
34257
35144
  detachFirehose() {
34258
- this.firehoseSend = null;
34259
- this.logViewerRefCountByServerId.clear();
35145
+ this.firehoseSink.detach();
34260
35146
  }
34261
35147
  handleFirehoseLogViewerOpen(serverId, _viewerId) {
34262
- const next = (this.logViewerRefCountByServerId.get(serverId) ?? 0) + 1;
34263
- this.logViewerRefCountByServerId.set(serverId, next);
34264
- this.sendSnapshotToFirehose(serverId, _viewerId);
35148
+ this.firehoseSink.openLogViewer(serverId, _viewerId);
34265
35149
  }
34266
35150
  handleFirehoseLogViewerClose(serverId, _viewerId) {
34267
- const n = (this.logViewerRefCountByServerId.get(serverId) ?? 0) - 1;
34268
- if (n <= 0) this.logViewerRefCountByServerId.delete(serverId);
34269
- else this.logViewerRefCountByServerId.set(serverId, n);
34270
- }
34271
- sendSnapshotToFirehose(serverId, viewerId) {
34272
- const tails = this.streamTailsByServerId.get(serverId);
34273
- const payload = {
34274
- type: "log_snapshot",
34275
- serverId,
34276
- viewerId,
34277
- stdoutTail: tails?.stdout.getTail() ?? [],
34278
- stderrTail: tails?.stderr.getTail() ?? []
34279
- };
34280
- setImmediate(() => {
34281
- const send = this.firehoseSend;
34282
- if (!send) return;
34283
- send(payload);
34284
- });
34285
- }
34286
- pushRemoteLogChunk(serverId, stream, chunk) {
34287
- if ((this.logViewerRefCountByServerId.get(serverId) ?? 0) <= 0) return;
34288
- if (!this.pipedCaptureByServerId.get(serverId)) return;
34289
- const send = this.firehoseSend;
34290
- if (!send) return;
34291
- const text = chunk.toString("utf8");
34292
- setImmediate(() => {
34293
- if (!this.firehoseSend) return;
34294
- this.firehoseSend({
34295
- type: "log_chunk",
34296
- serverId,
34297
- stream,
34298
- text
34299
- });
34300
- });
35151
+ this.firehoseSink.closeLogViewer(serverId);
34301
35152
  }
34302
35153
  applyConfig(servers) {
34303
35154
  this.defsById.clear();
@@ -34350,12 +35201,7 @@ var DevServerManager = class {
34350
35201
  }
34351
35202
  this.clearTails(serverId);
34352
35203
  this.pipedCaptureByServerId.delete(serverId);
34353
- const mergedDir = this.mergedLogCleanupDirByServerId.get(serverId);
34354
- if (mergedDir) {
34355
- this.mergedLogCleanupDirByServerId.delete(serverId);
34356
- void rm(mergedDir, { recursive: true, force: true }).catch(() => {
34357
- });
34358
- }
35204
+ cleanupMergedLogDirForServer(this.mergedLogCleanupDirByServerId, serverId);
34359
35205
  this.sendStatus(serverId, "stopped", void 0, tails);
34360
35206
  }
34361
35207
  start(serverId) {
@@ -34438,7 +35284,7 @@ var DevServerManager = class {
34438
35284
  log: this.log,
34439
35285
  stdoutTail,
34440
35286
  stderrTail,
34441
- pushRemoteLogChunk: (sid, stream, chunk) => this.pushRemoteLogChunk(sid, stream, chunk),
35287
+ pushRemoteLogChunk: (sid, stream, chunk) => this.firehoseSink.pushLogChunk(sid, stream, chunk),
34442
35288
  sendStatus: (status, detail, tails) => this.sendStatus(serverId, status, detail, tails),
34443
35289
  setPollInterval: (iv) => {
34444
35290
  if (iv) this.mergedLogPollByServerId.set(serverId, iv);
@@ -34452,7 +35298,7 @@ var DevServerManager = class {
34452
35298
  this.mergedLogCleanupDirByServerId.delete(serverId);
34453
35299
  },
34454
35300
  rmMergedCleanupDir: (dir) => {
34455
- void rm(dir, { recursive: true, force: true }).catch(() => {
35301
+ void rm2(dir, { recursive: true, force: true }).catch(() => {
34456
35302
  });
34457
35303
  },
34458
35304
  clearTailBuffers: () => this.clearTails(serverId)
@@ -34489,12 +35335,7 @@ var DevServerManager = class {
34489
35335
  this.processes.delete(serverId);
34490
35336
  this.clearPoll(serverId);
34491
35337
  this.pipedCaptureByServerId.delete(serverId);
34492
- const mergedDir = this.mergedLogCleanupDirByServerId.get(serverId);
34493
- if (mergedDir) {
34494
- this.mergedLogCleanupDirByServerId.delete(serverId);
34495
- void rm(mergedDir, { recursive: true, force: true }).catch(() => {
34496
- });
34497
- }
35338
+ cleanupMergedLogDirForServer(this.mergedLogCleanupDirByServerId, serverId);
34498
35339
  const tails = this.snapshotTails(serverId);
34499
35340
  this.clearTails(serverId);
34500
35341
  this.sendStatus(serverId, "unknown", "Bridge closed before process exited", tails);
@@ -34588,7 +35429,7 @@ async function proxyToLocal(request) {
34588
35429
  };
34589
35430
  const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
34590
35431
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
34591
- const once = await new Promise((resolve16) => {
35432
+ const once = await new Promise((resolve17) => {
34592
35433
  const req = mod.request(opts, (res) => {
34593
35434
  const chunks = [];
34594
35435
  res.on("data", (c) => chunks.push(c));
@@ -34599,7 +35440,7 @@ async function proxyToLocal(request) {
34599
35440
  if (typeof v === "string") headers[k] = v;
34600
35441
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
34601
35442
  }
34602
- resolve16({
35443
+ resolve17({
34603
35444
  id: request.id,
34604
35445
  statusCode: res.statusCode ?? 0,
34605
35446
  headers,
@@ -34608,7 +35449,7 @@ async function proxyToLocal(request) {
34608
35449
  });
34609
35450
  });
34610
35451
  req.on("error", (err) => {
34611
- resolve16({
35452
+ resolve17({
34612
35453
  id: request.id,
34613
35454
  statusCode: 0,
34614
35455
  headers: {},
@@ -34969,30 +35810,30 @@ function createOnBridgeIdentified(opts) {
34969
35810
  }
34970
35811
 
34971
35812
  // src/skills/discover-local-agent-skills.ts
34972
- import fs19 from "node:fs";
34973
- import path25 from "node:path";
35813
+ import fs25 from "node:fs";
35814
+ import path27 from "node:path";
34974
35815
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
34975
35816
  function discoverLocalSkills(cwd) {
34976
35817
  const out = [];
34977
35818
  const seenKeys = /* @__PURE__ */ new Set();
34978
35819
  for (const rel of SKILL_DISCOVERY_ROOTS) {
34979
- const base = path25.join(cwd, rel);
34980
- if (!fs19.existsSync(base) || !fs19.statSync(base).isDirectory()) continue;
35820
+ const base = path27.join(cwd, rel);
35821
+ if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
34981
35822
  let entries = [];
34982
35823
  try {
34983
- entries = fs19.readdirSync(base);
35824
+ entries = fs25.readdirSync(base);
34984
35825
  } catch {
34985
35826
  continue;
34986
35827
  }
34987
35828
  for (const name of entries) {
34988
- const dir = path25.join(base, name);
35829
+ const dir = path27.join(base, name);
34989
35830
  try {
34990
- if (!fs19.statSync(dir).isDirectory()) continue;
35831
+ if (!fs25.statSync(dir).isDirectory()) continue;
34991
35832
  } catch {
34992
35833
  continue;
34993
35834
  }
34994
- const skillMd = path25.join(dir, "SKILL.md");
34995
- if (!fs19.existsSync(skillMd)) continue;
35835
+ const skillMd = path27.join(dir, "SKILL.md");
35836
+ if (!fs25.existsSync(skillMd)) continue;
34996
35837
  const key = `${rel}/${name}`;
34997
35838
  if (seenKeys.has(key)) continue;
34998
35839
  seenKeys.add(key);
@@ -35004,23 +35845,23 @@ function discoverLocalSkills(cwd) {
35004
35845
  function discoverSkillLayoutRoots(cwd) {
35005
35846
  const roots = [];
35006
35847
  for (const rel of SKILL_DISCOVERY_ROOTS) {
35007
- const base = path25.join(cwd, rel);
35008
- if (!fs19.existsSync(base) || !fs19.statSync(base).isDirectory()) continue;
35848
+ const base = path27.join(cwd, rel);
35849
+ if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
35009
35850
  let entries = [];
35010
35851
  try {
35011
- entries = fs19.readdirSync(base);
35852
+ entries = fs25.readdirSync(base);
35012
35853
  } catch {
35013
35854
  continue;
35014
35855
  }
35015
35856
  const skills2 = [];
35016
35857
  for (const name of entries) {
35017
- const dir = path25.join(base, name);
35858
+ const dir = path27.join(base, name);
35018
35859
  try {
35019
- if (!fs19.statSync(dir).isDirectory()) continue;
35860
+ if (!fs25.statSync(dir).isDirectory()) continue;
35020
35861
  } catch {
35021
35862
  continue;
35022
35863
  }
35023
- if (!fs19.existsSync(path25.join(dir, "SKILL.md"))) continue;
35864
+ if (!fs25.existsSync(path27.join(dir, "SKILL.md"))) continue;
35024
35865
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
35025
35866
  skills2.push({ name, relPath });
35026
35867
  }
@@ -35122,7 +35963,7 @@ function reportGitRepos(getWs, log2) {
35122
35963
  var handleAuthToken = (msg, { log: log2 }) => {
35123
35964
  if (typeof msg.token !== "string") return;
35124
35965
  log2("Received auth token. Save it for future runs:");
35125
- log2(` export BUILDAMATON_AUTH_TOKEN="${msg.token}"`);
35966
+ log2(` export BUILDAUTOMATON_AUTH_TOKEN="${msg.token}"`);
35126
35967
  };
35127
35968
 
35128
35969
  // src/bridge/routing/handlers/bridge-identified.ts
@@ -35165,13 +36006,13 @@ var handleAgentConfigMessage = (msg, deps) => {
35165
36006
  };
35166
36007
 
35167
36008
  // src/agents/acp/from-bridge/handle-bridge-prompt.ts
35168
- import * as path27 from "node:path";
35169
- import { execFile as execFile5 } from "node:child_process";
35170
- import { promisify as promisify5 } from "node:util";
36009
+ import * as path29 from "node:path";
36010
+ import { execFile as execFile10 } from "node:child_process";
36011
+ import { promisify as promisify10 } from "node:util";
35171
36012
 
35172
36013
  // src/git/bridge-queue-key.ts
35173
- import * as path26 from "node:path";
35174
- import { createHash } from "node:crypto";
36014
+ import * as path28 from "node:path";
36015
+ import { createHash as createHash2 } from "node:crypto";
35175
36016
  function normalizeCanonicalGitUrl(url2) {
35176
36017
  let s = url2.trim();
35177
36018
  if (!s) return s;
@@ -35195,14 +36036,14 @@ function normalizeCanonicalGitUrl(url2) {
35195
36036
  }
35196
36037
  function canonicalUrlToRepoIdSync(url2) {
35197
36038
  const normalized = normalizeCanonicalGitUrl(url2);
35198
- return createHash("sha256").update(normalized).digest("hex").slice(0, 32);
36039
+ return createHash2("sha256").update(normalized).digest("hex").slice(0, 32);
35199
36040
  }
35200
36041
  function fallbackRepoIdFromPath(absPath) {
35201
- return createHash("sha256").update(path26.resolve(absPath)).digest("hex").slice(0, 32);
36042
+ return createHash2("sha256").update(path28.resolve(absPath)).digest("hex").slice(0, 32);
35202
36043
  }
35203
36044
  async function resolveBridgeQueueBindFields(options) {
35204
36045
  const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
35205
- const cwdAbs = worktreePaths.length > 0 ? path26.resolve(worktreePaths[0]) : path26.resolve(effectiveCwd);
36046
+ const cwdAbs = worktreePaths.length > 0 ? path28.resolve(worktreePaths[0]) : path28.resolve(effectiveCwd);
35206
36047
  if (!primaryRepoRoots.length) {
35207
36048
  log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
35208
36049
  return null;
@@ -35225,10 +36066,10 @@ async function resolveBridgeQueueBindFields(options) {
35225
36066
  }
35226
36067
 
35227
36068
  // src/agents/acp/from-bridge/handle-bridge-prompt.ts
35228
- var execFileAsync5 = promisify5(execFile5);
36069
+ var execFileAsync9 = promisify10(execFile10);
35229
36070
  async function readGitBranch(cwd) {
35230
36071
  try {
35231
- const { stdout } = await execFileAsync5("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
36072
+ const { stdout } = await execFileAsync9("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
35232
36073
  const b = stdout.trim();
35233
36074
  return b || null;
35234
36075
  } catch {
@@ -35239,22 +36080,40 @@ function handleBridgePrompt(msg, deps) {
35239
36080
  const { getWs, log: log2, acpManager, sessionWorktreeManager } = deps;
35240
36081
  const rawPrompt = msg.prompt;
35241
36082
  const promptText = typeof rawPrompt === "string" ? rawPrompt : rawPrompt != null ? String(rawPrompt) : "";
36083
+ const sessionId = msg.sessionId;
36084
+ const runId = typeof msg.runId === "string" ? msg.runId : void 0;
36085
+ const promptId = typeof msg.id === "string" ? msg.id : void 0;
36086
+ const sendBridgeMessage = (message, encryptedFields = []) => {
36087
+ const s = getWs();
36088
+ if (!s) return false;
36089
+ const wire = deps.e2ee && encryptedFields.length > 0 ? deps.e2ee.encryptFields(message, encryptedFields) : message;
36090
+ sendWsMessage(s, wire);
36091
+ return true;
36092
+ };
35242
36093
  if (!promptText.trim()) {
35243
36094
  log2(
35244
36095
  `[Bridge service] Prompt ignored: empty or missing prompt text (session ${typeof msg.sessionId === "string" ? msg.sessionId.slice(0, 8) : "\u2014"}\u2026, run ${typeof msg.runId === "string" ? msg.runId.slice(0, 8) : "\u2014"}\u2026).`
35245
36096
  );
36097
+ sendBridgeMessage(
36098
+ {
36099
+ type: "prompt_result",
36100
+ ...promptId ? { id: promptId } : {},
36101
+ ...sessionId ? { sessionId } : {},
36102
+ ...runId ? { runId } : {},
36103
+ success: false,
36104
+ error: "Empty or missing prompt text from the bridge; this turn was not sent to the agent."
36105
+ },
36106
+ ["error"]
36107
+ );
35246
36108
  return;
35247
36109
  }
35248
- const sessionId = msg.sessionId;
35249
36110
  const isNewSession = msg.isNewSession === true;
35250
36111
  const sessionWorktreesEnabled = msg.sessionWorktreesEnabled === true;
35251
36112
  const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
35252
- const runId = typeof msg.runId === "string" ? msg.runId : void 0;
35253
36113
  const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
35254
36114
  acpManager.logPromptReceivedFromBridge({ agentType, mode });
35255
36115
  const sendResult2 = (result) => {
35256
- const s = getWs();
35257
- if (s) sendWsMessage(s, result);
36116
+ sendBridgeMessage(result, result.type === "prompt_result" ? ["output", "error"] : []);
35258
36117
  };
35259
36118
  const sendSessionUpdate = (payload) => {
35260
36119
  const s = getWs();
@@ -35263,11 +36122,19 @@ function handleBridgePrompt(msg, deps) {
35263
36122
  return;
35264
36123
  }
35265
36124
  const p = payload;
35266
- sendWsMessage(s, payload);
36125
+ const wire = p.type === "session_update" && deps.e2ee ? deps.e2ee.encryptFields(payload, ["payload"]) : p.type === "session_file_change" && deps.e2ee ? deps.e2ee.encryptFields(payload, [
36126
+ "path",
36127
+ "oldText",
36128
+ "newText",
36129
+ "patchContent",
36130
+ "isDirectory",
36131
+ "directoryRemoved"
36132
+ ]) : payload;
36133
+ sendWsMessage(s, wire);
35267
36134
  };
35268
36135
  async function preambleAndPrompt(resolvedCwd) {
35269
36136
  const s = getWs();
35270
- const effectiveCwd = path27.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
36137
+ const effectiveCwd = path29.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
35271
36138
  const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
35272
36139
  const repoRoots = await resolveSnapshotRepoRoots({
35273
36140
  worktreePaths,
@@ -35375,8 +36242,8 @@ var PREVIEW_API_BASE_PATH = "/__preview";
35375
36242
  var PREVIEW_SECRET_HEADER = "X-Preview-Secret";
35376
36243
  var DEFAULT_PORT = 3e3;
35377
36244
  var DEFAULT_COMMAND = "npm run preview";
35378
- var PREVIEW_COMMAND_ENV = "BUILDAMATON_PREVIEW_COMMAND";
35379
- var PREVIEW_PORT_ENV = "BUILDAMATON_PREVIEW_PORT";
36245
+ var PREVIEW_COMMAND_ENV = "BUILDAUTOMATON_PREVIEW_COMMAND";
36246
+ var PREVIEW_PORT_ENV = "BUILDAUTOMATON_PREVIEW_PORT";
35380
36247
  var previewProcess = null;
35381
36248
  var previewPort = DEFAULT_PORT;
35382
36249
  var previewSecret = "";
@@ -35390,8 +36257,8 @@ function randomSecret() {
35390
36257
  }
35391
36258
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
35392
36259
  }
35393
- async function requestPreviewApi(port, secret, method, path32, body) {
35394
- const url2 = `http://127.0.0.1:${port}${path32}`;
36260
+ async function requestPreviewApi(port, secret, method, path34, body) {
36261
+ const url2 = `http://127.0.0.1:${port}${path34}`;
35395
36262
  const headers = {
35396
36263
  [PREVIEW_SECRET_HEADER]: secret,
35397
36264
  "Content-Type": "application/json"
@@ -35403,7 +36270,7 @@ async function requestPreviewApi(port, secret, method, path32, body) {
35403
36270
  });
35404
36271
  const data = await res.json().catch(() => ({}));
35405
36272
  if (!res.ok) {
35406
- throw new Error(data?.error ?? `Preview API ${method} ${path32}: ${res.status}`);
36273
+ throw new Error(data?.error ?? `Preview API ${method} ${path34}: ${res.status}`);
35407
36274
  }
35408
36275
  return data;
35409
36276
  }
@@ -35429,7 +36296,7 @@ var OPERATIONS = [
35429
36296
  var previewSkill = {
35430
36297
  id: "preview",
35431
36298
  name: "Preview",
35432
- description: "Start and manage a local preview server that implements the BuildAutomaton Preview Server API. Configure the command with BUILDAMATON_PREVIEW_COMMAND (default: npm run preview). The server receives PORT and PREVIEW_SECRET and must expose /__preview/status and /__preview/stop.",
36299
+ description: "Start and manage a local preview server that implements the BuildAutomaton Preview Server API. Configure the command with BUILDAUTOMATON_PREVIEW_COMMAND (default: npm run preview). The server receives PORT and PREVIEW_SECRET and must expose /__preview/status and /__preview/stop.",
35433
36300
  operations: OPERATIONS,
35434
36301
  async execute(operationId, params) {
35435
36302
  const command = getPreviewCommand();
@@ -35566,15 +36433,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
35566
36433
  };
35567
36434
 
35568
36435
  // src/files/list-dir.ts
35569
- import fs20 from "node:fs";
35570
- import path29 from "node:path";
36436
+ import fs26 from "node:fs";
36437
+ import path31 from "node:path";
35571
36438
 
35572
36439
  // src/files/ensure-under-cwd.ts
35573
- import path28 from "node:path";
36440
+ import path30 from "node:path";
35574
36441
  function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
35575
- const normalized = path28.normalize(relativePath).replace(/^(\.\/)+/, "");
35576
- const resolved = path28.resolve(cwd, normalized);
35577
- if (!resolved.startsWith(cwd + path28.sep) && resolved !== cwd) {
36442
+ const normalized = path30.normalize(relativePath).replace(/^(\.\/)+/, "");
36443
+ const resolved = path30.resolve(cwd, normalized);
36444
+ if (!resolved.startsWith(cwd + path30.sep) && resolved !== cwd) {
35578
36445
  return null;
35579
36446
  }
35580
36447
  return resolved;
@@ -35588,7 +36455,7 @@ async function listDirAsync(relativePath) {
35588
36455
  return { error: "Path is outside working directory" };
35589
36456
  }
35590
36457
  try {
35591
- const names = await fs20.promises.readdir(resolved, { withFileTypes: true });
36458
+ const names = await fs26.promises.readdir(resolved, { withFileTypes: true });
35592
36459
  const visible = names.filter((d) => !d.name.startsWith("."));
35593
36460
  const entries = [];
35594
36461
  for (let i = 0; i < visible.length; i++) {
@@ -35596,12 +36463,12 @@ async function listDirAsync(relativePath) {
35596
36463
  await yieldToEventLoop();
35597
36464
  }
35598
36465
  const d = visible[i];
35599
- const entryPath = path29.join(relativePath || ".", d.name).replace(/\\/g, "/");
35600
- const fullPath = path29.join(resolved, d.name);
36466
+ const entryPath = path31.join(relativePath || ".", d.name).replace(/\\/g, "/");
36467
+ const fullPath = path31.join(resolved, d.name);
35601
36468
  let isDir = d.isDirectory();
35602
36469
  if (d.isSymbolicLink()) {
35603
36470
  try {
35604
- const targetStat = await fs20.promises.stat(fullPath);
36471
+ const targetStat = await fs26.promises.stat(fullPath);
35605
36472
  isDir = targetStat.isDirectory();
35606
36473
  } catch {
35607
36474
  isDir = false;
@@ -35626,25 +36493,25 @@ async function listDirAsync(relativePath) {
35626
36493
  }
35627
36494
 
35628
36495
  // src/files/read-file.ts
35629
- import fs21 from "node:fs";
36496
+ import fs27 from "node:fs";
35630
36497
  import { StringDecoder } from "node:string_decoder";
35631
36498
  function resolveFilePath(relativePath) {
35632
36499
  const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
35633
36500
  if (!resolved) return { error: "Path is outside working directory" };
35634
36501
  let real;
35635
36502
  try {
35636
- real = fs21.realpathSync(resolved);
36503
+ real = fs27.realpathSync(resolved);
35637
36504
  } catch {
35638
36505
  real = resolved;
35639
36506
  }
35640
- const stat2 = fs21.statSync(real);
35641
- if (!stat2.isFile()) return { error: "Not a file" };
36507
+ const stat3 = fs27.statSync(real);
36508
+ if (!stat3.isFile()) return { error: "Not a file" };
35642
36509
  return real;
35643
36510
  }
35644
36511
  var LINE_CHUNK_SIZE = 64 * 1024;
35645
36512
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
35646
- const fileSize = fs21.statSync(filePath).size;
35647
- const fd = fs21.openSync(filePath, "r");
36513
+ const fileSize = fs27.statSync(filePath).size;
36514
+ const fd = fs27.openSync(filePath, "r");
35648
36515
  const bufSize = 64 * 1024;
35649
36516
  const buf = Buffer.alloc(bufSize);
35650
36517
  const decoder = new StringDecoder("utf8");
@@ -35657,7 +36524,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
35657
36524
  let line0Accum = "";
35658
36525
  try {
35659
36526
  let bytesRead;
35660
- while (!done && (bytesRead = fs21.readSync(fd, buf, 0, bufSize, null)) > 0) {
36527
+ while (!done && (bytesRead = fs27.readSync(fd, buf, 0, bufSize, null)) > 0) {
35661
36528
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
35662
36529
  partial2 = "";
35663
36530
  let lineStart = 0;
@@ -35792,10 +36659,10 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
35792
36659
  }
35793
36660
  return { content: resultLines.join("\n"), size: fileSize };
35794
36661
  } finally {
35795
- fs21.closeSync(fd);
36662
+ fs27.closeSync(fd);
35796
36663
  }
35797
36664
  }
35798
- function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
36665
+ function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
35799
36666
  try {
35800
36667
  const result = resolveFilePath(relativePath);
35801
36668
  if (typeof result === "object") return result;
@@ -35803,43 +36670,45 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
35803
36670
  if (hasRange) {
35804
36671
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
35805
36672
  }
35806
- const stat2 = fs21.statSync(result);
35807
- const raw = fs21.readFileSync(result, "utf8");
36673
+ const stat3 = fs27.statSync(result);
36674
+ const raw = fs27.readFileSync(result, "utf8");
35808
36675
  const lines = raw.split(/\r?\n/);
35809
- return { content: raw, totalLines: lines.length, size: stat2.size };
36676
+ return { content: raw, totalLines: lines.length, size: stat3.size };
35810
36677
  } catch (err) {
35811
36678
  return { error: err instanceof Error ? err.message : String(err) };
35812
36679
  }
35813
36680
  }
35814
36681
  async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
35815
36682
  await yieldToEventLoop();
35816
- return readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize);
36683
+ return readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize);
35817
36684
  }
35818
36685
 
35819
36686
  // src/files/handle-file-browser-search.ts
35820
36687
  var SEARCH_LIMIT = 100;
35821
- function handleFileBrowserSearch(msg, socket) {
36688
+ function handleFileBrowserSearch(msg, socket, e2ee) {
35822
36689
  void (async () => {
35823
36690
  await yieldToEventLoop();
35824
36691
  const q = typeof msg.q === "string" ? msg.q : "";
35825
36692
  const cwd = getBridgeWorkspaceDirectory();
35826
36693
  const index = loadFileIndex(cwd);
35827
36694
  if (index === null) {
35828
- sendWsMessage(socket, {
36695
+ const payload2 = {
35829
36696
  type: "file_browser_search_response",
35830
36697
  id: msg.id,
35831
36698
  paths: [],
35832
36699
  indexReady: false
35833
- });
36700
+ };
36701
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
35834
36702
  return;
35835
36703
  }
35836
36704
  const results = await searchFileIndexAsync(index, q, SEARCH_LIMIT);
35837
- sendWsMessage(socket, {
36705
+ const payload = {
35838
36706
  type: "file_browser_search_response",
35839
36707
  id: msg.id,
35840
36708
  paths: results,
35841
36709
  indexReady: true
35842
- });
36710
+ };
36711
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
35843
36712
  })();
35844
36713
  }
35845
36714
  function triggerFileIndexBuild() {
@@ -35851,7 +36720,10 @@ function triggerFileIndexBuild() {
35851
36720
  }
35852
36721
 
35853
36722
  // src/files/handle-file-browser-request.ts
35854
- function handleFileBrowserRequest(msg, socket) {
36723
+ function sendFileBrowserMessage(socket, e2ee, payload) {
36724
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
36725
+ }
36726
+ function handleFileBrowserRequest(msg, socket, e2ee) {
35855
36727
  void (async () => {
35856
36728
  const reqPath = msg.path.replace(/^\/+/, "") || ".";
35857
36729
  const op = msg.op === "read" ? "read" : "list";
@@ -35860,7 +36732,7 @@ function handleFileBrowserRequest(msg, socket) {
35860
36732
  if ("error" in result) {
35861
36733
  sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
35862
36734
  } else {
35863
- sendWsMessage(socket, { type: "file_browser_response", id: msg.id, entries: result.entries });
36735
+ sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id: msg.id, entries: result.entries });
35864
36736
  if (reqPath === "." || reqPath === "") {
35865
36737
  triggerFileIndexBuild();
35866
36738
  }
@@ -35882,27 +36754,28 @@ function handleFileBrowserRequest(msg, socket) {
35882
36754
  size: result.size
35883
36755
  };
35884
36756
  if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
35885
- sendWsMessage(socket, payload);
36757
+ sendFileBrowserMessage(socket, e2ee, payload);
35886
36758
  }
35887
36759
  }
35888
36760
  })();
35889
36761
  }
35890
36762
 
35891
36763
  // src/bridge/routing/handlers/file-browser-messages.ts
35892
- function handleFileBrowserRequestMessage(msg, { getWs }) {
36764
+ function handleFileBrowserRequestMessage(msg, { getWs, e2ee }) {
35893
36765
  if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
35894
36766
  const socket = getWs();
35895
36767
  if (!socket) return;
35896
36768
  handleFileBrowserRequest(
35897
36769
  msg,
35898
- socket
36770
+ socket,
36771
+ e2ee
35899
36772
  );
35900
36773
  }
35901
- function handleFileBrowserSearchMessage(msg, { getWs }) {
36774
+ function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
35902
36775
  if (typeof msg.id !== "string") return;
35903
36776
  const socket = getWs();
35904
36777
  if (!socket) return;
35905
- handleFileBrowserSearch(msg, socket);
36778
+ handleFileBrowserSearch(msg, socket, e2ee);
35906
36779
  }
35907
36780
 
35908
36781
  // src/bridge/routing/handlers/skill-layout-request.ts
@@ -35914,8 +36787,8 @@ function handleSkillLayoutRequest(msg, deps) {
35914
36787
  }
35915
36788
 
35916
36789
  // src/skills/install-remote-skills.ts
35917
- import fs22 from "node:fs";
35918
- import path30 from "node:path";
36790
+ import fs28 from "node:fs";
36791
+ import path32 from "node:path";
35919
36792
  function installRemoteSkills(cwd, targetDir, items) {
35920
36793
  const installed2 = [];
35921
36794
  if (!Array.isArray(items)) {
@@ -35926,15 +36799,15 @@ function installRemoteSkills(cwd, targetDir, items) {
35926
36799
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
35927
36800
  continue;
35928
36801
  }
35929
- const skillDir = path30.join(cwd, targetDir, item.skillName);
36802
+ const skillDir = path32.join(cwd, targetDir, item.skillName);
35930
36803
  for (const f of item.files) {
35931
36804
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
35932
- const dest = path30.join(skillDir, f.path);
35933
- fs22.mkdirSync(path30.dirname(dest), { recursive: true });
36805
+ const dest = path32.join(skillDir, f.path);
36806
+ fs28.mkdirSync(path32.dirname(dest), { recursive: true });
35934
36807
  if (f.text !== void 0) {
35935
- fs22.writeFileSync(dest, f.text, "utf8");
36808
+ fs28.writeFileSync(dest, f.text, "utf8");
35936
36809
  } else if (f.base64) {
35937
- fs22.writeFileSync(dest, Buffer.from(f.base64, "base64"));
36810
+ fs28.writeFileSync(dest, Buffer.from(f.base64, "base64"));
35938
36811
  }
35939
36812
  }
35940
36813
  installed2.push({
@@ -35972,9 +36845,10 @@ var handleRefreshLocalSkills = (_msg, deps) => {
35972
36845
  };
35973
36846
 
35974
36847
  // src/bridge/routing/handlers/session-git-request.ts
35975
- function sendResult(ws, id, payload) {
36848
+ function sendResult(ws, id, payload, e2ee, encryptedFields = []) {
35976
36849
  if (!ws) return;
35977
- sendWsMessage(ws, { type: "session_git_result", id, ...payload });
36850
+ const message = { type: "session_git_result", id, ...payload };
36851
+ sendWsMessage(ws, e2ee && encryptedFields.length > 0 ? e2ee.encryptFields(message, encryptedFields) : message);
35978
36852
  }
35979
36853
  var handleSessionGitRequestMessage = (msg, deps) => {
35980
36854
  if (typeof msg.id !== "string") return;
@@ -35984,7 +36858,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
35984
36858
  return;
35985
36859
  void (async () => {
35986
36860
  const ws = deps.getWs();
35987
- const reply = (payload) => sendResult(ws, msg.id, payload);
36861
+ const reply = (payload, encryptedFields = []) => sendResult(ws, msg.id, payload, deps.e2ee, encryptedFields);
35988
36862
  try {
35989
36863
  if (action === "status") {
35990
36864
  const r = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
@@ -36010,7 +36884,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
36010
36884
  reply({
36011
36885
  ok: true,
36012
36886
  repos
36013
- });
36887
+ }, ["repos"]);
36014
36888
  return;
36015
36889
  }
36016
36890
  if (action === "push") {
@@ -36079,7 +36953,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
36079
36953
  };
36080
36954
 
36081
36955
  // src/bridge/routing/handlers/revert-turn-snapshot.ts
36082
- import * as fs23 from "node:fs";
36956
+ import * as fs29 from "node:fs";
36083
36957
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
36084
36958
  const id = typeof msg.id === "string" ? msg.id : "";
36085
36959
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -36091,7 +36965,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
36091
36965
  if (!s) return;
36092
36966
  const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
36093
36967
  const file2 = snapshotFilePath(agentBase, turnId);
36094
- if (!fs23.existsSync(file2)) {
36968
+ if (!fs29.existsSync(file2)) {
36095
36969
  sendWsMessage(s, {
36096
36970
  type: "revert_turn_snapshot_result",
36097
36971
  id,
@@ -36112,8 +36986,15 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
36112
36986
 
36113
36987
  // src/bridge/routing/handlers/dev-server-control.ts
36114
36988
  var handleDevServerControl = (msg, deps) => {
36115
- const serverId = typeof msg.serverId === "string" ? msg.serverId : "";
36116
- const action = msg.action === "start" || msg.action === "stop" ? msg.action : null;
36989
+ let wire = msg;
36990
+ try {
36991
+ wire = deps.e2ee ? deps.e2ee.decryptMessage(msg) : msg;
36992
+ } catch (e) {
36993
+ deps.log(`[E2EE] Could not decrypt dev server command: ${e instanceof Error ? e.message : String(e)}`);
36994
+ return;
36995
+ }
36996
+ const serverId = typeof wire.serverId === "string" ? wire.serverId : "";
36997
+ const action = wire.action === "start" || wire.action === "stop" ? wire.action : null;
36117
36998
  if (!serverId || !action) return;
36118
36999
  deps.devServerManager?.handleControl(serverId, action);
36119
37000
  };
@@ -36239,7 +37120,8 @@ function createMainBridgeWebSocketLifecycle(params) {
36239
37120
  messageDeps,
36240
37121
  tokens,
36241
37122
  persistTokens,
36242
- onAuthInvalid
37123
+ onAuthInvalid,
37124
+ e2ee
36243
37125
  } = params;
36244
37126
  let authRefreshInFlight = false;
36245
37127
  function handleOpen() {
@@ -36252,15 +37134,15 @@ function createMainBridgeWebSocketLifecycle(params) {
36252
37134
  }
36253
37135
  const socket = getWs();
36254
37136
  if (socket) {
36255
- sendWsMessage(socket, { type: "identify", role: "cli" });
37137
+ sendWsMessage(socket, { type: "identify", role: "cli", ...e2ee ? { e: e2ee.handshake } : {} });
36256
37138
  reportGitRepos(getWs, logFn);
36257
37139
  }
36258
37140
  if (justAuthenticated && socket) {
36259
37141
  logFn(
36260
37142
  "Save these for future runs (access token may rotate; refresh token is stored in ~/.buildautomaton/config.json when you use browser auth):"
36261
37143
  );
36262
- logFn(` export BUILDAMATON_AUTH_TOKEN="${tokens.accessToken}"`);
36263
- logFn(` export BUILDAMATON_WORKSPACE_ID="${workspaceId}"`);
37144
+ logFn(` export BUILDAUTOMATON_AUTH_TOKEN="${tokens.accessToken}"`);
37145
+ logFn(` export BUILDAUTOMATON_WORKSPACE_ID="${workspaceId}"`);
36264
37146
  }
36265
37147
  }
36266
37148
  function handleClose(code, reason) {
@@ -36375,7 +37257,8 @@ async function createBridgeConnection(options) {
36375
37257
  function getWs() {
36376
37258
  return state.currentWs;
36377
37259
  }
36378
- const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory });
37260
+ const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
37261
+ const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory, e2ee });
36379
37262
  const onBridgeIdentified = createOnBridgeIdentified({
36380
37263
  sessionWorktreeManager,
36381
37264
  devServerManager,
@@ -36394,7 +37277,8 @@ async function createBridgeConnection(options) {
36394
37277
  onBridgeIdentified,
36395
37278
  sendLocalSkillsReport,
36396
37279
  reportAutoDetectedAgents,
36397
- devServerManager
37280
+ devServerManager,
37281
+ e2ee
36398
37282
  };
36399
37283
  const { connect } = createMainBridgeWebSocketLifecycle({
36400
37284
  state,
@@ -36406,7 +37290,8 @@ async function createBridgeConnection(options) {
36406
37290
  messageDeps,
36407
37291
  tokens,
36408
37292
  persistTokens,
36409
- onAuthInvalid
37293
+ onAuthInvalid,
37294
+ e2ee
36410
37295
  });
36411
37296
  connect();
36412
37297
  const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
@@ -36418,14 +37303,149 @@ async function createBridgeConnection(options) {
36418
37303
  };
36419
37304
  }
36420
37305
 
37306
+ // src/e2e-certificates/key-command.ts
37307
+ import * as readline3 from "node:readline";
37308
+ function installE2eCertificateKeyCommand({
37309
+ log: log2,
37310
+ onOpenCertificate,
37311
+ onInterrupt
37312
+ }) {
37313
+ if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
37314
+ log2("[E2EE] Press c to import the E2EE key in a browser when running in an interactive terminal.");
37315
+ return () => {
37316
+ };
37317
+ }
37318
+ readline3.emitKeypressEvents(process.stdin);
37319
+ process.stdin.setRawMode(true);
37320
+ process.stdin.resume();
37321
+ const onKeypress = (str, key) => {
37322
+ if (key?.ctrl && key.name === "c") {
37323
+ onInterrupt();
37324
+ return;
37325
+ }
37326
+ if (!key?.ctrl && !key?.meta && (key?.name === "c" || str === "c")) {
37327
+ onOpenCertificate();
37328
+ }
37329
+ };
37330
+ process.stdin.on("keypress", onKeypress);
37331
+ log2("[E2EE] Press c to import the active E2EE key into the browser.");
37332
+ return () => {
37333
+ process.stdin.off("keypress", onKeypress);
37334
+ if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
37335
+ process.stdin.setRawMode(false);
37336
+ }
37337
+ };
37338
+ }
37339
+
37340
+ // src/e2e-certificates/open-import-url.ts
37341
+ async function openE2eCertificateImportUrl({
37342
+ apiUrl,
37343
+ workspaceId,
37344
+ certificate,
37345
+ log: log2
37346
+ }) {
37347
+ const appUrl = appUrlForApiUrl(apiUrl);
37348
+ const payload = encodeURIComponent(certificate.pemBundle);
37349
+ const url2 = `${appUrl.replace(/\/$/, "")}/w/${encodeURIComponent(workspaceId)}/settings/e2e-encryption?certificate=${payload}`;
37350
+ log2(`[E2EE] Opening browser to import key "${certificate.name}" (${certificate.id})...`);
37351
+ try {
37352
+ await open_default(url2, { wait: false });
37353
+ } catch {
37354
+ log2("[E2EE] Could not open browser. Open this URL manually:");
37355
+ log2(url2);
37356
+ }
37357
+ }
37358
+
37359
+ // src/run-bridge-connected.ts
37360
+ async function runConnectedBridge(options, restartWithoutAuth) {
37361
+ const {
37362
+ apiUrl,
37363
+ workspaceId,
37364
+ authToken,
37365
+ refreshToken,
37366
+ justAuthenticated,
37367
+ worktreesRootAbs,
37368
+ e2eCertificate
37369
+ } = options;
37370
+ const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
37371
+ let cleanupKeyCommand;
37372
+ const handle = await createBridgeConnection({
37373
+ apiUrl,
37374
+ workspaceId,
37375
+ authToken,
37376
+ refreshToken,
37377
+ firehoseServerUrl,
37378
+ justAuthenticated,
37379
+ worktreesRootAbs,
37380
+ e2eCertificate,
37381
+ log,
37382
+ persistTokens: (t) => {
37383
+ writeConfigForApi(apiUrl, {
37384
+ workspaceId,
37385
+ token: t.token,
37386
+ refreshToken: t.refreshToken
37387
+ });
37388
+ },
37389
+ onAuthInvalid: () => {
37390
+ cleanupKeyCommand?.();
37391
+ log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
37392
+ clearConfigForApi(apiUrl);
37393
+ void handle.close().then(() => {
37394
+ void restartWithoutAuth({ apiUrl, firehoseServerUrl, worktreesRootAbs, e2eCertificate });
37395
+ });
37396
+ }
37397
+ });
37398
+ const onSignal = (kind) => {
37399
+ cleanupKeyCommand?.();
37400
+ logImmediate(
37401
+ kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
37402
+ );
37403
+ setImmediate(() => {
37404
+ void handle.close().then(() => {
37405
+ process.exit(0);
37406
+ });
37407
+ });
37408
+ };
37409
+ const onSigInt = () => onSignal("interrupt");
37410
+ const onSigTerm = () => onSignal("stop");
37411
+ process.on("SIGINT", onSigInt);
37412
+ process.on("SIGTERM", onSigTerm);
37413
+ if (e2eCertificate) {
37414
+ let openingCertificate = false;
37415
+ cleanupKeyCommand = installE2eCertificateKeyCommand({
37416
+ log,
37417
+ onInterrupt: onSigInt,
37418
+ onOpenCertificate: () => {
37419
+ if (openingCertificate) return;
37420
+ openingCertificate = true;
37421
+ void openE2eCertificateImportUrl({
37422
+ apiUrl,
37423
+ workspaceId,
37424
+ certificate: e2eCertificate,
37425
+ log
37426
+ }).finally(() => {
37427
+ openingCertificate = false;
37428
+ });
37429
+ }
37430
+ });
37431
+ }
37432
+ }
37433
+
36421
37434
  // src/run-bridge.ts
36422
37435
  async function runBridge(options) {
36423
37436
  installBridgeProcessResilience();
36424
- const { apiUrl, workspaceId, authToken, refreshToken, bridgeName, justAuthenticated, worktreesRootAbs } = options;
37437
+ const {
37438
+ apiUrl,
37439
+ workspaceId,
37440
+ authToken,
37441
+ bridgeName,
37442
+ worktreesRootAbs,
37443
+ e2eCertificate
37444
+ } = options;
36425
37445
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
36426
37446
  const hasAuth = workspaceId && authToken;
36427
37447
  if (!hasAuth) {
36428
- const handle2 = runPendingAuth({
37448
+ const handle = runPendingAuth({
36429
37449
  apiUrl,
36430
37450
  initialWorkspaceId: workspaceId,
36431
37451
  preferredBridgeName: bridgeName,
@@ -36433,23 +37453,23 @@ async function runBridge(options) {
36433
37453
  onAuth: (_auth) => {
36434
37454
  }
36435
37455
  });
36436
- const onSignal2 = (kind) => {
37456
+ const onSignal = (kind) => {
36437
37457
  logImmediate(
36438
37458
  kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
36439
37459
  );
36440
37460
  setImmediate(() => {
36441
- handle2.close();
37461
+ handle.close();
36442
37462
  process.exit(0);
36443
37463
  });
36444
37464
  };
36445
- const onSigInt2 = () => onSignal2("interrupt");
36446
- const onSigTerm2 = () => onSignal2("stop");
36447
- process.on("SIGINT", onSigInt2);
36448
- process.on("SIGTERM", onSigTerm2);
36449
- const auth = await handle2.authPromise;
36450
- process.off("SIGINT", onSigInt2);
36451
- process.off("SIGTERM", onSigTerm2);
36452
- handle2.close();
37465
+ const onSigInt = () => onSignal("interrupt");
37466
+ const onSigTerm = () => onSignal("stop");
37467
+ process.on("SIGINT", onSigInt);
37468
+ process.on("SIGTERM", onSigTerm);
37469
+ const auth = await handle.authPromise;
37470
+ process.off("SIGINT", onSigInt);
37471
+ process.off("SIGTERM", onSigTerm);
37472
+ handle.close();
36453
37473
  if (!auth) return;
36454
37474
  writeConfigForApi(apiUrl, {
36455
37475
  workspaceId: auth.workspaceId,
@@ -36464,111 +37484,91 @@ async function runBridge(options) {
36464
37484
  firehoseServerUrl,
36465
37485
  bridgeName,
36466
37486
  justAuthenticated: true,
36467
- worktreesRootAbs
37487
+ worktreesRootAbs,
37488
+ e2eCertificate
36468
37489
  });
36469
37490
  return;
36470
37491
  }
36471
- const handle = await createBridgeConnection({
37492
+ await runConnectedBridge(options, runBridge);
37493
+ }
37494
+
37495
+ // src/cli/run-cli-action.ts
37496
+ async function runCliAction(program2, opts) {
37497
+ const positionalUrl = program2.args?.[0];
37498
+ const urlFromPositional = typeof positionalUrl === "string" && /^https?:\/\//i.test(positionalUrl) ? positionalUrl : void 0;
37499
+ const apiUrlFromCli = opts.apiUrl ?? urlFromPositional;
37500
+ const apiUrl = apiUrlFromCli ?? DEFAULT_API_URL;
37501
+ let workspaceId = opts.workspaceId ?? "";
37502
+ let authToken = opts.token;
37503
+ const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
37504
+ if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
37505
+ const resolvedCwd = path33.resolve(process.cwd(), opts.cwd.trim());
37506
+ try {
37507
+ const st = fs30.statSync(resolvedCwd);
37508
+ if (!st.isDirectory()) {
37509
+ console.error(`--cwd is not a directory: ${resolvedCwd}`);
37510
+ process.exit(1);
37511
+ }
37512
+ } catch {
37513
+ console.error(`--cwd path does not exist or is not accessible: ${resolvedCwd}`);
37514
+ process.exit(1);
37515
+ }
37516
+ process.chdir(resolvedCwd);
37517
+ }
37518
+ initBridgeWorkspaceDirectory();
37519
+ let worktreesRootAbs;
37520
+ if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
37521
+ worktreesRootAbs = path33.resolve(opts.worktreesRoot.trim());
37522
+ }
37523
+ const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
37524
+ if (e2eCertificates) {
37525
+ const action = e2eCertificates.generated ? "Generated" : "Loaded";
37526
+ console.log(
37527
+ `[E2EE] ${action} ${e2eCertificates.certificates.length} key${e2eCertificates.certificates.length === 1 ? "" : "s"} from ${e2eCertificates.directory}`
37528
+ );
37529
+ console.log(
37530
+ `[E2EE] Active key: ${e2eCertificates.activeCertificate.name} (${e2eCertificates.activeCertificate.id})`
37531
+ );
37532
+ }
37533
+ let refreshToken;
37534
+ if ((!workspaceId || !authToken) && opts.config !== false) {
37535
+ const saved = readConfigForApi(apiUrl);
37536
+ if (saved?.workspaceId && saved?.token) {
37537
+ if (!workspaceId) workspaceId = saved.workspaceId;
37538
+ if (!authToken) authToken = saved.token;
37539
+ refreshToken = saved.refreshToken;
37540
+ }
37541
+ }
37542
+ await runBridge({
36472
37543
  apiUrl,
36473
- workspaceId,
37544
+ workspaceId: workspaceId || void 0,
36474
37545
  authToken,
36475
37546
  refreshToken,
36476
37547
  firehoseServerUrl,
36477
- justAuthenticated,
37548
+ bridgeName: opts.name?.trim() || void 0,
36478
37549
  worktreesRootAbs,
36479
- log,
36480
- persistTokens: (t) => {
36481
- writeConfigForApi(apiUrl, {
36482
- workspaceId,
36483
- token: t.token,
36484
- refreshToken: t.refreshToken
36485
- });
36486
- },
36487
- onAuthInvalid: () => {
36488
- log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
36489
- clearConfigForApi(apiUrl);
36490
- void handle.close().then(() => {
36491
- void runBridge({ apiUrl, firehoseServerUrl, worktreesRootAbs });
36492
- });
36493
- }
37550
+ e2eCertificate: e2eCertificates?.activeCertificate
36494
37551
  });
36495
- const onSignal = (kind) => {
36496
- logImmediate(
36497
- kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
36498
- );
36499
- setImmediate(() => {
36500
- void handle.close().then(() => {
36501
- process.exit(0);
36502
- });
36503
- });
36504
- };
36505
- const onSigInt = () => onSignal("interrupt");
36506
- const onSigTerm = () => onSignal("stop");
36507
- process.on("SIGINT", onSigInt);
36508
- process.on("SIGTERM", onSigTerm);
36509
37552
  }
36510
37553
 
36511
37554
  // src/cli.ts
36512
- var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
36513
- var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
36514
37555
  async function main() {
36515
37556
  const program2 = new Command();
36516
- program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version("0.1.0").option("-u, --api-url <url>", "Backend API URL", process.env.BUILDAUTOMATON_API_URL ?? DEFAULT_API_URL).option("-w, --workspace-id <id>", "Workspace ID (or set BUILDAMATON_WORKSPACE_ID)", process.env.BUILDAMATON_WORKSPACE_ID).option("-t, --token <token>", "Auth token (or set BUILDAMATON_AUTH_TOKEN)", process.env.BUILDAMATON_AUTH_TOKEN).option(
37557
+ program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version("0.1.0").option("-u, --api-url <url>", "Backend API URL", process.env.BUILDAUTOMATON_API_URL ?? DEFAULT_API_URL).option("-w, --workspace-id <id>", "Workspace ID (or set BUILDAUTOMATON_WORKSPACE_ID)", process.env.BUILDAUTOMATON_WORKSPACE_ID).option("-t, --token <token>", "Auth token (or set BUILDAUTOMATON_AUTH_TOKEN)", process.env.BUILDAUTOMATON_AUTH_TOKEN).option(
36517
37558
  "--firehose-url <url>",
36518
- "Firehose server URL (default: Fly app; or BUILDAMATON_FIREHOSE_URL / legacy BUILDAMATON_PROXY_URL)",
36519
- process.env.BUILDAMATON_FIREHOSE_URL ?? process.env.BUILDAMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL
37559
+ "Firehose server URL (default: Fly app; or BUILDAUTOMATON_FIREHOSE_URL / legacy BUILDAUTOMATON_PROXY_URL)",
37560
+ process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL
36520
37561
  ).option("--proxy-url <url>", "Deprecated alias for --firehose-url", void 0).option(
36521
37562
  "--cwd <path>",
36522
37563
  "Working directory for the bridge (absolute or relative to the current directory); affects skills, git, file index, and agent cwd"
36523
37564
  ).option("-n, --name <name>", "Bridge name when creating via browser (alphanumeric and underscores only)").option(
36524
37565
  "--worktrees-root <path>",
36525
37566
  "Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees). Whether worktrees are used is controlled in the cloud for each bridge token."
36526
- ).option("--no-config", "Ignore saved config at ~/.buildautomaton/config.json").action(async (opts) => {
36527
- const positionalUrl = program2.args?.[0];
36528
- const urlFromPositional = typeof positionalUrl === "string" && /^https?:\/\//i.test(positionalUrl) ? positionalUrl : void 0;
36529
- const apiUrlFromCli = opts.apiUrl ?? urlFromPositional;
36530
- let apiUrl = apiUrlFromCli ?? DEFAULT_API_URL;
36531
- let workspaceId = opts.workspaceId ?? "";
36532
- let authToken = opts.token;
36533
- const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAMATON_FIREHOSE_URL ?? process.env.BUILDAMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
36534
- if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
36535
- const resolvedCwd = path31.resolve(process.cwd(), opts.cwd.trim());
36536
- try {
36537
- const st = fs24.statSync(resolvedCwd);
36538
- if (!st.isDirectory()) {
36539
- console.error(`--cwd is not a directory: ${resolvedCwd}`);
36540
- process.exit(1);
36541
- }
36542
- } catch {
36543
- console.error(`--cwd path does not exist or is not accessible: ${resolvedCwd}`);
36544
- process.exit(1);
36545
- }
36546
- process.chdir(resolvedCwd);
36547
- }
36548
- initBridgeWorkspaceDirectory();
36549
- let worktreesRootAbs;
36550
- if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
36551
- worktreesRootAbs = path31.resolve(opts.worktreesRoot.trim());
36552
- }
36553
- let refreshToken;
36554
- if ((!workspaceId || !authToken) && opts.config !== false) {
36555
- const saved = readConfigForApi(apiUrl);
36556
- if (saved?.workspaceId && saved?.token) {
36557
- if (!workspaceId) workspaceId = saved.workspaceId;
36558
- if (!authToken) authToken = saved.token;
36559
- refreshToken = saved.refreshToken;
36560
- }
36561
- }
36562
- await runBridge({
36563
- apiUrl,
36564
- workspaceId: workspaceId || void 0,
36565
- authToken,
36566
- refreshToken,
36567
- firehoseServerUrl,
36568
- bridgeName: opts.name?.trim() || void 0,
36569
- worktreesRootAbs
36570
- });
36571
- });
37567
+ ).option(
37568
+ "--e2ee-certificates-dir <path>",
37569
+ "Directory to load or generate E2EE keys for sessions, files, and logs",
37570
+ process.env.BUILDAUTOMATON_E2EE_CERTIFICATES_DIR
37571
+ ).option("--no-config", "Ignore saved config at ~/.buildautomaton/config.json").action(async (opts) => runCliAction(program2, opts));
36572
37572
  await program2.parseAsync(process.argv);
36573
37573
  }
36574
37574
  main().catch((err) => {