@buildautomaton/cli 0.1.18 → 0.1.20

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 path34 = __require("node:path");
977
- var fs31 = __require("node:fs");
976
+ var path36 = __require("node:path");
977
+ var fs34 = __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 = path34.resolve(baseDir, baseName);
1910
- if (fs31.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path34.extname(baseName))) return void 0;
1909
+ const localBin = path36.resolve(baseDir, baseName);
1910
+ if (fs34.existsSync(localBin)) return localBin;
1911
+ if (sourceExt.includes(path36.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
- (ext) => fs31.existsSync(`${localBin}${ext}`)
1913
+ (ext) => fs34.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 = fs31.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs34.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path34.resolve(
1930
- path34.dirname(resolvedScriptPath),
1929
+ executableDir = path36.resolve(
1930
+ path36.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 = path34.basename(
1937
+ const legacyName = path36.basename(
1938
1938
  this._scriptPath,
1939
- path34.extname(this._scriptPath)
1939
+ path36.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(path34.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path36.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 = path34.basename(filename, path34.extname(filename));
2790
+ this._name = path36.basename(filename, path36.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(path35) {
2805
- if (path35 === void 0) return this._executableDir;
2806
- this._executableDir = path35;
2804
+ executableDir(path37) {
2805
+ if (path37 === void 0) return this._executableDir;
2806
+ this._executableDir = path37;
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: randomBytes3, createHash: createHash3 } = __require("crypto");
5239
+ var { randomBytes: randomBytes3, createHash: createHash2 } = __require("crypto");
5240
5240
  var { Duplex, Readable: Readable2 } = __require("stream");
5241
5241
  var { URL: URL2 } = __require("url");
5242
5242
  var PerMessageDeflate = require_permessage_deflate();
@@ -5896,7 +5896,7 @@ var require_websocket = __commonJS({
5896
5896
  abortHandshake(websocket, socket, "Invalid Upgrade header");
5897
5897
  return;
5898
5898
  }
5899
- const digest = createHash3("sha1").update(key + GUID).digest("base64");
5899
+ const digest = createHash2("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: createHash3 } = __require("crypto");
6266
+ var { createHash: createHash2 } = __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 = createHash3("sha1").update(key + GUID).digest("base64");
6567
+ const digest = createHash2("sha1").update(key + GUID).digest("base64");
6568
6568
  const headers = [
6569
6569
  "HTTP/1.1 101 Switching Protocols",
6570
6570
  "Upgrade: websocket",
@@ -7129,7 +7129,7 @@ var require_has_flag = __commonJS({
7129
7129
  var require_supports_color = __commonJS({
7130
7130
  "../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
7131
7131
  "use strict";
7132
- var os6 = __require("os");
7132
+ var os7 = __require("os");
7133
7133
  var tty = __require("tty");
7134
7134
  var hasFlag = require_has_flag();
7135
7135
  var { env } = process;
@@ -7177,7 +7177,7 @@ var require_supports_color = __commonJS({
7177
7177
  return min;
7178
7178
  }
7179
7179
  if (process.platform === "win32") {
7180
- const osRelease = os6.release().split(".");
7180
+ const osRelease = os7.release().split(".");
7181
7181
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
7182
7182
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
7183
7183
  }
@@ -7423,10 +7423,10 @@ 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(path34, isFile, isDirectory) {
7427
- log2(`checking %s`, path34);
7426
+ function check2(path36, isFile, isDirectory) {
7427
+ log2(`checking %s`, path36);
7428
7428
  try {
7429
- const stat3 = fs_1.statSync(path34);
7429
+ const stat3 = fs_1.statSync(path36);
7430
7430
  if (stat3.isFile() && isFile) {
7431
7431
  log2(`[OK] path represents a file`);
7432
7432
  return true;
@@ -7446,8 +7446,8 @@ var require_src2 = __commonJS({
7446
7446
  throw e;
7447
7447
  }
7448
7448
  }
7449
- function exists2(path34, type = exports.READABLE) {
7450
- return check2(path34, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
7449
+ function exists2(path36, type = exports.READABLE) {
7450
+ return check2(path36, (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: path34, errorMaps, issueData } = params;
7926
- const fullPath = [...path34, ...issueData.path || []];
7925
+ const { data, path: path36, errorMaps, issueData } = params;
7926
+ const fullPath = [...path36, ...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, path34, key) {
8234
+ constructor(parent, value, path36, key) {
8235
8235
  this._cachedPath = [];
8236
8236
  this.parent = parent;
8237
8237
  this.data = value;
8238
- this._path = path34;
8238
+ this._path = path36;
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, path34) {
11854
- if (!path34)
11853
+ function getElementAtPath(obj, path36) {
11854
+ if (!path36)
11855
11855
  return obj;
11856
- return path34.reduce((acc, key) => acc?.[key], obj);
11856
+ return path36.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(path34, issues) {
12105
+ function prefixIssues(path36, issues) {
12106
12106
  return issues.map((iss) => {
12107
12107
  var _a2;
12108
12108
  (_a2 = iss).path ?? (_a2.path = []);
12109
- iss.path.unshift(path34);
12109
+ iss.path.unshift(path36);
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, path34 = []) => {
12298
+ const processError = (error41, path36 = []) => {
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 = [...path34, ...issue2.path];
12308
+ const fullpath = [...path36, ...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(path34) {
12338
+ function toDotPath(path36) {
12339
12339
  const segs = [];
12340
- for (const seg of path34) {
12340
+ for (const seg of path36) {
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((resolve17) => {
24804
- this.#abortController.signal.addEventListener("abort", () => resolve17());
24803
+ this.#closedPromise = new Promise((resolve18) => {
24804
+ this.#abortController.signal.addEventListener("abort", () => resolve18());
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((resolve17, reject) => {
24954
- this.#pendingResponses.set(id, { resolve: resolve17, reject });
24953
+ const responsePromise = new Promise((resolve18, reject) => {
24954
+ this.#pendingResponses.set(id, { resolve: resolve18, reject });
24955
24955
  });
24956
24956
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
24957
24957
  return responsePromise;
@@ -25063,13 +25063,16 @@ var {
25063
25063
  Help
25064
25064
  } = import_index.default;
25065
25065
 
25066
+ // src/cli-version.ts
25067
+ var CLI_VERSION = "0.1.20".length > 0 ? "0.1.20" : "0.0.0-dev";
25068
+
25066
25069
  // src/cli/defaults.ts
25067
25070
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
25068
25071
  var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
25069
25072
 
25070
25073
  // src/cli/run-cli-action.ts
25071
- import * as fs30 from "node:fs";
25072
- import * as path33 from "node:path";
25074
+ import * as fs33 from "node:fs";
25075
+ import * as path35 from "node:path";
25073
25076
 
25074
25077
  // src/config.ts
25075
25078
  import fs from "node:fs";
@@ -26034,14 +26037,14 @@ var baseOpen = async (options) => {
26034
26037
  }
26035
26038
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
26036
26039
  if (options.wait) {
26037
- return new Promise((resolve17, reject) => {
26040
+ return new Promise((resolve18, reject) => {
26038
26041
  subprocess.once("error", reject);
26039
26042
  subprocess.once("close", (exitCode) => {
26040
26043
  if (!options.allowNonzeroExitCode && exitCode > 0) {
26041
26044
  reject(new Error(`Exited with code ${exitCode}`));
26042
26045
  return;
26043
26046
  }
26044
- resolve17(subprocess);
26047
+ resolve18(subprocess);
26045
26048
  });
26046
26049
  });
26047
26050
  }
@@ -26337,8 +26340,8 @@ function runPendingAuth(options) {
26337
26340
  let hasOpenedBrowser = false;
26338
26341
  let resolved = false;
26339
26342
  let resolveAuth;
26340
- const authPromise = new Promise((resolve17) => {
26341
- resolveAuth = resolve17;
26343
+ const authPromise = new Promise((resolve18) => {
26344
+ resolveAuth = resolve18;
26342
26345
  });
26343
26346
  let reconnectAttempt = 0;
26344
26347
  const signInQuiet = createEmptyReconnectQuietSlot();
@@ -26390,7 +26393,7 @@ function runPendingAuth(options) {
26390
26393
  url: url2,
26391
26394
  onOpen: () => {
26392
26395
  clearQuietOnOpen();
26393
- sendWsMessage(ws, { type: "identify", role: "cli" });
26396
+ sendWsMessage(ws, { type: "identify", role: "cli", cliVersion: CLI_VERSION });
26394
26397
  keepaliveInterval = setInterval(() => {
26395
26398
  if (resolved || !ws || ws.readyState !== 1) return;
26396
26399
  sendWsMessage(ws, { type: "ping", timestamp: Date.now() });
@@ -26460,7 +26463,7 @@ function runPendingAuth(options) {
26460
26463
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
26461
26464
  const say = log2 ?? logImmediate;
26462
26465
  say("Cleaning up connections\u2026");
26463
- await new Promise((resolve17) => setImmediate(resolve17));
26466
+ await new Promise((resolve18) => setImmediate(resolve18));
26464
26467
  state.closedByUser = true;
26465
26468
  clearReconnectQuietTimer(state.mainQuiet);
26466
26469
  clearReconnectQuietTimer(state.firehoseQuiet);
@@ -26582,8 +26585,8 @@ function pathspec(...paths) {
26582
26585
  cache.set(key, paths);
26583
26586
  return key;
26584
26587
  }
26585
- function isPathSpec(path34) {
26586
- return path34 instanceof String && cache.has(path34);
26588
+ function isPathSpec(path36) {
26589
+ return path36 instanceof String && cache.has(path36);
26587
26590
  }
26588
26591
  function toPaths(pathSpec) {
26589
26592
  return cache.get(pathSpec) || [];
@@ -26672,8 +26675,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
26672
26675
  function forEachLineWithContent(input, callback) {
26673
26676
  return toLinesWithContent(input, true).map((line) => callback(line));
26674
26677
  }
26675
- function folderExists(path34) {
26676
- return (0, import_file_exists.exists)(path34, import_file_exists.FOLDER);
26678
+ function folderExists(path36) {
26679
+ return (0, import_file_exists.exists)(path36, import_file_exists.FOLDER);
26677
26680
  }
26678
26681
  function append(target, item) {
26679
26682
  if (Array.isArray(target)) {
@@ -27077,8 +27080,8 @@ function checkIsRepoRootTask() {
27077
27080
  commands,
27078
27081
  format: "utf-8",
27079
27082
  onError,
27080
- parser(path34) {
27081
- return /^\.(git)?$/.test(path34.trim());
27083
+ parser(path36) {
27084
+ return /^\.(git)?$/.test(path36.trim());
27082
27085
  }
27083
27086
  };
27084
27087
  }
@@ -27512,11 +27515,11 @@ function parseGrep(grep) {
27512
27515
  const paths = /* @__PURE__ */ new Set();
27513
27516
  const results = {};
27514
27517
  forEachLineWithContent(grep, (input) => {
27515
- const [path34, line, preview] = input.split(NULL);
27516
- paths.add(path34);
27517
- (results[path34] = results[path34] || []).push({
27518
+ const [path36, line, preview] = input.split(NULL);
27519
+ paths.add(path36);
27520
+ (results[path36] = results[path36] || []).push({
27518
27521
  line: asNumber(line),
27519
- path: path34,
27522
+ path: path36,
27520
27523
  preview
27521
27524
  });
27522
27525
  });
@@ -28281,14 +28284,14 @@ var init_hash_object = __esm2({
28281
28284
  init_task();
28282
28285
  }
28283
28286
  });
28284
- function parseInit(bare, path34, text) {
28287
+ function parseInit(bare, path36, text) {
28285
28288
  const response = String(text).trim();
28286
28289
  let result;
28287
28290
  if (result = initResponseRegex.exec(response)) {
28288
- return new InitSummary(bare, path34, false, result[1]);
28291
+ return new InitSummary(bare, path36, false, result[1]);
28289
28292
  }
28290
28293
  if (result = reInitResponseRegex.exec(response)) {
28291
- return new InitSummary(bare, path34, true, result[1]);
28294
+ return new InitSummary(bare, path36, true, result[1]);
28292
28295
  }
28293
28296
  let gitDir = "";
28294
28297
  const tokens = response.split(" ");
@@ -28299,7 +28302,7 @@ function parseInit(bare, path34, text) {
28299
28302
  break;
28300
28303
  }
28301
28304
  }
28302
- return new InitSummary(bare, path34, /^re/i.test(response), gitDir);
28305
+ return new InitSummary(bare, path36, /^re/i.test(response), gitDir);
28303
28306
  }
28304
28307
  var InitSummary;
28305
28308
  var initResponseRegex;
@@ -28308,9 +28311,9 @@ var init_InitSummary = __esm2({
28308
28311
  "src/lib/responses/InitSummary.ts"() {
28309
28312
  "use strict";
28310
28313
  InitSummary = class {
28311
- constructor(bare, path34, existing, gitDir) {
28314
+ constructor(bare, path36, existing, gitDir) {
28312
28315
  this.bare = bare;
28313
- this.path = path34;
28316
+ this.path = path36;
28314
28317
  this.existing = existing;
28315
28318
  this.gitDir = gitDir;
28316
28319
  }
@@ -28322,7 +28325,7 @@ var init_InitSummary = __esm2({
28322
28325
  function hasBareCommand(command) {
28323
28326
  return command.includes(bareCommand);
28324
28327
  }
28325
- function initTask(bare = false, path34, customArgs) {
28328
+ function initTask(bare = false, path36, customArgs) {
28326
28329
  const commands = ["init", ...customArgs];
28327
28330
  if (bare && !hasBareCommand(commands)) {
28328
28331
  commands.splice(1, 0, bareCommand);
@@ -28331,7 +28334,7 @@ function initTask(bare = false, path34, customArgs) {
28331
28334
  commands,
28332
28335
  format: "utf-8",
28333
28336
  parser(text) {
28334
- return parseInit(commands.includes("--bare"), path34, text);
28337
+ return parseInit(commands.includes("--bare"), path36, text);
28335
28338
  }
28336
28339
  };
28337
28340
  }
@@ -29147,12 +29150,12 @@ var init_FileStatusSummary = __esm2({
29147
29150
  "use strict";
29148
29151
  fromPathRegex = /^(.+)\0(.+)$/;
29149
29152
  FileStatusSummary = class {
29150
- constructor(path34, index, working_dir) {
29151
- this.path = path34;
29153
+ constructor(path36, index, working_dir) {
29154
+ this.path = path36;
29152
29155
  this.index = index;
29153
29156
  this.working_dir = working_dir;
29154
29157
  if (index === "R" || working_dir === "R") {
29155
- const detail = fromPathRegex.exec(path34) || [null, path34, path34];
29158
+ const detail = fromPathRegex.exec(path36) || [null, path36, path36];
29156
29159
  this.from = detail[2] || "";
29157
29160
  this.path = detail[1] || "";
29158
29161
  }
@@ -29183,14 +29186,14 @@ function splitLine(result, lineStr) {
29183
29186
  default:
29184
29187
  return;
29185
29188
  }
29186
- function data(index, workingDir, path34) {
29189
+ function data(index, workingDir, path36) {
29187
29190
  const raw = `${index}${workingDir}`;
29188
29191
  const handler = parsers6.get(raw);
29189
29192
  if (handler) {
29190
- handler(result, path34);
29193
+ handler(result, path36);
29191
29194
  }
29192
29195
  if (raw !== "##" && raw !== "!!") {
29193
- result.files.push(new FileStatusSummary(path34, index, workingDir));
29196
+ result.files.push(new FileStatusSummary(path36, index, workingDir));
29194
29197
  }
29195
29198
  }
29196
29199
  }
@@ -29499,9 +29502,9 @@ var init_simple_git_api = __esm2({
29499
29502
  next
29500
29503
  );
29501
29504
  }
29502
- hashObject(path34, write) {
29505
+ hashObject(path36, write) {
29503
29506
  return this._runTask(
29504
- hashObjectTask(path34, write === true),
29507
+ hashObjectTask(path36, write === true),
29505
29508
  trailingFunctionArgument(arguments)
29506
29509
  );
29507
29510
  }
@@ -29854,8 +29857,8 @@ var init_branch = __esm2({
29854
29857
  }
29855
29858
  });
29856
29859
  function toPath(input) {
29857
- const path34 = input.trim().replace(/^["']|["']$/g, "");
29858
- return path34 && normalize(path34);
29860
+ const path36 = input.trim().replace(/^["']|["']$/g, "");
29861
+ return path36 && normalize(path36);
29859
29862
  }
29860
29863
  var parseCheckIgnore;
29861
29864
  var init_CheckIgnore = __esm2({
@@ -30169,8 +30172,8 @@ __export2(sub_module_exports, {
30169
30172
  subModuleTask: () => subModuleTask,
30170
30173
  updateSubModuleTask: () => updateSubModuleTask
30171
30174
  });
30172
- function addSubModuleTask(repo, path34) {
30173
- return subModuleTask(["add", repo, path34]);
30175
+ function addSubModuleTask(repo, path36) {
30176
+ return subModuleTask(["add", repo, path36]);
30174
30177
  }
30175
30178
  function initSubModuleTask(customArgs) {
30176
30179
  return subModuleTask(["init", ...customArgs]);
@@ -30503,8 +30506,8 @@ var require_git = __commonJS2({
30503
30506
  }
30504
30507
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
30505
30508
  };
30506
- Git2.prototype.submoduleAdd = function(repo, path34, then) {
30507
- return this._runTask(addSubModuleTask2(repo, path34), trailingFunctionArgument2(arguments));
30509
+ Git2.prototype.submoduleAdd = function(repo, path36, then) {
30510
+ return this._runTask(addSubModuleTask2(repo, path36), trailingFunctionArgument2(arguments));
30508
30511
  };
30509
30512
  Git2.prototype.submoduleUpdate = function(args, then) {
30510
30513
  return this._runTask(
@@ -31364,18 +31367,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
31364
31367
  }
31365
31368
  }
31366
31369
 
31367
- // ../types/dist/index.js
31368
- init_zod();
31369
- init_zod();
31370
- init_zod();
31371
- init_zod();
31372
- init_zod();
31373
- init_zod();
31374
- init_zod();
31375
- init_zod();
31376
- init_zod();
31377
- init_zod();
31378
- init_zod();
31370
+ // ../types/src/work-items.ts
31379
31371
  init_zod();
31380
31372
  var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
31381
31373
  var WorkItemProgressSchema = external_exports.object({
@@ -31416,6 +31408,9 @@ var WorkItemSchema = external_exports.object({
31416
31408
  dependencies: external_exports.array(WorkItemDependencySchema).default([]),
31417
31409
  assignedToUserId: external_exports.string().optional()
31418
31410
  });
31411
+
31412
+ // ../types/src/user-profiles.ts
31413
+ init_zod();
31419
31414
  var UserWorkspaceProfileSchema = external_exports.object({
31420
31415
  id: external_exports.string(),
31421
31416
  workspaceId: external_exports.string(),
@@ -31425,6 +31420,9 @@ var UserWorkspaceProfileSchema = external_exports.object({
31425
31420
  preferences: external_exports.record(external_exports.unknown()).optional(),
31426
31421
  learnings: external_exports.array(external_exports.string())
31427
31422
  });
31423
+
31424
+ // ../types/src/runtime.ts
31425
+ init_zod();
31428
31426
  var WorkspaceOwnerInfoSchema = external_exports.object({
31429
31427
  ownerId: external_exports.string(),
31430
31428
  ownerName: external_exports.string().optional(),
@@ -31438,6 +31436,9 @@ var WorkspaceRuntimeEntrySchema = external_exports.object({
31438
31436
  owner: WorkspaceOwnerInfoSchema.optional(),
31439
31437
  isOwner: external_exports.boolean().optional()
31440
31438
  });
31439
+
31440
+ // ../types/src/agent.ts
31441
+ init_zod();
31441
31442
  var ProjectContextSchema = external_exports.object({
31442
31443
  projectId: external_exports.string(),
31443
31444
  context: external_exports.record(external_exports.unknown()).default({}),
@@ -31462,6 +31463,9 @@ var WebSocketMessageSchema = external_exports.object({
31462
31463
  data: external_exports.any().optional(),
31463
31464
  error: external_exports.string().optional()
31464
31465
  });
31466
+
31467
+ // ../types/src/checkpoints.ts
31468
+ init_zod();
31465
31469
  var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
31466
31470
  var CheckpointSummarySchema = external_exports.object({
31467
31471
  id: external_exports.string(),
@@ -31472,6 +31476,9 @@ var CheckpointSummarySchema = external_exports.object({
31472
31476
  createdAt: external_exports.string(),
31473
31477
  updatedAt: external_exports.string()
31474
31478
  });
31479
+
31480
+ // ../types/src/threads.ts
31481
+ init_zod();
31475
31482
  var ThreadMetaSchema = external_exports.object({
31476
31483
  threadId: external_exports.string(),
31477
31484
  workspaceId: external_exports.string(),
@@ -31499,6 +31506,9 @@ var ThreadMessageSchema = external_exports.object({
31499
31506
  var ThreadCheckpointSummarySchema = CheckpointSummarySchema.extend({
31500
31507
  threadId: external_exports.string()
31501
31508
  });
31509
+
31510
+ // ../types/src/content-items.ts
31511
+ init_zod();
31502
31512
  var ContentSourceSchema = external_exports.enum(["notion", "doc", "slack_thread", "other"]);
31503
31513
  var ContentItemMetaSchema = external_exports.object({
31504
31514
  contentId: external_exports.string(),
@@ -31520,6 +31530,9 @@ var ContentStorageRefSchema = external_exports.object({
31520
31530
  var ContentCheckpointSummarySchema = CheckpointSummarySchema.extend({
31521
31531
  contentId: external_exports.string()
31522
31532
  });
31533
+
31534
+ // ../types/src/stories.ts
31535
+ init_zod();
31523
31536
  var StoryMetaSchema = external_exports.object({
31524
31537
  storyId: external_exports.string(),
31525
31538
  workspaceId: external_exports.string(),
@@ -31542,6 +31555,9 @@ var StoryContentItemRefSchema = external_exports.object({
31542
31555
  var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
31543
31556
  storyId: external_exports.string()
31544
31557
  });
31558
+
31559
+ // ../types/src/sessions.ts
31560
+ init_zod();
31545
31561
  var BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID = "__builtin_change_summary__";
31546
31562
  var SessionMetaSchema = external_exports.object({
31547
31563
  sessionId: external_exports.string(),
@@ -31584,6 +31600,8 @@ var SessionThreadRefSchema = external_exports.object({
31584
31600
  threadId: external_exports.string(),
31585
31601
  addedAt: external_exports.string()
31586
31602
  });
31603
+
31604
+ // ../types/src/change-summary-path.ts
31587
31605
  function normalizeRepoRelativePath(p) {
31588
31606
  let t = p.trim().replace(/\\/g, "/");
31589
31607
  while (t.startsWith("./")) t = t.slice(2);
@@ -31600,6 +31618,8 @@ function resolveChangeSummaryPathAgainstAllowed(rawPath, allowed) {
31600
31618
  }
31601
31619
  return null;
31602
31620
  }
31621
+
31622
+ // ../types/src/parse-change-summary-json.ts
31603
31623
  function clampSummaryToAtMostTwoLines(summary) {
31604
31624
  const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
31605
31625
  return lines.slice(0, 2).join("\n");
@@ -31636,12 +31656,14 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
31636
31656
  const rawPath = typeof o.path === "string" ? o.path.trim() : "";
31637
31657
  const summary = typeof o.summary === "string" ? o.summary.trim() : "";
31638
31658
  if (!rawPath || !summary) continue;
31639
- const path34 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
31640
- if (!path34) continue;
31641
- rows.push({ path: path34, summary: clampSummaryToAtMostTwoLines(summary) });
31659
+ const path36 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
31660
+ if (!path36) continue;
31661
+ rows.push({ path: path36, summary: clampSummaryToAtMostTwoLines(summary) });
31642
31662
  }
31643
31663
  return rows;
31644
31664
  }
31665
+
31666
+ // ../types/src/build-change-summary-prompt.ts
31645
31667
  var PATCH_PREVIEW_MAX = 12e3;
31646
31668
  function clip(s, max) {
31647
31669
  if (s.length <= max) return s;
@@ -31699,6 +31721,8 @@ function buildSessionChangeSummaryPrompt(files) {
31699
31721
  }
31700
31722
  return lines.join("\n");
31701
31723
  }
31724
+
31725
+ // ../types/src/dedupe-session-file-changes-by-path.ts
31702
31726
  function defaultRichness(c) {
31703
31727
  const patch = typeof c.patchContent === "string" ? c.patchContent.length : 0;
31704
31728
  const nt = typeof c.newText === "string" ? c.newText.length : 0;
@@ -31716,6 +31740,9 @@ function dedupeSessionFileChangesByPath(items, richness = (item) => defaultRichn
31716
31740
  }
31717
31741
  return Array.from(byPath.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([, v]) => v);
31718
31742
  }
31743
+
31744
+ // ../types/src/artifacts.ts
31745
+ init_zod();
31719
31746
  var ArtifactMetaSchema = external_exports.object({
31720
31747
  artifactId: external_exports.string(),
31721
31748
  workspaceId: external_exports.string(),
@@ -31729,6 +31756,9 @@ var ArtifactMetaSchema = external_exports.object({
31729
31756
  createdAt: external_exports.string(),
31730
31757
  updatedAt: external_exports.string()
31731
31758
  });
31759
+
31760
+ // ../types/src/templates.ts
31761
+ init_zod();
31732
31762
  var TemplateMetaSchema = external_exports.object({
31733
31763
  templateId: external_exports.string(),
31734
31764
  workspaceId: external_exports.string(),
@@ -31738,6 +31768,9 @@ var TemplateMetaSchema = external_exports.object({
31738
31768
  createdAt: external_exports.string(),
31739
31769
  updatedAt: external_exports.string()
31740
31770
  });
31771
+
31772
+ // ../types/src/git-repos.ts
31773
+ init_zod();
31741
31774
  var GitRepoMetaSchema = external_exports.object({
31742
31775
  /** Stable id for the repo (e.g. hash of normalized canonical URL). Used for DO idFromName. */
31743
31776
  repoId: external_exports.string(),
@@ -31753,9 +31786,9 @@ var GitRepoMetaSchema = external_exports.object({
31753
31786
  // src/agents/acp/put-summarize-change-summaries.ts
31754
31787
  async function putEncryptedChangeSummaryRows(params) {
31755
31788
  const base = params.apiBaseUrl.replace(/\/+$/, "");
31756
- const entries = params.rows.map(({ path: path34, summary }) => {
31789
+ const entries = params.rows.map(({ path: path36, summary }) => {
31757
31790
  const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
31758
- return { path: path34, summary: JSON.stringify(enc) };
31791
+ return { path: path36, summary: JSON.stringify(enc) };
31759
31792
  });
31760
31793
  const res = await fetch(
31761
31794
  `${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
@@ -32154,7 +32187,7 @@ async function createSdkStdioAcpClient(options) {
32154
32187
  child.once("close", (code, signal) => {
32155
32188
  onAgentSubprocessExit?.({ code, signal });
32156
32189
  });
32157
- return new Promise((resolve17, reject) => {
32190
+ return new Promise((resolve18, reject) => {
32158
32191
  let initSettled = false;
32159
32192
  const settleReject = (err) => {
32160
32193
  if (initSettled) return;
@@ -32168,7 +32201,7 @@ async function createSdkStdioAcpClient(options) {
32168
32201
  const settleResolve = (handle) => {
32169
32202
  if (initSettled) return;
32170
32203
  initSettled = true;
32171
- resolve17(handle);
32204
+ resolve18(handle);
32172
32205
  };
32173
32206
  child.on("error", (err) => {
32174
32207
  settleReject(new Error(formatSpawnError(err, command[0])));
@@ -32204,8 +32237,8 @@ async function createSdkStdioAcpClient(options) {
32204
32237
  });
32205
32238
  } catch {
32206
32239
  }
32207
- return await new Promise((resolve18) => {
32208
- pendingPermissionResolvers.set(requestId, resolve18);
32240
+ return await new Promise((resolve19) => {
32241
+ pendingPermissionResolvers.set(requestId, resolve19);
32209
32242
  });
32210
32243
  },
32211
32244
  async readTextFile(params) {
@@ -32313,9 +32346,9 @@ async function createSdkStdioAcpClient(options) {
32313
32346
  }
32314
32347
  },
32315
32348
  async cancel() {
32316
- for (const [id, resolve18] of [...pendingPermissionResolvers.entries()]) {
32349
+ for (const [id, resolve19] of [...pendingPermissionResolvers.entries()]) {
32317
32350
  pendingPermissionResolvers.delete(id);
32318
- resolve18({ outcome: { outcome: "cancelled" } });
32351
+ resolve19({ outcome: { outcome: "cancelled" } });
32319
32352
  }
32320
32353
  try {
32321
32354
  await connection.cancel({ sessionId });
@@ -32331,10 +32364,10 @@ async function createSdkStdioAcpClient(options) {
32331
32364
  }
32332
32365
  },
32333
32366
  resolveRequest(requestId, result) {
32334
- const resolve18 = pendingPermissionResolvers.get(requestId);
32335
- if (!resolve18) return;
32367
+ const resolve19 = pendingPermissionResolvers.get(requestId);
32368
+ if (!resolve19) return;
32336
32369
  pendingPermissionResolvers.delete(requestId);
32337
- resolve18(result);
32370
+ resolve19(result);
32338
32371
  },
32339
32372
  disconnect() {
32340
32373
  child.kill();
@@ -32485,7 +32518,7 @@ async function createCursorAcpClient(options) {
32485
32518
  });
32486
32519
  const stderrCapture = createStderrCapture(child);
32487
32520
  child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
32488
- return new Promise((resolve17, reject) => {
32521
+ return new Promise((resolve18, reject) => {
32489
32522
  child.on("error", (err) => {
32490
32523
  child.kill();
32491
32524
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -32672,7 +32705,7 @@ async function createCursorAcpClient(options) {
32672
32705
  const newResult = await send("session/new", { cwd, mcpServers: [] });
32673
32706
  const sessionId = newResult?.sessionId ?? "";
32674
32707
  if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
32675
- resolve17({
32708
+ resolve18({
32676
32709
  sessionId,
32677
32710
  async sendPrompt(prompt, _options) {
32678
32711
  promptOutputBuffer = "";
@@ -33740,7 +33773,7 @@ async function createAcpManager(options) {
33740
33773
  }
33741
33774
 
33742
33775
  // src/worktrees/session-worktree-manager.ts
33743
- import * as path17 from "node:path";
33776
+ import * as path18 from "node:path";
33744
33777
  import os4 from "node:os";
33745
33778
 
33746
33779
  // src/worktrees/prepare-new-session-worktrees.ts
@@ -33789,10 +33822,15 @@ function saveWorktreeLayout(layout) {
33789
33822
  function baseNameSafe(abs) {
33790
33823
  return path12.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
33791
33824
  }
33792
- function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
33825
+ function getLauncherDirNameIfPresent(layout, launcherCwdAbs) {
33793
33826
  const norm = path12.resolve(launcherCwdAbs);
33794
33827
  const existing = layout.launcherCwds.find((e) => path12.resolve(e.absolutePath) === norm);
33795
- if (existing) return existing.dirName;
33828
+ return existing?.dirName;
33829
+ }
33830
+ function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
33831
+ const existing = getLauncherDirNameIfPresent(layout, launcherCwdAbs);
33832
+ if (existing) return existing;
33833
+ const norm = path12.resolve(launcherCwdAbs);
33796
33834
  const base = baseNameSafe(norm);
33797
33835
  const used = new Set(layout.launcherCwds.map((e) => e.dirName));
33798
33836
  let name = base;
@@ -34570,11 +34608,88 @@ async function commitSessionWorktrees(options) {
34570
34608
  }
34571
34609
  }
34572
34610
 
34611
+ // src/worktrees/discover-session-worktree-on-disk.ts
34612
+ import * as fs18 from "node:fs";
34613
+ import * as path17 from "node:path";
34614
+ function isGitDir(abs) {
34615
+ try {
34616
+ return fs18.existsSync(path17.join(abs, ".git"));
34617
+ } catch {
34618
+ return false;
34619
+ }
34620
+ }
34621
+ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
34622
+ const out = [];
34623
+ const walk = (dir, depth) => {
34624
+ if (depth > maxDepth) return;
34625
+ let entries;
34626
+ try {
34627
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
34628
+ } catch {
34629
+ return;
34630
+ }
34631
+ for (const e of entries) {
34632
+ if (e.name.startsWith(".")) continue;
34633
+ const full = path17.join(dir, e.name);
34634
+ if (!e.isDirectory()) continue;
34635
+ if (e.name === sessionId) {
34636
+ if (isGitDir(full)) out.push(path17.resolve(full));
34637
+ } else {
34638
+ walk(full, depth + 1);
34639
+ }
34640
+ }
34641
+ };
34642
+ walk(root, 0);
34643
+ return out;
34644
+ }
34645
+ function discoverSessionWorktreeOnDisk(options) {
34646
+ const { sessionId, worktreesRootAbs, layout, launcherCwd } = options;
34647
+ if (!sessionId.trim() || !fs18.existsSync(worktreesRootAbs)) return null;
34648
+ const preferredKey = getLauncherDirNameIfPresent(layout, launcherCwd);
34649
+ const keys = [];
34650
+ if (preferredKey) keys.push(preferredKey);
34651
+ try {
34652
+ for (const name of fs18.readdirSync(worktreesRootAbs)) {
34653
+ if (name.startsWith(".")) continue;
34654
+ const p = path17.join(worktreesRootAbs, name);
34655
+ if (!fs18.statSync(p).isDirectory()) continue;
34656
+ if (name !== preferredKey) keys.push(name);
34657
+ }
34658
+ } catch {
34659
+ return null;
34660
+ }
34661
+ for (const key of keys) {
34662
+ const mirrorRoot = path17.join(worktreesRootAbs, key);
34663
+ if (!fs18.existsSync(mirrorRoot) || !fs18.statSync(mirrorRoot).isDirectory()) continue;
34664
+ const worktreePaths = collectWorktreeRootsNamed(mirrorRoot, sessionId, 24);
34665
+ if (worktreePaths.length > 0) {
34666
+ return { agentCwd: path17.resolve(mirrorRoot), worktreePaths };
34667
+ }
34668
+ }
34669
+ return null;
34670
+ }
34671
+ function discoverSessionWorktreesUnderMirrorRoot(mirrorRootAbs, sessionId) {
34672
+ const mirrorRoot = path17.resolve(mirrorRootAbs);
34673
+ if (!sessionId.trim() || !fs18.existsSync(mirrorRoot)) return null;
34674
+ try {
34675
+ if (!fs18.statSync(mirrorRoot).isDirectory()) return null;
34676
+ } catch {
34677
+ return null;
34678
+ }
34679
+ const worktreePaths = collectWorktreeRootsNamed(mirrorRoot, sessionId, 24);
34680
+ if (worktreePaths.length === 0) return null;
34681
+ return { agentCwd: mirrorRoot, worktreePaths };
34682
+ }
34683
+
34573
34684
  // src/worktrees/session-worktree-manager.ts
34685
+ function parseSessionParent(v) {
34686
+ if (v === "bridge_root" || v === "worktrees_root") return v;
34687
+ if (v === "session_worktrees_root") return "worktrees_root";
34688
+ return null;
34689
+ }
34574
34690
  var SessionWorktreeManager = class {
34575
34691
  rootAbs;
34576
34692
  log;
34577
- bridgeWantsWorktrees = false;
34578
34693
  sessionPaths = /* @__PURE__ */ new Map();
34579
34694
  sessionAgentCwd = /* @__PURE__ */ new Map();
34580
34695
  layout;
@@ -34583,22 +34698,67 @@ var SessionWorktreeManager = class {
34583
34698
  this.log = options.log;
34584
34699
  this.layout = loadWorktreeLayout();
34585
34700
  }
34586
- setBridgeSessionWorktrees(enabled) {
34587
- this.bridgeWantsWorktrees = enabled;
34701
+ rememberWorktrees(sessionId, agentCwd, worktreePaths) {
34702
+ this.sessionPaths.set(sessionId, worktreePaths);
34703
+ this.sessionAgentCwd.set(sessionId, path18.resolve(agentCwd));
34588
34704
  }
34589
- effective() {
34590
- return this.bridgeWantsWorktrees;
34705
+ tryDiscoverFromDisk(sessionId) {
34706
+ return discoverSessionWorktreeOnDisk({
34707
+ sessionId,
34708
+ worktreesRootAbs: this.rootAbs,
34709
+ layout: this.layout,
34710
+ launcherCwd: getBridgeWorkspaceDirectory()
34711
+ });
34591
34712
  }
34592
34713
  /**
34593
34714
  * Returns cwd for the agent (mirror of launcher tree), or undefined to use the bridge workspace directory.
34594
34715
  */
34595
34716
  async resolveCwdForPrompt(sessionId, opts) {
34596
- if (!sessionId || !this.effective() || !opts.sessionWorktreesEnabled) {
34717
+ if (!sessionId) return void 0;
34718
+ const parentPathRaw = opts.sessionParentPath?.trim();
34719
+ if (parentPathRaw) {
34720
+ const agentCwd = path18.resolve(parentPathRaw);
34721
+ const sid = sessionId?.trim();
34722
+ if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
34723
+ const fromMirror = discoverSessionWorktreesUnderMirrorRoot(agentCwd, sid);
34724
+ if (fromMirror) this.rememberWorktrees(sid, fromMirror.agentCwd, fromMirror.worktreePaths);
34725
+ }
34726
+ return agentCwd;
34727
+ }
34728
+ const parentKind = parseSessionParent(opts.sessionParent);
34729
+ if (parentKind === "bridge_root") {
34597
34730
  return void 0;
34598
34731
  }
34732
+ if (parentKind === "worktrees_root") {
34733
+ if (!opts.isNewSession) {
34734
+ const cached2 = this.sessionAgentCwd.get(sessionId);
34735
+ if (cached2) return path18.resolve(cached2);
34736
+ const disc = this.tryDiscoverFromDisk(sessionId);
34737
+ if (disc) {
34738
+ this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
34739
+ return path18.resolve(disc.agentCwd);
34740
+ }
34741
+ return void 0;
34742
+ }
34743
+ const prep2 = await prepareNewSessionWorktrees({
34744
+ rootAbs: this.rootAbs,
34745
+ launcherCwd: getBridgeWorkspaceDirectory(),
34746
+ sessionId,
34747
+ layout: this.layout,
34748
+ log: this.log
34749
+ });
34750
+ if (!prep2) return void 0;
34751
+ this.rememberWorktrees(sessionId, prep2.agentCwd, prep2.worktreePaths);
34752
+ return path18.resolve(prep2.agentCwd);
34753
+ }
34599
34754
  if (!opts.isNewSession) {
34600
- const agentCwd = this.sessionAgentCwd.get(sessionId);
34601
- if (agentCwd) return path17.resolve(agentCwd);
34755
+ const cached2 = this.sessionAgentCwd.get(sessionId);
34756
+ if (cached2) return path18.resolve(cached2);
34757
+ const disc = this.tryDiscoverFromDisk(sessionId);
34758
+ if (disc) {
34759
+ this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
34760
+ return path18.resolve(disc.agentCwd);
34761
+ }
34602
34762
  return void 0;
34603
34763
  }
34604
34764
  const prep = await prepareNewSessionWorktrees({
@@ -34609,9 +34769,8 @@ var SessionWorktreeManager = class {
34609
34769
  log: this.log
34610
34770
  });
34611
34771
  if (!prep) return void 0;
34612
- this.sessionPaths.set(sessionId, prep.worktreePaths);
34613
- this.sessionAgentCwd.set(sessionId, prep.agentCwd);
34614
- return path17.resolve(prep.agentCwd);
34772
+ this.rememberWorktrees(sessionId, prep.agentCwd, prep.worktreePaths);
34773
+ return path18.resolve(prep.agentCwd);
34615
34774
  }
34616
34775
  async renameSessionBranch(sessionId, newBranch) {
34617
34776
  const paths = this.sessionPaths.get(sessionId);
@@ -34632,7 +34791,7 @@ var SessionWorktreeManager = class {
34632
34791
  getAgentCwdForSession(sessionId) {
34633
34792
  if (!sessionId) return null;
34634
34793
  const c = this.sessionAgentCwd.get(sessionId);
34635
- return c ? path17.resolve(c) : null;
34794
+ return c ? path18.resolve(c) : null;
34636
34795
  }
34637
34796
  async removeSessionWorktrees(sessionId) {
34638
34797
  const paths = this.sessionPaths.get(sessionId);
@@ -34653,7 +34812,13 @@ var SessionWorktreeManager = class {
34653
34812
  }
34654
34813
  resolveCommitTargets(sessionId) {
34655
34814
  const paths = this.sessionPaths.get(sessionId);
34656
- return paths?.length ? paths : [getBridgeWorkspaceDirectory()];
34815
+ if (paths?.length) return paths;
34816
+ const disc = this.tryDiscoverFromDisk(sessionId);
34817
+ if (disc?.worktreePaths.length) {
34818
+ this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
34819
+ return disc.worktreePaths;
34820
+ }
34821
+ return [getBridgeWorkspaceDirectory()];
34657
34822
  }
34658
34823
  async getSessionWorkingTreeStatus(sessionId) {
34659
34824
  return aggregateSessionPathsWorkingTreeStatus(this.resolveCommitTargets(sessionId));
@@ -34680,30 +34845,30 @@ var SessionWorktreeManager = class {
34680
34845
  }
34681
34846
  };
34682
34847
  function defaultWorktreesRootAbs() {
34683
- return path17.join(os4.homedir(), ".buildautomaton", "worktrees");
34848
+ return path18.join(os4.homedir(), ".buildautomaton", "worktrees");
34684
34849
  }
34685
34850
 
34686
34851
  // src/files/watch-file-index.ts
34687
34852
  import { watch } from "node:fs";
34688
- import path24 from "node:path";
34853
+ import path25 from "node:path";
34689
34854
 
34690
34855
  // src/files/index/build-file-index.ts
34691
- import path21 from "node:path";
34856
+ import path22 from "node:path";
34692
34857
 
34693
34858
  // src/runtime/yield-to-event-loop.ts
34694
34859
  function yieldToEventLoop() {
34695
- return new Promise((resolve17) => setImmediate(resolve17));
34860
+ return new Promise((resolve18) => setImmediate(resolve18));
34696
34861
  }
34697
34862
 
34698
34863
  // src/files/index/walk-workspace-tree.ts
34699
- import fs18 from "node:fs";
34700
- import path19 from "node:path";
34864
+ import fs19 from "node:fs";
34865
+ import path20 from "node:path";
34701
34866
 
34702
34867
  // src/files/index/constants.ts
34703
- import path18 from "node:path";
34868
+ import path19 from "node:path";
34704
34869
  import os5 from "node:os";
34705
34870
  var INDEX_WORK_YIELD_EVERY = 256;
34706
- var INDEX_DIR = path18.join(os5.homedir(), ".buildautomaton");
34871
+ var INDEX_DIR = path19.join(os5.homedir(), ".buildautomaton");
34707
34872
  var INDEX_HASH_LEN = 16;
34708
34873
  var INDEX_VERSION = 2;
34709
34874
  var INDEX_LOG_PREFIX = "[file-index]";
@@ -34712,20 +34877,20 @@ var INDEX_LOG_PREFIX = "[file-index]";
34712
34877
  function walkWorkspaceTreeSync(dir, baseDir, out) {
34713
34878
  let names;
34714
34879
  try {
34715
- names = fs18.readdirSync(dir);
34880
+ names = fs19.readdirSync(dir);
34716
34881
  } catch {
34717
34882
  return;
34718
34883
  }
34719
34884
  for (const name of names) {
34720
34885
  if (name.startsWith(".")) continue;
34721
- const full = path19.join(dir, name);
34886
+ const full = path20.join(dir, name);
34722
34887
  let stat3;
34723
34888
  try {
34724
- stat3 = fs18.statSync(full);
34889
+ stat3 = fs19.statSync(full);
34725
34890
  } catch {
34726
34891
  continue;
34727
34892
  }
34728
- const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
34893
+ const relative5 = path20.relative(baseDir, full).replace(/\\/g, "/");
34729
34894
  if (stat3.isDirectory()) {
34730
34895
  walkWorkspaceTreeSync(full, baseDir, out);
34731
34896
  } else if (stat3.isFile()) {
@@ -34736,7 +34901,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
34736
34901
  async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
34737
34902
  let names;
34738
34903
  try {
34739
- names = await fs18.promises.readdir(dir);
34904
+ names = await fs19.promises.readdir(dir);
34740
34905
  } catch {
34741
34906
  return;
34742
34907
  }
@@ -34746,14 +34911,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
34746
34911
  await yieldToEventLoop();
34747
34912
  }
34748
34913
  state.n++;
34749
- const full = path19.join(dir, name);
34914
+ const full = path20.join(dir, name);
34750
34915
  let stat3;
34751
34916
  try {
34752
- stat3 = await fs18.promises.stat(full);
34917
+ stat3 = await fs19.promises.stat(full);
34753
34918
  } catch {
34754
34919
  continue;
34755
34920
  }
34756
- const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
34921
+ const relative5 = path20.relative(baseDir, full).replace(/\\/g, "/");
34757
34922
  if (stat3.isDirectory()) {
34758
34923
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
34759
34924
  } else if (stat3.isFile()) {
@@ -34834,22 +34999,22 @@ async function buildTrigramMapForPathsAsync(paths) {
34834
34999
  }
34835
35000
 
34836
35001
  // src/files/index/write-index-file.ts
34837
- import fs19 from "node:fs";
35002
+ import fs20 from "node:fs";
34838
35003
 
34839
35004
  // src/files/index/paths.ts
34840
- import path20 from "node:path";
35005
+ import path21 from "node:path";
34841
35006
  import crypto2 from "node:crypto";
34842
35007
  function getIndexPathForCwd(resolvedCwd) {
34843
35008
  const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
34844
- return path20.join(INDEX_DIR, `.file-index-${hash}.json`);
35009
+ return path21.join(INDEX_DIR, `.file-index-${hash}.json`);
34845
35010
  }
34846
35011
 
34847
35012
  // src/files/index/write-index-file.ts
34848
35013
  function writeIndexFileSync(resolvedCwd, data) {
34849
35014
  const indexPath = getIndexPathForCwd(resolvedCwd);
34850
35015
  try {
34851
- if (!fs19.existsSync(INDEX_DIR)) fs19.mkdirSync(INDEX_DIR, { recursive: true });
34852
- fs19.writeFileSync(indexPath, JSON.stringify(data), "utf8");
35016
+ if (!fs20.existsSync(INDEX_DIR)) fs20.mkdirSync(INDEX_DIR, { recursive: true });
35017
+ fs20.writeFileSync(indexPath, JSON.stringify(data), "utf8");
34853
35018
  } catch (e) {
34854
35019
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
34855
35020
  }
@@ -34857,8 +35022,8 @@ function writeIndexFileSync(resolvedCwd, data) {
34857
35022
  async function writeIndexFileAsync(resolvedCwd, data) {
34858
35023
  const indexPath = getIndexPathForCwd(resolvedCwd);
34859
35024
  try {
34860
- await fs19.promises.mkdir(INDEX_DIR, { recursive: true });
34861
- await fs19.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
35025
+ await fs20.promises.mkdir(INDEX_DIR, { recursive: true });
35026
+ await fs20.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
34862
35027
  } catch (e) {
34863
35028
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
34864
35029
  }
@@ -34872,7 +35037,7 @@ function sortPaths(paths) {
34872
35037
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
34873
35038
  }
34874
35039
  function buildFileIndex(cwd) {
34875
- const resolved = path21.resolve(cwd);
35040
+ const resolved = path22.resolve(cwd);
34876
35041
  const paths = [];
34877
35042
  walkWorkspaceTreeSync(resolved, resolved, paths);
34878
35043
  sortPaths(paths);
@@ -34882,7 +35047,7 @@ function buildFileIndex(cwd) {
34882
35047
  return data;
34883
35048
  }
34884
35049
  async function buildFileIndexAsync(cwd) {
34885
- const resolved = path21.resolve(cwd);
35050
+ const resolved = path22.resolve(cwd);
34886
35051
  const paths = [];
34887
35052
  await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
34888
35053
  await yieldToEventLoop();
@@ -34894,13 +35059,13 @@ async function buildFileIndexAsync(cwd) {
34894
35059
  }
34895
35060
 
34896
35061
  // src/files/index/load-file-index.ts
34897
- import fs20 from "node:fs";
34898
- import path22 from "node:path";
35062
+ import fs21 from "node:fs";
35063
+ import path23 from "node:path";
34899
35064
  function loadFileIndex(cwd) {
34900
- const resolved = path22.resolve(cwd);
35065
+ const resolved = path23.resolve(cwd);
34901
35066
  const indexPath = getIndexPathForCwd(resolved);
34902
35067
  try {
34903
- const raw = fs20.readFileSync(indexPath, "utf8");
35068
+ const raw = fs21.readFileSync(indexPath, "utf8");
34904
35069
  const parsed = JSON.parse(raw);
34905
35070
  if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
34906
35071
  const obj = parsed;
@@ -34919,9 +35084,9 @@ function loadFileIndex(cwd) {
34919
35084
  }
34920
35085
 
34921
35086
  // src/files/index/ensure-file-index.ts
34922
- import path23 from "node:path";
35087
+ import path24 from "node:path";
34923
35088
  async function ensureFileIndexAsync(cwd) {
34924
- const resolved = path23.resolve(cwd);
35089
+ const resolved = path24.resolve(cwd);
34925
35090
  const cached2 = loadFileIndex(resolved);
34926
35091
  if (cached2 !== null) return { data: cached2, fromCache: true };
34927
35092
  const data = await buildFileIndexAsync(resolved);
@@ -35004,7 +35169,7 @@ function createFsWatcher(resolved, schedule) {
35004
35169
  }
35005
35170
  }
35006
35171
  function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
35007
- const resolved = path24.resolve(cwd);
35172
+ const resolved = path25.resolve(cwd);
35008
35173
  void buildFileIndexAsync(resolved).catch((e) => {
35009
35174
  console.error("[file-index] Initial index build failed:", e);
35010
35175
  });
@@ -35031,6 +35196,9 @@ function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
35031
35196
  };
35032
35197
  }
35033
35198
 
35199
+ // src/bridge/connection/create-bridge-connection.ts
35200
+ import * as path34 from "node:path";
35201
+
35034
35202
  // src/dev-servers/manager/dev-server-manager.ts
35035
35203
  import { rm as rm2 } from "node:fs/promises";
35036
35204
 
@@ -35051,15 +35219,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
35051
35219
 
35052
35220
  // src/dev-servers/process/terminate-child-process.ts
35053
35221
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
35054
- const exited = new Promise((resolve17) => {
35055
- proc.once("exit", () => resolve17());
35222
+ const exited = new Promise((resolve18) => {
35223
+ proc.once("exit", () => resolve18());
35056
35224
  });
35057
35225
  log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
35058
35226
  try {
35059
35227
  proc.kill("SIGTERM");
35060
35228
  } catch {
35061
35229
  }
35062
- await Promise.race([exited, new Promise((resolve17) => setTimeout(resolve17, graceMs))]);
35230
+ await Promise.race([exited, new Promise((resolve18) => setTimeout(resolve18, graceMs))]);
35063
35231
  }
35064
35232
  function forceKillChild(proc, log2, shortId, graceMs) {
35065
35233
  log2(
@@ -35073,7 +35241,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
35073
35241
  }
35074
35242
 
35075
35243
  // src/dev-servers/process/wire-dev-server-child-process.ts
35076
- import fs21 from "node:fs";
35244
+ import fs22 from "node:fs";
35077
35245
 
35078
35246
  // src/dev-servers/manager/forward-pipe.ts
35079
35247
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -35109,7 +35277,7 @@ function wireDevServerChildProcess(d) {
35109
35277
  d.setPollInterval(void 0);
35110
35278
  return;
35111
35279
  }
35112
- fs21.readFile(d.mergedLogPath, (err, buf) => {
35280
+ fs22.readFile(d.mergedLogPath, (err, buf) => {
35113
35281
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
35114
35282
  if (buf.length <= d.mergedReadPos.value) return;
35115
35283
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -35147,7 +35315,7 @@ ${errTail}` : ""}`);
35147
35315
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
35148
35316
  };
35149
35317
  if (mergedPath) {
35150
- fs21.readFile(mergedPath, (err, buf) => {
35318
+ fs22.readFile(mergedPath, (err, buf) => {
35151
35319
  if (!err && buf.length > d.mergedReadPos.value) {
35152
35320
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
35153
35321
  if (chunk.length > 0) {
@@ -35249,13 +35417,13 @@ function parseDevServerDefs(servers) {
35249
35417
  }
35250
35418
 
35251
35419
  // src/dev-servers/manager/shell-spawn/utils.ts
35252
- import fs22 from "node:fs";
35420
+ import fs23 from "node:fs";
35253
35421
  function isSpawnEbadf(e) {
35254
35422
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
35255
35423
  }
35256
35424
  function rmDirQuiet(dir) {
35257
35425
  try {
35258
- fs22.rmSync(dir, { recursive: true, force: true });
35426
+ fs23.rmSync(dir, { recursive: true, force: true });
35259
35427
  } catch {
35260
35428
  }
35261
35429
  }
@@ -35263,7 +35431,7 @@ var cachedDevNullReadFd;
35263
35431
  function devNullReadFd() {
35264
35432
  if (cachedDevNullReadFd === void 0) {
35265
35433
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
35266
- cachedDevNullReadFd = fs22.openSync(devPath, "r");
35434
+ cachedDevNullReadFd = fs23.openSync(devPath, "r");
35267
35435
  }
35268
35436
  return cachedDevNullReadFd;
35269
35437
  }
@@ -35337,15 +35505,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
35337
35505
 
35338
35506
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
35339
35507
  import { spawn as spawn6 } from "node:child_process";
35340
- import fs23 from "node:fs";
35508
+ import fs24 from "node:fs";
35341
35509
  import { tmpdir } from "node:os";
35342
- import path25 from "node:path";
35510
+ import path26 from "node:path";
35343
35511
  function trySpawnMergedLogFile(command, env, cwd, signal) {
35344
- const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir(), "ba-devsrv-log-"));
35345
- const logPath = path25.join(tmpRoot, "combined.log");
35512
+ const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir(), "ba-devsrv-log-"));
35513
+ const logPath = path26.join(tmpRoot, "combined.log");
35346
35514
  let logFd;
35347
35515
  try {
35348
- logFd = fs23.openSync(logPath, "a");
35516
+ logFd = fs24.openSync(logPath, "a");
35349
35517
  } catch {
35350
35518
  rmDirQuiet(tmpRoot);
35351
35519
  return null;
@@ -35364,7 +35532,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
35364
35532
  } else {
35365
35533
  proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
35366
35534
  }
35367
- fs23.closeSync(logFd);
35535
+ fs24.closeSync(logFd);
35368
35536
  return {
35369
35537
  proc,
35370
35538
  pipedStdoutStderr: true,
@@ -35373,7 +35541,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
35373
35541
  };
35374
35542
  } catch (e) {
35375
35543
  try {
35376
- fs23.closeSync(logFd);
35544
+ fs24.closeSync(logFd);
35377
35545
  } catch {
35378
35546
  }
35379
35547
  rmDirQuiet(tmpRoot);
@@ -35384,22 +35552,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
35384
35552
 
35385
35553
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
35386
35554
  import { spawn as spawn7 } from "node:child_process";
35387
- import fs24 from "node:fs";
35555
+ import fs25 from "node:fs";
35388
35556
  import { tmpdir as tmpdir2 } from "node:os";
35389
- import path26 from "node:path";
35557
+ import path27 from "node:path";
35390
35558
  function shSingleQuote(s) {
35391
35559
  return `'${s.replace(/'/g, `'\\''`)}'`;
35392
35560
  }
35393
35561
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
35394
- const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
35395
- const logPath = path26.join(tmpRoot, "combined.log");
35396
- const innerPath = path26.join(tmpRoot, "_cmd.sh");
35397
- const runnerPath = path26.join(tmpRoot, "_run.sh");
35562
+ const tmpRoot = fs25.mkdtempSync(path27.join(tmpdir2(), "ba-devsrv-sh-"));
35563
+ const logPath = path27.join(tmpRoot, "combined.log");
35564
+ const innerPath = path27.join(tmpRoot, "_cmd.sh");
35565
+ const runnerPath = path27.join(tmpRoot, "_run.sh");
35398
35566
  try {
35399
- fs24.writeFileSync(innerPath, `#!/bin/sh
35567
+ fs25.writeFileSync(innerPath, `#!/bin/sh
35400
35568
  ${command}
35401
35569
  `);
35402
- fs24.writeFileSync(
35570
+ fs25.writeFileSync(
35403
35571
  runnerPath,
35404
35572
  `#!/bin/sh
35405
35573
  cd ${shSingleQuote(cwd)}
@@ -35425,13 +35593,13 @@ cd ${shSingleQuote(cwd)}
35425
35593
  }
35426
35594
  }
35427
35595
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
35428
- const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
35429
- const logPath = path26.join(tmpRoot, "combined.log");
35430
- const runnerPath = path26.join(tmpRoot, "_run.bat");
35596
+ const tmpRoot = fs25.mkdtempSync(path27.join(tmpdir2(), "ba-devsrv-sh-"));
35597
+ const logPath = path27.join(tmpRoot, "combined.log");
35598
+ const runnerPath = path27.join(tmpRoot, "_run.bat");
35431
35599
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
35432
35600
  const com = process.env.ComSpec || "cmd.exe";
35433
35601
  try {
35434
- fs24.writeFileSync(
35602
+ fs25.writeFileSync(
35435
35603
  runnerPath,
35436
35604
  `@ECHO OFF\r
35437
35605
  CD /D ${q(cwd)}\r
@@ -35942,7 +36110,7 @@ async function proxyToLocal(request) {
35942
36110
  };
35943
36111
  const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
35944
36112
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
35945
- const once = await new Promise((resolve17) => {
36113
+ const once = await new Promise((resolve18) => {
35946
36114
  const req = mod.request(opts, (res) => {
35947
36115
  const chunks = [];
35948
36116
  res.on("data", (c) => chunks.push(c));
@@ -35953,7 +36121,7 @@ async function proxyToLocal(request) {
35953
36121
  if (typeof v === "string") headers[k] = v;
35954
36122
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
35955
36123
  }
35956
- resolve17({
36124
+ resolve18({
35957
36125
  id: request.id,
35958
36126
  statusCode: res.statusCode ?? 0,
35959
36127
  headers,
@@ -35962,7 +36130,7 @@ async function proxyToLocal(request) {
35962
36130
  });
35963
36131
  });
35964
36132
  req.on("error", (err) => {
35965
- resolve17({
36133
+ resolve18({
35966
36134
  id: request.id,
35967
36135
  statusCode: 0,
35968
36136
  headers: {},
@@ -36301,10 +36469,9 @@ function attachFirehoseAfterIdentified(ctx, params) {
36301
36469
 
36302
36470
  // src/bridge/connection/create-bridge-identified-handler.ts
36303
36471
  function createOnBridgeIdentified(opts) {
36304
- const { sessionWorktreeManager, devServerManager, firehoseServerUrl, workspaceId, state, logFn } = opts;
36472
+ const { devServerManager, firehoseServerUrl, workspaceId, state, logFn } = opts;
36305
36473
  const firehoseCtx = { state, devServerManager, logFn };
36306
36474
  return (msg) => {
36307
- sessionWorktreeManager.setBridgeSessionWorktrees(msg.sessionWorktreesEnabled === true);
36308
36475
  const bridgeName = msg.bridgeName;
36309
36476
  const proxyPorts = Array.isArray(msg.proxyPorts) ? msg.proxyPorts : [];
36310
36477
  const devServers = msg.devServers ?? [];
@@ -36323,30 +36490,30 @@ function createOnBridgeIdentified(opts) {
36323
36490
  }
36324
36491
 
36325
36492
  // src/skills/discover-local-agent-skills.ts
36326
- import fs25 from "node:fs";
36327
- import path27 from "node:path";
36493
+ import fs26 from "node:fs";
36494
+ import path28 from "node:path";
36328
36495
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
36329
36496
  function discoverLocalSkills(cwd) {
36330
36497
  const out = [];
36331
36498
  const seenKeys = /* @__PURE__ */ new Set();
36332
36499
  for (const rel of SKILL_DISCOVERY_ROOTS) {
36333
- const base = path27.join(cwd, rel);
36334
- if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
36500
+ const base = path28.join(cwd, rel);
36501
+ if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
36335
36502
  let entries = [];
36336
36503
  try {
36337
- entries = fs25.readdirSync(base);
36504
+ entries = fs26.readdirSync(base);
36338
36505
  } catch {
36339
36506
  continue;
36340
36507
  }
36341
36508
  for (const name of entries) {
36342
- const dir = path27.join(base, name);
36509
+ const dir = path28.join(base, name);
36343
36510
  try {
36344
- if (!fs25.statSync(dir).isDirectory()) continue;
36511
+ if (!fs26.statSync(dir).isDirectory()) continue;
36345
36512
  } catch {
36346
36513
  continue;
36347
36514
  }
36348
- const skillMd = path27.join(dir, "SKILL.md");
36349
- if (!fs25.existsSync(skillMd)) continue;
36515
+ const skillMd = path28.join(dir, "SKILL.md");
36516
+ if (!fs26.existsSync(skillMd)) continue;
36350
36517
  const key = `${rel}/${name}`;
36351
36518
  if (seenKeys.has(key)) continue;
36352
36519
  seenKeys.add(key);
@@ -36358,23 +36525,23 @@ function discoverLocalSkills(cwd) {
36358
36525
  function discoverSkillLayoutRoots(cwd) {
36359
36526
  const roots = [];
36360
36527
  for (const rel of SKILL_DISCOVERY_ROOTS) {
36361
- const base = path27.join(cwd, rel);
36362
- if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
36528
+ const base = path28.join(cwd, rel);
36529
+ if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
36363
36530
  let entries = [];
36364
36531
  try {
36365
- entries = fs25.readdirSync(base);
36532
+ entries = fs26.readdirSync(base);
36366
36533
  } catch {
36367
36534
  continue;
36368
36535
  }
36369
36536
  const skills2 = [];
36370
36537
  for (const name of entries) {
36371
- const dir = path27.join(base, name);
36538
+ const dir = path28.join(base, name);
36372
36539
  try {
36373
- if (!fs25.statSync(dir).isDirectory()) continue;
36540
+ if (!fs26.statSync(dir).isDirectory()) continue;
36374
36541
  } catch {
36375
36542
  continue;
36376
36543
  }
36377
- if (!fs25.existsSync(path27.join(dir, "SKILL.md"))) continue;
36544
+ if (!fs26.existsSync(path28.join(dir, "SKILL.md"))) continue;
36378
36545
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
36379
36546
  skills2.push({ name, relPath });
36380
36547
  }
@@ -36419,7 +36586,7 @@ function createSendLocalSkillsReport(getWs, logFn) {
36419
36586
  const socket = getWs();
36420
36587
  if (!socket || socket.readyState !== wrapper_default.OPEN) return;
36421
36588
  const skills2 = discoverLocalSkills(getBridgeWorkspaceDirectory());
36422
- socket.send(JSON.stringify({ type: "local_skills", skills: skills2 }));
36589
+ sendWsMessage(socket, { type: "local_skills", skills: skills2 });
36423
36590
  } catch (e) {
36424
36591
  logFn(
36425
36592
  `[Bridge service] Local skills report failed: ${e instanceof Error ? e.message : String(e)}`
@@ -36472,6 +36639,42 @@ function reportGitRepos(getWs, log2) {
36472
36639
  });
36473
36640
  }
36474
36641
 
36642
+ // src/types/api-to-bridge-messages.ts
36643
+ var API_TO_BRIDGE_MESSAGE_TYPES = [
36644
+ "auth_token",
36645
+ "bridge_identified",
36646
+ "dev_servers_config",
36647
+ "server_control",
36648
+ "agent_config",
36649
+ "prompt_queue_state",
36650
+ "prompt",
36651
+ "session_git_request",
36652
+ "rename_session_branch",
36653
+ "session_archived",
36654
+ "session_discarded",
36655
+ "revert_turn_snapshot",
36656
+ "cancel_run",
36657
+ "cursor_request_response",
36658
+ "skill_call",
36659
+ "file_browser_request",
36660
+ "file_browser_search",
36661
+ "skill_layout_request",
36662
+ "install_skills",
36663
+ "refresh_local_skills"
36664
+ ];
36665
+ var API_TO_BRIDGE_TYPE_SET = new Set(API_TO_BRIDGE_MESSAGE_TYPES);
36666
+ function parseApiToBridgeMessage(data, log2) {
36667
+ if (data === null || typeof data !== "object" || Array.isArray(data)) return null;
36668
+ const t = data.type;
36669
+ if (typeof t !== "string" || !API_TO_BRIDGE_TYPE_SET.has(t)) {
36670
+ if (typeof t === "string") {
36671
+ log2?.(`[Bridge service] unhandled message type: ${t}`);
36672
+ }
36673
+ return null;
36674
+ }
36675
+ return data;
36676
+ }
36677
+
36475
36678
  // src/bridge/routing/handlers/auth-token.ts
36476
36679
  var handleAuthToken = (msg, { log: log2 }) => {
36477
36680
  if (typeof msg.token !== "string") return;
@@ -36482,9 +36685,11 @@ var handleAuthToken = (msg, { log: log2 }) => {
36482
36685
  // src/bridge/routing/handlers/bridge-identified.ts
36483
36686
  var handleBridgeIdentified = (msg, deps) => {
36484
36687
  if (typeof msg.bridgeName !== "string") return;
36485
- deps.onBridgeIdentified(
36486
- msg
36487
- );
36688
+ deps.onBridgeIdentified({
36689
+ bridgeName: msg.bridgeName,
36690
+ proxyPorts: msg.proxyPorts,
36691
+ devServers: msg.devServers
36692
+ });
36488
36693
  setImmediate(() => {
36489
36694
  void (async () => {
36490
36695
  try {
@@ -36519,7 +36724,174 @@ var handleAgentConfigMessage = (msg, deps) => {
36519
36724
  };
36520
36725
 
36521
36726
  // src/agents/acp/from-bridge/handle-bridge-prompt.ts
36522
- import * as path29 from "node:path";
36727
+ import * as path30 from "node:path";
36728
+
36729
+ // src/prompt-turn-queue/client-report.ts
36730
+ function sendPromptQueueClientReport(ws, queues) {
36731
+ if (!ws) return false;
36732
+ sendWsMessage(ws, { type: "prompt_queue_client_report", queues });
36733
+ return true;
36734
+ }
36735
+
36736
+ // src/prompt-turn-queue/disk-store.ts
36737
+ import fs28 from "node:fs";
36738
+
36739
+ // src/prompt-turn-queue/paths.ts
36740
+ import crypto3 from "node:crypto";
36741
+ import fs27 from "node:fs";
36742
+ import path29 from "node:path";
36743
+ import os6 from "node:os";
36744
+ var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
36745
+ function queueStateFileSlug(queueKey) {
36746
+ if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
36747
+ return crypto3.createHash("sha256").update(queueKey, "utf8").digest("hex");
36748
+ }
36749
+ function getPromptQueuesDirectory() {
36750
+ const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
36751
+ if (override) return path29.resolve(override);
36752
+ return path29.join(os6.homedir(), ".buildautomaton", "queues");
36753
+ }
36754
+ function ensurePromptQueuesDirectory() {
36755
+ const dir = getPromptQueuesDirectory();
36756
+ if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
36757
+ }
36758
+ function queueStateFilePath(queueKey) {
36759
+ return path29.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
36760
+ }
36761
+
36762
+ // src/prompt-turn-queue/disk-store.ts
36763
+ function parsePersistedQueueFile(raw) {
36764
+ try {
36765
+ const o = JSON.parse(raw);
36766
+ const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
36767
+ if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
36768
+ return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
36769
+ } catch {
36770
+ return null;
36771
+ }
36772
+ }
36773
+ function readPersistedQueue(queueKey) {
36774
+ const p = queueStateFilePath(queueKey);
36775
+ try {
36776
+ return parsePersistedQueueFile(fs28.readFileSync(p, "utf8"));
36777
+ } catch {
36778
+ return null;
36779
+ }
36780
+ }
36781
+ function writePersistedQueue(file2) {
36782
+ ensurePromptQueuesDirectory();
36783
+ const p = queueStateFilePath(file2.queueKey);
36784
+ fs28.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
36785
+ }
36786
+ function mergeServerQueueSnapshot(queueKey, serverTurns) {
36787
+ const prev = readPersistedQueue(queueKey);
36788
+ const turns = [];
36789
+ for (const raw of serverTurns) {
36790
+ if (!raw || typeof raw !== "object") continue;
36791
+ const o = raw;
36792
+ const turnId = typeof o.turnId === "string" ? o.turnId : "";
36793
+ const sessionId = typeof o.sessionId === "string" ? o.sessionId : "";
36794
+ const turnOrd = typeof o.turnOrd === "number" ? o.turnOrd : Number(o.turnOrd) || 0;
36795
+ const serverState = o.serverState;
36796
+ const lastClientState = o.lastClientState ?? null;
36797
+ const payload = o.payload && typeof o.payload === "object" ? o.payload : {};
36798
+ if (!turnId || !sessionId) continue;
36799
+ if (serverState !== "queued" && serverState !== "stopping" && serverState !== "discarded") continue;
36800
+ const old = prev?.turns.find((t) => t.turnId === turnId);
36801
+ const mergedClient = old?.lastClientState === "running" && lastClientState == null ? "running" : lastClientState;
36802
+ turns.push({
36803
+ turnId,
36804
+ sessionId,
36805
+ turnOrd,
36806
+ serverState,
36807
+ lastClientState: mergedClient,
36808
+ payload
36809
+ });
36810
+ }
36811
+ turns.sort((a, b) => a.turnOrd - b.turnOrd);
36812
+ return { queueKey, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), turns };
36813
+ }
36814
+
36815
+ // src/prompt-turn-queue/runner.ts
36816
+ var runIdToQueueKey = /* @__PURE__ */ new Map();
36817
+ function pickNextRunnableTurn(turns) {
36818
+ for (const t of turns) {
36819
+ if (t.serverState === "discarded" || t.serverState === "stopping") continue;
36820
+ if (t.serverState !== "queued") continue;
36821
+ if (t.lastClientState === "running" || t.lastClientState === "stopped" || t.lastClientState === "failed") continue;
36822
+ return t;
36823
+ }
36824
+ return null;
36825
+ }
36826
+ function hasRunningTurn(turns) {
36827
+ return turns.some((t) => t.lastClientState === "running");
36828
+ }
36829
+ function dispatchLocalPrompt(next, deps) {
36830
+ const pl = next.payload;
36831
+ const msg = {
36832
+ type: "prompt",
36833
+ sessionId: next.sessionId,
36834
+ runId: next.turnId,
36835
+ prompt: pl.prompt,
36836
+ mode: typeof pl.mode === "string" ? pl.mode : "agent",
36837
+ isNewSession: pl.isNewSession === true,
36838
+ ...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
36839
+ ...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
36840
+ ...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
36841
+ ...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {}
36842
+ };
36843
+ handleBridgePrompt(msg, deps);
36844
+ }
36845
+ function applyPromptQueueStateFromServer(msg, deps) {
36846
+ const raw = msg.queues;
36847
+ if (!raw || typeof raw !== "object") return;
36848
+ const getWs = deps.getWs;
36849
+ for (const [queueKey, serverTurns] of Object.entries(raw)) {
36850
+ if (!Array.isArray(serverTurns)) continue;
36851
+ const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
36852
+ writePersistedQueue(file2);
36853
+ }
36854
+ const report = {};
36855
+ const startedThisTick = /* @__PURE__ */ new Set();
36856
+ for (const [queueKey, serverTurns] of Object.entries(raw)) {
36857
+ if (!Array.isArray(serverTurns)) continue;
36858
+ const file2 = readPersistedQueue(queueKey);
36859
+ if (!file2) continue;
36860
+ if (hasRunningTurn(file2.turns)) continue;
36861
+ const next = pickNextRunnableTurn(file2.turns);
36862
+ if (!next) continue;
36863
+ next.lastClientState = "running";
36864
+ writePersistedQueue(file2);
36865
+ runIdToQueueKey.set(next.turnId, queueKey);
36866
+ startedThisTick.add(next.turnId);
36867
+ report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
36868
+ }
36869
+ if (Object.keys(report).length > 0) {
36870
+ sendPromptQueueClientReport(getWs(), report);
36871
+ }
36872
+ for (const [queueKey, serverTurns] of Object.entries(raw)) {
36873
+ if (!Array.isArray(serverTurns)) continue;
36874
+ const file2 = readPersistedQueue(queueKey);
36875
+ if (!file2) continue;
36876
+ const running = file2.turns.find((t) => t.lastClientState === "running");
36877
+ if (!running || !startedThisTick.has(running.turnId)) continue;
36878
+ if (runIdToQueueKey.get(running.turnId) !== queueKey) continue;
36879
+ dispatchLocalPrompt(running, deps);
36880
+ }
36881
+ }
36882
+ function finalizePromptTurnOnBridge(getWs, runId, success2) {
36883
+ if (!runId) return;
36884
+ const queueKey = runIdToQueueKey.get(runId);
36885
+ runIdToQueueKey.delete(runId);
36886
+ if (!queueKey) return;
36887
+ const f = readPersistedQueue(queueKey);
36888
+ if (!f) return;
36889
+ const t = f.turns.find((x) => x.turnId === runId);
36890
+ if (!t) return;
36891
+ t.lastClientState = success2 ? "stopped" : "failed";
36892
+ writePersistedQueue(f);
36893
+ sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
36894
+ }
36523
36895
 
36524
36896
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
36525
36897
  function createBridgePromptSenders(deps, getWs) {
@@ -36534,6 +36906,9 @@ function createBridgePromptSenders(deps, getWs) {
36534
36906
  const skipEncryptForChangeSummaryFollowUp = result.type === "prompt_result" && result.followUpCatalogPromptId === BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID;
36535
36907
  const encryptedFields = result.type === "prompt_result" && !skipEncryptForChangeSummaryFollowUp ? ["output", "error"] : [];
36536
36908
  sendBridgeMessage(result, encryptedFields);
36909
+ if (result.type === "prompt_result") {
36910
+ finalizePromptTurnOnBridge(getWs, typeof result.runId === "string" ? result.runId : void 0, result.success === true);
36911
+ }
36537
36912
  };
36538
36913
  const sendSessionUpdate = (payload) => {
36539
36914
  const s = getWs();
@@ -36558,63 +36933,6 @@ function createBridgePromptSenders(deps, getWs) {
36558
36933
  // src/agents/acp/from-bridge/bridge-prompt-preamble.ts
36559
36934
  import { execFile as execFile10 } from "node:child_process";
36560
36935
  import { promisify as promisify10 } from "node:util";
36561
-
36562
- // src/git/bridge-queue-key.ts
36563
- import * as path28 from "node:path";
36564
- import { createHash as createHash2 } from "node:crypto";
36565
- function normalizeCanonicalGitUrl(url2) {
36566
- let s = url2.trim();
36567
- if (!s) return s;
36568
- if (s.toLowerCase().endsWith(".git")) {
36569
- s = s.slice(0, -4);
36570
- }
36571
- s = s.replace(/\/+$/, "");
36572
- const httpsMatch = /^(https?):\/\/([^/]+)(\/.*)?$/i.exec(s);
36573
- if (httpsMatch) {
36574
- const host = httpsMatch[2].toLowerCase();
36575
- const p = httpsMatch[3] ?? "";
36576
- s = `${httpsMatch[1].toLowerCase()}://${host}${p}`;
36577
- } else {
36578
- const sshMatch = /^git@([^:]+):(.+)$/i.exec(s);
36579
- if (sshMatch) {
36580
- const host = sshMatch[1].toLowerCase();
36581
- s = `git@${host}:${sshMatch[2]}`;
36582
- }
36583
- }
36584
- return s;
36585
- }
36586
- function canonicalUrlToRepoIdSync(url2) {
36587
- const normalized = normalizeCanonicalGitUrl(url2);
36588
- return createHash2("sha256").update(normalized).digest("hex").slice(0, 32);
36589
- }
36590
- function fallbackRepoIdFromPath(absPath) {
36591
- return createHash2("sha256").update(path28.resolve(absPath)).digest("hex").slice(0, 32);
36592
- }
36593
- async function resolveBridgeQueueBindFields(options) {
36594
- const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
36595
- const cwdAbs = worktreePaths.length > 0 ? path28.resolve(worktreePaths[0]) : path28.resolve(effectiveCwd);
36596
- if (!primaryRepoRoots.length) {
36597
- log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
36598
- return null;
36599
- }
36600
- let primaryRoot = primaryRepoRoots[0];
36601
- let remote = await getRemoteOriginUrl(primaryRoot);
36602
- if (!remote) {
36603
- for (const r of primaryRepoRoots.slice(1)) {
36604
- const u = await getRemoteOriginUrl(r);
36605
- if (u) {
36606
- primaryRoot = r;
36607
- remote = u;
36608
- break;
36609
- }
36610
- }
36611
- }
36612
- const repoId = remote ? canonicalUrlToRepoIdSync(remote) : fallbackRepoIdFromPath(primaryRoot);
36613
- const canonicalQueueKey = `repo:${repoId}::cwd:${cwdAbs}`;
36614
- return { canonicalQueueKey, repoId, cwdAbs };
36615
- }
36616
-
36617
- // src/agents/acp/from-bridge/bridge-prompt-preamble.ts
36618
36936
  var execFileAsync9 = promisify10(execFile10);
36619
36937
  async function readGitBranch(cwd) {
36620
36938
  try {
@@ -36634,30 +36952,17 @@ async function runBridgePromptPreamble(params) {
36634
36952
  fallbackCwd: effectiveCwd,
36635
36953
  log: log2
36636
36954
  });
36637
- if (s && sessionId) {
36638
- const bind = await resolveBridgeQueueBindFields({
36639
- effectiveCwd,
36640
- worktreePaths,
36641
- primaryRepoRoots: repoRoots,
36642
- log: log2
36643
- });
36644
- if (bind) {
36645
- sendWsMessage(s, {
36646
- type: "bridge_queue_bind",
36647
- sessionId,
36648
- canonicalQueueKey: bind.canonicalQueueKey,
36649
- repoId: bind.repoId,
36650
- cwdAbs: bind.cwdAbs
36651
- });
36652
- }
36653
- }
36654
36955
  if (s && sessionId) {
36655
36956
  const cliGitBranch = await readGitBranch(effectiveCwd);
36957
+ const usesWt = sessionWorktreeManager.usesWorktreeSession(sessionId);
36958
+ const mirrorAbs = sessionWorktreeManager.getAgentCwdForSession(sessionId);
36656
36959
  sendWsMessage(s, {
36657
36960
  type: "session_git_context_report",
36658
36961
  sessionId,
36659
36962
  cliGitBranch,
36660
- agentUsesWorktree: sessionWorktreeManager.usesWorktreeSession(sessionId)
36963
+ agentUsesWorktree: usesWt,
36964
+ sessionParent: usesWt ? "worktrees_root" : "bridge_root",
36965
+ sessionParentPath: usesWt ? mirrorAbs : getBridgeWorkspaceDirectory()
36661
36966
  });
36662
36967
  }
36663
36968
  if (s && sessionId && runId) {
@@ -36676,9 +36981,9 @@ function parseChangeSummarySnapshots(raw) {
36676
36981
  for (const item of raw) {
36677
36982
  if (!item || typeof item !== "object") continue;
36678
36983
  const o = item;
36679
- const path34 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
36680
- if (!path34) continue;
36681
- const row = { path: path34 };
36984
+ const path36 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
36985
+ if (!path36) continue;
36986
+ const row = { path: path36 };
36682
36987
  if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
36683
36988
  if (typeof o.oldText === "string") row.oldText = o.oldText;
36684
36989
  if (typeof o.newText === "string") row.newText = o.newText;
@@ -36777,12 +37082,14 @@ function handleBridgePrompt(msg, deps) {
36777
37082
  return;
36778
37083
  }
36779
37084
  const isNewSession = msg.isNewSession === true;
36780
- const sessionWorktreesEnabled = msg.sessionWorktreesEnabled === true;
37085
+ const rawParent = msg.sessionParent;
37086
+ const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : rawParent === "session_worktrees_root" ? "worktrees_root" : null;
37087
+ const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
36781
37088
  const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
36782
37089
  const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
36783
37090
  acpManager.logPromptReceivedFromBridge({ agentType, mode });
36784
37091
  async function preambleAndPrompt(resolvedCwd) {
36785
- const effectiveCwd = path29.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
37092
+ const effectiveCwd = path30.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
36786
37093
  await runBridgePromptPreamble({
36787
37094
  getWs,
36788
37095
  log: log2,
@@ -36825,7 +37132,7 @@ function handleBridgePrompt(msg, deps) {
36825
37132
  e2ee: deps.e2ee
36826
37133
  });
36827
37134
  }
36828
- void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionWorktreesEnabled }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
37135
+ void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionParent, sessionParentPath }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
36829
37136
  log2(`[Agent] Worktree resolve failed: ${err instanceof Error ? err.message : String(err)}`);
36830
37137
  void preambleAndPrompt(void 0);
36831
37138
  });
@@ -36836,6 +37143,11 @@ var handlePromptMessage = (msg, deps) => {
36836
37143
  handleBridgePrompt(msg, deps);
36837
37144
  };
36838
37145
 
37146
+ // src/bridge/routing/handlers/prompt-queue-state.ts
37147
+ var handlePromptQueueStateMessage = (msg, deps) => {
37148
+ applyPromptQueueStateFromServer(msg, deps);
37149
+ };
37150
+
36839
37151
  // src/agents/acp/from-bridge/handle-bridge-cancel-run.ts
36840
37152
  async function handleBridgeCancelRun(msg, { log: log2, acpManager, getWs }) {
36841
37153
  const runId = msg.runId;
@@ -36855,6 +37167,7 @@ async function handleBridgeCancelRun(msg, { log: log2, acpManager, getWs }) {
36855
37167
  error: "Stopped by user",
36856
37168
  stopReason: "no_local_run"
36857
37169
  });
37170
+ finalizePromptTurnOnBridge(getWs, runId, false);
36858
37171
  }
36859
37172
 
36860
37173
  // src/bridge/routing/handlers/cancel-run.ts
@@ -36894,8 +37207,8 @@ function randomSecret() {
36894
37207
  }
36895
37208
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
36896
37209
  }
36897
- async function requestPreviewApi(port, secret, method, path34, body) {
36898
- const url2 = `http://127.0.0.1:${port}${path34}`;
37210
+ async function requestPreviewApi(port, secret, method, path36, body) {
37211
+ const url2 = `http://127.0.0.1:${port}${path36}`;
36899
37212
  const headers = {
36900
37213
  [PREVIEW_SECRET_HEADER]: secret,
36901
37214
  "Content-Type": "application/json"
@@ -36907,7 +37220,7 @@ async function requestPreviewApi(port, secret, method, path34, body) {
36907
37220
  });
36908
37221
  const data = await res.json().catch(() => ({}));
36909
37222
  if (!res.ok) {
36910
- throw new Error(data?.error ?? `Preview API ${method} ${path34}: ${res.status}`);
37223
+ throw new Error(data?.error ?? `Preview API ${method} ${path36}: ${res.status}`);
36911
37224
  }
36912
37225
  return data;
36913
37226
  }
@@ -37059,26 +37372,28 @@ function handleSkillCall(msg, socket, log2) {
37059
37372
 
37060
37373
  // src/bridge/routing/handlers/skill-call.ts
37061
37374
  var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
37062
- if (!msg.skillId || msg.operationId === void 0) return;
37375
+ const skillId = typeof msg.skillId === "string" ? msg.skillId : "";
37376
+ const operationId = typeof msg.operationId === "string" ? msg.operationId : "";
37377
+ if (!skillId || !operationId) return;
37063
37378
  const socket = getWs();
37064
37379
  if (!socket) return;
37065
37380
  handleSkillCall(
37066
- msg,
37381
+ { id: msg.id, skillId, operationId, params: msg.params },
37067
37382
  socket,
37068
37383
  log2
37069
37384
  );
37070
37385
  };
37071
37386
 
37072
37387
  // src/files/list-dir.ts
37073
- import fs26 from "node:fs";
37074
- import path31 from "node:path";
37388
+ import fs29 from "node:fs";
37389
+ import path32 from "node:path";
37075
37390
 
37076
37391
  // src/files/ensure-under-cwd.ts
37077
- import path30 from "node:path";
37392
+ import path31 from "node:path";
37078
37393
  function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
37079
- const normalized = path30.normalize(relativePath).replace(/^(\.\/)+/, "");
37080
- const resolved = path30.resolve(cwd, normalized);
37081
- if (!resolved.startsWith(cwd + path30.sep) && resolved !== cwd) {
37394
+ const normalized = path31.normalize(relativePath).replace(/^(\.\/)+/, "");
37395
+ const resolved = path31.resolve(cwd, normalized);
37396
+ if (!resolved.startsWith(cwd + path31.sep) && resolved !== cwd) {
37082
37397
  return null;
37083
37398
  }
37084
37399
  return resolved;
@@ -37092,7 +37407,7 @@ async function listDirAsync(relativePath) {
37092
37407
  return { error: "Path is outside working directory" };
37093
37408
  }
37094
37409
  try {
37095
- const names = await fs26.promises.readdir(resolved, { withFileTypes: true });
37410
+ const names = await fs29.promises.readdir(resolved, { withFileTypes: true });
37096
37411
  const visible = names.filter((d) => !d.name.startsWith("."));
37097
37412
  const entries = [];
37098
37413
  for (let i = 0; i < visible.length; i++) {
@@ -37100,12 +37415,12 @@ async function listDirAsync(relativePath) {
37100
37415
  await yieldToEventLoop();
37101
37416
  }
37102
37417
  const d = visible[i];
37103
- const entryPath = path31.join(relativePath || ".", d.name).replace(/\\/g, "/");
37104
- const fullPath = path31.join(resolved, d.name);
37418
+ const entryPath = path32.join(relativePath || ".", d.name).replace(/\\/g, "/");
37419
+ const fullPath = path32.join(resolved, d.name);
37105
37420
  let isDir = d.isDirectory();
37106
37421
  if (d.isSymbolicLink()) {
37107
37422
  try {
37108
- const targetStat = await fs26.promises.stat(fullPath);
37423
+ const targetStat = await fs29.promises.stat(fullPath);
37109
37424
  isDir = targetStat.isDirectory();
37110
37425
  } catch {
37111
37426
  isDir = false;
@@ -37130,25 +37445,25 @@ async function listDirAsync(relativePath) {
37130
37445
  }
37131
37446
 
37132
37447
  // src/files/read-file.ts
37133
- import fs27 from "node:fs";
37448
+ import fs30 from "node:fs";
37134
37449
  import { StringDecoder } from "node:string_decoder";
37135
37450
  function resolveFilePath(relativePath) {
37136
37451
  const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
37137
37452
  if (!resolved) return { error: "Path is outside working directory" };
37138
37453
  let real;
37139
37454
  try {
37140
- real = fs27.realpathSync(resolved);
37455
+ real = fs30.realpathSync(resolved);
37141
37456
  } catch {
37142
37457
  real = resolved;
37143
37458
  }
37144
- const stat3 = fs27.statSync(real);
37459
+ const stat3 = fs30.statSync(real);
37145
37460
  if (!stat3.isFile()) return { error: "Not a file" };
37146
37461
  return real;
37147
37462
  }
37148
37463
  var LINE_CHUNK_SIZE = 64 * 1024;
37149
37464
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
37150
- const fileSize = fs27.statSync(filePath).size;
37151
- const fd = fs27.openSync(filePath, "r");
37465
+ const fileSize = fs30.statSync(filePath).size;
37466
+ const fd = fs30.openSync(filePath, "r");
37152
37467
  const bufSize = 64 * 1024;
37153
37468
  const buf = Buffer.alloc(bufSize);
37154
37469
  const decoder = new StringDecoder("utf8");
@@ -37161,7 +37476,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
37161
37476
  let line0Accum = "";
37162
37477
  try {
37163
37478
  let bytesRead;
37164
- while (!done && (bytesRead = fs27.readSync(fd, buf, 0, bufSize, null)) > 0) {
37479
+ while (!done && (bytesRead = fs30.readSync(fd, buf, 0, bufSize, null)) > 0) {
37165
37480
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
37166
37481
  partial2 = "";
37167
37482
  let lineStart = 0;
@@ -37296,7 +37611,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
37296
37611
  }
37297
37612
  return { content: resultLines.join("\n"), size: fileSize };
37298
37613
  } finally {
37299
- fs27.closeSync(fd);
37614
+ fs30.closeSync(fd);
37300
37615
  }
37301
37616
  }
37302
37617
  function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
@@ -37307,8 +37622,8 @@ function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize =
37307
37622
  if (hasRange) {
37308
37623
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
37309
37624
  }
37310
- const stat3 = fs27.statSync(result);
37311
- const raw = fs27.readFileSync(result, "utf8");
37625
+ const stat3 = fs30.statSync(result);
37626
+ const raw = fs30.readFileSync(result, "utf8");
37312
37627
  const lines = raw.split(/\r?\n/);
37313
37628
  return { content: raw, totalLines: lines.length, size: stat3.size };
37314
37629
  } catch (err) {
@@ -37420,12 +37735,14 @@ function handleSkillLayoutRequest(msg, deps) {
37420
37735
  const socket = deps.getWs();
37421
37736
  const id = typeof msg.id === "string" ? msg.id : "";
37422
37737
  const roots = discoverSkillLayoutRoots(getBridgeWorkspaceDirectory());
37423
- socket?.send(JSON.stringify({ type: "skill_layout_response", id, roots }));
37738
+ if (socket) {
37739
+ sendWsMessage(socket, { type: "skill_layout_response", id, roots });
37740
+ }
37424
37741
  }
37425
37742
 
37426
37743
  // src/skills/install-remote-skills.ts
37427
- import fs28 from "node:fs";
37428
- import path32 from "node:path";
37744
+ import fs31 from "node:fs";
37745
+ import path33 from "node:path";
37429
37746
  function installRemoteSkills(cwd, targetDir, items) {
37430
37747
  const installed2 = [];
37431
37748
  if (!Array.isArray(items)) {
@@ -37436,15 +37753,15 @@ function installRemoteSkills(cwd, targetDir, items) {
37436
37753
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
37437
37754
  continue;
37438
37755
  }
37439
- const skillDir = path32.join(cwd, targetDir, item.skillName);
37756
+ const skillDir = path33.join(cwd, targetDir, item.skillName);
37440
37757
  for (const f of item.files) {
37441
37758
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
37442
- const dest = path32.join(skillDir, f.path);
37443
- fs28.mkdirSync(path32.dirname(dest), { recursive: true });
37759
+ const dest = path33.join(skillDir, f.path);
37760
+ fs31.mkdirSync(path33.dirname(dest), { recursive: true });
37444
37761
  if (f.text !== void 0) {
37445
- fs28.writeFileSync(dest, f.text, "utf8");
37762
+ fs31.writeFileSync(dest, f.text, "utf8");
37446
37763
  } else if (f.base64) {
37447
- fs28.writeFileSync(dest, Buffer.from(f.base64, "base64"));
37764
+ fs31.writeFileSync(dest, Buffer.from(f.base64, "base64"));
37448
37765
  }
37449
37766
  }
37450
37767
  installed2.push({
@@ -37470,10 +37787,14 @@ var handleInstallSkillsMessage = (msg, deps) => {
37470
37787
  if (!result.success) {
37471
37788
  const err = result.error ?? "Invalid items";
37472
37789
  deps.log(`[Bridge service] Install skills failed: ${err}`);
37473
- socket?.send(JSON.stringify({ type: "install_skills_result", id, success: false, error: err }));
37790
+ if (socket) {
37791
+ sendWsMessage(socket, { type: "install_skills_result", id, success: false, error: err });
37792
+ }
37474
37793
  return;
37475
37794
  }
37476
- socket?.send(JSON.stringify({ type: "install_skills_result", id, success: true, installed: result.installed }));
37795
+ if (socket) {
37796
+ sendWsMessage(socket, { type: "install_skills_result", id, success: true, installed: result.installed });
37797
+ }
37477
37798
  };
37478
37799
 
37479
37800
  // src/bridge/routing/handlers/refresh-local-skills.ts
@@ -37590,7 +37911,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
37590
37911
  };
37591
37912
 
37592
37913
  // src/bridge/routing/handlers/revert-turn-snapshot.ts
37593
- import * as fs29 from "node:fs";
37914
+ import * as fs32 from "node:fs";
37594
37915
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
37595
37916
  const id = typeof msg.id === "string" ? msg.id : "";
37596
37917
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -37602,7 +37923,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
37602
37923
  if (!s) return;
37603
37924
  const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
37604
37925
  const file2 = snapshotFilePath(agentBase, turnId);
37605
- if (!fs29.existsSync(file2)) {
37926
+ if (!fs32.existsSync(file2)) {
37606
37927
  sendWsMessage(s, {
37607
37928
  type: "revert_turn_snapshot_result",
37608
37929
  id,
@@ -37623,7 +37944,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
37623
37944
 
37624
37945
  // src/bridge/routing/handlers/dev-server-control.ts
37625
37946
  var handleDevServerControl = (msg, deps) => {
37626
- let wire = msg;
37947
+ let wire;
37627
37948
  try {
37628
37949
  wire = deps.e2ee ? deps.e2ee.decryptMessage(msg) : msg;
37629
37950
  } catch (e) {
@@ -37644,9 +37965,7 @@ var handleDevServersConfig = (msg, deps) => {
37644
37965
 
37645
37966
  // src/bridge/routing/dispatch-bridge-message.ts
37646
37967
  function dispatchBridgeMessage(msg, deps) {
37647
- const type = msg.type;
37648
- if (typeof type !== "string") return;
37649
- switch (type) {
37968
+ switch (msg.type) {
37650
37969
  case "auth_token":
37651
37970
  handleAuthToken(msg, deps);
37652
37971
  break;
@@ -37662,6 +37981,9 @@ function dispatchBridgeMessage(msg, deps) {
37662
37981
  case "agent_config":
37663
37982
  handleAgentConfigMessage(msg, deps);
37664
37983
  break;
37984
+ case "prompt_queue_state":
37985
+ handlePromptQueueStateMessage(msg, deps);
37986
+ break;
37665
37987
  case "prompt":
37666
37988
  handlePromptMessage(msg, deps);
37667
37989
  break;
@@ -37704,15 +38026,14 @@ function dispatchBridgeMessage(msg, deps) {
37704
38026
  case "refresh_local_skills":
37705
38027
  handleRefreshLocalSkills(msg, deps);
37706
38028
  break;
37707
- default:
37708
- deps.log?.(`[Bridge service] unhandled message type: ${type}`);
37709
38029
  }
37710
38030
  }
37711
38031
 
37712
38032
  // src/bridge/routing/handle-bridge-message.ts
37713
38033
  function handleBridgeMessage(data, deps) {
37714
- const msg = data;
37715
38034
  if (!deps.getWs()) return;
38035
+ const msg = parseApiToBridgeMessage(data, deps.log);
38036
+ if (!msg) return;
37716
38037
  setImmediate(() => {
37717
38038
  dispatchBridgeMessage(msg, deps);
37718
38039
  });
@@ -37758,7 +38079,8 @@ function createMainBridgeWebSocketLifecycle(params) {
37758
38079
  tokens,
37759
38080
  persistTokens,
37760
38081
  onAuthInvalid,
37761
- e2ee
38082
+ e2ee,
38083
+ identifyReportedPaths
37762
38084
  } = params;
37763
38085
  let authRefreshInFlight = false;
37764
38086
  function handleOpen() {
@@ -37771,7 +38093,14 @@ function createMainBridgeWebSocketLifecycle(params) {
37771
38093
  }
37772
38094
  const socket = getWs();
37773
38095
  if (socket) {
37774
- sendWsMessage(socket, { type: "identify", role: "cli", ...e2ee ? { e: e2ee.handshake } : {} });
38096
+ sendWsMessage(socket, {
38097
+ type: "identify",
38098
+ role: "cli",
38099
+ cliVersion: CLI_VERSION,
38100
+ bridgeRootPath: identifyReportedPaths.bridgeRootPath,
38101
+ worktreesRootPath: identifyReportedPaths.worktreesRootPath,
38102
+ ...e2ee ? { e: e2ee.handshake } : {}
38103
+ });
37775
38104
  reportGitRepos(getWs, logFn);
37776
38105
  }
37777
38106
  if (justAuthenticated && socket) {
@@ -37897,7 +38226,6 @@ async function createBridgeConnection(options) {
37897
38226
  const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
37898
38227
  const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory, e2ee });
37899
38228
  const onBridgeIdentified = createOnBridgeIdentified({
37900
- sessionWorktreeManager,
37901
38229
  devServerManager,
37902
38230
  firehoseServerUrl,
37903
38231
  workspaceId,
@@ -37919,6 +38247,10 @@ async function createBridgeConnection(options) {
37919
38247
  cloudApiBaseUrl: apiUrl,
37920
38248
  getCloudAccessToken: () => tokens.accessToken
37921
38249
  };
38250
+ const identifyReportedPaths = {
38251
+ bridgeRootPath: path34.resolve(getBridgeWorkspaceDirectory()),
38252
+ worktreesRootPath: path34.resolve(worktreesRootAbs)
38253
+ };
37922
38254
  const { connect } = createMainBridgeWebSocketLifecycle({
37923
38255
  state,
37924
38256
  getWs,
@@ -37930,7 +38262,8 @@ async function createBridgeConnection(options) {
37930
38262
  tokens,
37931
38263
  persistTokens,
37932
38264
  onAuthInvalid,
37933
- e2ee
38265
+ e2ee,
38266
+ identifyReportedPaths
37934
38267
  });
37935
38268
  connect();
37936
38269
  const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
@@ -38148,9 +38481,9 @@ async function runCliAction(program2, opts) {
38148
38481
  let authToken = opts.token;
38149
38482
  const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
38150
38483
  if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
38151
- const resolvedCwd = path33.resolve(process.cwd(), opts.cwd.trim());
38484
+ const resolvedCwd = path35.resolve(process.cwd(), opts.cwd.trim());
38152
38485
  try {
38153
- const st = fs30.statSync(resolvedCwd);
38486
+ const st = fs33.statSync(resolvedCwd);
38154
38487
  if (!st.isDirectory()) {
38155
38488
  console.error(`--cwd is not a directory: ${resolvedCwd}`);
38156
38489
  process.exit(1);
@@ -38170,7 +38503,7 @@ async function runCliAction(program2, opts) {
38170
38503
  );
38171
38504
  let worktreesRootAbs;
38172
38505
  if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
38173
- worktreesRootAbs = path33.resolve(opts.worktreesRoot.trim());
38506
+ worktreesRootAbs = path35.resolve(opts.worktreesRoot.trim());
38174
38507
  }
38175
38508
  const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
38176
38509
  if (e2eCertificates) {
@@ -38213,7 +38546,7 @@ async function runCliAction(program2, opts) {
38213
38546
  // src/cli.ts
38214
38547
  async function main() {
38215
38548
  const program2 = new Command();
38216
- 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(
38549
+ program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version(CLI_VERSION).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(
38217
38550
  "--firehose-url <url>",
38218
38551
  "Firehose server URL (default: Fly app; or BUILDAUTOMATON_FIREHOSE_URL / legacy BUILDAUTOMATON_PROXY_URL)",
38219
38552
  process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL
@@ -38222,7 +38555,7 @@ async function main() {
38222
38555
  "Working directory for the bridge (absolute or relative to the current directory); affects skills, git, file index, and agent cwd"
38223
38556
  ).option("-n, --name <name>", "Bridge name when creating via browser (alphanumeric and underscores only)").option(
38224
38557
  "--worktrees-root <path>",
38225
- "Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees). Whether worktrees are used is controlled in the cloud for each bridge token."
38558
+ "Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees)."
38226
38559
  ).option(
38227
38560
  "--e2ee-certificates-dir <path>",
38228
38561
  "Directory to load or generate E2EE keys for sessions, files, and logs",