@factiii/runner 0.9.0 → 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 +2139 -124
- 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";
|
|
@@ -15239,6 +15277,18 @@ ${buildPrompt(prompts_default.implement)}`;
|
|
|
15239
15277
|
}
|
|
15240
15278
|
};
|
|
15241
15279
|
|
|
15280
|
+
// ../../shared/all/helpers/terminal-ai/terminal-mode.ts
|
|
15281
|
+
var import_crypto4 = require("crypto");
|
|
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
|
+
|
|
15242
15292
|
// ../../shared/all/helpers/board-agent-core/tmux.ts
|
|
15243
15293
|
var TMUX_CONF = [
|
|
15244
15294
|
// Wheel scrolls, drag selects in copy mode.
|
|
@@ -15328,6 +15378,1865 @@ async function startTmuxSession(opts) {
|
|
|
15328
15378
|
};
|
|
15329
15379
|
}
|
|
15330
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
|
+
|
|
15331
17240
|
// ../../shared/all/helpers/terminal-ai/terminal-mode.ts
|
|
15332
17241
|
function posixNormalize(p) {
|
|
15333
17242
|
const parts2 = p.split("/").filter(Boolean);
|
|
@@ -15355,6 +17264,54 @@ var TerminalModeEngine = class {
|
|
|
15355
17264
|
this.core = core;
|
|
15356
17265
|
this.emitter = emitter;
|
|
15357
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));
|
|
15358
17315
|
}
|
|
15359
17316
|
// ── Lifecycle / ModeEngine ──
|
|
15360
17317
|
start(base, args) {
|
|
@@ -15398,6 +17355,8 @@ var TerminalModeEngine = class {
|
|
|
15398
17355
|
return !!s && (s.phase === "starting" || s.phase === "bare-active");
|
|
15399
17356
|
}
|
|
15400
17357
|
remove(postId) {
|
|
17358
|
+
this.stopWatching(postId);
|
|
17359
|
+
this.reservedNames.delete(postId);
|
|
15401
17360
|
this.sessions.delete(postId);
|
|
15402
17361
|
}
|
|
15403
17362
|
async kill(postId) {
|
|
@@ -15411,12 +17370,17 @@ var TerminalModeEngine = class {
|
|
|
15411
17370
|
}
|
|
15412
17371
|
}
|
|
15413
17372
|
if (!session) return;
|
|
17373
|
+
this.stopWatching(session.postId);
|
|
15414
17374
|
await this.teardown(session);
|
|
15415
17375
|
const removedPostId = session.postId;
|
|
17376
|
+
this.reservedNames.delete(removedPostId);
|
|
15416
17377
|
this.sessions.delete(removedPostId);
|
|
15417
17378
|
this.emitter.emitSessionRemoved(removedPostId);
|
|
15418
17379
|
}
|
|
15419
17380
|
destroy() {
|
|
17381
|
+
for (const watcher of this.watchers.values()) void watcher.close();
|
|
17382
|
+
this.watchers.clear();
|
|
17383
|
+
this.reservedNames.clear();
|
|
15420
17384
|
this.sessions.clear();
|
|
15421
17385
|
}
|
|
15422
17386
|
teardown(session) {
|
|
@@ -15461,6 +17425,7 @@ var TerminalModeEngine = class {
|
|
|
15461
17425
|
exposed: []
|
|
15462
17426
|
};
|
|
15463
17427
|
this.sessions.set(r.postId, session);
|
|
17428
|
+
this.startWatching(session);
|
|
15464
17429
|
this.emitter.emitSessionUpdate(session);
|
|
15465
17430
|
}
|
|
15466
17431
|
}
|
|
@@ -15503,6 +17468,8 @@ var TerminalModeEngine = class {
|
|
|
15503
17468
|
exposed: []
|
|
15504
17469
|
};
|
|
15505
17470
|
this.sessions.set(args.postId, session);
|
|
17471
|
+
this.stopWatching(args.postId);
|
|
17472
|
+
this.startWatching(session);
|
|
15506
17473
|
this.emitter.emitSessionUpdate(session);
|
|
15507
17474
|
}
|
|
15508
17475
|
// ── workspace + Claude CLI, user drives ──
|
|
@@ -15512,11 +17479,13 @@ var TerminalModeEngine = class {
|
|
|
15512
17479
|
await this.core.ensureSpaceWorkspace();
|
|
15513
17480
|
if (config.repoUrl && config.githubToken) {
|
|
15514
17481
|
const branch = baseBranch || config.mainBranch || "main";
|
|
15515
|
-
const
|
|
17482
|
+
const workName = isCardPostId(session.postId) ? session.taskId : await claimWorkName(
|
|
15516
17483
|
this.core.target(),
|
|
15517
|
-
session.
|
|
15518
|
-
|
|
17484
|
+
session.taskTitle,
|
|
17485
|
+
this.reservedNames.values()
|
|
15519
17486
|
);
|
|
17487
|
+
this.reservedNames.set(session.postId, workName);
|
|
17488
|
+
const { path: path15 } = await addWorktree(this.core.target(), workName, branch);
|
|
15520
17489
|
session.workspacePath = path15;
|
|
15521
17490
|
await setGitIdentity(
|
|
15522
17491
|
this.core.target(),
|
|
@@ -15546,6 +17515,7 @@ var TerminalModeEngine = class {
|
|
|
15546
17515
|
}
|
|
15547
17516
|
}
|
|
15548
17517
|
session.phase = "bare-active";
|
|
17518
|
+
this.startWatching(session);
|
|
15549
17519
|
this.emitter.emitSessionUpdate(session);
|
|
15550
17520
|
this.emitter.addLog(
|
|
15551
17521
|
session,
|
|
@@ -15653,12 +17623,41 @@ var TerminalModeEngine = class {
|
|
|
15653
17623
|
if (!/^[A-Za-z0-9+/=\n\r]*$/.test(b64)) {
|
|
15654
17624
|
throw new Error("Invalid base64 payload.");
|
|
15655
17625
|
}
|
|
17626
|
+
this.expectWrite(String(postId), path15);
|
|
15656
17627
|
await target.sh(
|
|
15657
17628
|
`mkdir -p ${shEscape(posixDirname(abs))} && printf %s ${shEscape(b64)} | base64 -d > ${shEscape(abs)}`
|
|
15658
17629
|
);
|
|
15659
17630
|
const session = this.sessions.get(String(postId));
|
|
15660
17631
|
if (session) delete session.buffers[path15];
|
|
15661
17632
|
}
|
|
17633
|
+
/** Write a dropped image to the per-space drops dir (`paths.root`, OUTSIDE the
|
|
17634
|
+
* card worktree so it never touches the repo) and return its absolute path. */
|
|
17635
|
+
async terminalDropImage({
|
|
17636
|
+
postId,
|
|
17637
|
+
content,
|
|
17638
|
+
ext
|
|
17639
|
+
}) {
|
|
17640
|
+
const target = this.getBareTarget(postId);
|
|
17641
|
+
if (!/^[A-Za-z0-9+/=\n\r]*$/.test(content)) {
|
|
17642
|
+
throw new Error("Invalid base64 payload.");
|
|
17643
|
+
}
|
|
17644
|
+
if (content.length > 14e6) {
|
|
17645
|
+
throw new Error("Image too large (max ~10MB).");
|
|
17646
|
+
}
|
|
17647
|
+
const safeExt = (ext || "png").toLowerCase().replace(/[^a-z0-9]/g, "") || "png";
|
|
17648
|
+
const dropsDir = `${target.paths.root}/drops`;
|
|
17649
|
+
const abs = `${dropsDir}/${(0, import_crypto4.randomUUID)()}.${safeExt}`;
|
|
17650
|
+
await target.sh(
|
|
17651
|
+
`mkdir -p ${shEscape(dropsDir)} && printf %s ${shEscape(content)} | base64 -d > ${shEscape(abs)}`
|
|
17652
|
+
);
|
|
17653
|
+
try {
|
|
17654
|
+
await target.sh(
|
|
17655
|
+
`find ${shEscape(dropsDir)} -type f -mtime +1 -delete 2>/dev/null || true`
|
|
17656
|
+
);
|
|
17657
|
+
} catch {
|
|
17658
|
+
}
|
|
17659
|
+
return abs;
|
|
17660
|
+
}
|
|
15662
17661
|
bareEditorState({
|
|
15663
17662
|
postId: rawPostId
|
|
15664
17663
|
}) {
|
|
@@ -15876,11 +17875,6 @@ var TerminalModeEngine = class {
|
|
|
15876
17875
|
}
|
|
15877
17876
|
};
|
|
15878
17877
|
|
|
15879
|
-
// ../../shared/all/helpers/board-agent-core/boardTerminal.ts
|
|
15880
|
-
function boardTerminalKey(spaceSlug) {
|
|
15881
|
-
return `board-${spaceSlug}`;
|
|
15882
|
-
}
|
|
15883
|
-
|
|
15884
17878
|
// ../../shared/all/helpers/board-agent-core/ansi.ts
|
|
15885
17879
|
var CSI = String.raw`\x1b\[[0-?]*[ -/]*[@-~]`;
|
|
15886
17880
|
var OSC = String.raw`\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)`;
|
|
@@ -15957,8 +17951,8 @@ var ClaudeLoginFlow = class {
|
|
|
15957
17951
|
if (this.active) throw new Error("A Claude sign-in is already running.");
|
|
15958
17952
|
this.reset();
|
|
15959
17953
|
this.inFlight = true;
|
|
15960
|
-
const urlPromise = new Promise((
|
|
15961
|
-
this.urlResolver =
|
|
17954
|
+
const urlPromise = new Promise((resolve4, reject) => {
|
|
17955
|
+
this.urlResolver = resolve4;
|
|
15962
17956
|
this.urlRejecter = reject;
|
|
15963
17957
|
});
|
|
15964
17958
|
urlPromise.catch(() => {
|
|
@@ -16019,10 +18013,10 @@ var ClaudeLoginFlow = class {
|
|
|
16019
18013
|
/https:\/\/[^\s\x00-\x1f]*oauth[^\s\x00-\x1f]*/
|
|
16020
18014
|
)?.[0];
|
|
16021
18015
|
if (url2) {
|
|
16022
|
-
const
|
|
18016
|
+
const resolve4 = this.urlResolver;
|
|
16023
18017
|
this.urlResolver = null;
|
|
16024
18018
|
this.urlRejecter = null;
|
|
16025
|
-
|
|
18019
|
+
resolve4(url2.replace(/[.,;)\]]+$/, ""));
|
|
16026
18020
|
}
|
|
16027
18021
|
}
|
|
16028
18022
|
if (this.submitMark < 0 || this.settled) return;
|
|
@@ -16118,8 +18112,8 @@ var CodexLoginFlow = class {
|
|
|
16118
18112
|
this.reset();
|
|
16119
18113
|
this.inFlight = true;
|
|
16120
18114
|
const startPromise = new Promise(
|
|
16121
|
-
(
|
|
16122
|
-
this.startResolver =
|
|
18115
|
+
(resolve4, reject) => {
|
|
18116
|
+
this.startResolver = resolve4;
|
|
16123
18117
|
this.startRejecter = reject;
|
|
16124
18118
|
}
|
|
16125
18119
|
);
|
|
@@ -16165,10 +18159,10 @@ var CodexLoginFlow = class {
|
|
|
16165
18159
|
const url2 = this.output.match(/https:\/\/[^\s\x00-\x1f]+/)?.[0];
|
|
16166
18160
|
const code = this.output.match(CODE_LINE_RE)?.[1] ?? this.output.match(CODE_TOKEN_RE)?.[1];
|
|
16167
18161
|
if (url2 && code) {
|
|
16168
|
-
const
|
|
18162
|
+
const resolve4 = this.startResolver;
|
|
16169
18163
|
this.startResolver = null;
|
|
16170
18164
|
this.startRejecter = null;
|
|
16171
|
-
|
|
18165
|
+
resolve4({ url: url2.replace(/[.,;)\]]+$/, ""), code });
|
|
16172
18166
|
}
|
|
16173
18167
|
return;
|
|
16174
18168
|
}
|
|
@@ -16347,7 +18341,7 @@ async function listGithubBranches(token, fullName) {
|
|
|
16347
18341
|
|
|
16348
18342
|
// ../../shared/all/helpers/board-agent-core/host-deploy.ts
|
|
16349
18343
|
var import_child_process5 = require("child_process");
|
|
16350
|
-
var
|
|
18344
|
+
var import_promises6 = __toESM(require("fs/promises"));
|
|
16351
18345
|
var import_path9 = __toESM(require("path"));
|
|
16352
18346
|
var import_util5 = require("util");
|
|
16353
18347
|
var execFileAsync2 = (0, import_util5.promisify)(import_child_process5.execFile);
|
|
@@ -16360,12 +18354,12 @@ var CLAUDE_LINK = `${CLAUDE_SKILLS_DIR}/deploy`;
|
|
|
16360
18354
|
async function ensureClaudeSkillLink(workspace) {
|
|
16361
18355
|
const linkPath = import_path9.default.join(workspace, CLAUDE_LINK);
|
|
16362
18356
|
try {
|
|
16363
|
-
await
|
|
18357
|
+
await import_promises6.default.lstat(linkPath);
|
|
16364
18358
|
return;
|
|
16365
18359
|
} catch {
|
|
16366
18360
|
}
|
|
16367
|
-
await
|
|
16368
|
-
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");
|
|
16369
18363
|
}
|
|
16370
18364
|
var GIT_NO_HELPER = ["-c", "credential.helper="];
|
|
16371
18365
|
var GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
@@ -16474,15 +18468,15 @@ function spaceEnv(spaceDir) {
|
|
|
16474
18468
|
};
|
|
16475
18469
|
}
|
|
16476
18470
|
async function readContract(workspace) {
|
|
16477
|
-
const skill = await
|
|
18471
|
+
const skill = await import_promises6.default.readFile(import_path9.default.join(workspace, SKILL_PATH), "utf-8").catch(() => {
|
|
16478
18472
|
throw new Error("The creator wrote no SKILL.md.");
|
|
16479
18473
|
});
|
|
16480
|
-
const checker = await
|
|
18474
|
+
const checker = await import_promises6.default.readFile(import_path9.default.join(workspace, CHECKER_PATH), "utf-8").catch(() => {
|
|
16481
18475
|
throw new Error("The creator wrote no check-environment.sh.");
|
|
16482
18476
|
});
|
|
16483
18477
|
try {
|
|
16484
18478
|
const raw = JSON.parse(
|
|
16485
|
-
await
|
|
18479
|
+
await import_promises6.default.readFile(import_path9.default.join(workspace, VARIABLES_PATH), "utf-8")
|
|
16486
18480
|
);
|
|
16487
18481
|
return {
|
|
16488
18482
|
skill,
|
|
@@ -16635,7 +18629,7 @@ async function runEnvironmentCheck(opts) {
|
|
|
16635
18629
|
`origin/${status.branch}:${CHECKER_PATH}`
|
|
16636
18630
|
);
|
|
16637
18631
|
const tmp = import_path9.default.join(opts.spaceDir, `.env-check.${process.pid}.sh`);
|
|
16638
|
-
await
|
|
18632
|
+
await import_promises6.default.writeFile(tmp, script, { mode: 448 });
|
|
16639
18633
|
let ok = true;
|
|
16640
18634
|
let output = "";
|
|
16641
18635
|
try {
|
|
@@ -16648,7 +18642,7 @@ async function runEnvironmentCheck(opts) {
|
|
|
16648
18642
|
output = res.output;
|
|
16649
18643
|
if (res.code !== 0) ok = false;
|
|
16650
18644
|
} finally {
|
|
16651
|
-
await
|
|
18645
|
+
await import_promises6.default.rm(tmp, { force: true });
|
|
16652
18646
|
}
|
|
16653
18647
|
const checks = [];
|
|
16654
18648
|
for (const line of output.split("\n")) {
|
|
@@ -16717,8 +18711,8 @@ var import_path11 = __toESM(require("path"));
|
|
|
16717
18711
|
|
|
16718
18712
|
// ../../shared/all/helpers/board-agent-core/host-secrets.ts
|
|
16719
18713
|
var import_child_process6 = require("child_process");
|
|
16720
|
-
var
|
|
16721
|
-
var
|
|
18714
|
+
var import_crypto5 = __toESM(require("crypto"));
|
|
18715
|
+
var import_promises7 = __toESM(require("fs/promises"));
|
|
16722
18716
|
var import_path10 = __toESM(require("path"));
|
|
16723
18717
|
var import_util6 = require("util");
|
|
16724
18718
|
var execFileAsync3 = (0, import_util6.promisify)(import_child_process6.execFile);
|
|
@@ -16745,14 +18739,14 @@ async function assertBinaries() {
|
|
|
16745
18739
|
}
|
|
16746
18740
|
}
|
|
16747
18741
|
function deriveKey(password, salt) {
|
|
16748
|
-
return
|
|
18742
|
+
return import_crypto5.default.scryptSync(password, salt, 32, {
|
|
16749
18743
|
N: SCRYPT_N2,
|
|
16750
18744
|
maxmem: 64 * 1024 * 1024
|
|
16751
18745
|
});
|
|
16752
18746
|
}
|
|
16753
18747
|
async function secretsInitialized(configDir) {
|
|
16754
18748
|
try {
|
|
16755
|
-
await
|
|
18749
|
+
await import_promises7.default.access(import_path10.default.join(configDir, IDENTITY_FILE));
|
|
16756
18750
|
return true;
|
|
16757
18751
|
} catch {
|
|
16758
18752
|
return false;
|
|
@@ -16774,9 +18768,9 @@ async function initSecrets(configDir, password) {
|
|
|
16774
18768
|
if (!identity || !recipient) {
|
|
16775
18769
|
throw new Error("age-keygen returned no usable keypair.");
|
|
16776
18770
|
}
|
|
16777
|
-
const salt =
|
|
16778
|
-
const iv =
|
|
16779
|
-
const cipher =
|
|
18771
|
+
const salt = import_crypto5.default.randomBytes(16);
|
|
18772
|
+
const iv = import_crypto5.default.randomBytes(12);
|
|
18773
|
+
const cipher = import_crypto5.default.createCipheriv(
|
|
16780
18774
|
"aes-256-gcm",
|
|
16781
18775
|
deriveKey(password, salt),
|
|
16782
18776
|
iv
|
|
@@ -16791,17 +18785,17 @@ async function initSecrets(configDir, password) {
|
|
|
16791
18785
|
tag: cipher.getAuthTag().toString("base64"),
|
|
16792
18786
|
data: data.toString("base64")
|
|
16793
18787
|
};
|
|
16794
|
-
await
|
|
18788
|
+
await import_promises7.default.writeFile(import_path10.default.join(configDir, IDENTITY_FILE), JSON.stringify(box), {
|
|
16795
18789
|
mode: 384
|
|
16796
18790
|
});
|
|
16797
|
-
await
|
|
18791
|
+
await import_promises7.default.writeFile(import_path10.default.join(configDir, RECIPIENT_FILE), `${recipient}
|
|
16798
18792
|
`, {
|
|
16799
18793
|
mode: 384
|
|
16800
18794
|
});
|
|
16801
18795
|
return { success: true };
|
|
16802
18796
|
}
|
|
16803
18797
|
function decryptIdentity(box, password) {
|
|
16804
|
-
const decipher =
|
|
18798
|
+
const decipher = import_crypto5.default.createDecipheriv(
|
|
16805
18799
|
"aes-256-gcm",
|
|
16806
18800
|
deriveKey(password, Buffer.from(box.salt, "base64")),
|
|
16807
18801
|
Buffer.from(box.iv, "base64")
|
|
@@ -16821,13 +18815,13 @@ function envPath(spaceDir) {
|
|
|
16821
18815
|
}
|
|
16822
18816
|
async function identityFor(configDir, password) {
|
|
16823
18817
|
const box = JSON.parse(
|
|
16824
|
-
await
|
|
18818
|
+
await import_promises7.default.readFile(import_path10.default.join(configDir, IDENTITY_FILE), "utf-8")
|
|
16825
18819
|
);
|
|
16826
18820
|
return decryptIdentity(box, password);
|
|
16827
18821
|
}
|
|
16828
18822
|
async function readEnv(spaceDir, identity) {
|
|
16829
18823
|
try {
|
|
16830
|
-
await
|
|
18824
|
+
await import_promises7.default.access(envPath(spaceDir));
|
|
16831
18825
|
} catch {
|
|
16832
18826
|
return {};
|
|
16833
18827
|
}
|
|
@@ -16856,14 +18850,14 @@ async function readEnv(spaceDir, identity) {
|
|
|
16856
18850
|
return values;
|
|
16857
18851
|
}
|
|
16858
18852
|
async function writeEnv(configDir, spaceDir, identity, values) {
|
|
16859
|
-
const recipient = (await
|
|
18853
|
+
const recipient = (await import_promises7.default.readFile(import_path10.default.join(configDir, RECIPIENT_FILE), "utf-8")).trim();
|
|
16860
18854
|
const plain = `${Object.entries(values).map(([k, v]) => `${k}=${v}`).join("\n")}
|
|
16861
18855
|
`;
|
|
16862
18856
|
const tmp = envPath(spaceDir).replace(
|
|
16863
18857
|
/\.enc\.env$/,
|
|
16864
18858
|
`.${process.pid}.tmp.env`
|
|
16865
18859
|
);
|
|
16866
|
-
await
|
|
18860
|
+
await import_promises7.default.writeFile(tmp, plain, { mode: 384 });
|
|
16867
18861
|
try {
|
|
16868
18862
|
const { stdout } = await execFileAsync3(
|
|
16869
18863
|
"sops",
|
|
@@ -16882,9 +18876,9 @@ async function writeEnv(configDir, spaceDir, identity, values) {
|
|
|
16882
18876
|
maxBuffer: 4 * 1024 * 1024
|
|
16883
18877
|
}
|
|
16884
18878
|
);
|
|
16885
|
-
await
|
|
18879
|
+
await import_promises7.default.writeFile(envPath(spaceDir), stdout, { mode: 384 });
|
|
16886
18880
|
} finally {
|
|
16887
|
-
await
|
|
18881
|
+
await import_promises7.default.rm(tmp, { force: true });
|
|
16888
18882
|
}
|
|
16889
18883
|
}
|
|
16890
18884
|
async function listSecretKeys(configDir, spaceDir, password) {
|
|
@@ -17619,6 +19613,12 @@ var SpaceCore = class {
|
|
|
17619
19613
|
await this.ensureSpaceWorkspace();
|
|
17620
19614
|
return { ready: true };
|
|
17621
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
|
+
}
|
|
17622
19622
|
async cardRemoteBranches() {
|
|
17623
19623
|
const config = this.configProvider.readConfig(this.spaceSlug);
|
|
17624
19624
|
if (!config.githubToken || !config.repoUrl) return [];
|
|
@@ -17737,6 +19737,9 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17737
19737
|
cardRemoteBranches() {
|
|
17738
19738
|
return this.core.cardRemoteBranches();
|
|
17739
19739
|
}
|
|
19740
|
+
bareWorkNames() {
|
|
19741
|
+
return this.core.bareWorkNames();
|
|
19742
|
+
}
|
|
17740
19743
|
// Deploy button entry: is the repo's deploy contract (SKILL.md +
|
|
17741
19744
|
// required-variables.json) on the default branch? See .specs/deploy.md.
|
|
17742
19745
|
async deployStatus() {
|
|
@@ -17806,18 +19809,18 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17806
19809
|
* setup-status channel. A second request cancels the pending one. */
|
|
17807
19810
|
askSudo(reason) {
|
|
17808
19811
|
this.sudoResolver?.(null);
|
|
17809
|
-
return new Promise((
|
|
17810
|
-
this.sudoResolver =
|
|
19812
|
+
return new Promise((resolve4) => {
|
|
19813
|
+
this.sudoResolver = resolve4;
|
|
17811
19814
|
this.emitter.emitSetupStatus(`${SETUP_AUTH_PREFIX}${reason}`);
|
|
17812
19815
|
});
|
|
17813
19816
|
}
|
|
17814
19817
|
/** Answer a pending sudo request. An empty password denies it, so setup
|
|
17815
19818
|
* fails with a message rather than hanging. */
|
|
17816
19819
|
setupAuthorize(p) {
|
|
17817
|
-
const
|
|
17818
|
-
if (!
|
|
19820
|
+
const resolve4 = this.sudoResolver;
|
|
19821
|
+
if (!resolve4) return { success: false };
|
|
17819
19822
|
this.sudoResolver = null;
|
|
17820
|
-
|
|
19823
|
+
resolve4(p.password || null);
|
|
17821
19824
|
return { success: true };
|
|
17822
19825
|
}
|
|
17823
19826
|
deployRunState() {
|
|
@@ -17871,12 +19874,12 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17871
19874
|
hooks: {
|
|
17872
19875
|
sendLog: bufferLog,
|
|
17873
19876
|
onTodos: (todos) => this.setRun({ todos }),
|
|
17874
|
-
requestHuman: (question) => new Promise((
|
|
17875
|
-
this.runResolvers.human =
|
|
19877
|
+
requestHuman: (question) => new Promise((resolve4) => {
|
|
19878
|
+
this.runResolvers.human = resolve4;
|
|
17876
19879
|
this.setRun({ phase: "awaiting-input", question });
|
|
17877
19880
|
}),
|
|
17878
|
-
requestAuth: (command, errorNote) => new Promise((
|
|
17879
|
-
this.runResolvers.auth =
|
|
19881
|
+
requestAuth: (command, errorNote) => new Promise((resolve4) => {
|
|
19882
|
+
this.runResolvers.auth = resolve4;
|
|
17880
19883
|
this.setRun({
|
|
17881
19884
|
phase: "awaiting-auth",
|
|
17882
19885
|
pendingCommand: command,
|
|
@@ -17909,35 +19912,35 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
17909
19912
|
return { started: true };
|
|
17910
19913
|
}
|
|
17911
19914
|
deployRunAnswer(payload) {
|
|
17912
|
-
const
|
|
17913
|
-
if (!
|
|
19915
|
+
const resolve4 = this.runResolvers.human;
|
|
19916
|
+
if (!resolve4 || this.runState.phase !== "awaiting-input") {
|
|
17914
19917
|
throw new Error("No step is awaiting input.");
|
|
17915
19918
|
}
|
|
17916
19919
|
this.runResolvers.human = void 0;
|
|
17917
19920
|
this.setRun({ phase: "running", question: "", error: "" });
|
|
17918
|
-
|
|
19921
|
+
resolve4(payload.answer);
|
|
17919
19922
|
return { success: true };
|
|
17920
19923
|
}
|
|
17921
19924
|
// The password arrives RUNNER-DIRECT here and only feeds decryption; it
|
|
17922
19925
|
// never enters the agent session (see .specs/deploy.md).
|
|
17923
19926
|
deployRunAuthorize(payload) {
|
|
17924
|
-
const
|
|
17925
|
-
if (!
|
|
19927
|
+
const resolve4 = this.runResolvers.auth;
|
|
19928
|
+
if (!resolve4 || this.runState.phase !== "awaiting-auth") {
|
|
17926
19929
|
throw new Error("No command is awaiting authorization.");
|
|
17927
19930
|
}
|
|
17928
19931
|
this.runResolvers.auth = void 0;
|
|
17929
19932
|
this.setRun({ phase: "running", pendingCommand: "", error: "" });
|
|
17930
|
-
|
|
19933
|
+
resolve4({ password: payload.password });
|
|
17931
19934
|
return { success: true };
|
|
17932
19935
|
}
|
|
17933
19936
|
deployRunDeny() {
|
|
17934
|
-
const
|
|
17935
|
-
if (!
|
|
19937
|
+
const resolve4 = this.runResolvers.auth;
|
|
19938
|
+
if (!resolve4 || this.runState.phase !== "awaiting-auth") {
|
|
17936
19939
|
throw new Error("No command is awaiting authorization.");
|
|
17937
19940
|
}
|
|
17938
19941
|
this.runResolvers.auth = void 0;
|
|
17939
19942
|
this.setRun({ phase: "running", pendingCommand: "" });
|
|
17940
|
-
|
|
19943
|
+
resolve4({ denied: true });
|
|
17941
19944
|
return { success: true };
|
|
17942
19945
|
}
|
|
17943
19946
|
deployRunCancel() {
|
|
@@ -18392,6 +20395,9 @@ var BoardAgentEngine = class _BoardAgentEngine {
|
|
|
18392
20395
|
bareFsWrite(p) {
|
|
18393
20396
|
return this.terminal.bareFsWrite(p);
|
|
18394
20397
|
}
|
|
20398
|
+
terminalDropImage(p) {
|
|
20399
|
+
return this.terminal.terminalDropImage(p);
|
|
20400
|
+
}
|
|
18395
20401
|
bareFsDelete(p) {
|
|
18396
20402
|
return this.terminal.bareFsDelete(p);
|
|
18397
20403
|
}
|
|
@@ -18822,6 +20828,8 @@ ${c.content.trim() || "(no description)"}`
|
|
|
18822
20828
|
return await this.ensureSetup();
|
|
18823
20829
|
case "cardRemoteBranches":
|
|
18824
20830
|
return await this.cardRemoteBranches();
|
|
20831
|
+
case "bareWorkNames":
|
|
20832
|
+
return await this.bareWorkNames();
|
|
18825
20833
|
case "deployStatus":
|
|
18826
20834
|
return await this.deployStatus();
|
|
18827
20835
|
case "deployCreateSkill":
|
|
@@ -18965,6 +20973,10 @@ ${c.content.trim() || "(no description)"}`
|
|
|
18965
20973
|
payload
|
|
18966
20974
|
);
|
|
18967
20975
|
return void 0;
|
|
20976
|
+
case "terminalDropImage":
|
|
20977
|
+
return await this.terminalDropImage(
|
|
20978
|
+
payload
|
|
20979
|
+
);
|
|
18968
20980
|
case "bareFsDelete":
|
|
18969
20981
|
await this.bareFsDelete(
|
|
18970
20982
|
payload
|
|
@@ -19029,9 +21041,9 @@ ${c.content.trim() || "(no description)"}`
|
|
|
19029
21041
|
|
|
19030
21042
|
// ../../shared/all/helpers/board-agent-core/index-service.ts
|
|
19031
21043
|
var import_child_process7 = require("child_process");
|
|
19032
|
-
var
|
|
19033
|
-
var
|
|
19034
|
-
var
|
|
21044
|
+
var import_crypto6 = require("crypto");
|
|
21045
|
+
var import_fs9 = require("fs");
|
|
21046
|
+
var import_promises8 = __toESM(require("fs/promises"));
|
|
19035
21047
|
var import_net2 = require("net");
|
|
19036
21048
|
var import_path13 = require("path");
|
|
19037
21049
|
var import_util7 = require("util");
|
|
@@ -19047,7 +21059,7 @@ var IndexService = class {
|
|
|
19047
21059
|
/** Per-space bearer for MCP + file, derived from the control token (the
|
|
19048
21060
|
* service computes the same). */
|
|
19049
21061
|
bearerToken(spaceSlug) {
|
|
19050
|
-
return (0,
|
|
21062
|
+
return (0, import_crypto6.createHmac)("sha256", this.opts.controlToken).update(`mcp:${spaceSlug}`).digest("hex");
|
|
19051
21063
|
}
|
|
19052
21064
|
/** MCP bridge for a space. Null until the service is up (which it kicks
|
|
19053
21065
|
* off), so a bad :0 URL is never baked in; provisionMcpLane re-runs. */
|
|
@@ -19120,8 +21132,8 @@ var IndexService = class {
|
|
|
19120
21132
|
* opened (a missing log must never stop the service from starting). */
|
|
19121
21133
|
async openLog() {
|
|
19122
21134
|
try {
|
|
19123
|
-
await
|
|
19124
|
-
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");
|
|
19125
21137
|
} catch {
|
|
19126
21138
|
return null;
|
|
19127
21139
|
}
|
|
@@ -19130,8 +21142,8 @@ var IndexService = class {
|
|
|
19130
21142
|
* platform needing node-gyp fails here rather than at query time. */
|
|
19131
21143
|
async installDeps() {
|
|
19132
21144
|
const dir = this.opts.indexDir;
|
|
19133
|
-
if ((0,
|
|
19134
|
-
await
|
|
21145
|
+
if ((0, import_fs9.existsSync)((0, import_path13.join)(dir, "node_modules"))) return;
|
|
21146
|
+
await import_promises8.default.copyFile(
|
|
19135
21147
|
(0, import_path13.join)(dir, "image-package.json"),
|
|
19136
21148
|
(0, import_path13.join)(dir, "package.json")
|
|
19137
21149
|
);
|
|
@@ -19146,14 +21158,14 @@ var IndexService = class {
|
|
|
19146
21158
|
* registration pointing at a dead one. */
|
|
19147
21159
|
async stablePort() {
|
|
19148
21160
|
const file = (0, import_path13.join)(this.opts.dataDir, ".port");
|
|
19149
|
-
const saved = Number(await
|
|
21161
|
+
const saved = Number(await import_promises8.default.readFile(file, "utf-8").catch(() => ""));
|
|
19150
21162
|
if (Number.isInteger(saved) && saved > 0 && await isFree(saved)) {
|
|
19151
21163
|
return saved;
|
|
19152
21164
|
}
|
|
19153
21165
|
const port = await freePort();
|
|
19154
|
-
await
|
|
21166
|
+
await import_promises8.default.mkdir(this.opts.dataDir, { recursive: true }).catch(() => {
|
|
19155
21167
|
});
|
|
19156
|
-
await
|
|
21168
|
+
await import_promises8.default.writeFile(file, String(port), "utf-8").catch(() => {
|
|
19157
21169
|
});
|
|
19158
21170
|
return port;
|
|
19159
21171
|
}
|
|
@@ -19246,20 +21258,20 @@ var IndexService = class {
|
|
|
19246
21258
|
}
|
|
19247
21259
|
};
|
|
19248
21260
|
function isFree(port) {
|
|
19249
|
-
return new Promise((
|
|
21261
|
+
return new Promise((resolve4) => {
|
|
19250
21262
|
const srv = (0, import_net2.createServer)();
|
|
19251
|
-
srv.once("error", () =>
|
|
19252
|
-
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)));
|
|
19253
21265
|
});
|
|
19254
21266
|
}
|
|
19255
21267
|
function freePort() {
|
|
19256
|
-
return new Promise((
|
|
21268
|
+
return new Promise((resolve4, reject) => {
|
|
19257
21269
|
const srv = (0, import_net2.createServer)();
|
|
19258
21270
|
srv.on("error", reject);
|
|
19259
21271
|
srv.listen(0, "127.0.0.1", () => {
|
|
19260
21272
|
const addr = srv.address();
|
|
19261
21273
|
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
19262
|
-
srv.close(() =>
|
|
21274
|
+
srv.close(() => resolve4(port));
|
|
19263
21275
|
});
|
|
19264
21276
|
});
|
|
19265
21277
|
}
|
|
@@ -19310,7 +21322,7 @@ async function setup(serverUrl) {
|
|
|
19310
21322
|
// src/selfUpdate.ts
|
|
19311
21323
|
var import_node_child_process = require("node:child_process");
|
|
19312
21324
|
var import_node_fs = __toESM(require("node:fs"));
|
|
19313
|
-
var
|
|
21325
|
+
var import_node_path2 = __toESM(require("node:path"));
|
|
19314
21326
|
var PACKAGE_NAME = "@factiii/runner";
|
|
19315
21327
|
var RESTART_FOR_UPDATE = 75;
|
|
19316
21328
|
var WORKER_ENV = "FACTIII_RUNNER_WORKER";
|
|
@@ -19323,7 +21335,7 @@ function isWorker() {
|
|
|
19323
21335
|
function currentVersion() {
|
|
19324
21336
|
try {
|
|
19325
21337
|
const pkg = JSON.parse(
|
|
19326
|
-
import_node_fs.default.readFileSync(
|
|
21338
|
+
import_node_fs.default.readFileSync(import_node_path2.default.join(__dirname, "..", "package.json"), "utf-8")
|
|
19327
21339
|
);
|
|
19328
21340
|
return pkg.version ?? "0.0.0";
|
|
19329
21341
|
} catch {
|
|
@@ -19398,8 +21410,8 @@ function makeChunkReassembler() {
|
|
|
19398
21410
|
}
|
|
19399
21411
|
|
|
19400
21412
|
// src/daemon.ts
|
|
19401
|
-
var
|
|
19402
|
-
var
|
|
21413
|
+
var import_crypto7 = require("crypto");
|
|
21414
|
+
var import_fs11 = __toESM(require("fs"));
|
|
19403
21415
|
var import_node_datachannel = require("node-datachannel");
|
|
19404
21416
|
var import_path15 = __toESM(require("path"));
|
|
19405
21417
|
|
|
@@ -21898,9 +23910,9 @@ var Socket2 = class extends import_component_emitter5.Emitter {
|
|
|
21898
23910
|
* @return a Promise that will be fulfilled when the server acknowledges the event
|
|
21899
23911
|
*/
|
|
21900
23912
|
emitWithAck(ev, ...args) {
|
|
21901
|
-
return new Promise((
|
|
23913
|
+
return new Promise((resolve4, reject) => {
|
|
21902
23914
|
const fn = (arg1, arg2) => {
|
|
21903
|
-
return arg1 ? reject(arg1) :
|
|
23915
|
+
return arg1 ? reject(arg1) : resolve4(arg2);
|
|
21904
23916
|
};
|
|
21905
23917
|
fn.withError = true;
|
|
21906
23918
|
args.push(fn);
|
|
@@ -23081,7 +25093,7 @@ var TerminalManager = class {
|
|
|
23081
25093
|
};
|
|
23082
25094
|
|
|
23083
25095
|
// src/agent-adapter.ts
|
|
23084
|
-
var
|
|
25096
|
+
var import_fs10 = __toESM(require("fs"));
|
|
23085
25097
|
var import_path14 = __toESM(require("path"));
|
|
23086
25098
|
var RUNNER_CONFIG_PATH = import_path14.default.join(CONFIG_DIR, "runner-config.json");
|
|
23087
25099
|
function connectionPath(spaceSlug) {
|
|
@@ -23112,7 +25124,7 @@ function migrateLegacyConfigs() {
|
|
|
23112
25124
|
const file = { boards: {} };
|
|
23113
25125
|
let legacy = [];
|
|
23114
25126
|
try {
|
|
23115
|
-
legacy =
|
|
25127
|
+
legacy = import_fs10.default.readdirSync(CONFIG_DIR).filter((f) => f.startsWith("space-") && f.endsWith(".json")).filter((f) => !f.endsWith(".onedrive.json"));
|
|
23116
25128
|
} catch {
|
|
23117
25129
|
return file;
|
|
23118
25130
|
}
|
|
@@ -23139,14 +25151,14 @@ function encryptStrayPlaintextConfigs() {
|
|
|
23139
25151
|
const OURS = /^(config|runner-config|space-.*)\.json(\.bak-\d+)?$/;
|
|
23140
25152
|
let names = [];
|
|
23141
25153
|
try {
|
|
23142
|
-
names =
|
|
25154
|
+
names = import_fs10.default.readdirSync(CONFIG_DIR).filter((f) => OURS.test(f));
|
|
23143
25155
|
} catch {
|
|
23144
25156
|
return;
|
|
23145
25157
|
}
|
|
23146
25158
|
for (const name of names) {
|
|
23147
25159
|
const filePath = import_path14.default.join(CONFIG_DIR, name);
|
|
23148
25160
|
try {
|
|
23149
|
-
const raw =
|
|
25161
|
+
const raw = import_fs10.default.readFileSync(filePath, "utf-8");
|
|
23150
25162
|
if (!raw.startsWith("{")) continue;
|
|
23151
25163
|
writeSecureJson(filePath, JSON.parse(raw));
|
|
23152
25164
|
} catch {
|
|
@@ -23177,7 +25189,7 @@ async function getConfiguredConnections() {
|
|
|
23177
25189
|
}
|
|
23178
25190
|
if (await isSignedIn(hostTarget(CONFIG_DIR), "claude")) kinds.add("claude");
|
|
23179
25191
|
try {
|
|
23180
|
-
const hasOneDrive =
|
|
25192
|
+
const hasOneDrive = import_fs10.default.readdirSync(CONFIG_DIR).some((f) => f.endsWith(".onedrive.json"));
|
|
23181
25193
|
if (hasOneDrive) kinds.add("onedrive");
|
|
23182
25194
|
} catch {
|
|
23183
25195
|
}
|
|
@@ -23248,7 +25260,7 @@ var localConfigProvider = {
|
|
|
23248
25260
|
writeOneDriveConnection(spaceSlug, connection) {
|
|
23249
25261
|
const filePath = connectionPath(spaceSlug);
|
|
23250
25262
|
if (!connection) {
|
|
23251
|
-
|
|
25263
|
+
import_fs10.default.rmSync(filePath, { force: true });
|
|
23252
25264
|
return;
|
|
23253
25265
|
}
|
|
23254
25266
|
writeJson(filePath, connection);
|
|
@@ -23273,7 +25285,7 @@ var localConfigProvider = {
|
|
|
23273
25285
|
"claude",
|
|
23274
25286
|
"codex"
|
|
23275
25287
|
]) {
|
|
23276
|
-
|
|
25288
|
+
import_fs10.default.mkdirSync(import_path14.default.join(dir, sub), { recursive: true });
|
|
23277
25289
|
}
|
|
23278
25290
|
return dir;
|
|
23279
25291
|
}
|
|
@@ -23397,17 +25409,17 @@ async function startDaemon(config) {
|
|
|
23397
25409
|
}
|
|
23398
25410
|
};
|
|
23399
25411
|
const mintWebhook = (spaceSlug) => new Promise(
|
|
23400
|
-
(
|
|
25412
|
+
(resolve4) => {
|
|
23401
25413
|
if (!socket.connected) {
|
|
23402
|
-
|
|
25414
|
+
resolve4(null);
|
|
23403
25415
|
return;
|
|
23404
25416
|
}
|
|
23405
25417
|
socket.timeout(8e3).emit("onedriveWebhookRegister", { spaceSlug }, (err, res) => {
|
|
23406
25418
|
if (err || !res || "error" in res) {
|
|
23407
|
-
|
|
25419
|
+
resolve4(null);
|
|
23408
25420
|
return;
|
|
23409
25421
|
}
|
|
23410
|
-
|
|
25422
|
+
resolve4({
|
|
23411
25423
|
notificationUrl: `${config.serverUrl.replace(/\/$/, "")}/onedrive/webhook`,
|
|
23412
25424
|
clientState: res.clientState
|
|
23413
25425
|
});
|
|
@@ -23418,9 +25430,9 @@ async function startDaemon(config) {
|
|
|
23418
25430
|
import_path15.default.join(__dirname, "..", "index"),
|
|
23419
25431
|
import_path15.default.join(__dirname, "..", "..", "index", "image")
|
|
23420
25432
|
];
|
|
23421
|
-
const indexDir = indexCandidates.find((p) =>
|
|
25433
|
+
const indexDir = indexCandidates.find((p) => import_fs11.default.existsSync(p)) ?? indexCandidates[0];
|
|
23422
25434
|
const odIndex = new IndexService({
|
|
23423
|
-
controlToken: (0,
|
|
25435
|
+
controlToken: (0, import_crypto7.createHash)("sha256").update(config.authToken).digest("hex"),
|
|
23424
25436
|
embedUrl: () => config.serverUrl,
|
|
23425
25437
|
indexDir,
|
|
23426
25438
|
dataDir: import_path15.default.join(CONFIG_DIR, "index-data")
|
|
@@ -24073,5 +26085,8 @@ xmlhttprequest-ssl/lib/XMLHttpRequest.js:
|
|
|
24073
26085
|
* @contributor David Ellis <d.f.ellis@ieee.org>
|
|
24074
26086
|
* @license MIT
|
|
24075
26087
|
*)
|
|
26088
|
+
|
|
26089
|
+
chokidar/esm/index.js:
|
|
26090
|
+
(*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
|
|
24076
26091
|
*/
|
|
24077
26092
|
//# sourceMappingURL=cli.js.map
|