@factiii/runner 0.9.1 → 0.9.2
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 +2091 -114
- package/package.json +15 -16
- package/vendor/frpc-darwin-amd64 +0 -0
- package/vendor/frpc-darwin-arm64 +0 -0
- package/vendor/frpc-linux-amd64 +0 -0
- package/vendor/frpc-linux-arm64 +0 -0
package/dist/cli.js
CHANGED
|
@@ -961,7 +961,7 @@ var require_suggestSimilar = __commonJS({
|
|
|
961
961
|
// node_modules/commander/lib/command.js
|
|
962
962
|
var require_command = __commonJS({
|
|
963
963
|
"node_modules/commander/lib/command.js"(exports2) {
|
|
964
|
-
var
|
|
964
|
+
var EventEmitter2 = require("node:events").EventEmitter;
|
|
965
965
|
var childProcess = require("node:child_process");
|
|
966
966
|
var path15 = require("node:path");
|
|
967
967
|
var fs13 = require("node:fs");
|
|
@@ -971,7 +971,7 @@ var require_command = __commonJS({
|
|
|
971
971
|
var { Help: Help2 } = require_help();
|
|
972
972
|
var { Option: Option2, DualOptions } = require_option();
|
|
973
973
|
var { suggestSimilar } = require_suggestSimilar();
|
|
974
|
-
var Command2 = class _Command extends
|
|
974
|
+
var Command2 = class _Command extends EventEmitter2 {
|
|
975
975
|
/**
|
|
976
976
|
* Initialize a new `Command`.
|
|
977
977
|
*
|
|
@@ -6503,13 +6503,13 @@ var require_extension = __commonJS({
|
|
|
6503
6503
|
var require_websocket = __commonJS({
|
|
6504
6504
|
"../../node_modules/ws/lib/websocket.js"(exports2, module2) {
|
|
6505
6505
|
"use strict";
|
|
6506
|
-
var
|
|
6506
|
+
var EventEmitter2 = require("events");
|
|
6507
6507
|
var https = require("https");
|
|
6508
6508
|
var http = require("http");
|
|
6509
6509
|
var net2 = require("net");
|
|
6510
6510
|
var tls = require("tls");
|
|
6511
6511
|
var { randomBytes, createHash: createHash2 } = require("crypto");
|
|
6512
|
-
var { Duplex, Readable } = require("stream");
|
|
6512
|
+
var { Duplex, Readable: Readable2 } = require("stream");
|
|
6513
6513
|
var { URL: URL2 } = require("url");
|
|
6514
6514
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
6515
6515
|
var Receiver2 = require_receiver();
|
|
@@ -6535,7 +6535,7 @@ var require_websocket = __commonJS({
|
|
|
6535
6535
|
var protocolVersions = [8, 13];
|
|
6536
6536
|
var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
|
|
6537
6537
|
var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
6538
|
-
var WebSocket2 = class _WebSocket extends
|
|
6538
|
+
var WebSocket2 = class _WebSocket extends EventEmitter2 {
|
|
6539
6539
|
/**
|
|
6540
6540
|
* Create a new `WebSocket`.
|
|
6541
6541
|
*
|
|
@@ -7457,7 +7457,7 @@ var require_stream = __commonJS({
|
|
|
7457
7457
|
};
|
|
7458
7458
|
duplex._final = function(callback) {
|
|
7459
7459
|
if (ws.readyState === ws.CONNECTING) {
|
|
7460
|
-
ws.once("open", function
|
|
7460
|
+
ws.once("open", function open2() {
|
|
7461
7461
|
duplex._final(callback);
|
|
7462
7462
|
});
|
|
7463
7463
|
return;
|
|
@@ -7478,7 +7478,7 @@ var require_stream = __commonJS({
|
|
|
7478
7478
|
};
|
|
7479
7479
|
duplex._write = function(chunk, encoding, callback) {
|
|
7480
7480
|
if (ws.readyState === ws.CONNECTING) {
|
|
7481
|
-
ws.once("open", function
|
|
7481
|
+
ws.once("open", function open2() {
|
|
7482
7482
|
duplex._write(chunk, encoding, callback);
|
|
7483
7483
|
});
|
|
7484
7484
|
return;
|
|
@@ -7542,7 +7542,7 @@ var require_subprotocol = __commonJS({
|
|
|
7542
7542
|
var require_websocket_server = __commonJS({
|
|
7543
7543
|
"../../node_modules/ws/lib/websocket-server.js"(exports2, module2) {
|
|
7544
7544
|
"use strict";
|
|
7545
|
-
var
|
|
7545
|
+
var EventEmitter2 = require("events");
|
|
7546
7546
|
var http = require("http");
|
|
7547
7547
|
var { Duplex } = require("stream");
|
|
7548
7548
|
var { createHash: createHash2 } = require("crypto");
|
|
@@ -7555,7 +7555,7 @@ var require_websocket_server = __commonJS({
|
|
|
7555
7555
|
var RUNNING = 0;
|
|
7556
7556
|
var CLOSING = 1;
|
|
7557
7557
|
var CLOSED = 2;
|
|
7558
|
-
var WebSocketServer2 = class extends
|
|
7558
|
+
var WebSocketServer2 = class extends EventEmitter2 {
|
|
7559
7559
|
/**
|
|
7560
7560
|
* Create a `WebSocketServer` instance.
|
|
7561
7561
|
*
|
|
@@ -7967,10 +7967,10 @@ function prompt(msg) {
|
|
|
7967
7967
|
input: process.stdin,
|
|
7968
7968
|
output: process.stdout
|
|
7969
7969
|
});
|
|
7970
|
-
return new Promise((
|
|
7970
|
+
return new Promise((resolve4) => {
|
|
7971
7971
|
rl.question(msg, (answer) => {
|
|
7972
7972
|
rl.close();
|
|
7973
|
-
|
|
7973
|
+
resolve4(answer.trim());
|
|
7974
7974
|
});
|
|
7975
7975
|
});
|
|
7976
7976
|
}
|
|
@@ -8779,11 +8779,11 @@ function promptPassword(label) {
|
|
|
8779
8779
|
rl._writeToOutput = (text) => {
|
|
8780
8780
|
if (!muted) write(text);
|
|
8781
8781
|
};
|
|
8782
|
-
return new Promise((
|
|
8782
|
+
return new Promise((resolve4) => {
|
|
8783
8783
|
rl.question(label, (answer) => {
|
|
8784
8784
|
rl.close();
|
|
8785
8785
|
process.stdout.write("\n");
|
|
8786
|
-
|
|
8786
|
+
resolve4(answer);
|
|
8787
8787
|
});
|
|
8788
8788
|
muted = true;
|
|
8789
8789
|
});
|
|
@@ -13603,7 +13603,7 @@ async function markOnboardingComplete(target) {
|
|
|
13603
13603
|
await target.sh(`node -e "${script}"`);
|
|
13604
13604
|
}
|
|
13605
13605
|
function runAgentProc(proc, prompt2, stream, label, errorPrefix) {
|
|
13606
|
-
return new Promise((
|
|
13606
|
+
return new Promise((resolve4, reject) => {
|
|
13607
13607
|
let errorOutput = "";
|
|
13608
13608
|
proc.stderr?.on("data", (chunk) => {
|
|
13609
13609
|
errorOutput += chunk.toString();
|
|
@@ -13618,7 +13618,7 @@ function runAgentProc(proc, prompt2, stream, label, errorPrefix) {
|
|
|
13618
13618
|
} else if (code !== 0 && !text) {
|
|
13619
13619
|
reject(new Error(errorOutput || `${label} exited with code ${code}`));
|
|
13620
13620
|
} else {
|
|
13621
|
-
|
|
13621
|
+
resolve4({ text, sessionId });
|
|
13622
13622
|
}
|
|
13623
13623
|
});
|
|
13624
13624
|
proc.on("error", (err) => {
|
|
@@ -13767,8 +13767,14 @@ function hostSpacePaths(spaceDir) {
|
|
|
13767
13767
|
bin: import_path6.default.join(spaceDir, "bin")
|
|
13768
13768
|
};
|
|
13769
13769
|
}
|
|
13770
|
-
function worktreeFor(paths,
|
|
13771
|
-
return `${paths.worktrees}/${
|
|
13770
|
+
function worktreeFor(paths, workName) {
|
|
13771
|
+
return `${paths.worktrees}/${workName.replace(/[^a-zA-Z0-9._-]/g, "_")}`;
|
|
13772
|
+
}
|
|
13773
|
+
|
|
13774
|
+
// ../../shared/all/helpers/board-agent-core/workName.ts
|
|
13775
|
+
var WORK_NAME_MAX = 48;
|
|
13776
|
+
function slugifyWorkName(name) {
|
|
13777
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, WORK_NAME_MAX).replace(/^-+|-+$/g, "");
|
|
13772
13778
|
}
|
|
13773
13779
|
|
|
13774
13780
|
// ../../shared/all/helpers/board-agent-core/git.ts
|
|
@@ -13784,8 +13790,37 @@ function buildCloneUrl(repoUrl, githubToken) {
|
|
|
13784
13790
|
async function gitInDir(target, workdir, ...args) {
|
|
13785
13791
|
return target.run(["git", "-C", workdir, ...args]);
|
|
13786
13792
|
}
|
|
13787
|
-
|
|
13788
|
-
|
|
13793
|
+
var WORK_BRANCH_PREFIX = "factiii/card-";
|
|
13794
|
+
function cardWorkBranch(workName) {
|
|
13795
|
+
return `${WORK_BRANCH_PREFIX}${workName.replace(/[^a-zA-Z0-9._-]/g, "-")}`;
|
|
13796
|
+
}
|
|
13797
|
+
async function listWorkNames(target) {
|
|
13798
|
+
const dirs = await target.sh(`ls -1 ${target.paths.worktrees} 2>/dev/null || true`).catch(() => "");
|
|
13799
|
+
const branches = await gitInDir(
|
|
13800
|
+
target,
|
|
13801
|
+
target.paths.repo,
|
|
13802
|
+
"for-each-ref",
|
|
13803
|
+
"--format=%(refname:short)",
|
|
13804
|
+
"refs/heads/"
|
|
13805
|
+
).catch(() => "");
|
|
13806
|
+
const names = new Set(dirs.split("\n").map((line) => line.trim()));
|
|
13807
|
+
for (const line of branches.split("\n")) {
|
|
13808
|
+
const name = line.trim();
|
|
13809
|
+
if (name.startsWith(WORK_BRANCH_PREFIX)) {
|
|
13810
|
+
names.add(name.slice(WORK_BRANCH_PREFIX.length));
|
|
13811
|
+
}
|
|
13812
|
+
}
|
|
13813
|
+
names.delete("");
|
|
13814
|
+
return [...names];
|
|
13815
|
+
}
|
|
13816
|
+
async function claimWorkName(target, desired, extraTaken = []) {
|
|
13817
|
+
const name = slugifyWorkName(desired);
|
|
13818
|
+
if (!name) throw new Error("Name this terminal before starting it.");
|
|
13819
|
+
const taken = /* @__PURE__ */ new Set([...await listWorkNames(target), ...extraTaken]);
|
|
13820
|
+
if (taken.has(name)) {
|
|
13821
|
+
throw new Error(`"${name}" is already in use. Pick another name.`);
|
|
13822
|
+
}
|
|
13823
|
+
return name;
|
|
13789
13824
|
}
|
|
13790
13825
|
async function ensurePrimaryClone(target, cloneUrl, branch) {
|
|
13791
13826
|
const repo = target.paths.repo;
|
|
@@ -13807,9 +13842,9 @@ async function ensurePrimaryClone(target, cloneUrl, branch) {
|
|
|
13807
13842
|
});
|
|
13808
13843
|
await target.sh(`mkdir -p ${target.paths.worktrees}`);
|
|
13809
13844
|
}
|
|
13810
|
-
async function addWorktree(target,
|
|
13811
|
-
const path15 = worktreeFor(target.paths,
|
|
13812
|
-
const branch = cardWorkBranch(
|
|
13845
|
+
async function addWorktree(target, workName, baseBranch) {
|
|
13846
|
+
const path15 = worktreeFor(target.paths, workName);
|
|
13847
|
+
const branch = cardWorkBranch(workName);
|
|
13813
13848
|
await removeWorktree(target, path15).catch(() => {
|
|
13814
13849
|
});
|
|
13815
13850
|
await gitInDir(
|
|
@@ -14066,14 +14101,14 @@ function killTree(proc, signal = "SIGKILL") {
|
|
|
14066
14101
|
function execLogin(command, opts) {
|
|
14067
14102
|
const [bin, args] = isWindows ? ["bash", ["-c", command]] : [process.env.SHELL || "/bin/bash", ["-lc", command]];
|
|
14068
14103
|
const cap = opts.maxBuffer ?? 4 * 1024 * 1024;
|
|
14069
|
-
return new Promise((
|
|
14104
|
+
return new Promise((resolve4) => {
|
|
14070
14105
|
let output = "";
|
|
14071
14106
|
let settled = false;
|
|
14072
14107
|
const done = (code, extra = "") => {
|
|
14073
14108
|
if (settled) return;
|
|
14074
14109
|
settled = true;
|
|
14075
14110
|
clearTimeout(timer);
|
|
14076
|
-
|
|
14111
|
+
resolve4({ code, output: (output + extra).slice(-cap) });
|
|
14077
14112
|
};
|
|
14078
14113
|
let proc;
|
|
14079
14114
|
try {
|
|
@@ -14143,7 +14178,7 @@ async function allocateSpacePorts(spaceDir) {
|
|
|
14143
14178
|
const ports = [];
|
|
14144
14179
|
const seen = /* @__PURE__ */ new Set();
|
|
14145
14180
|
while (ports.length < NUM_PORTS) {
|
|
14146
|
-
const port = await new Promise((
|
|
14181
|
+
const port = await new Promise((resolve4, reject) => {
|
|
14147
14182
|
const srv = import_net.default.createServer();
|
|
14148
14183
|
srv.unref();
|
|
14149
14184
|
srv.on("error", reject);
|
|
@@ -14151,7 +14186,7 @@ async function allocateSpacePorts(spaceDir) {
|
|
|
14151
14186
|
const addr = srv.address();
|
|
14152
14187
|
if (typeof addr === "object" && addr) {
|
|
14153
14188
|
const p = addr.port;
|
|
14154
|
-
srv.close(() =>
|
|
14189
|
+
srv.close(() => resolve4(p));
|
|
14155
14190
|
} else {
|
|
14156
14191
|
srv.close(() => reject(new Error("Failed to get a free port")));
|
|
14157
14192
|
}
|
|
@@ -14221,7 +14256,7 @@ function hostTarget(spaceDir, extraEnv) {
|
|
|
14221
14256
|
async runWithStdin(argv, input, label) {
|
|
14222
14257
|
const [bin, ...rest] = argv;
|
|
14223
14258
|
const env = await spawnEnv();
|
|
14224
|
-
return new Promise((
|
|
14259
|
+
return new Promise((resolve4, reject) => {
|
|
14225
14260
|
const proc = (0, import_child_process4.spawn)(bin, rest, { cwd: usableCwd(paths.root), env });
|
|
14226
14261
|
let stderr = "";
|
|
14227
14262
|
proc.stderr?.on("data", (d) => {
|
|
@@ -14229,7 +14264,7 @@ function hostTarget(spaceDir, extraEnv) {
|
|
|
14229
14264
|
});
|
|
14230
14265
|
proc.on("error", reject);
|
|
14231
14266
|
proc.on("close", (code) => {
|
|
14232
|
-
if (code === 0)
|
|
14267
|
+
if (code === 0) resolve4();
|
|
14233
14268
|
else reject(new Error(`${label}: ${stderr.trim()}`));
|
|
14234
14269
|
});
|
|
14235
14270
|
proc.stdin?.on("error", () => {
|
|
@@ -14398,6 +14433,9 @@ function createEventSink(send, spaceSlug, notify) {
|
|
|
14398
14433
|
},
|
|
14399
14434
|
emitDeployEnv(payload) {
|
|
14400
14435
|
send(channel("deploy-env"), payload);
|
|
14436
|
+
},
|
|
14437
|
+
emitBareFsChange(postId, change) {
|
|
14438
|
+
send(channel(`bare-fs:${postId}`), change);
|
|
14401
14439
|
}
|
|
14402
14440
|
};
|
|
14403
14441
|
}
|
|
@@ -14779,8 +14817,8 @@ var ClaudeModeEngine = class _ClaudeModeEngine {
|
|
|
14779
14817
|
"system",
|
|
14780
14818
|
"The agent has a question - waiting for your input."
|
|
14781
14819
|
);
|
|
14782
|
-
const answer = await new Promise((
|
|
14783
|
-
session.answerResolver =
|
|
14820
|
+
const answer = await new Promise((resolve4) => {
|
|
14821
|
+
session.answerResolver = resolve4;
|
|
14784
14822
|
});
|
|
14785
14823
|
if (this.stopped(session)) return;
|
|
14786
14824
|
session.phase = "research";
|
|
@@ -15242,6 +15280,15 @@ ${buildPrompt(prompts_default.implement)}`;
|
|
|
15242
15280
|
// ../../shared/all/helpers/terminal-ai/terminal-mode.ts
|
|
15243
15281
|
var import_crypto4 = require("crypto");
|
|
15244
15282
|
|
|
15283
|
+
// ../../shared/all/helpers/board-agent-core/boardTerminal.ts
|
|
15284
|
+
function boardTerminalKey(spaceSlug) {
|
|
15285
|
+
return `board-${spaceSlug}`;
|
|
15286
|
+
}
|
|
15287
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15288
|
+
function isCardPostId(id) {
|
|
15289
|
+
return UUID_RE.test(id);
|
|
15290
|
+
}
|
|
15291
|
+
|
|
15245
15292
|
// ../../shared/all/helpers/board-agent-core/tmux.ts
|
|
15246
15293
|
var TMUX_CONF = [
|
|
15247
15294
|
// Wheel scrolls, drag selects in copy mode.
|
|
@@ -15331,6 +15378,1865 @@ async function startTmuxSession(opts) {
|
|
|
15331
15378
|
};
|
|
15332
15379
|
}
|
|
15333
15380
|
|
|
15381
|
+
// ../../node_modules/chokidar/esm/index.js
|
|
15382
|
+
var import_fs8 = require("fs");
|
|
15383
|
+
var import_promises5 = require("fs/promises");
|
|
15384
|
+
var import_events = require("events");
|
|
15385
|
+
var sysPath2 = __toESM(require("path"), 1);
|
|
15386
|
+
|
|
15387
|
+
// ../../node_modules/readdirp/esm/index.js
|
|
15388
|
+
var import_promises3 = require("node:fs/promises");
|
|
15389
|
+
var import_node_stream = require("node:stream");
|
|
15390
|
+
var import_node_path = require("node:path");
|
|
15391
|
+
var EntryTypes = {
|
|
15392
|
+
FILE_TYPE: "files",
|
|
15393
|
+
DIR_TYPE: "directories",
|
|
15394
|
+
FILE_DIR_TYPE: "files_directories",
|
|
15395
|
+
EVERYTHING_TYPE: "all"
|
|
15396
|
+
};
|
|
15397
|
+
var defaultOptions = {
|
|
15398
|
+
root: ".",
|
|
15399
|
+
fileFilter: (_entryInfo) => true,
|
|
15400
|
+
directoryFilter: (_entryInfo) => true,
|
|
15401
|
+
type: EntryTypes.FILE_TYPE,
|
|
15402
|
+
lstat: false,
|
|
15403
|
+
depth: 2147483648,
|
|
15404
|
+
alwaysStat: false,
|
|
15405
|
+
highWaterMark: 4096
|
|
15406
|
+
};
|
|
15407
|
+
Object.freeze(defaultOptions);
|
|
15408
|
+
var RECURSIVE_ERROR_CODE = "READDIRP_RECURSIVE_ERROR";
|
|
15409
|
+
var NORMAL_FLOW_ERRORS = /* @__PURE__ */ new Set(["ENOENT", "EPERM", "EACCES", "ELOOP", RECURSIVE_ERROR_CODE]);
|
|
15410
|
+
var ALL_TYPES = [
|
|
15411
|
+
EntryTypes.DIR_TYPE,
|
|
15412
|
+
EntryTypes.EVERYTHING_TYPE,
|
|
15413
|
+
EntryTypes.FILE_DIR_TYPE,
|
|
15414
|
+
EntryTypes.FILE_TYPE
|
|
15415
|
+
];
|
|
15416
|
+
var DIR_TYPES = /* @__PURE__ */ new Set([
|
|
15417
|
+
EntryTypes.DIR_TYPE,
|
|
15418
|
+
EntryTypes.EVERYTHING_TYPE,
|
|
15419
|
+
EntryTypes.FILE_DIR_TYPE
|
|
15420
|
+
]);
|
|
15421
|
+
var FILE_TYPES = /* @__PURE__ */ new Set([
|
|
15422
|
+
EntryTypes.EVERYTHING_TYPE,
|
|
15423
|
+
EntryTypes.FILE_DIR_TYPE,
|
|
15424
|
+
EntryTypes.FILE_TYPE
|
|
15425
|
+
]);
|
|
15426
|
+
var isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);
|
|
15427
|
+
var wantBigintFsStats = process.platform === "win32";
|
|
15428
|
+
var emptyFn = (_entryInfo) => true;
|
|
15429
|
+
var normalizeFilter = (filter) => {
|
|
15430
|
+
if (filter === void 0)
|
|
15431
|
+
return emptyFn;
|
|
15432
|
+
if (typeof filter === "function")
|
|
15433
|
+
return filter;
|
|
15434
|
+
if (typeof filter === "string") {
|
|
15435
|
+
const fl = filter.trim();
|
|
15436
|
+
return (entry) => entry.basename === fl;
|
|
15437
|
+
}
|
|
15438
|
+
if (Array.isArray(filter)) {
|
|
15439
|
+
const trItems = filter.map((item) => item.trim());
|
|
15440
|
+
return (entry) => trItems.some((f) => entry.basename === f);
|
|
15441
|
+
}
|
|
15442
|
+
return emptyFn;
|
|
15443
|
+
};
|
|
15444
|
+
var ReaddirpStream = class extends import_node_stream.Readable {
|
|
15445
|
+
constructor(options = {}) {
|
|
15446
|
+
super({
|
|
15447
|
+
objectMode: true,
|
|
15448
|
+
autoDestroy: true,
|
|
15449
|
+
highWaterMark: options.highWaterMark
|
|
15450
|
+
});
|
|
15451
|
+
const opts = { ...defaultOptions, ...options };
|
|
15452
|
+
const { root, type } = opts;
|
|
15453
|
+
this._fileFilter = normalizeFilter(opts.fileFilter);
|
|
15454
|
+
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
15455
|
+
const statMethod = opts.lstat ? import_promises3.lstat : import_promises3.stat;
|
|
15456
|
+
if (wantBigintFsStats) {
|
|
15457
|
+
this._stat = (path15) => statMethod(path15, { bigint: true });
|
|
15458
|
+
} else {
|
|
15459
|
+
this._stat = statMethod;
|
|
15460
|
+
}
|
|
15461
|
+
this._maxDepth = opts.depth ?? defaultOptions.depth;
|
|
15462
|
+
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
15463
|
+
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
15464
|
+
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
15465
|
+
this._root = (0, import_node_path.resolve)(root);
|
|
15466
|
+
this._isDirent = !opts.alwaysStat;
|
|
15467
|
+
this._statsProp = this._isDirent ? "dirent" : "stats";
|
|
15468
|
+
this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
|
|
15469
|
+
this.parents = [this._exploreDir(root, 1)];
|
|
15470
|
+
this.reading = false;
|
|
15471
|
+
this.parent = void 0;
|
|
15472
|
+
}
|
|
15473
|
+
async _read(batch) {
|
|
15474
|
+
if (this.reading)
|
|
15475
|
+
return;
|
|
15476
|
+
this.reading = true;
|
|
15477
|
+
try {
|
|
15478
|
+
while (!this.destroyed && batch > 0) {
|
|
15479
|
+
const par = this.parent;
|
|
15480
|
+
const fil = par && par.files;
|
|
15481
|
+
if (fil && fil.length > 0) {
|
|
15482
|
+
const { path: path15, depth } = par;
|
|
15483
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path15));
|
|
15484
|
+
const awaited = await Promise.all(slice);
|
|
15485
|
+
for (const entry of awaited) {
|
|
15486
|
+
if (!entry)
|
|
15487
|
+
continue;
|
|
15488
|
+
if (this.destroyed)
|
|
15489
|
+
return;
|
|
15490
|
+
const entryType = await this._getEntryType(entry);
|
|
15491
|
+
if (entryType === "directory" && this._directoryFilter(entry)) {
|
|
15492
|
+
if (depth <= this._maxDepth) {
|
|
15493
|
+
this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
|
|
15494
|
+
}
|
|
15495
|
+
if (this._wantsDir) {
|
|
15496
|
+
this.push(entry);
|
|
15497
|
+
batch--;
|
|
15498
|
+
}
|
|
15499
|
+
} else if ((entryType === "file" || this._includeAsFile(entry)) && this._fileFilter(entry)) {
|
|
15500
|
+
if (this._wantsFile) {
|
|
15501
|
+
this.push(entry);
|
|
15502
|
+
batch--;
|
|
15503
|
+
}
|
|
15504
|
+
}
|
|
15505
|
+
}
|
|
15506
|
+
} else {
|
|
15507
|
+
const parent = this.parents.pop();
|
|
15508
|
+
if (!parent) {
|
|
15509
|
+
this.push(null);
|
|
15510
|
+
break;
|
|
15511
|
+
}
|
|
15512
|
+
this.parent = await parent;
|
|
15513
|
+
if (this.destroyed)
|
|
15514
|
+
return;
|
|
15515
|
+
}
|
|
15516
|
+
}
|
|
15517
|
+
} catch (error) {
|
|
15518
|
+
this.destroy(error);
|
|
15519
|
+
} finally {
|
|
15520
|
+
this.reading = false;
|
|
15521
|
+
}
|
|
15522
|
+
}
|
|
15523
|
+
async _exploreDir(path15, depth) {
|
|
15524
|
+
let files;
|
|
15525
|
+
try {
|
|
15526
|
+
files = await (0, import_promises3.readdir)(path15, this._rdOptions);
|
|
15527
|
+
} catch (error) {
|
|
15528
|
+
this._onError(error);
|
|
15529
|
+
}
|
|
15530
|
+
return { files, depth, path: path15 };
|
|
15531
|
+
}
|
|
15532
|
+
async _formatEntry(dirent, path15) {
|
|
15533
|
+
let entry;
|
|
15534
|
+
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
15535
|
+
try {
|
|
15536
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path15, basename3));
|
|
15537
|
+
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename3 };
|
|
15538
|
+
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15539
|
+
} catch (err) {
|
|
15540
|
+
this._onError(err);
|
|
15541
|
+
return;
|
|
15542
|
+
}
|
|
15543
|
+
return entry;
|
|
15544
|
+
}
|
|
15545
|
+
_onError(err) {
|
|
15546
|
+
if (isNormalFlowError(err) && !this.destroyed) {
|
|
15547
|
+
this.emit("warn", err);
|
|
15548
|
+
} else {
|
|
15549
|
+
this.destroy(err);
|
|
15550
|
+
}
|
|
15551
|
+
}
|
|
15552
|
+
async _getEntryType(entry) {
|
|
15553
|
+
if (!entry && this._statsProp in entry) {
|
|
15554
|
+
return "";
|
|
15555
|
+
}
|
|
15556
|
+
const stats = entry[this._statsProp];
|
|
15557
|
+
if (stats.isFile())
|
|
15558
|
+
return "file";
|
|
15559
|
+
if (stats.isDirectory())
|
|
15560
|
+
return "directory";
|
|
15561
|
+
if (stats && stats.isSymbolicLink()) {
|
|
15562
|
+
const full = entry.fullPath;
|
|
15563
|
+
try {
|
|
15564
|
+
const entryRealPath = await (0, import_promises3.realpath)(full);
|
|
15565
|
+
const entryRealPathStats = await (0, import_promises3.lstat)(entryRealPath);
|
|
15566
|
+
if (entryRealPathStats.isFile()) {
|
|
15567
|
+
return "file";
|
|
15568
|
+
}
|
|
15569
|
+
if (entryRealPathStats.isDirectory()) {
|
|
15570
|
+
const len = entryRealPath.length;
|
|
15571
|
+
if (full.startsWith(entryRealPath) && full.substr(len, 1) === import_node_path.sep) {
|
|
15572
|
+
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
|
|
15573
|
+
recursiveError.code = RECURSIVE_ERROR_CODE;
|
|
15574
|
+
return this._onError(recursiveError);
|
|
15575
|
+
}
|
|
15576
|
+
return "directory";
|
|
15577
|
+
}
|
|
15578
|
+
} catch (error) {
|
|
15579
|
+
this._onError(error);
|
|
15580
|
+
return "";
|
|
15581
|
+
}
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
15584
|
+
_includeAsFile(entry) {
|
|
15585
|
+
const stats = entry && entry[this._statsProp];
|
|
15586
|
+
return stats && this._wantsEverything && !stats.isDirectory();
|
|
15587
|
+
}
|
|
15588
|
+
};
|
|
15589
|
+
function readdirp(root, options = {}) {
|
|
15590
|
+
let type = options.entryType || options.type;
|
|
15591
|
+
if (type === "both")
|
|
15592
|
+
type = EntryTypes.FILE_DIR_TYPE;
|
|
15593
|
+
if (type)
|
|
15594
|
+
options.type = type;
|
|
15595
|
+
if (!root) {
|
|
15596
|
+
throw new Error("readdirp: root argument is required. Usage: readdirp(root, options)");
|
|
15597
|
+
} else if (typeof root !== "string") {
|
|
15598
|
+
throw new TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");
|
|
15599
|
+
} else if (type && !ALL_TYPES.includes(type)) {
|
|
15600
|
+
throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(", ")}`);
|
|
15601
|
+
}
|
|
15602
|
+
options.root = root;
|
|
15603
|
+
return new ReaddirpStream(options);
|
|
15604
|
+
}
|
|
15605
|
+
|
|
15606
|
+
// ../../node_modules/chokidar/esm/handler.js
|
|
15607
|
+
var import_fs7 = require("fs");
|
|
15608
|
+
var import_promises4 = require("fs/promises");
|
|
15609
|
+
var sysPath = __toESM(require("path"), 1);
|
|
15610
|
+
var import_os4 = require("os");
|
|
15611
|
+
var STR_DATA = "data";
|
|
15612
|
+
var STR_END = "end";
|
|
15613
|
+
var STR_CLOSE = "close";
|
|
15614
|
+
var EMPTY_FN = () => {
|
|
15615
|
+
};
|
|
15616
|
+
var pl = process.platform;
|
|
15617
|
+
var isWindows2 = pl === "win32";
|
|
15618
|
+
var isMacos = pl === "darwin";
|
|
15619
|
+
var isLinux = pl === "linux";
|
|
15620
|
+
var isFreeBSD = pl === "freebsd";
|
|
15621
|
+
var isIBMi = (0, import_os4.type)() === "OS400";
|
|
15622
|
+
var EVENTS = {
|
|
15623
|
+
ALL: "all",
|
|
15624
|
+
READY: "ready",
|
|
15625
|
+
ADD: "add",
|
|
15626
|
+
CHANGE: "change",
|
|
15627
|
+
ADD_DIR: "addDir",
|
|
15628
|
+
UNLINK: "unlink",
|
|
15629
|
+
UNLINK_DIR: "unlinkDir",
|
|
15630
|
+
RAW: "raw",
|
|
15631
|
+
ERROR: "error"
|
|
15632
|
+
};
|
|
15633
|
+
var EV = EVENTS;
|
|
15634
|
+
var THROTTLE_MODE_WATCH = "watch";
|
|
15635
|
+
var statMethods = { lstat: import_promises4.lstat, stat: import_promises4.stat };
|
|
15636
|
+
var KEY_LISTENERS = "listeners";
|
|
15637
|
+
var KEY_ERR = "errHandlers";
|
|
15638
|
+
var KEY_RAW = "rawEmitters";
|
|
15639
|
+
var HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
|
|
15640
|
+
var binaryExtensions = /* @__PURE__ */ new Set([
|
|
15641
|
+
"3dm",
|
|
15642
|
+
"3ds",
|
|
15643
|
+
"3g2",
|
|
15644
|
+
"3gp",
|
|
15645
|
+
"7z",
|
|
15646
|
+
"a",
|
|
15647
|
+
"aac",
|
|
15648
|
+
"adp",
|
|
15649
|
+
"afdesign",
|
|
15650
|
+
"afphoto",
|
|
15651
|
+
"afpub",
|
|
15652
|
+
"ai",
|
|
15653
|
+
"aif",
|
|
15654
|
+
"aiff",
|
|
15655
|
+
"alz",
|
|
15656
|
+
"ape",
|
|
15657
|
+
"apk",
|
|
15658
|
+
"appimage",
|
|
15659
|
+
"ar",
|
|
15660
|
+
"arj",
|
|
15661
|
+
"asf",
|
|
15662
|
+
"au",
|
|
15663
|
+
"avi",
|
|
15664
|
+
"bak",
|
|
15665
|
+
"baml",
|
|
15666
|
+
"bh",
|
|
15667
|
+
"bin",
|
|
15668
|
+
"bk",
|
|
15669
|
+
"bmp",
|
|
15670
|
+
"btif",
|
|
15671
|
+
"bz2",
|
|
15672
|
+
"bzip2",
|
|
15673
|
+
"cab",
|
|
15674
|
+
"caf",
|
|
15675
|
+
"cgm",
|
|
15676
|
+
"class",
|
|
15677
|
+
"cmx",
|
|
15678
|
+
"cpio",
|
|
15679
|
+
"cr2",
|
|
15680
|
+
"cur",
|
|
15681
|
+
"dat",
|
|
15682
|
+
"dcm",
|
|
15683
|
+
"deb",
|
|
15684
|
+
"dex",
|
|
15685
|
+
"djvu",
|
|
15686
|
+
"dll",
|
|
15687
|
+
"dmg",
|
|
15688
|
+
"dng",
|
|
15689
|
+
"doc",
|
|
15690
|
+
"docm",
|
|
15691
|
+
"docx",
|
|
15692
|
+
"dot",
|
|
15693
|
+
"dotm",
|
|
15694
|
+
"dra",
|
|
15695
|
+
"DS_Store",
|
|
15696
|
+
"dsk",
|
|
15697
|
+
"dts",
|
|
15698
|
+
"dtshd",
|
|
15699
|
+
"dvb",
|
|
15700
|
+
"dwg",
|
|
15701
|
+
"dxf",
|
|
15702
|
+
"ecelp4800",
|
|
15703
|
+
"ecelp7470",
|
|
15704
|
+
"ecelp9600",
|
|
15705
|
+
"egg",
|
|
15706
|
+
"eol",
|
|
15707
|
+
"eot",
|
|
15708
|
+
"epub",
|
|
15709
|
+
"exe",
|
|
15710
|
+
"f4v",
|
|
15711
|
+
"fbs",
|
|
15712
|
+
"fh",
|
|
15713
|
+
"fla",
|
|
15714
|
+
"flac",
|
|
15715
|
+
"flatpak",
|
|
15716
|
+
"fli",
|
|
15717
|
+
"flv",
|
|
15718
|
+
"fpx",
|
|
15719
|
+
"fst",
|
|
15720
|
+
"fvt",
|
|
15721
|
+
"g3",
|
|
15722
|
+
"gh",
|
|
15723
|
+
"gif",
|
|
15724
|
+
"graffle",
|
|
15725
|
+
"gz",
|
|
15726
|
+
"gzip",
|
|
15727
|
+
"h261",
|
|
15728
|
+
"h263",
|
|
15729
|
+
"h264",
|
|
15730
|
+
"icns",
|
|
15731
|
+
"ico",
|
|
15732
|
+
"ief",
|
|
15733
|
+
"img",
|
|
15734
|
+
"ipa",
|
|
15735
|
+
"iso",
|
|
15736
|
+
"jar",
|
|
15737
|
+
"jpeg",
|
|
15738
|
+
"jpg",
|
|
15739
|
+
"jpgv",
|
|
15740
|
+
"jpm",
|
|
15741
|
+
"jxr",
|
|
15742
|
+
"key",
|
|
15743
|
+
"ktx",
|
|
15744
|
+
"lha",
|
|
15745
|
+
"lib",
|
|
15746
|
+
"lvp",
|
|
15747
|
+
"lz",
|
|
15748
|
+
"lzh",
|
|
15749
|
+
"lzma",
|
|
15750
|
+
"lzo",
|
|
15751
|
+
"m3u",
|
|
15752
|
+
"m4a",
|
|
15753
|
+
"m4v",
|
|
15754
|
+
"mar",
|
|
15755
|
+
"mdi",
|
|
15756
|
+
"mht",
|
|
15757
|
+
"mid",
|
|
15758
|
+
"midi",
|
|
15759
|
+
"mj2",
|
|
15760
|
+
"mka",
|
|
15761
|
+
"mkv",
|
|
15762
|
+
"mmr",
|
|
15763
|
+
"mng",
|
|
15764
|
+
"mobi",
|
|
15765
|
+
"mov",
|
|
15766
|
+
"movie",
|
|
15767
|
+
"mp3",
|
|
15768
|
+
"mp4",
|
|
15769
|
+
"mp4a",
|
|
15770
|
+
"mpeg",
|
|
15771
|
+
"mpg",
|
|
15772
|
+
"mpga",
|
|
15773
|
+
"mxu",
|
|
15774
|
+
"nef",
|
|
15775
|
+
"npx",
|
|
15776
|
+
"numbers",
|
|
15777
|
+
"nupkg",
|
|
15778
|
+
"o",
|
|
15779
|
+
"odp",
|
|
15780
|
+
"ods",
|
|
15781
|
+
"odt",
|
|
15782
|
+
"oga",
|
|
15783
|
+
"ogg",
|
|
15784
|
+
"ogv",
|
|
15785
|
+
"otf",
|
|
15786
|
+
"ott",
|
|
15787
|
+
"pages",
|
|
15788
|
+
"pbm",
|
|
15789
|
+
"pcx",
|
|
15790
|
+
"pdb",
|
|
15791
|
+
"pdf",
|
|
15792
|
+
"pea",
|
|
15793
|
+
"pgm",
|
|
15794
|
+
"pic",
|
|
15795
|
+
"png",
|
|
15796
|
+
"pnm",
|
|
15797
|
+
"pot",
|
|
15798
|
+
"potm",
|
|
15799
|
+
"potx",
|
|
15800
|
+
"ppa",
|
|
15801
|
+
"ppam",
|
|
15802
|
+
"ppm",
|
|
15803
|
+
"pps",
|
|
15804
|
+
"ppsm",
|
|
15805
|
+
"ppsx",
|
|
15806
|
+
"ppt",
|
|
15807
|
+
"pptm",
|
|
15808
|
+
"pptx",
|
|
15809
|
+
"psd",
|
|
15810
|
+
"pya",
|
|
15811
|
+
"pyc",
|
|
15812
|
+
"pyo",
|
|
15813
|
+
"pyv",
|
|
15814
|
+
"qt",
|
|
15815
|
+
"rar",
|
|
15816
|
+
"ras",
|
|
15817
|
+
"raw",
|
|
15818
|
+
"resources",
|
|
15819
|
+
"rgb",
|
|
15820
|
+
"rip",
|
|
15821
|
+
"rlc",
|
|
15822
|
+
"rmf",
|
|
15823
|
+
"rmvb",
|
|
15824
|
+
"rpm",
|
|
15825
|
+
"rtf",
|
|
15826
|
+
"rz",
|
|
15827
|
+
"s3m",
|
|
15828
|
+
"s7z",
|
|
15829
|
+
"scpt",
|
|
15830
|
+
"sgi",
|
|
15831
|
+
"shar",
|
|
15832
|
+
"snap",
|
|
15833
|
+
"sil",
|
|
15834
|
+
"sketch",
|
|
15835
|
+
"slk",
|
|
15836
|
+
"smv",
|
|
15837
|
+
"snk",
|
|
15838
|
+
"so",
|
|
15839
|
+
"stl",
|
|
15840
|
+
"suo",
|
|
15841
|
+
"sub",
|
|
15842
|
+
"swf",
|
|
15843
|
+
"tar",
|
|
15844
|
+
"tbz",
|
|
15845
|
+
"tbz2",
|
|
15846
|
+
"tga",
|
|
15847
|
+
"tgz",
|
|
15848
|
+
"thmx",
|
|
15849
|
+
"tif",
|
|
15850
|
+
"tiff",
|
|
15851
|
+
"tlz",
|
|
15852
|
+
"ttc",
|
|
15853
|
+
"ttf",
|
|
15854
|
+
"txz",
|
|
15855
|
+
"udf",
|
|
15856
|
+
"uvh",
|
|
15857
|
+
"uvi",
|
|
15858
|
+
"uvm",
|
|
15859
|
+
"uvp",
|
|
15860
|
+
"uvs",
|
|
15861
|
+
"uvu",
|
|
15862
|
+
"viv",
|
|
15863
|
+
"vob",
|
|
15864
|
+
"war",
|
|
15865
|
+
"wav",
|
|
15866
|
+
"wax",
|
|
15867
|
+
"wbmp",
|
|
15868
|
+
"wdp",
|
|
15869
|
+
"weba",
|
|
15870
|
+
"webm",
|
|
15871
|
+
"webp",
|
|
15872
|
+
"whl",
|
|
15873
|
+
"wim",
|
|
15874
|
+
"wm",
|
|
15875
|
+
"wma",
|
|
15876
|
+
"wmv",
|
|
15877
|
+
"wmx",
|
|
15878
|
+
"woff",
|
|
15879
|
+
"woff2",
|
|
15880
|
+
"wrm",
|
|
15881
|
+
"wvx",
|
|
15882
|
+
"xbm",
|
|
15883
|
+
"xif",
|
|
15884
|
+
"xla",
|
|
15885
|
+
"xlam",
|
|
15886
|
+
"xls",
|
|
15887
|
+
"xlsb",
|
|
15888
|
+
"xlsm",
|
|
15889
|
+
"xlsx",
|
|
15890
|
+
"xlt",
|
|
15891
|
+
"xltm",
|
|
15892
|
+
"xltx",
|
|
15893
|
+
"xm",
|
|
15894
|
+
"xmind",
|
|
15895
|
+
"xpi",
|
|
15896
|
+
"xpm",
|
|
15897
|
+
"xwd",
|
|
15898
|
+
"xz",
|
|
15899
|
+
"z",
|
|
15900
|
+
"zip",
|
|
15901
|
+
"zipx"
|
|
15902
|
+
]);
|
|
15903
|
+
var isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
|
|
15904
|
+
var foreach = (val, fn) => {
|
|
15905
|
+
if (val instanceof Set) {
|
|
15906
|
+
val.forEach(fn);
|
|
15907
|
+
} else {
|
|
15908
|
+
fn(val);
|
|
15909
|
+
}
|
|
15910
|
+
};
|
|
15911
|
+
var addAndConvert = (main, prop, item) => {
|
|
15912
|
+
let container = main[prop];
|
|
15913
|
+
if (!(container instanceof Set)) {
|
|
15914
|
+
main[prop] = container = /* @__PURE__ */ new Set([container]);
|
|
15915
|
+
}
|
|
15916
|
+
container.add(item);
|
|
15917
|
+
};
|
|
15918
|
+
var clearItem = (cont) => (key) => {
|
|
15919
|
+
const set = cont[key];
|
|
15920
|
+
if (set instanceof Set) {
|
|
15921
|
+
set.clear();
|
|
15922
|
+
} else {
|
|
15923
|
+
delete cont[key];
|
|
15924
|
+
}
|
|
15925
|
+
};
|
|
15926
|
+
var delFromSet = (main, prop, item) => {
|
|
15927
|
+
const container = main[prop];
|
|
15928
|
+
if (container instanceof Set) {
|
|
15929
|
+
container.delete(item);
|
|
15930
|
+
} else if (container === item) {
|
|
15931
|
+
delete main[prop];
|
|
15932
|
+
}
|
|
15933
|
+
};
|
|
15934
|
+
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15935
|
+
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15936
|
+
function createFsWatchInstance(path15, options, listener, errHandler, emitRaw) {
|
|
15937
|
+
const handleEvent = (rawEvent, evPath) => {
|
|
15938
|
+
listener(path15);
|
|
15939
|
+
emitRaw(rawEvent, evPath, { watchedPath: path15 });
|
|
15940
|
+
if (evPath && path15 !== evPath) {
|
|
15941
|
+
fsWatchBroadcast(sysPath.resolve(path15, evPath), KEY_LISTENERS, sysPath.join(path15, evPath));
|
|
15942
|
+
}
|
|
15943
|
+
};
|
|
15944
|
+
try {
|
|
15945
|
+
return (0, import_fs7.watch)(path15, {
|
|
15946
|
+
persistent: options.persistent
|
|
15947
|
+
}, handleEvent);
|
|
15948
|
+
} catch (error) {
|
|
15949
|
+
errHandler(error);
|
|
15950
|
+
return void 0;
|
|
15951
|
+
}
|
|
15952
|
+
}
|
|
15953
|
+
var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
15954
|
+
const cont = FsWatchInstances.get(fullPath);
|
|
15955
|
+
if (!cont)
|
|
15956
|
+
return;
|
|
15957
|
+
foreach(cont[listenerType], (listener) => {
|
|
15958
|
+
listener(val1, val2, val3);
|
|
15959
|
+
});
|
|
15960
|
+
};
|
|
15961
|
+
var setFsWatchListener = (path15, fullPath, options, handlers) => {
|
|
15962
|
+
const { listener, errHandler, rawEmitter } = handlers;
|
|
15963
|
+
let cont = FsWatchInstances.get(fullPath);
|
|
15964
|
+
let watcher;
|
|
15965
|
+
if (!options.persistent) {
|
|
15966
|
+
watcher = createFsWatchInstance(path15, options, listener, errHandler, rawEmitter);
|
|
15967
|
+
if (!watcher)
|
|
15968
|
+
return;
|
|
15969
|
+
return watcher.close.bind(watcher);
|
|
15970
|
+
}
|
|
15971
|
+
if (cont) {
|
|
15972
|
+
addAndConvert(cont, KEY_LISTENERS, listener);
|
|
15973
|
+
addAndConvert(cont, KEY_ERR, errHandler);
|
|
15974
|
+
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
15975
|
+
} else {
|
|
15976
|
+
watcher = createFsWatchInstance(
|
|
15977
|
+
path15,
|
|
15978
|
+
options,
|
|
15979
|
+
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
15980
|
+
errHandler,
|
|
15981
|
+
// no need to use broadcast here
|
|
15982
|
+
fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
|
|
15983
|
+
);
|
|
15984
|
+
if (!watcher)
|
|
15985
|
+
return;
|
|
15986
|
+
watcher.on(EV.ERROR, async (error) => {
|
|
15987
|
+
const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
|
|
15988
|
+
if (cont)
|
|
15989
|
+
cont.watcherUnusable = true;
|
|
15990
|
+
if (isWindows2 && error.code === "EPERM") {
|
|
15991
|
+
try {
|
|
15992
|
+
const fd = await (0, import_promises4.open)(path15, "r");
|
|
15993
|
+
await fd.close();
|
|
15994
|
+
broadcastErr(error);
|
|
15995
|
+
} catch (err) {
|
|
15996
|
+
}
|
|
15997
|
+
} else {
|
|
15998
|
+
broadcastErr(error);
|
|
15999
|
+
}
|
|
16000
|
+
});
|
|
16001
|
+
cont = {
|
|
16002
|
+
listeners: listener,
|
|
16003
|
+
errHandlers: errHandler,
|
|
16004
|
+
rawEmitters: rawEmitter,
|
|
16005
|
+
watcher
|
|
16006
|
+
};
|
|
16007
|
+
FsWatchInstances.set(fullPath, cont);
|
|
16008
|
+
}
|
|
16009
|
+
return () => {
|
|
16010
|
+
delFromSet(cont, KEY_LISTENERS, listener);
|
|
16011
|
+
delFromSet(cont, KEY_ERR, errHandler);
|
|
16012
|
+
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
16013
|
+
if (isEmptySet(cont.listeners)) {
|
|
16014
|
+
cont.watcher.close();
|
|
16015
|
+
FsWatchInstances.delete(fullPath);
|
|
16016
|
+
HANDLER_KEYS.forEach(clearItem(cont));
|
|
16017
|
+
cont.watcher = void 0;
|
|
16018
|
+
Object.freeze(cont);
|
|
16019
|
+
}
|
|
16020
|
+
};
|
|
16021
|
+
};
|
|
16022
|
+
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
16023
|
+
var setFsWatchFileListener = (path15, fullPath, options, handlers) => {
|
|
16024
|
+
const { listener, rawEmitter } = handlers;
|
|
16025
|
+
let cont = FsWatchFileInstances.get(fullPath);
|
|
16026
|
+
const copts = cont && cont.options;
|
|
16027
|
+
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
|
|
16028
|
+
(0, import_fs7.unwatchFile)(fullPath);
|
|
16029
|
+
cont = void 0;
|
|
16030
|
+
}
|
|
16031
|
+
if (cont) {
|
|
16032
|
+
addAndConvert(cont, KEY_LISTENERS, listener);
|
|
16033
|
+
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
16034
|
+
} else {
|
|
16035
|
+
cont = {
|
|
16036
|
+
listeners: listener,
|
|
16037
|
+
rawEmitters: rawEmitter,
|
|
16038
|
+
options,
|
|
16039
|
+
watcher: (0, import_fs7.watchFile)(fullPath, options, (curr, prev) => {
|
|
16040
|
+
foreach(cont.rawEmitters, (rawEmitter2) => {
|
|
16041
|
+
rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
|
|
16042
|
+
});
|
|
16043
|
+
const currmtime = curr.mtimeMs;
|
|
16044
|
+
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
16045
|
+
foreach(cont.listeners, (listener2) => listener2(path15, curr));
|
|
16046
|
+
}
|
|
16047
|
+
})
|
|
16048
|
+
};
|
|
16049
|
+
FsWatchFileInstances.set(fullPath, cont);
|
|
16050
|
+
}
|
|
16051
|
+
return () => {
|
|
16052
|
+
delFromSet(cont, KEY_LISTENERS, listener);
|
|
16053
|
+
delFromSet(cont, KEY_RAW, rawEmitter);
|
|
16054
|
+
if (isEmptySet(cont.listeners)) {
|
|
16055
|
+
FsWatchFileInstances.delete(fullPath);
|
|
16056
|
+
(0, import_fs7.unwatchFile)(fullPath);
|
|
16057
|
+
cont.options = cont.watcher = void 0;
|
|
16058
|
+
Object.freeze(cont);
|
|
16059
|
+
}
|
|
16060
|
+
};
|
|
16061
|
+
};
|
|
16062
|
+
var NodeFsHandler = class {
|
|
16063
|
+
constructor(fsW) {
|
|
16064
|
+
this.fsw = fsW;
|
|
16065
|
+
this._boundHandleError = (error) => fsW._handleError(error);
|
|
16066
|
+
}
|
|
16067
|
+
/**
|
|
16068
|
+
* Watch file for changes with fs_watchFile or fs_watch.
|
|
16069
|
+
* @param path to file or dir
|
|
16070
|
+
* @param listener on fs change
|
|
16071
|
+
* @returns closer for the watcher instance
|
|
16072
|
+
*/
|
|
16073
|
+
_watchWithNodeFs(path15, listener) {
|
|
16074
|
+
const opts = this.fsw.options;
|
|
16075
|
+
const directory = sysPath.dirname(path15);
|
|
16076
|
+
const basename3 = sysPath.basename(path15);
|
|
16077
|
+
const parent = this.fsw._getWatchedDir(directory);
|
|
16078
|
+
parent.add(basename3);
|
|
16079
|
+
const absolutePath = sysPath.resolve(path15);
|
|
16080
|
+
const options = {
|
|
16081
|
+
persistent: opts.persistent
|
|
16082
|
+
};
|
|
16083
|
+
if (!listener)
|
|
16084
|
+
listener = EMPTY_FN;
|
|
16085
|
+
let closer;
|
|
16086
|
+
if (opts.usePolling) {
|
|
16087
|
+
const enableBin = opts.interval !== opts.binaryInterval;
|
|
16088
|
+
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
16089
|
+
closer = setFsWatchFileListener(path15, absolutePath, options, {
|
|
16090
|
+
listener,
|
|
16091
|
+
rawEmitter: this.fsw._emitRaw
|
|
16092
|
+
});
|
|
16093
|
+
} else {
|
|
16094
|
+
closer = setFsWatchListener(path15, absolutePath, options, {
|
|
16095
|
+
listener,
|
|
16096
|
+
errHandler: this._boundHandleError,
|
|
16097
|
+
rawEmitter: this.fsw._emitRaw
|
|
16098
|
+
});
|
|
16099
|
+
}
|
|
16100
|
+
return closer;
|
|
16101
|
+
}
|
|
16102
|
+
/**
|
|
16103
|
+
* Watch a file and emit add event if warranted.
|
|
16104
|
+
* @returns closer for the watcher instance
|
|
16105
|
+
*/
|
|
16106
|
+
_handleFile(file, stats, initialAdd) {
|
|
16107
|
+
if (this.fsw.closed) {
|
|
16108
|
+
return;
|
|
16109
|
+
}
|
|
16110
|
+
const dirname4 = sysPath.dirname(file);
|
|
16111
|
+
const basename3 = sysPath.basename(file);
|
|
16112
|
+
const parent = this.fsw._getWatchedDir(dirname4);
|
|
16113
|
+
let prevStats = stats;
|
|
16114
|
+
if (parent.has(basename3))
|
|
16115
|
+
return;
|
|
16116
|
+
const listener = async (path15, newStats) => {
|
|
16117
|
+
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
16118
|
+
return;
|
|
16119
|
+
if (!newStats || newStats.mtimeMs === 0) {
|
|
16120
|
+
try {
|
|
16121
|
+
const newStats2 = await (0, import_promises4.stat)(file);
|
|
16122
|
+
if (this.fsw.closed)
|
|
16123
|
+
return;
|
|
16124
|
+
const at = newStats2.atimeMs;
|
|
16125
|
+
const mt = newStats2.mtimeMs;
|
|
16126
|
+
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
16127
|
+
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
16128
|
+
}
|
|
16129
|
+
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
16130
|
+
this.fsw._closeFile(path15);
|
|
16131
|
+
prevStats = newStats2;
|
|
16132
|
+
const closer2 = this._watchWithNodeFs(file, listener);
|
|
16133
|
+
if (closer2)
|
|
16134
|
+
this.fsw._addPathCloser(path15, closer2);
|
|
16135
|
+
} else {
|
|
16136
|
+
prevStats = newStats2;
|
|
16137
|
+
}
|
|
16138
|
+
} catch (error) {
|
|
16139
|
+
this.fsw._remove(dirname4, basename3);
|
|
16140
|
+
}
|
|
16141
|
+
} else if (parent.has(basename3)) {
|
|
16142
|
+
const at = newStats.atimeMs;
|
|
16143
|
+
const mt = newStats.mtimeMs;
|
|
16144
|
+
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
|
|
16145
|
+
this.fsw._emit(EV.CHANGE, file, newStats);
|
|
16146
|
+
}
|
|
16147
|
+
prevStats = newStats;
|
|
16148
|
+
}
|
|
16149
|
+
};
|
|
16150
|
+
const closer = this._watchWithNodeFs(file, listener);
|
|
16151
|
+
if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
|
|
16152
|
+
if (!this.fsw._throttle(EV.ADD, file, 0))
|
|
16153
|
+
return;
|
|
16154
|
+
this.fsw._emit(EV.ADD, file, stats);
|
|
16155
|
+
}
|
|
16156
|
+
return closer;
|
|
16157
|
+
}
|
|
16158
|
+
/**
|
|
16159
|
+
* Handle symlinks encountered while reading a dir.
|
|
16160
|
+
* @param entry returned by readdirp
|
|
16161
|
+
* @param directory path of dir being read
|
|
16162
|
+
* @param path of this item
|
|
16163
|
+
* @param item basename of this item
|
|
16164
|
+
* @returns true if no more processing is needed for this entry.
|
|
16165
|
+
*/
|
|
16166
|
+
async _handleSymlink(entry, directory, path15, item) {
|
|
16167
|
+
if (this.fsw.closed) {
|
|
16168
|
+
return;
|
|
16169
|
+
}
|
|
16170
|
+
const full = entry.fullPath;
|
|
16171
|
+
const dir = this.fsw._getWatchedDir(directory);
|
|
16172
|
+
if (!this.fsw.options.followSymlinks) {
|
|
16173
|
+
this.fsw._incrReadyCount();
|
|
16174
|
+
let linkPath;
|
|
16175
|
+
try {
|
|
16176
|
+
linkPath = await (0, import_promises4.realpath)(path15);
|
|
16177
|
+
} catch (e) {
|
|
16178
|
+
this.fsw._emitReady();
|
|
16179
|
+
return true;
|
|
16180
|
+
}
|
|
16181
|
+
if (this.fsw.closed)
|
|
16182
|
+
return;
|
|
16183
|
+
if (dir.has(item)) {
|
|
16184
|
+
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
16185
|
+
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16186
|
+
this.fsw._emit(EV.CHANGE, path15, entry.stats);
|
|
16187
|
+
}
|
|
16188
|
+
} else {
|
|
16189
|
+
dir.add(item);
|
|
16190
|
+
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16191
|
+
this.fsw._emit(EV.ADD, path15, entry.stats);
|
|
16192
|
+
}
|
|
16193
|
+
this.fsw._emitReady();
|
|
16194
|
+
return true;
|
|
16195
|
+
}
|
|
16196
|
+
if (this.fsw._symlinkPaths.has(full)) {
|
|
16197
|
+
return true;
|
|
16198
|
+
}
|
|
16199
|
+
this.fsw._symlinkPaths.set(full, true);
|
|
16200
|
+
}
|
|
16201
|
+
_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
|
|
16202
|
+
directory = sysPath.join(directory, "");
|
|
16203
|
+
throttler = this.fsw._throttle("readdir", directory, 1e3);
|
|
16204
|
+
if (!throttler)
|
|
16205
|
+
return;
|
|
16206
|
+
const previous = this.fsw._getWatchedDir(wh.path);
|
|
16207
|
+
const current = /* @__PURE__ */ new Set();
|
|
16208
|
+
let stream = this.fsw._readdirp(directory, {
|
|
16209
|
+
fileFilter: (entry) => wh.filterPath(entry),
|
|
16210
|
+
directoryFilter: (entry) => wh.filterDir(entry)
|
|
16211
|
+
});
|
|
16212
|
+
if (!stream)
|
|
16213
|
+
return;
|
|
16214
|
+
stream.on(STR_DATA, async (entry) => {
|
|
16215
|
+
if (this.fsw.closed) {
|
|
16216
|
+
stream = void 0;
|
|
16217
|
+
return;
|
|
16218
|
+
}
|
|
16219
|
+
const item = entry.path;
|
|
16220
|
+
let path15 = sysPath.join(directory, item);
|
|
16221
|
+
current.add(item);
|
|
16222
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path15, item)) {
|
|
16223
|
+
return;
|
|
16224
|
+
}
|
|
16225
|
+
if (this.fsw.closed) {
|
|
16226
|
+
stream = void 0;
|
|
16227
|
+
return;
|
|
16228
|
+
}
|
|
16229
|
+
if (item === target || !target && !previous.has(item)) {
|
|
16230
|
+
this.fsw._incrReadyCount();
|
|
16231
|
+
path15 = sysPath.join(dir, sysPath.relative(dir, path15));
|
|
16232
|
+
this._addToNodeFs(path15, initialAdd, wh, depth + 1);
|
|
16233
|
+
}
|
|
16234
|
+
}).on(EV.ERROR, this._boundHandleError);
|
|
16235
|
+
return new Promise((resolve4, reject) => {
|
|
16236
|
+
if (!stream)
|
|
16237
|
+
return reject();
|
|
16238
|
+
stream.once(STR_END, () => {
|
|
16239
|
+
if (this.fsw.closed) {
|
|
16240
|
+
stream = void 0;
|
|
16241
|
+
return;
|
|
16242
|
+
}
|
|
16243
|
+
const wasThrottled = throttler ? throttler.clear() : false;
|
|
16244
|
+
resolve4(void 0);
|
|
16245
|
+
previous.getChildren().filter((item) => {
|
|
16246
|
+
return item !== directory && !current.has(item);
|
|
16247
|
+
}).forEach((item) => {
|
|
16248
|
+
this.fsw._remove(directory, item);
|
|
16249
|
+
});
|
|
16250
|
+
stream = void 0;
|
|
16251
|
+
if (wasThrottled)
|
|
16252
|
+
this._handleRead(directory, false, wh, target, dir, depth, throttler);
|
|
16253
|
+
});
|
|
16254
|
+
});
|
|
16255
|
+
}
|
|
16256
|
+
/**
|
|
16257
|
+
* Read directory to add / remove files from `@watched` list and re-read it on change.
|
|
16258
|
+
* @param dir fs path
|
|
16259
|
+
* @param stats
|
|
16260
|
+
* @param initialAdd
|
|
16261
|
+
* @param depth relative to user-supplied path
|
|
16262
|
+
* @param target child path targeted for watch
|
|
16263
|
+
* @param wh Common watch helpers for this path
|
|
16264
|
+
* @param realpath
|
|
16265
|
+
* @returns closer for the watcher instance.
|
|
16266
|
+
*/
|
|
16267
|
+
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
|
|
16268
|
+
const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
|
|
16269
|
+
const tracked = parentDir.has(sysPath.basename(dir));
|
|
16270
|
+
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
|
|
16271
|
+
this.fsw._emit(EV.ADD_DIR, dir, stats);
|
|
16272
|
+
}
|
|
16273
|
+
parentDir.add(sysPath.basename(dir));
|
|
16274
|
+
this.fsw._getWatchedDir(dir);
|
|
16275
|
+
let throttler;
|
|
16276
|
+
let closer;
|
|
16277
|
+
const oDepth = this.fsw.options.depth;
|
|
16278
|
+
if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath2)) {
|
|
16279
|
+
if (!target) {
|
|
16280
|
+
await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
|
|
16281
|
+
if (this.fsw.closed)
|
|
16282
|
+
return;
|
|
16283
|
+
}
|
|
16284
|
+
closer = this._watchWithNodeFs(dir, (dirPath, stats2) => {
|
|
16285
|
+
if (stats2 && stats2.mtimeMs === 0)
|
|
16286
|
+
return;
|
|
16287
|
+
this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
|
|
16288
|
+
});
|
|
16289
|
+
}
|
|
16290
|
+
return closer;
|
|
16291
|
+
}
|
|
16292
|
+
/**
|
|
16293
|
+
* Handle added file, directory, or glob pattern.
|
|
16294
|
+
* Delegates call to _handleFile / _handleDir after checks.
|
|
16295
|
+
* @param path to file or ir
|
|
16296
|
+
* @param initialAdd was the file added at watch instantiation?
|
|
16297
|
+
* @param priorWh depth relative to user-supplied path
|
|
16298
|
+
* @param depth Child path actually targeted for watch
|
|
16299
|
+
* @param target Child path actually targeted for watch
|
|
16300
|
+
*/
|
|
16301
|
+
async _addToNodeFs(path15, initialAdd, priorWh, depth, target) {
|
|
16302
|
+
const ready = this.fsw._emitReady;
|
|
16303
|
+
if (this.fsw._isIgnored(path15) || this.fsw.closed) {
|
|
16304
|
+
ready();
|
|
16305
|
+
return false;
|
|
16306
|
+
}
|
|
16307
|
+
const wh = this.fsw._getWatchHelpers(path15);
|
|
16308
|
+
if (priorWh) {
|
|
16309
|
+
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
16310
|
+
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
16311
|
+
}
|
|
16312
|
+
try {
|
|
16313
|
+
const stats = await statMethods[wh.statMethod](wh.watchPath);
|
|
16314
|
+
if (this.fsw.closed)
|
|
16315
|
+
return;
|
|
16316
|
+
if (this.fsw._isIgnored(wh.watchPath, stats)) {
|
|
16317
|
+
ready();
|
|
16318
|
+
return false;
|
|
16319
|
+
}
|
|
16320
|
+
const follow = this.fsw.options.followSymlinks;
|
|
16321
|
+
let closer;
|
|
16322
|
+
if (stats.isDirectory()) {
|
|
16323
|
+
const absPath = sysPath.resolve(path15);
|
|
16324
|
+
const targetPath = follow ? await (0, import_promises4.realpath)(path15) : path15;
|
|
16325
|
+
if (this.fsw.closed)
|
|
16326
|
+
return;
|
|
16327
|
+
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
16328
|
+
if (this.fsw.closed)
|
|
16329
|
+
return;
|
|
16330
|
+
if (absPath !== targetPath && targetPath !== void 0) {
|
|
16331
|
+
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
16332
|
+
}
|
|
16333
|
+
} else if (stats.isSymbolicLink()) {
|
|
16334
|
+
const targetPath = follow ? await (0, import_promises4.realpath)(path15) : path15;
|
|
16335
|
+
if (this.fsw.closed)
|
|
16336
|
+
return;
|
|
16337
|
+
const parent = sysPath.dirname(wh.watchPath);
|
|
16338
|
+
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
16339
|
+
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
16340
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path15, wh, targetPath);
|
|
16341
|
+
if (this.fsw.closed)
|
|
16342
|
+
return;
|
|
16343
|
+
if (targetPath !== void 0) {
|
|
16344
|
+
this.fsw._symlinkPaths.set(sysPath.resolve(path15), targetPath);
|
|
16345
|
+
}
|
|
16346
|
+
} else {
|
|
16347
|
+
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
16348
|
+
}
|
|
16349
|
+
ready();
|
|
16350
|
+
if (closer)
|
|
16351
|
+
this.fsw._addPathCloser(path15, closer);
|
|
16352
|
+
return false;
|
|
16353
|
+
} catch (error) {
|
|
16354
|
+
if (this.fsw._handleError(error)) {
|
|
16355
|
+
ready();
|
|
16356
|
+
return path15;
|
|
16357
|
+
}
|
|
16358
|
+
}
|
|
16359
|
+
}
|
|
16360
|
+
};
|
|
16361
|
+
|
|
16362
|
+
// ../../node_modules/chokidar/esm/index.js
|
|
16363
|
+
var SLASH = "/";
|
|
16364
|
+
var SLASH_SLASH = "//";
|
|
16365
|
+
var ONE_DOT = ".";
|
|
16366
|
+
var TWO_DOTS = "..";
|
|
16367
|
+
var STRING_TYPE = "string";
|
|
16368
|
+
var BACK_SLASH_RE = /\\/g;
|
|
16369
|
+
var DOUBLE_SLASH_RE = /\/\//;
|
|
16370
|
+
var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
|
|
16371
|
+
var REPLACER_RE = /^\.[/\\]/;
|
|
16372
|
+
function arrify(item) {
|
|
16373
|
+
return Array.isArray(item) ? item : [item];
|
|
16374
|
+
}
|
|
16375
|
+
var isMatcherObject = (matcher) => typeof matcher === "object" && matcher !== null && !(matcher instanceof RegExp);
|
|
16376
|
+
function createPattern(matcher) {
|
|
16377
|
+
if (typeof matcher === "function")
|
|
16378
|
+
return matcher;
|
|
16379
|
+
if (typeof matcher === "string")
|
|
16380
|
+
return (string) => matcher === string;
|
|
16381
|
+
if (matcher instanceof RegExp)
|
|
16382
|
+
return (string) => matcher.test(string);
|
|
16383
|
+
if (typeof matcher === "object" && matcher !== null) {
|
|
16384
|
+
return (string) => {
|
|
16385
|
+
if (matcher.path === string)
|
|
16386
|
+
return true;
|
|
16387
|
+
if (matcher.recursive) {
|
|
16388
|
+
const relative3 = sysPath2.relative(matcher.path, string);
|
|
16389
|
+
if (!relative3) {
|
|
16390
|
+
return false;
|
|
16391
|
+
}
|
|
16392
|
+
return !relative3.startsWith("..") && !sysPath2.isAbsolute(relative3);
|
|
16393
|
+
}
|
|
16394
|
+
return false;
|
|
16395
|
+
};
|
|
16396
|
+
}
|
|
16397
|
+
return () => false;
|
|
16398
|
+
}
|
|
16399
|
+
function normalizePath(path15) {
|
|
16400
|
+
if (typeof path15 !== "string")
|
|
16401
|
+
throw new Error("string expected");
|
|
16402
|
+
path15 = sysPath2.normalize(path15);
|
|
16403
|
+
path15 = path15.replace(/\\/g, "/");
|
|
16404
|
+
let prepend = false;
|
|
16405
|
+
if (path15.startsWith("//"))
|
|
16406
|
+
prepend = true;
|
|
16407
|
+
const DOUBLE_SLASH_RE2 = /\/\//;
|
|
16408
|
+
while (path15.match(DOUBLE_SLASH_RE2))
|
|
16409
|
+
path15 = path15.replace(DOUBLE_SLASH_RE2, "/");
|
|
16410
|
+
if (prepend)
|
|
16411
|
+
path15 = "/" + path15;
|
|
16412
|
+
return path15;
|
|
16413
|
+
}
|
|
16414
|
+
function matchPatterns(patterns, testString, stats) {
|
|
16415
|
+
const path15 = normalizePath(testString);
|
|
16416
|
+
for (let index = 0; index < patterns.length; index++) {
|
|
16417
|
+
const pattern = patterns[index];
|
|
16418
|
+
if (pattern(path15, stats)) {
|
|
16419
|
+
return true;
|
|
16420
|
+
}
|
|
16421
|
+
}
|
|
16422
|
+
return false;
|
|
16423
|
+
}
|
|
16424
|
+
function anymatch(matchers, testString) {
|
|
16425
|
+
if (matchers == null) {
|
|
16426
|
+
throw new TypeError("anymatch: specify first argument");
|
|
16427
|
+
}
|
|
16428
|
+
const matchersArray = arrify(matchers);
|
|
16429
|
+
const patterns = matchersArray.map((matcher) => createPattern(matcher));
|
|
16430
|
+
if (testString == null) {
|
|
16431
|
+
return (testString2, stats) => {
|
|
16432
|
+
return matchPatterns(patterns, testString2, stats);
|
|
16433
|
+
};
|
|
16434
|
+
}
|
|
16435
|
+
return matchPatterns(patterns, testString);
|
|
16436
|
+
}
|
|
16437
|
+
var unifyPaths = (paths_) => {
|
|
16438
|
+
const paths = arrify(paths_).flat();
|
|
16439
|
+
if (!paths.every((p) => typeof p === STRING_TYPE)) {
|
|
16440
|
+
throw new TypeError(`Non-string provided as watch path: ${paths}`);
|
|
16441
|
+
}
|
|
16442
|
+
return paths.map(normalizePathToUnix);
|
|
16443
|
+
};
|
|
16444
|
+
var toUnix = (string) => {
|
|
16445
|
+
let str = string.replace(BACK_SLASH_RE, SLASH);
|
|
16446
|
+
let prepend = false;
|
|
16447
|
+
if (str.startsWith(SLASH_SLASH)) {
|
|
16448
|
+
prepend = true;
|
|
16449
|
+
}
|
|
16450
|
+
while (str.match(DOUBLE_SLASH_RE)) {
|
|
16451
|
+
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
|
16452
|
+
}
|
|
16453
|
+
if (prepend) {
|
|
16454
|
+
str = SLASH + str;
|
|
16455
|
+
}
|
|
16456
|
+
return str;
|
|
16457
|
+
};
|
|
16458
|
+
var normalizePathToUnix = (path15) => toUnix(sysPath2.normalize(toUnix(path15)));
|
|
16459
|
+
var normalizeIgnored = (cwd = "") => (path15) => {
|
|
16460
|
+
if (typeof path15 === "string") {
|
|
16461
|
+
return normalizePathToUnix(sysPath2.isAbsolute(path15) ? path15 : sysPath2.join(cwd, path15));
|
|
16462
|
+
} else {
|
|
16463
|
+
return path15;
|
|
16464
|
+
}
|
|
16465
|
+
};
|
|
16466
|
+
var getAbsolutePath = (path15, cwd) => {
|
|
16467
|
+
if (sysPath2.isAbsolute(path15)) {
|
|
16468
|
+
return path15;
|
|
16469
|
+
}
|
|
16470
|
+
return sysPath2.join(cwd, path15);
|
|
16471
|
+
};
|
|
16472
|
+
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
16473
|
+
var DirEntry = class {
|
|
16474
|
+
constructor(dir, removeWatcher) {
|
|
16475
|
+
this.path = dir;
|
|
16476
|
+
this._removeWatcher = removeWatcher;
|
|
16477
|
+
this.items = /* @__PURE__ */ new Set();
|
|
16478
|
+
}
|
|
16479
|
+
add(item) {
|
|
16480
|
+
const { items } = this;
|
|
16481
|
+
if (!items)
|
|
16482
|
+
return;
|
|
16483
|
+
if (item !== ONE_DOT && item !== TWO_DOTS)
|
|
16484
|
+
items.add(item);
|
|
16485
|
+
}
|
|
16486
|
+
async remove(item) {
|
|
16487
|
+
const { items } = this;
|
|
16488
|
+
if (!items)
|
|
16489
|
+
return;
|
|
16490
|
+
items.delete(item);
|
|
16491
|
+
if (items.size > 0)
|
|
16492
|
+
return;
|
|
16493
|
+
const dir = this.path;
|
|
16494
|
+
try {
|
|
16495
|
+
await (0, import_promises5.readdir)(dir);
|
|
16496
|
+
} catch (err) {
|
|
16497
|
+
if (this._removeWatcher) {
|
|
16498
|
+
this._removeWatcher(sysPath2.dirname(dir), sysPath2.basename(dir));
|
|
16499
|
+
}
|
|
16500
|
+
}
|
|
16501
|
+
}
|
|
16502
|
+
has(item) {
|
|
16503
|
+
const { items } = this;
|
|
16504
|
+
if (!items)
|
|
16505
|
+
return;
|
|
16506
|
+
return items.has(item);
|
|
16507
|
+
}
|
|
16508
|
+
getChildren() {
|
|
16509
|
+
const { items } = this;
|
|
16510
|
+
if (!items)
|
|
16511
|
+
return [];
|
|
16512
|
+
return [...items.values()];
|
|
16513
|
+
}
|
|
16514
|
+
dispose() {
|
|
16515
|
+
this.items.clear();
|
|
16516
|
+
this.path = "";
|
|
16517
|
+
this._removeWatcher = EMPTY_FN;
|
|
16518
|
+
this.items = EMPTY_SET;
|
|
16519
|
+
Object.freeze(this);
|
|
16520
|
+
}
|
|
16521
|
+
};
|
|
16522
|
+
var STAT_METHOD_F = "stat";
|
|
16523
|
+
var STAT_METHOD_L = "lstat";
|
|
16524
|
+
var WatchHelper = class {
|
|
16525
|
+
constructor(path15, follow, fsw) {
|
|
16526
|
+
this.fsw = fsw;
|
|
16527
|
+
const watchPath = path15;
|
|
16528
|
+
this.path = path15 = path15.replace(REPLACER_RE, "");
|
|
16529
|
+
this.watchPath = watchPath;
|
|
16530
|
+
this.fullWatchPath = sysPath2.resolve(watchPath);
|
|
16531
|
+
this.dirParts = [];
|
|
16532
|
+
this.dirParts.forEach((parts2) => {
|
|
16533
|
+
if (parts2.length > 1)
|
|
16534
|
+
parts2.pop();
|
|
16535
|
+
});
|
|
16536
|
+
this.followSymlinks = follow;
|
|
16537
|
+
this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
|
|
16538
|
+
}
|
|
16539
|
+
entryPath(entry) {
|
|
16540
|
+
return sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
|
|
16541
|
+
}
|
|
16542
|
+
filterPath(entry) {
|
|
16543
|
+
const { stats } = entry;
|
|
16544
|
+
if (stats && stats.isSymbolicLink())
|
|
16545
|
+
return this.filterDir(entry);
|
|
16546
|
+
const resolvedPath = this.entryPath(entry);
|
|
16547
|
+
return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
|
|
16548
|
+
}
|
|
16549
|
+
filterDir(entry) {
|
|
16550
|
+
return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
|
|
16551
|
+
}
|
|
16552
|
+
};
|
|
16553
|
+
var FSWatcher = class extends import_events.EventEmitter {
|
|
16554
|
+
// Not indenting methods for history sake; for now.
|
|
16555
|
+
constructor(_opts = {}) {
|
|
16556
|
+
super();
|
|
16557
|
+
this.closed = false;
|
|
16558
|
+
this._closers = /* @__PURE__ */ new Map();
|
|
16559
|
+
this._ignoredPaths = /* @__PURE__ */ new Set();
|
|
16560
|
+
this._throttled = /* @__PURE__ */ new Map();
|
|
16561
|
+
this._streams = /* @__PURE__ */ new Set();
|
|
16562
|
+
this._symlinkPaths = /* @__PURE__ */ new Map();
|
|
16563
|
+
this._watched = /* @__PURE__ */ new Map();
|
|
16564
|
+
this._pendingWrites = /* @__PURE__ */ new Map();
|
|
16565
|
+
this._pendingUnlinks = /* @__PURE__ */ new Map();
|
|
16566
|
+
this._readyCount = 0;
|
|
16567
|
+
this._readyEmitted = false;
|
|
16568
|
+
const awf = _opts.awaitWriteFinish;
|
|
16569
|
+
const DEF_AWF = { stabilityThreshold: 2e3, pollInterval: 100 };
|
|
16570
|
+
const opts = {
|
|
16571
|
+
// Defaults
|
|
16572
|
+
persistent: true,
|
|
16573
|
+
ignoreInitial: false,
|
|
16574
|
+
ignorePermissionErrors: false,
|
|
16575
|
+
interval: 100,
|
|
16576
|
+
binaryInterval: 300,
|
|
16577
|
+
followSymlinks: true,
|
|
16578
|
+
usePolling: false,
|
|
16579
|
+
// useAsync: false,
|
|
16580
|
+
atomic: true,
|
|
16581
|
+
// NOTE: overwritten later (depends on usePolling)
|
|
16582
|
+
..._opts,
|
|
16583
|
+
// Change format
|
|
16584
|
+
ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
|
|
16585
|
+
awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === "object" ? { ...DEF_AWF, ...awf } : false
|
|
16586
|
+
};
|
|
16587
|
+
if (isIBMi)
|
|
16588
|
+
opts.usePolling = true;
|
|
16589
|
+
if (opts.atomic === void 0)
|
|
16590
|
+
opts.atomic = !opts.usePolling;
|
|
16591
|
+
const envPoll = process.env.CHOKIDAR_USEPOLLING;
|
|
16592
|
+
if (envPoll !== void 0) {
|
|
16593
|
+
const envLower = envPoll.toLowerCase();
|
|
16594
|
+
if (envLower === "false" || envLower === "0")
|
|
16595
|
+
opts.usePolling = false;
|
|
16596
|
+
else if (envLower === "true" || envLower === "1")
|
|
16597
|
+
opts.usePolling = true;
|
|
16598
|
+
else
|
|
16599
|
+
opts.usePolling = !!envLower;
|
|
16600
|
+
}
|
|
16601
|
+
const envInterval = process.env.CHOKIDAR_INTERVAL;
|
|
16602
|
+
if (envInterval)
|
|
16603
|
+
opts.interval = Number.parseInt(envInterval, 10);
|
|
16604
|
+
let readyCalls = 0;
|
|
16605
|
+
this._emitReady = () => {
|
|
16606
|
+
readyCalls++;
|
|
16607
|
+
if (readyCalls >= this._readyCount) {
|
|
16608
|
+
this._emitReady = EMPTY_FN;
|
|
16609
|
+
this._readyEmitted = true;
|
|
16610
|
+
process.nextTick(() => this.emit(EVENTS.READY));
|
|
16611
|
+
}
|
|
16612
|
+
};
|
|
16613
|
+
this._emitRaw = (...args) => this.emit(EVENTS.RAW, ...args);
|
|
16614
|
+
this._boundRemove = this._remove.bind(this);
|
|
16615
|
+
this.options = opts;
|
|
16616
|
+
this._nodeFsHandler = new NodeFsHandler(this);
|
|
16617
|
+
Object.freeze(opts);
|
|
16618
|
+
}
|
|
16619
|
+
_addIgnoredPath(matcher) {
|
|
16620
|
+
if (isMatcherObject(matcher)) {
|
|
16621
|
+
for (const ignored of this._ignoredPaths) {
|
|
16622
|
+
if (isMatcherObject(ignored) && ignored.path === matcher.path && ignored.recursive === matcher.recursive) {
|
|
16623
|
+
return;
|
|
16624
|
+
}
|
|
16625
|
+
}
|
|
16626
|
+
}
|
|
16627
|
+
this._ignoredPaths.add(matcher);
|
|
16628
|
+
}
|
|
16629
|
+
_removeIgnoredPath(matcher) {
|
|
16630
|
+
this._ignoredPaths.delete(matcher);
|
|
16631
|
+
if (typeof matcher === "string") {
|
|
16632
|
+
for (const ignored of this._ignoredPaths) {
|
|
16633
|
+
if (isMatcherObject(ignored) && ignored.path === matcher) {
|
|
16634
|
+
this._ignoredPaths.delete(ignored);
|
|
16635
|
+
}
|
|
16636
|
+
}
|
|
16637
|
+
}
|
|
16638
|
+
}
|
|
16639
|
+
// Public methods
|
|
16640
|
+
/**
|
|
16641
|
+
* Adds paths to be watched on an existing FSWatcher instance.
|
|
16642
|
+
* @param paths_ file or file list. Other arguments are unused
|
|
16643
|
+
*/
|
|
16644
|
+
add(paths_, _origAdd, _internal) {
|
|
16645
|
+
const { cwd } = this.options;
|
|
16646
|
+
this.closed = false;
|
|
16647
|
+
this._closePromise = void 0;
|
|
16648
|
+
let paths = unifyPaths(paths_);
|
|
16649
|
+
if (cwd) {
|
|
16650
|
+
paths = paths.map((path15) => {
|
|
16651
|
+
const absPath = getAbsolutePath(path15, cwd);
|
|
16652
|
+
return absPath;
|
|
16653
|
+
});
|
|
16654
|
+
}
|
|
16655
|
+
paths.forEach((path15) => {
|
|
16656
|
+
this._removeIgnoredPath(path15);
|
|
16657
|
+
});
|
|
16658
|
+
this._userIgnored = void 0;
|
|
16659
|
+
if (!this._readyCount)
|
|
16660
|
+
this._readyCount = 0;
|
|
16661
|
+
this._readyCount += paths.length;
|
|
16662
|
+
Promise.all(paths.map(async (path15) => {
|
|
16663
|
+
const res = await this._nodeFsHandler._addToNodeFs(path15, !_internal, void 0, 0, _origAdd);
|
|
16664
|
+
if (res)
|
|
16665
|
+
this._emitReady();
|
|
16666
|
+
return res;
|
|
16667
|
+
})).then((results) => {
|
|
16668
|
+
if (this.closed)
|
|
16669
|
+
return;
|
|
16670
|
+
results.forEach((item) => {
|
|
16671
|
+
if (item)
|
|
16672
|
+
this.add(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
|
|
16673
|
+
});
|
|
16674
|
+
});
|
|
16675
|
+
return this;
|
|
16676
|
+
}
|
|
16677
|
+
/**
|
|
16678
|
+
* Close watchers or start ignoring events from specified paths.
|
|
16679
|
+
*/
|
|
16680
|
+
unwatch(paths_) {
|
|
16681
|
+
if (this.closed)
|
|
16682
|
+
return this;
|
|
16683
|
+
const paths = unifyPaths(paths_);
|
|
16684
|
+
const { cwd } = this.options;
|
|
16685
|
+
paths.forEach((path15) => {
|
|
16686
|
+
if (!sysPath2.isAbsolute(path15) && !this._closers.has(path15)) {
|
|
16687
|
+
if (cwd)
|
|
16688
|
+
path15 = sysPath2.join(cwd, path15);
|
|
16689
|
+
path15 = sysPath2.resolve(path15);
|
|
16690
|
+
}
|
|
16691
|
+
this._closePath(path15);
|
|
16692
|
+
this._addIgnoredPath(path15);
|
|
16693
|
+
if (this._watched.has(path15)) {
|
|
16694
|
+
this._addIgnoredPath({
|
|
16695
|
+
path: path15,
|
|
16696
|
+
recursive: true
|
|
16697
|
+
});
|
|
16698
|
+
}
|
|
16699
|
+
this._userIgnored = void 0;
|
|
16700
|
+
});
|
|
16701
|
+
return this;
|
|
16702
|
+
}
|
|
16703
|
+
/**
|
|
16704
|
+
* Close watchers and remove all listeners from watched paths.
|
|
16705
|
+
*/
|
|
16706
|
+
close() {
|
|
16707
|
+
if (this._closePromise) {
|
|
16708
|
+
return this._closePromise;
|
|
16709
|
+
}
|
|
16710
|
+
this.closed = true;
|
|
16711
|
+
this.removeAllListeners();
|
|
16712
|
+
const closers = [];
|
|
16713
|
+
this._closers.forEach((closerList) => closerList.forEach((closer) => {
|
|
16714
|
+
const promise = closer();
|
|
16715
|
+
if (promise instanceof Promise)
|
|
16716
|
+
closers.push(promise);
|
|
16717
|
+
}));
|
|
16718
|
+
this._streams.forEach((stream) => stream.destroy());
|
|
16719
|
+
this._userIgnored = void 0;
|
|
16720
|
+
this._readyCount = 0;
|
|
16721
|
+
this._readyEmitted = false;
|
|
16722
|
+
this._watched.forEach((dirent) => dirent.dispose());
|
|
16723
|
+
this._closers.clear();
|
|
16724
|
+
this._watched.clear();
|
|
16725
|
+
this._streams.clear();
|
|
16726
|
+
this._symlinkPaths.clear();
|
|
16727
|
+
this._throttled.clear();
|
|
16728
|
+
this._closePromise = closers.length ? Promise.all(closers).then(() => void 0) : Promise.resolve();
|
|
16729
|
+
return this._closePromise;
|
|
16730
|
+
}
|
|
16731
|
+
/**
|
|
16732
|
+
* Expose list of watched paths
|
|
16733
|
+
* @returns for chaining
|
|
16734
|
+
*/
|
|
16735
|
+
getWatched() {
|
|
16736
|
+
const watchList = {};
|
|
16737
|
+
this._watched.forEach((entry, dir) => {
|
|
16738
|
+
const key = this.options.cwd ? sysPath2.relative(this.options.cwd, dir) : dir;
|
|
16739
|
+
const index = key || ONE_DOT;
|
|
16740
|
+
watchList[index] = entry.getChildren().sort();
|
|
16741
|
+
});
|
|
16742
|
+
return watchList;
|
|
16743
|
+
}
|
|
16744
|
+
emitWithAll(event, args) {
|
|
16745
|
+
this.emit(event, ...args);
|
|
16746
|
+
if (event !== EVENTS.ERROR)
|
|
16747
|
+
this.emit(EVENTS.ALL, event, ...args);
|
|
16748
|
+
}
|
|
16749
|
+
// Common helpers
|
|
16750
|
+
// --------------
|
|
16751
|
+
/**
|
|
16752
|
+
* Normalize and emit events.
|
|
16753
|
+
* Calling _emit DOES NOT MEAN emit() would be called!
|
|
16754
|
+
* @param event Type of event
|
|
16755
|
+
* @param path File or directory path
|
|
16756
|
+
* @param stats arguments to be passed with event
|
|
16757
|
+
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16758
|
+
*/
|
|
16759
|
+
async _emit(event, path15, stats) {
|
|
16760
|
+
if (this.closed)
|
|
16761
|
+
return;
|
|
16762
|
+
const opts = this.options;
|
|
16763
|
+
if (isWindows2)
|
|
16764
|
+
path15 = sysPath2.normalize(path15);
|
|
16765
|
+
if (opts.cwd)
|
|
16766
|
+
path15 = sysPath2.relative(opts.cwd, path15);
|
|
16767
|
+
const args = [path15];
|
|
16768
|
+
if (stats != null)
|
|
16769
|
+
args.push(stats);
|
|
16770
|
+
const awf = opts.awaitWriteFinish;
|
|
16771
|
+
let pw;
|
|
16772
|
+
if (awf && (pw = this._pendingWrites.get(path15))) {
|
|
16773
|
+
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16774
|
+
return this;
|
|
16775
|
+
}
|
|
16776
|
+
if (opts.atomic) {
|
|
16777
|
+
if (event === EVENTS.UNLINK) {
|
|
16778
|
+
this._pendingUnlinks.set(path15, [event, ...args]);
|
|
16779
|
+
setTimeout(() => {
|
|
16780
|
+
this._pendingUnlinks.forEach((entry, path16) => {
|
|
16781
|
+
this.emit(...entry);
|
|
16782
|
+
this.emit(EVENTS.ALL, ...entry);
|
|
16783
|
+
this._pendingUnlinks.delete(path16);
|
|
16784
|
+
});
|
|
16785
|
+
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16786
|
+
return this;
|
|
16787
|
+
}
|
|
16788
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path15)) {
|
|
16789
|
+
event = EVENTS.CHANGE;
|
|
16790
|
+
this._pendingUnlinks.delete(path15);
|
|
16791
|
+
}
|
|
16792
|
+
}
|
|
16793
|
+
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
16794
|
+
const awfEmit = (err, stats2) => {
|
|
16795
|
+
if (err) {
|
|
16796
|
+
event = EVENTS.ERROR;
|
|
16797
|
+
args[0] = err;
|
|
16798
|
+
this.emitWithAll(event, args);
|
|
16799
|
+
} else if (stats2) {
|
|
16800
|
+
if (args.length > 1) {
|
|
16801
|
+
args[1] = stats2;
|
|
16802
|
+
} else {
|
|
16803
|
+
args.push(stats2);
|
|
16804
|
+
}
|
|
16805
|
+
this.emitWithAll(event, args);
|
|
16806
|
+
}
|
|
16807
|
+
};
|
|
16808
|
+
this._awaitWriteFinish(path15, awf.stabilityThreshold, event, awfEmit);
|
|
16809
|
+
return this;
|
|
16810
|
+
}
|
|
16811
|
+
if (event === EVENTS.CHANGE) {
|
|
16812
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path15, 50);
|
|
16813
|
+
if (isThrottled)
|
|
16814
|
+
return this;
|
|
16815
|
+
}
|
|
16816
|
+
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16817
|
+
const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path15) : path15;
|
|
16818
|
+
let stats2;
|
|
16819
|
+
try {
|
|
16820
|
+
stats2 = await (0, import_promises5.stat)(fullPath);
|
|
16821
|
+
} catch (err) {
|
|
16822
|
+
}
|
|
16823
|
+
if (!stats2 || this.closed)
|
|
16824
|
+
return;
|
|
16825
|
+
args.push(stats2);
|
|
16826
|
+
}
|
|
16827
|
+
this.emitWithAll(event, args);
|
|
16828
|
+
return this;
|
|
16829
|
+
}
|
|
16830
|
+
/**
|
|
16831
|
+
* Common handler for errors
|
|
16832
|
+
* @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16833
|
+
*/
|
|
16834
|
+
_handleError(error) {
|
|
16835
|
+
const code = error && error.code;
|
|
16836
|
+
if (error && code !== "ENOENT" && code !== "ENOTDIR" && (!this.options.ignorePermissionErrors || code !== "EPERM" && code !== "EACCES")) {
|
|
16837
|
+
this.emit(EVENTS.ERROR, error);
|
|
16838
|
+
}
|
|
16839
|
+
return error || this.closed;
|
|
16840
|
+
}
|
|
16841
|
+
/**
|
|
16842
|
+
* Helper utility for throttling
|
|
16843
|
+
* @param actionType type being throttled
|
|
16844
|
+
* @param path being acted upon
|
|
16845
|
+
* @param timeout duration of time to suppress duplicate actions
|
|
16846
|
+
* @returns tracking object or false if action should be suppressed
|
|
16847
|
+
*/
|
|
16848
|
+
_throttle(actionType, path15, timeout) {
|
|
16849
|
+
if (!this._throttled.has(actionType)) {
|
|
16850
|
+
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16851
|
+
}
|
|
16852
|
+
const action = this._throttled.get(actionType);
|
|
16853
|
+
if (!action)
|
|
16854
|
+
throw new Error("invalid throttle");
|
|
16855
|
+
const actionPath = action.get(path15);
|
|
16856
|
+
if (actionPath) {
|
|
16857
|
+
actionPath.count++;
|
|
16858
|
+
return false;
|
|
16859
|
+
}
|
|
16860
|
+
let timeoutObject;
|
|
16861
|
+
const clear = () => {
|
|
16862
|
+
const item = action.get(path15);
|
|
16863
|
+
const count = item ? item.count : 0;
|
|
16864
|
+
action.delete(path15);
|
|
16865
|
+
clearTimeout(timeoutObject);
|
|
16866
|
+
if (item)
|
|
16867
|
+
clearTimeout(item.timeoutObject);
|
|
16868
|
+
return count;
|
|
16869
|
+
};
|
|
16870
|
+
timeoutObject = setTimeout(clear, timeout);
|
|
16871
|
+
const thr = { timeoutObject, clear, count: 0 };
|
|
16872
|
+
action.set(path15, thr);
|
|
16873
|
+
return thr;
|
|
16874
|
+
}
|
|
16875
|
+
_incrReadyCount() {
|
|
16876
|
+
return this._readyCount++;
|
|
16877
|
+
}
|
|
16878
|
+
/**
|
|
16879
|
+
* Awaits write operation to finish.
|
|
16880
|
+
* Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
|
|
16881
|
+
* @param path being acted upon
|
|
16882
|
+
* @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
|
|
16883
|
+
* @param event
|
|
16884
|
+
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16885
|
+
*/
|
|
16886
|
+
_awaitWriteFinish(path15, threshold, event, awfEmit) {
|
|
16887
|
+
const awf = this.options.awaitWriteFinish;
|
|
16888
|
+
if (typeof awf !== "object")
|
|
16889
|
+
return;
|
|
16890
|
+
const pollInterval = awf.pollInterval;
|
|
16891
|
+
let timeoutHandler;
|
|
16892
|
+
let fullPath = path15;
|
|
16893
|
+
if (this.options.cwd && !sysPath2.isAbsolute(path15)) {
|
|
16894
|
+
fullPath = sysPath2.join(this.options.cwd, path15);
|
|
16895
|
+
}
|
|
16896
|
+
const now = /* @__PURE__ */ new Date();
|
|
16897
|
+
const writes = this._pendingWrites;
|
|
16898
|
+
function awaitWriteFinishFn(prevStat) {
|
|
16899
|
+
(0, import_fs8.stat)(fullPath, (err, curStat) => {
|
|
16900
|
+
if (err || !writes.has(path15)) {
|
|
16901
|
+
if (err && err.code !== "ENOENT")
|
|
16902
|
+
awfEmit(err);
|
|
16903
|
+
return;
|
|
16904
|
+
}
|
|
16905
|
+
const now2 = Number(/* @__PURE__ */ new Date());
|
|
16906
|
+
if (prevStat && curStat.size !== prevStat.size) {
|
|
16907
|
+
writes.get(path15).lastChange = now2;
|
|
16908
|
+
}
|
|
16909
|
+
const pw = writes.get(path15);
|
|
16910
|
+
const df = now2 - pw.lastChange;
|
|
16911
|
+
if (df >= threshold) {
|
|
16912
|
+
writes.delete(path15);
|
|
16913
|
+
awfEmit(void 0, curStat);
|
|
16914
|
+
} else {
|
|
16915
|
+
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16916
|
+
}
|
|
16917
|
+
});
|
|
16918
|
+
}
|
|
16919
|
+
if (!writes.has(path15)) {
|
|
16920
|
+
writes.set(path15, {
|
|
16921
|
+
lastChange: now,
|
|
16922
|
+
cancelWait: () => {
|
|
16923
|
+
writes.delete(path15);
|
|
16924
|
+
clearTimeout(timeoutHandler);
|
|
16925
|
+
return event;
|
|
16926
|
+
}
|
|
16927
|
+
});
|
|
16928
|
+
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
|
|
16929
|
+
}
|
|
16930
|
+
}
|
|
16931
|
+
/**
|
|
16932
|
+
* Determines whether user has asked to ignore this path.
|
|
16933
|
+
*/
|
|
16934
|
+
_isIgnored(path15, stats) {
|
|
16935
|
+
if (this.options.atomic && DOT_RE.test(path15))
|
|
16936
|
+
return true;
|
|
16937
|
+
if (!this._userIgnored) {
|
|
16938
|
+
const { cwd } = this.options;
|
|
16939
|
+
const ign = this.options.ignored;
|
|
16940
|
+
const ignored = (ign || []).map(normalizeIgnored(cwd));
|
|
16941
|
+
const ignoredPaths = [...this._ignoredPaths];
|
|
16942
|
+
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
16943
|
+
this._userIgnored = anymatch(list, void 0);
|
|
16944
|
+
}
|
|
16945
|
+
return this._userIgnored(path15, stats);
|
|
16946
|
+
}
|
|
16947
|
+
_isntIgnored(path15, stat4) {
|
|
16948
|
+
return !this._isIgnored(path15, stat4);
|
|
16949
|
+
}
|
|
16950
|
+
/**
|
|
16951
|
+
* Provides a set of common helpers and properties relating to symlink handling.
|
|
16952
|
+
* @param path file or directory pattern being watched
|
|
16953
|
+
*/
|
|
16954
|
+
_getWatchHelpers(path15) {
|
|
16955
|
+
return new WatchHelper(path15, this.options.followSymlinks, this);
|
|
16956
|
+
}
|
|
16957
|
+
// Directory helpers
|
|
16958
|
+
// -----------------
|
|
16959
|
+
/**
|
|
16960
|
+
* Provides directory tracking objects
|
|
16961
|
+
* @param directory path of the directory
|
|
16962
|
+
*/
|
|
16963
|
+
_getWatchedDir(directory) {
|
|
16964
|
+
const dir = sysPath2.resolve(directory);
|
|
16965
|
+
if (!this._watched.has(dir))
|
|
16966
|
+
this._watched.set(dir, new DirEntry(dir, this._boundRemove));
|
|
16967
|
+
return this._watched.get(dir);
|
|
16968
|
+
}
|
|
16969
|
+
// File helpers
|
|
16970
|
+
// ------------
|
|
16971
|
+
/**
|
|
16972
|
+
* Check for read permissions: https://stackoverflow.com/a/11781404/1358405
|
|
16973
|
+
*/
|
|
16974
|
+
_hasReadPermissions(stats) {
|
|
16975
|
+
if (this.options.ignorePermissionErrors)
|
|
16976
|
+
return true;
|
|
16977
|
+
return Boolean(Number(stats.mode) & 256);
|
|
16978
|
+
}
|
|
16979
|
+
/**
|
|
16980
|
+
* Handles emitting unlink events for
|
|
16981
|
+
* files and directories, and via recursion, for
|
|
16982
|
+
* files and directories within directories that are unlinked
|
|
16983
|
+
* @param directory within which the following item is located
|
|
16984
|
+
* @param item base path of item/directory
|
|
16985
|
+
*/
|
|
16986
|
+
_remove(directory, item, isDirectory) {
|
|
16987
|
+
const path15 = sysPath2.join(directory, item);
|
|
16988
|
+
const fullPath = sysPath2.resolve(path15);
|
|
16989
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path15) || this._watched.has(fullPath);
|
|
16990
|
+
if (!this._throttle("remove", path15, 100))
|
|
16991
|
+
return;
|
|
16992
|
+
if (!isDirectory && this._watched.size === 1) {
|
|
16993
|
+
this.add(directory, item, true);
|
|
16994
|
+
}
|
|
16995
|
+
const wp = this._getWatchedDir(path15);
|
|
16996
|
+
const nestedDirectoryChildren = wp.getChildren();
|
|
16997
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path15, nested));
|
|
16998
|
+
const parent = this._getWatchedDir(directory);
|
|
16999
|
+
const wasTracked = parent.has(item);
|
|
17000
|
+
parent.remove(item);
|
|
17001
|
+
if (this._symlinkPaths.has(fullPath)) {
|
|
17002
|
+
this._symlinkPaths.delete(fullPath);
|
|
17003
|
+
}
|
|
17004
|
+
let relPath = path15;
|
|
17005
|
+
if (this.options.cwd)
|
|
17006
|
+
relPath = sysPath2.relative(this.options.cwd, path15);
|
|
17007
|
+
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
17008
|
+
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
17009
|
+
if (event === EVENTS.ADD)
|
|
17010
|
+
return;
|
|
17011
|
+
}
|
|
17012
|
+
this._watched.delete(path15);
|
|
17013
|
+
this._watched.delete(fullPath);
|
|
17014
|
+
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
17015
|
+
if (wasTracked && !this._isIgnored(path15))
|
|
17016
|
+
this._emit(eventName, path15);
|
|
17017
|
+
this._closePath(path15);
|
|
17018
|
+
}
|
|
17019
|
+
/**
|
|
17020
|
+
* Closes all watchers for a path
|
|
17021
|
+
*/
|
|
17022
|
+
_closePath(path15) {
|
|
17023
|
+
this._closeFile(path15);
|
|
17024
|
+
const dir = sysPath2.dirname(path15);
|
|
17025
|
+
this._getWatchedDir(dir).remove(sysPath2.basename(path15));
|
|
17026
|
+
}
|
|
17027
|
+
/**
|
|
17028
|
+
* Closes only file-specific watchers
|
|
17029
|
+
*/
|
|
17030
|
+
_closeFile(path15) {
|
|
17031
|
+
const closers = this._closers.get(path15);
|
|
17032
|
+
if (!closers)
|
|
17033
|
+
return;
|
|
17034
|
+
closers.forEach((closer) => closer());
|
|
17035
|
+
this._closers.delete(path15);
|
|
17036
|
+
}
|
|
17037
|
+
_addPathCloser(path15, closer) {
|
|
17038
|
+
if (!closer)
|
|
17039
|
+
return;
|
|
17040
|
+
let list = this._closers.get(path15);
|
|
17041
|
+
if (!list) {
|
|
17042
|
+
list = [];
|
|
17043
|
+
this._closers.set(path15, list);
|
|
17044
|
+
}
|
|
17045
|
+
list.push(closer);
|
|
17046
|
+
}
|
|
17047
|
+
_readdirp(root, opts) {
|
|
17048
|
+
if (this.closed)
|
|
17049
|
+
return;
|
|
17050
|
+
const options = { type: EVENTS.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
|
|
17051
|
+
let stream = readdirp(root, options);
|
|
17052
|
+
this._streams.add(stream);
|
|
17053
|
+
stream.once(STR_CLOSE, () => {
|
|
17054
|
+
stream = void 0;
|
|
17055
|
+
});
|
|
17056
|
+
stream.once(STR_END, () => {
|
|
17057
|
+
if (stream) {
|
|
17058
|
+
this._streams.delete(stream);
|
|
17059
|
+
stream = void 0;
|
|
17060
|
+
}
|
|
17061
|
+
});
|
|
17062
|
+
return stream;
|
|
17063
|
+
}
|
|
17064
|
+
};
|
|
17065
|
+
function watch(paths, options = {}) {
|
|
17066
|
+
const watcher = new FSWatcher(options);
|
|
17067
|
+
watcher.add(paths);
|
|
17068
|
+
return watcher;
|
|
17069
|
+
}
|
|
17070
|
+
|
|
17071
|
+
// ../../shared/all/helpers/terminal-ai/watcher.ts
|
|
17072
|
+
var PRUNED_DIRS = /* @__PURE__ */ new Set([
|
|
17073
|
+
".git",
|
|
17074
|
+
"node_modules",
|
|
17075
|
+
".next",
|
|
17076
|
+
".turbo",
|
|
17077
|
+
".expo",
|
|
17078
|
+
"dist",
|
|
17079
|
+
"build",
|
|
17080
|
+
"out",
|
|
17081
|
+
"coverage",
|
|
17082
|
+
".cache",
|
|
17083
|
+
".venv",
|
|
17084
|
+
"venv",
|
|
17085
|
+
"__pycache__",
|
|
17086
|
+
".gradle",
|
|
17087
|
+
"Pods",
|
|
17088
|
+
"DerivedData"
|
|
17089
|
+
]);
|
|
17090
|
+
function isNoiseFile(name) {
|
|
17091
|
+
return name === ".DS_Store" || name === "4913" || name.startsWith(".#") || name.startsWith("#") && name.endsWith("#");
|
|
17092
|
+
}
|
|
17093
|
+
var MAX_BATCH = 200;
|
|
17094
|
+
var FLUSH_MS = 120;
|
|
17095
|
+
var SELF_WRITE_MS = 2e3;
|
|
17096
|
+
var emptyPending = () => ({
|
|
17097
|
+
added: /* @__PURE__ */ new Set(),
|
|
17098
|
+
changed: /* @__PURE__ */ new Set(),
|
|
17099
|
+
removed: /* @__PURE__ */ new Set(),
|
|
17100
|
+
resync: false
|
|
17101
|
+
});
|
|
17102
|
+
var WorkspaceWatcher = class {
|
|
17103
|
+
/**
|
|
17104
|
+
* @param root Absolute path of the working tree. Every emitted path is
|
|
17105
|
+
* repo-relative and `/`-prefixed, matching `bareFsList`.
|
|
17106
|
+
* @param emit Called with a coalesced batch, never with an empty one.
|
|
17107
|
+
* @param exclude Absolute subtrees to skip on top of the name-based pruning.
|
|
17108
|
+
* A no-git card's root is the space dir itself, which also
|
|
17109
|
+
* holds the runner's own bookkeeping.
|
|
17110
|
+
*/
|
|
17111
|
+
constructor(root, emit, exclude = []) {
|
|
17112
|
+
this.root = root;
|
|
17113
|
+
this.emit = emit;
|
|
17114
|
+
this.exclude = exclude;
|
|
17115
|
+
this.watcher = null;
|
|
17116
|
+
this.pending = emptyPending();
|
|
17117
|
+
this.flushTimer = null;
|
|
17118
|
+
/** path -> expiry. Events for these paths are ours (the editor just saved)
|
|
17119
|
+
* and must not come back as "changed on disk". */
|
|
17120
|
+
this.selfWrites = /* @__PURE__ */ new Map();
|
|
17121
|
+
this.closed = false;
|
|
17122
|
+
}
|
|
17123
|
+
start() {
|
|
17124
|
+
if (this.watcher || this.closed) return;
|
|
17125
|
+
const watcher = watch(this.root, {
|
|
17126
|
+
// `ignored` prunes: returning true for a directory stops the walk there,
|
|
17127
|
+
// so a pruned tree is never even enumerated.
|
|
17128
|
+
ignored: (absPath) => this.shouldIgnore(absPath),
|
|
17129
|
+
ignoreInitial: true,
|
|
17130
|
+
// A symlink to $HOME (or a sibling checkout) would pull the whole machine
|
|
17131
|
+
// into the watch set.
|
|
17132
|
+
followSymlinks: false,
|
|
17133
|
+
// Report a write only once it stops growing - otherwise a large file
|
|
17134
|
+
// fires while it's still half on disk and the editor reads a torn read.
|
|
17135
|
+
awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 30 },
|
|
17136
|
+
// Recognise the unlink+rename that editors use to save atomically as a
|
|
17137
|
+
// single change rather than a delete followed by a create.
|
|
17138
|
+
atomic: true,
|
|
17139
|
+
ignorePermissionErrors: true,
|
|
17140
|
+
cwd: this.root
|
|
17141
|
+
});
|
|
17142
|
+
this.watcher = watcher;
|
|
17143
|
+
watcher.on("add", (p) => this.record("added", p));
|
|
17144
|
+
watcher.on("addDir", (p) => this.record("added", p));
|
|
17145
|
+
watcher.on("change", (p) => this.record("changed", p));
|
|
17146
|
+
watcher.on("unlink", (p) => this.record("removed", p));
|
|
17147
|
+
watcher.on("unlinkDir", (p) => this.record("removed", p));
|
|
17148
|
+
watcher.on("error", () => {
|
|
17149
|
+
if (this.closed) return;
|
|
17150
|
+
void this.close();
|
|
17151
|
+
this.emit({
|
|
17152
|
+
added: [],
|
|
17153
|
+
changed: [],
|
|
17154
|
+
removed: [],
|
|
17155
|
+
resync: false,
|
|
17156
|
+
stopped: true
|
|
17157
|
+
});
|
|
17158
|
+
});
|
|
17159
|
+
}
|
|
17160
|
+
/**
|
|
17161
|
+
* Mark a path as about to be written by us. The event the write produces is
|
|
17162
|
+
* dropped, so the editor doesn't get told its own save was an outside edit.
|
|
17163
|
+
*/
|
|
17164
|
+
expectWrite(repoPath) {
|
|
17165
|
+
this.selfWrites.set(repoPath, Date.now() + SELF_WRITE_MS);
|
|
17166
|
+
}
|
|
17167
|
+
async close() {
|
|
17168
|
+
this.closed = true;
|
|
17169
|
+
if (this.flushTimer) {
|
|
17170
|
+
clearTimeout(this.flushTimer);
|
|
17171
|
+
this.flushTimer = null;
|
|
17172
|
+
}
|
|
17173
|
+
this.pending = emptyPending();
|
|
17174
|
+
this.selfWrites.clear();
|
|
17175
|
+
const watcher = this.watcher;
|
|
17176
|
+
this.watcher = null;
|
|
17177
|
+
if (watcher) await watcher.close().catch(() => void 0);
|
|
17178
|
+
}
|
|
17179
|
+
/** chokidar tests absolute paths, always under the watch root. Matching is
|
|
17180
|
+
* done on the part BELOW the root, so a runner whose space dir happens to
|
|
17181
|
+
* sit under a `build/` or `dist/` of its own doesn't prune everything. */
|
|
17182
|
+
shouldIgnore(absPath) {
|
|
17183
|
+
if (absPath === this.root) return false;
|
|
17184
|
+
for (const excluded of this.exclude) {
|
|
17185
|
+
if (absPath === excluded || absPath.startsWith(excluded + "/")) {
|
|
17186
|
+
return true;
|
|
17187
|
+
}
|
|
17188
|
+
}
|
|
17189
|
+
const segments = absPath.slice(this.root.length + 1).split("/");
|
|
17190
|
+
for (const segment of segments) {
|
|
17191
|
+
if (PRUNED_DIRS.has(segment)) return true;
|
|
17192
|
+
}
|
|
17193
|
+
return isNoiseFile(segments[segments.length - 1] ?? "");
|
|
17194
|
+
}
|
|
17195
|
+
record(kind, relPath) {
|
|
17196
|
+
if (this.closed || !relPath) return;
|
|
17197
|
+
const path15 = "/" + relPath;
|
|
17198
|
+
const expiry = this.selfWrites.get(path15);
|
|
17199
|
+
if (expiry !== void 0) {
|
|
17200
|
+
if (expiry > Date.now()) return;
|
|
17201
|
+
this.selfWrites.delete(path15);
|
|
17202
|
+
}
|
|
17203
|
+
const { added, changed, removed } = this.pending;
|
|
17204
|
+
added.delete(path15);
|
|
17205
|
+
changed.delete(path15);
|
|
17206
|
+
removed.delete(path15);
|
|
17207
|
+
if (kind === "added") added.add(path15);
|
|
17208
|
+
else if (kind === "changed") changed.add(path15);
|
|
17209
|
+
else removed.add(path15);
|
|
17210
|
+
if (added.size + changed.size + removed.size > MAX_BATCH) {
|
|
17211
|
+
this.pending = { ...emptyPending(), resync: true };
|
|
17212
|
+
}
|
|
17213
|
+
this.scheduleFlush();
|
|
17214
|
+
}
|
|
17215
|
+
scheduleFlush() {
|
|
17216
|
+
if (this.flushTimer) return;
|
|
17217
|
+
this.flushTimer = setTimeout(() => {
|
|
17218
|
+
this.flushTimer = null;
|
|
17219
|
+
this.flush();
|
|
17220
|
+
}, FLUSH_MS);
|
|
17221
|
+
}
|
|
17222
|
+
flush() {
|
|
17223
|
+
if (this.closed) return;
|
|
17224
|
+
const { added, changed, removed, resync } = this.pending;
|
|
17225
|
+
this.pending = emptyPending();
|
|
17226
|
+
if (!resync && !added.size && !changed.size && !removed.size) return;
|
|
17227
|
+
const now = Date.now();
|
|
17228
|
+
for (const [path15, expiry] of this.selfWrites) {
|
|
17229
|
+
if (expiry <= now) this.selfWrites.delete(path15);
|
|
17230
|
+
}
|
|
17231
|
+
this.emit({
|
|
17232
|
+
added: resync ? [] : [...added],
|
|
17233
|
+
changed: resync ? [] : [...changed],
|
|
17234
|
+
removed: resync ? [] : [...removed],
|
|
17235
|
+
resync
|
|
17236
|
+
});
|
|
17237
|
+
}
|
|
17238
|
+
};
|
|
17239
|
+
|
|
15334
17240
|
// ../../shared/all/helpers/terminal-ai/terminal-mode.ts
|
|
15335
17241
|
function posixNormalize(p) {
|
|
15336
17242
|
const parts2 = p.split("/").filter(Boolean);
|
|
@@ -15358,6 +17264,54 @@ var TerminalModeEngine = class {
|
|
|
15358
17264
|
this.core = core;
|
|
15359
17265
|
this.emitter = emitter;
|
|
15360
17266
|
this.sessions = /* @__PURE__ */ new Map();
|
|
17267
|
+
/** One working-tree watcher per live bare session, keyed by postId. */
|
|
17268
|
+
this.watchers = /* @__PURE__ */ new Map();
|
|
17269
|
+
/** Worktree name each session claimed, keyed by postId. Covers the window
|
|
17270
|
+
* `claimWorkName`'s disk scan cannot: a name taken but not yet created. */
|
|
17271
|
+
this.reservedNames = /* @__PURE__ */ new Map();
|
|
17272
|
+
}
|
|
17273
|
+
// ── working-tree watching ──
|
|
17274
|
+
/** Start watching a session's tree. Idempotent: re-entering a session (the
|
|
17275
|
+
* modal reopening, a hydrate after restart) must not stack watchers. */
|
|
17276
|
+
startWatching(session) {
|
|
17277
|
+
const postId = session.postId;
|
|
17278
|
+
if (this.watchers.has(postId)) return;
|
|
17279
|
+
const paths = this.core.target().paths;
|
|
17280
|
+
const root = session.workspacePath || paths.root;
|
|
17281
|
+
if (!root) return;
|
|
17282
|
+
const exclude = session.workspacePath ? [] : [
|
|
17283
|
+
paths.state,
|
|
17284
|
+
paths.backups,
|
|
17285
|
+
paths.builds,
|
|
17286
|
+
paths.bin,
|
|
17287
|
+
paths.worktrees,
|
|
17288
|
+
paths.repo,
|
|
17289
|
+
`${paths.root}/drops`
|
|
17290
|
+
];
|
|
17291
|
+
const watcher = new WorkspaceWatcher(
|
|
17292
|
+
root,
|
|
17293
|
+
(change) => {
|
|
17294
|
+
this.emitter.emitBareFsChange(postId, change);
|
|
17295
|
+
},
|
|
17296
|
+
exclude
|
|
17297
|
+
);
|
|
17298
|
+
this.watchers.set(postId, watcher);
|
|
17299
|
+
watcher.start();
|
|
17300
|
+
}
|
|
17301
|
+
/** Silent by design: a session that ends also emits session-update, and a
|
|
17302
|
+
* re-point stops then starts. The one `stopped` the client cares about is
|
|
17303
|
+
* the watcher failing under a live session, which the watcher emits itself. */
|
|
17304
|
+
stopWatching(postId) {
|
|
17305
|
+
const watcher = this.watchers.get(postId);
|
|
17306
|
+
if (!watcher) return;
|
|
17307
|
+
this.watchers.delete(postId);
|
|
17308
|
+
void watcher.close();
|
|
17309
|
+
}
|
|
17310
|
+
/** Suppress the change event our own write is about to produce, so a save
|
|
17311
|
+
* never comes back to the editor as an outside edit. Normalized to the form
|
|
17312
|
+
* the watcher emits, since callers spell the path either way. */
|
|
17313
|
+
expectWrite(postId, path15) {
|
|
17314
|
+
this.watchers.get(postId)?.expectWrite(posixNormalize(path15));
|
|
15361
17315
|
}
|
|
15362
17316
|
// ── Lifecycle / ModeEngine ──
|
|
15363
17317
|
start(base, args) {
|
|
@@ -15401,6 +17355,8 @@ var TerminalModeEngine = class {
|
|
|
15401
17355
|
return !!s && (s.phase === "starting" || s.phase === "bare-active");
|
|
15402
17356
|
}
|
|
15403
17357
|
remove(postId) {
|
|
17358
|
+
this.stopWatching(postId);
|
|
17359
|
+
this.reservedNames.delete(postId);
|
|
15404
17360
|
this.sessions.delete(postId);
|
|
15405
17361
|
}
|
|
15406
17362
|
async kill(postId) {
|
|
@@ -15414,12 +17370,17 @@ var TerminalModeEngine = class {
|
|
|
15414
17370
|
}
|
|
15415
17371
|
}
|
|
15416
17372
|
if (!session) return;
|
|
17373
|
+
this.stopWatching(session.postId);
|
|
15417
17374
|
await this.teardown(session);
|
|
15418
17375
|
const removedPostId = session.postId;
|
|
17376
|
+
this.reservedNames.delete(removedPostId);
|
|
15419
17377
|
this.sessions.delete(removedPostId);
|
|
15420
17378
|
this.emitter.emitSessionRemoved(removedPostId);
|
|
15421
17379
|
}
|
|
15422
17380
|
destroy() {
|
|
17381
|
+
for (const watcher of this.watchers.values()) void watcher.close();
|
|
17382
|
+
this.watchers.clear();
|
|
17383
|
+
this.reservedNames.clear();
|
|
15423
17384
|
this.sessions.clear();
|
|
15424
17385
|
}
|
|
15425
17386
|
teardown(session) {
|
|
@@ -15464,6 +17425,7 @@ var TerminalModeEngine = class {
|
|
|
15464
17425
|
exposed: []
|
|
15465
17426
|
};
|
|
15466
17427
|
this.sessions.set(r.postId, session);
|
|
17428
|
+
this.startWatching(session);
|
|
15467
17429
|
this.emitter.emitSessionUpdate(session);
|
|
15468
17430
|
}
|
|
15469
17431
|
}
|
|
@@ -15506,6 +17468,8 @@ var TerminalModeEngine = class {
|
|
|
15506
17468
|
exposed: []
|
|
15507
17469
|
};
|
|
15508
17470
|
this.sessions.set(args.postId, session);
|
|
17471
|
+
this.stopWatching(args.postId);
|
|
17472
|
+
this.startWatching(session);
|
|
15509
17473
|
this.emitter.emitSessionUpdate(session);
|
|
15510
17474
|
}
|
|
15511
17475
|
// ── workspace + Claude CLI, user drives ──
|
|
@@ -15515,11 +17479,13 @@ var TerminalModeEngine = class {
|
|
|
15515
17479
|
await this.core.ensureSpaceWorkspace();
|
|
15516
17480
|
if (config.repoUrl && config.githubToken) {
|
|
15517
17481
|
const branch = baseBranch || config.mainBranch || "main";
|
|
15518
|
-
const
|
|
17482
|
+
const workName = isCardPostId(session.postId) ? session.taskId : await claimWorkName(
|
|
15519
17483
|
this.core.target(),
|
|
15520
|
-
session.
|
|
15521
|
-
|
|
17484
|
+
session.taskTitle,
|
|
17485
|
+
this.reservedNames.values()
|
|
15522
17486
|
);
|
|
17487
|
+
this.reservedNames.set(session.postId, workName);
|
|
17488
|
+
const { path: path15 } = await addWorktree(this.core.target(), workName, branch);
|
|
15523
17489
|
session.workspacePath = path15;
|
|
15524
17490
|
await setGitIdentity(
|
|
15525
17491
|
this.core.target(),
|
|
@@ -15549,6 +17515,7 @@ var TerminalModeEngine = class {
|
|
|
15549
17515
|
}
|
|
15550
17516
|
}
|
|
15551
17517
|
session.phase = "bare-active";
|
|
17518
|
+
this.startWatching(session);
|
|
15552
17519
|
this.emitter.emitSessionUpdate(session);
|
|
15553
17520
|
this.emitter.addLog(
|
|
15554
17521
|
session,
|
|
@@ -15656,6 +17623,7 @@ var TerminalModeEngine = class {
|
|
|
15656
17623
|
if (!/^[A-Za-z0-9+/=\n\r]*$/.test(b64)) {
|
|
15657
17624
|
throw new Error("Invalid base64 payload.");
|
|
15658
17625
|
}
|
|
17626
|
+
this.expectWrite(String(postId), path15);
|
|
15659
17627
|
await target.sh(
|
|
15660
17628
|
`mkdir -p ${shEscape(posixDirname(abs))} && printf %s ${shEscape(b64)} | base64 -d > ${shEscape(abs)}`
|
|
15661
17629
|
);
|
|
@@ -15907,11 +17875,6 @@ var TerminalModeEngine = class {
|
|
|
15907
17875
|
}
|
|
15908
17876
|
};
|
|
15909
17877
|
|
|
15910
|
-
// ../../shared/all/helpers/board-agent-core/boardTerminal.ts
|
|
15911
|
-
function boardTerminalKey(spaceSlug) {
|
|
15912
|
-
return `board-${spaceSlug}`;
|
|
15913
|
-
}
|
|
15914
|
-
|
|
15915
17878
|
// ../../shared/all/helpers/board-agent-core/ansi.ts
|
|
15916
17879
|
var CSI = String.raw`\x1b\[[0-?]*[ -/]*[@-~]`;
|
|
15917
17880
|
var OSC = String.raw`\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)`;
|
|
@@ -15988,8 +17951,8 @@ var ClaudeLoginFlow = class {
|
|
|
15988
17951
|
if (this.active) throw new Error("A Claude sign-in is already running.");
|
|
15989
17952
|
this.reset();
|
|
15990
17953
|
this.inFlight = true;
|
|
15991
|
-
const urlPromise = new Promise((
|
|
15992
|
-
this.urlResolver =
|
|
17954
|
+
const urlPromise = new Promise((resolve4, reject) => {
|
|
17955
|
+
this.urlResolver = resolve4;
|
|
15993
17956
|
this.urlRejecter = reject;
|
|
15994
17957
|
});
|
|
15995
17958
|
urlPromise.catch(() => {
|
|
@@ -16050,10 +18013,10 @@ var ClaudeLoginFlow = class {
|
|
|
16050
18013
|
/https:\/\/[^\s\x00-\x1f]*oauth[^\s\x00-\x1f]*/
|
|
16051
18014
|
)?.[0];
|
|
16052
18015
|
if (url2) {
|
|
16053
|
-
const
|
|
18016
|
+
const resolve4 = this.urlResolver;
|
|
16054
18017
|
this.urlResolver = null;
|
|
16055
18018
|
this.urlRejecter = null;
|
|
16056
|
-
|
|
18019
|
+
resolve4(url2.replace(/[.,;)\]]+$/, ""));
|
|
16057
18020
|
}
|
|
16058
18021
|
}
|
|
16059
18022
|
if (this.submitMark < 0 || this.settled) return;
|
|
@@ -16149,8 +18112,8 @@ var CodexLoginFlow = class {
|
|
|
16149
18112
|
this.reset();
|
|
16150
18113
|
this.inFlight = true;
|
|
16151
18114
|
const startPromise = new Promise(
|
|
16152
|
-
(
|
|
16153
|
-
this.startResolver =
|
|
18115
|
+
(resolve4, reject) => {
|
|
18116
|
+
this.startResolver = resolve4;
|
|
16154
18117
|
this.startRejecter = reject;
|
|
16155
18118
|
}
|
|
16156
18119
|
);
|
|
@@ -16196,10 +18159,10 @@ var CodexLoginFlow = class {
|
|
|
16196
18159
|
const url2 = this.output.match(/https:\/\/[^\s\x00-\x1f]+/)?.[0];
|
|
16197
18160
|
const code = this.output.match(CODE_LINE_RE)?.[1] ?? this.output.match(CODE_TOKEN_RE)?.[1];
|
|
16198
18161
|
if (url2 && code) {
|
|
16199
|
-
const
|
|
18162
|
+
const resolve4 = this.startResolver;
|
|
16200
18163
|
this.startResolver = null;
|
|
16201
18164
|
this.startRejecter = null;
|
|
16202
|
-
|
|
18165
|
+
resolve4({ url: url2.replace(/[.,;)\]]+$/, ""), code });
|
|
16203
18166
|
}
|
|
16204
18167
|
return;
|
|
16205
18168
|
}
|
|
@@ -16378,7 +18341,7 @@ async function listGithubBranches(token, fullName) {
|
|
|
16378
18341
|
|
|
16379
18342
|
// ../../shared/all/helpers/board-agent-core/host-deploy.ts
|
|
16380
18343
|
var import_child_process5 = require("child_process");
|
|
16381
|
-
var
|
|
18344
|
+
var import_promises6 = __toESM(require("fs/promises"));
|
|
16382
18345
|
var import_path9 = __toESM(require("path"));
|
|
16383
18346
|
var import_util5 = require("util");
|
|
16384
18347
|
var execFileAsync2 = (0, import_util5.promisify)(import_child_process5.execFile);
|
|
@@ -16391,12 +18354,12 @@ var CLAUDE_LINK = `${CLAUDE_SKILLS_DIR}/deploy`;
|
|
|
16391
18354
|
async function ensureClaudeSkillLink(workspace) {
|
|
16392
18355
|
const linkPath = import_path9.default.join(workspace, CLAUDE_LINK);
|
|
16393
18356
|
try {
|
|
16394
|
-
await
|
|
18357
|
+
await import_promises6.default.lstat(linkPath);
|
|
16395
18358
|
return;
|
|
16396
18359
|
} catch {
|
|
16397
18360
|
}
|
|
16398
|
-
await
|
|
16399
|
-
await
|
|
18361
|
+
await import_promises6.default.mkdir(import_path9.default.join(workspace, CLAUDE_SKILLS_DIR), { recursive: true });
|
|
18362
|
+
await import_promises6.default.symlink("../../.agents/skills/deploy", linkPath, "dir");
|
|
16400
18363
|
}
|
|
16401
18364
|
var GIT_NO_HELPER = ["-c", "credential.helper="];
|
|
16402
18365
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -16505,15 +18468,15 @@ function spaceEnv(spaceDir) {
|
|
|
16505
18468
|
};
|
|
16506
18469
|
}
|
|
16507
18470
|
async function readContract(workspace) {
|
|
16508
|
-
const skill = await
|
|
18471
|
+
const skill = await import_promises6.default.readFile(import_path9.default.join(workspace, SKILL_PATH), "utf-8").catch(() => {
|
|
16509
18472
|
throw new Error("The creator wrote no SKILL.md.");
|
|
16510
18473
|
});
|
|
16511
|
-
const checker = await
|
|
18474
|
+
const checker = await import_promises6.default.readFile(import_path9.default.join(workspace, CHECKER_PATH), "utf-8").catch(() => {
|
|
16512
18475
|
throw new Error("The creator wrote no check-environment.sh.");
|
|
16513
18476
|
});
|
|
16514
18477
|
try {
|
|
16515
18478
|
const raw = JSON.parse(
|
|
16516
|
-
await
|
|
18479
|
+
await import_promises6.default.readFile(import_path9.default.join(workspace, VARIABLES_PATH), "utf-8")
|
|
16517
18480
|
);
|
|
16518
18481
|
return {
|
|
16519
18482
|
skill,
|
|
@@ -16666,7 +18629,7 @@ async function runEnvironmentCheck(opts) {
|
|
|
16666
18629
|
`origin/${status.branch}:${CHECKER_PATH}`
|
|
16667
18630
|
);
|
|
16668
18631
|
const tmp = import_path9.default.join(opts.spaceDir, `.env-check.${process.pid}.sh`);
|
|
16669
|
-
await
|
|
18632
|
+
await import_promises6.default.writeFile(tmp, script, { mode: 448 });
|
|
16670
18633
|
let ok = true;
|
|
16671
18634
|
let output = "";
|
|
16672
18635
|
try {
|
|
@@ -16679,7 +18642,7 @@ async function runEnvironmentCheck(opts) {
|
|
|
16679
18642
|
output = res.output;
|
|
16680
18643
|
if (res.code !== 0) ok = false;
|
|
16681
18644
|
} finally {
|
|
16682
|
-
await
|
|
18645
|
+
await import_promises6.default.rm(tmp, { force: true });
|
|
16683
18646
|
}
|
|
16684
18647
|
const checks = [];
|
|
16685
18648
|
for (const line of output.split("\n")) {
|
|
@@ -16749,7 +18712,7 @@ var import_path11 = __toESM(require("path"));
|
|
|
16749
18712
|
// ../../shared/all/helpers/board-agent-core/host-secrets.ts
|
|
16750
18713
|
var import_child_process6 = require("child_process");
|
|
16751
18714
|
var import_crypto5 = __toESM(require("crypto"));
|
|
16752
|
-
var
|
|
18715
|
+
var import_promises7 = __toESM(require("fs/promises"));
|
|
16753
18716
|
var import_path10 = __toESM(require("path"));
|
|
16754
18717
|
var import_util6 = require("util");
|
|
16755
18718
|
var execFileAsync3 = (0, import_util6.promisify)(import_child_process6.execFile);
|
|
@@ -16783,7 +18746,7 @@ function deriveKey(password, salt) {
|
|
|
16783
18746
|
}
|
|
16784
18747
|
async function secretsInitialized(configDir) {
|
|
16785
18748
|
try {
|
|
16786
|
-
await
|
|
18749
|
+
await import_promises7.default.access(import_path10.default.join(configDir, IDENTITY_FILE));
|
|
16787
18750
|
return true;
|
|
16788
18751
|
} catch {
|
|
16789
18752
|
return false;
|
|
@@ -16822,10 +18785,10 @@ async function initSecrets(configDir, password) {
|
|
|
16822
18785
|
tag: cipher.getAuthTag().toString("base64"),
|
|
16823
18786
|
data: data.toString("base64")
|
|
16824
18787
|
};
|
|
16825
|
-
await
|
|
18788
|
+
await import_promises7.default.writeFile(import_path10.default.join(configDir, IDENTITY_FILE), JSON.stringify(box), {
|
|
16826
18789
|
mode: 384
|
|
16827
18790
|
});
|
|
16828
|
-
await
|
|
18791
|
+
await import_promises7.default.writeFile(import_path10.default.join(configDir, RECIPIENT_FILE), `${recipient}
|
|
16829
18792
|
`, {
|
|
16830
18793
|
mode: 384
|
|
16831
18794
|
});
|
|
@@ -16852,13 +18815,13 @@ function envPath(spaceDir) {
|
|
|
16852
18815
|
}
|
|
16853
18816
|
async function identityFor(configDir, password) {
|
|
16854
18817
|
const box = JSON.parse(
|
|
16855
|
-
await
|
|
18818
|
+
await import_promises7.default.readFile(import_path10.default.join(configDir, IDENTITY_FILE), "utf-8")
|
|
16856
18819
|
);
|
|
16857
18820
|
return decryptIdentity(box, password);
|
|
16858
18821
|
}
|
|
16859
18822
|
async function readEnv(spaceDir, identity) {
|
|
16860
18823
|
try {
|
|
16861
|
-
await
|
|
18824
|
+
await import_promises7.default.access(envPath(spaceDir));
|
|
16862
18825
|
} catch {
|
|
16863
18826
|
return {};
|
|
16864
18827
|
}
|
|
@@ -16887,14 +18850,14 @@ async function readEnv(spaceDir, identity) {
|
|
|
16887
18850
|
return values;
|
|
16888
18851
|
}
|
|
16889
18852
|
async function writeEnv(configDir, spaceDir, identity, values) {
|
|
16890
|
-
const recipient = (await
|
|
18853
|
+
const recipient = (await import_promises7.default.readFile(import_path10.default.join(configDir, RECIPIENT_FILE), "utf-8")).trim();
|
|
16891
18854
|
const plain = `${Object.entries(values).map(([k, v]) => `${k}=${v}`).join("\n")}
|
|
16892
18855
|
`;
|
|
16893
18856
|
const tmp = envPath(spaceDir).replace(
|
|
16894
18857
|
/\.enc\.env$/,
|
|
16895
18858
|
`.${process.pid}.tmp.env`
|
|
16896
18859
|
);
|
|
16897
|
-
await
|
|
18860
|
+
await import_promises7.default.writeFile(tmp, plain, { mode: 384 });
|
|
16898
18861
|
try {
|
|
16899
18862
|
const { stdout } = await execFileAsync3(
|
|
16900
18863
|
"sops",
|
|
@@ -16913,9 +18876,9 @@ async function writeEnv(configDir, spaceDir, identity, values) {
|
|
|
16913
18876
|
maxBuffer: 4 * 1024 * 1024
|
|
16914
18877
|
}
|
|
16915
18878
|
);
|
|
16916
|
-
await
|
|
18879
|
+
await import_promises7.default.writeFile(envPath(spaceDir), stdout, { mode: 384 });
|
|
16917
18880
|
} finally {
|
|
16918
|
-
await
|
|
18881
|
+
await import_promises7.default.rm(tmp, { force: true });
|
|
16919
18882
|
}
|
|
16920
18883
|
}
|
|
16921
18884
|
async function listSecretKeys(configDir, spaceDir, password) {
|
|
@@ -17650,6 +19613,12 @@ var SpaceCore = class {
|
|
|
17650
19613
|
await this.ensureSpaceWorkspace();
|
|
17651
19614
|
return { ready: true };
|
|
17652
19615
|
}
|
|
19616
|
+
async bareWorkNames() {
|
|
19617
|
+
const config = this.configProvider.readConfig(this.spaceSlug);
|
|
19618
|
+
if (!config.githubToken || !config.repoUrl) return [];
|
|
19619
|
+
await this.ensureSpaceWorkspace();
|
|
19620
|
+
return listWorkNames(this.target());
|
|
19621
|
+
}
|
|
17653
19622
|
async cardRemoteBranches() {
|
|
17654
19623
|
const config = this.configProvider.readConfig(this.spaceSlug);
|
|
17655
19624
|
if (!config.githubToken || !config.repoUrl) return [];
|
|
@@ -17768,6 +19737,9 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17768
19737
|
cardRemoteBranches() {
|
|
17769
19738
|
return this.core.cardRemoteBranches();
|
|
17770
19739
|
}
|
|
19740
|
+
bareWorkNames() {
|
|
19741
|
+
return this.core.bareWorkNames();
|
|
19742
|
+
}
|
|
17771
19743
|
// Deploy button entry: is the repo's deploy contract (SKILL.md +
|
|
17772
19744
|
// required-variables.json) on the default branch? See .specs/deploy.md.
|
|
17773
19745
|
async deployStatus() {
|
|
@@ -17837,18 +19809,18 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17837
19809
|
* setup-status channel. A second request cancels the pending one. */
|
|
17838
19810
|
askSudo(reason) {
|
|
17839
19811
|
this.sudoResolver?.(null);
|
|
17840
|
-
return new Promise((
|
|
17841
|
-
this.sudoResolver =
|
|
19812
|
+
return new Promise((resolve4) => {
|
|
19813
|
+
this.sudoResolver = resolve4;
|
|
17842
19814
|
this.emitter.emitSetupStatus(`${SETUP_AUTH_PREFIX}${reason}`);
|
|
17843
19815
|
});
|
|
17844
19816
|
}
|
|
17845
19817
|
/** Answer a pending sudo request. An empty password denies it, so setup
|
|
17846
19818
|
* fails with a message rather than hanging. */
|
|
17847
19819
|
setupAuthorize(p) {
|
|
17848
|
-
const
|
|
17849
|
-
if (!
|
|
19820
|
+
const resolve4 = this.sudoResolver;
|
|
19821
|
+
if (!resolve4) return { success: false };
|
|
17850
19822
|
this.sudoResolver = null;
|
|
17851
|
-
|
|
19823
|
+
resolve4(p.password || null);
|
|
17852
19824
|
return { success: true };
|
|
17853
19825
|
}
|
|
17854
19826
|
deployRunState() {
|
|
@@ -17902,12 +19874,12 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17902
19874
|
hooks: {
|
|
17903
19875
|
sendLog: bufferLog,
|
|
17904
19876
|
onTodos: (todos) => this.setRun({ todos }),
|
|
17905
|
-
requestHuman: (question) => new Promise((
|
|
17906
|
-
this.runResolvers.human =
|
|
19877
|
+
requestHuman: (question) => new Promise((resolve4) => {
|
|
19878
|
+
this.runResolvers.human = resolve4;
|
|
17907
19879
|
this.setRun({ phase: "awaiting-input", question });
|
|
17908
19880
|
}),
|
|
17909
|
-
requestAuth: (command, errorNote) => new Promise((
|
|
17910
|
-
this.runResolvers.auth =
|
|
19881
|
+
requestAuth: (command, errorNote) => new Promise((resolve4) => {
|
|
19882
|
+
this.runResolvers.auth = resolve4;
|
|
17911
19883
|
this.setRun({
|
|
17912
19884
|
phase: "awaiting-auth",
|
|
17913
19885
|
pendingCommand: command,
|
|
@@ -17940,35 +19912,35 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17940
19912
|
return { started: true };
|
|
17941
19913
|
}
|
|
17942
19914
|
deployRunAnswer(payload) {
|
|
17943
|
-
const
|
|
17944
|
-
if (!
|
|
19915
|
+
const resolve4 = this.runResolvers.human;
|
|
19916
|
+
if (!resolve4 || this.runState.phase !== "awaiting-input") {
|
|
17945
19917
|
throw new Error("No step is awaiting input.");
|
|
17946
19918
|
}
|
|
17947
19919
|
this.runResolvers.human = void 0;
|
|
17948
19920
|
this.setRun({ phase: "running", question: "", error: "" });
|
|
17949
|
-
|
|
19921
|
+
resolve4(payload.answer);
|
|
17950
19922
|
return { success: true };
|
|
17951
19923
|
}
|
|
17952
19924
|
// The password arrives RUNNER-DIRECT here and only feeds decryption; it
|
|
17953
19925
|
// never enters the agent session (see .specs/deploy.md).
|
|
17954
19926
|
deployRunAuthorize(payload) {
|
|
17955
|
-
const
|
|
17956
|
-
if (!
|
|
19927
|
+
const resolve4 = this.runResolvers.auth;
|
|
19928
|
+
if (!resolve4 || this.runState.phase !== "awaiting-auth") {
|
|
17957
19929
|
throw new Error("No command is awaiting authorization.");
|
|
17958
19930
|
}
|
|
17959
19931
|
this.runResolvers.auth = void 0;
|
|
17960
19932
|
this.setRun({ phase: "running", pendingCommand: "", error: "" });
|
|
17961
|
-
|
|
19933
|
+
resolve4({ password: payload.password });
|
|
17962
19934
|
return { success: true };
|
|
17963
19935
|
}
|
|
17964
19936
|
deployRunDeny() {
|
|
17965
|
-
const
|
|
17966
|
-
if (!
|
|
19937
|
+
const resolve4 = this.runResolvers.auth;
|
|
19938
|
+
if (!resolve4 || this.runState.phase !== "awaiting-auth") {
|
|
17967
19939
|
throw new Error("No command is awaiting authorization.");
|
|
17968
19940
|
}
|
|
17969
19941
|
this.runResolvers.auth = void 0;
|
|
17970
19942
|
this.setRun({ phase: "running", pendingCommand: "" });
|
|
17971
|
-
|
|
19943
|
+
resolve4({ denied: true });
|
|
17972
19944
|
return { success: true };
|
|
17973
19945
|
}
|
|
17974
19946
|
deployRunCancel() {
|
|
@@ -18856,6 +20828,8 @@ ${c.content.trim() || "(no description)"}`
|
|
|
18856
20828
|
return await this.ensureSetup();
|
|
18857
20829
|
case "cardRemoteBranches":
|
|
18858
20830
|
return await this.cardRemoteBranches();
|
|
20831
|
+
case "bareWorkNames":
|
|
20832
|
+
return await this.bareWorkNames();
|
|
18859
20833
|
case "deployStatus":
|
|
18860
20834
|
return await this.deployStatus();
|
|
18861
20835
|
case "deployCreateSkill":
|
|
@@ -19068,8 +21042,8 @@ ${c.content.trim() || "(no description)"}`
|
|
|
19068
21042
|
// ../../shared/all/helpers/board-agent-core/index-service.ts
|
|
19069
21043
|
var import_child_process7 = require("child_process");
|
|
19070
21044
|
var import_crypto6 = require("crypto");
|
|
19071
|
-
var
|
|
19072
|
-
var
|
|
21045
|
+
var import_fs9 = require("fs");
|
|
21046
|
+
var import_promises8 = __toESM(require("fs/promises"));
|
|
19073
21047
|
var import_net2 = require("net");
|
|
19074
21048
|
var import_path13 = require("path");
|
|
19075
21049
|
var import_util7 = require("util");
|
|
@@ -19158,8 +21132,8 @@ var IndexService = class {
|
|
|
19158
21132
|
* opened (a missing log must never stop the service from starting). */
|
|
19159
21133
|
async openLog() {
|
|
19160
21134
|
try {
|
|
19161
|
-
await
|
|
19162
|
-
return (0,
|
|
21135
|
+
await import_promises8.default.mkdir(this.opts.dataDir, { recursive: true });
|
|
21136
|
+
return (0, import_fs9.openSync)((0, import_path13.join)(this.opts.dataDir, "index.log"), "a");
|
|
19163
21137
|
} catch {
|
|
19164
21138
|
return null;
|
|
19165
21139
|
}
|
|
@@ -19168,8 +21142,8 @@ var IndexService = class {
|
|
|
19168
21142
|
* platform needing node-gyp fails here rather than at query time. */
|
|
19169
21143
|
async installDeps() {
|
|
19170
21144
|
const dir = this.opts.indexDir;
|
|
19171
|
-
if ((0,
|
|
19172
|
-
await
|
|
21145
|
+
if ((0, import_fs9.existsSync)((0, import_path13.join)(dir, "node_modules"))) return;
|
|
21146
|
+
await import_promises8.default.copyFile(
|
|
19173
21147
|
(0, import_path13.join)(dir, "image-package.json"),
|
|
19174
21148
|
(0, import_path13.join)(dir, "package.json")
|
|
19175
21149
|
);
|
|
@@ -19184,14 +21158,14 @@ var IndexService = class {
|
|
|
19184
21158
|
* registration pointing at a dead one. */
|
|
19185
21159
|
async stablePort() {
|
|
19186
21160
|
const file = (0, import_path13.join)(this.opts.dataDir, ".port");
|
|
19187
|
-
const saved = Number(await
|
|
21161
|
+
const saved = Number(await import_promises8.default.readFile(file, "utf-8").catch(() => ""));
|
|
19188
21162
|
if (Number.isInteger(saved) && saved > 0 && await isFree(saved)) {
|
|
19189
21163
|
return saved;
|
|
19190
21164
|
}
|
|
19191
21165
|
const port = await freePort();
|
|
19192
|
-
await
|
|
21166
|
+
await import_promises8.default.mkdir(this.opts.dataDir, { recursive: true }).catch(() => {
|
|
19193
21167
|
});
|
|
19194
|
-
await
|
|
21168
|
+
await import_promises8.default.writeFile(file, String(port), "utf-8").catch(() => {
|
|
19195
21169
|
});
|
|
19196
21170
|
return port;
|
|
19197
21171
|
}
|
|
@@ -19284,20 +21258,20 @@ var IndexService = class {
|
|
|
19284
21258
|
}
|
|
19285
21259
|
};
|
|
19286
21260
|
function isFree(port) {
|
|
19287
|
-
return new Promise((
|
|
21261
|
+
return new Promise((resolve4) => {
|
|
19288
21262
|
const srv = (0, import_net2.createServer)();
|
|
19289
|
-
srv.once("error", () =>
|
|
19290
|
-
srv.listen(port, "127.0.0.1", () => srv.close(() =>
|
|
21263
|
+
srv.once("error", () => resolve4(false));
|
|
21264
|
+
srv.listen(port, "127.0.0.1", () => srv.close(() => resolve4(true)));
|
|
19291
21265
|
});
|
|
19292
21266
|
}
|
|
19293
21267
|
function freePort() {
|
|
19294
|
-
return new Promise((
|
|
21268
|
+
return new Promise((resolve4, reject) => {
|
|
19295
21269
|
const srv = (0, import_net2.createServer)();
|
|
19296
21270
|
srv.on("error", reject);
|
|
19297
21271
|
srv.listen(0, "127.0.0.1", () => {
|
|
19298
21272
|
const addr = srv.address();
|
|
19299
21273
|
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
19300
|
-
srv.close(() =>
|
|
21274
|
+
srv.close(() => resolve4(port));
|
|
19301
21275
|
});
|
|
19302
21276
|
});
|
|
19303
21277
|
}
|
|
@@ -19348,7 +21322,7 @@ async function setup(serverUrl) {
|
|
|
19348
21322
|
// src/selfUpdate.ts
|
|
19349
21323
|
var import_node_child_process = require("node:child_process");
|
|
19350
21324
|
var import_node_fs = __toESM(require("node:fs"));
|
|
19351
|
-
var
|
|
21325
|
+
var import_node_path2 = __toESM(require("node:path"));
|
|
19352
21326
|
var PACKAGE_NAME = "@factiii/runner";
|
|
19353
21327
|
var RESTART_FOR_UPDATE = 75;
|
|
19354
21328
|
var WORKER_ENV = "FACTIII_RUNNER_WORKER";
|
|
@@ -19361,7 +21335,7 @@ function isWorker() {
|
|
|
19361
21335
|
function currentVersion() {
|
|
19362
21336
|
try {
|
|
19363
21337
|
const pkg = JSON.parse(
|
|
19364
|
-
import_node_fs.default.readFileSync(
|
|
21338
|
+
import_node_fs.default.readFileSync(import_node_path2.default.join(__dirname, "..", "package.json"), "utf-8")
|
|
19365
21339
|
);
|
|
19366
21340
|
return pkg.version ?? "0.0.0";
|
|
19367
21341
|
} catch {
|
|
@@ -19437,7 +21411,7 @@ function makeChunkReassembler() {
|
|
|
19437
21411
|
|
|
19438
21412
|
// src/daemon.ts
|
|
19439
21413
|
var import_crypto7 = require("crypto");
|
|
19440
|
-
var
|
|
21414
|
+
var import_fs11 = __toESM(require("fs"));
|
|
19441
21415
|
var import_node_datachannel = require("node-datachannel");
|
|
19442
21416
|
var import_path15 = __toESM(require("path"));
|
|
19443
21417
|
|
|
@@ -21936,9 +23910,9 @@ var Socket2 = class extends import_component_emitter5.Emitter {
|
|
|
21936
23910
|
* @return a Promise that will be fulfilled when the server acknowledges the event
|
|
21937
23911
|
*/
|
|
21938
23912
|
emitWithAck(ev, ...args) {
|
|
21939
|
-
return new Promise((
|
|
23913
|
+
return new Promise((resolve4, reject) => {
|
|
21940
23914
|
const fn = (arg1, arg2) => {
|
|
21941
|
-
return arg1 ? reject(arg1) :
|
|
23915
|
+
return arg1 ? reject(arg1) : resolve4(arg2);
|
|
21942
23916
|
};
|
|
21943
23917
|
fn.withError = true;
|
|
21944
23918
|
args.push(fn);
|
|
@@ -23119,7 +25093,7 @@ var TerminalManager = class {
|
|
|
23119
25093
|
};
|
|
23120
25094
|
|
|
23121
25095
|
// src/agent-adapter.ts
|
|
23122
|
-
var
|
|
25096
|
+
var import_fs10 = __toESM(require("fs"));
|
|
23123
25097
|
var import_path14 = __toESM(require("path"));
|
|
23124
25098
|
var RUNNER_CONFIG_PATH = import_path14.default.join(CONFIG_DIR, "runner-config.json");
|
|
23125
25099
|
function connectionPath(spaceSlug) {
|
|
@@ -23150,7 +25124,7 @@ function migrateLegacyConfigs() {
|
|
|
23150
25124
|
const file = { boards: {} };
|
|
23151
25125
|
let legacy = [];
|
|
23152
25126
|
try {
|
|
23153
|
-
legacy =
|
|
25127
|
+
legacy = import_fs10.default.readdirSync(CONFIG_DIR).filter((f) => f.startsWith("space-") && f.endsWith(".json")).filter((f) => !f.endsWith(".onedrive.json"));
|
|
23154
25128
|
} catch {
|
|
23155
25129
|
return file;
|
|
23156
25130
|
}
|
|
@@ -23177,14 +25151,14 @@ function encryptStrayPlaintextConfigs() {
|
|
|
23177
25151
|
const OURS = /^(config|runner-config|space-.*)\.json(\.bak-\d+)?$/;
|
|
23178
25152
|
let names = [];
|
|
23179
25153
|
try {
|
|
23180
|
-
names =
|
|
25154
|
+
names = import_fs10.default.readdirSync(CONFIG_DIR).filter((f) => OURS.test(f));
|
|
23181
25155
|
} catch {
|
|
23182
25156
|
return;
|
|
23183
25157
|
}
|
|
23184
25158
|
for (const name of names) {
|
|
23185
25159
|
const filePath = import_path14.default.join(CONFIG_DIR, name);
|
|
23186
25160
|
try {
|
|
23187
|
-
const raw =
|
|
25161
|
+
const raw = import_fs10.default.readFileSync(filePath, "utf-8");
|
|
23188
25162
|
if (!raw.startsWith("{")) continue;
|
|
23189
25163
|
writeSecureJson(filePath, JSON.parse(raw));
|
|
23190
25164
|
} catch {
|
|
@@ -23215,7 +25189,7 @@ async function getConfiguredConnections() {
|
|
|
23215
25189
|
}
|
|
23216
25190
|
if (await isSignedIn(hostTarget(CONFIG_DIR), "claude")) kinds.add("claude");
|
|
23217
25191
|
try {
|
|
23218
|
-
const hasOneDrive =
|
|
25192
|
+
const hasOneDrive = import_fs10.default.readdirSync(CONFIG_DIR).some((f) => f.endsWith(".onedrive.json"));
|
|
23219
25193
|
if (hasOneDrive) kinds.add("onedrive");
|
|
23220
25194
|
} catch {
|
|
23221
25195
|
}
|
|
@@ -23286,7 +25260,7 @@ var localConfigProvider = {
|
|
|
23286
25260
|
writeOneDriveConnection(spaceSlug, connection) {
|
|
23287
25261
|
const filePath = connectionPath(spaceSlug);
|
|
23288
25262
|
if (!connection) {
|
|
23289
|
-
|
|
25263
|
+
import_fs10.default.rmSync(filePath, { force: true });
|
|
23290
25264
|
return;
|
|
23291
25265
|
}
|
|
23292
25266
|
writeJson(filePath, connection);
|
|
@@ -23311,7 +25285,7 @@ var localConfigProvider = {
|
|
|
23311
25285
|
"claude",
|
|
23312
25286
|
"codex"
|
|
23313
25287
|
]) {
|
|
23314
|
-
|
|
25288
|
+
import_fs10.default.mkdirSync(import_path14.default.join(dir, sub), { recursive: true });
|
|
23315
25289
|
}
|
|
23316
25290
|
return dir;
|
|
23317
25291
|
}
|
|
@@ -23435,17 +25409,17 @@ async function startDaemon(config) {
|
|
|
23435
25409
|
}
|
|
23436
25410
|
};
|
|
23437
25411
|
const mintWebhook = (spaceSlug) => new Promise(
|
|
23438
|
-
(
|
|
25412
|
+
(resolve4) => {
|
|
23439
25413
|
if (!socket.connected) {
|
|
23440
|
-
|
|
25414
|
+
resolve4(null);
|
|
23441
25415
|
return;
|
|
23442
25416
|
}
|
|
23443
25417
|
socket.timeout(8e3).emit("onedriveWebhookRegister", { spaceSlug }, (err, res) => {
|
|
23444
25418
|
if (err || !res || "error" in res) {
|
|
23445
|
-
|
|
25419
|
+
resolve4(null);
|
|
23446
25420
|
return;
|
|
23447
25421
|
}
|
|
23448
|
-
|
|
25422
|
+
resolve4({
|
|
23449
25423
|
notificationUrl: `${config.serverUrl.replace(/\/$/, "")}/onedrive/webhook`,
|
|
23450
25424
|
clientState: res.clientState
|
|
23451
25425
|
});
|
|
@@ -23456,7 +25430,7 @@ async function startDaemon(config) {
|
|
|
23456
25430
|
import_path15.default.join(__dirname, "..", "index"),
|
|
23457
25431
|
import_path15.default.join(__dirname, "..", "..", "index", "image")
|
|
23458
25432
|
];
|
|
23459
|
-
const indexDir = indexCandidates.find((p) =>
|
|
25433
|
+
const indexDir = indexCandidates.find((p) => import_fs11.default.existsSync(p)) ?? indexCandidates[0];
|
|
23460
25434
|
const odIndex = new IndexService({
|
|
23461
25435
|
controlToken: (0, import_crypto7.createHash)("sha256").update(config.authToken).digest("hex"),
|
|
23462
25436
|
embedUrl: () => config.serverUrl,
|
|
@@ -24111,5 +26085,8 @@ xmlhttprequest-ssl/lib/XMLHttpRequest.js:
|
|
|
24111
26085
|
* @contributor David Ellis <d.f.ellis@ieee.org>
|
|
24112
26086
|
* @license MIT
|
|
24113
26087
|
*)
|
|
26088
|
+
|
|
26089
|
+
chokidar/esm/index.js:
|
|
26090
|
+
(*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
|
|
24114
26091
|
*/
|
|
24115
26092
|
//# sourceMappingURL=cli.js.map
|