@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/index.js
CHANGED
|
@@ -2235,13 +2235,13 @@ var require_extension = __commonJS({
|
|
|
2235
2235
|
var require_websocket = __commonJS({
|
|
2236
2236
|
"../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js"(exports, module) {
|
|
2237
2237
|
"use strict";
|
|
2238
|
-
var
|
|
2238
|
+
var EventEmitter2 = __require("events");
|
|
2239
2239
|
var https3 = __require("https");
|
|
2240
2240
|
var http = __require("http");
|
|
2241
2241
|
var net = __require("net");
|
|
2242
2242
|
var tls = __require("tls");
|
|
2243
2243
|
var { randomBytes, createHash: createHash2 } = __require("crypto");
|
|
2244
|
-
var { Duplex, Readable:
|
|
2244
|
+
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
2245
2245
|
var { URL: URL2 } = __require("url");
|
|
2246
2246
|
var PerMessageDeflate = require_permessage_deflate();
|
|
2247
2247
|
var Receiver2 = require_receiver();
|
|
@@ -2267,7 +2267,7 @@ var require_websocket = __commonJS({
|
|
|
2267
2267
|
var protocolVersions = [8, 13];
|
|
2268
2268
|
var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
|
|
2269
2269
|
var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
2270
|
-
var WebSocket2 = class _WebSocket extends
|
|
2270
|
+
var WebSocket2 = class _WebSocket extends EventEmitter2 {
|
|
2271
2271
|
/**
|
|
2272
2272
|
* Create a new `WebSocket`.
|
|
2273
2273
|
*
|
|
@@ -3179,7 +3179,7 @@ var require_stream = __commonJS({
|
|
|
3179
3179
|
};
|
|
3180
3180
|
duplex._final = function(callback) {
|
|
3181
3181
|
if (ws.readyState === ws.CONNECTING) {
|
|
3182
|
-
ws.once("open", function
|
|
3182
|
+
ws.once("open", function open() {
|
|
3183
3183
|
duplex._final(callback);
|
|
3184
3184
|
});
|
|
3185
3185
|
return;
|
|
@@ -3200,7 +3200,7 @@ var require_stream = __commonJS({
|
|
|
3200
3200
|
};
|
|
3201
3201
|
duplex._write = function(chunk, encoding, callback) {
|
|
3202
3202
|
if (ws.readyState === ws.CONNECTING) {
|
|
3203
|
-
ws.once("open", function
|
|
3203
|
+
ws.once("open", function open() {
|
|
3204
3204
|
duplex._write(chunk, encoding, callback);
|
|
3205
3205
|
});
|
|
3206
3206
|
return;
|
|
@@ -3264,7 +3264,7 @@ var require_subprotocol = __commonJS({
|
|
|
3264
3264
|
var require_websocket_server = __commonJS({
|
|
3265
3265
|
"../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
|
|
3266
3266
|
"use strict";
|
|
3267
|
-
var
|
|
3267
|
+
var EventEmitter2 = __require("events");
|
|
3268
3268
|
var http = __require("http");
|
|
3269
3269
|
var { Duplex } = __require("stream");
|
|
3270
3270
|
var { createHash: createHash2 } = __require("crypto");
|
|
@@ -3277,7 +3277,7 @@ var require_websocket_server = __commonJS({
|
|
|
3277
3277
|
var RUNNING = 0;
|
|
3278
3278
|
var CLOSING = 1;
|
|
3279
3279
|
var CLOSED = 2;
|
|
3280
|
-
var WebSocketServer2 = class extends
|
|
3280
|
+
var WebSocketServer2 = class extends EventEmitter2 {
|
|
3281
3281
|
/**
|
|
3282
3282
|
* Create a `WebSocketServer` instance.
|
|
3283
3283
|
*
|
|
@@ -20943,8 +20943,8 @@ var init_acp = __esm({
|
|
|
20943
20943
|
this.#requestHandler = requestHandler;
|
|
20944
20944
|
this.#notificationHandler = notificationHandler;
|
|
20945
20945
|
this.#stream = stream;
|
|
20946
|
-
this.#closedPromise = new Promise((
|
|
20947
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
20946
|
+
this.#closedPromise = new Promise((resolve14) => {
|
|
20947
|
+
this.#abortController.signal.addEventListener("abort", () => resolve14());
|
|
20948
20948
|
});
|
|
20949
20949
|
this.#receive();
|
|
20950
20950
|
}
|
|
@@ -21093,8 +21093,8 @@ var init_acp = __esm({
|
|
|
21093
21093
|
}
|
|
21094
21094
|
async sendRequest(method, params) {
|
|
21095
21095
|
const id = this.#nextRequestId++;
|
|
21096
|
-
const responsePromise = new Promise((
|
|
21097
|
-
this.#pendingResponses.set(id, { resolve:
|
|
21096
|
+
const responsePromise = new Promise((resolve14, reject) => {
|
|
21097
|
+
this.#pendingResponses.set(id, { resolve: resolve14, reject });
|
|
21098
21098
|
});
|
|
21099
21099
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
21100
21100
|
return responsePromise;
|
|
@@ -21966,12 +21966,12 @@ var require_src2 = __commonJS({
|
|
|
21966
21966
|
function check2(path24, isFile, isDirectory) {
|
|
21967
21967
|
log2(`checking %s`, path24);
|
|
21968
21968
|
try {
|
|
21969
|
-
const
|
|
21970
|
-
if (
|
|
21969
|
+
const stat = fs_1.statSync(path24);
|
|
21970
|
+
if (stat.isFile() && isFile) {
|
|
21971
21971
|
log2(`[OK] path represents a file`);
|
|
21972
21972
|
return true;
|
|
21973
21973
|
}
|
|
21974
|
-
if (
|
|
21974
|
+
if (stat.isDirectory() && isDirectory) {
|
|
21975
21975
|
log2(`[OK] path represents a directory`);
|
|
21976
21976
|
return true;
|
|
21977
21977
|
}
|
|
@@ -22065,12 +22065,19 @@ var wrapper_default = import_websocket.default;
|
|
|
22065
22065
|
var BRIDGE_AUTH_ERROR_HEADER = "x-bridge-auth-error";
|
|
22066
22066
|
var BRIDGE_AUTH_ERROR_TOKEN_INVALID = "token_invalid";
|
|
22067
22067
|
function createWsBridge(options) {
|
|
22068
|
-
const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid } = options;
|
|
22068
|
+
const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid, clientPingIntervalMs } = options;
|
|
22069
22069
|
const wsOptions = {};
|
|
22070
22070
|
if (url2.startsWith("wss://")) {
|
|
22071
22071
|
wsOptions.agent = new https.Agent({ rejectUnauthorized: false });
|
|
22072
22072
|
}
|
|
22073
22073
|
const ws = new wrapper_default(url2, wsOptions);
|
|
22074
|
+
let clientPingTimer = null;
|
|
22075
|
+
function clearClientPing() {
|
|
22076
|
+
if (clientPingTimer != null) {
|
|
22077
|
+
clearInterval(clientPingTimer);
|
|
22078
|
+
clientPingTimer = null;
|
|
22079
|
+
}
|
|
22080
|
+
}
|
|
22074
22081
|
ws.on("unexpected-response", (request, response) => {
|
|
22075
22082
|
const status = response?.statusCode ?? 0;
|
|
22076
22083
|
const headers = response?.headers ?? {};
|
|
@@ -22080,6 +22087,17 @@ function createWsBridge(options) {
|
|
|
22080
22087
|
}
|
|
22081
22088
|
});
|
|
22082
22089
|
ws.on("open", () => {
|
|
22090
|
+
clearClientPing();
|
|
22091
|
+
if (clientPingIntervalMs != null && clientPingIntervalMs > 0) {
|
|
22092
|
+
clientPingTimer = setInterval(() => {
|
|
22093
|
+
if (ws.readyState === wrapper_default.OPEN) {
|
|
22094
|
+
try {
|
|
22095
|
+
ws.ping();
|
|
22096
|
+
} catch {
|
|
22097
|
+
}
|
|
22098
|
+
}
|
|
22099
|
+
}, clientPingIntervalMs);
|
|
22100
|
+
}
|
|
22083
22101
|
onOpen?.();
|
|
22084
22102
|
});
|
|
22085
22103
|
ws.on("message", (raw) => {
|
|
@@ -22099,9 +22117,11 @@ function createWsBridge(options) {
|
|
|
22099
22117
|
}
|
|
22100
22118
|
});
|
|
22101
22119
|
ws.on("close", (code, reason) => {
|
|
22120
|
+
clearClientPing();
|
|
22102
22121
|
onClose?.(code, reason.toString());
|
|
22103
22122
|
});
|
|
22104
22123
|
ws.on("error", (err) => {
|
|
22124
|
+
clearClientPing();
|
|
22105
22125
|
onError2?.(err);
|
|
22106
22126
|
});
|
|
22107
22127
|
return ws;
|
|
@@ -22115,6 +22135,18 @@ function sendWsMessage(ws, payload) {
|
|
|
22115
22135
|
// src/acp/clients/acp-client.ts
|
|
22116
22136
|
import { spawn } from "node:child_process";
|
|
22117
22137
|
import { Readable, Writable } from "node:stream";
|
|
22138
|
+
|
|
22139
|
+
// src/files/cwd/bridge-workspace-directory.ts
|
|
22140
|
+
import * as path from "node:path";
|
|
22141
|
+
var bridgeWorkspaceDirectory = null;
|
|
22142
|
+
function getBridgeWorkspaceDirectory() {
|
|
22143
|
+
if (bridgeWorkspaceDirectory == null) {
|
|
22144
|
+
bridgeWorkspaceDirectory = path.resolve(process.cwd());
|
|
22145
|
+
}
|
|
22146
|
+
return bridgeWorkspaceDirectory;
|
|
22147
|
+
}
|
|
22148
|
+
|
|
22149
|
+
// src/acp/clients/acp-client.ts
|
|
22118
22150
|
function formatSpawnError(err, command) {
|
|
22119
22151
|
if (err.code === "ENOENT") {
|
|
22120
22152
|
return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
|
|
@@ -22131,15 +22163,15 @@ function toErrorMessage(err) {
|
|
|
22131
22163
|
}
|
|
22132
22164
|
async function createAcpClient(options) {
|
|
22133
22165
|
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
22134
|
-
const { command, cwd
|
|
22135
|
-
const
|
|
22166
|
+
const { command, cwd = getBridgeWorkspaceDirectory(), onSessionUpdate } = options;
|
|
22167
|
+
const isWindows = process.platform === "win32";
|
|
22136
22168
|
const child = spawn(command[0], command.slice(1), {
|
|
22137
|
-
cwd
|
|
22169
|
+
cwd,
|
|
22138
22170
|
stdio: ["pipe", "pipe", "inherit"],
|
|
22139
22171
|
env: process.env,
|
|
22140
|
-
shell:
|
|
22172
|
+
shell: isWindows
|
|
22141
22173
|
});
|
|
22142
|
-
return new Promise((
|
|
22174
|
+
return new Promise((resolve14, reject) => {
|
|
22143
22175
|
child.on("error", (err) => {
|
|
22144
22176
|
child.kill();
|
|
22145
22177
|
reject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -22166,9 +22198,9 @@ async function createAcpClient(options) {
|
|
|
22166
22198
|
capabilities: {},
|
|
22167
22199
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
22168
22200
|
});
|
|
22169
|
-
const newSessionRes = await connection.newSession({ workingDirectory:
|
|
22201
|
+
const newSessionRes = await connection.newSession({ workingDirectory: cwd });
|
|
22170
22202
|
const sessionId = newSessionRes.sessionId;
|
|
22171
|
-
|
|
22203
|
+
resolve14({
|
|
22172
22204
|
sessionId,
|
|
22173
22205
|
async sendPrompt(prompt, _options) {
|
|
22174
22206
|
try {
|
|
@@ -22244,7 +22276,7 @@ async function proxyToLocal(request) {
|
|
|
22244
22276
|
path: url2.pathname + url2.search,
|
|
22245
22277
|
headers: request.headers
|
|
22246
22278
|
};
|
|
22247
|
-
return new Promise((
|
|
22279
|
+
return new Promise((resolve14) => {
|
|
22248
22280
|
const req = mod.request(opts, (res) => {
|
|
22249
22281
|
const chunks = [];
|
|
22250
22282
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -22255,7 +22287,7 @@ async function proxyToLocal(request) {
|
|
|
22255
22287
|
if (typeof v === "string") headers[k] = v;
|
|
22256
22288
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
22257
22289
|
}
|
|
22258
|
-
|
|
22290
|
+
resolve14({
|
|
22259
22291
|
id: request.id,
|
|
22260
22292
|
statusCode: res.statusCode ?? 0,
|
|
22261
22293
|
headers,
|
|
@@ -22264,7 +22296,7 @@ async function proxyToLocal(request) {
|
|
|
22264
22296
|
});
|
|
22265
22297
|
});
|
|
22266
22298
|
req.on("error", (err) => {
|
|
22267
|
-
|
|
22299
|
+
resolve14({
|
|
22268
22300
|
id: request.id,
|
|
22269
22301
|
statusCode: 0,
|
|
22270
22302
|
headers: {},
|
|
@@ -22394,12 +22426,12 @@ var previewSkill = {
|
|
|
22394
22426
|
const port = params.port ?? (Number(process.env[PREVIEW_PORT_ENV]) || DEFAULT_PORT);
|
|
22395
22427
|
previewPort = port;
|
|
22396
22428
|
previewSecret = randomSecret();
|
|
22397
|
-
const
|
|
22429
|
+
const isWindows = process.platform === "win32";
|
|
22398
22430
|
const parts = command.split(/\s+/);
|
|
22399
22431
|
const exe = parts[0];
|
|
22400
22432
|
const args = parts.slice(1);
|
|
22401
|
-
previewProcess = spawn2(
|
|
22402
|
-
cwd:
|
|
22433
|
+
previewProcess = spawn2(isWindows && exe === "npm" ? "npm.cmd" : exe, args, {
|
|
22434
|
+
cwd: getBridgeWorkspaceDirectory(),
|
|
22403
22435
|
stdio: ["ignore", "pipe", "pipe"],
|
|
22404
22436
|
env: {
|
|
22405
22437
|
...process.env,
|
|
@@ -22508,11 +22540,11 @@ function logImmediate(line) {
|
|
|
22508
22540
|
|
|
22509
22541
|
// src/config.ts
|
|
22510
22542
|
import fs from "node:fs";
|
|
22511
|
-
import
|
|
22543
|
+
import path2 from "node:path";
|
|
22512
22544
|
import os from "node:os";
|
|
22513
22545
|
function getConfigPath() {
|
|
22514
|
-
const dir =
|
|
22515
|
-
return
|
|
22546
|
+
const dir = path2.join(os.homedir(), ".buildautomaton");
|
|
22547
|
+
return path2.join(dir, "config.json");
|
|
22516
22548
|
}
|
|
22517
22549
|
function normalizeApiUrl(url2) {
|
|
22518
22550
|
return url2.replace(/\/$/, "");
|
|
@@ -22528,7 +22560,7 @@ function readRawConfig() {
|
|
|
22528
22560
|
}
|
|
22529
22561
|
function writeConfigForApi(apiUrl, auth) {
|
|
22530
22562
|
const p = getConfigPath();
|
|
22531
|
-
const dir =
|
|
22563
|
+
const dir = path2.dirname(p);
|
|
22532
22564
|
const key = normalizeApiUrl(apiUrl);
|
|
22533
22565
|
const prev = readRawConfig() ?? {};
|
|
22534
22566
|
const servers = { ...prev.servers ?? {}, [key]: { ...auth } };
|
|
@@ -22537,7 +22569,7 @@ function writeConfigForApi(apiUrl, auth) {
|
|
|
22537
22569
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
22538
22570
|
fs.writeFileSync(p, JSON.stringify(next, null, 2), "utf8");
|
|
22539
22571
|
} catch (e) {
|
|
22540
|
-
console.error("Could not save
|
|
22572
|
+
console.error("Could not save authentication config:", e);
|
|
22541
22573
|
}
|
|
22542
22574
|
}
|
|
22543
22575
|
function clearConfigForApi(apiUrl) {
|
|
@@ -22599,6 +22631,28 @@ function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiU
|
|
|
22599
22631
|
}
|
|
22600
22632
|
}
|
|
22601
22633
|
|
|
22634
|
+
// src/bridge/connection/reconnect/constants.ts
|
|
22635
|
+
var RECONNECT_FIRST_MS = 100;
|
|
22636
|
+
var RECONNECT_MAX_MS = 3e4;
|
|
22637
|
+
var RECONNECT_QUIET_MS = 2e3;
|
|
22638
|
+
function reconnectDelayMs(attemptBeforeIncrement) {
|
|
22639
|
+
return Math.min(RECONNECT_FIRST_MS * 2 ** attemptBeforeIncrement, RECONNECT_MAX_MS);
|
|
22640
|
+
}
|
|
22641
|
+
|
|
22642
|
+
// src/bridge/connection/reconnect/format-reconnect-delay-for-log.ts
|
|
22643
|
+
function formatReconnectDelayForLog(delayMs) {
|
|
22644
|
+
if (delayMs < 1e3) return `${delayMs}ms`;
|
|
22645
|
+
const s = delayMs / 1e3;
|
|
22646
|
+
return Number.isInteger(s) ? `${s}s` : `${s.toFixed(1)}s`;
|
|
22647
|
+
}
|
|
22648
|
+
|
|
22649
|
+
// src/bridge/connection/reconnect/log-next-reconnect-attempt.ts
|
|
22650
|
+
function logNextReconnectAttempt(log2, serviceLabel, quiet, delayMs, attempt) {
|
|
22651
|
+
if (!quiet.verboseLogs) return;
|
|
22652
|
+
const delayLabel = formatReconnectDelayForLog(delayMs);
|
|
22653
|
+
log2(`${serviceLabel} Next connection attempt in ${delayLabel} (attempt ${attempt}).`);
|
|
22654
|
+
}
|
|
22655
|
+
|
|
22602
22656
|
// src/bridge/connection/ws-close-diagnostics.ts
|
|
22603
22657
|
function describeWebSocketCloseCode(code) {
|
|
22604
22658
|
const known = {
|
|
@@ -22627,11 +22681,122 @@ function formatWebSocketClose(label, code, reason, extra) {
|
|
|
22627
22681
|
const r = reason.trim();
|
|
22628
22682
|
const reasonPart = r ? ` reason="${r}"` : "";
|
|
22629
22683
|
const extraPart = extra ? ` ${extra}` : "";
|
|
22630
|
-
return `${label}
|
|
22684
|
+
return `${label} Disconnected: code=${code} (${describeWebSocketCloseCode(code)})${reasonPart}${extraPart}`;
|
|
22685
|
+
}
|
|
22686
|
+
|
|
22687
|
+
// src/bridge/connection/reconnect/reconnect-quiet-slot.ts
|
|
22688
|
+
function createEmptyReconnectQuietSlot() {
|
|
22689
|
+
return { timer: null, verboseLogs: false, pendingCloseLog: null };
|
|
22690
|
+
}
|
|
22691
|
+
function clearReconnectQuietTimer(quiet) {
|
|
22692
|
+
if (quiet.timer != null) {
|
|
22693
|
+
clearTimeout(quiet.timer);
|
|
22694
|
+
quiet.timer = null;
|
|
22695
|
+
}
|
|
22696
|
+
}
|
|
22697
|
+
function clearReconnectQuietOnSuccessfulConnection(quiet, log2, reconnectedMessage) {
|
|
22698
|
+
clearReconnectQuietTimer(quiet);
|
|
22699
|
+
quiet.pendingCloseLog = null;
|
|
22700
|
+
if (quiet.verboseLogs) {
|
|
22701
|
+
log2(reconnectedMessage);
|
|
22702
|
+
quiet.verboseLogs = false;
|
|
22703
|
+
}
|
|
22704
|
+
}
|
|
22705
|
+
function beginDeferredDisconnectForReconnect(options) {
|
|
22706
|
+
const {
|
|
22707
|
+
isClosedByUser,
|
|
22708
|
+
quiet,
|
|
22709
|
+
code,
|
|
22710
|
+
reason,
|
|
22711
|
+
willReconnect,
|
|
22712
|
+
log: log2,
|
|
22713
|
+
serviceLabel,
|
|
22714
|
+
shutdownDetail,
|
|
22715
|
+
reconnectingDetail,
|
|
22716
|
+
quietMs = RECONNECT_QUIET_MS,
|
|
22717
|
+
shouldAbortQuietWindow
|
|
22718
|
+
} = options;
|
|
22719
|
+
if (!willReconnect) {
|
|
22720
|
+
log2(formatWebSocketClose(serviceLabel, code, reason, shutdownDetail));
|
|
22721
|
+
return;
|
|
22722
|
+
}
|
|
22723
|
+
quiet.pendingCloseLog = { code, reason };
|
|
22724
|
+
if (quiet.timer == null) {
|
|
22725
|
+
quiet.timer = setTimeout(() => {
|
|
22726
|
+
quiet.timer = null;
|
|
22727
|
+
if (isClosedByUser()) return;
|
|
22728
|
+
if (shouldAbortQuietWindow()) return;
|
|
22729
|
+
if (quiet.pendingCloseLog) {
|
|
22730
|
+
const { code: c, reason: r } = quiet.pendingCloseLog;
|
|
22731
|
+
quiet.pendingCloseLog = null;
|
|
22732
|
+
log2(formatWebSocketClose(serviceLabel, c, r, reconnectingDetail));
|
|
22733
|
+
}
|
|
22734
|
+
quiet.verboseLogs = true;
|
|
22735
|
+
}, quietMs);
|
|
22736
|
+
}
|
|
22737
|
+
}
|
|
22738
|
+
|
|
22739
|
+
// src/bridge/connection/reconnect/bridge-main-reconnect.ts
|
|
22740
|
+
function beginMainBridgeDeferredDisconnect(state, code, reason, log2, willReconnect) {
|
|
22741
|
+
beginDeferredDisconnectForReconnect({
|
|
22742
|
+
isClosedByUser: () => state.closedByUser,
|
|
22743
|
+
quiet: state.mainQuiet,
|
|
22744
|
+
code,
|
|
22745
|
+
reason,
|
|
22746
|
+
willReconnect,
|
|
22747
|
+
log: log2,
|
|
22748
|
+
serviceLabel: "[Bridge service]",
|
|
22749
|
+
shutdownDetail: "Not reconnecting (shutting down).",
|
|
22750
|
+
reconnectingDetail: "Reconnecting\u2026",
|
|
22751
|
+
shouldAbortQuietWindow: () => {
|
|
22752
|
+
const w = state.currentWs;
|
|
22753
|
+
return w != null && w.readyState === wrapper_default.OPEN;
|
|
22754
|
+
}
|
|
22755
|
+
});
|
|
22756
|
+
}
|
|
22757
|
+
function clearMainBridgeReconnectQuietOnOpen(state, log2) {
|
|
22758
|
+
clearReconnectQuietOnSuccessfulConnection(state.mainQuiet, log2, "[Bridge service] Reconnected.");
|
|
22759
|
+
}
|
|
22760
|
+
function scheduleMainBridgeReconnect(state, connect, log2) {
|
|
22761
|
+
if (state.closedByUser || state.currentWs != null) return;
|
|
22762
|
+
const delay2 = reconnectDelayMs(state.reconnectAttempt);
|
|
22763
|
+
state.reconnectAttempt += 1;
|
|
22764
|
+
logNextReconnectAttempt(log2, "[Bridge service]", state.mainQuiet, delay2, state.reconnectAttempt);
|
|
22765
|
+
state.reconnectTimeout = setTimeout(() => {
|
|
22766
|
+
state.reconnectTimeout = null;
|
|
22767
|
+
connect();
|
|
22768
|
+
}, delay2);
|
|
22769
|
+
}
|
|
22770
|
+
|
|
22771
|
+
// src/bridge/connection/reconnect/firehose-reconnect.ts
|
|
22772
|
+
var PROXY_AND_LOG_SERVICE_LABEL = "[Proxy and log service]";
|
|
22773
|
+
function beginFirehoseDeferredDisconnect(ctx, code, reason, log2) {
|
|
22774
|
+
beginDeferredDisconnectForReconnect({
|
|
22775
|
+
isClosedByUser: () => ctx.closedByUser,
|
|
22776
|
+
quiet: ctx.firehoseQuiet,
|
|
22777
|
+
code,
|
|
22778
|
+
reason,
|
|
22779
|
+
willReconnect: true,
|
|
22780
|
+
log: log2,
|
|
22781
|
+
serviceLabel: PROXY_AND_LOG_SERVICE_LABEL,
|
|
22782
|
+
shutdownDetail: "Not reconnecting (shutting down).",
|
|
22783
|
+
reconnectingDetail: "Reconnecting\u2026",
|
|
22784
|
+
shouldAbortQuietWindow: () => {
|
|
22785
|
+
const w = ctx.currentWs;
|
|
22786
|
+
if (!w || w.readyState !== wrapper_default.OPEN) return true;
|
|
22787
|
+
return ctx.firehoseHandle?.isConnected() ?? false;
|
|
22788
|
+
}
|
|
22789
|
+
});
|
|
22790
|
+
}
|
|
22791
|
+
function clearFirehoseReconnectQuietOnOpen(ctx, log2) {
|
|
22792
|
+
clearReconnectQuietOnSuccessfulConnection(
|
|
22793
|
+
ctx.firehoseQuiet,
|
|
22794
|
+
log2,
|
|
22795
|
+
`${PROXY_AND_LOG_SERVICE_LABEL} Reconnected.`
|
|
22796
|
+
);
|
|
22631
22797
|
}
|
|
22632
22798
|
|
|
22633
22799
|
// src/auth/run-pending-auth.ts
|
|
22634
|
-
var PENDING_RECONNECT_MS = 2e3;
|
|
22635
22800
|
var PENDING_KEEPALIVE_MS = 25e3;
|
|
22636
22801
|
var BROWSER_OPEN_FALLBACK_MS = 4e3;
|
|
22637
22802
|
function buildPendingBridgeUrl(apiUrl, connectionId) {
|
|
@@ -22650,10 +22815,35 @@ function runPendingAuth(options) {
|
|
|
22650
22815
|
let hasOpenedBrowser = false;
|
|
22651
22816
|
let resolved = false;
|
|
22652
22817
|
let resolveAuth;
|
|
22653
|
-
const authPromise = new Promise((
|
|
22654
|
-
resolveAuth =
|
|
22818
|
+
const authPromise = new Promise((resolve14) => {
|
|
22819
|
+
resolveAuth = resolve14;
|
|
22655
22820
|
});
|
|
22821
|
+
let reconnectAttempt = 0;
|
|
22822
|
+
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
22823
|
+
function clearQuietOnOpen() {
|
|
22824
|
+
clearReconnectQuietOnSuccessfulConnection(
|
|
22825
|
+
signInQuiet,
|
|
22826
|
+
logFn,
|
|
22827
|
+
"[Bridge service] Sign-in connection restored."
|
|
22828
|
+
);
|
|
22829
|
+
reconnectAttempt = 0;
|
|
22830
|
+
}
|
|
22831
|
+
function beginDeferredPendingCloseLog(code, reason) {
|
|
22832
|
+
beginDeferredDisconnectForReconnect({
|
|
22833
|
+
isClosedByUser: () => resolved,
|
|
22834
|
+
quiet: signInQuiet,
|
|
22835
|
+
code,
|
|
22836
|
+
reason,
|
|
22837
|
+
willReconnect: true,
|
|
22838
|
+
log: logFn,
|
|
22839
|
+
serviceLabel: "[Bridge service]",
|
|
22840
|
+
shutdownDetail: "Not reconnecting (shutting down).",
|
|
22841
|
+
reconnectingDetail: "Waiting for browser sign-in; reconnecting\u2026",
|
|
22842
|
+
shouldAbortQuietWindow: () => ws != null && ws.readyState === wrapper_default.OPEN
|
|
22843
|
+
});
|
|
22844
|
+
}
|
|
22656
22845
|
function cleanup() {
|
|
22846
|
+
clearReconnectQuietTimer(signInQuiet);
|
|
22657
22847
|
if (reconnectTimeout) {
|
|
22658
22848
|
clearTimeout(reconnectTimeout);
|
|
22659
22849
|
reconnectTimeout = null;
|
|
@@ -22677,6 +22867,7 @@ function runPendingAuth(options) {
|
|
|
22677
22867
|
ws = createWsBridge({
|
|
22678
22868
|
url: url2,
|
|
22679
22869
|
onOpen: () => {
|
|
22870
|
+
clearQuietOnOpen();
|
|
22680
22871
|
sendWsMessage(ws, { type: "identify", role: "cli" });
|
|
22681
22872
|
keepaliveInterval = setInterval(() => {
|
|
22682
22873
|
if (resolved || !ws || ws.readyState !== 1) return;
|
|
@@ -22697,15 +22888,21 @@ function runPendingAuth(options) {
|
|
|
22697
22888
|
keepaliveInterval = null;
|
|
22698
22889
|
}
|
|
22699
22890
|
if (resolved) return;
|
|
22700
|
-
|
|
22701
|
-
|
|
22702
|
-
|
|
22891
|
+
beginDeferredPendingCloseLog(code, reason);
|
|
22892
|
+
const delay2 = reconnectDelayMs(reconnectAttempt);
|
|
22893
|
+
reconnectAttempt += 1;
|
|
22894
|
+
if (signInQuiet.verboseLogs) {
|
|
22895
|
+
const delayLabel = formatReconnectDelayForLog(delay2);
|
|
22896
|
+
logFn(
|
|
22897
|
+
`[Bridge service] Next sign-in connection attempt in ${delayLabel} (attempt ${reconnectAttempt}).`
|
|
22898
|
+
);
|
|
22899
|
+
}
|
|
22703
22900
|
reconnectTimeout = setTimeout(() => {
|
|
22704
22901
|
reconnectTimeout = null;
|
|
22705
22902
|
connect();
|
|
22706
|
-
},
|
|
22903
|
+
}, delay2);
|
|
22707
22904
|
},
|
|
22708
|
-
onError: (err) => logFn(`[Bridge service] WebSocket error
|
|
22905
|
+
onError: (err) => logFn(`[Bridge service] WebSocket error while waiting for sign-in: ${err.message}`),
|
|
22709
22906
|
onMessage: (data) => {
|
|
22710
22907
|
const msg = data;
|
|
22711
22908
|
if (msg.type === "auth_token" && typeof msg.token === "string") {
|
|
@@ -22746,7 +22943,7 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
|
|
|
22746
22943
|
|
|
22747
22944
|
// src/git/discover-repos.ts
|
|
22748
22945
|
import * as fs2 from "node:fs";
|
|
22749
|
-
import * as
|
|
22946
|
+
import * as path3 from "node:path";
|
|
22750
22947
|
|
|
22751
22948
|
// ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
|
|
22752
22949
|
var import_file_exists = __toESM(require_dist(), 1);
|
|
@@ -24008,8 +24205,8 @@ var init_git_executor_chain = __esm2({
|
|
|
24008
24205
|
get cwd() {
|
|
24009
24206
|
return this._cwd || this._executor.cwd;
|
|
24010
24207
|
}
|
|
24011
|
-
set cwd(
|
|
24012
|
-
this._cwd =
|
|
24208
|
+
set cwd(cwd) {
|
|
24209
|
+
this._cwd = cwd;
|
|
24013
24210
|
}
|
|
24014
24211
|
get env() {
|
|
24015
24212
|
return this._executor.env;
|
|
@@ -24200,8 +24397,8 @@ var init_git_executor = __esm2({
|
|
|
24200
24397
|
"use strict";
|
|
24201
24398
|
init_git_executor_chain();
|
|
24202
24399
|
GitExecutor = class {
|
|
24203
|
-
constructor(
|
|
24204
|
-
this.cwd =
|
|
24400
|
+
constructor(cwd, _scheduler, _plugins) {
|
|
24401
|
+
this.cwd = cwd;
|
|
24205
24402
|
this._scheduler = _scheduler;
|
|
24206
24403
|
this._plugins = _plugins;
|
|
24207
24404
|
this._chain = new GitExecutorChain(this, this._scheduler, this._plugins);
|
|
@@ -27331,9 +27528,9 @@ async function isGitRepoDirectory(dirPath) {
|
|
|
27331
27528
|
}
|
|
27332
27529
|
|
|
27333
27530
|
// src/git/discover-repos.ts
|
|
27334
|
-
async function discoverGitRepos(
|
|
27531
|
+
async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
27335
27532
|
const result = [];
|
|
27336
|
-
const cwdResolved =
|
|
27533
|
+
const cwdResolved = path3.resolve(cwd);
|
|
27337
27534
|
if (await isGitRepoDirectory(cwdResolved)) {
|
|
27338
27535
|
const remoteUrl = await getRemoteOriginUrl(cwdResolved);
|
|
27339
27536
|
result.push({ absolutePath: cwdResolved, remoteUrl });
|
|
@@ -27346,7 +27543,7 @@ async function discoverGitRepos(cwd3 = process.cwd()) {
|
|
|
27346
27543
|
}
|
|
27347
27544
|
for (const ent of entries) {
|
|
27348
27545
|
if (!ent.isDirectory()) continue;
|
|
27349
|
-
const childPath =
|
|
27546
|
+
const childPath = path3.join(cwdResolved, ent.name);
|
|
27350
27547
|
if (await isGitRepoDirectory(childPath)) {
|
|
27351
27548
|
const remoteUrl = await getRemoteOriginUrl(childPath);
|
|
27352
27549
|
result.push({ absolutePath: childPath, remoteUrl });
|
|
@@ -27355,11 +27552,11 @@ async function discoverGitRepos(cwd3 = process.cwd()) {
|
|
|
27355
27552
|
return result;
|
|
27356
27553
|
}
|
|
27357
27554
|
async function discoverGitReposUnderRoot(rootAbs) {
|
|
27358
|
-
const root =
|
|
27555
|
+
const root = path3.resolve(rootAbs);
|
|
27359
27556
|
const roots = [];
|
|
27360
27557
|
async function walk(dir) {
|
|
27361
27558
|
if (await isGitRepoDirectory(dir)) {
|
|
27362
|
-
roots.push(
|
|
27559
|
+
roots.push(path3.resolve(dir));
|
|
27363
27560
|
return;
|
|
27364
27561
|
}
|
|
27365
27562
|
let entries;
|
|
@@ -27370,7 +27567,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
|
|
|
27370
27567
|
}
|
|
27371
27568
|
for (const ent of entries) {
|
|
27372
27569
|
if (!ent.isDirectory() || ent.name === ".git") continue;
|
|
27373
|
-
await walk(
|
|
27570
|
+
await walk(path3.join(dir, ent.name));
|
|
27374
27571
|
}
|
|
27375
27572
|
}
|
|
27376
27573
|
await walk(root);
|
|
@@ -27397,56 +27594,43 @@ function reportGitRepos(getWs, log2) {
|
|
|
27397
27594
|
}
|
|
27398
27595
|
}
|
|
27399
27596
|
}).catch((err) => {
|
|
27400
|
-
log2(
|
|
27597
|
+
log2(
|
|
27598
|
+
`[Bridge service] Git repository discovery failed: ${err instanceof Error ? err.message : String(err)}`
|
|
27599
|
+
);
|
|
27401
27600
|
});
|
|
27402
27601
|
});
|
|
27403
27602
|
}
|
|
27404
27603
|
|
|
27405
|
-
// src/bridge/connection/schedule-reconnect.ts
|
|
27406
|
-
var RECONNECT_BASE_MS = 1e3;
|
|
27407
|
-
var RECONNECT_MAX_MS = 3e4;
|
|
27408
|
-
function scheduleReconnect(state, connect, log2) {
|
|
27409
|
-
if (state.closedByUser || state.currentWs != null) return;
|
|
27410
|
-
const delay2 = Math.min(
|
|
27411
|
-
RECONNECT_BASE_MS * 2 ** state.reconnectAttempt,
|
|
27412
|
-
RECONNECT_MAX_MS
|
|
27413
|
-
);
|
|
27414
|
-
state.reconnectAttempt += 1;
|
|
27415
|
-
log2(`[Bridge service] reconnect attempt ${state.reconnectAttempt} in ${delay2 / 1e3}s\u2026`);
|
|
27416
|
-
state.reconnectTimeout = setTimeout(() => {
|
|
27417
|
-
state.reconnectTimeout = null;
|
|
27418
|
-
connect();
|
|
27419
|
-
}, delay2);
|
|
27420
|
-
}
|
|
27421
|
-
|
|
27422
27604
|
// src/bridge/connection/close-bridge-connection.ts
|
|
27423
27605
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
27424
27606
|
log2?.("Shutting down\u2026");
|
|
27425
|
-
await new Promise((
|
|
27607
|
+
await new Promise((resolve14) => setImmediate(resolve14));
|
|
27426
27608
|
if (devServerManager) {
|
|
27427
27609
|
log2?.("Requesting dev server processes to stop\u2026");
|
|
27428
27610
|
await devServerManager.shutdownAllGraceful();
|
|
27429
27611
|
}
|
|
27430
27612
|
state.closedByUser = true;
|
|
27613
|
+
clearReconnectQuietTimer(state.mainQuiet);
|
|
27614
|
+
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
27431
27615
|
if (state.reconnectTimeout != null) {
|
|
27432
27616
|
log2?.("Cancelling reconnect timer\u2026");
|
|
27433
27617
|
clearTimeout(state.reconnectTimeout);
|
|
27434
27618
|
state.reconnectTimeout = null;
|
|
27435
27619
|
}
|
|
27436
27620
|
if (state.firehoseReconnectTimeout != null) {
|
|
27437
|
-
log2?.("[Proxy and log service]
|
|
27621
|
+
log2?.("[Proxy and log service] Cancelling reconnect timer\u2026");
|
|
27438
27622
|
clearTimeout(state.firehoseReconnectTimeout);
|
|
27439
27623
|
state.firehoseReconnectTimeout = null;
|
|
27440
27624
|
}
|
|
27441
27625
|
if (state.firehoseHandle) {
|
|
27442
|
-
log2?.("[Proxy and log service]
|
|
27626
|
+
log2?.("[Proxy and log service] Closing connection (CLI shutdown)\u2026");
|
|
27443
27627
|
state.firehoseHandle.close();
|
|
27444
27628
|
state.firehoseHandle = null;
|
|
27445
27629
|
}
|
|
27446
27630
|
log2?.("Disconnecting local agents (ACP)\u2026");
|
|
27447
27631
|
acpManager.disconnect();
|
|
27448
27632
|
if (state.currentWs) {
|
|
27449
|
-
log2?.("[Bridge service]
|
|
27633
|
+
log2?.("[Bridge service] Closing connection (CLI shutdown)\u2026");
|
|
27450
27634
|
state.currentWs.removeAllListeners();
|
|
27451
27635
|
const wsState = state.currentWs.readyState;
|
|
27452
27636
|
if (wsState === 1 || wsState === 2) {
|
|
@@ -27462,11 +27646,20 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
|
|
|
27462
27646
|
}
|
|
27463
27647
|
|
|
27464
27648
|
// src/git/session-git-queue.ts
|
|
27649
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
27650
|
+
import { promisify as promisify2 } from "node:util";
|
|
27651
|
+
import * as fs4 from "node:fs";
|
|
27652
|
+
import * as path5 from "node:path";
|
|
27653
|
+
|
|
27654
|
+
// src/git/pre-turn-snapshot.ts
|
|
27655
|
+
import * as fs3 from "node:fs";
|
|
27656
|
+
import * as path4 from "node:path";
|
|
27465
27657
|
import { execFile } from "node:child_process";
|
|
27466
27658
|
import { promisify } from "node:util";
|
|
27467
|
-
import * as path3 from "node:path";
|
|
27468
27659
|
var execFileAsync = promisify(execFile);
|
|
27469
|
-
|
|
27660
|
+
function snapshotsDirForCwd(agentCwd) {
|
|
27661
|
+
return path4.join(agentCwd, ".buildautomaton", "snapshots");
|
|
27662
|
+
}
|
|
27470
27663
|
async function gitStashCreate(repoRoot, log2) {
|
|
27471
27664
|
try {
|
|
27472
27665
|
const { stdout } = await execFileAsync("git", ["stash", "create"], {
|
|
@@ -27475,51 +27668,149 @@ async function gitStashCreate(repoRoot, log2) {
|
|
|
27475
27668
|
});
|
|
27476
27669
|
return stdout.trim();
|
|
27477
27670
|
} catch (e) {
|
|
27478
|
-
log2(
|
|
27671
|
+
log2(
|
|
27672
|
+
`[snapshot] Git stash create failed in ${repoRoot}: ${e instanceof Error ? e.message : String(e)}`
|
|
27673
|
+
);
|
|
27479
27674
|
return "";
|
|
27480
27675
|
}
|
|
27481
27676
|
}
|
|
27482
|
-
async function
|
|
27483
|
-
|
|
27484
|
-
|
|
27677
|
+
async function gitRun(repoRoot, args, log2, label) {
|
|
27678
|
+
try {
|
|
27679
|
+
await execFileAsync("git", args, { cwd: repoRoot, maxBuffer: 10 * 1024 * 1024 });
|
|
27680
|
+
return { ok: true };
|
|
27681
|
+
} catch (e) {
|
|
27682
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
27683
|
+
log2(`[snapshot] Git ${label} failed in ${repoRoot}: ${msg}`);
|
|
27684
|
+
return { ok: false, error: msg };
|
|
27685
|
+
}
|
|
27686
|
+
}
|
|
27687
|
+
async function resolveSnapshotRepoRoots(options) {
|
|
27688
|
+
const { worktreePaths, fallbackCwd, log: log2 } = options;
|
|
27689
|
+
if (worktreePaths?.length) {
|
|
27690
|
+
const uniq = [...new Set(worktreePaths.map((p) => path4.resolve(p)))];
|
|
27691
|
+
return uniq;
|
|
27692
|
+
}
|
|
27693
|
+
try {
|
|
27694
|
+
const repos = await discoverGitReposUnderRoot(fallbackCwd);
|
|
27695
|
+
return repos.map((r) => r.absolutePath);
|
|
27696
|
+
} catch (e) {
|
|
27697
|
+
log2(`[snapshot] Discover repositories failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
27698
|
+
return [];
|
|
27699
|
+
}
|
|
27700
|
+
}
|
|
27701
|
+
async function capturePreTurnSnapshot(options) {
|
|
27702
|
+
const { runId, repoRoots, agentCwd, log: log2 } = options;
|
|
27703
|
+
if (!runId || !repoRoots.length) {
|
|
27704
|
+
return { ok: false, error: "No git repos to snapshot" };
|
|
27705
|
+
}
|
|
27485
27706
|
const repos = [];
|
|
27486
27707
|
for (const root of repoRoots) {
|
|
27487
27708
|
const stashSha = await gitStashCreate(root, log2);
|
|
27488
27709
|
repos.push({ path: root, stashSha });
|
|
27489
27710
|
}
|
|
27490
|
-
|
|
27491
|
-
|
|
27711
|
+
const dir = snapshotsDirForCwd(agentCwd);
|
|
27712
|
+
try {
|
|
27713
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
27714
|
+
} catch (e) {
|
|
27715
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
27716
|
+
}
|
|
27717
|
+
const payload = {
|
|
27718
|
+
runId,
|
|
27719
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27720
|
+
repos
|
|
27721
|
+
};
|
|
27722
|
+
const filePath = path4.join(dir, `${runId}.json`);
|
|
27723
|
+
try {
|
|
27724
|
+
fs3.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
27725
|
+
} catch (e) {
|
|
27726
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
27727
|
+
}
|
|
27728
|
+
const repoList = repos.map((r) => r.path).join(", ");
|
|
27729
|
+
log2(
|
|
27730
|
+
`[snapshot] Saved pre-turn snapshot ${runId.slice(0, 8)}\u2026 (${repos.length} repo(s)): ${repoList}`
|
|
27731
|
+
);
|
|
27732
|
+
return { ok: true, filePath, repos };
|
|
27733
|
+
}
|
|
27734
|
+
async function applyPreTurnSnapshot(filePath, log2) {
|
|
27735
|
+
let data;
|
|
27736
|
+
try {
|
|
27737
|
+
const raw = fs3.readFileSync(filePath, "utf8");
|
|
27738
|
+
data = JSON.parse(raw);
|
|
27739
|
+
} catch (e) {
|
|
27740
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
27741
|
+
}
|
|
27742
|
+
if (!Array.isArray(data.repos)) {
|
|
27743
|
+
return { ok: false, error: "Invalid snapshot file" };
|
|
27744
|
+
}
|
|
27745
|
+
for (const r of data.repos) {
|
|
27746
|
+
if (!r.path) continue;
|
|
27747
|
+
const reset = await gitRun(r.path, ["reset", "--hard", "HEAD"], log2, "reset --hard");
|
|
27748
|
+
if (!reset.ok) return reset;
|
|
27749
|
+
const clean = await gitRun(r.path, ["clean", "-fd"], log2, "clean -fd");
|
|
27750
|
+
if (!clean.ok) return clean;
|
|
27751
|
+
if (r.stashSha) {
|
|
27752
|
+
const ap = await gitRun(r.path, ["stash", "apply", r.stashSha], log2, "stash apply");
|
|
27753
|
+
if (!ap.ok) return ap;
|
|
27754
|
+
}
|
|
27755
|
+
}
|
|
27756
|
+
log2(`[snapshot] Restored pre-turn state for ${data.runId.slice(0, 8)}\u2026`);
|
|
27757
|
+
return { ok: true };
|
|
27758
|
+
}
|
|
27759
|
+
function snapshotFilePath(agentCwd, runId) {
|
|
27760
|
+
return path4.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
|
|
27761
|
+
}
|
|
27762
|
+
|
|
27763
|
+
// src/git/session-git-queue.ts
|
|
27764
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
27765
|
+
var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
|
|
27766
|
+
function readWorkspaceFileAsUtf8(absPath) {
|
|
27767
|
+
try {
|
|
27768
|
+
const st = fs4.statSync(absPath);
|
|
27769
|
+
if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
|
|
27770
|
+
return fs4.readFileSync(absPath, "utf8");
|
|
27771
|
+
} catch {
|
|
27772
|
+
return void 0;
|
|
27773
|
+
}
|
|
27492
27774
|
}
|
|
27493
|
-
async function
|
|
27494
|
-
const { sessionId, runId, sendSessionUpdate, log: log2 } = options;
|
|
27495
|
-
const
|
|
27496
|
-
|
|
27497
|
-
|
|
27775
|
+
async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
27776
|
+
const { sessionId, runId, agentCwd, sendSessionUpdate, log: log2 } = options;
|
|
27777
|
+
const filePath = snapshotFilePath(agentCwd, runId);
|
|
27778
|
+
let data;
|
|
27779
|
+
try {
|
|
27780
|
+
const raw = fs4.readFileSync(filePath, "utf8");
|
|
27781
|
+
data = JSON.parse(raw);
|
|
27782
|
+
} catch (e) {
|
|
27783
|
+
log2(
|
|
27784
|
+
`[session-git-queue] No pre-turn snapshot for run ${runId.slice(0, 8)}\u2026: ${e instanceof Error ? e.message : String(e)}`
|
|
27785
|
+
);
|
|
27498
27786
|
return;
|
|
27499
27787
|
}
|
|
27500
|
-
|
|
27501
|
-
|
|
27502
|
-
|
|
27788
|
+
if (!Array.isArray(data.repos) || !data.repos.length) {
|
|
27789
|
+
log2(`[session-git-queue] Empty repos in snapshot ${runId.slice(0, 8)}\u2026; skipping aggregate diff.`);
|
|
27790
|
+
return;
|
|
27791
|
+
}
|
|
27792
|
+
const multiRepo = data.repos.length > 1;
|
|
27793
|
+
for (const repo of data.repos) {
|
|
27503
27794
|
if (!repo.stashSha) continue;
|
|
27504
27795
|
let namesRaw;
|
|
27505
27796
|
try {
|
|
27506
|
-
const { stdout } = await
|
|
27797
|
+
const { stdout } = await execFileAsync2("git", ["diff", "--name-only", repo.stashSha], {
|
|
27507
27798
|
cwd: repo.path,
|
|
27508
27799
|
maxBuffer: 10 * 1024 * 1024
|
|
27509
27800
|
});
|
|
27510
27801
|
namesRaw = stdout;
|
|
27511
27802
|
} catch (e) {
|
|
27512
27803
|
log2(
|
|
27513
|
-
`[session-git-queue]
|
|
27804
|
+
`[session-git-queue] Git diff --name-only failed in ${repo.path}: ${e instanceof Error ? e.message : String(e)}`
|
|
27514
27805
|
);
|
|
27515
27806
|
continue;
|
|
27516
27807
|
}
|
|
27517
27808
|
const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
27518
|
-
const slug =
|
|
27809
|
+
const slug = path5.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
|
|
27519
27810
|
for (const rel of lines) {
|
|
27520
27811
|
if (rel.includes("..")) continue;
|
|
27521
27812
|
try {
|
|
27522
|
-
const { stdout: patchContent } = await
|
|
27813
|
+
const { stdout: patchContent } = await execFileAsync2(
|
|
27523
27814
|
"git",
|
|
27524
27815
|
["diff", "--no-color", repo.stashSha, "--", rel],
|
|
27525
27816
|
{
|
|
@@ -27529,15 +27820,20 @@ async function collectSessionDiffAndNotify(options) {
|
|
|
27529
27820
|
);
|
|
27530
27821
|
if (!patchContent.trim()) continue;
|
|
27531
27822
|
const displayPath = multiRepo ? `${slug}/${rel}` : rel;
|
|
27823
|
+
const absFile = path5.join(repo.path, rel);
|
|
27824
|
+
const newText = readWorkspaceFileAsUtf8(absFile);
|
|
27532
27825
|
sendSessionUpdate({
|
|
27533
27826
|
type: "session_file_change",
|
|
27534
27827
|
sessionId,
|
|
27535
27828
|
runId,
|
|
27536
27829
|
path: displayPath,
|
|
27537
|
-
patchContent
|
|
27830
|
+
patchContent,
|
|
27831
|
+
...newText !== void 0 ? { newText } : {}
|
|
27538
27832
|
});
|
|
27539
27833
|
} catch (e) {
|
|
27540
|
-
log2(
|
|
27834
|
+
log2(
|
|
27835
|
+
`[session-git-queue] Git diff failed for ${rel}: ${e instanceof Error ? e.message : String(e)}`
|
|
27836
|
+
);
|
|
27541
27837
|
}
|
|
27542
27838
|
}
|
|
27543
27839
|
}
|
|
@@ -27551,15 +27847,21 @@ async function sendPromptToAgent(options) {
|
|
|
27551
27847
|
promptId,
|
|
27552
27848
|
sessionId,
|
|
27553
27849
|
runId,
|
|
27850
|
+
agentCwd,
|
|
27554
27851
|
sendResult,
|
|
27555
27852
|
sendSessionUpdate,
|
|
27556
|
-
collectSessionDiffAfterTurn,
|
|
27557
27853
|
log: log2
|
|
27558
27854
|
} = options;
|
|
27559
27855
|
try {
|
|
27560
27856
|
const result = await handle.sendPrompt(promptText, {});
|
|
27561
|
-
if (
|
|
27562
|
-
await
|
|
27857
|
+
if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
|
|
27858
|
+
await collectTurnGitDiffFromPreTurnSnapshot({
|
|
27859
|
+
sessionId,
|
|
27860
|
+
runId,
|
|
27861
|
+
agentCwd,
|
|
27862
|
+
sendSessionUpdate,
|
|
27863
|
+
log: log2
|
|
27864
|
+
});
|
|
27563
27865
|
}
|
|
27564
27866
|
sendResult({
|
|
27565
27867
|
type: "prompt_result",
|
|
@@ -27569,12 +27871,12 @@ async function sendPromptToAgent(options) {
|
|
|
27569
27871
|
...result
|
|
27570
27872
|
});
|
|
27571
27873
|
if (!result.success) {
|
|
27572
|
-
log2(`[
|
|
27874
|
+
log2(`[Agent] ${result.error ?? "Error"}`);
|
|
27573
27875
|
}
|
|
27574
27876
|
} catch (err) {
|
|
27575
27877
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
27576
|
-
log2(`[
|
|
27577
|
-
if (err instanceof Error && err.stack) log2(`[
|
|
27878
|
+
log2(`[Agent] Send failed: ${errMsg}`);
|
|
27879
|
+
if (err instanceof Error && err.stack) log2(`[Agent] ${err.stack}`);
|
|
27578
27880
|
sendResult({
|
|
27579
27881
|
type: "prompt_result",
|
|
27580
27882
|
id: promptId,
|
|
@@ -27587,8 +27889,8 @@ async function sendPromptToAgent(options) {
|
|
|
27587
27889
|
}
|
|
27588
27890
|
|
|
27589
27891
|
// src/acp/ensure-acp-client.ts
|
|
27590
|
-
import * as
|
|
27591
|
-
import * as
|
|
27892
|
+
import * as fs5 from "node:fs";
|
|
27893
|
+
import * as path9 from "node:path";
|
|
27592
27894
|
|
|
27593
27895
|
// src/error-message.ts
|
|
27594
27896
|
function errorMessage(err) {
|
|
@@ -27612,27 +27914,27 @@ async function createCodexAcpClient(options) {
|
|
|
27612
27914
|
}
|
|
27613
27915
|
|
|
27614
27916
|
// src/acp/clients/cursor-acp-client.ts
|
|
27615
|
-
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
27917
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
27616
27918
|
import { dirname } from "node:path";
|
|
27617
27919
|
import { spawn as spawn4 } from "node:child_process";
|
|
27618
27920
|
import * as readline from "node:readline";
|
|
27619
27921
|
|
|
27620
27922
|
// src/acp/safe-fs-path.ts
|
|
27621
|
-
import * as
|
|
27622
|
-
function resolveSafePathUnderCwd(
|
|
27923
|
+
import * as path6 from "node:path";
|
|
27924
|
+
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
27623
27925
|
const trimmed2 = filePath.trim();
|
|
27624
27926
|
if (!trimmed2) return null;
|
|
27625
|
-
const normalizedCwd =
|
|
27626
|
-
const resolved =
|
|
27627
|
-
const rel =
|
|
27628
|
-
if (rel.startsWith("..") ||
|
|
27927
|
+
const normalizedCwd = path6.resolve(cwd);
|
|
27928
|
+
const resolved = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.resolve(normalizedCwd, trimmed2);
|
|
27929
|
+
const rel = path6.relative(normalizedCwd, resolved);
|
|
27930
|
+
if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
|
|
27629
27931
|
return resolved;
|
|
27630
27932
|
}
|
|
27631
|
-
function toDisplayPathRelativeToCwd(
|
|
27632
|
-
const normalizedCwd =
|
|
27633
|
-
const rel =
|
|
27634
|
-
if (!rel || rel === "") return
|
|
27635
|
-
return rel.split(
|
|
27933
|
+
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
27934
|
+
const normalizedCwd = path6.resolve(cwd);
|
|
27935
|
+
const rel = path6.relative(normalizedCwd, path6.resolve(absolutePath));
|
|
27936
|
+
if (!rel || rel === "") return path6.basename(absolutePath);
|
|
27937
|
+
return rel.split(path6.sep).join("/");
|
|
27636
27938
|
}
|
|
27637
27939
|
|
|
27638
27940
|
// src/files/diff/unified-diff.ts
|
|
@@ -27681,6 +27983,19 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
|
27681
27983
|
return out.join("\n");
|
|
27682
27984
|
}
|
|
27683
27985
|
|
|
27986
|
+
// src/acp/format-session-update-kind-for-log.ts
|
|
27987
|
+
var SESSION_UPDATE_KIND_LABELS = {
|
|
27988
|
+
tool_call: "Tool call",
|
|
27989
|
+
tool_call_update: "Tool call status",
|
|
27990
|
+
agent_message_chunk: "Agent message chunk",
|
|
27991
|
+
update: "Session update"
|
|
27992
|
+
};
|
|
27993
|
+
function formatSessionUpdateKindForLog(kind) {
|
|
27994
|
+
const known = SESSION_UPDATE_KIND_LABELS[kind];
|
|
27995
|
+
if (known) return known;
|
|
27996
|
+
return kind.split("_").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
27997
|
+
}
|
|
27998
|
+
|
|
27684
27999
|
// src/acp/clients/cursor-acp-client.ts
|
|
27685
28000
|
var FS_READ_METHODS = /* @__PURE__ */ new Set(["fs/read_text_file", "fs/readTextFile"]);
|
|
27686
28001
|
var FS_WRITE_METHODS = /* @__PURE__ */ new Set(["fs/write_text_file", "fs/writeTextFile"]);
|
|
@@ -27706,16 +28021,16 @@ function sliceLinesByRange(content, line, limit) {
|
|
|
27706
28021
|
return lines.slice(start, end).join("\n");
|
|
27707
28022
|
}
|
|
27708
28023
|
async function createCursorAcpClient(options) {
|
|
27709
|
-
const { command, cwd
|
|
28024
|
+
const { command, cwd = getBridgeWorkspaceDirectory(), onSessionUpdate, onRequest, onFileChange } = options;
|
|
27710
28025
|
const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
|
|
27711
|
-
const
|
|
28026
|
+
const isWindows = process.platform === "win32";
|
|
27712
28027
|
const child = spawn4(command[0], command.slice(1), {
|
|
27713
|
-
cwd
|
|
28028
|
+
cwd,
|
|
27714
28029
|
stdio: ["pipe", "pipe", "inherit"],
|
|
27715
28030
|
env: process.env,
|
|
27716
|
-
shell:
|
|
28031
|
+
shell: isWindows
|
|
27717
28032
|
});
|
|
27718
|
-
return new Promise((
|
|
28033
|
+
return new Promise((resolve14, reject) => {
|
|
27719
28034
|
child.on("error", (err) => {
|
|
27720
28035
|
child.kill();
|
|
27721
28036
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -27768,7 +28083,10 @@ async function createCursorAcpClient(options) {
|
|
|
27768
28083
|
const toolCall = update.toolCall ?? update.tool_call;
|
|
27769
28084
|
const toolName = typeof toolCall?.name === "string" ? toolCall.name : "";
|
|
27770
28085
|
if (dbgFs && (sessionUpdate === "tool_call" || sessionUpdate === "tool_call_update")) {
|
|
27771
|
-
|
|
28086
|
+
const kindLabel = formatSessionUpdateKindForLog(sessionUpdate ?? "update");
|
|
28087
|
+
console.error(
|
|
28088
|
+
`[acp] Received session update (${kindLabel}) tool=${toolName || "(none)"}`
|
|
28089
|
+
);
|
|
27772
28090
|
}
|
|
27773
28091
|
const isTextChunk = sessionUpdate === "agent_message_chunk" && update.content?.text;
|
|
27774
28092
|
if (isTextChunk && update.content?.text) {
|
|
@@ -27788,14 +28106,14 @@ async function createCursorAcpClient(options) {
|
|
|
27788
28106
|
if (dbgFs) {
|
|
27789
28107
|
console.error(`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""}`);
|
|
27790
28108
|
}
|
|
27791
|
-
const abs = resolveSafePathUnderCwd(
|
|
28109
|
+
const abs = resolveSafePathUnderCwd(cwd, filePath);
|
|
27792
28110
|
if (!abs) {
|
|
27793
28111
|
if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty)`);
|
|
27794
28112
|
respondJsonRpcError(id, -32602, "Invalid or disallowed path");
|
|
27795
28113
|
return;
|
|
27796
28114
|
}
|
|
27797
28115
|
try {
|
|
27798
|
-
let content =
|
|
28116
|
+
let content = readFileSync3(abs, "utf8");
|
|
27799
28117
|
const line2 = typeof params.line === "number" ? params.line : void 0;
|
|
27800
28118
|
const limit = typeof params.limit === "number" ? params.limit : void 0;
|
|
27801
28119
|
content = sliceLinesByRange(content, line2, limit);
|
|
@@ -27819,7 +28137,7 @@ async function createCursorAcpClient(options) {
|
|
|
27819
28137
|
`[acp-fs] ${method} path=${filePath.slice(0, 200)}${filePath.length > 200 ? "\u2026" : ""} newBytes=${newText.length}`
|
|
27820
28138
|
);
|
|
27821
28139
|
}
|
|
27822
|
-
const abs = resolveSafePathUnderCwd(
|
|
28140
|
+
const abs = resolveSafePathUnderCwd(cwd, filePath);
|
|
27823
28141
|
if (!abs) {
|
|
27824
28142
|
if (dbgFs) console.error(`[acp-fs] ${method} rejected path (outside cwd or empty): ${filePath.slice(0, 120)}`);
|
|
27825
28143
|
respondJsonRpcError(id, -32602, "Invalid or disallowed path");
|
|
@@ -27827,7 +28145,7 @@ async function createCursorAcpClient(options) {
|
|
|
27827
28145
|
}
|
|
27828
28146
|
let oldText = "";
|
|
27829
28147
|
try {
|
|
27830
|
-
oldText =
|
|
28148
|
+
oldText = readFileSync3(abs, "utf8");
|
|
27831
28149
|
} catch (e) {
|
|
27832
28150
|
if (e.code !== "ENOENT") {
|
|
27833
28151
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
@@ -27835,13 +28153,13 @@ async function createCursorAcpClient(options) {
|
|
|
27835
28153
|
}
|
|
27836
28154
|
}
|
|
27837
28155
|
try {
|
|
27838
|
-
|
|
27839
|
-
|
|
28156
|
+
mkdirSync2(dirname(abs), { recursive: true });
|
|
28157
|
+
writeFileSync2(abs, newText, "utf8");
|
|
27840
28158
|
} catch (e) {
|
|
27841
28159
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
27842
28160
|
return;
|
|
27843
28161
|
}
|
|
27844
|
-
const displayPath = toDisplayPathRelativeToCwd(
|
|
28162
|
+
const displayPath = toDisplayPathRelativeToCwd(cwd, abs);
|
|
27845
28163
|
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
27846
28164
|
onFileChange?.({ path: displayPath, oldText, newText, patchContent });
|
|
27847
28165
|
respond(id, null);
|
|
@@ -27883,10 +28201,10 @@ async function createCursorAcpClient(options) {
|
|
|
27883
28201
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
27884
28202
|
});
|
|
27885
28203
|
await send("authenticate", { methodId: "cursor_login" });
|
|
27886
|
-
const newResult = await send("session/new", { cwd
|
|
28204
|
+
const newResult = await send("session/new", { cwd, mcpServers: [] });
|
|
27887
28205
|
const sessionId = newResult?.sessionId ?? "";
|
|
27888
28206
|
if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
|
|
27889
|
-
|
|
28207
|
+
resolve14({
|
|
27890
28208
|
sessionId,
|
|
27891
28209
|
async sendPrompt(prompt, _options) {
|
|
27892
28210
|
promptOutputBuffer = "";
|
|
@@ -27955,20 +28273,20 @@ function resolveAgentCommand(preferredAgentType) {
|
|
|
27955
28273
|
|
|
27956
28274
|
// src/acp/session-file-change-path-kind.ts
|
|
27957
28275
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
27958
|
-
import { existsSync, statSync } from "node:fs";
|
|
28276
|
+
import { existsSync, statSync as statSync2 } from "node:fs";
|
|
27959
28277
|
|
|
27960
28278
|
// src/git/get-git-repo-root-sync.ts
|
|
27961
28279
|
import { execFileSync } from "node:child_process";
|
|
27962
|
-
import * as
|
|
28280
|
+
import * as path7 from "node:path";
|
|
27963
28281
|
function getGitRepoRootSync(startDir) {
|
|
27964
28282
|
try {
|
|
27965
28283
|
const out = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
27966
|
-
cwd:
|
|
28284
|
+
cwd: path7.resolve(startDir),
|
|
27967
28285
|
encoding: "utf8",
|
|
27968
28286
|
stdio: ["ignore", "pipe", "ignore"],
|
|
27969
28287
|
maxBuffer: 1024 * 1024
|
|
27970
28288
|
}).trim();
|
|
27971
|
-
return out ?
|
|
28289
|
+
return out ? path7.resolve(out) : null;
|
|
27972
28290
|
} catch {
|
|
27973
28291
|
return null;
|
|
27974
28292
|
}
|
|
@@ -27976,65 +28294,65 @@ function getGitRepoRootSync(startDir) {
|
|
|
27976
28294
|
|
|
27977
28295
|
// src/acp/workspace-files.ts
|
|
27978
28296
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
27979
|
-
import { readFileSync as
|
|
27980
|
-
import * as
|
|
27981
|
-
function resolveWorkspaceFilePath(
|
|
28297
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
28298
|
+
import * as path8 from "node:path";
|
|
28299
|
+
function resolveWorkspaceFilePath(cwd, rawPath) {
|
|
27982
28300
|
const trimmed2 = rawPath.trim();
|
|
27983
28301
|
if (!trimmed2) return null;
|
|
27984
|
-
const normalizedCwd =
|
|
27985
|
-
let abs = resolveSafePathUnderCwd(
|
|
28302
|
+
const normalizedCwd = path8.resolve(cwd);
|
|
28303
|
+
let abs = resolveSafePathUnderCwd(cwd, trimmed2);
|
|
27986
28304
|
if (!abs) {
|
|
27987
|
-
const candidate =
|
|
27988
|
-
const gitRoot2 = getGitRepoRootSync(
|
|
28305
|
+
const candidate = path8.isAbsolute(trimmed2) ? path8.normalize(trimmed2) : path8.normalize(path8.resolve(normalizedCwd, trimmed2));
|
|
28306
|
+
const gitRoot2 = getGitRepoRootSync(cwd);
|
|
27989
28307
|
if (!gitRoot2) return null;
|
|
27990
|
-
const rel =
|
|
27991
|
-
if (rel.startsWith("..") ||
|
|
28308
|
+
const rel = path8.relative(gitRoot2, candidate);
|
|
28309
|
+
if (rel.startsWith("..") || path8.isAbsolute(rel)) return null;
|
|
27992
28310
|
abs = candidate;
|
|
27993
28311
|
}
|
|
27994
|
-
const gitRoot = getGitRepoRootSync(
|
|
28312
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
27995
28313
|
if (gitRoot) {
|
|
27996
|
-
const relFromRoot =
|
|
27997
|
-
if (!relFromRoot.startsWith("..") && !
|
|
27998
|
-
return { abs, display: relFromRoot.split(
|
|
28314
|
+
const relFromRoot = path8.relative(gitRoot, abs);
|
|
28315
|
+
if (!relFromRoot.startsWith("..") && !path8.isAbsolute(relFromRoot)) {
|
|
28316
|
+
return { abs, display: relFromRoot.split(path8.sep).join("/") };
|
|
27999
28317
|
}
|
|
28000
28318
|
}
|
|
28001
|
-
return { abs, display: toDisplayPathRelativeToCwd(
|
|
28319
|
+
return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
|
|
28002
28320
|
}
|
|
28003
|
-
function readUtf8WorkspaceFile(
|
|
28321
|
+
function readUtf8WorkspaceFile(cwd, displayPath) {
|
|
28004
28322
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
28005
|
-
const gitRoot = getGitRepoRootSync(
|
|
28323
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
28006
28324
|
if (gitRoot) {
|
|
28007
|
-
const abs2 =
|
|
28008
|
-
const rel =
|
|
28009
|
-
if (!rel.startsWith("..") && !
|
|
28325
|
+
const abs2 = path8.resolve(gitRoot, displayPath);
|
|
28326
|
+
const rel = path8.relative(gitRoot, abs2);
|
|
28327
|
+
if (!rel.startsWith("..") && !path8.isAbsolute(rel)) {
|
|
28010
28328
|
try {
|
|
28011
|
-
return
|
|
28329
|
+
return readFileSync4(abs2, "utf8");
|
|
28012
28330
|
} catch {
|
|
28013
28331
|
}
|
|
28014
28332
|
}
|
|
28015
28333
|
}
|
|
28016
|
-
const abs = resolveSafePathUnderCwd(
|
|
28334
|
+
const abs = resolveSafePathUnderCwd(cwd, displayPath);
|
|
28017
28335
|
if (!abs) return "";
|
|
28018
28336
|
try {
|
|
28019
|
-
return
|
|
28337
|
+
return readFileSync4(abs, "utf8");
|
|
28020
28338
|
} catch {
|
|
28021
28339
|
return "";
|
|
28022
28340
|
}
|
|
28023
28341
|
}
|
|
28024
|
-
function tryWorkspaceDisplayToAbs(
|
|
28342
|
+
function tryWorkspaceDisplayToAbs(cwd, displayPath) {
|
|
28025
28343
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
28026
|
-
const gitRoot = getGitRepoRootSync(
|
|
28344
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
28027
28345
|
if (gitRoot) {
|
|
28028
|
-
const abs =
|
|
28029
|
-
const rel =
|
|
28030
|
-
if (!rel.startsWith("..") && !
|
|
28346
|
+
const abs = path8.resolve(gitRoot, displayPath);
|
|
28347
|
+
const rel = path8.relative(gitRoot, abs);
|
|
28348
|
+
if (!rel.startsWith("..") && !path8.isAbsolute(rel)) return abs;
|
|
28031
28349
|
}
|
|
28032
|
-
return resolveSafePathUnderCwd(
|
|
28350
|
+
return resolveSafePathUnderCwd(cwd, displayPath);
|
|
28033
28351
|
}
|
|
28034
|
-
function readGitHeadBlob(
|
|
28352
|
+
function readGitHeadBlob(cwd, displayPath) {
|
|
28035
28353
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
28036
|
-
const gitRoot = getGitRepoRootSync(
|
|
28037
|
-
const execCwd = gitRoot ??
|
|
28354
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
28355
|
+
const execCwd = gitRoot ?? cwd;
|
|
28038
28356
|
try {
|
|
28039
28357
|
return execFileSync2("git", ["show", `HEAD:${displayPath}`], {
|
|
28040
28358
|
cwd: execCwd,
|
|
@@ -28047,9 +28365,9 @@ function readGitHeadBlob(cwd3, displayPath) {
|
|
|
28047
28365
|
}
|
|
28048
28366
|
|
|
28049
28367
|
// src/acp/session-file-change-path-kind.ts
|
|
28050
|
-
function gitHeadPathObjectType(
|
|
28368
|
+
function gitHeadPathObjectType(cwd, displayPath) {
|
|
28051
28369
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
28052
|
-
const gitRoot = getGitRepoRootSync(
|
|
28370
|
+
const gitRoot = getGitRepoRootSync(cwd);
|
|
28053
28371
|
if (!gitRoot) return null;
|
|
28054
28372
|
try {
|
|
28055
28373
|
return execFileSync3("git", ["cat-file", "-t", `HEAD:${displayPath}`], {
|
|
@@ -28060,11 +28378,11 @@ function gitHeadPathObjectType(cwd3, displayPath) {
|
|
|
28060
28378
|
return null;
|
|
28061
28379
|
}
|
|
28062
28380
|
}
|
|
28063
|
-
function getSessionFileChangeDirectoryFlags(
|
|
28064
|
-
const abs = tryWorkspaceDisplayToAbs(
|
|
28381
|
+
function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
|
|
28382
|
+
const abs = tryWorkspaceDisplayToAbs(cwd, displayPath);
|
|
28065
28383
|
if (abs && existsSync(abs)) {
|
|
28066
28384
|
try {
|
|
28067
|
-
if (
|
|
28385
|
+
if (statSync2(abs).isDirectory()) {
|
|
28068
28386
|
return { isDirectory: true, directoryRemoved: false };
|
|
28069
28387
|
}
|
|
28070
28388
|
return { isDirectory: false, directoryRemoved: false };
|
|
@@ -28072,7 +28390,7 @@ function getSessionFileChangeDirectoryFlags(cwd3, displayPath) {
|
|
|
28072
28390
|
return { isDirectory: false, directoryRemoved: false };
|
|
28073
28391
|
}
|
|
28074
28392
|
}
|
|
28075
|
-
if (gitHeadPathObjectType(
|
|
28393
|
+
if (gitHeadPathObjectType(cwd, displayPath) === "tree") {
|
|
28076
28394
|
return { isDirectory: true, directoryRemoved: true };
|
|
28077
28395
|
}
|
|
28078
28396
|
return { isDirectory: false, directoryRemoved: false };
|
|
@@ -28086,11 +28404,13 @@ function createBridgeOnFileChange(opts) {
|
|
|
28086
28404
|
const sessionId = routing.sessionId;
|
|
28087
28405
|
const send = getSendSessionUpdate();
|
|
28088
28406
|
if (!send || !runId || !sessionId) {
|
|
28089
|
-
log2(
|
|
28407
|
+
log2(
|
|
28408
|
+
`[Bridge service] File change not forwarded (${evt.path}): session or run not wired to the bridge.`
|
|
28409
|
+
);
|
|
28090
28410
|
return;
|
|
28091
28411
|
}
|
|
28092
|
-
const
|
|
28093
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(
|
|
28412
|
+
const cwd = getBridgeWorkspaceDirectory();
|
|
28413
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(cwd, evt.path);
|
|
28094
28414
|
try {
|
|
28095
28415
|
send({
|
|
28096
28416
|
type: "session_file_change",
|
|
@@ -28104,7 +28424,7 @@ function createBridgeOnFileChange(opts) {
|
|
|
28104
28424
|
directoryRemoved: dirFlags.directoryRemoved
|
|
28105
28425
|
});
|
|
28106
28426
|
} catch (err) {
|
|
28107
|
-
log2(`[Bridge service]
|
|
28427
|
+
log2(`[Bridge service] Session file change failed for ${evt.path}: ${errorMessage(err)}`);
|
|
28108
28428
|
}
|
|
28109
28429
|
};
|
|
28110
28430
|
}
|
|
@@ -28131,7 +28451,9 @@ function createBridgeOnRequest(opts) {
|
|
|
28131
28451
|
}
|
|
28132
28452
|
});
|
|
28133
28453
|
} catch (err) {
|
|
28134
|
-
log2(
|
|
28454
|
+
log2(
|
|
28455
|
+
`[Bridge service] Agent protocol request forward failed (${request.method}): ${errorMessage(err)}`
|
|
28456
|
+
);
|
|
28135
28457
|
}
|
|
28136
28458
|
};
|
|
28137
28459
|
}
|
|
@@ -28163,12 +28485,12 @@ function extractDiffPath(o) {
|
|
|
28163
28485
|
}
|
|
28164
28486
|
|
|
28165
28487
|
// src/acp/hooks/extract-acp-file-diffs-from-update/push-diff.ts
|
|
28166
|
-
function pushDiffIfComplete(o,
|
|
28488
|
+
function pushDiffIfComplete(o, cwd, out) {
|
|
28167
28489
|
const t = o.type;
|
|
28168
28490
|
if (typeof t !== "string" || t.toLowerCase() !== "diff") return;
|
|
28169
28491
|
const rawPath = extractDiffPath(o);
|
|
28170
28492
|
if (!rawPath) return;
|
|
28171
|
-
const resolved = resolveWorkspaceFilePath(
|
|
28493
|
+
const resolved = resolveWorkspaceFilePath(cwd, rawPath);
|
|
28172
28494
|
if (!resolved) return;
|
|
28173
28495
|
const oldText = readOptionalTextField(o.oldText ?? o.old_text ?? o.before ?? o.oldContent);
|
|
28174
28496
|
const newText = readOptionalTextField(o.newText ?? o.new_text ?? o.after ?? o.newContent);
|
|
@@ -28187,17 +28509,17 @@ var NEST_KEYS = [
|
|
|
28187
28509
|
"data",
|
|
28188
28510
|
"arguments"
|
|
28189
28511
|
];
|
|
28190
|
-
function walkValue(value,
|
|
28512
|
+
function walkValue(value, cwd, depth, out) {
|
|
28191
28513
|
if (depth > 12 || value == null) return;
|
|
28192
28514
|
if (Array.isArray(value)) {
|
|
28193
|
-
for (const x of value) walkValue(x,
|
|
28515
|
+
for (const x of value) walkValue(x, cwd, depth + 1, out);
|
|
28194
28516
|
return;
|
|
28195
28517
|
}
|
|
28196
28518
|
if (typeof value !== "object") return;
|
|
28197
28519
|
const o = value;
|
|
28198
|
-
pushDiffIfComplete(o,
|
|
28520
|
+
pushDiffIfComplete(o, cwd, out);
|
|
28199
28521
|
if (o.type === "content" && o.content != null && typeof o.content === "object") {
|
|
28200
|
-
walkValue(o.content,
|
|
28522
|
+
walkValue(o.content, cwd, depth + 1, out);
|
|
28201
28523
|
}
|
|
28202
28524
|
for (const k of NEST_KEYS) {
|
|
28203
28525
|
if (o.type === "content" && k === "content") continue;
|
|
@@ -28205,23 +28527,23 @@ function walkValue(value, cwd3, depth, out) {
|
|
|
28205
28527
|
if (v == null) continue;
|
|
28206
28528
|
if (k === "arguments" && typeof v === "string") {
|
|
28207
28529
|
try {
|
|
28208
|
-
walkValue(JSON.parse(v),
|
|
28530
|
+
walkValue(JSON.parse(v), cwd, depth + 1, out);
|
|
28209
28531
|
} catch {
|
|
28210
28532
|
}
|
|
28211
28533
|
continue;
|
|
28212
28534
|
}
|
|
28213
|
-
walkValue(v,
|
|
28535
|
+
walkValue(v, cwd, depth + 1, out);
|
|
28214
28536
|
}
|
|
28215
28537
|
}
|
|
28216
28538
|
|
|
28217
28539
|
// src/acp/hooks/extract-acp-file-diffs-from-update/extract.ts
|
|
28218
|
-
function extractAcpFileDiffsFromUpdate(update,
|
|
28540
|
+
function extractAcpFileDiffsFromUpdate(update, cwd) {
|
|
28219
28541
|
if (!update || typeof update !== "object") return [];
|
|
28220
28542
|
const u = update;
|
|
28221
28543
|
const out = [];
|
|
28222
28544
|
const content = u.content;
|
|
28223
28545
|
if (Array.isArray(content)) {
|
|
28224
|
-
for (const x of content) walkValue(x,
|
|
28546
|
+
for (const x of content) walkValue(x, cwd, 0, out);
|
|
28225
28547
|
}
|
|
28226
28548
|
const byPath = /* @__PURE__ */ new Map();
|
|
28227
28549
|
for (const d of out) byPath.set(d.path, d);
|
|
@@ -28229,18 +28551,18 @@ function extractAcpFileDiffsFromUpdate(update, cwd3) {
|
|
|
28229
28551
|
}
|
|
28230
28552
|
|
|
28231
28553
|
// src/acp/hooks/extract-tool-target-paths.ts
|
|
28232
|
-
function addPath(
|
|
28554
|
+
function addPath(cwd, raw, out) {
|
|
28233
28555
|
if (typeof raw !== "string") return;
|
|
28234
28556
|
const trimmed2 = raw.trim();
|
|
28235
28557
|
if (!trimmed2) return;
|
|
28236
|
-
const resolved = resolveWorkspaceFilePath(
|
|
28558
|
+
const resolved = resolveWorkspaceFilePath(cwd, trimmed2);
|
|
28237
28559
|
if (!resolved) return;
|
|
28238
28560
|
out.add(resolved.display);
|
|
28239
28561
|
}
|
|
28240
|
-
function walkLocations(
|
|
28562
|
+
function walkLocations(cwd, loc, out) {
|
|
28241
28563
|
if (!Array.isArray(loc)) return;
|
|
28242
28564
|
for (const item of loc) {
|
|
28243
|
-
if (item && typeof item === "object") addPath(
|
|
28565
|
+
if (item && typeof item === "object") addPath(cwd, item.path, out);
|
|
28244
28566
|
}
|
|
28245
28567
|
}
|
|
28246
28568
|
var PATH_KEYS = [
|
|
@@ -28253,56 +28575,56 @@ var PATH_KEYS = [
|
|
|
28253
28575
|
"file_path",
|
|
28254
28576
|
"target_file"
|
|
28255
28577
|
];
|
|
28256
|
-
function collectFromObject(
|
|
28578
|
+
function collectFromObject(cwd, obj, out, depth) {
|
|
28257
28579
|
if (depth > 10) return;
|
|
28258
28580
|
for (const k of PATH_KEYS) {
|
|
28259
|
-
if (k in obj) addPath(
|
|
28581
|
+
if (k in obj) addPath(cwd, obj[k], out);
|
|
28260
28582
|
}
|
|
28261
28583
|
for (const v of Object.values(obj)) {
|
|
28262
|
-
if (v != null && typeof v === "object") collectUnknown(
|
|
28584
|
+
if (v != null && typeof v === "object") collectUnknown(cwd, v, out, depth + 1);
|
|
28263
28585
|
}
|
|
28264
28586
|
}
|
|
28265
|
-
function collectUnknown(
|
|
28587
|
+
function collectUnknown(cwd, v, out, depth) {
|
|
28266
28588
|
if (depth > 10 || v == null) return;
|
|
28267
28589
|
if (Array.isArray(v)) {
|
|
28268
|
-
for (const x of v) collectUnknown(
|
|
28590
|
+
for (const x of v) collectUnknown(cwd, x, out, depth + 1);
|
|
28269
28591
|
return;
|
|
28270
28592
|
}
|
|
28271
|
-
if (typeof v === "object") collectFromObject(
|
|
28593
|
+
if (typeof v === "object") collectFromObject(cwd, v, out, depth);
|
|
28272
28594
|
}
|
|
28273
|
-
function walkContentArray(
|
|
28595
|
+
function walkContentArray(cwd, content, out) {
|
|
28274
28596
|
if (!Array.isArray(content)) return;
|
|
28275
28597
|
for (const item of content) {
|
|
28276
28598
|
if (!item || typeof item !== "object") continue;
|
|
28277
28599
|
const o = item;
|
|
28278
28600
|
if (typeof o.type === "string" && o.type.toLowerCase() === "diff") {
|
|
28279
|
-
for (const k of PATH_KEYS) if (k in o) addPath(
|
|
28601
|
+
for (const k of PATH_KEYS) if (k in o) addPath(cwd, o[k], out);
|
|
28280
28602
|
}
|
|
28281
28603
|
if (o.type === "content" && o.content != null && typeof o.content === "object") {
|
|
28282
28604
|
const inner = o.content;
|
|
28283
28605
|
if (typeof inner.type === "string" && inner.type.toLowerCase() === "diff") {
|
|
28284
|
-
for (const k of PATH_KEYS) if (k in inner) addPath(
|
|
28606
|
+
for (const k of PATH_KEYS) if (k in inner) addPath(cwd, inner[k], out);
|
|
28285
28607
|
}
|
|
28286
28608
|
}
|
|
28287
28609
|
}
|
|
28288
28610
|
}
|
|
28289
|
-
function extractToolTargetDisplayPaths(update,
|
|
28611
|
+
function extractToolTargetDisplayPaths(update, cwd) {
|
|
28290
28612
|
const out = /* @__PURE__ */ new Set();
|
|
28291
28613
|
if (!update || typeof update !== "object") return [];
|
|
28292
28614
|
const u = update;
|
|
28293
|
-
walkLocations(
|
|
28294
|
-
walkLocations(
|
|
28295
|
-
walkLocations(
|
|
28615
|
+
walkLocations(cwd, u.locations, out);
|
|
28616
|
+
walkLocations(cwd, u.fileLocations, out);
|
|
28617
|
+
walkLocations(cwd, u.file_locations, out);
|
|
28296
28618
|
const tc = u.toolCall ?? u.tool_call;
|
|
28297
28619
|
if (tc && typeof tc.arguments === "string") {
|
|
28298
28620
|
try {
|
|
28299
28621
|
const parsed = JSON.parse(tc.arguments);
|
|
28300
|
-
collectUnknown(
|
|
28622
|
+
collectUnknown(cwd, parsed, out, 0);
|
|
28301
28623
|
} catch {
|
|
28302
28624
|
}
|
|
28303
28625
|
}
|
|
28304
|
-
walkContentArray(
|
|
28305
|
-
collectFromObject(
|
|
28626
|
+
walkContentArray(cwd, u.content, out);
|
|
28627
|
+
collectFromObject(cwd, u, out, 0);
|
|
28306
28628
|
return [...out];
|
|
28307
28629
|
}
|
|
28308
28630
|
|
|
@@ -28368,7 +28690,7 @@ var PathSnapshotTracker = class {
|
|
|
28368
28690
|
this.beforeByToolKey.delete(toolKey);
|
|
28369
28691
|
this.accumulatedPathsByToolKey.delete(toolKey);
|
|
28370
28692
|
}
|
|
28371
|
-
captureBeforeFromDisk(toolKey, paths,
|
|
28693
|
+
captureBeforeFromDisk(toolKey, paths, cwd) {
|
|
28372
28694
|
if (paths.length === 0) return;
|
|
28373
28695
|
let m = this.beforeByToolKey.get(toolKey);
|
|
28374
28696
|
if (!m) {
|
|
@@ -28377,10 +28699,10 @@ var PathSnapshotTracker = class {
|
|
|
28377
28699
|
}
|
|
28378
28700
|
for (const p of paths) {
|
|
28379
28701
|
if (m.has(p)) continue;
|
|
28380
|
-
m.set(p, readUtf8WorkspaceFile(
|
|
28702
|
+
m.set(p, readUtf8WorkspaceFile(cwd, p));
|
|
28381
28703
|
}
|
|
28382
28704
|
}
|
|
28383
|
-
ensureBeforeFromHeadForMissing(toolKey, paths,
|
|
28705
|
+
ensureBeforeFromHeadForMissing(toolKey, paths, cwd) {
|
|
28384
28706
|
let m = this.beforeByToolKey.get(toolKey);
|
|
28385
28707
|
if (!m) {
|
|
28386
28708
|
m = /* @__PURE__ */ new Map();
|
|
@@ -28388,10 +28710,10 @@ var PathSnapshotTracker = class {
|
|
|
28388
28710
|
}
|
|
28389
28711
|
for (const p of paths) {
|
|
28390
28712
|
if (m.has(p)) continue;
|
|
28391
|
-
m.set(p, readGitHeadBlob(
|
|
28713
|
+
m.set(p, readGitHeadBlob(cwd, p));
|
|
28392
28714
|
}
|
|
28393
28715
|
}
|
|
28394
|
-
flushPathSnapshots(toolKey,
|
|
28716
|
+
flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2) {
|
|
28395
28717
|
const t = this.debouncers.get(toolKey);
|
|
28396
28718
|
if (t) clearTimeout(t);
|
|
28397
28719
|
this.debouncers.delete(toolKey);
|
|
@@ -28400,10 +28722,10 @@ var PathSnapshotTracker = class {
|
|
|
28400
28722
|
this.beforeByToolKey.delete(toolKey);
|
|
28401
28723
|
if (!send || !runId || !sessionId) return;
|
|
28402
28724
|
for (const [displayPath, oldText] of beforeMap) {
|
|
28403
|
-
const newText = readUtf8WorkspaceFile(
|
|
28725
|
+
const newText = readUtf8WorkspaceFile(cwd, displayPath);
|
|
28404
28726
|
if (oldText === newText) continue;
|
|
28405
28727
|
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
28406
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(
|
|
28728
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(cwd, displayPath);
|
|
28407
28729
|
try {
|
|
28408
28730
|
send({
|
|
28409
28731
|
type: "session_file_change",
|
|
@@ -28418,35 +28740,35 @@ var PathSnapshotTracker = class {
|
|
|
28418
28740
|
});
|
|
28419
28741
|
sentPaths.add(displayPath);
|
|
28420
28742
|
} catch (err) {
|
|
28421
|
-
log2(`[Bridge service]
|
|
28743
|
+
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
28422
28744
|
}
|
|
28423
28745
|
}
|
|
28424
28746
|
}
|
|
28425
|
-
scheduleDebouncedFlush(toolKey,
|
|
28747
|
+
scheduleDebouncedFlush(toolKey, cwd, sentPaths, send, runId, sessionId, log2) {
|
|
28426
28748
|
const prev = this.debouncers.get(toolKey);
|
|
28427
28749
|
if (prev) clearTimeout(prev);
|
|
28428
28750
|
this.debouncers.set(
|
|
28429
28751
|
toolKey,
|
|
28430
28752
|
setTimeout(() => {
|
|
28431
28753
|
this.debouncers.delete(toolKey);
|
|
28432
|
-
this.flushPathSnapshots(toolKey,
|
|
28754
|
+
this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
|
|
28433
28755
|
}, PATH_SNAPSHOT_DEBOUNCE_MS)
|
|
28434
28756
|
);
|
|
28435
28757
|
}
|
|
28436
|
-
handleToolCallLifecycle(updateKind, toolKey, toolPaths, status,
|
|
28758
|
+
handleToolCallLifecycle(updateKind, toolKey, toolPaths, status, cwd, sentPaths, send, runId, sessionId, log2) {
|
|
28437
28759
|
if (updateKind === "tool_call") {
|
|
28438
28760
|
this.resetToolSnapshots(toolKey);
|
|
28439
28761
|
}
|
|
28440
28762
|
if (updateKind === "tool_call") {
|
|
28441
|
-
this.captureBeforeFromDisk(toolKey, toolPaths,
|
|
28763
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
|
|
28442
28764
|
} else if (updateKind === "tool_call_update") {
|
|
28443
28765
|
if (isCompletedToolStatus(status)) {
|
|
28444
|
-
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths,
|
|
28445
|
-
this.flushPathSnapshots(toolKey,
|
|
28766
|
+
this.ensureBeforeFromHeadForMissing(toolKey, toolPaths, cwd);
|
|
28767
|
+
this.flushPathSnapshots(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
|
|
28446
28768
|
} else {
|
|
28447
|
-
this.captureBeforeFromDisk(toolKey, toolPaths,
|
|
28769
|
+
this.captureBeforeFromDisk(toolKey, toolPaths, cwd);
|
|
28448
28770
|
if (this.beforeByToolKey.has(toolKey)) {
|
|
28449
|
-
this.scheduleDebouncedFlush(toolKey,
|
|
28771
|
+
this.scheduleDebouncedFlush(toolKey, cwd, sentPaths, send, runId, sessionId, log2);
|
|
28450
28772
|
}
|
|
28451
28773
|
}
|
|
28452
28774
|
}
|
|
@@ -28454,11 +28776,11 @@ var PathSnapshotTracker = class {
|
|
|
28454
28776
|
};
|
|
28455
28777
|
|
|
28456
28778
|
// src/acp/hooks/bridge-on-session-update/send-structured-file-changes.ts
|
|
28457
|
-
function sendExtractedDiffsAsSessionFileChanges(diffs, send,
|
|
28779
|
+
function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentPaths, log2) {
|
|
28458
28780
|
for (const d of diffs) {
|
|
28459
28781
|
try {
|
|
28460
28782
|
const patchContent = editSnippetToUnifiedDiff(d.path, d.oldText, d.newText);
|
|
28461
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(
|
|
28783
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(cwd, d.path);
|
|
28462
28784
|
send({
|
|
28463
28785
|
type: "session_file_change",
|
|
28464
28786
|
sessionId,
|
|
@@ -28472,19 +28794,19 @@ function sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd3, sessionId, ru
|
|
|
28472
28794
|
});
|
|
28473
28795
|
sentPaths.add(d.path);
|
|
28474
28796
|
} catch (err) {
|
|
28475
|
-
log2(`[Bridge service]
|
|
28797
|
+
log2(`[Bridge service] Session file change failed for ${d.path}: ${errorMessage(err)}`);
|
|
28476
28798
|
}
|
|
28477
28799
|
}
|
|
28478
28800
|
}
|
|
28479
|
-
function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send,
|
|
28801
|
+
function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd, sessionId, runId, log2) {
|
|
28480
28802
|
for (const displayPath of mergedPaths) {
|
|
28481
28803
|
if (sentPaths.has(displayPath)) continue;
|
|
28482
|
-
const oldText = readGitHeadBlob(
|
|
28483
|
-
const newText = readUtf8WorkspaceFile(
|
|
28804
|
+
const oldText = readGitHeadBlob(cwd, displayPath);
|
|
28805
|
+
const newText = readUtf8WorkspaceFile(cwd, displayPath);
|
|
28484
28806
|
if (oldText === newText) continue;
|
|
28485
28807
|
try {
|
|
28486
28808
|
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, newText);
|
|
28487
|
-
const dirFlags = getSessionFileChangeDirectoryFlags(
|
|
28809
|
+
const dirFlags = getSessionFileChangeDirectoryFlags(cwd, displayPath);
|
|
28488
28810
|
send({
|
|
28489
28811
|
type: "session_file_change",
|
|
28490
28812
|
sessionId,
|
|
@@ -28498,7 +28820,7 @@ function sendGitHeadVsWorkspaceForToolPaths(mergedPaths, sentPaths, send, cwd3,
|
|
|
28498
28820
|
});
|
|
28499
28821
|
sentPaths.add(displayPath);
|
|
28500
28822
|
} catch (err) {
|
|
28501
|
-
log2(`[Bridge service]
|
|
28823
|
+
log2(`[Bridge service] Session file change failed for ${displayPath}: ${errorMessage(err)}`);
|
|
28502
28824
|
}
|
|
28503
28825
|
}
|
|
28504
28826
|
}
|
|
@@ -28511,7 +28833,7 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
28511
28833
|
const runId = routing.runId;
|
|
28512
28834
|
const sessionId = routing.sessionId;
|
|
28513
28835
|
pathTracker.onRunIdChanged(runId);
|
|
28514
|
-
const
|
|
28836
|
+
const cwd = getBridgeWorkspaceDirectory();
|
|
28515
28837
|
const send = getSendSessionUpdate();
|
|
28516
28838
|
const sentFileChangePaths = /* @__PURE__ */ new Set();
|
|
28517
28839
|
const p = params;
|
|
@@ -28519,7 +28841,7 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
28519
28841
|
const isCompletedToolCallUpdate = updateKind === "tool_call_update" && isCompletedToolStatus(p.status);
|
|
28520
28842
|
const toolName = p.toolCall?.name ?? p.tool_call?.name ?? "";
|
|
28521
28843
|
const isToolUpdate = updateKind === "tool_call" || updateKind === "tool_call_update" || typeof toolName === "string" && toolName.length > 0;
|
|
28522
|
-
const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params,
|
|
28844
|
+
const toolPaths = isToolUpdate ? extractToolTargetDisplayPaths(params, cwd) : [];
|
|
28523
28845
|
const toolKey = isToolUpdate ? pathTracker.resolveToolKey(params, updateKind) : "";
|
|
28524
28846
|
if (updateKind === "tool_call") {
|
|
28525
28847
|
pathTracker.resetToolSnapshots(toolKey);
|
|
@@ -28534,7 +28856,7 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
28534
28856
|
toolKey,
|
|
28535
28857
|
toolPaths,
|
|
28536
28858
|
p.status,
|
|
28537
|
-
|
|
28859
|
+
cwd,
|
|
28538
28860
|
sentFileChangePaths,
|
|
28539
28861
|
deliver,
|
|
28540
28862
|
runId ?? "",
|
|
@@ -28542,18 +28864,18 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
28542
28864
|
log2
|
|
28543
28865
|
);
|
|
28544
28866
|
}
|
|
28545
|
-
const diffs = extractAcpFileDiffsFromUpdate(params,
|
|
28867
|
+
const diffs = extractAcpFileDiffsFromUpdate(params, cwd);
|
|
28546
28868
|
if (diffs.length > 0 && send && runId && sessionId) {
|
|
28547
|
-
sendExtractedDiffsAsSessionFileChanges(diffs, send,
|
|
28869
|
+
sendExtractedDiffsAsSessionFileChanges(diffs, send, cwd, sessionId, runId, sentFileChangePaths, log2);
|
|
28548
28870
|
} else if (diffs.length > 0) {
|
|
28549
28871
|
log2(
|
|
28550
|
-
`[Bridge service]
|
|
28872
|
+
`[Bridge service] Agent file diff(s) not forwarded (${diffs.length}): session or run not wired to the bridge.`
|
|
28551
28873
|
);
|
|
28552
28874
|
}
|
|
28553
28875
|
if (isCompletedToolCallUpdate && send && runId && sessionId) {
|
|
28554
28876
|
const acc = pathTracker.accumulatedPathsByToolKey.get(toolKey);
|
|
28555
28877
|
const merged = [.../* @__PURE__ */ new Set([...acc ? [...acc] : [], ...toolPaths])];
|
|
28556
|
-
sendGitHeadVsWorkspaceForToolPaths(merged, sentFileChangePaths, send,
|
|
28878
|
+
sendGitHeadVsWorkspaceForToolPaths(merged, sentFileChangePaths, send, cwd, sessionId, runId, log2);
|
|
28557
28879
|
pathTracker.accumulatedPathsByToolKey.delete(toolKey);
|
|
28558
28880
|
}
|
|
28559
28881
|
if (runId && send) {
|
|
@@ -28566,7 +28888,9 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
28566
28888
|
payload: params
|
|
28567
28889
|
});
|
|
28568
28890
|
} catch (err) {
|
|
28569
|
-
log2(
|
|
28891
|
+
log2(
|
|
28892
|
+
`[Bridge service] Session update send failed (${formatSessionUpdateKindForLog(updateKind)}): ${errorMessage(err)}`
|
|
28893
|
+
);
|
|
28570
28894
|
}
|
|
28571
28895
|
}
|
|
28572
28896
|
};
|
|
@@ -28583,11 +28907,11 @@ function buildAcpSessionBridgeHooks(opts) {
|
|
|
28583
28907
|
|
|
28584
28908
|
// src/acp/ensure-acp-client.ts
|
|
28585
28909
|
async function ensureAcpClient(options) {
|
|
28586
|
-
const { state, preferredAgentType, mode, cwd
|
|
28587
|
-
const targetCwd =
|
|
28588
|
-
|
|
28910
|
+
const { state, preferredAgentType, mode, cwd, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
|
|
28911
|
+
const targetCwd = path9.resolve(
|
|
28912
|
+
cwd != null && String(cwd).trim() !== "" ? String(cwd).trim() : getBridgeWorkspaceDirectory()
|
|
28589
28913
|
);
|
|
28590
|
-
if (state.acpHandle && state.lastAcpCwd != null &&
|
|
28914
|
+
if (state.acpHandle && state.lastAcpCwd != null && path9.resolve(state.lastAcpCwd) !== path9.resolve(targetCwd)) {
|
|
28591
28915
|
try {
|
|
28592
28916
|
state.acpHandle.disconnect();
|
|
28593
28917
|
} catch {
|
|
@@ -28599,7 +28923,7 @@ async function ensureAcpClient(options) {
|
|
|
28599
28923
|
const resolved = resolveAgentCommand(preferredAgentType);
|
|
28600
28924
|
if (!resolved) {
|
|
28601
28925
|
log2(
|
|
28602
|
-
`[
|
|
28926
|
+
`[Agent] No local agent type (${preferredAgentType === null ? "none" : `"${preferredAgentType}"`}). Send agent type on prompts or agent configuration after identify.`
|
|
28603
28927
|
);
|
|
28604
28928
|
state.lastAcpStartError = "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge.";
|
|
28605
28929
|
return null;
|
|
@@ -28618,15 +28942,15 @@ async function ensureAcpClient(options) {
|
|
|
28618
28942
|
if (!state.acpStartPromise) {
|
|
28619
28943
|
let statOk = false;
|
|
28620
28944
|
try {
|
|
28621
|
-
const st =
|
|
28945
|
+
const st = fs5.statSync(targetCwd);
|
|
28622
28946
|
statOk = st.isDirectory();
|
|
28623
28947
|
if (!statOk) {
|
|
28624
28948
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
|
|
28625
|
-
log2(`[
|
|
28949
|
+
log2(`[Agent] ${state.lastAcpStartError}`);
|
|
28626
28950
|
}
|
|
28627
28951
|
} catch {
|
|
28628
28952
|
state.lastAcpStartError = `Agent cwd missing or inaccessible: ${targetCwd}`;
|
|
28629
|
-
log2(`[
|
|
28953
|
+
log2(`[Agent] ${state.lastAcpStartError}`);
|
|
28630
28954
|
}
|
|
28631
28955
|
if (!statOk) {
|
|
28632
28956
|
return null;
|
|
@@ -28651,7 +28975,7 @@ async function ensureAcpClient(options) {
|
|
|
28651
28975
|
return h;
|
|
28652
28976
|
}).catch((err) => {
|
|
28653
28977
|
state.lastAcpStartError = errorMessage(err);
|
|
28654
|
-
log2(`[
|
|
28978
|
+
log2(`[Agent] Failed to start: ${state.lastAcpStartError}`);
|
|
28655
28979
|
state.acpStartPromise = null;
|
|
28656
28980
|
state.acpAgentKey = null;
|
|
28657
28981
|
return null;
|
|
@@ -28687,10 +29011,9 @@ async function createAcpManager(options) {
|
|
|
28687
29011
|
runId,
|
|
28688
29012
|
mode,
|
|
28689
29013
|
agentType,
|
|
28690
|
-
cwd
|
|
29014
|
+
cwd,
|
|
28691
29015
|
sendResult,
|
|
28692
|
-
sendSessionUpdate
|
|
28693
|
-
collectSessionDiffAfterTurn
|
|
29016
|
+
sendSessionUpdate
|
|
28694
29017
|
} = opts;
|
|
28695
29018
|
const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
|
|
28696
29019
|
pendingCancelRunId = void 0;
|
|
@@ -28702,7 +29025,7 @@ async function createAcpManager(options) {
|
|
|
28702
29025
|
state,
|
|
28703
29026
|
preferredAgentType: preferredForPrompt,
|
|
28704
29027
|
mode,
|
|
28705
|
-
cwd
|
|
29028
|
+
cwd,
|
|
28706
29029
|
routing: promptRouting,
|
|
28707
29030
|
sendSessionUpdate,
|
|
28708
29031
|
sendRequest: sendSessionUpdate,
|
|
@@ -28743,9 +29066,9 @@ async function createAcpManager(options) {
|
|
|
28743
29066
|
promptId,
|
|
28744
29067
|
sessionId,
|
|
28745
29068
|
runId,
|
|
29069
|
+
agentCwd: cwd,
|
|
28746
29070
|
sendResult,
|
|
28747
29071
|
sendSessionUpdate,
|
|
28748
|
-
collectSessionDiffAfterTurn,
|
|
28749
29072
|
log: log2
|
|
28750
29073
|
});
|
|
28751
29074
|
}
|
|
@@ -28764,7 +29087,7 @@ async function createAcpManager(options) {
|
|
|
28764
29087
|
await handle.cancel();
|
|
28765
29088
|
return true;
|
|
28766
29089
|
} catch (err) {
|
|
28767
|
-
log2(`[
|
|
29090
|
+
log2(`[Agent] Cancel failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
28768
29091
|
return false;
|
|
28769
29092
|
}
|
|
28770
29093
|
}
|
|
@@ -28801,7 +29124,9 @@ var handleBridgeIdentified = (msg, deps) => {
|
|
|
28801
29124
|
try {
|
|
28802
29125
|
await deps.reportAutoDetectedAgents?.();
|
|
28803
29126
|
} catch (e) {
|
|
28804
|
-
deps.log(
|
|
29127
|
+
deps.log(
|
|
29128
|
+
`[Bridge service] Auto-detect agents failed: ${e instanceof Error ? e.message : String(e)}`
|
|
29129
|
+
);
|
|
28805
29130
|
}
|
|
28806
29131
|
})();
|
|
28807
29132
|
});
|
|
@@ -28809,7 +29134,9 @@ var handleBridgeIdentified = (msg, deps) => {
|
|
|
28809
29134
|
try {
|
|
28810
29135
|
deps.sendLocalSkillsReport?.();
|
|
28811
29136
|
} catch (e) {
|
|
28812
|
-
deps.log(
|
|
29137
|
+
deps.log(
|
|
29138
|
+
`[Bridge service] Local skills report failed: ${e instanceof Error ? e.message : String(e)}`
|
|
29139
|
+
);
|
|
28813
29140
|
}
|
|
28814
29141
|
});
|
|
28815
29142
|
};
|
|
@@ -28826,12 +29153,12 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
28826
29153
|
};
|
|
28827
29154
|
|
|
28828
29155
|
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
28829
|
-
import * as
|
|
29156
|
+
import * as path11 from "node:path";
|
|
28830
29157
|
import { execFile as execFile3 } from "node:child_process";
|
|
28831
29158
|
import { promisify as promisify3 } from "node:util";
|
|
28832
29159
|
|
|
28833
29160
|
// src/git/bridge-queue-key.ts
|
|
28834
|
-
import * as
|
|
29161
|
+
import * as path10 from "node:path";
|
|
28835
29162
|
import { createHash } from "node:crypto";
|
|
28836
29163
|
function normalizeCanonicalGitUrl(url2) {
|
|
28837
29164
|
let s = url2.trim();
|
|
@@ -28859,13 +29186,13 @@ function canonicalUrlToRepoIdSync(url2) {
|
|
|
28859
29186
|
return createHash("sha256").update(normalized).digest("hex").slice(0, 32);
|
|
28860
29187
|
}
|
|
28861
29188
|
function fallbackRepoIdFromPath(absPath) {
|
|
28862
|
-
return createHash("sha256").update(
|
|
29189
|
+
return createHash("sha256").update(path10.resolve(absPath)).digest("hex").slice(0, 32);
|
|
28863
29190
|
}
|
|
28864
29191
|
async function resolveBridgeQueueBindFields(options) {
|
|
28865
29192
|
const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
|
|
28866
|
-
const cwdAbs = worktreePaths.length > 0 ?
|
|
29193
|
+
const cwdAbs = worktreePaths.length > 0 ? path10.resolve(worktreePaths[0]) : path10.resolve(effectiveCwd);
|
|
28867
29194
|
if (!primaryRepoRoots.length) {
|
|
28868
|
-
log2("[Bridge service]
|
|
29195
|
+
log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
|
|
28869
29196
|
return null;
|
|
28870
29197
|
}
|
|
28871
29198
|
let primaryRoot = primaryRepoRoots[0];
|
|
@@ -28885,138 +29212,32 @@ async function resolveBridgeQueueBindFields(options) {
|
|
|
28885
29212
|
return { canonicalQueueKey, repoId, cwdAbs };
|
|
28886
29213
|
}
|
|
28887
29214
|
|
|
28888
|
-
// src/
|
|
28889
|
-
|
|
28890
|
-
|
|
28891
|
-
import { execFile as execFile2 } from "node:child_process";
|
|
28892
|
-
import { promisify as promisify2 } from "node:util";
|
|
28893
|
-
var execFileAsync2 = promisify2(execFile2);
|
|
28894
|
-
function snapshotsDirForCwd(agentCwd) {
|
|
28895
|
-
return path9.join(agentCwd, ".buildautomaton", "snapshots");
|
|
28896
|
-
}
|
|
28897
|
-
async function gitStashCreate2(repoRoot, log2) {
|
|
28898
|
-
try {
|
|
28899
|
-
const { stdout } = await execFileAsync2("git", ["stash", "create"], {
|
|
28900
|
-
cwd: repoRoot,
|
|
28901
|
-
maxBuffer: 10 * 1024 * 1024
|
|
28902
|
-
});
|
|
28903
|
-
return stdout.trim();
|
|
28904
|
-
} catch (e) {
|
|
28905
|
-
log2(`[snapshot] git stash create failed in ${repoRoot}: ${e instanceof Error ? e.message : String(e)}`);
|
|
28906
|
-
return "";
|
|
28907
|
-
}
|
|
28908
|
-
}
|
|
28909
|
-
async function gitRun(repoRoot, args, log2, label) {
|
|
28910
|
-
try {
|
|
28911
|
-
await execFileAsync2("git", args, { cwd: repoRoot, maxBuffer: 10 * 1024 * 1024 });
|
|
28912
|
-
return { ok: true };
|
|
28913
|
-
} catch (e) {
|
|
28914
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
28915
|
-
log2(`[snapshot] git ${label} failed in ${repoRoot}: ${msg}`);
|
|
28916
|
-
return { ok: false, error: msg };
|
|
28917
|
-
}
|
|
28918
|
-
}
|
|
28919
|
-
async function resolveSnapshotRepoRoots(options) {
|
|
28920
|
-
const { worktreePaths, fallbackCwd, log: log2 } = options;
|
|
28921
|
-
if (worktreePaths?.length) {
|
|
28922
|
-
const uniq = [...new Set(worktreePaths.map((p) => path9.resolve(p)))];
|
|
28923
|
-
return uniq;
|
|
28924
|
-
}
|
|
29215
|
+
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
29216
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
29217
|
+
async function readGitBranch(cwd) {
|
|
28925
29218
|
try {
|
|
28926
|
-
const
|
|
28927
|
-
|
|
28928
|
-
|
|
28929
|
-
|
|
28930
|
-
return
|
|
29219
|
+
const { stdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
|
|
29220
|
+
const b = stdout.trim();
|
|
29221
|
+
return b || null;
|
|
29222
|
+
} catch {
|
|
29223
|
+
return null;
|
|
28931
29224
|
}
|
|
28932
29225
|
}
|
|
28933
|
-
|
|
28934
|
-
const {
|
|
28935
|
-
|
|
28936
|
-
|
|
28937
|
-
|
|
28938
|
-
|
|
28939
|
-
|
|
28940
|
-
|
|
28941
|
-
|
|
28942
|
-
}
|
|
28943
|
-
const dir = snapshotsDirForCwd(agentCwd);
|
|
28944
|
-
try {
|
|
28945
|
-
fs4.mkdirSync(dir, { recursive: true });
|
|
28946
|
-
} catch (e) {
|
|
28947
|
-
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
28948
|
-
}
|
|
28949
|
-
const payload = {
|
|
28950
|
-
runId,
|
|
28951
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28952
|
-
repos
|
|
28953
|
-
};
|
|
28954
|
-
const filePath = path9.join(dir, `${runId}.json`);
|
|
28955
|
-
try {
|
|
28956
|
-
fs4.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
28957
|
-
} catch (e) {
|
|
28958
|
-
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
28959
|
-
}
|
|
28960
|
-
log2(`[snapshot] Saved pre-turn snapshot ${runId.slice(0, 8)}\u2026 (${repos.length} repo(s)) \u2192 ${filePath}`);
|
|
28961
|
-
return { ok: true, filePath, repos };
|
|
28962
|
-
}
|
|
28963
|
-
async function applyPreTurnSnapshot(filePath, log2) {
|
|
28964
|
-
let data;
|
|
28965
|
-
try {
|
|
28966
|
-
const raw = fs4.readFileSync(filePath, "utf8");
|
|
28967
|
-
data = JSON.parse(raw);
|
|
28968
|
-
} catch (e) {
|
|
28969
|
-
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
28970
|
-
}
|
|
28971
|
-
if (!Array.isArray(data.repos)) {
|
|
28972
|
-
return { ok: false, error: "Invalid snapshot file" };
|
|
28973
|
-
}
|
|
28974
|
-
for (const r of data.repos) {
|
|
28975
|
-
if (!r.path) continue;
|
|
28976
|
-
const reset = await gitRun(r.path, ["reset", "--hard", "HEAD"], log2, "reset --hard");
|
|
28977
|
-
if (!reset.ok) return reset;
|
|
28978
|
-
const clean = await gitRun(r.path, ["clean", "-fd"], log2, "clean -fd");
|
|
28979
|
-
if (!clean.ok) return clean;
|
|
28980
|
-
if (r.stashSha) {
|
|
28981
|
-
const ap = await gitRun(r.path, ["stash", "apply", r.stashSha], log2, "stash apply");
|
|
28982
|
-
if (!ap.ok) return ap;
|
|
28983
|
-
}
|
|
28984
|
-
}
|
|
28985
|
-
log2(`[snapshot] Restored pre-turn state for ${data.runId.slice(0, 8)}\u2026`);
|
|
28986
|
-
return { ok: true };
|
|
28987
|
-
}
|
|
28988
|
-
function snapshotFilePath(agentCwd, runId) {
|
|
28989
|
-
return path9.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
|
|
28990
|
-
}
|
|
28991
|
-
|
|
28992
|
-
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
28993
|
-
var execFileAsync3 = promisify3(execFile3);
|
|
28994
|
-
async function readGitBranch(cwd3) {
|
|
28995
|
-
try {
|
|
28996
|
-
const { stdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: cwd3, maxBuffer: 64 * 1024 });
|
|
28997
|
-
const b = stdout.trim();
|
|
28998
|
-
return b || null;
|
|
28999
|
-
} catch {
|
|
29000
|
-
return null;
|
|
29001
|
-
}
|
|
29002
|
-
}
|
|
29003
|
-
function handleBridgePrompt(msg, deps) {
|
|
29004
|
-
const { getWs, log: log2, acpManager, sessionWorktreeManager } = deps;
|
|
29005
|
-
const rawPrompt = msg.prompt;
|
|
29006
|
-
const promptText = typeof rawPrompt === "string" ? rawPrompt : rawPrompt != null ? String(rawPrompt) : "";
|
|
29007
|
-
if (!promptText.trim()) {
|
|
29008
|
-
log2(
|
|
29009
|
-
`[Bridge service] prompt ignored: empty or missing prompt field (sessionId=${typeof msg.sessionId === "string" ? msg.sessionId.slice(0, 8) : "\u2014"}\u2026 runId=${typeof msg.runId === "string" ? msg.runId.slice(0, 8) : "\u2014"}\u2026)`
|
|
29010
|
-
);
|
|
29011
|
-
return;
|
|
29226
|
+
function handleBridgePrompt(msg, deps) {
|
|
29227
|
+
const { getWs, log: log2, acpManager, sessionWorktreeManager } = deps;
|
|
29228
|
+
const rawPrompt = msg.prompt;
|
|
29229
|
+
const promptText = typeof rawPrompt === "string" ? rawPrompt : rawPrompt != null ? String(rawPrompt) : "";
|
|
29230
|
+
if (!promptText.trim()) {
|
|
29231
|
+
log2(
|
|
29232
|
+
`[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).`
|
|
29233
|
+
);
|
|
29234
|
+
return;
|
|
29012
29235
|
}
|
|
29013
29236
|
const sessionId = msg.sessionId;
|
|
29014
29237
|
const isNewSession = msg.isNewSession === true;
|
|
29015
29238
|
const sessionWorktreesEnabled = msg.sessionWorktreesEnabled === true;
|
|
29016
29239
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
29017
29240
|
const runId = typeof msg.runId === "string" ? msg.runId : void 0;
|
|
29018
|
-
const sessionGitQueueStart = msg.sessionGitQueueStart === true;
|
|
29019
|
-
const collectSessionDiffAfterTurn = msg.collectSessionDiffAfterTurn === true;
|
|
29020
29241
|
const sendResult = (result) => {
|
|
29021
29242
|
const s = getWs();
|
|
29022
29243
|
if (s) sendWsMessage(s, result);
|
|
@@ -29024,7 +29245,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
29024
29245
|
const sendSessionUpdate = (payload) => {
|
|
29025
29246
|
const s = getWs();
|
|
29026
29247
|
if (!s) {
|
|
29027
|
-
log2("[Bridge service]
|
|
29248
|
+
log2("[Bridge service] Session update not sent: not connected to the bridge.");
|
|
29028
29249
|
return;
|
|
29029
29250
|
}
|
|
29030
29251
|
const p = payload;
|
|
@@ -29032,7 +29253,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
29032
29253
|
};
|
|
29033
29254
|
async function preambleAndPrompt(resolvedCwd) {
|
|
29034
29255
|
const s = getWs();
|
|
29035
|
-
const effectiveCwd =
|
|
29256
|
+
const effectiveCwd = path11.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
|
|
29036
29257
|
const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
|
|
29037
29258
|
const repoRoots = await resolveSnapshotRepoRoots({
|
|
29038
29259
|
worktreePaths,
|
|
@@ -29065,9 +29286,6 @@ function handleBridgePrompt(msg, deps) {
|
|
|
29065
29286
|
agentUsesWorktree: sessionWorktreeManager.usesWorktreeSession(sessionId)
|
|
29066
29287
|
});
|
|
29067
29288
|
}
|
|
29068
|
-
if (sessionGitQueueStart && sessionId && repoRoots.length > 0) {
|
|
29069
|
-
await captureSessionGitBoundary({ sessionId, repoRoots, log: log2 });
|
|
29070
|
-
}
|
|
29071
29289
|
if (s && sessionId && runId) {
|
|
29072
29290
|
const cap = repoRoots.length > 0 ? await capturePreTurnSnapshot({ runId, repoRoots, agentCwd: effectiveCwd, log: log2 }) : { ok: false, error: "No git repos" };
|
|
29073
29291
|
sendWsMessage(s, {
|
|
@@ -29086,12 +29304,11 @@ function handleBridgePrompt(msg, deps) {
|
|
|
29086
29304
|
agentType,
|
|
29087
29305
|
cwd: effectiveCwd,
|
|
29088
29306
|
sendResult,
|
|
29089
|
-
sendSessionUpdate
|
|
29090
|
-
collectSessionDiffAfterTurn
|
|
29307
|
+
sendSessionUpdate
|
|
29091
29308
|
});
|
|
29092
29309
|
}
|
|
29093
|
-
void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionWorktreesEnabled }).then((
|
|
29094
|
-
log2(`[
|
|
29310
|
+
void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionWorktreesEnabled }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
|
|
29311
|
+
log2(`[Agent] Worktree resolve failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
29095
29312
|
void preambleAndPrompt(void 0);
|
|
29096
29313
|
});
|
|
29097
29314
|
}
|
|
@@ -29108,7 +29325,7 @@ function handleBridgeCancelRun(msg, { log: log2, acpManager }) {
|
|
|
29108
29325
|
void acpManager.cancelRun(runId).then((sent) => {
|
|
29109
29326
|
if (!sent) {
|
|
29110
29327
|
log2(
|
|
29111
|
-
`[
|
|
29328
|
+
`[Agent] Cancel ignored for run ${runId.slice(0, 8)}\u2026 (no active run or cancel not available).`
|
|
29112
29329
|
);
|
|
29113
29330
|
}
|
|
29114
29331
|
});
|
|
@@ -29136,7 +29353,7 @@ function handleSkillCall(msg, socket, log2) {
|
|
|
29136
29353
|
sendWsMessage(socket, { type: "skill_result", id: msg.id, result });
|
|
29137
29354
|
}).catch((err) => {
|
|
29138
29355
|
sendWsMessage(socket, { type: "skill_result", id: msg.id, error: String(err) });
|
|
29139
|
-
log2(`[Bridge service]
|
|
29356
|
+
log2(`[Bridge service] Skill invocation failed (${msg.skillId}/${msg.operationId}): ${err}`);
|
|
29140
29357
|
});
|
|
29141
29358
|
}
|
|
29142
29359
|
|
|
@@ -29153,36 +29370,35 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
29153
29370
|
};
|
|
29154
29371
|
|
|
29155
29372
|
// src/files/list-dir.ts
|
|
29156
|
-
import
|
|
29157
|
-
import
|
|
29373
|
+
import fs6 from "node:fs";
|
|
29374
|
+
import path13 from "node:path";
|
|
29158
29375
|
|
|
29159
29376
|
// src/files/ensure-under-cwd.ts
|
|
29160
|
-
import
|
|
29161
|
-
function ensureUnderCwd(relativePath,
|
|
29162
|
-
const normalized =
|
|
29163
|
-
const resolved =
|
|
29164
|
-
if (!resolved.startsWith(
|
|
29377
|
+
import path12 from "node:path";
|
|
29378
|
+
function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
|
|
29379
|
+
const normalized = path12.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
29380
|
+
const resolved = path12.resolve(cwd, normalized);
|
|
29381
|
+
if (!resolved.startsWith(cwd + path12.sep) && resolved !== cwd) {
|
|
29165
29382
|
return null;
|
|
29166
29383
|
}
|
|
29167
29384
|
return resolved;
|
|
29168
29385
|
}
|
|
29169
29386
|
|
|
29170
29387
|
// src/files/list-dir.ts
|
|
29171
|
-
var cwd = process.cwd();
|
|
29172
29388
|
function listDir(relativePath) {
|
|
29173
|
-
const resolved = ensureUnderCwd(relativePath || ".",
|
|
29389
|
+
const resolved = ensureUnderCwd(relativePath || ".", getBridgeWorkspaceDirectory());
|
|
29174
29390
|
if (!resolved) {
|
|
29175
29391
|
return { error: "Path is outside working directory" };
|
|
29176
29392
|
}
|
|
29177
29393
|
try {
|
|
29178
|
-
const names =
|
|
29394
|
+
const names = fs6.readdirSync(resolved, { withFileTypes: true });
|
|
29179
29395
|
const entries = names.filter((d) => !d.name.startsWith(".")).map((d) => {
|
|
29180
|
-
const entryPath =
|
|
29181
|
-
const fullPath =
|
|
29396
|
+
const entryPath = path13.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
29397
|
+
const fullPath = path13.join(resolved, d.name);
|
|
29182
29398
|
let isDir = d.isDirectory();
|
|
29183
29399
|
if (d.isSymbolicLink()) {
|
|
29184
29400
|
try {
|
|
29185
|
-
const targetStat =
|
|
29401
|
+
const targetStat = fs6.statSync(fullPath);
|
|
29186
29402
|
isDir = targetStat.isDirectory();
|
|
29187
29403
|
} catch {
|
|
29188
29404
|
isDir = false;
|
|
@@ -29206,26 +29422,25 @@ function listDir(relativePath) {
|
|
|
29206
29422
|
}
|
|
29207
29423
|
|
|
29208
29424
|
// src/files/read-file.ts
|
|
29209
|
-
import
|
|
29425
|
+
import fs7 from "node:fs";
|
|
29210
29426
|
import { StringDecoder } from "node:string_decoder";
|
|
29211
|
-
var cwd2 = process.cwd();
|
|
29212
29427
|
function resolveFilePath(relativePath) {
|
|
29213
|
-
const resolved = ensureUnderCwd(relativePath,
|
|
29428
|
+
const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
|
|
29214
29429
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
29215
29430
|
let real;
|
|
29216
29431
|
try {
|
|
29217
|
-
real =
|
|
29432
|
+
real = fs7.realpathSync(resolved);
|
|
29218
29433
|
} catch {
|
|
29219
29434
|
real = resolved;
|
|
29220
29435
|
}
|
|
29221
|
-
const
|
|
29222
|
-
if (!
|
|
29436
|
+
const stat = fs7.statSync(real);
|
|
29437
|
+
if (!stat.isFile()) return { error: "Not a file" };
|
|
29223
29438
|
return real;
|
|
29224
29439
|
}
|
|
29225
29440
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
29226
29441
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
29227
|
-
const fileSize =
|
|
29228
|
-
const fd =
|
|
29442
|
+
const fileSize = fs7.statSync(filePath).size;
|
|
29443
|
+
const fd = fs7.openSync(filePath, "r");
|
|
29229
29444
|
const bufSize = 64 * 1024;
|
|
29230
29445
|
const buf = Buffer.alloc(bufSize);
|
|
29231
29446
|
const decoder = new StringDecoder("utf8");
|
|
@@ -29238,7 +29453,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
29238
29453
|
let line0Accum = "";
|
|
29239
29454
|
try {
|
|
29240
29455
|
let bytesRead;
|
|
29241
|
-
while (!done && (bytesRead =
|
|
29456
|
+
while (!done && (bytesRead = fs7.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
29242
29457
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
29243
29458
|
partial2 = "";
|
|
29244
29459
|
let lineStart = 0;
|
|
@@ -29373,7 +29588,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
29373
29588
|
}
|
|
29374
29589
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
29375
29590
|
} finally {
|
|
29376
|
-
|
|
29591
|
+
fs7.closeSync(fd);
|
|
29377
29592
|
}
|
|
29378
29593
|
}
|
|
29379
29594
|
function readFile(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
@@ -29384,26 +29599,26 @@ function readFile(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
29384
29599
|
if (hasRange) {
|
|
29385
29600
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
29386
29601
|
}
|
|
29387
|
-
const
|
|
29388
|
-
const raw =
|
|
29602
|
+
const stat = fs7.statSync(result);
|
|
29603
|
+
const raw = fs7.readFileSync(result, "utf8");
|
|
29389
29604
|
const lines = raw.split(/\r?\n/);
|
|
29390
|
-
return { content: raw, totalLines: lines.length, size:
|
|
29605
|
+
return { content: raw, totalLines: lines.length, size: stat.size };
|
|
29391
29606
|
} catch (err) {
|
|
29392
29607
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
29393
29608
|
}
|
|
29394
29609
|
}
|
|
29395
29610
|
|
|
29396
29611
|
// src/files/file-index.ts
|
|
29397
|
-
import
|
|
29398
|
-
import
|
|
29612
|
+
import fs8 from "node:fs";
|
|
29613
|
+
import path14 from "node:path";
|
|
29399
29614
|
import os2 from "node:os";
|
|
29400
29615
|
import crypto2 from "node:crypto";
|
|
29401
|
-
var INDEX_DIR =
|
|
29616
|
+
var INDEX_DIR = path14.join(os2.homedir(), ".buildautomaton");
|
|
29402
29617
|
var HASH_LEN = 16;
|
|
29403
29618
|
var INDEX_VERSION = 2;
|
|
29404
|
-
function getIndexPath(
|
|
29405
|
-
const hash = crypto2.createHash("sha256").update(
|
|
29406
|
-
return
|
|
29619
|
+
function getIndexPath(cwd) {
|
|
29620
|
+
const hash = crypto2.createHash("sha256").update(cwd).digest("hex").slice(0, HASH_LEN);
|
|
29621
|
+
return path14.join(INDEX_DIR, `.file-index-${hash}.json`);
|
|
29407
29622
|
}
|
|
29408
29623
|
function getTrigrams(s) {
|
|
29409
29624
|
const lower = s.toLowerCase();
|
|
@@ -29441,29 +29656,29 @@ function binarySearch(arr, x) {
|
|
|
29441
29656
|
function walkDir(dir, baseDir, out) {
|
|
29442
29657
|
let names;
|
|
29443
29658
|
try {
|
|
29444
|
-
names =
|
|
29659
|
+
names = fs8.readdirSync(dir);
|
|
29445
29660
|
} catch {
|
|
29446
29661
|
return;
|
|
29447
29662
|
}
|
|
29448
29663
|
for (const name of names) {
|
|
29449
29664
|
if (name.startsWith(".")) continue;
|
|
29450
|
-
const full =
|
|
29451
|
-
let
|
|
29665
|
+
const full = path14.join(dir, name);
|
|
29666
|
+
let stat;
|
|
29452
29667
|
try {
|
|
29453
|
-
|
|
29668
|
+
stat = fs8.statSync(full);
|
|
29454
29669
|
} catch {
|
|
29455
29670
|
continue;
|
|
29456
29671
|
}
|
|
29457
|
-
const
|
|
29458
|
-
if (
|
|
29672
|
+
const relative4 = path14.relative(baseDir, full).replace(/\\/g, "/");
|
|
29673
|
+
if (stat.isDirectory()) {
|
|
29459
29674
|
walkDir(full, baseDir, out);
|
|
29460
|
-
} else if (
|
|
29461
|
-
out.push(
|
|
29675
|
+
} else if (stat.isFile()) {
|
|
29676
|
+
out.push(relative4);
|
|
29462
29677
|
}
|
|
29463
29678
|
}
|
|
29464
29679
|
}
|
|
29465
|
-
function buildFileIndex(
|
|
29466
|
-
const resolved =
|
|
29680
|
+
function buildFileIndex(cwd) {
|
|
29681
|
+
const resolved = path14.resolve(cwd);
|
|
29467
29682
|
const paths = [];
|
|
29468
29683
|
walkDir(resolved, resolved, paths);
|
|
29469
29684
|
paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
@@ -29481,18 +29696,18 @@ function buildFileIndex(cwd3) {
|
|
|
29481
29696
|
const data = { version: INDEX_VERSION, paths, trigramIndex };
|
|
29482
29697
|
const indexPath = getIndexPath(resolved);
|
|
29483
29698
|
try {
|
|
29484
|
-
if (!
|
|
29485
|
-
|
|
29699
|
+
if (!fs8.existsSync(INDEX_DIR)) fs8.mkdirSync(INDEX_DIR, { recursive: true });
|
|
29700
|
+
fs8.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
29486
29701
|
} catch (e) {
|
|
29487
29702
|
console.error("[file-index] Failed to write index:", e);
|
|
29488
29703
|
}
|
|
29489
29704
|
return data;
|
|
29490
29705
|
}
|
|
29491
|
-
function loadFileIndex(
|
|
29492
|
-
const resolved =
|
|
29706
|
+
function loadFileIndex(cwd) {
|
|
29707
|
+
const resolved = path14.resolve(cwd);
|
|
29493
29708
|
const indexPath = getIndexPath(resolved);
|
|
29494
29709
|
try {
|
|
29495
|
-
const raw =
|
|
29710
|
+
const raw = fs8.readFileSync(indexPath, "utf8");
|
|
29496
29711
|
const parsed = JSON.parse(raw);
|
|
29497
29712
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
29498
29713
|
const obj = parsed;
|
|
@@ -29509,8 +29724,8 @@ function loadFileIndex(cwd3) {
|
|
|
29509
29724
|
return null;
|
|
29510
29725
|
}
|
|
29511
29726
|
}
|
|
29512
|
-
function ensureFileIndex(
|
|
29513
|
-
const resolved =
|
|
29727
|
+
function ensureFileIndex(cwd) {
|
|
29728
|
+
const resolved = path14.resolve(cwd);
|
|
29514
29729
|
const cached2 = loadFileIndex(resolved);
|
|
29515
29730
|
if (cached2 !== null) return { data: cached2, fromCache: true };
|
|
29516
29731
|
const data = buildFileIndex(resolved);
|
|
@@ -29548,8 +29763,8 @@ function searchFileIndex(index, query, limit = 100) {
|
|
|
29548
29763
|
var SEARCH_LIMIT = 100;
|
|
29549
29764
|
function handleFileBrowserSearch(msg, socket) {
|
|
29550
29765
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
29551
|
-
const
|
|
29552
|
-
const index = loadFileIndex(
|
|
29766
|
+
const cwd = getBridgeWorkspaceDirectory();
|
|
29767
|
+
const index = loadFileIndex(cwd);
|
|
29553
29768
|
if (index === null) {
|
|
29554
29769
|
sendWsMessage(socket, {
|
|
29555
29770
|
type: "file_browser_search_response",
|
|
@@ -29570,7 +29785,7 @@ function handleFileBrowserSearch(msg, socket) {
|
|
|
29570
29785
|
function triggerFileIndexBuild() {
|
|
29571
29786
|
setImmediate(() => {
|
|
29572
29787
|
try {
|
|
29573
|
-
ensureFileIndex(
|
|
29788
|
+
ensureFileIndex(getBridgeWorkspaceDirectory());
|
|
29574
29789
|
} catch (e) {
|
|
29575
29790
|
console.error("[file-index] Background build failed:", e);
|
|
29576
29791
|
}
|
|
@@ -29631,30 +29846,30 @@ function handleFileBrowserSearchMessage(msg, { getWs }) {
|
|
|
29631
29846
|
}
|
|
29632
29847
|
|
|
29633
29848
|
// src/skills/discover-local-agent-skills.ts
|
|
29634
|
-
import
|
|
29635
|
-
import
|
|
29849
|
+
import fs9 from "node:fs";
|
|
29850
|
+
import path15 from "node:path";
|
|
29636
29851
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
29637
|
-
function discoverLocalSkills(
|
|
29852
|
+
function discoverLocalSkills(cwd) {
|
|
29638
29853
|
const out = [];
|
|
29639
29854
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
29640
29855
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
29641
|
-
const base =
|
|
29642
|
-
if (!
|
|
29856
|
+
const base = path15.join(cwd, rel);
|
|
29857
|
+
if (!fs9.existsSync(base) || !fs9.statSync(base).isDirectory()) continue;
|
|
29643
29858
|
let entries = [];
|
|
29644
29859
|
try {
|
|
29645
|
-
entries =
|
|
29860
|
+
entries = fs9.readdirSync(base);
|
|
29646
29861
|
} catch {
|
|
29647
29862
|
continue;
|
|
29648
29863
|
}
|
|
29649
29864
|
for (const name of entries) {
|
|
29650
|
-
const dir =
|
|
29865
|
+
const dir = path15.join(base, name);
|
|
29651
29866
|
try {
|
|
29652
|
-
if (!
|
|
29867
|
+
if (!fs9.statSync(dir).isDirectory()) continue;
|
|
29653
29868
|
} catch {
|
|
29654
29869
|
continue;
|
|
29655
29870
|
}
|
|
29656
|
-
const skillMd =
|
|
29657
|
-
if (!
|
|
29871
|
+
const skillMd = path15.join(dir, "SKILL.md");
|
|
29872
|
+
if (!fs9.existsSync(skillMd)) continue;
|
|
29658
29873
|
const key = `${rel}/${name}`;
|
|
29659
29874
|
if (seenKeys.has(key)) continue;
|
|
29660
29875
|
seenKeys.add(key);
|
|
@@ -29663,26 +29878,26 @@ function discoverLocalSkills(cwd3) {
|
|
|
29663
29878
|
}
|
|
29664
29879
|
return out;
|
|
29665
29880
|
}
|
|
29666
|
-
function discoverSkillLayoutRoots(
|
|
29881
|
+
function discoverSkillLayoutRoots(cwd) {
|
|
29667
29882
|
const roots = [];
|
|
29668
29883
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
29669
|
-
const base =
|
|
29670
|
-
if (!
|
|
29884
|
+
const base = path15.join(cwd, rel);
|
|
29885
|
+
if (!fs9.existsSync(base) || !fs9.statSync(base).isDirectory()) continue;
|
|
29671
29886
|
let entries = [];
|
|
29672
29887
|
try {
|
|
29673
|
-
entries =
|
|
29888
|
+
entries = fs9.readdirSync(base);
|
|
29674
29889
|
} catch {
|
|
29675
29890
|
continue;
|
|
29676
29891
|
}
|
|
29677
29892
|
const skills2 = [];
|
|
29678
29893
|
for (const name of entries) {
|
|
29679
|
-
const dir =
|
|
29894
|
+
const dir = path15.join(base, name);
|
|
29680
29895
|
try {
|
|
29681
|
-
if (!
|
|
29896
|
+
if (!fs9.statSync(dir).isDirectory()) continue;
|
|
29682
29897
|
} catch {
|
|
29683
29898
|
continue;
|
|
29684
29899
|
}
|
|
29685
|
-
if (!
|
|
29900
|
+
if (!fs9.existsSync(path15.join(dir, "SKILL.md"))) continue;
|
|
29686
29901
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
29687
29902
|
skills2.push({ name, relPath });
|
|
29688
29903
|
}
|
|
@@ -29697,14 +29912,14 @@ function discoverSkillLayoutRoots(cwd3) {
|
|
|
29697
29912
|
function handleSkillLayoutRequest(msg, deps) {
|
|
29698
29913
|
const socket = deps.getWs();
|
|
29699
29914
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
29700
|
-
const roots = discoverSkillLayoutRoots(
|
|
29915
|
+
const roots = discoverSkillLayoutRoots(getBridgeWorkspaceDirectory());
|
|
29701
29916
|
socket?.send(JSON.stringify({ type: "skill_layout_response", id, roots }));
|
|
29702
29917
|
}
|
|
29703
29918
|
|
|
29704
29919
|
// src/skills/install-remote-skills.ts
|
|
29705
|
-
import
|
|
29706
|
-
import
|
|
29707
|
-
function installRemoteSkills(
|
|
29920
|
+
import fs10 from "node:fs";
|
|
29921
|
+
import path16 from "node:path";
|
|
29922
|
+
function installRemoteSkills(cwd, targetDir, items) {
|
|
29708
29923
|
const installed = [];
|
|
29709
29924
|
if (!Array.isArray(items)) {
|
|
29710
29925
|
return { success: false, error: "Invalid items" };
|
|
@@ -29714,15 +29929,15 @@ function installRemoteSkills(cwd3, targetDir, items) {
|
|
|
29714
29929
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
29715
29930
|
continue;
|
|
29716
29931
|
}
|
|
29717
|
-
const skillDir =
|
|
29932
|
+
const skillDir = path16.join(cwd, targetDir, item.skillName);
|
|
29718
29933
|
for (const f of item.files) {
|
|
29719
29934
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
29720
|
-
const dest =
|
|
29721
|
-
|
|
29935
|
+
const dest = path16.join(skillDir, f.path);
|
|
29936
|
+
fs10.mkdirSync(path16.dirname(dest), { recursive: true });
|
|
29722
29937
|
if (f.text !== void 0) {
|
|
29723
|
-
|
|
29938
|
+
fs10.writeFileSync(dest, f.text, "utf8");
|
|
29724
29939
|
} else if (f.base64) {
|
|
29725
|
-
|
|
29940
|
+
fs10.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
29726
29941
|
}
|
|
29727
29942
|
}
|
|
29728
29943
|
installed.push({
|
|
@@ -29743,11 +29958,11 @@ var handleInstallSkillsMessage = (msg, deps) => {
|
|
|
29743
29958
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
29744
29959
|
const targetDir = typeof msg.targetDir === "string" && msg.targetDir.trim() ? msg.targetDir.trim() : ".agents/skills";
|
|
29745
29960
|
const rawItems = msg.items;
|
|
29746
|
-
const
|
|
29747
|
-
const result = installRemoteSkills(
|
|
29961
|
+
const cwd = getBridgeWorkspaceDirectory();
|
|
29962
|
+
const result = installRemoteSkills(cwd, targetDir, rawItems);
|
|
29748
29963
|
if (!result.success) {
|
|
29749
29964
|
const err = result.error ?? "Invalid items";
|
|
29750
|
-
deps.log(`[Bridge service]
|
|
29965
|
+
deps.log(`[Bridge service] Install skills failed: ${err}`);
|
|
29751
29966
|
socket?.send(JSON.stringify({ type: "install_skills_result", id, success: false, error: err }));
|
|
29752
29967
|
return;
|
|
29753
29968
|
}
|
|
@@ -29816,8 +30031,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
29816
30031
|
};
|
|
29817
30032
|
|
|
29818
30033
|
// src/bridge/routing/handlers/revert-turn-snapshot.ts
|
|
29819
|
-
import * as
|
|
29820
|
-
import * as path16 from "node:path";
|
|
30034
|
+
import * as fs11 from "node:fs";
|
|
29821
30035
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
29822
30036
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
29823
30037
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -29827,9 +30041,9 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
29827
30041
|
void (async () => {
|
|
29828
30042
|
const s = getWs();
|
|
29829
30043
|
if (!s) return;
|
|
29830
|
-
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ??
|
|
30044
|
+
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
|
|
29831
30045
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
29832
|
-
if (!
|
|
30046
|
+
if (!fs11.existsSync(file2)) {
|
|
29833
30047
|
sendWsMessage(s, {
|
|
29834
30048
|
type: "revert_turn_snapshot_result",
|
|
29835
30049
|
id,
|
|
@@ -29956,7 +30170,7 @@ import * as path20 from "node:path";
|
|
|
29956
30170
|
import os4 from "node:os";
|
|
29957
30171
|
|
|
29958
30172
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
29959
|
-
import * as
|
|
30173
|
+
import * as fs13 from "node:fs";
|
|
29960
30174
|
import * as path18 from "node:path";
|
|
29961
30175
|
|
|
29962
30176
|
// src/git/worktree-add.ts
|
|
@@ -29966,7 +30180,7 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
29966
30180
|
}
|
|
29967
30181
|
|
|
29968
30182
|
// src/worktrees/worktree-layout-file.ts
|
|
29969
|
-
import * as
|
|
30183
|
+
import * as fs12 from "node:fs";
|
|
29970
30184
|
import * as path17 from "node:path";
|
|
29971
30185
|
import os3 from "node:os";
|
|
29972
30186
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
@@ -29983,8 +30197,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
29983
30197
|
function loadWorktreeLayout() {
|
|
29984
30198
|
try {
|
|
29985
30199
|
const p = defaultWorktreeLayoutPath();
|
|
29986
|
-
if (!
|
|
29987
|
-
const raw = JSON.parse(
|
|
30200
|
+
if (!fs12.existsSync(p)) return { launcherCwds: [] };
|
|
30201
|
+
const raw = JSON.parse(fs12.readFileSync(p, "utf8"));
|
|
29988
30202
|
return normalizeLoadedLayout(raw);
|
|
29989
30203
|
} catch {
|
|
29990
30204
|
return { launcherCwds: [] };
|
|
@@ -29993,8 +30207,8 @@ function loadWorktreeLayout() {
|
|
|
29993
30207
|
function saveWorktreeLayout(layout) {
|
|
29994
30208
|
try {
|
|
29995
30209
|
const dir = path17.dirname(defaultWorktreeLayoutPath());
|
|
29996
|
-
|
|
29997
|
-
|
|
30210
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
30211
|
+
fs12.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
29998
30212
|
} catch {
|
|
29999
30213
|
}
|
|
30000
30214
|
}
|
|
@@ -30026,25 +30240,25 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
30026
30240
|
const agentMirrorRoot = path18.join(rootAbs, cwdKey);
|
|
30027
30241
|
const repos = await discoverGitReposUnderRoot(launcherResolved);
|
|
30028
30242
|
if (repos.length === 0) {
|
|
30029
|
-
log2("[worktrees] No
|
|
30243
|
+
log2("[worktrees] No Git repositories under launcher working directory; skipping worktree creation.");
|
|
30030
30244
|
return null;
|
|
30031
30245
|
}
|
|
30032
30246
|
const branch = `session-${sessionId}`;
|
|
30033
30247
|
const worktreePaths = [];
|
|
30034
|
-
|
|
30248
|
+
fs13.mkdirSync(agentMirrorRoot, { recursive: true });
|
|
30035
30249
|
for (const repo of repos) {
|
|
30036
30250
|
let rel = path18.relative(launcherResolved, repo.absolutePath);
|
|
30037
30251
|
if (rel.startsWith("..") || path18.isAbsolute(rel)) continue;
|
|
30038
30252
|
const relNorm = rel === "" ? "." : rel;
|
|
30039
30253
|
const wtPath = path18.join(agentMirrorRoot, relNorm, sessionId);
|
|
30040
|
-
|
|
30254
|
+
fs13.mkdirSync(path18.dirname(wtPath), { recursive: true });
|
|
30041
30255
|
try {
|
|
30042
30256
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
30043
|
-
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch})
|
|
30257
|
+
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
|
|
30044
30258
|
worktreePaths.push(wtPath);
|
|
30045
30259
|
} catch (e) {
|
|
30046
30260
|
log2(
|
|
30047
|
-
`[worktrees]
|
|
30261
|
+
`[worktrees] Worktree add failed for ${repo.absolutePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
30048
30262
|
);
|
|
30049
30263
|
}
|
|
30050
30264
|
}
|
|
@@ -30066,24 +30280,26 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
30066
30280
|
await gitRenameCurrentBranch(wt, safe);
|
|
30067
30281
|
log2(`[worktrees] Renamed branch in ${wt} \u2192 ${safe}`);
|
|
30068
30282
|
} catch (e) {
|
|
30069
|
-
log2(
|
|
30283
|
+
log2(
|
|
30284
|
+
`[worktrees] Branch rename failed in ${wt}: ${e instanceof Error ? e.message : String(e)}`
|
|
30285
|
+
);
|
|
30070
30286
|
}
|
|
30071
30287
|
}
|
|
30072
30288
|
}
|
|
30073
30289
|
|
|
30074
30290
|
// src/worktrees/remove-session-worktrees.ts
|
|
30075
|
-
import * as
|
|
30291
|
+
import * as fs16 from "node:fs";
|
|
30076
30292
|
|
|
30077
30293
|
// src/git/worktree-remove.ts
|
|
30078
|
-
import * as
|
|
30294
|
+
import * as fs15 from "node:fs";
|
|
30079
30295
|
|
|
30080
30296
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
30081
|
-
import * as
|
|
30297
|
+
import * as fs14 from "node:fs";
|
|
30082
30298
|
import * as path19 from "node:path";
|
|
30083
30299
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
30084
30300
|
const gitDirFile = path19.join(wt, ".git");
|
|
30085
|
-
if (!
|
|
30086
|
-
const first2 =
|
|
30301
|
+
if (!fs14.existsSync(gitDirFile) || !fs14.statSync(gitDirFile).isFile()) return "";
|
|
30302
|
+
const first2 = fs14.readFileSync(gitDirFile, "utf8").trim();
|
|
30087
30303
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
30088
30304
|
if (!m) return "";
|
|
30089
30305
|
const gitWorktreePath = path19.resolve(wt, m[1].trim());
|
|
@@ -30097,7 +30313,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
30097
30313
|
if (mainRepo) {
|
|
30098
30314
|
await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
30099
30315
|
} else {
|
|
30100
|
-
|
|
30316
|
+
fs15.rmSync(worktreePath, { recursive: true, force: true });
|
|
30101
30317
|
}
|
|
30102
30318
|
}
|
|
30103
30319
|
|
|
@@ -30108,9 +30324,9 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
30108
30324
|
await gitWorktreeRemoveForce(wt);
|
|
30109
30325
|
log2(`[worktrees] Removed worktree ${wt}`);
|
|
30110
30326
|
} catch (e) {
|
|
30111
|
-
log2(`[worktrees]
|
|
30327
|
+
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
30112
30328
|
try {
|
|
30113
|
-
|
|
30329
|
+
fs16.rmSync(wt, { recursive: true, force: true });
|
|
30114
30330
|
} catch {
|
|
30115
30331
|
}
|
|
30116
30332
|
}
|
|
@@ -30174,7 +30390,7 @@ var SessionWorktreeManager = class {
|
|
|
30174
30390
|
return this.bridgeWantsWorktrees;
|
|
30175
30391
|
}
|
|
30176
30392
|
/**
|
|
30177
|
-
* Returns cwd for the agent (mirror of launcher tree), or undefined to use
|
|
30393
|
+
* Returns cwd for the agent (mirror of launcher tree), or undefined to use the bridge workspace directory.
|
|
30178
30394
|
*/
|
|
30179
30395
|
async resolveCwdForPrompt(sessionId, opts) {
|
|
30180
30396
|
if (!sessionId || !this.effective() || !opts.sessionWorktreesEnabled) {
|
|
@@ -30187,7 +30403,7 @@ var SessionWorktreeManager = class {
|
|
|
30187
30403
|
}
|
|
30188
30404
|
const prep = await prepareNewSessionWorktrees({
|
|
30189
30405
|
rootAbs: this.rootAbs,
|
|
30190
|
-
launcherCwd:
|
|
30406
|
+
launcherCwd: getBridgeWorkspaceDirectory(),
|
|
30191
30407
|
sessionId,
|
|
30192
30408
|
layout: this.layout,
|
|
30193
30409
|
log: this.log
|
|
@@ -30227,7 +30443,7 @@ var SessionWorktreeManager = class {
|
|
|
30227
30443
|
}
|
|
30228
30444
|
async commitSession(params) {
|
|
30229
30445
|
const paths = this.sessionPaths.get(params.sessionId);
|
|
30230
|
-
const targets = paths?.length ? paths : [
|
|
30446
|
+
const targets = paths?.length ? paths : [getBridgeWorkspaceDirectory()];
|
|
30231
30447
|
return commitSessionWorktrees({
|
|
30232
30448
|
paths: targets,
|
|
30233
30449
|
branch: params.branch,
|
|
@@ -30268,1700 +30484,8 @@ async function refreshBridgeTokens(params) {
|
|
|
30268
30484
|
}
|
|
30269
30485
|
|
|
30270
30486
|
// src/files/watch-file-index.ts
|
|
30487
|
+
import { watch } from "node:fs";
|
|
30271
30488
|
import path21 from "node:path";
|
|
30272
|
-
|
|
30273
|
-
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
30274
|
-
import { stat as statcb } from "fs";
|
|
30275
|
-
import { stat as stat3, readdir as readdir2 } from "fs/promises";
|
|
30276
|
-
import { EventEmitter as EventEmitter2 } from "events";
|
|
30277
|
-
import * as sysPath2 from "path";
|
|
30278
|
-
|
|
30279
|
-
// ../../node_modules/.pnpm/readdirp@4.1.2/node_modules/readdirp/esm/index.js
|
|
30280
|
-
import { stat, lstat, readdir, realpath } from "node:fs/promises";
|
|
30281
|
-
import { Readable as Readable2 } from "node:stream";
|
|
30282
|
-
import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "node:path";
|
|
30283
|
-
var EntryTypes = {
|
|
30284
|
-
FILE_TYPE: "files",
|
|
30285
|
-
DIR_TYPE: "directories",
|
|
30286
|
-
FILE_DIR_TYPE: "files_directories",
|
|
30287
|
-
EVERYTHING_TYPE: "all"
|
|
30288
|
-
};
|
|
30289
|
-
var defaultOptions2 = {
|
|
30290
|
-
root: ".",
|
|
30291
|
-
fileFilter: (_entryInfo) => true,
|
|
30292
|
-
directoryFilter: (_entryInfo) => true,
|
|
30293
|
-
type: EntryTypes.FILE_TYPE,
|
|
30294
|
-
lstat: false,
|
|
30295
|
-
depth: 2147483648,
|
|
30296
|
-
alwaysStat: false,
|
|
30297
|
-
highWaterMark: 4096
|
|
30298
|
-
};
|
|
30299
|
-
Object.freeze(defaultOptions2);
|
|
30300
|
-
var RECURSIVE_ERROR_CODE = "READDIRP_RECURSIVE_ERROR";
|
|
30301
|
-
var NORMAL_FLOW_ERRORS = /* @__PURE__ */ new Set(["ENOENT", "EPERM", "EACCES", "ELOOP", RECURSIVE_ERROR_CODE]);
|
|
30302
|
-
var ALL_TYPES = [
|
|
30303
|
-
EntryTypes.DIR_TYPE,
|
|
30304
|
-
EntryTypes.EVERYTHING_TYPE,
|
|
30305
|
-
EntryTypes.FILE_DIR_TYPE,
|
|
30306
|
-
EntryTypes.FILE_TYPE
|
|
30307
|
-
];
|
|
30308
|
-
var DIR_TYPES = /* @__PURE__ */ new Set([
|
|
30309
|
-
EntryTypes.DIR_TYPE,
|
|
30310
|
-
EntryTypes.EVERYTHING_TYPE,
|
|
30311
|
-
EntryTypes.FILE_DIR_TYPE
|
|
30312
|
-
]);
|
|
30313
|
-
var FILE_TYPES = /* @__PURE__ */ new Set([
|
|
30314
|
-
EntryTypes.EVERYTHING_TYPE,
|
|
30315
|
-
EntryTypes.FILE_DIR_TYPE,
|
|
30316
|
-
EntryTypes.FILE_TYPE
|
|
30317
|
-
]);
|
|
30318
|
-
var isNormalFlowError = (error40) => NORMAL_FLOW_ERRORS.has(error40.code);
|
|
30319
|
-
var wantBigintFsStats = process.platform === "win32";
|
|
30320
|
-
var emptyFn = (_entryInfo) => true;
|
|
30321
|
-
var normalizeFilter = (filter) => {
|
|
30322
|
-
if (filter === void 0)
|
|
30323
|
-
return emptyFn;
|
|
30324
|
-
if (typeof filter === "function")
|
|
30325
|
-
return filter;
|
|
30326
|
-
if (typeof filter === "string") {
|
|
30327
|
-
const fl = filter.trim();
|
|
30328
|
-
return (entry) => entry.basename === fl;
|
|
30329
|
-
}
|
|
30330
|
-
if (Array.isArray(filter)) {
|
|
30331
|
-
const trItems = filter.map((item) => item.trim());
|
|
30332
|
-
return (entry) => trItems.some((f) => entry.basename === f);
|
|
30333
|
-
}
|
|
30334
|
-
return emptyFn;
|
|
30335
|
-
};
|
|
30336
|
-
var ReaddirpStream = class extends Readable2 {
|
|
30337
|
-
constructor(options = {}) {
|
|
30338
|
-
super({
|
|
30339
|
-
objectMode: true,
|
|
30340
|
-
autoDestroy: true,
|
|
30341
|
-
highWaterMark: options.highWaterMark
|
|
30342
|
-
});
|
|
30343
|
-
const opts = { ...defaultOptions2, ...options };
|
|
30344
|
-
const { root, type } = opts;
|
|
30345
|
-
this._fileFilter = normalizeFilter(opts.fileFilter);
|
|
30346
|
-
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
30347
|
-
const statMethod = opts.lstat ? lstat : stat;
|
|
30348
|
-
if (wantBigintFsStats) {
|
|
30349
|
-
this._stat = (path24) => statMethod(path24, { bigint: true });
|
|
30350
|
-
} else {
|
|
30351
|
-
this._stat = statMethod;
|
|
30352
|
-
}
|
|
30353
|
-
this._maxDepth = opts.depth ?? defaultOptions2.depth;
|
|
30354
|
-
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
30355
|
-
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
30356
|
-
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
30357
|
-
this._root = presolve(root);
|
|
30358
|
-
this._isDirent = !opts.alwaysStat;
|
|
30359
|
-
this._statsProp = this._isDirent ? "dirent" : "stats";
|
|
30360
|
-
this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
|
|
30361
|
-
this.parents = [this._exploreDir(root, 1)];
|
|
30362
|
-
this.reading = false;
|
|
30363
|
-
this.parent = void 0;
|
|
30364
|
-
}
|
|
30365
|
-
async _read(batch) {
|
|
30366
|
-
if (this.reading)
|
|
30367
|
-
return;
|
|
30368
|
-
this.reading = true;
|
|
30369
|
-
try {
|
|
30370
|
-
while (!this.destroyed && batch > 0) {
|
|
30371
|
-
const par = this.parent;
|
|
30372
|
-
const fil = par && par.files;
|
|
30373
|
-
if (fil && fil.length > 0) {
|
|
30374
|
-
const { path: path24, depth } = par;
|
|
30375
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path24));
|
|
30376
|
-
const awaited = await Promise.all(slice);
|
|
30377
|
-
for (const entry of awaited) {
|
|
30378
|
-
if (!entry)
|
|
30379
|
-
continue;
|
|
30380
|
-
if (this.destroyed)
|
|
30381
|
-
return;
|
|
30382
|
-
const entryType = await this._getEntryType(entry);
|
|
30383
|
-
if (entryType === "directory" && this._directoryFilter(entry)) {
|
|
30384
|
-
if (depth <= this._maxDepth) {
|
|
30385
|
-
this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
|
|
30386
|
-
}
|
|
30387
|
-
if (this._wantsDir) {
|
|
30388
|
-
this.push(entry);
|
|
30389
|
-
batch--;
|
|
30390
|
-
}
|
|
30391
|
-
} else if ((entryType === "file" || this._includeAsFile(entry)) && this._fileFilter(entry)) {
|
|
30392
|
-
if (this._wantsFile) {
|
|
30393
|
-
this.push(entry);
|
|
30394
|
-
batch--;
|
|
30395
|
-
}
|
|
30396
|
-
}
|
|
30397
|
-
}
|
|
30398
|
-
} else {
|
|
30399
|
-
const parent = this.parents.pop();
|
|
30400
|
-
if (!parent) {
|
|
30401
|
-
this.push(null);
|
|
30402
|
-
break;
|
|
30403
|
-
}
|
|
30404
|
-
this.parent = await parent;
|
|
30405
|
-
if (this.destroyed)
|
|
30406
|
-
return;
|
|
30407
|
-
}
|
|
30408
|
-
}
|
|
30409
|
-
} catch (error40) {
|
|
30410
|
-
this.destroy(error40);
|
|
30411
|
-
} finally {
|
|
30412
|
-
this.reading = false;
|
|
30413
|
-
}
|
|
30414
|
-
}
|
|
30415
|
-
async _exploreDir(path24, depth) {
|
|
30416
|
-
let files;
|
|
30417
|
-
try {
|
|
30418
|
-
files = await readdir(path24, this._rdOptions);
|
|
30419
|
-
} catch (error40) {
|
|
30420
|
-
this._onError(error40);
|
|
30421
|
-
}
|
|
30422
|
-
return { files, depth, path: path24 };
|
|
30423
|
-
}
|
|
30424
|
-
async _formatEntry(dirent, path24) {
|
|
30425
|
-
let entry;
|
|
30426
|
-
const basename6 = this._isDirent ? dirent.name : dirent;
|
|
30427
|
-
try {
|
|
30428
|
-
const fullPath = presolve(pjoin(path24, basename6));
|
|
30429
|
-
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
|
|
30430
|
-
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
30431
|
-
} catch (err) {
|
|
30432
|
-
this._onError(err);
|
|
30433
|
-
return;
|
|
30434
|
-
}
|
|
30435
|
-
return entry;
|
|
30436
|
-
}
|
|
30437
|
-
_onError(err) {
|
|
30438
|
-
if (isNormalFlowError(err) && !this.destroyed) {
|
|
30439
|
-
this.emit("warn", err);
|
|
30440
|
-
} else {
|
|
30441
|
-
this.destroy(err);
|
|
30442
|
-
}
|
|
30443
|
-
}
|
|
30444
|
-
async _getEntryType(entry) {
|
|
30445
|
-
if (!entry && this._statsProp in entry) {
|
|
30446
|
-
return "";
|
|
30447
|
-
}
|
|
30448
|
-
const stats = entry[this._statsProp];
|
|
30449
|
-
if (stats.isFile())
|
|
30450
|
-
return "file";
|
|
30451
|
-
if (stats.isDirectory())
|
|
30452
|
-
return "directory";
|
|
30453
|
-
if (stats && stats.isSymbolicLink()) {
|
|
30454
|
-
const full = entry.fullPath;
|
|
30455
|
-
try {
|
|
30456
|
-
const entryRealPath = await realpath(full);
|
|
30457
|
-
const entryRealPathStats = await lstat(entryRealPath);
|
|
30458
|
-
if (entryRealPathStats.isFile()) {
|
|
30459
|
-
return "file";
|
|
30460
|
-
}
|
|
30461
|
-
if (entryRealPathStats.isDirectory()) {
|
|
30462
|
-
const len = entryRealPath.length;
|
|
30463
|
-
if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {
|
|
30464
|
-
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
|
|
30465
|
-
recursiveError.code = RECURSIVE_ERROR_CODE;
|
|
30466
|
-
return this._onError(recursiveError);
|
|
30467
|
-
}
|
|
30468
|
-
return "directory";
|
|
30469
|
-
}
|
|
30470
|
-
} catch (error40) {
|
|
30471
|
-
this._onError(error40);
|
|
30472
|
-
return "";
|
|
30473
|
-
}
|
|
30474
|
-
}
|
|
30475
|
-
}
|
|
30476
|
-
_includeAsFile(entry) {
|
|
30477
|
-
const stats = entry && entry[this._statsProp];
|
|
30478
|
-
return stats && this._wantsEverything && !stats.isDirectory();
|
|
30479
|
-
}
|
|
30480
|
-
};
|
|
30481
|
-
function readdirp(root, options = {}) {
|
|
30482
|
-
let type = options.entryType || options.type;
|
|
30483
|
-
if (type === "both")
|
|
30484
|
-
type = EntryTypes.FILE_DIR_TYPE;
|
|
30485
|
-
if (type)
|
|
30486
|
-
options.type = type;
|
|
30487
|
-
if (!root) {
|
|
30488
|
-
throw new Error("readdirp: root argument is required. Usage: readdirp(root, options)");
|
|
30489
|
-
} else if (typeof root !== "string") {
|
|
30490
|
-
throw new TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");
|
|
30491
|
-
} else if (type && !ALL_TYPES.includes(type)) {
|
|
30492
|
-
throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(", ")}`);
|
|
30493
|
-
}
|
|
30494
|
-
options.root = root;
|
|
30495
|
-
return new ReaddirpStream(options);
|
|
30496
|
-
}
|
|
30497
|
-
|
|
30498
|
-
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/handler.js
|
|
30499
|
-
import { watchFile, unwatchFile, watch as fs_watch } from "fs";
|
|
30500
|
-
import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
|
|
30501
|
-
import * as sysPath from "path";
|
|
30502
|
-
import { type as osType } from "os";
|
|
30503
|
-
var STR_DATA = "data";
|
|
30504
|
-
var STR_END = "end";
|
|
30505
|
-
var STR_CLOSE = "close";
|
|
30506
|
-
var EMPTY_FN = () => {
|
|
30507
|
-
};
|
|
30508
|
-
var pl = process.platform;
|
|
30509
|
-
var isWindows = pl === "win32";
|
|
30510
|
-
var isMacos = pl === "darwin";
|
|
30511
|
-
var isLinux = pl === "linux";
|
|
30512
|
-
var isFreeBSD = pl === "freebsd";
|
|
30513
|
-
var isIBMi = osType() === "OS400";
|
|
30514
|
-
var EVENTS = {
|
|
30515
|
-
ALL: "all",
|
|
30516
|
-
READY: "ready",
|
|
30517
|
-
ADD: "add",
|
|
30518
|
-
CHANGE: "change",
|
|
30519
|
-
ADD_DIR: "addDir",
|
|
30520
|
-
UNLINK: "unlink",
|
|
30521
|
-
UNLINK_DIR: "unlinkDir",
|
|
30522
|
-
RAW: "raw",
|
|
30523
|
-
ERROR: "error"
|
|
30524
|
-
};
|
|
30525
|
-
var EV = EVENTS;
|
|
30526
|
-
var THROTTLE_MODE_WATCH = "watch";
|
|
30527
|
-
var statMethods = { lstat: lstat2, stat: stat2 };
|
|
30528
|
-
var KEY_LISTENERS = "listeners";
|
|
30529
|
-
var KEY_ERR = "errHandlers";
|
|
30530
|
-
var KEY_RAW = "rawEmitters";
|
|
30531
|
-
var HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
|
|
30532
|
-
var binaryExtensions = /* @__PURE__ */ new Set([
|
|
30533
|
-
"3dm",
|
|
30534
|
-
"3ds",
|
|
30535
|
-
"3g2",
|
|
30536
|
-
"3gp",
|
|
30537
|
-
"7z",
|
|
30538
|
-
"a",
|
|
30539
|
-
"aac",
|
|
30540
|
-
"adp",
|
|
30541
|
-
"afdesign",
|
|
30542
|
-
"afphoto",
|
|
30543
|
-
"afpub",
|
|
30544
|
-
"ai",
|
|
30545
|
-
"aif",
|
|
30546
|
-
"aiff",
|
|
30547
|
-
"alz",
|
|
30548
|
-
"ape",
|
|
30549
|
-
"apk",
|
|
30550
|
-
"appimage",
|
|
30551
|
-
"ar",
|
|
30552
|
-
"arj",
|
|
30553
|
-
"asf",
|
|
30554
|
-
"au",
|
|
30555
|
-
"avi",
|
|
30556
|
-
"bak",
|
|
30557
|
-
"baml",
|
|
30558
|
-
"bh",
|
|
30559
|
-
"bin",
|
|
30560
|
-
"bk",
|
|
30561
|
-
"bmp",
|
|
30562
|
-
"btif",
|
|
30563
|
-
"bz2",
|
|
30564
|
-
"bzip2",
|
|
30565
|
-
"cab",
|
|
30566
|
-
"caf",
|
|
30567
|
-
"cgm",
|
|
30568
|
-
"class",
|
|
30569
|
-
"cmx",
|
|
30570
|
-
"cpio",
|
|
30571
|
-
"cr2",
|
|
30572
|
-
"cur",
|
|
30573
|
-
"dat",
|
|
30574
|
-
"dcm",
|
|
30575
|
-
"deb",
|
|
30576
|
-
"dex",
|
|
30577
|
-
"djvu",
|
|
30578
|
-
"dll",
|
|
30579
|
-
"dmg",
|
|
30580
|
-
"dng",
|
|
30581
|
-
"doc",
|
|
30582
|
-
"docm",
|
|
30583
|
-
"docx",
|
|
30584
|
-
"dot",
|
|
30585
|
-
"dotm",
|
|
30586
|
-
"dra",
|
|
30587
|
-
"DS_Store",
|
|
30588
|
-
"dsk",
|
|
30589
|
-
"dts",
|
|
30590
|
-
"dtshd",
|
|
30591
|
-
"dvb",
|
|
30592
|
-
"dwg",
|
|
30593
|
-
"dxf",
|
|
30594
|
-
"ecelp4800",
|
|
30595
|
-
"ecelp7470",
|
|
30596
|
-
"ecelp9600",
|
|
30597
|
-
"egg",
|
|
30598
|
-
"eol",
|
|
30599
|
-
"eot",
|
|
30600
|
-
"epub",
|
|
30601
|
-
"exe",
|
|
30602
|
-
"f4v",
|
|
30603
|
-
"fbs",
|
|
30604
|
-
"fh",
|
|
30605
|
-
"fla",
|
|
30606
|
-
"flac",
|
|
30607
|
-
"flatpak",
|
|
30608
|
-
"fli",
|
|
30609
|
-
"flv",
|
|
30610
|
-
"fpx",
|
|
30611
|
-
"fst",
|
|
30612
|
-
"fvt",
|
|
30613
|
-
"g3",
|
|
30614
|
-
"gh",
|
|
30615
|
-
"gif",
|
|
30616
|
-
"graffle",
|
|
30617
|
-
"gz",
|
|
30618
|
-
"gzip",
|
|
30619
|
-
"h261",
|
|
30620
|
-
"h263",
|
|
30621
|
-
"h264",
|
|
30622
|
-
"icns",
|
|
30623
|
-
"ico",
|
|
30624
|
-
"ief",
|
|
30625
|
-
"img",
|
|
30626
|
-
"ipa",
|
|
30627
|
-
"iso",
|
|
30628
|
-
"jar",
|
|
30629
|
-
"jpeg",
|
|
30630
|
-
"jpg",
|
|
30631
|
-
"jpgv",
|
|
30632
|
-
"jpm",
|
|
30633
|
-
"jxr",
|
|
30634
|
-
"key",
|
|
30635
|
-
"ktx",
|
|
30636
|
-
"lha",
|
|
30637
|
-
"lib",
|
|
30638
|
-
"lvp",
|
|
30639
|
-
"lz",
|
|
30640
|
-
"lzh",
|
|
30641
|
-
"lzma",
|
|
30642
|
-
"lzo",
|
|
30643
|
-
"m3u",
|
|
30644
|
-
"m4a",
|
|
30645
|
-
"m4v",
|
|
30646
|
-
"mar",
|
|
30647
|
-
"mdi",
|
|
30648
|
-
"mht",
|
|
30649
|
-
"mid",
|
|
30650
|
-
"midi",
|
|
30651
|
-
"mj2",
|
|
30652
|
-
"mka",
|
|
30653
|
-
"mkv",
|
|
30654
|
-
"mmr",
|
|
30655
|
-
"mng",
|
|
30656
|
-
"mobi",
|
|
30657
|
-
"mov",
|
|
30658
|
-
"movie",
|
|
30659
|
-
"mp3",
|
|
30660
|
-
"mp4",
|
|
30661
|
-
"mp4a",
|
|
30662
|
-
"mpeg",
|
|
30663
|
-
"mpg",
|
|
30664
|
-
"mpga",
|
|
30665
|
-
"mxu",
|
|
30666
|
-
"nef",
|
|
30667
|
-
"npx",
|
|
30668
|
-
"numbers",
|
|
30669
|
-
"nupkg",
|
|
30670
|
-
"o",
|
|
30671
|
-
"odp",
|
|
30672
|
-
"ods",
|
|
30673
|
-
"odt",
|
|
30674
|
-
"oga",
|
|
30675
|
-
"ogg",
|
|
30676
|
-
"ogv",
|
|
30677
|
-
"otf",
|
|
30678
|
-
"ott",
|
|
30679
|
-
"pages",
|
|
30680
|
-
"pbm",
|
|
30681
|
-
"pcx",
|
|
30682
|
-
"pdb",
|
|
30683
|
-
"pdf",
|
|
30684
|
-
"pea",
|
|
30685
|
-
"pgm",
|
|
30686
|
-
"pic",
|
|
30687
|
-
"png",
|
|
30688
|
-
"pnm",
|
|
30689
|
-
"pot",
|
|
30690
|
-
"potm",
|
|
30691
|
-
"potx",
|
|
30692
|
-
"ppa",
|
|
30693
|
-
"ppam",
|
|
30694
|
-
"ppm",
|
|
30695
|
-
"pps",
|
|
30696
|
-
"ppsm",
|
|
30697
|
-
"ppsx",
|
|
30698
|
-
"ppt",
|
|
30699
|
-
"pptm",
|
|
30700
|
-
"pptx",
|
|
30701
|
-
"psd",
|
|
30702
|
-
"pya",
|
|
30703
|
-
"pyc",
|
|
30704
|
-
"pyo",
|
|
30705
|
-
"pyv",
|
|
30706
|
-
"qt",
|
|
30707
|
-
"rar",
|
|
30708
|
-
"ras",
|
|
30709
|
-
"raw",
|
|
30710
|
-
"resources",
|
|
30711
|
-
"rgb",
|
|
30712
|
-
"rip",
|
|
30713
|
-
"rlc",
|
|
30714
|
-
"rmf",
|
|
30715
|
-
"rmvb",
|
|
30716
|
-
"rpm",
|
|
30717
|
-
"rtf",
|
|
30718
|
-
"rz",
|
|
30719
|
-
"s3m",
|
|
30720
|
-
"s7z",
|
|
30721
|
-
"scpt",
|
|
30722
|
-
"sgi",
|
|
30723
|
-
"shar",
|
|
30724
|
-
"snap",
|
|
30725
|
-
"sil",
|
|
30726
|
-
"sketch",
|
|
30727
|
-
"slk",
|
|
30728
|
-
"smv",
|
|
30729
|
-
"snk",
|
|
30730
|
-
"so",
|
|
30731
|
-
"stl",
|
|
30732
|
-
"suo",
|
|
30733
|
-
"sub",
|
|
30734
|
-
"swf",
|
|
30735
|
-
"tar",
|
|
30736
|
-
"tbz",
|
|
30737
|
-
"tbz2",
|
|
30738
|
-
"tga",
|
|
30739
|
-
"tgz",
|
|
30740
|
-
"thmx",
|
|
30741
|
-
"tif",
|
|
30742
|
-
"tiff",
|
|
30743
|
-
"tlz",
|
|
30744
|
-
"ttc",
|
|
30745
|
-
"ttf",
|
|
30746
|
-
"txz",
|
|
30747
|
-
"udf",
|
|
30748
|
-
"uvh",
|
|
30749
|
-
"uvi",
|
|
30750
|
-
"uvm",
|
|
30751
|
-
"uvp",
|
|
30752
|
-
"uvs",
|
|
30753
|
-
"uvu",
|
|
30754
|
-
"viv",
|
|
30755
|
-
"vob",
|
|
30756
|
-
"war",
|
|
30757
|
-
"wav",
|
|
30758
|
-
"wax",
|
|
30759
|
-
"wbmp",
|
|
30760
|
-
"wdp",
|
|
30761
|
-
"weba",
|
|
30762
|
-
"webm",
|
|
30763
|
-
"webp",
|
|
30764
|
-
"whl",
|
|
30765
|
-
"wim",
|
|
30766
|
-
"wm",
|
|
30767
|
-
"wma",
|
|
30768
|
-
"wmv",
|
|
30769
|
-
"wmx",
|
|
30770
|
-
"woff",
|
|
30771
|
-
"woff2",
|
|
30772
|
-
"wrm",
|
|
30773
|
-
"wvx",
|
|
30774
|
-
"xbm",
|
|
30775
|
-
"xif",
|
|
30776
|
-
"xla",
|
|
30777
|
-
"xlam",
|
|
30778
|
-
"xls",
|
|
30779
|
-
"xlsb",
|
|
30780
|
-
"xlsm",
|
|
30781
|
-
"xlsx",
|
|
30782
|
-
"xlt",
|
|
30783
|
-
"xltm",
|
|
30784
|
-
"xltx",
|
|
30785
|
-
"xm",
|
|
30786
|
-
"xmind",
|
|
30787
|
-
"xpi",
|
|
30788
|
-
"xpm",
|
|
30789
|
-
"xwd",
|
|
30790
|
-
"xz",
|
|
30791
|
-
"z",
|
|
30792
|
-
"zip",
|
|
30793
|
-
"zipx"
|
|
30794
|
-
]);
|
|
30795
|
-
var isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
|
|
30796
|
-
var foreach = (val, fn) => {
|
|
30797
|
-
if (val instanceof Set) {
|
|
30798
|
-
val.forEach(fn);
|
|
30799
|
-
} else {
|
|
30800
|
-
fn(val);
|
|
30801
|
-
}
|
|
30802
|
-
};
|
|
30803
|
-
var addAndConvert = (main, prop, item) => {
|
|
30804
|
-
let container = main[prop];
|
|
30805
|
-
if (!(container instanceof Set)) {
|
|
30806
|
-
main[prop] = container = /* @__PURE__ */ new Set([container]);
|
|
30807
|
-
}
|
|
30808
|
-
container.add(item);
|
|
30809
|
-
};
|
|
30810
|
-
var clearItem = (cont) => (key) => {
|
|
30811
|
-
const set2 = cont[key];
|
|
30812
|
-
if (set2 instanceof Set) {
|
|
30813
|
-
set2.clear();
|
|
30814
|
-
} else {
|
|
30815
|
-
delete cont[key];
|
|
30816
|
-
}
|
|
30817
|
-
};
|
|
30818
|
-
var delFromSet = (main, prop, item) => {
|
|
30819
|
-
const container = main[prop];
|
|
30820
|
-
if (container instanceof Set) {
|
|
30821
|
-
container.delete(item);
|
|
30822
|
-
} else if (container === item) {
|
|
30823
|
-
delete main[prop];
|
|
30824
|
-
}
|
|
30825
|
-
};
|
|
30826
|
-
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
30827
|
-
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
30828
|
-
function createFsWatchInstance(path24, options, listener, errHandler, emitRaw) {
|
|
30829
|
-
const handleEvent = (rawEvent, evPath) => {
|
|
30830
|
-
listener(path24);
|
|
30831
|
-
emitRaw(rawEvent, evPath, { watchedPath: path24 });
|
|
30832
|
-
if (evPath && path24 !== evPath) {
|
|
30833
|
-
fsWatchBroadcast(sysPath.resolve(path24, evPath), KEY_LISTENERS, sysPath.join(path24, evPath));
|
|
30834
|
-
}
|
|
30835
|
-
};
|
|
30836
|
-
try {
|
|
30837
|
-
return fs_watch(path24, {
|
|
30838
|
-
persistent: options.persistent
|
|
30839
|
-
}, handleEvent);
|
|
30840
|
-
} catch (error40) {
|
|
30841
|
-
errHandler(error40);
|
|
30842
|
-
return void 0;
|
|
30843
|
-
}
|
|
30844
|
-
}
|
|
30845
|
-
var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
30846
|
-
const cont = FsWatchInstances.get(fullPath);
|
|
30847
|
-
if (!cont)
|
|
30848
|
-
return;
|
|
30849
|
-
foreach(cont[listenerType], (listener) => {
|
|
30850
|
-
listener(val1, val2, val3);
|
|
30851
|
-
});
|
|
30852
|
-
};
|
|
30853
|
-
var setFsWatchListener = (path24, fullPath, options, handlers) => {
|
|
30854
|
-
const { listener, errHandler, rawEmitter } = handlers;
|
|
30855
|
-
let cont = FsWatchInstances.get(fullPath);
|
|
30856
|
-
let watcher;
|
|
30857
|
-
if (!options.persistent) {
|
|
30858
|
-
watcher = createFsWatchInstance(path24, options, listener, errHandler, rawEmitter);
|
|
30859
|
-
if (!watcher)
|
|
30860
|
-
return;
|
|
30861
|
-
return watcher.close.bind(watcher);
|
|
30862
|
-
}
|
|
30863
|
-
if (cont) {
|
|
30864
|
-
addAndConvert(cont, KEY_LISTENERS, listener);
|
|
30865
|
-
addAndConvert(cont, KEY_ERR, errHandler);
|
|
30866
|
-
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
30867
|
-
} else {
|
|
30868
|
-
watcher = createFsWatchInstance(
|
|
30869
|
-
path24,
|
|
30870
|
-
options,
|
|
30871
|
-
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
30872
|
-
errHandler,
|
|
30873
|
-
// no need to use broadcast here
|
|
30874
|
-
fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
|
|
30875
|
-
);
|
|
30876
|
-
if (!watcher)
|
|
30877
|
-
return;
|
|
30878
|
-
watcher.on(EV.ERROR, async (error40) => {
|
|
30879
|
-
const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
|
|
30880
|
-
if (cont)
|
|
30881
|
-
cont.watcherUnusable = true;
|
|
30882
|
-
if (isWindows && error40.code === "EPERM") {
|
|
30883
|
-
try {
|
|
30884
|
-
const fd = await open(path24, "r");
|
|
30885
|
-
await fd.close();
|
|
30886
|
-
broadcastErr(error40);
|
|
30887
|
-
} catch (err) {
|
|
30888
|
-
}
|
|
30889
|
-
} else {
|
|
30890
|
-
broadcastErr(error40);
|
|
30891
|
-
}
|
|
30892
|
-
});
|
|
30893
|
-
cont = {
|
|
30894
|
-
listeners: listener,
|
|
30895
|
-
errHandlers: errHandler,
|
|
30896
|
-
rawEmitters: rawEmitter,
|
|
30897
|
-
watcher
|
|
30898
|
-
};
|
|
30899
|
-
FsWatchInstances.set(fullPath, cont);
|
|
30900
|
-
}
|
|
30901
|
-
return () => {
|
|
30902
|
-
delFromSet(cont, KEY_LISTENERS, listener);
|
|
30903
|
-
delFromSet(cont, KEY_ERR, errHandler);
|
|
30904
|
-
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
30905
|
-
if (isEmptySet(cont.listeners)) {
|
|
30906
|
-
cont.watcher.close();
|
|
30907
|
-
FsWatchInstances.delete(fullPath);
|
|
30908
|
-
HANDLER_KEYS.forEach(clearItem(cont));
|
|
30909
|
-
cont.watcher = void 0;
|
|
30910
|
-
Object.freeze(cont);
|
|
30911
|
-
}
|
|
30912
|
-
};
|
|
30913
|
-
};
|
|
30914
|
-
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
30915
|
-
var setFsWatchFileListener = (path24, fullPath, options, handlers) => {
|
|
30916
|
-
const { listener, rawEmitter } = handlers;
|
|
30917
|
-
let cont = FsWatchFileInstances.get(fullPath);
|
|
30918
|
-
const copts = cont && cont.options;
|
|
30919
|
-
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
|
30920
|
-
unwatchFile(fullPath);
|
|
30921
|
-
cont = void 0;
|
|
30922
|
-
}
|
|
30923
|
-
if (cont) {
|
|
30924
|
-
addAndConvert(cont, KEY_LISTENERS, listener);
|
|
30925
|
-
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
30926
|
-
} else {
|
|
30927
|
-
cont = {
|
|
30928
|
-
listeners: listener,
|
|
30929
|
-
rawEmitters: rawEmitter,
|
|
30930
|
-
options,
|
|
30931
|
-
watcher: watchFile(fullPath, options, (curr, prev) => {
|
|
30932
|
-
foreach(cont.rawEmitters, (rawEmitter2) => {
|
|
30933
|
-
rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
|
|
30934
|
-
});
|
|
30935
|
-
const currmtime = curr.mtimeMs;
|
|
30936
|
-
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
30937
|
-
foreach(cont.listeners, (listener2) => listener2(path24, curr));
|
|
30938
|
-
}
|
|
30939
|
-
})
|
|
30940
|
-
};
|
|
30941
|
-
FsWatchFileInstances.set(fullPath, cont);
|
|
30942
|
-
}
|
|
30943
|
-
return () => {
|
|
30944
|
-
delFromSet(cont, KEY_LISTENERS, listener);
|
|
30945
|
-
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
30946
|
-
if (isEmptySet(cont.listeners)) {
|
|
30947
|
-
FsWatchFileInstances.delete(fullPath);
|
|
30948
|
-
unwatchFile(fullPath);
|
|
30949
|
-
cont.options = cont.watcher = void 0;
|
|
30950
|
-
Object.freeze(cont);
|
|
30951
|
-
}
|
|
30952
|
-
};
|
|
30953
|
-
};
|
|
30954
|
-
var NodeFsHandler = class {
|
|
30955
|
-
constructor(fsW) {
|
|
30956
|
-
this.fsw = fsW;
|
|
30957
|
-
this._boundHandleError = (error40) => fsW._handleError(error40);
|
|
30958
|
-
}
|
|
30959
|
-
/**
|
|
30960
|
-
* Watch file for changes with fs_watchFile or fs_watch.
|
|
30961
|
-
* @param path to file or dir
|
|
30962
|
-
* @param listener on fs change
|
|
30963
|
-
* @returns closer for the watcher instance
|
|
30964
|
-
*/
|
|
30965
|
-
_watchWithNodeFs(path24, listener) {
|
|
30966
|
-
const opts = this.fsw.options;
|
|
30967
|
-
const directory = sysPath.dirname(path24);
|
|
30968
|
-
const basename6 = sysPath.basename(path24);
|
|
30969
|
-
const parent = this.fsw._getWatchedDir(directory);
|
|
30970
|
-
parent.add(basename6);
|
|
30971
|
-
const absolutePath = sysPath.resolve(path24);
|
|
30972
|
-
const options = {
|
|
30973
|
-
persistent: opts.persistent
|
|
30974
|
-
};
|
|
30975
|
-
if (!listener)
|
|
30976
|
-
listener = EMPTY_FN;
|
|
30977
|
-
let closer;
|
|
30978
|
-
if (opts.usePolling) {
|
|
30979
|
-
const enableBin = opts.interval !== opts.binaryInterval;
|
|
30980
|
-
options.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
|
|
30981
|
-
closer = setFsWatchFileListener(path24, absolutePath, options, {
|
|
30982
|
-
listener,
|
|
30983
|
-
rawEmitter: this.fsw._emitRaw
|
|
30984
|
-
});
|
|
30985
|
-
} else {
|
|
30986
|
-
closer = setFsWatchListener(path24, absolutePath, options, {
|
|
30987
|
-
listener,
|
|
30988
|
-
errHandler: this._boundHandleError,
|
|
30989
|
-
rawEmitter: this.fsw._emitRaw
|
|
30990
|
-
});
|
|
30991
|
-
}
|
|
30992
|
-
return closer;
|
|
30993
|
-
}
|
|
30994
|
-
/**
|
|
30995
|
-
* Watch a file and emit add event if warranted.
|
|
30996
|
-
* @returns closer for the watcher instance
|
|
30997
|
-
*/
|
|
30998
|
-
_handleFile(file2, stats, initialAdd) {
|
|
30999
|
-
if (this.fsw.closed) {
|
|
31000
|
-
return;
|
|
31001
|
-
}
|
|
31002
|
-
const dirname7 = sysPath.dirname(file2);
|
|
31003
|
-
const basename6 = sysPath.basename(file2);
|
|
31004
|
-
const parent = this.fsw._getWatchedDir(dirname7);
|
|
31005
|
-
let prevStats = stats;
|
|
31006
|
-
if (parent.has(basename6))
|
|
31007
|
-
return;
|
|
31008
|
-
const listener = async (path24, newStats) => {
|
|
31009
|
-
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
|
|
31010
|
-
return;
|
|
31011
|
-
if (!newStats || newStats.mtimeMs === 0) {
|
|
31012
|
-
try {
|
|
31013
|
-
const newStats2 = await stat2(file2);
|
|
31014
|
-
if (this.fsw.closed)
|
|
31015
|
-
return;
|
|
31016
|
-
const at = newStats2.atimeMs;
|
|
31017
|
-
const mt = newStats2.mtimeMs;
|
|
31018
|
-
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
31019
|
-
this.fsw._emit(EV.CHANGE, file2, newStats2);
|
|
31020
|
-
}
|
|
31021
|
-
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
31022
|
-
this.fsw._closeFile(path24);
|
|
31023
|
-
prevStats = newStats2;
|
|
31024
|
-
const closer2 = this._watchWithNodeFs(file2, listener);
|
|
31025
|
-
if (closer2)
|
|
31026
|
-
this.fsw._addPathCloser(path24, closer2);
|
|
31027
|
-
} else {
|
|
31028
|
-
prevStats = newStats2;
|
|
31029
|
-
}
|
|
31030
|
-
} catch (error40) {
|
|
31031
|
-
this.fsw._remove(dirname7, basename6);
|
|
31032
|
-
}
|
|
31033
|
-
} else if (parent.has(basename6)) {
|
|
31034
|
-
const at = newStats.atimeMs;
|
|
31035
|
-
const mt = newStats.mtimeMs;
|
|
31036
|
-
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
31037
|
-
this.fsw._emit(EV.CHANGE, file2, newStats);
|
|
31038
|
-
}
|
|
31039
|
-
prevStats = newStats;
|
|
31040
|
-
}
|
|
31041
|
-
};
|
|
31042
|
-
const closer = this._watchWithNodeFs(file2, listener);
|
|
31043
|
-
if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file2)) {
|
|
31044
|
-
if (!this.fsw._throttle(EV.ADD, file2, 0))
|
|
31045
|
-
return;
|
|
31046
|
-
this.fsw._emit(EV.ADD, file2, stats);
|
|
31047
|
-
}
|
|
31048
|
-
return closer;
|
|
31049
|
-
}
|
|
31050
|
-
/**
|
|
31051
|
-
* Handle symlinks encountered while reading a dir.
|
|
31052
|
-
* @param entry returned by readdirp
|
|
31053
|
-
* @param directory path of dir being read
|
|
31054
|
-
* @param path of this item
|
|
31055
|
-
* @param item basename of this item
|
|
31056
|
-
* @returns true if no more processing is needed for this entry.
|
|
31057
|
-
*/
|
|
31058
|
-
async _handleSymlink(entry, directory, path24, item) {
|
|
31059
|
-
if (this.fsw.closed) {
|
|
31060
|
-
return;
|
|
31061
|
-
}
|
|
31062
|
-
const full = entry.fullPath;
|
|
31063
|
-
const dir = this.fsw._getWatchedDir(directory);
|
|
31064
|
-
if (!this.fsw.options.followSymlinks) {
|
|
31065
|
-
this.fsw._incrReadyCount();
|
|
31066
|
-
let linkPath;
|
|
31067
|
-
try {
|
|
31068
|
-
linkPath = await fsrealpath(path24);
|
|
31069
|
-
} catch (e) {
|
|
31070
|
-
this.fsw._emitReady();
|
|
31071
|
-
return true;
|
|
31072
|
-
}
|
|
31073
|
-
if (this.fsw.closed)
|
|
31074
|
-
return;
|
|
31075
|
-
if (dir.has(item)) {
|
|
31076
|
-
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
31077
|
-
this.fsw._symlinkPaths.set(full, linkPath);
|
|
31078
|
-
this.fsw._emit(EV.CHANGE, path24, entry.stats);
|
|
31079
|
-
}
|
|
31080
|
-
} else {
|
|
31081
|
-
dir.add(item);
|
|
31082
|
-
this.fsw._symlinkPaths.set(full, linkPath);
|
|
31083
|
-
this.fsw._emit(EV.ADD, path24, entry.stats);
|
|
31084
|
-
}
|
|
31085
|
-
this.fsw._emitReady();
|
|
31086
|
-
return true;
|
|
31087
|
-
}
|
|
31088
|
-
if (this.fsw._symlinkPaths.has(full)) {
|
|
31089
|
-
return true;
|
|
31090
|
-
}
|
|
31091
|
-
this.fsw._symlinkPaths.set(full, true);
|
|
31092
|
-
}
|
|
31093
|
-
_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
|
|
31094
|
-
directory = sysPath.join(directory, "");
|
|
31095
|
-
throttler = this.fsw._throttle("readdir", directory, 1e3);
|
|
31096
|
-
if (!throttler)
|
|
31097
|
-
return;
|
|
31098
|
-
const previous = this.fsw._getWatchedDir(wh.path);
|
|
31099
|
-
const current = /* @__PURE__ */ new Set();
|
|
31100
|
-
let stream = this.fsw._readdirp(directory, {
|
|
31101
|
-
fileFilter: (entry) => wh.filterPath(entry),
|
|
31102
|
-
directoryFilter: (entry) => wh.filterDir(entry)
|
|
31103
|
-
});
|
|
31104
|
-
if (!stream)
|
|
31105
|
-
return;
|
|
31106
|
-
stream.on(STR_DATA, async (entry) => {
|
|
31107
|
-
if (this.fsw.closed) {
|
|
31108
|
-
stream = void 0;
|
|
31109
|
-
return;
|
|
31110
|
-
}
|
|
31111
|
-
const item = entry.path;
|
|
31112
|
-
let path24 = sysPath.join(directory, item);
|
|
31113
|
-
current.add(item);
|
|
31114
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path24, item)) {
|
|
31115
|
-
return;
|
|
31116
|
-
}
|
|
31117
|
-
if (this.fsw.closed) {
|
|
31118
|
-
stream = void 0;
|
|
31119
|
-
return;
|
|
31120
|
-
}
|
|
31121
|
-
if (item === target || !target && !previous.has(item)) {
|
|
31122
|
-
this.fsw._incrReadyCount();
|
|
31123
|
-
path24 = sysPath.join(dir, sysPath.relative(dir, path24));
|
|
31124
|
-
this._addToNodeFs(path24, initialAdd, wh, depth + 1);
|
|
31125
|
-
}
|
|
31126
|
-
}).on(EV.ERROR, this._boundHandleError);
|
|
31127
|
-
return new Promise((resolve16, reject) => {
|
|
31128
|
-
if (!stream)
|
|
31129
|
-
return reject();
|
|
31130
|
-
stream.once(STR_END, () => {
|
|
31131
|
-
if (this.fsw.closed) {
|
|
31132
|
-
stream = void 0;
|
|
31133
|
-
return;
|
|
31134
|
-
}
|
|
31135
|
-
const wasThrottled = throttler ? throttler.clear() : false;
|
|
31136
|
-
resolve16(void 0);
|
|
31137
|
-
previous.getChildren().filter((item) => {
|
|
31138
|
-
return item !== directory && !current.has(item);
|
|
31139
|
-
}).forEach((item) => {
|
|
31140
|
-
this.fsw._remove(directory, item);
|
|
31141
|
-
});
|
|
31142
|
-
stream = void 0;
|
|
31143
|
-
if (wasThrottled)
|
|
31144
|
-
this._handleRead(directory, false, wh, target, dir, depth, throttler);
|
|
31145
|
-
});
|
|
31146
|
-
});
|
|
31147
|
-
}
|
|
31148
|
-
/**
|
|
31149
|
-
* Read directory to add / remove files from `@watched` list and re-read it on change.
|
|
31150
|
-
* @param dir fs path
|
|
31151
|
-
* @param stats
|
|
31152
|
-
* @param initialAdd
|
|
31153
|
-
* @param depth relative to user-supplied path
|
|
31154
|
-
* @param target child path targeted for watch
|
|
31155
|
-
* @param wh Common watch helpers for this path
|
|
31156
|
-
* @param realpath
|
|
31157
|
-
* @returns closer for the watcher instance.
|
|
31158
|
-
*/
|
|
31159
|
-
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
|
|
31160
|
-
const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
|
|
31161
|
-
const tracked = parentDir.has(sysPath.basename(dir));
|
|
31162
|
-
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
|
|
31163
|
-
this.fsw._emit(EV.ADD_DIR, dir, stats);
|
|
31164
|
-
}
|
|
31165
|
-
parentDir.add(sysPath.basename(dir));
|
|
31166
|
-
this.fsw._getWatchedDir(dir);
|
|
31167
|
-
let throttler;
|
|
31168
|
-
let closer;
|
|
31169
|
-
const oDepth = this.fsw.options.depth;
|
|
31170
|
-
if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath2)) {
|
|
31171
|
-
if (!target) {
|
|
31172
|
-
await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
|
|
31173
|
-
if (this.fsw.closed)
|
|
31174
|
-
return;
|
|
31175
|
-
}
|
|
31176
|
-
closer = this._watchWithNodeFs(dir, (dirPath, stats2) => {
|
|
31177
|
-
if (stats2 && stats2.mtimeMs === 0)
|
|
31178
|
-
return;
|
|
31179
|
-
this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
|
|
31180
|
-
});
|
|
31181
|
-
}
|
|
31182
|
-
return closer;
|
|
31183
|
-
}
|
|
31184
|
-
/**
|
|
31185
|
-
* Handle added file, directory, or glob pattern.
|
|
31186
|
-
* Delegates call to _handleFile / _handleDir after checks.
|
|
31187
|
-
* @param path to file or ir
|
|
31188
|
-
* @param initialAdd was the file added at watch instantiation?
|
|
31189
|
-
* @param priorWh depth relative to user-supplied path
|
|
31190
|
-
* @param depth Child path actually targeted for watch
|
|
31191
|
-
* @param target Child path actually targeted for watch
|
|
31192
|
-
*/
|
|
31193
|
-
async _addToNodeFs(path24, initialAdd, priorWh, depth, target) {
|
|
31194
|
-
const ready = this.fsw._emitReady;
|
|
31195
|
-
if (this.fsw._isIgnored(path24) || this.fsw.closed) {
|
|
31196
|
-
ready();
|
|
31197
|
-
return false;
|
|
31198
|
-
}
|
|
31199
|
-
const wh = this.fsw._getWatchHelpers(path24);
|
|
31200
|
-
if (priorWh) {
|
|
31201
|
-
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
31202
|
-
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
31203
|
-
}
|
|
31204
|
-
try {
|
|
31205
|
-
const stats = await statMethods[wh.statMethod](wh.watchPath);
|
|
31206
|
-
if (this.fsw.closed)
|
|
31207
|
-
return;
|
|
31208
|
-
if (this.fsw._isIgnored(wh.watchPath, stats)) {
|
|
31209
|
-
ready();
|
|
31210
|
-
return false;
|
|
31211
|
-
}
|
|
31212
|
-
const follow = this.fsw.options.followSymlinks;
|
|
31213
|
-
let closer;
|
|
31214
|
-
if (stats.isDirectory()) {
|
|
31215
|
-
const absPath = sysPath.resolve(path24);
|
|
31216
|
-
const targetPath = follow ? await fsrealpath(path24) : path24;
|
|
31217
|
-
if (this.fsw.closed)
|
|
31218
|
-
return;
|
|
31219
|
-
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
31220
|
-
if (this.fsw.closed)
|
|
31221
|
-
return;
|
|
31222
|
-
if (absPath !== targetPath && targetPath !== void 0) {
|
|
31223
|
-
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
31224
|
-
}
|
|
31225
|
-
} else if (stats.isSymbolicLink()) {
|
|
31226
|
-
const targetPath = follow ? await fsrealpath(path24) : path24;
|
|
31227
|
-
if (this.fsw.closed)
|
|
31228
|
-
return;
|
|
31229
|
-
const parent = sysPath.dirname(wh.watchPath);
|
|
31230
|
-
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
31231
|
-
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
31232
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth, path24, wh, targetPath);
|
|
31233
|
-
if (this.fsw.closed)
|
|
31234
|
-
return;
|
|
31235
|
-
if (targetPath !== void 0) {
|
|
31236
|
-
this.fsw._symlinkPaths.set(sysPath.resolve(path24), targetPath);
|
|
31237
|
-
}
|
|
31238
|
-
} else {
|
|
31239
|
-
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
31240
|
-
}
|
|
31241
|
-
ready();
|
|
31242
|
-
if (closer)
|
|
31243
|
-
this.fsw._addPathCloser(path24, closer);
|
|
31244
|
-
return false;
|
|
31245
|
-
} catch (error40) {
|
|
31246
|
-
if (this.fsw._handleError(error40)) {
|
|
31247
|
-
ready();
|
|
31248
|
-
return path24;
|
|
31249
|
-
}
|
|
31250
|
-
}
|
|
31251
|
-
}
|
|
31252
|
-
};
|
|
31253
|
-
|
|
31254
|
-
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
31255
|
-
var SLASH = "/";
|
|
31256
|
-
var SLASH_SLASH = "//";
|
|
31257
|
-
var ONE_DOT = ".";
|
|
31258
|
-
var TWO_DOTS = "..";
|
|
31259
|
-
var STRING_TYPE = "string";
|
|
31260
|
-
var BACK_SLASH_RE = /\\/g;
|
|
31261
|
-
var DOUBLE_SLASH_RE = /\/\//;
|
|
31262
|
-
var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
|
|
31263
|
-
var REPLACER_RE = /^\.[/\\]/;
|
|
31264
|
-
function arrify(item) {
|
|
31265
|
-
return Array.isArray(item) ? item : [item];
|
|
31266
|
-
}
|
|
31267
|
-
var isMatcherObject = (matcher) => typeof matcher === "object" && matcher !== null && !(matcher instanceof RegExp);
|
|
31268
|
-
function createPattern(matcher) {
|
|
31269
|
-
if (typeof matcher === "function")
|
|
31270
|
-
return matcher;
|
|
31271
|
-
if (typeof matcher === "string")
|
|
31272
|
-
return (string4) => matcher === string4;
|
|
31273
|
-
if (matcher instanceof RegExp)
|
|
31274
|
-
return (string4) => matcher.test(string4);
|
|
31275
|
-
if (typeof matcher === "object" && matcher !== null) {
|
|
31276
|
-
return (string4) => {
|
|
31277
|
-
if (matcher.path === string4)
|
|
31278
|
-
return true;
|
|
31279
|
-
if (matcher.recursive) {
|
|
31280
|
-
const relative6 = sysPath2.relative(matcher.path, string4);
|
|
31281
|
-
if (!relative6) {
|
|
31282
|
-
return false;
|
|
31283
|
-
}
|
|
31284
|
-
return !relative6.startsWith("..") && !sysPath2.isAbsolute(relative6);
|
|
31285
|
-
}
|
|
31286
|
-
return false;
|
|
31287
|
-
};
|
|
31288
|
-
}
|
|
31289
|
-
return () => false;
|
|
31290
|
-
}
|
|
31291
|
-
function normalizePath(path24) {
|
|
31292
|
-
if (typeof path24 !== "string")
|
|
31293
|
-
throw new Error("string expected");
|
|
31294
|
-
path24 = sysPath2.normalize(path24);
|
|
31295
|
-
path24 = path24.replace(/\\/g, "/");
|
|
31296
|
-
let prepend = false;
|
|
31297
|
-
if (path24.startsWith("//"))
|
|
31298
|
-
prepend = true;
|
|
31299
|
-
const DOUBLE_SLASH_RE2 = /\/\//;
|
|
31300
|
-
while (path24.match(DOUBLE_SLASH_RE2))
|
|
31301
|
-
path24 = path24.replace(DOUBLE_SLASH_RE2, "/");
|
|
31302
|
-
if (prepend)
|
|
31303
|
-
path24 = "/" + path24;
|
|
31304
|
-
return path24;
|
|
31305
|
-
}
|
|
31306
|
-
function matchPatterns(patterns, testString, stats) {
|
|
31307
|
-
const path24 = normalizePath(testString);
|
|
31308
|
-
for (let index = 0; index < patterns.length; index++) {
|
|
31309
|
-
const pattern = patterns[index];
|
|
31310
|
-
if (pattern(path24, stats)) {
|
|
31311
|
-
return true;
|
|
31312
|
-
}
|
|
31313
|
-
}
|
|
31314
|
-
return false;
|
|
31315
|
-
}
|
|
31316
|
-
function anymatch(matchers, testString) {
|
|
31317
|
-
if (matchers == null) {
|
|
31318
|
-
throw new TypeError("anymatch: specify first argument");
|
|
31319
|
-
}
|
|
31320
|
-
const matchersArray = arrify(matchers);
|
|
31321
|
-
const patterns = matchersArray.map((matcher) => createPattern(matcher));
|
|
31322
|
-
if (testString == null) {
|
|
31323
|
-
return (testString2, stats) => {
|
|
31324
|
-
return matchPatterns(patterns, testString2, stats);
|
|
31325
|
-
};
|
|
31326
|
-
}
|
|
31327
|
-
return matchPatterns(patterns, testString);
|
|
31328
|
-
}
|
|
31329
|
-
var unifyPaths = (paths_) => {
|
|
31330
|
-
const paths = arrify(paths_).flat();
|
|
31331
|
-
if (!paths.every((p) => typeof p === STRING_TYPE)) {
|
|
31332
|
-
throw new TypeError(`Non-string provided as watch path: ${paths}`);
|
|
31333
|
-
}
|
|
31334
|
-
return paths.map(normalizePathToUnix);
|
|
31335
|
-
};
|
|
31336
|
-
var toUnix = (string4) => {
|
|
31337
|
-
let str = string4.replace(BACK_SLASH_RE, SLASH);
|
|
31338
|
-
let prepend = false;
|
|
31339
|
-
if (str.startsWith(SLASH_SLASH)) {
|
|
31340
|
-
prepend = true;
|
|
31341
|
-
}
|
|
31342
|
-
while (str.match(DOUBLE_SLASH_RE)) {
|
|
31343
|
-
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
|
31344
|
-
}
|
|
31345
|
-
if (prepend) {
|
|
31346
|
-
str = SLASH + str;
|
|
31347
|
-
}
|
|
31348
|
-
return str;
|
|
31349
|
-
};
|
|
31350
|
-
var normalizePathToUnix = (path24) => toUnix(sysPath2.normalize(toUnix(path24)));
|
|
31351
|
-
var normalizeIgnored = (cwd3 = "") => (path24) => {
|
|
31352
|
-
if (typeof path24 === "string") {
|
|
31353
|
-
return normalizePathToUnix(sysPath2.isAbsolute(path24) ? path24 : sysPath2.join(cwd3, path24));
|
|
31354
|
-
} else {
|
|
31355
|
-
return path24;
|
|
31356
|
-
}
|
|
31357
|
-
};
|
|
31358
|
-
var getAbsolutePath = (path24, cwd3) => {
|
|
31359
|
-
if (sysPath2.isAbsolute(path24)) {
|
|
31360
|
-
return path24;
|
|
31361
|
-
}
|
|
31362
|
-
return sysPath2.join(cwd3, path24);
|
|
31363
|
-
};
|
|
31364
|
-
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
31365
|
-
var DirEntry = class {
|
|
31366
|
-
constructor(dir, removeWatcher) {
|
|
31367
|
-
this.path = dir;
|
|
31368
|
-
this._removeWatcher = removeWatcher;
|
|
31369
|
-
this.items = /* @__PURE__ */ new Set();
|
|
31370
|
-
}
|
|
31371
|
-
add(item) {
|
|
31372
|
-
const { items } = this;
|
|
31373
|
-
if (!items)
|
|
31374
|
-
return;
|
|
31375
|
-
if (item !== ONE_DOT && item !== TWO_DOTS)
|
|
31376
|
-
items.add(item);
|
|
31377
|
-
}
|
|
31378
|
-
async remove(item) {
|
|
31379
|
-
const { items } = this;
|
|
31380
|
-
if (!items)
|
|
31381
|
-
return;
|
|
31382
|
-
items.delete(item);
|
|
31383
|
-
if (items.size > 0)
|
|
31384
|
-
return;
|
|
31385
|
-
const dir = this.path;
|
|
31386
|
-
try {
|
|
31387
|
-
await readdir2(dir);
|
|
31388
|
-
} catch (err) {
|
|
31389
|
-
if (this._removeWatcher) {
|
|
31390
|
-
this._removeWatcher(sysPath2.dirname(dir), sysPath2.basename(dir));
|
|
31391
|
-
}
|
|
31392
|
-
}
|
|
31393
|
-
}
|
|
31394
|
-
has(item) {
|
|
31395
|
-
const { items } = this;
|
|
31396
|
-
if (!items)
|
|
31397
|
-
return;
|
|
31398
|
-
return items.has(item);
|
|
31399
|
-
}
|
|
31400
|
-
getChildren() {
|
|
31401
|
-
const { items } = this;
|
|
31402
|
-
if (!items)
|
|
31403
|
-
return [];
|
|
31404
|
-
return [...items.values()];
|
|
31405
|
-
}
|
|
31406
|
-
dispose() {
|
|
31407
|
-
this.items.clear();
|
|
31408
|
-
this.path = "";
|
|
31409
|
-
this._removeWatcher = EMPTY_FN;
|
|
31410
|
-
this.items = EMPTY_SET;
|
|
31411
|
-
Object.freeze(this);
|
|
31412
|
-
}
|
|
31413
|
-
};
|
|
31414
|
-
var STAT_METHOD_F = "stat";
|
|
31415
|
-
var STAT_METHOD_L = "lstat";
|
|
31416
|
-
var WatchHelper = class {
|
|
31417
|
-
constructor(path24, follow, fsw) {
|
|
31418
|
-
this.fsw = fsw;
|
|
31419
|
-
const watchPath = path24;
|
|
31420
|
-
this.path = path24 = path24.replace(REPLACER_RE, "");
|
|
31421
|
-
this.watchPath = watchPath;
|
|
31422
|
-
this.fullWatchPath = sysPath2.resolve(watchPath);
|
|
31423
|
-
this.dirParts = [];
|
|
31424
|
-
this.dirParts.forEach((parts) => {
|
|
31425
|
-
if (parts.length > 1)
|
|
31426
|
-
parts.pop();
|
|
31427
|
-
});
|
|
31428
|
-
this.followSymlinks = follow;
|
|
31429
|
-
this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
|
|
31430
|
-
}
|
|
31431
|
-
entryPath(entry) {
|
|
31432
|
-
return sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
|
|
31433
|
-
}
|
|
31434
|
-
filterPath(entry) {
|
|
31435
|
-
const { stats } = entry;
|
|
31436
|
-
if (stats && stats.isSymbolicLink())
|
|
31437
|
-
return this.filterDir(entry);
|
|
31438
|
-
const resolvedPath = this.entryPath(entry);
|
|
31439
|
-
return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
|
|
31440
|
-
}
|
|
31441
|
-
filterDir(entry) {
|
|
31442
|
-
return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
|
|
31443
|
-
}
|
|
31444
|
-
};
|
|
31445
|
-
var FSWatcher = class extends EventEmitter2 {
|
|
31446
|
-
// Not indenting methods for history sake; for now.
|
|
31447
|
-
constructor(_opts = {}) {
|
|
31448
|
-
super();
|
|
31449
|
-
this.closed = false;
|
|
31450
|
-
this._closers = /* @__PURE__ */ new Map();
|
|
31451
|
-
this._ignoredPaths = /* @__PURE__ */ new Set();
|
|
31452
|
-
this._throttled = /* @__PURE__ */ new Map();
|
|
31453
|
-
this._streams = /* @__PURE__ */ new Set();
|
|
31454
|
-
this._symlinkPaths = /* @__PURE__ */ new Map();
|
|
31455
|
-
this._watched = /* @__PURE__ */ new Map();
|
|
31456
|
-
this._pendingWrites = /* @__PURE__ */ new Map();
|
|
31457
|
-
this._pendingUnlinks = /* @__PURE__ */ new Map();
|
|
31458
|
-
this._readyCount = 0;
|
|
31459
|
-
this._readyEmitted = false;
|
|
31460
|
-
const awf = _opts.awaitWriteFinish;
|
|
31461
|
-
const DEF_AWF = { stabilityThreshold: 2e3, pollInterval: 100 };
|
|
31462
|
-
const opts = {
|
|
31463
|
-
// Defaults
|
|
31464
|
-
persistent: true,
|
|
31465
|
-
ignoreInitial: false,
|
|
31466
|
-
ignorePermissionErrors: false,
|
|
31467
|
-
interval: 100,
|
|
31468
|
-
binaryInterval: 300,
|
|
31469
|
-
followSymlinks: true,
|
|
31470
|
-
usePolling: false,
|
|
31471
|
-
// useAsync: false,
|
|
31472
|
-
atomic: true,
|
|
31473
|
-
// NOTE: overwritten later (depends on usePolling)
|
|
31474
|
-
..._opts,
|
|
31475
|
-
// Change format
|
|
31476
|
-
ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
|
|
31477
|
-
awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === "object" ? { ...DEF_AWF, ...awf } : false
|
|
31478
|
-
};
|
|
31479
|
-
if (isIBMi)
|
|
31480
|
-
opts.usePolling = true;
|
|
31481
|
-
if (opts.atomic === void 0)
|
|
31482
|
-
opts.atomic = !opts.usePolling;
|
|
31483
|
-
const envPoll = process.env.CHOKIDAR_USEPOLLING;
|
|
31484
|
-
if (envPoll !== void 0) {
|
|
31485
|
-
const envLower = envPoll.toLowerCase();
|
|
31486
|
-
if (envLower === "false" || envLower === "0")
|
|
31487
|
-
opts.usePolling = false;
|
|
31488
|
-
else if (envLower === "true" || envLower === "1")
|
|
31489
|
-
opts.usePolling = true;
|
|
31490
|
-
else
|
|
31491
|
-
opts.usePolling = !!envLower;
|
|
31492
|
-
}
|
|
31493
|
-
const envInterval = process.env.CHOKIDAR_INTERVAL;
|
|
31494
|
-
if (envInterval)
|
|
31495
|
-
opts.interval = Number.parseInt(envInterval, 10);
|
|
31496
|
-
let readyCalls = 0;
|
|
31497
|
-
this._emitReady = () => {
|
|
31498
|
-
readyCalls++;
|
|
31499
|
-
if (readyCalls >= this._readyCount) {
|
|
31500
|
-
this._emitReady = EMPTY_FN;
|
|
31501
|
-
this._readyEmitted = true;
|
|
31502
|
-
process.nextTick(() => this.emit(EVENTS.READY));
|
|
31503
|
-
}
|
|
31504
|
-
};
|
|
31505
|
-
this._emitRaw = (...args) => this.emit(EVENTS.RAW, ...args);
|
|
31506
|
-
this._boundRemove = this._remove.bind(this);
|
|
31507
|
-
this.options = opts;
|
|
31508
|
-
this._nodeFsHandler = new NodeFsHandler(this);
|
|
31509
|
-
Object.freeze(opts);
|
|
31510
|
-
}
|
|
31511
|
-
_addIgnoredPath(matcher) {
|
|
31512
|
-
if (isMatcherObject(matcher)) {
|
|
31513
|
-
for (const ignored of this._ignoredPaths) {
|
|
31514
|
-
if (isMatcherObject(ignored) && ignored.path === matcher.path && ignored.recursive === matcher.recursive) {
|
|
31515
|
-
return;
|
|
31516
|
-
}
|
|
31517
|
-
}
|
|
31518
|
-
}
|
|
31519
|
-
this._ignoredPaths.add(matcher);
|
|
31520
|
-
}
|
|
31521
|
-
_removeIgnoredPath(matcher) {
|
|
31522
|
-
this._ignoredPaths.delete(matcher);
|
|
31523
|
-
if (typeof matcher === "string") {
|
|
31524
|
-
for (const ignored of this._ignoredPaths) {
|
|
31525
|
-
if (isMatcherObject(ignored) && ignored.path === matcher) {
|
|
31526
|
-
this._ignoredPaths.delete(ignored);
|
|
31527
|
-
}
|
|
31528
|
-
}
|
|
31529
|
-
}
|
|
31530
|
-
}
|
|
31531
|
-
// Public methods
|
|
31532
|
-
/**
|
|
31533
|
-
* Adds paths to be watched on an existing FSWatcher instance.
|
|
31534
|
-
* @param paths_ file or file list. Other arguments are unused
|
|
31535
|
-
*/
|
|
31536
|
-
add(paths_, _origAdd, _internal) {
|
|
31537
|
-
const { cwd: cwd3 } = this.options;
|
|
31538
|
-
this.closed = false;
|
|
31539
|
-
this._closePromise = void 0;
|
|
31540
|
-
let paths = unifyPaths(paths_);
|
|
31541
|
-
if (cwd3) {
|
|
31542
|
-
paths = paths.map((path24) => {
|
|
31543
|
-
const absPath = getAbsolutePath(path24, cwd3);
|
|
31544
|
-
return absPath;
|
|
31545
|
-
});
|
|
31546
|
-
}
|
|
31547
|
-
paths.forEach((path24) => {
|
|
31548
|
-
this._removeIgnoredPath(path24);
|
|
31549
|
-
});
|
|
31550
|
-
this._userIgnored = void 0;
|
|
31551
|
-
if (!this._readyCount)
|
|
31552
|
-
this._readyCount = 0;
|
|
31553
|
-
this._readyCount += paths.length;
|
|
31554
|
-
Promise.all(paths.map(async (path24) => {
|
|
31555
|
-
const res = await this._nodeFsHandler._addToNodeFs(path24, !_internal, void 0, 0, _origAdd);
|
|
31556
|
-
if (res)
|
|
31557
|
-
this._emitReady();
|
|
31558
|
-
return res;
|
|
31559
|
-
})).then((results) => {
|
|
31560
|
-
if (this.closed)
|
|
31561
|
-
return;
|
|
31562
|
-
results.forEach((item) => {
|
|
31563
|
-
if (item)
|
|
31564
|
-
this.add(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
|
|
31565
|
-
});
|
|
31566
|
-
});
|
|
31567
|
-
return this;
|
|
31568
|
-
}
|
|
31569
|
-
/**
|
|
31570
|
-
* Close watchers or start ignoring events from specified paths.
|
|
31571
|
-
*/
|
|
31572
|
-
unwatch(paths_) {
|
|
31573
|
-
if (this.closed)
|
|
31574
|
-
return this;
|
|
31575
|
-
const paths = unifyPaths(paths_);
|
|
31576
|
-
const { cwd: cwd3 } = this.options;
|
|
31577
|
-
paths.forEach((path24) => {
|
|
31578
|
-
if (!sysPath2.isAbsolute(path24) && !this._closers.has(path24)) {
|
|
31579
|
-
if (cwd3)
|
|
31580
|
-
path24 = sysPath2.join(cwd3, path24);
|
|
31581
|
-
path24 = sysPath2.resolve(path24);
|
|
31582
|
-
}
|
|
31583
|
-
this._closePath(path24);
|
|
31584
|
-
this._addIgnoredPath(path24);
|
|
31585
|
-
if (this._watched.has(path24)) {
|
|
31586
|
-
this._addIgnoredPath({
|
|
31587
|
-
path: path24,
|
|
31588
|
-
recursive: true
|
|
31589
|
-
});
|
|
31590
|
-
}
|
|
31591
|
-
this._userIgnored = void 0;
|
|
31592
|
-
});
|
|
31593
|
-
return this;
|
|
31594
|
-
}
|
|
31595
|
-
/**
|
|
31596
|
-
* Close watchers and remove all listeners from watched paths.
|
|
31597
|
-
*/
|
|
31598
|
-
close() {
|
|
31599
|
-
if (this._closePromise) {
|
|
31600
|
-
return this._closePromise;
|
|
31601
|
-
}
|
|
31602
|
-
this.closed = true;
|
|
31603
|
-
this.removeAllListeners();
|
|
31604
|
-
const closers = [];
|
|
31605
|
-
this._closers.forEach((closerList) => closerList.forEach((closer) => {
|
|
31606
|
-
const promise2 = closer();
|
|
31607
|
-
if (promise2 instanceof Promise)
|
|
31608
|
-
closers.push(promise2);
|
|
31609
|
-
}));
|
|
31610
|
-
this._streams.forEach((stream) => stream.destroy());
|
|
31611
|
-
this._userIgnored = void 0;
|
|
31612
|
-
this._readyCount = 0;
|
|
31613
|
-
this._readyEmitted = false;
|
|
31614
|
-
this._watched.forEach((dirent) => dirent.dispose());
|
|
31615
|
-
this._closers.clear();
|
|
31616
|
-
this._watched.clear();
|
|
31617
|
-
this._streams.clear();
|
|
31618
|
-
this._symlinkPaths.clear();
|
|
31619
|
-
this._throttled.clear();
|
|
31620
|
-
this._closePromise = closers.length ? Promise.all(closers).then(() => void 0) : Promise.resolve();
|
|
31621
|
-
return this._closePromise;
|
|
31622
|
-
}
|
|
31623
|
-
/**
|
|
31624
|
-
* Expose list of watched paths
|
|
31625
|
-
* @returns for chaining
|
|
31626
|
-
*/
|
|
31627
|
-
getWatched() {
|
|
31628
|
-
const watchList = {};
|
|
31629
|
-
this._watched.forEach((entry, dir) => {
|
|
31630
|
-
const key = this.options.cwd ? sysPath2.relative(this.options.cwd, dir) : dir;
|
|
31631
|
-
const index = key || ONE_DOT;
|
|
31632
|
-
watchList[index] = entry.getChildren().sort();
|
|
31633
|
-
});
|
|
31634
|
-
return watchList;
|
|
31635
|
-
}
|
|
31636
|
-
emitWithAll(event, args) {
|
|
31637
|
-
this.emit(event, ...args);
|
|
31638
|
-
if (event !== EVENTS.ERROR)
|
|
31639
|
-
this.emit(EVENTS.ALL, event, ...args);
|
|
31640
|
-
}
|
|
31641
|
-
// Common helpers
|
|
31642
|
-
// --------------
|
|
31643
|
-
/**
|
|
31644
|
-
* Normalize and emit events.
|
|
31645
|
-
* Calling _emit DOES NOT MEAN emit() would be called!
|
|
31646
|
-
* @param event Type of event
|
|
31647
|
-
* @param path File or directory path
|
|
31648
|
-
* @param stats arguments to be passed with event
|
|
31649
|
-
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
31650
|
-
*/
|
|
31651
|
-
async _emit(event, path24, stats) {
|
|
31652
|
-
if (this.closed)
|
|
31653
|
-
return;
|
|
31654
|
-
const opts = this.options;
|
|
31655
|
-
if (isWindows)
|
|
31656
|
-
path24 = sysPath2.normalize(path24);
|
|
31657
|
-
if (opts.cwd)
|
|
31658
|
-
path24 = sysPath2.relative(opts.cwd, path24);
|
|
31659
|
-
const args = [path24];
|
|
31660
|
-
if (stats != null)
|
|
31661
|
-
args.push(stats);
|
|
31662
|
-
const awf = opts.awaitWriteFinish;
|
|
31663
|
-
let pw;
|
|
31664
|
-
if (awf && (pw = this._pendingWrites.get(path24))) {
|
|
31665
|
-
pw.lastChange = /* @__PURE__ */ new Date();
|
|
31666
|
-
return this;
|
|
31667
|
-
}
|
|
31668
|
-
if (opts.atomic) {
|
|
31669
|
-
if (event === EVENTS.UNLINK) {
|
|
31670
|
-
this._pendingUnlinks.set(path24, [event, ...args]);
|
|
31671
|
-
setTimeout(() => {
|
|
31672
|
-
this._pendingUnlinks.forEach((entry, path25) => {
|
|
31673
|
-
this.emit(...entry);
|
|
31674
|
-
this.emit(EVENTS.ALL, ...entry);
|
|
31675
|
-
this._pendingUnlinks.delete(path25);
|
|
31676
|
-
});
|
|
31677
|
-
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
31678
|
-
return this;
|
|
31679
|
-
}
|
|
31680
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(path24)) {
|
|
31681
|
-
event = EVENTS.CHANGE;
|
|
31682
|
-
this._pendingUnlinks.delete(path24);
|
|
31683
|
-
}
|
|
31684
|
-
}
|
|
31685
|
-
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
31686
|
-
const awfEmit = (err, stats2) => {
|
|
31687
|
-
if (err) {
|
|
31688
|
-
event = EVENTS.ERROR;
|
|
31689
|
-
args[0] = err;
|
|
31690
|
-
this.emitWithAll(event, args);
|
|
31691
|
-
} else if (stats2) {
|
|
31692
|
-
if (args.length > 1) {
|
|
31693
|
-
args[1] = stats2;
|
|
31694
|
-
} else {
|
|
31695
|
-
args.push(stats2);
|
|
31696
|
-
}
|
|
31697
|
-
this.emitWithAll(event, args);
|
|
31698
|
-
}
|
|
31699
|
-
};
|
|
31700
|
-
this._awaitWriteFinish(path24, awf.stabilityThreshold, event, awfEmit);
|
|
31701
|
-
return this;
|
|
31702
|
-
}
|
|
31703
|
-
if (event === EVENTS.CHANGE) {
|
|
31704
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE, path24, 50);
|
|
31705
|
-
if (isThrottled)
|
|
31706
|
-
return this;
|
|
31707
|
-
}
|
|
31708
|
-
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
31709
|
-
const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path24) : path24;
|
|
31710
|
-
let stats2;
|
|
31711
|
-
try {
|
|
31712
|
-
stats2 = await stat3(fullPath);
|
|
31713
|
-
} catch (err) {
|
|
31714
|
-
}
|
|
31715
|
-
if (!stats2 || this.closed)
|
|
31716
|
-
return;
|
|
31717
|
-
args.push(stats2);
|
|
31718
|
-
}
|
|
31719
|
-
this.emitWithAll(event, args);
|
|
31720
|
-
return this;
|
|
31721
|
-
}
|
|
31722
|
-
/**
|
|
31723
|
-
* Common handler for errors
|
|
31724
|
-
* @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
31725
|
-
*/
|
|
31726
|
-
_handleError(error40) {
|
|
31727
|
-
const code = error40 && error40.code;
|
|
31728
|
-
if (error40 && code !== "ENOENT" && code !== "ENOTDIR" && (!this.options.ignorePermissionErrors || code !== "EPERM" && code !== "EACCES")) {
|
|
31729
|
-
this.emit(EVENTS.ERROR, error40);
|
|
31730
|
-
}
|
|
31731
|
-
return error40 || this.closed;
|
|
31732
|
-
}
|
|
31733
|
-
/**
|
|
31734
|
-
* Helper utility for throttling
|
|
31735
|
-
* @param actionType type being throttled
|
|
31736
|
-
* @param path being acted upon
|
|
31737
|
-
* @param timeout duration of time to suppress duplicate actions
|
|
31738
|
-
* @returns tracking object or false if action should be suppressed
|
|
31739
|
-
*/
|
|
31740
|
-
_throttle(actionType, path24, timeout) {
|
|
31741
|
-
if (!this._throttled.has(actionType)) {
|
|
31742
|
-
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
31743
|
-
}
|
|
31744
|
-
const action = this._throttled.get(actionType);
|
|
31745
|
-
if (!action)
|
|
31746
|
-
throw new Error("invalid throttle");
|
|
31747
|
-
const actionPath = action.get(path24);
|
|
31748
|
-
if (actionPath) {
|
|
31749
|
-
actionPath.count++;
|
|
31750
|
-
return false;
|
|
31751
|
-
}
|
|
31752
|
-
let timeoutObject;
|
|
31753
|
-
const clear = () => {
|
|
31754
|
-
const item = action.get(path24);
|
|
31755
|
-
const count = item ? item.count : 0;
|
|
31756
|
-
action.delete(path24);
|
|
31757
|
-
clearTimeout(timeoutObject);
|
|
31758
|
-
if (item)
|
|
31759
|
-
clearTimeout(item.timeoutObject);
|
|
31760
|
-
return count;
|
|
31761
|
-
};
|
|
31762
|
-
timeoutObject = setTimeout(clear, timeout);
|
|
31763
|
-
const thr = { timeoutObject, clear, count: 0 };
|
|
31764
|
-
action.set(path24, thr);
|
|
31765
|
-
return thr;
|
|
31766
|
-
}
|
|
31767
|
-
_incrReadyCount() {
|
|
31768
|
-
return this._readyCount++;
|
|
31769
|
-
}
|
|
31770
|
-
/**
|
|
31771
|
-
* Awaits write operation to finish.
|
|
31772
|
-
* Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
|
|
31773
|
-
* @param path being acted upon
|
|
31774
|
-
* @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
|
|
31775
|
-
* @param event
|
|
31776
|
-
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
31777
|
-
*/
|
|
31778
|
-
_awaitWriteFinish(path24, threshold, event, awfEmit) {
|
|
31779
|
-
const awf = this.options.awaitWriteFinish;
|
|
31780
|
-
if (typeof awf !== "object")
|
|
31781
|
-
return;
|
|
31782
|
-
const pollInterval = awf.pollInterval;
|
|
31783
|
-
let timeoutHandler;
|
|
31784
|
-
let fullPath = path24;
|
|
31785
|
-
if (this.options.cwd && !sysPath2.isAbsolute(path24)) {
|
|
31786
|
-
fullPath = sysPath2.join(this.options.cwd, path24);
|
|
31787
|
-
}
|
|
31788
|
-
const now = /* @__PURE__ */ new Date();
|
|
31789
|
-
const writes = this._pendingWrites;
|
|
31790
|
-
function awaitWriteFinishFn(prevStat) {
|
|
31791
|
-
statcb(fullPath, (err, curStat) => {
|
|
31792
|
-
if (err || !writes.has(path24)) {
|
|
31793
|
-
if (err && err.code !== "ENOENT")
|
|
31794
|
-
awfEmit(err);
|
|
31795
|
-
return;
|
|
31796
|
-
}
|
|
31797
|
-
const now2 = Number(/* @__PURE__ */ new Date());
|
|
31798
|
-
if (prevStat && curStat.size !== prevStat.size) {
|
|
31799
|
-
writes.get(path24).lastChange = now2;
|
|
31800
|
-
}
|
|
31801
|
-
const pw = writes.get(path24);
|
|
31802
|
-
const df = now2 - pw.lastChange;
|
|
31803
|
-
if (df >= threshold) {
|
|
31804
|
-
writes.delete(path24);
|
|
31805
|
-
awfEmit(void 0, curStat);
|
|
31806
|
-
} else {
|
|
31807
|
-
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
31808
|
-
}
|
|
31809
|
-
});
|
|
31810
|
-
}
|
|
31811
|
-
if (!writes.has(path24)) {
|
|
31812
|
-
writes.set(path24, {
|
|
31813
|
-
lastChange: now,
|
|
31814
|
-
cancelWait: () => {
|
|
31815
|
-
writes.delete(path24);
|
|
31816
|
-
clearTimeout(timeoutHandler);
|
|
31817
|
-
return event;
|
|
31818
|
-
}
|
|
31819
|
-
});
|
|
31820
|
-
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
|
|
31821
|
-
}
|
|
31822
|
-
}
|
|
31823
|
-
/**
|
|
31824
|
-
* Determines whether user has asked to ignore this path.
|
|
31825
|
-
*/
|
|
31826
|
-
_isIgnored(path24, stats) {
|
|
31827
|
-
if (this.options.atomic && DOT_RE.test(path24))
|
|
31828
|
-
return true;
|
|
31829
|
-
if (!this._userIgnored) {
|
|
31830
|
-
const { cwd: cwd3 } = this.options;
|
|
31831
|
-
const ign = this.options.ignored;
|
|
31832
|
-
const ignored = (ign || []).map(normalizeIgnored(cwd3));
|
|
31833
|
-
const ignoredPaths = [...this._ignoredPaths];
|
|
31834
|
-
const list = [...ignoredPaths.map(normalizeIgnored(cwd3)), ...ignored];
|
|
31835
|
-
this._userIgnored = anymatch(list, void 0);
|
|
31836
|
-
}
|
|
31837
|
-
return this._userIgnored(path24, stats);
|
|
31838
|
-
}
|
|
31839
|
-
_isntIgnored(path24, stat4) {
|
|
31840
|
-
return !this._isIgnored(path24, stat4);
|
|
31841
|
-
}
|
|
31842
|
-
/**
|
|
31843
|
-
* Provides a set of common helpers and properties relating to symlink handling.
|
|
31844
|
-
* @param path file or directory pattern being watched
|
|
31845
|
-
*/
|
|
31846
|
-
_getWatchHelpers(path24) {
|
|
31847
|
-
return new WatchHelper(path24, this.options.followSymlinks, this);
|
|
31848
|
-
}
|
|
31849
|
-
// Directory helpers
|
|
31850
|
-
// -----------------
|
|
31851
|
-
/**
|
|
31852
|
-
* Provides directory tracking objects
|
|
31853
|
-
* @param directory path of the directory
|
|
31854
|
-
*/
|
|
31855
|
-
_getWatchedDir(directory) {
|
|
31856
|
-
const dir = sysPath2.resolve(directory);
|
|
31857
|
-
if (!this._watched.has(dir))
|
|
31858
|
-
this._watched.set(dir, new DirEntry(dir, this._boundRemove));
|
|
31859
|
-
return this._watched.get(dir);
|
|
31860
|
-
}
|
|
31861
|
-
// File helpers
|
|
31862
|
-
// ------------
|
|
31863
|
-
/**
|
|
31864
|
-
* Check for read permissions: https://stackoverflow.com/a/11781404/1358405
|
|
31865
|
-
*/
|
|
31866
|
-
_hasReadPermissions(stats) {
|
|
31867
|
-
if (this.options.ignorePermissionErrors)
|
|
31868
|
-
return true;
|
|
31869
|
-
return Boolean(Number(stats.mode) & 256);
|
|
31870
|
-
}
|
|
31871
|
-
/**
|
|
31872
|
-
* Handles emitting unlink events for
|
|
31873
|
-
* files and directories, and via recursion, for
|
|
31874
|
-
* files and directories within directories that are unlinked
|
|
31875
|
-
* @param directory within which the following item is located
|
|
31876
|
-
* @param item base path of item/directory
|
|
31877
|
-
*/
|
|
31878
|
-
_remove(directory, item, isDirectory) {
|
|
31879
|
-
const path24 = sysPath2.join(directory, item);
|
|
31880
|
-
const fullPath = sysPath2.resolve(path24);
|
|
31881
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path24) || this._watched.has(fullPath);
|
|
31882
|
-
if (!this._throttle("remove", path24, 100))
|
|
31883
|
-
return;
|
|
31884
|
-
if (!isDirectory && this._watched.size === 1) {
|
|
31885
|
-
this.add(directory, item, true);
|
|
31886
|
-
}
|
|
31887
|
-
const wp = this._getWatchedDir(path24);
|
|
31888
|
-
const nestedDirectoryChildren = wp.getChildren();
|
|
31889
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(path24, nested));
|
|
31890
|
-
const parent = this._getWatchedDir(directory);
|
|
31891
|
-
const wasTracked = parent.has(item);
|
|
31892
|
-
parent.remove(item);
|
|
31893
|
-
if (this._symlinkPaths.has(fullPath)) {
|
|
31894
|
-
this._symlinkPaths.delete(fullPath);
|
|
31895
|
-
}
|
|
31896
|
-
let relPath = path24;
|
|
31897
|
-
if (this.options.cwd)
|
|
31898
|
-
relPath = sysPath2.relative(this.options.cwd, path24);
|
|
31899
|
-
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
31900
|
-
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
31901
|
-
if (event === EVENTS.ADD)
|
|
31902
|
-
return;
|
|
31903
|
-
}
|
|
31904
|
-
this._watched.delete(path24);
|
|
31905
|
-
this._watched.delete(fullPath);
|
|
31906
|
-
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
31907
|
-
if (wasTracked && !this._isIgnored(path24))
|
|
31908
|
-
this._emit(eventName, path24);
|
|
31909
|
-
this._closePath(path24);
|
|
31910
|
-
}
|
|
31911
|
-
/**
|
|
31912
|
-
* Closes all watchers for a path
|
|
31913
|
-
*/
|
|
31914
|
-
_closePath(path24) {
|
|
31915
|
-
this._closeFile(path24);
|
|
31916
|
-
const dir = sysPath2.dirname(path24);
|
|
31917
|
-
this._getWatchedDir(dir).remove(sysPath2.basename(path24));
|
|
31918
|
-
}
|
|
31919
|
-
/**
|
|
31920
|
-
* Closes only file-specific watchers
|
|
31921
|
-
*/
|
|
31922
|
-
_closeFile(path24) {
|
|
31923
|
-
const closers = this._closers.get(path24);
|
|
31924
|
-
if (!closers)
|
|
31925
|
-
return;
|
|
31926
|
-
closers.forEach((closer) => closer());
|
|
31927
|
-
this._closers.delete(path24);
|
|
31928
|
-
}
|
|
31929
|
-
_addPathCloser(path24, closer) {
|
|
31930
|
-
if (!closer)
|
|
31931
|
-
return;
|
|
31932
|
-
let list = this._closers.get(path24);
|
|
31933
|
-
if (!list) {
|
|
31934
|
-
list = [];
|
|
31935
|
-
this._closers.set(path24, list);
|
|
31936
|
-
}
|
|
31937
|
-
list.push(closer);
|
|
31938
|
-
}
|
|
31939
|
-
_readdirp(root, opts) {
|
|
31940
|
-
if (this.closed)
|
|
31941
|
-
return;
|
|
31942
|
-
const options = { type: EVENTS.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
|
|
31943
|
-
let stream = readdirp(root, options);
|
|
31944
|
-
this._streams.add(stream);
|
|
31945
|
-
stream.once(STR_CLOSE, () => {
|
|
31946
|
-
stream = void 0;
|
|
31947
|
-
});
|
|
31948
|
-
stream.once(STR_END, () => {
|
|
31949
|
-
if (stream) {
|
|
31950
|
-
this._streams.delete(stream);
|
|
31951
|
-
stream = void 0;
|
|
31952
|
-
}
|
|
31953
|
-
});
|
|
31954
|
-
return stream;
|
|
31955
|
-
}
|
|
31956
|
-
};
|
|
31957
|
-
function watch(paths, options = {}) {
|
|
31958
|
-
const watcher = new FSWatcher(options);
|
|
31959
|
-
watcher.add(paths);
|
|
31960
|
-
return watcher;
|
|
31961
|
-
}
|
|
31962
|
-
var esm_default = { watch, FSWatcher };
|
|
31963
|
-
|
|
31964
|
-
// src/files/watch-file-index.ts
|
|
31965
30489
|
var DEBOUNCE_MS = 900;
|
|
31966
30490
|
function shouldIgnoreRelative(rel) {
|
|
31967
30491
|
const n = rel.replace(/\\/g, "/");
|
|
@@ -31970,8 +30494,43 @@ function shouldIgnoreRelative(rel) {
|
|
|
31970
30494
|
if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
|
|
31971
30495
|
return false;
|
|
31972
30496
|
}
|
|
31973
|
-
function
|
|
31974
|
-
|
|
30497
|
+
function attachWatchErrorLog(w) {
|
|
30498
|
+
w.on("error", (err) => {
|
|
30499
|
+
console.error("[file-index] File watcher error:", err);
|
|
30500
|
+
});
|
|
30501
|
+
}
|
|
30502
|
+
function createFsWatcher(resolved, schedule) {
|
|
30503
|
+
const onEvent = (_event, filename) => {
|
|
30504
|
+
if (filename != null) {
|
|
30505
|
+
const rel = typeof filename === "string" ? filename.replace(/\\/g, "/") : filename.toString("utf8").replace(/\\/g, "/");
|
|
30506
|
+
if (shouldIgnoreRelative(rel)) return;
|
|
30507
|
+
}
|
|
30508
|
+
schedule();
|
|
30509
|
+
};
|
|
30510
|
+
try {
|
|
30511
|
+
const w = watch(resolved, { recursive: true }, onEvent);
|
|
30512
|
+
attachWatchErrorLog(w);
|
|
30513
|
+
return w;
|
|
30514
|
+
} catch (e) {
|
|
30515
|
+
const code = typeof e === "object" && e !== null && "code" in e ? e.code : void 0;
|
|
30516
|
+
if (code === "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM") {
|
|
30517
|
+
console.warn(
|
|
30518
|
+
"[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."
|
|
30519
|
+
);
|
|
30520
|
+
const w = watch(resolved, { recursive: false }, onEvent);
|
|
30521
|
+
attachWatchErrorLog(w);
|
|
30522
|
+
return w;
|
|
30523
|
+
}
|
|
30524
|
+
throw e;
|
|
30525
|
+
}
|
|
30526
|
+
}
|
|
30527
|
+
function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
|
|
30528
|
+
const resolved = path21.resolve(cwd);
|
|
30529
|
+
try {
|
|
30530
|
+
buildFileIndex(resolved);
|
|
30531
|
+
} catch (e) {
|
|
30532
|
+
console.error("[file-index] Initial index build failed:", e);
|
|
30533
|
+
}
|
|
31975
30534
|
let timer = null;
|
|
31976
30535
|
const runRebuild = () => {
|
|
31977
30536
|
try {
|
|
@@ -31987,27 +30546,13 @@ function startFileIndexWatcher(cwd3 = process.cwd()) {
|
|
|
31987
30546
|
runRebuild();
|
|
31988
30547
|
}, DEBOUNCE_MS);
|
|
31989
30548
|
};
|
|
31990
|
-
const watcher =
|
|
31991
|
-
cwd: resolved,
|
|
31992
|
-
ignoreInitial: true,
|
|
31993
|
-
persistent: true,
|
|
31994
|
-
ignored: (p) => {
|
|
31995
|
-
const rel = path21.isAbsolute(p) ? path21.relative(resolved, p).replace(/\\/g, "/") : p.replace(/\\/g, "/");
|
|
31996
|
-
return shouldIgnoreRelative(rel || ".");
|
|
31997
|
-
},
|
|
31998
|
-
awaitWriteFinish: { stabilityThreshold: 250, pollInterval: 100 }
|
|
31999
|
-
});
|
|
32000
|
-
watcher.on("add", schedule);
|
|
32001
|
-
watcher.on("change", schedule);
|
|
32002
|
-
watcher.on("unlink", schedule);
|
|
32003
|
-
watcher.on("addDir", schedule);
|
|
32004
|
-
watcher.on("unlinkDir", schedule);
|
|
30549
|
+
const watcher = createFsWatcher(resolved, schedule);
|
|
32005
30550
|
return () => {
|
|
32006
30551
|
if (timer) {
|
|
32007
30552
|
clearTimeout(timer);
|
|
32008
30553
|
timer = null;
|
|
32009
30554
|
}
|
|
32010
|
-
|
|
30555
|
+
watcher.close();
|
|
32011
30556
|
};
|
|
32012
30557
|
}
|
|
32013
30558
|
|
|
@@ -32031,18 +30576,20 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
32031
30576
|
|
|
32032
30577
|
// src/dev-servers/process/terminate-child-process.ts
|
|
32033
30578
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
32034
|
-
const exited = new Promise((
|
|
32035
|
-
proc.once("exit", () =>
|
|
30579
|
+
const exited = new Promise((resolve14) => {
|
|
30580
|
+
proc.once("exit", () => resolve14());
|
|
32036
30581
|
});
|
|
32037
|
-
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"})
|
|
30582
|
+
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
32038
30583
|
try {
|
|
32039
30584
|
proc.kill("SIGTERM");
|
|
32040
30585
|
} catch {
|
|
32041
30586
|
}
|
|
32042
|
-
await Promise.race([exited, new Promise((
|
|
30587
|
+
await Promise.race([exited, new Promise((resolve14) => setTimeout(resolve14, graceMs))]);
|
|
32043
30588
|
}
|
|
32044
30589
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
32045
|
-
log2(
|
|
30590
|
+
log2(
|
|
30591
|
+
`[dev-server] ${shortId} did not exit within ${graceMs}ms; sending SIGKILL (pid=${proc.pid ?? "?"}).`
|
|
30592
|
+
);
|
|
32046
30593
|
proc.removeAllListeners();
|
|
32047
30594
|
try {
|
|
32048
30595
|
proc.kill("SIGKILL");
|
|
@@ -32051,7 +30598,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
32051
30598
|
}
|
|
32052
30599
|
|
|
32053
30600
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
32054
|
-
import
|
|
30601
|
+
import fs17 from "node:fs";
|
|
32055
30602
|
|
|
32056
30603
|
// src/dev-servers/manager/forward-pipe.ts
|
|
32057
30604
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -32087,7 +30634,7 @@ function wireDevServerChildProcess(d) {
|
|
|
32087
30634
|
d.setPollInterval(void 0);
|
|
32088
30635
|
return;
|
|
32089
30636
|
}
|
|
32090
|
-
|
|
30637
|
+
fs17.readFile(d.mergedLogPath, (err, buf) => {
|
|
32091
30638
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
32092
30639
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
32093
30640
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -32112,7 +30659,7 @@ function wireDevServerChildProcess(d) {
|
|
|
32112
30659
|
d.rmMergedCleanupDir(cleanupDir);
|
|
32113
30660
|
}
|
|
32114
30661
|
if (signal) {
|
|
32115
|
-
d.log(`[dev-server] ${title} stopped (signal ${String(signal)})
|
|
30662
|
+
d.log(`[dev-server] ${title} stopped (signal: ${String(signal)}).`);
|
|
32116
30663
|
} else if (code !== null && code !== 0) {
|
|
32117
30664
|
const errTail = d.stderrTail.getTail().slice(-3).join("\n");
|
|
32118
30665
|
d.log(`[dev-server] ${title} exited with code ${code}${errTail ? `
|
|
@@ -32125,7 +30672,7 @@ ${errTail}` : ""}`);
|
|
|
32125
30672
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
32126
30673
|
};
|
|
32127
30674
|
if (mergedPath) {
|
|
32128
|
-
|
|
30675
|
+
fs17.readFile(mergedPath, (err, buf) => {
|
|
32129
30676
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
32130
30677
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
32131
30678
|
if (chunk.length > 0) {
|
|
@@ -32227,13 +30774,13 @@ function parseDevServerDefs(servers) {
|
|
|
32227
30774
|
}
|
|
32228
30775
|
|
|
32229
30776
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
32230
|
-
import
|
|
30777
|
+
import fs18 from "node:fs";
|
|
32231
30778
|
function isSpawnEbadf(e) {
|
|
32232
30779
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
32233
30780
|
}
|
|
32234
30781
|
function rmDirQuiet(dir) {
|
|
32235
30782
|
try {
|
|
32236
|
-
|
|
30783
|
+
fs18.rmSync(dir, { recursive: true, force: true });
|
|
32237
30784
|
} catch {
|
|
32238
30785
|
}
|
|
32239
30786
|
}
|
|
@@ -32241,7 +30788,7 @@ var cachedDevNullReadFd;
|
|
|
32241
30788
|
function devNullReadFd() {
|
|
32242
30789
|
if (cachedDevNullReadFd === void 0) {
|
|
32243
30790
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
32244
|
-
cachedDevNullReadFd =
|
|
30791
|
+
cachedDevNullReadFd = fs18.openSync(devPath, "r");
|
|
32245
30792
|
}
|
|
32246
30793
|
return cachedDevNullReadFd;
|
|
32247
30794
|
}
|
|
@@ -32251,7 +30798,7 @@ function pipedStdoutStderrFor(attemptStdio) {
|
|
|
32251
30798
|
|
|
32252
30799
|
// src/dev-servers/manager/shell-spawn/try-spawn-piped-via-sh.ts
|
|
32253
30800
|
import { spawn as spawn5 } from "node:child_process";
|
|
32254
|
-
function trySpawnPipedViaSh(command, env,
|
|
30801
|
+
function trySpawnPipedViaSh(command, env, cwd, signal) {
|
|
32255
30802
|
const attempts = [
|
|
32256
30803
|
{ stdio: [devNullReadFd(), "pipe", "pipe"], endStdin: false },
|
|
32257
30804
|
{ stdio: ["ignore", "pipe", "pipe"], endStdin: true },
|
|
@@ -32262,7 +30809,7 @@ function trySpawnPipedViaSh(command, env, cwd3, signal) {
|
|
|
32262
30809
|
const attempt = attempts[i];
|
|
32263
30810
|
const opts = {
|
|
32264
30811
|
env,
|
|
32265
|
-
cwd
|
|
30812
|
+
cwd,
|
|
32266
30813
|
stdio: attempt.stdio,
|
|
32267
30814
|
...signal ? { signal } : {}
|
|
32268
30815
|
};
|
|
@@ -32294,11 +30841,11 @@ function trySpawnPipedViaSh(command, env, cwd3, signal) {
|
|
|
32294
30841
|
|
|
32295
30842
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-true-piped.ts
|
|
32296
30843
|
import { spawn as spawn6 } from "node:child_process";
|
|
32297
|
-
function trySpawnShellTruePiped(command, env,
|
|
30844
|
+
function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
32298
30845
|
try {
|
|
32299
30846
|
const opts = {
|
|
32300
30847
|
env,
|
|
32301
|
-
cwd
|
|
30848
|
+
cwd,
|
|
32302
30849
|
stdio: [devNullFd, "pipe", "pipe"],
|
|
32303
30850
|
shell: true,
|
|
32304
30851
|
...signal ? { signal } : {}
|
|
@@ -32315,15 +30862,15 @@ function trySpawnShellTruePiped(command, env, cwd3, devNullFd, signal) {
|
|
|
32315
30862
|
|
|
32316
30863
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
32317
30864
|
import { spawn as spawn7 } from "node:child_process";
|
|
32318
|
-
import
|
|
30865
|
+
import fs19 from "node:fs";
|
|
32319
30866
|
import { tmpdir } from "node:os";
|
|
32320
30867
|
import path22 from "node:path";
|
|
32321
|
-
function trySpawnMergedLogFile(command, env,
|
|
32322
|
-
const tmpRoot =
|
|
30868
|
+
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
30869
|
+
const tmpRoot = fs19.mkdtempSync(path22.join(tmpdir(), "ba-devsrv-log-"));
|
|
32323
30870
|
const logPath = path22.join(tmpRoot, "combined.log");
|
|
32324
30871
|
let logFd;
|
|
32325
30872
|
try {
|
|
32326
|
-
logFd =
|
|
30873
|
+
logFd = fs19.openSync(logPath, "a");
|
|
32327
30874
|
} catch {
|
|
32328
30875
|
rmDirQuiet(tmpRoot);
|
|
32329
30876
|
return null;
|
|
@@ -32334,15 +30881,15 @@ function trySpawnMergedLogFile(command, env, cwd3, signal) {
|
|
|
32334
30881
|
if (process.platform === "win32") {
|
|
32335
30882
|
proc = spawn7(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", command], {
|
|
32336
30883
|
env,
|
|
32337
|
-
cwd
|
|
30884
|
+
cwd,
|
|
32338
30885
|
stdio,
|
|
32339
30886
|
windowsHide: true,
|
|
32340
30887
|
...signal ? { signal } : {}
|
|
32341
30888
|
});
|
|
32342
30889
|
} else {
|
|
32343
|
-
proc = spawn7("/bin/sh", ["-c", command], { env, cwd
|
|
30890
|
+
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
32344
30891
|
}
|
|
32345
|
-
|
|
30892
|
+
fs19.closeSync(logFd);
|
|
32346
30893
|
return {
|
|
32347
30894
|
proc,
|
|
32348
30895
|
pipedStdoutStderr: true,
|
|
@@ -32351,7 +30898,7 @@ function trySpawnMergedLogFile(command, env, cwd3, signal) {
|
|
|
32351
30898
|
};
|
|
32352
30899
|
} catch (e) {
|
|
32353
30900
|
try {
|
|
32354
|
-
|
|
30901
|
+
fs19.closeSync(logFd);
|
|
32355
30902
|
} catch {
|
|
32356
30903
|
}
|
|
32357
30904
|
rmDirQuiet(tmpRoot);
|
|
@@ -32362,25 +30909,25 @@ function trySpawnMergedLogFile(command, env, cwd3, signal) {
|
|
|
32362
30909
|
|
|
32363
30910
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
32364
30911
|
import { spawn as spawn8 } from "node:child_process";
|
|
32365
|
-
import
|
|
30912
|
+
import fs20 from "node:fs";
|
|
32366
30913
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
32367
30914
|
import path23 from "node:path";
|
|
32368
30915
|
function shSingleQuote(s) {
|
|
32369
30916
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
32370
30917
|
}
|
|
32371
|
-
function trySpawnShellScriptLogRedirectUnix(command, env,
|
|
32372
|
-
const tmpRoot =
|
|
30918
|
+
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
30919
|
+
const tmpRoot = fs20.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
32373
30920
|
const logPath = path23.join(tmpRoot, "combined.log");
|
|
32374
30921
|
const innerPath = path23.join(tmpRoot, "_cmd.sh");
|
|
32375
30922
|
const runnerPath = path23.join(tmpRoot, "_run.sh");
|
|
32376
30923
|
try {
|
|
32377
|
-
|
|
30924
|
+
fs20.writeFileSync(innerPath, `#!/bin/sh
|
|
32378
30925
|
${command}
|
|
32379
30926
|
`);
|
|
32380
|
-
|
|
30927
|
+
fs20.writeFileSync(
|
|
32381
30928
|
runnerPath,
|
|
32382
30929
|
`#!/bin/sh
|
|
32383
|
-
cd ${shSingleQuote(
|
|
30930
|
+
cd ${shSingleQuote(cwd)}
|
|
32384
30931
|
/bin/sh ${shSingleQuote(innerPath)} >>${shSingleQuote(logPath)} 2>&1
|
|
32385
30932
|
`
|
|
32386
30933
|
);
|
|
@@ -32402,17 +30949,17 @@ cd ${shSingleQuote(cwd3)}
|
|
|
32402
30949
|
throw e;
|
|
32403
30950
|
}
|
|
32404
30951
|
}
|
|
32405
|
-
function trySpawnShellScriptLogRedirectWin(command, env,
|
|
32406
|
-
const tmpRoot =
|
|
30952
|
+
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
30953
|
+
const tmpRoot = fs20.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
32407
30954
|
const logPath = path23.join(tmpRoot, "combined.log");
|
|
32408
30955
|
const runnerPath = path23.join(tmpRoot, "_run.bat");
|
|
32409
30956
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
32410
30957
|
const com = process.env.ComSpec || "cmd.exe";
|
|
32411
30958
|
try {
|
|
32412
|
-
|
|
30959
|
+
fs20.writeFileSync(
|
|
32413
30960
|
runnerPath,
|
|
32414
30961
|
`@ECHO OFF\r
|
|
32415
|
-
CD /D ${q(
|
|
30962
|
+
CD /D ${q(cwd)}\r
|
|
32416
30963
|
${command} >> ${q(logPath)} 2>&1\r
|
|
32417
30964
|
`
|
|
32418
30965
|
);
|
|
@@ -32438,10 +30985,10 @@ ${command} >> ${q(logPath)} 2>&1\r
|
|
|
32438
30985
|
|
|
32439
30986
|
// src/dev-servers/manager/shell-spawn/try-spawn-inherit.ts
|
|
32440
30987
|
import { spawn as spawn9 } from "node:child_process";
|
|
32441
|
-
function trySpawnInheritStdio(command, env,
|
|
30988
|
+
function trySpawnInheritStdio(command, env, cwd, signal) {
|
|
32442
30989
|
const opts = {
|
|
32443
30990
|
env,
|
|
32444
|
-
cwd
|
|
30991
|
+
cwd,
|
|
32445
30992
|
stdio: "inherit",
|
|
32446
30993
|
...signal ? { signal } : {}
|
|
32447
30994
|
};
|
|
@@ -32457,27 +31004,27 @@ function trySpawnInheritStdio(command, env, cwd3, signal) {
|
|
|
32457
31004
|
}
|
|
32458
31005
|
|
|
32459
31006
|
// src/dev-servers/manager/shell-spawn/shell-spawn.ts
|
|
32460
|
-
function shellSpawn(command, env,
|
|
31007
|
+
function shellSpawn(command, env, cwd, options) {
|
|
32461
31008
|
const signal = options?.signal;
|
|
32462
|
-
const piped = trySpawnPipedViaSh(command, env,
|
|
31009
|
+
const piped = trySpawnPipedViaSh(command, env, cwd, signal);
|
|
32463
31010
|
if (piped.ok) {
|
|
32464
31011
|
return piped.result;
|
|
32465
31012
|
}
|
|
32466
31013
|
let lastErr = piped.lastErr;
|
|
32467
|
-
const shellTrueProc = trySpawnShellTruePiped(command, env,
|
|
31014
|
+
const shellTrueProc = trySpawnShellTruePiped(command, env, cwd, devNullReadFd(), signal);
|
|
32468
31015
|
if (shellTrueProc) {
|
|
32469
31016
|
return { proc: shellTrueProc, pipedStdoutStderr: true };
|
|
32470
31017
|
}
|
|
32471
|
-
const fileCapture = trySpawnMergedLogFile(command, env,
|
|
31018
|
+
const fileCapture = trySpawnMergedLogFile(command, env, cwd, signal);
|
|
32472
31019
|
if (fileCapture) {
|
|
32473
31020
|
return fileCapture;
|
|
32474
31021
|
}
|
|
32475
|
-
const scriptCapture = process.platform === "win32" ? trySpawnShellScriptLogRedirectWin(command, env,
|
|
31022
|
+
const scriptCapture = process.platform === "win32" ? trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) : trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal);
|
|
32476
31023
|
if (scriptCapture) {
|
|
32477
31024
|
return scriptCapture;
|
|
32478
31025
|
}
|
|
32479
31026
|
try {
|
|
32480
|
-
return trySpawnInheritStdio(command, env,
|
|
31027
|
+
return trySpawnInheritStdio(command, env, cwd, signal);
|
|
32481
31028
|
} catch (e) {
|
|
32482
31029
|
throw lastErr instanceof Error ? lastErr : e instanceof Error ? e : new Error(String(e));
|
|
32483
31030
|
}
|
|
@@ -32535,9 +31082,11 @@ var DevServerManager = class {
|
|
|
32535
31082
|
abortControllersByServerId = /* @__PURE__ */ new Map();
|
|
32536
31083
|
getWs;
|
|
32537
31084
|
log;
|
|
31085
|
+
getBridgeCwd;
|
|
32538
31086
|
constructor(options) {
|
|
32539
31087
|
this.getWs = options.getWs;
|
|
32540
31088
|
this.log = options.log;
|
|
31089
|
+
this.getBridgeCwd = options.getBridgeCwd ?? (() => process.cwd());
|
|
32541
31090
|
}
|
|
32542
31091
|
attachFirehose(send) {
|
|
32543
31092
|
this.firehoseSend = send;
|
|
@@ -32661,7 +31210,7 @@ var DevServerManager = class {
|
|
|
32661
31210
|
this.sendStatus(serverId, "starting", void 0, emptyTails());
|
|
32662
31211
|
const ac = new AbortController();
|
|
32663
31212
|
this.abortControllersByServerId.set(serverId, ac);
|
|
32664
|
-
const
|
|
31213
|
+
const cwd = this.getBridgeCwd();
|
|
32665
31214
|
const childEnv = envForSpawn(process.env, def.env, def.ports);
|
|
32666
31215
|
const cmd = substituteCommand(def.command.trim(), childEnv);
|
|
32667
31216
|
const title = def.name.trim() || serverId.slice(0, 8);
|
|
@@ -32676,7 +31225,7 @@ var DevServerManager = class {
|
|
|
32676
31225
|
let mergedLogPath;
|
|
32677
31226
|
let mergedCleanupDir;
|
|
32678
31227
|
try {
|
|
32679
|
-
const spawned = shellSpawn(cmd, childEnv,
|
|
31228
|
+
const spawned = shellSpawn(cmd, childEnv, cwd, {
|
|
32680
31229
|
signal: ac.signal
|
|
32681
31230
|
});
|
|
32682
31231
|
proc = spawned.proc;
|
|
@@ -32685,7 +31234,7 @@ var DevServerManager = class {
|
|
|
32685
31234
|
mergedCleanupDir = spawned.mergedLogCleanupDir;
|
|
32686
31235
|
} catch (e) {
|
|
32687
31236
|
const msg = e instanceof Error ? e.message : String(e);
|
|
32688
|
-
this.log(`[dev-server] ${title}
|
|
31237
|
+
this.log(`[dev-server] Failed to start ${title}: ${msg}`);
|
|
32689
31238
|
this.abortControllersByServerId.delete(serverId);
|
|
32690
31239
|
this.sendStatus(serverId, "error", msg, emptyTails());
|
|
32691
31240
|
return;
|
|
@@ -32810,7 +31359,7 @@ function startStreamingProxy(ws, log2, pr) {
|
|
|
32810
31359
|
},
|
|
32811
31360
|
onEnd: () => sendWsMessage(ws, { type: "proxy_result_end", id: pr.id }),
|
|
32812
31361
|
onError: (error40) => {
|
|
32813
|
-
log2(`[Proxy and log service]
|
|
31362
|
+
log2(`[Proxy and log service] Streaming preview failed: ${error40}`);
|
|
32814
31363
|
sendWsMessage(ws, { type: "proxy_result_error", id: pr.id, error: error40 });
|
|
32815
31364
|
}
|
|
32816
31365
|
});
|
|
@@ -32883,11 +31432,11 @@ var handleProxyMessage = (msg, deps) => {
|
|
|
32883
31432
|
return;
|
|
32884
31433
|
}
|
|
32885
31434
|
void proxyToLocal(pr).then((res) => {
|
|
32886
|
-
if (res.error) deps.log(`[Proxy and log service]
|
|
31435
|
+
if (res.error) deps.log(`[Proxy and log service] Preview proxy failed: ${res.error}`);
|
|
32887
31436
|
sendWsMessage(deps.ws, { type: "proxy_result", ...res, id: pr.id });
|
|
32888
31437
|
}).catch((err) => {
|
|
32889
31438
|
deps.log(
|
|
32890
|
-
`[Proxy and log service]
|
|
31439
|
+
`[Proxy and log service] Preview proxy failed: ${err instanceof Error ? err.message : String(err)}`
|
|
32891
31440
|
);
|
|
32892
31441
|
sendWsMessage(deps.ws, { type: "proxy_result", id: pr.id, error: String(err) });
|
|
32893
31442
|
});
|
|
@@ -32924,6 +31473,7 @@ function tryConsumeBinaryProxyBody(raw, deps) {
|
|
|
32924
31473
|
}
|
|
32925
31474
|
|
|
32926
31475
|
// src/firehose/connect-firehose.ts
|
|
31476
|
+
var FIREHOSE_CLIENT_PING_MS = 25e3;
|
|
32927
31477
|
function connectFirehose(options) {
|
|
32928
31478
|
const { firehoseServerUrl, workspaceId, bridgeName, proxyPorts, log: log2, devServerManager, onOpen, onClose } = options;
|
|
32929
31479
|
const wsUrl = buildFirehoseCliWsUrl(firehoseServerUrl);
|
|
@@ -32932,6 +31482,13 @@ function connectFirehose(options) {
|
|
|
32932
31482
|
wsOptions.agent = new https2.Agent({ rejectUnauthorized: false });
|
|
32933
31483
|
}
|
|
32934
31484
|
const ws = new wrapper_default(wsUrl, wsOptions);
|
|
31485
|
+
let clientPingTimer = null;
|
|
31486
|
+
function clearClientPing() {
|
|
31487
|
+
if (clientPingTimer != null) {
|
|
31488
|
+
clearInterval(clientPingTimer);
|
|
31489
|
+
clientPingTimer = null;
|
|
31490
|
+
}
|
|
31491
|
+
}
|
|
32935
31492
|
const firehoseSend = (payload) => {
|
|
32936
31493
|
sendWsMessage(ws, payload);
|
|
32937
31494
|
};
|
|
@@ -32944,6 +31501,15 @@ function connectFirehose(options) {
|
|
|
32944
31501
|
startStreamingProxy: (pr) => startStreamingProxy(ws, log2, pr)
|
|
32945
31502
|
};
|
|
32946
31503
|
ws.on("open", () => {
|
|
31504
|
+
clearClientPing();
|
|
31505
|
+
clientPingTimer = setInterval(() => {
|
|
31506
|
+
if (ws.readyState === wrapper_default.OPEN) {
|
|
31507
|
+
try {
|
|
31508
|
+
ws.ping();
|
|
31509
|
+
} catch {
|
|
31510
|
+
}
|
|
31511
|
+
}
|
|
31512
|
+
}, FIREHOSE_CLIENT_PING_MS);
|
|
32947
31513
|
onOpen?.();
|
|
32948
31514
|
devServerManager.attachFirehose(firehoseSend);
|
|
32949
31515
|
sendWsMessage(ws, { type: "identify", workspaceId, bridgeName, proxyPorts });
|
|
@@ -32961,35 +31527,30 @@ function connectFirehose(options) {
|
|
|
32961
31527
|
});
|
|
32962
31528
|
});
|
|
32963
31529
|
ws.on("close", (code, reason) => {
|
|
31530
|
+
clearClientPing();
|
|
32964
31531
|
devServerManager.detachFirehose();
|
|
32965
|
-
|
|
32966
|
-
|
|
32967
|
-
"[Proxy and log service]",
|
|
32968
|
-
code,
|
|
32969
|
-
typeof reason === "string" ? reason : reason.toString(),
|
|
32970
|
-
"reconnects automatically if the bridge service stays connected"
|
|
32971
|
-
)
|
|
32972
|
-
);
|
|
32973
|
-
onClose?.();
|
|
31532
|
+
const reasonStr = typeof reason === "string" ? reason : reason.toString();
|
|
31533
|
+
onClose?.(code, reasonStr);
|
|
32974
31534
|
});
|
|
32975
31535
|
ws.on("error", (err) => {
|
|
31536
|
+
clearClientPing();
|
|
32976
31537
|
log2(`[Proxy and log service] WebSocket error: ${err.message}`);
|
|
32977
31538
|
});
|
|
32978
31539
|
return {
|
|
32979
31540
|
close() {
|
|
31541
|
+
clearClientPing();
|
|
32980
31542
|
devServerManager.detachFirehose();
|
|
32981
31543
|
try {
|
|
32982
31544
|
ws.removeAllListeners();
|
|
32983
31545
|
ws.close();
|
|
32984
31546
|
} catch {
|
|
32985
31547
|
}
|
|
32986
|
-
}
|
|
31548
|
+
},
|
|
31549
|
+
isConnected: () => ws.readyState === wrapper_default.OPEN
|
|
32987
31550
|
};
|
|
32988
31551
|
}
|
|
32989
31552
|
|
|
32990
31553
|
// src/bridge/connection/create-bridge-identified-handler.ts
|
|
32991
|
-
var FH_RECONNECT_BASE_MS = 2e3;
|
|
32992
|
-
var FH_RECONNECT_MAX_MS = 3e4;
|
|
32993
31554
|
function createOnBridgeIdentified(opts) {
|
|
32994
31555
|
const { sessionWorktreeManager, devServerManager, firehoseServerUrl, workspaceId, state, logFn } = opts;
|
|
32995
31556
|
function clearFirehoseReconnectTimer() {
|
|
@@ -32998,6 +31559,14 @@ function createOnBridgeIdentified(opts) {
|
|
|
32998
31559
|
state.firehoseReconnectTimeout = null;
|
|
32999
31560
|
}
|
|
33000
31561
|
}
|
|
31562
|
+
function firehoseCtx() {
|
|
31563
|
+
return {
|
|
31564
|
+
closedByUser: state.closedByUser,
|
|
31565
|
+
currentWs: state.currentWs,
|
|
31566
|
+
firehoseHandle: state.firehoseHandle,
|
|
31567
|
+
firehoseQuiet: state.firehoseQuiet
|
|
31568
|
+
};
|
|
31569
|
+
}
|
|
33001
31570
|
function attachFirehose(params) {
|
|
33002
31571
|
state.lastFirehoseParams = params;
|
|
33003
31572
|
clearFirehoseReconnectTimer();
|
|
@@ -33016,37 +31585,52 @@ function createOnBridgeIdentified(opts) {
|
|
|
33016
31585
|
devServerManager,
|
|
33017
31586
|
onOpen: () => {
|
|
33018
31587
|
if (myGen !== state.firehoseGeneration) return;
|
|
31588
|
+
clearFirehoseReconnectQuietOnOpen({ firehoseQuiet: state.firehoseQuiet }, logFn);
|
|
31589
|
+
const logOpenAsFirehoseReconnect = state.firehoseReconnectAttempt > 0;
|
|
33019
31590
|
state.firehoseReconnectAttempt = 0;
|
|
31591
|
+
if (logOpenAsFirehoseReconnect) {
|
|
31592
|
+
logFn("[Proxy and log service] reconnected.");
|
|
31593
|
+
}
|
|
33020
31594
|
},
|
|
33021
|
-
onClose: () => {
|
|
31595
|
+
onClose: (code, reason) => {
|
|
33022
31596
|
if (myGen !== state.firehoseGeneration) return;
|
|
33023
31597
|
state.firehoseHandle = null;
|
|
33024
31598
|
if (state.closedByUser) return;
|
|
33025
31599
|
const main = state.currentWs;
|
|
33026
31600
|
if (!main || main.readyState !== wrapper_default.OPEN) {
|
|
33027
|
-
logFn(
|
|
31601
|
+
logFn(
|
|
31602
|
+
`${PROXY_AND_LOG_SERVICE_LABEL} Not reconnecting preview and log stream: main bridge connection is not open.`
|
|
31603
|
+
);
|
|
33028
31604
|
return;
|
|
33029
31605
|
}
|
|
31606
|
+
beginFirehoseDeferredDisconnect(firehoseCtx(), code, reason, logFn);
|
|
33030
31607
|
clearFirehoseReconnectTimer();
|
|
33031
|
-
const delay2 =
|
|
33032
|
-
FH_RECONNECT_BASE_MS * 2 ** state.firehoseReconnectAttempt,
|
|
33033
|
-
FH_RECONNECT_MAX_MS
|
|
33034
|
-
);
|
|
31608
|
+
const delay2 = reconnectDelayMs(state.firehoseReconnectAttempt);
|
|
33035
31609
|
state.firehoseReconnectAttempt += 1;
|
|
33036
|
-
|
|
33037
|
-
|
|
31610
|
+
logNextReconnectAttempt(
|
|
31611
|
+
logFn,
|
|
31612
|
+
PROXY_AND_LOG_SERVICE_LABEL,
|
|
31613
|
+
state.firehoseQuiet,
|
|
31614
|
+
delay2,
|
|
31615
|
+
state.firehoseReconnectAttempt
|
|
33038
31616
|
);
|
|
33039
31617
|
state.firehoseReconnectTimeout = setTimeout(() => {
|
|
33040
31618
|
state.firehoseReconnectTimeout = null;
|
|
33041
31619
|
if (state.closedByUser) return;
|
|
33042
31620
|
const w = state.currentWs;
|
|
33043
31621
|
if (!w || w.readyState !== wrapper_default.OPEN) {
|
|
33044
|
-
|
|
31622
|
+
if (state.firehoseQuiet.verboseLogs) {
|
|
31623
|
+
logFn(
|
|
31624
|
+
`${PROXY_AND_LOG_SERVICE_LABEL} Reconnect skipped: main bridge connection closed before preview stream could reconnect.`
|
|
31625
|
+
);
|
|
31626
|
+
}
|
|
33045
31627
|
return;
|
|
33046
31628
|
}
|
|
33047
31629
|
const p = state.lastFirehoseParams;
|
|
33048
31630
|
if (!p) {
|
|
33049
|
-
|
|
31631
|
+
if (state.firehoseQuiet.verboseLogs) {
|
|
31632
|
+
logFn(`${PROXY_AND_LOG_SERVICE_LABEL} Reconnect skipped: no stored connection parameters.`);
|
|
31633
|
+
}
|
|
33050
31634
|
return;
|
|
33051
31635
|
}
|
|
33052
31636
|
attachFirehose(p);
|
|
@@ -33129,10 +31713,12 @@ function createSendLocalSkillsReport(getWs, logFn) {
|
|
|
33129
31713
|
try {
|
|
33130
31714
|
const socket = getWs();
|
|
33131
31715
|
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
33132
|
-
const skills2 = discoverLocalSkills(
|
|
31716
|
+
const skills2 = discoverLocalSkills(getBridgeWorkspaceDirectory());
|
|
33133
31717
|
socket.send(JSON.stringify({ type: "local_skills", skills: skills2 }));
|
|
33134
31718
|
} catch (e) {
|
|
33135
|
-
logFn(
|
|
31719
|
+
logFn(
|
|
31720
|
+
`[Bridge service] Local skills report failed: ${e instanceof Error ? e.message : String(e)}`
|
|
31721
|
+
);
|
|
33136
31722
|
}
|
|
33137
31723
|
};
|
|
33138
31724
|
}
|
|
@@ -33145,12 +31731,15 @@ function createReportAutoDetectedAgents(getWs, logFn) {
|
|
|
33145
31731
|
sendWsMessage(socket, { type: "auto_detected_agents_report", agentTypes: types });
|
|
33146
31732
|
}
|
|
33147
31733
|
} catch (e) {
|
|
33148
|
-
logFn(
|
|
31734
|
+
logFn(
|
|
31735
|
+
`[Bridge service] Auto-detected agents report failed: ${e instanceof Error ? e.message : String(e)}`
|
|
31736
|
+
);
|
|
33149
31737
|
}
|
|
33150
31738
|
};
|
|
33151
31739
|
}
|
|
33152
31740
|
|
|
33153
31741
|
// src/bridge/connection/create-bridge-connection.ts
|
|
31742
|
+
var BRIDGE_CLIENT_PING_MS = 25e3;
|
|
33154
31743
|
async function createBridgeConnection(options) {
|
|
33155
31744
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
33156
31745
|
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
@@ -33161,13 +31750,16 @@ async function createBridgeConnection(options) {
|
|
|
33161
31750
|
const state = {
|
|
33162
31751
|
closedByUser: false,
|
|
33163
31752
|
reconnectAttempt: 0,
|
|
31753
|
+
logBridgeOpenAsReconnect: false,
|
|
33164
31754
|
reconnectTimeout: null,
|
|
33165
31755
|
currentWs: null,
|
|
31756
|
+
mainQuiet: createEmptyReconnectQuietSlot(),
|
|
33166
31757
|
firehoseHandle: null,
|
|
33167
31758
|
lastFirehoseParams: null,
|
|
33168
31759
|
firehoseReconnectTimeout: null,
|
|
33169
31760
|
firehoseReconnectAttempt: 0,
|
|
33170
|
-
firehoseGeneration: 0
|
|
31761
|
+
firehoseGeneration: 0,
|
|
31762
|
+
firehoseQuiet: createEmptyReconnectQuietSlot()
|
|
33171
31763
|
};
|
|
33172
31764
|
const worktreesRootAbs = options.worktreesRootAbs ?? defaultWorktreesRootAbs();
|
|
33173
31765
|
const sessionWorktreeManager = new SessionWorktreeManager({
|
|
@@ -33179,7 +31771,7 @@ async function createBridgeConnection(options) {
|
|
|
33179
31771
|
function getWs() {
|
|
33180
31772
|
return state.currentWs;
|
|
33181
31773
|
}
|
|
33182
|
-
const devServerManager = new DevServerManager({ getWs, log: logFn });
|
|
31774
|
+
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory });
|
|
33183
31775
|
const onBridgeIdentified = createOnBridgeIdentified({
|
|
33184
31776
|
sessionWorktreeManager,
|
|
33185
31777
|
devServerManager,
|
|
@@ -33191,7 +31783,13 @@ async function createBridgeConnection(options) {
|
|
|
33191
31783
|
const sendLocalSkillsReport = createSendLocalSkillsReport(getWs, logFn);
|
|
33192
31784
|
const reportAutoDetectedAgents = createReportAutoDetectedAgents(getWs, logFn);
|
|
33193
31785
|
function handleOpen() {
|
|
31786
|
+
const logOpenAsPostRefreshReconnect = state.logBridgeOpenAsReconnect;
|
|
31787
|
+
clearMainBridgeReconnectQuietOnOpen(state, logFn);
|
|
33194
31788
|
state.reconnectAttempt = 0;
|
|
31789
|
+
state.logBridgeOpenAsReconnect = false;
|
|
31790
|
+
if (logOpenAsPostRefreshReconnect) {
|
|
31791
|
+
logFn("[Bridge service] reconnected.");
|
|
31792
|
+
}
|
|
33195
31793
|
const socket = getWs();
|
|
33196
31794
|
if (socket) {
|
|
33197
31795
|
sendWsMessage(socket, { type: "identify", role: "cli" });
|
|
@@ -33208,11 +31806,9 @@ async function createBridgeConnection(options) {
|
|
|
33208
31806
|
state.currentWs = null;
|
|
33209
31807
|
if (was) was.removeAllListeners();
|
|
33210
31808
|
const willReconnect = !state.closedByUser;
|
|
33211
|
-
logFn
|
|
33212
|
-
formatWebSocketClose("[Bridge service]", code, reason, willReconnect ? "will schedule reconnect" : "not reconnecting (CLI shutting down)")
|
|
33213
|
-
);
|
|
31809
|
+
beginMainBridgeDeferredDisconnect(state, code, reason, logFn, willReconnect);
|
|
33214
31810
|
if (willReconnect) {
|
|
33215
|
-
|
|
31811
|
+
scheduleMainBridgeReconnect(state, connect, logFn);
|
|
33216
31812
|
}
|
|
33217
31813
|
}
|
|
33218
31814
|
const messageDeps = {
|
|
@@ -33227,6 +31823,10 @@ async function createBridgeConnection(options) {
|
|
|
33227
31823
|
};
|
|
33228
31824
|
function connect() {
|
|
33229
31825
|
if (state.closedByUser) return;
|
|
31826
|
+
if (state.reconnectTimeout != null) {
|
|
31827
|
+
clearTimeout(state.reconnectTimeout);
|
|
31828
|
+
state.reconnectTimeout = null;
|
|
31829
|
+
}
|
|
33230
31830
|
const prev = state.currentWs;
|
|
33231
31831
|
if (prev) {
|
|
33232
31832
|
prev.removeAllListeners();
|
|
@@ -33239,6 +31839,7 @@ async function createBridgeConnection(options) {
|
|
|
33239
31839
|
const url2 = buildBridgeUrl(apiUrl, workspaceId, accessToken);
|
|
33240
31840
|
state.currentWs = createWsBridge({
|
|
33241
31841
|
url: url2,
|
|
31842
|
+
clientPingIntervalMs: BRIDGE_CLIENT_PING_MS,
|
|
33242
31843
|
onAuthInvalid: () => {
|
|
33243
31844
|
if (authRefreshInFlight) return;
|
|
33244
31845
|
void (async () => {
|
|
@@ -33250,8 +31851,9 @@ async function createBridgeConnection(options) {
|
|
|
33250
31851
|
accessToken = next.token;
|
|
33251
31852
|
refreshTok = next.refreshToken;
|
|
33252
31853
|
persistTokens?.({ token: accessToken, refreshToken: refreshTok });
|
|
33253
|
-
logFn("[Bridge service]
|
|
31854
|
+
logFn("[Bridge service] Access token refreshed; reconnecting\u2026");
|
|
33254
31855
|
state.reconnectAttempt = 0;
|
|
31856
|
+
state.logBridgeOpenAsReconnect = true;
|
|
33255
31857
|
authRefreshInFlight = false;
|
|
33256
31858
|
connect();
|
|
33257
31859
|
return;
|
|
@@ -33274,7 +31876,7 @@ async function createBridgeConnection(options) {
|
|
|
33274
31876
|
});
|
|
33275
31877
|
}
|
|
33276
31878
|
connect();
|
|
33277
|
-
const stopFileIndexWatcher = startFileIndexWatcher(
|
|
31879
|
+
const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
|
|
33278
31880
|
return {
|
|
33279
31881
|
close: async () => {
|
|
33280
31882
|
stopFileIndexWatcher();
|
|
@@ -33347,7 +31949,7 @@ async function runBridge(options) {
|
|
|
33347
31949
|
});
|
|
33348
31950
|
},
|
|
33349
31951
|
onAuthInvalid: () => {
|
|
33350
|
-
log("[Bridge service] token invalid or revoked; re-authenticating\u2026");
|
|
31952
|
+
log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
|
|
33351
31953
|
clearConfigForApi(apiUrl);
|
|
33352
31954
|
void handle.close().then(() => {
|
|
33353
31955
|
void runBridge({ apiUrl, firehoseServerUrl, worktreesRootAbs });
|
|
@@ -33381,9 +31983,4 @@ export {
|
|
|
33381
31983
|
runPendingAuth,
|
|
33382
31984
|
sendWsMessage
|
|
33383
31985
|
};
|
|
33384
|
-
/*! Bundled license information:
|
|
33385
|
-
|
|
33386
|
-
chokidar/esm/index.js:
|
|
33387
|
-
(*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
|
|
33388
|
-
*/
|
|
33389
31986
|
//# sourceMappingURL=index.js.map
|