@buildautomaton/cli 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -971,17 +971,17 @@ var require_suggestSimilar = __commonJS({
971
971
  // ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js
972
972
  var require_command = __commonJS({
973
973
  "../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
974
- var EventEmitter3 = __require("node:events").EventEmitter;
974
+ var EventEmitter2 = __require("node:events").EventEmitter;
975
975
  var childProcess = __require("node:child_process");
976
976
  var path25 = __require("node:path");
977
- var fs21 = __require("node:fs");
977
+ var fs22 = __require("node:fs");
978
978
  var process2 = __require("node:process");
979
979
  var { Argument: Argument2, humanReadableArgName } = require_argument();
980
980
  var { CommanderError: CommanderError2 } = require_error();
981
981
  var { Help: Help2 } = require_help();
982
982
  var { Option: Option2, DualOptions } = require_option();
983
983
  var { suggestSimilar } = require_suggestSimilar();
984
- var Command2 = class _Command extends EventEmitter3 {
984
+ var Command2 = class _Command extends EventEmitter2 {
985
985
  /**
986
986
  * Initialize a new `Command`.
987
987
  *
@@ -1907,10 +1907,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
1907
1907
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1908
1908
  function findFile(baseDir, baseName) {
1909
1909
  const localBin = path25.resolve(baseDir, baseName);
1910
- if (fs21.existsSync(localBin)) return localBin;
1910
+ if (fs22.existsSync(localBin)) return localBin;
1911
1911
  if (sourceExt.includes(path25.extname(baseName))) return void 0;
1912
1912
  const foundExt = sourceExt.find(
1913
- (ext) => fs21.existsSync(`${localBin}${ext}`)
1913
+ (ext) => fs22.existsSync(`${localBin}${ext}`)
1914
1914
  );
1915
1915
  if (foundExt) return `${localBin}${foundExt}`;
1916
1916
  return void 0;
@@ -1922,7 +1922,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1922
1922
  if (this._scriptPath) {
1923
1923
  let resolvedScriptPath;
1924
1924
  try {
1925
- resolvedScriptPath = fs21.realpathSync(this._scriptPath);
1925
+ resolvedScriptPath = fs22.realpathSync(this._scriptPath);
1926
1926
  } catch (err) {
1927
1927
  resolvedScriptPath = this._scriptPath;
1928
1928
  }
@@ -5231,13 +5231,13 @@ var require_extension = __commonJS({
5231
5231
  var require_websocket = __commonJS({
5232
5232
  "../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js"(exports, module) {
5233
5233
  "use strict";
5234
- var EventEmitter3 = __require("events");
5234
+ var EventEmitter2 = __require("events");
5235
5235
  var https3 = __require("https");
5236
5236
  var http = __require("http");
5237
5237
  var net = __require("net");
5238
5238
  var tls = __require("tls");
5239
5239
  var { randomBytes, createHash: createHash2 } = __require("crypto");
5240
- var { Duplex, Readable: Readable3 } = __require("stream");
5240
+ var { Duplex, Readable: Readable2 } = __require("stream");
5241
5241
  var { URL: URL2 } = __require("url");
5242
5242
  var PerMessageDeflate = require_permessage_deflate();
5243
5243
  var Receiver2 = require_receiver();
@@ -5263,7 +5263,7 @@ var require_websocket = __commonJS({
5263
5263
  var protocolVersions = [8, 13];
5264
5264
  var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
5265
5265
  var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
5266
- var WebSocket2 = class _WebSocket extends EventEmitter3 {
5266
+ var WebSocket2 = class _WebSocket extends EventEmitter2 {
5267
5267
  /**
5268
5268
  * Create a new `WebSocket`.
5269
5269
  *
@@ -6175,7 +6175,7 @@ var require_stream = __commonJS({
6175
6175
  };
6176
6176
  duplex._final = function(callback) {
6177
6177
  if (ws.readyState === ws.CONNECTING) {
6178
- ws.once("open", function open2() {
6178
+ ws.once("open", function open() {
6179
6179
  duplex._final(callback);
6180
6180
  });
6181
6181
  return;
@@ -6196,7 +6196,7 @@ var require_stream = __commonJS({
6196
6196
  };
6197
6197
  duplex._write = function(chunk, encoding, callback) {
6198
6198
  if (ws.readyState === ws.CONNECTING) {
6199
- ws.once("open", function open2() {
6199
+ ws.once("open", function open() {
6200
6200
  duplex._write(chunk, encoding, callback);
6201
6201
  });
6202
6202
  return;
@@ -6260,7 +6260,7 @@ var require_subprotocol = __commonJS({
6260
6260
  var require_websocket_server = __commonJS({
6261
6261
  "../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
6262
6262
  "use strict";
6263
- var EventEmitter3 = __require("events");
6263
+ var EventEmitter2 = __require("events");
6264
6264
  var http = __require("http");
6265
6265
  var { Duplex } = __require("stream");
6266
6266
  var { createHash: createHash2 } = __require("crypto");
@@ -6273,7 +6273,7 @@ var require_websocket_server = __commonJS({
6273
6273
  var RUNNING = 0;
6274
6274
  var CLOSING = 1;
6275
6275
  var CLOSED = 2;
6276
- var WebSocketServer2 = class extends EventEmitter3 {
6276
+ var WebSocketServer2 = class extends EventEmitter2 {
6277
6277
  /**
6278
6278
  * Create a `WebSocketServer` instance.
6279
6279
  *
@@ -7426,12 +7426,12 @@ var require_src2 = __commonJS({
7426
7426
  function check2(path25, isFile, isDirectory) {
7427
7427
  log2(`checking %s`, path25);
7428
7428
  try {
7429
- const stat4 = fs_1.statSync(path25);
7430
- if (stat4.isFile() && isFile) {
7429
+ const stat = fs_1.statSync(path25);
7430
+ if (stat.isFile() && isFile) {
7431
7431
  log2(`[OK] path represents a file`);
7432
7432
  return true;
7433
7433
  }
7434
- if (stat4.isDirectory() && isDirectory) {
7434
+ if (stat.isDirectory() && isDirectory) {
7435
7435
  log2(`[OK] path represents a directory`);
7436
7436
  return true;
7437
7437
  }
@@ -24800,8 +24800,8 @@ var init_acp = __esm({
24800
24800
  this.#requestHandler = requestHandler;
24801
24801
  this.#notificationHandler = notificationHandler;
24802
24802
  this.#stream = stream;
24803
- this.#closedPromise = new Promise((resolve17) => {
24804
- this.#abortController.signal.addEventListener("abort", () => resolve17());
24803
+ this.#closedPromise = new Promise((resolve15) => {
24804
+ this.#abortController.signal.addEventListener("abort", () => resolve15());
24805
24805
  });
24806
24806
  this.#receive();
24807
24807
  }
@@ -24950,8 +24950,8 @@ var init_acp = __esm({
24950
24950
  }
24951
24951
  async sendRequest(method, params) {
24952
24952
  const id = this.#nextRequestId++;
24953
- const responsePromise = new Promise((resolve17, reject) => {
24954
- this.#pendingResponses.set(id, { resolve: resolve17, reject });
24953
+ const responsePromise = new Promise((resolve15, reject) => {
24954
+ this.#pendingResponses.set(id, { resolve: resolve15, reject });
24955
24955
  });
24956
24956
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
24957
24957
  return responsePromise;
@@ -25047,7 +25047,7 @@ var init_acp = __esm({
25047
25047
  });
25048
25048
 
25049
25049
  // src/cli.ts
25050
- import * as fs20 from "node:fs";
25050
+ import * as fs21 from "node:fs";
25051
25051
  import * as path24 from "node:path";
25052
25052
 
25053
25053
  // ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
@@ -25118,7 +25118,7 @@ function writeConfigForApi(apiUrl, auth) {
25118
25118
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
25119
25119
  fs.writeFileSync(p, JSON.stringify(next, null, 2), "utf8");
25120
25120
  } catch (e) {
25121
- console.error("Could not save auth config:", e);
25121
+ console.error("Could not save authentication config:", e);
25122
25122
  }
25123
25123
  }
25124
25124
  function clearConfigForApi(apiUrl) {
@@ -25145,6 +25145,19 @@ function clearConfigForApi(apiUrl) {
25145
25145
  }
25146
25146
  }
25147
25147
 
25148
+ // src/files/cwd/bridge-workspace-directory.ts
25149
+ import * as path2 from "node:path";
25150
+ var bridgeWorkspaceDirectory = null;
25151
+ function initBridgeWorkspaceDirectory() {
25152
+ bridgeWorkspaceDirectory = path2.resolve(process.cwd());
25153
+ }
25154
+ function getBridgeWorkspaceDirectory() {
25155
+ if (bridgeWorkspaceDirectory == null) {
25156
+ bridgeWorkspaceDirectory = path2.resolve(process.cwd());
25157
+ }
25158
+ return bridgeWorkspaceDirectory;
25159
+ }
25160
+
25148
25161
  // src/log.ts
25149
25162
  function log(line) {
25150
25163
  const time3 = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
@@ -25156,9 +25169,6 @@ function logImmediate(line) {
25156
25169
  `);
25157
25170
  }
25158
25171
 
25159
- // src/bridge/connection/create-ws-bridge.ts
25160
- import https from "node:https";
25161
-
25162
25172
  // ../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
25163
25173
  var import_stream = __toESM(require_stream(), 1);
25164
25174
  var import_receiver = __toESM(require_receiver(), 1);
@@ -25168,15 +25178,23 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
25168
25178
  var wrapper_default = import_websocket.default;
25169
25179
 
25170
25180
  // src/bridge/connection/create-ws-bridge.ts
25181
+ import https from "node:https";
25171
25182
  var BRIDGE_AUTH_ERROR_HEADER = "x-bridge-auth-error";
25172
25183
  var BRIDGE_AUTH_ERROR_TOKEN_INVALID = "token_invalid";
25173
25184
  function createWsBridge(options) {
25174
- const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid } = options;
25185
+ const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid, clientPingIntervalMs } = options;
25175
25186
  const wsOptions = {};
25176
25187
  if (url2.startsWith("wss://")) {
25177
25188
  wsOptions.agent = new https.Agent({ rejectUnauthorized: false });
25178
25189
  }
25179
25190
  const ws = new wrapper_default(url2, wsOptions);
25191
+ let clientPingTimer = null;
25192
+ function clearClientPing() {
25193
+ if (clientPingTimer != null) {
25194
+ clearInterval(clientPingTimer);
25195
+ clientPingTimer = null;
25196
+ }
25197
+ }
25180
25198
  ws.on("unexpected-response", (request, response) => {
25181
25199
  const status = response?.statusCode ?? 0;
25182
25200
  const headers = response?.headers ?? {};
@@ -25186,6 +25204,17 @@ function createWsBridge(options) {
25186
25204
  }
25187
25205
  });
25188
25206
  ws.on("open", () => {
25207
+ clearClientPing();
25208
+ if (clientPingIntervalMs != null && clientPingIntervalMs > 0) {
25209
+ clientPingTimer = setInterval(() => {
25210
+ if (ws.readyState === wrapper_default.OPEN) {
25211
+ try {
25212
+ ws.ping();
25213
+ } catch {
25214
+ }
25215
+ }
25216
+ }, clientPingIntervalMs);
25217
+ }
25189
25218
  onOpen?.();
25190
25219
  });
25191
25220
  ws.on("message", (raw) => {
@@ -25205,9 +25234,11 @@ function createWsBridge(options) {
25205
25234
  }
25206
25235
  });
25207
25236
  ws.on("close", (code, reason) => {
25237
+ clearClientPing();
25208
25238
  onClose?.(code, reason.toString());
25209
25239
  });
25210
25240
  ws.on("error", (err) => {
25241
+ clearClientPing();
25211
25242
  onError2?.(err);
25212
25243
  });
25213
25244
  return ws;
@@ -25253,6 +25284,28 @@ function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiU
25253
25284
  }
25254
25285
  }
25255
25286
 
25287
+ // src/bridge/connection/reconnect/constants.ts
25288
+ var RECONNECT_FIRST_MS = 100;
25289
+ var RECONNECT_MAX_MS = 3e4;
25290
+ var RECONNECT_QUIET_MS = 2e3;
25291
+ function reconnectDelayMs(attemptBeforeIncrement) {
25292
+ return Math.min(RECONNECT_FIRST_MS * 2 ** attemptBeforeIncrement, RECONNECT_MAX_MS);
25293
+ }
25294
+
25295
+ // src/bridge/connection/reconnect/format-reconnect-delay-for-log.ts
25296
+ function formatReconnectDelayForLog(delayMs) {
25297
+ if (delayMs < 1e3) return `${delayMs}ms`;
25298
+ const s = delayMs / 1e3;
25299
+ return Number.isInteger(s) ? `${s}s` : `${s.toFixed(1)}s`;
25300
+ }
25301
+
25302
+ // src/bridge/connection/reconnect/log-next-reconnect-attempt.ts
25303
+ function logNextReconnectAttempt(log2, serviceLabel, quiet, delayMs, attempt) {
25304
+ if (!quiet.verboseLogs) return;
25305
+ const delayLabel = formatReconnectDelayForLog(delayMs);
25306
+ log2(`${serviceLabel} Next connection attempt in ${delayLabel} (attempt ${attempt}).`);
25307
+ }
25308
+
25256
25309
  // src/bridge/connection/ws-close-diagnostics.ts
25257
25310
  function describeWebSocketCloseCode(code) {
25258
25311
  const known = {
@@ -25281,11 +25334,122 @@ function formatWebSocketClose(label, code, reason, extra) {
25281
25334
  const r = reason.trim();
25282
25335
  const reasonPart = r ? ` reason="${r}"` : "";
25283
25336
  const extraPart = extra ? ` ${extra}` : "";
25284
- return `${label} closed: code=${code} (${describeWebSocketCloseCode(code)})${reasonPart}${extraPart}`;
25337
+ return `${label} Disconnected: code=${code} (${describeWebSocketCloseCode(code)})${reasonPart}${extraPart}`;
25338
+ }
25339
+
25340
+ // src/bridge/connection/reconnect/reconnect-quiet-slot.ts
25341
+ function createEmptyReconnectQuietSlot() {
25342
+ return { timer: null, verboseLogs: false, pendingCloseLog: null };
25343
+ }
25344
+ function clearReconnectQuietTimer(quiet) {
25345
+ if (quiet.timer != null) {
25346
+ clearTimeout(quiet.timer);
25347
+ quiet.timer = null;
25348
+ }
25349
+ }
25350
+ function clearReconnectQuietOnSuccessfulConnection(quiet, log2, reconnectedMessage) {
25351
+ clearReconnectQuietTimer(quiet);
25352
+ quiet.pendingCloseLog = null;
25353
+ if (quiet.verboseLogs) {
25354
+ log2(reconnectedMessage);
25355
+ quiet.verboseLogs = false;
25356
+ }
25357
+ }
25358
+ function beginDeferredDisconnectForReconnect(options) {
25359
+ const {
25360
+ isClosedByUser,
25361
+ quiet,
25362
+ code,
25363
+ reason,
25364
+ willReconnect,
25365
+ log: log2,
25366
+ serviceLabel,
25367
+ shutdownDetail,
25368
+ reconnectingDetail,
25369
+ quietMs = RECONNECT_QUIET_MS,
25370
+ shouldAbortQuietWindow
25371
+ } = options;
25372
+ if (!willReconnect) {
25373
+ log2(formatWebSocketClose(serviceLabel, code, reason, shutdownDetail));
25374
+ return;
25375
+ }
25376
+ quiet.pendingCloseLog = { code, reason };
25377
+ if (quiet.timer == null) {
25378
+ quiet.timer = setTimeout(() => {
25379
+ quiet.timer = null;
25380
+ if (isClosedByUser()) return;
25381
+ if (shouldAbortQuietWindow()) return;
25382
+ if (quiet.pendingCloseLog) {
25383
+ const { code: c, reason: r } = quiet.pendingCloseLog;
25384
+ quiet.pendingCloseLog = null;
25385
+ log2(formatWebSocketClose(serviceLabel, c, r, reconnectingDetail));
25386
+ }
25387
+ quiet.verboseLogs = true;
25388
+ }, quietMs);
25389
+ }
25390
+ }
25391
+
25392
+ // src/bridge/connection/reconnect/bridge-main-reconnect.ts
25393
+ function beginMainBridgeDeferredDisconnect(state, code, reason, log2, willReconnect) {
25394
+ beginDeferredDisconnectForReconnect({
25395
+ isClosedByUser: () => state.closedByUser,
25396
+ quiet: state.mainQuiet,
25397
+ code,
25398
+ reason,
25399
+ willReconnect,
25400
+ log: log2,
25401
+ serviceLabel: "[Bridge service]",
25402
+ shutdownDetail: "Not reconnecting (shutting down).",
25403
+ reconnectingDetail: "Reconnecting\u2026",
25404
+ shouldAbortQuietWindow: () => {
25405
+ const w = state.currentWs;
25406
+ return w != null && w.readyState === wrapper_default.OPEN;
25407
+ }
25408
+ });
25409
+ }
25410
+ function clearMainBridgeReconnectQuietOnOpen(state, log2) {
25411
+ clearReconnectQuietOnSuccessfulConnection(state.mainQuiet, log2, "[Bridge service] Reconnected.");
25412
+ }
25413
+ function scheduleMainBridgeReconnect(state, connect, log2) {
25414
+ if (state.closedByUser || state.currentWs != null) return;
25415
+ const delay2 = reconnectDelayMs(state.reconnectAttempt);
25416
+ state.reconnectAttempt += 1;
25417
+ logNextReconnectAttempt(log2, "[Bridge service]", state.mainQuiet, delay2, state.reconnectAttempt);
25418
+ state.reconnectTimeout = setTimeout(() => {
25419
+ state.reconnectTimeout = null;
25420
+ connect();
25421
+ }, delay2);
25422
+ }
25423
+
25424
+ // src/bridge/connection/reconnect/firehose-reconnect.ts
25425
+ var PROXY_AND_LOG_SERVICE_LABEL = "[Proxy and log service]";
25426
+ function beginFirehoseDeferredDisconnect(ctx, code, reason, log2) {
25427
+ beginDeferredDisconnectForReconnect({
25428
+ isClosedByUser: () => ctx.closedByUser,
25429
+ quiet: ctx.firehoseQuiet,
25430
+ code,
25431
+ reason,
25432
+ willReconnect: true,
25433
+ log: log2,
25434
+ serviceLabel: PROXY_AND_LOG_SERVICE_LABEL,
25435
+ shutdownDetail: "Not reconnecting (shutting down).",
25436
+ reconnectingDetail: "Reconnecting\u2026",
25437
+ shouldAbortQuietWindow: () => {
25438
+ const w = ctx.currentWs;
25439
+ if (!w || w.readyState !== wrapper_default.OPEN) return true;
25440
+ return ctx.firehoseHandle?.isConnected() ?? false;
25441
+ }
25442
+ });
25443
+ }
25444
+ function clearFirehoseReconnectQuietOnOpen(ctx, log2) {
25445
+ clearReconnectQuietOnSuccessfulConnection(
25446
+ ctx.firehoseQuiet,
25447
+ log2,
25448
+ `${PROXY_AND_LOG_SERVICE_LABEL} Reconnected.`
25449
+ );
25285
25450
  }
25286
25451
 
25287
25452
  // src/auth/run-pending-auth.ts
25288
- var PENDING_RECONNECT_MS = 2e3;
25289
25453
  var PENDING_KEEPALIVE_MS = 25e3;
25290
25454
  var BROWSER_OPEN_FALLBACK_MS = 4e3;
25291
25455
  function buildPendingBridgeUrl(apiUrl, connectionId) {
@@ -25304,10 +25468,35 @@ function runPendingAuth(options) {
25304
25468
  let hasOpenedBrowser = false;
25305
25469
  let resolved = false;
25306
25470
  let resolveAuth;
25307
- const authPromise = new Promise((resolve17) => {
25308
- resolveAuth = resolve17;
25471
+ const authPromise = new Promise((resolve15) => {
25472
+ resolveAuth = resolve15;
25309
25473
  });
25474
+ let reconnectAttempt = 0;
25475
+ const signInQuiet = createEmptyReconnectQuietSlot();
25476
+ function clearQuietOnOpen() {
25477
+ clearReconnectQuietOnSuccessfulConnection(
25478
+ signInQuiet,
25479
+ logFn,
25480
+ "[Bridge service] Sign-in connection restored."
25481
+ );
25482
+ reconnectAttempt = 0;
25483
+ }
25484
+ function beginDeferredPendingCloseLog(code, reason) {
25485
+ beginDeferredDisconnectForReconnect({
25486
+ isClosedByUser: () => resolved,
25487
+ quiet: signInQuiet,
25488
+ code,
25489
+ reason,
25490
+ willReconnect: true,
25491
+ log: logFn,
25492
+ serviceLabel: "[Bridge service]",
25493
+ shutdownDetail: "Not reconnecting (shutting down).",
25494
+ reconnectingDetail: "Waiting for browser sign-in; reconnecting\u2026",
25495
+ shouldAbortQuietWindow: () => ws != null && ws.readyState === wrapper_default.OPEN
25496
+ });
25497
+ }
25310
25498
  function cleanup() {
25499
+ clearReconnectQuietTimer(signInQuiet);
25311
25500
  if (reconnectTimeout) {
25312
25501
  clearTimeout(reconnectTimeout);
25313
25502
  reconnectTimeout = null;
@@ -25331,6 +25520,7 @@ function runPendingAuth(options) {
25331
25520
  ws = createWsBridge({
25332
25521
  url: url2,
25333
25522
  onOpen: () => {
25523
+ clearQuietOnOpen();
25334
25524
  sendWsMessage(ws, { type: "identify", role: "cli" });
25335
25525
  keepaliveInterval = setInterval(() => {
25336
25526
  if (resolved || !ws || ws.readyState !== 1) return;
@@ -25351,15 +25541,21 @@ function runPendingAuth(options) {
25351
25541
  keepaliveInterval = null;
25352
25542
  }
25353
25543
  if (resolved) return;
25354
- logFn(
25355
- formatWebSocketClose("[Bridge service]", code, reason, "pending sign-in; will reconnect in 2s")
25356
- );
25544
+ beginDeferredPendingCloseLog(code, reason);
25545
+ const delay2 = reconnectDelayMs(reconnectAttempt);
25546
+ reconnectAttempt += 1;
25547
+ if (signInQuiet.verboseLogs) {
25548
+ const delayLabel = formatReconnectDelayForLog(delay2);
25549
+ logFn(
25550
+ `[Bridge service] Next sign-in connection attempt in ${delayLabel} (attempt ${reconnectAttempt}).`
25551
+ );
25552
+ }
25357
25553
  reconnectTimeout = setTimeout(() => {
25358
25554
  reconnectTimeout = null;
25359
25555
  connect();
25360
- }, PENDING_RECONNECT_MS);
25556
+ }, delay2);
25361
25557
  },
25362
- onError: (err) => logFn(`[Bridge service] WebSocket error (pending sign-in): ${err.message}`),
25558
+ onError: (err) => logFn(`[Bridge service] WebSocket error while waiting for sign-in: ${err.message}`),
25363
25559
  onMessage: (data) => {
25364
25560
  const msg = data;
25365
25561
  if (msg.type === "auth_token" && typeof msg.token === "string") {
@@ -25400,7 +25596,7 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
25400
25596
 
25401
25597
  // src/git/discover-repos.ts
25402
25598
  import * as fs2 from "node:fs";
25403
- import * as path2 from "node:path";
25599
+ import * as path3 from "node:path";
25404
25600
 
25405
25601
  // ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
25406
25602
  var import_file_exists = __toESM(require_dist(), 1);
@@ -26662,8 +26858,8 @@ var init_git_executor_chain = __esm2({
26662
26858
  get cwd() {
26663
26859
  return this._cwd || this._executor.cwd;
26664
26860
  }
26665
- set cwd(cwd3) {
26666
- this._cwd = cwd3;
26861
+ set cwd(cwd) {
26862
+ this._cwd = cwd;
26667
26863
  }
26668
26864
  get env() {
26669
26865
  return this._executor.env;
@@ -26854,8 +27050,8 @@ var init_git_executor = __esm2({
26854
27050
  "use strict";
26855
27051
  init_git_executor_chain();
26856
27052
  GitExecutor = class {
26857
- constructor(cwd3, _scheduler, _plugins) {
26858
- this.cwd = cwd3;
27053
+ constructor(cwd, _scheduler, _plugins) {
27054
+ this.cwd = cwd;
26859
27055
  this._scheduler = _scheduler;
26860
27056
  this._plugins = _plugins;
26861
27057
  this._chain = new GitExecutorChain(this, this._scheduler, this._plugins);
@@ -29985,9 +30181,9 @@ async function isGitRepoDirectory(dirPath) {
29985
30181
  }
29986
30182
 
29987
30183
  // src/git/discover-repos.ts
29988
- async function discoverGitRepos(cwd3 = process.cwd()) {
30184
+ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
29989
30185
  const result = [];
29990
- const cwdResolved = path2.resolve(cwd3);
30186
+ const cwdResolved = path3.resolve(cwd);
29991
30187
  if (await isGitRepoDirectory(cwdResolved)) {
29992
30188
  const remoteUrl = await getRemoteOriginUrl(cwdResolved);
29993
30189
  result.push({ absolutePath: cwdResolved, remoteUrl });
@@ -30000,7 +30196,7 @@ async function discoverGitRepos(cwd3 = process.cwd()) {
30000
30196
  }
30001
30197
  for (const ent of entries) {
30002
30198
  if (!ent.isDirectory()) continue;
30003
- const childPath = path2.join(cwdResolved, ent.name);
30199
+ const childPath = path3.join(cwdResolved, ent.name);
30004
30200
  if (await isGitRepoDirectory(childPath)) {
30005
30201
  const remoteUrl = await getRemoteOriginUrl(childPath);
30006
30202
  result.push({ absolutePath: childPath, remoteUrl });
@@ -30009,11 +30205,11 @@ async function discoverGitRepos(cwd3 = process.cwd()) {
30009
30205
  return result;
30010
30206
  }
30011
30207
  async function discoverGitReposUnderRoot(rootAbs) {
30012
- const root = path2.resolve(rootAbs);
30208
+ const root = path3.resolve(rootAbs);
30013
30209
  const roots = [];
30014
30210
  async function walk(dir) {
30015
30211
  if (await isGitRepoDirectory(dir)) {
30016
- roots.push(path2.resolve(dir));
30212
+ roots.push(path3.resolve(dir));
30017
30213
  return;
30018
30214
  }
30019
30215
  let entries;
@@ -30024,7 +30220,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
30024
30220
  }
30025
30221
  for (const ent of entries) {
30026
30222
  if (!ent.isDirectory() || ent.name === ".git") continue;
30027
- await walk(path2.join(dir, ent.name));
30223
+ await walk(path3.join(dir, ent.name));
30028
30224
  }
30029
30225
  }
30030
30226
  await walk(root);
@@ -30051,56 +30247,43 @@ function reportGitRepos(getWs, log2) {
30051
30247
  }
30052
30248
  }
30053
30249
  }).catch((err) => {
30054
- log2(`[Bridge service] git repo discovery failed: ${err instanceof Error ? err.message : String(err)}`);
30250
+ log2(
30251
+ `[Bridge service] Git repository discovery failed: ${err instanceof Error ? err.message : String(err)}`
30252
+ );
30055
30253
  });
30056
30254
  });
30057
30255
  }
30058
30256
 
30059
- // src/bridge/connection/schedule-reconnect.ts
30060
- var RECONNECT_BASE_MS = 1e3;
30061
- var RECONNECT_MAX_MS = 3e4;
30062
- function scheduleReconnect(state, connect, log2) {
30063
- if (state.closedByUser || state.currentWs != null) return;
30064
- const delay2 = Math.min(
30065
- RECONNECT_BASE_MS * 2 ** state.reconnectAttempt,
30066
- RECONNECT_MAX_MS
30067
- );
30068
- state.reconnectAttempt += 1;
30069
- log2(`[Bridge service] reconnect attempt ${state.reconnectAttempt} in ${delay2 / 1e3}s\u2026`);
30070
- state.reconnectTimeout = setTimeout(() => {
30071
- state.reconnectTimeout = null;
30072
- connect();
30073
- }, delay2);
30074
- }
30075
-
30076
30257
  // src/bridge/connection/close-bridge-connection.ts
30077
30258
  async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
30078
30259
  log2?.("Shutting down\u2026");
30079
- await new Promise((resolve17) => setImmediate(resolve17));
30260
+ await new Promise((resolve15) => setImmediate(resolve15));
30080
30261
  if (devServerManager) {
30081
30262
  log2?.("Requesting dev server processes to stop\u2026");
30082
30263
  await devServerManager.shutdownAllGraceful();
30083
30264
  }
30084
30265
  state.closedByUser = true;
30266
+ clearReconnectQuietTimer(state.mainQuiet);
30267
+ clearReconnectQuietTimer(state.firehoseQuiet);
30085
30268
  if (state.reconnectTimeout != null) {
30086
30269
  log2?.("Cancelling reconnect timer\u2026");
30087
30270
  clearTimeout(state.reconnectTimeout);
30088
30271
  state.reconnectTimeout = null;
30089
30272
  }
30090
30273
  if (state.firehoseReconnectTimeout != null) {
30091
- log2?.("[Proxy and log service] cancelling reconnect timer\u2026");
30274
+ log2?.("[Proxy and log service] Cancelling reconnect timer\u2026");
30092
30275
  clearTimeout(state.firehoseReconnectTimeout);
30093
30276
  state.firehoseReconnectTimeout = null;
30094
30277
  }
30095
30278
  if (state.firehoseHandle) {
30096
- log2?.("[Proxy and log service] closing connection (CLI shutdown)\u2026");
30279
+ log2?.("[Proxy and log service] Closing connection (CLI shutdown)\u2026");
30097
30280
  state.firehoseHandle.close();
30098
30281
  state.firehoseHandle = null;
30099
30282
  }
30100
30283
  log2?.("Disconnecting local agents (ACP)\u2026");
30101
30284
  acpManager.disconnect();
30102
30285
  if (state.currentWs) {
30103
- log2?.("[Bridge service] closing connection (CLI shutdown)\u2026");
30286
+ log2?.("[Bridge service] Closing connection (CLI shutdown)\u2026");
30104
30287
  state.currentWs.removeAllListeners();
30105
30288
  const wsState = state.currentWs.readyState;
30106
30289
  if (wsState === 1 || wsState === 2) {
@@ -30116,11 +30299,20 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
30116
30299
  }
30117
30300
 
30118
30301
  // src/git/session-git-queue.ts
30302
+ import { execFile as execFile2 } from "node:child_process";
30303
+ import { promisify as promisify2 } from "node:util";
30304
+ import * as fs4 from "node:fs";
30305
+ import * as path5 from "node:path";
30306
+
30307
+ // src/git/pre-turn-snapshot.ts
30308
+ import * as fs3 from "node:fs";
30309
+ import * as path4 from "node:path";
30119
30310
  import { execFile } from "node:child_process";
30120
30311
  import { promisify } from "node:util";
30121
- import * as path3 from "node:path";
30122
30312
  var execFileAsync = promisify(execFile);
30123
- var sessionBoundaryBySessionId = /* @__PURE__ */ new Map();
30313
+ function snapshotsDirForCwd(agentCwd) {
30314
+ return path4.join(agentCwd, ".buildautomaton", "snapshots");
30315
+ }
30124
30316
  async function gitStashCreate(repoRoot, log2) {
30125
30317
  try {
30126
30318
  const { stdout } = await execFileAsync("git", ["stash", "create"], {
@@ -30129,51 +30321,149 @@ async function gitStashCreate(repoRoot, log2) {
30129
30321
  });
30130
30322
  return stdout.trim();
30131
30323
  } catch (e) {
30132
- log2(`[session-git-queue] stash create failed in ${repoRoot}: ${e instanceof Error ? e.message : String(e)}`);
30324
+ log2(
30325
+ `[snapshot] Git stash create failed in ${repoRoot}: ${e instanceof Error ? e.message : String(e)}`
30326
+ );
30133
30327
  return "";
30134
30328
  }
30135
30329
  }
30136
- async function captureSessionGitBoundary(options) {
30137
- const { sessionId, repoRoots, log: log2 } = options;
30138
- if (!repoRoots.length) return;
30330
+ async function gitRun(repoRoot, args, log2, label) {
30331
+ try {
30332
+ await execFileAsync("git", args, { cwd: repoRoot, maxBuffer: 10 * 1024 * 1024 });
30333
+ return { ok: true };
30334
+ } catch (e) {
30335
+ const msg = e instanceof Error ? e.message : String(e);
30336
+ log2(`[snapshot] Git ${label} failed in ${repoRoot}: ${msg}`);
30337
+ return { ok: false, error: msg };
30338
+ }
30339
+ }
30340
+ async function resolveSnapshotRepoRoots(options) {
30341
+ const { worktreePaths, fallbackCwd, log: log2 } = options;
30342
+ if (worktreePaths?.length) {
30343
+ const uniq = [...new Set(worktreePaths.map((p) => path4.resolve(p)))];
30344
+ return uniq;
30345
+ }
30346
+ try {
30347
+ const repos = await discoverGitReposUnderRoot(fallbackCwd);
30348
+ return repos.map((r) => r.absolutePath);
30349
+ } catch (e) {
30350
+ log2(`[snapshot] Discover repositories failed: ${e instanceof Error ? e.message : String(e)}`);
30351
+ return [];
30352
+ }
30353
+ }
30354
+ async function capturePreTurnSnapshot(options) {
30355
+ const { runId, repoRoots, agentCwd, log: log2 } = options;
30356
+ if (!runId || !repoRoots.length) {
30357
+ return { ok: false, error: "No git repos to snapshot" };
30358
+ }
30139
30359
  const repos = [];
30140
30360
  for (const root of repoRoots) {
30141
30361
  const stashSha = await gitStashCreate(root, log2);
30142
30362
  repos.push({ path: root, stashSha });
30143
30363
  }
30144
- sessionBoundaryBySessionId.set(sessionId, repos);
30145
- log2(`[session-git-queue] boundary stash ${sessionId.slice(0, 8)}\u2026 (${repos.length} repo(s))`);
30364
+ const dir = snapshotsDirForCwd(agentCwd);
30365
+ try {
30366
+ fs3.mkdirSync(dir, { recursive: true });
30367
+ } catch (e) {
30368
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
30369
+ }
30370
+ const payload = {
30371
+ runId,
30372
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
30373
+ repos
30374
+ };
30375
+ const filePath = path4.join(dir, `${runId}.json`);
30376
+ try {
30377
+ fs3.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
30378
+ } catch (e) {
30379
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
30380
+ }
30381
+ const repoList = repos.map((r) => r.path).join(", ");
30382
+ log2(
30383
+ `[snapshot] Saved pre-turn snapshot ${runId.slice(0, 8)}\u2026 (${repos.length} repo(s)): ${repoList}`
30384
+ );
30385
+ return { ok: true, filePath, repos };
30146
30386
  }
30147
- async function collectSessionDiffAndNotify(options) {
30148
- const { sessionId, runId, sendSessionUpdate, log: log2 } = options;
30149
- const repos = sessionBoundaryBySessionId.get(sessionId);
30150
- if (!repos?.length) {
30151
- log2(`[session-git-queue] no boundary for ${sessionId.slice(0, 8)}\u2026; skip aggregate diff`);
30387
+ async function applyPreTurnSnapshot(filePath, log2) {
30388
+ let data;
30389
+ try {
30390
+ const raw = fs3.readFileSync(filePath, "utf8");
30391
+ data = JSON.parse(raw);
30392
+ } catch (e) {
30393
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
30394
+ }
30395
+ if (!Array.isArray(data.repos)) {
30396
+ return { ok: false, error: "Invalid snapshot file" };
30397
+ }
30398
+ for (const r of data.repos) {
30399
+ if (!r.path) continue;
30400
+ const reset = await gitRun(r.path, ["reset", "--hard", "HEAD"], log2, "reset --hard");
30401
+ if (!reset.ok) return reset;
30402
+ const clean = await gitRun(r.path, ["clean", "-fd"], log2, "clean -fd");
30403
+ if (!clean.ok) return clean;
30404
+ if (r.stashSha) {
30405
+ const ap = await gitRun(r.path, ["stash", "apply", r.stashSha], log2, "stash apply");
30406
+ if (!ap.ok) return ap;
30407
+ }
30408
+ }
30409
+ log2(`[snapshot] Restored pre-turn state for ${data.runId.slice(0, 8)}\u2026`);
30410
+ return { ok: true };
30411
+ }
30412
+ function snapshotFilePath(agentCwd, runId) {
30413
+ return path4.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
30414
+ }
30415
+
30416
+ // src/git/session-git-queue.ts
30417
+ var execFileAsync2 = promisify2(execFile2);
30418
+ var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
30419
+ function readWorkspaceFileAsUtf8(absPath) {
30420
+ try {
30421
+ const st = fs4.statSync(absPath);
30422
+ if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
30423
+ return fs4.readFileSync(absPath, "utf8");
30424
+ } catch {
30425
+ return void 0;
30426
+ }
30427
+ }
30428
+ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
30429
+ const { sessionId, runId, agentCwd, sendSessionUpdate, log: log2 } = options;
30430
+ const filePath = snapshotFilePath(agentCwd, runId);
30431
+ let data;
30432
+ try {
30433
+ const raw = fs4.readFileSync(filePath, "utf8");
30434
+ data = JSON.parse(raw);
30435
+ } catch (e) {
30436
+ log2(
30437
+ `[session-git-queue] No pre-turn snapshot for run ${runId.slice(0, 8)}\u2026: ${e instanceof Error ? e.message : String(e)}`
30438
+ );
30152
30439
  return;
30153
30440
  }
30154
- sessionBoundaryBySessionId.delete(sessionId);
30155
- const multiRepo = repos.length > 1;
30156
- for (const repo of repos) {
30441
+ if (!Array.isArray(data.repos) || !data.repos.length) {
30442
+ log2(`[session-git-queue] Empty repos in snapshot ${runId.slice(0, 8)}\u2026; skipping aggregate diff.`);
30443
+ return;
30444
+ }
30445
+ const multiRepo = data.repos.length > 1;
30446
+ for (const repo of data.repos) {
30157
30447
  if (!repo.stashSha) continue;
30158
30448
  let namesRaw;
30159
30449
  try {
30160
- const { stdout } = await execFileAsync("git", ["diff", "--name-only", repo.stashSha], {
30450
+ const { stdout } = await execFileAsync2("git", ["diff", "--name-only", repo.stashSha], {
30161
30451
  cwd: repo.path,
30162
30452
  maxBuffer: 10 * 1024 * 1024
30163
30453
  });
30164
30454
  namesRaw = stdout;
30165
30455
  } catch (e) {
30166
30456
  log2(
30167
- `[session-git-queue] git diff --name-only failed in ${repo.path}: ${e instanceof Error ? e.message : String(e)}`
30457
+ `[session-git-queue] Git diff --name-only failed in ${repo.path}: ${e instanceof Error ? e.message : String(e)}`
30168
30458
  );
30169
30459
  continue;
30170
30460
  }
30171
30461
  const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
30172
- const slug = path3.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
30462
+ const slug = path5.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
30173
30463
  for (const rel of lines) {
30174
30464
  if (rel.includes("..")) continue;
30175
30465
  try {
30176
- const { stdout: patchContent } = await execFileAsync(
30466
+ const { stdout: patchContent } = await execFileAsync2(
30177
30467
  "git",
30178
30468
  ["diff", "--no-color", repo.stashSha, "--", rel],
30179
30469
  {
@@ -30183,15 +30473,20 @@ async function collectSessionDiffAndNotify(options) {
30183
30473
  );
30184
30474
  if (!patchContent.trim()) continue;
30185
30475
  const displayPath = multiRepo ? `${slug}/${rel}` : rel;
30476
+ const absFile = path5.join(repo.path, rel);
30477
+ const newText = readWorkspaceFileAsUtf8(absFile);
30186
30478
  sendSessionUpdate({
30187
30479
  type: "session_file_change",
30188
30480
  sessionId,
30189
30481
  runId,
30190
30482
  path: displayPath,
30191
- patchContent
30483
+ patchContent,
30484
+ ...newText !== void 0 ? { newText } : {}
30192
30485
  });
30193
30486
  } catch (e) {
30194
- log2(`[session-git-queue] git diff failed for ${rel}: ${e instanceof Error ? e.message : String(e)}`);
30487
+ log2(
30488
+ `[session-git-queue] Git diff failed for ${rel}: ${e instanceof Error ? e.message : String(e)}`
30489
+ );
30195
30490
  }
30196
30491
  }
30197
30492
  }
@@ -30205,15 +30500,21 @@ async function sendPromptToAgent(options) {
30205
30500
  promptId,
30206
30501
  sessionId,
30207
30502
  runId,
30503
+ agentCwd,
30208
30504
  sendResult,
30209
30505
  sendSessionUpdate,
30210
- collectSessionDiffAfterTurn,
30211
30506
  log: log2
30212
30507
  } = options;
30213
30508
  try {
30214
30509
  const result = await handle.sendPrompt(promptText, {});
30215
- if (collectSessionDiffAfterTurn && sessionId && runId && sendSessionUpdate && result.success) {
30216
- await collectSessionDiffAndNotify({ sessionId, runId, sendSessionUpdate, log: log2 });
30510
+ if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
30511
+ await collectTurnGitDiffFromPreTurnSnapshot({
30512
+ sessionId,
30513
+ runId,
30514
+ agentCwd,
30515
+ sendSessionUpdate,
30516
+ log: log2
30517
+ });
30217
30518
  }
30218
30519
  sendResult({
30219
30520
  type: "prompt_result",
@@ -30223,12 +30524,12 @@ async function sendPromptToAgent(options) {
30223
30524
  ...result
30224
30525
  });
30225
30526
  if (!result.success) {
30226
- log2(`[agent] ${result.error ?? "error"}`);
30527
+ log2(`[Agent] ${result.error ?? "Error"}`);
30227
30528
  }
30228
30529
  } catch (err) {
30229
30530
  const errMsg = err instanceof Error ? err.message : String(err);
30230
- log2(`[agent] send failed: ${errMsg}`);
30231
- if (err instanceof Error && err.stack) log2(`[agent] ${err.stack}`);
30531
+ log2(`[Agent] Send failed: ${errMsg}`);
30532
+ if (err instanceof Error && err.stack) log2(`[Agent] ${err.stack}`);
30232
30533
  sendResult({
30233
30534
  type: "prompt_result",
30234
30535
  id: promptId,
@@ -30241,8 +30542,8 @@ async function sendPromptToAgent(options) {
30241
30542
  }
30242
30543
 
30243
30544
  // src/acp/ensure-acp-client.ts
30244
- import * as fs3 from "node:fs";
30245
- import * as path7 from "node:path";
30545
+ import * as fs5 from "node:fs";
30546
+ import * as path9 from "node:path";
30246
30547
 
30247
30548
  // src/error-message.ts
30248
30549
  function errorMessage(err) {
@@ -30273,15 +30574,15 @@ function toErrorMessage(err) {
30273
30574
  }
30274
30575
  async function createAcpClient(options) {
30275
30576
  const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
30276
- const { command, cwd: cwd3 = process.cwd(), onSessionUpdate } = options;
30277
- const isWindows2 = process.platform === "win32";
30577
+ const { command, cwd = getBridgeWorkspaceDirectory(), onSessionUpdate } = options;
30578
+ const isWindows = process.platform === "win32";
30278
30579
  const child = spawn2(command[0], command.slice(1), {
30279
- cwd: cwd3,
30580
+ cwd,
30280
30581
  stdio: ["pipe", "pipe", "inherit"],
30281
30582
  env: process.env,
30282
- shell: isWindows2
30583
+ shell: isWindows
30283
30584
  });
30284
- return new Promise((resolve17, reject) => {
30585
+ return new Promise((resolve15, reject) => {
30285
30586
  child.on("error", (err) => {
30286
30587
  child.kill();
30287
30588
  reject(new Error(formatSpawnError(err, command[0])));
@@ -30308,9 +30609,9 @@ async function createAcpClient(options) {
30308
30609
  capabilities: {},
30309
30610
  clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
30310
30611
  });
30311
- const newSessionRes = await connection.newSession({ workingDirectory: cwd3 });
30612
+ const newSessionRes = await connection.newSession({ workingDirectory: cwd });
30312
30613
  const sessionId = newSessionRes.sessionId;
30313
- resolve17({
30614
+ resolve15({
30314
30615
  sessionId,
30315
30616
  async sendPrompt(prompt, _options) {
30316
30617
  try {
@@ -30365,27 +30666,27 @@ async function createCodexAcpClient(options) {
30365
30666
  }
30366
30667
 
30367
30668
  // src/acp/clients/cursor-acp-client.ts
30368
- import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
30669
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
30369
30670
  import { dirname } from "node:path";
30370
30671
  import { spawn as spawn3 } from "node:child_process";
30371
30672
  import * as readline from "node:readline";
30372
30673
 
30373
30674
  // src/acp/safe-fs-path.ts
30374
- import * as path4 from "node:path";
30375
- function resolveSafePathUnderCwd(cwd3, filePath) {
30675
+ import * as path6 from "node:path";
30676
+ function resolveSafePathUnderCwd(cwd, filePath) {
30376
30677
  const trimmed2 = filePath.trim();
30377
30678
  if (!trimmed2) return null;
30378
- const normalizedCwd = path4.resolve(cwd3);
30379
- const resolved = path4.isAbsolute(trimmed2) ? path4.normalize(trimmed2) : path4.resolve(normalizedCwd, trimmed2);
30380
- const rel = path4.relative(normalizedCwd, resolved);
30381
- if (rel.startsWith("..") || path4.isAbsolute(rel)) return null;
30679
+ const normalizedCwd = path6.resolve(cwd);
30680
+ const resolved = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.resolve(normalizedCwd, trimmed2);
30681
+ const rel = path6.relative(normalizedCwd, resolved);
30682
+ if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
30382
30683
  return resolved;
30383
30684
  }
30384
- function toDisplayPathRelativeToCwd(cwd3, absolutePath) {
30385
- const normalizedCwd = path4.resolve(cwd3);
30386
- const rel = path4.relative(normalizedCwd, path4.resolve(absolutePath));
30387
- if (!rel || rel === "") return path4.basename(absolutePath);
30388
- return rel.split(path4.sep).join("/");
30685
+ function toDisplayPathRelativeToCwd(cwd, absolutePath) {
30686
+ const normalizedCwd = path6.resolve(cwd);
30687
+ const rel = path6.relative(normalizedCwd, path6.resolve(absolutePath));
30688
+ if (!rel || rel === "") return path6.basename(absolutePath);
30689
+ return rel.split(path6.sep).join("/");
30389
30690
  }
30390
30691
 
30391
30692
  // src/files/diff/unified-diff.ts
@@ -30434,6 +30735,19 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
30434
30735
  return out.join("\n");
30435
30736
  }
30436
30737
 
30738
+ // src/acp/format-session-update-kind-for-log.ts
30739
+ var SESSION_UPDATE_KIND_LABELS = {
30740
+ tool_call: "Tool call",
30741
+ tool_call_update: "Tool call status",
30742
+ agent_message_chunk: "Agent message chunk",
30743
+ update: "Session update"
30744
+ };
30745
+ function formatSessionUpdateKindForLog(kind) {
30746
+ const known = SESSION_UPDATE_KIND_LABELS[kind];
30747
+ if (known) return known;
30748
+ return kind.split("_").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
30749
+ }
30750
+
30437
30751
  // src/acp/clients/cursor-acp-client.ts
30438
30752
  var FS_READ_METHODS = /* @__PURE__ */ new Set(["fs/read_text_file", "fs/readTextFile"]);
30439
30753
  var FS_WRITE_METHODS = /* @__PURE__ */ new Set(["fs/write_text_file", "fs/writeTextFile"]);
@@ -30459,16 +30773,16 @@ function sliceLinesByRange(content, line, limit) {
30459
30773
  return lines.slice(start, end).join("\n");
30460
30774
  }
30461
30775
  async function createCursorAcpClient(options) {
30462
- const { command, cwd: cwd3 = process.cwd(), onSessionUpdate, onRequest, onFileChange } = options;
30776
+ const { command, cwd = getBridgeWorkspaceDirectory(), onSessionUpdate, onRequest, onFileChange } = options;
30463
30777
  const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
30464
- const isWindows2 = process.platform === "win32";
30778
+ const isWindows = process.platform === "win32";
30465
30779
  const child = spawn3(command[0], command.slice(1), {
30466
- cwd: cwd3,
30780
+ cwd,
30467
30781
  stdio: ["pipe", "pipe", "inherit"],
30468
30782
  env: process.env,
30469
- shell: isWindows2
30783
+ shell: isWindows
30470
30784
  });
30471
- return new Promise((resolve17, reject) => {
30785
+ return new Promise((resolve15, reject) => {
30472
30786
  child.on("error", (err) => {
30473
30787
  child.kill();
30474
30788
  reject(new Error(formatSpawnError2(err, command[0])));
@@ -30521,7 +30835,10 @@ async function createCursorAcpClient(options) {
30521
30835
  const toolCall = update.toolCall ?? update.tool_call;
30522
30836
  const toolName = typeof toolCall?.name === "string" ? toolCall.name : "";
30523
30837
  if (dbgFs && (sessionUpdate === "tool_call" || sessionUpdate === "tool_call_update")) {
30524
- console.error(`[acp] recv session/update kind=${sessionUpdate} tool=${toolName || "(none)"}`);
30838
+ const kindLabel = formatSessionUpdateKindForLog(sessionUpdate ?? "update");
30839
+ console.error(
30840
+ `[acp] Received session update (${kindLabel}) tool=${toolName || "(none)"}`
30841
+ );
30525
30842
  }
30526
30843
  const isTextChunk = sessionUpdate === "agent_message_chunk" && update.content?.text;
30527
30844
  if (isTextChunk && update.content?.text) {
@@ -30541,14 +30858,14 @@ async function createCursorAcpClient(options) {
30541
30858
  if (dbgFs) {
30542
30859
  console.error(`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""}`);
30543
30860
  }
30544
- const abs = resolveSafePathUnderCwd(cwd3, filePath);
30861
+ const abs = resolveSafePathUnderCwd(cwd, filePath);
30545
30862
  if (!abs) {
30546
30863
  if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty)`);
30547
30864
  respondJsonRpcError(id, -32602, "Invalid or disallowed path");
30548
30865
  return;
30549
30866
  }
30550
30867
  try {
30551
- let content = readFileSync(abs, "utf8");
30868
+ let content = readFileSync3(abs, "utf8");
30552
30869
  const line2 = typeof params.line === "number" ? params.line : void 0;
30553
30870
  const limit = typeof params.limit === "number" ? params.limit : void 0;
30554
30871
  content = sliceLinesByRange(content, line2, limit);
@@ -30572,7 +30889,7 @@ async function createCursorAcpClient(options) {
30572
30889
  `[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""} newBytes=${newText.length}`
30573
30890
  );
30574
30891
  }
30575
- const abs = resolveSafePathUnderCwd(cwd3, filePath);
30892
+ const abs = resolveSafePathUnderCwd(cwd, filePath);
30576
30893
  if (!abs) {
30577
30894
  if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
30578
30895
  respondJsonRpcError(id, -32602, "Invalid or disallowed path");
@@ -30580,7 +30897,7 @@ async function createCursorAcpClient(options) {
30580
30897
  }
30581
30898
  let oldText = "";
30582
30899
  try {
30583
- oldText = readFileSync(abs, "utf8");
30900
+ oldText = readFileSync3(abs, "utf8");
30584
30901
  } catch (e) {
30585
30902
  if (e.code !== "ENOENT") {
30586
30903
  respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
@@ -30588,13 +30905,13 @@ async function createCursorAcpClient(options) {
30588
30905
  }
30589
30906
  }
30590
30907
  try {
30591
- mkdirSync(dirname(abs), { recursive: true });
30592
- writeFileSync(abs, newText, "utf8");
30908
+ mkdirSync2(dirname(abs), { recursive: true });
30909
+ writeFileSync2(abs, newText, "utf8");
30593
30910
  } catch (e) {
30594
30911
  respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
30595
30912
  return;
30596
30913
  }
30597
- const displayPath = toDisplayPathRelativeToCwd(cwd3, abs);
30914
+ const displayPath = toDisplayPathRelativeToCwd(cwd, abs);
30598
30915
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
30599
30916
  onFileChange?.({ path: displayPath, oldText, newText, patchContent });
30600
30917
  respond(id, null);
@@ -30636,10 +30953,10 @@ async function createCursorAcpClient(options) {
30636
30953
  clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
30637
30954
  });
30638
30955
  await send("authenticate", { methodId: "cursor_login" });
30639
- const newResult = await send("session/new", { cwd: cwd3, mcpServers: [] });
30956
+ const newResult = await send("session/new", { cwd, mcpServers: [] });
30640
30957
  const sessionId = newResult?.sessionId ?? "";
30641
30958
  if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
30642
- resolve17({
30959
+ resolve15({
30643
30960
  sessionId,
30644
30961
  async sendPrompt(prompt, _options) {
30645
30962
  promptOutputBuffer = "";
@@ -30708,20 +31025,20 @@ function resolveAgentCommand(preferredAgentType) {
30708
31025
 
30709
31026
  // src/acp/session-file-change-path-kind.ts
30710
31027
  import { execFileSync as execFileSync3 } from "node:child_process";
30711
- import { existsSync, statSync } from "node:fs";
31028
+ import { existsSync, statSync as statSync2 } from "node:fs";
30712
31029
 
30713
31030
  // src/git/get-git-repo-root-sync.ts
30714
31031
  import { execFileSync } from "node:child_process";
30715
- import * as path5 from "node:path";
31032
+ import * as path7 from "node:path";
30716
31033
  function getGitRepoRootSync(startDir) {
30717
31034
  try {
30718
31035
  const out = execFileSync("git", ["rev-parse", "--show-toplevel"], {
30719
- cwd: path5.resolve(startDir),
31036
+ cwd: path7.resolve(startDir),
30720
31037
  encoding: "utf8",
30721
31038
  stdio: ["ignore", "pipe", "ignore"],
30722
31039
  maxBuffer: 1024 * 1024
30723
31040
  }).trim();
30724
- return out ? path5.resolve(out) : null;
31041
+ return out ? path7.resolve(out) : null;
30725
31042
  } catch {
30726
31043
  return null;
30727
31044
  }
@@ -30729,65 +31046,65 @@ function getGitRepoRootSync(startDir) {
30729
31046
 
30730
31047
  // src/acp/workspace-files.ts
30731
31048
  import { execFileSync as execFileSync2 } from "node:child_process";
30732
- import { readFileSync as readFileSync2 } from "node:fs";
30733
- import * as path6 from "node:path";
30734
- function resolveWorkspaceFilePath(cwd3, rawPath) {
31049
+ import { readFileSync as readFileSync4 } from "node:fs";
31050
+ import * as path8 from "node:path";
31051
+ function resolveWorkspaceFilePath(cwd, rawPath) {
30735
31052
  const trimmed2 = rawPath.trim();
30736
31053
  if (!trimmed2) return null;
30737
- const normalizedCwd = path6.resolve(cwd3);
30738
- let abs = resolveSafePathUnderCwd(cwd3, trimmed2);
31054
+ const normalizedCwd = path8.resolve(cwd);
31055
+ let abs = resolveSafePathUnderCwd(cwd, trimmed2);
30739
31056
  if (!abs) {
30740
- const candidate = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.normalize(path6.resolve(normalizedCwd, trimmed2));
30741
- const gitRoot2 = getGitRepoRootSync(cwd3);
31057
+ const candidate = path8.isAbsolute(trimmed2) ? path8.normalize(trimmed2) : path8.normalize(path8.resolve(normalizedCwd, trimmed2));
31058
+ const gitRoot2 = getGitRepoRootSync(cwd);
30742
31059
  if (!gitRoot2) return null;
30743
- const rel = path6.relative(gitRoot2, candidate);
30744
- if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
31060
+ const rel = path8.relative(gitRoot2, candidate);
31061
+ if (rel.startsWith("..") || path8.isAbsolute(rel)) return null;
30745
31062
  abs = candidate;
30746
31063
  }
30747
- const gitRoot = getGitRepoRootSync(cwd3);
31064
+ const gitRoot = getGitRepoRootSync(cwd);
30748
31065
  if (gitRoot) {
30749
- const relFromRoot = path6.relative(gitRoot, abs);
30750
- if (!relFromRoot.startsWith("..") && !path6.isAbsolute(relFromRoot)) {
30751
- return { abs, display: relFromRoot.split(path6.sep).join("/") };
31066
+ const relFromRoot = path8.relative(gitRoot, abs);
31067
+ if (!relFromRoot.startsWith("..") && !path8.isAbsolute(relFromRoot)) {
31068
+ return { abs, display: relFromRoot.split(path8.sep).join("/") };
30752
31069
  }
30753
31070
  }
30754
- return { abs, display: toDisplayPathRelativeToCwd(cwd3, abs) };
31071
+ return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
30755
31072
  }
30756
- function readUtf8WorkspaceFile(cwd3, displayPath) {
31073
+ function readUtf8WorkspaceFile(cwd, displayPath) {
30757
31074
  if (!displayPath || displayPath.includes("..")) return "";
30758
- const gitRoot = getGitRepoRootSync(cwd3);
31075
+ const gitRoot = getGitRepoRootSync(cwd);
30759
31076
  if (gitRoot) {
30760
- const abs2 = path6.resolve(gitRoot, displayPath);
30761
- const rel = path6.relative(gitRoot, abs2);
30762
- if (!rel.startsWith("..") && !path6.isAbsolute(rel)) {
31077
+ const abs2 = path8.resolve(gitRoot, displayPath);
31078
+ const rel = path8.relative(gitRoot, abs2);
31079
+ if (!rel.startsWith("..") && !path8.isAbsolute(rel)) {
30763
31080
  try {
30764
- return readFileSync2(abs2, "utf8");
31081
+ return readFileSync4(abs2, "utf8");
30765
31082
  } catch {
30766
31083
  }
30767
31084
  }
30768
31085
  }
30769
- const abs = resolveSafePathUnderCwd(cwd3, displayPath);
31086
+ const abs = resolveSafePathUnderCwd(cwd, displayPath);
30770
31087
  if (!abs) return "";
30771
31088
  try {
30772
- return readFileSync2(abs, "utf8");
31089
+ return readFileSync4(abs, "utf8");
30773
31090
  } catch {
30774
31091
  return "";
30775
31092
  }
30776
31093
  }
30777
- function tryWorkspaceDisplayToAbs(cwd3, displayPath) {
31094
+ function tryWorkspaceDisplayToAbs(cwd, displayPath) {
30778
31095
  if (!displayPath || displayPath.includes("..")) return null;
30779
- const gitRoot = getGitRepoRootSync(cwd3);
31096
+ const gitRoot = getGitRepoRootSync(cwd);
30780
31097
  if (gitRoot) {
30781
- const abs = path6.resolve(gitRoot, displayPath);
30782
- const rel = path6.relative(gitRoot, abs);
30783
- if (!rel.startsWith("..") && !path6.isAbsolute(rel)) return abs;
31098
+ const abs = path8.resolve(gitRoot, displayPath);
31099
+ const rel = path8.relative(gitRoot, abs);
31100
+ if (!rel.startsWith("..") && !path8.isAbsolute(rel)) return abs;
30784
31101
  }
30785
- return resolveSafePathUnderCwd(cwd3, displayPath);
31102
+ return resolveSafePathUnderCwd(cwd, displayPath);
30786
31103
  }
30787
- function readGitHeadBlob(cwd3, displayPath) {
31104
+ function readGitHeadBlob(cwd, displayPath) {
30788
31105
  if (!displayPath || displayPath.includes("..")) return "";
30789
- const gitRoot = getGitRepoRootSync(cwd3);
30790
- const execCwd = gitRoot ?? cwd3;
31106
+ const gitRoot = getGitRepoRootSync(cwd);
31107
+ const execCwd = gitRoot ?? cwd;
30791
31108
  try {
30792
31109
  return execFileSync2("git", ["show", `HEAD:${displayPath}`], {
30793
31110
  cwd: execCwd,
@@ -30800,9 +31117,9 @@ function readGitHeadBlob(cwd3, displayPath) {
30800
31117
  }
30801
31118
 
30802
31119
  // src/acp/session-file-change-path-kind.ts
30803
- function gitHeadPathObjectType(cwd3, displayPath) {
31120
+ function gitHeadPathObjectType(cwd, displayPath) {
30804
31121
  if (!displayPath || displayPath.includes("..")) return null;
30805
- const gitRoot = getGitRepoRootSync(cwd3);
31122
+ const gitRoot = getGitRepoRootSync(cwd);
30806
31123
  if (!gitRoot) return null;
30807
31124
  try {
30808
31125
  return execFileSync3("git", ["cat-file", "-t", `HEAD:${displayPath}`], {
@@ -30813,11 +31130,11 @@ function gitHeadPathObjectType(cwd3, displayPath) {
30813
31130
  return null;
30814
31131
  }
30815
31132
  }
30816
- function getSessionFileChangeDirectoryFlags(cwd3, displayPath) {
30817
- const abs = tryWorkspaceDisplayToAbs(cwd3, displayPath);
31133
+ function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
31134
+ const abs = tryWorkspaceDisplayToAbs(cwd, displayPath);
30818
31135
  if (abs && existsSync(abs)) {
30819
31136
  try {
30820
- if (statSync(abs).isDirectory()) {
31137
+ if (statSync2(abs).isDirectory()) {
30821
31138
  return { isDirectory: true, directoryRemoved: false };
30822
31139
  }
30823
31140
  return { isDirectory: false, directoryRemoved: false };
@@ -30825,7 +31142,7 @@ function getSessionFileChangeDirectoryFlags(cwd3, displayPath) {
30825
31142
  return { isDirectory: false, directoryRemoved: false };
30826
31143
  }
30827
31144
  }
30828
- if (gitHeadPathObjectType(cwd3, displayPath) === "tree") {
31145
+ if (gitHeadPathObjectType(cwd, displayPath) === "tree") {
30829
31146
  return { isDirectory: true, directoryRemoved: true };
30830
31147
  }
30831
31148
  return { isDirectory: false, directoryRemoved: false };
@@ -30839,11 +31156,13 @@ function createBridgeOnFileChange(opts) {
30839
31156
  const sessionId = routing.sessionId;
30840
31157
  const send = getSendSessionUpdate();
30841
31158
  if (!send || !runId || !sessionId) {
30842
- log2(`[Bridge service] file change not forwarded path=${evt.path} (session/run not wired)`);
31159
+ log2(
31160
+ `[Bridge service] File change not forwarded (${evt.path}): session or run not wired to the bridge.`
31161
+ );
30843
31162
  return;
30844
31163
  }
30845
- const cwd3 = process.cwd();
30846
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd3, evt.path);
31164
+ const cwd = getBridgeWorkspaceDirectory();
31165
+ const dirFlags = getSessionFileChangeDirectoryFlags(cwd, evt.path);
30847
31166
  try {
30848
31167
  send({
30849
31168
  type: "session_file_change",
@@ -30857,7 +31176,7 @@ function createBridgeOnFileChange(opts) {
30857
31176
  directoryRemoved: dirFlags.directoryRemoved
30858
31177
  });
30859
31178
  } catch (err) {
30860
- log2(`[Bridge service] session_file_change failed ${evt.path}: ${errorMessage(err)}`);
31179
+ log2(`[Bridge service] Session file change failed for ${evt.path}: ${errorMessage(err)}`);
30861
31180
  }
30862
31181
  };
30863
31182
  }
@@ -30884,7 +31203,9 @@ function createBridgeOnRequest(opts) {
30884
31203
  }
30885
31204
  });
30886
31205
  } catch (err) {
30887
- log2(`[Bridge service] ACP request forward failed (${request.method}): ${errorMessage(err)}`);
31206
+ log2(
31207
+ `[Bridge service] Agent protocol request forward failed (${request.method}): ${errorMessage(err)}`
31208
+ );
30888
31209
  }
30889
31210
  };
30890
31211
  }
@@ -30916,12 +31237,12 @@ function extractDiffPath(o) {
30916
31237
  }
30917
31238
 
30918
31239
  // src/acp/hooks/extract-acp-file-diffs-from-update/push-diff.ts
30919
- function pushDiffIfComplete(o, cwd3, out) {
31240
+ function pushDiffIfComplete(o, cwd, out) {
30920
31241
  const t = o.type;
30921
31242
  if (typeof t !== "string" || t.toLowerCase() !== "diff") return;
30922
31243
  const rawPath = extractDiffPath(o);
30923
31244
  if (!rawPath) return;
30924
- const resolved = resolveWorkspaceFilePath(cwd3, rawPath);
31245
+ const resolved = resolveWorkspaceFilePath(cwd, rawPath);
30925
31246
  if (!resolved) return;
30926
31247
  const oldText = readOptionalTextField(o.oldText ?? o.old_text ?? o.before ?? o.oldContent);
30927
31248
  const newText = readOptionalTextField(o.newText ?? o.new_text ?? o.after ?? o.newContent);
@@ -30940,17 +31261,17 @@ var NEST_KEYS = [
30940
31261
  "data",
30941
31262
  "arguments"
30942
31263
  ];
30943
- function walkValue(value, cwd3, depth, out) {
31264
+ function walkValue(value, cwd, depth, out) {
30944
31265
  if (depth > 12 || value == null) return;
30945
31266
  if (Array.isArray(value)) {
30946
- for (const x of value) walkValue(x, cwd3, depth + 1, out);
31267
+ for (const x of value) walkValue(x, cwd, depth + 1, out);
30947
31268
  return;
30948
31269
  }
30949
31270
  if (typeof value !== "object") return;
30950
31271
  const o = value;
30951
- pushDiffIfComplete(o, cwd3, out);
31272
+ pushDiffIfComplete(o, cwd, out);
30952
31273
  if (o.type === "content" && o.content != null && typeof o.content === "object") {
30953
- walkValue(o.content, cwd3, depth + 1, out);
31274
+ walkValue(o.content, cwd, depth + 1, out);
30954
31275
  }
30955
31276
  for (const k of NEST_KEYS) {
30956
31277
  if (o.type === "content" && k === "content") continue;
@@ -30958,23 +31279,23 @@ function walkValue(value, cwd3, depth, out) {
30958
31279
  if (v == null) continue;
30959
31280
  if (k === "arguments" && typeof v === "string") {
30960
31281
  try {
30961
- walkValue(JSON.parse(v), cwd3, depth + 1, out);
31282
+ walkValue(JSON.parse(v), cwd, depth + 1, out);
30962
31283
  } catch {
30963
31284
  }
30964
31285
  continue;
30965
31286
  }
30966
- walkValue(v, cwd3, depth + 1, out);
31287
+ walkValue(v, cwd, depth + 1, out);
30967
31288
  }
30968
31289
  }
30969
31290
 
30970
31291
  // src/acp/hooks/extract-acp-file-diffs-from-update/extract.ts
30971
- function extractAcpFileDiffsFromUpdate(update, cwd3) {
31292
+ function extractAcpFileDiffsFromUpdate(update, cwd) {
30972
31293
  if (!update || typeof update !== "object") return [];
30973
31294
  const u = update;
30974
31295
  const out = [];
30975
31296
  const content = u.content;
30976
31297
  if (Array.isArray(content)) {
30977
- for (const x of content) walkValue(x, cwd3, 0, out);
31298
+ for (const x of content) walkValue(x, cwd, 0, out);
30978
31299
  }
30979
31300
  const byPath = /* @__PURE__ */ new Map();
30980
31301
  for (const d of out) byPath.set(d.path, d);
@@ -30982,18 +31303,18 @@ function extractAcpFileDiffsFromUpdate(update, cwd3) {
30982
31303
  }
30983
31304
 
30984
31305
  // src/acp/hooks/extract-tool-target-paths.ts
30985
- function addPath(cwd3, raw, out) {
31306
+ function addPath(cwd, raw, out) {
30986
31307
  if (typeof raw !== "string") return;
30987
31308
  const trimmed2 = raw.trim();
30988
31309
  if (!trimmed2) return;
30989
- const resolved = resolveWorkspaceFilePath(cwd3, trimmed2);
31310
+ const resolved = resolveWorkspaceFilePath(cwd, trimmed2);
30990
31311
  if (!resolved) return;
30991
31312
  out.add(resolved.display);
30992
31313
  }
30993
- function walkLocations(cwd3, loc, out) {
31314
+ function walkLocations(cwd, loc, out) {
30994
31315
  if (!Array.isArray(loc)) return;
30995
31316
  for (const item of loc) {
30996
- if (item && typeof item === "object") addPath(cwd3, item.path, out);
31317
+ if (item && typeof item === "object") addPath(cwd, item.path, out);
30997
31318
  }
30998
31319
  }
30999
31320
  var PATH_KEYS = [
@@ -31006,56 +31327,56 @@ var PATH_KEYS = [
31006
31327
  "file_path",
31007
31328
  "target_file"
31008
31329
  ];
31009
- function collectFromObject(cwd3, obj, out, depth) {
31330
+ function collectFromObject(cwd, obj, out, depth) {
31010
31331
  if (depth > 10) return;
31011
31332
  for (const k of PATH_KEYS) {
31012
- if (k in obj) addPath(cwd3, obj[k], out);
31333
+ if (k in obj) addPath(cwd, obj[k], out);
31013
31334
  }
31014
31335
  for (const v of Object.values(obj)) {
31015
- if (v != null && typeof v === "object") collectUnknown(cwd3, v, out, depth + 1);
31336
+ if (v != null && typeof v === "object") collectUnknown(cwd, v, out, depth + 1);
31016
31337
  }
31017
31338
  }
31018
- function collectUnknown(cwd3, v, out, depth) {
31339
+ function collectUnknown(cwd, v, out, depth) {
31019
31340
  if (depth > 10 || v == null) return;
31020
31341
  if (Array.isArray(v)) {
31021
- for (const x of v) collectUnknown(cwd3, x, out, depth + 1);
31342
+ for (const x of v) collectUnknown(cwd, x, out, depth + 1);
31022
31343
  return;
31023
31344
  }
31024
- if (typeof v === "object") collectFromObject(cwd3, v, out, depth);
31345
+ if (typeof v === "object") collectFromObject(cwd, v, out, depth);
31025
31346
  }
31026
- function walkContentArray(cwd3, content, out) {
31347
+ function walkContentArray(cwd, content, out) {
31027
31348
  if (!Array.isArray(content)) return;
31028
31349
  for (const item of content) {
31029
31350
  if (!item || typeof item !== "object") continue;
31030
31351
  const o = item;
31031
31352
  if (typeof o.type === "string" && o.type.toLowerCase() === "diff") {
31032
- for (const k of PATH_KEYS) if (k in o) addPath(cwd3, o[k], out);
31353
+ for (const k of PATH_KEYS) if (k in o) addPath(cwd, o[k], out);
31033
31354
  }
31034
31355
  if (o.type === "content" && o.content != null && typeof o.content === "object") {
31035
31356
  const inner = o.content;
31036
31357
  if (typeof inner.type === "string" && inner.type.toLowerCase() === "diff") {
31037
- for (const k of PATH_KEYS) if (k in inner) addPath(cwd3, inner[k], out);
31358
+ for (const k of PATH_KEYS) if (k in inner) addPath(cwd, inner[k], out);
31038
31359
  }
31039
31360
  }
31040
31361
  }
31041
31362
  }
31042
- function extractToolTargetDisplayPaths(update, cwd3) {
31363
+ function extractToolTargetDisplayPaths(update, cwd) {
31043
31364
  const out = /* @__PURE__ */ new Set();
31044
31365
  if (!update || typeof update !== "object") return [];
31045
31366
  const u = update;
31046
- walkLocations(cwd3, u.locations, out);
31047
- walkLocations(cwd3, u.fileLocations, out);
31048
- walkLocations(cwd3, u.file_locations, out);
31367
+ walkLocations(cwd, u.locations, out);
31368
+ walkLocations(cwd, u.fileLocations, out);
31369
+ walkLocations(cwd, u.file_locations, out);
31049
31370
  const tc = u.toolCall ?? u.tool_call;
31050
31371
  if (tc && typeof tc.arguments === "string") {
31051
31372
  try {
31052
31373
  const parsed = JSON.parse(tc.arguments);
31053
- collectUnknown(cwd3, parsed, out, 0);
31374
+ collectUnknown(cwd, parsed, out, 0);
31054
31375
  } catch {
31055
31376
  }
31056
31377
  }
31057
- walkContentArray(cwd3, u.content, out);
31058
- collectFromObject(cwd3, u, out, 0);
31378
+ walkContentArray(cwd, u.content, out);
31379
+ collectFromObject(cwd, u, out, 0);
31059
31380
  return [...out];
31060
31381
  }
31061
31382
 
@@ -31121,7 +31442,7 @@ var PathSnapshotTracker = class {
31121
31442
  this.beforeByToolKey.delete(toolKey);
31122
31443
  this.accumulatedPathsByToolKey.delete(toolKey);
31123
31444
  }
31124
- captureBeforeFromDisk(toolKey, paths, cwd3) {
31445
+ captureBeforeFromDisk(toolKey, paths, cwd) {
31125
31446
  if (paths.length === 0) return;
31126
31447
  let m = this.beforeByToolKey.get(toolKey);
31127
31448
  if (!m) {
@@ -31130,10 +31451,10 @@ var PathSnapshotTracker = class {
31130
31451
  }
31131
31452
  for (const p of paths) {
31132
31453
  if (m.has(p)) continue;
31133
- m.set(p, readUtf8WorkspaceFile(cwd3, p));
31454
+ m.set(p, readUtf8WorkspaceFile(cwd, p));
31134
31455
  }
31135
31456
  }
31136
- ensureBeforeFromHeadForMissing(toolKey, paths, cwd3) {
31457
+ ensureBeforeFromHeadForMissing(toolKey, paths, cwd) {
31137
31458
  let m = this.beforeByToolKey.get(toolKey);
31138
31459
  if (!m) {
31139
31460
  m = /* @__PURE__ */ new Map();
@@ -31141,10 +31462,10 @@ var PathSnapshotTracker = class {
31141
31462
  }
31142
31463
  for (const p of paths) {
31143
31464
  if (m.has(p)) continue;
31144
- m.set(p, readGitHeadBlob(cwd3, p));
31465
+ m.set(p, readGitHeadBlob(cwd, p));
31145
31466
  }
31146
31467
  }
31147
- flushPathSnapshots(toolKey, cwd3, sentPaths, send, runId, sessionId, log2) {
31468
+ flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2) {
31148
31469
  const t = this.debouncers.get(toolKey);
31149
31470
  if (t) clearTimeout(t);
31150
31471
  this.debouncers.delete(toolKey);
@@ -31153,10 +31474,10 @@ var PathSnapshotTracker = class {
31153
31474
  this.beforeByToolKey.delete(toolKey);
31154
31475
  if (!send || !runId || !sessionId) return;
31155
31476
  for (const [displayPath, oldText] of beforeMap) {
31156
- const newText = readUtf8WorkspaceFile(cwd3, displayPath);
31477
+ const newText = readUtf8WorkspaceFile(cwd, displayPath);
31157
31478
  if (oldText === newText) continue;
31158
31479
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
31159
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd3, displayPath);
31480
+ const dirFlags = getSessionFileChangeDirectoryFlags(cwd, displayPath);
31160
31481
  try {
31161
31482
  send({
31162
31483
  type: "session_file_change",
@@ -31171,35 +31492,35 @@ var PathSnapshotTracker = class {
31171
31492
  });
31172
31493
  sentPaths.add(displayPath);
31173
31494
  } catch (err) {
31174
- log2(`[Bridge service] session_file_change failed ${displayPath}: ${errorMessage(err)}`);
31495
+ log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
31175
31496
  }
31176
31497
  }
31177
31498
  }
31178
- scheduleDebouncedFlush(toolKey, cwd3, sentPaths, send, runId, sessionId, log2) {
31499
+ scheduleDebouncedFlush(toolKey, cwd, sentPaths, send, runId, sessionId, log2) {
31179
31500
  const prev = this.debouncers.get(toolKey);
31180
31501
  if (prev) clearTimeout(prev);
31181
31502
  this.debouncers.set(
31182
31503
  toolKey,
31183
31504
  setTimeout(() => {
31184
31505
  this.debouncers.delete(toolKey);
31185
- this.flushPathSnapshots(toolKey, cwd3, sentPaths, send, runId, sessionId, log2);
31506
+ this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
31186
31507
  }, PATH_SNAPSHOT_DEBOUNCE_MS)
31187
31508
  );
31188
31509
  }
31189
- handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, cwd3, sentPaths, send, runId, sessionId, log2) {
31510
+ handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, cwd, sentPaths, send, runId, sessionId, log2) {
31190
31511
  if (updateKind === "tool_call") {
31191
31512
  this.resetToolSnapshots(toolKey);
31192
31513
  }
31193
31514
  if (updateKind === "tool_call") {
31194
- this.captureBeforeFromDisk(toolKey, toolPaths, cwd3);
31515
+ this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
31195
31516
  } else if (updateKind === "tool_call_update") {
31196
31517
  if (isCompletedToolStatus(status)) {
31197
- this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, cwd3);
31198
- this.flushPathSnapshots(toolKey, cwd3, sentPaths, send, runId, sessionId, log2);
31518
+ this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, cwd);
31519
+ this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
31199
31520
  } else {
31200
- this.captureBeforeFromDisk(toolKey, toolPaths, cwd3);
31521
+ this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
31201
31522
  if (this.beforeByToolKey.has(toolKey)) {
31202
- this.scheduleDebouncedFlush(toolKey, cwd3, sentPaths, send, runId, sessionId, log2);
31523
+ this.scheduleDebouncedFlush(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
31203
31524
  }
31204
31525
  }
31205
31526
  }
@@ -31207,11 +31528,11 @@ var PathSnapshotTracker = class {
31207
31528
  };
31208
31529
 
31209
31530
  // src/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
31210
- function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd3, sessionId, runId, sentPaths, log2) {
31531
+ function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentPaths, log2) {
31211
31532
  for (const d of diffs) {
31212
31533
  try {
31213
31534
  const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
31214
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd3, d.path);
31535
+ const dirFlags = getSessionFileChangeDirectoryFlags(cwd, d.path);
31215
31536
  send({
31216
31537
  type: "session_file_change",
31217
31538
  sessionId,
@@ -31225,19 +31546,19 @@ function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd3, sessionId, ru
31225
31546
  });
31226
31547
  sentPaths.add(d.path);
31227
31548
  } catch (err) {
31228
- log2(`[Bridge service] session_file_change failed ${d.path}: ${errorMessage(err)}`);
31549
+ log2(`[Bridge service] Session file change failed for ${d.path}: ${errorMessage(err)}`);
31229
31550
  }
31230
31551
  }
31231
31552
  }
31232
- function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd3, sessionId, runId, log2) {
31553
+ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd, sessionId, runId, log2) {
31233
31554
  for (const displayPath of mergedPaths) {
31234
31555
  if (sentPaths.has(displayPath)) continue;
31235
- const oldText = readGitHeadBlob(cwd3, displayPath);
31236
- const newText = readUtf8WorkspaceFile(cwd3, displayPath);
31556
+ const oldText = readGitHeadBlob(cwd, displayPath);
31557
+ const newText = readUtf8WorkspaceFile(cwd, displayPath);
31237
31558
  if (oldText === newText) continue;
31238
31559
  try {
31239
31560
  const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
31240
- const dirFlags = getSessionFileChangeDirectoryFlags(cwd3, displayPath);
31561
+ const dirFlags = getSessionFileChangeDirectoryFlags(cwd, displayPath);
31241
31562
  send({
31242
31563
  type: "session_file_change",
31243
31564
  sessionId,
@@ -31251,7 +31572,7 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd3,
31251
31572
  });
31252
31573
  sentPaths.add(displayPath);
31253
31574
  } catch (err) {
31254
- log2(`[Bridge service] session_file_change failed ${displayPath}: ${errorMessage(err)}`);
31575
+ log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
31255
31576
  }
31256
31577
  }
31257
31578
  }
@@ -31264,7 +31585,7 @@ function createBridgeOnSessionUpdate(opts) {
31264
31585
  const runId = routing.runId;
31265
31586
  const sessionId = routing.sessionId;
31266
31587
  pathTracker.onRunIdChanged(runId);
31267
- const cwd3 = process.cwd();
31588
+ const cwd = getBridgeWorkspaceDirectory();
31268
31589
  const send = getSendSessionUpdate();
31269
31590
  const sentFileChangePaths = /* @__PURE__ */ new Set();
31270
31591
  const p = params;
@@ -31272,7 +31593,7 @@ function createBridgeOnSessionUpdate(opts) {
31272
31593
  const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
31273
31594
  const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
31274
31595
  const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
31275
- const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, cwd3) : [];
31596
+ const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, cwd) : [];
31276
31597
  const toolKey = isToolUpdate ? pathTracker.resolveToolKey(params, updateKind) : "";
31277
31598
  if (updateKind === "tool_call") {
31278
31599
  pathTracker.resetToolSnapshots(toolKey);
@@ -31287,7 +31608,7 @@ function createBridgeOnSessionUpdate(opts) {
31287
31608
  toolKey,
31288
31609
  toolPaths,
31289
31610
  p.status,
31290
- cwd3,
31611
+ cwd,
31291
31612
  sentFileChangePaths,
31292
31613
  deliver,
31293
31614
  runId ?? "",
@@ -31295,18 +31616,18 @@ function createBridgeOnSessionUpdate(opts) {
31295
31616
  log2
31296
31617
  );
31297
31618
  }
31298
- const diffs = extractAcpFileDiffsFromUpdate(params, cwd3);
31619
+ const diffs = extractAcpFileDiffsFromUpdate(params, cwd);
31299
31620
  if (diffs.length > 0 && send && runId && sessionId) {
31300
- sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd3, sessionId, runId, sentFileChangePaths, log2);
31621
+ sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentFileChangePaths, log2);
31301
31622
  } else if (diffs.length > 0) {
31302
31623
  log2(
31303
- `[Bridge service] ACP file diff(s) not forwarded (${diffs.length}): session/run not wired to bridge`
31624
+ `[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
31304
31625
  );
31305
31626
  }
31306
31627
  if (isCompletedToolCallUpdate && send && runId && sessionId) {
31307
31628
  const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
31308
31629
  const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
31309
- sendGitHeadVsWorkspaceForToolPaths(merged, sentFileChangePaths, send, cwd3, sessionId, runId, log2);
31630
+ sendGitHeadVsWorkspaceForToolPaths(merged, sentFileChangePaths, send, cwd, sessionId, runId, log2);
31310
31631
  pathTracker.accumulatedPathsByToolKey.delete(toolKey);
31311
31632
  }
31312
31633
  if (runId && send) {
@@ -31319,7 +31640,9 @@ function createBridgeOnSessionUpdate(opts) {
31319
31640
  payload: params
31320
31641
  });
31321
31642
  } catch (err) {
31322
- log2(`[Bridge service] session_update send failed (${updateKind}): ${errorMessage(err)}`);
31643
+ log2(
31644
+ `[Bridge service] Session update send failed (${formatSessionUpdateKindForLog(updateKind)}): ${errorMessage(err)}`
31645
+ );
31323
31646
  }
31324
31647
  }
31325
31648
  };
@@ -31336,11 +31659,11 @@ function buildAcpSessionBridgeHooks(opts) {
31336
31659
 
31337
31660
  // src/acp/ensure-acp-client.ts
31338
31661
  async function ensureAcpClient(options) {
31339
- const { state, preferredAgentType, mode, cwd: cwd3, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
31340
- const targetCwd = path7.resolve(
31341
- cwd3 != null && String(cwd3).trim() !== "" ? String(cwd3).trim() : process.cwd()
31662
+ const { state, preferredAgentType, mode, cwd, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
31663
+ const targetCwd = path9.resolve(
31664
+ cwd != null && String(cwd).trim() !== "" ? String(cwd).trim() : getBridgeWorkspaceDirectory()
31342
31665
  );
31343
- if (state.acpHandle && state.lastAcpCwd != null && path7.resolve(state.lastAcpCwd) !== path7.resolve(targetCwd)) {
31666
+ if (state.acpHandle && state.lastAcpCwd != null && path9.resolve(state.lastAcpCwd) !== path9.resolve(targetCwd)) {
31344
31667
  try {
31345
31668
  state.acpHandle.disconnect();
31346
31669
  } catch {
@@ -31352,7 +31675,7 @@ async function ensureAcpClient(options) {
31352
31675
  const resolved = resolveAgentCommand(preferredAgentType);
31353
31676
  if (!resolved) {
31354
31677
  log2(
31355
- `[agent] No local agent type (${preferredAgentType === null ? "none" : `"${preferredAgentType}"`}). Send agentType on prompts or agent_config after identify.`
31678
+ `[Agent] No local agent type (${preferredAgentType === null ? "none" : `"${preferredAgentType}"`}). Send agent type on prompts or agent configuration after identify.`
31356
31679
  );
31357
31680
  state.lastAcpStartError = "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge.";
31358
31681
  return null;
@@ -31371,15 +31694,15 @@ async function ensureAcpClient(options) {
31371
31694
  if (!state.acpStartPromise) {
31372
31695
  let statOk = false;
31373
31696
  try {
31374
- const st = fs3.statSync(targetCwd);
31697
+ const st = fs5.statSync(targetCwd);
31375
31698
  statOk = st.isDirectory();
31376
31699
  if (!statOk) {
31377
31700
  state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
31378
- log2(`[agent] ${state.lastAcpStartError}`);
31701
+ log2(`[Agent] ${state.lastAcpStartError}`);
31379
31702
  }
31380
31703
  } catch {
31381
31704
  state.lastAcpStartError = `Agent cwd missing or inaccessible: ${targetCwd}`;
31382
- log2(`[agent] ${state.lastAcpStartError}`);
31705
+ log2(`[Agent] ${state.lastAcpStartError}`);
31383
31706
  }
31384
31707
  if (!statOk) {
31385
31708
  return null;
@@ -31404,7 +31727,7 @@ async function ensureAcpClient(options) {
31404
31727
  return h;
31405
31728
  }).catch((err) => {
31406
31729
  state.lastAcpStartError = errorMessage(err);
31407
- log2(`[agent] failed to start: ${state.lastAcpStartError}`);
31730
+ log2(`[Agent] Failed to start: ${state.lastAcpStartError}`);
31408
31731
  state.acpStartPromise = null;
31409
31732
  state.acpAgentKey = null;
31410
31733
  return null;
@@ -31440,10 +31763,9 @@ async function createAcpManager(options) {
31440
31763
  runId,
31441
31764
  mode,
31442
31765
  agentType,
31443
- cwd: cwd3,
31766
+ cwd,
31444
31767
  sendResult,
31445
- sendSessionUpdate,
31446
- collectSessionDiffAfterTurn
31768
+ sendSessionUpdate
31447
31769
  } = opts;
31448
31770
  const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
31449
31771
  pendingCancelRunId = void 0;
@@ -31455,7 +31777,7 @@ async function createAcpManager(options) {
31455
31777
  state,
31456
31778
  preferredAgentType: preferredForPrompt,
31457
31779
  mode,
31458
- cwd: cwd3,
31780
+ cwd,
31459
31781
  routing: promptRouting,
31460
31782
  sendSessionUpdate,
31461
31783
  sendRequest: sendSessionUpdate,
@@ -31496,9 +31818,9 @@ async function createAcpManager(options) {
31496
31818
  promptId,
31497
31819
  sessionId,
31498
31820
  runId,
31821
+ agentCwd: cwd,
31499
31822
  sendResult,
31500
31823
  sendSessionUpdate,
31501
- collectSessionDiffAfterTurn,
31502
31824
  log: log2
31503
31825
  });
31504
31826
  }
@@ -31517,7 +31839,7 @@ async function createAcpManager(options) {
31517
31839
  await handle.cancel();
31518
31840
  return true;
31519
31841
  } catch (err) {
31520
- log2(`[agent] cancel failed: ${err instanceof Error ? err.message : String(err)}`);
31842
+ log2(`[Agent] Cancel failed: ${err instanceof Error ? err.message : String(err)}`);
31521
31843
  return false;
31522
31844
  }
31523
31845
  }
@@ -31554,7 +31876,9 @@ var handleBridgeIdentified = (msg, deps) => {
31554
31876
  try {
31555
31877
  await deps.reportAutoDetectedAgents?.();
31556
31878
  } catch (e) {
31557
- deps.log(`[Bridge service] auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`);
31879
+ deps.log(
31880
+ `[Bridge service] Auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`
31881
+ );
31558
31882
  }
31559
31883
  })();
31560
31884
  });
@@ -31562,7 +31886,9 @@ var handleBridgeIdentified = (msg, deps) => {
31562
31886
  try {
31563
31887
  deps.sendLocalSkillsReport?.();
31564
31888
  } catch (e) {
31565
- deps.log(`[Bridge service] local skills report failed: ${e instanceof Error ? e.message : String(e)}`);
31889
+ deps.log(
31890
+ `[Bridge service] Local skills report failed: ${e instanceof Error ? e.message : String(e)}`
31891
+ );
31566
31892
  }
31567
31893
  });
31568
31894
  };
@@ -31579,12 +31905,12 @@ var handleAgentConfigMessage = (msg, deps) => {
31579
31905
  };
31580
31906
 
31581
31907
  // src/acp/from-bridge/handle-bridge-prompt.ts
31582
- import * as path10 from "node:path";
31908
+ import * as path11 from "node:path";
31583
31909
  import { execFile as execFile3 } from "node:child_process";
31584
31910
  import { promisify as promisify3 } from "node:util";
31585
31911
 
31586
31912
  // src/git/bridge-queue-key.ts
31587
- import * as path8 from "node:path";
31913
+ import * as path10 from "node:path";
31588
31914
  import { createHash } from "node:crypto";
31589
31915
  function normalizeCanonicalGitUrl(url2) {
31590
31916
  let s = url2.trim();
@@ -31612,13 +31938,13 @@ function canonicalUrlToRepoIdSync(url2) {
31612
31938
  return createHash("sha256").update(normalized).digest("hex").slice(0, 32);
31613
31939
  }
31614
31940
  function fallbackRepoIdFromPath(absPath) {
31615
- return createHash("sha256").update(path8.resolve(absPath)).digest("hex").slice(0, 32);
31941
+ return createHash("sha256").update(path10.resolve(absPath)).digest("hex").slice(0, 32);
31616
31942
  }
31617
31943
  async function resolveBridgeQueueBindFields(options) {
31618
31944
  const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
31619
- const cwdAbs = worktreePaths.length > 0 ? path8.resolve(worktreePaths[0]) : path8.resolve(effectiveCwd);
31945
+ const cwdAbs = worktreePaths.length > 0 ? path10.resolve(worktreePaths[0]) : path10.resolve(effectiveCwd);
31620
31946
  if (!primaryRepoRoots.length) {
31621
- log2("[Bridge service] prompt queue bind skipped: no git repo roots under cwd");
31947
+ log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
31622
31948
  return null;
31623
31949
  }
31624
31950
  let primaryRoot = primaryRepoRoots[0];
@@ -31638,115 +31964,11 @@ async function resolveBridgeQueueBindFields(options) {
31638
31964
  return { canonicalQueueKey, repoId, cwdAbs };
31639
31965
  }
31640
31966
 
31641
- // src/git/pre-turn-snapshot.ts
31642
- import * as fs4 from "node:fs";
31643
- import * as path9 from "node:path";
31644
- import { execFile as execFile2 } from "node:child_process";
31645
- import { promisify as promisify2 } from "node:util";
31646
- var execFileAsync2 = promisify2(execFile2);
31647
- function snapshotsDirForCwd(agentCwd) {
31648
- return path9.join(agentCwd, ".buildautomaton", "snapshots");
31649
- }
31650
- async function gitStashCreate2(repoRoot, log2) {
31651
- try {
31652
- const { stdout } = await execFileAsync2("git", ["stash", "create"], {
31653
- cwd: repoRoot,
31654
- maxBuffer: 10 * 1024 * 1024
31655
- });
31656
- return stdout.trim();
31657
- } catch (e) {
31658
- log2(`[snapshot] git stash create failed in ${repoRoot}: ${e instanceof Error ? e.message : String(e)}`);
31659
- return "";
31660
- }
31661
- }
31662
- async function gitRun(repoRoot, args, log2, label) {
31663
- try {
31664
- await execFileAsync2("git", args, { cwd: repoRoot, maxBuffer: 10 * 1024 * 1024 });
31665
- return { ok: true };
31666
- } catch (e) {
31667
- const msg = e instanceof Error ? e.message : String(e);
31668
- log2(`[snapshot] git ${label} failed in ${repoRoot}: ${msg}`);
31669
- return { ok: false, error: msg };
31670
- }
31671
- }
31672
- async function resolveSnapshotRepoRoots(options) {
31673
- const { worktreePaths, fallbackCwd, log: log2 } = options;
31674
- if (worktreePaths?.length) {
31675
- const uniq = [...new Set(worktreePaths.map((p) => path9.resolve(p)))];
31676
- return uniq;
31677
- }
31678
- try {
31679
- const repos = await discoverGitReposUnderRoot(fallbackCwd);
31680
- return repos.map((r) => r.absolutePath);
31681
- } catch (e) {
31682
- log2(`[snapshot] discover repos failed: ${e instanceof Error ? e.message : String(e)}`);
31683
- return [];
31684
- }
31685
- }
31686
- async function capturePreTurnSnapshot(options) {
31687
- const { runId, repoRoots, agentCwd, log: log2 } = options;
31688
- if (!runId || !repoRoots.length) {
31689
- return { ok: false, error: "No git repos to snapshot" };
31690
- }
31691
- const repos = [];
31692
- for (const root of repoRoots) {
31693
- const stashSha = await gitStashCreate2(root, log2);
31694
- repos.push({ path: root, stashSha });
31695
- }
31696
- const dir = snapshotsDirForCwd(agentCwd);
31697
- try {
31698
- fs4.mkdirSync(dir, { recursive: true });
31699
- } catch (e) {
31700
- return { ok: false, error: e instanceof Error ? e.message : String(e) };
31701
- }
31702
- const payload = {
31703
- runId,
31704
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
31705
- repos
31706
- };
31707
- const filePath = path9.join(dir, `${runId}.json`);
31708
- try {
31709
- fs4.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
31710
- } catch (e) {
31711
- return { ok: false, error: e instanceof Error ? e.message : String(e) };
31712
- }
31713
- log2(`[snapshot] Saved pre-turn snapshot ${runId.slice(0, 8)}\u2026 (${repos.length} repo(s)) \u2192 ${filePath}`);
31714
- return { ok: true, filePath, repos };
31715
- }
31716
- async function applyPreTurnSnapshot(filePath, log2) {
31717
- let data;
31718
- try {
31719
- const raw = fs4.readFileSync(filePath, "utf8");
31720
- data = JSON.parse(raw);
31721
- } catch (e) {
31722
- return { ok: false, error: e instanceof Error ? e.message : String(e) };
31723
- }
31724
- if (!Array.isArray(data.repos)) {
31725
- return { ok: false, error: "Invalid snapshot file" };
31726
- }
31727
- for (const r of data.repos) {
31728
- if (!r.path) continue;
31729
- const reset = await gitRun(r.path, ["reset", "--hard", "HEAD"], log2, "reset --hard");
31730
- if (!reset.ok) return reset;
31731
- const clean = await gitRun(r.path, ["clean", "-fd"], log2, "clean -fd");
31732
- if (!clean.ok) return clean;
31733
- if (r.stashSha) {
31734
- const ap = await gitRun(r.path, ["stash", "apply", r.stashSha], log2, "stash apply");
31735
- if (!ap.ok) return ap;
31736
- }
31737
- }
31738
- log2(`[snapshot] Restored pre-turn state for ${data.runId.slice(0, 8)}\u2026`);
31739
- return { ok: true };
31740
- }
31741
- function snapshotFilePath(agentCwd, runId) {
31742
- return path9.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
31743
- }
31744
-
31745
31967
  // src/acp/from-bridge/handle-bridge-prompt.ts
31746
31968
  var execFileAsync3 = promisify3(execFile3);
31747
- async function readGitBranch(cwd3) {
31969
+ async function readGitBranch(cwd) {
31748
31970
  try {
31749
- const { stdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: cwd3, maxBuffer: 64 * 1024 });
31971
+ const { stdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
31750
31972
  const b = stdout.trim();
31751
31973
  return b || null;
31752
31974
  } catch {
@@ -31759,7 +31981,7 @@ function handleBridgePrompt(msg, deps) {
31759
31981
  const promptText = typeof rawPrompt === "string" ? rawPrompt : rawPrompt != null ? String(rawPrompt) : "";
31760
31982
  if (!promptText.trim()) {
31761
31983
  log2(
31762
- `[Bridge service] prompt ignored: empty or missing prompt field (sessionId=${typeof msg.sessionId === "string" ? msg.sessionId.slice(0, 8) : "\u2014"}\u2026 runId=${typeof msg.runId === "string" ? msg.runId.slice(0, 8) : "\u2014"}\u2026)`
31984
+ `[Bridge service] Prompt ignored: empty or missing prompt text (session ${typeof msg.sessionId === "string" ? msg.sessionId.slice(0, 8) : "\u2014"}\u2026, run ${typeof msg.runId === "string" ? msg.runId.slice(0, 8) : "\u2014"}\u2026).`
31763
31985
  );
31764
31986
  return;
31765
31987
  }
@@ -31768,8 +31990,6 @@ function handleBridgePrompt(msg, deps) {
31768
31990
  const sessionWorktreesEnabled = msg.sessionWorktreesEnabled === true;
31769
31991
  const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
31770
31992
  const runId = typeof msg.runId === "string" ? msg.runId : void 0;
31771
- const sessionGitQueueStart = msg.sessionGitQueueStart === true;
31772
- const collectSessionDiffAfterTurn = msg.collectSessionDiffAfterTurn === true;
31773
31993
  const sendResult = (result) => {
31774
31994
  const s = getWs();
31775
31995
  if (s) sendWsMessage(s, result);
@@ -31777,7 +31997,7 @@ function handleBridgePrompt(msg, deps) {
31777
31997
  const sendSessionUpdate = (payload) => {
31778
31998
  const s = getWs();
31779
31999
  if (!s) {
31780
- log2("[Bridge service] session_update not sent: not connected");
32000
+ log2("[Bridge service] Session update not sent: not connected to the bridge.");
31781
32001
  return;
31782
32002
  }
31783
32003
  const p = payload;
@@ -31785,7 +32005,7 @@ function handleBridgePrompt(msg, deps) {
31785
32005
  };
31786
32006
  async function preambleAndPrompt(resolvedCwd) {
31787
32007
  const s = getWs();
31788
- const effectiveCwd = path10.resolve(resolvedCwd ?? process.cwd());
32008
+ const effectiveCwd = path11.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
31789
32009
  const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
31790
32010
  const repoRoots = await resolveSnapshotRepoRoots({
31791
32011
  worktreePaths,
@@ -31818,9 +32038,6 @@ function handleBridgePrompt(msg, deps) {
31818
32038
  agentUsesWorktree: sessionWorktreeManager.usesWorktreeSession(sessionId)
31819
32039
  });
31820
32040
  }
31821
- if (sessionGitQueueStart && sessionId && repoRoots.length > 0) {
31822
- await captureSessionGitBoundary({ sessionId, repoRoots, log: log2 });
31823
- }
31824
32041
  if (s && sessionId && runId) {
31825
32042
  const cap = repoRoots.length > 0 ? await capturePreTurnSnapshot({ runId, repoRoots, agentCwd: effectiveCwd, log: log2 }) : { ok: false, error: "No git repos" };
31826
32043
  sendWsMessage(s, {
@@ -31839,12 +32056,11 @@ function handleBridgePrompt(msg, deps) {
31839
32056
  agentType,
31840
32057
  cwd: effectiveCwd,
31841
32058
  sendResult,
31842
- sendSessionUpdate,
31843
- collectSessionDiffAfterTurn
32059
+ sendSessionUpdate
31844
32060
  });
31845
32061
  }
31846
- void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionWorktreesEnabled }).then((cwd3) => preambleAndPrompt(cwd3)).catch((err) => {
31847
- log2(`[agent] worktree resolve failed: ${err instanceof Error ? err.message : String(err)}`);
32062
+ void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionWorktreesEnabled }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
32063
+ log2(`[Agent] Worktree resolve failed: ${err instanceof Error ? err.message : String(err)}`);
31848
32064
  void preambleAndPrompt(void 0);
31849
32065
  });
31850
32066
  }
@@ -31861,7 +32077,7 @@ function handleBridgeCancelRun(msg, { log: log2, acpManager }) {
31861
32077
  void acpManager.cancelRun(runId).then((sent) => {
31862
32078
  if (!sent) {
31863
32079
  log2(
31864
- `[agent] cancel ignored for run ${runId.slice(0, 8)}\u2026 (no active run or cancel not available)`
32080
+ `[Agent] Cancel ignored for run ${runId.slice(0, 8)}\u2026 (no active run or cancel not available).`
31865
32081
  );
31866
32082
  }
31867
32083
  });
@@ -31959,12 +32175,12 @@ var previewSkill = {
31959
32175
  const port = params.port ?? (Number(process.env[PREVIEW_PORT_ENV]) || DEFAULT_PORT);
31960
32176
  previewPort = port;
31961
32177
  previewSecret = randomSecret();
31962
- const isWindows2 = process.platform === "win32";
32178
+ const isWindows = process.platform === "win32";
31963
32179
  const parts = command.split(/\s+/);
31964
32180
  const exe = parts[0];
31965
32181
  const args = parts.slice(1);
31966
- previewProcess = spawn4(isWindows2 && exe === "npm" ? "npm.cmd" : exe, args, {
31967
- cwd: process.cwd(),
32182
+ previewProcess = spawn4(isWindows && exe === "npm" ? "npm.cmd" : exe, args, {
32183
+ cwd: getBridgeWorkspaceDirectory(),
31968
32184
  stdio: ["ignore", "pipe", "pipe"],
31969
32185
  env: {
31970
32186
  ...process.env,
@@ -32063,7 +32279,7 @@ function handleSkillCall(msg, socket, log2) {
32063
32279
  sendWsMessage(socket, { type: "skill_result", id: msg.id, result });
32064
32280
  }).catch((err) => {
32065
32281
  sendWsMessage(socket, { type: "skill_result", id: msg.id, error: String(err) });
32066
- log2(`[Bridge service] skill_call failed (${msg.skillId}/${msg.operationId}): ${err}`);
32282
+ log2(`[Bridge service] Skill invocation failed (${msg.skillId}/${msg.operationId}): ${err}`);
32067
32283
  });
32068
32284
  }
32069
32285
 
@@ -32080,36 +32296,35 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
32080
32296
  };
32081
32297
 
32082
32298
  // src/files/list-dir.ts
32083
- import fs5 from "node:fs";
32084
- import path12 from "node:path";
32299
+ import fs6 from "node:fs";
32300
+ import path13 from "node:path";
32085
32301
 
32086
32302
  // src/files/ensure-under-cwd.ts
32087
- import path11 from "node:path";
32088
- function ensureUnderCwd(relativePath, cwd3 = process.cwd()) {
32089
- const normalized = path11.normalize(relativePath).replace(/^(\.\/)+/, "");
32090
- const resolved = path11.resolve(cwd3, normalized);
32091
- if (!resolved.startsWith(cwd3 + path11.sep) && resolved !== cwd3) {
32303
+ import path12 from "node:path";
32304
+ function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
32305
+ const normalized = path12.normalize(relativePath).replace(/^(\.\/)+/, "");
32306
+ const resolved = path12.resolve(cwd, normalized);
32307
+ if (!resolved.startsWith(cwd + path12.sep) && resolved !== cwd) {
32092
32308
  return null;
32093
32309
  }
32094
32310
  return resolved;
32095
32311
  }
32096
32312
 
32097
32313
  // src/files/list-dir.ts
32098
- var cwd = process.cwd();
32099
32314
  function listDir(relativePath) {
32100
- const resolved = ensureUnderCwd(relativePath || ".", cwd);
32315
+ const resolved = ensureUnderCwd(relativePath || ".", getBridgeWorkspaceDirectory());
32101
32316
  if (!resolved) {
32102
32317
  return { error: "Path is outside working directory" };
32103
32318
  }
32104
32319
  try {
32105
- const names = fs5.readdirSync(resolved, { withFileTypes: true });
32320
+ const names = fs6.readdirSync(resolved, { withFileTypes: true });
32106
32321
  const entries = names.filter((d) => !d.name.startsWith(".")).map((d) => {
32107
- const entryPath = path12.join(relativePath || ".", d.name).replace(/\\/g, "/");
32108
- const fullPath = path12.join(resolved, d.name);
32322
+ const entryPath = path13.join(relativePath || ".", d.name).replace(/\\/g, "/");
32323
+ const fullPath = path13.join(resolved, d.name);
32109
32324
  let isDir = d.isDirectory();
32110
32325
  if (d.isSymbolicLink()) {
32111
32326
  try {
32112
- const targetStat = fs5.statSync(fullPath);
32327
+ const targetStat = fs6.statSync(fullPath);
32113
32328
  isDir = targetStat.isDirectory();
32114
32329
  } catch {
32115
32330
  isDir = false;
@@ -32133,26 +32348,25 @@ function listDir(relativePath) {
32133
32348
  }
32134
32349
 
32135
32350
  // src/files/read-file.ts
32136
- import fs6 from "node:fs";
32351
+ import fs7 from "node:fs";
32137
32352
  import { StringDecoder } from "node:string_decoder";
32138
- var cwd2 = process.cwd();
32139
32353
  function resolveFilePath(relativePath) {
32140
- const resolved = ensureUnderCwd(relativePath, cwd2);
32354
+ const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
32141
32355
  if (!resolved) return { error: "Path is outside working directory" };
32142
32356
  let real;
32143
32357
  try {
32144
- real = fs6.realpathSync(resolved);
32358
+ real = fs7.realpathSync(resolved);
32145
32359
  } catch {
32146
32360
  real = resolved;
32147
32361
  }
32148
- const stat4 = fs6.statSync(real);
32149
- if (!stat4.isFile()) return { error: "Not a file" };
32362
+ const stat = fs7.statSync(real);
32363
+ if (!stat.isFile()) return { error: "Not a file" };
32150
32364
  return real;
32151
32365
  }
32152
32366
  var LINE_CHUNK_SIZE = 64 * 1024;
32153
32367
  function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
32154
- const fileSize = fs6.statSync(filePath).size;
32155
- const fd = fs6.openSync(filePath, "r");
32368
+ const fileSize = fs7.statSync(filePath).size;
32369
+ const fd = fs7.openSync(filePath, "r");
32156
32370
  const bufSize = 64 * 1024;
32157
32371
  const buf = Buffer.alloc(bufSize);
32158
32372
  const decoder = new StringDecoder("utf8");
@@ -32165,7 +32379,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
32165
32379
  let line0Accum = "";
32166
32380
  try {
32167
32381
  let bytesRead;
32168
- while (!done && (bytesRead = fs6.readSync(fd, buf, 0, bufSize, null)) > 0) {
32382
+ while (!done && (bytesRead = fs7.readSync(fd, buf, 0, bufSize, null)) > 0) {
32169
32383
  const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
32170
32384
  partial2 = "";
32171
32385
  let lineStart = 0;
@@ -32300,7 +32514,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
32300
32514
  }
32301
32515
  return { content: resultLines.join("\n"), size: fileSize };
32302
32516
  } finally {
32303
- fs6.closeSync(fd);
32517
+ fs7.closeSync(fd);
32304
32518
  }
32305
32519
  }
32306
32520
  function readFile(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
@@ -32311,26 +32525,26 @@ function readFile(relativePath, startLine, endLine, lineOffset, lineChunkSize =
32311
32525
  if (hasRange) {
32312
32526
  return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
32313
32527
  }
32314
- const stat4 = fs6.statSync(result);
32315
- const raw = fs6.readFileSync(result, "utf8");
32528
+ const stat = fs7.statSync(result);
32529
+ const raw = fs7.readFileSync(result, "utf8");
32316
32530
  const lines = raw.split(/\r?\n/);
32317
- return { content: raw, totalLines: lines.length, size: stat4.size };
32531
+ return { content: raw, totalLines: lines.length, size: stat.size };
32318
32532
  } catch (err) {
32319
32533
  return { error: err instanceof Error ? err.message : String(err) };
32320
32534
  }
32321
32535
  }
32322
32536
 
32323
32537
  // src/files/file-index.ts
32324
- import fs7 from "node:fs";
32325
- import path13 from "node:path";
32538
+ import fs8 from "node:fs";
32539
+ import path14 from "node:path";
32326
32540
  import os2 from "node:os";
32327
32541
  import crypto2 from "node:crypto";
32328
- var INDEX_DIR = path13.join(os2.homedir(), ".buildautomaton");
32542
+ var INDEX_DIR = path14.join(os2.homedir(), ".buildautomaton");
32329
32543
  var HASH_LEN = 16;
32330
32544
  var INDEX_VERSION = 2;
32331
- function getIndexPath(cwd3) {
32332
- const hash = crypto2.createHash("sha256").update(cwd3).digest("hex").slice(0, HASH_LEN);
32333
- return path13.join(INDEX_DIR, `.file-index-${hash}.json`);
32545
+ function getIndexPath(cwd) {
32546
+ const hash = crypto2.createHash("sha256").update(cwd).digest("hex").slice(0, HASH_LEN);
32547
+ return path14.join(INDEX_DIR, `.file-index-${hash}.json`);
32334
32548
  }
32335
32549
  function getTrigrams(s) {
32336
32550
  const lower = s.toLowerCase();
@@ -32368,29 +32582,29 @@ function binarySearch(arr, x) {
32368
32582
  function walkDir(dir, baseDir, out) {
32369
32583
  let names;
32370
32584
  try {
32371
- names = fs7.readdirSync(dir);
32585
+ names = fs8.readdirSync(dir);
32372
32586
  } catch {
32373
32587
  return;
32374
32588
  }
32375
32589
  for (const name of names) {
32376
32590
  if (name.startsWith(".")) continue;
32377
- const full = path13.join(dir, name);
32378
- let stat4;
32591
+ const full = path14.join(dir, name);
32592
+ let stat;
32379
32593
  try {
32380
- stat4 = fs7.statSync(full);
32594
+ stat = fs8.statSync(full);
32381
32595
  } catch {
32382
32596
  continue;
32383
32597
  }
32384
- const relative6 = path13.relative(baseDir, full).replace(/\\/g, "/");
32385
- if (stat4.isDirectory()) {
32598
+ const relative4 = path14.relative(baseDir, full).replace(/\\/g, "/");
32599
+ if (stat.isDirectory()) {
32386
32600
  walkDir(full, baseDir, out);
32387
- } else if (stat4.isFile()) {
32388
- out.push(relative6);
32601
+ } else if (stat.isFile()) {
32602
+ out.push(relative4);
32389
32603
  }
32390
32604
  }
32391
32605
  }
32392
- function buildFileIndex(cwd3) {
32393
- const resolved = path13.resolve(cwd3);
32606
+ function buildFileIndex(cwd) {
32607
+ const resolved = path14.resolve(cwd);
32394
32608
  const paths = [];
32395
32609
  walkDir(resolved, resolved, paths);
32396
32610
  paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
@@ -32408,18 +32622,18 @@ function buildFileIndex(cwd3) {
32408
32622
  const data = { version: INDEX_VERSION, paths, trigramIndex };
32409
32623
  const indexPath = getIndexPath(resolved);
32410
32624
  try {
32411
- if (!fs7.existsSync(INDEX_DIR)) fs7.mkdirSync(INDEX_DIR, { recursive: true });
32412
- fs7.writeFileSync(indexPath, JSON.stringify(data), "utf8");
32625
+ if (!fs8.existsSync(INDEX_DIR)) fs8.mkdirSync(INDEX_DIR, { recursive: true });
32626
+ fs8.writeFileSync(indexPath, JSON.stringify(data), "utf8");
32413
32627
  } catch (e) {
32414
32628
  console.error("[file-index] Failed to write index:", e);
32415
32629
  }
32416
32630
  return data;
32417
32631
  }
32418
- function loadFileIndex(cwd3) {
32419
- const resolved = path13.resolve(cwd3);
32632
+ function loadFileIndex(cwd) {
32633
+ const resolved = path14.resolve(cwd);
32420
32634
  const indexPath = getIndexPath(resolved);
32421
32635
  try {
32422
- const raw = fs7.readFileSync(indexPath, "utf8");
32636
+ const raw = fs8.readFileSync(indexPath, "utf8");
32423
32637
  const parsed = JSON.parse(raw);
32424
32638
  if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
32425
32639
  const obj = parsed;
@@ -32436,8 +32650,8 @@ function loadFileIndex(cwd3) {
32436
32650
  return null;
32437
32651
  }
32438
32652
  }
32439
- function ensureFileIndex(cwd3) {
32440
- const resolved = path13.resolve(cwd3);
32653
+ function ensureFileIndex(cwd) {
32654
+ const resolved = path14.resolve(cwd);
32441
32655
  const cached2 = loadFileIndex(resolved);
32442
32656
  if (cached2 !== null) return { data: cached2, fromCache: true };
32443
32657
  const data = buildFileIndex(resolved);
@@ -32475,8 +32689,8 @@ function searchFileIndex(index, query, limit = 100) {
32475
32689
  var SEARCH_LIMIT = 100;
32476
32690
  function handleFileBrowserSearch(msg, socket) {
32477
32691
  const q = typeof msg.q === "string" ? msg.q : "";
32478
- const cwd3 = process.cwd();
32479
- const index = loadFileIndex(cwd3);
32692
+ const cwd = getBridgeWorkspaceDirectory();
32693
+ const index = loadFileIndex(cwd);
32480
32694
  if (index === null) {
32481
32695
  sendWsMessage(socket, {
32482
32696
  type: "file_browser_search_response",
@@ -32497,7 +32711,7 @@ function handleFileBrowserSearch(msg, socket) {
32497
32711
  function triggerFileIndexBuild() {
32498
32712
  setImmediate(() => {
32499
32713
  try {
32500
- ensureFileIndex(process.cwd());
32714
+ ensureFileIndex(getBridgeWorkspaceDirectory());
32501
32715
  } catch (e) {
32502
32716
  console.error("[file-index] Background build failed:", e);
32503
32717
  }
@@ -32558,30 +32772,30 @@ function handleFileBrowserSearchMessage(msg, { getWs }) {
32558
32772
  }
32559
32773
 
32560
32774
  // src/skills/discover-local-agent-skills.ts
32561
- import fs8 from "node:fs";
32562
- import path14 from "node:path";
32775
+ import fs9 from "node:fs";
32776
+ import path15 from "node:path";
32563
32777
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
32564
- function discoverLocalSkills(cwd3) {
32778
+ function discoverLocalSkills(cwd) {
32565
32779
  const out = [];
32566
32780
  const seenKeys = /* @__PURE__ */ new Set();
32567
32781
  for (const rel of SKILL_DISCOVERY_ROOTS) {
32568
- const base = path14.join(cwd3, rel);
32569
- if (!fs8.existsSync(base) || !fs8.statSync(base).isDirectory()) continue;
32782
+ const base = path15.join(cwd, rel);
32783
+ if (!fs9.existsSync(base) || !fs9.statSync(base).isDirectory()) continue;
32570
32784
  let entries = [];
32571
32785
  try {
32572
- entries = fs8.readdirSync(base);
32786
+ entries = fs9.readdirSync(base);
32573
32787
  } catch {
32574
32788
  continue;
32575
32789
  }
32576
32790
  for (const name of entries) {
32577
- const dir = path14.join(base, name);
32791
+ const dir = path15.join(base, name);
32578
32792
  try {
32579
- if (!fs8.statSync(dir).isDirectory()) continue;
32793
+ if (!fs9.statSync(dir).isDirectory()) continue;
32580
32794
  } catch {
32581
32795
  continue;
32582
32796
  }
32583
- const skillMd = path14.join(dir, "SKILL.md");
32584
- if (!fs8.existsSync(skillMd)) continue;
32797
+ const skillMd = path15.join(dir, "SKILL.md");
32798
+ if (!fs9.existsSync(skillMd)) continue;
32585
32799
  const key = `${rel}/${name}`;
32586
32800
  if (seenKeys.has(key)) continue;
32587
32801
  seenKeys.add(key);
@@ -32590,26 +32804,26 @@ function discoverLocalSkills(cwd3) {
32590
32804
  }
32591
32805
  return out;
32592
32806
  }
32593
- function discoverSkillLayoutRoots(cwd3) {
32807
+ function discoverSkillLayoutRoots(cwd) {
32594
32808
  const roots = [];
32595
32809
  for (const rel of SKILL_DISCOVERY_ROOTS) {
32596
- const base = path14.join(cwd3, rel);
32597
- if (!fs8.existsSync(base) || !fs8.statSync(base).isDirectory()) continue;
32810
+ const base = path15.join(cwd, rel);
32811
+ if (!fs9.existsSync(base) || !fs9.statSync(base).isDirectory()) continue;
32598
32812
  let entries = [];
32599
32813
  try {
32600
- entries = fs8.readdirSync(base);
32814
+ entries = fs9.readdirSync(base);
32601
32815
  } catch {
32602
32816
  continue;
32603
32817
  }
32604
32818
  const skills2 = [];
32605
32819
  for (const name of entries) {
32606
- const dir = path14.join(base, name);
32820
+ const dir = path15.join(base, name);
32607
32821
  try {
32608
- if (!fs8.statSync(dir).isDirectory()) continue;
32822
+ if (!fs9.statSync(dir).isDirectory()) continue;
32609
32823
  } catch {
32610
32824
  continue;
32611
32825
  }
32612
- if (!fs8.existsSync(path14.join(dir, "SKILL.md"))) continue;
32826
+ if (!fs9.existsSync(path15.join(dir, "SKILL.md"))) continue;
32613
32827
  const relPath = `${rel}/${name}`.replace(/\\/g, "/");
32614
32828
  skills2.push({ name, relPath });
32615
32829
  }
@@ -32624,14 +32838,14 @@ function discoverSkillLayoutRoots(cwd3) {
32624
32838
  function handleSkillLayoutRequest(msg, deps) {
32625
32839
  const socket = deps.getWs();
32626
32840
  const id = typeof msg.id === "string" ? msg.id : "";
32627
- const roots = discoverSkillLayoutRoots(process.cwd());
32841
+ const roots = discoverSkillLayoutRoots(getBridgeWorkspaceDirectory());
32628
32842
  socket?.send(JSON.stringify({ type: "skill_layout_response", id, roots }));
32629
32843
  }
32630
32844
 
32631
32845
  // src/skills/install-remote-skills.ts
32632
- import fs9 from "node:fs";
32633
- import path15 from "node:path";
32634
- function installRemoteSkills(cwd3, targetDir, items) {
32846
+ import fs10 from "node:fs";
32847
+ import path16 from "node:path";
32848
+ function installRemoteSkills(cwd, targetDir, items) {
32635
32849
  const installed = [];
32636
32850
  if (!Array.isArray(items)) {
32637
32851
  return { success: false, error: "Invalid items" };
@@ -32641,15 +32855,15 @@ function installRemoteSkills(cwd3, targetDir, items) {
32641
32855
  if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
32642
32856
  continue;
32643
32857
  }
32644
- const skillDir = path15.join(cwd3, targetDir, item.skillName);
32858
+ const skillDir = path16.join(cwd, targetDir, item.skillName);
32645
32859
  for (const f of item.files) {
32646
32860
  if (typeof f.path !== "string" || !f.text && !f.base64) continue;
32647
- const dest = path15.join(skillDir, f.path);
32648
- fs9.mkdirSync(path15.dirname(dest), { recursive: true });
32861
+ const dest = path16.join(skillDir, f.path);
32862
+ fs10.mkdirSync(path16.dirname(dest), { recursive: true });
32649
32863
  if (f.text !== void 0) {
32650
- fs9.writeFileSync(dest, f.text, "utf8");
32864
+ fs10.writeFileSync(dest, f.text, "utf8");
32651
32865
  } else if (f.base64) {
32652
- fs9.writeFileSync(dest, Buffer.from(f.base64, "base64"));
32866
+ fs10.writeFileSync(dest, Buffer.from(f.base64, "base64"));
32653
32867
  }
32654
32868
  }
32655
32869
  installed.push({
@@ -32670,11 +32884,11 @@ var handleInstallSkillsMessage = (msg, deps) => {
32670
32884
  const id = typeof msg.id === "string" ? msg.id : "";
32671
32885
  const targetDir = typeof msg.targetDir === "string" && msg.targetDir.trim() ? msg.targetDir.trim() : ".agents/skills";
32672
32886
  const rawItems = msg.items;
32673
- const cwd3 = process.cwd();
32674
- const result = installRemoteSkills(cwd3, targetDir, rawItems);
32887
+ const cwd = getBridgeWorkspaceDirectory();
32888
+ const result = installRemoteSkills(cwd, targetDir, rawItems);
32675
32889
  if (!result.success) {
32676
32890
  const err = result.error ?? "Invalid items";
32677
- deps.log(`[Bridge service] install_skills failed: ${err}`);
32891
+ deps.log(`[Bridge service] Install skills failed: ${err}`);
32678
32892
  socket?.send(JSON.stringify({ type: "install_skills_result", id, success: false, error: err }));
32679
32893
  return;
32680
32894
  }
@@ -32743,8 +32957,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
32743
32957
  };
32744
32958
 
32745
32959
  // src/bridge/routing/handlers/revert-turn-snapshot.ts
32746
- import * as fs10 from "node:fs";
32747
- import * as path16 from "node:path";
32960
+ import * as fs11 from "node:fs";
32748
32961
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
32749
32962
  const id = typeof msg.id === "string" ? msg.id : "";
32750
32963
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -32754,9 +32967,9 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
32754
32967
  void (async () => {
32755
32968
  const s = getWs();
32756
32969
  if (!s) return;
32757
- const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? path16.resolve(process.cwd());
32970
+ const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
32758
32971
  const file2 = snapshotFilePath(agentBase, turnId);
32759
- if (!fs10.existsSync(file2)) {
32972
+ if (!fs11.existsSync(file2)) {
32760
32973
  sendWsMessage(s, {
32761
32974
  type: "revert_turn_snapshot_result",
32762
32975
  id,
@@ -32883,7 +33096,7 @@ import * as path20 from "node:path";
32883
33096
  import os4 from "node:os";
32884
33097
 
32885
33098
  // src/worktrees/prepare-new-session-worktrees.ts
32886
- import * as fs12 from "node:fs";
33099
+ import * as fs13 from "node:fs";
32887
33100
  import * as path18 from "node:path";
32888
33101
 
32889
33102
  // src/git/worktree-add.ts
@@ -32893,7 +33106,7 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
32893
33106
  }
32894
33107
 
32895
33108
  // src/worktrees/worktree-layout-file.ts
32896
- import * as fs11 from "node:fs";
33109
+ import * as fs12 from "node:fs";
32897
33110
  import * as path17 from "node:path";
32898
33111
  import os3 from "node:os";
32899
33112
  var LAYOUT_FILENAME = "worktree-launcher-layout.json";
@@ -32910,8 +33123,8 @@ function normalizeLoadedLayout(raw) {
32910
33123
  function loadWorktreeLayout() {
32911
33124
  try {
32912
33125
  const p = defaultWorktreeLayoutPath();
32913
- if (!fs11.existsSync(p)) return { launcherCwds: [] };
32914
- const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
33126
+ if (!fs12.existsSync(p)) return { launcherCwds: [] };
33127
+ const raw = JSON.parse(fs12.readFileSync(p, "utf8"));
32915
33128
  return normalizeLoadedLayout(raw);
32916
33129
  } catch {
32917
33130
  return { launcherCwds: [] };
@@ -32920,8 +33133,8 @@ function loadWorktreeLayout() {
32920
33133
  function saveWorktreeLayout(layout) {
32921
33134
  try {
32922
33135
  const dir = path17.dirname(defaultWorktreeLayoutPath());
32923
- fs11.mkdirSync(dir, { recursive: true });
32924
- fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
33136
+ fs12.mkdirSync(dir, { recursive: true });
33137
+ fs12.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
32925
33138
  } catch {
32926
33139
  }
32927
33140
  }
@@ -32953,25 +33166,25 @@ async function prepareNewSessionWorktrees(options) {
32953
33166
  const agentMirrorRoot = path18.join(rootAbs, cwdKey);
32954
33167
  const repos = await discoverGitReposUnderRoot(launcherResolved);
32955
33168
  if (repos.length === 0) {
32956
- log2("[worktrees] No git repos under launcher cwd; skipping worktree creation");
33169
+ log2("[worktrees] No Git repositories under launcher working directory; skipping worktree creation.");
32957
33170
  return null;
32958
33171
  }
32959
33172
  const branch = `session-${sessionId}`;
32960
33173
  const worktreePaths = [];
32961
- fs12.mkdirSync(agentMirrorRoot, { recursive: true });
33174
+ fs13.mkdirSync(agentMirrorRoot, { recursive: true });
32962
33175
  for (const repo of repos) {
32963
33176
  let rel = path18.relative(launcherResolved, repo.absolutePath);
32964
33177
  if (rel.startsWith("..") || path18.isAbsolute(rel)) continue;
32965
33178
  const relNorm = rel === "" ? "." : rel;
32966
33179
  const wtPath = path18.join(agentMirrorRoot, relNorm, sessionId);
32967
- fs12.mkdirSync(path18.dirname(wtPath), { recursive: true });
33180
+ fs13.mkdirSync(path18.dirname(wtPath), { recursive: true });
32968
33181
  try {
32969
33182
  await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
32970
- log2(`[worktrees] Added worktree ${wtPath} (branch ${branch})`);
33183
+ log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
32971
33184
  worktreePaths.push(wtPath);
32972
33185
  } catch (e) {
32973
33186
  log2(
32974
- `[worktrees] worktree add failed for ${repo.absolutePath}: ${e instanceof Error ? e.message : String(e)}`
33187
+ `[worktrees] Worktree add failed for ${repo.absolutePath}: ${e instanceof Error ? e.message : String(e)}`
32975
33188
  );
32976
33189
  }
32977
33190
  }
@@ -32993,24 +33206,26 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
32993
33206
  await gitRenameCurrentBranch(wt, safe);
32994
33207
  log2(`[worktrees] Renamed branch in ${wt} \u2192 ${safe}`);
32995
33208
  } catch (e) {
32996
- log2(`[worktrees] branch rename failed in ${wt}: ${e instanceof Error ? e.message : String(e)}`);
33209
+ log2(
33210
+ `[worktrees] Branch rename failed in ${wt}: ${e instanceof Error ? e.message : String(e)}`
33211
+ );
32997
33212
  }
32998
33213
  }
32999
33214
  }
33000
33215
 
33001
33216
  // src/worktrees/remove-session-worktrees.ts
33002
- import * as fs15 from "node:fs";
33217
+ import * as fs16 from "node:fs";
33003
33218
 
33004
33219
  // src/git/worktree-remove.ts
33005
- import * as fs14 from "node:fs";
33220
+ import * as fs15 from "node:fs";
33006
33221
 
33007
33222
  // src/git/resolve-main-repo-from-git-file.ts
33008
- import * as fs13 from "node:fs";
33223
+ import * as fs14 from "node:fs";
33009
33224
  import * as path19 from "node:path";
33010
33225
  function resolveMainRepoFromWorktreeGitFile(wt) {
33011
33226
  const gitDirFile = path19.join(wt, ".git");
33012
- if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
33013
- const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
33227
+ if (!fs14.existsSync(gitDirFile) || !fs14.statSync(gitDirFile).isFile()) return "";
33228
+ const first2 = fs14.readFileSync(gitDirFile, "utf8").trim();
33014
33229
  const m = first2.match(/^gitdir:\s*(.+)$/im);
33015
33230
  if (!m) return "";
33016
33231
  const gitWorktreePath = path19.resolve(wt, m[1].trim());
@@ -33024,7 +33239,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
33024
33239
  if (mainRepo) {
33025
33240
  await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
33026
33241
  } else {
33027
- fs14.rmSync(worktreePath, { recursive: true, force: true });
33242
+ fs15.rmSync(worktreePath, { recursive: true, force: true });
33028
33243
  }
33029
33244
  }
33030
33245
 
@@ -33035,9 +33250,9 @@ async function removeSessionWorktrees(paths, log2) {
33035
33250
  await gitWorktreeRemoveForce(wt);
33036
33251
  log2(`[worktrees] Removed worktree ${wt}`);
33037
33252
  } catch (e) {
33038
- log2(`[worktrees] remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
33253
+ log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
33039
33254
  try {
33040
- fs15.rmSync(wt, { recursive: true, force: true });
33255
+ fs16.rmSync(wt, { recursive: true, force: true });
33041
33256
  } catch {
33042
33257
  }
33043
33258
  }
@@ -33101,7 +33316,7 @@ var SessionWorktreeManager = class {
33101
33316
  return this.bridgeWantsWorktrees;
33102
33317
  }
33103
33318
  /**
33104
- * Returns cwd for the agent (mirror of launcher tree), or undefined to use process.cwd().
33319
+ * Returns cwd for the agent (mirror of launcher tree), or undefined to use the bridge workspace directory.
33105
33320
  */
33106
33321
  async resolveCwdForPrompt(sessionId, opts) {
33107
33322
  if (!sessionId || !this.effective() || !opts.sessionWorktreesEnabled) {
@@ -33114,7 +33329,7 @@ var SessionWorktreeManager = class {
33114
33329
  }
33115
33330
  const prep = await prepareNewSessionWorktrees({
33116
33331
  rootAbs: this.rootAbs,
33117
- launcherCwd: process.cwd(),
33332
+ launcherCwd: getBridgeWorkspaceDirectory(),
33118
33333
  sessionId,
33119
33334
  layout: this.layout,
33120
33335
  log: this.log
@@ -33154,7 +33369,7 @@ var SessionWorktreeManager = class {
33154
33369
  }
33155
33370
  async commitSession(params) {
33156
33371
  const paths = this.sessionPaths.get(params.sessionId);
33157
- const targets = paths?.length ? paths : [process.cwd()];
33372
+ const targets = paths?.length ? paths : [getBridgeWorkspaceDirectory()];
33158
33373
  return commitSessionWorktrees({
33159
33374
  paths: targets,
33160
33375
  branch: params.branch,
@@ -33195,1700 +33410,8 @@ async function refreshBridgeTokens(params) {
33195
33410
  }
33196
33411
 
33197
33412
  // src/files/watch-file-index.ts
33413
+ import { watch } from "node:fs";
33198
33414
  import path21 from "node:path";
33199
-
33200
- // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
33201
- import { stat as statcb } from "fs";
33202
- import { stat as stat3, readdir as readdir2 } from "fs/promises";
33203
- import { EventEmitter as EventEmitter2 } from "events";
33204
- import * as sysPath2 from "path";
33205
-
33206
- // ../../node_modules/.pnpm/readdirp@4.1.2/node_modules/readdirp/esm/index.js
33207
- import { stat, lstat, readdir, realpath } from "node:fs/promises";
33208
- import { Readable as Readable2 } from "node:stream";
33209
- import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "node:path";
33210
- var EntryTypes = {
33211
- FILE_TYPE: "files",
33212
- DIR_TYPE: "directories",
33213
- FILE_DIR_TYPE: "files_directories",
33214
- EVERYTHING_TYPE: "all"
33215
- };
33216
- var defaultOptions2 = {
33217
- root: ".",
33218
- fileFilter: (_entryInfo) => true,
33219
- directoryFilter: (_entryInfo) => true,
33220
- type: EntryTypes.FILE_TYPE,
33221
- lstat: false,
33222
- depth: 2147483648,
33223
- alwaysStat: false,
33224
- highWaterMark: 4096
33225
- };
33226
- Object.freeze(defaultOptions2);
33227
- var RECURSIVE_ERROR_CODE = "READDIRP_RECURSIVE_ERROR";
33228
- var NORMAL_FLOW_ERRORS = /* @__PURE__ */ new Set(["ENOENT", "EPERM", "EACCES", "ELOOP", RECURSIVE_ERROR_CODE]);
33229
- var ALL_TYPES = [
33230
- EntryTypes.DIR_TYPE,
33231
- EntryTypes.EVERYTHING_TYPE,
33232
- EntryTypes.FILE_DIR_TYPE,
33233
- EntryTypes.FILE_TYPE
33234
- ];
33235
- var DIR_TYPES = /* @__PURE__ */ new Set([
33236
- EntryTypes.DIR_TYPE,
33237
- EntryTypes.EVERYTHING_TYPE,
33238
- EntryTypes.FILE_DIR_TYPE
33239
- ]);
33240
- var FILE_TYPES = /* @__PURE__ */ new Set([
33241
- EntryTypes.EVERYTHING_TYPE,
33242
- EntryTypes.FILE_DIR_TYPE,
33243
- EntryTypes.FILE_TYPE
33244
- ]);
33245
- var isNormalFlowError = (error40) => NORMAL_FLOW_ERRORS.has(error40.code);
33246
- var wantBigintFsStats = process.platform === "win32";
33247
- var emptyFn = (_entryInfo) => true;
33248
- var normalizeFilter = (filter) => {
33249
- if (filter === void 0)
33250
- return emptyFn;
33251
- if (typeof filter === "function")
33252
- return filter;
33253
- if (typeof filter === "string") {
33254
- const fl = filter.trim();
33255
- return (entry) => entry.basename === fl;
33256
- }
33257
- if (Array.isArray(filter)) {
33258
- const trItems = filter.map((item) => item.trim());
33259
- return (entry) => trItems.some((f) => entry.basename === f);
33260
- }
33261
- return emptyFn;
33262
- };
33263
- var ReaddirpStream = class extends Readable2 {
33264
- constructor(options = {}) {
33265
- super({
33266
- objectMode: true,
33267
- autoDestroy: true,
33268
- highWaterMark: options.highWaterMark
33269
- });
33270
- const opts = { ...defaultOptions2, ...options };
33271
- const { root, type } = opts;
33272
- this._fileFilter = normalizeFilter(opts.fileFilter);
33273
- this._directoryFilter = normalizeFilter(opts.directoryFilter);
33274
- const statMethod = opts.lstat ? lstat : stat;
33275
- if (wantBigintFsStats) {
33276
- this._stat = (path25) => statMethod(path25, { bigint: true });
33277
- } else {
33278
- this._stat = statMethod;
33279
- }
33280
- this._maxDepth = opts.depth ?? defaultOptions2.depth;
33281
- this._wantsDir = type ? DIR_TYPES.has(type) : false;
33282
- this._wantsFile = type ? FILE_TYPES.has(type) : false;
33283
- this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
33284
- this._root = presolve(root);
33285
- this._isDirent = !opts.alwaysStat;
33286
- this._statsProp = this._isDirent ? "dirent" : "stats";
33287
- this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
33288
- this.parents = [this._exploreDir(root, 1)];
33289
- this.reading = false;
33290
- this.parent = void 0;
33291
- }
33292
- async _read(batch) {
33293
- if (this.reading)
33294
- return;
33295
- this.reading = true;
33296
- try {
33297
- while (!this.destroyed && batch > 0) {
33298
- const par = this.parent;
33299
- const fil = par && par.files;
33300
- if (fil && fil.length > 0) {
33301
- const { path: path25, depth } = par;
33302
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path25));
33303
- const awaited = await Promise.all(slice);
33304
- for (const entry of awaited) {
33305
- if (!entry)
33306
- continue;
33307
- if (this.destroyed)
33308
- return;
33309
- const entryType = await this._getEntryType(entry);
33310
- if (entryType === "directory" && this._directoryFilter(entry)) {
33311
- if (depth <= this._maxDepth) {
33312
- this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
33313
- }
33314
- if (this._wantsDir) {
33315
- this.push(entry);
33316
- batch--;
33317
- }
33318
- } else if ((entryType === "file" || this._includeAsFile(entry)) && this._fileFilter(entry)) {
33319
- if (this._wantsFile) {
33320
- this.push(entry);
33321
- batch--;
33322
- }
33323
- }
33324
- }
33325
- } else {
33326
- const parent = this.parents.pop();
33327
- if (!parent) {
33328
- this.push(null);
33329
- break;
33330
- }
33331
- this.parent = await parent;
33332
- if (this.destroyed)
33333
- return;
33334
- }
33335
- }
33336
- } catch (error40) {
33337
- this.destroy(error40);
33338
- } finally {
33339
- this.reading = false;
33340
- }
33341
- }
33342
- async _exploreDir(path25, depth) {
33343
- let files;
33344
- try {
33345
- files = await readdir(path25, this._rdOptions);
33346
- } catch (error40) {
33347
- this._onError(error40);
33348
- }
33349
- return { files, depth, path: path25 };
33350
- }
33351
- async _formatEntry(dirent, path25) {
33352
- let entry;
33353
- const basename6 = this._isDirent ? dirent.name : dirent;
33354
- try {
33355
- const fullPath = presolve(pjoin(path25, basename6));
33356
- entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
33357
- entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
33358
- } catch (err) {
33359
- this._onError(err);
33360
- return;
33361
- }
33362
- return entry;
33363
- }
33364
- _onError(err) {
33365
- if (isNormalFlowError(err) && !this.destroyed) {
33366
- this.emit("warn", err);
33367
- } else {
33368
- this.destroy(err);
33369
- }
33370
- }
33371
- async _getEntryType(entry) {
33372
- if (!entry && this._statsProp in entry) {
33373
- return "";
33374
- }
33375
- const stats = entry[this._statsProp];
33376
- if (stats.isFile())
33377
- return "file";
33378
- if (stats.isDirectory())
33379
- return "directory";
33380
- if (stats && stats.isSymbolicLink()) {
33381
- const full = entry.fullPath;
33382
- try {
33383
- const entryRealPath = await realpath(full);
33384
- const entryRealPathStats = await lstat(entryRealPath);
33385
- if (entryRealPathStats.isFile()) {
33386
- return "file";
33387
- }
33388
- if (entryRealPathStats.isDirectory()) {
33389
- const len = entryRealPath.length;
33390
- if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {
33391
- const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
33392
- recursiveError.code = RECURSIVE_ERROR_CODE;
33393
- return this._onError(recursiveError);
33394
- }
33395
- return "directory";
33396
- }
33397
- } catch (error40) {
33398
- this._onError(error40);
33399
- return "";
33400
- }
33401
- }
33402
- }
33403
- _includeAsFile(entry) {
33404
- const stats = entry && entry[this._statsProp];
33405
- return stats && this._wantsEverything && !stats.isDirectory();
33406
- }
33407
- };
33408
- function readdirp(root, options = {}) {
33409
- let type = options.entryType || options.type;
33410
- if (type === "both")
33411
- type = EntryTypes.FILE_DIR_TYPE;
33412
- if (type)
33413
- options.type = type;
33414
- if (!root) {
33415
- throw new Error("readdirp: root argument is required. Usage: readdirp(root, options)");
33416
- } else if (typeof root !== "string") {
33417
- throw new TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");
33418
- } else if (type && !ALL_TYPES.includes(type)) {
33419
- throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(", ")}`);
33420
- }
33421
- options.root = root;
33422
- return new ReaddirpStream(options);
33423
- }
33424
-
33425
- // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/handler.js
33426
- import { watchFile, unwatchFile, watch as fs_watch } from "fs";
33427
- import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
33428
- import * as sysPath from "path";
33429
- import { type as osType } from "os";
33430
- var STR_DATA = "data";
33431
- var STR_END = "end";
33432
- var STR_CLOSE = "close";
33433
- var EMPTY_FN = () => {
33434
- };
33435
- var pl = process.platform;
33436
- var isWindows = pl === "win32";
33437
- var isMacos = pl === "darwin";
33438
- var isLinux = pl === "linux";
33439
- var isFreeBSD = pl === "freebsd";
33440
- var isIBMi = osType() === "OS400";
33441
- var EVENTS = {
33442
- ALL: "all",
33443
- READY: "ready",
33444
- ADD: "add",
33445
- CHANGE: "change",
33446
- ADD_DIR: "addDir",
33447
- UNLINK: "unlink",
33448
- UNLINK_DIR: "unlinkDir",
33449
- RAW: "raw",
33450
- ERROR: "error"
33451
- };
33452
- var EV = EVENTS;
33453
- var THROTTLE_MODE_WATCH = "watch";
33454
- var statMethods = { lstat: lstat2, stat: stat2 };
33455
- var KEY_LISTENERS = "listeners";
33456
- var KEY_ERR = "errHandlers";
33457
- var KEY_RAW = "rawEmitters";
33458
- var HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
33459
- var binaryExtensions = /* @__PURE__ */ new Set([
33460
- "3dm",
33461
- "3ds",
33462
- "3g2",
33463
- "3gp",
33464
- "7z",
33465
- "a",
33466
- "aac",
33467
- "adp",
33468
- "afdesign",
33469
- "afphoto",
33470
- "afpub",
33471
- "ai",
33472
- "aif",
33473
- "aiff",
33474
- "alz",
33475
- "ape",
33476
- "apk",
33477
- "appimage",
33478
- "ar",
33479
- "arj",
33480
- "asf",
33481
- "au",
33482
- "avi",
33483
- "bak",
33484
- "baml",
33485
- "bh",
33486
- "bin",
33487
- "bk",
33488
- "bmp",
33489
- "btif",
33490
- "bz2",
33491
- "bzip2",
33492
- "cab",
33493
- "caf",
33494
- "cgm",
33495
- "class",
33496
- "cmx",
33497
- "cpio",
33498
- "cr2",
33499
- "cur",
33500
- "dat",
33501
- "dcm",
33502
- "deb",
33503
- "dex",
33504
- "djvu",
33505
- "dll",
33506
- "dmg",
33507
- "dng",
33508
- "doc",
33509
- "docm",
33510
- "docx",
33511
- "dot",
33512
- "dotm",
33513
- "dra",
33514
- "DS_Store",
33515
- "dsk",
33516
- "dts",
33517
- "dtshd",
33518
- "dvb",
33519
- "dwg",
33520
- "dxf",
33521
- "ecelp4800",
33522
- "ecelp7470",
33523
- "ecelp9600",
33524
- "egg",
33525
- "eol",
33526
- "eot",
33527
- "epub",
33528
- "exe",
33529
- "f4v",
33530
- "fbs",
33531
- "fh",
33532
- "fla",
33533
- "flac",
33534
- "flatpak",
33535
- "fli",
33536
- "flv",
33537
- "fpx",
33538
- "fst",
33539
- "fvt",
33540
- "g3",
33541
- "gh",
33542
- "gif",
33543
- "graffle",
33544
- "gz",
33545
- "gzip",
33546
- "h261",
33547
- "h263",
33548
- "h264",
33549
- "icns",
33550
- "ico",
33551
- "ief",
33552
- "img",
33553
- "ipa",
33554
- "iso",
33555
- "jar",
33556
- "jpeg",
33557
- "jpg",
33558
- "jpgv",
33559
- "jpm",
33560
- "jxr",
33561
- "key",
33562
- "ktx",
33563
- "lha",
33564
- "lib",
33565
- "lvp",
33566
- "lz",
33567
- "lzh",
33568
- "lzma",
33569
- "lzo",
33570
- "m3u",
33571
- "m4a",
33572
- "m4v",
33573
- "mar",
33574
- "mdi",
33575
- "mht",
33576
- "mid",
33577
- "midi",
33578
- "mj2",
33579
- "mka",
33580
- "mkv",
33581
- "mmr",
33582
- "mng",
33583
- "mobi",
33584
- "mov",
33585
- "movie",
33586
- "mp3",
33587
- "mp4",
33588
- "mp4a",
33589
- "mpeg",
33590
- "mpg",
33591
- "mpga",
33592
- "mxu",
33593
- "nef",
33594
- "npx",
33595
- "numbers",
33596
- "nupkg",
33597
- "o",
33598
- "odp",
33599
- "ods",
33600
- "odt",
33601
- "oga",
33602
- "ogg",
33603
- "ogv",
33604
- "otf",
33605
- "ott",
33606
- "pages",
33607
- "pbm",
33608
- "pcx",
33609
- "pdb",
33610
- "pdf",
33611
- "pea",
33612
- "pgm",
33613
- "pic",
33614
- "png",
33615
- "pnm",
33616
- "pot",
33617
- "potm",
33618
- "potx",
33619
- "ppa",
33620
- "ppam",
33621
- "ppm",
33622
- "pps",
33623
- "ppsm",
33624
- "ppsx",
33625
- "ppt",
33626
- "pptm",
33627
- "pptx",
33628
- "psd",
33629
- "pya",
33630
- "pyc",
33631
- "pyo",
33632
- "pyv",
33633
- "qt",
33634
- "rar",
33635
- "ras",
33636
- "raw",
33637
- "resources",
33638
- "rgb",
33639
- "rip",
33640
- "rlc",
33641
- "rmf",
33642
- "rmvb",
33643
- "rpm",
33644
- "rtf",
33645
- "rz",
33646
- "s3m",
33647
- "s7z",
33648
- "scpt",
33649
- "sgi",
33650
- "shar",
33651
- "snap",
33652
- "sil",
33653
- "sketch",
33654
- "slk",
33655
- "smv",
33656
- "snk",
33657
- "so",
33658
- "stl",
33659
- "suo",
33660
- "sub",
33661
- "swf",
33662
- "tar",
33663
- "tbz",
33664
- "tbz2",
33665
- "tga",
33666
- "tgz",
33667
- "thmx",
33668
- "tif",
33669
- "tiff",
33670
- "tlz",
33671
- "ttc",
33672
- "ttf",
33673
- "txz",
33674
- "udf",
33675
- "uvh",
33676
- "uvi",
33677
- "uvm",
33678
- "uvp",
33679
- "uvs",
33680
- "uvu",
33681
- "viv",
33682
- "vob",
33683
- "war",
33684
- "wav",
33685
- "wax",
33686
- "wbmp",
33687
- "wdp",
33688
- "weba",
33689
- "webm",
33690
- "webp",
33691
- "whl",
33692
- "wim",
33693
- "wm",
33694
- "wma",
33695
- "wmv",
33696
- "wmx",
33697
- "woff",
33698
- "woff2",
33699
- "wrm",
33700
- "wvx",
33701
- "xbm",
33702
- "xif",
33703
- "xla",
33704
- "xlam",
33705
- "xls",
33706
- "xlsb",
33707
- "xlsm",
33708
- "xlsx",
33709
- "xlt",
33710
- "xltm",
33711
- "xltx",
33712
- "xm",
33713
- "xmind",
33714
- "xpi",
33715
- "xpm",
33716
- "xwd",
33717
- "xz",
33718
- "z",
33719
- "zip",
33720
- "zipx"
33721
- ]);
33722
- var isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
33723
- var foreach = (val, fn) => {
33724
- if (val instanceof Set) {
33725
- val.forEach(fn);
33726
- } else {
33727
- fn(val);
33728
- }
33729
- };
33730
- var addAndConvert = (main2, prop, item) => {
33731
- let container = main2[prop];
33732
- if (!(container instanceof Set)) {
33733
- main2[prop] = container = /* @__PURE__ */ new Set([container]);
33734
- }
33735
- container.add(item);
33736
- };
33737
- var clearItem = (cont) => (key) => {
33738
- const set2 = cont[key];
33739
- if (set2 instanceof Set) {
33740
- set2.clear();
33741
- } else {
33742
- delete cont[key];
33743
- }
33744
- };
33745
- var delFromSet = (main2, prop, item) => {
33746
- const container = main2[prop];
33747
- if (container instanceof Set) {
33748
- container.delete(item);
33749
- } else if (container === item) {
33750
- delete main2[prop];
33751
- }
33752
- };
33753
- var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
33754
- var FsWatchInstances = /* @__PURE__ */ new Map();
33755
- function createFsWatchInstance(path25, options, listener, errHandler, emitRaw) {
33756
- const handleEvent = (rawEvent, evPath) => {
33757
- listener(path25);
33758
- emitRaw(rawEvent, evPath, { watchedPath: path25 });
33759
- if (evPath && path25 !== evPath) {
33760
- fsWatchBroadcast(sysPath.resolve(path25, evPath), KEY_LISTENERS, sysPath.join(path25, evPath));
33761
- }
33762
- };
33763
- try {
33764
- return fs_watch(path25, {
33765
- persistent: options.persistent
33766
- }, handleEvent);
33767
- } catch (error40) {
33768
- errHandler(error40);
33769
- return void 0;
33770
- }
33771
- }
33772
- var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
33773
- const cont = FsWatchInstances.get(fullPath);
33774
- if (!cont)
33775
- return;
33776
- foreach(cont[listenerType], (listener) => {
33777
- listener(val1, val2, val3);
33778
- });
33779
- };
33780
- var setFsWatchListener = (path25, fullPath, options, handlers) => {
33781
- const { listener, errHandler, rawEmitter } = handlers;
33782
- let cont = FsWatchInstances.get(fullPath);
33783
- let watcher;
33784
- if (!options.persistent) {
33785
- watcher = createFsWatchInstance(path25, options, listener, errHandler, rawEmitter);
33786
- if (!watcher)
33787
- return;
33788
- return watcher.close.bind(watcher);
33789
- }
33790
- if (cont) {
33791
- addAndConvert(cont, KEY_LISTENERS, listener);
33792
- addAndConvert(cont, KEY_ERR, errHandler);
33793
- addAndConvert(cont, KEY_RAW, rawEmitter);
33794
- } else {
33795
- watcher = createFsWatchInstance(
33796
- path25,
33797
- options,
33798
- fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
33799
- errHandler,
33800
- // no need to use broadcast here
33801
- fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
33802
- );
33803
- if (!watcher)
33804
- return;
33805
- watcher.on(EV.ERROR, async (error40) => {
33806
- const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
33807
- if (cont)
33808
- cont.watcherUnusable = true;
33809
- if (isWindows && error40.code === "EPERM") {
33810
- try {
33811
- const fd = await open(path25, "r");
33812
- await fd.close();
33813
- broadcastErr(error40);
33814
- } catch (err) {
33815
- }
33816
- } else {
33817
- broadcastErr(error40);
33818
- }
33819
- });
33820
- cont = {
33821
- listeners: listener,
33822
- errHandlers: errHandler,
33823
- rawEmitters: rawEmitter,
33824
- watcher
33825
- };
33826
- FsWatchInstances.set(fullPath, cont);
33827
- }
33828
- return () => {
33829
- delFromSet(cont, KEY_LISTENERS, listener);
33830
- delFromSet(cont, KEY_ERR, errHandler);
33831
- delFromSet(cont, KEY_RAW, rawEmitter);
33832
- if (isEmptySet(cont.listeners)) {
33833
- cont.watcher.close();
33834
- FsWatchInstances.delete(fullPath);
33835
- HANDLER_KEYS.forEach(clearItem(cont));
33836
- cont.watcher = void 0;
33837
- Object.freeze(cont);
33838
- }
33839
- };
33840
- };
33841
- var FsWatchFileInstances = /* @__PURE__ */ new Map();
33842
- var setFsWatchFileListener = (path25, fullPath, options, handlers) => {
33843
- const { listener, rawEmitter } = handlers;
33844
- let cont = FsWatchFileInstances.get(fullPath);
33845
- const copts = cont && cont.options;
33846
- if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
33847
- unwatchFile(fullPath);
33848
- cont = void 0;
33849
- }
33850
- if (cont) {
33851
- addAndConvert(cont, KEY_LISTENERS, listener);
33852
- addAndConvert(cont, KEY_RAW, rawEmitter);
33853
- } else {
33854
- cont = {
33855
- listeners: listener,
33856
- rawEmitters: rawEmitter,
33857
- options,
33858
- watcher: watchFile(fullPath, options, (curr, prev) => {
33859
- foreach(cont.rawEmitters, (rawEmitter2) => {
33860
- rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
33861
- });
33862
- const currmtime = curr.mtimeMs;
33863
- if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
33864
- foreach(cont.listeners, (listener2) => listener2(path25, curr));
33865
- }
33866
- })
33867
- };
33868
- FsWatchFileInstances.set(fullPath, cont);
33869
- }
33870
- return () => {
33871
- delFromSet(cont, KEY_LISTENERS, listener);
33872
- delFromSet(cont, KEY_RAW, rawEmitter);
33873
- if (isEmptySet(cont.listeners)) {
33874
- FsWatchFileInstances.delete(fullPath);
33875
- unwatchFile(fullPath);
33876
- cont.options = cont.watcher = void 0;
33877
- Object.freeze(cont);
33878
- }
33879
- };
33880
- };
33881
- var NodeFsHandler = class {
33882
- constructor(fsW) {
33883
- this.fsw = fsW;
33884
- this._boundHandleError = (error40) => fsW._handleError(error40);
33885
- }
33886
- /**
33887
- * Watch file for changes with fs_watchFile or fs_watch.
33888
- * @param path to file or dir
33889
- * @param listener on fs change
33890
- * @returns closer for the watcher instance
33891
- */
33892
- _watchWithNodeFs(path25, listener) {
33893
- const opts = this.fsw.options;
33894
- const directory = sysPath.dirname(path25);
33895
- const basename6 = sysPath.basename(path25);
33896
- const parent = this.fsw._getWatchedDir(directory);
33897
- parent.add(basename6);
33898
- const absolutePath = sysPath.resolve(path25);
33899
- const options = {
33900
- persistent: opts.persistent
33901
- };
33902
- if (!listener)
33903
- listener = EMPTY_FN;
33904
- let closer;
33905
- if (opts.usePolling) {
33906
- const enableBin = opts.interval !== opts.binaryInterval;
33907
- options.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
33908
- closer = setFsWatchFileListener(path25, absolutePath, options, {
33909
- listener,
33910
- rawEmitter: this.fsw._emitRaw
33911
- });
33912
- } else {
33913
- closer = setFsWatchListener(path25, absolutePath, options, {
33914
- listener,
33915
- errHandler: this._boundHandleError,
33916
- rawEmitter: this.fsw._emitRaw
33917
- });
33918
- }
33919
- return closer;
33920
- }
33921
- /**
33922
- * Watch a file and emit add event if warranted.
33923
- * @returns closer for the watcher instance
33924
- */
33925
- _handleFile(file2, stats, initialAdd) {
33926
- if (this.fsw.closed) {
33927
- return;
33928
- }
33929
- const dirname7 = sysPath.dirname(file2);
33930
- const basename6 = sysPath.basename(file2);
33931
- const parent = this.fsw._getWatchedDir(dirname7);
33932
- let prevStats = stats;
33933
- if (parent.has(basename6))
33934
- return;
33935
- const listener = async (path25, newStats) => {
33936
- if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
33937
- return;
33938
- if (!newStats || newStats.mtimeMs === 0) {
33939
- try {
33940
- const newStats2 = await stat2(file2);
33941
- if (this.fsw.closed)
33942
- return;
33943
- const at = newStats2.atimeMs;
33944
- const mt = newStats2.mtimeMs;
33945
- if (!at || at <= mt || mt !== prevStats.mtimeMs) {
33946
- this.fsw._emit(EV.CHANGE, file2, newStats2);
33947
- }
33948
- if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
33949
- this.fsw._closeFile(path25);
33950
- prevStats = newStats2;
33951
- const closer2 = this._watchWithNodeFs(file2, listener);
33952
- if (closer2)
33953
- this.fsw._addPathCloser(path25, closer2);
33954
- } else {
33955
- prevStats = newStats2;
33956
- }
33957
- } catch (error40) {
33958
- this.fsw._remove(dirname7, basename6);
33959
- }
33960
- } else if (parent.has(basename6)) {
33961
- const at = newStats.atimeMs;
33962
- const mt = newStats.mtimeMs;
33963
- if (!at || at <= mt || mt !== prevStats.mtimeMs) {
33964
- this.fsw._emit(EV.CHANGE, file2, newStats);
33965
- }
33966
- prevStats = newStats;
33967
- }
33968
- };
33969
- const closer = this._watchWithNodeFs(file2, listener);
33970
- if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file2)) {
33971
- if (!this.fsw._throttle(EV.ADD, file2, 0))
33972
- return;
33973
- this.fsw._emit(EV.ADD, file2, stats);
33974
- }
33975
- return closer;
33976
- }
33977
- /**
33978
- * Handle symlinks encountered while reading a dir.
33979
- * @param entry returned by readdirp
33980
- * @param directory path of dir being read
33981
- * @param path of this item
33982
- * @param item basename of this item
33983
- * @returns true if no more processing is needed for this entry.
33984
- */
33985
- async _handleSymlink(entry, directory, path25, item) {
33986
- if (this.fsw.closed) {
33987
- return;
33988
- }
33989
- const full = entry.fullPath;
33990
- const dir = this.fsw._getWatchedDir(directory);
33991
- if (!this.fsw.options.followSymlinks) {
33992
- this.fsw._incrReadyCount();
33993
- let linkPath;
33994
- try {
33995
- linkPath = await fsrealpath(path25);
33996
- } catch (e) {
33997
- this.fsw._emitReady();
33998
- return true;
33999
- }
34000
- if (this.fsw.closed)
34001
- return;
34002
- if (dir.has(item)) {
34003
- if (this.fsw._symlinkPaths.get(full) !== linkPath) {
34004
- this.fsw._symlinkPaths.set(full, linkPath);
34005
- this.fsw._emit(EV.CHANGE, path25, entry.stats);
34006
- }
34007
- } else {
34008
- dir.add(item);
34009
- this.fsw._symlinkPaths.set(full, linkPath);
34010
- this.fsw._emit(EV.ADD, path25, entry.stats);
34011
- }
34012
- this.fsw._emitReady();
34013
- return true;
34014
- }
34015
- if (this.fsw._symlinkPaths.has(full)) {
34016
- return true;
34017
- }
34018
- this.fsw._symlinkPaths.set(full, true);
34019
- }
34020
- _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
34021
- directory = sysPath.join(directory, "");
34022
- throttler = this.fsw._throttle("readdir", directory, 1e3);
34023
- if (!throttler)
34024
- return;
34025
- const previous = this.fsw._getWatchedDir(wh.path);
34026
- const current = /* @__PURE__ */ new Set();
34027
- let stream = this.fsw._readdirp(directory, {
34028
- fileFilter: (entry) => wh.filterPath(entry),
34029
- directoryFilter: (entry) => wh.filterDir(entry)
34030
- });
34031
- if (!stream)
34032
- return;
34033
- stream.on(STR_DATA, async (entry) => {
34034
- if (this.fsw.closed) {
34035
- stream = void 0;
34036
- return;
34037
- }
34038
- const item = entry.path;
34039
- let path25 = sysPath.join(directory, item);
34040
- current.add(item);
34041
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path25, item)) {
34042
- return;
34043
- }
34044
- if (this.fsw.closed) {
34045
- stream = void 0;
34046
- return;
34047
- }
34048
- if (item === target || !target && !previous.has(item)) {
34049
- this.fsw._incrReadyCount();
34050
- path25 = sysPath.join(dir, sysPath.relative(dir, path25));
34051
- this._addToNodeFs(path25, initialAdd, wh, depth + 1);
34052
- }
34053
- }).on(EV.ERROR, this._boundHandleError);
34054
- return new Promise((resolve17, reject) => {
34055
- if (!stream)
34056
- return reject();
34057
- stream.once(STR_END, () => {
34058
- if (this.fsw.closed) {
34059
- stream = void 0;
34060
- return;
34061
- }
34062
- const wasThrottled = throttler ? throttler.clear() : false;
34063
- resolve17(void 0);
34064
- previous.getChildren().filter((item) => {
34065
- return item !== directory && !current.has(item);
34066
- }).forEach((item) => {
34067
- this.fsw._remove(directory, item);
34068
- });
34069
- stream = void 0;
34070
- if (wasThrottled)
34071
- this._handleRead(directory, false, wh, target, dir, depth, throttler);
34072
- });
34073
- });
34074
- }
34075
- /**
34076
- * Read directory to add / remove files from `@watched` list and re-read it on change.
34077
- * @param dir fs path
34078
- * @param stats
34079
- * @param initialAdd
34080
- * @param depth relative to user-supplied path
34081
- * @param target child path targeted for watch
34082
- * @param wh Common watch helpers for this path
34083
- * @param realpath
34084
- * @returns closer for the watcher instance.
34085
- */
34086
- async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
34087
- const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
34088
- const tracked = parentDir.has(sysPath.basename(dir));
34089
- if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
34090
- this.fsw._emit(EV.ADD_DIR, dir, stats);
34091
- }
34092
- parentDir.add(sysPath.basename(dir));
34093
- this.fsw._getWatchedDir(dir);
34094
- let throttler;
34095
- let closer;
34096
- const oDepth = this.fsw.options.depth;
34097
- if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath2)) {
34098
- if (!target) {
34099
- await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
34100
- if (this.fsw.closed)
34101
- return;
34102
- }
34103
- closer = this._watchWithNodeFs(dir, (dirPath, stats2) => {
34104
- if (stats2 && stats2.mtimeMs === 0)
34105
- return;
34106
- this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
34107
- });
34108
- }
34109
- return closer;
34110
- }
34111
- /**
34112
- * Handle added file, directory, or glob pattern.
34113
- * Delegates call to _handleFile / _handleDir after checks.
34114
- * @param path to file or ir
34115
- * @param initialAdd was the file added at watch instantiation?
34116
- * @param priorWh depth relative to user-supplied path
34117
- * @param depth Child path actually targeted for watch
34118
- * @param target Child path actually targeted for watch
34119
- */
34120
- async _addToNodeFs(path25, initialAdd, priorWh, depth, target) {
34121
- const ready = this.fsw._emitReady;
34122
- if (this.fsw._isIgnored(path25) || this.fsw.closed) {
34123
- ready();
34124
- return false;
34125
- }
34126
- const wh = this.fsw._getWatchHelpers(path25);
34127
- if (priorWh) {
34128
- wh.filterPath = (entry) => priorWh.filterPath(entry);
34129
- wh.filterDir = (entry) => priorWh.filterDir(entry);
34130
- }
34131
- try {
34132
- const stats = await statMethods[wh.statMethod](wh.watchPath);
34133
- if (this.fsw.closed)
34134
- return;
34135
- if (this.fsw._isIgnored(wh.watchPath, stats)) {
34136
- ready();
34137
- return false;
34138
- }
34139
- const follow = this.fsw.options.followSymlinks;
34140
- let closer;
34141
- if (stats.isDirectory()) {
34142
- const absPath = sysPath.resolve(path25);
34143
- const targetPath = follow ? await fsrealpath(path25) : path25;
34144
- if (this.fsw.closed)
34145
- return;
34146
- closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
34147
- if (this.fsw.closed)
34148
- return;
34149
- if (absPath !== targetPath && targetPath !== void 0) {
34150
- this.fsw._symlinkPaths.set(absPath, targetPath);
34151
- }
34152
- } else if (stats.isSymbolicLink()) {
34153
- const targetPath = follow ? await fsrealpath(path25) : path25;
34154
- if (this.fsw.closed)
34155
- return;
34156
- const parent = sysPath.dirname(wh.watchPath);
34157
- this.fsw._getWatchedDir(parent).add(wh.watchPath);
34158
- this.fsw._emit(EV.ADD, wh.watchPath, stats);
34159
- closer = await this._handleDir(parent, stats, initialAdd, depth, path25, wh, targetPath);
34160
- if (this.fsw.closed)
34161
- return;
34162
- if (targetPath !== void 0) {
34163
- this.fsw._symlinkPaths.set(sysPath.resolve(path25), targetPath);
34164
- }
34165
- } else {
34166
- closer = this._handleFile(wh.watchPath, stats, initialAdd);
34167
- }
34168
- ready();
34169
- if (closer)
34170
- this.fsw._addPathCloser(path25, closer);
34171
- return false;
34172
- } catch (error40) {
34173
- if (this.fsw._handleError(error40)) {
34174
- ready();
34175
- return path25;
34176
- }
34177
- }
34178
- }
34179
- };
34180
-
34181
- // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
34182
- var SLASH = "/";
34183
- var SLASH_SLASH = "//";
34184
- var ONE_DOT = ".";
34185
- var TWO_DOTS = "..";
34186
- var STRING_TYPE = "string";
34187
- var BACK_SLASH_RE = /\\/g;
34188
- var DOUBLE_SLASH_RE = /\/\//;
34189
- var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
34190
- var REPLACER_RE = /^\.[/\\]/;
34191
- function arrify(item) {
34192
- return Array.isArray(item) ? item : [item];
34193
- }
34194
- var isMatcherObject = (matcher) => typeof matcher === "object" && matcher !== null && !(matcher instanceof RegExp);
34195
- function createPattern(matcher) {
34196
- if (typeof matcher === "function")
34197
- return matcher;
34198
- if (typeof matcher === "string")
34199
- return (string4) => matcher === string4;
34200
- if (matcher instanceof RegExp)
34201
- return (string4) => matcher.test(string4);
34202
- if (typeof matcher === "object" && matcher !== null) {
34203
- return (string4) => {
34204
- if (matcher.path === string4)
34205
- return true;
34206
- if (matcher.recursive) {
34207
- const relative6 = sysPath2.relative(matcher.path, string4);
34208
- if (!relative6) {
34209
- return false;
34210
- }
34211
- return !relative6.startsWith("..") && !sysPath2.isAbsolute(relative6);
34212
- }
34213
- return false;
34214
- };
34215
- }
34216
- return () => false;
34217
- }
34218
- function normalizePath(path25) {
34219
- if (typeof path25 !== "string")
34220
- throw new Error("string expected");
34221
- path25 = sysPath2.normalize(path25);
34222
- path25 = path25.replace(/\\/g, "/");
34223
- let prepend = false;
34224
- if (path25.startsWith("//"))
34225
- prepend = true;
34226
- const DOUBLE_SLASH_RE2 = /\/\//;
34227
- while (path25.match(DOUBLE_SLASH_RE2))
34228
- path25 = path25.replace(DOUBLE_SLASH_RE2, "/");
34229
- if (prepend)
34230
- path25 = "/" + path25;
34231
- return path25;
34232
- }
34233
- function matchPatterns(patterns, testString, stats) {
34234
- const path25 = normalizePath(testString);
34235
- for (let index = 0; index < patterns.length; index++) {
34236
- const pattern = patterns[index];
34237
- if (pattern(path25, stats)) {
34238
- return true;
34239
- }
34240
- }
34241
- return false;
34242
- }
34243
- function anymatch(matchers, testString) {
34244
- if (matchers == null) {
34245
- throw new TypeError("anymatch: specify first argument");
34246
- }
34247
- const matchersArray = arrify(matchers);
34248
- const patterns = matchersArray.map((matcher) => createPattern(matcher));
34249
- if (testString == null) {
34250
- return (testString2, stats) => {
34251
- return matchPatterns(patterns, testString2, stats);
34252
- };
34253
- }
34254
- return matchPatterns(patterns, testString);
34255
- }
34256
- var unifyPaths = (paths_) => {
34257
- const paths = arrify(paths_).flat();
34258
- if (!paths.every((p) => typeof p === STRING_TYPE)) {
34259
- throw new TypeError(`Non-string provided as watch path: ${paths}`);
34260
- }
34261
- return paths.map(normalizePathToUnix);
34262
- };
34263
- var toUnix = (string4) => {
34264
- let str = string4.replace(BACK_SLASH_RE, SLASH);
34265
- let prepend = false;
34266
- if (str.startsWith(SLASH_SLASH)) {
34267
- prepend = true;
34268
- }
34269
- while (str.match(DOUBLE_SLASH_RE)) {
34270
- str = str.replace(DOUBLE_SLASH_RE, SLASH);
34271
- }
34272
- if (prepend) {
34273
- str = SLASH + str;
34274
- }
34275
- return str;
34276
- };
34277
- var normalizePathToUnix = (path25) => toUnix(sysPath2.normalize(toUnix(path25)));
34278
- var normalizeIgnored = (cwd3 = "") => (path25) => {
34279
- if (typeof path25 === "string") {
34280
- return normalizePathToUnix(sysPath2.isAbsolute(path25) ? path25 : sysPath2.join(cwd3, path25));
34281
- } else {
34282
- return path25;
34283
- }
34284
- };
34285
- var getAbsolutePath = (path25, cwd3) => {
34286
- if (sysPath2.isAbsolute(path25)) {
34287
- return path25;
34288
- }
34289
- return sysPath2.join(cwd3, path25);
34290
- };
34291
- var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
34292
- var DirEntry = class {
34293
- constructor(dir, removeWatcher) {
34294
- this.path = dir;
34295
- this._removeWatcher = removeWatcher;
34296
- this.items = /* @__PURE__ */ new Set();
34297
- }
34298
- add(item) {
34299
- const { items } = this;
34300
- if (!items)
34301
- return;
34302
- if (item !== ONE_DOT && item !== TWO_DOTS)
34303
- items.add(item);
34304
- }
34305
- async remove(item) {
34306
- const { items } = this;
34307
- if (!items)
34308
- return;
34309
- items.delete(item);
34310
- if (items.size > 0)
34311
- return;
34312
- const dir = this.path;
34313
- try {
34314
- await readdir2(dir);
34315
- } catch (err) {
34316
- if (this._removeWatcher) {
34317
- this._removeWatcher(sysPath2.dirname(dir), sysPath2.basename(dir));
34318
- }
34319
- }
34320
- }
34321
- has(item) {
34322
- const { items } = this;
34323
- if (!items)
34324
- return;
34325
- return items.has(item);
34326
- }
34327
- getChildren() {
34328
- const { items } = this;
34329
- if (!items)
34330
- return [];
34331
- return [...items.values()];
34332
- }
34333
- dispose() {
34334
- this.items.clear();
34335
- this.path = "";
34336
- this._removeWatcher = EMPTY_FN;
34337
- this.items = EMPTY_SET;
34338
- Object.freeze(this);
34339
- }
34340
- };
34341
- var STAT_METHOD_F = "stat";
34342
- var STAT_METHOD_L = "lstat";
34343
- var WatchHelper = class {
34344
- constructor(path25, follow, fsw) {
34345
- this.fsw = fsw;
34346
- const watchPath = path25;
34347
- this.path = path25 = path25.replace(REPLACER_RE, "");
34348
- this.watchPath = watchPath;
34349
- this.fullWatchPath = sysPath2.resolve(watchPath);
34350
- this.dirParts = [];
34351
- this.dirParts.forEach((parts) => {
34352
- if (parts.length > 1)
34353
- parts.pop();
34354
- });
34355
- this.followSymlinks = follow;
34356
- this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
34357
- }
34358
- entryPath(entry) {
34359
- return sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
34360
- }
34361
- filterPath(entry) {
34362
- const { stats } = entry;
34363
- if (stats && stats.isSymbolicLink())
34364
- return this.filterDir(entry);
34365
- const resolvedPath = this.entryPath(entry);
34366
- return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
34367
- }
34368
- filterDir(entry) {
34369
- return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
34370
- }
34371
- };
34372
- var FSWatcher = class extends EventEmitter2 {
34373
- // Not indenting methods for history sake; for now.
34374
- constructor(_opts = {}) {
34375
- super();
34376
- this.closed = false;
34377
- this._closers = /* @__PURE__ */ new Map();
34378
- this._ignoredPaths = /* @__PURE__ */ new Set();
34379
- this._throttled = /* @__PURE__ */ new Map();
34380
- this._streams = /* @__PURE__ */ new Set();
34381
- this._symlinkPaths = /* @__PURE__ */ new Map();
34382
- this._watched = /* @__PURE__ */ new Map();
34383
- this._pendingWrites = /* @__PURE__ */ new Map();
34384
- this._pendingUnlinks = /* @__PURE__ */ new Map();
34385
- this._readyCount = 0;
34386
- this._readyEmitted = false;
34387
- const awf = _opts.awaitWriteFinish;
34388
- const DEF_AWF = { stabilityThreshold: 2e3, pollInterval: 100 };
34389
- const opts = {
34390
- // Defaults
34391
- persistent: true,
34392
- ignoreInitial: false,
34393
- ignorePermissionErrors: false,
34394
- interval: 100,
34395
- binaryInterval: 300,
34396
- followSymlinks: true,
34397
- usePolling: false,
34398
- // useAsync: false,
34399
- atomic: true,
34400
- // NOTE: overwritten later (depends on usePolling)
34401
- ..._opts,
34402
- // Change format
34403
- ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
34404
- awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === "object" ? { ...DEF_AWF, ...awf } : false
34405
- };
34406
- if (isIBMi)
34407
- opts.usePolling = true;
34408
- if (opts.atomic === void 0)
34409
- opts.atomic = !opts.usePolling;
34410
- const envPoll = process.env.CHOKIDAR_USEPOLLING;
34411
- if (envPoll !== void 0) {
34412
- const envLower = envPoll.toLowerCase();
34413
- if (envLower === "false" || envLower === "0")
34414
- opts.usePolling = false;
34415
- else if (envLower === "true" || envLower === "1")
34416
- opts.usePolling = true;
34417
- else
34418
- opts.usePolling = !!envLower;
34419
- }
34420
- const envInterval = process.env.CHOKIDAR_INTERVAL;
34421
- if (envInterval)
34422
- opts.interval = Number.parseInt(envInterval, 10);
34423
- let readyCalls = 0;
34424
- this._emitReady = () => {
34425
- readyCalls++;
34426
- if (readyCalls >= this._readyCount) {
34427
- this._emitReady = EMPTY_FN;
34428
- this._readyEmitted = true;
34429
- process.nextTick(() => this.emit(EVENTS.READY));
34430
- }
34431
- };
34432
- this._emitRaw = (...args) => this.emit(EVENTS.RAW, ...args);
34433
- this._boundRemove = this._remove.bind(this);
34434
- this.options = opts;
34435
- this._nodeFsHandler = new NodeFsHandler(this);
34436
- Object.freeze(opts);
34437
- }
34438
- _addIgnoredPath(matcher) {
34439
- if (isMatcherObject(matcher)) {
34440
- for (const ignored of this._ignoredPaths) {
34441
- if (isMatcherObject(ignored) && ignored.path === matcher.path && ignored.recursive === matcher.recursive) {
34442
- return;
34443
- }
34444
- }
34445
- }
34446
- this._ignoredPaths.add(matcher);
34447
- }
34448
- _removeIgnoredPath(matcher) {
34449
- this._ignoredPaths.delete(matcher);
34450
- if (typeof matcher === "string") {
34451
- for (const ignored of this._ignoredPaths) {
34452
- if (isMatcherObject(ignored) && ignored.path === matcher) {
34453
- this._ignoredPaths.delete(ignored);
34454
- }
34455
- }
34456
- }
34457
- }
34458
- // Public methods
34459
- /**
34460
- * Adds paths to be watched on an existing FSWatcher instance.
34461
- * @param paths_ file or file list. Other arguments are unused
34462
- */
34463
- add(paths_, _origAdd, _internal) {
34464
- const { cwd: cwd3 } = this.options;
34465
- this.closed = false;
34466
- this._closePromise = void 0;
34467
- let paths = unifyPaths(paths_);
34468
- if (cwd3) {
34469
- paths = paths.map((path25) => {
34470
- const absPath = getAbsolutePath(path25, cwd3);
34471
- return absPath;
34472
- });
34473
- }
34474
- paths.forEach((path25) => {
34475
- this._removeIgnoredPath(path25);
34476
- });
34477
- this._userIgnored = void 0;
34478
- if (!this._readyCount)
34479
- this._readyCount = 0;
34480
- this._readyCount += paths.length;
34481
- Promise.all(paths.map(async (path25) => {
34482
- const res = await this._nodeFsHandler._addToNodeFs(path25, !_internal, void 0, 0, _origAdd);
34483
- if (res)
34484
- this._emitReady();
34485
- return res;
34486
- })).then((results) => {
34487
- if (this.closed)
34488
- return;
34489
- results.forEach((item) => {
34490
- if (item)
34491
- this.add(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
34492
- });
34493
- });
34494
- return this;
34495
- }
34496
- /**
34497
- * Close watchers or start ignoring events from specified paths.
34498
- */
34499
- unwatch(paths_) {
34500
- if (this.closed)
34501
- return this;
34502
- const paths = unifyPaths(paths_);
34503
- const { cwd: cwd3 } = this.options;
34504
- paths.forEach((path25) => {
34505
- if (!sysPath2.isAbsolute(path25) && !this._closers.has(path25)) {
34506
- if (cwd3)
34507
- path25 = sysPath2.join(cwd3, path25);
34508
- path25 = sysPath2.resolve(path25);
34509
- }
34510
- this._closePath(path25);
34511
- this._addIgnoredPath(path25);
34512
- if (this._watched.has(path25)) {
34513
- this._addIgnoredPath({
34514
- path: path25,
34515
- recursive: true
34516
- });
34517
- }
34518
- this._userIgnored = void 0;
34519
- });
34520
- return this;
34521
- }
34522
- /**
34523
- * Close watchers and remove all listeners from watched paths.
34524
- */
34525
- close() {
34526
- if (this._closePromise) {
34527
- return this._closePromise;
34528
- }
34529
- this.closed = true;
34530
- this.removeAllListeners();
34531
- const closers = [];
34532
- this._closers.forEach((closerList) => closerList.forEach((closer) => {
34533
- const promise2 = closer();
34534
- if (promise2 instanceof Promise)
34535
- closers.push(promise2);
34536
- }));
34537
- this._streams.forEach((stream) => stream.destroy());
34538
- this._userIgnored = void 0;
34539
- this._readyCount = 0;
34540
- this._readyEmitted = false;
34541
- this._watched.forEach((dirent) => dirent.dispose());
34542
- this._closers.clear();
34543
- this._watched.clear();
34544
- this._streams.clear();
34545
- this._symlinkPaths.clear();
34546
- this._throttled.clear();
34547
- this._closePromise = closers.length ? Promise.all(closers).then(() => void 0) : Promise.resolve();
34548
- return this._closePromise;
34549
- }
34550
- /**
34551
- * Expose list of watched paths
34552
- * @returns for chaining
34553
- */
34554
- getWatched() {
34555
- const watchList = {};
34556
- this._watched.forEach((entry, dir) => {
34557
- const key = this.options.cwd ? sysPath2.relative(this.options.cwd, dir) : dir;
34558
- const index = key || ONE_DOT;
34559
- watchList[index] = entry.getChildren().sort();
34560
- });
34561
- return watchList;
34562
- }
34563
- emitWithAll(event, args) {
34564
- this.emit(event, ...args);
34565
- if (event !== EVENTS.ERROR)
34566
- this.emit(EVENTS.ALL, event, ...args);
34567
- }
34568
- // Common helpers
34569
- // --------------
34570
- /**
34571
- * Normalize and emit events.
34572
- * Calling _emit DOES NOT MEAN emit() would be called!
34573
- * @param event Type of event
34574
- * @param path File or directory path
34575
- * @param stats arguments to be passed with event
34576
- * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
34577
- */
34578
- async _emit(event, path25, stats) {
34579
- if (this.closed)
34580
- return;
34581
- const opts = this.options;
34582
- if (isWindows)
34583
- path25 = sysPath2.normalize(path25);
34584
- if (opts.cwd)
34585
- path25 = sysPath2.relative(opts.cwd, path25);
34586
- const args = [path25];
34587
- if (stats != null)
34588
- args.push(stats);
34589
- const awf = opts.awaitWriteFinish;
34590
- let pw;
34591
- if (awf && (pw = this._pendingWrites.get(path25))) {
34592
- pw.lastChange = /* @__PURE__ */ new Date();
34593
- return this;
34594
- }
34595
- if (opts.atomic) {
34596
- if (event === EVENTS.UNLINK) {
34597
- this._pendingUnlinks.set(path25, [event, ...args]);
34598
- setTimeout(() => {
34599
- this._pendingUnlinks.forEach((entry, path26) => {
34600
- this.emit(...entry);
34601
- this.emit(EVENTS.ALL, ...entry);
34602
- this._pendingUnlinks.delete(path26);
34603
- });
34604
- }, typeof opts.atomic === "number" ? opts.atomic : 100);
34605
- return this;
34606
- }
34607
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path25)) {
34608
- event = EVENTS.CHANGE;
34609
- this._pendingUnlinks.delete(path25);
34610
- }
34611
- }
34612
- if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
34613
- const awfEmit = (err, stats2) => {
34614
- if (err) {
34615
- event = EVENTS.ERROR;
34616
- args[0] = err;
34617
- this.emitWithAll(event, args);
34618
- } else if (stats2) {
34619
- if (args.length > 1) {
34620
- args[1] = stats2;
34621
- } else {
34622
- args.push(stats2);
34623
- }
34624
- this.emitWithAll(event, args);
34625
- }
34626
- };
34627
- this._awaitWriteFinish(path25, awf.stabilityThreshold, event, awfEmit);
34628
- return this;
34629
- }
34630
- if (event === EVENTS.CHANGE) {
34631
- const isThrottled = !this._throttle(EVENTS.CHANGE, path25, 50);
34632
- if (isThrottled)
34633
- return this;
34634
- }
34635
- if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
34636
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path25) : path25;
34637
- let stats2;
34638
- try {
34639
- stats2 = await stat3(fullPath);
34640
- } catch (err) {
34641
- }
34642
- if (!stats2 || this.closed)
34643
- return;
34644
- args.push(stats2);
34645
- }
34646
- this.emitWithAll(event, args);
34647
- return this;
34648
- }
34649
- /**
34650
- * Common handler for errors
34651
- * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
34652
- */
34653
- _handleError(error40) {
34654
- const code = error40 && error40.code;
34655
- if (error40 && code !== "ENOENT" && code !== "ENOTDIR" && (!this.options.ignorePermissionErrors || code !== "EPERM" && code !== "EACCES")) {
34656
- this.emit(EVENTS.ERROR, error40);
34657
- }
34658
- return error40 || this.closed;
34659
- }
34660
- /**
34661
- * Helper utility for throttling
34662
- * @param actionType type being throttled
34663
- * @param path being acted upon
34664
- * @param timeout duration of time to suppress duplicate actions
34665
- * @returns tracking object or false if action should be suppressed
34666
- */
34667
- _throttle(actionType, path25, timeout) {
34668
- if (!this._throttled.has(actionType)) {
34669
- this._throttled.set(actionType, /* @__PURE__ */ new Map());
34670
- }
34671
- const action = this._throttled.get(actionType);
34672
- if (!action)
34673
- throw new Error("invalid throttle");
34674
- const actionPath = action.get(path25);
34675
- if (actionPath) {
34676
- actionPath.count++;
34677
- return false;
34678
- }
34679
- let timeoutObject;
34680
- const clear = () => {
34681
- const item = action.get(path25);
34682
- const count = item ? item.count : 0;
34683
- action.delete(path25);
34684
- clearTimeout(timeoutObject);
34685
- if (item)
34686
- clearTimeout(item.timeoutObject);
34687
- return count;
34688
- };
34689
- timeoutObject = setTimeout(clear, timeout);
34690
- const thr = { timeoutObject, clear, count: 0 };
34691
- action.set(path25, thr);
34692
- return thr;
34693
- }
34694
- _incrReadyCount() {
34695
- return this._readyCount++;
34696
- }
34697
- /**
34698
- * Awaits write operation to finish.
34699
- * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
34700
- * @param path being acted upon
34701
- * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
34702
- * @param event
34703
- * @param awfEmit Callback to be called when ready for event to be emitted.
34704
- */
34705
- _awaitWriteFinish(path25, threshold, event, awfEmit) {
34706
- const awf = this.options.awaitWriteFinish;
34707
- if (typeof awf !== "object")
34708
- return;
34709
- const pollInterval = awf.pollInterval;
34710
- let timeoutHandler;
34711
- let fullPath = path25;
34712
- if (this.options.cwd && !sysPath2.isAbsolute(path25)) {
34713
- fullPath = sysPath2.join(this.options.cwd, path25);
34714
- }
34715
- const now = /* @__PURE__ */ new Date();
34716
- const writes = this._pendingWrites;
34717
- function awaitWriteFinishFn(prevStat) {
34718
- statcb(fullPath, (err, curStat) => {
34719
- if (err || !writes.has(path25)) {
34720
- if (err && err.code !== "ENOENT")
34721
- awfEmit(err);
34722
- return;
34723
- }
34724
- const now2 = Number(/* @__PURE__ */ new Date());
34725
- if (prevStat && curStat.size !== prevStat.size) {
34726
- writes.get(path25).lastChange = now2;
34727
- }
34728
- const pw = writes.get(path25);
34729
- const df = now2 - pw.lastChange;
34730
- if (df >= threshold) {
34731
- writes.delete(path25);
34732
- awfEmit(void 0, curStat);
34733
- } else {
34734
- timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
34735
- }
34736
- });
34737
- }
34738
- if (!writes.has(path25)) {
34739
- writes.set(path25, {
34740
- lastChange: now,
34741
- cancelWait: () => {
34742
- writes.delete(path25);
34743
- clearTimeout(timeoutHandler);
34744
- return event;
34745
- }
34746
- });
34747
- timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
34748
- }
34749
- }
34750
- /**
34751
- * Determines whether user has asked to ignore this path.
34752
- */
34753
- _isIgnored(path25, stats) {
34754
- if (this.options.atomic && DOT_RE.test(path25))
34755
- return true;
34756
- if (!this._userIgnored) {
34757
- const { cwd: cwd3 } = this.options;
34758
- const ign = this.options.ignored;
34759
- const ignored = (ign || []).map(normalizeIgnored(cwd3));
34760
- const ignoredPaths = [...this._ignoredPaths];
34761
- const list = [...ignoredPaths.map(normalizeIgnored(cwd3)), ...ignored];
34762
- this._userIgnored = anymatch(list, void 0);
34763
- }
34764
- return this._userIgnored(path25, stats);
34765
- }
34766
- _isntIgnored(path25, stat4) {
34767
- return !this._isIgnored(path25, stat4);
34768
- }
34769
- /**
34770
- * Provides a set of common helpers and properties relating to symlink handling.
34771
- * @param path file or directory pattern being watched
34772
- */
34773
- _getWatchHelpers(path25) {
34774
- return new WatchHelper(path25, this.options.followSymlinks, this);
34775
- }
34776
- // Directory helpers
34777
- // -----------------
34778
- /**
34779
- * Provides directory tracking objects
34780
- * @param directory path of the directory
34781
- */
34782
- _getWatchedDir(directory) {
34783
- const dir = sysPath2.resolve(directory);
34784
- if (!this._watched.has(dir))
34785
- this._watched.set(dir, new DirEntry(dir, this._boundRemove));
34786
- return this._watched.get(dir);
34787
- }
34788
- // File helpers
34789
- // ------------
34790
- /**
34791
- * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
34792
- */
34793
- _hasReadPermissions(stats) {
34794
- if (this.options.ignorePermissionErrors)
34795
- return true;
34796
- return Boolean(Number(stats.mode) & 256);
34797
- }
34798
- /**
34799
- * Handles emitting unlink events for
34800
- * files and directories, and via recursion, for
34801
- * files and directories within directories that are unlinked
34802
- * @param directory within which the following item is located
34803
- * @param item base path of item/directory
34804
- */
34805
- _remove(directory, item, isDirectory) {
34806
- const path25 = sysPath2.join(directory, item);
34807
- const fullPath = sysPath2.resolve(path25);
34808
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path25) || this._watched.has(fullPath);
34809
- if (!this._throttle("remove", path25, 100))
34810
- return;
34811
- if (!isDirectory && this._watched.size === 1) {
34812
- this.add(directory, item, true);
34813
- }
34814
- const wp = this._getWatchedDir(path25);
34815
- const nestedDirectoryChildren = wp.getChildren();
34816
- nestedDirectoryChildren.forEach((nested) => this._remove(path25, nested));
34817
- const parent = this._getWatchedDir(directory);
34818
- const wasTracked = parent.has(item);
34819
- parent.remove(item);
34820
- if (this._symlinkPaths.has(fullPath)) {
34821
- this._symlinkPaths.delete(fullPath);
34822
- }
34823
- let relPath = path25;
34824
- if (this.options.cwd)
34825
- relPath = sysPath2.relative(this.options.cwd, path25);
34826
- if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
34827
- const event = this._pendingWrites.get(relPath).cancelWait();
34828
- if (event === EVENTS.ADD)
34829
- return;
34830
- }
34831
- this._watched.delete(path25);
34832
- this._watched.delete(fullPath);
34833
- const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
34834
- if (wasTracked && !this._isIgnored(path25))
34835
- this._emit(eventName, path25);
34836
- this._closePath(path25);
34837
- }
34838
- /**
34839
- * Closes all watchers for a path
34840
- */
34841
- _closePath(path25) {
34842
- this._closeFile(path25);
34843
- const dir = sysPath2.dirname(path25);
34844
- this._getWatchedDir(dir).remove(sysPath2.basename(path25));
34845
- }
34846
- /**
34847
- * Closes only file-specific watchers
34848
- */
34849
- _closeFile(path25) {
34850
- const closers = this._closers.get(path25);
34851
- if (!closers)
34852
- return;
34853
- closers.forEach((closer) => closer());
34854
- this._closers.delete(path25);
34855
- }
34856
- _addPathCloser(path25, closer) {
34857
- if (!closer)
34858
- return;
34859
- let list = this._closers.get(path25);
34860
- if (!list) {
34861
- list = [];
34862
- this._closers.set(path25, list);
34863
- }
34864
- list.push(closer);
34865
- }
34866
- _readdirp(root, opts) {
34867
- if (this.closed)
34868
- return;
34869
- const options = { type: EVENTS.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
34870
- let stream = readdirp(root, options);
34871
- this._streams.add(stream);
34872
- stream.once(STR_CLOSE, () => {
34873
- stream = void 0;
34874
- });
34875
- stream.once(STR_END, () => {
34876
- if (stream) {
34877
- this._streams.delete(stream);
34878
- stream = void 0;
34879
- }
34880
- });
34881
- return stream;
34882
- }
34883
- };
34884
- function watch(paths, options = {}) {
34885
- const watcher = new FSWatcher(options);
34886
- watcher.add(paths);
34887
- return watcher;
34888
- }
34889
- var esm_default = { watch, FSWatcher };
34890
-
34891
- // src/files/watch-file-index.ts
34892
33415
  var DEBOUNCE_MS = 900;
34893
33416
  function shouldIgnoreRelative(rel) {
34894
33417
  const n = rel.replace(/\\/g, "/");
@@ -34897,8 +33420,43 @@ function shouldIgnoreRelative(rel) {
34897
33420
  if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
34898
33421
  return false;
34899
33422
  }
34900
- function startFileIndexWatcher(cwd3 = process.cwd()) {
34901
- const resolved = path21.resolve(cwd3);
33423
+ function attachWatchErrorLog(w) {
33424
+ w.on("error", (err) => {
33425
+ console.error("[file-index] File watcher error:", err);
33426
+ });
33427
+ }
33428
+ function createFsWatcher(resolved, schedule) {
33429
+ const onEvent = (_event, filename) => {
33430
+ if (filename != null) {
33431
+ const rel = typeof filename === "string" ? filename.replace(/\\/g, "/") : filename.toString("utf8").replace(/\\/g, "/");
33432
+ if (shouldIgnoreRelative(rel)) return;
33433
+ }
33434
+ schedule();
33435
+ };
33436
+ try {
33437
+ const w = watch(resolved, { recursive: true }, onEvent);
33438
+ attachWatchErrorLog(w);
33439
+ return w;
33440
+ } catch (e) {
33441
+ const code = typeof e === "object" && e !== null && "code" in e ? e.code : void 0;
33442
+ if (code === "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM") {
33443
+ console.warn(
33444
+ "[file-index] Recursive file watching is unavailable on this platform; using non-recursive watch (Node 20+ on Linux enables recursive). Nested file changes may be missed until you upgrade."
33445
+ );
33446
+ const w = watch(resolved, { recursive: false }, onEvent);
33447
+ attachWatchErrorLog(w);
33448
+ return w;
33449
+ }
33450
+ throw e;
33451
+ }
33452
+ }
33453
+ function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
33454
+ const resolved = path21.resolve(cwd);
33455
+ try {
33456
+ buildFileIndex(resolved);
33457
+ } catch (e) {
33458
+ console.error("[file-index] Initial index build failed:", e);
33459
+ }
34902
33460
  let timer = null;
34903
33461
  const runRebuild = () => {
34904
33462
  try {
@@ -34914,27 +33472,13 @@ function startFileIndexWatcher(cwd3 = process.cwd()) {
34914
33472
  runRebuild();
34915
33473
  }, DEBOUNCE_MS);
34916
33474
  };
34917
- const watcher = esm_default.watch(".", {
34918
- cwd: resolved,
34919
- ignoreInitial: true,
34920
- persistent: true,
34921
- ignored: (p) => {
34922
- const rel = path21.isAbsolute(p) ? path21.relative(resolved, p).replace(/\\/g, "/") : p.replace(/\\/g, "/");
34923
- return shouldIgnoreRelative(rel || ".");
34924
- },
34925
- awaitWriteFinish: { stabilityThreshold: 250, pollInterval: 100 }
34926
- });
34927
- watcher.on("add", schedule);
34928
- watcher.on("change", schedule);
34929
- watcher.on("unlink", schedule);
34930
- watcher.on("addDir", schedule);
34931
- watcher.on("unlinkDir", schedule);
33475
+ const watcher = createFsWatcher(resolved, schedule);
34932
33476
  return () => {
34933
33477
  if (timer) {
34934
33478
  clearTimeout(timer);
34935
33479
  timer = null;
34936
33480
  }
34937
- void watcher.close();
33481
+ watcher.close();
34938
33482
  };
34939
33483
  }
34940
33484
 
@@ -34958,18 +33502,20 @@ function sendDevServerStatus(getWs, serverId, status, options) {
34958
33502
 
34959
33503
  // src/dev-servers/process/terminate-child-process.ts
34960
33504
  async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
34961
- const exited = new Promise((resolve17) => {
34962
- proc.once("exit", () => resolve17());
33505
+ const exited = new Promise((resolve15) => {
33506
+ proc.once("exit", () => resolve15());
34963
33507
  });
34964
- log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"})\u2026`);
33508
+ log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
34965
33509
  try {
34966
33510
  proc.kill("SIGTERM");
34967
33511
  } catch {
34968
33512
  }
34969
- await Promise.race([exited, new Promise((resolve17) => setTimeout(resolve17, graceMs))]);
33513
+ await Promise.race([exited, new Promise((resolve15) => setTimeout(resolve15, graceMs))]);
34970
33514
  }
34971
33515
  function forceKillChild(proc, log2, shortId, graceMs) {
34972
- log2(`[dev-server] ${shortId} did not exit within ${graceMs}ms; sending SIGKILL (pid=${proc.pid ?? "?"})\u2026`);
33516
+ log2(
33517
+ `[dev-server] ${shortId} did not exit within ${graceMs}ms; sending SIGKILL (pid=${proc.pid ?? "?"}).`
33518
+ );
34973
33519
  proc.removeAllListeners();
34974
33520
  try {
34975
33521
  proc.kill("SIGKILL");
@@ -34978,7 +33524,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
34978
33524
  }
34979
33525
 
34980
33526
  // src/dev-servers/process/wire-dev-server-child-process.ts
34981
- import fs16 from "node:fs";
33527
+ import fs17 from "node:fs";
34982
33528
 
34983
33529
  // src/dev-servers/manager/forward-pipe.ts
34984
33530
  function forwardChildPipe(childReadable, terminal, onData) {
@@ -35014,7 +33560,7 @@ function wireDevServerChildProcess(d) {
35014
33560
  d.setPollInterval(void 0);
35015
33561
  return;
35016
33562
  }
35017
- fs16.readFile(d.mergedLogPath, (err, buf) => {
33563
+ fs17.readFile(d.mergedLogPath, (err, buf) => {
35018
33564
  if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
35019
33565
  if (buf.length <= d.mergedReadPos.value) return;
35020
33566
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
@@ -35039,7 +33585,7 @@ function wireDevServerChildProcess(d) {
35039
33585
  d.rmMergedCleanupDir(cleanupDir);
35040
33586
  }
35041
33587
  if (signal) {
35042
- d.log(`[dev-server] ${title} stopped (signal ${String(signal)})`);
33588
+ d.log(`[dev-server] ${title} stopped (signal: ${String(signal)}).`);
35043
33589
  } else if (code !== null && code !== 0) {
35044
33590
  const errTail = d.stderrTail.getTail().slice(-3).join("\n");
35045
33591
  d.log(`[dev-server] ${title} exited with code ${code}${errTail ? `
@@ -35052,7 +33598,7 @@ ${errTail}` : ""}`);
35052
33598
  d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
35053
33599
  };
35054
33600
  if (mergedPath) {
35055
- fs16.readFile(mergedPath, (err, buf) => {
33601
+ fs17.readFile(mergedPath, (err, buf) => {
35056
33602
  if (!err && buf.length > d.mergedReadPos.value) {
35057
33603
  const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
35058
33604
  if (chunk.length > 0) {
@@ -35154,13 +33700,13 @@ function parseDevServerDefs(servers) {
35154
33700
  }
35155
33701
 
35156
33702
  // src/dev-servers/manager/shell-spawn/utils.ts
35157
- import fs17 from "node:fs";
33703
+ import fs18 from "node:fs";
35158
33704
  function isSpawnEbadf(e) {
35159
33705
  return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
35160
33706
  }
35161
33707
  function rmDirQuiet(dir) {
35162
33708
  try {
35163
- fs17.rmSync(dir, { recursive: true, force: true });
33709
+ fs18.rmSync(dir, { recursive: true, force: true });
35164
33710
  } catch {
35165
33711
  }
35166
33712
  }
@@ -35168,7 +33714,7 @@ var cachedDevNullReadFd;
35168
33714
  function devNullReadFd() {
35169
33715
  if (cachedDevNullReadFd === void 0) {
35170
33716
  const devPath = process.platform === "win32" ? "nul" : "/dev/null";
35171
- cachedDevNullReadFd = fs17.openSync(devPath, "r");
33717
+ cachedDevNullReadFd = fs18.openSync(devPath, "r");
35172
33718
  }
35173
33719
  return cachedDevNullReadFd;
35174
33720
  }
@@ -35178,7 +33724,7 @@ function pipedStdoutStderrFor(attemptStdio) {
35178
33724
 
35179
33725
  // src/dev-servers/manager/shell-spawn/try-spawn-piped-via-sh.ts
35180
33726
  import { spawn as spawn5 } from "node:child_process";
35181
- function trySpawnPipedViaSh(command, env, cwd3, signal) {
33727
+ function trySpawnPipedViaSh(command, env, cwd, signal) {
35182
33728
  const attempts = [
35183
33729
  { stdio: [devNullReadFd(), "pipe", "pipe"], endStdin: false },
35184
33730
  { stdio: ["ignore", "pipe", "pipe"], endStdin: true },
@@ -35189,7 +33735,7 @@ function trySpawnPipedViaSh(command, env, cwd3, signal) {
35189
33735
  const attempt = attempts[i];
35190
33736
  const opts = {
35191
33737
  env,
35192
- cwd: cwd3,
33738
+ cwd,
35193
33739
  stdio: attempt.stdio,
35194
33740
  ...signal ? { signal } : {}
35195
33741
  };
@@ -35221,11 +33767,11 @@ function trySpawnPipedViaSh(command, env, cwd3, signal) {
35221
33767
 
35222
33768
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-true-piped.ts
35223
33769
  import { spawn as spawn6 } from "node:child_process";
35224
- function trySpawnShellTruePiped(command, env, cwd3, devNullFd, signal) {
33770
+ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
35225
33771
  try {
35226
33772
  const opts = {
35227
33773
  env,
35228
- cwd: cwd3,
33774
+ cwd,
35229
33775
  stdio: [devNullFd, "pipe", "pipe"],
35230
33776
  shell: true,
35231
33777
  ...signal ? { signal } : {}
@@ -35242,15 +33788,15 @@ function trySpawnShellTruePiped(command, env, cwd3, devNullFd, signal) {
35242
33788
 
35243
33789
  // src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
35244
33790
  import { spawn as spawn7 } from "node:child_process";
35245
- import fs18 from "node:fs";
33791
+ import fs19 from "node:fs";
35246
33792
  import { tmpdir } from "node:os";
35247
33793
  import path22 from "node:path";
35248
- function trySpawnMergedLogFile(command, env, cwd3, signal) {
35249
- const tmpRoot = fs18.mkdtempSync(path22.join(tmpdir(), "ba-devsrv-log-"));
33794
+ function trySpawnMergedLogFile(command, env, cwd, signal) {
33795
+ const tmpRoot = fs19.mkdtempSync(path22.join(tmpdir(), "ba-devsrv-log-"));
35250
33796
  const logPath = path22.join(tmpRoot, "combined.log");
35251
33797
  let logFd;
35252
33798
  try {
35253
- logFd = fs18.openSync(logPath, "a");
33799
+ logFd = fs19.openSync(logPath, "a");
35254
33800
  } catch {
35255
33801
  rmDirQuiet(tmpRoot);
35256
33802
  return null;
@@ -35261,15 +33807,15 @@ function trySpawnMergedLogFile(command, env, cwd3, signal) {
35261
33807
  if (process.platform === "win32") {
35262
33808
  proc = spawn7(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", command], {
35263
33809
  env,
35264
- cwd: cwd3,
33810
+ cwd,
35265
33811
  stdio,
35266
33812
  windowsHide: true,
35267
33813
  ...signal ? { signal } : {}
35268
33814
  });
35269
33815
  } else {
35270
- proc = spawn7("/bin/sh", ["-c", command], { env, cwd: cwd3, stdio, ...signal ? { signal } : {} });
33816
+ proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
35271
33817
  }
35272
- fs18.closeSync(logFd);
33818
+ fs19.closeSync(logFd);
35273
33819
  return {
35274
33820
  proc,
35275
33821
  pipedStdoutStderr: true,
@@ -35278,7 +33824,7 @@ function trySpawnMergedLogFile(command, env, cwd3, signal) {
35278
33824
  };
35279
33825
  } catch (e) {
35280
33826
  try {
35281
- fs18.closeSync(logFd);
33827
+ fs19.closeSync(logFd);
35282
33828
  } catch {
35283
33829
  }
35284
33830
  rmDirQuiet(tmpRoot);
@@ -35289,25 +33835,25 @@ function trySpawnMergedLogFile(command, env, cwd3, signal) {
35289
33835
 
35290
33836
  // src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
35291
33837
  import { spawn as spawn8 } from "node:child_process";
35292
- import fs19 from "node:fs";
33838
+ import fs20 from "node:fs";
35293
33839
  import { tmpdir as tmpdir2 } from "node:os";
35294
33840
  import path23 from "node:path";
35295
33841
  function shSingleQuote(s) {
35296
33842
  return `'${s.replace(/'/g, `'\\''`)}'`;
35297
33843
  }
35298
- function trySpawnShellScriptLogRedirectUnix(command, env, cwd3, signal) {
35299
- const tmpRoot = fs19.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
33844
+ function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
33845
+ const tmpRoot = fs20.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
35300
33846
  const logPath = path23.join(tmpRoot, "combined.log");
35301
33847
  const innerPath = path23.join(tmpRoot, "_cmd.sh");
35302
33848
  const runnerPath = path23.join(tmpRoot, "_run.sh");
35303
33849
  try {
35304
- fs19.writeFileSync(innerPath, `#!/bin/sh
33850
+ fs20.writeFileSync(innerPath, `#!/bin/sh
35305
33851
  ${command}
35306
33852
  `);
35307
- fs19.writeFileSync(
33853
+ fs20.writeFileSync(
35308
33854
  runnerPath,
35309
33855
  `#!/bin/sh
35310
- cd ${shSingleQuote(cwd3)}
33856
+ cd ${shSingleQuote(cwd)}
35311
33857
  /bin/sh ${shSingleQuote(innerPath)} >>${shSingleQuote(logPath)} 2>&1
35312
33858
  `
35313
33859
  );
@@ -35329,17 +33875,17 @@ cd ${shSingleQuote(cwd3)}
35329
33875
  throw e;
35330
33876
  }
35331
33877
  }
35332
- function trySpawnShellScriptLogRedirectWin(command, env, cwd3, signal) {
35333
- const tmpRoot = fs19.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
33878
+ function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
33879
+ const tmpRoot = fs20.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
35334
33880
  const logPath = path23.join(tmpRoot, "combined.log");
35335
33881
  const runnerPath = path23.join(tmpRoot, "_run.bat");
35336
33882
  const q = (p) => `"${p.replace(/"/g, '""')}"`;
35337
33883
  const com = process.env.ComSpec || "cmd.exe";
35338
33884
  try {
35339
- fs19.writeFileSync(
33885
+ fs20.writeFileSync(
35340
33886
  runnerPath,
35341
33887
  `@ECHO OFF\r
35342
- CD /D ${q(cwd3)}\r
33888
+ CD /D ${q(cwd)}\r
35343
33889
  ${command} >> ${q(logPath)} 2>&1\r
35344
33890
  `
35345
33891
  );
@@ -35365,10 +33911,10 @@ ${command} >> ${q(logPath)} 2>&1\r
35365
33911
 
35366
33912
  // src/dev-servers/manager/shell-spawn/try-spawn-inherit.ts
35367
33913
  import { spawn as spawn9 } from "node:child_process";
35368
- function trySpawnInheritStdio(command, env, cwd3, signal) {
33914
+ function trySpawnInheritStdio(command, env, cwd, signal) {
35369
33915
  const opts = {
35370
33916
  env,
35371
- cwd: cwd3,
33917
+ cwd,
35372
33918
  stdio: "inherit",
35373
33919
  ...signal ? { signal } : {}
35374
33920
  };
@@ -35384,27 +33930,27 @@ function trySpawnInheritStdio(command, env, cwd3, signal) {
35384
33930
  }
35385
33931
 
35386
33932
  // src/dev-servers/manager/shell-spawn/shell-spawn.ts
35387
- function shellSpawn(command, env, cwd3, options) {
33933
+ function shellSpawn(command, env, cwd, options) {
35388
33934
  const signal = options?.signal;
35389
- const piped = trySpawnPipedViaSh(command, env, cwd3, signal);
33935
+ const piped = trySpawnPipedViaSh(command, env, cwd, signal);
35390
33936
  if (piped.ok) {
35391
33937
  return piped.result;
35392
33938
  }
35393
33939
  let lastErr = piped.lastErr;
35394
- const shellTrueProc = trySpawnShellTruePiped(command, env, cwd3, devNullReadFd(), signal);
33940
+ const shellTrueProc = trySpawnShellTruePiped(command, env, cwd, devNullReadFd(), signal);
35395
33941
  if (shellTrueProc) {
35396
33942
  return { proc: shellTrueProc, pipedStdoutStderr: true };
35397
33943
  }
35398
- const fileCapture = trySpawnMergedLogFile(command, env, cwd3, signal);
33944
+ const fileCapture = trySpawnMergedLogFile(command, env, cwd, signal);
35399
33945
  if (fileCapture) {
35400
33946
  return fileCapture;
35401
33947
  }
35402
- const scriptCapture = process.platform === "win32" ? trySpawnShellScriptLogRedirectWin(command, env, cwd3, signal) : trySpawnShellScriptLogRedirectUnix(command, env, cwd3, signal);
33948
+ const scriptCapture = process.platform === "win32" ? trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) : trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal);
35403
33949
  if (scriptCapture) {
35404
33950
  return scriptCapture;
35405
33951
  }
35406
33952
  try {
35407
- return trySpawnInheritStdio(command, env, cwd3, signal);
33953
+ return trySpawnInheritStdio(command, env, cwd, signal);
35408
33954
  } catch (e) {
35409
33955
  throw lastErr instanceof Error ? lastErr : e instanceof Error ? e : new Error(String(e));
35410
33956
  }
@@ -35462,9 +34008,11 @@ var DevServerManager = class {
35462
34008
  abortControllersByServerId = /* @__PURE__ */ new Map();
35463
34009
  getWs;
35464
34010
  log;
34011
+ getBridgeCwd;
35465
34012
  constructor(options) {
35466
34013
  this.getWs = options.getWs;
35467
34014
  this.log = options.log;
34015
+ this.getBridgeCwd = options.getBridgeCwd ?? (() => process.cwd());
35468
34016
  }
35469
34017
  attachFirehose(send) {
35470
34018
  this.firehoseSend = send;
@@ -35588,7 +34136,7 @@ var DevServerManager = class {
35588
34136
  this.sendStatus(serverId, "starting", void 0, emptyTails());
35589
34137
  const ac = new AbortController();
35590
34138
  this.abortControllersByServerId.set(serverId, ac);
35591
- const cwd3 = process.cwd();
34139
+ const cwd = this.getBridgeCwd();
35592
34140
  const childEnv = envForSpawn(process.env, def.env, def.ports);
35593
34141
  const cmd = substituteCommand(def.command.trim(), childEnv);
35594
34142
  const title = def.name.trim() || serverId.slice(0, 8);
@@ -35603,7 +34151,7 @@ var DevServerManager = class {
35603
34151
  let mergedLogPath;
35604
34152
  let mergedCleanupDir;
35605
34153
  try {
35606
- const spawned = shellSpawn(cmd, childEnv, cwd3, {
34154
+ const spawned = shellSpawn(cmd, childEnv, cwd, {
35607
34155
  signal: ac.signal
35608
34156
  });
35609
34157
  proc = spawned.proc;
@@ -35612,7 +34160,7 @@ var DevServerManager = class {
35612
34160
  mergedCleanupDir = spawned.mergedLogCleanupDir;
35613
34161
  } catch (e) {
35614
34162
  const msg = e instanceof Error ? e.message : String(e);
35615
- this.log(`[dev-server] ${title} failed to start: ${msg}`);
34163
+ this.log(`[dev-server] Failed to start ${title}: ${msg}`);
35616
34164
  this.abortControllersByServerId.delete(serverId);
35617
34165
  this.sendStatus(serverId, "error", msg, emptyTails());
35618
34166
  return;
@@ -35750,7 +34298,7 @@ async function proxyToLocal(request) {
35750
34298
  path: url2.pathname + url2.search,
35751
34299
  headers: request.headers
35752
34300
  };
35753
- return new Promise((resolve17) => {
34301
+ return new Promise((resolve15) => {
35754
34302
  const req = mod.request(opts, (res) => {
35755
34303
  const chunks = [];
35756
34304
  res.on("data", (c) => chunks.push(c));
@@ -35761,7 +34309,7 @@ async function proxyToLocal(request) {
35761
34309
  if (typeof v === "string") headers[k] = v;
35762
34310
  else if (Array.isArray(v) && v[0]) headers[k] = v[0];
35763
34311
  }
35764
- resolve17({
34312
+ resolve15({
35765
34313
  id: request.id,
35766
34314
  statusCode: res.statusCode ?? 0,
35767
34315
  headers,
@@ -35770,7 +34318,7 @@ async function proxyToLocal(request) {
35770
34318
  });
35771
34319
  });
35772
34320
  req.on("error", (err) => {
35773
- resolve17({
34321
+ resolve15({
35774
34322
  id: request.id,
35775
34323
  statusCode: 0,
35776
34324
  headers: {},
@@ -35844,7 +34392,7 @@ function startStreamingProxy(ws, log2, pr) {
35844
34392
  },
35845
34393
  onEnd: () => sendWsMessage(ws, { type: "proxy_result_end", id: pr.id }),
35846
34394
  onError: (error40) => {
35847
- log2(`[Proxy and log service] streaming preview failed: ${error40}`);
34395
+ log2(`[Proxy and log service] Streaming preview failed: ${error40}`);
35848
34396
  sendWsMessage(ws, { type: "proxy_result_error", id: pr.id, error: error40 });
35849
34397
  }
35850
34398
  });
@@ -35917,11 +34465,11 @@ var handleProxyMessage = (msg, deps) => {
35917
34465
  return;
35918
34466
  }
35919
34467
  void proxyToLocal(pr).then((res) => {
35920
- if (res.error) deps.log(`[Proxy and log service] preview proxy failed: ${res.error}`);
34468
+ if (res.error) deps.log(`[Proxy and log service] Preview proxy failed: ${res.error}`);
35921
34469
  sendWsMessage(deps.ws, { type: "proxy_result", ...res, id: pr.id });
35922
34470
  }).catch((err) => {
35923
34471
  deps.log(
35924
- `[Proxy and log service] preview proxy failed: ${err instanceof Error ? err.message : String(err)}`
34472
+ `[Proxy and log service] Preview proxy failed: ${err instanceof Error ? err.message : String(err)}`
35925
34473
  );
35926
34474
  sendWsMessage(deps.ws, { type: "proxy_result", id: pr.id, error: String(err) });
35927
34475
  });
@@ -35958,6 +34506,7 @@ function tryConsumeBinaryProxyBody(raw, deps) {
35958
34506
  }
35959
34507
 
35960
34508
  // src/firehose/connect-firehose.ts
34509
+ var FIREHOSE_CLIENT_PING_MS = 25e3;
35961
34510
  function connectFirehose(options) {
35962
34511
  const { firehoseServerUrl, workspaceId, bridgeName, proxyPorts, log: log2, devServerManager, onOpen, onClose } = options;
35963
34512
  const wsUrl = buildFirehoseCliWsUrl(firehoseServerUrl);
@@ -35966,6 +34515,13 @@ function connectFirehose(options) {
35966
34515
  wsOptions.agent = new https2.Agent({ rejectUnauthorized: false });
35967
34516
  }
35968
34517
  const ws = new wrapper_default(wsUrl, wsOptions);
34518
+ let clientPingTimer = null;
34519
+ function clearClientPing() {
34520
+ if (clientPingTimer != null) {
34521
+ clearInterval(clientPingTimer);
34522
+ clientPingTimer = null;
34523
+ }
34524
+ }
35969
34525
  const firehoseSend = (payload) => {
35970
34526
  sendWsMessage(ws, payload);
35971
34527
  };
@@ -35978,6 +34534,15 @@ function connectFirehose(options) {
35978
34534
  startStreamingProxy: (pr) => startStreamingProxy(ws, log2, pr)
35979
34535
  };
35980
34536
  ws.on("open", () => {
34537
+ clearClientPing();
34538
+ clientPingTimer = setInterval(() => {
34539
+ if (ws.readyState === wrapper_default.OPEN) {
34540
+ try {
34541
+ ws.ping();
34542
+ } catch {
34543
+ }
34544
+ }
34545
+ }, FIREHOSE_CLIENT_PING_MS);
35981
34546
  onOpen?.();
35982
34547
  devServerManager.attachFirehose(firehoseSend);
35983
34548
  sendWsMessage(ws, { type: "identify", workspaceId, bridgeName, proxyPorts });
@@ -35995,35 +34560,30 @@ function connectFirehose(options) {
35995
34560
  });
35996
34561
  });
35997
34562
  ws.on("close", (code, reason) => {
34563
+ clearClientPing();
35998
34564
  devServerManager.detachFirehose();
35999
- log2(
36000
- formatWebSocketClose(
36001
- "[Proxy and log service]",
36002
- code,
36003
- typeof reason === "string" ? reason : reason.toString(),
36004
- "reconnects automatically if the bridge service stays connected"
36005
- )
36006
- );
36007
- onClose?.();
34565
+ const reasonStr = typeof reason === "string" ? reason : reason.toString();
34566
+ onClose?.(code, reasonStr);
36008
34567
  });
36009
34568
  ws.on("error", (err) => {
34569
+ clearClientPing();
36010
34570
  log2(`[Proxy and log service] WebSocket error: ${err.message}`);
36011
34571
  });
36012
34572
  return {
36013
34573
  close() {
34574
+ clearClientPing();
36014
34575
  devServerManager.detachFirehose();
36015
34576
  try {
36016
34577
  ws.removeAllListeners();
36017
34578
  ws.close();
36018
34579
  } catch {
36019
34580
  }
36020
- }
34581
+ },
34582
+ isConnected: () => ws.readyState === wrapper_default.OPEN
36021
34583
  };
36022
34584
  }
36023
34585
 
36024
34586
  // src/bridge/connection/create-bridge-identified-handler.ts
36025
- var FH_RECONNECT_BASE_MS = 2e3;
36026
- var FH_RECONNECT_MAX_MS = 3e4;
36027
34587
  function createOnBridgeIdentified(opts) {
36028
34588
  const { sessionWorktreeManager, devServerManager, firehoseServerUrl, workspaceId, state, logFn } = opts;
36029
34589
  function clearFirehoseReconnectTimer() {
@@ -36032,6 +34592,14 @@ function createOnBridgeIdentified(opts) {
36032
34592
  state.firehoseReconnectTimeout = null;
36033
34593
  }
36034
34594
  }
34595
+ function firehoseCtx() {
34596
+ return {
34597
+ closedByUser: state.closedByUser,
34598
+ currentWs: state.currentWs,
34599
+ firehoseHandle: state.firehoseHandle,
34600
+ firehoseQuiet: state.firehoseQuiet
34601
+ };
34602
+ }
36035
34603
  function attachFirehose(params) {
36036
34604
  state.lastFirehoseParams = params;
36037
34605
  clearFirehoseReconnectTimer();
@@ -36050,37 +34618,52 @@ function createOnBridgeIdentified(opts) {
36050
34618
  devServerManager,
36051
34619
  onOpen: () => {
36052
34620
  if (myGen !== state.firehoseGeneration) return;
34621
+ clearFirehoseReconnectQuietOnOpen({ firehoseQuiet: state.firehoseQuiet }, logFn);
34622
+ const logOpenAsFirehoseReconnect = state.firehoseReconnectAttempt > 0;
36053
34623
  state.firehoseReconnectAttempt = 0;
34624
+ if (logOpenAsFirehoseReconnect) {
34625
+ logFn("[Proxy and log service] reconnected.");
34626
+ }
36054
34627
  },
36055
- onClose: () => {
34628
+ onClose: (code, reason) => {
36056
34629
  if (myGen !== state.firehoseGeneration) return;
36057
34630
  state.firehoseHandle = null;
36058
34631
  if (state.closedByUser) return;
36059
34632
  const main2 = state.currentWs;
36060
34633
  if (!main2 || main2.readyState !== wrapper_default.OPEN) {
36061
- logFn("[Proxy and log service] not reconnecting: bridge service socket is not open");
34634
+ logFn(
34635
+ `${PROXY_AND_LOG_SERVICE_LABEL} Not reconnecting preview and log stream: main bridge connection is not open.`
34636
+ );
36062
34637
  return;
36063
34638
  }
34639
+ beginFirehoseDeferredDisconnect(firehoseCtx(), code, reason, logFn);
36064
34640
  clearFirehoseReconnectTimer();
36065
- const delay2 = Math.min(
36066
- FH_RECONNECT_BASE_MS * 2 ** state.firehoseReconnectAttempt,
36067
- FH_RECONNECT_MAX_MS
36068
- );
34641
+ const delay2 = reconnectDelayMs(state.firehoseReconnectAttempt);
36069
34642
  state.firehoseReconnectAttempt += 1;
36070
- logFn(
36071
- `[Proxy and log service] reconnect attempt ${state.firehoseReconnectAttempt} in ${delay2 / 1e3}s\u2026`
34643
+ logNextReconnectAttempt(
34644
+ logFn,
34645
+ PROXY_AND_LOG_SERVICE_LABEL,
34646
+ state.firehoseQuiet,
34647
+ delay2,
34648
+ state.firehoseReconnectAttempt
36072
34649
  );
36073
34650
  state.firehoseReconnectTimeout = setTimeout(() => {
36074
34651
  state.firehoseReconnectTimeout = null;
36075
34652
  if (state.closedByUser) return;
36076
34653
  const w = state.currentWs;
36077
34654
  if (!w || w.readyState !== wrapper_default.OPEN) {
36078
- logFn("[Proxy and log service] reconnect skipped: bridge service socket closed");
34655
+ if (state.firehoseQuiet.verboseLogs) {
34656
+ logFn(
34657
+ `${PROXY_AND_LOG_SERVICE_LABEL} Reconnect skipped: main bridge connection closed before preview stream could reconnect.`
34658
+ );
34659
+ }
36079
34660
  return;
36080
34661
  }
36081
34662
  const p = state.lastFirehoseParams;
36082
34663
  if (!p) {
36083
- logFn("[Proxy and log service] reconnect skipped: no stored connection params");
34664
+ if (state.firehoseQuiet.verboseLogs) {
34665
+ logFn(`${PROXY_AND_LOG_SERVICE_LABEL} Reconnect skipped: no stored connection parameters.`);
34666
+ }
36084
34667
  return;
36085
34668
  }
36086
34669
  attachFirehose(p);
@@ -36163,10 +34746,12 @@ function createSendLocalSkillsReport(getWs, logFn) {
36163
34746
  try {
36164
34747
  const socket = getWs();
36165
34748
  if (!socket || socket.readyState !== wrapper_default.OPEN) return;
36166
- const skills2 = discoverLocalSkills(process.cwd());
34749
+ const skills2 = discoverLocalSkills(getBridgeWorkspaceDirectory());
36167
34750
  socket.send(JSON.stringify({ type: "local_skills", skills: skills2 }));
36168
34751
  } catch (e) {
36169
- logFn(`[Bridge service] local_skills report failed: ${e instanceof Error ? e.message : String(e)}`);
34752
+ logFn(
34753
+ `[Bridge service] Local skills report failed: ${e instanceof Error ? e.message : String(e)}`
34754
+ );
36170
34755
  }
36171
34756
  };
36172
34757
  }
@@ -36179,12 +34764,15 @@ function createReportAutoDetectedAgents(getWs, logFn) {
36179
34764
  sendWsMessage(socket, { type: "auto_detected_agents_report", agentTypes: types });
36180
34765
  }
36181
34766
  } catch (e) {
36182
- logFn(`[Bridge service] auto_detected_agents report failed: ${e instanceof Error ? e.message : String(e)}`);
34767
+ logFn(
34768
+ `[Bridge service] Auto-detected agents report failed: ${e instanceof Error ? e.message : String(e)}`
34769
+ );
36183
34770
  }
36184
34771
  };
36185
34772
  }
36186
34773
 
36187
34774
  // src/bridge/connection/create-bridge-connection.ts
34775
+ var BRIDGE_CLIENT_PING_MS = 25e3;
36188
34776
  async function createBridgeConnection(options) {
36189
34777
  const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
36190
34778
  const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
@@ -36195,13 +34783,16 @@ async function createBridgeConnection(options) {
36195
34783
  const state = {
36196
34784
  closedByUser: false,
36197
34785
  reconnectAttempt: 0,
34786
+ logBridgeOpenAsReconnect: false,
36198
34787
  reconnectTimeout: null,
36199
34788
  currentWs: null,
34789
+ mainQuiet: createEmptyReconnectQuietSlot(),
36200
34790
  firehoseHandle: null,
36201
34791
  lastFirehoseParams: null,
36202
34792
  firehoseReconnectTimeout: null,
36203
34793
  firehoseReconnectAttempt: 0,
36204
- firehoseGeneration: 0
34794
+ firehoseGeneration: 0,
34795
+ firehoseQuiet: createEmptyReconnectQuietSlot()
36205
34796
  };
36206
34797
  const worktreesRootAbs = options.worktreesRootAbs ?? defaultWorktreesRootAbs();
36207
34798
  const sessionWorktreeManager = new SessionWorktreeManager({
@@ -36213,7 +34804,7 @@ async function createBridgeConnection(options) {
36213
34804
  function getWs() {
36214
34805
  return state.currentWs;
36215
34806
  }
36216
- const devServerManager = new DevServerManager({ getWs, log: logFn });
34807
+ const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory });
36217
34808
  const onBridgeIdentified = createOnBridgeIdentified({
36218
34809
  sessionWorktreeManager,
36219
34810
  devServerManager,
@@ -36225,7 +34816,13 @@ async function createBridgeConnection(options) {
36225
34816
  const sendLocalSkillsReport = createSendLocalSkillsReport(getWs, logFn);
36226
34817
  const reportAutoDetectedAgents = createReportAutoDetectedAgents(getWs, logFn);
36227
34818
  function handleOpen() {
34819
+ const logOpenAsPostRefreshReconnect = state.logBridgeOpenAsReconnect;
34820
+ clearMainBridgeReconnectQuietOnOpen(state, logFn);
36228
34821
  state.reconnectAttempt = 0;
34822
+ state.logBridgeOpenAsReconnect = false;
34823
+ if (logOpenAsPostRefreshReconnect) {
34824
+ logFn("[Bridge service] reconnected.");
34825
+ }
36229
34826
  const socket = getWs();
36230
34827
  if (socket) {
36231
34828
  sendWsMessage(socket, { type: "identify", role: "cli" });
@@ -36242,11 +34839,9 @@ async function createBridgeConnection(options) {
36242
34839
  state.currentWs = null;
36243
34840
  if (was) was.removeAllListeners();
36244
34841
  const willReconnect = !state.closedByUser;
36245
- logFn(
36246
- formatWebSocketClose("[Bridge service]", code, reason, willReconnect ? "will schedule reconnect" : "not reconnecting (CLI shutting down)")
36247
- );
34842
+ beginMainBridgeDeferredDisconnect(state, code, reason, logFn, willReconnect);
36248
34843
  if (willReconnect) {
36249
- scheduleReconnect(state, connect, logFn);
34844
+ scheduleMainBridgeReconnect(state, connect, logFn);
36250
34845
  }
36251
34846
  }
36252
34847
  const messageDeps = {
@@ -36261,6 +34856,10 @@ async function createBridgeConnection(options) {
36261
34856
  };
36262
34857
  function connect() {
36263
34858
  if (state.closedByUser) return;
34859
+ if (state.reconnectTimeout != null) {
34860
+ clearTimeout(state.reconnectTimeout);
34861
+ state.reconnectTimeout = null;
34862
+ }
36264
34863
  const prev = state.currentWs;
36265
34864
  if (prev) {
36266
34865
  prev.removeAllListeners();
@@ -36273,6 +34872,7 @@ async function createBridgeConnection(options) {
36273
34872
  const url2 = buildBridgeUrl(apiUrl, workspaceId, accessToken);
36274
34873
  state.currentWs = createWsBridge({
36275
34874
  url: url2,
34875
+ clientPingIntervalMs: BRIDGE_CLIENT_PING_MS,
36276
34876
  onAuthInvalid: () => {
36277
34877
  if (authRefreshInFlight) return;
36278
34878
  void (async () => {
@@ -36284,8 +34884,9 @@ async function createBridgeConnection(options) {
36284
34884
  accessToken = next.token;
36285
34885
  refreshTok = next.refreshToken;
36286
34886
  persistTokens?.({ token: accessToken, refreshToken: refreshTok });
36287
- logFn("[Bridge service] access token refreshed; reconnecting\u2026");
34887
+ logFn("[Bridge service] Access token refreshed; reconnecting\u2026");
36288
34888
  state.reconnectAttempt = 0;
34889
+ state.logBridgeOpenAsReconnect = true;
36289
34890
  authRefreshInFlight = false;
36290
34891
  connect();
36291
34892
  return;
@@ -36308,7 +34909,7 @@ async function createBridgeConnection(options) {
36308
34909
  });
36309
34910
  }
36310
34911
  connect();
36311
- const stopFileIndexWatcher = startFileIndexWatcher(process.cwd());
34912
+ const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
36312
34913
  return {
36313
34914
  close: async () => {
36314
34915
  stopFileIndexWatcher();
@@ -36381,7 +34982,7 @@ async function runBridge(options) {
36381
34982
  });
36382
34983
  },
36383
34984
  onAuthInvalid: () => {
36384
- log("[Bridge service] token invalid or revoked; re-authenticating\u2026");
34985
+ log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
36385
34986
  clearConfigForApi(apiUrl);
36386
34987
  void handle.close().then(() => {
36387
34988
  void runBridge({ apiUrl, firehoseServerUrl, worktreesRootAbs });
@@ -36428,7 +35029,7 @@ async function main() {
36428
35029
  if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
36429
35030
  const resolvedCwd = path24.resolve(process.cwd(), opts.cwd.trim());
36430
35031
  try {
36431
- const st = fs20.statSync(resolvedCwd);
35032
+ const st = fs21.statSync(resolvedCwd);
36432
35033
  if (!st.isDirectory()) {
36433
35034
  console.error(`--cwd is not a directory: ${resolvedCwd}`);
36434
35035
  process.exit(1);
@@ -36439,6 +35040,7 @@ async function main() {
36439
35040
  }
36440
35041
  process.chdir(resolvedCwd);
36441
35042
  }
35043
+ initBridgeWorkspaceDirectory();
36442
35044
  let worktreesRootAbs;
36443
35045
  if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
36444
35046
  worktreesRootAbs = path24.resolve(opts.worktreesRoot.trim());
@@ -36468,9 +35070,4 @@ main().catch((err) => {
36468
35070
  console.error(err);
36469
35071
  process.exit(1);
36470
35072
  });
36471
- /*! Bundled license information:
36472
-
36473
- chokidar/esm/index.js:
36474
- (*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
36475
- */
36476
35073
  //# sourceMappingURL=cli.js.map