@buildautomaton/cli 0.1.15 → 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
@@ -973,8 +973,8 @@ 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
975
  var childProcess2 = __require("node:child_process");
976
- var path33 = __require("node:path");
977
- var fs30 = __require("node:fs");
976
+ var path34 = __require("node:path");
977
+ var fs31 = __require("node:fs");
978
978
  var process8 = __require("node:process");
979
979
  var { Argument: Argument2, humanReadableArgName } = require_argument();
980
980
  var { CommanderError: CommanderError2 } = require_error();
@@ -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 = path33.resolve(baseDir, baseName);
1910
- if (fs30.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path33.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) => fs30.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 = fs30.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs31.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path33.resolve(
1930
- path33.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 = path33.basename(
1937
+ const legacyName = path34.basename(
1938
1938
  this._scriptPath,
1939
- path33.extname(this._scriptPath)
1939
+ path34.extname(this._scriptPath)
1940
1940
  );
1941
1941
  if (legacyName !== this._name) {
1942
1942
  localFile = findFile(
@@ -1947,7 +1947,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1947
1947
  }
1948
1948
  executableFile = localFile || executableFile;
1949
1949
  }
1950
- launchWithNode = sourceExt.includes(path33.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path34.extname(executableFile));
1951
1951
  let proc;
1952
1952
  if (process8.platform !== "win32") {
1953
1953
  if (launchWithNode) {
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2787
2787
  * @return {Command}
2788
2788
  */
2789
2789
  nameFromFilename(filename) {
2790
- this._name = path33.basename(filename, path33.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(path34) {
2805
- if (path34 === void 0) return this._executableDir;
2806
- this._executableDir = path34;
2804
+ executableDir(path35) {
2805
+ if (path35 === void 0) return this._executableDir;
2806
+ this._executableDir = path35;
2807
2807
  return this;
2808
2808
  }
2809
2809
  /**
@@ -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;
@@ -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",
@@ -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(path33, isFile, isDirectory) {
7427
- log2(`checking %s`, path33);
7426
+ function check2(path34, isFile, isDirectory) {
7427
+ log2(`checking %s`, path34);
7428
7428
  try {
7429
- const stat2 = fs_1.statSync(path33);
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(path33, type = exports.READABLE) {
7450
- return check2(path33, (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: path33, errorMaps, issueData } = params;
7926
- const fullPath = [...path33, ...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, path33, key) {
8234
+ constructor(parent, value, path34, key) {
8235
8235
  this._cachedPath = [];
8236
8236
  this.parent = parent;
8237
8237
  this.data = value;
8238
- this._path = path33;
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, path33) {
11854
- if (!path33)
11853
+ function getElementAtPath(obj, path34) {
11854
+ if (!path34)
11855
11855
  return obj;
11856
- return path33.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(path33, 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(path33);
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, path33 = []) => {
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 = [...path33, ...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(path33) {
12338
+ function toDotPath(path34) {
12339
12339
  const segs = [];
12340
- for (const seg of path33) {
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 fs29 from "node:fs";
25051
- import * as path32 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
  }
@@ -25324,30 +25604,30 @@ function sendWsMessage(ws, payload) {
25324
25604
  // ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
25325
25605
  import process7 from "node:process";
25326
25606
  import { Buffer as Buffer2 } from "node:buffer";
25327
- import path3 from "node:path";
25607
+ import path4 from "node:path";
25328
25608
  import { fileURLToPath } from "node:url";
25329
25609
  import { promisify as promisify5 } from "node:util";
25330
25610
  import childProcess from "node:child_process";
25331
- import fs6, { constants as fsConstants2 } from "node:fs/promises";
25611
+ import fs7, { constants as fsConstants2 } from "node:fs/promises";
25332
25612
 
25333
25613
  // ../../node_modules/.pnpm/wsl-utils@0.1.0/node_modules/wsl-utils/index.js
25334
25614
  import process3 from "node:process";
25335
- import fs5, { constants as fsConstants } from "node:fs/promises";
25615
+ import fs6, { constants as fsConstants } from "node:fs/promises";
25336
25616
 
25337
25617
  // ../../node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js
25338
25618
  import process2 from "node:process";
25339
25619
  import os2 from "node:os";
25340
- import fs4 from "node:fs";
25620
+ import fs5 from "node:fs";
25341
25621
 
25342
25622
  // ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
25343
- import fs3 from "node:fs";
25623
+ import fs4 from "node:fs";
25344
25624
 
25345
25625
  // ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
25346
- import fs2 from "node:fs";
25626
+ import fs3 from "node:fs";
25347
25627
  var isDockerCached;
25348
25628
  function hasDockerEnv() {
25349
25629
  try {
25350
- fs2.statSync("/.dockerenv");
25630
+ fs3.statSync("/.dockerenv");
25351
25631
  return true;
25352
25632
  } catch {
25353
25633
  return false;
@@ -25355,7 +25635,7 @@ function hasDockerEnv() {
25355
25635
  }
25356
25636
  function hasDockerCGroup() {
25357
25637
  try {
25358
- return fs2.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
25638
+ return fs3.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
25359
25639
  } catch {
25360
25640
  return false;
25361
25641
  }
@@ -25371,7 +25651,7 @@ function isDocker() {
25371
25651
  var cachedResult;
25372
25652
  var hasContainerEnv = () => {
25373
25653
  try {
25374
- fs3.statSync("/run/.containerenv");
25654
+ fs4.statSync("/run/.containerenv");
25375
25655
  return true;
25376
25656
  } catch {
25377
25657
  return false;
@@ -25396,12 +25676,12 @@ var isWsl = () => {
25396
25676
  return true;
25397
25677
  }
25398
25678
  try {
25399
- if (fs4.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
25679
+ if (fs5.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
25400
25680
  return !isInsideContainer();
25401
25681
  }
25402
25682
  } catch {
25403
25683
  }
25404
- if (fs4.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs4.existsSync("/run/WSL")) {
25684
+ if (fs5.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs5.existsSync("/run/WSL")) {
25405
25685
  return !isInsideContainer();
25406
25686
  }
25407
25687
  return false;
@@ -25419,14 +25699,14 @@ var wslDrivesMountPoint = /* @__PURE__ */ (() => {
25419
25699
  const configFilePath2 = "/etc/wsl.conf";
25420
25700
  let isConfigFileExists = false;
25421
25701
  try {
25422
- await fs5.access(configFilePath2, fsConstants.F_OK);
25702
+ await fs6.access(configFilePath2, fsConstants.F_OK);
25423
25703
  isConfigFileExists = true;
25424
25704
  } catch {
25425
25705
  }
25426
25706
  if (!isConfigFileExists) {
25427
25707
  return defaultMountPoint;
25428
25708
  }
25429
- const configContent = await fs5.readFile(configFilePath2, { encoding: "utf8" });
25709
+ const configContent = await fs6.readFile(configFilePath2, { encoding: "utf8" });
25430
25710
  const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
25431
25711
  if (!configMountPoint) {
25432
25712
  return defaultMountPoint;
@@ -25580,8 +25860,8 @@ async function defaultBrowser2() {
25580
25860
 
25581
25861
  // ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
25582
25862
  var execFile5 = promisify5(childProcess.execFile);
25583
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
25584
- var localXdgOpenPath = path3.join(__dirname, "xdg-open");
25863
+ var __dirname = path4.dirname(fileURLToPath(import.meta.url));
25864
+ var localXdgOpenPath = path4.join(__dirname, "xdg-open");
25585
25865
  var { platform, arch } = process7;
25586
25866
  async function getWindowsDefaultBrowserFromWsl() {
25587
25867
  const powershellPath = await powerShellPath();
@@ -25731,7 +26011,7 @@ var baseOpen = async (options) => {
25731
26011
  const isBundled = !__dirname || __dirname === "/";
25732
26012
  let exeLocalXdgOpen = false;
25733
26013
  try {
25734
- await fs6.access(localXdgOpenPath, fsConstants2.X_OK);
26014
+ await fs7.access(localXdgOpenPath, fsConstants2.X_OK);
25735
26015
  exeLocalXdgOpen = true;
25736
26016
  } catch {
25737
26017
  }
@@ -25754,14 +26034,14 @@ var baseOpen = async (options) => {
25754
26034
  }
25755
26035
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
25756
26036
  if (options.wait) {
25757
- return new Promise((resolve16, reject) => {
26037
+ return new Promise((resolve17, reject) => {
25758
26038
  subprocess.once("error", reject);
25759
26039
  subprocess.once("close", (exitCode) => {
25760
26040
  if (!options.allowNonzeroExitCode && exitCode > 0) {
25761
26041
  reject(new Error(`Exited with code ${exitCode}`));
25762
26042
  return;
25763
26043
  }
25764
- resolve16(subprocess);
26044
+ resolve17(subprocess);
25765
26045
  });
25766
26046
  });
25767
26047
  }
@@ -25845,8 +26125,11 @@ function isLocalApiUrl(apiUrl) {
25845
26125
  return false;
25846
26126
  }
25847
26127
  }
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
+ }
25848
26131
  async function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn = log) {
25849
- const appUrl = apiUrl && isLocalApiUrl(apiUrl) ? process.env.BUILDAUTOMATON_APP_URL ?? "http://localhost:3000" : process.env.BUILDAUTOMATON_APP_URL ?? "https://app.buildautomaton.com";
26132
+ const appUrl = appUrlForApiUrl(apiUrl);
25850
26133
  let connectCliUrl = `${appUrl.replace(/\/$/, "")}/bridges/connect?connectionId=${connectionId}`;
25851
26134
  if (initialWorkspaceId) {
25852
26135
  try {
@@ -26054,8 +26337,8 @@ function runPendingAuth(options) {
26054
26337
  let hasOpenedBrowser = false;
26055
26338
  let resolved = false;
26056
26339
  let resolveAuth;
26057
- const authPromise = new Promise((resolve16) => {
26058
- resolveAuth = resolve16;
26340
+ const authPromise = new Promise((resolve17) => {
26341
+ resolveAuth = resolve17;
26059
26342
  });
26060
26343
  let reconnectAttempt = 0;
26061
26344
  const signInQuiet = createEmptyReconnectQuietSlot();
@@ -26177,7 +26460,7 @@ function runPendingAuth(options) {
26177
26460
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
26178
26461
  const say = log2 ?? logImmediate;
26179
26462
  say("Cleaning up connections\u2026");
26180
- await new Promise((resolve16) => setImmediate(resolve16));
26463
+ await new Promise((resolve17) => setImmediate(resolve17));
26181
26464
  state.closedByUser = true;
26182
26465
  clearReconnectQuietTimer(state.mainQuiet);
26183
26466
  clearReconnectQuietTimer(state.firehoseQuiet);
@@ -26248,19 +26531,19 @@ function localAgentErrorSuggestsAuth(agentType, errorText) {
26248
26531
 
26249
26532
  // src/git/session-git-queue.ts
26250
26533
  import { execFile as execFile7 } from "node:child_process";
26251
- import { readFile, stat } from "node:fs/promises";
26534
+ import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
26252
26535
  import { promisify as promisify7 } from "node:util";
26253
- import * as path6 from "node:path";
26536
+ import * as path7 from "node:path";
26254
26537
 
26255
26538
  // src/git/pre-turn-snapshot.ts
26256
- import * as fs8 from "node:fs";
26257
- import * as path5 from "node:path";
26539
+ import * as fs9 from "node:fs";
26540
+ import * as path6 from "node:path";
26258
26541
  import { execFile as execFile6 } from "node:child_process";
26259
26542
  import { promisify as promisify6 } from "node:util";
26260
26543
 
26261
26544
  // src/git/discover-repos.ts
26262
- import * as fs7 from "node:fs";
26263
- import * as path4 from "node:path";
26545
+ import * as fs8 from "node:fs";
26546
+ import * as path5 from "node:path";
26264
26547
 
26265
26548
  // ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
26266
26549
  var import_file_exists = __toESM(require_dist(), 1);
@@ -26299,8 +26582,8 @@ function pathspec(...paths) {
26299
26582
  cache.set(key, paths);
26300
26583
  return key;
26301
26584
  }
26302
- function isPathSpec(path33) {
26303
- return path33 instanceof String && cache.has(path33);
26585
+ function isPathSpec(path34) {
26586
+ return path34 instanceof String && cache.has(path34);
26304
26587
  }
26305
26588
  function toPaths(pathSpec) {
26306
26589
  return cache.get(pathSpec) || [];
@@ -26389,8 +26672,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
26389
26672
  function forEachLineWithContent(input, callback) {
26390
26673
  return toLinesWithContent(input, true).map((line) => callback(line));
26391
26674
  }
26392
- function folderExists(path33) {
26393
- return (0, import_file_exists.exists)(path33, import_file_exists.FOLDER);
26675
+ function folderExists(path34) {
26676
+ return (0, import_file_exists.exists)(path34, import_file_exists.FOLDER);
26394
26677
  }
26395
26678
  function append(target, item) {
26396
26679
  if (Array.isArray(target)) {
@@ -26794,8 +27077,8 @@ function checkIsRepoRootTask() {
26794
27077
  commands,
26795
27078
  format: "utf-8",
26796
27079
  onError,
26797
- parser(path33) {
26798
- return /^\.(git)?$/.test(path33.trim());
27080
+ parser(path34) {
27081
+ return /^\.(git)?$/.test(path34.trim());
26799
27082
  }
26800
27083
  };
26801
27084
  }
@@ -27229,11 +27512,11 @@ function parseGrep(grep) {
27229
27512
  const paths = /* @__PURE__ */ new Set();
27230
27513
  const results = {};
27231
27514
  forEachLineWithContent(grep, (input) => {
27232
- const [path33, line, preview] = input.split(NULL);
27233
- paths.add(path33);
27234
- (results[path33] = results[path33] || []).push({
27515
+ const [path34, line, preview] = input.split(NULL);
27516
+ paths.add(path34);
27517
+ (results[path34] = results[path34] || []).push({
27235
27518
  line: asNumber(line),
27236
- path: path33,
27519
+ path: path34,
27237
27520
  preview
27238
27521
  });
27239
27522
  });
@@ -27998,14 +28281,14 @@ var init_hash_object = __esm2({
27998
28281
  init_task();
27999
28282
  }
28000
28283
  });
28001
- function parseInit(bare, path33, text) {
28284
+ function parseInit(bare, path34, text) {
28002
28285
  const response = String(text).trim();
28003
28286
  let result;
28004
28287
  if (result = initResponseRegex.exec(response)) {
28005
- return new InitSummary(bare, path33, false, result[1]);
28288
+ return new InitSummary(bare, path34, false, result[1]);
28006
28289
  }
28007
28290
  if (result = reInitResponseRegex.exec(response)) {
28008
- return new InitSummary(bare, path33, true, result[1]);
28291
+ return new InitSummary(bare, path34, true, result[1]);
28009
28292
  }
28010
28293
  let gitDir = "";
28011
28294
  const tokens = response.split(" ");
@@ -28016,7 +28299,7 @@ function parseInit(bare, path33, text) {
28016
28299
  break;
28017
28300
  }
28018
28301
  }
28019
- return new InitSummary(bare, path33, /^re/i.test(response), gitDir);
28302
+ return new InitSummary(bare, path34, /^re/i.test(response), gitDir);
28020
28303
  }
28021
28304
  var InitSummary;
28022
28305
  var initResponseRegex;
@@ -28025,9 +28308,9 @@ var init_InitSummary = __esm2({
28025
28308
  "src/lib/responses/InitSummary.ts"() {
28026
28309
  "use strict";
28027
28310
  InitSummary = class {
28028
- constructor(bare, path33, existing, gitDir) {
28311
+ constructor(bare, path34, existing, gitDir) {
28029
28312
  this.bare = bare;
28030
- this.path = path33;
28313
+ this.path = path34;
28031
28314
  this.existing = existing;
28032
28315
  this.gitDir = gitDir;
28033
28316
  }
@@ -28039,7 +28322,7 @@ var init_InitSummary = __esm2({
28039
28322
  function hasBareCommand(command) {
28040
28323
  return command.includes(bareCommand);
28041
28324
  }
28042
- function initTask(bare = false, path33, customArgs) {
28325
+ function initTask(bare = false, path34, customArgs) {
28043
28326
  const commands = ["init", ...customArgs];
28044
28327
  if (bare && !hasBareCommand(commands)) {
28045
28328
  commands.splice(1, 0, bareCommand);
@@ -28048,7 +28331,7 @@ function initTask(bare = false, path33, customArgs) {
28048
28331
  commands,
28049
28332
  format: "utf-8",
28050
28333
  parser(text) {
28051
- return parseInit(commands.includes("--bare"), path33, text);
28334
+ return parseInit(commands.includes("--bare"), path34, text);
28052
28335
  }
28053
28336
  };
28054
28337
  }
@@ -28864,12 +29147,12 @@ var init_FileStatusSummary = __esm2({
28864
29147
  "use strict";
28865
29148
  fromPathRegex = /^(.+)\0(.+)$/;
28866
29149
  FileStatusSummary = class {
28867
- constructor(path33, index, working_dir) {
28868
- this.path = path33;
29150
+ constructor(path34, index, working_dir) {
29151
+ this.path = path34;
28869
29152
  this.index = index;
28870
29153
  this.working_dir = working_dir;
28871
29154
  if (index === "R" || working_dir === "R") {
28872
- const detail = fromPathRegex.exec(path33) || [null, path33, path33];
29155
+ const detail = fromPathRegex.exec(path34) || [null, path34, path34];
28873
29156
  this.from = detail[2] || "";
28874
29157
  this.path = detail[1] || "";
28875
29158
  }
@@ -28900,14 +29183,14 @@ function splitLine(result, lineStr) {
28900
29183
  default:
28901
29184
  return;
28902
29185
  }
28903
- function data(index, workingDir, path33) {
29186
+ function data(index, workingDir, path34) {
28904
29187
  const raw = `${index}${workingDir}`;
28905
29188
  const handler = parsers6.get(raw);
28906
29189
  if (handler) {
28907
- handler(result, path33);
29190
+ handler(result, path34);
28908
29191
  }
28909
29192
  if (raw !== "##" && raw !== "!!") {
28910
- result.files.push(new FileStatusSummary(path33, index, workingDir));
29193
+ result.files.push(new FileStatusSummary(path34, index, workingDir));
28911
29194
  }
28912
29195
  }
28913
29196
  }
@@ -29216,9 +29499,9 @@ var init_simple_git_api = __esm2({
29216
29499
  next
29217
29500
  );
29218
29501
  }
29219
- hashObject(path33, write) {
29502
+ hashObject(path34, write) {
29220
29503
  return this._runTask(
29221
- hashObjectTask(path33, write === true),
29504
+ hashObjectTask(path34, write === true),
29222
29505
  trailingFunctionArgument(arguments)
29223
29506
  );
29224
29507
  }
@@ -29571,8 +29854,8 @@ var init_branch = __esm2({
29571
29854
  }
29572
29855
  });
29573
29856
  function toPath(input) {
29574
- const path33 = input.trim().replace(/^["']|["']$/g, "");
29575
- return path33 && normalize(path33);
29857
+ const path34 = input.trim().replace(/^["']|["']$/g, "");
29858
+ return path34 && normalize(path34);
29576
29859
  }
29577
29860
  var parseCheckIgnore;
29578
29861
  var init_CheckIgnore = __esm2({
@@ -29886,8 +30169,8 @@ __export2(sub_module_exports, {
29886
30169
  subModuleTask: () => subModuleTask,
29887
30170
  updateSubModuleTask: () => updateSubModuleTask
29888
30171
  });
29889
- function addSubModuleTask(repo, path33) {
29890
- return subModuleTask(["add", repo, path33]);
30172
+ function addSubModuleTask(repo, path34) {
30173
+ return subModuleTask(["add", repo, path34]);
29891
30174
  }
29892
30175
  function initSubModuleTask(customArgs) {
29893
30176
  return subModuleTask(["init", ...customArgs]);
@@ -30220,8 +30503,8 @@ var require_git = __commonJS2({
30220
30503
  }
30221
30504
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
30222
30505
  };
30223
- Git2.prototype.submoduleAdd = function(repo, path33, then) {
30224
- return this._runTask(addSubModuleTask2(repo, path33), trailingFunctionArgument2(arguments));
30506
+ Git2.prototype.submoduleAdd = function(repo, path34, then) {
30507
+ return this._runTask(addSubModuleTask2(repo, path34), trailingFunctionArgument2(arguments));
30225
30508
  };
30226
30509
  Git2.prototype.submoduleUpdate = function(args, then) {
30227
30510
  return this._runTask(
@@ -30847,20 +31130,20 @@ async function isGitRepoDirectory(dirPath) {
30847
31130
  // src/git/discover-repos.ts
30848
31131
  async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
30849
31132
  const result = [];
30850
- const cwdResolved = path4.resolve(cwd);
31133
+ const cwdResolved = path5.resolve(cwd);
30851
31134
  if (await isGitRepoDirectory(cwdResolved)) {
30852
31135
  const remoteUrl = await getRemoteOriginUrl(cwdResolved);
30853
31136
  result.push({ absolutePath: cwdResolved, remoteUrl });
30854
31137
  }
30855
31138
  let entries;
30856
31139
  try {
30857
- entries = fs7.readdirSync(cwdResolved, { withFileTypes: true });
31140
+ entries = fs8.readdirSync(cwdResolved, { withFileTypes: true });
30858
31141
  } catch {
30859
31142
  return result;
30860
31143
  }
30861
31144
  for (const ent of entries) {
30862
31145
  if (!ent.isDirectory()) continue;
30863
- const childPath = path4.join(cwdResolved, ent.name);
31146
+ const childPath = path5.join(cwdResolved, ent.name);
30864
31147
  if (await isGitRepoDirectory(childPath)) {
30865
31148
  const remoteUrl = await getRemoteOriginUrl(childPath);
30866
31149
  result.push({ absolutePath: childPath, remoteUrl });
@@ -30869,22 +31152,22 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
30869
31152
  return result;
30870
31153
  }
30871
31154
  async function discoverGitReposUnderRoot(rootAbs) {
30872
- const root = path4.resolve(rootAbs);
31155
+ const root = path5.resolve(rootAbs);
30873
31156
  const roots = [];
30874
31157
  async function walk(dir) {
30875
31158
  if (await isGitRepoDirectory(dir)) {
30876
- roots.push(path4.resolve(dir));
31159
+ roots.push(path5.resolve(dir));
30877
31160
  return;
30878
31161
  }
30879
31162
  let entries;
30880
31163
  try {
30881
- entries = fs7.readdirSync(dir, { withFileTypes: true });
31164
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
30882
31165
  } catch {
30883
31166
  return;
30884
31167
  }
30885
31168
  for (const ent of entries) {
30886
31169
  if (!ent.isDirectory() || ent.name === ".git") continue;
30887
- await walk(path4.join(dir, ent.name));
31170
+ await walk(path5.join(dir, ent.name));
30888
31171
  }
30889
31172
  }
30890
31173
  await walk(root);
@@ -30900,7 +31183,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
30900
31183
  // src/git/pre-turn-snapshot.ts
30901
31184
  var execFileAsync5 = promisify6(execFile6);
30902
31185
  function snapshotsDirForCwd(agentCwd) {
30903
- return path5.join(agentCwd, ".buildautomaton", "snapshots");
31186
+ return path6.join(agentCwd, ".buildautomaton", "snapshots");
30904
31187
  }
30905
31188
  async function gitStashCreate(repoRoot, log2) {
30906
31189
  try {
@@ -30929,7 +31212,7 @@ async function gitRun(repoRoot, args, log2, label) {
30929
31212
  async function resolveSnapshotRepoRoots(options) {
30930
31213
  const { worktreePaths, fallbackCwd, log: log2 } = options;
30931
31214
  if (worktreePaths?.length) {
30932
- const uniq = [...new Set(worktreePaths.map((p) => path5.resolve(p)))];
31215
+ const uniq = [...new Set(worktreePaths.map((p) => path6.resolve(p)))];
30933
31216
  return uniq;
30934
31217
  }
30935
31218
  try {
@@ -30952,7 +31235,7 @@ async function capturePreTurnSnapshot(options) {
30952
31235
  }
30953
31236
  const dir = snapshotsDirForCwd(agentCwd);
30954
31237
  try {
30955
- fs8.mkdirSync(dir, { recursive: true });
31238
+ fs9.mkdirSync(dir, { recursive: true });
30956
31239
  } catch (e) {
30957
31240
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
30958
31241
  }
@@ -30961,9 +31244,9 @@ async function capturePreTurnSnapshot(options) {
30961
31244
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
30962
31245
  repos
30963
31246
  };
30964
- const filePath = path5.join(dir, `${runId}.json`);
31247
+ const filePath = path6.join(dir, `${runId}.json`);
30965
31248
  try {
30966
- fs8.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
31249
+ fs9.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
30967
31250
  } catch (e) {
30968
31251
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
30969
31252
  }
@@ -30976,7 +31259,7 @@ async function capturePreTurnSnapshot(options) {
30976
31259
  async function applyPreTurnSnapshot(filePath, log2) {
30977
31260
  let data;
30978
31261
  try {
30979
- const raw = fs8.readFileSync(filePath, "utf8");
31262
+ const raw = fs9.readFileSync(filePath, "utf8");
30980
31263
  data = JSON.parse(raw);
30981
31264
  } catch (e) {
30982
31265
  return { ok: false, error: e instanceof Error ? e.message : String(e) };
@@ -30999,7 +31282,7 @@ async function applyPreTurnSnapshot(filePath, log2) {
30999
31282
  return { ok: true };
31000
31283
  }
31001
31284
  function snapshotFilePath(agentCwd, runId) {
31002
- return path5.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
31285
+ return path6.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
31003
31286
  }
31004
31287
 
31005
31288
  // src/git/session-git-queue.ts
@@ -31007,9 +31290,9 @@ var execFileAsync6 = promisify7(execFile7);
31007
31290
  var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
31008
31291
  async function readWorkspaceFileAsUtf8(absPath) {
31009
31292
  try {
31010
- const st = await stat(absPath);
31293
+ const st = await stat2(absPath);
31011
31294
  if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
31012
- return await readFile(absPath, "utf8");
31295
+ return await readFile2(absPath, "utf8");
31013
31296
  } catch {
31014
31297
  return void 0;
31015
31298
  }
@@ -31019,7 +31302,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
31019
31302
  const filePath = snapshotFilePath(agentCwd, runId);
31020
31303
  let data;
31021
31304
  try {
31022
- const raw = await readFile(filePath, "utf8");
31305
+ const raw = await readFile2(filePath, "utf8");
31023
31306
  data = JSON.parse(raw);
31024
31307
  } catch (e) {
31025
31308
  log2(
@@ -31048,7 +31331,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
31048
31331
  continue;
31049
31332
  }
31050
31333
  const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
31051
- const slug = path6.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
31334
+ const slug = path7.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
31052
31335
  for (const rel of lines) {
31053
31336
  if (rel.includes("..")) continue;
31054
31337
  try {
@@ -31062,7 +31345,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
31062
31345
  );
31063
31346
  if (!patchContent.trim()) continue;
31064
31347
  const displayPath = multiRepo ? `${slug}/${rel}` : rel;
31065
- const absFile = path6.join(repo.path, rel);
31348
+ const absFile = path7.join(repo.path, rel);
31066
31349
  const newText = await readWorkspaceFileAsUtf8(absFile);
31067
31350
  sendSessionUpdate({
31068
31351
  type: "session_file_change",
@@ -31144,8 +31427,8 @@ async function sendPromptToAgent(options) {
31144
31427
  }
31145
31428
 
31146
31429
  // src/agents/acp/ensure-acp-client.ts
31147
- import * as fs9 from "node:fs";
31148
- import * as path10 from "node:path";
31430
+ import * as fs10 from "node:fs";
31431
+ import * as path11 from "node:path";
31149
31432
 
31150
31433
  // src/error-message.ts
31151
31434
  function errorMessage(err) {
@@ -31234,21 +31517,21 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
31234
31517
  }
31235
31518
 
31236
31519
  // src/agents/acp/safe-fs-path.ts
31237
- import * as path7 from "node:path";
31520
+ import * as path8 from "node:path";
31238
31521
  function resolveSafePathUnderCwd(cwd, filePath) {
31239
31522
  const trimmed2 = filePath.trim();
31240
31523
  if (!trimmed2) return null;
31241
- const normalizedCwd = path7.resolve(cwd);
31242
- const resolved = path7.isAbsolute(trimmed2) ? path7.normalize(trimmed2) : path7.resolve(normalizedCwd, trimmed2);
31243
- const rel = path7.relative(normalizedCwd, resolved);
31244
- if (rel.startsWith("..") || path7.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;
31245
31528
  return resolved;
31246
31529
  }
31247
31530
  function toDisplayPathRelativeToCwd(cwd, absolutePath) {
31248
- const normalizedCwd = path7.resolve(cwd);
31249
- const rel = path7.relative(normalizedCwd, path7.resolve(absolutePath));
31250
- if (!rel || rel === "") return path7.basename(absolutePath);
31251
- return rel.split(path7.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("/");
31252
31535
  }
31253
31536
 
31254
31537
  // src/agents/acp/clients/agent-stderr-capture.ts
@@ -31368,7 +31651,7 @@ async function createSdkStdioAcpClient(options) {
31368
31651
  child.once("close", (code, signal) => {
31369
31652
  onAgentSubprocessExit?.({ code, signal });
31370
31653
  });
31371
- return new Promise((resolve16, reject) => {
31654
+ return new Promise((resolve17, reject) => {
31372
31655
  let initSettled = false;
31373
31656
  const settleReject = (err) => {
31374
31657
  if (initSettled) return;
@@ -31382,7 +31665,7 @@ async function createSdkStdioAcpClient(options) {
31382
31665
  const settleResolve = (handle) => {
31383
31666
  if (initSettled) return;
31384
31667
  initSettled = true;
31385
- resolve16(handle);
31668
+ resolve17(handle);
31386
31669
  };
31387
31670
  child.on("error", (err) => {
31388
31671
  settleReject(new Error(formatSpawnError(err, command[0])));
@@ -31418,8 +31701,8 @@ async function createSdkStdioAcpClient(options) {
31418
31701
  });
31419
31702
  } catch {
31420
31703
  }
31421
- return await new Promise((resolve17) => {
31422
- pendingPermissionResolvers.set(requestId, resolve17);
31704
+ return await new Promise((resolve18) => {
31705
+ pendingPermissionResolvers.set(requestId, resolve18);
31423
31706
  });
31424
31707
  },
31425
31708
  async readTextFile(params) {
@@ -31527,9 +31810,9 @@ async function createSdkStdioAcpClient(options) {
31527
31810
  }
31528
31811
  },
31529
31812
  async cancel() {
31530
- for (const [id, resolve17] of [...pendingPermissionResolvers.entries()]) {
31813
+ for (const [id, resolve18] of [...pendingPermissionResolvers.entries()]) {
31531
31814
  pendingPermissionResolvers.delete(id);
31532
- resolve17({ outcome: { outcome: "cancelled" } });
31815
+ resolve18({ outcome: { outcome: "cancelled" } });
31533
31816
  }
31534
31817
  try {
31535
31818
  await connection.cancel({ sessionId });
@@ -31545,10 +31828,10 @@ async function createSdkStdioAcpClient(options) {
31545
31828
  }
31546
31829
  },
31547
31830
  resolveRequest(requestId, result) {
31548
- const resolve17 = pendingPermissionResolvers.get(requestId);
31549
- if (!resolve17) return;
31831
+ const resolve18 = pendingPermissionResolvers.get(requestId);
31832
+ if (!resolve18) return;
31550
31833
  pendingPermissionResolvers.delete(requestId);
31551
- resolve17(result);
31834
+ resolve18(result);
31552
31835
  },
31553
31836
  disconnect() {
31554
31837
  child.kill();
@@ -31689,7 +31972,7 @@ async function createCursorAcpClient(options) {
31689
31972
  onRequest,
31690
31973
  onFileChange
31691
31974
  } = options;
31692
- const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
31975
+ const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
31693
31976
  const isWindows = process.platform === "win32";
31694
31977
  const child = spawn3(command[0], command.slice(1), {
31695
31978
  cwd,
@@ -31699,7 +31982,7 @@ async function createCursorAcpClient(options) {
31699
31982
  });
31700
31983
  const stderrCapture = createStderrCapture(child);
31701
31984
  child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
31702
- return new Promise((resolve16, reject) => {
31985
+ return new Promise((resolve17, reject) => {
31703
31986
  child.on("error", (err) => {
31704
31987
  child.kill();
31705
31988
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -31886,7 +32169,7 @@ async function createCursorAcpClient(options) {
31886
32169
  const newResult = await send("session/new", { cwd, mcpServers: [] });
31887
32170
  const sessionId = newResult?.sessionId ?? "";
31888
32171
  if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
31889
- resolve16({
32172
+ resolve17({
31890
32173
  sessionId,
31891
32174
  async sendPrompt(prompt, _options) {
31892
32175
  promptOutputBuffer = "";
@@ -32077,16 +32360,16 @@ import { existsSync, statSync } from "node:fs";
32077
32360
 
32078
32361
  // src/git/get-git-repo-root-sync.ts
32079
32362
  import { execFileSync as execFileSync2 } from "node:child_process";
32080
- import * as path8 from "node:path";
32363
+ import * as path9 from "node:path";
32081
32364
  function getGitRepoRootSync(startDir) {
32082
32365
  try {
32083
32366
  const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
32084
- cwd: path8.resolve(startDir),
32367
+ cwd: path9.resolve(startDir),
32085
32368
  encoding: "utf8",
32086
32369
  stdio: ["ignore", "pipe", "ignore"],
32087
32370
  maxBuffer: 1024 * 1024
32088
32371
  }).trim();
32089
- return out ? path8.resolve(out) : null;
32372
+ return out ? path9.resolve(out) : null;
32090
32373
  } catch {
32091
32374
  return null;
32092
32375
  }
@@ -32095,25 +32378,25 @@ function getGitRepoRootSync(startDir) {
32095
32378
  // src/agents/acp/workspace-files.ts
32096
32379
  import { execFileSync as execFileSync3 } from "node:child_process";
32097
32380
  import { readFileSync as readFileSync4 } from "node:fs";
32098
- import * as path9 from "node:path";
32381
+ import * as path10 from "node:path";
32099
32382
  function resolveWorkspaceFilePath(cwd, rawPath) {
32100
32383
  const trimmed2 = rawPath.trim();
32101
32384
  if (!trimmed2) return null;
32102
- const normalizedCwd = path9.resolve(cwd);
32385
+ const normalizedCwd = path10.resolve(cwd);
32103
32386
  let abs = resolveSafePathUnderCwd(cwd, trimmed2);
32104
32387
  if (!abs) {
32105
- const candidate = path9.isAbsolute(trimmed2) ? path9.normalize(trimmed2) : path9.normalize(path9.resolve(normalizedCwd, trimmed2));
32388
+ const candidate = path10.isAbsolute(trimmed2) ? path10.normalize(trimmed2) : path10.normalize(path10.resolve(normalizedCwd, trimmed2));
32106
32389
  const gitRoot2 = getGitRepoRootSync(cwd);
32107
32390
  if (!gitRoot2) return null;
32108
- const rel = path9.relative(gitRoot2, candidate);
32109
- if (rel.startsWith("..") || path9.isAbsolute(rel)) return null;
32391
+ const rel = path10.relative(gitRoot2, candidate);
32392
+ if (rel.startsWith("..") || path10.isAbsolute(rel)) return null;
32110
32393
  abs = candidate;
32111
32394
  }
32112
32395
  const gitRoot = getGitRepoRootSync(cwd);
32113
32396
  if (gitRoot) {
32114
- const relFromRoot = path9.relative(gitRoot, abs);
32115
- if (!relFromRoot.startsWith("..") && !path9.isAbsolute(relFromRoot)) {
32116
- return { abs, display: relFromRoot.split(path9.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("/") };
32117
32400
  }
32118
32401
  }
32119
32402
  return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
@@ -32122,9 +32405,9 @@ function readUtf8WorkspaceFile(cwd, displayPath) {
32122
32405
  if (!displayPath || displayPath.includes("..")) return "";
32123
32406
  const gitRoot = getGitRepoRootSync(cwd);
32124
32407
  if (gitRoot) {
32125
- const abs2 = path9.resolve(gitRoot, displayPath);
32126
- const rel = path9.relative(gitRoot, abs2);
32127
- if (!rel.startsWith("..") && !path9.isAbsolute(rel)) {
32408
+ const abs2 = path10.resolve(gitRoot, displayPath);
32409
+ const rel = path10.relative(gitRoot, abs2);
32410
+ if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
32128
32411
  try {
32129
32412
  return readFileSync4(abs2, "utf8");
32130
32413
  } catch {
@@ -32143,9 +32426,9 @@ function tryWorkspaceDisplayToAbs(cwd, displayPath) {
32143
32426
  if (!displayPath || displayPath.includes("..")) return null;
32144
32427
  const gitRoot = getGitRepoRootSync(cwd);
32145
32428
  if (gitRoot) {
32146
- const abs = path9.resolve(gitRoot, displayPath);
32147
- const rel = path9.relative(gitRoot, abs);
32148
- if (!rel.startsWith("..") && !path9.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;
32149
32432
  }
32150
32433
  return resolveSafePathUnderCwd(cwd, displayPath);
32151
32434
  }
@@ -32713,10 +32996,10 @@ function buildAcpSessionBridgeHooks(opts) {
32713
32996
  // src/agents/acp/ensure-acp-client.ts
32714
32997
  async function ensureAcpClient(options) {
32715
32998
  const { state, preferredAgentType, mode, cwd, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
32716
- const targetCwd = path10.resolve(
32999
+ const targetCwd = path11.resolve(
32717
33000
  cwd != null && String(cwd).trim() !== "" ? String(cwd).trim() : getBridgeWorkspaceDirectory()
32718
33001
  );
32719
- if (state.acpHandle && state.lastAcpCwd != null && path10.resolve(state.lastAcpCwd) !== path10.resolve(targetCwd)) {
33002
+ if (state.acpHandle && state.lastAcpCwd != null && path11.resolve(state.lastAcpCwd) !== path11.resolve(targetCwd)) {
32720
33003
  try {
32721
33004
  state.acpHandle.disconnect();
32722
33005
  } catch {
@@ -32748,7 +33031,7 @@ async function ensureAcpClient(options) {
32748
33031
  if (!state.acpStartPromise) {
32749
33032
  let statOk = false;
32750
33033
  try {
32751
- const st = fs9.statSync(targetCwd);
33034
+ const st = fs10.statSync(targetCwd);
32752
33035
  statOk = st.isDirectory();
32753
33036
  if (!statOk) {
32754
33037
  state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
@@ -32944,12 +33227,12 @@ async function createAcpManager(options) {
32944
33227
  }
32945
33228
 
32946
33229
  // src/worktrees/session-worktree-manager.ts
32947
- import * as path16 from "node:path";
33230
+ import * as path17 from "node:path";
32948
33231
  import os4 from "node:os";
32949
33232
 
32950
33233
  // src/worktrees/prepare-new-session-worktrees.ts
32951
- import * as fs11 from "node:fs";
32952
- import * as path12 from "node:path";
33234
+ import * as fs12 from "node:fs";
33235
+ import * as path13 from "node:path";
32953
33236
 
32954
33237
  // src/git/worktree-add.ts
32955
33238
  async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
@@ -32958,12 +33241,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
32958
33241
  }
32959
33242
 
32960
33243
  // src/worktrees/worktree-layout-file.ts
32961
- import * as fs10 from "node:fs";
32962
- import * as path11 from "node:path";
33244
+ import * as fs11 from "node:fs";
33245
+ import * as path12 from "node:path";
32963
33246
  import os3 from "node:os";
32964
33247
  var LAYOUT_FILENAME = "worktree-launcher-layout.json";
32965
33248
  function defaultWorktreeLayoutPath() {
32966
- return path11.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
33249
+ return path12.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
32967
33250
  }
32968
33251
  function normalizeLoadedLayout(raw) {
32969
33252
  if (raw && typeof raw === "object" && "launcherCwds" in raw) {
@@ -32975,8 +33258,8 @@ function normalizeLoadedLayout(raw) {
32975
33258
  function loadWorktreeLayout() {
32976
33259
  try {
32977
33260
  const p = defaultWorktreeLayoutPath();
32978
- if (!fs10.existsSync(p)) return { launcherCwds: [] };
32979
- const raw = JSON.parse(fs10.readFileSync(p, "utf8"));
33261
+ if (!fs11.existsSync(p)) return { launcherCwds: [] };
33262
+ const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
32980
33263
  return normalizeLoadedLayout(raw);
32981
33264
  } catch {
32982
33265
  return { launcherCwds: [] };
@@ -32984,18 +33267,18 @@ function loadWorktreeLayout() {
32984
33267
  }
32985
33268
  function saveWorktreeLayout(layout) {
32986
33269
  try {
32987
- const dir = path11.dirname(defaultWorktreeLayoutPath());
32988
- fs10.mkdirSync(dir, { recursive: true });
32989
- fs10.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");
32990
33273
  } catch {
32991
33274
  }
32992
33275
  }
32993
33276
  function baseNameSafe(abs) {
32994
- return path11.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
33277
+ return path12.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
32995
33278
  }
32996
33279
  function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
32997
- const norm = path11.resolve(launcherCwdAbs);
32998
- const existing = layout.launcherCwds.find((e) => path11.resolve(e.absolutePath) === norm);
33280
+ const norm = path12.resolve(launcherCwdAbs);
33281
+ const existing = layout.launcherCwds.find((e) => path12.resolve(e.absolutePath) === norm);
32999
33282
  if (existing) return existing.dirName;
33000
33283
  const base = baseNameSafe(norm);
33001
33284
  const used = new Set(layout.launcherCwds.map((e) => e.dirName));
@@ -33013,9 +33296,9 @@ function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
33013
33296
  // src/worktrees/prepare-new-session-worktrees.ts
33014
33297
  async function prepareNewSessionWorktrees(options) {
33015
33298
  const { rootAbs, launcherCwd, sessionId, layout, log: log2 } = options;
33016
- const launcherResolved = path12.resolve(launcherCwd);
33299
+ const launcherResolved = path13.resolve(launcherCwd);
33017
33300
  const cwdKey = allocateDirNameForLauncherCwd(layout, launcherResolved);
33018
- const agentMirrorRoot = path12.join(rootAbs, cwdKey);
33301
+ const agentMirrorRoot = path13.join(rootAbs, cwdKey);
33019
33302
  const repos = await discoverGitReposUnderRoot(launcherResolved);
33020
33303
  if (repos.length === 0) {
33021
33304
  log2("[worktrees] No Git repositories under launcher working directory; skipping worktree creation.");
@@ -33023,13 +33306,13 @@ async function prepareNewSessionWorktrees(options) {
33023
33306
  }
33024
33307
  const branch = `session-${sessionId}`;
33025
33308
  const worktreePaths = [];
33026
- fs11.mkdirSync(agentMirrorRoot, { recursive: true });
33309
+ fs12.mkdirSync(agentMirrorRoot, { recursive: true });
33027
33310
  for (const repo of repos) {
33028
- let rel = path12.relative(launcherResolved, repo.absolutePath);
33029
- if (rel.startsWith("..") || path12.isAbsolute(rel)) continue;
33311
+ let rel = path13.relative(launcherResolved, repo.absolutePath);
33312
+ if (rel.startsWith("..") || path13.isAbsolute(rel)) continue;
33030
33313
  const relNorm = rel === "" ? "." : rel;
33031
- const wtPath = path12.join(agentMirrorRoot, relNorm, sessionId);
33032
- fs11.mkdirSync(path12.dirname(wtPath), { recursive: true });
33314
+ const wtPath = path13.join(agentMirrorRoot, relNorm, sessionId);
33315
+ fs12.mkdirSync(path13.dirname(wtPath), { recursive: true });
33033
33316
  try {
33034
33317
  await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
33035
33318
  log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
@@ -33066,23 +33349,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
33066
33349
  }
33067
33350
 
33068
33351
  // src/worktrees/remove-session-worktrees.ts
33069
- import * as fs14 from "node:fs";
33352
+ import * as fs15 from "node:fs";
33070
33353
 
33071
33354
  // src/git/worktree-remove.ts
33072
- import * as fs13 from "node:fs";
33355
+ import * as fs14 from "node:fs";
33073
33356
 
33074
33357
  // src/git/resolve-main-repo-from-git-file.ts
33075
- import * as fs12 from "node:fs";
33076
- import * as path13 from "node:path";
33358
+ import * as fs13 from "node:fs";
33359
+ import * as path14 from "node:path";
33077
33360
  function resolveMainRepoFromWorktreeGitFile(wt) {
33078
- const gitDirFile = path13.join(wt, ".git");
33079
- if (!fs12.existsSync(gitDirFile) || !fs12.statSync(gitDirFile).isFile()) return "";
33080
- const first2 = fs12.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();
33081
33364
  const m = first2.match(/^gitdir:\s*(.+)$/im);
33082
33365
  if (!m) return "";
33083
- const gitWorktreePath = path13.resolve(wt, m[1].trim());
33084
- const gitDir = path13.dirname(path13.dirname(gitWorktreePath));
33085
- return path13.dirname(gitDir);
33366
+ const gitWorktreePath = path14.resolve(wt, m[1].trim());
33367
+ const gitDir = path14.dirname(path14.dirname(gitWorktreePath));
33368
+ return path14.dirname(gitDir);
33086
33369
  }
33087
33370
 
33088
33371
  // src/git/worktree-remove.ts
@@ -33091,7 +33374,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
33091
33374
  if (mainRepo) {
33092
33375
  await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
33093
33376
  } else {
33094
- fs13.rmSync(worktreePath, { recursive: true, force: true });
33377
+ fs14.rmSync(worktreePath, { recursive: true, force: true });
33095
33378
  }
33096
33379
  }
33097
33380
 
@@ -33104,7 +33387,7 @@ async function removeSessionWorktrees(paths, log2) {
33104
33387
  } catch (e) {
33105
33388
  log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
33106
33389
  try {
33107
- fs14.rmSync(wt, { recursive: true, force: true });
33390
+ fs15.rmSync(wt, { recursive: true, force: true });
33108
33391
  } catch {
33109
33392
  }
33110
33393
  }
@@ -33324,7 +33607,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
33324
33607
  }
33325
33608
 
33326
33609
  // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
33327
- import * as path15 from "node:path";
33610
+ import * as path16 from "node:path";
33328
33611
 
33329
33612
  // src/git/working-directory/changes/parse-git-status.ts
33330
33613
  function parseNameStatusLines(lines) {
@@ -33444,8 +33727,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
33444
33727
  }
33445
33728
 
33446
33729
  // src/git/working-directory/changes/list-changed-files-for-repo.ts
33447
- import * as fs16 from "node:fs";
33448
- import * as path14 from "node:path";
33730
+ import * as fs17 from "node:fs";
33731
+ import * as path15 from "node:path";
33449
33732
 
33450
33733
  // src/git/working-directory/changes/count-lines.ts
33451
33734
  import { createReadStream } from "node:fs";
@@ -33469,7 +33752,7 @@ async function countTextFileLines(absFile) {
33469
33752
  }
33470
33753
 
33471
33754
  // src/git/working-directory/changes/hydrate-patch.ts
33472
- import * as fs15 from "node:fs";
33755
+ import * as fs16 from "node:fs";
33473
33756
  var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
33474
33757
  var MAX_HYDRATE_LINES_PER_GAP = 8e3;
33475
33758
  var MAX_HYDRATE_LINES_PER_FILE = 8e4;
@@ -33484,7 +33767,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
33484
33767
  }
33485
33768
  async function readWorktreeFileLines(abs) {
33486
33769
  try {
33487
- const raw = await fs15.promises.readFile(abs, "utf8");
33770
+ const raw = await fs16.promises.readFile(abs, "utf8");
33488
33771
  return raw.split(/\r?\n/);
33489
33772
  } catch {
33490
33773
  return null;
@@ -33619,7 +33902,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33619
33902
  const rows = [];
33620
33903
  for (const pathInRepo of paths) {
33621
33904
  const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
33622
- const abs = path14.join(repoGitCwd, pathInRepo);
33905
+ const abs = path15.join(repoGitCwd, pathInRepo);
33623
33906
  const nums = numByPath.get(pathInRepo);
33624
33907
  let additions = nums?.additions ?? 0;
33625
33908
  let deletions = nums?.deletions ?? 0;
@@ -33632,7 +33915,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33632
33915
  deletions = fromGit.deletions;
33633
33916
  } else {
33634
33917
  try {
33635
- const st = await fs16.promises.stat(abs);
33918
+ const st = await fs17.promises.stat(abs);
33636
33919
  if (st.isFile()) additions = await countTextFileLines(abs);
33637
33920
  else additions = 0;
33638
33921
  } catch {
@@ -33658,7 +33941,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33658
33941
  } else {
33659
33942
  pathInRepo = row.pathRelLauncher;
33660
33943
  }
33661
- const absFile = path14.join(repoGitCwd, pathInRepo);
33944
+ const absFile = path15.join(repoGitCwd, pathInRepo);
33662
33945
  let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
33663
33946
  if (patch) {
33664
33947
  patch = await hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, row.change);
@@ -33674,8 +33957,8 @@ function normRepoRel(p) {
33674
33957
  return x === "" ? "." : x;
33675
33958
  }
33676
33959
  async function getWorkingTreeChangeRepoDetails(options) {
33677
- const launcher = path15.resolve(getBridgeWorkspaceDirectory());
33678
- const mirror = options.agentMirrorRootAbs ? path15.resolve(options.agentMirrorRootAbs) : null;
33960
+ const launcher = path16.resolve(getBridgeWorkspaceDirectory());
33961
+ const mirror = options.agentMirrorRootAbs ? path16.resolve(options.agentMirrorRootAbs) : null;
33679
33962
  const out = [];
33680
33963
  const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
33681
33964
  const basisInput = options.basis ?? { kind: "working" };
@@ -33687,7 +33970,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
33687
33970
  }
33688
33971
  const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
33689
33972
  for (const target of options.commitTargetAbsDirs) {
33690
- const t = path15.resolve(target);
33973
+ const t = path16.resolve(target);
33691
33974
  if (!await isGitRepoDirectory(t)) continue;
33692
33975
  const g = simpleGit(t);
33693
33976
  let branch = "HEAD";
@@ -33700,7 +33983,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
33700
33983
  const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
33701
33984
  let repoRelPath;
33702
33985
  if (mirror) {
33703
- const relNorm = path15.relative(mirror, path15.dirname(t));
33986
+ const relNorm = path16.relative(mirror, path16.dirname(t));
33704
33987
  repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
33705
33988
  } else {
33706
33989
  let top = t;
@@ -33709,8 +33992,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
33709
33992
  } catch {
33710
33993
  top = t;
33711
33994
  }
33712
- const rel = path15.relative(launcher, path15.resolve(top)).replace(/\\/g, "/") || ".";
33713
- repoRelPath = rel.startsWith("..") ? path15.basename(path15.resolve(top)) : rel;
33995
+ const rel = path16.relative(launcher, path16.resolve(top)).replace(/\\/g, "/") || ".";
33996
+ repoRelPath = rel.startsWith("..") ? path16.basename(path16.resolve(top)) : rel;
33714
33997
  }
33715
33998
  const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
33716
33999
  if (filter && norm !== filter) continue;
@@ -33802,7 +34085,7 @@ var SessionWorktreeManager = class {
33802
34085
  }
33803
34086
  if (!opts.isNewSession) {
33804
34087
  const agentCwd = this.sessionAgentCwd.get(sessionId);
33805
- if (agentCwd) return path16.resolve(agentCwd);
34088
+ if (agentCwd) return path17.resolve(agentCwd);
33806
34089
  return void 0;
33807
34090
  }
33808
34091
  const prep = await prepareNewSessionWorktrees({
@@ -33815,7 +34098,7 @@ var SessionWorktreeManager = class {
33815
34098
  if (!prep) return void 0;
33816
34099
  this.sessionPaths.set(sessionId, prep.worktreePaths);
33817
34100
  this.sessionAgentCwd.set(sessionId, prep.agentCwd);
33818
- return path16.resolve(prep.agentCwd);
34101
+ return path17.resolve(prep.agentCwd);
33819
34102
  }
33820
34103
  async renameSessionBranch(sessionId, newBranch) {
33821
34104
  const paths = this.sessionPaths.get(sessionId);
@@ -33836,7 +34119,7 @@ var SessionWorktreeManager = class {
33836
34119
  getAgentCwdForSession(sessionId) {
33837
34120
  if (!sessionId) return null;
33838
34121
  const c = this.sessionAgentCwd.get(sessionId);
33839
- return c ? path16.resolve(c) : null;
34122
+ return c ? path17.resolve(c) : null;
33840
34123
  }
33841
34124
  async removeSessionWorktrees(sessionId) {
33842
34125
  const paths = this.sessionPaths.get(sessionId);
@@ -33884,30 +34167,30 @@ var SessionWorktreeManager = class {
33884
34167
  }
33885
34168
  };
33886
34169
  function defaultWorktreesRootAbs() {
33887
- return path16.join(os4.homedir(), ".buildautomaton", "worktrees");
34170
+ return path17.join(os4.homedir(), ".buildautomaton", "worktrees");
33888
34171
  }
33889
34172
 
33890
34173
  // src/files/watch-file-index.ts
33891
34174
  import { watch } from "node:fs";
33892
- import path23 from "node:path";
34175
+ import path24 from "node:path";
33893
34176
 
33894
34177
  // src/files/index/build-file-index.ts
33895
- import path20 from "node:path";
34178
+ import path21 from "node:path";
33896
34179
 
33897
34180
  // src/runtime/yield-to-event-loop.ts
33898
34181
  function yieldToEventLoop() {
33899
- return new Promise((resolve16) => setImmediate(resolve16));
34182
+ return new Promise((resolve17) => setImmediate(resolve17));
33900
34183
  }
33901
34184
 
33902
34185
  // src/files/index/walk-workspace-tree.ts
33903
- import fs17 from "node:fs";
33904
- import path18 from "node:path";
34186
+ import fs18 from "node:fs";
34187
+ import path19 from "node:path";
33905
34188
 
33906
34189
  // src/files/index/constants.ts
33907
- import path17 from "node:path";
34190
+ import path18 from "node:path";
33908
34191
  import os5 from "node:os";
33909
34192
  var INDEX_WORK_YIELD_EVERY = 256;
33910
- var INDEX_DIR = path17.join(os5.homedir(), ".buildautomaton");
34193
+ var INDEX_DIR = path18.join(os5.homedir(), ".buildautomaton");
33911
34194
  var INDEX_HASH_LEN = 16;
33912
34195
  var INDEX_VERSION = 2;
33913
34196
  var INDEX_LOG_PREFIX = "[file-index]";
@@ -33916,23 +34199,23 @@ var INDEX_LOG_PREFIX = "[file-index]";
33916
34199
  function walkWorkspaceTreeSync(dir, baseDir, out) {
33917
34200
  let names;
33918
34201
  try {
33919
- names = fs17.readdirSync(dir);
34202
+ names = fs18.readdirSync(dir);
33920
34203
  } catch {
33921
34204
  return;
33922
34205
  }
33923
34206
  for (const name of names) {
33924
34207
  if (name.startsWith(".")) continue;
33925
- const full = path18.join(dir, name);
33926
- let stat2;
34208
+ const full = path19.join(dir, name);
34209
+ let stat3;
33927
34210
  try {
33928
- stat2 = fs17.statSync(full);
34211
+ stat3 = fs18.statSync(full);
33929
34212
  } catch {
33930
34213
  continue;
33931
34214
  }
33932
- const relative5 = path18.relative(baseDir, full).replace(/\\/g, "/");
33933
- if (stat2.isDirectory()) {
34215
+ const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
34216
+ if (stat3.isDirectory()) {
33934
34217
  walkWorkspaceTreeSync(full, baseDir, out);
33935
- } else if (stat2.isFile()) {
34218
+ } else if (stat3.isFile()) {
33936
34219
  out.push(relative5);
33937
34220
  }
33938
34221
  }
@@ -33940,7 +34223,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
33940
34223
  async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
33941
34224
  let names;
33942
34225
  try {
33943
- names = await fs17.promises.readdir(dir);
34226
+ names = await fs18.promises.readdir(dir);
33944
34227
  } catch {
33945
34228
  return;
33946
34229
  }
@@ -33950,17 +34233,17 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
33950
34233
  await yieldToEventLoop();
33951
34234
  }
33952
34235
  state.n++;
33953
- const full = path18.join(dir, name);
33954
- let stat2;
34236
+ const full = path19.join(dir, name);
34237
+ let stat3;
33955
34238
  try {
33956
- stat2 = await fs17.promises.stat(full);
34239
+ stat3 = await fs18.promises.stat(full);
33957
34240
  } catch {
33958
34241
  continue;
33959
34242
  }
33960
- const relative5 = path18.relative(baseDir, full).replace(/\\/g, "/");
33961
- if (stat2.isDirectory()) {
34243
+ const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
34244
+ if (stat3.isDirectory()) {
33962
34245
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
33963
- } else if (stat2.isFile()) {
34246
+ } else if (stat3.isFile()) {
33964
34247
  out.push(relative5);
33965
34248
  }
33966
34249
  }
@@ -34038,22 +34321,22 @@ async function buildTrigramMapForPathsAsync(paths) {
34038
34321
  }
34039
34322
 
34040
34323
  // src/files/index/write-index-file.ts
34041
- import fs18 from "node:fs";
34324
+ import fs19 from "node:fs";
34042
34325
 
34043
34326
  // src/files/index/paths.ts
34044
- import path19 from "node:path";
34327
+ import path20 from "node:path";
34045
34328
  import crypto2 from "node:crypto";
34046
34329
  function getIndexPathForCwd(resolvedCwd) {
34047
34330
  const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
34048
- return path19.join(INDEX_DIR, `.file-index-${hash}.json`);
34331
+ return path20.join(INDEX_DIR, `.file-index-${hash}.json`);
34049
34332
  }
34050
34333
 
34051
34334
  // src/files/index/write-index-file.ts
34052
34335
  function writeIndexFileSync(resolvedCwd, data) {
34053
34336
  const indexPath = getIndexPathForCwd(resolvedCwd);
34054
34337
  try {
34055
- if (!fs18.existsSync(INDEX_DIR)) fs18.mkdirSync(INDEX_DIR, { recursive: true });
34056
- fs18.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");
34057
34340
  } catch (e) {
34058
34341
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
34059
34342
  }
@@ -34061,8 +34344,8 @@ function writeIndexFileSync(resolvedCwd, data) {
34061
34344
  async function writeIndexFileAsync(resolvedCwd, data) {
34062
34345
  const indexPath = getIndexPathForCwd(resolvedCwd);
34063
34346
  try {
34064
- await fs18.promises.mkdir(INDEX_DIR, { recursive: true });
34065
- await fs18.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");
34066
34349
  } catch (e) {
34067
34350
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
34068
34351
  }
@@ -34076,7 +34359,7 @@ function sortPaths(paths) {
34076
34359
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
34077
34360
  }
34078
34361
  function buildFileIndex(cwd) {
34079
- const resolved = path20.resolve(cwd);
34362
+ const resolved = path21.resolve(cwd);
34080
34363
  const paths = [];
34081
34364
  walkWorkspaceTreeSync(resolved, resolved, paths);
34082
34365
  sortPaths(paths);
@@ -34086,7 +34369,7 @@ function buildFileIndex(cwd) {
34086
34369
  return data;
34087
34370
  }
34088
34371
  async function buildFileIndexAsync(cwd) {
34089
- const resolved = path20.resolve(cwd);
34372
+ const resolved = path21.resolve(cwd);
34090
34373
  const paths = [];
34091
34374
  await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
34092
34375
  await yieldToEventLoop();
@@ -34098,13 +34381,13 @@ async function buildFileIndexAsync(cwd) {
34098
34381
  }
34099
34382
 
34100
34383
  // src/files/index/load-file-index.ts
34101
- import fs19 from "node:fs";
34102
- import path21 from "node:path";
34384
+ import fs20 from "node:fs";
34385
+ import path22 from "node:path";
34103
34386
  function loadFileIndex(cwd) {
34104
- const resolved = path21.resolve(cwd);
34387
+ const resolved = path22.resolve(cwd);
34105
34388
  const indexPath = getIndexPathForCwd(resolved);
34106
34389
  try {
34107
- const raw = fs19.readFileSync(indexPath, "utf8");
34390
+ const raw = fs20.readFileSync(indexPath, "utf8");
34108
34391
  const parsed = JSON.parse(raw);
34109
34392
  if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
34110
34393
  const obj = parsed;
@@ -34123,9 +34406,9 @@ function loadFileIndex(cwd) {
34123
34406
  }
34124
34407
 
34125
34408
  // src/files/index/ensure-file-index.ts
34126
- import path22 from "node:path";
34409
+ import path23 from "node:path";
34127
34410
  async function ensureFileIndexAsync(cwd) {
34128
- const resolved = path22.resolve(cwd);
34411
+ const resolved = path23.resolve(cwd);
34129
34412
  const cached2 = loadFileIndex(resolved);
34130
34413
  if (cached2 !== null) return { data: cached2, fromCache: true };
34131
34414
  const data = await buildFileIndexAsync(resolved);
@@ -34208,7 +34491,7 @@ function createFsWatcher(resolved, schedule) {
34208
34491
  }
34209
34492
  }
34210
34493
  function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
34211
- const resolved = path23.resolve(cwd);
34494
+ const resolved = path24.resolve(cwd);
34212
34495
  void buildFileIndexAsync(resolved).catch((e) => {
34213
34496
  console.error("[file-index] Initial index build failed:", e);
34214
34497
  });
@@ -34236,7 +34519,7 @@ function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
34236
34519
  }
34237
34520
 
34238
34521
  // src/dev-servers/manager/dev-server-manager.ts
34239
- import { rm } from "node:fs/promises";
34522
+ import { rm as rm2 } from "node:fs/promises";
34240
34523
 
34241
34524
  // src/dev-servers/process/send-server-status.ts
34242
34525
  function sendDevServerStatus(getWs, serverId, status, options) {
@@ -34255,15 +34538,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
34255
34538
 
34256
34539
  // src/dev-servers/process/terminate-child-process.ts
34257
34540
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
34258
- const exited = new Promise((resolve16) => {
34259
- proc.once("exit", () => resolve16());
34541
+ const exited = new Promise((resolve17) => {
34542
+ proc.once("exit", () => resolve17());
34260
34543
  });
34261
34544
  log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
34262
34545
  try {
34263
34546
  proc.kill("SIGTERM");
34264
34547
  } catch {
34265
34548
  }
34266
- await Promise.race([exited, new Promise((resolve16) => setTimeout(resolve16, graceMs))]);
34549
+ await Promise.race([exited, new Promise((resolve17) => setTimeout(resolve17, graceMs))]);
34267
34550
  }
34268
34551
  function forceKillChild(proc, log2, shortId, graceMs) {
34269
34552
  log2(
@@ -34277,7 +34560,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
34277
34560
  }
34278
34561
 
34279
34562
  // src/dev-servers/process/wire-dev-server-child-process.ts
34280
- import fs20 from "node:fs";
34563
+ import fs21 from "node:fs";
34281
34564
 
34282
34565
  // src/dev-servers/manager/forward-pipe.ts
34283
34566
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -34313,7 +34596,7 @@ function wireDevServerChildProcess(d) {
34313
34596
  d.setPollInterval(void 0);
34314
34597
  return;
34315
34598
  }
34316
- fs20.readFile(d.mergedLogPath, (err, buf) => {
34599
+ fs21.readFile(d.mergedLogPath, (err, buf) => {
34317
34600
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
34318
34601
  if (buf.length <= d.mergedReadPos.value) return;
34319
34602
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -34351,7 +34634,7 @@ ${errTail}` : ""}`);
34351
34634
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
34352
34635
  };
34353
34636
  if (mergedPath) {
34354
- fs20.readFile(mergedPath, (err, buf) => {
34637
+ fs21.readFile(mergedPath, (err, buf) => {
34355
34638
  if (!err && buf.length > d.mergedReadPos.value) {
34356
34639
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
34357
34640
  if (chunk.length > 0) {
@@ -34453,13 +34736,13 @@ function parseDevServerDefs(servers) {
34453
34736
  }
34454
34737
 
34455
34738
  // src/dev-servers/manager/shell-spawn/utils.ts
34456
- import fs21 from "node:fs";
34739
+ import fs22 from "node:fs";
34457
34740
  function isSpawnEbadf(e) {
34458
34741
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
34459
34742
  }
34460
34743
  function rmDirQuiet(dir) {
34461
34744
  try {
34462
- fs21.rmSync(dir, { recursive: true, force: true });
34745
+ fs22.rmSync(dir, { recursive: true, force: true });
34463
34746
  } catch {
34464
34747
  }
34465
34748
  }
@@ -34467,7 +34750,7 @@ var cachedDevNullReadFd;
34467
34750
  function devNullReadFd() {
34468
34751
  if (cachedDevNullReadFd === void 0) {
34469
34752
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
34470
- cachedDevNullReadFd = fs21.openSync(devPath, "r");
34753
+ cachedDevNullReadFd = fs22.openSync(devPath, "r");
34471
34754
  }
34472
34755
  return cachedDevNullReadFd;
34473
34756
  }
@@ -34541,15 +34824,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
34541
34824
 
34542
34825
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
34543
34826
  import { spawn as spawn6 } from "node:child_process";
34544
- import fs22 from "node:fs";
34827
+ import fs23 from "node:fs";
34545
34828
  import { tmpdir } from "node:os";
34546
- import path24 from "node:path";
34829
+ import path25 from "node:path";
34547
34830
  function trySpawnMergedLogFile(command, env, cwd, signal) {
34548
- const tmpRoot = fs22.mkdtempSync(path24.join(tmpdir(), "ba-devsrv-log-"));
34549
- const logPath = path24.join(tmpRoot, "combined.log");
34831
+ const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir(), "ba-devsrv-log-"));
34832
+ const logPath = path25.join(tmpRoot, "combined.log");
34550
34833
  let logFd;
34551
34834
  try {
34552
- logFd = fs22.openSync(logPath, "a");
34835
+ logFd = fs23.openSync(logPath, "a");
34553
34836
  } catch {
34554
34837
  rmDirQuiet(tmpRoot);
34555
34838
  return null;
@@ -34568,7 +34851,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
34568
34851
  } else {
34569
34852
  proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
34570
34853
  }
34571
- fs22.closeSync(logFd);
34854
+ fs23.closeSync(logFd);
34572
34855
  return {
34573
34856
  proc,
34574
34857
  pipedStdoutStderr: true,
@@ -34577,7 +34860,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
34577
34860
  };
34578
34861
  } catch (e) {
34579
34862
  try {
34580
- fs22.closeSync(logFd);
34863
+ fs23.closeSync(logFd);
34581
34864
  } catch {
34582
34865
  }
34583
34866
  rmDirQuiet(tmpRoot);
@@ -34588,22 +34871,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
34588
34871
 
34589
34872
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
34590
34873
  import { spawn as spawn7 } from "node:child_process";
34591
- import fs23 from "node:fs";
34874
+ import fs24 from "node:fs";
34592
34875
  import { tmpdir as tmpdir2 } from "node:os";
34593
- import path25 from "node:path";
34876
+ import path26 from "node:path";
34594
34877
  function shSingleQuote(s) {
34595
34878
  return `'${s.replace(/'/g, `'\\''`)}'`;
34596
34879
  }
34597
34880
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
34598
- const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir2(), "ba-devsrv-sh-"));
34599
- const logPath = path25.join(tmpRoot, "combined.log");
34600
- const innerPath = path25.join(tmpRoot, "_cmd.sh");
34601
- const runnerPath = path25.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");
34602
34885
  try {
34603
- fs23.writeFileSync(innerPath, `#!/bin/sh
34886
+ fs24.writeFileSync(innerPath, `#!/bin/sh
34604
34887
  ${command}
34605
34888
  `);
34606
- fs23.writeFileSync(
34889
+ fs24.writeFileSync(
34607
34890
  runnerPath,
34608
34891
  `#!/bin/sh
34609
34892
  cd ${shSingleQuote(cwd)}
@@ -34629,13 +34912,13 @@ cd ${shSingleQuote(cwd)}
34629
34912
  }
34630
34913
  }
34631
34914
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
34632
- const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir2(), "ba-devsrv-sh-"));
34633
- const logPath = path25.join(tmpRoot, "combined.log");
34634
- const runnerPath = path25.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");
34635
34918
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
34636
34919
  const com = process.env.ComSpec || "cmd.exe";
34637
34920
  try {
34638
- fs23.writeFileSync(
34921
+ fs24.writeFileSync(
34639
34922
  runnerPath,
34640
34923
  `@ECHO OFF\r
34641
34924
  CD /D ${q(cwd)}\r
@@ -34745,8 +35028,90 @@ var StreamTail = class {
34745
35028
  }
34746
35029
  };
34747
35030
 
34748
- // src/dev-servers/manager/dev-server-manager.ts
35031
+ // src/dev-servers/manager/dev-server-constants.ts
34749
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
34750
35115
  var emptyTails = () => ({ stdout: [], stderr: [] });
34751
35116
  var DevServerManager = class {
34752
35117
  defsById = /* @__PURE__ */ new Map();
@@ -34754,66 +35119,36 @@ var DevServerManager = class {
34754
35119
  streamTailsByServerId = /* @__PURE__ */ new Map();
34755
35120
  spawnGenerationByServerId = /* @__PURE__ */ new Map();
34756
35121
  pipedCaptureByServerId = /* @__PURE__ */ new Map();
34757
- logViewerRefCountByServerId = /* @__PURE__ */ new Map();
34758
- firehoseSend = null;
34759
35122
  mergedLogPollByServerId = /* @__PURE__ */ new Map();
34760
35123
  mergedLogCleanupDirByServerId = /* @__PURE__ */ new Map();
34761
35124
  abortControllersByServerId = /* @__PURE__ */ new Map();
34762
35125
  getWs;
34763
35126
  log;
34764
35127
  getBridgeCwd;
35128
+ e2ee;
35129
+ firehoseSink;
34765
35130
  constructor(options) {
34766
35131
  this.getWs = options.getWs;
34767
35132
  this.log = options.log;
34768
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
+ });
34769
35140
  }
34770
35141
  attachFirehose(send) {
34771
- this.firehoseSend = send;
35142
+ this.firehoseSink.attach(send);
34772
35143
  }
34773
35144
  detachFirehose() {
34774
- this.firehoseSend = null;
34775
- this.logViewerRefCountByServerId.clear();
35145
+ this.firehoseSink.detach();
34776
35146
  }
34777
35147
  handleFirehoseLogViewerOpen(serverId, _viewerId) {
34778
- const next = (this.logViewerRefCountByServerId.get(serverId) ?? 0) + 1;
34779
- this.logViewerRefCountByServerId.set(serverId, next);
34780
- this.sendSnapshotToFirehose(serverId, _viewerId);
35148
+ this.firehoseSink.openLogViewer(serverId, _viewerId);
34781
35149
  }
34782
35150
  handleFirehoseLogViewerClose(serverId, _viewerId) {
34783
- const n = (this.logViewerRefCountByServerId.get(serverId) ?? 0) - 1;
34784
- if (n <= 0) this.logViewerRefCountByServerId.delete(serverId);
34785
- else this.logViewerRefCountByServerId.set(serverId, n);
34786
- }
34787
- sendSnapshotToFirehose(serverId, viewerId) {
34788
- const tails = this.streamTailsByServerId.get(serverId);
34789
- const payload = {
34790
- type: "log_snapshot",
34791
- serverId,
34792
- viewerId,
34793
- stdoutTail: tails?.stdout.getTail() ?? [],
34794
- stderrTail: tails?.stderr.getTail() ?? []
34795
- };
34796
- setImmediate(() => {
34797
- const send = this.firehoseSend;
34798
- if (!send) return;
34799
- send(payload);
34800
- });
34801
- }
34802
- pushRemoteLogChunk(serverId, stream, chunk) {
34803
- if ((this.logViewerRefCountByServerId.get(serverId) ?? 0) <= 0) return;
34804
- if (!this.pipedCaptureByServerId.get(serverId)) return;
34805
- const send = this.firehoseSend;
34806
- if (!send) return;
34807
- const text = chunk.toString("utf8");
34808
- setImmediate(() => {
34809
- if (!this.firehoseSend) return;
34810
- this.firehoseSend({
34811
- type: "log_chunk",
34812
- serverId,
34813
- stream,
34814
- text
34815
- });
34816
- });
35151
+ this.firehoseSink.closeLogViewer(serverId);
34817
35152
  }
34818
35153
  applyConfig(servers) {
34819
35154
  this.defsById.clear();
@@ -34866,12 +35201,7 @@ var DevServerManager = class {
34866
35201
  }
34867
35202
  this.clearTails(serverId);
34868
35203
  this.pipedCaptureByServerId.delete(serverId);
34869
- const mergedDir = this.mergedLogCleanupDirByServerId.get(serverId);
34870
- if (mergedDir) {
34871
- this.mergedLogCleanupDirByServerId.delete(serverId);
34872
- void rm(mergedDir, { recursive: true, force: true }).catch(() => {
34873
- });
34874
- }
35204
+ cleanupMergedLogDirForServer(this.mergedLogCleanupDirByServerId, serverId);
34875
35205
  this.sendStatus(serverId, "stopped", void 0, tails);
34876
35206
  }
34877
35207
  start(serverId) {
@@ -34954,7 +35284,7 @@ var DevServerManager = class {
34954
35284
  log: this.log,
34955
35285
  stdoutTail,
34956
35286
  stderrTail,
34957
- pushRemoteLogChunk: (sid, stream, chunk) => this.pushRemoteLogChunk(sid, stream, chunk),
35287
+ pushRemoteLogChunk: (sid, stream, chunk) => this.firehoseSink.pushLogChunk(sid, stream, chunk),
34958
35288
  sendStatus: (status, detail, tails) => this.sendStatus(serverId, status, detail, tails),
34959
35289
  setPollInterval: (iv) => {
34960
35290
  if (iv) this.mergedLogPollByServerId.set(serverId, iv);
@@ -34968,7 +35298,7 @@ var DevServerManager = class {
34968
35298
  this.mergedLogCleanupDirByServerId.delete(serverId);
34969
35299
  },
34970
35300
  rmMergedCleanupDir: (dir) => {
34971
- void rm(dir, { recursive: true, force: true }).catch(() => {
35301
+ void rm2(dir, { recursive: true, force: true }).catch(() => {
34972
35302
  });
34973
35303
  },
34974
35304
  clearTailBuffers: () => this.clearTails(serverId)
@@ -35005,12 +35335,7 @@ var DevServerManager = class {
35005
35335
  this.processes.delete(serverId);
35006
35336
  this.clearPoll(serverId);
35007
35337
  this.pipedCaptureByServerId.delete(serverId);
35008
- const mergedDir = this.mergedLogCleanupDirByServerId.get(serverId);
35009
- if (mergedDir) {
35010
- this.mergedLogCleanupDirByServerId.delete(serverId);
35011
- void rm(mergedDir, { recursive: true, force: true }).catch(() => {
35012
- });
35013
- }
35338
+ cleanupMergedLogDirForServer(this.mergedLogCleanupDirByServerId, serverId);
35014
35339
  const tails = this.snapshotTails(serverId);
35015
35340
  this.clearTails(serverId);
35016
35341
  this.sendStatus(serverId, "unknown", "Bridge closed before process exited", tails);
@@ -35104,7 +35429,7 @@ async function proxyToLocal(request) {
35104
35429
  };
35105
35430
  const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
35106
35431
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
35107
- const once = await new Promise((resolve16) => {
35432
+ const once = await new Promise((resolve17) => {
35108
35433
  const req = mod.request(opts, (res) => {
35109
35434
  const chunks = [];
35110
35435
  res.on("data", (c) => chunks.push(c));
@@ -35115,7 +35440,7 @@ async function proxyToLocal(request) {
35115
35440
  if (typeof v === "string") headers[k] = v;
35116
35441
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
35117
35442
  }
35118
- resolve16({
35443
+ resolve17({
35119
35444
  id: request.id,
35120
35445
  statusCode: res.statusCode ?? 0,
35121
35446
  headers,
@@ -35124,7 +35449,7 @@ async function proxyToLocal(request) {
35124
35449
  });
35125
35450
  });
35126
35451
  req.on("error", (err) => {
35127
- resolve16({
35452
+ resolve17({
35128
35453
  id: request.id,
35129
35454
  statusCode: 0,
35130
35455
  headers: {},
@@ -35485,30 +35810,30 @@ function createOnBridgeIdentified(opts) {
35485
35810
  }
35486
35811
 
35487
35812
  // src/skills/discover-local-agent-skills.ts
35488
- import fs24 from "node:fs";
35489
- import path26 from "node:path";
35813
+ import fs25 from "node:fs";
35814
+ import path27 from "node:path";
35490
35815
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
35491
35816
  function discoverLocalSkills(cwd) {
35492
35817
  const out = [];
35493
35818
  const seenKeys = /* @__PURE__ */ new Set();
35494
35819
  for (const rel of SKILL_DISCOVERY_ROOTS) {
35495
- const base = path26.join(cwd, rel);
35496
- if (!fs24.existsSync(base) || !fs24.statSync(base).isDirectory()) continue;
35820
+ const base = path27.join(cwd, rel);
35821
+ if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
35497
35822
  let entries = [];
35498
35823
  try {
35499
- entries = fs24.readdirSync(base);
35824
+ entries = fs25.readdirSync(base);
35500
35825
  } catch {
35501
35826
  continue;
35502
35827
  }
35503
35828
  for (const name of entries) {
35504
- const dir = path26.join(base, name);
35829
+ const dir = path27.join(base, name);
35505
35830
  try {
35506
- if (!fs24.statSync(dir).isDirectory()) continue;
35831
+ if (!fs25.statSync(dir).isDirectory()) continue;
35507
35832
  } catch {
35508
35833
  continue;
35509
35834
  }
35510
- const skillMd = path26.join(dir, "SKILL.md");
35511
- if (!fs24.existsSync(skillMd)) continue;
35835
+ const skillMd = path27.join(dir, "SKILL.md");
35836
+ if (!fs25.existsSync(skillMd)) continue;
35512
35837
  const key = `${rel}/${name}`;
35513
35838
  if (seenKeys.has(key)) continue;
35514
35839
  seenKeys.add(key);
@@ -35520,23 +35845,23 @@ function discoverLocalSkills(cwd) {
35520
35845
  function discoverSkillLayoutRoots(cwd) {
35521
35846
  const roots = [];
35522
35847
  for (const rel of SKILL_DISCOVERY_ROOTS) {
35523
- const base = path26.join(cwd, rel);
35524
- if (!fs24.existsSync(base) || !fs24.statSync(base).isDirectory()) continue;
35848
+ const base = path27.join(cwd, rel);
35849
+ if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
35525
35850
  let entries = [];
35526
35851
  try {
35527
- entries = fs24.readdirSync(base);
35852
+ entries = fs25.readdirSync(base);
35528
35853
  } catch {
35529
35854
  continue;
35530
35855
  }
35531
35856
  const skills2 = [];
35532
35857
  for (const name of entries) {
35533
- const dir = path26.join(base, name);
35858
+ const dir = path27.join(base, name);
35534
35859
  try {
35535
- if (!fs24.statSync(dir).isDirectory()) continue;
35860
+ if (!fs25.statSync(dir).isDirectory()) continue;
35536
35861
  } catch {
35537
35862
  continue;
35538
35863
  }
35539
- if (!fs24.existsSync(path26.join(dir, "SKILL.md"))) continue;
35864
+ if (!fs25.existsSync(path27.join(dir, "SKILL.md"))) continue;
35540
35865
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
35541
35866
  skills2.push({ name, relPath });
35542
35867
  }
@@ -35638,7 +35963,7 @@ function reportGitRepos(getWs, log2) {
35638
35963
  var handleAuthToken = (msg, { log: log2 }) => {
35639
35964
  if (typeof msg.token !== "string") return;
35640
35965
  log2("Received auth token. Save it for future runs:");
35641
- log2(` export BUILDAMATON_AUTH_TOKEN="${msg.token}"`);
35966
+ log2(` export BUILDAUTOMATON_AUTH_TOKEN="${msg.token}"`);
35642
35967
  };
35643
35968
 
35644
35969
  // src/bridge/routing/handlers/bridge-identified.ts
@@ -35681,13 +36006,13 @@ var handleAgentConfigMessage = (msg, deps) => {
35681
36006
  };
35682
36007
 
35683
36008
  // src/agents/acp/from-bridge/handle-bridge-prompt.ts
35684
- import * as path28 from "node:path";
36009
+ import * as path29 from "node:path";
35685
36010
  import { execFile as execFile10 } from "node:child_process";
35686
36011
  import { promisify as promisify10 } from "node:util";
35687
36012
 
35688
36013
  // src/git/bridge-queue-key.ts
35689
- import * as path27 from "node:path";
35690
- import { createHash } from "node:crypto";
36014
+ import * as path28 from "node:path";
36015
+ import { createHash as createHash2 } from "node:crypto";
35691
36016
  function normalizeCanonicalGitUrl(url2) {
35692
36017
  let s = url2.trim();
35693
36018
  if (!s) return s;
@@ -35711,14 +36036,14 @@ function normalizeCanonicalGitUrl(url2) {
35711
36036
  }
35712
36037
  function canonicalUrlToRepoIdSync(url2) {
35713
36038
  const normalized = normalizeCanonicalGitUrl(url2);
35714
- return createHash("sha256").update(normalized).digest("hex").slice(0, 32);
36039
+ return createHash2("sha256").update(normalized).digest("hex").slice(0, 32);
35715
36040
  }
35716
36041
  function fallbackRepoIdFromPath(absPath) {
35717
- return createHash("sha256").update(path27.resolve(absPath)).digest("hex").slice(0, 32);
36042
+ return createHash2("sha256").update(path28.resolve(absPath)).digest("hex").slice(0, 32);
35718
36043
  }
35719
36044
  async function resolveBridgeQueueBindFields(options) {
35720
36045
  const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
35721
- const cwdAbs = worktreePaths.length > 0 ? path27.resolve(worktreePaths[0]) : path27.resolve(effectiveCwd);
36046
+ const cwdAbs = worktreePaths.length > 0 ? path28.resolve(worktreePaths[0]) : path28.resolve(effectiveCwd);
35722
36047
  if (!primaryRepoRoots.length) {
35723
36048
  log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
35724
36049
  return null;
@@ -35758,21 +36083,28 @@ function handleBridgePrompt(msg, deps) {
35758
36083
  const sessionId = msg.sessionId;
35759
36084
  const runId = typeof msg.runId === "string" ? msg.runId : void 0;
35760
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
+ };
35761
36093
  if (!promptText.trim()) {
35762
36094
  log2(
35763
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).`
35764
36096
  );
35765
- const s = getWs();
35766
- if (s) {
35767
- sendWsMessage(s, {
36097
+ sendBridgeMessage(
36098
+ {
35768
36099
  type: "prompt_result",
35769
36100
  ...promptId ? { id: promptId } : {},
35770
36101
  ...sessionId ? { sessionId } : {},
35771
36102
  ...runId ? { runId } : {},
35772
36103
  success: false,
35773
36104
  error: "Empty or missing prompt text from the bridge; this turn was not sent to the agent."
35774
- });
35775
- }
36105
+ },
36106
+ ["error"]
36107
+ );
35776
36108
  return;
35777
36109
  }
35778
36110
  const isNewSession = msg.isNewSession === true;
@@ -35781,8 +36113,7 @@ function handleBridgePrompt(msg, deps) {
35781
36113
  const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
35782
36114
  acpManager.logPromptReceivedFromBridge({ agentType, mode });
35783
36115
  const sendResult2 = (result) => {
35784
- const s = getWs();
35785
- if (s) sendWsMessage(s, result);
36116
+ sendBridgeMessage(result, result.type === "prompt_result" ? ["output", "error"] : []);
35786
36117
  };
35787
36118
  const sendSessionUpdate = (payload) => {
35788
36119
  const s = getWs();
@@ -35791,11 +36122,19 @@ function handleBridgePrompt(msg, deps) {
35791
36122
  return;
35792
36123
  }
35793
36124
  const p = payload;
35794
- 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);
35795
36134
  };
35796
36135
  async function preambleAndPrompt(resolvedCwd) {
35797
36136
  const s = getWs();
35798
- const effectiveCwd = path28.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
36137
+ const effectiveCwd = path29.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
35799
36138
  const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
35800
36139
  const repoRoots = await resolveSnapshotRepoRoots({
35801
36140
  worktreePaths,
@@ -35903,8 +36242,8 @@ var PREVIEW_API_BASE_PATH = "/__preview";
35903
36242
  var PREVIEW_SECRET_HEADER = "X-Preview-Secret";
35904
36243
  var DEFAULT_PORT = 3e3;
35905
36244
  var DEFAULT_COMMAND = "npm run preview";
35906
- var PREVIEW_COMMAND_ENV = "BUILDAMATON_PREVIEW_COMMAND";
35907
- var PREVIEW_PORT_ENV = "BUILDAMATON_PREVIEW_PORT";
36245
+ var PREVIEW_COMMAND_ENV = "BUILDAUTOMATON_PREVIEW_COMMAND";
36246
+ var PREVIEW_PORT_ENV = "BUILDAUTOMATON_PREVIEW_PORT";
35908
36247
  var previewProcess = null;
35909
36248
  var previewPort = DEFAULT_PORT;
35910
36249
  var previewSecret = "";
@@ -35918,8 +36257,8 @@ function randomSecret() {
35918
36257
  }
35919
36258
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
35920
36259
  }
35921
- async function requestPreviewApi(port, secret, method, path33, body) {
35922
- const url2 = `http://127.0.0.1:${port}${path33}`;
36260
+ async function requestPreviewApi(port, secret, method, path34, body) {
36261
+ const url2 = `http://127.0.0.1:${port}${path34}`;
35923
36262
  const headers = {
35924
36263
  [PREVIEW_SECRET_HEADER]: secret,
35925
36264
  "Content-Type": "application/json"
@@ -35931,7 +36270,7 @@ async function requestPreviewApi(port, secret, method, path33, body) {
35931
36270
  });
35932
36271
  const data = await res.json().catch(() => ({}));
35933
36272
  if (!res.ok) {
35934
- throw new Error(data?.error ?? `Preview API ${method} ${path33}: ${res.status}`);
36273
+ throw new Error(data?.error ?? `Preview API ${method} ${path34}: ${res.status}`);
35935
36274
  }
35936
36275
  return data;
35937
36276
  }
@@ -35957,7 +36296,7 @@ var OPERATIONS = [
35957
36296
  var previewSkill = {
35958
36297
  id: "preview",
35959
36298
  name: "Preview",
35960
- 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.",
35961
36300
  operations: OPERATIONS,
35962
36301
  async execute(operationId, params) {
35963
36302
  const command = getPreviewCommand();
@@ -36094,15 +36433,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
36094
36433
  };
36095
36434
 
36096
36435
  // src/files/list-dir.ts
36097
- import fs25 from "node:fs";
36098
- import path30 from "node:path";
36436
+ import fs26 from "node:fs";
36437
+ import path31 from "node:path";
36099
36438
 
36100
36439
  // src/files/ensure-under-cwd.ts
36101
- import path29 from "node:path";
36440
+ import path30 from "node:path";
36102
36441
  function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
36103
- const normalized = path29.normalize(relativePath).replace(/^(\.\/)+/, "");
36104
- const resolved = path29.resolve(cwd, normalized);
36105
- if (!resolved.startsWith(cwd + path29.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) {
36106
36445
  return null;
36107
36446
  }
36108
36447
  return resolved;
@@ -36116,7 +36455,7 @@ async function listDirAsync(relativePath) {
36116
36455
  return { error: "Path is outside working directory" };
36117
36456
  }
36118
36457
  try {
36119
- const names = await fs25.promises.readdir(resolved, { withFileTypes: true });
36458
+ const names = await fs26.promises.readdir(resolved, { withFileTypes: true });
36120
36459
  const visible = names.filter((d) => !d.name.startsWith("."));
36121
36460
  const entries = [];
36122
36461
  for (let i = 0; i < visible.length; i++) {
@@ -36124,12 +36463,12 @@ async function listDirAsync(relativePath) {
36124
36463
  await yieldToEventLoop();
36125
36464
  }
36126
36465
  const d = visible[i];
36127
- const entryPath = path30.join(relativePath || ".", d.name).replace(/\\/g, "/");
36128
- const fullPath = path30.join(resolved, d.name);
36466
+ const entryPath = path31.join(relativePath || ".", d.name).replace(/\\/g, "/");
36467
+ const fullPath = path31.join(resolved, d.name);
36129
36468
  let isDir = d.isDirectory();
36130
36469
  if (d.isSymbolicLink()) {
36131
36470
  try {
36132
- const targetStat = await fs25.promises.stat(fullPath);
36471
+ const targetStat = await fs26.promises.stat(fullPath);
36133
36472
  isDir = targetStat.isDirectory();
36134
36473
  } catch {
36135
36474
  isDir = false;
@@ -36154,25 +36493,25 @@ async function listDirAsync(relativePath) {
36154
36493
  }
36155
36494
 
36156
36495
  // src/files/read-file.ts
36157
- import fs26 from "node:fs";
36496
+ import fs27 from "node:fs";
36158
36497
  import { StringDecoder } from "node:string_decoder";
36159
36498
  function resolveFilePath(relativePath) {
36160
36499
  const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
36161
36500
  if (!resolved) return { error: "Path is outside working directory" };
36162
36501
  let real;
36163
36502
  try {
36164
- real = fs26.realpathSync(resolved);
36503
+ real = fs27.realpathSync(resolved);
36165
36504
  } catch {
36166
36505
  real = resolved;
36167
36506
  }
36168
- const stat2 = fs26.statSync(real);
36169
- if (!stat2.isFile()) return { error: "Not a file" };
36507
+ const stat3 = fs27.statSync(real);
36508
+ if (!stat3.isFile()) return { error: "Not a file" };
36170
36509
  return real;
36171
36510
  }
36172
36511
  var LINE_CHUNK_SIZE = 64 * 1024;
36173
36512
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
36174
- const fileSize = fs26.statSync(filePath).size;
36175
- const fd = fs26.openSync(filePath, "r");
36513
+ const fileSize = fs27.statSync(filePath).size;
36514
+ const fd = fs27.openSync(filePath, "r");
36176
36515
  const bufSize = 64 * 1024;
36177
36516
  const buf = Buffer.alloc(bufSize);
36178
36517
  const decoder = new StringDecoder("utf8");
@@ -36185,7 +36524,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
36185
36524
  let line0Accum = "";
36186
36525
  try {
36187
36526
  let bytesRead;
36188
- while (!done && (bytesRead = fs26.readSync(fd, buf, 0, bufSize, null)) > 0) {
36527
+ while (!done && (bytesRead = fs27.readSync(fd, buf, 0, bufSize, null)) > 0) {
36189
36528
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
36190
36529
  partial2 = "";
36191
36530
  let lineStart = 0;
@@ -36320,10 +36659,10 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
36320
36659
  }
36321
36660
  return { content: resultLines.join("\n"), size: fileSize };
36322
36661
  } finally {
36323
- fs26.closeSync(fd);
36662
+ fs27.closeSync(fd);
36324
36663
  }
36325
36664
  }
36326
- function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
36665
+ function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
36327
36666
  try {
36328
36667
  const result = resolveFilePath(relativePath);
36329
36668
  if (typeof result === "object") return result;
@@ -36331,43 +36670,45 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
36331
36670
  if (hasRange) {
36332
36671
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
36333
36672
  }
36334
- const stat2 = fs26.statSync(result);
36335
- const raw = fs26.readFileSync(result, "utf8");
36673
+ const stat3 = fs27.statSync(result);
36674
+ const raw = fs27.readFileSync(result, "utf8");
36336
36675
  const lines = raw.split(/\r?\n/);
36337
- return { content: raw, totalLines: lines.length, size: stat2.size };
36676
+ return { content: raw, totalLines: lines.length, size: stat3.size };
36338
36677
  } catch (err) {
36339
36678
  return { error: err instanceof Error ? err.message : String(err) };
36340
36679
  }
36341
36680
  }
36342
36681
  async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
36343
36682
  await yieldToEventLoop();
36344
- return readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize);
36683
+ return readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize);
36345
36684
  }
36346
36685
 
36347
36686
  // src/files/handle-file-browser-search.ts
36348
36687
  var SEARCH_LIMIT = 100;
36349
- function handleFileBrowserSearch(msg, socket) {
36688
+ function handleFileBrowserSearch(msg, socket, e2ee) {
36350
36689
  void (async () => {
36351
36690
  await yieldToEventLoop();
36352
36691
  const q = typeof msg.q === "string" ? msg.q : "";
36353
36692
  const cwd = getBridgeWorkspaceDirectory();
36354
36693
  const index = loadFileIndex(cwd);
36355
36694
  if (index === null) {
36356
- sendWsMessage(socket, {
36695
+ const payload2 = {
36357
36696
  type: "file_browser_search_response",
36358
36697
  id: msg.id,
36359
36698
  paths: [],
36360
36699
  indexReady: false
36361
- });
36700
+ };
36701
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
36362
36702
  return;
36363
36703
  }
36364
36704
  const results = await searchFileIndexAsync(index, q, SEARCH_LIMIT);
36365
- sendWsMessage(socket, {
36705
+ const payload = {
36366
36706
  type: "file_browser_search_response",
36367
36707
  id: msg.id,
36368
36708
  paths: results,
36369
36709
  indexReady: true
36370
- });
36710
+ };
36711
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
36371
36712
  })();
36372
36713
  }
36373
36714
  function triggerFileIndexBuild() {
@@ -36379,7 +36720,10 @@ function triggerFileIndexBuild() {
36379
36720
  }
36380
36721
 
36381
36722
  // src/files/handle-file-browser-request.ts
36382
- 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) {
36383
36727
  void (async () => {
36384
36728
  const reqPath = msg.path.replace(/^\/+/, "") || ".";
36385
36729
  const op = msg.op === "read" ? "read" : "list";
@@ -36388,7 +36732,7 @@ function handleFileBrowserRequest(msg, socket) {
36388
36732
  if ("error" in result) {
36389
36733
  sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
36390
36734
  } else {
36391
- 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 });
36392
36736
  if (reqPath === "." || reqPath === "") {
36393
36737
  triggerFileIndexBuild();
36394
36738
  }
@@ -36410,27 +36754,28 @@ function handleFileBrowserRequest(msg, socket) {
36410
36754
  size: result.size
36411
36755
  };
36412
36756
  if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
36413
- sendWsMessage(socket, payload);
36757
+ sendFileBrowserMessage(socket, e2ee, payload);
36414
36758
  }
36415
36759
  }
36416
36760
  })();
36417
36761
  }
36418
36762
 
36419
36763
  // src/bridge/routing/handlers/file-browser-messages.ts
36420
- function handleFileBrowserRequestMessage(msg, { getWs }) {
36764
+ function handleFileBrowserRequestMessage(msg, { getWs, e2ee }) {
36421
36765
  if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
36422
36766
  const socket = getWs();
36423
36767
  if (!socket) return;
36424
36768
  handleFileBrowserRequest(
36425
36769
  msg,
36426
- socket
36770
+ socket,
36771
+ e2ee
36427
36772
  );
36428
36773
  }
36429
- function handleFileBrowserSearchMessage(msg, { getWs }) {
36774
+ function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
36430
36775
  if (typeof msg.id !== "string") return;
36431
36776
  const socket = getWs();
36432
36777
  if (!socket) return;
36433
- handleFileBrowserSearch(msg, socket);
36778
+ handleFileBrowserSearch(msg, socket, e2ee);
36434
36779
  }
36435
36780
 
36436
36781
  // src/bridge/routing/handlers/skill-layout-request.ts
@@ -36442,8 +36787,8 @@ function handleSkillLayoutRequest(msg, deps) {
36442
36787
  }
36443
36788
 
36444
36789
  // src/skills/install-remote-skills.ts
36445
- import fs27 from "node:fs";
36446
- import path31 from "node:path";
36790
+ import fs28 from "node:fs";
36791
+ import path32 from "node:path";
36447
36792
  function installRemoteSkills(cwd, targetDir, items) {
36448
36793
  const installed2 = [];
36449
36794
  if (!Array.isArray(items)) {
@@ -36454,15 +36799,15 @@ function installRemoteSkills(cwd, targetDir, items) {
36454
36799
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
36455
36800
  continue;
36456
36801
  }
36457
- const skillDir = path31.join(cwd, targetDir, item.skillName);
36802
+ const skillDir = path32.join(cwd, targetDir, item.skillName);
36458
36803
  for (const f of item.files) {
36459
36804
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
36460
- const dest = path31.join(skillDir, f.path);
36461
- fs27.mkdirSync(path31.dirname(dest), { recursive: true });
36805
+ const dest = path32.join(skillDir, f.path);
36806
+ fs28.mkdirSync(path32.dirname(dest), { recursive: true });
36462
36807
  if (f.text !== void 0) {
36463
- fs27.writeFileSync(dest, f.text, "utf8");
36808
+ fs28.writeFileSync(dest, f.text, "utf8");
36464
36809
  } else if (f.base64) {
36465
- fs27.writeFileSync(dest, Buffer.from(f.base64, "base64"));
36810
+ fs28.writeFileSync(dest, Buffer.from(f.base64, "base64"));
36466
36811
  }
36467
36812
  }
36468
36813
  installed2.push({
@@ -36500,9 +36845,10 @@ var handleRefreshLocalSkills = (_msg, deps) => {
36500
36845
  };
36501
36846
 
36502
36847
  // src/bridge/routing/handlers/session-git-request.ts
36503
- function sendResult(ws, id, payload) {
36848
+ function sendResult(ws, id, payload, e2ee, encryptedFields = []) {
36504
36849
  if (!ws) return;
36505
- 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);
36506
36852
  }
36507
36853
  var handleSessionGitRequestMessage = (msg, deps) => {
36508
36854
  if (typeof msg.id !== "string") return;
@@ -36512,7 +36858,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
36512
36858
  return;
36513
36859
  void (async () => {
36514
36860
  const ws = deps.getWs();
36515
- const reply = (payload) => sendResult(ws, msg.id, payload);
36861
+ const reply = (payload, encryptedFields = []) => sendResult(ws, msg.id, payload, deps.e2ee, encryptedFields);
36516
36862
  try {
36517
36863
  if (action === "status") {
36518
36864
  const r = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
@@ -36538,7 +36884,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
36538
36884
  reply({
36539
36885
  ok: true,
36540
36886
  repos
36541
- });
36887
+ }, ["repos"]);
36542
36888
  return;
36543
36889
  }
36544
36890
  if (action === "push") {
@@ -36607,7 +36953,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
36607
36953
  };
36608
36954
 
36609
36955
  // src/bridge/routing/handlers/revert-turn-snapshot.ts
36610
- import * as fs28 from "node:fs";
36956
+ import * as fs29 from "node:fs";
36611
36957
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
36612
36958
  const id = typeof msg.id === "string" ? msg.id : "";
36613
36959
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -36619,7 +36965,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
36619
36965
  if (!s) return;
36620
36966
  const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
36621
36967
  const file2 = snapshotFilePath(agentBase, turnId);
36622
- if (!fs28.existsSync(file2)) {
36968
+ if (!fs29.existsSync(file2)) {
36623
36969
  sendWsMessage(s, {
36624
36970
  type: "revert_turn_snapshot_result",
36625
36971
  id,
@@ -36640,8 +36986,15 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
36640
36986
 
36641
36987
  // src/bridge/routing/handlers/dev-server-control.ts
36642
36988
  var handleDevServerControl = (msg, deps) => {
36643
- const serverId = typeof msg.serverId === "string" ? msg.serverId : "";
36644
- 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;
36645
36998
  if (!serverId || !action) return;
36646
36999
  deps.devServerManager?.handleControl(serverId, action);
36647
37000
  };
@@ -36767,7 +37120,8 @@ function createMainBridgeWebSocketLifecycle(params) {
36767
37120
  messageDeps,
36768
37121
  tokens,
36769
37122
  persistTokens,
36770
- onAuthInvalid
37123
+ onAuthInvalid,
37124
+ e2ee
36771
37125
  } = params;
36772
37126
  let authRefreshInFlight = false;
36773
37127
  function handleOpen() {
@@ -36780,15 +37134,15 @@ function createMainBridgeWebSocketLifecycle(params) {
36780
37134
  }
36781
37135
  const socket = getWs();
36782
37136
  if (socket) {
36783
- sendWsMessage(socket, { type: "identify", role: "cli" });
37137
+ sendWsMessage(socket, { type: "identify", role: "cli", ...e2ee ? { e: e2ee.handshake } : {} });
36784
37138
  reportGitRepos(getWs, logFn);
36785
37139
  }
36786
37140
  if (justAuthenticated && socket) {
36787
37141
  logFn(
36788
37142
  "Save these for future runs (access token may rotate; refresh token is stored in ~/.buildautomaton/config.json when you use browser auth):"
36789
37143
  );
36790
- logFn(` export BUILDAMATON_AUTH_TOKEN="${tokens.accessToken}"`);
36791
- logFn(` export BUILDAMATON_WORKSPACE_ID="${workspaceId}"`);
37144
+ logFn(` export BUILDAUTOMATON_AUTH_TOKEN="${tokens.accessToken}"`);
37145
+ logFn(` export BUILDAUTOMATON_WORKSPACE_ID="${workspaceId}"`);
36792
37146
  }
36793
37147
  }
36794
37148
  function handleClose(code, reason) {
@@ -36903,7 +37257,8 @@ async function createBridgeConnection(options) {
36903
37257
  function getWs() {
36904
37258
  return state.currentWs;
36905
37259
  }
36906
- 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 });
36907
37262
  const onBridgeIdentified = createOnBridgeIdentified({
36908
37263
  sessionWorktreeManager,
36909
37264
  devServerManager,
@@ -36922,7 +37277,8 @@ async function createBridgeConnection(options) {
36922
37277
  onBridgeIdentified,
36923
37278
  sendLocalSkillsReport,
36924
37279
  reportAutoDetectedAgents,
36925
- devServerManager
37280
+ devServerManager,
37281
+ e2ee
36926
37282
  };
36927
37283
  const { connect } = createMainBridgeWebSocketLifecycle({
36928
37284
  state,
@@ -36934,7 +37290,8 @@ async function createBridgeConnection(options) {
36934
37290
  messageDeps,
36935
37291
  tokens,
36936
37292
  persistTokens,
36937
- onAuthInvalid
37293
+ onAuthInvalid,
37294
+ e2ee
36938
37295
  });
36939
37296
  connect();
36940
37297
  const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
@@ -36946,14 +37303,149 @@ async function createBridgeConnection(options) {
36946
37303
  };
36947
37304
  }
36948
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
+
36949
37434
  // src/run-bridge.ts
36950
37435
  async function runBridge(options) {
36951
37436
  installBridgeProcessResilience();
36952
- 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;
36953
37445
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
36954
37446
  const hasAuth = workspaceId && authToken;
36955
37447
  if (!hasAuth) {
36956
- const handle2 = runPendingAuth({
37448
+ const handle = runPendingAuth({
36957
37449
  apiUrl,
36958
37450
  initialWorkspaceId: workspaceId,
36959
37451
  preferredBridgeName: bridgeName,
@@ -36961,23 +37453,23 @@ async function runBridge(options) {
36961
37453
  onAuth: (_auth) => {
36962
37454
  }
36963
37455
  });
36964
- const onSignal2 = (kind) => {
37456
+ const onSignal = (kind) => {
36965
37457
  logImmediate(
36966
37458
  kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
36967
37459
  );
36968
37460
  setImmediate(() => {
36969
- handle2.close();
37461
+ handle.close();
36970
37462
  process.exit(0);
36971
37463
  });
36972
37464
  };
36973
- const onSigInt2 = () => onSignal2("interrupt");
36974
- const onSigTerm2 = () => onSignal2("stop");
36975
- process.on("SIGINT", onSigInt2);
36976
- process.on("SIGTERM", onSigTerm2);
36977
- const auth = await handle2.authPromise;
36978
- process.off("SIGINT", onSigInt2);
36979
- process.off("SIGTERM", onSigTerm2);
36980
- 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();
36981
37473
  if (!auth) return;
36982
37474
  writeConfigForApi(apiUrl, {
36983
37475
  workspaceId: auth.workspaceId,
@@ -36992,111 +37484,91 @@ async function runBridge(options) {
36992
37484
  firehoseServerUrl,
36993
37485
  bridgeName,
36994
37486
  justAuthenticated: true,
36995
- worktreesRootAbs
37487
+ worktreesRootAbs,
37488
+ e2eCertificate
36996
37489
  });
36997
37490
  return;
36998
37491
  }
36999
- 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({
37000
37543
  apiUrl,
37001
- workspaceId,
37544
+ workspaceId: workspaceId || void 0,
37002
37545
  authToken,
37003
37546
  refreshToken,
37004
37547
  firehoseServerUrl,
37005
- justAuthenticated,
37548
+ bridgeName: opts.name?.trim() || void 0,
37006
37549
  worktreesRootAbs,
37007
- log,
37008
- persistTokens: (t) => {
37009
- writeConfigForApi(apiUrl, {
37010
- workspaceId,
37011
- token: t.token,
37012
- refreshToken: t.refreshToken
37013
- });
37014
- },
37015
- onAuthInvalid: () => {
37016
- log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
37017
- clearConfigForApi(apiUrl);
37018
- void handle.close().then(() => {
37019
- void runBridge({ apiUrl, firehoseServerUrl, worktreesRootAbs });
37020
- });
37021
- }
37550
+ e2eCertificate: e2eCertificates?.activeCertificate
37022
37551
  });
37023
- const onSignal = (kind) => {
37024
- logImmediate(
37025
- kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
37026
- );
37027
- setImmediate(() => {
37028
- void handle.close().then(() => {
37029
- process.exit(0);
37030
- });
37031
- });
37032
- };
37033
- const onSigInt = () => onSignal("interrupt");
37034
- const onSigTerm = () => onSignal("stop");
37035
- process.on("SIGINT", onSigInt);
37036
- process.on("SIGTERM", onSigTerm);
37037
37552
  }
37038
37553
 
37039
37554
  // src/cli.ts
37040
- var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
37041
- var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
37042
37555
  async function main() {
37043
37556
  const program2 = new Command();
37044
- 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(
37045
37558
  "--firehose-url <url>",
37046
- "Firehose server URL (default: Fly app; or BUILDAMATON_FIREHOSE_URL / legacy BUILDAMATON_PROXY_URL)",
37047
- 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
37048
37561
  ).option("--proxy-url <url>", "Deprecated alias for --firehose-url", void 0).option(
37049
37562
  "--cwd <path>",
37050
37563
  "Working directory for the bridge (absolute or relative to the current directory); affects skills, git, file index, and agent cwd"
37051
37564
  ).option("-n, --name <name>", "Bridge name when creating via browser (alphanumeric and underscores only)").option(
37052
37565
  "--worktrees-root <path>",
37053
37566
  "Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees). Whether worktrees are used is controlled in the cloud for each bridge token."
37054
- ).option("--no-config", "Ignore saved config at ~/.buildautomaton/config.json").action(async (opts) => {
37055
- const positionalUrl = program2.args?.[0];
37056
- const urlFromPositional = typeof positionalUrl === "string" && /^https?:\/\//i.test(positionalUrl) ? positionalUrl : void 0;
37057
- const apiUrlFromCli = opts.apiUrl ?? urlFromPositional;
37058
- let apiUrl = apiUrlFromCli ?? DEFAULT_API_URL;
37059
- let workspaceId = opts.workspaceId ?? "";
37060
- let authToken = opts.token;
37061
- const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAMATON_FIREHOSE_URL ?? process.env.BUILDAMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
37062
- if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
37063
- const resolvedCwd = path32.resolve(process.cwd(), opts.cwd.trim());
37064
- try {
37065
- const st = fs29.statSync(resolvedCwd);
37066
- if (!st.isDirectory()) {
37067
- console.error(`--cwd is not a directory: ${resolvedCwd}`);
37068
- process.exit(1);
37069
- }
37070
- } catch {
37071
- console.error(`--cwd path does not exist or is not accessible: ${resolvedCwd}`);
37072
- process.exit(1);
37073
- }
37074
- process.chdir(resolvedCwd);
37075
- }
37076
- initBridgeWorkspaceDirectory();
37077
- let worktreesRootAbs;
37078
- if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
37079
- worktreesRootAbs = path32.resolve(opts.worktreesRoot.trim());
37080
- }
37081
- let refreshToken;
37082
- if ((!workspaceId || !authToken) && opts.config !== false) {
37083
- const saved = readConfigForApi(apiUrl);
37084
- if (saved?.workspaceId && saved?.token) {
37085
- if (!workspaceId) workspaceId = saved.workspaceId;
37086
- if (!authToken) authToken = saved.token;
37087
- refreshToken = saved.refreshToken;
37088
- }
37089
- }
37090
- await runBridge({
37091
- apiUrl,
37092
- workspaceId: workspaceId || void 0,
37093
- authToken,
37094
- refreshToken,
37095
- firehoseServerUrl,
37096
- bridgeName: opts.name?.trim() || void 0,
37097
- worktreesRootAbs
37098
- });
37099
- });
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));
37100
37572
  await program2.parseAsync(process.argv);
37101
37573
  }
37102
37574
  main().catch((err) => {