@buildautomaton/cli 0.1.13 → 0.1.14

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 childProcess = __require("node:child_process");
976
- var path30 = __require("node:path");
977
- var fs23 = __require("node:fs");
976
+ var path32 = __require("node:path");
977
+ var fs25 = __require("node:fs");
978
978
  var process2 = __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 = path30.resolve(baseDir, baseName);
1910
- if (fs23.existsSync(localBin)) return localBin;
1911
- if (sourceExt.includes(path30.extname(baseName))) return void 0;
1909
+ const localBin = path32.resolve(baseDir, baseName);
1910
+ if (fs25.existsSync(localBin)) return localBin;
1911
+ if (sourceExt.includes(path32.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
- (ext) => fs23.existsSync(`${localBin}${ext}`)
1913
+ (ext) => fs25.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 = fs23.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs25.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
1929
- executableDir = path30.resolve(
1930
- path30.dirname(resolvedScriptPath),
1929
+ executableDir = path32.resolve(
1930
+ path32.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 = path30.basename(
1937
+ const legacyName = path32.basename(
1938
1938
  this._scriptPath,
1939
- path30.extname(this._scriptPath)
1939
+ path32.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(path30.extname(executableFile));
1950
+ launchWithNode = sourceExt.includes(path32.extname(executableFile));
1951
1951
  let proc;
1952
1952
  if (process2.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 = path30.basename(filename, path30.extname(filename));
2790
+ this._name = path32.basename(filename, path32.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(path31) {
2805
- if (path31 === void 0) return this._executableDir;
2806
- this._executableDir = path31;
2804
+ executableDir(path33) {
2805
+ if (path33 === void 0) return this._executableDir;
2806
+ this._executableDir = path33;
2807
2807
  return this;
2808
2808
  }
2809
2809
  /**
@@ -7423,10 +7423,10 @@ var require_src2 = __commonJS({
7423
7423
  var fs_1 = __require("fs");
7424
7424
  var debug_1 = __importDefault(require_src());
7425
7425
  var log2 = debug_1.default("@kwsites/file-exists");
7426
- function check2(path30, isFile, isDirectory) {
7427
- log2(`checking %s`, path30);
7426
+ function check2(path32, isFile, isDirectory) {
7427
+ log2(`checking %s`, path32);
7428
7428
  try {
7429
- const stat2 = fs_1.statSync(path30);
7429
+ const stat2 = fs_1.statSync(path32);
7430
7430
  if (stat2.isFile() && isFile) {
7431
7431
  log2(`[OK] path represents a file`);
7432
7432
  return true;
@@ -7446,8 +7446,8 @@ var require_src2 = __commonJS({
7446
7446
  throw e;
7447
7447
  }
7448
7448
  }
7449
- function exists2(path30, type = exports.READABLE) {
7450
- return check2(path30, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
7449
+ function exists2(path32, type = exports.READABLE) {
7450
+ return check2(path32, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
7451
7451
  }
7452
7452
  exports.exists = exists2;
7453
7453
  exports.FILE = 1;
@@ -7922,8 +7922,8 @@ var init_parseUtil = __esm({
7922
7922
  init_errors();
7923
7923
  init_en();
7924
7924
  makeIssue = (params) => {
7925
- const { data, path: path30, errorMaps, issueData } = params;
7926
- const fullPath = [...path30, ...issueData.path || []];
7925
+ const { data, path: path32, errorMaps, issueData } = params;
7926
+ const fullPath = [...path32, ...issueData.path || []];
7927
7927
  const fullIssue = {
7928
7928
  ...issueData,
7929
7929
  path: fullPath
@@ -8231,11 +8231,11 @@ var init_types = __esm({
8231
8231
  init_parseUtil();
8232
8232
  init_util2();
8233
8233
  ParseInputLazyPath = class {
8234
- constructor(parent, value, path30, key) {
8234
+ constructor(parent, value, path32, key) {
8235
8235
  this._cachedPath = [];
8236
8236
  this.parent = parent;
8237
8237
  this.data = value;
8238
- this._path = path30;
8238
+ this._path = path32;
8239
8239
  this._key = key;
8240
8240
  }
8241
8241
  get path() {
@@ -11850,15 +11850,15 @@ function assignProp(target, prop, value) {
11850
11850
  configurable: true
11851
11851
  });
11852
11852
  }
11853
- function getElementAtPath(obj, path30) {
11854
- if (!path30)
11853
+ function getElementAtPath(obj, path32) {
11854
+ if (!path32)
11855
11855
  return obj;
11856
- return path30.reduce((acc, key) => acc?.[key], obj);
11856
+ return path32.reduce((acc, key) => acc?.[key], obj);
11857
11857
  }
11858
11858
  function promiseAllObject(promisesObj) {
11859
11859
  const keys = Object.keys(promisesObj);
11860
- const promises = keys.map((key) => promisesObj[key]);
11861
- return Promise.all(promises).then((results) => {
11860
+ const promises3 = keys.map((key) => promisesObj[key]);
11861
+ return Promise.all(promises3).then((results) => {
11862
11862
  const resolvedObj = {};
11863
11863
  for (let i = 0; i < keys.length; i++) {
11864
11864
  resolvedObj[keys[i]] = results[i];
@@ -12102,11 +12102,11 @@ function aborted(x, startIndex = 0) {
12102
12102
  }
12103
12103
  return false;
12104
12104
  }
12105
- function prefixIssues(path30, issues) {
12105
+ function prefixIssues(path32, issues) {
12106
12106
  return issues.map((iss) => {
12107
12107
  var _a2;
12108
12108
  (_a2 = iss).path ?? (_a2.path = []);
12109
- iss.path.unshift(path30);
12109
+ iss.path.unshift(path32);
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, path30 = []) => {
12298
+ const processError = (error41, path32 = []) => {
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 = [...path30, ...issue2.path];
12308
+ const fullpath = [...path32, ...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(path30) {
12338
+ function toDotPath(path32) {
12339
12339
  const segs = [];
12340
- for (const seg of path30) {
12340
+ for (const seg of path32) {
12341
12341
  if (typeof seg === "number")
12342
12342
  segs.push(`[${seg}]`);
12343
12343
  else if (typeof seg === "symbol")
@@ -24800,8 +24800,8 @@ var init_acp = __esm({
24800
24800
  this.#requestHandler = requestHandler;
24801
24801
  this.#notificationHandler = notificationHandler;
24802
24802
  this.#stream = stream;
24803
- this.#closedPromise = new Promise((resolve15) => {
24804
- this.#abortController.signal.addEventListener("abort", () => resolve15());
24803
+ this.#closedPromise = new Promise((resolve16) => {
24804
+ this.#abortController.signal.addEventListener("abort", () => resolve16());
24805
24805
  });
24806
24806
  this.#receive();
24807
24807
  }
@@ -24950,8 +24950,8 @@ var init_acp = __esm({
24950
24950
  }
24951
24951
  async sendRequest(method, params) {
24952
24952
  const id = this.#nextRequestId++;
24953
- const responsePromise = new Promise((resolve15, reject) => {
24954
- this.#pendingResponses.set(id, { resolve: resolve15, reject });
24953
+ const responsePromise = new Promise((resolve16, reject) => {
24954
+ this.#pendingResponses.set(id, { resolve: resolve16, reject });
24955
24955
  });
24956
24956
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
24957
24957
  return responsePromise;
@@ -25047,8 +25047,8 @@ var init_acp = __esm({
25047
25047
  });
25048
25048
 
25049
25049
  // src/cli.ts
25050
- import * as fs22 from "node:fs";
25051
- import * as path29 from "node:path";
25050
+ import * as fs24 from "node:fs";
25051
+ import * as path31 from "node:path";
25052
25052
 
25053
25053
  // ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
25054
25054
  var import_index = __toESM(require_commander(), 1);
@@ -25169,6 +25169,19 @@ function logImmediate(line) {
25169
25169
  `);
25170
25170
  }
25171
25171
 
25172
+ // src/process-bridge-resilience.ts
25173
+ var installed = false;
25174
+ function installBridgeProcessResilience() {
25175
+ if (installed) return;
25176
+ installed = true;
25177
+ process.on("uncaughtException", (err) => {
25178
+ logImmediate(`[bridge] uncaughtException \u2014 continuing: ${err.stack ?? String(err)}`);
25179
+ });
25180
+ process.on("unhandledRejection", (reason) => {
25181
+ logImmediate(`[bridge] unhandledRejection \u2014 continuing: ${reason instanceof Error ? reason.stack : String(reason)}`);
25182
+ });
25183
+ }
25184
+
25172
25185
  // ../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
25173
25186
  var import_stream = __toESM(require_stream(), 1);
25174
25187
  var import_receiver = __toESM(require_receiver(), 1);
@@ -25527,8 +25540,8 @@ function runPendingAuth(options) {
25527
25540
  let hasOpenedBrowser = false;
25528
25541
  let resolved = false;
25529
25542
  let resolveAuth;
25530
- const authPromise = new Promise((resolve15) => {
25531
- resolveAuth = resolve15;
25543
+ const authPromise = new Promise((resolve16) => {
25544
+ resolveAuth = resolve16;
25532
25545
  });
25533
25546
  let reconnectAttempt = 0;
25534
25547
  const signInQuiet = createEmptyReconnectQuietSlot();
@@ -25650,7 +25663,7 @@ function runPendingAuth(options) {
25650
25663
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
25651
25664
  const say = log2 ?? logImmediate;
25652
25665
  say("Cleaning up connections\u2026");
25653
- await new Promise((resolve15) => setImmediate(resolve15));
25666
+ await new Promise((resolve16) => setImmediate(resolve16));
25654
25667
  state.closedByUser = true;
25655
25668
  clearReconnectQuietTimer(state.mainQuiet);
25656
25669
  clearReconnectQuietTimer(state.firehoseQuiet);
@@ -25772,8 +25785,8 @@ function pathspec(...paths) {
25772
25785
  cache.set(key, paths);
25773
25786
  return key;
25774
25787
  }
25775
- function isPathSpec(path30) {
25776
- return path30 instanceof String && cache.has(path30);
25788
+ function isPathSpec(path32) {
25789
+ return path32 instanceof String && cache.has(path32);
25777
25790
  }
25778
25791
  function toPaths(pathSpec) {
25779
25792
  return cache.get(pathSpec) || [];
@@ -25862,8 +25875,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
25862
25875
  function forEachLineWithContent(input, callback) {
25863
25876
  return toLinesWithContent(input, true).map((line) => callback(line));
25864
25877
  }
25865
- function folderExists(path30) {
25866
- return (0, import_file_exists.exists)(path30, import_file_exists.FOLDER);
25878
+ function folderExists(path32) {
25879
+ return (0, import_file_exists.exists)(path32, import_file_exists.FOLDER);
25867
25880
  }
25868
25881
  function append(target, item) {
25869
25882
  if (Array.isArray(target)) {
@@ -26267,8 +26280,8 @@ function checkIsRepoRootTask() {
26267
26280
  commands,
26268
26281
  format: "utf-8",
26269
26282
  onError,
26270
- parser(path30) {
26271
- return /^\.(git)?$/.test(path30.trim());
26283
+ parser(path32) {
26284
+ return /^\.(git)?$/.test(path32.trim());
26272
26285
  }
26273
26286
  };
26274
26287
  }
@@ -26702,11 +26715,11 @@ function parseGrep(grep) {
26702
26715
  const paths = /* @__PURE__ */ new Set();
26703
26716
  const results = {};
26704
26717
  forEachLineWithContent(grep, (input) => {
26705
- const [path30, line, preview] = input.split(NULL);
26706
- paths.add(path30);
26707
- (results[path30] = results[path30] || []).push({
26718
+ const [path32, line, preview] = input.split(NULL);
26719
+ paths.add(path32);
26720
+ (results[path32] = results[path32] || []).push({
26708
26721
  line: asNumber(line),
26709
- path: path30,
26722
+ path: path32,
26710
26723
  preview
26711
26724
  });
26712
26725
  });
@@ -27471,14 +27484,14 @@ var init_hash_object = __esm2({
27471
27484
  init_task();
27472
27485
  }
27473
27486
  });
27474
- function parseInit(bare, path30, text) {
27487
+ function parseInit(bare, path32, text) {
27475
27488
  const response = String(text).trim();
27476
27489
  let result;
27477
27490
  if (result = initResponseRegex.exec(response)) {
27478
- return new InitSummary(bare, path30, false, result[1]);
27491
+ return new InitSummary(bare, path32, false, result[1]);
27479
27492
  }
27480
27493
  if (result = reInitResponseRegex.exec(response)) {
27481
- return new InitSummary(bare, path30, true, result[1]);
27494
+ return new InitSummary(bare, path32, true, result[1]);
27482
27495
  }
27483
27496
  let gitDir = "";
27484
27497
  const tokens = response.split(" ");
@@ -27489,7 +27502,7 @@ function parseInit(bare, path30, text) {
27489
27502
  break;
27490
27503
  }
27491
27504
  }
27492
- return new InitSummary(bare, path30, /^re/i.test(response), gitDir);
27505
+ return new InitSummary(bare, path32, /^re/i.test(response), gitDir);
27493
27506
  }
27494
27507
  var InitSummary;
27495
27508
  var initResponseRegex;
@@ -27498,9 +27511,9 @@ var init_InitSummary = __esm2({
27498
27511
  "src/lib/responses/InitSummary.ts"() {
27499
27512
  "use strict";
27500
27513
  InitSummary = class {
27501
- constructor(bare, path30, existing, gitDir) {
27514
+ constructor(bare, path32, existing, gitDir) {
27502
27515
  this.bare = bare;
27503
- this.path = path30;
27516
+ this.path = path32;
27504
27517
  this.existing = existing;
27505
27518
  this.gitDir = gitDir;
27506
27519
  }
@@ -27512,7 +27525,7 @@ var init_InitSummary = __esm2({
27512
27525
  function hasBareCommand(command) {
27513
27526
  return command.includes(bareCommand);
27514
27527
  }
27515
- function initTask(bare = false, path30, customArgs) {
27528
+ function initTask(bare = false, path32, customArgs) {
27516
27529
  const commands = ["init", ...customArgs];
27517
27530
  if (bare && !hasBareCommand(commands)) {
27518
27531
  commands.splice(1, 0, bareCommand);
@@ -27521,7 +27534,7 @@ function initTask(bare = false, path30, customArgs) {
27521
27534
  commands,
27522
27535
  format: "utf-8",
27523
27536
  parser(text) {
27524
- return parseInit(commands.includes("--bare"), path30, text);
27537
+ return parseInit(commands.includes("--bare"), path32, text);
27525
27538
  }
27526
27539
  };
27527
27540
  }
@@ -28337,12 +28350,12 @@ var init_FileStatusSummary = __esm2({
28337
28350
  "use strict";
28338
28351
  fromPathRegex = /^(.+)\0(.+)$/;
28339
28352
  FileStatusSummary = class {
28340
- constructor(path30, index, working_dir) {
28341
- this.path = path30;
28353
+ constructor(path32, index, working_dir) {
28354
+ this.path = path32;
28342
28355
  this.index = index;
28343
28356
  this.working_dir = working_dir;
28344
28357
  if (index === "R" || working_dir === "R") {
28345
- const detail = fromPathRegex.exec(path30) || [null, path30, path30];
28358
+ const detail = fromPathRegex.exec(path32) || [null, path32, path32];
28346
28359
  this.from = detail[2] || "";
28347
28360
  this.path = detail[1] || "";
28348
28361
  }
@@ -28373,14 +28386,14 @@ function splitLine(result, lineStr) {
28373
28386
  default:
28374
28387
  return;
28375
28388
  }
28376
- function data(index, workingDir, path30) {
28389
+ function data(index, workingDir, path32) {
28377
28390
  const raw = `${index}${workingDir}`;
28378
28391
  const handler = parsers6.get(raw);
28379
28392
  if (handler) {
28380
- handler(result, path30);
28393
+ handler(result, path32);
28381
28394
  }
28382
28395
  if (raw !== "##" && raw !== "!!") {
28383
- result.files.push(new FileStatusSummary(path30, index, workingDir));
28396
+ result.files.push(new FileStatusSummary(path32, index, workingDir));
28384
28397
  }
28385
28398
  }
28386
28399
  }
@@ -28551,14 +28564,14 @@ var init_status = __esm2({
28551
28564
  ignoredOptions = ["--null", "-z"];
28552
28565
  }
28553
28566
  });
28554
- function versionResponse(major = 0, minor = 0, patch = 0, agent = "", installed = true) {
28567
+ function versionResponse(major = 0, minor = 0, patch = 0, agent = "", installed2 = true) {
28555
28568
  return Object.defineProperty(
28556
28569
  {
28557
28570
  major,
28558
28571
  minor,
28559
28572
  patch,
28560
28573
  agent,
28561
- installed
28574
+ installed: installed2
28562
28575
  },
28563
28576
  "toString",
28564
28577
  {
@@ -28689,9 +28702,9 @@ var init_simple_git_api = __esm2({
28689
28702
  next
28690
28703
  );
28691
28704
  }
28692
- hashObject(path30, write) {
28705
+ hashObject(path32, write) {
28693
28706
  return this._runTask(
28694
- hashObjectTask(path30, write === true),
28707
+ hashObjectTask(path32, write === true),
28695
28708
  trailingFunctionArgument(arguments)
28696
28709
  );
28697
28710
  }
@@ -29044,8 +29057,8 @@ var init_branch = __esm2({
29044
29057
  }
29045
29058
  });
29046
29059
  function toPath(input) {
29047
- const path30 = input.trim().replace(/^["']|["']$/g, "");
29048
- return path30 && normalize(path30);
29060
+ const path32 = input.trim().replace(/^["']|["']$/g, "");
29061
+ return path32 && normalize(path32);
29049
29062
  }
29050
29063
  var parseCheckIgnore;
29051
29064
  var init_CheckIgnore = __esm2({
@@ -29359,8 +29372,8 @@ __export2(sub_module_exports, {
29359
29372
  subModuleTask: () => subModuleTask,
29360
29373
  updateSubModuleTask: () => updateSubModuleTask
29361
29374
  });
29362
- function addSubModuleTask(repo, path30) {
29363
- return subModuleTask(["add", repo, path30]);
29375
+ function addSubModuleTask(repo, path32) {
29376
+ return subModuleTask(["add", repo, path32]);
29364
29377
  }
29365
29378
  function initSubModuleTask(customArgs) {
29366
29379
  return subModuleTask(["init", ...customArgs]);
@@ -29693,8 +29706,8 @@ var require_git = __commonJS2({
29693
29706
  }
29694
29707
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
29695
29708
  };
29696
- Git2.prototype.submoduleAdd = function(repo, path30, then) {
29697
- return this._runTask(addSubModuleTask2(repo, path30), trailingFunctionArgument2(arguments));
29709
+ Git2.prototype.submoduleAdd = function(repo, path32, then) {
29710
+ return this._runTask(addSubModuleTask2(repo, path32), trailingFunctionArgument2(arguments));
29698
29711
  };
29699
29712
  Git2.prototype.submoduleUpdate = function(args, then) {
29700
29713
  return this._runTask(
@@ -30839,7 +30852,7 @@ async function createSdkStdioAcpClient(options) {
30839
30852
  child.once("close", (code, signal) => {
30840
30853
  onAgentSubprocessExit?.({ code, signal });
30841
30854
  });
30842
- return new Promise((resolve15, reject) => {
30855
+ return new Promise((resolve16, reject) => {
30843
30856
  let initSettled = false;
30844
30857
  const settleReject = (err) => {
30845
30858
  if (initSettled) return;
@@ -30853,7 +30866,7 @@ async function createSdkStdioAcpClient(options) {
30853
30866
  const settleResolve = (handle) => {
30854
30867
  if (initSettled) return;
30855
30868
  initSettled = true;
30856
- resolve15(handle);
30869
+ resolve16(handle);
30857
30870
  };
30858
30871
  child.on("error", (err) => {
30859
30872
  settleReject(new Error(formatSpawnError(err, command[0])));
@@ -30889,8 +30902,8 @@ async function createSdkStdioAcpClient(options) {
30889
30902
  });
30890
30903
  } catch {
30891
30904
  }
30892
- return await new Promise((resolve16) => {
30893
- pendingPermissionResolvers.set(requestId, resolve16);
30905
+ return await new Promise((resolve17) => {
30906
+ pendingPermissionResolvers.set(requestId, resolve17);
30894
30907
  });
30895
30908
  },
30896
30909
  async readTextFile(params) {
@@ -30998,9 +31011,9 @@ async function createSdkStdioAcpClient(options) {
30998
31011
  }
30999
31012
  },
31000
31013
  async cancel() {
31001
- for (const [id, resolve16] of [...pendingPermissionResolvers.entries()]) {
31014
+ for (const [id, resolve17] of [...pendingPermissionResolvers.entries()]) {
31002
31015
  pendingPermissionResolvers.delete(id);
31003
- resolve16({ outcome: { outcome: "cancelled" } });
31016
+ resolve17({ outcome: { outcome: "cancelled" } });
31004
31017
  }
31005
31018
  try {
31006
31019
  await connection.cancel({ sessionId });
@@ -31016,10 +31029,10 @@ async function createSdkStdioAcpClient(options) {
31016
31029
  }
31017
31030
  },
31018
31031
  resolveRequest(requestId, result) {
31019
- const resolve16 = pendingPermissionResolvers.get(requestId);
31020
- if (!resolve16) return;
31032
+ const resolve17 = pendingPermissionResolvers.get(requestId);
31033
+ if (!resolve17) return;
31021
31034
  pendingPermissionResolvers.delete(requestId);
31022
- resolve16(result);
31035
+ resolve17(result);
31023
31036
  },
31024
31037
  disconnect() {
31025
31038
  child.kill();
@@ -31170,7 +31183,7 @@ async function createCursorAcpClient(options) {
31170
31183
  });
31171
31184
  const stderrCapture = createStderrCapture(child);
31172
31185
  child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
31173
- return new Promise((resolve15, reject) => {
31186
+ return new Promise((resolve16, reject) => {
31174
31187
  child.on("error", (err) => {
31175
31188
  child.kill();
31176
31189
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -31357,7 +31370,7 @@ async function createCursorAcpClient(options) {
31357
31370
  const newResult = await send("session/new", { cwd, mcpServers: [] });
31358
31371
  const sessionId = newResult?.sessionId ?? "";
31359
31372
  if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
31360
- resolve15({
31373
+ resolve16({
31361
31374
  sessionId,
31362
31375
  async sendPrompt(prompt, _options) {
31363
31376
  promptOutputBuffer = "";
@@ -32415,7 +32428,7 @@ async function createAcpManager(options) {
32415
32428
  }
32416
32429
 
32417
32430
  // src/worktrees/session-worktree-manager.ts
32418
- import * as path13 from "node:path";
32431
+ import * as path15 from "node:path";
32419
32432
  import os3 from "node:os";
32420
32433
 
32421
32434
  // src/worktrees/prepare-new-session-worktrees.ts
@@ -32582,7 +32595,7 @@ async function removeSessionWorktrees(paths, log2) {
32582
32595
  }
32583
32596
  }
32584
32597
 
32585
- // src/git/working-tree-status.ts
32598
+ // src/git/working-directory/status/working-tree-status.ts
32586
32599
  async function tryConfigGet(g, key) {
32587
32600
  try {
32588
32601
  const out = await g.raw(["config", "--get", key]);
@@ -32592,11 +32605,24 @@ async function tryConfigGet(g, key) {
32592
32605
  return null;
32593
32606
  }
32594
32607
  }
32608
+ async function revParseSafe(g, ref) {
32609
+ try {
32610
+ const v = (await g.raw(["rev-parse", ref])).trim();
32611
+ return v || null;
32612
+ } catch {
32613
+ return null;
32614
+ }
32615
+ }
32595
32616
  async function resolveRemoteTrackingRefForAhead(g) {
32596
32617
  try {
32597
- await g.raw(["rev-parse", "--verify", "@{u}"]);
32598
- return "@{u}";
32618
+ await g.raw(["rev-parse", "--verify", "HEAD@{upstream}"]);
32619
+ return "HEAD@{upstream}";
32599
32620
  } catch {
32621
+ try {
32622
+ await g.raw(["rev-parse", "--verify", "@{u}"]);
32623
+ return "@{u}";
32624
+ } catch {
32625
+ }
32600
32626
  }
32601
32627
  const branch = (await g.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim();
32602
32628
  if (!branch || branch === "HEAD") return null;
@@ -32619,16 +32645,76 @@ async function resolveRemoteTrackingRefForAhead(g) {
32619
32645
  return null;
32620
32646
  }
32621
32647
  }
32648
+ async function remoteForCurrentBranch(g) {
32649
+ const branch = (await g.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim();
32650
+ if (!branch || branch === "HEAD") return "origin";
32651
+ return await tryConfigGet(g, `branch.${branch}.remote`) ?? "origin";
32652
+ }
32653
+ async function resolveDefaultRemoteBranchRef(g, remote) {
32654
+ const headSym = `refs/remotes/${remote}/HEAD`;
32655
+ try {
32656
+ const resolved = (await g.raw(["symbolic-ref", "-q", "--verify", headSym])).trim();
32657
+ if (resolved.startsWith("refs/remotes/")) return resolved;
32658
+ } catch {
32659
+ }
32660
+ for (const name of ["main", "master", "trunk", "develop"]) {
32661
+ const r = `refs/remotes/${remote}/${name}`;
32662
+ try {
32663
+ await g.raw(["rev-parse", "--verify", r]);
32664
+ return r;
32665
+ } catch {
32666
+ }
32667
+ }
32668
+ return null;
32669
+ }
32670
+ async function resolveBaseShaForUnpushedCommits(g) {
32671
+ const trackingRef = await resolveRemoteTrackingRefForAhead(g);
32672
+ if (trackingRef) {
32673
+ const sha = await revParseSafe(g, trackingRef);
32674
+ if (sha) return sha;
32675
+ }
32676
+ const remote = await remoteForCurrentBranch(g);
32677
+ const defaultRef = await resolveDefaultRemoteBranchRef(g, remote);
32678
+ if (!defaultRef) return null;
32679
+ return revParseSafe(g, defaultRef);
32680
+ }
32681
+ function parseLogShaDateSubjectLines(raw) {
32682
+ const out = [];
32683
+ for (const line of String(raw).split("\n")) {
32684
+ const l = line.trimEnd();
32685
+ if (!l.trim()) continue;
32686
+ const parts = l.split(" ");
32687
+ if (parts.length < 3) continue;
32688
+ const sha = parts[0].trim();
32689
+ const committedAt = parts[1].trim();
32690
+ const subject = parts.slice(2).join(" ").trim();
32691
+ if (!/^[0-9a-f]{7,40}$/i.test(sha)) continue;
32692
+ out.push({ sha, shortSha: sha.slice(0, 7), subject, committedAt });
32693
+ }
32694
+ return out;
32695
+ }
32696
+ async function gitLogNotReachableFromBase(g, baseSha, headSha) {
32697
+ if (baseSha === headSha) return [];
32698
+ try {
32699
+ const logOut = await g.raw(["log", "--format=%H %cI %s", `${baseSha}..${headSha}`]);
32700
+ return parseLogShaDateSubjectLines(logOut);
32701
+ } catch {
32702
+ return [];
32703
+ }
32704
+ }
32622
32705
  async function commitsAheadOfRemoteTracking(repoDir) {
32623
32706
  const g = simpleGit(repoDir);
32624
- const trackingRef = await resolveRemoteTrackingRefForAhead(g);
32625
- if (!trackingRef) return 0;
32626
- const localSha = (await g.raw(["rev-parse", "HEAD"])).trim();
32627
- const remoteSha = (await g.raw(["rev-parse", trackingRef])).trim();
32628
- if (localSha === remoteSha) return 0;
32629
- const out = await g.raw(["rev-list", "--count", `${trackingRef}..HEAD`]);
32630
- const n = parseInt(String(out).trim(), 10);
32631
- return Number.isNaN(n) ? 0 : n;
32707
+ const headSha = await revParseSafe(g, "HEAD");
32708
+ if (!headSha) return 0;
32709
+ const baseSha = await resolveBaseShaForUnpushedCommits(g);
32710
+ if (!baseSha || baseSha === headSha) return 0;
32711
+ try {
32712
+ const out = await g.raw(["rev-list", "--count", `${baseSha}..${headSha}`]);
32713
+ const n = parseInt(String(out).trim(), 10);
32714
+ return Number.isNaN(n) ? 0 : n;
32715
+ } catch {
32716
+ return 0;
32717
+ }
32632
32718
  }
32633
32719
  async function getRepoWorkingTreeStatus(repoDir) {
32634
32720
  const g = simpleGit(repoDir);
@@ -32637,6 +32723,14 @@ async function getRepoWorkingTreeStatus(repoDir) {
32637
32723
  const ahead = await commitsAheadOfRemoteTracking(repoDir);
32638
32724
  return { hasUncommittedChanges, hasUnpushedCommits: ahead > 0 };
32639
32725
  }
32726
+ async function listUnpushedCommits(repoDir) {
32727
+ const g = simpleGit(repoDir);
32728
+ const headSha = await revParseSafe(g, "HEAD");
32729
+ if (!headSha) return [];
32730
+ const baseSha = await resolveBaseShaForUnpushedCommits(g);
32731
+ if (!baseSha) return [];
32732
+ return gitLogNotReachableFromBase(g, baseSha, headSha);
32733
+ }
32640
32734
  async function aggregateSessionPathsWorkingTreeStatus(paths) {
32641
32735
  let hasUncommittedChanges = false;
32642
32736
  let hasUnpushedCommits = false;
@@ -32656,6 +32750,477 @@ async function pushAheadOfUpstreamForPaths(paths) {
32656
32750
  }
32657
32751
  }
32658
32752
 
32753
+ // src/git/working-directory/changes/types.ts
32754
+ var MAX_PATCH_CHARS = 35e4;
32755
+
32756
+ // src/git/working-directory/changes/repo-format.ts
32757
+ function posixJoinDirFile(dir, file2) {
32758
+ const d = dir === "." || dir === "" ? "" : dir.replace(/\\/g, "/").replace(/\/+$/, "");
32759
+ const f = file2.replace(/\\/g, "/").replace(/^\/+/, "");
32760
+ return d ? `${d}/${f}` : f;
32761
+ }
32762
+ function formatRepoShortTitle(remoteUrl, repoRelPath) {
32763
+ const u = remoteUrl.trim();
32764
+ if (u) {
32765
+ try {
32766
+ if (u.startsWith("git@")) {
32767
+ const colon = u.indexOf(":");
32768
+ if (colon > 0) {
32769
+ const pathPart = u.slice(colon + 1).replace(/\.git$/i, "").replace(/\/+$/, "");
32770
+ if (pathPart.includes("/")) return pathPart;
32771
+ }
32772
+ } else {
32773
+ const parsed = new URL(u);
32774
+ const p = parsed.pathname.replace(/^\//, "").replace(/\.git$/i, "");
32775
+ const parts = p.split("/").filter(Boolean);
32776
+ if (parts.length >= 2) {
32777
+ return `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
32778
+ }
32779
+ if (parts.length === 1) return parts[0];
32780
+ }
32781
+ } catch {
32782
+ }
32783
+ }
32784
+ if (repoRelPath && repoRelPath !== ".") {
32785
+ const segments = repoRelPath.split("/").filter(Boolean);
32786
+ const last2 = segments[segments.length - 1];
32787
+ if (last2) return last2;
32788
+ }
32789
+ return "Repository";
32790
+ }
32791
+ function formatRemoteDisplayLabel(remoteUrl) {
32792
+ const u = remoteUrl.trim();
32793
+ if (!u) return "";
32794
+ let hostPath = u;
32795
+ try {
32796
+ if (u.startsWith("git@")) {
32797
+ const rest = u.slice("git@".length);
32798
+ const slash = rest.indexOf(":");
32799
+ if (slash > 0) hostPath = `${rest.slice(0, slash)}/${rest.slice(slash + 1)}`;
32800
+ } else {
32801
+ const parsed = new URL(u);
32802
+ hostPath = `${parsed.hostname}${parsed.pathname}`.replace(/\/\.git$/i, "").replace(/\.git$/i, "");
32803
+ }
32804
+ } catch {
32805
+ hostPath = u.replace(/^https?:\/\//i, "").replace(/\.git$/i, "");
32806
+ }
32807
+ return `origin \xB7 ${hostPath}`;
32808
+ }
32809
+
32810
+ // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
32811
+ import * as path14 from "node:path";
32812
+
32813
+ // src/git/working-directory/changes/parse-git-status.ts
32814
+ function parseNameStatusLines(lines) {
32815
+ const m = /* @__PURE__ */ new Map();
32816
+ for (const line of lines) {
32817
+ if (!line.trim()) continue;
32818
+ const tabParts = line.split(" ");
32819
+ if (tabParts.length < 2) continue;
32820
+ const status = tabParts[0].trim();
32821
+ const code = status[0];
32822
+ if (code === "A") {
32823
+ m.set(tabParts[tabParts.length - 1], "added");
32824
+ } else if (code === "D") {
32825
+ m.set(tabParts[tabParts.length - 1], "removed");
32826
+ } else if (code === "R" || code === "C") {
32827
+ if (tabParts.length >= 3) m.set(tabParts[tabParts.length - 1], "modified");
32828
+ } else if (code === "M" || code === "U" || code === "T") {
32829
+ m.set(tabParts[tabParts.length - 1], "modified");
32830
+ }
32831
+ }
32832
+ return m;
32833
+ }
32834
+ function parseNumstatFirstLine(line) {
32835
+ const parts = line.split(" ");
32836
+ if (parts.length < 3) return null;
32837
+ const [a, d] = parts;
32838
+ const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
32839
+ const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
32840
+ return { additions, deletions };
32841
+ }
32842
+ function parseNumstat(lines) {
32843
+ const m = /* @__PURE__ */ new Map();
32844
+ for (const line of lines) {
32845
+ if (!line.trim()) continue;
32846
+ const parts = line.split(" ");
32847
+ if (parts.length < 3) continue;
32848
+ const [a, d, p] = parts;
32849
+ const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
32850
+ const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
32851
+ m.set(p, { additions, deletions });
32852
+ }
32853
+ return m;
32854
+ }
32855
+ async function numstatFromGitNoIndex(g, pathInRepo) {
32856
+ const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
32857
+ try {
32858
+ const out = await g.raw(["diff", "--numstat", "--no-index", "--", devNull, pathInRepo]);
32859
+ const first2 = String(out).split("\n").find((l) => l.trim()) ?? "";
32860
+ return parseNumstatFirstLine(first2);
32861
+ } catch {
32862
+ return null;
32863
+ }
32864
+ }
32865
+
32866
+ // src/git/working-directory/changes/patch-truncate.ts
32867
+ function truncatePatch(s) {
32868
+ if (s.length <= MAX_PATCH_CHARS) return s;
32869
+ return `${s.slice(0, MAX_PATCH_CHARS)}
32870
+
32871
+ \u2026 (diff truncated)`;
32872
+ }
32873
+
32874
+ // src/git/working-directory/changes/list-changed-files-for-commit.ts
32875
+ var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
32876
+ async function parentForCommitDiff(g, sha) {
32877
+ try {
32878
+ return (await g.raw(["rev-parse", `${sha}^1`])).trim();
32879
+ } catch {
32880
+ try {
32881
+ return (await g.raw(["rev-parse", `${sha}^`])).trim();
32882
+ } catch {
32883
+ return EMPTY_TREE;
32884
+ }
32885
+ }
32886
+ }
32887
+ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
32888
+ const g = simpleGit(repoGitCwd);
32889
+ const parent = await parentForCommitDiff(g, commitSha);
32890
+ const range = `${parent}..${commitSha}`;
32891
+ const [nameStatusRaw, numstatRaw] = await Promise.all([
32892
+ g.raw(["diff", "--name-status", range]).catch(() => ""),
32893
+ g.raw(["diff", "--numstat", range]).catch(() => "")
32894
+ ]);
32895
+ const kindByPath = parseNameStatusLines(String(nameStatusRaw).split("\n"));
32896
+ const numByPath = parseNumstat(String(numstatRaw).split("\n"));
32897
+ const paths = new Set([...kindByPath.keys(), ...numByPath.keys()].filter(Boolean));
32898
+ const rows = [];
32899
+ const normRel = repoRelPath === "." || repoRelPath === "" ? "." : repoRelPath;
32900
+ for (const pathInRepo of paths) {
32901
+ const relLauncher = posixJoinDirFile(normRel, pathInRepo.replace(/\\/g, "/"));
32902
+ const nums = numByPath.get(pathInRepo);
32903
+ let additions = nums?.additions ?? 0;
32904
+ let deletions = nums?.deletions ?? 0;
32905
+ let change = kindByPath.get(pathInRepo) ?? "modified";
32906
+ if (!kindByPath.has(pathInRepo) && nums) {
32907
+ if (additions > 0 && deletions === 0) change = "added";
32908
+ else if (deletions > 0 && additions === 0) change = "removed";
32909
+ else change = "modified";
32910
+ }
32911
+ rows.push({ pathRelLauncher: relLauncher, additions, deletions, change });
32912
+ }
32913
+ for (const row of rows) {
32914
+ let pathInRepo;
32915
+ if (normRel === ".") {
32916
+ pathInRepo = row.pathRelLauncher;
32917
+ } else if (row.pathRelLauncher.startsWith(`${normRel}/`)) {
32918
+ pathInRepo = row.pathRelLauncher.slice(normRel.length + 1);
32919
+ } else {
32920
+ pathInRepo = row.pathRelLauncher;
32921
+ }
32922
+ const raw = await g.raw(["diff", "-U20000", range, "--", pathInRepo]).catch(() => "");
32923
+ const t = String(raw).trim();
32924
+ row.patchContent = t ? truncatePatch(t) : void 0;
32925
+ }
32926
+ rows.sort((a, b) => a.pathRelLauncher.localeCompare(b.pathRelLauncher));
32927
+ return rows;
32928
+ }
32929
+
32930
+ // src/git/working-directory/changes/list-changed-files-for-repo.ts
32931
+ import * as fs11 from "node:fs";
32932
+ import * as path13 from "node:path";
32933
+
32934
+ // src/git/working-directory/changes/count-lines.ts
32935
+ import { createReadStream } from "node:fs";
32936
+ import * as readline2 from "node:readline";
32937
+ async function countTextFileLines(absFile) {
32938
+ let bytes = 0;
32939
+ const maxBytes = 512e3;
32940
+ let lines = 0;
32941
+ const stream = createReadStream(absFile, { encoding: "utf8" });
32942
+ const rl = readline2.createInterface({ input: stream, crlfDelay: Infinity });
32943
+ for await (const _line of rl) {
32944
+ lines += 1;
32945
+ bytes += Buffer.byteLength(String(_line), "utf8") + 1;
32946
+ if (bytes > maxBytes) {
32947
+ rl.close();
32948
+ stream.destroy();
32949
+ return lines;
32950
+ }
32951
+ }
32952
+ return lines;
32953
+ }
32954
+
32955
+ // src/git/working-directory/changes/hydrate-patch.ts
32956
+ import * as fs10 from "node:fs";
32957
+ var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
32958
+ var MAX_HYDRATE_LINES_PER_GAP = 8e3;
32959
+ var MAX_HYDRATE_LINES_PER_FILE = 8e4;
32960
+ async function readGitBlobLines(repoCwd, pathInRepo) {
32961
+ try {
32962
+ const rel = pathInRepo.replace(/\\/g, "/");
32963
+ const raw = await simpleGit(repoCwd).show([`HEAD:${rel}`]);
32964
+ return String(raw).split(/\r?\n/);
32965
+ } catch {
32966
+ return null;
32967
+ }
32968
+ }
32969
+ async function readWorktreeFileLines(abs) {
32970
+ try {
32971
+ const raw = await fs10.promises.readFile(abs, "utf8");
32972
+ return raw.split(/\r?\n/);
32973
+ } catch {
32974
+ return null;
32975
+ }
32976
+ }
32977
+ async function hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, change) {
32978
+ if (!patch.trim() || patch.includes("Binary files")) return patch;
32979
+ const all = patch.split("\n");
32980
+ const out = [];
32981
+ let prevOldEnd = 0;
32982
+ let prevNewEnd = 0;
32983
+ let injectedTotal = 0;
32984
+ let i = 0;
32985
+ let blobCache;
32986
+ let diskCache;
32987
+ const blobLines = async () => {
32988
+ if (blobCache !== void 0) return blobCache;
32989
+ blobCache = await readGitBlobLines(repoGitCwd, pathInRepo);
32990
+ return blobCache;
32991
+ };
32992
+ const diskLines = async () => {
32993
+ if (diskCache !== void 0) return diskCache;
32994
+ diskCache = await readWorktreeFileLines(absFile);
32995
+ return diskCache;
32996
+ };
32997
+ while (i < all.length) {
32998
+ const line = all[i];
32999
+ const hm = line.match(UNIFIED_HUNK_HEADER_RE);
33000
+ if (!hm) {
33001
+ out.push(line);
33002
+ i++;
33003
+ continue;
33004
+ }
33005
+ const oldStart = parseInt(hm[1], 10) || 0;
33006
+ const newStart = parseInt(hm[3], 10) || 0;
33007
+ const gapOldStart = prevOldEnd + 1;
33008
+ const gapOldEnd = oldStart - 1;
33009
+ const gapNewStart = prevNewEnd + 1;
33010
+ const gapNewEnd = newStart - 1;
33011
+ if (injectedTotal < MAX_HYDRATE_LINES_PER_FILE) {
33012
+ let inject = null;
33013
+ if (gapNewEnd >= gapNewStart && change !== "removed") {
33014
+ const nNew = gapNewEnd - gapNewStart + 1;
33015
+ if (gapOldEnd < gapOldStart || gapOldEnd - gapOldStart + 1 === nNew) {
33016
+ const cap = Math.min(nNew, MAX_HYDRATE_LINES_PER_GAP, MAX_HYDRATE_LINES_PER_FILE - injectedTotal);
33017
+ const dl = await diskLines();
33018
+ if (dl && cap > 0) {
33019
+ inject = dl.slice(gapNewStart - 1, gapNewStart - 1 + cap);
33020
+ }
33021
+ }
33022
+ } else if (gapOldEnd >= gapOldStart && change === "removed") {
33023
+ const nOld = gapOldEnd - gapOldStart + 1;
33024
+ const cap = Math.min(nOld, MAX_HYDRATE_LINES_PER_GAP, MAX_HYDRATE_LINES_PER_FILE - injectedTotal);
33025
+ const bl = await blobLines();
33026
+ if (bl && cap > 0) {
33027
+ inject = bl.slice(gapOldStart - 1, gapOldStart - 1 + cap);
33028
+ }
33029
+ }
33030
+ if (inject && inject.length > 0) {
33031
+ for (const t of inject) {
33032
+ out.push(` ${t}`);
33033
+ injectedTotal++;
33034
+ }
33035
+ }
33036
+ }
33037
+ out.push(line);
33038
+ i++;
33039
+ let oldConsumed = 0;
33040
+ let newConsumed = 0;
33041
+ while (i < all.length) {
33042
+ const bl = all[i];
33043
+ if (UNIFIED_HUNK_HEADER_RE.test(bl)) break;
33044
+ out.push(bl);
33045
+ i++;
33046
+ if (bl.startsWith("\\")) continue;
33047
+ const ch = bl[0];
33048
+ if (ch === " ") {
33049
+ oldConsumed++;
33050
+ newConsumed++;
33051
+ } else if (ch === "-") {
33052
+ oldConsumed++;
33053
+ } else if (ch === "+") {
33054
+ newConsumed++;
33055
+ }
33056
+ }
33057
+ if (oldStart > 0) {
33058
+ prevOldEnd = oldStart + oldConsumed - 1;
33059
+ } else {
33060
+ prevOldEnd = 0;
33061
+ }
33062
+ if (newStart > 0) {
33063
+ prevNewEnd = newStart + newConsumed - 1;
33064
+ } else {
33065
+ prevNewEnd = 0;
33066
+ }
33067
+ }
33068
+ return truncatePatch(out.join("\n"));
33069
+ }
33070
+
33071
+ // src/git/working-directory/changes/unified-diff-for-file.ts
33072
+ async function unifiedDiffForFile(repoCwd, pathInRepo, change) {
33073
+ const g = simpleGit(repoCwd);
33074
+ try {
33075
+ let raw;
33076
+ if (change === "added") {
33077
+ const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
33078
+ raw = await g.raw(["diff", "--no-index", "--", devNull, pathInRepo]);
33079
+ } else {
33080
+ raw = await g.raw(["diff", "HEAD", "--", pathInRepo]);
33081
+ }
33082
+ const t = String(raw).trim();
33083
+ if (!t) return void 0;
33084
+ return truncatePatch(t);
33085
+ } catch {
33086
+ return void 0;
33087
+ }
33088
+ }
33089
+
33090
+ // src/git/working-directory/changes/list-changed-files-for-repo.ts
33091
+ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
33092
+ const g = simpleGit(repoGitCwd);
33093
+ const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
33094
+ g.raw(["diff", "--name-status", "HEAD"]).catch(() => ""),
33095
+ g.raw(["diff", "HEAD", "--numstat"]).catch(() => ""),
33096
+ g.raw(["ls-files", "--others", "--exclude-standard"]).catch(() => "")
33097
+ ]);
33098
+ const kindByPath = parseNameStatusLines(String(nameStatusRaw).split("\n"));
33099
+ const numByPath = parseNumstat(String(numstatRaw).split("\n"));
33100
+ const paths = /* @__PURE__ */ new Set([...kindByPath.keys(), ...numByPath.keys()]);
33101
+ const untracked = String(untrackedRaw).split("\n").map((s) => s.trim()).filter(Boolean);
33102
+ for (const p of untracked) paths.add(p);
33103
+ const rows = [];
33104
+ for (const pathInRepo of paths) {
33105
+ const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
33106
+ const abs = path13.join(repoGitCwd, pathInRepo);
33107
+ const nums = numByPath.get(pathInRepo);
33108
+ let additions = nums?.additions ?? 0;
33109
+ let deletions = nums?.deletions ?? 0;
33110
+ let change = kindByPath.get(pathInRepo) ?? "modified";
33111
+ if (untracked.includes(pathInRepo) && !kindByPath.has(pathInRepo)) {
33112
+ change = "added";
33113
+ const fromGit = await numstatFromGitNoIndex(g, pathInRepo);
33114
+ if (fromGit) {
33115
+ additions = fromGit.additions;
33116
+ deletions = fromGit.deletions;
33117
+ } else {
33118
+ try {
33119
+ const st = await fs11.promises.stat(abs);
33120
+ if (st.isFile()) additions = await countTextFileLines(abs);
33121
+ else additions = 0;
33122
+ } catch {
33123
+ additions = 0;
33124
+ }
33125
+ deletions = 0;
33126
+ }
33127
+ }
33128
+ if (!kindByPath.has(pathInRepo) && nums) {
33129
+ if (additions > 0 && deletions === 0) change = "added";
33130
+ else if (deletions > 0 && additions === 0) change = "removed";
33131
+ else change = "modified";
33132
+ }
33133
+ rows.push({ pathRelLauncher: relLauncher, additions, deletions, change });
33134
+ }
33135
+ const normRel = repoRelPath === "." || repoRelPath === "" ? "." : repoRelPath;
33136
+ for (const row of rows) {
33137
+ let pathInRepo;
33138
+ if (normRel === ".") {
33139
+ pathInRepo = row.pathRelLauncher;
33140
+ } else if (row.pathRelLauncher.startsWith(`${normRel}/`)) {
33141
+ pathInRepo = row.pathRelLauncher.slice(normRel.length + 1);
33142
+ } else {
33143
+ pathInRepo = row.pathRelLauncher;
33144
+ }
33145
+ const absFile = path13.join(repoGitCwd, pathInRepo);
33146
+ let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
33147
+ if (patch) {
33148
+ patch = await hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, row.change);
33149
+ }
33150
+ row.patchContent = patch;
33151
+ }
33152
+ return rows;
33153
+ }
33154
+
33155
+ // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
33156
+ function normRepoRel(p) {
33157
+ const x = p.replace(/\\/g, "/").trim();
33158
+ return x === "" ? "." : x;
33159
+ }
33160
+ async function getWorkingTreeChangeRepoDetails(options) {
33161
+ const launcher = path14.resolve(getBridgeWorkspaceDirectory());
33162
+ const mirror = options.agentMirrorRootAbs ? path14.resolve(options.agentMirrorRootAbs) : null;
33163
+ const out = [];
33164
+ const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
33165
+ const basisInput = options.basis ?? { kind: "working" };
33166
+ if (basisInput.kind === "commit" && !filter) {
33167
+ throw new Error("repoFilterRelPath is required for commit changes");
33168
+ }
33169
+ if (basisInput.kind === "commit" && !basisInput.sha.trim()) {
33170
+ throw new Error("commit sha is required for commit changes");
33171
+ }
33172
+ const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
33173
+ for (const target of options.commitTargetAbsDirs) {
33174
+ const t = path14.resolve(target);
33175
+ if (!await isGitRepoDirectory(t)) continue;
33176
+ const g = simpleGit(t);
33177
+ let branch = "HEAD";
33178
+ try {
33179
+ branch = (await g.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim() || "HEAD";
33180
+ } catch {
33181
+ branch = "HEAD";
33182
+ }
33183
+ const remoteUrl = await getRemoteOriginUrl(t);
33184
+ const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
33185
+ let repoRelPath;
33186
+ if (mirror) {
33187
+ const relNorm = path14.relative(mirror, path14.dirname(t));
33188
+ repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
33189
+ } else {
33190
+ let top = t;
33191
+ try {
33192
+ top = (await g.raw(["rev-parse", "--show-toplevel"])).trim();
33193
+ } catch {
33194
+ top = t;
33195
+ }
33196
+ const rel = path14.relative(launcher, path14.resolve(top)).replace(/\\/g, "/") || ".";
33197
+ repoRelPath = rel.startsWith("..") ? path14.basename(path14.resolve(top)) : rel;
33198
+ }
33199
+ const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
33200
+ if (filter && norm !== filter) continue;
33201
+ const repoDisplayName = formatRepoShortTitle(remoteUrl, norm === "." ? "." : norm);
33202
+ const relForList = norm === "." ? "." : norm;
33203
+ const files = basis.kind === "commit" ? await listChangedFilesForCommit(t, relForList, basis.sha.trim()) : await listChangedFilesForRepo(t, relForList);
33204
+ const st = await g.status();
33205
+ const hasUncommittedChanges = (st.files?.length ?? 0) > 0;
33206
+ const unpushedCommits = await listUnpushedCommits(t);
33207
+ out.push({
33208
+ repoRelPath: norm,
33209
+ repoDisplayName,
33210
+ branch,
33211
+ remoteUrl,
33212
+ remoteDisplay,
33213
+ files,
33214
+ hasUncommittedChanges,
33215
+ unpushedCommits,
33216
+ changesView: basis.kind === "commit" ? "commit" : "working",
33217
+ changesCommitSha: basis.kind === "commit" ? basis.sha.trim() : null
33218
+ });
33219
+ if (filter) return out;
33220
+ }
33221
+ return out;
33222
+ }
33223
+
32659
33224
  // src/git/commit-and-push.ts
32660
33225
  async function gitCommitAllIfDirty(repoDir, message, options) {
32661
33226
  const g = simpleGit(repoDir);
@@ -32721,7 +33286,7 @@ var SessionWorktreeManager = class {
32721
33286
  }
32722
33287
  if (!opts.isNewSession) {
32723
33288
  const agentCwd = this.sessionAgentCwd.get(sessionId);
32724
- if (agentCwd) return path13.resolve(agentCwd);
33289
+ if (agentCwd) return path15.resolve(agentCwd);
32725
33290
  return void 0;
32726
33291
  }
32727
33292
  const prep = await prepareNewSessionWorktrees({
@@ -32734,7 +33299,7 @@ var SessionWorktreeManager = class {
32734
33299
  if (!prep) return void 0;
32735
33300
  this.sessionPaths.set(sessionId, prep.worktreePaths);
32736
33301
  this.sessionAgentCwd.set(sessionId, prep.agentCwd);
32737
- return path13.resolve(prep.agentCwd);
33302
+ return path15.resolve(prep.agentCwd);
32738
33303
  }
32739
33304
  async renameSessionBranch(sessionId, newBranch) {
32740
33305
  const paths = this.sessionPaths.get(sessionId);
@@ -32755,7 +33320,7 @@ var SessionWorktreeManager = class {
32755
33320
  getAgentCwdForSession(sessionId) {
32756
33321
  if (!sessionId) return null;
32757
33322
  const c = this.sessionAgentCwd.get(sessionId);
32758
- return c ? path13.resolve(c) : null;
33323
+ return c ? path15.resolve(c) : null;
32759
33324
  }
32760
33325
  async removeSessionWorktrees(sessionId) {
32761
33326
  const paths = this.sessionPaths.get(sessionId);
@@ -32781,6 +33346,17 @@ var SessionWorktreeManager = class {
32781
33346
  async getSessionWorkingTreeStatus(sessionId) {
32782
33347
  return aggregateSessionPathsWorkingTreeStatus(this.resolveCommitTargets(sessionId));
32783
33348
  }
33349
+ /** Per-repo changed files vs HEAD (or a single commit vs parent) for the same git roots used for commit/push. */
33350
+ async getSessionWorkingTreeChangeDetails(sessionId, opts) {
33351
+ const targets = this.resolveCommitTargets(sessionId);
33352
+ const mirror = this.getAgentCwdForSession(sessionId);
33353
+ return getWorkingTreeChangeRepoDetails({
33354
+ commitTargetAbsDirs: targets,
33355
+ agentMirrorRootAbs: mirror,
33356
+ repoFilterRelPath: opts?.repoRelPath?.trim() ? opts.repoRelPath.trim() : null,
33357
+ basis: opts?.basis
33358
+ });
33359
+ }
32784
33360
  async pushSessionUpstream(sessionId) {
32785
33361
  try {
32786
33362
  await pushAheadOfUpstreamForPaths(this.resolveCommitTargets(sessionId));
@@ -32792,30 +33368,30 @@ var SessionWorktreeManager = class {
32792
33368
  }
32793
33369
  };
32794
33370
  function defaultWorktreesRootAbs() {
32795
- return path13.join(os3.homedir(), ".buildautomaton", "worktrees");
33371
+ return path15.join(os3.homedir(), ".buildautomaton", "worktrees");
32796
33372
  }
32797
33373
 
32798
33374
  // src/files/watch-file-index.ts
32799
33375
  import { watch } from "node:fs";
32800
- import path20 from "node:path";
33376
+ import path22 from "node:path";
32801
33377
 
32802
33378
  // src/files/index/build-file-index.ts
32803
- import path17 from "node:path";
33379
+ import path19 from "node:path";
32804
33380
 
32805
33381
  // src/runtime/yield-to-event-loop.ts
32806
33382
  function yieldToEventLoop() {
32807
- return new Promise((resolve15) => setImmediate(resolve15));
33383
+ return new Promise((resolve16) => setImmediate(resolve16));
32808
33384
  }
32809
33385
 
32810
33386
  // src/files/index/walk-workspace-tree.ts
32811
- import fs10 from "node:fs";
32812
- import path15 from "node:path";
33387
+ import fs12 from "node:fs";
33388
+ import path17 from "node:path";
32813
33389
 
32814
33390
  // src/files/index/constants.ts
32815
- import path14 from "node:path";
33391
+ import path16 from "node:path";
32816
33392
  import os4 from "node:os";
32817
33393
  var INDEX_WORK_YIELD_EVERY = 256;
32818
- var INDEX_DIR = path14.join(os4.homedir(), ".buildautomaton");
33394
+ var INDEX_DIR = path16.join(os4.homedir(), ".buildautomaton");
32819
33395
  var INDEX_HASH_LEN = 16;
32820
33396
  var INDEX_VERSION = 2;
32821
33397
  var INDEX_LOG_PREFIX = "[file-index]";
@@ -32824,31 +33400,31 @@ var INDEX_LOG_PREFIX = "[file-index]";
32824
33400
  function walkWorkspaceTreeSync(dir, baseDir, out) {
32825
33401
  let names;
32826
33402
  try {
32827
- names = fs10.readdirSync(dir);
33403
+ names = fs12.readdirSync(dir);
32828
33404
  } catch {
32829
33405
  return;
32830
33406
  }
32831
33407
  for (const name of names) {
32832
33408
  if (name.startsWith(".")) continue;
32833
- const full = path15.join(dir, name);
33409
+ const full = path17.join(dir, name);
32834
33410
  let stat2;
32835
33411
  try {
32836
- stat2 = fs10.statSync(full);
33412
+ stat2 = fs12.statSync(full);
32837
33413
  } catch {
32838
33414
  continue;
32839
33415
  }
32840
- const relative4 = path15.relative(baseDir, full).replace(/\\/g, "/");
33416
+ const relative5 = path17.relative(baseDir, full).replace(/\\/g, "/");
32841
33417
  if (stat2.isDirectory()) {
32842
33418
  walkWorkspaceTreeSync(full, baseDir, out);
32843
33419
  } else if (stat2.isFile()) {
32844
- out.push(relative4);
33420
+ out.push(relative5);
32845
33421
  }
32846
33422
  }
32847
33423
  }
32848
33424
  async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
32849
33425
  let names;
32850
33426
  try {
32851
- names = await fs10.promises.readdir(dir);
33427
+ names = await fs12.promises.readdir(dir);
32852
33428
  } catch {
32853
33429
  return;
32854
33430
  }
@@ -32858,18 +33434,18 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
32858
33434
  await yieldToEventLoop();
32859
33435
  }
32860
33436
  state.n++;
32861
- const full = path15.join(dir, name);
33437
+ const full = path17.join(dir, name);
32862
33438
  let stat2;
32863
33439
  try {
32864
- stat2 = await fs10.promises.stat(full);
33440
+ stat2 = await fs12.promises.stat(full);
32865
33441
  } catch {
32866
33442
  continue;
32867
33443
  }
32868
- const relative4 = path15.relative(baseDir, full).replace(/\\/g, "/");
33444
+ const relative5 = path17.relative(baseDir, full).replace(/\\/g, "/");
32869
33445
  if (stat2.isDirectory()) {
32870
33446
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
32871
33447
  } else if (stat2.isFile()) {
32872
- out.push(relative4);
33448
+ out.push(relative5);
32873
33449
  }
32874
33450
  }
32875
33451
  }
@@ -32946,22 +33522,22 @@ async function buildTrigramMapForPathsAsync(paths) {
32946
33522
  }
32947
33523
 
32948
33524
  // src/files/index/write-index-file.ts
32949
- import fs11 from "node:fs";
33525
+ import fs13 from "node:fs";
32950
33526
 
32951
33527
  // src/files/index/paths.ts
32952
- import path16 from "node:path";
33528
+ import path18 from "node:path";
32953
33529
  import crypto2 from "node:crypto";
32954
33530
  function getIndexPathForCwd(resolvedCwd) {
32955
33531
  const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
32956
- return path16.join(INDEX_DIR, `.file-index-${hash}.json`);
33532
+ return path18.join(INDEX_DIR, `.file-index-${hash}.json`);
32957
33533
  }
32958
33534
 
32959
33535
  // src/files/index/write-index-file.ts
32960
33536
  function writeIndexFileSync(resolvedCwd, data) {
32961
33537
  const indexPath = getIndexPathForCwd(resolvedCwd);
32962
33538
  try {
32963
- if (!fs11.existsSync(INDEX_DIR)) fs11.mkdirSync(INDEX_DIR, { recursive: true });
32964
- fs11.writeFileSync(indexPath, JSON.stringify(data), "utf8");
33539
+ if (!fs13.existsSync(INDEX_DIR)) fs13.mkdirSync(INDEX_DIR, { recursive: true });
33540
+ fs13.writeFileSync(indexPath, JSON.stringify(data), "utf8");
32965
33541
  } catch (e) {
32966
33542
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
32967
33543
  }
@@ -32969,8 +33545,8 @@ function writeIndexFileSync(resolvedCwd, data) {
32969
33545
  async function writeIndexFileAsync(resolvedCwd, data) {
32970
33546
  const indexPath = getIndexPathForCwd(resolvedCwd);
32971
33547
  try {
32972
- await fs11.promises.mkdir(INDEX_DIR, { recursive: true });
32973
- await fs11.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
33548
+ await fs13.promises.mkdir(INDEX_DIR, { recursive: true });
33549
+ await fs13.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
32974
33550
  } catch (e) {
32975
33551
  console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
32976
33552
  }
@@ -32984,7 +33560,7 @@ function sortPaths(paths) {
32984
33560
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
32985
33561
  }
32986
33562
  function buildFileIndex(cwd) {
32987
- const resolved = path17.resolve(cwd);
33563
+ const resolved = path19.resolve(cwd);
32988
33564
  const paths = [];
32989
33565
  walkWorkspaceTreeSync(resolved, resolved, paths);
32990
33566
  sortPaths(paths);
@@ -32994,7 +33570,7 @@ function buildFileIndex(cwd) {
32994
33570
  return data;
32995
33571
  }
32996
33572
  async function buildFileIndexAsync(cwd) {
32997
- const resolved = path17.resolve(cwd);
33573
+ const resolved = path19.resolve(cwd);
32998
33574
  const paths = [];
32999
33575
  await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
33000
33576
  await yieldToEventLoop();
@@ -33006,13 +33582,13 @@ async function buildFileIndexAsync(cwd) {
33006
33582
  }
33007
33583
 
33008
33584
  // src/files/index/load-file-index.ts
33009
- import fs12 from "node:fs";
33010
- import path18 from "node:path";
33585
+ import fs14 from "node:fs";
33586
+ import path20 from "node:path";
33011
33587
  function loadFileIndex(cwd) {
33012
- const resolved = path18.resolve(cwd);
33588
+ const resolved = path20.resolve(cwd);
33013
33589
  const indexPath = getIndexPathForCwd(resolved);
33014
33590
  try {
33015
- const raw = fs12.readFileSync(indexPath, "utf8");
33591
+ const raw = fs14.readFileSync(indexPath, "utf8");
33016
33592
  const parsed = JSON.parse(raw);
33017
33593
  if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
33018
33594
  const obj = parsed;
@@ -33031,9 +33607,9 @@ function loadFileIndex(cwd) {
33031
33607
  }
33032
33608
 
33033
33609
  // src/files/index/ensure-file-index.ts
33034
- import path19 from "node:path";
33610
+ import path21 from "node:path";
33035
33611
  async function ensureFileIndexAsync(cwd) {
33036
- const resolved = path19.resolve(cwd);
33612
+ const resolved = path21.resolve(cwd);
33037
33613
  const cached2 = loadFileIndex(resolved);
33038
33614
  if (cached2 !== null) return { data: cached2, fromCache: true };
33039
33615
  const data = await buildFileIndexAsync(resolved);
@@ -33116,7 +33692,7 @@ function createFsWatcher(resolved, schedule) {
33116
33692
  }
33117
33693
  }
33118
33694
  function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
33119
- const resolved = path20.resolve(cwd);
33695
+ const resolved = path22.resolve(cwd);
33120
33696
  void buildFileIndexAsync(resolved).catch((e) => {
33121
33697
  console.error("[file-index] Initial index build failed:", e);
33122
33698
  });
@@ -33163,15 +33739,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
33163
33739
 
33164
33740
  // src/dev-servers/process/terminate-child-process.ts
33165
33741
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
33166
- const exited = new Promise((resolve15) => {
33167
- proc.once("exit", () => resolve15());
33742
+ const exited = new Promise((resolve16) => {
33743
+ proc.once("exit", () => resolve16());
33168
33744
  });
33169
33745
  log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
33170
33746
  try {
33171
33747
  proc.kill("SIGTERM");
33172
33748
  } catch {
33173
33749
  }
33174
- await Promise.race([exited, new Promise((resolve15) => setTimeout(resolve15, graceMs))]);
33750
+ await Promise.race([exited, new Promise((resolve16) => setTimeout(resolve16, graceMs))]);
33175
33751
  }
33176
33752
  function forceKillChild(proc, log2, shortId, graceMs) {
33177
33753
  log2(
@@ -33185,7 +33761,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
33185
33761
  }
33186
33762
 
33187
33763
  // src/dev-servers/process/wire-dev-server-child-process.ts
33188
- import fs13 from "node:fs";
33764
+ import fs15 from "node:fs";
33189
33765
 
33190
33766
  // src/dev-servers/manager/forward-pipe.ts
33191
33767
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -33221,7 +33797,7 @@ function wireDevServerChildProcess(d) {
33221
33797
  d.setPollInterval(void 0);
33222
33798
  return;
33223
33799
  }
33224
- fs13.readFile(d.mergedLogPath, (err, buf) => {
33800
+ fs15.readFile(d.mergedLogPath, (err, buf) => {
33225
33801
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
33226
33802
  if (buf.length <= d.mergedReadPos.value) return;
33227
33803
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -33259,7 +33835,7 @@ ${errTail}` : ""}`);
33259
33835
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
33260
33836
  };
33261
33837
  if (mergedPath) {
33262
- fs13.readFile(mergedPath, (err, buf) => {
33838
+ fs15.readFile(mergedPath, (err, buf) => {
33263
33839
  if (!err && buf.length > d.mergedReadPos.value) {
33264
33840
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
33265
33841
  if (chunk.length > 0) {
@@ -33361,13 +33937,13 @@ function parseDevServerDefs(servers) {
33361
33937
  }
33362
33938
 
33363
33939
  // src/dev-servers/manager/shell-spawn/utils.ts
33364
- import fs14 from "node:fs";
33940
+ import fs16 from "node:fs";
33365
33941
  function isSpawnEbadf(e) {
33366
33942
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
33367
33943
  }
33368
33944
  function rmDirQuiet(dir) {
33369
33945
  try {
33370
- fs14.rmSync(dir, { recursive: true, force: true });
33946
+ fs16.rmSync(dir, { recursive: true, force: true });
33371
33947
  } catch {
33372
33948
  }
33373
33949
  }
@@ -33375,7 +33951,7 @@ var cachedDevNullReadFd;
33375
33951
  function devNullReadFd() {
33376
33952
  if (cachedDevNullReadFd === void 0) {
33377
33953
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
33378
- cachedDevNullReadFd = fs14.openSync(devPath, "r");
33954
+ cachedDevNullReadFd = fs16.openSync(devPath, "r");
33379
33955
  }
33380
33956
  return cachedDevNullReadFd;
33381
33957
  }
@@ -33449,15 +34025,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
33449
34025
 
33450
34026
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
33451
34027
  import { spawn as spawn6 } from "node:child_process";
33452
- import fs15 from "node:fs";
34028
+ import fs17 from "node:fs";
33453
34029
  import { tmpdir } from "node:os";
33454
- import path21 from "node:path";
34030
+ import path23 from "node:path";
33455
34031
  function trySpawnMergedLogFile(command, env, cwd, signal) {
33456
- const tmpRoot = fs15.mkdtempSync(path21.join(tmpdir(), "ba-devsrv-log-"));
33457
- const logPath = path21.join(tmpRoot, "combined.log");
34032
+ const tmpRoot = fs17.mkdtempSync(path23.join(tmpdir(), "ba-devsrv-log-"));
34033
+ const logPath = path23.join(tmpRoot, "combined.log");
33458
34034
  let logFd;
33459
34035
  try {
33460
- logFd = fs15.openSync(logPath, "a");
34036
+ logFd = fs17.openSync(logPath, "a");
33461
34037
  } catch {
33462
34038
  rmDirQuiet(tmpRoot);
33463
34039
  return null;
@@ -33476,7 +34052,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
33476
34052
  } else {
33477
34053
  proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
33478
34054
  }
33479
- fs15.closeSync(logFd);
34055
+ fs17.closeSync(logFd);
33480
34056
  return {
33481
34057
  proc,
33482
34058
  pipedStdoutStderr: true,
@@ -33485,7 +34061,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
33485
34061
  };
33486
34062
  } catch (e) {
33487
34063
  try {
33488
- fs15.closeSync(logFd);
34064
+ fs17.closeSync(logFd);
33489
34065
  } catch {
33490
34066
  }
33491
34067
  rmDirQuiet(tmpRoot);
@@ -33496,22 +34072,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
33496
34072
 
33497
34073
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
33498
34074
  import { spawn as spawn7 } from "node:child_process";
33499
- import fs16 from "node:fs";
34075
+ import fs18 from "node:fs";
33500
34076
  import { tmpdir as tmpdir2 } from "node:os";
33501
- import path22 from "node:path";
34077
+ import path24 from "node:path";
33502
34078
  function shSingleQuote(s) {
33503
34079
  return `'${s.replace(/'/g, `'\\''`)}'`;
33504
34080
  }
33505
34081
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
33506
- const tmpRoot = fs16.mkdtempSync(path22.join(tmpdir2(), "ba-devsrv-sh-"));
33507
- const logPath = path22.join(tmpRoot, "combined.log");
33508
- const innerPath = path22.join(tmpRoot, "_cmd.sh");
33509
- const runnerPath = path22.join(tmpRoot, "_run.sh");
34082
+ const tmpRoot = fs18.mkdtempSync(path24.join(tmpdir2(), "ba-devsrv-sh-"));
34083
+ const logPath = path24.join(tmpRoot, "combined.log");
34084
+ const innerPath = path24.join(tmpRoot, "_cmd.sh");
34085
+ const runnerPath = path24.join(tmpRoot, "_run.sh");
33510
34086
  try {
33511
- fs16.writeFileSync(innerPath, `#!/bin/sh
34087
+ fs18.writeFileSync(innerPath, `#!/bin/sh
33512
34088
  ${command}
33513
34089
  `);
33514
- fs16.writeFileSync(
34090
+ fs18.writeFileSync(
33515
34091
  runnerPath,
33516
34092
  `#!/bin/sh
33517
34093
  cd ${shSingleQuote(cwd)}
@@ -33537,13 +34113,13 @@ cd ${shSingleQuote(cwd)}
33537
34113
  }
33538
34114
  }
33539
34115
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
33540
- const tmpRoot = fs16.mkdtempSync(path22.join(tmpdir2(), "ba-devsrv-sh-"));
33541
- const logPath = path22.join(tmpRoot, "combined.log");
33542
- const runnerPath = path22.join(tmpRoot, "_run.bat");
34116
+ const tmpRoot = fs18.mkdtempSync(path24.join(tmpdir2(), "ba-devsrv-sh-"));
34117
+ const logPath = path24.join(tmpRoot, "combined.log");
34118
+ const runnerPath = path24.join(tmpRoot, "_run.bat");
33543
34119
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
33544
34120
  const com = process.env.ComSpec || "cmd.exe";
33545
34121
  try {
33546
- fs16.writeFileSync(
34122
+ fs18.writeFileSync(
33547
34123
  runnerPath,
33548
34124
  `@ECHO OFF\r
33549
34125
  CD /D ${q(cwd)}\r
@@ -34012,7 +34588,7 @@ async function proxyToLocal(request) {
34012
34588
  };
34013
34589
  const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
34014
34590
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
34015
- const once = await new Promise((resolve15) => {
34591
+ const once = await new Promise((resolve16) => {
34016
34592
  const req = mod.request(opts, (res) => {
34017
34593
  const chunks = [];
34018
34594
  res.on("data", (c) => chunks.push(c));
@@ -34023,7 +34599,7 @@ async function proxyToLocal(request) {
34023
34599
  if (typeof v === "string") headers[k] = v;
34024
34600
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
34025
34601
  }
34026
- resolve15({
34602
+ resolve16({
34027
34603
  id: request.id,
34028
34604
  statusCode: res.statusCode ?? 0,
34029
34605
  headers,
@@ -34032,7 +34608,7 @@ async function proxyToLocal(request) {
34032
34608
  });
34033
34609
  });
34034
34610
  req.on("error", (err) => {
34035
- resolve15({
34611
+ resolve16({
34036
34612
  id: request.id,
34037
34613
  statusCode: 0,
34038
34614
  headers: {},
@@ -34393,30 +34969,30 @@ function createOnBridgeIdentified(opts) {
34393
34969
  }
34394
34970
 
34395
34971
  // src/skills/discover-local-agent-skills.ts
34396
- import fs17 from "node:fs";
34397
- import path23 from "node:path";
34972
+ import fs19 from "node:fs";
34973
+ import path25 from "node:path";
34398
34974
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
34399
34975
  function discoverLocalSkills(cwd) {
34400
34976
  const out = [];
34401
34977
  const seenKeys = /* @__PURE__ */ new Set();
34402
34978
  for (const rel of SKILL_DISCOVERY_ROOTS) {
34403
- const base = path23.join(cwd, rel);
34404
- if (!fs17.existsSync(base) || !fs17.statSync(base).isDirectory()) continue;
34979
+ const base = path25.join(cwd, rel);
34980
+ if (!fs19.existsSync(base) || !fs19.statSync(base).isDirectory()) continue;
34405
34981
  let entries = [];
34406
34982
  try {
34407
- entries = fs17.readdirSync(base);
34983
+ entries = fs19.readdirSync(base);
34408
34984
  } catch {
34409
34985
  continue;
34410
34986
  }
34411
34987
  for (const name of entries) {
34412
- const dir = path23.join(base, name);
34988
+ const dir = path25.join(base, name);
34413
34989
  try {
34414
- if (!fs17.statSync(dir).isDirectory()) continue;
34990
+ if (!fs19.statSync(dir).isDirectory()) continue;
34415
34991
  } catch {
34416
34992
  continue;
34417
34993
  }
34418
- const skillMd = path23.join(dir, "SKILL.md");
34419
- if (!fs17.existsSync(skillMd)) continue;
34994
+ const skillMd = path25.join(dir, "SKILL.md");
34995
+ if (!fs19.existsSync(skillMd)) continue;
34420
34996
  const key = `${rel}/${name}`;
34421
34997
  if (seenKeys.has(key)) continue;
34422
34998
  seenKeys.add(key);
@@ -34428,23 +35004,23 @@ function discoverLocalSkills(cwd) {
34428
35004
  function discoverSkillLayoutRoots(cwd) {
34429
35005
  const roots = [];
34430
35006
  for (const rel of SKILL_DISCOVERY_ROOTS) {
34431
- const base = path23.join(cwd, rel);
34432
- if (!fs17.existsSync(base) || !fs17.statSync(base).isDirectory()) continue;
35007
+ const base = path25.join(cwd, rel);
35008
+ if (!fs19.existsSync(base) || !fs19.statSync(base).isDirectory()) continue;
34433
35009
  let entries = [];
34434
35010
  try {
34435
- entries = fs17.readdirSync(base);
35011
+ entries = fs19.readdirSync(base);
34436
35012
  } catch {
34437
35013
  continue;
34438
35014
  }
34439
35015
  const skills2 = [];
34440
35016
  for (const name of entries) {
34441
- const dir = path23.join(base, name);
35017
+ const dir = path25.join(base, name);
34442
35018
  try {
34443
- if (!fs17.statSync(dir).isDirectory()) continue;
35019
+ if (!fs19.statSync(dir).isDirectory()) continue;
34444
35020
  } catch {
34445
35021
  continue;
34446
35022
  }
34447
- if (!fs17.existsSync(path23.join(dir, "SKILL.md"))) continue;
35023
+ if (!fs19.existsSync(path25.join(dir, "SKILL.md"))) continue;
34448
35024
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
34449
35025
  skills2.push({ name, relPath });
34450
35026
  }
@@ -34589,12 +35165,12 @@ var handleAgentConfigMessage = (msg, deps) => {
34589
35165
  };
34590
35166
 
34591
35167
  // src/agents/acp/from-bridge/handle-bridge-prompt.ts
34592
- import * as path25 from "node:path";
35168
+ import * as path27 from "node:path";
34593
35169
  import { execFile as execFile5 } from "node:child_process";
34594
35170
  import { promisify as promisify5 } from "node:util";
34595
35171
 
34596
35172
  // src/git/bridge-queue-key.ts
34597
- import * as path24 from "node:path";
35173
+ import * as path26 from "node:path";
34598
35174
  import { createHash } from "node:crypto";
34599
35175
  function normalizeCanonicalGitUrl(url2) {
34600
35176
  let s = url2.trim();
@@ -34622,11 +35198,11 @@ function canonicalUrlToRepoIdSync(url2) {
34622
35198
  return createHash("sha256").update(normalized).digest("hex").slice(0, 32);
34623
35199
  }
34624
35200
  function fallbackRepoIdFromPath(absPath) {
34625
- return createHash("sha256").update(path24.resolve(absPath)).digest("hex").slice(0, 32);
35201
+ return createHash("sha256").update(path26.resolve(absPath)).digest("hex").slice(0, 32);
34626
35202
  }
34627
35203
  async function resolveBridgeQueueBindFields(options) {
34628
35204
  const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
34629
- const cwdAbs = worktreePaths.length > 0 ? path24.resolve(worktreePaths[0]) : path24.resolve(effectiveCwd);
35205
+ const cwdAbs = worktreePaths.length > 0 ? path26.resolve(worktreePaths[0]) : path26.resolve(effectiveCwd);
34630
35206
  if (!primaryRepoRoots.length) {
34631
35207
  log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
34632
35208
  return null;
@@ -34691,7 +35267,7 @@ function handleBridgePrompt(msg, deps) {
34691
35267
  };
34692
35268
  async function preambleAndPrompt(resolvedCwd) {
34693
35269
  const s = getWs();
34694
- const effectiveCwd = path25.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
35270
+ const effectiveCwd = path27.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
34695
35271
  const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
34696
35272
  const repoRoots = await resolveSnapshotRepoRoots({
34697
35273
  worktreePaths,
@@ -34814,8 +35390,8 @@ function randomSecret() {
34814
35390
  }
34815
35391
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
34816
35392
  }
34817
- async function requestPreviewApi(port, secret, method, path30, body) {
34818
- const url2 = `http://127.0.0.1:${port}${path30}`;
35393
+ async function requestPreviewApi(port, secret, method, path32, body) {
35394
+ const url2 = `http://127.0.0.1:${port}${path32}`;
34819
35395
  const headers = {
34820
35396
  [PREVIEW_SECRET_HEADER]: secret,
34821
35397
  "Content-Type": "application/json"
@@ -34827,7 +35403,7 @@ async function requestPreviewApi(port, secret, method, path30, body) {
34827
35403
  });
34828
35404
  const data = await res.json().catch(() => ({}));
34829
35405
  if (!res.ok) {
34830
- throw new Error(data?.error ?? `Preview API ${method} ${path30}: ${res.status}`);
35406
+ throw new Error(data?.error ?? `Preview API ${method} ${path32}: ${res.status}`);
34831
35407
  }
34832
35408
  return data;
34833
35409
  }
@@ -34990,15 +35566,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
34990
35566
  };
34991
35567
 
34992
35568
  // src/files/list-dir.ts
34993
- import fs18 from "node:fs";
34994
- import path27 from "node:path";
35569
+ import fs20 from "node:fs";
35570
+ import path29 from "node:path";
34995
35571
 
34996
35572
  // src/files/ensure-under-cwd.ts
34997
- import path26 from "node:path";
35573
+ import path28 from "node:path";
34998
35574
  function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
34999
- const normalized = path26.normalize(relativePath).replace(/^(\.\/)+/, "");
35000
- const resolved = path26.resolve(cwd, normalized);
35001
- if (!resolved.startsWith(cwd + path26.sep) && resolved !== cwd) {
35575
+ const normalized = path28.normalize(relativePath).replace(/^(\.\/)+/, "");
35576
+ const resolved = path28.resolve(cwd, normalized);
35577
+ if (!resolved.startsWith(cwd + path28.sep) && resolved !== cwd) {
35002
35578
  return null;
35003
35579
  }
35004
35580
  return resolved;
@@ -35012,7 +35588,7 @@ async function listDirAsync(relativePath) {
35012
35588
  return { error: "Path is outside working directory" };
35013
35589
  }
35014
35590
  try {
35015
- const names = await fs18.promises.readdir(resolved, { withFileTypes: true });
35591
+ const names = await fs20.promises.readdir(resolved, { withFileTypes: true });
35016
35592
  const visible = names.filter((d) => !d.name.startsWith("."));
35017
35593
  const entries = [];
35018
35594
  for (let i = 0; i < visible.length; i++) {
@@ -35020,12 +35596,12 @@ async function listDirAsync(relativePath) {
35020
35596
  await yieldToEventLoop();
35021
35597
  }
35022
35598
  const d = visible[i];
35023
- const entryPath = path27.join(relativePath || ".", d.name).replace(/\\/g, "/");
35024
- const fullPath = path27.join(resolved, d.name);
35599
+ const entryPath = path29.join(relativePath || ".", d.name).replace(/\\/g, "/");
35600
+ const fullPath = path29.join(resolved, d.name);
35025
35601
  let isDir = d.isDirectory();
35026
35602
  if (d.isSymbolicLink()) {
35027
35603
  try {
35028
- const targetStat = await fs18.promises.stat(fullPath);
35604
+ const targetStat = await fs20.promises.stat(fullPath);
35029
35605
  isDir = targetStat.isDirectory();
35030
35606
  } catch {
35031
35607
  isDir = false;
@@ -35050,25 +35626,25 @@ async function listDirAsync(relativePath) {
35050
35626
  }
35051
35627
 
35052
35628
  // src/files/read-file.ts
35053
- import fs19 from "node:fs";
35629
+ import fs21 from "node:fs";
35054
35630
  import { StringDecoder } from "node:string_decoder";
35055
35631
  function resolveFilePath(relativePath) {
35056
35632
  const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
35057
35633
  if (!resolved) return { error: "Path is outside working directory" };
35058
35634
  let real;
35059
35635
  try {
35060
- real = fs19.realpathSync(resolved);
35636
+ real = fs21.realpathSync(resolved);
35061
35637
  } catch {
35062
35638
  real = resolved;
35063
35639
  }
35064
- const stat2 = fs19.statSync(real);
35640
+ const stat2 = fs21.statSync(real);
35065
35641
  if (!stat2.isFile()) return { error: "Not a file" };
35066
35642
  return real;
35067
35643
  }
35068
35644
  var LINE_CHUNK_SIZE = 64 * 1024;
35069
35645
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
35070
- const fileSize = fs19.statSync(filePath).size;
35071
- const fd = fs19.openSync(filePath, "r");
35646
+ const fileSize = fs21.statSync(filePath).size;
35647
+ const fd = fs21.openSync(filePath, "r");
35072
35648
  const bufSize = 64 * 1024;
35073
35649
  const buf = Buffer.alloc(bufSize);
35074
35650
  const decoder = new StringDecoder("utf8");
@@ -35081,7 +35657,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
35081
35657
  let line0Accum = "";
35082
35658
  try {
35083
35659
  let bytesRead;
35084
- while (!done && (bytesRead = fs19.readSync(fd, buf, 0, bufSize, null)) > 0) {
35660
+ while (!done && (bytesRead = fs21.readSync(fd, buf, 0, bufSize, null)) > 0) {
35085
35661
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
35086
35662
  partial2 = "";
35087
35663
  let lineStart = 0;
@@ -35216,7 +35792,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
35216
35792
  }
35217
35793
  return { content: resultLines.join("\n"), size: fileSize };
35218
35794
  } finally {
35219
- fs19.closeSync(fd);
35795
+ fs21.closeSync(fd);
35220
35796
  }
35221
35797
  }
35222
35798
  function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
@@ -35227,8 +35803,8 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
35227
35803
  if (hasRange) {
35228
35804
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
35229
35805
  }
35230
- const stat2 = fs19.statSync(result);
35231
- const raw = fs19.readFileSync(result, "utf8");
35806
+ const stat2 = fs21.statSync(result);
35807
+ const raw = fs21.readFileSync(result, "utf8");
35232
35808
  const lines = raw.split(/\r?\n/);
35233
35809
  return { content: raw, totalLines: lines.length, size: stat2.size };
35234
35810
  } catch (err) {
@@ -35338,10 +35914,10 @@ function handleSkillLayoutRequest(msg, deps) {
35338
35914
  }
35339
35915
 
35340
35916
  // src/skills/install-remote-skills.ts
35341
- import fs20 from "node:fs";
35342
- import path28 from "node:path";
35917
+ import fs22 from "node:fs";
35918
+ import path30 from "node:path";
35343
35919
  function installRemoteSkills(cwd, targetDir, items) {
35344
- const installed = [];
35920
+ const installed2 = [];
35345
35921
  if (!Array.isArray(items)) {
35346
35922
  return { success: false, error: "Invalid items" };
35347
35923
  }
@@ -35350,24 +35926,24 @@ function installRemoteSkills(cwd, targetDir, items) {
35350
35926
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
35351
35927
  continue;
35352
35928
  }
35353
- const skillDir = path28.join(cwd, targetDir, item.skillName);
35929
+ const skillDir = path30.join(cwd, targetDir, item.skillName);
35354
35930
  for (const f of item.files) {
35355
35931
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
35356
- const dest = path28.join(skillDir, f.path);
35357
- fs20.mkdirSync(path28.dirname(dest), { recursive: true });
35932
+ const dest = path30.join(skillDir, f.path);
35933
+ fs22.mkdirSync(path30.dirname(dest), { recursive: true });
35358
35934
  if (f.text !== void 0) {
35359
- fs20.writeFileSync(dest, f.text, "utf8");
35935
+ fs22.writeFileSync(dest, f.text, "utf8");
35360
35936
  } else if (f.base64) {
35361
- fs20.writeFileSync(dest, Buffer.from(f.base64, "base64"));
35937
+ fs22.writeFileSync(dest, Buffer.from(f.base64, "base64"));
35362
35938
  }
35363
35939
  }
35364
- installed.push({
35940
+ installed2.push({
35365
35941
  sourceId: item.sourceId,
35366
35942
  skillName: item.skillName,
35367
35943
  versionHash: item.versionHash
35368
35944
  });
35369
35945
  }
35370
- return { success: true, installed };
35946
+ return { success: true, installed: installed2 };
35371
35947
  } catch (e) {
35372
35948
  return { success: false, error: e instanceof Error ? e.message : String(e) };
35373
35949
  }
@@ -35404,7 +35980,8 @@ var handleSessionGitRequestMessage = (msg, deps) => {
35404
35980
  if (typeof msg.id !== "string") return;
35405
35981
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
35406
35982
  const action = msg.action;
35407
- if (!sessionId || action !== "status" && action !== "push" && action !== "commit") return;
35983
+ if (!sessionId || action !== "status" && action !== "push" && action !== "commit" && action !== "list_changes")
35984
+ return;
35408
35985
  void (async () => {
35409
35986
  const ws = deps.getWs();
35410
35987
  const reply = (payload) => sendResult(ws, msg.id, payload);
@@ -35418,6 +35995,24 @@ var handleSessionGitRequestMessage = (msg, deps) => {
35418
35995
  });
35419
35996
  return;
35420
35997
  }
35998
+ if (action === "list_changes") {
35999
+ const repoRel = typeof msg.changesRepoRelPath === "string" ? msg.changesRepoRelPath.trim() : "";
36000
+ const view = msg.changesView === "commit" ? "commit" : "working";
36001
+ const commitSha = typeof msg.changesCommitSha === "string" ? msg.changesCommitSha.trim() : "";
36002
+ if (view === "commit") {
36003
+ if (!repoRel || !commitSha) {
36004
+ reply({ ok: false, error: "changesRepoRelPath and changesCommitSha are required for commit view" });
36005
+ return;
36006
+ }
36007
+ }
36008
+ const opts = repoRel && view === "commit" && commitSha ? { repoRelPath: repoRel, basis: { kind: "commit", sha: commitSha } } : repoRel ? { repoRelPath: repoRel, basis: { kind: "working" } } : void 0;
36009
+ const repos = await deps.sessionWorktreeManager.getSessionWorkingTreeChangeDetails(sessionId, opts);
36010
+ reply({
36011
+ ok: true,
36012
+ repos
36013
+ });
36014
+ return;
36015
+ }
35421
36016
  if (action === "push") {
35422
36017
  const pushRes = await deps.sessionWorktreeManager.pushSessionUpstream(sessionId);
35423
36018
  if (!pushRes.ok) {
@@ -35484,7 +36079,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
35484
36079
  };
35485
36080
 
35486
36081
  // src/bridge/routing/handlers/revert-turn-snapshot.ts
35487
- import * as fs21 from "node:fs";
36082
+ import * as fs23 from "node:fs";
35488
36083
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
35489
36084
  const id = typeof msg.id === "string" ? msg.id : "";
35490
36085
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -35496,7 +36091,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
35496
36091
  if (!s) return;
35497
36092
  const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
35498
36093
  const file2 = snapshotFilePath(agentBase, turnId);
35499
- if (!fs21.existsSync(file2)) {
36094
+ if (!fs23.existsSync(file2)) {
35500
36095
  sendWsMessage(s, {
35501
36096
  type: "revert_turn_snapshot_result",
35502
36097
  id,
@@ -35825,6 +36420,7 @@ async function createBridgeConnection(options) {
35825
36420
 
35826
36421
  // src/run-bridge.ts
35827
36422
  async function runBridge(options) {
36423
+ installBridgeProcessResilience();
35828
36424
  const { apiUrl, workspaceId, authToken, refreshToken, bridgeName, justAuthenticated, worktreesRootAbs } = options;
35829
36425
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
35830
36426
  const hasAuth = workspaceId && authToken;
@@ -35936,9 +36532,9 @@ async function main() {
35936
36532
  let authToken = opts.token;
35937
36533
  const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAMATON_FIREHOSE_URL ?? process.env.BUILDAMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
35938
36534
  if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
35939
- const resolvedCwd = path29.resolve(process.cwd(), opts.cwd.trim());
36535
+ const resolvedCwd = path31.resolve(process.cwd(), opts.cwd.trim());
35940
36536
  try {
35941
- const st = fs22.statSync(resolvedCwd);
36537
+ const st = fs24.statSync(resolvedCwd);
35942
36538
  if (!st.isDirectory()) {
35943
36539
  console.error(`--cwd is not a directory: ${resolvedCwd}`);
35944
36540
  process.exit(1);
@@ -35952,7 +36548,7 @@ async function main() {
35952
36548
  initBridgeWorkspaceDirectory();
35953
36549
  let worktreesRootAbs;
35954
36550
  if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
35955
- worktreesRootAbs = path29.resolve(opts.worktreesRoot.trim());
36551
+ worktreesRootAbs = path31.resolve(opts.worktreesRoot.trim());
35956
36552
  }
35957
36553
  let refreshToken;
35958
36554
  if ((!workspaceId || !authToken) && opts.config !== false) {