@buildautomaton/cli 0.1.24 → 0.1.25

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 path36 = __require("node:path");
977
- var fs35 = __require("node:fs");
976
+ var path37 = __require("node:path");
977
+ var fs36 = __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 = path36.resolve(baseDir, baseName);
1910
- if (fs35.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path36.extname(baseName))) return void 0;
1909
+ const localBin = path37.resolve(baseDir, baseName);
1910
+ if (fs36.existsSync(localBin)) return localBin;
1911
+ if (sourceExt.includes(path37.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
- (ext) => fs35.existsSync(`${localBin}${ext}`)
1913
+ (ext) => fs36.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 = fs35.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs36.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path36.resolve(
1930
- path36.dirname(resolvedScriptPath),
1929
+ executableDir = path37.resolve(
1930
+ path37.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 = path36.basename(
1937
+ const legacyName = path37.basename(
1938
1938
  this._scriptPath,
1939
- path36.extname(this._scriptPath)
1939
+ path37.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(path36.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path37.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 = path36.basename(filename, path36.extname(filename));
2790
+ this._name = path37.basename(filename, path37.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(path37) {
2805
- if (path37 === void 0) return this._executableDir;
2806
- this._executableDir = path37;
2804
+ executableDir(path38) {
2805
+ if (path38 === void 0) return this._executableDir;
2806
+ this._executableDir = path38;
2807
2807
  return this;
2808
2808
  }
2809
2809
  /**
@@ -7061,8 +7061,8 @@ var init_parseUtil = __esm({
7061
7061
  init_errors();
7062
7062
  init_en();
7063
7063
  makeIssue = (params) => {
7064
- const { data, path: path36, errorMaps, issueData } = params;
7065
- const fullPath = [...path36, ...issueData.path || []];
7064
+ const { data, path: path37, errorMaps, issueData } = params;
7065
+ const fullPath = [...path37, ...issueData.path || []];
7066
7066
  const fullIssue = {
7067
7067
  ...issueData,
7068
7068
  path: fullPath
@@ -7370,11 +7370,11 @@ var init_types = __esm({
7370
7370
  init_parseUtil();
7371
7371
  init_util();
7372
7372
  ParseInputLazyPath = class {
7373
- constructor(parent, value, path36, key) {
7373
+ constructor(parent, value, path37, key) {
7374
7374
  this._cachedPath = [];
7375
7375
  this.parent = parent;
7376
7376
  this.data = value;
7377
- this._path = path36;
7377
+ this._path = path37;
7378
7378
  this._key = key;
7379
7379
  }
7380
7380
  get path() {
@@ -11235,7 +11235,7 @@ var require_has_flag = __commonJS({
11235
11235
  var require_supports_color = __commonJS({
11236
11236
  "../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
11237
11237
  "use strict";
11238
- var os7 = __require("os");
11238
+ var os8 = __require("os");
11239
11239
  var tty = __require("tty");
11240
11240
  var hasFlag = require_has_flag();
11241
11241
  var { env } = process;
@@ -11283,7 +11283,7 @@ var require_supports_color = __commonJS({
11283
11283
  return min;
11284
11284
  }
11285
11285
  if (process.platform === "win32") {
11286
- const osRelease = os7.release().split(".");
11286
+ const osRelease = os8.release().split(".");
11287
11287
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
11288
11288
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
11289
11289
  }
@@ -11529,10 +11529,10 @@ var require_src2 = __commonJS({
11529
11529
  var fs_1 = __require("fs");
11530
11530
  var debug_1 = __importDefault(require_src());
11531
11531
  var log2 = debug_1.default("@kwsites/file-exists");
11532
- function check2(path36, isFile, isDirectory) {
11533
- log2(`checking %s`, path36);
11532
+ function check2(path37, isFile, isDirectory) {
11533
+ log2(`checking %s`, path37);
11534
11534
  try {
11535
- const stat3 = fs_1.statSync(path36);
11535
+ const stat3 = fs_1.statSync(path37);
11536
11536
  if (stat3.isFile() && isFile) {
11537
11537
  log2(`[OK] path represents a file`);
11538
11538
  return true;
@@ -11552,8 +11552,8 @@ var require_src2 = __commonJS({
11552
11552
  throw e;
11553
11553
  }
11554
11554
  }
11555
- function exists2(path36, type = exports.READABLE) {
11556
- return check2(path36, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
11555
+ function exists2(path37, type = exports.READABLE) {
11556
+ return check2(path37, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
11557
11557
  }
11558
11558
  exports.exists = exists2;
11559
11559
  exports.FILE = 1;
@@ -11850,10 +11850,10 @@ function assignProp(target, prop, value) {
11850
11850
  configurable: true
11851
11851
  });
11852
11852
  }
11853
- function getElementAtPath(obj, path36) {
11854
- if (!path36)
11853
+ function getElementAtPath(obj, path37) {
11854
+ if (!path37)
11855
11855
  return obj;
11856
- return path36.reduce((acc, key) => acc?.[key], obj);
11856
+ return path37.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(path36, issues) {
12105
+ function prefixIssues(path37, issues) {
12106
12106
  return issues.map((iss) => {
12107
12107
  var _a2;
12108
12108
  (_a2 = iss).path ?? (_a2.path = []);
12109
- iss.path.unshift(path36);
12109
+ iss.path.unshift(path37);
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, path36 = []) => {
12298
+ const processError = (error41, path37 = []) => {
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 = [...path36, ...issue2.path];
12308
+ const fullpath = [...path37, ...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(path36) {
12338
+ function toDotPath(path37) {
12339
12339
  const segs = [];
12340
- for (const seg of path36) {
12340
+ for (const seg of path37) {
12341
12341
  if (typeof seg === "number")
12342
12342
  segs.push(`[${seg}]`);
12343
12343
  else if (typeof seg === "symbol")
@@ -25064,15 +25064,15 @@ var {
25064
25064
  } = import_index.default;
25065
25065
 
25066
25066
  // src/cli-version.ts
25067
- var CLI_VERSION = "0.1.24".length > 0 ? "0.1.24" : "0.0.0-dev";
25067
+ var CLI_VERSION = "0.1.25".length > 0 ? "0.1.25" : "0.0.0-dev";
25068
25068
 
25069
25069
  // src/cli/defaults.ts
25070
25070
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
25071
25071
  var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
25072
25072
 
25073
25073
  // src/cli/run-cli-action.ts
25074
- import * as fs34 from "node:fs";
25075
- import * as path35 from "node:path";
25074
+ import * as fs35 from "node:fs";
25075
+ import * as path36 from "node:path";
25076
25076
 
25077
25077
  // src/cli-log-level.ts
25078
25078
  var verbosity = "info";
@@ -25465,6 +25465,11 @@ function logImmediate(line) {
25465
25465
  process.stdout.write(`${timestampPrefix()} ${line}
25466
25466
  `);
25467
25467
  }
25468
+ function logDebug(line) {
25469
+ const v = getCliLogVerbosity();
25470
+ if (v !== "debug" && v !== "trace") return;
25471
+ console.log(`${timestampPrefix()} [debug] ${line}`);
25472
+ }
25468
25473
  function logTrace(line) {
25469
25474
  if (getCliLogVerbosity() !== "trace") return;
25470
25475
  console.log(`${timestampPrefix()} [trace] ${line}`);
@@ -27058,9 +27063,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
27058
27063
  const rawPath = typeof o.path === "string" ? o.path.trim() : "";
27059
27064
  const summary = typeof o.summary === "string" ? o.summary.trim() : "";
27060
27065
  if (!rawPath || !summary) continue;
27061
- const path36 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
27062
- if (!path36) continue;
27063
- rows.push({ path: path36, summary: clampSummaryToAtMostTwoLines(summary) });
27066
+ const path37 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
27067
+ if (!path37) continue;
27068
+ rows.push({ path: path37, summary: clampSummaryToAtMostTwoLines(summary) });
27064
27069
  }
27065
27070
  return rows;
27066
27071
  }
@@ -27262,8 +27267,8 @@ function pathspec(...paths) {
27262
27267
  cache.set(key, paths);
27263
27268
  return key;
27264
27269
  }
27265
- function isPathSpec(path36) {
27266
- return path36 instanceof String && cache.has(path36);
27270
+ function isPathSpec(path37) {
27271
+ return path37 instanceof String && cache.has(path37);
27267
27272
  }
27268
27273
  function toPaths(pathSpec) {
27269
27274
  return cache.get(pathSpec) || [];
@@ -27352,8 +27357,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
27352
27357
  function forEachLineWithContent(input, callback) {
27353
27358
  return toLinesWithContent(input, true).map((line) => callback(line));
27354
27359
  }
27355
- function folderExists(path36) {
27356
- return (0, import_file_exists.exists)(path36, import_file_exists.FOLDER);
27360
+ function folderExists(path37) {
27361
+ return (0, import_file_exists.exists)(path37, import_file_exists.FOLDER);
27357
27362
  }
27358
27363
  function append(target, item) {
27359
27364
  if (Array.isArray(target)) {
@@ -27757,8 +27762,8 @@ function checkIsRepoRootTask() {
27757
27762
  commands,
27758
27763
  format: "utf-8",
27759
27764
  onError,
27760
- parser(path36) {
27761
- return /^\.(git)?$/.test(path36.trim());
27765
+ parser(path37) {
27766
+ return /^\.(git)?$/.test(path37.trim());
27762
27767
  }
27763
27768
  };
27764
27769
  }
@@ -28192,11 +28197,11 @@ function parseGrep(grep) {
28192
28197
  const paths = /* @__PURE__ */ new Set();
28193
28198
  const results = {};
28194
28199
  forEachLineWithContent(grep, (input) => {
28195
- const [path36, line, preview] = input.split(NULL);
28196
- paths.add(path36);
28197
- (results[path36] = results[path36] || []).push({
28200
+ const [path37, line, preview] = input.split(NULL);
28201
+ paths.add(path37);
28202
+ (results[path37] = results[path37] || []).push({
28198
28203
  line: asNumber(line),
28199
- path: path36,
28204
+ path: path37,
28200
28205
  preview
28201
28206
  });
28202
28207
  });
@@ -28961,14 +28966,14 @@ var init_hash_object = __esm2({
28961
28966
  init_task();
28962
28967
  }
28963
28968
  });
28964
- function parseInit(bare, path36, text) {
28969
+ function parseInit(bare, path37, text) {
28965
28970
  const response = String(text).trim();
28966
28971
  let result;
28967
28972
  if (result = initResponseRegex.exec(response)) {
28968
- return new InitSummary(bare, path36, false, result[1]);
28973
+ return new InitSummary(bare, path37, false, result[1]);
28969
28974
  }
28970
28975
  if (result = reInitResponseRegex.exec(response)) {
28971
- return new InitSummary(bare, path36, true, result[1]);
28976
+ return new InitSummary(bare, path37, true, result[1]);
28972
28977
  }
28973
28978
  let gitDir = "";
28974
28979
  const tokens = response.split(" ");
@@ -28979,7 +28984,7 @@ function parseInit(bare, path36, text) {
28979
28984
  break;
28980
28985
  }
28981
28986
  }
28982
- return new InitSummary(bare, path36, /^re/i.test(response), gitDir);
28987
+ return new InitSummary(bare, path37, /^re/i.test(response), gitDir);
28983
28988
  }
28984
28989
  var InitSummary;
28985
28990
  var initResponseRegex;
@@ -28988,9 +28993,9 @@ var init_InitSummary = __esm2({
28988
28993
  "src/lib/responses/InitSummary.ts"() {
28989
28994
  "use strict";
28990
28995
  InitSummary = class {
28991
- constructor(bare, path36, existing, gitDir) {
28996
+ constructor(bare, path37, existing, gitDir) {
28992
28997
  this.bare = bare;
28993
- this.path = path36;
28998
+ this.path = path37;
28994
28999
  this.existing = existing;
28995
29000
  this.gitDir = gitDir;
28996
29001
  }
@@ -29002,7 +29007,7 @@ var init_InitSummary = __esm2({
29002
29007
  function hasBareCommand(command) {
29003
29008
  return command.includes(bareCommand);
29004
29009
  }
29005
- function initTask(bare = false, path36, customArgs) {
29010
+ function initTask(bare = false, path37, customArgs) {
29006
29011
  const commands = ["init", ...customArgs];
29007
29012
  if (bare && !hasBareCommand(commands)) {
29008
29013
  commands.splice(1, 0, bareCommand);
@@ -29011,7 +29016,7 @@ function initTask(bare = false, path36, customArgs) {
29011
29016
  commands,
29012
29017
  format: "utf-8",
29013
29018
  parser(text) {
29014
- return parseInit(commands.includes("--bare"), path36, text);
29019
+ return parseInit(commands.includes("--bare"), path37, text);
29015
29020
  }
29016
29021
  };
29017
29022
  }
@@ -29827,12 +29832,12 @@ var init_FileStatusSummary = __esm2({
29827
29832
  "use strict";
29828
29833
  fromPathRegex = /^(.+)\0(.+)$/;
29829
29834
  FileStatusSummary = class {
29830
- constructor(path36, index, working_dir) {
29831
- this.path = path36;
29835
+ constructor(path37, index, working_dir) {
29836
+ this.path = path37;
29832
29837
  this.index = index;
29833
29838
  this.working_dir = working_dir;
29834
29839
  if (index === "R" || working_dir === "R") {
29835
- const detail = fromPathRegex.exec(path36) || [null, path36, path36];
29840
+ const detail = fromPathRegex.exec(path37) || [null, path37, path37];
29836
29841
  this.from = detail[2] || "";
29837
29842
  this.path = detail[1] || "";
29838
29843
  }
@@ -29863,14 +29868,14 @@ function splitLine(result, lineStr) {
29863
29868
  default:
29864
29869
  return;
29865
29870
  }
29866
- function data(index, workingDir, path36) {
29871
+ function data(index, workingDir, path37) {
29867
29872
  const raw = `${index}${workingDir}`;
29868
29873
  const handler = parsers6.get(raw);
29869
29874
  if (handler) {
29870
- handler(result, path36);
29875
+ handler(result, path37);
29871
29876
  }
29872
29877
  if (raw !== "##" && raw !== "!!") {
29873
- result.files.push(new FileStatusSummary(path36, index, workingDir));
29878
+ result.files.push(new FileStatusSummary(path37, index, workingDir));
29874
29879
  }
29875
29880
  }
29876
29881
  }
@@ -30179,9 +30184,9 @@ var init_simple_git_api = __esm2({
30179
30184
  next
30180
30185
  );
30181
30186
  }
30182
- hashObject(path36, write) {
30187
+ hashObject(path37, write) {
30183
30188
  return this._runTask(
30184
- hashObjectTask(path36, write === true),
30189
+ hashObjectTask(path37, write === true),
30185
30190
  trailingFunctionArgument(arguments)
30186
30191
  );
30187
30192
  }
@@ -30534,8 +30539,8 @@ var init_branch = __esm2({
30534
30539
  }
30535
30540
  });
30536
30541
  function toPath(input) {
30537
- const path36 = input.trim().replace(/^["']|["']$/g, "");
30538
- return path36 && normalize(path36);
30542
+ const path37 = input.trim().replace(/^["']|["']$/g, "");
30543
+ return path37 && normalize(path37);
30539
30544
  }
30540
30545
  var parseCheckIgnore;
30541
30546
  var init_CheckIgnore = __esm2({
@@ -30849,8 +30854,8 @@ __export2(sub_module_exports, {
30849
30854
  subModuleTask: () => subModuleTask,
30850
30855
  updateSubModuleTask: () => updateSubModuleTask
30851
30856
  });
30852
- function addSubModuleTask(repo, path36) {
30853
- return subModuleTask(["add", repo, path36]);
30857
+ function addSubModuleTask(repo, path37) {
30858
+ return subModuleTask(["add", repo, path37]);
30854
30859
  }
30855
30860
  function initSubModuleTask(customArgs) {
30856
30861
  return subModuleTask(["init", ...customArgs]);
@@ -31183,8 +31188,8 @@ var require_git = __commonJS2({
31183
31188
  }
31184
31189
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
31185
31190
  };
31186
- Git2.prototype.submoduleAdd = function(repo, path36, then) {
31187
- return this._runTask(addSubModuleTask2(repo, path36), trailingFunctionArgument2(arguments));
31191
+ Git2.prototype.submoduleAdd = function(repo, path37, then) {
31192
+ return this._runTask(addSubModuleTask2(repo, path37), trailingFunctionArgument2(arguments));
31188
31193
  };
31189
31194
  Git2.prototype.submoduleUpdate = function(args, then) {
31190
31195
  return this._runTask(
@@ -32071,9 +32076,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
32071
32076
  // src/agents/acp/put-summarize-change-summaries.ts
32072
32077
  async function putEncryptedChangeSummaryRows(params) {
32073
32078
  const base = params.apiBaseUrl.replace(/\/+$/, "");
32074
- const entries = params.rows.map(({ path: path36, summary }) => {
32079
+ const entries = params.rows.map(({ path: path37, summary }) => {
32075
32080
  const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
32076
- return { path: path36, summary: JSON.stringify(enc) };
32081
+ return { path: path37, summary: JSON.stringify(enc) };
32077
32082
  });
32078
32083
  const res = await fetch(
32079
32084
  `${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
@@ -32255,8 +32260,8 @@ async function sendPromptToAgent(options) {
32255
32260
  }
32256
32261
 
32257
32262
  // src/agents/acp/ensure-acp-client.ts
32258
- import * as fs10 from "node:fs";
32259
- import * as path12 from "node:path";
32263
+ import * as fs11 from "node:fs";
32264
+ import * as path13 from "node:path";
32260
32265
 
32261
32266
  // src/error-message.ts
32262
32267
  function errorMessage(err) {
@@ -32292,76 +32297,10 @@ async function isCommandOnPath(command, timeoutMs = 4e3) {
32292
32297
  }
32293
32298
  }
32294
32299
 
32295
- // src/agents/acp/clients/sdk-stdio-acp-client.ts
32300
+ // src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
32296
32301
  import { spawn as spawn2 } from "node:child_process";
32297
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
32298
- import { dirname as dirname2 } from "node:path";
32299
32302
  import { Readable, Writable } from "node:stream";
32300
32303
 
32301
- // src/files/diff/unified-diff.ts
32302
- function computeLineDiff(oldText, newText) {
32303
- const oldLines = oldText.split("\n");
32304
- const newLines = newText.split("\n");
32305
- const m = oldLines.length;
32306
- const n = newLines.length;
32307
- const dp = Array(m + 1);
32308
- for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
32309
- for (let i2 = 1; i2 <= m; i2++) {
32310
- for (let j2 = 1; j2 <= n; j2++) {
32311
- if (oldLines[i2 - 1] === newLines[j2 - 1]) {
32312
- dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
32313
- } else {
32314
- dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
32315
- }
32316
- }
32317
- }
32318
- const result = [];
32319
- let i = m;
32320
- let j = n;
32321
- while (i > 0 || j > 0) {
32322
- if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
32323
- result.unshift({ type: "context", line: oldLines[i - 1] });
32324
- i--;
32325
- j--;
32326
- } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
32327
- result.unshift({ type: "add", line: newLines[j - 1] });
32328
- j--;
32329
- } else {
32330
- result.unshift({ type: "remove", line: oldLines[i - 1] });
32331
- i--;
32332
- }
32333
- }
32334
- return result;
32335
- }
32336
- function editSnippetToUnifiedDiff(filePath, oldText, newText) {
32337
- const lines = computeLineDiff(oldText, newText);
32338
- const out = [`--- ${filePath}`, `+++ ${filePath}`];
32339
- for (const d of lines) {
32340
- if (d.type === "add") out.push(`+${d.line}`);
32341
- else if (d.type === "remove") out.push(`-${d.line}`);
32342
- else out.push(` ${d.line}`);
32343
- }
32344
- return out.join("\n");
32345
- }
32346
-
32347
- // src/agents/acp/safe-fs-path.ts
32348
- import * as path9 from "node:path";
32349
- function resolveSafePathUnderCwd(cwd, filePath) {
32350
- const trimmed2 = filePath.trim();
32351
- if (!trimmed2) return null;
32352
- const normalizedCwd = path9.resolve(cwd);
32353
- const resolved = path9.isAbsolute(trimmed2) ? path9.normalize(trimmed2) : path9.resolve(normalizedCwd, trimmed2);
32354
- const rel = path9.relative(normalizedCwd, resolved);
32355
- if (rel.startsWith("..") || path9.isAbsolute(rel)) return null;
32356
- return resolved;
32357
- }
32358
- function toDisplayPathRelativeToCwd(cwd, absolutePath) {
32359
- const normalizedCwd = path9.resolve(cwd);
32360
- const rel = path9.relative(normalizedCwd, path9.resolve(absolutePath));
32361
- if (!rel || rel === "") return path9.basename(absolutePath);
32362
- return rel.split(path9.sep).join("/");
32363
- }
32364
-
32365
32304
  // src/agents/acp/clients/agent-stderr-capture.ts
32366
32305
  var STDERR_CAPTURE_MAX = 48e3;
32367
32306
  function createStderrCapture(child) {
@@ -32426,7 +32365,7 @@ function createKiroSdkExtNotificationHandler(options) {
32426
32365
  };
32427
32366
  }
32428
32367
 
32429
- // src/agents/acp/clients/sdk-stdio-ext-notifications.ts
32368
+ // src/agents/acp/clients/sdk/sdk-stdio-ext-notifications.ts
32430
32369
  var noopExtNotification = async () => {
32431
32370
  };
32432
32371
  function createSdkStdioExtNotificationHandler(options) {
@@ -32485,23 +32424,364 @@ function enrichAcpPermissionRpcResultFromRequestParams(result, params) {
32485
32424
  };
32486
32425
  }
32487
32426
 
32488
- // src/agents/acp/clients/sdk-stdio-acp-client.ts
32489
- function formatSpawnError(err, command) {
32490
- if (err.code === "ENOENT") {
32491
- return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
32427
+ // src/agents/acp/clients/shared/acp-fs-read-write.ts
32428
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
32429
+ import { dirname as dirname2 } from "node:path";
32430
+
32431
+ // src/files/diff/unified-diff.ts
32432
+ function computeLineDiff(oldText, newText) {
32433
+ const oldLines = oldText.split("\n");
32434
+ const newLines = newText.split("\n");
32435
+ const m = oldLines.length;
32436
+ const n = newLines.length;
32437
+ const dp = Array(m + 1);
32438
+ for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
32439
+ for (let i2 = 1; i2 <= m; i2++) {
32440
+ for (let j2 = 1; j2 <= n; j2++) {
32441
+ if (oldLines[i2 - 1] === newLines[j2 - 1]) {
32442
+ dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
32443
+ } else {
32444
+ dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
32445
+ }
32446
+ }
32492
32447
  }
32493
- return err.message || String(err);
32448
+ const result = [];
32449
+ let i = m;
32450
+ let j = n;
32451
+ while (i > 0 || j > 0) {
32452
+ if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
32453
+ result.unshift({ type: "context", line: oldLines[i - 1] });
32454
+ i--;
32455
+ j--;
32456
+ } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
32457
+ result.unshift({ type: "add", line: newLines[j - 1] });
32458
+ j--;
32459
+ } else {
32460
+ result.unshift({ type: "remove", line: oldLines[i - 1] });
32461
+ i--;
32462
+ }
32463
+ }
32464
+ return result;
32494
32465
  }
32495
- function sliceFileContentRange(content, line, limit) {
32466
+ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
32467
+ const lines = computeLineDiff(oldText, newText);
32468
+ const out = [`--- ${filePath}`, `+++ ${filePath}`];
32469
+ for (const d of lines) {
32470
+ if (d.type === "add") out.push(`+${d.line}`);
32471
+ else if (d.type === "remove") out.push(`-${d.line}`);
32472
+ else out.push(` ${d.line}`);
32473
+ }
32474
+ return out.join("\n");
32475
+ }
32476
+
32477
+ // src/agents/acp/safe-fs-path.ts
32478
+ import * as path9 from "node:path";
32479
+ function resolveSafePathUnderCwd(cwd, filePath) {
32480
+ const trimmed2 = filePath.trim();
32481
+ if (!trimmed2) return null;
32482
+ const normalizedCwd = path9.resolve(cwd);
32483
+ const resolved = path9.isAbsolute(trimmed2) ? path9.normalize(trimmed2) : path9.resolve(normalizedCwd, trimmed2);
32484
+ const rel = path9.relative(normalizedCwd, resolved);
32485
+ if (rel.startsWith("..") || path9.isAbsolute(rel)) return null;
32486
+ return resolved;
32487
+ }
32488
+ function toDisplayPathRelativeToCwd(cwd, absolutePath) {
32489
+ const normalizedCwd = path9.resolve(cwd);
32490
+ const rel = path9.relative(normalizedCwd, path9.resolve(absolutePath));
32491
+ if (!rel || rel === "") return path9.basename(absolutePath);
32492
+ return rel.split(path9.sep).join("/");
32493
+ }
32494
+
32495
+ // src/agents/acp/clients/shared/acp-fs-read-write.ts
32496
+ function sliceFileContentForAcp(content, line, limit) {
32496
32497
  if (line == null && limit == null) return content;
32497
32498
  const lines = content.split("\n");
32498
32499
  const start = line != null && line > 0 ? line - 1 : 0;
32499
32500
  const end = limit != null && limit > 0 ? start + limit : lines.length;
32500
32501
  return lines.slice(start, end).join("\n");
32501
32502
  }
32502
- function bridgePayloadFromSdkSessionNotification(params) {
32503
+ function acpReadTextFileInProcess(ctx, filePath, line, limit) {
32504
+ const resolvedPath = resolveSafePathUnderCwd(ctx.cwd, filePath);
32505
+ if (!resolvedPath) throw new Error("Invalid or disallowed path");
32506
+ try {
32507
+ let content = readFileSync2(resolvedPath, "utf8");
32508
+ content = sliceFileContentForAcp(content, line, limit);
32509
+ return { content };
32510
+ } catch (e) {
32511
+ if (e.code === "ENOENT") return { content: "" };
32512
+ throw e;
32513
+ }
32514
+ }
32515
+ function acpWriteTextFileInProcess(ctx, filePath, newText) {
32516
+ const resolvedPath = resolveSafePathUnderCwd(ctx.cwd, filePath);
32517
+ if (!resolvedPath) throw new Error("Invalid or disallowed path");
32518
+ let oldText = "";
32519
+ try {
32520
+ oldText = readFileSync2(resolvedPath, "utf8");
32521
+ } catch (e) {
32522
+ if (e.code !== "ENOENT") throw e;
32523
+ }
32524
+ mkdirSync2(dirname2(resolvedPath), { recursive: true });
32525
+ writeFileSync2(resolvedPath, newText, "utf8");
32526
+ const displayPath = toDisplayPathRelativeToCwd(ctx.cwd, resolvedPath);
32527
+ const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
32528
+ ctx.onFileChange?.({ path: displayPath, oldText, newText, patchContent });
32529
+ return {};
32530
+ }
32531
+
32532
+ // src/agents/acp/claude-acp-permission-from-session.ts
32533
+ function flattenSelectOptions(options) {
32534
+ if (options == null || options.length === 0) return [];
32535
+ const first2 = options[0];
32536
+ if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
32537
+ return options.flatMap(
32538
+ (g) => Array.isArray(g.options) ? g.options : []
32539
+ );
32540
+ }
32541
+ return options;
32542
+ }
32543
+ function pickModeConfigOption(configOptions) {
32544
+ if (configOptions == null || configOptions.length === 0) return null;
32545
+ const byCategory = configOptions.find((o) => o.category === "mode");
32546
+ if (byCategory) return byCategory;
32547
+ return configOptions.find((o) => o.id === "mode") ?? null;
32548
+ }
32549
+ async function applyClaudePermissionFromAcpSession(params) {
32550
+ const { sessionId, agentConfig, configOptions, modes, setSessionConfigOption, setSessionMode, logDebug: logDebug2 } = params;
32551
+ const desiredMode = getClaudePermissionModeFromAgentConfig(agentConfig);
32552
+ if (desiredMode == null) return;
32553
+ const modeOpt = pickModeConfigOption(configOptions ?? null);
32554
+ if (modeOpt != null) {
32555
+ const flat = flattenSelectOptions(modeOpt.options);
32556
+ const allowed = flat.some((o) => o.value === desiredMode);
32557
+ if (allowed && modeOpt.currentValue !== desiredMode) {
32558
+ try {
32559
+ logDebug2(
32560
+ `[Agent] Claude Code: sending ACP session/set_config_option (permission mode) configId=${JSON.stringify(modeOpt.id)} value=${JSON.stringify(desiredMode)} was=${JSON.stringify(modeOpt.currentValue)} sessionId=${sessionId.slice(0, 8)}\u2026`
32561
+ );
32562
+ await setSessionConfigOption({ sessionId, configId: modeOpt.id, value: desiredMode });
32563
+ } catch (e) {
32564
+ logDebug2(
32565
+ `[Agent] Claude Code: session/set_config_option failed: ${e instanceof Error ? e.message : String(e)}`
32566
+ );
32567
+ }
32568
+ }
32569
+ return;
32570
+ }
32571
+ if (modes?.availableModes?.length) {
32572
+ const allowed = modes.availableModes.some((m) => m.id === desiredMode);
32573
+ if (allowed && desiredMode !== modes.currentModeId) {
32574
+ try {
32575
+ logDebug2(
32576
+ `[Agent] Claude Code: sending ACP session/set_mode (permission mode) modeId=${JSON.stringify(desiredMode)} was=${JSON.stringify(modes.currentModeId ?? null)} sessionId=${sessionId.slice(0, 8)}\u2026`
32577
+ );
32578
+ await setSessionMode({ sessionId, modeId: desiredMode });
32579
+ } catch (e) {
32580
+ logDebug2(`[Agent] Claude Code: session/set_mode failed: ${e instanceof Error ? e.message : String(e)}`);
32581
+ }
32582
+ }
32583
+ }
32584
+ }
32585
+
32586
+ // src/agents/acp/clients/shared/config-options-for-permission.ts
32587
+ function configOptionsForPermission(getActive, established) {
32588
+ const mem = getActive?.();
32589
+ if (Array.isArray(mem) && mem.length > 0) return mem;
32590
+ return established ?? void 0;
32591
+ }
32592
+
32593
+ // src/agents/acp/clients/shared/establish-acp-session.ts
32594
+ function establishedFromResult(raw, sessionId) {
32595
+ const r = raw && typeof raw === "object" ? raw : {};
32596
+ return {
32597
+ sessionId,
32598
+ configOptions: Array.isArray(r.configOptions) ? r.configOptions : null,
32599
+ modes: r.modes ?? null
32600
+ };
32601
+ }
32602
+ function sessionIdFromNewSessionResult(raw) {
32603
+ const r = raw && typeof raw === "object" ? raw : {};
32604
+ return typeof r.sessionId === "string" ? r.sessionId : "";
32605
+ }
32606
+ async function establishAcpSessionWithTransport(transport, ctx, canResume, canLoad) {
32607
+ const { cwd, mcpServers, persistedAcpSessionId, agentLabel, suppressLoadReplay } = ctx;
32608
+ const prev = typeof persistedAcpSessionId === "string" && persistedAcpSessionId.trim() !== "" ? persistedAcpSessionId.trim() : "";
32609
+ if (prev) {
32610
+ if (canResume) {
32611
+ try {
32612
+ logDebug(`[Agent] ${agentLabel} ACP session/resume for stored session ${prev.slice(0, 8)}\u2026`);
32613
+ const result2 = await transport.resumeSession({ sessionId: prev, cwd, mcpServers });
32614
+ return establishedFromResult(result2, prev);
32615
+ } catch (e) {
32616
+ logDebug(`[Agent] ${agentLabel} ACP session/resume failed: ${e instanceof Error ? e.message : String(e)}`);
32617
+ }
32618
+ }
32619
+ if (canLoad) {
32620
+ suppressLoadReplay.value = true;
32621
+ try {
32622
+ logDebug(`[Agent] ${agentLabel} ACP session/load for stored session ${prev.slice(0, 8)}\u2026`);
32623
+ const result2 = await transport.loadSession({ sessionId: prev, cwd, mcpServers });
32624
+ return establishedFromResult(result2, prev);
32625
+ } catch (e) {
32626
+ logDebug(`[Agent] ${agentLabel} ACP session/load failed: ${e instanceof Error ? e.message : String(e)}`);
32627
+ } finally {
32628
+ suppressLoadReplay.value = false;
32629
+ }
32630
+ }
32631
+ }
32632
+ const result = await transport.newSession({ cwd, mcpServers });
32633
+ const sid = sessionIdFromNewSessionResult(result);
32634
+ if (!sid) throw new Error(`${agentLabel} ACP session/new did not return sessionId`);
32635
+ return establishedFromResult(result, sid);
32636
+ }
32637
+
32638
+ // src/agents/acp/clients/shared/parse-acp-init-capabilities.ts
32639
+ function parseAcpInitAgentCapabilities(initResult) {
32640
+ const agentCapabilities = initResult?.agentCapabilities;
32641
+ const canLoad = agentCapabilities?.loadSession === true;
32642
+ const sessionCaps = agentCapabilities?.sessionCapabilities;
32643
+ const canResume = Boolean(sessionCaps?.resume);
32644
+ return { canResume, canLoad };
32645
+ }
32646
+
32647
+ // src/agents/acp/clients/shared/bootstrap-acp-wire-session.ts
32648
+ async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
32649
+ const initResult = await transport.initialize(initializeRequest);
32650
+ const { canResume, canLoad } = parseAcpInitAgentCapabilities(initResult);
32651
+ await transport.afterInitialize?.();
32652
+ const established = await establishAcpSessionWithTransport(transport, ctx, canResume, canLoad);
32653
+ const sessionId = established.sessionId;
32654
+ ctx.onAcpSessionEstablished?.({
32655
+ acpSessionId: sessionId,
32656
+ configOptions: established.configOptions,
32657
+ modes: established.modes
32658
+ });
32659
+ if (ctx.backendAgentType === "claude-code") {
32660
+ const cfg = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
32661
+ const configOptionsTyped = established.configOptions;
32662
+ const modesTyped = established.modes;
32663
+ await applyClaudePermissionFromAcpSession({
32664
+ sessionId,
32665
+ agentConfig: cfg,
32666
+ configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsTyped),
32667
+ modes: modesTyped,
32668
+ setSessionConfigOption: transport.setSessionConfigOption ? (p) => transport.setSessionConfigOption(p) : async () => {
32669
+ },
32670
+ setSessionMode: transport.setSessionMode ? (p) => transport.setSessionMode(p) : async () => {
32671
+ },
32672
+ logDebug: ctx.logDebug
32673
+ });
32674
+ }
32675
+ return established;
32676
+ }
32677
+
32678
+ // src/agents/acp/clients/shared/dispatch-session-update.ts
32679
+ function dispatchAcpSessionUpdate(opts) {
32680
+ const { flatPayload, onAcpConfigOptionsUpdated, onSessionUpdate, suppressLoadReplay } = opts;
32681
+ const su = flatPayload.sessionUpdate ?? flatPayload.session_update;
32682
+ if (su === "config_option_update") {
32683
+ const co = flatPayload.configOptions;
32684
+ if (Array.isArray(co)) onAcpConfigOptionsUpdated?.(co);
32685
+ return;
32686
+ }
32687
+ if (suppressLoadReplay()) return;
32688
+ onSessionUpdate?.(flatPayload);
32689
+ }
32690
+
32691
+ // src/agents/acp/clients/shared/flatten-sdk-session-notification.ts
32692
+ function flattenSdkSessionNotificationParams(params) {
32503
32693
  return { sessionId: params.sessionId, ...params.update };
32504
32694
  }
32695
+
32696
+ // src/agents/acp/clients/shared/normalize-acp-prompt-result.ts
32697
+ function normalizeAcpPromptTurnSuccess(opts) {
32698
+ const { stopReason, output, stderrCaptureText, backendAgentType } = opts;
32699
+ const mergedOutput = output || void 0;
32700
+ const stop = (stopReason ?? "").toLowerCase();
32701
+ const cancelled = stop === "cancelled";
32702
+ const refusal = stop === "refusal";
32703
+ const stderrEvaluated = Boolean(stderrCaptureText && backendAgentType);
32704
+ const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(backendAgentType, stderrCaptureText) : false;
32705
+ if (cancelled) {
32706
+ return {
32707
+ success: false,
32708
+ stopReason,
32709
+ output: mergedOutput,
32710
+ error: mergeErrorWithStderr("Stopped by user", stderrCaptureText)
32711
+ };
32712
+ }
32713
+ if (refusal) {
32714
+ return {
32715
+ success: false,
32716
+ stopReason,
32717
+ output: mergedOutput,
32718
+ error: mergeErrorWithStderr("The agent refused the request.", stderrCaptureText)
32719
+ };
32720
+ }
32721
+ if (stderrSuggestsAuth) {
32722
+ return {
32723
+ success: false,
32724
+ stopReason,
32725
+ output: mergedOutput,
32726
+ error: stderrCaptureText
32727
+ };
32728
+ }
32729
+ return {
32730
+ success: true,
32731
+ stopReason,
32732
+ output: mergedOutput
32733
+ };
32734
+ }
32735
+ function normalizeAcpPromptTurnFailure(err, stderrCaptureText) {
32736
+ const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrCaptureText);
32737
+ return { success: false, error: merged };
32738
+ }
32739
+
32740
+ // src/agents/acp/clients/shared/send-acp-prompt-via-transport.ts
32741
+ async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText) {
32742
+ try {
32743
+ const response = await transport.prompt({
32744
+ sessionId,
32745
+ prompt: [{ type: "text", text: promptText }]
32746
+ });
32747
+ await new Promise((r2) => setImmediate(r2));
32748
+ const r = response;
32749
+ return normalizeAcpPromptTurnSuccess({
32750
+ stopReason: r?.stopReason,
32751
+ output: r?.output,
32752
+ stderrCaptureText: ctx.getStderrText(),
32753
+ backendAgentType: ctx.backendAgentType
32754
+ });
32755
+ } catch (err) {
32756
+ await new Promise((r) => setImmediate(r));
32757
+ return normalizeAcpPromptTurnFailure(err, ctx.getStderrText());
32758
+ }
32759
+ }
32760
+
32761
+ // src/agents/acp/clients/sdk/sdk-acp-session-transport.ts
32762
+ function createSdkAcpSessionTransport(connection) {
32763
+ const c = connection;
32764
+ return {
32765
+ initialize: (request) => c.initialize(request),
32766
+ resumeSession: (p) => c.unstable_resumeSession(p),
32767
+ loadSession: (p) => c.loadSession(p),
32768
+ newSession: (p) => c.newSession(p),
32769
+ prompt: (p) => c.prompt(p),
32770
+ cancelSession: async (sessionId) => {
32771
+ await c.cancel({ sessionId });
32772
+ },
32773
+ setSessionConfigOption: c.setSessionConfigOption ? (p) => c.setSessionConfigOption(p) : void 0,
32774
+ setSessionMode: c.setSessionMode ? (p) => c.setSessionMode(p) : void 0
32775
+ };
32776
+ }
32777
+
32778
+ // src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
32779
+ function formatSpawnError(err, command) {
32780
+ if (err.code === "ENOENT") {
32781
+ return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
32782
+ }
32783
+ return err.message || String(err);
32784
+ }
32505
32785
  async function createSdkStdioAcpClient(options) {
32506
32786
  const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
32507
32787
  const {
@@ -32513,7 +32793,11 @@ async function createSdkStdioAcpClient(options) {
32513
32793
  onFileChange,
32514
32794
  killSubprocessAfterCancelMs,
32515
32795
  onAgentSubprocessExit,
32516
- agentConfig
32796
+ agentConfig,
32797
+ persistedAcpSessionId,
32798
+ onAcpSessionEstablished,
32799
+ onAcpConfigOptionsUpdated,
32800
+ getActiveConfigOptions
32517
32801
  } = options;
32518
32802
  const isWindows = process.platform === "win32";
32519
32803
  const child = spawn2(command[0], command.slice(1), {
@@ -32562,6 +32846,22 @@ async function createSdkStdioAcpClient(options) {
32562
32846
  backendAgentType,
32563
32847
  onSessionUpdate
32564
32848
  });
32849
+ const suppressLoadReplayRef = { value: false };
32850
+ const sessionCtx = {
32851
+ cwd,
32852
+ onFileChange,
32853
+ mcpServers: [],
32854
+ persistedAcpSessionId,
32855
+ agentLabel: "ACP",
32856
+ suppressLoadReplay: suppressLoadReplayRef,
32857
+ backendAgentType: backendAgentType ?? null,
32858
+ agentConfig,
32859
+ getActiveConfigOptions,
32860
+ onAcpSessionEstablished,
32861
+ onAcpConfigOptionsUpdated,
32862
+ logDebug,
32863
+ getStderrText: () => stderrCapture.getText()
32864
+ };
32565
32865
  let permissionSeq = 0;
32566
32866
  const pendingPermissionReplies = /* @__PURE__ */ new Map();
32567
32867
  const client = (_agent) => ({
@@ -32581,35 +32881,19 @@ async function createSdkStdioAcpClient(options) {
32581
32881
  });
32582
32882
  },
32583
32883
  async readTextFile(params) {
32584
- const resolvedPath = resolveSafePathUnderCwd(cwd, params.path);
32585
- if (!resolvedPath) throw new Error("Invalid or disallowed path");
32586
- try {
32587
- let content = readFileSync2(resolvedPath, "utf8");
32588
- content = sliceFileContentRange(content, params.line, params.limit);
32589
- return { content };
32590
- } catch (e) {
32591
- if (e.code === "ENOENT") return { content: "" };
32592
- throw e;
32593
- }
32884
+ return acpReadTextFileInProcess(sessionCtx, params.path, params.line, params.limit);
32594
32885
  },
32595
32886
  async writeTextFile(params) {
32596
- const resolvedPath = resolveSafePathUnderCwd(cwd, params.path);
32597
- if (!resolvedPath) throw new Error("Invalid or disallowed path");
32598
- let oldText = "";
32599
- try {
32600
- oldText = readFileSync2(resolvedPath, "utf8");
32601
- } catch (e) {
32602
- if (e.code !== "ENOENT") throw e;
32603
- }
32604
- mkdirSync2(dirname2(resolvedPath), { recursive: true });
32605
- writeFileSync2(resolvedPath, params.content, "utf8");
32606
- const displayPath = toDisplayPathRelativeToCwd(cwd, resolvedPath);
32607
- const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, params.content);
32608
- onFileChange?.({ path: displayPath, oldText, newText: params.content, patchContent });
32609
- return {};
32887
+ return acpWriteTextFileInProcess(sessionCtx, params.path, params.content);
32610
32888
  },
32611
32889
  async sessionUpdate(params) {
32612
- onSessionUpdate?.(bridgePayloadFromSdkSessionNotification(params));
32890
+ const bridged = flattenSdkSessionNotificationParams(params);
32891
+ dispatchAcpSessionUpdate({
32892
+ flatPayload: bridged,
32893
+ onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
32894
+ onSessionUpdate,
32895
+ suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
32896
+ });
32613
32897
  },
32614
32898
  async extNotification(method, params) {
32615
32899
  await extNotification(method, params);
@@ -32619,84 +32903,19 @@ async function createSdkStdioAcpClient(options) {
32619
32903
  connection.signal.addEventListener("abort", () => {
32620
32904
  child.kill();
32621
32905
  });
32622
- await connection.initialize({
32906
+ const transport = createSdkAcpSessionTransport(connection);
32907
+ const established = await bootstrapAcpWireSession(transport, sessionCtx, {
32623
32908
  protocolVersion: PROTOCOL_VERSION2,
32624
32909
  clientCapabilities: {
32625
32910
  fs: { readTextFile: true, writeTextFile: true }
32626
32911
  },
32627
32912
  clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
32628
32913
  });
32629
- const newSessionRes = await connection.newSession({ cwd, mcpServers: [] });
32630
- const sessionId = newSessionRes.sessionId;
32631
- if (backendAgentType === "claude-code") {
32632
- const cfg = agentConfig != null && typeof agentConfig === "object" && !Array.isArray(agentConfig) ? agentConfig : null;
32633
- const desiredMode = getClaudePermissionModeFromAgentConfig(cfg);
32634
- const modes = newSessionRes.modes;
32635
- if (desiredMode != null && modes?.availableModes?.length) {
32636
- const allowed = modes.availableModes.some((m) => m.id === desiredMode);
32637
- if (allowed && desiredMode !== modes.currentModeId) {
32638
- try {
32639
- await connection.setSessionMode({ sessionId, modeId: desiredMode });
32640
- } catch {
32641
- }
32642
- }
32643
- }
32644
- }
32914
+ const sessionId = established.sessionId;
32645
32915
  settleResolve({
32646
32916
  sessionId,
32647
32917
  async sendPrompt(prompt, _options) {
32648
- try {
32649
- const response = await connection.prompt({
32650
- sessionId,
32651
- prompt: [{ type: "text", text: prompt }]
32652
- });
32653
- await new Promise((r2) => setImmediate(r2));
32654
- const r = response;
32655
- const stopReason = (r?.stopReason ?? "").toLowerCase();
32656
- const cancelled = stopReason === "cancelled";
32657
- const refusal = stopReason === "refusal";
32658
- const stderrAfter = stderrCapture.getText();
32659
- const agentType = backendAgentType ?? null;
32660
- const stderrEvaluated = Boolean(stderrAfter && agentType);
32661
- const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
32662
- if (cancelled) {
32663
- return {
32664
- success: false,
32665
- stopReason: r?.stopReason,
32666
- output: r?.output,
32667
- error: mergeErrorWithStderr("Stopped by user", stderrAfter)
32668
- };
32669
- }
32670
- if (refusal) {
32671
- return {
32672
- success: false,
32673
- stopReason: r?.stopReason,
32674
- output: r?.output,
32675
- error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
32676
- };
32677
- }
32678
- if (stderrSuggestsAuth) {
32679
- return {
32680
- success: false,
32681
- stopReason: r?.stopReason,
32682
- output: r?.output,
32683
- error: stderrAfter
32684
- };
32685
- }
32686
- return {
32687
- success: true,
32688
- stopReason: r?.stopReason,
32689
- output: r?.output
32690
- };
32691
- } catch (err) {
32692
- await new Promise((r) => setImmediate(r));
32693
- const stderrAfter = stderrCapture.getText();
32694
- const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
32695
- return {
32696
- success: false,
32697
- error: merged
32698
- };
32699
- }
32918
+ return sendAcpPromptViaTransport(transport, sessionCtx, sessionId, prompt);
32700
32919
  },
32701
32920
  async cancel() {
32702
32921
  for (const [id, entry] of [...pendingPermissionReplies.entries()]) {
@@ -32704,7 +32923,7 @@ async function createSdkStdioAcpClient(options) {
32704
32923
  entry.resolve({ outcome: { outcome: "cancelled" } });
32705
32924
  }
32706
32925
  try {
32707
- await connection.cancel({ sessionId });
32926
+ await transport.cancelSession(sessionId);
32708
32927
  } catch {
32709
32928
  }
32710
32929
  if (killSubprocessAfterCancelMs != null && killSubprocessAfterCancelMs >= 0) {
@@ -32795,7 +33014,7 @@ async function createCodexAcpClient(options) {
32795
33014
  return createSdkStdioAcpClient({ ...options, command });
32796
33015
  }
32797
33016
 
32798
- // src/agents/acp/clients/cursor-acp-client.ts
33017
+ // src/agents/acp/clients/cursor/cursor-acp-client.ts
32799
33018
  var cursor_acp_client_exports = {};
32800
33019
  __export(cursor_acp_client_exports, {
32801
33020
  BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE3,
@@ -32803,8 +33022,6 @@ __export(cursor_acp_client_exports, {
32803
33022
  createCursorAcpClient: () => createCursorAcpClient,
32804
33023
  detectLocalAgentPresence: () => detectLocalAgentPresence3
32805
33024
  });
32806
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
32807
- import { dirname as dirname3 } from "node:path";
32808
33025
  import { spawn as spawn3 } from "node:child_process";
32809
33026
  import * as readline from "node:readline";
32810
33027
 
@@ -32821,7 +33038,23 @@ function formatSessionUpdateKindForLog(kind) {
32821
33038
  return kind.split("_").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
32822
33039
  }
32823
33040
 
32824
- // src/agents/acp/clients/cursor-acp-client.ts
33041
+ // src/agents/acp/clients/cursor/cursor-json-rpc-acp-transport.ts
33042
+ function createCursorJsonRpcAcpTransport(deps) {
33043
+ const { send, cancelSessionNotification } = deps;
33044
+ return {
33045
+ initialize: (request) => send("initialize", request),
33046
+ afterInitialize: async () => {
33047
+ await send("authenticate", { methodId: "cursor_login" });
33048
+ },
33049
+ resumeSession: (p) => send("session/resume", p),
33050
+ loadSession: (p) => send("session/load", p),
33051
+ newSession: (p) => send("session/new", p),
33052
+ prompt: (p) => send("session/prompt", p),
33053
+ cancelSession: (sessionId) => cancelSessionNotification(sessionId)
33054
+ };
33055
+ }
33056
+
33057
+ // src/agents/acp/clients/cursor/cursor-acp-client.ts
32825
33058
  var FS_READ_METHODS = /* @__PURE__ */ new Set(["fs/read_text_file", "fs/readTextFile"]);
32826
33059
  var FS_WRITE_METHODS = /* @__PURE__ */ new Set(["fs/write_text_file", "fs/writeTextFile"]);
32827
33060
  function formatSpawnError2(err, command) {
@@ -32838,13 +33071,6 @@ function safeJsonParse(value) {
32838
33071
  return null;
32839
33072
  }
32840
33073
  }
32841
- function sliceLinesByRange(content, line, limit) {
32842
- if (line == null && limit == null) return content;
32843
- const lines = content.split("\n");
32844
- const start = line != null && line > 0 ? line - 1 : 0;
32845
- const end = limit != null && limit > 0 ? start + limit : lines.length;
32846
- return lines.slice(start, end).join("\n");
32847
- }
32848
33074
  function buildCursorAcpSpawnCommand(base, sessionMode) {
32849
33075
  if (!sessionMode) return [...base];
32850
33076
  const m = sessionMode.trim();
@@ -32858,7 +33084,11 @@ async function createCursorAcpClient(options) {
32858
33084
  backendAgentType,
32859
33085
  onSessionUpdate,
32860
33086
  onRequest,
32861
- onFileChange
33087
+ onFileChange,
33088
+ persistedAcpSessionId,
33089
+ onAcpSessionEstablished,
33090
+ onAcpConfigOptionsUpdated,
33091
+ onAgentSubprocessExit
32862
33092
  } = options;
32863
33093
  const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
32864
33094
  const isWindows = process.platform === "win32";
@@ -32870,6 +33100,25 @@ async function createCursorAcpClient(options) {
32870
33100
  });
32871
33101
  const stderrCapture = createStderrCapture(child);
32872
33102
  child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
33103
+ child.once("close", (code, signal) => {
33104
+ onAgentSubprocessExit?.({ code, signal });
33105
+ });
33106
+ const suppressLoadReplayRef = { value: false };
33107
+ const sessionCtx = {
33108
+ cwd,
33109
+ onFileChange,
33110
+ mcpServers: [],
33111
+ persistedAcpSessionId,
33112
+ agentLabel: "Cursor",
33113
+ suppressLoadReplay: suppressLoadReplayRef,
33114
+ backendAgentType: backendAgentType ?? null,
33115
+ agentConfig: options.agentConfig,
33116
+ getActiveConfigOptions: options.getActiveConfigOptions,
33117
+ onAcpSessionEstablished,
33118
+ onAcpConfigOptionsUpdated,
33119
+ logDebug,
33120
+ getStderrText: () => stderrCapture.getText()
33121
+ };
32873
33122
  return new Promise((resolve18, reject) => {
32874
33123
  child.on("error", (err) => {
32875
33124
  child.kill();
@@ -32878,6 +33127,16 @@ async function createCursorAcpClient(options) {
32878
33127
  let nextId = 1;
32879
33128
  const pending = /* @__PURE__ */ new Map();
32880
33129
  const pendingRequests = /* @__PURE__ */ new Map();
33130
+ function cancelSessionNotification(sessionId) {
33131
+ const line = JSON.stringify({
33132
+ jsonrpc: "2.0",
33133
+ method: "session/cancel",
33134
+ params: { sessionId }
33135
+ }) + "\n";
33136
+ return new Promise((res, rej) => {
33137
+ child.stdin.write(line, (err) => err ? rej(err) : res());
33138
+ });
33139
+ }
32881
33140
  function send(method, params) {
32882
33141
  const id = nextId++;
32883
33142
  const line = JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n";
@@ -32901,7 +33160,6 @@ async function createCursorAcpClient(options) {
32901
33160
  respond(requestId, payload);
32902
33161
  pendingRequests.delete(requestId);
32903
33162
  }
32904
- let promptOutputBuffer = "";
32905
33163
  const rl = readline.createInterface({ input: child.stdout });
32906
33164
  rl.on("line", (line) => {
32907
33165
  const msg = safeJsonParse(line);
@@ -32930,11 +33188,12 @@ async function createCursorAcpClient(options) {
32930
33188
  `[acp] Received session update (${kindLabel}) tool=${toolName || "(none)"}`
32931
33189
  );
32932
33190
  }
32933
- const isTextChunk = sessionUpdate === "agent_message_chunk" && update.content?.text;
32934
- if (isTextChunk && update.content?.text) {
32935
- promptOutputBuffer += update.content.text;
32936
- }
32937
- onSessionUpdate?.(update);
33191
+ dispatchAcpSessionUpdate({
33192
+ flatPayload: update,
33193
+ onAcpConfigOptionsUpdated: sessionCtx.onAcpConfigOptionsUpdated,
33194
+ onSessionUpdate,
33195
+ suppressLoadReplay: () => sessionCtx.suppressLoadReplay.value
33196
+ });
32938
33197
  return;
32939
33198
  }
32940
33199
  if (method === "session/request_permission" && typeof id === "number") {
@@ -32954,21 +33213,13 @@ async function createCursorAcpClient(options) {
32954
33213
  if (dbgFs) {
32955
33214
  console.error(`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""}`);
32956
33215
  }
32957
- const resolvedPath = resolveSafePathUnderCwd(cwd, filePath);
32958
- if (!resolvedPath) {
32959
- if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty)`);
32960
- respondJsonRpcError(id, -32602, "Invalid or disallowed path");
32961
- return;
32962
- }
32963
33216
  try {
32964
- let content = readFileSync3(resolvedPath, "utf8");
32965
- const line2 = typeof params.line === "number" ? params.line : void 0;
32966
- const limit = typeof params.limit === "number" ? params.limit : void 0;
32967
- content = sliceLinesByRange(content, line2, limit);
32968
- respond(id, { content });
33217
+ const lineNum = typeof params.line === "number" ? params.line : void 0;
33218
+ const limitNum = typeof params.limit === "number" ? params.limit : void 0;
33219
+ const out = acpReadTextFileInProcess(sessionCtx, filePath, lineNum, limitNum);
33220
+ respond(id, out);
32969
33221
  } catch (e) {
32970
- const code = e?.code;
32971
- if (code === "ENOENT") {
33222
+ if (e?.code === "ENOENT") {
32972
33223
  respond(id, { content: "" });
32973
33224
  } else {
32974
33225
  respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
@@ -32985,32 +33236,17 @@ async function createCursorAcpClient(options) {
32985
33236
  `[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""} newBytes=${newText.length}`
32986
33237
  );
32987
33238
  }
32988
- const resolvedPath = resolveSafePathUnderCwd(cwd, filePath);
32989
- if (!resolvedPath) {
32990
- if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
32991
- respondJsonRpcError(id, -32602, "Invalid or disallowed path");
32992
- return;
32993
- }
32994
- let oldText = "";
32995
33239
  try {
32996
- oldText = readFileSync3(resolvedPath, "utf8");
33240
+ acpWriteTextFileInProcess(sessionCtx, filePath, newText);
33241
+ respond(id, null);
32997
33242
  } catch (e) {
32998
- if (e.code !== "ENOENT") {
33243
+ if (e.message === "Invalid or disallowed path") {
33244
+ if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
33245
+ respondJsonRpcError(id, -32602, "Invalid or disallowed path");
33246
+ } else {
32999
33247
  respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
33000
- return;
33001
33248
  }
33002
33249
  }
33003
- try {
33004
- mkdirSync3(dirname3(resolvedPath), { recursive: true });
33005
- writeFileSync3(resolvedPath, newText, "utf8");
33006
- } catch (e) {
33007
- respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
33008
- return;
33009
- }
33010
- const displayPath = toDisplayPathRelativeToCwd(cwd, resolvedPath);
33011
- const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
33012
- onFileChange?.({ path: displayPath, oldText, newText, patchContent });
33013
- respond(id, null);
33014
33250
  return;
33015
33251
  }
33016
33252
  if (method === "cursor/create_plan" || method === "cursor/ask_question") {
@@ -33032,16 +33268,7 @@ async function createCursorAcpClient(options) {
33032
33268
  });
33033
33269
  (async () => {
33034
33270
  try {
33035
- let sendSessionCancelNotification2 = function() {
33036
- const line = JSON.stringify({
33037
- jsonrpc: "2.0",
33038
- method: "session/cancel",
33039
- params: { sessionId }
33040
- }) + "\n";
33041
- return new Promise((res, rej) => {
33042
- child.stdin.write(line, (err) => err ? rej(err) : res());
33043
- });
33044
- }, cancelPendingPermissionRequests2 = function() {
33271
+ let cancelPendingPermissionRequests2 = function() {
33045
33272
  for (const [reqId, pending2] of [...pendingRequests.entries()]) {
33046
33273
  if (pending2.method === "session/request_permission") {
33047
33274
  respond(reqId, { outcome: { outcome: "cancelled" } });
@@ -33049,76 +33276,25 @@ async function createCursorAcpClient(options) {
33049
33276
  }
33050
33277
  }
33051
33278
  };
33052
- var sendSessionCancelNotification = sendSessionCancelNotification2, cancelPendingPermissionRequests = cancelPendingPermissionRequests2;
33053
- await send("initialize", {
33279
+ var cancelPendingPermissionRequests = cancelPendingPermissionRequests2;
33280
+ const transport = createCursorJsonRpcAcpTransport({
33281
+ send,
33282
+ cancelSessionNotification
33283
+ });
33284
+ const established = await bootstrapAcpWireSession(transport, sessionCtx, {
33054
33285
  protocolVersion: 1,
33055
33286
  clientCapabilities: { fs: { readTextFile: true, writeTextFile: true }, terminal: false },
33056
33287
  clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
33057
33288
  });
33058
- await send("authenticate", { methodId: "cursor_login" });
33059
- const newResult = await send("session/new", { cwd, mcpServers: [] });
33060
- const sessionId = newResult?.sessionId ?? "";
33061
- if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
33289
+ const sessionId = established.sessionId;
33062
33290
  resolve18({
33063
33291
  sessionId,
33064
33292
  async sendPrompt(prompt, _options) {
33065
- promptOutputBuffer = "";
33066
- try {
33067
- const result = await send("session/prompt", {
33068
- sessionId,
33069
- prompt: [{ type: "text", text: prompt }]
33070
- });
33071
- await new Promise((r) => setImmediate(r));
33072
- const output = (result?.output ?? promptOutputBuffer) || void 0;
33073
- const stopReason = (result?.stopReason ?? "").toLowerCase();
33074
- const cancelled = stopReason === "cancelled";
33075
- const refusal = stopReason === "refusal";
33076
- const stderrAfter = stderrCapture.getText();
33077
- const agentType = backendAgentType ?? null;
33078
- const stderrEvaluated = Boolean(stderrAfter && agentType);
33079
- const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
33080
- if (cancelled) {
33081
- return {
33082
- success: false,
33083
- stopReason: result?.stopReason,
33084
- output: output || void 0,
33085
- error: mergeErrorWithStderr("Stopped by user", stderrAfter)
33086
- };
33087
- }
33088
- if (refusal) {
33089
- return {
33090
- success: false,
33091
- stopReason: result?.stopReason,
33092
- output: output || void 0,
33093
- error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
33094
- };
33095
- }
33096
- if (stderrSuggestsAuth) {
33097
- return {
33098
- success: false,
33099
- stopReason: result?.stopReason,
33100
- output: output || void 0,
33101
- error: stderrAfter
33102
- };
33103
- }
33104
- return {
33105
- success: true,
33106
- stopReason: result?.stopReason,
33107
- output: output || void 0
33108
- };
33109
- } catch (err) {
33110
- await new Promise((r) => setImmediate(r));
33111
- const stderrAfter = stderrCapture.getText();
33112
- const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
33113
- return {
33114
- success: false,
33115
- error: merged
33116
- };
33117
- }
33293
+ return sendAcpPromptViaTransport(transport, sessionCtx, sessionId, prompt);
33118
33294
  },
33119
33295
  async cancel() {
33120
33296
  cancelPendingPermissionRequests2();
33121
- await sendSessionCancelNotification2();
33297
+ await transport.cancelSession(sessionId);
33122
33298
  },
33123
33299
  resolveRequest(requestId, result) {
33124
33300
  const numericId = Number(requestId);
@@ -33266,7 +33442,7 @@ function getGitRepoRootSync(startDir) {
33266
33442
 
33267
33443
  // src/agents/acp/workspace-files.ts
33268
33444
  import { execFileSync as execFileSync3 } from "node:child_process";
33269
- import { readFileSync as readFileSync4 } from "node:fs";
33445
+ import { readFileSync as readFileSync3 } from "node:fs";
33270
33446
  import * as path11 from "node:path";
33271
33447
  function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
33272
33448
  const trimmed2 = rawPath.trim();
@@ -33298,7 +33474,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
33298
33474
  const rel = path11.relative(gitRoot, resolvedPath2);
33299
33475
  if (!rel.startsWith("..") && !path11.isAbsolute(rel)) {
33300
33476
  try {
33301
- return readFileSync4(resolvedPath2, "utf8");
33477
+ return readFileSync3(resolvedPath2, "utf8");
33302
33478
  } catch {
33303
33479
  }
33304
33480
  }
@@ -33306,7 +33482,7 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
33306
33482
  const resolvedPath = resolveSafePathUnderCwd(sessionParentPath, displayPath);
33307
33483
  if (!resolvedPath) return "";
33308
33484
  try {
33309
- return readFileSync4(resolvedPath, "utf8");
33485
+ return readFileSync3(resolvedPath, "utf8");
33310
33486
  } catch {
33311
33487
  return "";
33312
33488
  }
@@ -33810,6 +33986,9 @@ function createBridgeOnSessionUpdate(opts) {
33810
33986
  const sentFileChangePaths = /* @__PURE__ */ new Set();
33811
33987
  const p = params;
33812
33988
  const updateKind = p.sessionUpdate ?? p.session_update ?? p.type ?? "update";
33989
+ if (updateKind === "config_option_update") {
33990
+ return;
33991
+ }
33813
33992
  const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
33814
33993
  const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
33815
33994
  const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
@@ -33896,14 +34075,72 @@ function buildAcpSessionBridgeHooks(opts) {
33896
34075
  };
33897
34076
  }
33898
34077
 
34078
+ // src/agents/acp/local-agent-session-file.ts
34079
+ import fs10 from "node:fs";
34080
+ import os3 from "node:os";
34081
+ import path12 from "node:path";
34082
+ var LOCAL_AGENT_SESSION_DIR = path12.join(os3.homedir(), ".buildautomaton", "agent-sessions");
34083
+ function safeFileSlug(cloudSessionId) {
34084
+ const t = cloudSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 220);
34085
+ return t.length > 0 ? t : "session";
34086
+ }
34087
+ function localAgentSessionFilePath(cloudSessionId) {
34088
+ return path12.join(LOCAL_AGENT_SESSION_DIR, `${safeFileSlug(cloudSessionId)}.json`);
34089
+ }
34090
+ function readLocalAgentSessionFile(cloudSessionId) {
34091
+ try {
34092
+ const p = localAgentSessionFilePath(cloudSessionId);
34093
+ const raw = fs10.readFileSync(p, "utf8");
34094
+ const parsed = JSON.parse(raw);
34095
+ if (parsed.v !== 1) return null;
34096
+ return {
34097
+ v: 1,
34098
+ acpSessionId: typeof parsed.acpSessionId === "string" ? parsed.acpSessionId : null,
34099
+ backendAgentType: typeof parsed.backendAgentType === "string" ? parsed.backendAgentType : null,
34100
+ configOptions: Array.isArray(parsed.configOptions) ? parsed.configOptions : null,
34101
+ updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
34102
+ };
34103
+ } catch {
34104
+ return null;
34105
+ }
34106
+ }
34107
+ function writeLocalAgentSessionFile(cloudSessionId, patch) {
34108
+ try {
34109
+ const dir = LOCAL_AGENT_SESSION_DIR;
34110
+ if (!fs10.existsSync(dir)) fs10.mkdirSync(dir, { recursive: true });
34111
+ const p = localAgentSessionFilePath(cloudSessionId);
34112
+ const prev = readLocalAgentSessionFile(cloudSessionId);
34113
+ const next = {
34114
+ v: 1,
34115
+ acpSessionId: patch.acpSessionId !== void 0 ? patch.acpSessionId : prev?.acpSessionId ?? null,
34116
+ backendAgentType: patch.backendAgentType !== void 0 ? patch.backendAgentType : prev?.backendAgentType ?? null,
34117
+ configOptions: patch.configOptions !== void 0 ? patch.configOptions : prev?.configOptions ?? null,
34118
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
34119
+ };
34120
+ fs10.writeFileSync(p, JSON.stringify(next, null, 2), "utf8");
34121
+ } catch {
34122
+ }
34123
+ }
34124
+
33899
34125
  // src/agents/acp/ensure-acp-client.ts
33900
34126
  async function ensureAcpClient(options) {
33901
- const { state, preferredAgentType, mode, agentConfig, sessionParentPath, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
34127
+ const {
34128
+ state,
34129
+ preferredAgentType,
34130
+ mode,
34131
+ agentConfig,
34132
+ sessionParentPath,
34133
+ routing,
34134
+ cloudSessionId,
34135
+ sendSessionUpdate,
34136
+ sendRequest,
34137
+ log: log2
34138
+ } = options;
33902
34139
  const targetSessionParentPath = resolveSessionParentPathForAgentProcess(sessionParentPath);
33903
34140
  if (state.acpStartPromise && !state.acpHandle) {
33904
34141
  await state.acpStartPromise;
33905
34142
  }
33906
- if (state.acpHandle && state.lastAcpCwd != null && path12.resolve(state.lastAcpCwd) !== path12.resolve(targetSessionParentPath)) {
34143
+ if (state.acpHandle && state.lastAcpCwd != null && path13.resolve(state.lastAcpCwd) !== path13.resolve(targetSessionParentPath)) {
33907
34144
  try {
33908
34145
  state.acpHandle.disconnect();
33909
34146
  } catch {
@@ -33911,6 +34148,7 @@ async function ensureAcpClient(options) {
33911
34148
  state.acpHandle = null;
33912
34149
  state.acpStartPromise = null;
33913
34150
  state.acpAgentKey = null;
34151
+ state.activeSessionConfigOptions = null;
33914
34152
  }
33915
34153
  const resolved = resolveAgentCommand(preferredAgentType);
33916
34154
  if (!resolved) {
@@ -33931,12 +34169,13 @@ async function ensureAcpClient(options) {
33931
34169
  state.acpHandle = null;
33932
34170
  state.acpStartPromise = null;
33933
34171
  state.acpAgentKey = null;
34172
+ state.activeSessionConfigOptions = null;
33934
34173
  }
33935
34174
  if (state.acpHandle) return state.acpHandle;
33936
34175
  if (!state.acpStartPromise) {
33937
34176
  let statOk = false;
33938
34177
  try {
33939
- const st = fs10.statSync(targetSessionParentPath);
34178
+ const st = fs11.statSync(targetSessionParentPath);
33940
34179
  statOk = st.isDirectory();
33941
34180
  if (!statOk) {
33942
34181
  state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
@@ -33956,15 +34195,40 @@ async function ensureAcpClient(options) {
33956
34195
  getSendRequest: () => sendRequest,
33957
34196
  log: log2
33958
34197
  });
34198
+ const persisted = cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "" ? readLocalAgentSessionFile(cloudSessionId) : null;
34199
+ const persistedAcpSessionId = persisted && persisted.backendAgentType === preferredAgentType && typeof persisted.acpSessionId === "string" && persisted.acpSessionId.trim() !== "" ? persisted.acpSessionId.trim() : null;
34200
+ state.activeSessionConfigOptions = Array.isArray(persisted?.configOptions) ? persisted.configOptions : null;
33959
34201
  state.acpStartPromise = resolved.createClient({
33960
34202
  command: resolved.command,
33961
34203
  sessionMode: mode,
33962
34204
  agentConfig: agentConfig ?? null,
33963
34205
  backendAgentType: preferredAgentType,
34206
+ persistedAcpSessionId,
34207
+ getActiveConfigOptions: () => state.activeSessionConfigOptions,
34208
+ onAcpSessionEstablished: (info) => {
34209
+ state.activeSessionConfigOptions = info.configOptions ?? state.activeSessionConfigOptions;
34210
+ if (cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "") {
34211
+ writeLocalAgentSessionFile(cloudSessionId, {
34212
+ acpSessionId: info.acpSessionId,
34213
+ configOptions: info.configOptions,
34214
+ backendAgentType: preferredAgentType
34215
+ });
34216
+ }
34217
+ },
34218
+ onAcpConfigOptionsUpdated: (configOptions) => {
34219
+ state.activeSessionConfigOptions = configOptions;
34220
+ if (cloudSessionId != null && cloudSessionId !== "" && preferredAgentType != null && preferredAgentType !== "") {
34221
+ writeLocalAgentSessionFile(cloudSessionId, {
34222
+ configOptions,
34223
+ backendAgentType: preferredAgentType
34224
+ });
34225
+ }
34226
+ },
33964
34227
  onAgentSubprocessExit: () => {
33965
34228
  state.acpHandle = null;
33966
34229
  state.acpStartPromise = null;
33967
34230
  state.acpAgentKey = null;
34231
+ state.activeSessionConfigOptions = null;
33968
34232
  state.lastAcpStartError = "Agent subprocess exited";
33969
34233
  },
33970
34234
  ...hooks,
@@ -33994,7 +34258,8 @@ async function createAcpManager(options) {
33994
34258
  acpStartPromise: null,
33995
34259
  lastAcpStartError: null,
33996
34260
  lastAcpCwd: null,
33997
- acpAgentKey: null
34261
+ acpAgentKey: null,
34262
+ activeSessionConfigOptions: null
33998
34263
  };
33999
34264
  let backendFallbackAgentType = null;
34000
34265
  const promptRouting = {};
@@ -34044,6 +34309,7 @@ async function createAcpManager(options) {
34044
34309
  agentConfig: agentConfig ?? null,
34045
34310
  sessionParentPath,
34046
34311
  routing: promptRouting,
34312
+ cloudSessionId: sessionId,
34047
34313
  sendSessionUpdate,
34048
34314
  sendRequest: sendSessionUpdate,
34049
34315
  log: log2
@@ -34134,6 +34400,7 @@ async function createAcpManager(options) {
34134
34400
  state.acpHandle = null;
34135
34401
  state.acpStartPromise = null;
34136
34402
  state.acpAgentKey = null;
34403
+ state.activeSessionConfigOptions = null;
34137
34404
  }
34138
34405
  return {
34139
34406
  setPreferredAgentType,
@@ -34146,12 +34413,12 @@ async function createAcpManager(options) {
34146
34413
  }
34147
34414
 
34148
34415
  // src/worktrees/session-worktree-manager.ts
34149
- import * as path19 from "node:path";
34150
- import os4 from "node:os";
34416
+ import * as path20 from "node:path";
34417
+ import os5 from "node:os";
34151
34418
 
34152
34419
  // src/worktrees/prepare-new-session-worktrees.ts
34153
- import * as fs12 from "node:fs";
34154
- import * as path14 from "node:path";
34420
+ import * as fs13 from "node:fs";
34421
+ import * as path15 from "node:path";
34155
34422
 
34156
34423
  // src/git/worktree-add.ts
34157
34424
  async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
@@ -34160,12 +34427,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
34160
34427
  }
34161
34428
 
34162
34429
  // src/worktrees/worktree-layout-file.ts
34163
- import * as fs11 from "node:fs";
34164
- import * as path13 from "node:path";
34165
- import os3 from "node:os";
34430
+ import * as fs12 from "node:fs";
34431
+ import * as path14 from "node:path";
34432
+ import os4 from "node:os";
34166
34433
  var LAYOUT_FILENAME = "worktree-launcher-layout.json";
34167
34434
  function defaultWorktreeLayoutPath() {
34168
- return path13.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
34435
+ return path14.join(os4.homedir(), ".buildautomaton", LAYOUT_FILENAME);
34169
34436
  }
34170
34437
  function normalizeLoadedLayout(raw) {
34171
34438
  if (raw && typeof raw === "object" && "launcherCwds" in raw) {
@@ -34177,8 +34444,8 @@ function normalizeLoadedLayout(raw) {
34177
34444
  function loadWorktreeLayout() {
34178
34445
  try {
34179
34446
  const p = defaultWorktreeLayoutPath();
34180
- if (!fs11.existsSync(p)) return { launcherCwds: [] };
34181
- const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
34447
+ if (!fs12.existsSync(p)) return { launcherCwds: [] };
34448
+ const raw = JSON.parse(fs12.readFileSync(p, "utf8"));
34182
34449
  return normalizeLoadedLayout(raw);
34183
34450
  } catch {
34184
34451
  return { launcherCwds: [] };
@@ -34186,24 +34453,24 @@ function loadWorktreeLayout() {
34186
34453
  }
34187
34454
  function saveWorktreeLayout(layout) {
34188
34455
  try {
34189
- const dir = path13.dirname(defaultWorktreeLayoutPath());
34190
- fs11.mkdirSync(dir, { recursive: true });
34191
- fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
34456
+ const dir = path14.dirname(defaultWorktreeLayoutPath());
34457
+ fs12.mkdirSync(dir, { recursive: true });
34458
+ fs12.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
34192
34459
  } catch {
34193
34460
  }
34194
34461
  }
34195
34462
  function baseNameSafe(pathString) {
34196
- return path13.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
34463
+ return path14.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
34197
34464
  }
34198
34465
  function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
34199
- const norm = path13.resolve(bridgeRootPath2);
34200
- const existing = layout.launcherCwds.find((e) => path13.resolve(e.absolutePath) === norm);
34466
+ const norm = path14.resolve(bridgeRootPath2);
34467
+ const existing = layout.launcherCwds.find((e) => path14.resolve(e.absolutePath) === norm);
34201
34468
  return existing?.dirName;
34202
34469
  }
34203
34470
  function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
34204
34471
  const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
34205
34472
  if (existing) return existing;
34206
- const norm = path13.resolve(bridgeRootPath2);
34473
+ const norm = path14.resolve(bridgeRootPath2);
34207
34474
  const base = baseNameSafe(norm);
34208
34475
  const used = new Set(layout.launcherCwds.map((e) => e.dirName));
34209
34476
  let name = base;
@@ -34220,10 +34487,10 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
34220
34487
  // src/worktrees/prepare-new-session-worktrees.ts
34221
34488
  async function prepareNewSessionWorktrees(options) {
34222
34489
  const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
34223
- const bridgeResolved = path14.resolve(bridgeRoot);
34490
+ const bridgeResolved = path15.resolve(bridgeRoot);
34224
34491
  const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
34225
- const bridgeKeyDir = path14.join(worktreesRootPath, cwdKey);
34226
- const sessionDir = path14.join(bridgeKeyDir, sessionId);
34492
+ const bridgeKeyDir = path15.join(worktreesRootPath, cwdKey);
34493
+ const sessionDir = path15.join(bridgeKeyDir, sessionId);
34227
34494
  const repos = await discoverGitReposUnderRoot(bridgeResolved);
34228
34495
  if (repos.length === 0) {
34229
34496
  log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
@@ -34231,14 +34498,14 @@ async function prepareNewSessionWorktrees(options) {
34231
34498
  }
34232
34499
  const branch = `session-${sessionId}`;
34233
34500
  const worktreePaths = [];
34234
- fs12.mkdirSync(sessionDir, { recursive: true });
34501
+ fs13.mkdirSync(sessionDir, { recursive: true });
34235
34502
  for (const repo of repos) {
34236
- let rel = path14.relative(bridgeResolved, repo.absolutePath);
34237
- if (rel.startsWith("..") || path14.isAbsolute(rel)) continue;
34503
+ let rel = path15.relative(bridgeResolved, repo.absolutePath);
34504
+ if (rel.startsWith("..") || path15.isAbsolute(rel)) continue;
34238
34505
  const relNorm = rel === "" ? "." : rel;
34239
- const wtPath = relNorm === "." ? sessionDir : path14.join(sessionDir, relNorm);
34506
+ const wtPath = relNorm === "." ? sessionDir : path15.join(sessionDir, relNorm);
34240
34507
  if (relNorm !== ".") {
34241
- fs12.mkdirSync(path14.dirname(wtPath), { recursive: true });
34508
+ fs13.mkdirSync(path15.dirname(wtPath), { recursive: true });
34242
34509
  }
34243
34510
  try {
34244
34511
  await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
@@ -34280,23 +34547,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
34280
34547
  }
34281
34548
 
34282
34549
  // src/worktrees/remove-session-worktrees.ts
34283
- import * as fs15 from "node:fs";
34550
+ import * as fs16 from "node:fs";
34284
34551
 
34285
34552
  // src/git/worktree-remove.ts
34286
- import * as fs14 from "node:fs";
34553
+ import * as fs15 from "node:fs";
34287
34554
 
34288
34555
  // src/git/resolve-main-repo-from-git-file.ts
34289
- import * as fs13 from "node:fs";
34290
- import * as path15 from "node:path";
34556
+ import * as fs14 from "node:fs";
34557
+ import * as path16 from "node:path";
34291
34558
  function resolveMainRepoFromWorktreeGitFile(wt) {
34292
- const gitDirFile = path15.join(wt, ".git");
34293
- if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
34294
- const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
34559
+ const gitDirFile = path16.join(wt, ".git");
34560
+ if (!fs14.existsSync(gitDirFile) || !fs14.statSync(gitDirFile).isFile()) return "";
34561
+ const first2 = fs14.readFileSync(gitDirFile, "utf8").trim();
34295
34562
  const m = first2.match(/^gitdir:\s*(.+)$/im);
34296
34563
  if (!m) return "";
34297
- const gitWorktreePath = path15.resolve(wt, m[1].trim());
34298
- const gitDir = path15.dirname(path15.dirname(gitWorktreePath));
34299
- return path15.dirname(gitDir);
34564
+ const gitWorktreePath = path16.resolve(wt, m[1].trim());
34565
+ const gitDir = path16.dirname(path16.dirname(gitWorktreePath));
34566
+ return path16.dirname(gitDir);
34300
34567
  }
34301
34568
 
34302
34569
  // src/git/worktree-remove.ts
@@ -34305,7 +34572,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
34305
34572
  if (mainRepo) {
34306
34573
  await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
34307
34574
  } else {
34308
- fs14.rmSync(worktreePath, { recursive: true, force: true });
34575
+ fs15.rmSync(worktreePath, { recursive: true, force: true });
34309
34576
  }
34310
34577
  }
34311
34578
 
@@ -34318,7 +34585,7 @@ async function removeSessionWorktrees(paths, log2) {
34318
34585
  } catch (e) {
34319
34586
  log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
34320
34587
  try {
34321
- fs15.rmSync(wt, { recursive: true, force: true });
34588
+ fs16.rmSync(wt, { recursive: true, force: true });
34322
34589
  } catch {
34323
34590
  }
34324
34591
  }
@@ -34538,7 +34805,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
34538
34805
  }
34539
34806
 
34540
34807
  // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
34541
- import * as path17 from "node:path";
34808
+ import * as path18 from "node:path";
34542
34809
 
34543
34810
  // src/git/working-directory/changes/parse-git-status.ts
34544
34811
  function parseNameStatusLines(lines) {
@@ -34658,8 +34925,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
34658
34925
  }
34659
34926
 
34660
34927
  // src/git/working-directory/changes/list-changed-files-for-repo.ts
34661
- import * as fs17 from "node:fs";
34662
- import * as path16 from "node:path";
34928
+ import * as fs18 from "node:fs";
34929
+ import * as path17 from "node:path";
34663
34930
 
34664
34931
  // src/git/working-directory/changes/count-lines.ts
34665
34932
  import { createReadStream } from "node:fs";
@@ -34683,7 +34950,7 @@ async function countTextFileLines(filePath) {
34683
34950
  }
34684
34951
 
34685
34952
  // src/git/working-directory/changes/hydrate-patch.ts
34686
- import * as fs16 from "node:fs";
34953
+ import * as fs17 from "node:fs";
34687
34954
  var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
34688
34955
  var MAX_HYDRATE_LINES_PER_GAP = 8e3;
34689
34956
  var MAX_HYDRATE_LINES_PER_FILE = 8e4;
@@ -34698,7 +34965,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
34698
34965
  }
34699
34966
  async function readWorktreeFileLines(filePath) {
34700
34967
  try {
34701
- const raw = await fs16.promises.readFile(filePath, "utf8");
34968
+ const raw = await fs17.promises.readFile(filePath, "utf8");
34702
34969
  return raw.split(/\r?\n/);
34703
34970
  } catch {
34704
34971
  return null;
@@ -34833,7 +35100,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
34833
35100
  const rows = [];
34834
35101
  for (const pathInRepo of paths) {
34835
35102
  const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
34836
- const repoFilePath = path16.join(repoGitCwd, pathInRepo);
35103
+ const repoFilePath = path17.join(repoGitCwd, pathInRepo);
34837
35104
  const nums = numByPath.get(pathInRepo);
34838
35105
  let additions = nums?.additions ?? 0;
34839
35106
  let deletions = nums?.deletions ?? 0;
@@ -34846,7 +35113,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
34846
35113
  deletions = fromGit.deletions;
34847
35114
  } else {
34848
35115
  try {
34849
- const st = await fs17.promises.stat(repoFilePath);
35116
+ const st = await fs18.promises.stat(repoFilePath);
34850
35117
  if (st.isFile()) additions = await countTextFileLines(repoFilePath);
34851
35118
  else additions = 0;
34852
35119
  } catch {
@@ -34872,7 +35139,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
34872
35139
  } else {
34873
35140
  pathInRepo = row.pathRelLauncher;
34874
35141
  }
34875
- const filePath = path16.join(repoGitCwd, pathInRepo);
35142
+ const filePath = path17.join(repoGitCwd, pathInRepo);
34876
35143
  let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
34877
35144
  if (patch) {
34878
35145
  patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
@@ -34888,8 +35155,8 @@ function normRepoRel(p) {
34888
35155
  return x === "" ? "." : x;
34889
35156
  }
34890
35157
  async function getWorkingTreeChangeRepoDetails(options) {
34891
- const bridgeRoot = path17.resolve(getBridgeRoot());
34892
- const sessionWtRoot = options.sessionWorktreeRootPath ? path17.resolve(options.sessionWorktreeRootPath) : null;
35158
+ const bridgeRoot = path18.resolve(getBridgeRoot());
35159
+ const sessionWtRoot = options.sessionWorktreeRootPath ? path18.resolve(options.sessionWorktreeRootPath) : null;
34893
35160
  const legacyNested = options.legacyRepoNestedSessionLayout === true;
34894
35161
  const out = [];
34895
35162
  const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
@@ -34902,7 +35169,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
34902
35169
  }
34903
35170
  const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
34904
35171
  for (const target of options.commitTargetPaths) {
34905
- const t = path17.resolve(target);
35172
+ const t = path18.resolve(target);
34906
35173
  if (!await isGitRepoDirectory(t)) continue;
34907
35174
  const g = cliSimpleGit(t);
34908
35175
  let branch = "HEAD";
@@ -34915,8 +35182,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
34915
35182
  const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
34916
35183
  let repoRelPath;
34917
35184
  if (sessionWtRoot) {
34918
- const anchor = legacyNested ? path17.dirname(t) : t;
34919
- const relNorm = path17.relative(sessionWtRoot, anchor);
35185
+ const anchor = legacyNested ? path18.dirname(t) : t;
35186
+ const relNorm = path18.relative(sessionWtRoot, anchor);
34920
35187
  repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
34921
35188
  } else {
34922
35189
  let top = t;
@@ -34925,8 +35192,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
34925
35192
  } catch {
34926
35193
  top = t;
34927
35194
  }
34928
- const rel = path17.relative(bridgeRoot, path17.resolve(top)).replace(/\\/g, "/") || ".";
34929
- repoRelPath = rel.startsWith("..") ? path17.basename(path17.resolve(top)) : rel;
35195
+ const rel = path18.relative(bridgeRoot, path18.resolve(top)).replace(/\\/g, "/") || ".";
35196
+ repoRelPath = rel.startsWith("..") ? path18.basename(path18.resolve(top)) : rel;
34930
35197
  }
34931
35198
  const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
34932
35199
  if (filter && norm !== filter) continue;
@@ -34991,11 +35258,11 @@ async function commitSessionWorktrees(options) {
34991
35258
  }
34992
35259
 
34993
35260
  // src/worktrees/discover-session-worktree-on-disk.ts
34994
- import * as fs18 from "node:fs";
34995
- import * as path18 from "node:path";
35261
+ import * as fs19 from "node:fs";
35262
+ import * as path19 from "node:path";
34996
35263
  function isGitDir(dirPath) {
34997
35264
  try {
34998
- return fs18.existsSync(path18.join(dirPath, ".git"));
35265
+ return fs19.existsSync(path19.join(dirPath, ".git"));
34999
35266
  } catch {
35000
35267
  return false;
35001
35268
  }
@@ -35004,23 +35271,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
35004
35271
  const out = [];
35005
35272
  const walk = (dir) => {
35006
35273
  if (isGitDir(dir)) {
35007
- out.push(path18.resolve(dir));
35274
+ out.push(path19.resolve(dir));
35008
35275
  return;
35009
35276
  }
35010
35277
  let entries;
35011
35278
  try {
35012
- entries = fs18.readdirSync(dir, { withFileTypes: true });
35279
+ entries = fs19.readdirSync(dir, { withFileTypes: true });
35013
35280
  } catch {
35014
35281
  return;
35015
35282
  }
35016
35283
  for (const e of entries) {
35017
35284
  if (e.name.startsWith(".")) continue;
35018
- const full = path18.join(dir, e.name);
35285
+ const full = path19.join(dir, e.name);
35019
35286
  if (!e.isDirectory()) continue;
35020
35287
  walk(full);
35021
35288
  }
35022
35289
  };
35023
- walk(path18.resolve(rootPath));
35290
+ walk(path19.resolve(rootPath));
35024
35291
  return [...new Set(out)];
35025
35292
  }
35026
35293
  function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
@@ -35029,16 +35296,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
35029
35296
  if (depth > maxDepth) return;
35030
35297
  let entries;
35031
35298
  try {
35032
- entries = fs18.readdirSync(dir, { withFileTypes: true });
35299
+ entries = fs19.readdirSync(dir, { withFileTypes: true });
35033
35300
  } catch {
35034
35301
  return;
35035
35302
  }
35036
35303
  for (const e of entries) {
35037
35304
  if (e.name.startsWith(".")) continue;
35038
- const full = path18.join(dir, e.name);
35305
+ const full = path19.join(dir, e.name);
35039
35306
  if (!e.isDirectory()) continue;
35040
35307
  if (e.name === sessionId) {
35041
- if (isGitDir(full)) out.push(path18.resolve(full));
35308
+ if (isGitDir(full)) out.push(path19.resolve(full));
35042
35309
  } else {
35043
35310
  walk(full, depth + 1);
35044
35311
  }
@@ -35050,14 +35317,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
35050
35317
  function tryBindingFromSessionDirectory(sessionDir) {
35051
35318
  let st;
35052
35319
  try {
35053
- st = fs18.statSync(sessionDir);
35320
+ st = fs19.statSync(sessionDir);
35054
35321
  } catch {
35055
35322
  return null;
35056
35323
  }
35057
35324
  if (!st.isDirectory()) return null;
35058
35325
  const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
35059
35326
  if (worktreePaths.length === 0) return null;
35060
- const abs = path18.resolve(sessionDir);
35327
+ const abs = path19.resolve(sessionDir);
35061
35328
  return {
35062
35329
  sessionParentPath: abs,
35063
35330
  workingTreeRelRoot: abs,
@@ -35067,20 +35334,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
35067
35334
  function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
35068
35335
  const sid = sessionId.trim();
35069
35336
  if (!sid) return null;
35070
- const hintR = path18.resolve(checkoutPath);
35337
+ const hintR = path19.resolve(checkoutPath);
35071
35338
  let best = null;
35072
- let cur = path18.dirname(hintR);
35339
+ let cur = path19.dirname(hintR);
35073
35340
  for (let i = 0; i < 40; i++) {
35074
35341
  const paths = collectWorktreeRootsNamed(cur, sid, 24);
35075
- if (paths.some((p) => path18.resolve(p) === hintR)) {
35076
- const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path18.resolve(paths[0]);
35342
+ if (paths.some((p) => path19.resolve(p) === hintR)) {
35343
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path19.resolve(paths[0]);
35077
35344
  best = {
35078
- sessionParentPath: path18.resolve(isolated),
35079
- workingTreeRelRoot: path18.resolve(cur),
35080
- repoCheckoutPaths: paths.map((p) => path18.resolve(p))
35345
+ sessionParentPath: path19.resolve(isolated),
35346
+ workingTreeRelRoot: path19.resolve(cur),
35347
+ repoCheckoutPaths: paths.map((p) => path19.resolve(p))
35081
35348
  };
35082
35349
  }
35083
- const next = path18.dirname(cur);
35350
+ const next = path19.dirname(cur);
35084
35351
  if (next === cur) break;
35085
35352
  cur = next;
35086
35353
  }
@@ -35088,33 +35355,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
35088
35355
  }
35089
35356
  function discoverSessionWorktreeOnDisk(options) {
35090
35357
  const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
35091
- if (!sessionId.trim() || !fs18.existsSync(worktreesRootPath)) return null;
35358
+ if (!sessionId.trim() || !fs19.existsSync(worktreesRootPath)) return null;
35092
35359
  const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
35093
35360
  const keys = [];
35094
35361
  if (preferredKey) keys.push(preferredKey);
35095
35362
  try {
35096
- for (const name of fs18.readdirSync(worktreesRootPath)) {
35363
+ for (const name of fs19.readdirSync(worktreesRootPath)) {
35097
35364
  if (name.startsWith(".")) continue;
35098
- const p = path18.join(worktreesRootPath, name);
35099
- if (!fs18.statSync(p).isDirectory()) continue;
35365
+ const p = path19.join(worktreesRootPath, name);
35366
+ if (!fs19.statSync(p).isDirectory()) continue;
35100
35367
  if (name !== preferredKey) keys.push(name);
35101
35368
  }
35102
35369
  } catch {
35103
35370
  return null;
35104
35371
  }
35105
35372
  for (const key of keys) {
35106
- const layoutRoot = path18.join(worktreesRootPath, key);
35107
- if (!fs18.existsSync(layoutRoot) || !fs18.statSync(layoutRoot).isDirectory()) continue;
35108
- const sessionDir = path18.join(layoutRoot, sessionId);
35373
+ const layoutRoot = path19.join(worktreesRootPath, key);
35374
+ if (!fs19.existsSync(layoutRoot) || !fs19.statSync(layoutRoot).isDirectory()) continue;
35375
+ const sessionDir = path19.join(layoutRoot, sessionId);
35109
35376
  const nested = tryBindingFromSessionDirectory(sessionDir);
35110
35377
  if (nested) return nested;
35111
35378
  const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
35112
35379
  if (legacyPaths.length > 0) {
35113
- const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path18.resolve(legacyPaths[0]);
35380
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path19.resolve(legacyPaths[0]);
35114
35381
  return {
35115
- sessionParentPath: path18.resolve(isolated),
35116
- workingTreeRelRoot: path18.resolve(layoutRoot),
35117
- repoCheckoutPaths: legacyPaths.map((p) => path18.resolve(p))
35382
+ sessionParentPath: path19.resolve(isolated),
35383
+ workingTreeRelRoot: path19.resolve(layoutRoot),
35384
+ repoCheckoutPaths: legacyPaths.map((p) => path19.resolve(p))
35118
35385
  };
35119
35386
  }
35120
35387
  }
@@ -35123,12 +35390,12 @@ function discoverSessionWorktreeOnDisk(options) {
35123
35390
  function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
35124
35391
  const sid = sessionId.trim();
35125
35392
  if (!sid) return null;
35126
- const hint = path18.resolve(sessionWorktreeRootPathOrHint);
35127
- const underHint = tryBindingFromSessionDirectory(path18.join(hint, sid));
35393
+ const hint = path19.resolve(sessionWorktreeRootPathOrHint);
35394
+ const underHint = tryBindingFromSessionDirectory(path19.join(hint, sid));
35128
35395
  if (underHint) return underHint;
35129
35396
  const direct = tryBindingFromSessionDirectory(hint);
35130
35397
  if (direct) {
35131
- if (path18.basename(hint) === sid && isGitDir(hint)) {
35398
+ if (path19.basename(hint) === sid && isGitDir(hint)) {
35132
35399
  const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
35133
35400
  if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
35134
35401
  return legacyFromCheckout;
@@ -35136,24 +35403,24 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
35136
35403
  }
35137
35404
  return direct;
35138
35405
  }
35139
- if (path18.basename(hint) === sid && isGitDir(hint)) {
35406
+ if (path19.basename(hint) === sid && isGitDir(hint)) {
35140
35407
  const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
35141
35408
  if (legacyFromCheckout) return legacyFromCheckout;
35142
35409
  }
35143
35410
  let st;
35144
35411
  try {
35145
- st = fs18.statSync(hint);
35412
+ st = fs19.statSync(hint);
35146
35413
  } catch {
35147
35414
  return null;
35148
35415
  }
35149
35416
  if (!st.isDirectory()) return null;
35150
35417
  const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
35151
35418
  if (legacyPaths.length === 0) return null;
35152
- const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path18.resolve(legacyPaths[0]);
35419
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path19.resolve(legacyPaths[0]);
35153
35420
  return {
35154
- sessionParentPath: path18.resolve(isolated),
35421
+ sessionParentPath: path19.resolve(isolated),
35155
35422
  workingTreeRelRoot: hint,
35156
- repoCheckoutPaths: legacyPaths.map((p) => path18.resolve(p))
35423
+ repoCheckoutPaths: legacyPaths.map((p) => path19.resolve(p))
35157
35424
  };
35158
35425
  }
35159
35426
 
@@ -35176,10 +35443,10 @@ var SessionWorktreeManager = class {
35176
35443
  this.layout = loadWorktreeLayout();
35177
35444
  }
35178
35445
  rememberSessionWorktrees(sessionId, binding) {
35179
- const paths = binding.repoCheckoutPaths.map((p) => path19.resolve(p));
35446
+ const paths = binding.repoCheckoutPaths.map((p) => path20.resolve(p));
35180
35447
  this.sessionRepoCheckoutPaths.set(sessionId, paths);
35181
- this.sessionParentPathBySession.set(sessionId, path19.resolve(binding.sessionParentPath));
35182
- this.sessionWorkingTreeRelRootBySession.set(sessionId, path19.resolve(binding.workingTreeRelRoot));
35448
+ this.sessionParentPathBySession.set(sessionId, path20.resolve(binding.sessionParentPath));
35449
+ this.sessionWorkingTreeRelRootBySession.set(sessionId, path20.resolve(binding.workingTreeRelRoot));
35183
35450
  }
35184
35451
  sessionParentPathAfterRemember(sessionId) {
35185
35452
  return this.sessionParentPathBySession.get(sessionId);
@@ -35196,7 +35463,7 @@ var SessionWorktreeManager = class {
35196
35463
  const parent = this.sessionParentPathBySession.get(sessionId);
35197
35464
  const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
35198
35465
  if (!parent || !relRoot) return false;
35199
- return path19.resolve(parent) !== path19.resolve(relRoot);
35466
+ return path20.resolve(parent) !== path20.resolve(relRoot);
35200
35467
  }
35201
35468
  /**
35202
35469
  * Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
@@ -35205,7 +35472,7 @@ var SessionWorktreeManager = class {
35205
35472
  if (!sessionId) return null;
35206
35473
  const sid = sessionId.trim();
35207
35474
  const cached2 = this.sessionParentPathBySession.get(sid);
35208
- if (cached2) return path19.resolve(cached2);
35475
+ if (cached2) return path20.resolve(cached2);
35209
35476
  const paths = this.ensureRepoCheckoutPathsForSession(sid) ?? this.getRepoCheckoutPathsForSession(sid);
35210
35477
  if (!paths?.length) return null;
35211
35478
  return resolveIsolatedSessionParentPathFromCheckouts(paths);
@@ -35219,7 +35486,7 @@ var SessionWorktreeManager = class {
35219
35486
  const sid = sessionId.trim();
35220
35487
  const parentPathRaw = opts.sessionParentPath?.trim();
35221
35488
  if (parentPathRaw) {
35222
- const resolved = path19.resolve(parentPathRaw);
35489
+ const resolved = path20.resolve(parentPathRaw);
35223
35490
  if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
35224
35491
  const diskFirst = this.tryDiscoverFromDisk(sid);
35225
35492
  if (diskFirst) {
@@ -35238,7 +35505,7 @@ var SessionWorktreeManager = class {
35238
35505
  this.rememberSessionWorktrees(sid, tryRoot);
35239
35506
  return this.sessionParentPathAfterRemember(sid);
35240
35507
  }
35241
- const next = path19.dirname(cur);
35508
+ const next = path20.dirname(cur);
35242
35509
  if (next === cur) break;
35243
35510
  cur = next;
35244
35511
  }
@@ -35391,15 +35658,15 @@ var SessionWorktreeManager = class {
35391
35658
  }
35392
35659
  };
35393
35660
  function defaultWorktreesRootPath() {
35394
- return path19.join(os4.homedir(), ".buildautomaton", "worktrees");
35661
+ return path20.join(os5.homedir(), ".buildautomaton", "worktrees");
35395
35662
  }
35396
35663
 
35397
35664
  // src/files/watch-file-index.ts
35398
35665
  import { watch } from "node:fs";
35399
- import path26 from "node:path";
35666
+ import path27 from "node:path";
35400
35667
 
35401
35668
  // src/files/index/build-file-index.ts
35402
- import path23 from "node:path";
35669
+ import path24 from "node:path";
35403
35670
 
35404
35671
  // src/runtime/yield-to-event-loop.ts
35405
35672
  function yieldToEventLoop() {
@@ -35407,14 +35674,14 @@ function yieldToEventLoop() {
35407
35674
  }
35408
35675
 
35409
35676
  // src/files/index/walk-workspace-tree.ts
35410
- import fs19 from "node:fs";
35411
- import path21 from "node:path";
35677
+ import fs20 from "node:fs";
35678
+ import path22 from "node:path";
35412
35679
 
35413
35680
  // src/files/index/constants.ts
35414
- import path20 from "node:path";
35415
- import os5 from "node:os";
35681
+ import path21 from "node:path";
35682
+ import os6 from "node:os";
35416
35683
  var INDEX_WORK_YIELD_EVERY = 256;
35417
- var INDEX_DIR = path20.join(os5.homedir(), ".buildautomaton");
35684
+ var INDEX_DIR = path21.join(os6.homedir(), ".buildautomaton");
35418
35685
  var INDEX_HASH_LEN = 16;
35419
35686
  var INDEX_VERSION = 2;
35420
35687
  var INDEX_LOG_PREFIX = "[file-index]";
@@ -35423,20 +35690,20 @@ var INDEX_LOG_PREFIX = "[file-index]";
35423
35690
  function walkWorkspaceTreeSync(dir, baseDir, out) {
35424
35691
  let names;
35425
35692
  try {
35426
- names = fs19.readdirSync(dir);
35693
+ names = fs20.readdirSync(dir);
35427
35694
  } catch {
35428
35695
  return;
35429
35696
  }
35430
35697
  for (const name of names) {
35431
35698
  if (name.startsWith(".")) continue;
35432
- const full = path21.join(dir, name);
35699
+ const full = path22.join(dir, name);
35433
35700
  let stat3;
35434
35701
  try {
35435
- stat3 = fs19.statSync(full);
35702
+ stat3 = fs20.statSync(full);
35436
35703
  } catch {
35437
35704
  continue;
35438
35705
  }
35439
- const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
35706
+ const relative5 = path22.relative(baseDir, full).replace(/\\/g, "/");
35440
35707
  if (stat3.isDirectory()) {
35441
35708
  walkWorkspaceTreeSync(full, baseDir, out);
35442
35709
  } else if (stat3.isFile()) {
@@ -35447,7 +35714,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
35447
35714
  async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
35448
35715
  let names;
35449
35716
  try {
35450
- names = await fs19.promises.readdir(dir);
35717
+ names = await fs20.promises.readdir(dir);
35451
35718
  } catch {
35452
35719
  return;
35453
35720
  }
@@ -35457,14 +35724,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
35457
35724
  await yieldToEventLoop();
35458
35725
  }
35459
35726
  state.n++;
35460
- const full = path21.join(dir, name);
35727
+ const full = path22.join(dir, name);
35461
35728
  let stat3;
35462
35729
  try {
35463
- stat3 = await fs19.promises.stat(full);
35730
+ stat3 = await fs20.promises.stat(full);
35464
35731
  } catch {
35465
35732
  continue;
35466
35733
  }
35467
- const relative5 = path21.relative(baseDir, full).replace(/\\/g, "/");
35734
+ const relative5 = path22.relative(baseDir, full).replace(/\\/g, "/");
35468
35735
  if (stat3.isDirectory()) {
35469
35736
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
35470
35737
  } else if (stat3.isFile()) {
@@ -35545,22 +35812,22 @@ async function buildTrigramMapForPathsAsync(paths) {
35545
35812
  }
35546
35813
 
35547
35814
  // src/files/index/write-index-file.ts
35548
- import fs20 from "node:fs";
35815
+ import fs21 from "node:fs";
35549
35816
 
35550
35817
  // src/files/index/paths.ts
35551
- import path22 from "node:path";
35818
+ import path23 from "node:path";
35552
35819
  import crypto2 from "node:crypto";
35553
35820
  function getIndexPathForCwd(resolvedCwd) {
35554
35821
  const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
35555
- return path22.join(INDEX_DIR, `.file-index-${hash}.json`);
35822
+ return path23.join(INDEX_DIR, `.file-index-${hash}.json`);
35556
35823
  }
35557
35824
 
35558
35825
  // src/files/index/write-index-file.ts
35559
35826
  function writeIndexFileSync(resolvedCwd, data) {
35560
35827
  const indexPath = getIndexPathForCwd(resolvedCwd);
35561
35828
  try {
35562
- if (!fs20.existsSync(INDEX_DIR)) fs20.mkdirSync(INDEX_DIR, { recursive: true });
35563
- fs20.writeFileSync(indexPath, JSON.stringify(data), "utf8");
35829
+ if (!fs21.existsSync(INDEX_DIR)) fs21.mkdirSync(INDEX_DIR, { recursive: true });
35830
+ fs21.writeFileSync(indexPath, JSON.stringify(data), "utf8");
35564
35831
  } catch (e) {
35565
35832
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
35566
35833
  }
@@ -35568,8 +35835,8 @@ function writeIndexFileSync(resolvedCwd, data) {
35568
35835
  async function writeIndexFileAsync(resolvedCwd, data) {
35569
35836
  const indexPath = getIndexPathForCwd(resolvedCwd);
35570
35837
  try {
35571
- await fs20.promises.mkdir(INDEX_DIR, { recursive: true });
35572
- await fs20.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
35838
+ await fs21.promises.mkdir(INDEX_DIR, { recursive: true });
35839
+ await fs21.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
35573
35840
  } catch (e) {
35574
35841
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
35575
35842
  }
@@ -35583,7 +35850,7 @@ function sortPaths(paths) {
35583
35850
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
35584
35851
  }
35585
35852
  function buildFileIndex(cwd) {
35586
- const resolved = path23.resolve(cwd);
35853
+ const resolved = path24.resolve(cwd);
35587
35854
  const paths = [];
35588
35855
  walkWorkspaceTreeSync(resolved, resolved, paths);
35589
35856
  sortPaths(paths);
@@ -35593,7 +35860,7 @@ function buildFileIndex(cwd) {
35593
35860
  return data;
35594
35861
  }
35595
35862
  async function buildFileIndexAsync(cwd) {
35596
- const resolved = path23.resolve(cwd);
35863
+ const resolved = path24.resolve(cwd);
35597
35864
  const paths = [];
35598
35865
  await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
35599
35866
  await yieldToEventLoop();
@@ -35605,13 +35872,13 @@ async function buildFileIndexAsync(cwd) {
35605
35872
  }
35606
35873
 
35607
35874
  // src/files/index/load-file-index.ts
35608
- import fs21 from "node:fs";
35609
- import path24 from "node:path";
35875
+ import fs22 from "node:fs";
35876
+ import path25 from "node:path";
35610
35877
  function loadFileIndex(cwd) {
35611
- const resolved = path24.resolve(cwd);
35878
+ const resolved = path25.resolve(cwd);
35612
35879
  const indexPath = getIndexPathForCwd(resolved);
35613
35880
  try {
35614
- const raw = fs21.readFileSync(indexPath, "utf8");
35881
+ const raw = fs22.readFileSync(indexPath, "utf8");
35615
35882
  const parsed = JSON.parse(raw);
35616
35883
  if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
35617
35884
  const obj = parsed;
@@ -35630,9 +35897,9 @@ function loadFileIndex(cwd) {
35630
35897
  }
35631
35898
 
35632
35899
  // src/files/index/ensure-file-index.ts
35633
- import path25 from "node:path";
35900
+ import path26 from "node:path";
35634
35901
  async function ensureFileIndexAsync(cwd) {
35635
- const resolved = path25.resolve(cwd);
35902
+ const resolved = path26.resolve(cwd);
35636
35903
  const cached2 = loadFileIndex(resolved);
35637
35904
  if (cached2 !== null) return { data: cached2, fromCache: true };
35638
35905
  const data = await buildFileIndexAsync(resolved);
@@ -35715,7 +35982,7 @@ function createFsWatcher(resolved, schedule) {
35715
35982
  }
35716
35983
  }
35717
35984
  function startFileIndexWatcher(cwd = getBridgeRoot()) {
35718
- const resolved = path26.resolve(cwd);
35985
+ const resolved = path27.resolve(cwd);
35719
35986
  void buildFileIndexAsync(resolved).catch((e) => {
35720
35987
  console.error("[file-index] Initial index build failed:", e);
35721
35988
  });
@@ -35743,7 +36010,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
35743
36010
  }
35744
36011
 
35745
36012
  // src/connection/create-bridge-connection.ts
35746
- import * as path34 from "node:path";
36013
+ import * as path35 from "node:path";
35747
36014
 
35748
36015
  // src/dev-servers/manager/dev-server-manager.ts
35749
36016
  import { rm as rm2 } from "node:fs/promises";
@@ -35787,7 +36054,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
35787
36054
  }
35788
36055
 
35789
36056
  // src/dev-servers/process/wire-dev-server-child-process.ts
35790
- import fs22 from "node:fs";
36057
+ import fs23 from "node:fs";
35791
36058
 
35792
36059
  // src/dev-servers/manager/forward-pipe.ts
35793
36060
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -35823,7 +36090,7 @@ function wireDevServerChildProcess(d) {
35823
36090
  d.setPollInterval(void 0);
35824
36091
  return;
35825
36092
  }
35826
- fs22.readFile(d.mergedLogPath, (err, buf) => {
36093
+ fs23.readFile(d.mergedLogPath, (err, buf) => {
35827
36094
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
35828
36095
  if (buf.length <= d.mergedReadPos.value) return;
35829
36096
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -35861,7 +36128,7 @@ ${errTail}` : ""}`);
35861
36128
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
35862
36129
  };
35863
36130
  if (mergedPath) {
35864
- fs22.readFile(mergedPath, (err, buf) => {
36131
+ fs23.readFile(mergedPath, (err, buf) => {
35865
36132
  if (!err && buf.length > d.mergedReadPos.value) {
35866
36133
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
35867
36134
  if (chunk.length > 0) {
@@ -35963,13 +36230,13 @@ function parseDevServerDefs(servers) {
35963
36230
  }
35964
36231
 
35965
36232
  // src/dev-servers/manager/shell-spawn/utils.ts
35966
- import fs23 from "node:fs";
36233
+ import fs24 from "node:fs";
35967
36234
  function isSpawnEbadf(e) {
35968
36235
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
35969
36236
  }
35970
36237
  function rmDirQuiet(dir) {
35971
36238
  try {
35972
- fs23.rmSync(dir, { recursive: true, force: true });
36239
+ fs24.rmSync(dir, { recursive: true, force: true });
35973
36240
  } catch {
35974
36241
  }
35975
36242
  }
@@ -35977,7 +36244,7 @@ var cachedDevNullReadFd;
35977
36244
  function devNullReadFd() {
35978
36245
  if (cachedDevNullReadFd === void 0) {
35979
36246
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
35980
- cachedDevNullReadFd = fs23.openSync(devPath, "r");
36247
+ cachedDevNullReadFd = fs24.openSync(devPath, "r");
35981
36248
  }
35982
36249
  return cachedDevNullReadFd;
35983
36250
  }
@@ -36051,15 +36318,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
36051
36318
 
36052
36319
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
36053
36320
  import { spawn as spawn6 } from "node:child_process";
36054
- import fs24 from "node:fs";
36321
+ import fs25 from "node:fs";
36055
36322
  import { tmpdir } from "node:os";
36056
- import path27 from "node:path";
36323
+ import path28 from "node:path";
36057
36324
  function trySpawnMergedLogFile(command, env, cwd, signal) {
36058
- const tmpRoot = fs24.mkdtempSync(path27.join(tmpdir(), "ba-devsrv-log-"));
36059
- const logPath = path27.join(tmpRoot, "combined.log");
36325
+ const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir(), "ba-devsrv-log-"));
36326
+ const logPath = path28.join(tmpRoot, "combined.log");
36060
36327
  let logFd;
36061
36328
  try {
36062
- logFd = fs24.openSync(logPath, "a");
36329
+ logFd = fs25.openSync(logPath, "a");
36063
36330
  } catch {
36064
36331
  rmDirQuiet(tmpRoot);
36065
36332
  return null;
@@ -36078,7 +36345,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
36078
36345
  } else {
36079
36346
  proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
36080
36347
  }
36081
- fs24.closeSync(logFd);
36348
+ fs25.closeSync(logFd);
36082
36349
  return {
36083
36350
  proc,
36084
36351
  pipedStdoutStderr: true,
@@ -36087,7 +36354,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
36087
36354
  };
36088
36355
  } catch (e) {
36089
36356
  try {
36090
- fs24.closeSync(logFd);
36357
+ fs25.closeSync(logFd);
36091
36358
  } catch {
36092
36359
  }
36093
36360
  rmDirQuiet(tmpRoot);
@@ -36098,22 +36365,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
36098
36365
 
36099
36366
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
36100
36367
  import { spawn as spawn7 } from "node:child_process";
36101
- import fs25 from "node:fs";
36368
+ import fs26 from "node:fs";
36102
36369
  import { tmpdir as tmpdir2 } from "node:os";
36103
- import path28 from "node:path";
36370
+ import path29 from "node:path";
36104
36371
  function shSingleQuote(s) {
36105
36372
  return `'${s.replace(/'/g, `'\\''`)}'`;
36106
36373
  }
36107
36374
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
36108
- const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir2(), "ba-devsrv-sh-"));
36109
- const logPath = path28.join(tmpRoot, "combined.log");
36110
- const innerPath = path28.join(tmpRoot, "_cmd.sh");
36111
- const runnerPath = path28.join(tmpRoot, "_run.sh");
36375
+ const tmpRoot = fs26.mkdtempSync(path29.join(tmpdir2(), "ba-devsrv-sh-"));
36376
+ const logPath = path29.join(tmpRoot, "combined.log");
36377
+ const innerPath = path29.join(tmpRoot, "_cmd.sh");
36378
+ const runnerPath = path29.join(tmpRoot, "_run.sh");
36112
36379
  try {
36113
- fs25.writeFileSync(innerPath, `#!/bin/sh
36380
+ fs26.writeFileSync(innerPath, `#!/bin/sh
36114
36381
  ${command}
36115
36382
  `);
36116
- fs25.writeFileSync(
36383
+ fs26.writeFileSync(
36117
36384
  runnerPath,
36118
36385
  `#!/bin/sh
36119
36386
  cd ${shSingleQuote(cwd)}
@@ -36139,13 +36406,13 @@ cd ${shSingleQuote(cwd)}
36139
36406
  }
36140
36407
  }
36141
36408
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
36142
- const tmpRoot = fs25.mkdtempSync(path28.join(tmpdir2(), "ba-devsrv-sh-"));
36143
- const logPath = path28.join(tmpRoot, "combined.log");
36144
- const runnerPath = path28.join(tmpRoot, "_run.bat");
36409
+ const tmpRoot = fs26.mkdtempSync(path29.join(tmpdir2(), "ba-devsrv-sh-"));
36410
+ const logPath = path29.join(tmpRoot, "combined.log");
36411
+ const runnerPath = path29.join(tmpRoot, "_run.bat");
36145
36412
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
36146
36413
  const com = process.env.ComSpec || "cmd.exe";
36147
36414
  try {
36148
- fs25.writeFileSync(
36415
+ fs26.writeFileSync(
36149
36416
  runnerPath,
36150
36417
  `@ECHO OFF\r
36151
36418
  CD /D ${q(cwd)}\r
@@ -37082,30 +37349,30 @@ function createOnBridgeIdentified(opts) {
37082
37349
  }
37083
37350
 
37084
37351
  // src/skills/discover-local-agent-skills.ts
37085
- import fs26 from "node:fs";
37086
- import path29 from "node:path";
37352
+ import fs27 from "node:fs";
37353
+ import path30 from "node:path";
37087
37354
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
37088
37355
  function discoverLocalSkills(cwd) {
37089
37356
  const out = [];
37090
37357
  const seenKeys = /* @__PURE__ */ new Set();
37091
37358
  for (const rel of SKILL_DISCOVERY_ROOTS) {
37092
- const base = path29.join(cwd, rel);
37093
- if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
37359
+ const base = path30.join(cwd, rel);
37360
+ if (!fs27.existsSync(base) || !fs27.statSync(base).isDirectory()) continue;
37094
37361
  let entries = [];
37095
37362
  try {
37096
- entries = fs26.readdirSync(base);
37363
+ entries = fs27.readdirSync(base);
37097
37364
  } catch {
37098
37365
  continue;
37099
37366
  }
37100
37367
  for (const name of entries) {
37101
- const dir = path29.join(base, name);
37368
+ const dir = path30.join(base, name);
37102
37369
  try {
37103
- if (!fs26.statSync(dir).isDirectory()) continue;
37370
+ if (!fs27.statSync(dir).isDirectory()) continue;
37104
37371
  } catch {
37105
37372
  continue;
37106
37373
  }
37107
- const skillMd = path29.join(dir, "SKILL.md");
37108
- if (!fs26.existsSync(skillMd)) continue;
37374
+ const skillMd = path30.join(dir, "SKILL.md");
37375
+ if (!fs27.existsSync(skillMd)) continue;
37109
37376
  const key = `${rel}/${name}`;
37110
37377
  if (seenKeys.has(key)) continue;
37111
37378
  seenKeys.add(key);
@@ -37117,23 +37384,23 @@ function discoverLocalSkills(cwd) {
37117
37384
  function discoverSkillLayoutRoots(cwd) {
37118
37385
  const roots = [];
37119
37386
  for (const rel of SKILL_DISCOVERY_ROOTS) {
37120
- const base = path29.join(cwd, rel);
37121
- if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
37387
+ const base = path30.join(cwd, rel);
37388
+ if (!fs27.existsSync(base) || !fs27.statSync(base).isDirectory()) continue;
37122
37389
  let entries = [];
37123
37390
  try {
37124
- entries = fs26.readdirSync(base);
37391
+ entries = fs27.readdirSync(base);
37125
37392
  } catch {
37126
37393
  continue;
37127
37394
  }
37128
37395
  const skills2 = [];
37129
37396
  for (const name of entries) {
37130
- const dir = path29.join(base, name);
37397
+ const dir = path30.join(base, name);
37131
37398
  try {
37132
- if (!fs26.statSync(dir).isDirectory()) continue;
37399
+ if (!fs27.statSync(dir).isDirectory()) continue;
37133
37400
  } catch {
37134
37401
  continue;
37135
37402
  }
37136
- if (!fs26.existsSync(path29.join(dir, "SKILL.md"))) continue;
37403
+ if (!fs27.existsSync(path30.join(dir, "SKILL.md"))) continue;
37137
37404
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
37138
37405
  skills2.push({ name, relPath });
37139
37406
  }
@@ -37315,7 +37582,7 @@ var handleAgentConfigMessage = (msg, deps) => {
37315
37582
  };
37316
37583
 
37317
37584
  // src/prompt-turn-queue/runner.ts
37318
- import fs29 from "node:fs";
37585
+ import fs30 from "node:fs";
37319
37586
 
37320
37587
  // src/prompt-turn-queue/client-report.ts
37321
37588
  function sendPromptQueueClientReport(ws, queues) {
@@ -37325,13 +37592,13 @@ function sendPromptQueueClientReport(ws, queues) {
37325
37592
  }
37326
37593
 
37327
37594
  // src/prompt-turn-queue/disk-store.ts
37328
- import fs28 from "node:fs";
37595
+ import fs29 from "node:fs";
37329
37596
 
37330
37597
  // src/prompt-turn-queue/paths.ts
37331
37598
  import crypto3 from "node:crypto";
37332
- import fs27 from "node:fs";
37333
- import path30 from "node:path";
37334
- import os6 from "node:os";
37599
+ import fs28 from "node:fs";
37600
+ import path31 from "node:path";
37601
+ import os7 from "node:os";
37335
37602
  var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
37336
37603
  function queueStateFileSlug(queueKey) {
37337
37604
  if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
@@ -37339,15 +37606,15 @@ function queueStateFileSlug(queueKey) {
37339
37606
  }
37340
37607
  function getPromptQueuesDirectory() {
37341
37608
  const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
37342
- if (override) return path30.resolve(override);
37343
- return path30.join(os6.homedir(), ".buildautomaton", "queues");
37609
+ if (override) return path31.resolve(override);
37610
+ return path31.join(os7.homedir(), ".buildautomaton", "queues");
37344
37611
  }
37345
37612
  function ensurePromptQueuesDirectory() {
37346
37613
  const dir = getPromptQueuesDirectory();
37347
- if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
37614
+ if (!fs28.existsSync(dir)) fs28.mkdirSync(dir, { recursive: true });
37348
37615
  }
37349
37616
  function queueStateFilePath(queueKey) {
37350
- return path30.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
37617
+ return path31.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
37351
37618
  }
37352
37619
 
37353
37620
  // src/prompt-turn-queue/disk-store.ts
@@ -37372,7 +37639,7 @@ function parsePersistedQueueFile(raw) {
37372
37639
  function readPersistedQueue(queueKey) {
37373
37640
  const p = queueStateFilePath(queueKey);
37374
37641
  try {
37375
- return parsePersistedQueueFile(fs28.readFileSync(p, "utf8"));
37642
+ return parsePersistedQueueFile(fs29.readFileSync(p, "utf8"));
37376
37643
  } catch {
37377
37644
  return null;
37378
37645
  }
@@ -37380,7 +37647,7 @@ function readPersistedQueue(queueKey) {
37380
37647
  function writePersistedQueue(file2) {
37381
37648
  ensurePromptQueuesDirectory();
37382
37649
  const p = queueStateFilePath(file2.queueKey);
37383
- fs28.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
37650
+ fs29.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
37384
37651
  }
37385
37652
  function mergeServerQueueSnapshot(queueKey, serverTurns) {
37386
37653
  const prev = readPersistedQueue(queueKey);
@@ -37438,7 +37705,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
37438
37705
  const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
37439
37706
  const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
37440
37707
  const file2 = snapshotFilePath(agentBase, tid);
37441
- if (!fs29.existsSync(file2)) {
37708
+ if (!fs30.existsSync(file2)) {
37442
37709
  deps.log(
37443
37710
  `[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
37444
37711
  );
@@ -37661,9 +37928,9 @@ function parseChangeSummarySnapshots(raw) {
37661
37928
  for (const item of raw) {
37662
37929
  if (!item || typeof item !== "object") continue;
37663
37930
  const o = item;
37664
- const path36 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
37665
- if (!path36) continue;
37666
- const row = { path: path36 };
37931
+ const path37 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
37932
+ if (!path37) continue;
37933
+ const row = { path: path37 };
37667
37934
  if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
37668
37935
  if (typeof o.oldText === "string") row.oldText = o.oldText;
37669
37936
  if (typeof o.newText === "string") row.newText = o.newText;
@@ -37864,8 +38131,8 @@ function randomSecret() {
37864
38131
  }
37865
38132
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
37866
38133
  }
37867
- async function requestPreviewApi(port, secret, method, path36, body) {
37868
- const url2 = `http://127.0.0.1:${port}${path36}`;
38134
+ async function requestPreviewApi(port, secret, method, path37, body) {
38135
+ const url2 = `http://127.0.0.1:${port}${path37}`;
37869
38136
  const headers = {
37870
38137
  [PREVIEW_SECRET_HEADER]: secret,
37871
38138
  "Content-Type": "application/json"
@@ -37877,7 +38144,7 @@ async function requestPreviewApi(port, secret, method, path36, body) {
37877
38144
  });
37878
38145
  const data = await res.json().catch(() => ({}));
37879
38146
  if (!res.ok) {
37880
- throw new Error(data?.error ?? `Preview API ${method} ${path36}: ${res.status}`);
38147
+ throw new Error(data?.error ?? `Preview API ${method} ${path37}: ${res.status}`);
37881
38148
  }
37882
38149
  return data;
37883
38150
  }
@@ -38042,15 +38309,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
38042
38309
  };
38043
38310
 
38044
38311
  // src/files/list-dir.ts
38045
- import fs30 from "node:fs";
38046
- import path32 from "node:path";
38312
+ import fs31 from "node:fs";
38313
+ import path33 from "node:path";
38047
38314
 
38048
38315
  // src/files/ensure-under-cwd.ts
38049
- import path31 from "node:path";
38316
+ import path32 from "node:path";
38050
38317
  function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
38051
- const normalized = path31.normalize(relativePath).replace(/^(\.\/)+/, "");
38052
- const resolved = path31.resolve(cwd, normalized);
38053
- if (!resolved.startsWith(cwd + path31.sep) && resolved !== cwd) {
38318
+ const normalized = path32.normalize(relativePath).replace(/^(\.\/)+/, "");
38319
+ const resolved = path32.resolve(cwd, normalized);
38320
+ if (!resolved.startsWith(cwd + path32.sep) && resolved !== cwd) {
38054
38321
  return null;
38055
38322
  }
38056
38323
  return resolved;
@@ -38064,7 +38331,7 @@ async function listDirAsync(relativePath) {
38064
38331
  return { error: "Path is outside working directory" };
38065
38332
  }
38066
38333
  try {
38067
- const names = await fs30.promises.readdir(resolved, { withFileTypes: true });
38334
+ const names = await fs31.promises.readdir(resolved, { withFileTypes: true });
38068
38335
  const visible = names.filter((d) => !d.name.startsWith("."));
38069
38336
  const entries = [];
38070
38337
  for (let i = 0; i < visible.length; i++) {
@@ -38072,12 +38339,12 @@ async function listDirAsync(relativePath) {
38072
38339
  await yieldToEventLoop();
38073
38340
  }
38074
38341
  const d = visible[i];
38075
- const entryPath = path32.join(relativePath || ".", d.name).replace(/\\/g, "/");
38076
- const fullPath = path32.join(resolved, d.name);
38342
+ const entryPath = path33.join(relativePath || ".", d.name).replace(/\\/g, "/");
38343
+ const fullPath = path33.join(resolved, d.name);
38077
38344
  let isDir = d.isDirectory();
38078
38345
  if (d.isSymbolicLink()) {
38079
38346
  try {
38080
- const targetStat = await fs30.promises.stat(fullPath);
38347
+ const targetStat = await fs31.promises.stat(fullPath);
38081
38348
  isDir = targetStat.isDirectory();
38082
38349
  } catch {
38083
38350
  isDir = false;
@@ -38102,25 +38369,25 @@ async function listDirAsync(relativePath) {
38102
38369
  }
38103
38370
 
38104
38371
  // src/files/read-file.ts
38105
- import fs31 from "node:fs";
38372
+ import fs32 from "node:fs";
38106
38373
  import { StringDecoder } from "node:string_decoder";
38107
38374
  function resolveFilePath(relativePath) {
38108
38375
  const resolved = ensureUnderCwd(relativePath, getBridgeRoot());
38109
38376
  if (!resolved) return { error: "Path is outside working directory" };
38110
38377
  let real;
38111
38378
  try {
38112
- real = fs31.realpathSync(resolved);
38379
+ real = fs32.realpathSync(resolved);
38113
38380
  } catch {
38114
38381
  real = resolved;
38115
38382
  }
38116
- const stat3 = fs31.statSync(real);
38383
+ const stat3 = fs32.statSync(real);
38117
38384
  if (!stat3.isFile()) return { error: "Not a file" };
38118
38385
  return real;
38119
38386
  }
38120
38387
  var LINE_CHUNK_SIZE = 64 * 1024;
38121
38388
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
38122
- const fileSize = fs31.statSync(filePath).size;
38123
- const fd = fs31.openSync(filePath, "r");
38389
+ const fileSize = fs32.statSync(filePath).size;
38390
+ const fd = fs32.openSync(filePath, "r");
38124
38391
  const bufSize = 64 * 1024;
38125
38392
  const buf = Buffer.alloc(bufSize);
38126
38393
  const decoder = new StringDecoder("utf8");
@@ -38133,7 +38400,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
38133
38400
  let line0Accum = "";
38134
38401
  try {
38135
38402
  let bytesRead;
38136
- while (!done && (bytesRead = fs31.readSync(fd, buf, 0, bufSize, null)) > 0) {
38403
+ while (!done && (bytesRead = fs32.readSync(fd, buf, 0, bufSize, null)) > 0) {
38137
38404
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
38138
38405
  partial2 = "";
38139
38406
  let lineStart = 0;
@@ -38268,7 +38535,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
38268
38535
  }
38269
38536
  return { content: resultLines.join("\n"), size: fileSize };
38270
38537
  } finally {
38271
- fs31.closeSync(fd);
38538
+ fs32.closeSync(fd);
38272
38539
  }
38273
38540
  }
38274
38541
  function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
@@ -38279,8 +38546,8 @@ function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize =
38279
38546
  if (hasRange) {
38280
38547
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
38281
38548
  }
38282
- const stat3 = fs31.statSync(result);
38283
- const raw = fs31.readFileSync(result, "utf8");
38549
+ const stat3 = fs32.statSync(result);
38550
+ const raw = fs32.readFileSync(result, "utf8");
38284
38551
  const lines = raw.split(/\r?\n/);
38285
38552
  return { content: raw, totalLines: lines.length, size: stat3.size };
38286
38553
  } catch (err) {
@@ -38398,8 +38665,8 @@ function handleSkillLayoutRequest(msg, deps) {
38398
38665
  }
38399
38666
 
38400
38667
  // src/skills/install-remote-skills.ts
38401
- import fs32 from "node:fs";
38402
- import path33 from "node:path";
38668
+ import fs33 from "node:fs";
38669
+ import path34 from "node:path";
38403
38670
  function installRemoteSkills(cwd, targetDir, items) {
38404
38671
  const installed2 = [];
38405
38672
  if (!Array.isArray(items)) {
@@ -38410,15 +38677,15 @@ function installRemoteSkills(cwd, targetDir, items) {
38410
38677
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
38411
38678
  continue;
38412
38679
  }
38413
- const skillDir = path33.join(cwd, targetDir, item.skillName);
38680
+ const skillDir = path34.join(cwd, targetDir, item.skillName);
38414
38681
  for (const f of item.files) {
38415
38682
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
38416
- const dest = path33.join(skillDir, f.path);
38417
- fs32.mkdirSync(path33.dirname(dest), { recursive: true });
38683
+ const dest = path34.join(skillDir, f.path);
38684
+ fs33.mkdirSync(path34.dirname(dest), { recursive: true });
38418
38685
  if (f.text !== void 0) {
38419
- fs32.writeFileSync(dest, f.text, "utf8");
38686
+ fs33.writeFileSync(dest, f.text, "utf8");
38420
38687
  } else if (f.base64) {
38421
- fs32.writeFileSync(dest, Buffer.from(f.base64, "base64"));
38688
+ fs33.writeFileSync(dest, Buffer.from(f.base64, "base64"));
38422
38689
  }
38423
38690
  }
38424
38691
  installed2.push({
@@ -38568,7 +38835,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
38568
38835
  };
38569
38836
 
38570
38837
  // src/routing/handlers/revert-turn-snapshot.ts
38571
- import * as fs33 from "node:fs";
38838
+ import * as fs34 from "node:fs";
38572
38839
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
38573
38840
  const id = typeof msg.id === "string" ? msg.id : "";
38574
38841
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -38580,7 +38847,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
38580
38847
  if (!s) return;
38581
38848
  const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
38582
38849
  const file2 = snapshotFilePath(agentBase, turnId);
38583
- if (!fs33.existsSync(file2)) {
38850
+ if (!fs34.existsSync(file2)) {
38584
38851
  sendWsMessage(s, {
38585
38852
  type: "revert_turn_snapshot_result",
38586
38853
  id,
@@ -38953,8 +39220,8 @@ async function createBridgeConnection(options) {
38953
39220
  getCloudAccessToken: () => tokens.accessToken
38954
39221
  };
38955
39222
  const identifyReportedPaths = {
38956
- bridgeRootPath: path34.resolve(getBridgeRoot()),
38957
- worktreesRootPath: path34.resolve(worktreesRootPath)
39223
+ bridgeRootPath: path35.resolve(getBridgeRoot()),
39224
+ worktreesRootPath: path35.resolve(worktreesRootPath)
38958
39225
  };
38959
39226
  const { connect } = createMainBridgeWebSocketLifecycle({
38960
39227
  state,
@@ -39190,9 +39457,9 @@ async function runCliAction(program2, opts) {
39190
39457
  const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
39191
39458
  const bridgeRootOpt = (opts.bridgeRoot && typeof opts.bridgeRoot === "string" && opts.bridgeRoot.trim() ? opts.bridgeRoot.trim() : null) ?? (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim() ? opts.cwd.trim() : null);
39192
39459
  if (bridgeRootOpt) {
39193
- const resolvedBridgeRoot = path35.resolve(process.cwd(), bridgeRootOpt);
39460
+ const resolvedBridgeRoot = path36.resolve(process.cwd(), bridgeRootOpt);
39194
39461
  try {
39195
- const st = fs34.statSync(resolvedBridgeRoot);
39462
+ const st = fs35.statSync(resolvedBridgeRoot);
39196
39463
  if (!st.isDirectory()) {
39197
39464
  console.error(`Bridge root is not a directory: ${resolvedBridgeRoot}`);
39198
39465
  process.exit(1);
@@ -39212,7 +39479,7 @@ async function runCliAction(program2, opts) {
39212
39479
  );
39213
39480
  let worktreesRootPath;
39214
39481
  if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
39215
- worktreesRootPath = path35.resolve(opts.worktreesRoot.trim());
39482
+ worktreesRootPath = path36.resolve(opts.worktreesRoot.trim());
39216
39483
  }
39217
39484
  const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
39218
39485
  if (e2eCertificates) {