@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 +892 -2295
- package/dist/cli.js.map +4 -4
- package/dist/index.js +899 -2302
- package/dist/index.js.map +4 -4
- package/package.json +1 -2
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
|
|
974
|
+
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
975
975
|
var childProcess = __require("node:child_process");
|
|
976
976
|
var path25 = __require("node:path");
|
|
977
|
-
var
|
|
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
|
|
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 (
|
|
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) =>
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
7430
|
-
if (
|
|
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 (
|
|
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((
|
|
24804
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
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((
|
|
24954
|
-
this.#pendingResponses.set(id, { resolve:
|
|
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
|
|
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
|
|
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}
|
|
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((
|
|
25308
|
-
resolveAuth =
|
|
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
|
-
|
|
25355
|
-
|
|
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
|
-
},
|
|
25556
|
+
}, delay2);
|
|
25361
25557
|
},
|
|
25362
|
-
onError: (err) => logFn(`[Bridge service] WebSocket error
|
|
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
|
|
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(
|
|
26666
|
-
this._cwd =
|
|
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(
|
|
26858
|
-
this.cwd =
|
|
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(
|
|
30184
|
+
async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
29989
30185
|
const result = [];
|
|
29990
|
-
const cwdResolved =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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((
|
|
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]
|
|
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]
|
|
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]
|
|
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
|
-
|
|
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(
|
|
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
|
|
30137
|
-
|
|
30138
|
-
|
|
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
|
-
|
|
30145
|
-
|
|
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
|
|
30148
|
-
|
|
30149
|
-
|
|
30150
|
-
|
|
30151
|
-
|
|
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
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
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
|
|
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]
|
|
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 =
|
|
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
|
|
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(
|
|
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 (
|
|
30216
|
-
await
|
|
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(`[
|
|
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(`[
|
|
30231
|
-
if (err instanceof Error && err.stack) log2(`[
|
|
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
|
|
30245
|
-
import * as
|
|
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
|
|
30277
|
-
const
|
|
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
|
|
30580
|
+
cwd,
|
|
30280
30581
|
stdio: ["pipe", "pipe", "inherit"],
|
|
30281
30582
|
env: process.env,
|
|
30282
|
-
shell:
|
|
30583
|
+
shell: isWindows
|
|
30283
30584
|
});
|
|
30284
|
-
return new Promise((
|
|
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:
|
|
30612
|
+
const newSessionRes = await connection.newSession({ workingDirectory: cwd });
|
|
30312
30613
|
const sessionId = newSessionRes.sessionId;
|
|
30313
|
-
|
|
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
|
|
30375
|
-
function resolveSafePathUnderCwd(
|
|
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 =
|
|
30379
|
-
const resolved =
|
|
30380
|
-
const rel =
|
|
30381
|
-
if (rel.startsWith("..") ||
|
|
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(
|
|
30385
|
-
const normalizedCwd =
|
|
30386
|
-
const rel =
|
|
30387
|
-
if (!rel || rel === "") return
|
|
30388
|
-
return rel.split(
|
|
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
|
|
30776
|
+
const { command, cwd = getBridgeWorkspaceDirectory(), onSessionUpdate, onRequest, onFileChange } = options;
|
|
30463
30777
|
const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
|
|
30464
|
-
const
|
|
30778
|
+
const isWindows = process.platform === "win32";
|
|
30465
30779
|
const child = spawn3(command[0], command.slice(1), {
|
|
30466
|
-
cwd
|
|
30780
|
+
cwd,
|
|
30467
30781
|
stdio: ["pipe", "pipe", "inherit"],
|
|
30468
30782
|
env: process.env,
|
|
30469
|
-
shell:
|
|
30783
|
+
shell: isWindows
|
|
30470
30784
|
});
|
|
30471
|
-
return new Promise((
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
30592
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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 ?
|
|
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
|
|
30733
|
-
import * as
|
|
30734
|
-
function resolveWorkspaceFilePath(
|
|
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 =
|
|
30738
|
-
let abs = resolveSafePathUnderCwd(
|
|
31054
|
+
const normalizedCwd = path8.resolve(cwd);
|
|
31055
|
+
let abs = resolveSafePathUnderCwd(cwd, trimmed2);
|
|
30739
31056
|
if (!abs) {
|
|
30740
|
-
const candidate =
|
|
30741
|
-
const gitRoot2 = getGitRepoRootSync(
|
|
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 =
|
|
30744
|
-
if (rel.startsWith("..") ||
|
|
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(
|
|
31064
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
30748
31065
|
if (gitRoot) {
|
|
30749
|
-
const relFromRoot =
|
|
30750
|
-
if (!relFromRoot.startsWith("..") && !
|
|
30751
|
-
return { abs, display: relFromRoot.split(
|
|
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(
|
|
31071
|
+
return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
|
|
30755
31072
|
}
|
|
30756
|
-
function readUtf8WorkspaceFile(
|
|
31073
|
+
function readUtf8WorkspaceFile(cwd, displayPath) {
|
|
30757
31074
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
30758
|
-
const gitRoot = getGitRepoRootSync(
|
|
31075
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
30759
31076
|
if (gitRoot) {
|
|
30760
|
-
const abs2 =
|
|
30761
|
-
const rel =
|
|
30762
|
-
if (!rel.startsWith("..") && !
|
|
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
|
|
31081
|
+
return readFileSync4(abs2, "utf8");
|
|
30765
31082
|
} catch {
|
|
30766
31083
|
}
|
|
30767
31084
|
}
|
|
30768
31085
|
}
|
|
30769
|
-
const abs = resolveSafePathUnderCwd(
|
|
31086
|
+
const abs = resolveSafePathUnderCwd(cwd, displayPath);
|
|
30770
31087
|
if (!abs) return "";
|
|
30771
31088
|
try {
|
|
30772
|
-
return
|
|
31089
|
+
return readFileSync4(abs, "utf8");
|
|
30773
31090
|
} catch {
|
|
30774
31091
|
return "";
|
|
30775
31092
|
}
|
|
30776
31093
|
}
|
|
30777
|
-
function tryWorkspaceDisplayToAbs(
|
|
31094
|
+
function tryWorkspaceDisplayToAbs(cwd, displayPath) {
|
|
30778
31095
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
30779
|
-
const gitRoot = getGitRepoRootSync(
|
|
31096
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
30780
31097
|
if (gitRoot) {
|
|
30781
|
-
const abs =
|
|
30782
|
-
const rel =
|
|
30783
|
-
if (!rel.startsWith("..") && !
|
|
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(
|
|
31102
|
+
return resolveSafePathUnderCwd(cwd, displayPath);
|
|
30786
31103
|
}
|
|
30787
|
-
function readGitHeadBlob(
|
|
31104
|
+
function readGitHeadBlob(cwd, displayPath) {
|
|
30788
31105
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
30789
|
-
const gitRoot = getGitRepoRootSync(
|
|
30790
|
-
const execCwd = gitRoot ??
|
|
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(
|
|
31120
|
+
function gitHeadPathObjectType(cwd, displayPath) {
|
|
30804
31121
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
30805
|
-
const gitRoot = getGitRepoRootSync(
|
|
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(
|
|
30817
|
-
const abs = tryWorkspaceDisplayToAbs(
|
|
31133
|
+
function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
|
|
31134
|
+
const abs = tryWorkspaceDisplayToAbs(cwd, displayPath);
|
|
30818
31135
|
if (abs && existsSync(abs)) {
|
|
30819
31136
|
try {
|
|
30820
|
-
if (
|
|
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(
|
|
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(
|
|
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
|
|
30846
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(
|
|
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]
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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,
|
|
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,
|
|
31272
|
+
pushDiffIfComplete(o, cwd, out);
|
|
30952
31273
|
if (o.type === "content" && o.content != null && typeof o.content === "object") {
|
|
30953
|
-
walkValue(o.content,
|
|
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),
|
|
31282
|
+
walkValue(JSON.parse(v), cwd, depth + 1, out);
|
|
30962
31283
|
} catch {
|
|
30963
31284
|
}
|
|
30964
31285
|
continue;
|
|
30965
31286
|
}
|
|
30966
|
-
walkValue(v,
|
|
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,
|
|
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,
|
|
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(
|
|
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(
|
|
31310
|
+
const resolved = resolveWorkspaceFilePath(cwd, trimmed2);
|
|
30990
31311
|
if (!resolved) return;
|
|
30991
31312
|
out.add(resolved.display);
|
|
30992
31313
|
}
|
|
30993
|
-
function walkLocations(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
31336
|
+
if (v != null && typeof v === "object") collectUnknown(cwd, v, out, depth + 1);
|
|
31016
31337
|
}
|
|
31017
31338
|
}
|
|
31018
|
-
function collectUnknown(
|
|
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(
|
|
31342
|
+
for (const x of v) collectUnknown(cwd, x, out, depth + 1);
|
|
31022
31343
|
return;
|
|
31023
31344
|
}
|
|
31024
|
-
if (typeof v === "object") collectFromObject(
|
|
31345
|
+
if (typeof v === "object") collectFromObject(cwd, v, out, depth);
|
|
31025
31346
|
}
|
|
31026
|
-
function walkContentArray(
|
|
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(
|
|
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(
|
|
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,
|
|
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(
|
|
31047
|
-
walkLocations(
|
|
31048
|
-
walkLocations(
|
|
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(
|
|
31374
|
+
collectUnknown(cwd, parsed, out, 0);
|
|
31054
31375
|
} catch {
|
|
31055
31376
|
}
|
|
31056
31377
|
}
|
|
31057
|
-
walkContentArray(
|
|
31058
|
-
collectFromObject(
|
|
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,
|
|
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(
|
|
31454
|
+
m.set(p, readUtf8WorkspaceFile(cwd, p));
|
|
31134
31455
|
}
|
|
31135
31456
|
}
|
|
31136
|
-
ensureBeforeFromHeadForMissing(toolKey, paths,
|
|
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(
|
|
31465
|
+
m.set(p, readGitHeadBlob(cwd, p));
|
|
31145
31466
|
}
|
|
31146
31467
|
}
|
|
31147
|
-
flushPathSnapshots(toolKey,
|
|
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(
|
|
31477
|
+
const newText = readUtf8WorkspaceFile(cwd, displayPath);
|
|
31157
31478
|
if (oldText === newText) continue;
|
|
31158
31479
|
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
31159
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(
|
|
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]
|
|
31495
|
+
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
31175
31496
|
}
|
|
31176
31497
|
}
|
|
31177
31498
|
}
|
|
31178
|
-
scheduleDebouncedFlush(toolKey,
|
|
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,
|
|
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,
|
|
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,
|
|
31515
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
|
|
31195
31516
|
} else if (updateKind === "tool_call_update") {
|
|
31196
31517
|
if (isCompletedToolStatus(status)) {
|
|
31197
|
-
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths,
|
|
31198
|
-
this.flushPathSnapshots(toolKey,
|
|
31518
|
+
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, cwd);
|
|
31519
|
+
this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
|
|
31199
31520
|
} else {
|
|
31200
|
-
this.captureBeforeFromDisk(toolKey, toolPaths,
|
|
31521
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
|
|
31201
31522
|
if (this.beforeByToolKey.has(toolKey)) {
|
|
31202
|
-
this.scheduleDebouncedFlush(toolKey,
|
|
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,
|
|
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(
|
|
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]
|
|
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,
|
|
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(
|
|
31236
|
-
const newText = readUtf8WorkspaceFile(
|
|
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(
|
|
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]
|
|
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
|
|
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,
|
|
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
|
-
|
|
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,
|
|
31619
|
+
const diffs = extractAcpFileDiffsFromUpdate(params, cwd);
|
|
31299
31620
|
if (diffs.length > 0 && send && runId && sessionId) {
|
|
31300
|
-
sendExtractedDiffsAsSessionFileChanges(diffs, send,
|
|
31621
|
+
sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentFileChangePaths, log2);
|
|
31301
31622
|
} else if (diffs.length > 0) {
|
|
31302
31623
|
log2(
|
|
31303
|
-
`[Bridge service]
|
|
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,
|
|
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(
|
|
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
|
|
31340
|
-
const targetCwd =
|
|
31341
|
-
|
|
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 &&
|
|
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
|
-
`[
|
|
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 =
|
|
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(`[
|
|
31701
|
+
log2(`[Agent] ${state.lastAcpStartError}`);
|
|
31379
31702
|
}
|
|
31380
31703
|
} catch {
|
|
31381
31704
|
state.lastAcpStartError = `Agent cwd missing or inaccessible: ${targetCwd}`;
|
|
31382
|
-
log2(`[
|
|
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(`[
|
|
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
|
|
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
|
|
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(`[
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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 ?
|
|
31945
|
+
const cwdAbs = worktreePaths.length > 0 ? path10.resolve(worktreePaths[0]) : path10.resolve(effectiveCwd);
|
|
31620
31946
|
if (!primaryRepoRoots.length) {
|
|
31621
|
-
log2("[Bridge service]
|
|
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(
|
|
31969
|
+
async function readGitBranch(cwd) {
|
|
31748
31970
|
try {
|
|
31749
|
-
const { stdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd
|
|
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]
|
|
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]
|
|
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 =
|
|
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((
|
|
31847
|
-
log2(`[
|
|
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
|
-
`[
|
|
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
|
|
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(
|
|
31967
|
-
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]
|
|
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
|
|
32084
|
-
import
|
|
32299
|
+
import fs6 from "node:fs";
|
|
32300
|
+
import path13 from "node:path";
|
|
32085
32301
|
|
|
32086
32302
|
// src/files/ensure-under-cwd.ts
|
|
32087
|
-
import
|
|
32088
|
-
function ensureUnderCwd(relativePath,
|
|
32089
|
-
const normalized =
|
|
32090
|
-
const resolved =
|
|
32091
|
-
if (!resolved.startsWith(
|
|
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 || ".",
|
|
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 =
|
|
32320
|
+
const names = fs6.readdirSync(resolved, { withFileTypes: true });
|
|
32106
32321
|
const entries = names.filter((d) => !d.name.startsWith(".")).map((d) => {
|
|
32107
|
-
const entryPath =
|
|
32108
|
-
const fullPath =
|
|
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 =
|
|
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
|
|
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,
|
|
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 =
|
|
32358
|
+
real = fs7.realpathSync(resolved);
|
|
32145
32359
|
} catch {
|
|
32146
32360
|
real = resolved;
|
|
32147
32361
|
}
|
|
32148
|
-
const
|
|
32149
|
-
if (!
|
|
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 =
|
|
32155
|
-
const fd =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
32315
|
-
const raw =
|
|
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:
|
|
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
|
|
32325
|
-
import
|
|
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 =
|
|
32542
|
+
var INDEX_DIR = path14.join(os2.homedir(), ".buildautomaton");
|
|
32329
32543
|
var HASH_LEN = 16;
|
|
32330
32544
|
var INDEX_VERSION = 2;
|
|
32331
|
-
function getIndexPath(
|
|
32332
|
-
const hash = crypto2.createHash("sha256").update(
|
|
32333
|
-
return
|
|
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 =
|
|
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 =
|
|
32378
|
-
let
|
|
32591
|
+
const full = path14.join(dir, name);
|
|
32592
|
+
let stat;
|
|
32379
32593
|
try {
|
|
32380
|
-
|
|
32594
|
+
stat = fs8.statSync(full);
|
|
32381
32595
|
} catch {
|
|
32382
32596
|
continue;
|
|
32383
32597
|
}
|
|
32384
|
-
const
|
|
32385
|
-
if (
|
|
32598
|
+
const relative4 = path14.relative(baseDir, full).replace(/\\/g, "/");
|
|
32599
|
+
if (stat.isDirectory()) {
|
|
32386
32600
|
walkDir(full, baseDir, out);
|
|
32387
|
-
} else if (
|
|
32388
|
-
out.push(
|
|
32601
|
+
} else if (stat.isFile()) {
|
|
32602
|
+
out.push(relative4);
|
|
32389
32603
|
}
|
|
32390
32604
|
}
|
|
32391
32605
|
}
|
|
32392
|
-
function buildFileIndex(
|
|
32393
|
-
const resolved =
|
|
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 (!
|
|
32412
|
-
|
|
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(
|
|
32419
|
-
const resolved =
|
|
32632
|
+
function loadFileIndex(cwd) {
|
|
32633
|
+
const resolved = path14.resolve(cwd);
|
|
32420
32634
|
const indexPath = getIndexPath(resolved);
|
|
32421
32635
|
try {
|
|
32422
|
-
const raw =
|
|
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(
|
|
32440
|
-
const resolved =
|
|
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
|
|
32479
|
-
const index = loadFileIndex(
|
|
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(
|
|
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
|
|
32562
|
-
import
|
|
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(
|
|
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 =
|
|
32569
|
-
if (!
|
|
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 =
|
|
32786
|
+
entries = fs9.readdirSync(base);
|
|
32573
32787
|
} catch {
|
|
32574
32788
|
continue;
|
|
32575
32789
|
}
|
|
32576
32790
|
for (const name of entries) {
|
|
32577
|
-
const dir =
|
|
32791
|
+
const dir = path15.join(base, name);
|
|
32578
32792
|
try {
|
|
32579
|
-
if (!
|
|
32793
|
+
if (!fs9.statSync(dir).isDirectory()) continue;
|
|
32580
32794
|
} catch {
|
|
32581
32795
|
continue;
|
|
32582
32796
|
}
|
|
32583
|
-
const skillMd =
|
|
32584
|
-
if (!
|
|
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(
|
|
32807
|
+
function discoverSkillLayoutRoots(cwd) {
|
|
32594
32808
|
const roots = [];
|
|
32595
32809
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
32596
|
-
const base =
|
|
32597
|
-
if (!
|
|
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 =
|
|
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 =
|
|
32820
|
+
const dir = path15.join(base, name);
|
|
32607
32821
|
try {
|
|
32608
|
-
if (!
|
|
32822
|
+
if (!fs9.statSync(dir).isDirectory()) continue;
|
|
32609
32823
|
} catch {
|
|
32610
32824
|
continue;
|
|
32611
32825
|
}
|
|
32612
|
-
if (!
|
|
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(
|
|
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
|
|
32633
|
-
import
|
|
32634
|
-
function installRemoteSkills(
|
|
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 =
|
|
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 =
|
|
32648
|
-
|
|
32861
|
+
const dest = path16.join(skillDir, f.path);
|
|
32862
|
+
fs10.mkdirSync(path16.dirname(dest), { recursive: true });
|
|
32649
32863
|
if (f.text !== void 0) {
|
|
32650
|
-
|
|
32864
|
+
fs10.writeFileSync(dest, f.text, "utf8");
|
|
32651
32865
|
} else if (f.base64) {
|
|
32652
|
-
|
|
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
|
|
32674
|
-
const result = installRemoteSkills(
|
|
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]
|
|
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
|
|
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) ??
|
|
32970
|
+
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
|
|
32758
32971
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
32759
|
-
if (!
|
|
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
|
|
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
|
|
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 (!
|
|
32914
|
-
const raw = JSON.parse(
|
|
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
|
-
|
|
32924
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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]
|
|
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(
|
|
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
|
|
33217
|
+
import * as fs16 from "node:fs";
|
|
33003
33218
|
|
|
33004
33219
|
// src/git/worktree-remove.ts
|
|
33005
|
-
import * as
|
|
33220
|
+
import * as fs15 from "node:fs";
|
|
33006
33221
|
|
|
33007
33222
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
33008
|
-
import * as
|
|
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 (!
|
|
33013
|
-
const first2 =
|
|
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
|
-
|
|
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]
|
|
33253
|
+
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
33039
33254
|
try {
|
|
33040
|
-
|
|
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
|
|
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:
|
|
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 : [
|
|
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
|
|
34901
|
-
|
|
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 =
|
|
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
|
-
|
|
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((
|
|
34962
|
-
proc.once("exit", () =>
|
|
33505
|
+
const exited = new Promise((resolve15) => {
|
|
33506
|
+
proc.once("exit", () => resolve15());
|
|
34963
33507
|
});
|
|
34964
|
-
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"})
|
|
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((
|
|
33513
|
+
await Promise.race([exited, new Promise((resolve15) => setTimeout(resolve15, graceMs))]);
|
|
34970
33514
|
}
|
|
34971
33515
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
34972
|
-
log2(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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,
|
|
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
|
|
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,
|
|
33770
|
+
function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
35225
33771
|
try {
|
|
35226
33772
|
const opts = {
|
|
35227
33773
|
env,
|
|
35228
|
-
cwd
|
|
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
|
|
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,
|
|
35249
|
-
const tmpRoot =
|
|
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 =
|
|
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
|
|
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
|
|
33816
|
+
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
35271
33817
|
}
|
|
35272
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
35299
|
-
const tmpRoot =
|
|
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
|
-
|
|
33850
|
+
fs20.writeFileSync(innerPath, `#!/bin/sh
|
|
35305
33851
|
${command}
|
|
35306
33852
|
`);
|
|
35307
|
-
|
|
33853
|
+
fs20.writeFileSync(
|
|
35308
33854
|
runnerPath,
|
|
35309
33855
|
`#!/bin/sh
|
|
35310
|
-
cd ${shSingleQuote(
|
|
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,
|
|
35333
|
-
const tmpRoot =
|
|
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
|
-
|
|
33885
|
+
fs20.writeFileSync(
|
|
35340
33886
|
runnerPath,
|
|
35341
33887
|
`@ECHO OFF\r
|
|
35342
|
-
CD /D ${q(
|
|
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,
|
|
33914
|
+
function trySpawnInheritStdio(command, env, cwd, signal) {
|
|
35369
33915
|
const opts = {
|
|
35370
33916
|
env,
|
|
35371
|
-
cwd
|
|
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,
|
|
33933
|
+
function shellSpawn(command, env, cwd, options) {
|
|
35388
33934
|
const signal = options?.signal;
|
|
35389
|
-
const piped = trySpawnPipedViaSh(command, env,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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}
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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]
|
|
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]
|
|
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]
|
|
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
|
-
|
|
36000
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
36071
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
34749
|
+
const skills2 = discoverLocalSkills(getBridgeWorkspaceDirectory());
|
|
36167
34750
|
socket.send(JSON.stringify({ type: "local_skills", skills: skills2 }));
|
|
36168
34751
|
} catch (e) {
|
|
36169
|
-
logFn(
|
|
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(
|
|
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
|
-
|
|
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]
|
|
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(
|
|
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 =
|
|
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
|