@buildautomaton/cli 0.1.19 → 0.1.21

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/index.js CHANGED
@@ -2240,7 +2240,7 @@ var require_websocket = __commonJS({
2240
2240
  var http = __require("http");
2241
2241
  var net = __require("net");
2242
2242
  var tls = __require("tls");
2243
- var { randomBytes: randomBytes2, createHash: createHash2 } = __require("crypto");
2243
+ var { randomBytes: randomBytes2, createHash } = __require("crypto");
2244
2244
  var { Duplex, Readable: Readable2 } = __require("stream");
2245
2245
  var { URL: URL2 } = __require("url");
2246
2246
  var PerMessageDeflate = require_permessage_deflate();
@@ -2900,7 +2900,7 @@ var require_websocket = __commonJS({
2900
2900
  abortHandshake(websocket, socket, "Invalid Upgrade header");
2901
2901
  return;
2902
2902
  }
2903
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
2903
+ const digest = createHash("sha1").update(key + GUID).digest("base64");
2904
2904
  if (res.headers["sec-websocket-accept"] !== digest) {
2905
2905
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
2906
2906
  return;
@@ -3267,7 +3267,7 @@ var require_websocket_server = __commonJS({
3267
3267
  var EventEmitter2 = __require("events");
3268
3268
  var http = __require("http");
3269
3269
  var { Duplex } = __require("stream");
3270
- var { createHash: createHash2 } = __require("crypto");
3270
+ var { createHash } = __require("crypto");
3271
3271
  var extension = require_extension();
3272
3272
  var PerMessageDeflate = require_permessage_deflate();
3273
3273
  var subprotocol = require_subprotocol();
@@ -3568,7 +3568,7 @@ var require_websocket_server = __commonJS({
3568
3568
  );
3569
3569
  }
3570
3570
  if (this._state > RUNNING) return abortHandshake(socket, 503);
3571
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
3571
+ const digest = createHash("sha1").update(key + GUID).digest("base64");
3572
3572
  const headers = [
3573
3573
  "HTTP/1.1 101 Switching Protocols",
3574
3574
  "Upgrade: websocket",
@@ -20943,8 +20943,8 @@ var init_acp = __esm({
20943
20943
  this.#requestHandler = requestHandler;
20944
20944
  this.#notificationHandler = notificationHandler;
20945
20945
  this.#stream = stream;
20946
- this.#closedPromise = new Promise((resolve17) => {
20947
- this.#abortController.signal.addEventListener("abort", () => resolve17());
20946
+ this.#closedPromise = new Promise((resolve16) => {
20947
+ this.#abortController.signal.addEventListener("abort", () => resolve16());
20948
20948
  });
20949
20949
  this.#receive();
20950
20950
  }
@@ -21093,8 +21093,8 @@ var init_acp = __esm({
21093
21093
  }
21094
21094
  async sendRequest(method, params) {
21095
21095
  const id = this.#nextRequestId++;
21096
- const responsePromise = new Promise((resolve17, reject) => {
21097
- this.#pendingResponses.set(id, { resolve: resolve17, reject });
21096
+ const responsePromise = new Promise((resolve16, reject) => {
21097
+ this.#pendingResponses.set(id, { resolve: resolve16, reject });
21098
21098
  });
21099
21099
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
21100
21100
  return responsePromise;
@@ -21669,7 +21669,7 @@ var require_has_flag = __commonJS({
21669
21669
  var require_supports_color = __commonJS({
21670
21670
  "../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
21671
21671
  "use strict";
21672
- var os6 = __require("os");
21672
+ var os7 = __require("os");
21673
21673
  var tty = __require("tty");
21674
21674
  var hasFlag = require_has_flag();
21675
21675
  var { env } = process;
@@ -21717,7 +21717,7 @@ var require_supports_color = __commonJS({
21717
21717
  return min;
21718
21718
  }
21719
21719
  if (process.platform === "win32") {
21720
- const osRelease = os6.release().split(".");
21720
+ const osRelease = os7.release().split(".");
21721
21721
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
21722
21722
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
21723
21723
  }
@@ -22268,14 +22268,14 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
22268
22268
  return out.join("\n");
22269
22269
  }
22270
22270
 
22271
- // src/files/cwd/bridge-workspace-directory.ts
22271
+ // src/files/cwd/bridge-root.ts
22272
22272
  import * as path from "node:path";
22273
- var bridgeWorkspaceDirectory = null;
22274
- function getBridgeWorkspaceDirectory() {
22275
- if (bridgeWorkspaceDirectory == null) {
22276
- bridgeWorkspaceDirectory = path.resolve(process.cwd());
22273
+ var bridgeRootPath = null;
22274
+ function getBridgeRoot() {
22275
+ if (bridgeRootPath == null) {
22276
+ bridgeRootPath = path.resolve(process.cwd());
22277
22277
  }
22278
- return bridgeWorkspaceDirectory;
22278
+ return bridgeRootPath;
22279
22279
  }
22280
22280
 
22281
22281
  // src/agents/acp/safe-fs-path.ts
@@ -22373,6 +22373,52 @@ function createSdkStdioExtNotificationHandler(options) {
22373
22373
  }
22374
22374
  }
22375
22375
 
22376
+ // src/agents/acp/enrich-acp-permission-rpc-result.ts
22377
+ var META_KEY = "permissionOptionKind";
22378
+ function optionRecordId(rec) {
22379
+ const raw = rec.optionId ?? rec.id;
22380
+ if (typeof raw === "string" && raw.trim() !== "") return raw.trim();
22381
+ if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
22382
+ return "";
22383
+ }
22384
+ function enrichAcpPermissionRpcResultFromRequestParams(result, params) {
22385
+ if (params == null || result == null || typeof result !== "object" || Array.isArray(result)) {
22386
+ return result;
22387
+ }
22388
+ const root = result;
22389
+ const outcome = root.outcome;
22390
+ if (outcome == null || typeof outcome !== "object" || Array.isArray(outcome)) return result;
22391
+ const o = outcome;
22392
+ if (o.outcome !== "selected" || typeof o.optionId !== "string" || o.optionId.trim() === "") {
22393
+ return result;
22394
+ }
22395
+ const selectedId = o.optionId.trim();
22396
+ const prevMeta = o._meta != null && typeof o._meta === "object" && !Array.isArray(o._meta) ? o._meta : {};
22397
+ if (typeof prevMeta[META_KEY] === "string" && prevMeta[META_KEY].trim() !== "") {
22398
+ return result;
22399
+ }
22400
+ const rawOpts = Array.isArray(params.options) ? params.options : [];
22401
+ let matchedKind;
22402
+ for (const item of rawOpts) {
22403
+ if (item == null || typeof item !== "object" || Array.isArray(item)) continue;
22404
+ const rec = item;
22405
+ const id = optionRecordId(rec);
22406
+ if (!id || id !== selectedId) continue;
22407
+ if (typeof rec.kind === "string" && rec.kind.trim() !== "") {
22408
+ matchedKind = rec.kind.trim();
22409
+ break;
22410
+ }
22411
+ }
22412
+ if (!matchedKind) return result;
22413
+ return {
22414
+ ...root,
22415
+ outcome: {
22416
+ ...o,
22417
+ _meta: { ...prevMeta, [META_KEY]: matchedKind }
22418
+ }
22419
+ };
22420
+ }
22421
+
22376
22422
  // src/agents/acp/clients/sdk-stdio-acp-client.ts
22377
22423
  function formatSpawnError(err, command) {
22378
22424
  if (err.code === "ENOENT") {
@@ -22394,7 +22440,7 @@ async function createSdkStdioAcpClient(options) {
22394
22440
  const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
22395
22441
  const {
22396
22442
  command,
22397
- cwd = getBridgeWorkspaceDirectory(),
22443
+ cwd = getBridgeRoot(),
22398
22444
  backendAgentType,
22399
22445
  onSessionUpdate,
22400
22446
  onRequest,
@@ -22413,7 +22459,7 @@ async function createSdkStdioAcpClient(options) {
22413
22459
  child.once("close", (code, signal) => {
22414
22460
  onAgentSubprocessExit?.({ code, signal });
22415
22461
  });
22416
- return new Promise((resolve17, reject) => {
22462
+ return new Promise((resolve16, reject) => {
22417
22463
  let initSettled = false;
22418
22464
  const settleReject = (err) => {
22419
22465
  if (initSettled) return;
@@ -22427,7 +22473,7 @@ async function createSdkStdioAcpClient(options) {
22427
22473
  const settleResolve = (handle) => {
22428
22474
  if (initSettled) return;
22429
22475
  initSettled = true;
22430
- resolve17(handle);
22476
+ resolve16(handle);
22431
22477
  };
22432
22478
  child.on("error", (err) => {
22433
22479
  settleReject(new Error(formatSpawnError(err, command[0])));
@@ -22450,7 +22496,7 @@ async function createSdkStdioAcpClient(options) {
22450
22496
  onSessionUpdate
22451
22497
  });
22452
22498
  let permissionSeq = 0;
22453
- const pendingPermissionResolvers = /* @__PURE__ */ new Map();
22499
+ const pendingPermissionReplies = /* @__PURE__ */ new Map();
22454
22500
  const client = (_agent) => ({
22455
22501
  async requestPermission(params) {
22456
22502
  const requestId = `perm-${++permissionSeq}`;
@@ -22463,15 +22509,15 @@ async function createSdkStdioAcpClient(options) {
22463
22509
  });
22464
22510
  } catch {
22465
22511
  }
22466
- return await new Promise((resolve18) => {
22467
- pendingPermissionResolvers.set(requestId, resolve18);
22512
+ return await new Promise((resolve17) => {
22513
+ pendingPermissionReplies.set(requestId, { resolve: resolve17, params: paramsRecord });
22468
22514
  });
22469
22515
  },
22470
22516
  async readTextFile(params) {
22471
- const abs = resolveSafePathUnderCwd(cwd, params.path);
22472
- if (!abs) throw new Error("Invalid or disallowed path");
22517
+ const resolvedPath = resolveSafePathUnderCwd(cwd, params.path);
22518
+ if (!resolvedPath) throw new Error("Invalid or disallowed path");
22473
22519
  try {
22474
- let content = readFileSync(abs, "utf8");
22520
+ let content = readFileSync(resolvedPath, "utf8");
22475
22521
  content = sliceFileContentRange(content, params.line, params.limit);
22476
22522
  return { content };
22477
22523
  } catch (e) {
@@ -22480,17 +22526,17 @@ async function createSdkStdioAcpClient(options) {
22480
22526
  }
22481
22527
  },
22482
22528
  async writeTextFile(params) {
22483
- const abs = resolveSafePathUnderCwd(cwd, params.path);
22484
- if (!abs) throw new Error("Invalid or disallowed path");
22529
+ const resolvedPath = resolveSafePathUnderCwd(cwd, params.path);
22530
+ if (!resolvedPath) throw new Error("Invalid or disallowed path");
22485
22531
  let oldText = "";
22486
22532
  try {
22487
- oldText = readFileSync(abs, "utf8");
22533
+ oldText = readFileSync(resolvedPath, "utf8");
22488
22534
  } catch (e) {
22489
22535
  if (e.code !== "ENOENT") throw e;
22490
22536
  }
22491
- mkdirSync(dirname(abs), { recursive: true });
22492
- writeFileSync(abs, params.content, "utf8");
22493
- const displayPath = toDisplayPathRelativeToCwd(cwd, abs);
22537
+ mkdirSync(dirname(resolvedPath), { recursive: true });
22538
+ writeFileSync(resolvedPath, params.content, "utf8");
22539
+ const displayPath = toDisplayPathRelativeToCwd(cwd, resolvedPath);
22494
22540
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, params.content);
22495
22541
  onFileChange?.({ path: displayPath, oldText, newText: params.content, patchContent });
22496
22542
  return {};
@@ -22572,9 +22618,9 @@ async function createSdkStdioAcpClient(options) {
22572
22618
  }
22573
22619
  },
22574
22620
  async cancel() {
22575
- for (const [id, resolve18] of [...pendingPermissionResolvers.entries()]) {
22576
- pendingPermissionResolvers.delete(id);
22577
- resolve18({ outcome: { outcome: "cancelled" } });
22621
+ for (const [id, entry] of [...pendingPermissionReplies.entries()]) {
22622
+ pendingPermissionReplies.delete(id);
22623
+ entry.resolve({ outcome: { outcome: "cancelled" } });
22578
22624
  }
22579
22625
  try {
22580
22626
  await connection.cancel({ sessionId });
@@ -22590,10 +22636,11 @@ async function createSdkStdioAcpClient(options) {
22590
22636
  }
22591
22637
  },
22592
22638
  resolveRequest(requestId, result) {
22593
- const resolve18 = pendingPermissionResolvers.get(requestId);
22594
- if (!resolve18) return;
22595
- pendingPermissionResolvers.delete(requestId);
22596
- resolve18(result);
22639
+ const entry = pendingPermissionReplies.get(requestId);
22640
+ if (!entry) return;
22641
+ pendingPermissionReplies.delete(requestId);
22642
+ const enriched = enrichAcpPermissionRpcResultFromRequestParams(result, entry.params);
22643
+ entry.resolve(enriched);
22597
22644
  },
22598
22645
  disconnect() {
22599
22646
  child.kill();
@@ -22700,7 +22747,7 @@ async function proxyToLocal(request) {
22700
22747
  };
22701
22748
  const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
22702
22749
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
22703
- const once = await new Promise((resolve17) => {
22750
+ const once = await new Promise((resolve16) => {
22704
22751
  const req = mod.request(opts, (res) => {
22705
22752
  const chunks = [];
22706
22753
  res.on("data", (c) => chunks.push(c));
@@ -22711,7 +22758,7 @@ async function proxyToLocal(request) {
22711
22758
  if (typeof v === "string") headers[k] = v;
22712
22759
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
22713
22760
  }
22714
- resolve17({
22761
+ resolve16({
22715
22762
  id: request.id,
22716
22763
  statusCode: res.statusCode ?? 0,
22717
22764
  headers,
@@ -22720,7 +22767,7 @@ async function proxyToLocal(request) {
22720
22767
  });
22721
22768
  });
22722
22769
  req.on("error", (err) => {
22723
- resolve17({
22770
+ resolve16({
22724
22771
  id: request.id,
22725
22772
  statusCode: 0,
22726
22773
  headers: {},
@@ -22862,7 +22909,7 @@ var previewSkill = {
22862
22909
  const exe = parts[0];
22863
22910
  const args = parts.slice(1);
22864
22911
  previewProcess = spawn2(isWindows && exe === "npm" ? "npm.cmd" : exe, args, {
22865
- cwd: getBridgeWorkspaceDirectory(),
22912
+ cwd: getBridgeRoot(),
22866
22913
  stdio: ["ignore", "pipe", "pipe"],
22867
22914
  env: {
22868
22915
  ...process.env,
@@ -23041,7 +23088,7 @@ function installBridgeProcessResilience() {
23041
23088
  }
23042
23089
 
23043
23090
  // src/cli-version.ts
23044
- var CLI_VERSION = "0.1.19".length > 0 ? "0.1.19" : "0.0.0-dev";
23091
+ var CLI_VERSION = "0.1.21".length > 0 ? "0.1.21" : "0.0.0-dev";
23045
23092
 
23046
23093
  // ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
23047
23094
  import process7 from "node:process";
@@ -23476,14 +23523,14 @@ var baseOpen = async (options) => {
23476
23523
  }
23477
23524
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
23478
23525
  if (options.wait) {
23479
- return new Promise((resolve17, reject) => {
23526
+ return new Promise((resolve16, reject) => {
23480
23527
  subprocess.once("error", reject);
23481
23528
  subprocess.once("close", (exitCode) => {
23482
23529
  if (!options.allowNonzeroExitCode && exitCode > 0) {
23483
23530
  reject(new Error(`Exited with code ${exitCode}`));
23484
23531
  return;
23485
23532
  }
23486
- resolve17(subprocess);
23533
+ resolve16(subprocess);
23487
23534
  });
23488
23535
  });
23489
23536
  }
@@ -23779,8 +23826,8 @@ function runPendingAuth(options) {
23779
23826
  let hasOpenedBrowser = false;
23780
23827
  let resolved = false;
23781
23828
  let resolveAuth;
23782
- const authPromise = new Promise((resolve17) => {
23783
- resolveAuth = resolve17;
23829
+ const authPromise = new Promise((resolve16) => {
23830
+ resolveAuth = resolve16;
23784
23831
  });
23785
23832
  let reconnectAttempt = 0;
23786
23833
  const signInQuiet = createEmptyReconnectQuietSlot();
@@ -23902,7 +23949,7 @@ function runPendingAuth(options) {
23902
23949
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
23903
23950
  const say = log2 ?? logImmediate;
23904
23951
  say("Cleaning up connections\u2026");
23905
- await new Promise((resolve17) => setImmediate(resolve17));
23952
+ await new Promise((resolve16) => setImmediate(resolve16));
23906
23953
  state.closedByUser = true;
23907
23954
  clearReconnectQuietTimer(state.mainQuiet);
23908
23955
  clearReconnectQuietTimer(state.firehoseQuiet);
@@ -23944,21 +23991,36 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
23944
23991
  say("Shutdown complete.");
23945
23992
  }
23946
23993
 
23994
+ // src/paths/session-layout-paths.ts
23995
+ import * as path5 from "node:path";
23996
+ function resolveIsolatedSessionParentPathFromCheckouts(worktreePaths) {
23997
+ const resolved = worktreePaths.map((p) => path5.resolve(p)).filter(Boolean);
23998
+ if (resolved.length === 0) return null;
23999
+ resolved.sort();
24000
+ return resolved[0];
24001
+ }
24002
+ function resolveSessionParentPathForAgentProcess(resolvedSessionParentPath) {
24003
+ if (resolvedSessionParentPath != null && String(resolvedSessionParentPath).trim() !== "") {
24004
+ return path5.resolve(String(resolvedSessionParentPath).trim());
24005
+ }
24006
+ return getBridgeRoot();
24007
+ }
24008
+
23947
24009
  // src/git/session-git-queue.ts
23948
24010
  import { execFile as execFile7 } from "node:child_process";
23949
24011
  import { readFile, stat } from "node:fs/promises";
23950
24012
  import { promisify as promisify7 } from "node:util";
23951
- import * as path7 from "node:path";
24013
+ import * as path8 from "node:path";
23952
24014
 
23953
24015
  // src/git/pre-turn-snapshot.ts
23954
24016
  import * as fs8 from "node:fs";
23955
- import * as path6 from "node:path";
24017
+ import * as path7 from "node:path";
23956
24018
  import { execFile as execFile6 } from "node:child_process";
23957
24019
  import { promisify as promisify6 } from "node:util";
23958
24020
 
23959
24021
  // src/git/discover-repos.ts
23960
24022
  import * as fs7 from "node:fs";
23961
- import * as path5 from "node:path";
24023
+ import * as path6 from "node:path";
23962
24024
 
23963
24025
  // ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
23964
24026
  var import_file_exists = __toESM(require_dist(), 1);
@@ -28543,9 +28605,9 @@ async function isGitRepoDirectory(dirPath) {
28543
28605
  }
28544
28606
 
28545
28607
  // src/git/discover-repos.ts
28546
- async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
28608
+ async function discoverGitRepos(cwd = getBridgeRoot()) {
28547
28609
  const result = [];
28548
- const cwdResolved = path5.resolve(cwd);
28610
+ const cwdResolved = path6.resolve(cwd);
28549
28611
  if (await isGitRepoDirectory(cwdResolved)) {
28550
28612
  const remoteUrl = await getRemoteOriginUrl(cwdResolved);
28551
28613
  result.push({ absolutePath: cwdResolved, remoteUrl });
@@ -28558,7 +28620,7 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
28558
28620
  }
28559
28621
  for (const ent of entries) {
28560
28622
  if (!ent.isDirectory()) continue;
28561
- const childPath = path5.join(cwdResolved, ent.name);
28623
+ const childPath = path6.join(cwdResolved, ent.name);
28562
28624
  if (await isGitRepoDirectory(childPath)) {
28563
28625
  const remoteUrl = await getRemoteOriginUrl(childPath);
28564
28626
  result.push({ absolutePath: childPath, remoteUrl });
@@ -28566,12 +28628,12 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
28566
28628
  }
28567
28629
  return result;
28568
28630
  }
28569
- async function discoverGitReposUnderRoot(rootAbs) {
28570
- const root = path5.resolve(rootAbs);
28631
+ async function discoverGitReposUnderRoot(rootPath) {
28632
+ const root = path6.resolve(rootPath);
28571
28633
  const roots = [];
28572
28634
  async function walk(dir) {
28573
28635
  if (await isGitRepoDirectory(dir)) {
28574
- roots.push(path5.resolve(dir));
28636
+ roots.push(path6.resolve(dir));
28575
28637
  return;
28576
28638
  }
28577
28639
  let entries;
@@ -28582,7 +28644,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
28582
28644
  }
28583
28645
  for (const ent of entries) {
28584
28646
  if (!ent.isDirectory() || ent.name === ".git") continue;
28585
- await walk(path5.join(dir, ent.name));
28647
+ await walk(path6.join(dir, ent.name));
28586
28648
  }
28587
28649
  }
28588
28650
  await walk(root);
@@ -28598,7 +28660,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
28598
28660
  // src/git/pre-turn-snapshot.ts
28599
28661
  var execFileAsync5 = promisify6(execFile6);
28600
28662
  function snapshotsDirForCwd(agentCwd) {
28601
- return path6.join(agentCwd, ".buildautomaton", "snapshots");
28663
+ return path7.join(agentCwd, ".buildautomaton", "snapshots");
28602
28664
  }
28603
28665
  async function gitStashCreate(repoRoot, log2) {
28604
28666
  try {
@@ -28625,14 +28687,20 @@ async function gitRun(repoRoot, args, log2, label) {
28625
28687
  }
28626
28688
  }
28627
28689
  async function resolveSnapshotRepoRoots(options) {
28628
- const { worktreePaths, fallbackCwd, log: log2 } = options;
28690
+ const { worktreePaths, fallbackCwd, sessionId, log: log2 } = options;
28629
28691
  if (worktreePaths?.length) {
28630
- const uniq = [...new Set(worktreePaths.map((p) => path6.resolve(p)))];
28692
+ const uniq = [...new Set(worktreePaths.map((p) => path7.resolve(p)))];
28631
28693
  return uniq;
28632
28694
  }
28633
28695
  try {
28634
28696
  const repos = await discoverGitReposUnderRoot(fallbackCwd);
28635
- return repos.map((r) => r.absolutePath);
28697
+ const mapped = repos.map((r) => r.absolutePath);
28698
+ const sid = sessionId?.trim();
28699
+ if (sid) {
28700
+ const filtered = mapped.filter((root) => path7.basename(root) === sid);
28701
+ if (filtered.length > 0) return filtered;
28702
+ }
28703
+ return mapped;
28636
28704
  } catch (e) {
28637
28705
  log2(`[snapshot] Discover repositories failed: ${e instanceof Error ? e.message : String(e)}`);
28638
28706
  return [];
@@ -28659,7 +28727,7 @@ async function capturePreTurnSnapshot(options) {
28659
28727
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
28660
28728
  repos
28661
28729
  };
28662
- const filePath = path6.join(dir, `${runId}.json`);
28730
+ const filePath = path7.join(dir, `${runId}.json`);
28663
28731
  try {
28664
28732
  fs8.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
28665
28733
  } catch (e) {
@@ -28697,7 +28765,7 @@ async function applyPreTurnSnapshot(filePath, log2) {
28697
28765
  return { ok: true };
28698
28766
  }
28699
28767
  function snapshotFilePath(agentCwd, runId) {
28700
- return path6.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
28768
+ return path7.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
28701
28769
  }
28702
28770
 
28703
28771
  // src/git/session-git-queue.ts
@@ -28746,7 +28814,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
28746
28814
  continue;
28747
28815
  }
28748
28816
  const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
28749
- const slug = path7.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
28817
+ const slug = path8.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
28750
28818
  for (const rel of lines) {
28751
28819
  if (rel.includes("..")) continue;
28752
28820
  try {
@@ -28760,8 +28828,8 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
28760
28828
  );
28761
28829
  if (!patchContent.trim()) continue;
28762
28830
  const displayPath = multiRepo ? `${slug}/${rel}` : rel;
28763
- const absFile = path7.join(repo.path, rel);
28764
- const newText = await readWorkspaceFileAsUtf8(absFile);
28831
+ const workspaceFilePath = path8.join(repo.path, rel);
28832
+ const newText = await readWorkspaceFileAsUtf8(workspaceFilePath);
28765
28833
  sendSessionUpdate({
28766
28834
  type: "session_file_change",
28767
28835
  sessionId,
@@ -28779,18 +28847,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
28779
28847
  }
28780
28848
  }
28781
28849
 
28782
- // ../types/dist/index.js
28783
- init_zod();
28784
- init_zod();
28785
- init_zod();
28786
- init_zod();
28787
- init_zod();
28788
- init_zod();
28789
- init_zod();
28790
- init_zod();
28791
- init_zod();
28792
- init_zod();
28793
- init_zod();
28850
+ // ../types/src/work-items.ts
28794
28851
  init_zod();
28795
28852
  var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
28796
28853
  var WorkItemProgressSchema = external_exports.object({
@@ -28831,6 +28888,9 @@ var WorkItemSchema = external_exports.object({
28831
28888
  dependencies: external_exports.array(WorkItemDependencySchema).default([]),
28832
28889
  assignedToUserId: external_exports.string().optional()
28833
28890
  });
28891
+
28892
+ // ../types/src/user-profiles.ts
28893
+ init_zod();
28834
28894
  var UserWorkspaceProfileSchema = external_exports.object({
28835
28895
  id: external_exports.string(),
28836
28896
  workspaceId: external_exports.string(),
@@ -28840,6 +28900,9 @@ var UserWorkspaceProfileSchema = external_exports.object({
28840
28900
  preferences: external_exports.record(external_exports.unknown()).optional(),
28841
28901
  learnings: external_exports.array(external_exports.string())
28842
28902
  });
28903
+
28904
+ // ../types/src/runtime.ts
28905
+ init_zod();
28843
28906
  var WorkspaceOwnerInfoSchema = external_exports.object({
28844
28907
  ownerId: external_exports.string(),
28845
28908
  ownerName: external_exports.string().optional(),
@@ -28853,6 +28916,9 @@ var WorkspaceRuntimeEntrySchema = external_exports.object({
28853
28916
  owner: WorkspaceOwnerInfoSchema.optional(),
28854
28917
  isOwner: external_exports.boolean().optional()
28855
28918
  });
28919
+
28920
+ // ../types/src/agent.ts
28921
+ init_zod();
28856
28922
  var ProjectContextSchema = external_exports.object({
28857
28923
  projectId: external_exports.string(),
28858
28924
  context: external_exports.record(external_exports.unknown()).default({}),
@@ -28877,6 +28943,9 @@ var WebSocketMessageSchema = external_exports.object({
28877
28943
  data: external_exports.any().optional(),
28878
28944
  error: external_exports.string().optional()
28879
28945
  });
28946
+
28947
+ // ../types/src/checkpoints.ts
28948
+ init_zod();
28880
28949
  var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
28881
28950
  var CheckpointSummarySchema = external_exports.object({
28882
28951
  id: external_exports.string(),
@@ -28887,6 +28956,9 @@ var CheckpointSummarySchema = external_exports.object({
28887
28956
  createdAt: external_exports.string(),
28888
28957
  updatedAt: external_exports.string()
28889
28958
  });
28959
+
28960
+ // ../types/src/threads.ts
28961
+ init_zod();
28890
28962
  var ThreadMetaSchema = external_exports.object({
28891
28963
  threadId: external_exports.string(),
28892
28964
  workspaceId: external_exports.string(),
@@ -28914,6 +28986,9 @@ var ThreadMessageSchema = external_exports.object({
28914
28986
  var ThreadCheckpointSummarySchema = CheckpointSummarySchema.extend({
28915
28987
  threadId: external_exports.string()
28916
28988
  });
28989
+
28990
+ // ../types/src/content-items.ts
28991
+ init_zod();
28917
28992
  var ContentSourceSchema = external_exports.enum(["notion", "doc", "slack_thread", "other"]);
28918
28993
  var ContentItemMetaSchema = external_exports.object({
28919
28994
  contentId: external_exports.string(),
@@ -28935,6 +29010,9 @@ var ContentStorageRefSchema = external_exports.object({
28935
29010
  var ContentCheckpointSummarySchema = CheckpointSummarySchema.extend({
28936
29011
  contentId: external_exports.string()
28937
29012
  });
29013
+
29014
+ // ../types/src/stories.ts
29015
+ init_zod();
28938
29016
  var StoryMetaSchema = external_exports.object({
28939
29017
  storyId: external_exports.string(),
28940
29018
  workspaceId: external_exports.string(),
@@ -28957,6 +29035,9 @@ var StoryContentItemRefSchema = external_exports.object({
28957
29035
  var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
28958
29036
  storyId: external_exports.string()
28959
29037
  });
29038
+
29039
+ // ../types/src/sessions.ts
29040
+ init_zod();
28960
29041
  var BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID = "__builtin_change_summary__";
28961
29042
  var SessionMetaSchema = external_exports.object({
28962
29043
  sessionId: external_exports.string(),
@@ -28999,6 +29080,8 @@ var SessionThreadRefSchema = external_exports.object({
28999
29080
  threadId: external_exports.string(),
29000
29081
  addedAt: external_exports.string()
29001
29082
  });
29083
+
29084
+ // ../types/src/change-summary-path.ts
29002
29085
  function normalizeRepoRelativePath(p) {
29003
29086
  let t = p.trim().replace(/\\/g, "/");
29004
29087
  while (t.startsWith("./")) t = t.slice(2);
@@ -29015,6 +29098,8 @@ function resolveChangeSummaryPathAgainstAllowed(rawPath, allowed) {
29015
29098
  }
29016
29099
  return null;
29017
29100
  }
29101
+
29102
+ // ../types/src/parse-change-summary-json.ts
29018
29103
  function clampSummaryToAtMostTwoLines(summary) {
29019
29104
  const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
29020
29105
  return lines.slice(0, 2).join("\n");
@@ -29057,6 +29142,8 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
29057
29142
  }
29058
29143
  return rows;
29059
29144
  }
29145
+
29146
+ // ../types/src/build-change-summary-prompt.ts
29060
29147
  var PATCH_PREVIEW_MAX = 12e3;
29061
29148
  function clip(s, max) {
29062
29149
  if (s.length <= max) return s;
@@ -29114,6 +29201,8 @@ function buildSessionChangeSummaryPrompt(files) {
29114
29201
  }
29115
29202
  return lines.join("\n");
29116
29203
  }
29204
+
29205
+ // ../types/src/dedupe-session-file-changes-by-path.ts
29117
29206
  function defaultRichness(c) {
29118
29207
  const patch = typeof c.patchContent === "string" ? c.patchContent.length : 0;
29119
29208
  const nt = typeof c.newText === "string" ? c.newText.length : 0;
@@ -29131,6 +29220,9 @@ function dedupeSessionFileChangesByPath(items, richness = (item) => defaultRichn
29131
29220
  }
29132
29221
  return Array.from(byPath.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([, v]) => v);
29133
29222
  }
29223
+
29224
+ // ../types/src/artifacts.ts
29225
+ init_zod();
29134
29226
  var ArtifactMetaSchema = external_exports.object({
29135
29227
  artifactId: external_exports.string(),
29136
29228
  workspaceId: external_exports.string(),
@@ -29144,6 +29236,9 @@ var ArtifactMetaSchema = external_exports.object({
29144
29236
  createdAt: external_exports.string(),
29145
29237
  updatedAt: external_exports.string()
29146
29238
  });
29239
+
29240
+ // ../types/src/templates.ts
29241
+ init_zod();
29147
29242
  var TemplateMetaSchema = external_exports.object({
29148
29243
  templateId: external_exports.string(),
29149
29244
  workspaceId: external_exports.string(),
@@ -29153,6 +29248,9 @@ var TemplateMetaSchema = external_exports.object({
29153
29248
  createdAt: external_exports.string(),
29154
29249
  updatedAt: external_exports.string()
29155
29250
  });
29251
+
29252
+ // ../types/src/git-repos.ts
29253
+ init_zod();
29156
29254
  var GitRepoMetaSchema = external_exports.object({
29157
29255
  /** Stable id for the repo (e.g. hash of normalized canonical URL). Used for DO idFromName. */
29158
29256
  repoId: external_exports.string(),
@@ -29346,7 +29444,7 @@ async function sendPromptToAgent(options) {
29346
29444
 
29347
29445
  // src/agents/acp/ensure-acp-client.ts
29348
29446
  import * as fs9 from "node:fs";
29349
- import * as path10 from "node:path";
29447
+ import * as path11 from "node:path";
29350
29448
 
29351
29449
  // src/error-message.ts
29352
29450
  function errorMessage(err) {
@@ -29447,7 +29545,7 @@ __export(cursor_acp_client_exports, {
29447
29545
  detectLocalAgentPresence: () => detectLocalAgentPresence3
29448
29546
  });
29449
29547
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
29450
- import { dirname as dirname2 } from "node:path";
29548
+ import { dirname as dirname3 } from "node:path";
29451
29549
  import { spawn as spawn4 } from "node:child_process";
29452
29550
  import * as readline from "node:readline";
29453
29551
 
@@ -29497,7 +29595,7 @@ function buildCursorAcpSpawnCommand(base, sessionMode) {
29497
29595
  async function createCursorAcpClient(options) {
29498
29596
  const command = buildCursorAcpSpawnCommand(options.command, options.sessionMode);
29499
29597
  const {
29500
- cwd = getBridgeWorkspaceDirectory(),
29598
+ cwd = getBridgeRoot(),
29501
29599
  backendAgentType,
29502
29600
  onSessionUpdate,
29503
29601
  onRequest,
@@ -29513,7 +29611,7 @@ async function createCursorAcpClient(options) {
29513
29611
  });
29514
29612
  const stderrCapture = createStderrCapture(child);
29515
29613
  child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
29516
- return new Promise((resolve17, reject) => {
29614
+ return new Promise((resolve16, reject) => {
29517
29615
  child.on("error", (err) => {
29518
29616
  child.kill();
29519
29617
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -29539,7 +29637,9 @@ async function createCursorAcpClient(options) {
29539
29637
  child.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } }) + "\n");
29540
29638
  }
29541
29639
  function resolveRequest(requestId, result) {
29542
- respond(requestId, result);
29640
+ const pending2 = pendingRequests.get(requestId);
29641
+ const payload = pending2?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending2.params) : result;
29642
+ respond(requestId, payload);
29543
29643
  pendingRequests.delete(requestId);
29544
29644
  }
29545
29645
  let promptOutputBuffer = "";
@@ -29595,14 +29695,14 @@ async function createCursorAcpClient(options) {
29595
29695
  if (dbgFs) {
29596
29696
  console.error(`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""}`);
29597
29697
  }
29598
- const abs = resolveSafePathUnderCwd(cwd, filePath);
29599
- if (!abs) {
29698
+ const resolvedPath = resolveSafePathUnderCwd(cwd, filePath);
29699
+ if (!resolvedPath) {
29600
29700
  if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty)`);
29601
29701
  respondJsonRpcError(id, -32602, "Invalid or disallowed path");
29602
29702
  return;
29603
29703
  }
29604
29704
  try {
29605
- let content = readFileSync3(abs, "utf8");
29705
+ let content = readFileSync3(resolvedPath, "utf8");
29606
29706
  const line2 = typeof params.line === "number" ? params.line : void 0;
29607
29707
  const limit = typeof params.limit === "number" ? params.limit : void 0;
29608
29708
  content = sliceLinesByRange(content, line2, limit);
@@ -29626,15 +29726,15 @@ async function createCursorAcpClient(options) {
29626
29726
  `[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""} newBytes=${newText.length}`
29627
29727
  );
29628
29728
  }
29629
- const abs = resolveSafePathUnderCwd(cwd, filePath);
29630
- if (!abs) {
29729
+ const resolvedPath = resolveSafePathUnderCwd(cwd, filePath);
29730
+ if (!resolvedPath) {
29631
29731
  if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
29632
29732
  respondJsonRpcError(id, -32602, "Invalid or disallowed path");
29633
29733
  return;
29634
29734
  }
29635
29735
  let oldText = "";
29636
29736
  try {
29637
- oldText = readFileSync3(abs, "utf8");
29737
+ oldText = readFileSync3(resolvedPath, "utf8");
29638
29738
  } catch (e) {
29639
29739
  if (e.code !== "ENOENT") {
29640
29740
  respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
@@ -29642,13 +29742,13 @@ async function createCursorAcpClient(options) {
29642
29742
  }
29643
29743
  }
29644
29744
  try {
29645
- mkdirSync3(dirname2(abs), { recursive: true });
29646
- writeFileSync3(abs, newText, "utf8");
29745
+ mkdirSync3(dirname3(resolvedPath), { recursive: true });
29746
+ writeFileSync3(resolvedPath, newText, "utf8");
29647
29747
  } catch (e) {
29648
29748
  respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
29649
29749
  return;
29650
29750
  }
29651
- const displayPath = toDisplayPathRelativeToCwd(cwd, abs);
29751
+ const displayPath = toDisplayPathRelativeToCwd(cwd, resolvedPath);
29652
29752
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
29653
29753
  onFileChange?.({ path: displayPath, oldText, newText, patchContent });
29654
29754
  respond(id, null);
@@ -29700,7 +29800,7 @@ async function createCursorAcpClient(options) {
29700
29800
  const newResult = await send("session/new", { cwd, mcpServers: [] });
29701
29801
  const sessionId = newResult?.sessionId ?? "";
29702
29802
  if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
29703
- resolve17({
29803
+ resolve16({
29704
29804
  sessionId,
29705
29805
  async sendPrompt(prompt, _options) {
29706
29806
  promptOutputBuffer = "";
@@ -29764,8 +29864,7 @@ async function createCursorAcpClient(options) {
29764
29864
  resolveRequest(requestId, result) {
29765
29865
  const numericId = Number(requestId);
29766
29866
  if (!Number.isFinite(numericId)) return;
29767
- const pendingRequest = pendingRequests.get(numericId);
29768
- if (!pendingRequest) return;
29867
+ if (!pendingRequests.get(numericId)) return;
29769
29868
  resolveRequest(numericId, result);
29770
29869
  },
29771
29870
  disconnect() {
@@ -29891,16 +29990,16 @@ import { existsSync, statSync } from "node:fs";
29891
29990
 
29892
29991
  // src/git/get-git-repo-root-sync.ts
29893
29992
  import { execFileSync as execFileSync2 } from "node:child_process";
29894
- import * as path8 from "node:path";
29993
+ import * as path9 from "node:path";
29895
29994
  function getGitRepoRootSync(startDir) {
29896
29995
  try {
29897
29996
  const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
29898
- cwd: path8.resolve(startDir),
29997
+ cwd: path9.resolve(startDir),
29899
29998
  encoding: "utf8",
29900
29999
  stdio: ["ignore", "pipe", "ignore"],
29901
30000
  maxBuffer: 1024 * 1024
29902
30001
  }).trim();
29903
- return out ? path8.resolve(out) : null;
30002
+ return out ? path9.resolve(out) : null;
29904
30003
  } catch {
29905
30004
  return null;
29906
30005
  }
@@ -29909,64 +30008,64 @@ function getGitRepoRootSync(startDir) {
29909
30008
  // src/agents/acp/workspace-files.ts
29910
30009
  import { execFileSync as execFileSync3 } from "node:child_process";
29911
30010
  import { readFileSync as readFileSync4 } from "node:fs";
29912
- import * as path9 from "node:path";
29913
- function resolveWorkspaceFilePath(cwd, rawPath) {
30011
+ import * as path10 from "node:path";
30012
+ function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
29914
30013
  const trimmed2 = rawPath.trim();
29915
30014
  if (!trimmed2) return null;
29916
- const normalizedCwd = path9.resolve(cwd);
29917
- let abs = resolveSafePathUnderCwd(cwd, trimmed2);
29918
- if (!abs) {
29919
- const candidate = path9.isAbsolute(trimmed2) ? path9.normalize(trimmed2) : path9.normalize(path9.resolve(normalizedCwd, trimmed2));
29920
- const gitRoot2 = getGitRepoRootSync(cwd);
30015
+ const normalizedSessionParent = path10.resolve(sessionParentPath);
30016
+ let resolvedPath = resolveSafePathUnderCwd(sessionParentPath, trimmed2);
30017
+ if (!resolvedPath) {
30018
+ const candidate = path10.isAbsolute(trimmed2) ? path10.normalize(trimmed2) : path10.normalize(path10.resolve(normalizedSessionParent, trimmed2));
30019
+ const gitRoot2 = getGitRepoRootSync(sessionParentPath);
29921
30020
  if (!gitRoot2) return null;
29922
- const rel = path9.relative(gitRoot2, candidate);
29923
- if (rel.startsWith("..") || path9.isAbsolute(rel)) return null;
29924
- abs = candidate;
30021
+ const rel = path10.relative(gitRoot2, candidate);
30022
+ if (rel.startsWith("..") || path10.isAbsolute(rel)) return null;
30023
+ resolvedPath = candidate;
29925
30024
  }
29926
- const gitRoot = getGitRepoRootSync(cwd);
30025
+ const gitRoot = getGitRepoRootSync(sessionParentPath);
29927
30026
  if (gitRoot) {
29928
- const relFromRoot = path9.relative(gitRoot, abs);
29929
- if (!relFromRoot.startsWith("..") && !path9.isAbsolute(relFromRoot)) {
29930
- return { abs, display: relFromRoot.split(path9.sep).join("/") };
30027
+ const relFromRoot = path10.relative(gitRoot, resolvedPath);
30028
+ if (!relFromRoot.startsWith("..") && !path10.isAbsolute(relFromRoot)) {
30029
+ return { resolvedPath, display: relFromRoot.split(path10.sep).join("/") };
29931
30030
  }
29932
30031
  }
29933
- return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
30032
+ return { resolvedPath, display: toDisplayPathRelativeToCwd(sessionParentPath, resolvedPath) };
29934
30033
  }
29935
- function readUtf8WorkspaceFile(cwd, displayPath) {
30034
+ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
29936
30035
  if (!displayPath || displayPath.includes("..")) return "";
29937
- const gitRoot = getGitRepoRootSync(cwd);
30036
+ const gitRoot = getGitRepoRootSync(sessionParentPath);
29938
30037
  if (gitRoot) {
29939
- const abs2 = path9.resolve(gitRoot, displayPath);
29940
- const rel = path9.relative(gitRoot, abs2);
29941
- if (!rel.startsWith("..") && !path9.isAbsolute(rel)) {
30038
+ const resolvedPath2 = path10.resolve(gitRoot, displayPath);
30039
+ const rel = path10.relative(gitRoot, resolvedPath2);
30040
+ if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
29942
30041
  try {
29943
- return readFileSync4(abs2, "utf8");
30042
+ return readFileSync4(resolvedPath2, "utf8");
29944
30043
  } catch {
29945
30044
  }
29946
30045
  }
29947
30046
  }
29948
- const abs = resolveSafePathUnderCwd(cwd, displayPath);
29949
- if (!abs) return "";
30047
+ const resolvedPath = resolveSafePathUnderCwd(sessionParentPath, displayPath);
30048
+ if (!resolvedPath) return "";
29950
30049
  try {
29951
- return readFileSync4(abs, "utf8");
30050
+ return readFileSync4(resolvedPath, "utf8");
29952
30051
  } catch {
29953
30052
  return "";
29954
30053
  }
29955
30054
  }
29956
- function tryWorkspaceDisplayToAbs(cwd, displayPath) {
30055
+ function tryWorkspaceDisplayToPath(sessionParentPath, displayPath) {
29957
30056
  if (!displayPath || displayPath.includes("..")) return null;
29958
- const gitRoot = getGitRepoRootSync(cwd);
30057
+ const gitRoot = getGitRepoRootSync(sessionParentPath);
29959
30058
  if (gitRoot) {
29960
- const abs = path9.resolve(gitRoot, displayPath);
29961
- const rel = path9.relative(gitRoot, abs);
29962
- if (!rel.startsWith("..") && !path9.isAbsolute(rel)) return abs;
30059
+ const resolvedPath = path10.resolve(gitRoot, displayPath);
30060
+ const rel = path10.relative(gitRoot, resolvedPath);
30061
+ if (!rel.startsWith("..") && !path10.isAbsolute(rel)) return resolvedPath;
29963
30062
  }
29964
- return resolveSafePathUnderCwd(cwd, displayPath);
30063
+ return resolveSafePathUnderCwd(sessionParentPath, displayPath);
29965
30064
  }
29966
- function readGitHeadBlob(cwd, displayPath) {
30065
+ function readGitHeadBlob(sessionParentPath, displayPath) {
29967
30066
  if (!displayPath || displayPath.includes("..")) return "";
29968
- const gitRoot = getGitRepoRootSync(cwd);
29969
- const execCwd = gitRoot ?? cwd;
30067
+ const gitRoot = getGitRepoRootSync(sessionParentPath);
30068
+ const execCwd = gitRoot ?? sessionParentPath;
29970
30069
  try {
29971
30070
  return execFileSync3("git", ["show", `HEAD:${displayPath}`], {
29972
30071
  cwd: execCwd,
@@ -29979,9 +30078,9 @@ function readGitHeadBlob(cwd, displayPath) {
29979
30078
  }
29980
30079
 
29981
30080
  // src/agents/acp/session-file-change-path-kind.ts
29982
- function gitHeadPathObjectType(cwd, displayPath) {
30081
+ function gitHeadPathObjectType(sessionParentPath, displayPath) {
29983
30082
  if (!displayPath || displayPath.includes("..")) return null;
29984
- const gitRoot = getGitRepoRootSync(cwd);
30083
+ const gitRoot = getGitRepoRootSync(sessionParentPath);
29985
30084
  if (!gitRoot) return null;
29986
30085
  try {
29987
30086
  return execFileSync4("git", ["cat-file", "-t", `HEAD:${displayPath}`], {
@@ -29992,11 +30091,11 @@ function gitHeadPathObjectType(cwd, displayPath) {
29992
30091
  return null;
29993
30092
  }
29994
30093
  }
29995
- function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
29996
- const abs = tryWorkspaceDisplayToAbs(cwd, displayPath);
29997
- if (abs && existsSync(abs)) {
30094
+ function getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath) {
30095
+ const resolvedPath = tryWorkspaceDisplayToPath(sessionParentPath, displayPath);
30096
+ if (resolvedPath && existsSync(resolvedPath)) {
29998
30097
  try {
29999
- if (statSync(abs).isDirectory()) {
30098
+ if (statSync(resolvedPath).isDirectory()) {
30000
30099
  return { isDirectory: true, directoryRemoved: false };
30001
30100
  }
30002
30101
  return { isDirectory: false, directoryRemoved: false };
@@ -30004,7 +30103,7 @@ function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
30004
30103
  return { isDirectory: false, directoryRemoved: false };
30005
30104
  }
30006
30105
  }
30007
- if (gitHeadPathObjectType(cwd, displayPath) === "tree") {
30106
+ if (gitHeadPathObjectType(sessionParentPath, displayPath) === "tree") {
30008
30107
  return { isDirectory: true, directoryRemoved: true };
30009
30108
  }
30010
30109
  return { isDirectory: false, directoryRemoved: false };
@@ -30012,7 +30111,7 @@ function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
30012
30111
 
30013
30112
  // src/agents/acp/hooks/bridge-on-file-change.ts
30014
30113
  function createBridgeOnFileChange(opts) {
30015
- const { routing, getSendSessionUpdate, log: log2 } = opts;
30114
+ const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
30016
30115
  return (evt) => {
30017
30116
  const runId = routing.runId;
30018
30117
  const sessionId = routing.sessionId;
@@ -30023,8 +30122,7 @@ function createBridgeOnFileChange(opts) {
30023
30122
  );
30024
30123
  return;
30025
30124
  }
30026
- const cwd = getBridgeWorkspaceDirectory();
30027
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd, evt.path);
30125
+ const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, evt.path);
30028
30126
  try {
30029
30127
  send({
30030
30128
  type: "session_file_change",
@@ -30101,12 +30199,12 @@ function extractDiffPath(o) {
30101
30199
  }
30102
30200
 
30103
30201
  // src/agents/acp/hooks/extract-acp-file-diffs-from-update/push-diff.ts
30104
- function pushDiffIfComplete(o, cwd, out) {
30202
+ function pushDiffIfComplete(o, sessionParentPath, out) {
30105
30203
  const t = o.type;
30106
30204
  if (typeof t !== "string" || t.toLowerCase() !== "diff") return;
30107
30205
  const rawPath = extractDiffPath(o);
30108
30206
  if (!rawPath) return;
30109
- const resolved = resolveWorkspaceFilePath(cwd, rawPath);
30207
+ const resolved = resolveWorkspaceFilePath(sessionParentPath, rawPath);
30110
30208
  if (!resolved) return;
30111
30209
  const oldText = readOptionalTextField(o.oldText ?? o.old_text ?? o.before ?? o.oldContent);
30112
30210
  const newText = readOptionalTextField(o.newText ?? o.new_text ?? o.after ?? o.newContent);
@@ -30125,17 +30223,17 @@ var NEST_KEYS = [
30125
30223
  "data",
30126
30224
  "arguments"
30127
30225
  ];
30128
- function walkValue(value, cwd, depth, out) {
30226
+ function walkValue(value, sessionParentPath, depth, out) {
30129
30227
  if (depth > 12 || value == null) return;
30130
30228
  if (Array.isArray(value)) {
30131
- for (const x of value) walkValue(x, cwd, depth + 1, out);
30229
+ for (const x of value) walkValue(x, sessionParentPath, depth + 1, out);
30132
30230
  return;
30133
30231
  }
30134
30232
  if (typeof value !== "object") return;
30135
30233
  const o = value;
30136
- pushDiffIfComplete(o, cwd, out);
30234
+ pushDiffIfComplete(o, sessionParentPath, out);
30137
30235
  if (o.type === "content" && o.content != null && typeof o.content === "object") {
30138
- walkValue(o.content, cwd, depth + 1, out);
30236
+ walkValue(o.content, sessionParentPath, depth + 1, out);
30139
30237
  }
30140
30238
  for (const k of NEST_KEYS) {
30141
30239
  if (o.type === "content" && k === "content") continue;
@@ -30143,23 +30241,23 @@ function walkValue(value, cwd, depth, out) {
30143
30241
  if (v == null) continue;
30144
30242
  if (k === "arguments" && typeof v === "string") {
30145
30243
  try {
30146
- walkValue(JSON.parse(v), cwd, depth + 1, out);
30244
+ walkValue(JSON.parse(v), sessionParentPath, depth + 1, out);
30147
30245
  } catch {
30148
30246
  }
30149
30247
  continue;
30150
30248
  }
30151
- walkValue(v, cwd, depth + 1, out);
30249
+ walkValue(v, sessionParentPath, depth + 1, out);
30152
30250
  }
30153
30251
  }
30154
30252
 
30155
30253
  // src/agents/acp/hooks/extract-acp-file-diffs-from-update/extract.ts
30156
- function extractAcpFileDiffsFromUpdate(update, cwd) {
30254
+ function extractAcpFileDiffsFromUpdate(update, sessionParentPath) {
30157
30255
  if (!update || typeof update !== "object") return [];
30158
30256
  const u = update;
30159
30257
  const out = [];
30160
30258
  const content = u.content;
30161
30259
  if (Array.isArray(content)) {
30162
- for (const x of content) walkValue(x, cwd, 0, out);
30260
+ for (const x of content) walkValue(x, sessionParentPath, 0, out);
30163
30261
  }
30164
30262
  const byPath = /* @__PURE__ */ new Map();
30165
30263
  for (const d of out) byPath.set(d.path, d);
@@ -30167,18 +30265,18 @@ function extractAcpFileDiffsFromUpdate(update, cwd) {
30167
30265
  }
30168
30266
 
30169
30267
  // src/agents/acp/hooks/extract-tool-target-paths.ts
30170
- function addPath(cwd, raw, out) {
30268
+ function addPath(sessionParentPath, raw, out) {
30171
30269
  if (typeof raw !== "string") return;
30172
30270
  const trimmed2 = raw.trim();
30173
30271
  if (!trimmed2) return;
30174
- const resolved = resolveWorkspaceFilePath(cwd, trimmed2);
30272
+ const resolved = resolveWorkspaceFilePath(sessionParentPath, trimmed2);
30175
30273
  if (!resolved) return;
30176
30274
  out.add(resolved.display);
30177
30275
  }
30178
- function walkLocations(cwd, loc, out) {
30276
+ function walkLocations(sessionParentPath, loc, out) {
30179
30277
  if (!Array.isArray(loc)) return;
30180
30278
  for (const item of loc) {
30181
- if (item && typeof item === "object") addPath(cwd, item.path, out);
30279
+ if (item && typeof item === "object") addPath(sessionParentPath, item.path, out);
30182
30280
  }
30183
30281
  }
30184
30282
  var PATH_KEYS = [
@@ -30191,56 +30289,56 @@ var PATH_KEYS = [
30191
30289
  "file_path",
30192
30290
  "target_file"
30193
30291
  ];
30194
- function collectFromObject(cwd, obj, out, depth) {
30292
+ function collectFromObject(sessionParentPath, obj, out, depth) {
30195
30293
  if (depth > 10) return;
30196
30294
  for (const k of PATH_KEYS) {
30197
- if (k in obj) addPath(cwd, obj[k], out);
30295
+ if (k in obj) addPath(sessionParentPath, obj[k], out);
30198
30296
  }
30199
30297
  for (const v of Object.values(obj)) {
30200
- if (v != null && typeof v === "object") collectUnknown(cwd, v, out, depth + 1);
30298
+ if (v != null && typeof v === "object") collectUnknown(sessionParentPath, v, out, depth + 1);
30201
30299
  }
30202
30300
  }
30203
- function collectUnknown(cwd, v, out, depth) {
30301
+ function collectUnknown(sessionParentPath, v, out, depth) {
30204
30302
  if (depth > 10 || v == null) return;
30205
30303
  if (Array.isArray(v)) {
30206
- for (const x of v) collectUnknown(cwd, x, out, depth + 1);
30304
+ for (const x of v) collectUnknown(sessionParentPath, x, out, depth + 1);
30207
30305
  return;
30208
30306
  }
30209
- if (typeof v === "object") collectFromObject(cwd, v, out, depth);
30307
+ if (typeof v === "object") collectFromObject(sessionParentPath, v, out, depth);
30210
30308
  }
30211
- function walkContentArray(cwd, content, out) {
30309
+ function walkContentArray(sessionParentPath, content, out) {
30212
30310
  if (!Array.isArray(content)) return;
30213
30311
  for (const item of content) {
30214
30312
  if (!item || typeof item !== "object") continue;
30215
30313
  const o = item;
30216
30314
  if (typeof o.type === "string" && o.type.toLowerCase() === "diff") {
30217
- for (const k of PATH_KEYS) if (k in o) addPath(cwd, o[k], out);
30315
+ for (const k of PATH_KEYS) if (k in o) addPath(sessionParentPath, o[k], out);
30218
30316
  }
30219
30317
  if (o.type === "content" && o.content != null && typeof o.content === "object") {
30220
30318
  const inner = o.content;
30221
30319
  if (typeof inner.type === "string" && inner.type.toLowerCase() === "diff") {
30222
- for (const k of PATH_KEYS) if (k in inner) addPath(cwd, inner[k], out);
30320
+ for (const k of PATH_KEYS) if (k in inner) addPath(sessionParentPath, inner[k], out);
30223
30321
  }
30224
30322
  }
30225
30323
  }
30226
30324
  }
30227
- function extractToolTargetDisplayPaths(update, cwd) {
30325
+ function extractToolTargetDisplayPaths(update, sessionParentPath) {
30228
30326
  const out = /* @__PURE__ */ new Set();
30229
30327
  if (!update || typeof update !== "object") return [];
30230
30328
  const u = update;
30231
- walkLocations(cwd, u.locations, out);
30232
- walkLocations(cwd, u.fileLocations, out);
30233
- walkLocations(cwd, u.file_locations, out);
30329
+ walkLocations(sessionParentPath, u.locations, out);
30330
+ walkLocations(sessionParentPath, u.fileLocations, out);
30331
+ walkLocations(sessionParentPath, u.file_locations, out);
30234
30332
  const tc = u.toolCall ?? u.tool_call;
30235
30333
  if (tc && typeof tc.arguments === "string") {
30236
30334
  try {
30237
30335
  const parsed = JSON.parse(tc.arguments);
30238
- collectUnknown(cwd, parsed, out, 0);
30336
+ collectUnknown(sessionParentPath, parsed, out, 0);
30239
30337
  } catch {
30240
30338
  }
30241
30339
  }
30242
- walkContentArray(cwd, u.content, out);
30243
- collectFromObject(cwd, u, out, 0);
30340
+ walkContentArray(sessionParentPath, u.content, out);
30341
+ collectFromObject(sessionParentPath, u, out, 0);
30244
30342
  return [...out];
30245
30343
  }
30246
30344
 
@@ -30306,7 +30404,7 @@ var PathSnapshotTracker = class {
30306
30404
  this.beforeByToolKey.delete(toolKey);
30307
30405
  this.accumulatedPathsByToolKey.delete(toolKey);
30308
30406
  }
30309
- captureBeforeFromDisk(toolKey, paths, cwd) {
30407
+ captureBeforeFromDisk(toolKey, paths, sessionParentPath) {
30310
30408
  if (paths.length === 0) return;
30311
30409
  let m = this.beforeByToolKey.get(toolKey);
30312
30410
  if (!m) {
@@ -30315,10 +30413,10 @@ var PathSnapshotTracker = class {
30315
30413
  }
30316
30414
  for (const p of paths) {
30317
30415
  if (m.has(p)) continue;
30318
- m.set(p, readUtf8WorkspaceFile(cwd, p));
30416
+ m.set(p, readUtf8WorkspaceFile(sessionParentPath, p));
30319
30417
  }
30320
30418
  }
30321
- ensureBeforeFromHeadForMissing(toolKey, paths, cwd) {
30419
+ ensureBeforeFromHeadForMissing(toolKey, paths, sessionParentPath) {
30322
30420
  let m = this.beforeByToolKey.get(toolKey);
30323
30421
  if (!m) {
30324
30422
  m = /* @__PURE__ */ new Map();
@@ -30326,10 +30424,10 @@ var PathSnapshotTracker = class {
30326
30424
  }
30327
30425
  for (const p of paths) {
30328
30426
  if (m.has(p)) continue;
30329
- m.set(p, readGitHeadBlob(cwd, p));
30427
+ m.set(p, readGitHeadBlob(sessionParentPath, p));
30330
30428
  }
30331
30429
  }
30332
- flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2) {
30430
+ flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
30333
30431
  const t = this.debouncers.get(toolKey);
30334
30432
  if (t) clearTimeout(t);
30335
30433
  this.debouncers.delete(toolKey);
@@ -30338,10 +30436,10 @@ var PathSnapshotTracker = class {
30338
30436
  this.beforeByToolKey.delete(toolKey);
30339
30437
  if (!send || !runId || !sessionId) return;
30340
30438
  for (const [displayPath, oldText] of beforeMap) {
30341
- const newText = readUtf8WorkspaceFile(cwd, displayPath);
30439
+ const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
30342
30440
  if (oldText === newText) continue;
30343
30441
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
30344
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd, displayPath);
30442
+ const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
30345
30443
  try {
30346
30444
  send({
30347
30445
  type: "session_file_change",
@@ -30360,31 +30458,31 @@ var PathSnapshotTracker = class {
30360
30458
  }
30361
30459
  }
30362
30460
  }
30363
- scheduleDebouncedFlush(toolKey, cwd, sentPaths, send, runId, sessionId, log2) {
30461
+ scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
30364
30462
  const prev = this.debouncers.get(toolKey);
30365
30463
  if (prev) clearTimeout(prev);
30366
30464
  this.debouncers.set(
30367
30465
  toolKey,
30368
30466
  setTimeout(() => {
30369
30467
  this.debouncers.delete(toolKey);
30370
- this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
30468
+ this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
30371
30469
  }, PATH_SNAPSHOT_DEBOUNCE_MS)
30372
30470
  );
30373
30471
  }
30374
- handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, cwd, sentPaths, send, runId, sessionId, log2) {
30472
+ handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, sessionParentPath, sentPaths, send, runId, sessionId, log2) {
30375
30473
  if (updateKind === "tool_call") {
30376
30474
  this.resetToolSnapshots(toolKey);
30377
30475
  }
30378
30476
  if (updateKind === "tool_call") {
30379
- this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
30477
+ this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
30380
30478
  } else if (updateKind === "tool_call_update") {
30381
30479
  if (isCompletedToolStatus(status)) {
30382
- this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, cwd);
30383
- this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
30480
+ this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, sessionParentPath);
30481
+ this.flushPathSnapshots(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
30384
30482
  } else {
30385
- this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
30483
+ this.captureBeforeFromDisk(toolKey, toolPaths, sessionParentPath);
30386
30484
  if (this.beforeByToolKey.has(toolKey)) {
30387
- this.scheduleDebouncedFlush(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
30485
+ this.scheduleDebouncedFlush(toolKey, sessionParentPath, sentPaths, send, runId, sessionId, log2);
30388
30486
  }
30389
30487
  }
30390
30488
  }
@@ -30392,11 +30490,11 @@ var PathSnapshotTracker = class {
30392
30490
  };
30393
30491
 
30394
30492
  // src/agents/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
30395
- function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentPaths, log2) {
30493
+ function sendExtractedDiffsAsSessionFileChanges(diffs, send, sessionParentPath, sessionId, runId, sentPaths, log2) {
30396
30494
  for (const d of diffs) {
30397
30495
  try {
30398
30496
  const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
30399
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd, d.path);
30497
+ const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, d.path);
30400
30498
  send({
30401
30499
  type: "session_file_change",
30402
30500
  sessionId,
@@ -30414,15 +30512,15 @@ function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, run
30414
30512
  }
30415
30513
  }
30416
30514
  }
30417
- function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd, sessionId, runId, log2) {
30515
+ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, sessionParentPath, sessionId, runId, log2) {
30418
30516
  for (const displayPath of mergedPaths) {
30419
30517
  if (sentPaths.has(displayPath)) continue;
30420
- const oldText = readGitHeadBlob(cwd, displayPath);
30421
- const newText = readUtf8WorkspaceFile(cwd, displayPath);
30518
+ const oldText = readGitHeadBlob(sessionParentPath, displayPath);
30519
+ const newText = readUtf8WorkspaceFile(sessionParentPath, displayPath);
30422
30520
  if (oldText === newText) continue;
30423
30521
  try {
30424
30522
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
30425
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd, displayPath);
30523
+ const dirFlags = getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath);
30426
30524
  send({
30427
30525
  type: "session_file_change",
30428
30526
  sessionId,
@@ -30443,13 +30541,12 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd, s
30443
30541
 
30444
30542
  // src/agents/acp/hooks/bridge-on-session-update/create-bridge-on-session-update.ts
30445
30543
  function createBridgeOnSessionUpdate(opts) {
30446
- const { routing, getSendSessionUpdate, log: log2 } = opts;
30544
+ const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
30447
30545
  const pathTracker = new PathSnapshotTracker();
30448
30546
  return (params) => {
30449
30547
  const runId = routing.runId;
30450
30548
  const sessionId = routing.sessionId;
30451
30549
  pathTracker.onRunIdChanged(runId);
30452
- const cwd = getBridgeWorkspaceDirectory();
30453
30550
  const send = getSendSessionUpdate();
30454
30551
  const sentFileChangePaths = /* @__PURE__ */ new Set();
30455
30552
  const p = params;
@@ -30457,7 +30554,7 @@ function createBridgeOnSessionUpdate(opts) {
30457
30554
  const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
30458
30555
  const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
30459
30556
  const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
30460
- const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, cwd) : [];
30557
+ const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, sessionParentPath) : [];
30461
30558
  const toolKey = isToolUpdate ? pathTracker.resolveToolKey(params, updateKind) : "";
30462
30559
  if (updateKind === "tool_call") {
30463
30560
  pathTracker.resetToolSnapshots(toolKey);
@@ -30472,7 +30569,7 @@ function createBridgeOnSessionUpdate(opts) {
30472
30569
  toolKey,
30473
30570
  toolPaths,
30474
30571
  p.status,
30475
- cwd,
30572
+ sessionParentPath,
30476
30573
  sentFileChangePaths,
30477
30574
  deliver,
30478
30575
  runId ?? "",
@@ -30480,9 +30577,17 @@ function createBridgeOnSessionUpdate(opts) {
30480
30577
  log2
30481
30578
  );
30482
30579
  }
30483
- const diffs = extractAcpFileDiffsFromUpdate(params, cwd);
30580
+ const diffs = extractAcpFileDiffsFromUpdate(params, sessionParentPath);
30484
30581
  if (diffs.length > 0 && send && runId && sessionId) {
30485
- sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentFileChangePaths, log2);
30582
+ sendExtractedDiffsAsSessionFileChanges(
30583
+ diffs,
30584
+ send,
30585
+ sessionParentPath,
30586
+ sessionId,
30587
+ runId,
30588
+ sentFileChangePaths,
30589
+ log2
30590
+ );
30486
30591
  } else if (diffs.length > 0) {
30487
30592
  log2(
30488
30593
  `[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
@@ -30491,7 +30596,15 @@ function createBridgeOnSessionUpdate(opts) {
30491
30596
  if (isCompletedToolCallUpdate && send && runId && sessionId) {
30492
30597
  const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
30493
30598
  const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
30494
- sendGitHeadVsWorkspaceForToolPaths(merged, sentFileChangePaths, send, cwd, sessionId, runId, log2);
30599
+ sendGitHeadVsWorkspaceForToolPaths(
30600
+ merged,
30601
+ sentFileChangePaths,
30602
+ send,
30603
+ sessionParentPath,
30604
+ sessionId,
30605
+ runId,
30606
+ log2
30607
+ );
30495
30608
  pathTracker.accumulatedPathsByToolKey.delete(toolKey);
30496
30609
  }
30497
30610
  if (runId && send) {
@@ -30526,11 +30639,12 @@ function buildAcpSessionBridgeHooks(opts) {
30526
30639
 
30527
30640
  // src/agents/acp/ensure-acp-client.ts
30528
30641
  async function ensureAcpClient(options) {
30529
- const { state, preferredAgentType, mode, cwd, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
30530
- const targetCwd = path10.resolve(
30531
- cwd != null && String(cwd).trim() !== "" ? String(cwd).trim() : getBridgeWorkspaceDirectory()
30532
- );
30533
- if (state.acpHandle && state.lastAcpCwd != null && path10.resolve(state.lastAcpCwd) !== path10.resolve(targetCwd)) {
30642
+ const { state, preferredAgentType, mode, sessionParentPath, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
30643
+ const targetSessionParentPath = resolveSessionParentPathForAgentProcess(sessionParentPath);
30644
+ if (state.acpStartPromise && !state.acpHandle) {
30645
+ await state.acpStartPromise;
30646
+ }
30647
+ if (state.acpHandle && state.lastAcpCwd != null && path11.resolve(state.lastAcpCwd) !== path11.resolve(targetSessionParentPath)) {
30534
30648
  try {
30535
30649
  state.acpHandle.disconnect();
30536
30650
  } catch {
@@ -30562,14 +30676,14 @@ async function ensureAcpClient(options) {
30562
30676
  if (!state.acpStartPromise) {
30563
30677
  let statOk = false;
30564
30678
  try {
30565
- const st = fs9.statSync(targetCwd);
30679
+ const st = fs9.statSync(targetSessionParentPath);
30566
30680
  statOk = st.isDirectory();
30567
30681
  if (!statOk) {
30568
- state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
30682
+ state.lastAcpStartError = `Agent cwd is not a directory: ${targetSessionParentPath}`;
30569
30683
  log2(`[Agent] ${state.lastAcpStartError}`);
30570
30684
  }
30571
30685
  } catch {
30572
- state.lastAcpStartError = `Agent cwd missing or inaccessible: ${targetCwd}`;
30686
+ state.lastAcpStartError = `Agent cwd missing or inaccessible: ${targetSessionParentPath}`;
30573
30687
  log2(`[Agent] ${state.lastAcpStartError}`);
30574
30688
  }
30575
30689
  if (!statOk) {
@@ -30577,6 +30691,7 @@ async function ensureAcpClient(options) {
30577
30691
  }
30578
30692
  const hooks = buildAcpSessionBridgeHooks({
30579
30693
  routing,
30694
+ sessionParentPath: targetSessionParentPath,
30580
30695
  getSendSessionUpdate: () => sendSessionUpdate,
30581
30696
  getSendRequest: () => sendRequest,
30582
30697
  log: log2
@@ -30584,7 +30699,6 @@ async function ensureAcpClient(options) {
30584
30699
  state.acpStartPromise = resolved.createClient({
30585
30700
  command: resolved.command,
30586
30701
  sessionMode: mode,
30587
- cwd: targetCwd,
30588
30702
  backendAgentType: preferredAgentType,
30589
30703
  onAgentSubprocessExit: () => {
30590
30704
  state.acpHandle = null;
@@ -30592,11 +30706,12 @@ async function ensureAcpClient(options) {
30592
30706
  state.acpAgentKey = null;
30593
30707
  state.lastAcpStartError = "Agent subprocess exited";
30594
30708
  },
30595
- ...hooks
30709
+ ...hooks,
30710
+ cwd: targetSessionParentPath
30596
30711
  }).then((h) => {
30597
30712
  state.lastAcpStartError = null;
30598
30713
  state.acpHandle = h;
30599
- state.lastAcpCwd = targetCwd;
30714
+ state.lastAcpCwd = targetSessionParentPath;
30600
30715
  state.acpAgentKey = agentKey;
30601
30716
  return h;
30602
30717
  }).catch((err) => {
@@ -30645,7 +30760,7 @@ async function createAcpManager(options) {
30645
30760
  runId,
30646
30761
  mode,
30647
30762
  agentType,
30648
- cwd,
30763
+ sessionParentPath,
30649
30764
  sendResult: sendResult2,
30650
30765
  sendSessionUpdate,
30651
30766
  followUpCatalogPromptId,
@@ -30664,7 +30779,7 @@ async function createAcpManager(options) {
30664
30779
  state,
30665
30780
  preferredAgentType: preferredForPrompt,
30666
30781
  mode,
30667
- cwd,
30782
+ sessionParentPath,
30668
30783
  routing: promptRouting,
30669
30784
  sendSessionUpdate,
30670
30785
  sendRequest: sendSessionUpdate,
@@ -30713,7 +30828,7 @@ async function createAcpManager(options) {
30713
30828
  sessionId,
30714
30829
  runId,
30715
30830
  agentType: preferredForPrompt,
30716
- agentCwd: cwd,
30831
+ agentCwd: resolveSessionParentPathForAgentProcess(sessionParentPath),
30717
30832
  sendResult: sendResult2,
30718
30833
  sendSessionUpdate,
30719
30834
  log: log2,
@@ -30768,12 +30883,12 @@ async function createAcpManager(options) {
30768
30883
  }
30769
30884
 
30770
30885
  // src/worktrees/session-worktree-manager.ts
30771
- import * as path17 from "node:path";
30886
+ import * as path18 from "node:path";
30772
30887
  import os4 from "node:os";
30773
30888
 
30774
30889
  // src/worktrees/prepare-new-session-worktrees.ts
30775
30890
  import * as fs11 from "node:fs";
30776
- import * as path12 from "node:path";
30891
+ import * as path13 from "node:path";
30777
30892
 
30778
30893
  // src/git/worktree-add.ts
30779
30894
  async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
@@ -30783,11 +30898,11 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
30783
30898
 
30784
30899
  // src/worktrees/worktree-layout-file.ts
30785
30900
  import * as fs10 from "node:fs";
30786
- import * as path11 from "node:path";
30901
+ import * as path12 from "node:path";
30787
30902
  import os3 from "node:os";
30788
30903
  var LAYOUT_FILENAME = "worktree-launcher-layout.json";
30789
30904
  function defaultWorktreeLayoutPath() {
30790
- return path11.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
30905
+ return path12.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
30791
30906
  }
30792
30907
  function normalizeLoadedLayout(raw) {
30793
30908
  if (raw && typeof raw === "object" && "launcherCwds" in raw) {
@@ -30808,24 +30923,24 @@ function loadWorktreeLayout() {
30808
30923
  }
30809
30924
  function saveWorktreeLayout(layout) {
30810
30925
  try {
30811
- const dir = path11.dirname(defaultWorktreeLayoutPath());
30926
+ const dir = path12.dirname(defaultWorktreeLayoutPath());
30812
30927
  fs10.mkdirSync(dir, { recursive: true });
30813
30928
  fs10.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
30814
30929
  } catch {
30815
30930
  }
30816
30931
  }
30817
- function baseNameSafe(abs) {
30818
- return path11.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
30932
+ function baseNameSafe(pathString) {
30933
+ return path12.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
30819
30934
  }
30820
- function getLauncherDirNameIfPresent(layout, launcherCwdAbs) {
30821
- const norm = path11.resolve(launcherCwdAbs);
30822
- const existing = layout.launcherCwds.find((e) => path11.resolve(e.absolutePath) === norm);
30935
+ function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
30936
+ const norm = path12.resolve(bridgeRootPath2);
30937
+ const existing = layout.launcherCwds.find((e) => path12.resolve(e.absolutePath) === norm);
30823
30938
  return existing?.dirName;
30824
30939
  }
30825
- function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
30826
- const existing = getLauncherDirNameIfPresent(layout, launcherCwdAbs);
30940
+ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
30941
+ const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
30827
30942
  if (existing) return existing;
30828
- const norm = path11.resolve(launcherCwdAbs);
30943
+ const norm = path12.resolve(bridgeRootPath2);
30829
30944
  const base = baseNameSafe(norm);
30830
30945
  const used = new Set(layout.launcherCwds.map((e) => e.dirName));
30831
30946
  let name = base;
@@ -30841,24 +30956,27 @@ function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
30841
30956
 
30842
30957
  // src/worktrees/prepare-new-session-worktrees.ts
30843
30958
  async function prepareNewSessionWorktrees(options) {
30844
- const { rootAbs, launcherCwd, sessionId, layout, log: log2 } = options;
30845
- const launcherResolved = path12.resolve(launcherCwd);
30846
- const cwdKey = allocateDirNameForLauncherCwd(layout, launcherResolved);
30847
- const agentMirrorRoot = path12.join(rootAbs, cwdKey);
30848
- const repos = await discoverGitReposUnderRoot(launcherResolved);
30959
+ const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
30960
+ const bridgeResolved = path13.resolve(bridgeRoot);
30961
+ const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
30962
+ const bridgeKeyDir = path13.join(worktreesRootPath, cwdKey);
30963
+ const sessionDir = path13.join(bridgeKeyDir, sessionId);
30964
+ const repos = await discoverGitReposUnderRoot(bridgeResolved);
30849
30965
  if (repos.length === 0) {
30850
- log2("[worktrees] No Git repositories under launcher working directory; skipping worktree creation.");
30966
+ log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
30851
30967
  return null;
30852
30968
  }
30853
30969
  const branch = `session-${sessionId}`;
30854
30970
  const worktreePaths = [];
30855
- fs11.mkdirSync(agentMirrorRoot, { recursive: true });
30971
+ fs11.mkdirSync(sessionDir, { recursive: true });
30856
30972
  for (const repo of repos) {
30857
- let rel = path12.relative(launcherResolved, repo.absolutePath);
30858
- if (rel.startsWith("..") || path12.isAbsolute(rel)) continue;
30973
+ let rel = path13.relative(bridgeResolved, repo.absolutePath);
30974
+ if (rel.startsWith("..") || path13.isAbsolute(rel)) continue;
30859
30975
  const relNorm = rel === "" ? "." : rel;
30860
- const wtPath = path12.join(agentMirrorRoot, relNorm, sessionId);
30861
- fs11.mkdirSync(path12.dirname(wtPath), { recursive: true });
30976
+ const wtPath = relNorm === "." ? sessionDir : path13.join(sessionDir, relNorm);
30977
+ if (relNorm !== ".") {
30978
+ fs11.mkdirSync(path13.dirname(wtPath), { recursive: true });
30979
+ }
30862
30980
  try {
30863
30981
  await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
30864
30982
  log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
@@ -30870,7 +30988,11 @@ async function prepareNewSessionWorktrees(options) {
30870
30988
  }
30871
30989
  }
30872
30990
  if (worktreePaths.length === 0) return null;
30873
- return { worktreePaths, agentCwd: agentMirrorRoot };
30991
+ return {
30992
+ worktreePaths,
30993
+ sessionParentPath: sessionDir,
30994
+ workingTreeRelRoot: sessionDir
30995
+ };
30874
30996
  }
30875
30997
 
30876
30998
  // src/git/rename-branch.ts
@@ -30902,16 +31024,16 @@ import * as fs13 from "node:fs";
30902
31024
 
30903
31025
  // src/git/resolve-main-repo-from-git-file.ts
30904
31026
  import * as fs12 from "node:fs";
30905
- import * as path13 from "node:path";
31027
+ import * as path14 from "node:path";
30906
31028
  function resolveMainRepoFromWorktreeGitFile(wt) {
30907
- const gitDirFile = path13.join(wt, ".git");
31029
+ const gitDirFile = path14.join(wt, ".git");
30908
31030
  if (!fs12.existsSync(gitDirFile) || !fs12.statSync(gitDirFile).isFile()) return "";
30909
31031
  const first2 = fs12.readFileSync(gitDirFile, "utf8").trim();
30910
31032
  const m = first2.match(/^gitdir:\s*(.+)$/im);
30911
31033
  if (!m) return "";
30912
- const gitWorktreePath = path13.resolve(wt, m[1].trim());
30913
- const gitDir = path13.dirname(path13.dirname(gitWorktreePath));
30914
- return path13.dirname(gitDir);
31034
+ const gitWorktreePath = path14.resolve(wt, m[1].trim());
31035
+ const gitDir = path14.dirname(path14.dirname(gitWorktreePath));
31036
+ return path14.dirname(gitDir);
30915
31037
  }
30916
31038
 
30917
31039
  // src/git/worktree-remove.ts
@@ -31153,7 +31275,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
31153
31275
  }
31154
31276
 
31155
31277
  // src/git/working-directory/changes/get-working-tree-change-repo-details.ts
31156
- import * as path15 from "node:path";
31278
+ import * as path16 from "node:path";
31157
31279
 
31158
31280
  // src/git/working-directory/changes/parse-git-status.ts
31159
31281
  function parseNameStatusLines(lines) {
@@ -31274,16 +31396,16 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
31274
31396
 
31275
31397
  // src/git/working-directory/changes/list-changed-files-for-repo.ts
31276
31398
  import * as fs16 from "node:fs";
31277
- import * as path14 from "node:path";
31399
+ import * as path15 from "node:path";
31278
31400
 
31279
31401
  // src/git/working-directory/changes/count-lines.ts
31280
31402
  import { createReadStream } from "node:fs";
31281
31403
  import * as readline2 from "node:readline";
31282
- async function countTextFileLines(absFile) {
31404
+ async function countTextFileLines(filePath) {
31283
31405
  let bytes = 0;
31284
31406
  const maxBytes = 512e3;
31285
31407
  let lines = 0;
31286
- const stream = createReadStream(absFile, { encoding: "utf8" });
31408
+ const stream = createReadStream(filePath, { encoding: "utf8" });
31287
31409
  const rl = readline2.createInterface({ input: stream, crlfDelay: Infinity });
31288
31410
  for await (const _line of rl) {
31289
31411
  lines += 1;
@@ -31311,15 +31433,15 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
31311
31433
  return null;
31312
31434
  }
31313
31435
  }
31314
- async function readWorktreeFileLines(abs) {
31436
+ async function readWorktreeFileLines(filePath) {
31315
31437
  try {
31316
- const raw = await fs15.promises.readFile(abs, "utf8");
31438
+ const raw = await fs15.promises.readFile(filePath, "utf8");
31317
31439
  return raw.split(/\r?\n/);
31318
31440
  } catch {
31319
31441
  return null;
31320
31442
  }
31321
31443
  }
31322
- async function hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, change) {
31444
+ async function hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, change) {
31323
31445
  if (!patch.trim() || patch.includes("Binary files")) return patch;
31324
31446
  const all = patch.split("\n");
31325
31447
  const out = [];
@@ -31336,7 +31458,7 @@ async function hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pa
31336
31458
  };
31337
31459
  const diskLines = async () => {
31338
31460
  if (diskCache !== void 0) return diskCache;
31339
- diskCache = await readWorktreeFileLines(absFile);
31461
+ diskCache = await readWorktreeFileLines(filePath);
31340
31462
  return diskCache;
31341
31463
  };
31342
31464
  while (i < all.length) {
@@ -31448,7 +31570,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
31448
31570
  const rows = [];
31449
31571
  for (const pathInRepo of paths) {
31450
31572
  const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
31451
- const abs = path14.join(repoGitCwd, pathInRepo);
31573
+ const repoFilePath = path15.join(repoGitCwd, pathInRepo);
31452
31574
  const nums = numByPath.get(pathInRepo);
31453
31575
  let additions = nums?.additions ?? 0;
31454
31576
  let deletions = nums?.deletions ?? 0;
@@ -31461,8 +31583,8 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
31461
31583
  deletions = fromGit.deletions;
31462
31584
  } else {
31463
31585
  try {
31464
- const st = await fs16.promises.stat(abs);
31465
- if (st.isFile()) additions = await countTextFileLines(abs);
31586
+ const st = await fs16.promises.stat(repoFilePath);
31587
+ if (st.isFile()) additions = await countTextFileLines(repoFilePath);
31466
31588
  else additions = 0;
31467
31589
  } catch {
31468
31590
  additions = 0;
@@ -31487,10 +31609,10 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
31487
31609
  } else {
31488
31610
  pathInRepo = row.pathRelLauncher;
31489
31611
  }
31490
- const absFile = path14.join(repoGitCwd, pathInRepo);
31612
+ const filePath = path15.join(repoGitCwd, pathInRepo);
31491
31613
  let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
31492
31614
  if (patch) {
31493
- patch = await hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, row.change);
31615
+ patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
31494
31616
  }
31495
31617
  row.patchContent = patch;
31496
31618
  }
@@ -31503,8 +31625,9 @@ function normRepoRel(p) {
31503
31625
  return x === "" ? "." : x;
31504
31626
  }
31505
31627
  async function getWorkingTreeChangeRepoDetails(options) {
31506
- const launcher = path15.resolve(getBridgeWorkspaceDirectory());
31507
- const mirror = options.agentMirrorRootAbs ? path15.resolve(options.agentMirrorRootAbs) : null;
31628
+ const bridgeRoot = path16.resolve(getBridgeRoot());
31629
+ const sessionWtRoot = options.sessionWorktreeRootPath ? path16.resolve(options.sessionWorktreeRootPath) : null;
31630
+ const legacyNested = options.legacyRepoNestedSessionLayout === true;
31508
31631
  const out = [];
31509
31632
  const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
31510
31633
  const basisInput = options.basis ?? { kind: "working" };
@@ -31515,8 +31638,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
31515
31638
  throw new Error("commit sha is required for commit changes");
31516
31639
  }
31517
31640
  const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
31518
- for (const target of options.commitTargetAbsDirs) {
31519
- const t = path15.resolve(target);
31641
+ for (const target of options.commitTargetPaths) {
31642
+ const t = path16.resolve(target);
31520
31643
  if (!await isGitRepoDirectory(t)) continue;
31521
31644
  const g = simpleGit(t);
31522
31645
  let branch = "HEAD";
@@ -31528,8 +31651,9 @@ async function getWorkingTreeChangeRepoDetails(options) {
31528
31651
  const remoteUrl = await getRemoteOriginUrl(t);
31529
31652
  const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
31530
31653
  let repoRelPath;
31531
- if (mirror) {
31532
- const relNorm = path15.relative(mirror, path15.dirname(t));
31654
+ if (sessionWtRoot) {
31655
+ const anchor = legacyNested ? path16.dirname(t) : t;
31656
+ const relNorm = path16.relative(sessionWtRoot, anchor);
31533
31657
  repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
31534
31658
  } else {
31535
31659
  let top = t;
@@ -31538,8 +31662,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
31538
31662
  } catch {
31539
31663
  top = t;
31540
31664
  }
31541
- const rel = path15.relative(launcher, path15.resolve(top)).replace(/\\/g, "/") || ".";
31542
- repoRelPath = rel.startsWith("..") ? path15.basename(path15.resolve(top)) : rel;
31665
+ const rel = path16.relative(bridgeRoot, path16.resolve(top)).replace(/\\/g, "/") || ".";
31666
+ repoRelPath = rel.startsWith("..") ? path16.basename(path16.resolve(top)) : rel;
31543
31667
  }
31544
31668
  const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
31545
31669
  if (filter && norm !== filter) continue;
@@ -31605,14 +31729,37 @@ async function commitSessionWorktrees(options) {
31605
31729
 
31606
31730
  // src/worktrees/discover-session-worktree-on-disk.ts
31607
31731
  import * as fs17 from "node:fs";
31608
- import * as path16 from "node:path";
31609
- function isGitDir(abs) {
31732
+ import * as path17 from "node:path";
31733
+ function isGitDir(dirPath) {
31610
31734
  try {
31611
- return fs17.existsSync(path16.join(abs, ".git"));
31735
+ return fs17.existsSync(path17.join(dirPath, ".git"));
31612
31736
  } catch {
31613
31737
  return false;
31614
31738
  }
31615
31739
  }
31740
+ function collectGitRepoRootsUnderDirectory(rootPath) {
31741
+ const out = [];
31742
+ const walk = (dir) => {
31743
+ if (isGitDir(dir)) {
31744
+ out.push(path17.resolve(dir));
31745
+ return;
31746
+ }
31747
+ let entries;
31748
+ try {
31749
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
31750
+ } catch {
31751
+ return;
31752
+ }
31753
+ for (const e of entries) {
31754
+ if (e.name.startsWith(".")) continue;
31755
+ const full = path17.join(dir, e.name);
31756
+ if (!e.isDirectory()) continue;
31757
+ walk(full);
31758
+ }
31759
+ };
31760
+ walk(path17.resolve(rootPath));
31761
+ return [...new Set(out)];
31762
+ }
31616
31763
  function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
31617
31764
  const out = [];
31618
31765
  const walk = (dir, depth) => {
@@ -31625,10 +31772,10 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
31625
31772
  }
31626
31773
  for (const e of entries) {
31627
31774
  if (e.name.startsWith(".")) continue;
31628
- const full = path16.join(dir, e.name);
31775
+ const full = path17.join(dir, e.name);
31629
31776
  if (!e.isDirectory()) continue;
31630
31777
  if (e.name === sessionId) {
31631
- if (isGitDir(full)) out.push(path16.resolve(full));
31778
+ if (isGitDir(full)) out.push(path17.resolve(full));
31632
31779
  } else {
31633
31780
  walk(full, depth + 1);
31634
31781
  }
@@ -31637,16 +31784,55 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
31637
31784
  walk(root, 0);
31638
31785
  return out;
31639
31786
  }
31787
+ function tryBindingFromSessionDirectory(sessionDir) {
31788
+ let st;
31789
+ try {
31790
+ st = fs17.statSync(sessionDir);
31791
+ } catch {
31792
+ return null;
31793
+ }
31794
+ if (!st.isDirectory()) return null;
31795
+ const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
31796
+ if (worktreePaths.length === 0) return null;
31797
+ const abs = path17.resolve(sessionDir);
31798
+ return {
31799
+ sessionParentPath: abs,
31800
+ workingTreeRelRoot: abs,
31801
+ repoCheckoutPaths: worktreePaths
31802
+ };
31803
+ }
31804
+ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
31805
+ const sid = sessionId.trim();
31806
+ if (!sid) return null;
31807
+ const hintR = path17.resolve(checkoutPath);
31808
+ let best = null;
31809
+ let cur = path17.dirname(hintR);
31810
+ for (let i = 0; i < 40; i++) {
31811
+ const paths = collectWorktreeRootsNamed(cur, sid, 24);
31812
+ if (paths.some((p) => path17.resolve(p) === hintR)) {
31813
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path17.resolve(paths[0]);
31814
+ best = {
31815
+ sessionParentPath: path17.resolve(isolated),
31816
+ workingTreeRelRoot: path17.resolve(cur),
31817
+ repoCheckoutPaths: paths.map((p) => path17.resolve(p))
31818
+ };
31819
+ }
31820
+ const next = path17.dirname(cur);
31821
+ if (next === cur) break;
31822
+ cur = next;
31823
+ }
31824
+ return best;
31825
+ }
31640
31826
  function discoverSessionWorktreeOnDisk(options) {
31641
- const { sessionId, worktreesRootAbs, layout, launcherCwd } = options;
31642
- if (!sessionId.trim() || !fs17.existsSync(worktreesRootAbs)) return null;
31643
- const preferredKey = getLauncherDirNameIfPresent(layout, launcherCwd);
31827
+ const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
31828
+ if (!sessionId.trim() || !fs17.existsSync(worktreesRootPath)) return null;
31829
+ const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
31644
31830
  const keys = [];
31645
31831
  if (preferredKey) keys.push(preferredKey);
31646
31832
  try {
31647
- for (const name of fs17.readdirSync(worktreesRootAbs)) {
31833
+ for (const name of fs17.readdirSync(worktreesRootPath)) {
31648
31834
  if (name.startsWith(".")) continue;
31649
- const p = path16.join(worktreesRootAbs, name);
31835
+ const p = path17.join(worktreesRootPath, name);
31650
31836
  if (!fs17.statSync(p).isDirectory()) continue;
31651
31837
  if (name !== preferredKey) keys.push(name);
31652
31838
  }
@@ -31654,26 +31840,58 @@ function discoverSessionWorktreeOnDisk(options) {
31654
31840
  return null;
31655
31841
  }
31656
31842
  for (const key of keys) {
31657
- const mirrorRoot = path16.join(worktreesRootAbs, key);
31658
- if (!fs17.existsSync(mirrorRoot) || !fs17.statSync(mirrorRoot).isDirectory()) continue;
31659
- const worktreePaths = collectWorktreeRootsNamed(mirrorRoot, sessionId, 24);
31660
- if (worktreePaths.length > 0) {
31661
- return { agentCwd: path16.resolve(mirrorRoot), worktreePaths };
31843
+ const layoutRoot = path17.join(worktreesRootPath, key);
31844
+ if (!fs17.existsSync(layoutRoot) || !fs17.statSync(layoutRoot).isDirectory()) continue;
31845
+ const sessionDir = path17.join(layoutRoot, sessionId);
31846
+ const nested = tryBindingFromSessionDirectory(sessionDir);
31847
+ if (nested) return nested;
31848
+ const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
31849
+ if (legacyPaths.length > 0) {
31850
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path17.resolve(legacyPaths[0]);
31851
+ return {
31852
+ sessionParentPath: path17.resolve(isolated),
31853
+ workingTreeRelRoot: path17.resolve(layoutRoot),
31854
+ repoCheckoutPaths: legacyPaths.map((p) => path17.resolve(p))
31855
+ };
31662
31856
  }
31663
31857
  }
31664
31858
  return null;
31665
31859
  }
31666
- function discoverSessionWorktreesUnderMirrorRoot(mirrorRootAbs, sessionId) {
31667
- const mirrorRoot = path16.resolve(mirrorRootAbs);
31668
- if (!sessionId.trim() || !fs17.existsSync(mirrorRoot)) return null;
31860
+ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
31861
+ const sid = sessionId.trim();
31862
+ if (!sid) return null;
31863
+ const hint = path17.resolve(sessionWorktreeRootPathOrHint);
31864
+ const underHint = tryBindingFromSessionDirectory(path17.join(hint, sid));
31865
+ if (underHint) return underHint;
31866
+ const direct = tryBindingFromSessionDirectory(hint);
31867
+ if (direct) {
31868
+ if (path17.basename(hint) === sid && isGitDir(hint)) {
31869
+ const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
31870
+ if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
31871
+ return legacyFromCheckout;
31872
+ }
31873
+ }
31874
+ return direct;
31875
+ }
31876
+ if (path17.basename(hint) === sid && isGitDir(hint)) {
31877
+ const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
31878
+ if (legacyFromCheckout) return legacyFromCheckout;
31879
+ }
31880
+ let st;
31669
31881
  try {
31670
- if (!fs17.statSync(mirrorRoot).isDirectory()) return null;
31882
+ st = fs17.statSync(hint);
31671
31883
  } catch {
31672
31884
  return null;
31673
31885
  }
31674
- const worktreePaths = collectWorktreeRootsNamed(mirrorRoot, sessionId, 24);
31675
- if (worktreePaths.length === 0) return null;
31676
- return { agentCwd: mirrorRoot, worktreePaths };
31886
+ if (!st.isDirectory()) return null;
31887
+ const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
31888
+ if (legacyPaths.length === 0) return null;
31889
+ const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path17.resolve(legacyPaths[0]);
31890
+ return {
31891
+ sessionParentPath: path17.resolve(isolated),
31892
+ workingTreeRelRoot: hint,
31893
+ repoCheckoutPaths: legacyPaths.map((p) => path17.resolve(p))
31894
+ };
31677
31895
  }
31678
31896
 
31679
31897
  // src/worktrees/session-worktree-manager.ts
@@ -31683,42 +31901,86 @@ function parseSessionParent(v) {
31683
31901
  return null;
31684
31902
  }
31685
31903
  var SessionWorktreeManager = class {
31686
- rootAbs;
31904
+ worktreesRootPath;
31687
31905
  log;
31688
- sessionPaths = /* @__PURE__ */ new Map();
31689
- sessionAgentCwd = /* @__PURE__ */ new Map();
31906
+ sessionRepoCheckoutPaths = /* @__PURE__ */ new Map();
31907
+ sessionParentPathBySession = /* @__PURE__ */ new Map();
31908
+ sessionWorkingTreeRelRootBySession = /* @__PURE__ */ new Map();
31690
31909
  layout;
31691
31910
  constructor(options) {
31692
- this.rootAbs = options.worktreesRootAbs;
31911
+ this.worktreesRootPath = options.worktreesRootPath;
31693
31912
  this.log = options.log;
31694
31913
  this.layout = loadWorktreeLayout();
31695
31914
  }
31696
- rememberWorktrees(sessionId, agentCwd, worktreePaths) {
31697
- this.sessionPaths.set(sessionId, worktreePaths);
31698
- this.sessionAgentCwd.set(sessionId, path17.resolve(agentCwd));
31915
+ rememberSessionWorktrees(sessionId, binding) {
31916
+ const paths = binding.repoCheckoutPaths.map((p) => path18.resolve(p));
31917
+ this.sessionRepoCheckoutPaths.set(sessionId, paths);
31918
+ this.sessionParentPathBySession.set(sessionId, path18.resolve(binding.sessionParentPath));
31919
+ this.sessionWorkingTreeRelRootBySession.set(sessionId, path18.resolve(binding.workingTreeRelRoot));
31920
+ }
31921
+ sessionParentPathAfterRemember(sessionId) {
31922
+ return this.sessionParentPathBySession.get(sessionId);
31699
31923
  }
31700
31924
  tryDiscoverFromDisk(sessionId) {
31701
31925
  return discoverSessionWorktreeOnDisk({
31702
31926
  sessionId,
31703
- worktreesRootAbs: this.rootAbs,
31927
+ worktreesRootPath: this.worktreesRootPath,
31704
31928
  layout: this.layout,
31705
- launcherCwd: getBridgeWorkspaceDirectory()
31929
+ bridgeRoot: getBridgeRoot()
31706
31930
  });
31707
31931
  }
31932
+ isLegacyNestedLayout(sessionId) {
31933
+ const parent = this.sessionParentPathBySession.get(sessionId);
31934
+ const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
31935
+ if (!parent || !relRoot) return false;
31936
+ return path18.resolve(parent) !== path18.resolve(relRoot);
31937
+ }
31938
+ /**
31939
+ * Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
31940
+ */
31941
+ getIsolatedSessionParentPathForSession(sessionId) {
31942
+ if (!sessionId) return null;
31943
+ const sid = sessionId.trim();
31944
+ const cached2 = this.sessionParentPathBySession.get(sid);
31945
+ if (cached2) return path18.resolve(cached2);
31946
+ const paths = this.ensureRepoCheckoutPathsForSession(sid) ?? this.getRepoCheckoutPathsForSession(sid);
31947
+ if (!paths?.length) return null;
31948
+ return resolveIsolatedSessionParentPathFromCheckouts(paths);
31949
+ }
31708
31950
  /**
31709
- * Returns cwd for the agent (mirror of launcher tree), or undefined to use the bridge workspace directory.
31951
+ * Resolved **session parent path** for the agent: session directory in worktrees mode,
31952
+ * or `undefined` meaning use {@link getBridgeRoot}.
31710
31953
  */
31711
- async resolveCwdForPrompt(sessionId, opts) {
31954
+ async resolveSessionParentPathForPrompt(sessionId, opts) {
31712
31955
  if (!sessionId) return void 0;
31956
+ const sid = sessionId.trim();
31713
31957
  const parentPathRaw = opts.sessionParentPath?.trim();
31714
31958
  if (parentPathRaw) {
31715
- const agentCwd = path17.resolve(parentPathRaw);
31716
- const sid = sessionId?.trim();
31959
+ const resolved = path18.resolve(parentPathRaw);
31717
31960
  if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
31718
- const fromMirror = discoverSessionWorktreesUnderMirrorRoot(agentCwd, sid);
31719
- if (fromMirror) this.rememberWorktrees(sid, fromMirror.agentCwd, fromMirror.worktreePaths);
31961
+ const diskFirst = this.tryDiscoverFromDisk(sid);
31962
+ if (diskFirst) {
31963
+ this.rememberSessionWorktrees(sid, diskFirst);
31964
+ return this.sessionParentPathAfterRemember(sid);
31965
+ }
31966
+ const fromRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(resolved, sid);
31967
+ if (fromRoot) {
31968
+ this.rememberSessionWorktrees(sid, fromRoot);
31969
+ return this.sessionParentPathAfterRemember(sid);
31970
+ }
31971
+ let cur = resolved;
31972
+ for (let i = 0; i < 16; i++) {
31973
+ const tryRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(cur, sid);
31974
+ if (tryRoot) {
31975
+ this.rememberSessionWorktrees(sid, tryRoot);
31976
+ return this.sessionParentPathAfterRemember(sid);
31977
+ }
31978
+ const next = path18.dirname(cur);
31979
+ if (next === cur) break;
31980
+ cur = next;
31981
+ }
31720
31982
  }
31721
- return agentCwd;
31983
+ return resolved;
31722
31984
  }
31723
31985
  const parentKind = parseSessionParent(opts.sessionParent);
31724
31986
  if (parentKind === "bridge_root") {
@@ -31726,78 +31988,102 @@ var SessionWorktreeManager = class {
31726
31988
  }
31727
31989
  if (parentKind === "worktrees_root") {
31728
31990
  if (!opts.isNewSession) {
31729
- const cached2 = this.sessionAgentCwd.get(sessionId);
31730
- if (cached2) return path17.resolve(cached2);
31731
- const disc = this.tryDiscoverFromDisk(sessionId);
31991
+ const cached2 = this.sessionParentPathAfterRemember(sid);
31992
+ if (cached2) return cached2;
31993
+ const disc = this.tryDiscoverFromDisk(sid);
31732
31994
  if (disc) {
31733
- this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
31734
- return path17.resolve(disc.agentCwd);
31995
+ this.rememberSessionWorktrees(sid, disc);
31996
+ return this.sessionParentPathAfterRemember(sid);
31735
31997
  }
31736
31998
  return void 0;
31737
31999
  }
31738
32000
  const prep2 = await prepareNewSessionWorktrees({
31739
- rootAbs: this.rootAbs,
31740
- launcherCwd: getBridgeWorkspaceDirectory(),
31741
- sessionId,
32001
+ worktreesRootPath: this.worktreesRootPath,
32002
+ bridgeRoot: getBridgeRoot(),
32003
+ sessionId: sid,
31742
32004
  layout: this.layout,
31743
32005
  log: this.log
31744
32006
  });
31745
32007
  if (!prep2) return void 0;
31746
- this.rememberWorktrees(sessionId, prep2.agentCwd, prep2.worktreePaths);
31747
- return path17.resolve(prep2.agentCwd);
32008
+ this.rememberSessionWorktrees(sid, {
32009
+ sessionParentPath: prep2.sessionParentPath,
32010
+ workingTreeRelRoot: prep2.workingTreeRelRoot,
32011
+ repoCheckoutPaths: prep2.worktreePaths
32012
+ });
32013
+ return this.sessionParentPathAfterRemember(sid);
31748
32014
  }
31749
32015
  if (!opts.isNewSession) {
31750
- const cached2 = this.sessionAgentCwd.get(sessionId);
31751
- if (cached2) return path17.resolve(cached2);
31752
- const disc = this.tryDiscoverFromDisk(sessionId);
32016
+ const cached2 = this.sessionParentPathAfterRemember(sid);
32017
+ if (cached2) return cached2;
32018
+ const disc = this.tryDiscoverFromDisk(sid);
31753
32019
  if (disc) {
31754
- this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
31755
- return path17.resolve(disc.agentCwd);
32020
+ this.rememberSessionWorktrees(sid, disc);
32021
+ return this.sessionParentPathAfterRemember(sid);
31756
32022
  }
31757
32023
  return void 0;
31758
32024
  }
31759
32025
  const prep = await prepareNewSessionWorktrees({
31760
- rootAbs: this.rootAbs,
31761
- launcherCwd: getBridgeWorkspaceDirectory(),
31762
- sessionId,
32026
+ worktreesRootPath: this.worktreesRootPath,
32027
+ bridgeRoot: getBridgeRoot(),
32028
+ sessionId: sid,
31763
32029
  layout: this.layout,
31764
32030
  log: this.log
31765
32031
  });
31766
32032
  if (!prep) return void 0;
31767
- this.rememberWorktrees(sessionId, prep.agentCwd, prep.worktreePaths);
31768
- return path17.resolve(prep.agentCwd);
32033
+ this.rememberSessionWorktrees(sid, {
32034
+ sessionParentPath: prep.sessionParentPath,
32035
+ workingTreeRelRoot: prep.workingTreeRelRoot,
32036
+ repoCheckoutPaths: prep.worktreePaths
32037
+ });
32038
+ return this.sessionParentPathAfterRemember(sid);
31769
32039
  }
31770
32040
  async renameSessionBranch(sessionId, newBranch) {
31771
- const paths = this.sessionPaths.get(sessionId);
32041
+ const paths = this.sessionRepoCheckoutPaths.get(sessionId);
31772
32042
  if (!paths?.length) return;
31773
32043
  await renameSessionWorktreeBranches(paths, newBranch, this.log);
31774
32044
  }
31775
- /** True when this session runs in an isolated worktree mirror (not launcher cwd). */
32045
+ /** True when this session uses an isolated worktree layout (not the bridge root). */
31776
32046
  usesWorktreeSession(sessionId) {
31777
32047
  if (!sessionId) return false;
31778
- return this.sessionAgentCwd.has(sessionId);
32048
+ return this.sessionParentPathBySession.has(sessionId);
31779
32049
  }
31780
- getWorktreePathsForSession(sessionId) {
32050
+ /** Per-repo git checkout directories for this session (for snapshots, commits, change lists). */
32051
+ getRepoCheckoutPathsForSession(sessionId) {
31781
32052
  if (!sessionId) return void 0;
31782
- const paths = this.sessionPaths.get(sessionId);
32053
+ const paths = this.sessionRepoCheckoutPaths.get(sessionId);
31783
32054
  return paths?.length ? [...paths] : void 0;
31784
32055
  }
31785
- /** Session mirror root (parent of per-repo worktrees), when using worktrees for this session. */
31786
- getAgentCwdForSession(sessionId) {
31787
- if (!sessionId) return null;
31788
- const c = this.sessionAgentCwd.get(sessionId);
31789
- return c ? path17.resolve(c) : null;
32056
+ /**
32057
+ * Same paths as {@link getRepoCheckoutPathsForSession}, but loads from disk into memory when the CLI
32058
+ * restarted or maps were not yet populated (avoids discovering every repo under the worktrees root).
32059
+ */
32060
+ ensureRepoCheckoutPathsForSession(sessionId) {
32061
+ if (!sessionId?.trim()) return void 0;
32062
+ const sid = sessionId.trim();
32063
+ const cached2 = this.sessionRepoCheckoutPaths.get(sid);
32064
+ if (cached2?.length) return [...cached2];
32065
+ const disc = this.tryDiscoverFromDisk(sid);
32066
+ if (disc?.repoCheckoutPaths.length) {
32067
+ this.rememberSessionWorktrees(sid, disc);
32068
+ return [...disc.repoCheckoutPaths];
32069
+ }
32070
+ return void 0;
32071
+ }
32072
+ /** Session parent directory when in worktrees mode; null otherwise (same as {@link getIsolatedSessionParentPathForSession} path). */
32073
+ getSessionWorktreeRootForSession(sessionId) {
32074
+ return this.getIsolatedSessionParentPathForSession(sessionId);
31790
32075
  }
31791
32076
  async removeSessionWorktrees(sessionId) {
31792
- const paths = this.sessionPaths.get(sessionId);
31793
- this.sessionPaths.delete(sessionId);
31794
- this.sessionAgentCwd.delete(sessionId);
32077
+ const paths = this.sessionRepoCheckoutPaths.get(sessionId);
32078
+ this.sessionRepoCheckoutPaths.delete(sessionId);
32079
+ this.sessionParentPathBySession.delete(sessionId);
32080
+ this.sessionWorkingTreeRelRootBySession.delete(sessionId);
31795
32081
  if (!paths?.length) return;
31796
32082
  await removeSessionWorktrees(paths, this.log);
31797
32083
  }
31798
32084
  async commitSession(params) {
31799
- const paths = this.sessionPaths.get(params.sessionId);
31800
- const targets = paths?.length ? paths : [getBridgeWorkspaceDirectory()];
32085
+ const paths = this.sessionRepoCheckoutPaths.get(params.sessionId);
32086
+ const targets = paths?.length ? paths : [getBridgeRoot()];
31801
32087
  return commitSessionWorktrees({
31802
32088
  paths: targets,
31803
32089
  branch: params.branch,
@@ -31806,14 +32092,14 @@ var SessionWorktreeManager = class {
31806
32092
  });
31807
32093
  }
31808
32094
  resolveCommitTargets(sessionId) {
31809
- const paths = this.sessionPaths.get(sessionId);
32095
+ const paths = this.sessionRepoCheckoutPaths.get(sessionId);
31810
32096
  if (paths?.length) return paths;
31811
32097
  const disc = this.tryDiscoverFromDisk(sessionId);
31812
- if (disc?.worktreePaths.length) {
31813
- this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
31814
- return disc.worktreePaths;
32098
+ if (disc?.repoCheckoutPaths.length) {
32099
+ this.rememberSessionWorktrees(sessionId, disc);
32100
+ return disc.repoCheckoutPaths;
31815
32101
  }
31816
- return [getBridgeWorkspaceDirectory()];
32102
+ return [getBridgeRoot()];
31817
32103
  }
31818
32104
  async getSessionWorkingTreeStatus(sessionId) {
31819
32105
  return aggregateSessionPathsWorkingTreeStatus(this.resolveCommitTargets(sessionId));
@@ -31821,10 +32107,12 @@ var SessionWorktreeManager = class {
31821
32107
  /** Per-repo changed files vs HEAD (or a single commit vs parent) for the same git roots used for commit/push. */
31822
32108
  async getSessionWorkingTreeChangeDetails(sessionId, opts) {
31823
32109
  const targets = this.resolveCommitTargets(sessionId);
31824
- const mirror = this.getAgentCwdForSession(sessionId);
32110
+ const sessionWorkingTreeRelRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId) ?? null;
32111
+ const legacyNested = this.isLegacyNestedLayout(sessionId);
31825
32112
  return getWorkingTreeChangeRepoDetails({
31826
- commitTargetAbsDirs: targets,
31827
- agentMirrorRootAbs: mirror,
32113
+ commitTargetPaths: targets,
32114
+ sessionWorktreeRootPath: sessionWorkingTreeRelRoot,
32115
+ legacyRepoNestedSessionLayout: legacyNested,
31828
32116
  repoFilterRelPath: opts?.repoRelPath?.trim() ? opts.repoRelPath.trim() : null,
31829
32117
  basis: opts?.basis
31830
32118
  });
@@ -31839,31 +32127,31 @@ var SessionWorktreeManager = class {
31839
32127
  }
31840
32128
  }
31841
32129
  };
31842
- function defaultWorktreesRootAbs() {
31843
- return path17.join(os4.homedir(), ".buildautomaton", "worktrees");
32130
+ function defaultWorktreesRootPath() {
32131
+ return path18.join(os4.homedir(), ".buildautomaton", "worktrees");
31844
32132
  }
31845
32133
 
31846
32134
  // src/files/watch-file-index.ts
31847
32135
  import { watch } from "node:fs";
31848
- import path24 from "node:path";
32136
+ import path25 from "node:path";
31849
32137
 
31850
32138
  // src/files/index/build-file-index.ts
31851
- import path21 from "node:path";
32139
+ import path22 from "node:path";
31852
32140
 
31853
32141
  // src/runtime/yield-to-event-loop.ts
31854
32142
  function yieldToEventLoop() {
31855
- return new Promise((resolve17) => setImmediate(resolve17));
32143
+ return new Promise((resolve16) => setImmediate(resolve16));
31856
32144
  }
31857
32145
 
31858
32146
  // src/files/index/walk-workspace-tree.ts
31859
32147
  import fs18 from "node:fs";
31860
- import path19 from "node:path";
32148
+ import path20 from "node:path";
31861
32149
 
31862
32150
  // src/files/index/constants.ts
31863
- import path18 from "node:path";
32151
+ import path19 from "node:path";
31864
32152
  import os5 from "node:os";
31865
32153
  var INDEX_WORK_YIELD_EVERY = 256;
31866
- var INDEX_DIR = path18.join(os5.homedir(), ".buildautomaton");
32154
+ var INDEX_DIR = path19.join(os5.homedir(), ".buildautomaton");
31867
32155
  var INDEX_HASH_LEN = 16;
31868
32156
  var INDEX_VERSION = 2;
31869
32157
  var INDEX_LOG_PREFIX = "[file-index]";
@@ -31878,14 +32166,14 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
31878
32166
  }
31879
32167
  for (const name of names) {
31880
32168
  if (name.startsWith(".")) continue;
31881
- const full = path19.join(dir, name);
32169
+ const full = path20.join(dir, name);
31882
32170
  let stat2;
31883
32171
  try {
31884
32172
  stat2 = fs18.statSync(full);
31885
32173
  } catch {
31886
32174
  continue;
31887
32175
  }
31888
- const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
32176
+ const relative5 = path20.relative(baseDir, full).replace(/\\/g, "/");
31889
32177
  if (stat2.isDirectory()) {
31890
32178
  walkWorkspaceTreeSync(full, baseDir, out);
31891
32179
  } else if (stat2.isFile()) {
@@ -31906,14 +32194,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
31906
32194
  await yieldToEventLoop();
31907
32195
  }
31908
32196
  state.n++;
31909
- const full = path19.join(dir, name);
32197
+ const full = path20.join(dir, name);
31910
32198
  let stat2;
31911
32199
  try {
31912
32200
  stat2 = await fs18.promises.stat(full);
31913
32201
  } catch {
31914
32202
  continue;
31915
32203
  }
31916
- const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
32204
+ const relative5 = path20.relative(baseDir, full).replace(/\\/g, "/");
31917
32205
  if (stat2.isDirectory()) {
31918
32206
  await walkWorkspaceTreeAsync(full, baseDir, out, state);
31919
32207
  } else if (stat2.isFile()) {
@@ -31997,11 +32285,11 @@ async function buildTrigramMapForPathsAsync(paths) {
31997
32285
  import fs19 from "node:fs";
31998
32286
 
31999
32287
  // src/files/index/paths.ts
32000
- import path20 from "node:path";
32288
+ import path21 from "node:path";
32001
32289
  import crypto2 from "node:crypto";
32002
32290
  function getIndexPathForCwd(resolvedCwd) {
32003
32291
  const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
32004
- return path20.join(INDEX_DIR, `.file-index-${hash}.json`);
32292
+ return path21.join(INDEX_DIR, `.file-index-${hash}.json`);
32005
32293
  }
32006
32294
 
32007
32295
  // src/files/index/write-index-file.ts
@@ -32032,7 +32320,7 @@ function sortPaths(paths) {
32032
32320
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
32033
32321
  }
32034
32322
  function buildFileIndex(cwd) {
32035
- const resolved = path21.resolve(cwd);
32323
+ const resolved = path22.resolve(cwd);
32036
32324
  const paths = [];
32037
32325
  walkWorkspaceTreeSync(resolved, resolved, paths);
32038
32326
  sortPaths(paths);
@@ -32042,7 +32330,7 @@ function buildFileIndex(cwd) {
32042
32330
  return data;
32043
32331
  }
32044
32332
  async function buildFileIndexAsync(cwd) {
32045
- const resolved = path21.resolve(cwd);
32333
+ const resolved = path22.resolve(cwd);
32046
32334
  const paths = [];
32047
32335
  await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
32048
32336
  await yieldToEventLoop();
@@ -32055,9 +32343,9 @@ async function buildFileIndexAsync(cwd) {
32055
32343
 
32056
32344
  // src/files/index/load-file-index.ts
32057
32345
  import fs20 from "node:fs";
32058
- import path22 from "node:path";
32346
+ import path23 from "node:path";
32059
32347
  function loadFileIndex(cwd) {
32060
- const resolved = path22.resolve(cwd);
32348
+ const resolved = path23.resolve(cwd);
32061
32349
  const indexPath = getIndexPathForCwd(resolved);
32062
32350
  try {
32063
32351
  const raw = fs20.readFileSync(indexPath, "utf8");
@@ -32079,9 +32367,9 @@ function loadFileIndex(cwd) {
32079
32367
  }
32080
32368
 
32081
32369
  // src/files/index/ensure-file-index.ts
32082
- import path23 from "node:path";
32370
+ import path24 from "node:path";
32083
32371
  async function ensureFileIndexAsync(cwd) {
32084
- const resolved = path23.resolve(cwd);
32372
+ const resolved = path24.resolve(cwd);
32085
32373
  const cached2 = loadFileIndex(resolved);
32086
32374
  if (cached2 !== null) return { data: cached2, fromCache: true };
32087
32375
  const data = await buildFileIndexAsync(resolved);
@@ -32163,8 +32451,8 @@ function createFsWatcher(resolved, schedule) {
32163
32451
  throw e;
32164
32452
  }
32165
32453
  }
32166
- function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
32167
- const resolved = path24.resolve(cwd);
32454
+ function startFileIndexWatcher(cwd = getBridgeRoot()) {
32455
+ const resolved = path25.resolve(cwd);
32168
32456
  void buildFileIndexAsync(resolved).catch((e) => {
32169
32457
  console.error("[file-index] Initial index build failed:", e);
32170
32458
  });
@@ -32214,15 +32502,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
32214
32502
 
32215
32503
  // src/dev-servers/process/terminate-child-process.ts
32216
32504
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
32217
- const exited = new Promise((resolve17) => {
32218
- proc.once("exit", () => resolve17());
32505
+ const exited = new Promise((resolve16) => {
32506
+ proc.once("exit", () => resolve16());
32219
32507
  });
32220
32508
  log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
32221
32509
  try {
32222
32510
  proc.kill("SIGTERM");
32223
32511
  } catch {
32224
32512
  }
32225
- await Promise.race([exited, new Promise((resolve17) => setTimeout(resolve17, graceMs))]);
32513
+ await Promise.race([exited, new Promise((resolve16) => setTimeout(resolve16, graceMs))]);
32226
32514
  }
32227
32515
  function forceKillChild(proc, log2, shortId, graceMs) {
32228
32516
  log2(
@@ -32502,10 +32790,10 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
32502
32790
  import { spawn as spawn7 } from "node:child_process";
32503
32791
  import fs23 from "node:fs";
32504
32792
  import { tmpdir } from "node:os";
32505
- import path25 from "node:path";
32793
+ import path26 from "node:path";
32506
32794
  function trySpawnMergedLogFile(command, env, cwd, signal) {
32507
- const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir(), "ba-devsrv-log-"));
32508
- const logPath = path25.join(tmpRoot, "combined.log");
32795
+ const tmpRoot = fs23.mkdtempSync(path26.join(tmpdir(), "ba-devsrv-log-"));
32796
+ const logPath = path26.join(tmpRoot, "combined.log");
32509
32797
  let logFd;
32510
32798
  try {
32511
32799
  logFd = fs23.openSync(logPath, "a");
@@ -32549,15 +32837,15 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
32549
32837
  import { spawn as spawn8 } from "node:child_process";
32550
32838
  import fs24 from "node:fs";
32551
32839
  import { tmpdir as tmpdir2 } from "node:os";
32552
- import path26 from "node:path";
32840
+ import path27 from "node:path";
32553
32841
  function shSingleQuote(s) {
32554
32842
  return `'${s.replace(/'/g, `'\\''`)}'`;
32555
32843
  }
32556
32844
  function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
32557
- const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
32558
- const logPath = path26.join(tmpRoot, "combined.log");
32559
- const innerPath = path26.join(tmpRoot, "_cmd.sh");
32560
- const runnerPath = path26.join(tmpRoot, "_run.sh");
32845
+ const tmpRoot = fs24.mkdtempSync(path27.join(tmpdir2(), "ba-devsrv-sh-"));
32846
+ const logPath = path27.join(tmpRoot, "combined.log");
32847
+ const innerPath = path27.join(tmpRoot, "_cmd.sh");
32848
+ const runnerPath = path27.join(tmpRoot, "_run.sh");
32561
32849
  try {
32562
32850
  fs24.writeFileSync(innerPath, `#!/bin/sh
32563
32851
  ${command}
@@ -32588,9 +32876,9 @@ cd ${shSingleQuote(cwd)}
32588
32876
  }
32589
32877
  }
32590
32878
  function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
32591
- const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
32592
- const logPath = path26.join(tmpRoot, "combined.log");
32593
- const runnerPath = path26.join(tmpRoot, "_run.bat");
32879
+ const tmpRoot = fs24.mkdtempSync(path27.join(tmpdir2(), "ba-devsrv-sh-"));
32880
+ const logPath = path27.join(tmpRoot, "combined.log");
32881
+ const runnerPath = path27.join(tmpRoot, "_run.bat");
32594
32882
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
32595
32883
  const com = process.env.ComSpec || "cmd.exe";
32596
32884
  try {
@@ -32800,13 +33088,13 @@ var DevServerManager = class {
32800
33088
  abortControllersByServerId = /* @__PURE__ */ new Map();
32801
33089
  getWs;
32802
33090
  log;
32803
- getBridgeCwd;
33091
+ getBridgeRoot;
32804
33092
  e2ee;
32805
33093
  firehoseSink;
32806
33094
  constructor(options) {
32807
33095
  this.getWs = options.getWs;
32808
33096
  this.log = options.log;
32809
- this.getBridgeCwd = options.getBridgeCwd ?? (() => process.cwd());
33097
+ this.getBridgeRoot = options.getBridgeRoot ?? (() => process.cwd());
32810
33098
  this.e2ee = options.e2ee;
32811
33099
  this.firehoseSink = new DevServerFirehoseSink({
32812
33100
  getTails: (serverId) => this.snapshotTails(serverId),
@@ -32895,7 +33183,7 @@ var DevServerManager = class {
32895
33183
  this.sendStatus(serverId, "starting", void 0, emptyTails());
32896
33184
  const ac = new AbortController();
32897
33185
  this.abortControllersByServerId.set(serverId, ac);
32898
- const cwd = this.getBridgeCwd();
33186
+ const cwd = this.getBridgeRoot();
32899
33187
  const childEnv = envForSpawn(process.env, def.env, def.ports);
32900
33188
  const cmd = substituteCommand(def.command.trim(), childEnv);
32901
33189
  const title = def.name.trim() || serverId.slice(0, 8);
@@ -33318,13 +33606,13 @@ function createOnBridgeIdentified(opts) {
33318
33606
 
33319
33607
  // src/skills/discover-local-agent-skills.ts
33320
33608
  import fs25 from "node:fs";
33321
- import path27 from "node:path";
33609
+ import path28 from "node:path";
33322
33610
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
33323
33611
  function discoverLocalSkills(cwd) {
33324
33612
  const out = [];
33325
33613
  const seenKeys = /* @__PURE__ */ new Set();
33326
33614
  for (const rel of SKILL_DISCOVERY_ROOTS) {
33327
- const base = path27.join(cwd, rel);
33615
+ const base = path28.join(cwd, rel);
33328
33616
  if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
33329
33617
  let entries = [];
33330
33618
  try {
@@ -33333,13 +33621,13 @@ function discoverLocalSkills(cwd) {
33333
33621
  continue;
33334
33622
  }
33335
33623
  for (const name of entries) {
33336
- const dir = path27.join(base, name);
33624
+ const dir = path28.join(base, name);
33337
33625
  try {
33338
33626
  if (!fs25.statSync(dir).isDirectory()) continue;
33339
33627
  } catch {
33340
33628
  continue;
33341
33629
  }
33342
- const skillMd = path27.join(dir, "SKILL.md");
33630
+ const skillMd = path28.join(dir, "SKILL.md");
33343
33631
  if (!fs25.existsSync(skillMd)) continue;
33344
33632
  const key = `${rel}/${name}`;
33345
33633
  if (seenKeys.has(key)) continue;
@@ -33352,7 +33640,7 @@ function discoverLocalSkills(cwd) {
33352
33640
  function discoverSkillLayoutRoots(cwd) {
33353
33641
  const roots = [];
33354
33642
  for (const rel of SKILL_DISCOVERY_ROOTS) {
33355
- const base = path27.join(cwd, rel);
33643
+ const base = path28.join(cwd, rel);
33356
33644
  if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
33357
33645
  let entries = [];
33358
33646
  try {
@@ -33362,13 +33650,13 @@ function discoverSkillLayoutRoots(cwd) {
33362
33650
  }
33363
33651
  const skills2 = [];
33364
33652
  for (const name of entries) {
33365
- const dir = path27.join(base, name);
33653
+ const dir = path28.join(base, name);
33366
33654
  try {
33367
33655
  if (!fs25.statSync(dir).isDirectory()) continue;
33368
33656
  } catch {
33369
33657
  continue;
33370
33658
  }
33371
- if (!fs25.existsSync(path27.join(dir, "SKILL.md"))) continue;
33659
+ if (!fs25.existsSync(path28.join(dir, "SKILL.md"))) continue;
33372
33660
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
33373
33661
  skills2.push({ name, relPath });
33374
33662
  }
@@ -33412,7 +33700,7 @@ function createSendLocalSkillsReport(getWs, logFn) {
33412
33700
  try {
33413
33701
  const socket = getWs();
33414
33702
  if (!socket || socket.readyState !== wrapper_default.OPEN) return;
33415
- const skills2 = discoverLocalSkills(getBridgeWorkspaceDirectory());
33703
+ const skills2 = discoverLocalSkills(getBridgeRoot());
33416
33704
  sendWsMessage(socket, { type: "local_skills", skills: skills2 });
33417
33705
  } catch (e) {
33418
33706
  logFn(
@@ -33473,6 +33761,7 @@ var API_TO_BRIDGE_MESSAGE_TYPES = [
33473
33761
  "dev_servers_config",
33474
33762
  "server_control",
33475
33763
  "agent_config",
33764
+ "prompt_queue_state",
33476
33765
  "prompt",
33477
33766
  "session_git_request",
33478
33767
  "rename_session_branch",
@@ -33549,8 +33838,178 @@ var handleAgentConfigMessage = (msg, deps) => {
33549
33838
  handleBridgeAgentConfig(msg, deps);
33550
33839
  };
33551
33840
 
33552
- // src/agents/acp/from-bridge/handle-bridge-prompt.ts
33553
- import * as path29 from "node:path";
33841
+ // src/prompt-turn-queue/client-report.ts
33842
+ function sendPromptQueueClientReport(ws, queues) {
33843
+ if (!ws) return false;
33844
+ sendWsMessage(ws, { type: "prompt_queue_client_report", queues });
33845
+ return true;
33846
+ }
33847
+
33848
+ // src/prompt-turn-queue/disk-store.ts
33849
+ import fs27 from "node:fs";
33850
+
33851
+ // src/prompt-turn-queue/paths.ts
33852
+ import crypto3 from "node:crypto";
33853
+ import fs26 from "node:fs";
33854
+ import path29 from "node:path";
33855
+ import os6 from "node:os";
33856
+ var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
33857
+ function queueStateFileSlug(queueKey) {
33858
+ if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
33859
+ return crypto3.createHash("sha256").update(queueKey, "utf8").digest("hex");
33860
+ }
33861
+ function getPromptQueuesDirectory() {
33862
+ const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
33863
+ if (override) return path29.resolve(override);
33864
+ return path29.join(os6.homedir(), ".buildautomaton", "queues");
33865
+ }
33866
+ function ensurePromptQueuesDirectory() {
33867
+ const dir = getPromptQueuesDirectory();
33868
+ if (!fs26.existsSync(dir)) fs26.mkdirSync(dir, { recursive: true });
33869
+ }
33870
+ function queueStateFilePath(queueKey) {
33871
+ return path29.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
33872
+ }
33873
+
33874
+ // src/prompt-turn-queue/disk-store.ts
33875
+ function parsePersistedQueueFile(raw) {
33876
+ try {
33877
+ const o = JSON.parse(raw);
33878
+ const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
33879
+ if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
33880
+ return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
33881
+ } catch {
33882
+ return null;
33883
+ }
33884
+ }
33885
+ function readPersistedQueue(queueKey) {
33886
+ const p = queueStateFilePath(queueKey);
33887
+ try {
33888
+ return parsePersistedQueueFile(fs27.readFileSync(p, "utf8"));
33889
+ } catch {
33890
+ return null;
33891
+ }
33892
+ }
33893
+ function writePersistedQueue(file2) {
33894
+ ensurePromptQueuesDirectory();
33895
+ const p = queueStateFilePath(file2.queueKey);
33896
+ fs27.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
33897
+ }
33898
+ function mergeServerQueueSnapshot(queueKey, serverTurns) {
33899
+ const prev = readPersistedQueue(queueKey);
33900
+ const turns = [];
33901
+ for (const raw of serverTurns) {
33902
+ if (!raw || typeof raw !== "object") continue;
33903
+ const o = raw;
33904
+ const turnId = typeof o.turnId === "string" ? o.turnId : "";
33905
+ const sessionId = typeof o.sessionId === "string" ? o.sessionId : "";
33906
+ const turnOrd = typeof o.turnOrd === "number" ? o.turnOrd : Number(o.turnOrd) || 0;
33907
+ const serverState = o.serverState;
33908
+ const lastClientState = o.lastClientState ?? null;
33909
+ const payload = o.payload && typeof o.payload === "object" ? o.payload : {};
33910
+ if (!turnId || !sessionId) continue;
33911
+ if (serverState !== "queued" && serverState !== "stopping" && serverState !== "discarded") continue;
33912
+ const old = prev?.turns.find((t) => t.turnId === turnId);
33913
+ const mergedClient = old?.lastClientState === "running" && lastClientState == null ? "running" : lastClientState;
33914
+ turns.push({
33915
+ turnId,
33916
+ sessionId,
33917
+ turnOrd,
33918
+ serverState,
33919
+ lastClientState: mergedClient,
33920
+ payload
33921
+ });
33922
+ }
33923
+ turns.sort((a, b) => a.turnOrd - b.turnOrd);
33924
+ return { queueKey, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), turns };
33925
+ }
33926
+
33927
+ // src/prompt-turn-queue/runner.ts
33928
+ var runIdToQueueKey = /* @__PURE__ */ new Map();
33929
+ function pickNextRunnableTurn(turns) {
33930
+ for (const t of turns) {
33931
+ if (t.serverState === "discarded" || t.serverState === "stopping") continue;
33932
+ if (t.serverState !== "queued") continue;
33933
+ if (t.lastClientState === "running" || t.lastClientState === "stopped" || t.lastClientState === "failed") continue;
33934
+ return t;
33935
+ }
33936
+ return null;
33937
+ }
33938
+ function hasRunningTurn(turns) {
33939
+ return turns.some((t) => t.lastClientState === "running");
33940
+ }
33941
+ function dispatchLocalPrompt(next, deps) {
33942
+ const pl = next.payload;
33943
+ const rawParent = pl["sessionParent"];
33944
+ const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : void 0;
33945
+ const rawParentPath = pl["sessionParentPath"];
33946
+ const sessionParentPath = typeof rawParentPath === "string" && rawParentPath.trim() !== "" ? rawParentPath.trim() : void 0;
33947
+ const msg = {
33948
+ type: "prompt",
33949
+ sessionId: next.sessionId,
33950
+ runId: next.turnId,
33951
+ prompt: pl.prompt,
33952
+ mode: typeof pl.mode === "string" ? pl.mode : "agent",
33953
+ isNewSession: pl.isNewSession === true,
33954
+ ...sessionParent ? { sessionParent } : {},
33955
+ ...sessionParentPath ? { sessionParentPath } : {},
33956
+ ...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
33957
+ ...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
33958
+ ...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
33959
+ ...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {}
33960
+ };
33961
+ handleBridgePrompt(msg, deps);
33962
+ }
33963
+ function applyPromptQueueStateFromServer(msg, deps) {
33964
+ const raw = msg.queues;
33965
+ if (!raw || typeof raw !== "object") return;
33966
+ const getWs = deps.getWs;
33967
+ for (const [queueKey, serverTurns] of Object.entries(raw)) {
33968
+ if (!Array.isArray(serverTurns)) continue;
33969
+ const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
33970
+ writePersistedQueue(file2);
33971
+ }
33972
+ const report = {};
33973
+ const startedThisTick = /* @__PURE__ */ new Set();
33974
+ for (const [queueKey, serverTurns] of Object.entries(raw)) {
33975
+ if (!Array.isArray(serverTurns)) continue;
33976
+ const file2 = readPersistedQueue(queueKey);
33977
+ if (!file2) continue;
33978
+ if (hasRunningTurn(file2.turns)) continue;
33979
+ const next = pickNextRunnableTurn(file2.turns);
33980
+ if (!next) continue;
33981
+ next.lastClientState = "running";
33982
+ writePersistedQueue(file2);
33983
+ runIdToQueueKey.set(next.turnId, queueKey);
33984
+ startedThisTick.add(next.turnId);
33985
+ report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
33986
+ }
33987
+ if (Object.keys(report).length > 0) {
33988
+ sendPromptQueueClientReport(getWs(), report);
33989
+ }
33990
+ for (const [queueKey, serverTurns] of Object.entries(raw)) {
33991
+ if (!Array.isArray(serverTurns)) continue;
33992
+ const file2 = readPersistedQueue(queueKey);
33993
+ if (!file2) continue;
33994
+ const running = file2.turns.find((t) => t.lastClientState === "running");
33995
+ if (!running || !startedThisTick.has(running.turnId)) continue;
33996
+ if (runIdToQueueKey.get(running.turnId) !== queueKey) continue;
33997
+ dispatchLocalPrompt(running, deps);
33998
+ }
33999
+ }
34000
+ function finalizePromptTurnOnBridge(getWs, runId, success2) {
34001
+ if (!runId) return;
34002
+ const queueKey = runIdToQueueKey.get(runId);
34003
+ runIdToQueueKey.delete(runId);
34004
+ if (!queueKey) return;
34005
+ const f = readPersistedQueue(queueKey);
34006
+ if (!f) return;
34007
+ const t = f.turns.find((x) => x.turnId === runId);
34008
+ if (!t) return;
34009
+ t.lastClientState = success2 ? "stopped" : "failed";
34010
+ writePersistedQueue(f);
34011
+ sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
34012
+ }
33554
34013
 
33555
34014
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
33556
34015
  function createBridgePromptSenders(deps, getWs) {
@@ -33565,6 +34024,9 @@ function createBridgePromptSenders(deps, getWs) {
33565
34024
  const skipEncryptForChangeSummaryFollowUp = result.type === "prompt_result" && result.followUpCatalogPromptId === BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID;
33566
34025
  const encryptedFields = result.type === "prompt_result" && !skipEncryptForChangeSummaryFollowUp ? ["output", "error"] : [];
33567
34026
  sendBridgeMessage(result, encryptedFields);
34027
+ if (result.type === "prompt_result") {
34028
+ finalizePromptTurnOnBridge(getWs, typeof result.runId === "string" ? result.runId : void 0, result.success === true);
34029
+ }
33568
34030
  };
33569
34031
  const sendSessionUpdate = (payload) => {
33570
34032
  const s = getWs();
@@ -33589,63 +34051,6 @@ function createBridgePromptSenders(deps, getWs) {
33589
34051
  // src/agents/acp/from-bridge/bridge-prompt-preamble.ts
33590
34052
  import { execFile as execFile10 } from "node:child_process";
33591
34053
  import { promisify as promisify10 } from "node:util";
33592
-
33593
- // src/git/bridge-queue-key.ts
33594
- import * as path28 from "node:path";
33595
- import { createHash } from "node:crypto";
33596
- function normalizeCanonicalGitUrl(url2) {
33597
- let s = url2.trim();
33598
- if (!s) return s;
33599
- if (s.toLowerCase().endsWith(".git")) {
33600
- s = s.slice(0, -4);
33601
- }
33602
- s = s.replace(/\/+$/, "");
33603
- const httpsMatch = /^(https?):\/\/([^/]+)(\/.*)?$/i.exec(s);
33604
- if (httpsMatch) {
33605
- const host = httpsMatch[2].toLowerCase();
33606
- const p = httpsMatch[3] ?? "";
33607
- s = `${httpsMatch[1].toLowerCase()}://${host}${p}`;
33608
- } else {
33609
- const sshMatch = /^git@([^:]+):(.+)$/i.exec(s);
33610
- if (sshMatch) {
33611
- const host = sshMatch[1].toLowerCase();
33612
- s = `git@${host}:${sshMatch[2]}`;
33613
- }
33614
- }
33615
- return s;
33616
- }
33617
- function canonicalUrlToRepoIdSync(url2) {
33618
- const normalized = normalizeCanonicalGitUrl(url2);
33619
- return createHash("sha256").update(normalized).digest("hex").slice(0, 32);
33620
- }
33621
- function fallbackRepoIdFromPath(absPath) {
33622
- return createHash("sha256").update(path28.resolve(absPath)).digest("hex").slice(0, 32);
33623
- }
33624
- async function resolveBridgeQueueBindFields(options) {
33625
- const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
33626
- const cwdAbs = worktreePaths.length > 0 ? path28.resolve(worktreePaths[0]) : path28.resolve(effectiveCwd);
33627
- if (!primaryRepoRoots.length) {
33628
- log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
33629
- return null;
33630
- }
33631
- let primaryRoot = primaryRepoRoots[0];
33632
- let remote = await getRemoteOriginUrl(primaryRoot);
33633
- if (!remote) {
33634
- for (const r of primaryRepoRoots.slice(1)) {
33635
- const u = await getRemoteOriginUrl(r);
33636
- if (u) {
33637
- primaryRoot = r;
33638
- remote = u;
33639
- break;
33640
- }
33641
- }
33642
- }
33643
- const repoId = remote ? canonicalUrlToRepoIdSync(remote) : fallbackRepoIdFromPath(primaryRoot);
33644
- const canonicalQueueKey = `repo:${repoId}::cwd:${cwdAbs}`;
33645
- return { canonicalQueueKey, repoId, cwdAbs };
33646
- }
33647
-
33648
- // src/agents/acp/from-bridge/bridge-prompt-preamble.ts
33649
34054
  var execFileAsync9 = promisify10(execFile10);
33650
34055
  async function readGitBranch(cwd) {
33651
34056
  try {
@@ -33659,40 +34064,24 @@ async function readGitBranch(cwd) {
33659
34064
  async function runBridgePromptPreamble(params) {
33660
34065
  const { getWs, log: log2, sessionWorktreeManager, sessionId, runId, effectiveCwd } = params;
33661
34066
  const s = getWs();
33662
- const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
34067
+ const repoCheckoutPaths = sessionWorktreeManager.ensureRepoCheckoutPathsForSession(sessionId);
33663
34068
  const repoRoots = await resolveSnapshotRepoRoots({
33664
- worktreePaths,
34069
+ worktreePaths: repoCheckoutPaths,
33665
34070
  fallbackCwd: effectiveCwd,
34071
+ sessionId: sessionId?.trim() || void 0,
33666
34072
  log: log2
33667
34073
  });
33668
- if (s && sessionId) {
33669
- const bind = await resolveBridgeQueueBindFields({
33670
- effectiveCwd,
33671
- worktreePaths,
33672
- primaryRepoRoots: repoRoots,
33673
- log: log2
33674
- });
33675
- if (bind) {
33676
- sendWsMessage(s, {
33677
- type: "bridge_queue_bind",
33678
- sessionId,
33679
- canonicalQueueKey: bind.canonicalQueueKey,
33680
- repoId: bind.repoId,
33681
- cwdAbs: bind.cwdAbs
33682
- });
33683
- }
33684
- }
33685
34074
  if (s && sessionId) {
33686
34075
  const cliGitBranch = await readGitBranch(effectiveCwd);
33687
34076
  const usesWt = sessionWorktreeManager.usesWorktreeSession(sessionId);
33688
- const mirrorAbs = sessionWorktreeManager.getAgentCwdForSession(sessionId);
34077
+ const isolatedSessionParentPath = sessionWorktreeManager.getIsolatedSessionParentPathForSession(sessionId);
33689
34078
  sendWsMessage(s, {
33690
34079
  type: "session_git_context_report",
33691
34080
  sessionId,
33692
34081
  cliGitBranch,
33693
34082
  agentUsesWorktree: usesWt,
33694
34083
  sessionParent: usesWt ? "worktrees_root" : "bridge_root",
33695
- sessionParentPath: usesWt ? mirrorAbs : getBridgeWorkspaceDirectory()
34084
+ sessionParentPath: usesWt ? isolatedSessionParentPath ?? effectiveCwd : getBridgeRoot()
33696
34085
  });
33697
34086
  }
33698
34087
  if (s && sessionId && runId) {
@@ -33845,7 +34234,7 @@ function handleBridgePrompt(msg, deps) {
33845
34234
  const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
33846
34235
  acpManager.logPromptReceivedFromBridge({ agentType, mode });
33847
34236
  async function preambleAndPrompt(resolvedCwd) {
33848
- const effectiveCwd = path29.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
34237
+ const effectiveCwd = resolveSessionParentPathForAgentProcess(resolvedCwd);
33849
34238
  await runBridgePromptPreamble({
33850
34239
  getWs,
33851
34240
  log: log2,
@@ -33878,7 +34267,7 @@ function handleBridgePrompt(msg, deps) {
33878
34267
  runId,
33879
34268
  mode,
33880
34269
  agentType,
33881
- cwd: effectiveCwd,
34270
+ sessionParentPath: effectiveCwd,
33882
34271
  sendResult: sendResult2,
33883
34272
  sendSessionUpdate,
33884
34273
  followUpCatalogPromptId,
@@ -33888,8 +34277,8 @@ function handleBridgePrompt(msg, deps) {
33888
34277
  e2ee: deps.e2ee
33889
34278
  });
33890
34279
  }
33891
- void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionParent, sessionParentPath }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
33892
- log2(`[Agent] Worktree resolve failed: ${err instanceof Error ? err.message : String(err)}`);
34280
+ void sessionWorktreeManager.resolveSessionParentPathForPrompt(sessionId, { isNewSession, sessionParent, sessionParentPath }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
34281
+ log2(`[Agent] Session parent path resolve failed: ${err instanceof Error ? err.message : String(err)}`);
33893
34282
  void preambleAndPrompt(void 0);
33894
34283
  });
33895
34284
  }
@@ -33899,6 +34288,11 @@ var handlePromptMessage = (msg, deps) => {
33899
34288
  handleBridgePrompt(msg, deps);
33900
34289
  };
33901
34290
 
34291
+ // src/bridge/routing/handlers/prompt-queue-state.ts
34292
+ var handlePromptQueueStateMessage = (msg, deps) => {
34293
+ applyPromptQueueStateFromServer(msg, deps);
34294
+ };
34295
+
33902
34296
  // src/agents/acp/from-bridge/handle-bridge-cancel-run.ts
33903
34297
  async function handleBridgeCancelRun(msg, { log: log2, acpManager, getWs }) {
33904
34298
  const runId = msg.runId;
@@ -33918,6 +34312,7 @@ async function handleBridgeCancelRun(msg, { log: log2, acpManager, getWs }) {
33918
34312
  error: "Stopped by user",
33919
34313
  stopReason: "no_local_run"
33920
34314
  });
34315
+ finalizePromptTurnOnBridge(getWs, runId, false);
33921
34316
  }
33922
34317
 
33923
34318
  // src/bridge/routing/handlers/cancel-run.ts
@@ -33961,12 +34356,12 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
33961
34356
  };
33962
34357
 
33963
34358
  // src/files/list-dir.ts
33964
- import fs26 from "node:fs";
34359
+ import fs28 from "node:fs";
33965
34360
  import path31 from "node:path";
33966
34361
 
33967
34362
  // src/files/ensure-under-cwd.ts
33968
34363
  import path30 from "node:path";
33969
- function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
34364
+ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
33970
34365
  const normalized = path30.normalize(relativePath).replace(/^(\.\/)+/, "");
33971
34366
  const resolved = path30.resolve(cwd, normalized);
33972
34367
  if (!resolved.startsWith(cwd + path30.sep) && resolved !== cwd) {
@@ -33978,12 +34373,12 @@ function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
33978
34373
  // src/files/list-dir.ts
33979
34374
  var LIST_DIR_YIELD_EVERY = 256;
33980
34375
  async function listDirAsync(relativePath) {
33981
- const resolved = ensureUnderCwd(relativePath || ".", getBridgeWorkspaceDirectory());
34376
+ const resolved = ensureUnderCwd(relativePath || ".", getBridgeRoot());
33982
34377
  if (!resolved) {
33983
34378
  return { error: "Path is outside working directory" };
33984
34379
  }
33985
34380
  try {
33986
- const names = await fs26.promises.readdir(resolved, { withFileTypes: true });
34381
+ const names = await fs28.promises.readdir(resolved, { withFileTypes: true });
33987
34382
  const visible = names.filter((d) => !d.name.startsWith("."));
33988
34383
  const entries = [];
33989
34384
  for (let i = 0; i < visible.length; i++) {
@@ -33996,7 +34391,7 @@ async function listDirAsync(relativePath) {
33996
34391
  let isDir = d.isDirectory();
33997
34392
  if (d.isSymbolicLink()) {
33998
34393
  try {
33999
- const targetStat = await fs26.promises.stat(fullPath);
34394
+ const targetStat = await fs28.promises.stat(fullPath);
34000
34395
  isDir = targetStat.isDirectory();
34001
34396
  } catch {
34002
34397
  isDir = false;
@@ -34021,25 +34416,25 @@ async function listDirAsync(relativePath) {
34021
34416
  }
34022
34417
 
34023
34418
  // src/files/read-file.ts
34024
- import fs27 from "node:fs";
34419
+ import fs29 from "node:fs";
34025
34420
  import { StringDecoder } from "node:string_decoder";
34026
34421
  function resolveFilePath(relativePath) {
34027
- const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
34422
+ const resolved = ensureUnderCwd(relativePath, getBridgeRoot());
34028
34423
  if (!resolved) return { error: "Path is outside working directory" };
34029
34424
  let real;
34030
34425
  try {
34031
- real = fs27.realpathSync(resolved);
34426
+ real = fs29.realpathSync(resolved);
34032
34427
  } catch {
34033
34428
  real = resolved;
34034
34429
  }
34035
- const stat2 = fs27.statSync(real);
34430
+ const stat2 = fs29.statSync(real);
34036
34431
  if (!stat2.isFile()) return { error: "Not a file" };
34037
34432
  return real;
34038
34433
  }
34039
34434
  var LINE_CHUNK_SIZE = 64 * 1024;
34040
34435
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
34041
- const fileSize = fs27.statSync(filePath).size;
34042
- const fd = fs27.openSync(filePath, "r");
34436
+ const fileSize = fs29.statSync(filePath).size;
34437
+ const fd = fs29.openSync(filePath, "r");
34043
34438
  const bufSize = 64 * 1024;
34044
34439
  const buf = Buffer.alloc(bufSize);
34045
34440
  const decoder = new StringDecoder("utf8");
@@ -34052,7 +34447,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
34052
34447
  let line0Accum = "";
34053
34448
  try {
34054
34449
  let bytesRead;
34055
- while (!done && (bytesRead = fs27.readSync(fd, buf, 0, bufSize, null)) > 0) {
34450
+ while (!done && (bytesRead = fs29.readSync(fd, buf, 0, bufSize, null)) > 0) {
34056
34451
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
34057
34452
  partial2 = "";
34058
34453
  let lineStart = 0;
@@ -34187,7 +34582,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
34187
34582
  }
34188
34583
  return { content: resultLines.join("\n"), size: fileSize };
34189
34584
  } finally {
34190
- fs27.closeSync(fd);
34585
+ fs29.closeSync(fd);
34191
34586
  }
34192
34587
  }
34193
34588
  function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
@@ -34198,8 +34593,8 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
34198
34593
  if (hasRange) {
34199
34594
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
34200
34595
  }
34201
- const stat2 = fs27.statSync(result);
34202
- const raw = fs27.readFileSync(result, "utf8");
34596
+ const stat2 = fs29.statSync(result);
34597
+ const raw = fs29.readFileSync(result, "utf8");
34203
34598
  const lines = raw.split(/\r?\n/);
34204
34599
  return { content: raw, totalLines: lines.length, size: stat2.size };
34205
34600
  } catch (err) {
@@ -34217,7 +34612,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
34217
34612
  void (async () => {
34218
34613
  await yieldToEventLoop();
34219
34614
  const q = typeof msg.q === "string" ? msg.q : "";
34220
- const cwd = getBridgeWorkspaceDirectory();
34615
+ const cwd = getBridgeRoot();
34221
34616
  const index = loadFileIndex(cwd);
34222
34617
  if (index === null) {
34223
34618
  const payload2 = {
@@ -34241,7 +34636,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
34241
34636
  }
34242
34637
  function triggerFileIndexBuild() {
34243
34638
  setImmediate(() => {
34244
- void ensureFileIndexAsync(getBridgeWorkspaceDirectory()).catch((e) => {
34639
+ void ensureFileIndexAsync(getBridgeRoot()).catch((e) => {
34245
34640
  console.error("[file-index] Background build failed:", e);
34246
34641
  });
34247
34642
  });
@@ -34310,14 +34705,14 @@ function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
34310
34705
  function handleSkillLayoutRequest(msg, deps) {
34311
34706
  const socket = deps.getWs();
34312
34707
  const id = typeof msg.id === "string" ? msg.id : "";
34313
- const roots = discoverSkillLayoutRoots(getBridgeWorkspaceDirectory());
34708
+ const roots = discoverSkillLayoutRoots(getBridgeRoot());
34314
34709
  if (socket) {
34315
34710
  sendWsMessage(socket, { type: "skill_layout_response", id, roots });
34316
34711
  }
34317
34712
  }
34318
34713
 
34319
34714
  // src/skills/install-remote-skills.ts
34320
- import fs28 from "node:fs";
34715
+ import fs30 from "node:fs";
34321
34716
  import path32 from "node:path";
34322
34717
  function installRemoteSkills(cwd, targetDir, items) {
34323
34718
  const installed2 = [];
@@ -34333,11 +34728,11 @@ function installRemoteSkills(cwd, targetDir, items) {
34333
34728
  for (const f of item.files) {
34334
34729
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
34335
34730
  const dest = path32.join(skillDir, f.path);
34336
- fs28.mkdirSync(path32.dirname(dest), { recursive: true });
34731
+ fs30.mkdirSync(path32.dirname(dest), { recursive: true });
34337
34732
  if (f.text !== void 0) {
34338
- fs28.writeFileSync(dest, f.text, "utf8");
34733
+ fs30.writeFileSync(dest, f.text, "utf8");
34339
34734
  } else if (f.base64) {
34340
- fs28.writeFileSync(dest, Buffer.from(f.base64, "base64"));
34735
+ fs30.writeFileSync(dest, Buffer.from(f.base64, "base64"));
34341
34736
  }
34342
34737
  }
34343
34738
  installed2.push({
@@ -34358,7 +34753,7 @@ var handleInstallSkillsMessage = (msg, deps) => {
34358
34753
  const id = typeof msg.id === "string" ? msg.id : "";
34359
34754
  const targetDir = typeof msg.targetDir === "string" && msg.targetDir.trim() ? msg.targetDir.trim() : ".agents/skills";
34360
34755
  const rawItems = msg.items;
34361
- const cwd = getBridgeWorkspaceDirectory();
34756
+ const cwd = getBridgeRoot();
34362
34757
  const result = installRemoteSkills(cwd, targetDir, rawItems);
34363
34758
  if (!result.success) {
34364
34759
  const err = result.error ?? "Invalid items";
@@ -34487,7 +34882,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
34487
34882
  };
34488
34883
 
34489
34884
  // src/bridge/routing/handlers/revert-turn-snapshot.ts
34490
- import * as fs29 from "node:fs";
34885
+ import * as fs31 from "node:fs";
34491
34886
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
34492
34887
  const id = typeof msg.id === "string" ? msg.id : "";
34493
34888
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -34497,9 +34892,9 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
34497
34892
  void (async () => {
34498
34893
  const s = getWs();
34499
34894
  if (!s) return;
34500
- const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
34895
+ const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
34501
34896
  const file2 = snapshotFilePath(agentBase, turnId);
34502
- if (!fs29.existsSync(file2)) {
34897
+ if (!fs31.existsSync(file2)) {
34503
34898
  sendWsMessage(s, {
34504
34899
  type: "revert_turn_snapshot_result",
34505
34900
  id,
@@ -34557,6 +34952,9 @@ function dispatchBridgeMessage(msg, deps) {
34557
34952
  case "agent_config":
34558
34953
  handleAgentConfigMessage(msg, deps);
34559
34954
  break;
34955
+ case "prompt_queue_state":
34956
+ handlePromptQueueStateMessage(msg, deps);
34957
+ break;
34560
34958
  case "prompt":
34561
34959
  handlePromptMessage(msg, deps);
34562
34960
  break;
@@ -34854,9 +35252,9 @@ async function createBridgeConnection(options) {
34854
35252
  firehoseGeneration: 0,
34855
35253
  firehoseQuiet: createEmptyReconnectQuietSlot()
34856
35254
  };
34857
- const worktreesRootAbs = options.worktreesRootAbs ?? defaultWorktreesRootAbs();
35255
+ const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
34858
35256
  const sessionWorktreeManager = new SessionWorktreeManager({
34859
- worktreesRootAbs,
35257
+ worktreesRootPath,
34860
35258
  log: logFn
34861
35259
  });
34862
35260
  const acpManager = await createAcpManager({ log: logFn });
@@ -34865,7 +35263,7 @@ async function createBridgeConnection(options) {
34865
35263
  return state.currentWs;
34866
35264
  }
34867
35265
  const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
34868
- const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory, e2ee });
35266
+ const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
34869
35267
  const onBridgeIdentified = createOnBridgeIdentified({
34870
35268
  devServerManager,
34871
35269
  firehoseServerUrl,
@@ -34889,8 +35287,8 @@ async function createBridgeConnection(options) {
34889
35287
  getCloudAccessToken: () => tokens.accessToken
34890
35288
  };
34891
35289
  const identifyReportedPaths = {
34892
- bridgeRootPath: path33.resolve(getBridgeWorkspaceDirectory()),
34893
- worktreesRootPath: path33.resolve(worktreesRootAbs)
35290
+ bridgeRootPath: path33.resolve(getBridgeRoot()),
35291
+ worktreesRootPath: path33.resolve(worktreesRootPath)
34894
35292
  };
34895
35293
  const { connect } = createMainBridgeWebSocketLifecycle({
34896
35294
  state,
@@ -34907,7 +35305,7 @@ async function createBridgeConnection(options) {
34907
35305
  identifyReportedPaths
34908
35306
  });
34909
35307
  connect();
34910
- const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
35308
+ const stopFileIndexWatcher = startFileIndexWatcher(getBridgeRoot());
34911
35309
  return {
34912
35310
  close: async () => {
34913
35311
  stopFileIndexWatcher();
@@ -34977,7 +35375,7 @@ async function runConnectedBridge(options, restartWithoutAuth) {
34977
35375
  authToken,
34978
35376
  refreshToken,
34979
35377
  justAuthenticated,
34980
- worktreesRootAbs,
35378
+ worktreesRootPath,
34981
35379
  e2eCertificate
34982
35380
  } = options;
34983
35381
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
@@ -34989,7 +35387,7 @@ async function runConnectedBridge(options, restartWithoutAuth) {
34989
35387
  refreshToken,
34990
35388
  firehoseServerUrl,
34991
35389
  justAuthenticated,
34992
- worktreesRootAbs,
35390
+ worktreesRootPath,
34993
35391
  e2eCertificate,
34994
35392
  log,
34995
35393
  persistTokens: (t) => {
@@ -35004,7 +35402,7 @@ async function runConnectedBridge(options, restartWithoutAuth) {
35004
35402
  log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
35005
35403
  clearConfigForApi(apiUrl);
35006
35404
  void handle.close().then(() => {
35007
- void restartWithoutAuth({ apiUrl, firehoseServerUrl, worktreesRootAbs, e2eCertificate });
35405
+ void restartWithoutAuth({ apiUrl, firehoseServerUrl, worktreesRootPath, e2eCertificate });
35008
35406
  });
35009
35407
  }
35010
35408
  });
@@ -35052,7 +35450,7 @@ async function runBridge(options) {
35052
35450
  workspaceId,
35053
35451
  authToken,
35054
35452
  bridgeName,
35055
- worktreesRootAbs,
35453
+ worktreesRootPath,
35056
35454
  e2eCertificate
35057
35455
  } = options;
35058
35456
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
@@ -35097,7 +35495,7 @@ async function runBridge(options) {
35097
35495
  firehoseServerUrl,
35098
35496
  bridgeName,
35099
35497
  justAuthenticated: true,
35100
- worktreesRootAbs,
35498
+ worktreesRootPath,
35101
35499
  e2eCertificate
35102
35500
  });
35103
35501
  return;